1717#import " CCEffect_Private.h"
1818#import " CCSprite_Private.h"
1919
20- static const NSUInteger CCEffectLightingMaxLightCount = 16 ;
20+ typedef struct _CCLightKey
21+ {
22+ NSUInteger pointLightMask;
23+ NSUInteger directionalLightMask;
24+
25+ } CCLightKey;
26+
27+ static CCLightKey CCLightKeyMake (NSArray *lights);
28+ static BOOL CCLightKeyCompare (CCLightKey a, CCLightKey b);
29+
30+
2131
2232@interface CCEffectLighting ()
2333
2434@property (nonatomic , strong ) NSMutableArray *lights;
25- @property (nonatomic , assign ) NSUInteger lightKey;
35+ @property (nonatomic , assign ) CCLightKey lightKey;
36+ @property (nonatomic , readonly ) BOOL hasSpecular;
37+ @property (nonatomic , assign ) BOOL previousHasSpecular;
2638
2739@end
2840
@@ -48,7 +60,12 @@ -(id)initWithLights:(NSArray *)lights
4860 {
4961 _lights = [[NSMutableArray alloc ] init ];
5062 }
51- _lightKey = 0 ;
63+
64+ _specularColor = [CCColor whiteColor ];
65+ _shininess = 5 .0f ;
66+
67+ _lightKey = CCLightKeyMake (nil );
68+ _previousHasSpecular = NO ;
5269 }
5370 return self;
5471}
@@ -77,7 +94,7 @@ -(void)removeAllLights
7794}
7895
7996
80- +(NSMutableArray *)buildFragmentFunctionsWithLights : (NSArray *)lights
97+ +(NSMutableArray *)buildFragmentFunctionsWithLights : (NSArray *)lights andSpecular : ( BOOL ) hasSpecular
8198{
8299 CCEffectFunctionInput *input = [[CCEffectFunctionInput alloc ] initWithType: @" vec4" name: @" inputValue" initialSnippet: CCEffectDefaultInitialInputSnippet snippet: CCEffectDefaultInputSnippet];
83100
@@ -94,7 +111,7 @@ +(NSMutableArray *)buildFragmentFunctionsWithLights:(NSArray*)lights
94111
95112 vec4 lightColor;
96113 vec4 diffuseLightColor = u_globalAmbientColor;
97- vec4 specularLightColor = vec4 (0 ,0 ,0 ,1 );
114+ vec4 specularLightColor = vec4 (0 ,0 ,0 ,0 );
98115
99116 vec3 tangentSpaceLightDir;
100117 vec3 halfAngleDir;
@@ -123,11 +140,19 @@ +(NSMutableArray *)buildFragmentFunctionsWithLights:(NSArray*)lights
123140 [effectBody appendString: @" diffuseTerm = max(0.0, dot(tangentSpaceNormal, tangentSpaceLightDir));\n " ];
124141 [effectBody appendString: @" diffuseLightColor += lightColor * diffuseTerm;\n " ];
125142
126- [effectBody appendString: @" halfAngleDir = (2.0 * dot(tangentSpaceLightDir, tangentSpaceNormal) * tangentSpaceNormal - tangentSpaceLightDir);\n " ];
127- [effectBody appendString: @" specularTerm = max(0.0, dot(halfAngleDir, vec3(0,0,1))) * step(0.0, diffuseTerm);\n " ];
128- [effectBody appendString: @" specularLightColor += lightColor * pow(specularTerm, 10.0);\n " ];
143+ if (hasSpecular)
144+ {
145+ [effectBody appendString: @" halfAngleDir = (2.0 * dot(tangentSpaceLightDir, tangentSpaceNormal) * tangentSpaceNormal - tangentSpaceLightDir);\n " ];
146+ [effectBody appendString: @" specularTerm = max(0.0, dot(halfAngleDir, vec3(0,0,1))) * step(0.0, diffuseTerm);\n " ];
147+ [effectBody appendString: @" specularLightColor += lightColor * pow(specularTerm, u_specularExponent);\n " ];
148+ }
129149 }
130- [effectBody appendString: @" return diffuseLightColor * inputValue + specularLightColor;\n " ];
150+ [effectBody appendString: @" vec4 resultColor = diffuseLightColor * inputValue;\n " ];
151+ if (hasSpecular)
152+ {
153+ [effectBody appendString: @" resultColor += specularLightColor * u_specularColor;\n " ];
154+ }
155+ [effectBody appendString: @" return vec4(resultColor.xyz, inputValue.a);\n " ];
131156
132157 CCEffectFunction* fragmentFunction = [[CCEffectFunction alloc ] initWithName: @" lightingEffectFrag" body: effectBody inputs: @[input] returnType: @" vec4" ];
133158 return [NSMutableArray arrayWithObject: fragmentFunction];
@@ -210,6 +235,8 @@ -(void)buildRenderPasses
210235 }
211236
212237 pass.shaderUniforms [weakSelf.uniformTranslationTable[@" u_globalAmbientColor" ]] = [NSValue valueWithGLKVector4: globalAmbientColor];
238+ pass.shaderUniforms [weakSelf.uniformTranslationTable[@" u_specularExponent" ]] = [NSNumber numberWithFloat: weakSelf.shininess];
239+ pass.shaderUniforms [weakSelf.uniformTranslationTable[@" u_specularColor" ]] = [NSValue valueWithGLKVector4: weakSelf.specularColor.glkVector4];
213240
214241 } copy]];
215242
@@ -220,10 +247,12 @@ - (CCEffectPrepareStatus)prepareForRendering
220247{
221248 CCEffectPrepareStatus result = CCEffectPrepareNothingToDo;
222249
223- NSUInteger newLightKey = [CCEffectLighting computeLightKey: _lights];
224- if (newLightKey != _lightKey)
250+ CCLightKey newLightKey = CCLightKeyMake (_lights);
251+ if (!CCLightKeyCompare (newLightKey, _lightKey) ||
252+ (_previousHasSpecular != self.hasSpecular ))
225253 {
226254 _lightKey = newLightKey;
255+ _previousHasSpecular = self.hasSpecular ;
227256
228257 NSMutableArray *fragUniforms = [[NSMutableArray alloc ] initWithArray: @[[CCEffectUniform uniform: @" vec4" name: @" u_globalAmbientColor" value: [NSValue valueWithGLKVector4: GLKVector4Make (1 .0f , 1 .0f , 1 .0f , 1 .0f )]]]];
229258 NSMutableArray *vertUniforms = [[NSMutableArray alloc ] initWithArray: @[[CCEffectUniform uniform: @" mat4" name: @" u_ndcToTangentSpace" value: [NSValue valueWithGLKMatrix4: GLKMatrix4Identity]]]];
@@ -244,7 +273,13 @@ - (CCEffectPrepareStatus)prepareForRendering
244273 [varyings addObject: [CCEffectVarying varying: @" vec4" name: [NSString stringWithFormat: @" v_tangentSpaceLightDir%lu " , (unsigned long )lightIndex]]];
245274 }
246275
247- NSMutableArray *fragFunctions = [CCEffectLighting buildFragmentFunctionsWithLights: _lights];
276+ if (self.hasSpecular )
277+ {
278+ [fragUniforms addObject: [CCEffectUniform uniform: @" float" name: @" u_specularExponent" value: [NSNumber numberWithFloat: 5 .0f ]]];
279+ [fragUniforms addObject: [CCEffectUniform uniform: @" vec4" name: @" u_specularColor" value: [NSValue valueWithGLKVector4: GLKVector4Make (1 .0f , 1 .0f , 1 .0f , 1 .0f )]]];
280+ }
281+
282+ NSMutableArray *fragFunctions = [CCEffectLighting buildFragmentFunctionsWithLights: _lights andSpecular: self .hasSpecular];
248283 NSMutableArray *vertFunctions = [CCEffectLighting buildVertexFunctionsWithLights: _lights];
249284
250285 [self buildEffectWithFragmentFunction: fragFunctions vertexFunctions: vertFunctions fragmentUniforms: fragUniforms vertexUniforms: vertUniforms varyings: varyings firstInStack: YES ];
@@ -254,26 +289,38 @@ - (CCEffectPrepareStatus)prepareForRendering
254289 return result;
255290}
256291
257- +(NSUInteger )computeLightKey : (NSArray *)lights
292+ - (BOOL )hasSpecular
293+ {
294+ return (!ccc4FEqual (_specularColor.ccColor4f , ccc4f (0 .0f , 0 .0f , 0 .0f , 0 .0f )) && (_shininess > 0 .0f ));
295+ }
296+
297+ @end
298+
299+ CCLightKey CCLightKeyMake (NSArray *lights)
258300{
259- static const NSUInteger CCEffectLightingPointOffset = 0 ;
260- static const NSUInteger CCEffectLightingDirectionalOffset = CCEffectLightingMaxLightCount ;
261-
262- NSUInteger lightKey = 0 ;
301+ CCLightKey lightKey ;
302+ lightKey. pointLightMask = 0 ;
303+ lightKey. directionalLightMask = 0 ;
304+
263305 for (NSUInteger lightIndex = 0 ; lightIndex < lights.count ; lightIndex++)
264306 {
265307 CCLightNode *light = lights[lightIndex];
266308 if (light.type == CCLightPoint)
267309 {
268- lightKey |= (1 << ( lightIndex + CCEffectLightingPointOffset) );
310+ lightKey. pointLightMask |= (1 << lightIndex);
269311 }
270312 else if (light.type == CCLightDirectional)
271313 {
272- lightKey |= (1 << ( lightIndex + CCEffectLightingDirectionalOffset) );
314+ lightKey. directionalLightMask |= (1 << lightIndex);
273315 }
274316 }
275317 return lightKey;
276318}
277319
278- @end
320+ BOOL CCLightKeyCompare (CCLightKey a, CCLightKey b)
321+ {
322+ return (((a.pointLightMask ) == (b.pointLightMask )) &&
323+ ((a.directionalLightMask ) == (b.directionalLightMask )));
324+ }
325+
279326
0 commit comments