Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * Contributor(s): none yet. 00019 * 00020 * ***** END GPL LICENSE BLOCK ***** 00021 */ 00022 00028 #define STRINGIFY(A) #A 00029 00030 #include "RAS_OpenGLFilters/RAS_Blur2DFilter.h" 00031 #include "RAS_OpenGLFilters/RAS_Sharpen2DFilter.h" 00032 #include "RAS_OpenGLFilters/RAS_Dilation2DFilter.h" 00033 #include "RAS_OpenGLFilters/RAS_Erosion2DFilter.h" 00034 #include "RAS_OpenGLFilters/RAS_Laplacian2DFilter.h" 00035 #include "RAS_OpenGLFilters/RAS_Sobel2DFilter.h" 00036 #include "RAS_OpenGLFilters/RAS_Prewitt2DFilter.h" 00037 #include "RAS_OpenGLFilters/RAS_GrayScale2DFilter.h" 00038 #include "RAS_OpenGLFilters/RAS_Sepia2DFilter.h" 00039 #include "RAS_OpenGLFilters/RAS_Invert2DFilter.h" 00040 00041 #include "STR_String.h" 00042 #include "RAS_ICanvas.h" 00043 #include "RAS_Rect.h" 00044 #include "RAS_2DFilterManager.h" 00045 #include <iostream> 00046 00047 #include "GL/glew.h" 00048 00049 #include <stdio.h> 00050 00051 #include "Value.h" 00052 00053 RAS_2DFilterManager::RAS_2DFilterManager(): 00054 texturewidth(-1), textureheight(-1), 00055 canvaswidth(-1), canvasheight(-1), 00056 numberoffilters(0), need_tex_update(true) 00057 { 00058 isshadersupported = GLEW_ARB_shader_objects && 00059 GLEW_ARB_fragment_shader && GLEW_ARB_multitexture; 00060 00061 /* used to return before 2.49 but need to initialize values so dont */ 00062 if(!isshadersupported) 00063 std::cout<<"shaders not supported!" << std::endl; 00064 00065 int passindex; 00066 for(passindex =0; passindex<MAX_RENDER_PASS; passindex++) 00067 { 00068 m_filters[passindex] = 0; 00069 m_enabled[passindex] = 0; 00070 texflag[passindex] = 0; 00071 m_gameObjects[passindex] = NULL; 00072 } 00073 texname[0] = texname[1] = texname[2] = -1; 00074 errorprinted= false; 00075 } 00076 00077 RAS_2DFilterManager::~RAS_2DFilterManager() 00078 { 00079 FreeTextures(); 00080 } 00081 00082 void RAS_2DFilterManager::PrintShaderErrors(unsigned int shader, const char *task, const char *code) 00083 { 00084 GLcharARB log[5000]; 00085 GLsizei length = 0; 00086 const char *c, *pos, *end; 00087 int line = 1; 00088 00089 if(errorprinted) 00090 return; 00091 00092 errorprinted= true; 00093 00094 glGetInfoLogARB(shader, sizeof(log), &length, log); 00095 end = code + strlen(code); 00096 00097 printf("2D Filter GLSL Shader: %s error:\n", task); 00098 00099 c = code; 00100 while ((c < end) && (pos = strchr(c, '\n'))) { 00101 printf("%2d ", line); 00102 fwrite(c, (pos+1)-c, 1, stdout); 00103 c = pos+1; 00104 line++; 00105 } 00106 printf("%s", c); 00107 00108 printf("%s\n", log); 00109 } 00110 00111 unsigned int RAS_2DFilterManager::CreateShaderProgram(const char* shadersource) 00112 { 00113 GLuint program = 0; 00114 GLuint fShader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER); 00115 GLint success; 00116 00117 glShaderSourceARB(fShader, 1, (const char**)&shadersource, NULL); 00118 00119 glCompileShaderARB(fShader); 00120 00121 00122 glGetObjectParameterivARB(fShader, GL_COMPILE_STATUS, &success); 00123 if(!success) 00124 { 00125 /*Shader Comile Error*/ 00126 PrintShaderErrors(fShader, "compile", shadersource); 00127 return 0; 00128 } 00129 00130 program = glCreateProgramObjectARB(); 00131 glAttachObjectARB(program, fShader); 00132 00133 glLinkProgramARB(program); 00134 glGetObjectParameterivARB(program, GL_LINK_STATUS, &success); 00135 if (!success) 00136 { 00137 /*Program Link Error*/ 00138 PrintShaderErrors(fShader, "link", shadersource); 00139 return 0; 00140 } 00141 00142 glValidateProgramARB(program); 00143 glGetObjectParameterivARB(program, GL_VALIDATE_STATUS, &success); 00144 if (!success) 00145 { 00146 /*Program Validation Error*/ 00147 PrintShaderErrors(fShader, "validate", shadersource); 00148 return 0; 00149 } 00150 00151 return program; 00152 } 00153 00154 unsigned int RAS_2DFilterManager::CreateShaderProgram(int filtermode) 00155 { 00156 switch(filtermode) 00157 { 00158 case RAS_2DFILTER_BLUR: 00159 return CreateShaderProgram(BlurFragmentShader); 00160 case RAS_2DFILTER_SHARPEN: 00161 return CreateShaderProgram(SharpenFragmentShader); 00162 case RAS_2DFILTER_DILATION: 00163 return CreateShaderProgram(DilationFragmentShader); 00164 case RAS_2DFILTER_EROSION: 00165 return CreateShaderProgram(ErosionFragmentShader); 00166 case RAS_2DFILTER_LAPLACIAN: 00167 return CreateShaderProgram(LaplacionFragmentShader); 00168 case RAS_2DFILTER_SOBEL: 00169 return CreateShaderProgram(SobelFragmentShader); 00170 case RAS_2DFILTER_PREWITT: 00171 return CreateShaderProgram(PrewittFragmentShader); 00172 case RAS_2DFILTER_GRAYSCALE: 00173 return CreateShaderProgram(GrayScaleFragmentShader); 00174 case RAS_2DFILTER_SEPIA: 00175 return CreateShaderProgram(SepiaFragmentShader); 00176 case RAS_2DFILTER_INVERT: 00177 return CreateShaderProgram(InvertFragmentShader); 00178 } 00179 return 0; 00180 } 00181 00182 void RAS_2DFilterManager::AnalyseShader(int passindex, vector<STR_String>& propNames) 00183 { 00184 texflag[passindex] = 0; 00185 if(glGetUniformLocationARB(m_filters[passindex], "bgl_DepthTexture") != -1) 00186 { 00187 if(GLEW_ARB_depth_texture) 00188 texflag[passindex] |= 0x1; 00189 } 00190 if(glGetUniformLocationARB(m_filters[passindex], "bgl_LuminanceTexture") != -1) 00191 { 00192 texflag[passindex] |= 0x2; 00193 } 00194 00195 if(m_gameObjects[passindex]) 00196 { 00197 int objProperties = propNames.size(); 00198 int i; 00199 for(i=0; i<objProperties; i++) 00200 if(glGetUniformLocationARB(m_filters[passindex], propNames[i]) != -1) 00201 m_properties[passindex].push_back(propNames[i]); 00202 } 00203 } 00204 00205 void RAS_2DFilterManager::StartShaderProgram(int passindex) 00206 { 00207 GLint uniformLoc; 00208 glUseProgramObjectARB(m_filters[passindex]); 00209 uniformLoc = glGetUniformLocationARB(m_filters[passindex], "bgl_RenderedTexture"); 00210 glActiveTextureARB(GL_TEXTURE0); 00211 glBindTexture(GL_TEXTURE_2D, texname[0]); 00212 00213 if (uniformLoc != -1) 00214 { 00215 glUniform1iARB(uniformLoc, 0); 00216 } 00217 00218 /* send depth texture to glsl program if it needs */ 00219 if(texflag[passindex] & 0x1){ 00220 uniformLoc = glGetUniformLocationARB(m_filters[passindex], "bgl_DepthTexture"); 00221 glActiveTextureARB(GL_TEXTURE1); 00222 glBindTexture(GL_TEXTURE_2D, texname[1]); 00223 00224 if (uniformLoc != -1) 00225 { 00226 glUniform1iARB(uniformLoc, 1); 00227 } 00228 } 00229 00230 /* send luminance texture to glsl program if it needs */ 00231 if(texflag[passindex] & 0x2){ 00232 uniformLoc = glGetUniformLocationARB(m_filters[passindex], "bgl_LuminanceTexture"); 00233 glActiveTextureARB(GL_TEXTURE2); 00234 glBindTexture(GL_TEXTURE_2D, texname[2]); 00235 00236 if (uniformLoc != -1) 00237 { 00238 glUniform1iARB(uniformLoc, 2); 00239 } 00240 } 00241 00242 uniformLoc = glGetUniformLocationARB(m_filters[passindex], "bgl_TextureCoordinateOffset"); 00243 if (uniformLoc != -1) 00244 { 00245 glUniform2fvARB(uniformLoc, 9, textureoffsets); 00246 } 00247 uniformLoc = glGetUniformLocationARB(m_filters[passindex], "bgl_RenderedTextureWidth"); 00248 if (uniformLoc != -1) 00249 { 00250 glUniform1fARB(uniformLoc,texturewidth); 00251 } 00252 uniformLoc = glGetUniformLocationARB(m_filters[passindex], "bgl_RenderedTextureHeight"); 00253 if (uniformLoc != -1) 00254 { 00255 glUniform1fARB(uniformLoc,textureheight); 00256 } 00257 00258 int i, objProperties = m_properties[passindex].size(); 00259 for(i=0; i<objProperties; i++) 00260 { 00261 uniformLoc = glGetUniformLocationARB(m_filters[passindex], m_properties[passindex][i]); 00262 if(uniformLoc != -1) 00263 { 00264 float value = ((CValue*)m_gameObjects[passindex])->GetPropertyNumber(m_properties[passindex][i], 0.0); 00265 glUniform1fARB(uniformLoc,value); 00266 } 00267 } 00268 } 00269 00270 void RAS_2DFilterManager::EndShaderProgram() 00271 { 00272 glUseProgramObjectARB(0); 00273 } 00274 00275 void RAS_2DFilterManager::FreeTextures() 00276 { 00277 if(texname[0]!=(unsigned int)-1) 00278 glDeleteTextures(1, (GLuint*)&texname[0]); 00279 if(texname[1]!=(unsigned int)-1) 00280 glDeleteTextures(1, (GLuint*)&texname[1]); 00281 if(texname[2]!=(unsigned int)-1) 00282 glDeleteTextures(1, (GLuint*)&texname[2]); 00283 } 00284 00285 void RAS_2DFilterManager::SetupTextures(bool depth, bool luminance) 00286 { 00287 FreeTextures(); 00288 00289 glGenTextures(1, (GLuint*)&texname[0]); 00290 glBindTexture(GL_TEXTURE_2D, texname[0]); 00291 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texturewidth, textureheight, 0, GL_RGBA, 00292 GL_UNSIGNED_BYTE, 0); 00293 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 00294 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 00295 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); 00296 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); 00297 00298 if(depth){ 00299 glGenTextures(1, (GLuint*)&texname[1]); 00300 glBindTexture(GL_TEXTURE_2D, texname[1]); 00301 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, texturewidth,textureheight, 00302 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE,NULL); 00303 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, 00304 GL_NONE); 00305 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 00306 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 00307 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); 00308 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); 00309 } 00310 00311 if(luminance){ 00312 glGenTextures(1, (GLuint*)&texname[2]); 00313 glBindTexture(GL_TEXTURE_2D, texname[2]); 00314 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE16, texturewidth, textureheight, 00315 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, 0); 00316 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 00317 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 00318 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); 00319 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); 00320 } 00321 } 00322 00323 void RAS_2DFilterManager::UpdateOffsetMatrix(RAS_ICanvas* canvas) 00324 { 00325 RAS_Rect canvas_rect = canvas->GetWindowArea(); 00326 canvaswidth = canvas->GetWidth(); 00327 canvasheight = canvas->GetHeight(); 00328 00329 texturewidth = canvaswidth + canvas_rect.GetLeft(); 00330 textureheight = canvasheight + canvas_rect.GetBottom(); 00331 GLint i,j; 00332 i = 0; 00333 while ((1 << i) <= texturewidth) 00334 i++; 00335 texturewidth = (1 << (i)); 00336 00337 // Now for height 00338 i = 0; 00339 while ((1 << i) <= textureheight) 00340 i++; 00341 textureheight = (1 << (i)); 00342 00343 GLfloat xInc = 1.0f / (GLfloat)texturewidth; 00344 GLfloat yInc = 1.0f / (GLfloat)textureheight; 00345 00346 for (i = 0; i < 3; i++) 00347 { 00348 for (j = 0; j < 3; j++) 00349 { 00350 textureoffsets[(((i*3)+j)*2)+0] = (-1.0f * xInc) + ((GLfloat)i * xInc); 00351 textureoffsets[(((i*3)+j)*2)+1] = (-1.0f * yInc) + ((GLfloat)j * yInc); 00352 } 00353 } 00354 } 00355 00356 void RAS_2DFilterManager::UpdateCanvasTextureCoord(unsigned int * viewport) 00357 { 00358 /* 00359 This function update canvascoord[]. 00360 These parameters are used to create texcoord[1] 00361 That way we can access the texcoord relative to the canvas: 00362 (0.0,0.0) bottom left, (1.0,1.0) top right, (0.5,0.5) center 00363 */ 00364 canvascoord[0] = (GLfloat) viewport[0] / viewport[2]; 00365 canvascoord[0] *= -1; 00366 canvascoord[1] = (GLfloat) (texturewidth - viewport[0]) / viewport[2]; 00367 00368 canvascoord[2] = (GLfloat) viewport[1] / viewport[3]; 00369 canvascoord[2] *= -1; 00370 canvascoord[3] = (GLfloat)(textureheight - viewport[1]) / viewport[3]; 00371 } 00372 00373 void RAS_2DFilterManager::RenderFilters(RAS_ICanvas* canvas) 00374 { 00375 bool need_depth=false; 00376 bool need_luminance=false; 00377 int num_filters = 0; 00378 00379 int passindex; 00380 00381 if(!isshadersupported) 00382 return; 00383 00384 for(passindex =0; passindex<MAX_RENDER_PASS; passindex++) 00385 { 00386 if(m_filters[passindex] && m_enabled[passindex]){ 00387 num_filters ++; 00388 if(texflag[passindex] & 0x1) 00389 need_depth = true; 00390 if(texflag[passindex] & 0x2) 00391 need_luminance = true; 00392 if(need_depth && need_luminance) 00393 break; 00394 } 00395 } 00396 00397 if(num_filters <= 0) 00398 return; 00399 00400 GLuint viewport[4]={0}; 00401 glGetIntegerv(GL_VIEWPORT,(GLint *)viewport); 00402 00403 if(canvaswidth != canvas->GetWidth() || canvasheight != canvas->GetHeight()) 00404 { 00405 UpdateOffsetMatrix(canvas); 00406 UpdateCanvasTextureCoord((unsigned int*)viewport); 00407 need_tex_update = true; 00408 } 00409 00410 if(need_tex_update) 00411 { 00412 SetupTextures(need_depth, need_luminance); 00413 need_tex_update = false; 00414 } 00415 00416 if(need_depth){ 00417 glActiveTextureARB(GL_TEXTURE1); 00418 glBindTexture(GL_TEXTURE_2D, texname[1]); 00419 glCopyTexImage2D(GL_TEXTURE_2D,0,GL_DEPTH_COMPONENT, 0, 0, texturewidth,textureheight, 0); 00420 } 00421 00422 if(need_luminance){ 00423 glActiveTextureARB(GL_TEXTURE2); 00424 glBindTexture(GL_TEXTURE_2D, texname[2]); 00425 glCopyTexImage2D(GL_TEXTURE_2D,0,GL_LUMINANCE16, 0, 0, texturewidth,textureheight, 0); 00426 } 00427 00428 // reverting to texunit 0, without this we get bug [#28462] 00429 glActiveTextureARB(GL_TEXTURE0); 00430 00431 glViewport(0,0, texturewidth, textureheight); 00432 00433 glDisable(GL_DEPTH_TEST); 00434 // in case the previous material was wire 00435 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 00436 // if the last rendered face had alpha add it would messes with the color of the plane we apply 2DFilter to 00437 glDisable(GL_BLEND); 00438 glPushMatrix(); //GL_MODELVIEW 00439 glLoadIdentity(); // GL_MODELVIEW 00440 glMatrixMode(GL_TEXTURE); 00441 glLoadIdentity(); 00442 glMatrixMode(GL_PROJECTION); 00443 glPushMatrix(); 00444 glLoadIdentity(); 00445 00446 for(passindex =0; passindex<MAX_RENDER_PASS; passindex++) 00447 { 00448 if(m_filters[passindex] && m_enabled[passindex]) 00449 { 00450 StartShaderProgram(passindex); 00451 00452 glActiveTextureARB(GL_TEXTURE0); 00453 glBindTexture(GL_TEXTURE_2D, texname[0]); 00454 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, texturewidth, textureheight, 0); 00455 glClear(GL_COLOR_BUFFER_BIT); 00456 00457 glBegin(GL_QUADS); 00458 glColor4f(1.f, 1.f, 1.f, 1.f); 00459 glTexCoord2f(1.0, 1.0); glMultiTexCoord2fARB(GL_TEXTURE3_ARB, canvascoord[1], canvascoord[3]); glVertex2f(1,1); 00460 glTexCoord2f(0.0, 1.0); glMultiTexCoord2fARB(GL_TEXTURE3_ARB, canvascoord[0], canvascoord[3]); glVertex2f(-1,1); 00461 glTexCoord2f(0.0, 0.0); glMultiTexCoord2fARB(GL_TEXTURE3_ARB, canvascoord[0], canvascoord[2]); glVertex2f(-1,-1); 00462 glTexCoord2f(1.0, 0.0); glMultiTexCoord2fARB(GL_TEXTURE3_ARB, canvascoord[1], canvascoord[2]); glVertex2f(1,-1); 00463 glEnd(); 00464 } 00465 } 00466 00467 glEnable(GL_DEPTH_TEST); 00468 glViewport(viewport[0],viewport[1],viewport[2],viewport[3]); 00469 EndShaderProgram(); 00470 glPopMatrix(); 00471 glMatrixMode(GL_MODELVIEW); 00472 glPopMatrix(); 00473 } 00474 00475 void RAS_2DFilterManager::EnableFilter(vector<STR_String>& propNames, void* gameObj, RAS_2DFILTER_MODE mode, int pass, STR_String& text) 00476 { 00477 if(!isshadersupported) 00478 return; 00479 if(pass<0 || pass>=MAX_RENDER_PASS) 00480 return; 00481 need_tex_update = true; 00482 if(mode == RAS_2DFILTER_DISABLED) 00483 { 00484 m_enabled[pass] = 0; 00485 return; 00486 } 00487 00488 if(mode == RAS_2DFILTER_ENABLED) 00489 { 00490 m_enabled[pass] = 1; 00491 return; 00492 } 00493 00494 if(mode == RAS_2DFILTER_NOFILTER) 00495 { 00496 if(m_filters[pass]) 00497 glDeleteObjectARB(m_filters[pass]); 00498 m_enabled[pass] = 0; 00499 m_filters[pass] = 0; 00500 m_gameObjects[pass] = NULL; 00501 m_properties[pass].clear(); 00502 texflag[pass] = 0; 00503 return; 00504 } 00505 00506 if(mode == RAS_2DFILTER_CUSTOMFILTER) 00507 { 00508 if(m_filters[pass]) 00509 glDeleteObjectARB(m_filters[pass]); 00510 m_filters[pass] = CreateShaderProgram(text.Ptr()); 00511 m_gameObjects[pass] = gameObj; 00512 AnalyseShader(pass, propNames); 00513 m_enabled[pass] = 1; 00514 return; 00515 } 00516 00517 // We've checked all other cases, which means we must be dealing with a builtin filter 00518 if(m_filters[pass]) 00519 glDeleteObjectARB(m_filters[pass]); 00520 m_filters[pass] = CreateShaderProgram(mode); 00521 m_gameObjects[pass] = NULL; 00522 AnalyseShader(pass, propNames); 00523 m_enabled[pass] = 1; 00524 }