Index: source/blender/makesdna/DNA_actuator_types.h =================================================================== --- source/blender/makesdna/DNA_actuator_types.h (revision 32801) +++ source/blender/makesdna/DNA_actuator_types.h (working copy) @@ -474,9 +474,11 @@ #define ACT_2DFILTER_GRAYSCALE 9 #define ACT_2DFILTER_SEPIA 10 #define ACT_2DFILTER_INVERT 11 -#define ACT_2DFILTER_CUSTOMFILTER 12 -#define ACT_2DFILTER_NUMBER_OF_FILTERS 13 +#define ACT_2DFILTER_CUSTOMFILTER 12 // Keep the custom Filter here to still work with old .blends +#define ACT_2DFILTER_CELL 13 +#define ACT_2DFILTER_NUMBER_OF_FILTERS 14 + /* parentactuator->type */ #define ACT_PARENT_SET 0 #define ACT_PARENT_REMOVE 1 Index: source/blender/makesrna/intern/rna_actuator.c =================================================================== --- source/blender/makesrna/intern/rna_actuator.c (revision 32801) +++ source/blender/makesrna/intern/rna_actuator.c (working copy) @@ -1624,7 +1624,8 @@ {ACT_2DFILTER_GRAYSCALE, "GRAYSCALE", 0, "Gray Scale", ""}, {ACT_2DFILTER_SEPIA, "SEPIA", 0, "Sepia", ""}, {ACT_2DFILTER_INVERT, "INVERT", 0, "Invert", ""}, - {ACT_2DFILTER_CUSTOMFILTER, "CUSTOMFILTER", 0, "Custom Filter", ""}, + {ACT_2DFILTER_CELL,"CELL",0,"Outline", ""}, + {ACT_2DFILTER_CUSTOMFILTER, "CUSTOMFILTER", 0, "Custom Filter", ""}, // {ACT_2DFILTER_NUMBER_OF_FILTERS, "", 0, "Do not use it. Sentinel", ""}, {0, NULL, 0, NULL, NULL}}; Index: source/gameengine/Converter/KX_ConvertActuators.cpp =================================================================== --- source/gameengine/Converter/KX_ConvertActuators.cpp (revision 32801) +++ source/gameengine/Converter/KX_ConvertActuators.cpp (working copy) @@ -951,6 +951,9 @@ case ACT_2DFILTER_INVERT: filtermode = RAS_2DFilterManager::RAS_2DFILTER_INVERT; break; + case ACT_2DFILTER_CELL: + filtermode = RAS_2DFilterManager::RAS_2DFILTER_CELL; + break; case ACT_2DFILTER_CUSTOMFILTER: filtermode = RAS_2DFilterManager::RAS_2DFILTER_CUSTOMFILTER; break; @@ -967,9 +970,9 @@ filtermode = RAS_2DFilterManager::RAS_2DFILTER_NOFILTER; break; } - - tmp = new SCA_2DFilterActuator(gameobj, filtermode, _2dfilter->flag, - _2dfilter->float_arg,_2dfilter->int_arg,ketsjiEngine->GetRasterizer(),scene); + tmp = new SCA_2DFilterActuator(gameobj, filtermode, _2dfilter->flag, + _2dfilter->float_arg,_2dfilter->int_arg, + ketsjiEngine->GetRasterizer(),scene); if (_2dfilter->text) { Index: source/gameengine/Rasterizer/RAS_2DFilterManager.cpp =================================================================== --- source/gameengine/Rasterizer/RAS_2DFilterManager.cpp (revision 32801) +++ source/gameengine/Rasterizer/RAS_2DFilterManager.cpp (working copy) @@ -40,6 +40,7 @@ #include "RAS_OpenGLFilters/RAS_GrayScale2DFilter.h" #include "RAS_OpenGLFilters/RAS_Sepia2DFilter.h" #include "RAS_OpenGLFilters/RAS_Invert2DFilter.h" +#include "RAS_OpenGLFilters/RAS_Cell2DFilter.h" #include "STR_String.h" #include "RAS_ICanvas.h" @@ -178,6 +179,8 @@ return CreateShaderProgram(SepiaFragmentShader); case RAS_2DFILTER_INVERT: return CreateShaderProgram(InvertFragmentShader); + case RAS_2DFILTER_CELL: + return CreateShaderProgram(CellFragmentShader); } return 0; } @@ -511,7 +514,6 @@ 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]); @@ -519,4 +521,4 @@ m_gameObjects[pass] = NULL; AnalyseShader(pass, propNames); m_enabled[pass] = 1; -} +} \ No newline at end of file Index: source/gameengine/Rasterizer/RAS_2DFilterManager.h =================================================================== --- source/gameengine/Rasterizer/RAS_2DFilterManager.h (revision 32801) +++ source/gameengine/Rasterizer/RAS_2DFilterManager.h (working copy) @@ -91,7 +91,8 @@ RAS_2DFILTER_GRAYSCALE, RAS_2DFILTER_SEPIA, RAS_2DFILTER_INVERT, - RAS_2DFILTER_CUSTOMFILTER, + RAS_2DFILTER_CUSTOMFILTER, + RAS_2DFILTER_CELL, RAS_2DFILTER_NUMBER_OF_FILTERS }; Index: source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Cell2DFilter.h =================================================================== --- source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Cell2DFilter.h (revision 0) +++ source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Cell2DFilter.h (revision 0) @@ -0,0 +1,100 @@ +/** + * ***** 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. + * + * 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): Vitor Balbio + * + * ***** END GPL LICENSE BLOCK ***** + */ +// Based in Paper "Combining Screen-Space Ambient Occlusion and Cartoon Rendering on Graphics Hardware " +// Outline code by : Brett Lajzer and Dan Nottingham +// Normals from Depth code by: Martinsh +// Final Code: Vitor Balbio + + + +#ifndef __RAS_CELL2DFILTER +#define __RAS_CELL2DFILTER + +const char * CellFragmentShader=STRINGIFY(uniform sampler2D bgl_DepthTexture; +uniform sampler2D bgl_RenderedTexture; + +const float near = 0.01; +const float far = 1000000.0; + + +vec4 normal(vec2 co) +{ + vec4 depth = texture2D(bgl_DepthTexture, co); + float depth1 = -near / (-1.0+float(depth) * ((far-near)/far)); + vec4 worldPoint = vec4(co,depth1,1) * depth1; + vec3 normal = normalize(cross(dFdx(worldPoint.xyz),dFdy(worldPoint.xyz))); + return vec4(normal*0.5+0.5,0); +} + +void main(void) +{ + vec2 offsets [8]; + vec2 texcoord = vec2(gl_TexCoord[0]).st; + + vec4 depth = texture2D(bgl_DepthTexture, gl_TexCoord[0].st); + vec4 norm = normal(texcoord); + + float dp = 1.0 / 512.0; + offsets[0] = vec2(dp,dp); + offsets[1] = vec2(dp,0); + offsets[2] = vec2(dp,dp); + offsets[3] = vec2(0,dp); + offsets[4] = vec2(0,dp); + offsets[5] = vec2(dp,dp); + offsets[6] = vec2(dp,0); + offsets[7] = vec2(dp,dp); + + float darkness_depth = 0.0; + float darkness_norm = 0.0; + float base_depth = depth.r; + + vec3 base_norm = normalize(norm.xyz); + + float threshhold_depth = 0.05 * (1.0 - depth.r); + float threshhold_norm = 0.95; + + for(int i = 0; i < 8; i++) + { + depth = texture2D(bgl_DepthTexture, texcoord + offsets[i]); + norm.xyz = normalize(norm.xyz); + + if (abs(depth.r - base_depth) > threshhold_depth) + darkness_depth += 1.0; + if (dot(norm.xyz, base_norm) < threshhold_norm) + darkness_norm += 1.0; + } + + float illum = 1.0- (darkness_depth + darkness_norm); + + vec4 OutlinePass = vec4(illum, illum, illum,1.0); + vec4 ColorPass = texture2D(bgl_RenderedTexture, texcoord); + gl_FragColor = ColorPass*OutlinePass; + + +} +); +#endif
Index: source/blender/makesdna/DNA_actuator_types.h =================================================================== --- source/blender/makesdna/DNA_actuator_types.h (revision 32801) +++ source/blender/makesdna/DNA_actuator_types.h (working copy) @@ -474,9 +474,11 @@ #define ACT_2DFILTER_GRAYSCALE 9 #define ACT_2DFILTER_SEPIA 10 #define ACT_2DFILTER_INVERT 11 -#define ACT_2DFILTER_CUSTOMFILTER 12 -#define ACT_2DFILTER_NUMBER_OF_FILTERS 13 +#define ACT_2DFILTER_CUSTOMFILTER 12 // Keep the custom Filter here to still work with old .blends +#define ACT_2DFILTER_CELL 13 +#define ACT_2DFILTER_NUMBER_OF_FILTERS 14 + /* parentactuator->type */ #define ACT_PARENT_SET 0 #define ACT_PARENT_REMOVE 1 Index: source/blender/makesrna/intern/rna_actuator.c =================================================================== --- source/blender/makesrna/intern/rna_actuator.c (revision 32801) +++ source/blender/makesrna/intern/rna_actuator.c (working copy) @@ -1624,7 +1624,8 @@ {ACT_2DFILTER_GRAYSCALE, "GRAYSCALE", 0, "Gray Scale", ""}, {ACT_2DFILTER_SEPIA, "SEPIA", 0, "Sepia", ""}, {ACT_2DFILTER_INVERT, "INVERT", 0, "Invert", ""}, - {ACT_2DFILTER_CUSTOMFILTER, "CUSTOMFILTER", 0, "Custom Filter", ""}, + {ACT_2DFILTER_CELL,"CELL",0,"Outline", ""}, + {ACT_2DFILTER_CUSTOMFILTER, "CUSTOMFILTER", 0, "Custom Filter", ""}, // {ACT_2DFILTER_NUMBER_OF_FILTERS, "", 0, "Do not use it. Sentinel", ""}, {0, NULL, 0, NULL, NULL}}; Index: source/gameengine/Converter/KX_ConvertActuators.cpp =================================================================== --- source/gameengine/Converter/KX_ConvertActuators.cpp (revision 32801) +++ source/gameengine/Converter/KX_ConvertActuators.cpp (working copy) @@ -951,6 +951,9 @@ case ACT_2DFILTER_INVERT: filtermode = RAS_2DFilterManager::RAS_2DFILTER_INVERT; break; + case ACT_2DFILTER_CELL: + filtermode = RAS_2DFilterManager::RAS_2DFILTER_CELL; + break; case ACT_2DFILTER_CUSTOMFILTER: filtermode = RAS_2DFilterManager::RAS_2DFILTER_CUSTOMFILTER; break; @@ -967,9 +970,9 @@ filtermode = RAS_2DFilterManager::RAS_2DFILTER_NOFILTER; break; } - - tmp = new SCA_2DFilterActuator(gameobj, filtermode, _2dfilter->flag, - _2dfilter->float_arg,_2dfilter->int_arg,ketsjiEngine->GetRasterizer(),scene); + tmp = new SCA_2DFilterActuator(gameobj, filtermode, _2dfilter->flag, + _2dfilter->float_arg,_2dfilter->int_arg, + ketsjiEngine->GetRasterizer(),scene); if (_2dfilter->text) { Index: source/gameengine/Rasterizer/RAS_2DFilterManager.cpp =================================================================== --- source/gameengine/Rasterizer/RAS_2DFilterManager.cpp (revision 32801) +++ source/gameengine/Rasterizer/RAS_2DFilterManager.cpp (working copy) @@ -40,6 +40,7 @@ #include "RAS_OpenGLFilters/RAS_GrayScale2DFilter.h" #include "RAS_OpenGLFilters/RAS_Sepia2DFilter.h" #include "RAS_OpenGLFilters/RAS_Invert2DFilter.h" +#include "RAS_OpenGLFilters/RAS_Cell2DFilter.h" #include "STR_String.h" #include "RAS_ICanvas.h" @@ -178,6 +179,8 @@ return CreateShaderProgram(SepiaFragmentShader); case RAS_2DFILTER_INVERT: return CreateShaderProgram(InvertFragmentShader); + case RAS_2DFILTER_CELL: + return CreateShaderProgram(CellFragmentShader); } return 0; } @@ -511,7 +514,6 @@ 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]); @@ -519,4 +521,4 @@ m_gameObjects[pass] = NULL; AnalyseShader(pass, propNames); m_enabled[pass] = 1; -} +} \ No newline at end of file Index: source/gameengine/Rasterizer/RAS_2DFilterManager.h =================================================================== --- source/gameengine/Rasterizer/RAS_2DFilterManager.h (revision 32801) +++ source/gameengine/Rasterizer/RAS_2DFilterManager.h (working copy) @@ -91,7 +91,8 @@ RAS_2DFILTER_GRAYSCALE, RAS_2DFILTER_SEPIA, RAS_2DFILTER_INVERT, - RAS_2DFILTER_CUSTOMFILTER, + RAS_2DFILTER_CUSTOMFILTER, + RAS_2DFILTER_CELL, RAS_2DFILTER_NUMBER_OF_FILTERS }; Index: source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Cell2DFilter.h =================================================================== --- source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Cell2DFilter.h (revision 0) +++ source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Cell2DFilter.h (revision 0) @@ -0,0 +1,100 @@ +/** + * ***** 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. + * + * 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): Vitor Balbio + * + * ***** END GPL LICENSE BLOCK ***** + */ +// Based in Paper "Combining Screen-Space Ambient Occlusion and Cartoon Rendering on Graphics Hardware " +// Outline code by : Brett Lajzer and Dan Nottingham +// Normals from Depth code by: Martinsh +// Final Code: Vitor Balbio + + + +#ifndef __RAS_CELL2DFILTER +#define __RAS_CELL2DFILTER + +const char * CellFragmentShader=STRINGIFY(uniform sampler2D bgl_DepthTexture; +uniform sampler2D bgl_RenderedTexture; + +const float near = 0.01; +const float far = 1000000.0; + + +vec4 normal(vec2 co) +{ + vec4 depth = texture2D(bgl_DepthTexture, co); + float depth1 = -near / (-1.0+float(depth) * ((far-near)/far)); + vec4 worldPoint = vec4(co,depth1,1) * depth1; + vec3 normal = normalize(cross(dFdx(worldPoint.xyz),dFdy(worldPoint.xyz))); + return vec4(normal*0.5+0.5,0); +} + +void main(void) +{ + vec2 offsets [8]; + vec2 texcoord = vec2(gl_TexCoord[0]).st; + + vec4 depth = texture2D(bgl_DepthTexture, gl_TexCoord[0].st); + vec4 norm = normal(texcoord); + + float dp = 1.0 / 512.0; + offsets[0] = vec2(dp,dp); + offsets[1] = vec2(dp,0); + offsets[2] = vec2(dp,dp); + offsets[3] = vec2(0,dp); + offsets[4] = vec2(0,dp); + offsets[5] = vec2(dp,dp); + offsets[6] = vec2(dp,0); + offsets[7] = vec2(dp,dp); + + float darkness_depth = 0.0; + float darkness_norm = 0.0; + float base_depth = depth.r; + + vec3 base_norm = normalize(norm.xyz); + + float threshhold_depth = 0.05 * (1.0 - depth.r); + float threshhold_norm = 0.95; + + for(int i = 0; i < 8; i++) + { + depth = texture2D(bgl_DepthTexture, texcoord + offsets[i]); + norm.xyz = normalize(norm.xyz); + + if (abs(depth.r - base_depth) > threshhold_depth) + darkness_depth += 1.0; + if (dot(norm.xyz, base_norm) < threshhold_norm) + darkness_norm += 1.0; + } + + float illum = 1.0- (darkness_depth + darkness_norm); + + vec4 OutlinePass = vec4(illum, illum, illum,1.0); + vec4 ColorPass = texture2D(bgl_RenderedTexture, texcoord); + gl_FragColor = ColorPass*OutlinePass; + + +} +); +#endif
|