diff --git a/cocos/renderer/CCGLProgram.cpp b/cocos/renderer/CCGLProgram.cpp index 8db0c5904a..6941241989 100644 --- a/cocos/renderer/CCGLProgram.cpp +++ b/cocos/renderer/CCGLProgram.cpp @@ -449,14 +449,17 @@ bool GLProgram::compileShader(GLuint * shader, GLenum type, const GLchar* source "uniform vec3 CC_DirLightSourceDirection[CC_MAX_DIRECTIONAL_LIGHT_NUM]; \n" "#endif \n" "#if CC_MAX_POINT_LIGHT_NUM \n" - "uniform vec4 CC_PointLightSourceColor[CC_MAX_POINT_LIGHT_NUM]; \n" + "uniform vec3 CC_PointLightSourceColor[CC_MAX_POINT_LIGHT_NUM]; \n" "uniform vec3 CC_PointLightSourcePosition[CC_MAX_POINT_LIGHT_NUM]; \n" + "uniform float CC_PointLightSourceRangeInverse[CC_MAX_POINT_LIGHT_NUM]; \n" "#endif \n" "#if CC_MAX_SPOT_LIGHT_NUM \n" "uniform vec3 CC_SpotLightSourceColor[CC_MAX_SPOT_LIGHT_NUM]; \n" "uniform vec3 CC_SpotLightSourcePosition[CC_MAX_SPOT_LIGHT_NUM]; \n" "uniform vec3 CC_SpotLightSourceDirection[CC_MAX_SPOT_LIGHT_NUM]; \n" - "uniform vec3 CC_SpotLightSourceParams[CC_MAX_SPOT_LIGHT_NUM]; \n" + "uniform float CC_SpotLightSourceInnerAngleCos[CC_MAX_SPOT_LIGHT_NUM]; \n" + "uniform float CC_SpotLightSourceOuterAngleCos[CC_MAX_SPOT_LIGHT_NUM]; \n" + "uniform float CC_SpotLightSourceRangeInverse[CC_MAX_SPOT_LIGHT_NUM]; \n" "#endif \n" "uniform vec4 CC_AmbientColor; \n" }; @@ -556,9 +559,9 @@ void GLProgram::updateUniforms() // _builtInUniforms[UNIFORM_ENABLED_SPOT_LIGHT_NUM] != -1 // ); - _flags.usesLights = CC_MAX_DIRECTIONAL_LIGHT_NUM || - CC_MAX_POINT_LIGHT_NUM || - CC_MAX_SPOT_LIGHT_NUM; + _flags.usesLights = (0 < CC_MAX_DIRECTIONAL_LIGHT_NUM) || + (0 < CC_MAX_POINT_LIGHT_NUM) || + (0 < CC_MAX_SPOT_LIGHT_NUM); _flags.usesP = _builtInUniforms[UNIFORM_P_MATRIX] != -1; _flags.usesMV = _builtInUniforms[UNIFORM_MV_MATRIX] != -1; _flags.usesMVP = _builtInUniforms[UNIFORM_MVP_MATRIX] != -1; @@ -1005,9 +1008,11 @@ void GLProgram::setUniformsForBuiltins(const Mat4 &matrixMV) CCASSERT(enabledPointLightNum < CC_MAX_POINT_LIGHT_NUM, ""); Mat4 mat= light->getNodeToWorldTransform(); sprintf(str, "CC_PointLightSourceColor[%d]", enabledPointLightNum); - setUniformLocationWith4f(glGetUniformLocation(_program, str), col.r / 255.0f, col.g / 255.0f, col.b / 255.0f, 1.0f / light->getRange()); + setUniformLocationWith3f(glGetUniformLocation(_program, str), col.r / 255.0f, col.g / 255.0f, col.b / 255.0f); sprintf(str, "CC_PointLightSourcePosition[%d]", enabledPointLightNum); setUniformLocationWith3f(glGetUniformLocation(_program, str), mat.m[12], mat.m[13], mat.m[14]); + sprintf(str, "CC_PointLightSourceRangeInverse[%d]", enabledPointLightNum); + setUniformLocationWith1f(glGetUniformLocation(_program, str), 1.0f / light->getRange()); ++enabledPointLightNum; } else @@ -1022,8 +1027,12 @@ void GLProgram::setUniformsForBuiltins(const Mat4 &matrixMV) setUniformLocationWith3f(glGetUniformLocation(_program, str), mat.m[12], mat.m[13], mat.m[14]); sprintf(str, "CC_SpotLightSourceDirection[%d]", enabledSpotLightNum); setUniformLocationWith3f(glGetUniformLocation(_program, str), dir.x, dir.y, dir.z); - sprintf(str, "CC_SpotLightSourceParams[%d]", enabledSpotLightNum); - setUniformLocationWith3f(glGetUniformLocation(_program, str), cosf(light->getInnerAngle()), cosf(light->getOuterAngle()), 1.0f / light->getRange()); + sprintf(str, "CC_SpotLightSourceInnerAngleCos[%d]", enabledSpotLightNum); + setUniformLocationWith1f(glGetUniformLocation(_program, str), cosf(light->getInnerAngle())); + sprintf(str, "CC_SpotLightSourceOuterAngleCos[%d]", enabledSpotLightNum); + setUniformLocationWith1f(glGetUniformLocation(_program, str), cosf(light->getOuterAngle())); + sprintf(str, "CC_SpotLightSourceRangeInverse[%d]", enabledSpotLightNum); + setUniformLocationWith1f(glGetUniformLocation(_program, str), 1.0f / light->getRange()); ++enabledSpotLightNum; } } diff --git a/cocos/renderer/ccShader_3D_ColorNormal.frag b/cocos/renderer/ccShader_3D_ColorNormal.frag index 55749f6d3c..bec8b94dfe 100644 --- a/cocos/renderer/ccShader_3D_ColorNormal.frag +++ b/cocos/renderer/ccShader_3D_ColorNormal.frag @@ -27,53 +27,63 @@ varying vec3 v_normal; uniform vec4 u_color; +vec3 computeLighting(vec3 normalVector, vec3 lightDirection, vec3 lightColor, float attenuation) +{ + float diffuse = max(dot(normalVector, lightDirection), 0.0); + vec3 diffuseColor = lightColor * diffuse * attenuation; + + return diffuseColor; +} + void main(void) { - vec4 intensity = vec4(0.0, 0.0, 0.0, 1.0); -\n#if (CC_MAX_DIRECTIONAL_LIGHT_NUM || CC_MAX_POINT_LIGHT_NUM || CC_MAX_SPOT_LIGHT_NUM)\n +\n#if ((CC_MAX_DIRECTIONAL_LIGHT_NUM > 0) || (CC_MAX_POINT_LIGHT_NUM > 0) || (CC_MAX_SPOT_LIGHT_NUM > 0))\n vec3 normal = normalize(v_normal); \n#endif\n + vec4 combinedColor = CC_AmbientColor; + + // Directional light contribution \n#if (CC_MAX_DIRECTIONAL_LIGHT_NUM > 0)\n - - for (int n = 0; n < CC_MAX_DIRECTIONAL_LIGHT_NUM; ++n) + for (int i = 0; i < CC_MAX_DIRECTIONAL_LIGHT_NUM; ++i) { - intensity.xyz += CC_DirLightSourceColor[n] * max(0.0, dot(-CC_DirLightSourceDirection[n], normal)); + vec3 lightDirection = normalize(CC_DirLightSourceDirection[i] * 2.0); + combinedColor.xyz += computeLighting(normal, -lightDirection, CC_DirLightSourceColor[i], 1.0); } - \n#endif\n + // Point light contribution \n#if (CC_MAX_POINT_LIGHT_NUM > 0)\n - - for (int n = 0; n < CC_MAX_POINT_LIGHT_NUM; ++n) + for (int i = 0; i < CC_MAX_POINT_LIGHT_NUM; ++i) { - vec3 dir = v_vertexToPointLightDirection[n]; - vec3 ldir = dir * CC_PointLightSourceColor[n].w; + vec3 ldir = v_vertexToPointLightDirection[i] * CC_PointLightSourceRangeInverse[i]; float attenuation = clamp(1.0 - dot(ldir, ldir), 0.0, 1.0); - intensity.xyz += CC_PointLightSourceColor[n] * max(0.0, dot(normalize(dir), normal)) * attenuation; + combinedColor.xyz += computeLighting(normal, normalize(v_vertexToPointLightDirection[i]), CC_PointLightSourceColor[i], attenuation); } - \n#endif\n + // Spot light contribution \n#if (CC_MAX_SPOT_LIGHT_NUM > 0)\n - - for (int n = 0; n < CC_MAX_SPOT_LIGHT_NUM; ++n) + for (int i = 0; i < CC_MAX_SPOT_LIGHT_NUM; ++i) { - vec3 dir = v_vertexToSpotLightDirection[n]; - vec3 ldir = dir * CC_SpotLightSourceParams[n].z; + // Compute range attenuation + vec3 ldir = v_vertexToSpotLightDirection[i] * CC_SpotLightSourceRangeInverse[i]; float attenuation = clamp(1.0 - dot(ldir, ldir), 0.0, 1.0); - dir = normalize(dir); - float spotDot = dot(normalize(dir), -CC_SpotLightSourceDirection[n]); - float innerCos = CC_SpotLightSourceParams[n].x; - float outerCos = CC_SpotLightSourceParams[n].y; - float factor = smoothstep(outerCos, innerCos, spotDot); - intensity.xyz += CC_SpotLightSourceColor[n] * max(0.0, dot(normalize(dir), normal)) * factor * attenuation; - } + vec3 vertexToSpotLightDirection = normalize(v_vertexToSpotLightDirection[i]); + vec3 spotLightDirection = normalize(CC_SpotLightSourceDirection[i] * 2.0); + + // "-lightDirection" is used because light direction points in opposite direction to spot direction. + float spotCurrentAngleCos = dot(spotLightDirection, -vertexToSpotLightDirection); + + // Apply spot attenuation + attenuation *= smoothstep(CC_SpotLightSourceOuterAngleCos[i], CC_SpotLightSourceInnerAngleCos[i], spotCurrentAngleCos); + combinedColor.xyz += computeLighting(normal, vertexToSpotLightDirection, CC_SpotLightSourceColor[i], attenuation); + } \n#endif\n -\n#if (CC_MAX_DIRECTIONAL_LIGHT_NUM || CC_MAX_POINT_LIGHT_NUM || CC_MAX_SPOT_LIGHT_NUM)\n - gl_FragColor = u_color * (CC_AmbientColor + intensity); +\n#if ((CC_MAX_DIRECTIONAL_LIGHT_NUM > 0) || (CC_MAX_POINT_LIGHT_NUM > 0) || (CC_MAX_SPOT_LIGHT_NUM > 0))\n + gl_FragColor = u_color * combinedColor; \n#else\n gl_FragColor = u_color; \n#endif\n diff --git a/cocos/renderer/ccShader_3D_ColorNormalTex.frag b/cocos/renderer/ccShader_3D_ColorNormalTex.frag index 3c4fabcf97..a614905d13 100644 --- a/cocos/renderer/ccShader_3D_ColorNormalTex.frag +++ b/cocos/renderer/ccShader_3D_ColorNormalTex.frag @@ -27,55 +27,66 @@ varying vec3 v_normal; uniform vec4 u_color; +vec3 computeLighting(vec3 normalVector, vec3 lightDirection, vec3 lightColor, float attenuation) +{ + float diffuse = max(dot(normalVector, lightDirection), 0.0); + vec3 diffuseColor = lightColor * diffuse * attenuation; + + return diffuseColor; +} + void main(void) { - vec4 intensity = vec4(0.0, 0.0, 0.0, 1.0); -\n#if (CC_MAX_DIRECTIONAL_LIGHT_NUM || CC_MAX_POINT_LIGHT_NUM || CC_MAX_SPOT_LIGHT_NUM)\n +\n#if ((CC_MAX_DIRECTIONAL_LIGHT_NUM > 0) || (CC_MAX_POINT_LIGHT_NUM > 0) || (CC_MAX_SPOT_LIGHT_NUM > 0))\n vec3 normal = normalize(v_normal); \n#endif\n + vec4 combinedColor = CC_AmbientColor; + + // Directional light contribution \n#if (CC_MAX_DIRECTIONAL_LIGHT_NUM > 0)\n - - for (int n = 0; n < CC_MAX_DIRECTIONAL_LIGHT_NUM; ++n) + for (int i = 0; i < CC_MAX_DIRECTIONAL_LIGHT_NUM; ++i) { - intensity.xyz += CC_DirLightSourceColor[n] * max(0.0, dot(-CC_DirLightSourceDirection[n], normal)); + vec3 lightDirection = normalize(CC_DirLightSourceDirection[i] * 2.0); + combinedColor.xyz += computeLighting(normal, -lightDirection, CC_DirLightSourceColor[i], 1.0); } - \n#endif\n + // Point light contribution \n#if (CC_MAX_POINT_LIGHT_NUM > 0)\n - - for (int n = 0; n < CC_MAX_POINT_LIGHT_NUM; ++n) + for (int i = 0; i < CC_MAX_POINT_LIGHT_NUM; ++i) { - vec3 dir = v_vertexToPointLightDirection[n]; - vec3 ldir = dir * CC_PointLightSourceColor[n].w; + vec3 ldir = v_vertexToPointLightDirection[i] * CC_PointLightSourceRangeInverse[i]; float attenuation = clamp(1.0 - dot(ldir, ldir), 0.0, 1.0); - intensity.xyz += CC_PointLightSourceColor[n] * max(0.0, dot(normalize(dir), normal)) * attenuation; + combinedColor.xyz += computeLighting(normal, normalize(v_vertexToPointLightDirection[i]), CC_PointLightSourceColor[i], attenuation); } - \n#endif\n + // Spot light contribution \n#if (CC_MAX_SPOT_LIGHT_NUM > 0)\n - - for (int n = 0; n < CC_MAX_SPOT_LIGHT_NUM; ++n) + for (int i = 0; i < CC_MAX_SPOT_LIGHT_NUM; ++i) { - vec3 dir = v_vertexToSpotLightDirection[n]; - vec3 ldir = dir * CC_SpotLightSourceParams[n].z; + // Compute range attenuation + vec3 ldir = v_vertexToSpotLightDirection[i] * CC_SpotLightSourceRangeInverse[i]; float attenuation = clamp(1.0 - dot(ldir, ldir), 0.0, 1.0); - dir = normalize(dir); - float spotDot = dot(normalize(dir), -CC_SpotLightSourceDirection[n]); - float innerCos = CC_SpotLightSourceParams[n].x; - float outerCos = CC_SpotLightSourceParams[n].y; - float factor = smoothstep(outerCos, innerCos, spotDot); - intensity.xyz += CC_SpotLightSourceColor[n] * max(0.0, dot(normalize(dir), normal)) * factor * attenuation; - } + vec3 vertexToSpotLightDirection = normalize(v_vertexToSpotLightDirection[i]); + vec3 spotLightDirection = normalize(CC_SpotLightSourceDirection[i] * 2.0); + + // "-lightDirection" is used because light direction points in opposite direction to spot direction. + float spotCurrentAngleCos = dot(spotLightDirection, -vertexToSpotLightDirection); + + // Apply spot attenuation + attenuation *= smoothstep(CC_SpotLightSourceOuterAngleCos[i], CC_SpotLightSourceInnerAngleCos[i], spotCurrentAngleCos); + combinedColor.xyz += computeLighting(normal, vertexToSpotLightDirection, CC_SpotLightSourceColor[i], attenuation); + } \n#endif\n -\n#if (CC_MAX_DIRECTIONAL_LIGHT_NUM || CC_MAX_POINT_LIGHT_NUM || CC_MAX_SPOT_LIGHT_NUM)\n - gl_FragColor = texture2D(CC_Texture0, TextureCoordOut) * u_color * (CC_AmbientColor + intensity); + +\n#if ((CC_MAX_DIRECTIONAL_LIGHT_NUM > 0) || (CC_MAX_POINT_LIGHT_NUM > 0) || (CC_MAX_SPOT_LIGHT_NUM > 0))\n + gl_FragColor = texture2D(CC_Texture0, TextureCoordOut) * u_color * combinedColor; \n#else\n - gl_FragColor = texture2D(CC_Texture0, TextureCoordOut) * u_color; + gl_FragColor = texture2D(CC_Texture0, TextureCoordOut) * u_color; \n#endif\n } diff --git a/cocos/renderer/ccShader_3D_PositionNormalTex.vert b/cocos/renderer/ccShader_3D_PositionNormalTex.vert index 6d19baaa82..80bce316ea 100644 --- a/cocos/renderer/ccShader_3D_PositionNormalTex.vert +++ b/cocos/renderer/ccShader_3D_PositionNormalTex.vert @@ -31,7 +31,7 @@ void main(void) } \n#endif\n -\n#if (CC_MAX_DIRECTIONAL_LIGHT_NUM || CC_MAX_POINT_LIGHT_NUM || CC_MAX_SPOT_LIGHT_NUM)\n +\n#if ((CC_MAX_DIRECTIONAL_LIGHT_NUM > 0) || (CC_MAX_POINT_LIGHT_NUM > 0) || (CC_MAX_SPOT_LIGHT_NUM > 0))\n v_normal = CC_NormalMatrix * a_normal; \n#endif\n @@ -112,7 +112,7 @@ void getPositionAndNormal(out vec4 position, out vec3 normal) position.z = dot(p, matrixPalette3); position.w = p.w; -\n#if (CC_MAX_DIRECTIONAL_LIGHT_NUM || CC_MAX_POINT_LIGHT_NUM || CC_MAX_SPOT_LIGHT_NUM)\n +\n#if ((CC_MAX_DIRECTIONAL_LIGHT_NUM > 0) || (CC_MAX_POINT_LIGHT_NUM > 0) || (CC_MAX_SPOT_LIGHT_NUM > 0))\n vec4 n = vec4(a_normal, 0.0); normal.x = dot(n, matrixPalette1); normal.y = dot(n, matrixPalette2); @@ -141,7 +141,7 @@ void main() } \n#endif\n -\n#if (CC_MAX_DIRECTIONAL_LIGHT_NUM || CC_MAX_POINT_LIGHT_NUM || CC_MAX_SPOT_LIGHT_NUM)\n +\n#if ((CC_MAX_DIRECTIONAL_LIGHT_NUM > 0) || (CC_MAX_POINT_LIGHT_NUM > 0) || (CC_MAX_SPOT_LIGHT_NUM > 0))\n v_normal = CC_NormalMatrix * normal; \n#endif\n