@@ -35,8 +35,9 @@ @interface CCEffectLighting ()
3535
3636@property (nonatomic , strong ) NSMutableArray *lights;
3737@property (nonatomic , assign ) CCLightKey lightKey;
38- @property (nonatomic , readonly ) BOOL hasSpecular;
39- @property (nonatomic , assign ) BOOL previousHasSpecular;
38+ @property (nonatomic , readonly ) BOOL needsSpecular;
39+ @property (nonatomic , assign ) BOOL shaderHasSpecular;
40+ @property (nonatomic , assign ) BOOL shaderHasNormalMap;
4041
4142@end
4243
@@ -66,8 +67,9 @@ -(id)initWithLights:(NSArray *)lights
6667 _specularColor = [CCColor whiteColor ];
6768 _shininess = 5 .0f ;
6869
69- _lightKey = CCLightKeyMake (nil );
70- _previousHasSpecular = NO ;
70+ _lightKey = CCLightKeyMake (lights);
71+ _shaderHasSpecular = NO ;
72+ _shaderHasNormalMap = NO ;
7173 }
7274 return self;
7375}
@@ -96,21 +98,12 @@ -(void)removeAllLights
9698}
9799
98100
99- +(NSMutableArray *)buildFragmentFunctionsWithLights : (NSArray *)lights andSpecular : (BOOL )hasSpecular
101+ +(NSMutableArray *)buildFragmentFunctionsWithLights : (NSArray *)lights normalMap : (BOOL )needsNormalMap specular : ( BOOL ) needsSpecular
100102{
101103 CCEffectFunctionInput *input = [[CCEffectFunctionInput alloc ] initWithType: @" vec4" name: @" inputValue" initialSnippet: CCEffectDefaultInitialInputSnippet snippet: CCEffectDefaultInputSnippet];
102104
103105 NSMutableString *effectBody = [[NSMutableString alloc ] init ];
104106 [effectBody appendString: CC_GLSL (
105- // Index the normal map and expand the color value from [0..1] to [-1..1]
106- vec4 normalMap = texture2D (cc_NormalMapTexture, cc_FragTexCoord2);
107- vec3 tangentSpaceNormal = normalize (normalMap.xyz * 2.0 - 1.0 );
108-
109- if ((inputValue.a * normalMap.a) == 0.0 )
110- {
111- return vec4 (0 ,0 ,0 ,0 );
112- }
113-
114107 vec4 lightColor;
115108 vec4 diffuseLightColor = u_globalAmbientColor;
116109 vec4 specularLightColor = vec4 (0 ,0 ,0 ,0 );
@@ -122,8 +115,30 @@ +(NSMutableArray *)buildFragmentFunctionsWithLights:(NSArray*)lights andSpecular
122115 float falloffTerm;
123116 float diffuseTerm;
124117 float specularTerm;
118+ float composedAlpha = inputValue.a;
125119 )];
126120
121+ if (needsNormalMap)
122+ {
123+ [effectBody appendString: CC_GLSL (
124+ // Index the normal map and expand the color value from [0..1] to [-1..1]
125+ vec4 normalMap = texture2D (cc_NormalMapTexture, cc_FragTexCoord2);
126+ vec3 tangentSpaceNormal = normalize (normalMap.xyz * 2.0 - 1.0 );
127+ composedAlpha *= normalMap.a;
128+ )];
129+ }
130+ else
131+ {
132+ [effectBody appendString: @" vec3 tangentSpaceNormal = vec3(0,0,1);\n " ];
133+ }
134+
135+ [effectBody appendString: CC_GLSL (
136+ if (composedAlpha == 0.0 )
137+ {
138+ return vec4 (0 ,0 ,0 ,0 );
139+ }
140+ )];
141+
127142 for (NSUInteger lightIndex = 0 ; lightIndex < lights.count ; lightIndex++)
128143 {
129144 CCLightNode *light = lights[lightIndex];
@@ -142,15 +157,15 @@ +(NSMutableArray *)buildFragmentFunctionsWithLights:(NSArray*)lights andSpecular
142157 [effectBody appendString: @" diffuseTerm = max(0.0, dot(tangentSpaceNormal, tangentSpaceLightDir));\n " ];
143158 [effectBody appendString: @" diffuseLightColor += lightColor * diffuseTerm;\n " ];
144159
145- if (hasSpecular )
160+ if (needsSpecular )
146161 {
147162 [effectBody appendString: @" halfAngleDir = (2.0 * dot(tangentSpaceLightDir, tangentSpaceNormal) * tangentSpaceNormal - tangentSpaceLightDir);\n " ];
148163 [effectBody appendString: @" specularTerm = max(0.0, dot(halfAngleDir, vec3(0,0,1))) * step(0.0, diffuseTerm);\n " ];
149164 [effectBody appendString: @" specularLightColor += lightColor * pow(specularTerm, u_specularExponent);\n " ];
150165 }
151166 }
152167 [effectBody appendString: @" vec4 resultColor = diffuseLightColor * inputValue;\n " ];
153- if (hasSpecular )
168+ if (needsSpecular )
154169 {
155170 [effectBody appendString: @" resultColor += specularLightColor * u_specularColor;\n " ];
156171 }
@@ -249,12 +264,17 @@ - (CCEffectPrepareStatus)prepareForRenderingWithSprite:(CCSprite *)sprite
249264{
250265 CCEffectPrepareStatus result = CCEffectPrepareNothingToDo;
251266
267+ BOOL needsNormalMap = (sprite.normalMapSpriteFrame != nil );
268+
252269 CCLightKey newLightKey = CCLightKeyMake (_lights);
253- if (!CCLightKeyCompare (newLightKey, _lightKey) ||
254- (_previousHasSpecular != self.hasSpecular ))
270+ if (!self.shader ||
271+ !CCLightKeyCompare (newLightKey, _lightKey) ||
272+ (_shaderHasSpecular != self.needsSpecular ) ||
273+ (_shaderHasNormalMap != needsNormalMap))
255274 {
256275 _lightKey = newLightKey;
257- _previousHasSpecular = self.hasSpecular ;
276+ _shaderHasSpecular = self.needsSpecular ;
277+ _shaderHasNormalMap = needsNormalMap;
258278
259279 NSMutableArray *fragUniforms = [[NSMutableArray alloc ] initWithArray: @[[CCEffectUniform uniform: @" vec4" name: @" u_globalAmbientColor" value: [NSValue valueWithGLKVector4: GLKVector4Make (1 .0f , 1 .0f , 1 .0f , 1 .0f )]]]];
260280 NSMutableArray *vertUniforms = [[NSMutableArray alloc ] initWithArray: @[[CCEffectUniform uniform: @" mat4" name: @" u_ndcToTangentSpace" value: [NSValue valueWithGLKMatrix4: GLKMatrix4Identity]]]];
@@ -275,13 +295,13 @@ - (CCEffectPrepareStatus)prepareForRenderingWithSprite:(CCSprite *)sprite
275295 [varyings addObject: [CCEffectVarying varying: @" vec4" name: [NSString stringWithFormat: @" v_tangentSpaceLightDir%lu " , (unsigned long )lightIndex]]];
276296 }
277297
278- if (self.hasSpecular )
298+ if (self.needsSpecular )
279299 {
280300 [fragUniforms addObject: [CCEffectUniform uniform: @" float" name: @" u_specularExponent" value: [NSNumber numberWithFloat: 5 .0f ]]];
281301 [fragUniforms addObject: [CCEffectUniform uniform: @" vec4" name: @" u_specularColor" value: [NSValue valueWithGLKVector4: GLKVector4Make (1 .0f , 1 .0f , 1 .0f , 1 .0f )]]];
282302 }
283303
284- NSMutableArray *fragFunctions = [CCEffectLighting buildFragmentFunctionsWithLights: _lights andSpecular: self .hasSpecular ];
304+ NSMutableArray *fragFunctions = [CCEffectLighting buildFragmentFunctionsWithLights: _lights normalMap: needsNormalMap specular: self .needsSpecular ];
285305 NSMutableArray *vertFunctions = [CCEffectLighting buildVertexFunctionsWithLights: _lights];
286306
287307 [self buildEffectWithFragmentFunction: fragFunctions vertexFunctions: vertFunctions fragmentUniforms: fragUniforms vertexUniforms: vertUniforms varyings: varyings firstInStack: YES ];
@@ -291,7 +311,7 @@ - (CCEffectPrepareStatus)prepareForRenderingWithSprite:(CCSprite *)sprite
291311 return result;
292312}
293313
294- - (BOOL )hasSpecular
314+ - (BOOL )needsSpecular
295315{
296316 return (!ccc4FEqual (_specularColor.ccColor4f , ccc4f (0 .0f , 0 .0f , 0 .0f , 0 .0f )) && (_shininess > 0 .0f ));
297317}
0 commit comments