00001
00007 #include "OpenGLRenderer.h"
00008
00009
00010 const int NEVER = GL_NEVER;
00011 const int LESS = GL_LESS;
00012 const int EQUAL = GL_EQUAL;
00013 const int LEQUAL = GL_LEQUAL;
00014 const int GREATER = GL_GREATER;
00015 const int NOTEQUAL = GL_NOTEQUAL;
00016 const int GEQUAL = GL_GEQUAL;
00017 const int ALWAYS = GL_ALWAYS;
00018
00019
00020 const int ZERO = GL_ZERO;
00021 const int ONE = GL_ONE;
00022 const int SRC_COLOR = GL_SRC_COLOR;
00023 const int ONE_MINUS_SRC_COLOR = GL_ONE_MINUS_SRC_COLOR;
00024 const int DST_COLOR = GL_DST_COLOR;
00025 const int ONE_MINUS_DST_COLOR = GL_ONE_MINUS_DST_COLOR;
00026 const int SRC_ALPHA = GL_SRC_ALPHA;
00027 const int ONE_MINUS_SRC_ALPHA = GL_ONE_MINUS_SRC_ALPHA;
00028 const int DST_ALPHA = GL_DST_ALPHA;
00029 const int ONE_MINUS_DST_ALPHA = GL_ONE_MINUS_DST_ALPHA;
00030 const int SRC_ALPHA_SATURATE = GL_SRC_ALPHA_SATURATE;
00031
00032 const int BLENDMODE_ADD = GL_FUNC_ADD_EXT;
00033 const int BLENDMODE_SUBTRACT = GL_FUNC_SUBTRACT_EXT;
00034 const int BLENDMODE_REVERSE_SUBSTRACT = GL_FUNC_REVERSE_SUBTRACT_EXT;
00035 const int BLENDMODE_MIN = GL_MIN_EXT;
00036 const int BLENDMOXE_MAX = GL_MAX_EXT;
00037
00038 GLenum OpenGLRenderer::targets[] = { GL_TEXTURE_2D, GL_TEXTURE_CUBE_MAP_ARB};
00039
00040 OpenGLRenderer::OpenGLRenderer() {
00041 init();
00042 }
00043
00044
00045
00046
00047 void OpenGLRenderer::init() {
00048 if (GL_ARB_multitexture_supported) {
00049 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &maxTextures);
00050 if (maxTextures > MAX_TEXTURES) maxTextures = MAX_TEXTURES;
00051 }
00052 else
00053 maxTextures = 1;
00054
00055 resetToDefaults();
00056 setDefaults();
00057 }
00058
00059
00060
00061
00062
00063 void OpenGLRenderer::setDefaults() {
00064 glEnable(GL_DEPTH_TEST);
00065 glDepthFunc(GL_LEQUAL);
00066 glPixelStorei(GL_PACK_ALIGNMENT, 1);
00067 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
00068 glFrontFace(GL_CW);
00069
00070 glShadeModel(GL_SMOOTH);
00071 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
00072 }
00073
00074
00075
00076
00077 void OpenGLRenderer::changeDepthFunc(const int depthFunc) {
00078 if (depthFunc != currentDepthFunc) {
00079 if (depthFunc == DEPTH_NONE) {
00080 glDisable(GL_DEPTH_TEST);
00081 }
00082 else {
00083 if (currentDepthFunc == DEPTH_NONE)
00084 glEnable(GL_DEPTH_TEST);
00085 glDepthFunc(depthFunc);
00086 }
00087 currentDepthFunc = depthFunc;
00088 }
00089 }
00090
00091
00092
00093
00094 void OpenGLRenderer::changeBlending(const int src, const int dest, const int blendMode) {
00095 if (src != BLENDING_NONE) {
00096 if (currentBlendSrc == BLENDING_NONE)
00097 glEnable(GL_BLEND);
00098
00099 if (src != currentBlendSrc || dest != currentBlendDest)
00100 glBlendFunc(currentBlendSrc = src, currentBlendDest = dest);
00101
00102 if (blendMode != currentBlendMode)
00103 glBlendEquationEXT(currentBlendMode = blendMode);
00104 }
00105 else {
00106 if (currentBlendSrc != BLENDING_NONE) {
00107 glDisable(GL_BLEND);
00108 currentBlendSrc = BLENDING_NONE;
00109 }
00110 }
00111 }
00112
00113
00114
00115
00116 void OpenGLRenderer::changeMask(const int mask) {
00117 if (mask != currentMask) {
00118 if ((mask & DEPTH) != (currentMask & DEPTH))
00119 glDepthMask(mask & DEPTH);
00120
00121 if ((mask & COLOR) != (currentMask & COLOR))
00122 glColorMask(((mask & RED) >> 1) & 1, ((mask & GREEN) >> 2) & 1, ((mask & BLUE) >> 3) & 1, ((mask & ALPHA) >> 4 & 1));
00123
00124 currentMask = mask;
00125 }
00126 }
00127
00128
00129
00130
00131 bool OpenGLRenderer::createTexture(Texture &texture) {
00132 GLenum target = targets[texture.textureKind];
00133 int nImages = 1;
00134
00135 glGenTextures(1, &texture.textureID);
00136 glBindTexture(target, texture.textureID);
00137
00138 switch (texture.textureKind) {
00139 case TEXTURE_2D:
00140 glTexParameteri(target, GL_TEXTURE_WRAP_S, (texture.clampS ? GL_CLAMP_TO_EDGE_EXT : GL_REPEAT));
00141 glTexParameteri(target, GL_TEXTURE_WRAP_T, (texture.clampT ? GL_CLAMP_TO_EDGE_EXT : GL_REPEAT));
00142 break;
00143
00144 case TEXTURE_CUBEMAP:
00145 nImages = 6;
00146 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE_EXT);
00147 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE_EXT);
00148 break;
00149
00150 default:
00151 return false;
00152 }
00153
00154 glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00155
00156 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00157
00158 for (int i=0; i<nImages; i++) {
00159 Image *image = texture.images[i];
00160
00161 GLenum imgTarget = (texture.textureKind == TEXTURE_2D) ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + i;
00162
00163 gluBuild2DMipmaps(imgTarget, 3, image->getWidth(), image->getHeight(), image->getFormat(), GL_UNSIGNED_BYTE, image->getData());
00164 }
00165
00166 return true;
00167 }
00168
00169
00170
00171
00172 void OpenGLRenderer::removeTexture(Texture &texture) {
00173 glDeleteTextures(1, &texture.textureID);
00174 }
00175
00176
00177
00178
00179 void OpenGLRenderer::changeTextureUnit(const int tex) {
00180 if (tex != currentTextureUnit)
00181 glActiveTextureARB(GL_TEXTURE0_ARB + (currentTextureUnit =tex));
00182 }
00183
00184
00185
00186
00187 void OpenGLRenderer::changeTexture(const TextureID textureID) {
00188 TextureID currTex = currentTextures[currentTextureUnit];
00189
00190 if (textureID != currTex) {
00191 if (textureID == TEXTURE_NONE) {
00192 glDisable(targets[textures[currTex].textureKind]);
00193 }
00194 else {
00195 GLenum target = targets[textures[textureID].textureKind];
00196
00197 if (currTex == TEXTURE_NONE) {
00198 glEnable(target);
00199 }
00200 else {
00201 if (textures[textureID].textureKind != textures[currTex].textureKind) {
00202 glDisable(targets[textures[currTex].textureKind]);
00203 glEnable(target);
00204 }
00205 }
00206
00207 glBindTexture(target, textures[textureID].textureID);
00208 }
00209 currentTextures[currentTextureUnit] = textureID;
00210 }
00211
00219 }
00220
00221
00222
00223
00224 void OpenGLRenderer::assignNamedTextures() {
00225 if (currentShader != SHADER_NONE) {
00226 for (int i=0; i<nNamedTextures; i++) {
00227 int location = glGetUniformLocationARB(shaders[currentShader].programObj, selectedTextureNames[i]);
00228 if (location >= 0) glUniform1iARB(location, i);
00229 }
00230 }
00231 }
00232
00233
00234
00235
00236 bool OpenGLRenderer::createShader(Shader &shader, const char *vertexShaderText, const char *fragmentShaderText) {
00237 const char *shaderStrings[2];
00238 int vResult, fResult, lResult;
00239 char str[4096];
00240
00241 shaderStrings[0] = "#define saturate(x) clamp(x,0.0,1.0)\n"
00242 "#define lerp mix\n";
00243
00244 shader.programObj = glCreateProgramObjectARB();
00245
00246 shader.vertexShader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
00247 shaderStrings[1] = vertexShaderText;
00248 glShaderSourceARB(shader.vertexShader, 2, shaderStrings, NULL);
00249 glCompileShaderARB(shader.vertexShader);
00250 glGetObjectParameterivARB(shader.vertexShader, GL_OBJECT_COMPILE_STATUS_ARB, &vResult);
00251 if (vResult) {
00252 glAttachObjectARB(shader.programObj, shader.vertexShader);
00253 }
00254 else {
00255 glGetInfoLogARB(shader.vertexShader, sizeof(str), NULL, str);
00256 LOG_ERROR(("Vertex shader error! Log:\n%s", str));
00257 }
00258
00259 shader.fragmentShader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
00260 shaderStrings[1] = fragmentShaderText;
00261 glShaderSourceARB(shader.fragmentShader, 2, shaderStrings, NULL);
00262 glCompileShaderARB(shader.fragmentShader);
00263 glGetObjectParameterivARB(shader.fragmentShader, GL_OBJECT_COMPILE_STATUS_ARB, &fResult);
00264 if (fResult) {
00265 glAttachObjectARB(shader.programObj, shader.fragmentShader);
00266 }
00267 else {
00268 glGetInfoLogARB(shader.fragmentShader, sizeof(str), NULL, str);
00269 LOG_ERROR(("Fragment shader error! Log:\n%s", str));
00270 }
00271
00272
00273 if (vResult && fResult) {
00274 glLinkProgramARB(shader.programObj);
00275 glGetObjectParameterivARB(shader.programObj, GL_OBJECT_LINK_STATUS_ARB, &lResult);
00276
00277
00278
00279
00280 if (lResult) {
00281 return true;
00282 }
00283 else {
00284 glGetInfoLogARB(shader.programObj, sizeof(str), NULL, str);
00285 LOG_ERROR(("Program object error! Log:\n%s", str));
00286 }
00287 }
00288
00289 removeShader(shader);
00290 return false;
00291 }
00292
00293
00294
00295
00296 void OpenGLRenderer::removeShader(Shader &shader) {
00297 glDeleteObjectARB(shader.vertexShader);
00298 glDeleteObjectARB(shader.fragmentShader);
00299 glDeleteObjectARB(shader.programObj);
00300 }
00301
00302
00303
00304
00305 void OpenGLRenderer::changeShader(const ShaderID shader) {
00306 if (shader != currentShader) {
00307 if (shader == SHADER_NONE)
00308 glUseProgramObjectARB(0);
00309 else
00310 glUseProgramObjectARB(shaders[shader].programObj);
00311
00312 currentShader = shader;
00313 }
00314 }
00315
00316
00317
00318
00319 void OpenGLRenderer::changeShaderConstant1f(const char *name, const float constant) {
00320 if (currentShader != SHADER_NONE) {
00321 int location = glGetUniformLocationARB(shaders[currentShader].programObj, name);
00322 if (location >= 0) glUniform1fARB(location, constant);
00323 }
00324 }
00325
00326
00327
00328
00329 void OpenGLRenderer::changeShaderConstant2f(const char *name, const Vec2 &constant) {
00330 if (currentShader != SHADER_NONE) {
00331 int location = glGetUniformLocationARB(shaders[currentShader].programObj, name);
00332
00333 if (location >= 0) glUniform2fARB(location, constant.x, constant.y);
00334 }
00335 }
00336
00337
00338
00339
00340 void OpenGLRenderer::changeShaderConstant3f(const char *name, const Vec3 &constant) {
00341 if (currentShader != SHADER_NONE) {
00342 int location = glGetUniformLocationARB(shaders[currentShader].programObj, name);
00343
00344 if (location >= 0) glUniform3fARB(location, constant.x, constant.y, constant.z);
00345 }
00346 }
00347
00348
00349
00350
00351 void OpenGLRenderer::changeShaderConstant4f(const char *name, const Vec4 &constant) {
00352 if (currentShader != SHADER_NONE) {
00353 int location = glGetUniformLocationARB(shaders[currentShader].programObj, name);
00354
00355 if (location >= 0) glUniform4fARB(location, constant.x, constant.y, constant.z, constant.w);
00356 }
00357 }
00358
00359
00360
00361
00362
00363 void OpenGLRenderer::createFragmentShader(FragmentShader &fragmentShader) {
00364
00365
00366
00368 glGenProgramsARB(1, &fragmentShader.shaderID);
00369 glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, fragmentShader.shaderID);
00370 }
00371
00372
00373
00374
00375 }
00376
00377
00378
00379
00380 void OpenGLRenderer::removeFragmentShader(FragmentShader &fragmentShader) {
00381 if (fragmentShader.type == GL_FRAGMENT_PROGRAM_ARB) {
00382 glDeleteProgramsARB(1, &fragmentShader.shaderID);
00383 }
00384
00385
00386
00387
00388
00389
00390 }
00391
00392
00393
00394
00395 void OpenGLRenderer::uploadFragmentShader(FragmentShader &fragmentShader) {
00396 glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, fragmentShader.length, fragmentShader.program);
00397 }
00398
00399
00400
00401
00402 void OpenGLRenderer::createVertexShader(VertexShader &vertexShader) {
00403 glGenProgramsARB(1, &vertexShader.shaderID);
00404 glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertexShader.shaderID);
00405 }
00406
00407
00408
00409
00410 void OpenGLRenderer::removeVertexShader(VertexShader &vertexShader) {
00411 glDeleteProgramsARB(1, &vertexShader.shaderID);
00412 }
00413
00414
00415
00416
00417 void OpenGLRenderer::uploadVertexShader(VertexShader &vertexShader) {
00418 glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, vertexShader.length, vertexShader.program);
00419 }
00420
00421
00422
00423
00424 void OpenGLRenderer::changeFragmentShader(const ShaderID shader) {
00425 if (currentFragmentShader != shader) {
00426 if (shader == SHADER_NONE) {
00427 glDisable(fragmentShaders[currentFragmentShader].type);
00428 }
00429 else {
00430 if (currentFragmentShader == SHADER_NONE) {
00431 glEnable(fragmentShaders[shader].type);
00432 }
00433 else if (fragmentShaders[currentFragmentShader].type != fragmentShaders[shader].type) {
00434 glDisable(fragmentShaders[currentFragmentShader].type);
00435 glEnable(fragmentShaders[shader].type);
00436 }
00437
00438 if (fragmentShaders[shader].type == GL_FRAGMENT_PROGRAM_ARB) {
00439 glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, fragmentShaders[shader].shaderID);
00440 }
00447 }
00448
00449 currentFragmentShader = shader;
00450 }
00451 }
00452
00453
00454
00455
00456 void OpenGLRenderer::changeVertexShader(const ShaderID shader) {
00457 if (currentVertexShader != shader) {
00458 if (shader == SHADER_NONE) {
00459 glDisable(GL_VERTEX_PROGRAM_ARB);
00460 }
00461 else {
00462 if (currentVertexShader == SHADER_NONE) {
00463 glEnable(GL_VERTEX_PROGRAM_ARB);
00464 }
00465
00466 glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertexShaders[shader].shaderID);
00467 }
00468
00469 currentVertexShader = shader;
00470 }
00471 }