/* * ***** BEGIN GPL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. The Blender * Foundation also sells licenses for use in proprietary software under * the Blender License. See http://www.blender.org/BL/ for information * about this. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. * * The Original Code is: all of this file. * * Contributor(s): none yet. * * ***** END GPL LICENSE BLOCK ***** */ #define STRINGIFY(A) #A #include "RAS_OpenGLFilters/RAS_Blur2DFilter.h" #include "RAS_OpenGLFilters/RAS_Sharpen2DFilter.h" #include "RAS_OpenGLFilters/RAS_Dilation2DFilter.h" #include "RAS_OpenGLFilters/RAS_Erosion2DFilter.h" #include "RAS_OpenGLFilters/RAS_Laplacian2DFilter.h" #include "RAS_OpenGLFilters/RAS_Sobel2DFilter.h" #include "RAS_OpenGLFilters/RAS_Prewitt2DFilter.h" #include "RAS_OpenGLFilters/RAS_GrayScale2DFilter.h" #include "RAS_OpenGLFilters/RAS_Sepia2DFilter.h" #include "RAS_OpenGLFilters/RAS_Invert2DFilter.h" #include "STR_String.h" #include "RAS_ICanvas.h" #include "RAS_Rect.h" #include "RAS_2DFilterManager.h" #include #include "GL/glew.h" #include #include "Value.h" RAS_2DFilterManager::RAS_2DFilterManager(): texturewidth(-1), textureheight(-1), canvaswidth(-1), canvasheight(-1), numberoffilters(0), need_tex_update(true) { isshadersupported = GLEW_ARB_shader_objects && GLEW_ARB_fragment_shader && GLEW_ARB_multitexture; /* used to return before 2.49 but need to initialize values so dont */ if(!isshadersupported) std::cout<<"shaders not supported!" << std::endl; int passindex; for(passindex =0; passindex& propNames) { texflag[passindex] = 0; if(glGetUniformLocationARB(m_filters[passindex], "bgl_DepthTexture") != -1) { if(GLEW_ARB_depth_texture) texflag[passindex] |= 0x1; } if(glGetUniformLocationARB(m_filters[passindex], "bgl_LuminanceTexture") != -1) { texflag[passindex] |= 0x2; } if(m_gameObjects[passindex]) { int objProperties = propNames.size(); int i; for(i=0; iGetPropertyNumber(m_properties[passindex][i], 0.0); glUniform1fARB(uniformLoc,value); } } } void RAS_2DFilterManager::EndShaderProgram() { glUseProgramObjectARB(0); } void RAS_2DFilterManager::FreeTextures() { if(texname[0]!=(unsigned int)-1) glDeleteTextures(1, (GLuint*)&texname[0]); if(texname[1]!=(unsigned int)-1) glDeleteTextures(1, (GLuint*)&texname[1]); if(texname[2]!=(unsigned int)-1) glDeleteTextures(1, (GLuint*)&texname[2]); } void RAS_2DFilterManager::SetupTextures(bool depth, bool luminance) { FreeTextures(); glGenTextures(1, (GLuint*)&texname[0]); glBindTexture(GL_TEXTURE_2D, texname[0]); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texturewidth, textureheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); if(depth){ glGenTextures(1, (GLuint*)&texname[1]); glBindTexture(GL_TEXTURE_2D, texname[1]); glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, texturewidth,textureheight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE,NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); } if(luminance){ glGenTextures(1, (GLuint*)&texname[2]); glBindTexture(GL_TEXTURE_2D, texname[2]); glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE16, texturewidth, textureheight, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); } } void RAS_2DFilterManager::UpdateOffsetMatrix(RAS_ICanvas* canvas) { RAS_Rect canvas_rect = canvas->GetWindowArea(); canvaswidth = canvas->GetWidth(); canvasheight = canvas->GetHeight(); texturewidth = canvaswidth + canvas_rect.GetLeft(); textureheight = canvasheight + canvas_rect.GetBottom(); GLint i,j; i = 0; while ((1 << i) <= texturewidth) i++; texturewidth = (1 << (i)); // Now for height i = 0; while ((1 << i) <= textureheight) i++; textureheight = (1 << (i)); GLfloat xInc = 1.0f / (GLfloat)texturewidth; GLfloat yInc = 1.0f / (GLfloat)textureheight; for (i = 0; i < 3; i++) { for (j = 0; j < 3; j++) { textureoffsets[(((i*3)+j)*2)+0] = (-1.0f * xInc) + ((GLfloat)i * xInc); textureoffsets[(((i*3)+j)*2)+1] = (-1.0f * yInc) + ((GLfloat)j * yInc); } } } void RAS_2DFilterManager::UpdateCanvasTextureCoord(unsigned int * viewport) { /* This function update canvascoord[]. These parameters are used to create texcoord[1] That way we can access the texcoord relative to the canvas: (0.0,0.0) bottom left, (1.0,1.0) top right, (0.5,0.5) center */ canvascoord[0] = (GLfloat) viewport[0] / viewport[2]; canvascoord[0] *= -1; canvascoord[1] = (GLfloat) (texturewidth - viewport[0]) / viewport[2]; canvascoord[2] = (GLfloat) viewport[1] / viewport[3]; canvascoord[2] *= -1; canvascoord[3] = (GLfloat)(textureheight - viewport[1]) / viewport[3]; } void RAS_2DFilterManager::RenderFilters(RAS_ICanvas* canvas) { bool need_depth=false; bool need_luminance=false; int num_filters = 0; int passindex; if(!isshadersupported) return; for(passindex =0; passindexGetWidth() || canvasheight != canvas->GetHeight()) { UpdateOffsetMatrix(canvas); UpdateCanvasTextureCoord((unsigned int*)viewport); need_tex_update = true; } if(need_tex_update) { SetupTextures(need_depth, need_luminance); need_tex_update = false; } if(need_depth){ glActiveTextureARB(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, texname[1]); glCopyTexImage2D(GL_TEXTURE_2D,0,GL_DEPTH_COMPONENT, 0, 0, texturewidth,textureheight, 0); } if(need_luminance){ glActiveTextureARB(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, texname[2]); glCopyTexImage2D(GL_TEXTURE_2D,0,GL_LUMINANCE16, 0, 0, texturewidth,textureheight, 0); } glViewport(0,0, texturewidth, textureheight); glDisable(GL_DEPTH_TEST); // if the last rendered face had alpha add it would messes with the color of the plane we apply 2DFilter to glDisable(GL_BLEND); glPushMatrix(); //GL_MODELVIEW glLoadIdentity(); // GL_MODELVIEW glMatrixMode(GL_TEXTURE); glLoadIdentity(); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); for(passindex =0; passindex& propNames, void* gameObj, RAS_2DFILTER_MODE mode, int pass, STR_String& text) { if(!isshadersupported) return; if(pass<0 || pass>=MAX_RENDER_PASS) return; need_tex_update = true; if(mode == RAS_2DFILTER_DISABLED) { m_enabled[pass] = 0; return; } if(mode == RAS_2DFILTER_ENABLED) { m_enabled[pass] = 1; return; } if(mode == RAS_2DFILTER_NOFILTER) { if(m_filters[pass]) glDeleteObjectARB(m_filters[pass]); m_enabled[pass] = 0; m_filters[pass] = 0; m_gameObjects[pass] = NULL; m_properties[pass].clear(); texflag[pass] = 0; return; } if(mode == RAS_2DFILTER_CUSTOMFILTER) { if(m_filters[pass]) glDeleteObjectARB(m_filters[pass]); m_filters[pass] = CreateShaderProgram(text.Ptr()); m_gameObjects[pass] = gameObj; AnalyseShader(pass, propNames); m_enabled[pass] = 1; return; } // We've checked all other cases, which means we must be dealing with a builtin filter if(m_filters[pass]) glDeleteObjectARB(m_filters[pass]); m_filters[pass] = CreateShaderProgram(mode); m_gameObjects[pass] = NULL; AnalyseShader(pass, propNames); m_enabled[pass] = 1; }