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