17
17
#import " CCEffect_Private.h"
18
18
#import " CCSprite_Private.h"
19
19
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
+
21
31
22
32
@interface CCEffectLighting ()
23
33
24
34
@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;
26
38
27
39
@end
28
40
@@ -48,7 +60,12 @@ -(id)initWithLights:(NSArray *)lights
48
60
{
49
61
_lights = [[NSMutableArray alloc ] init ];
50
62
}
51
- _lightKey = 0 ;
63
+
64
+ _specularColor = [CCColor whiteColor ];
65
+ _shininess = 5 .0f ;
66
+
67
+ _lightKey = CCLightKeyMake (nil );
68
+ _previousHasSpecular = NO ;
52
69
}
53
70
return self;
54
71
}
@@ -77,7 +94,7 @@ -(void)removeAllLights
77
94
}
78
95
79
96
80
- +(NSMutableArray *)buildFragmentFunctionsWithLights : (NSArray *)lights
97
+ +(NSMutableArray *)buildFragmentFunctionsWithLights : (NSArray *)lights andSpecular : ( BOOL ) hasSpecular
81
98
{
82
99
CCEffectFunctionInput *input = [[CCEffectFunctionInput alloc ] initWithType: @" vec4" name: @" inputValue" initialSnippet: CCEffectDefaultInitialInputSnippet snippet: CCEffectDefaultInputSnippet];
83
100
@@ -94,7 +111,7 @@ +(NSMutableArray *)buildFragmentFunctionsWithLights:(NSArray*)lights
94
111
95
112
vec4 lightColor;
96
113
vec4 diffuseLightColor = u_globalAmbientColor;
97
- vec4 specularLightColor = vec4 (0 ,0 ,0 ,1 );
114
+ vec4 specularLightColor = vec4 (0 ,0 ,0 ,0 );
98
115
99
116
vec3 tangentSpaceLightDir;
100
117
vec3 halfAngleDir;
@@ -123,11 +140,19 @@ +(NSMutableArray *)buildFragmentFunctionsWithLights:(NSArray*)lights
123
140
[effectBody appendString: @" diffuseTerm = max(0.0, dot(tangentSpaceNormal, tangentSpaceLightDir));\n " ];
124
141
[effectBody appendString: @" diffuseLightColor += lightColor * diffuseTerm;\n " ];
125
142
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
+ }
129
149
}
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 " ];
131
156
132
157
CCEffectFunction* fragmentFunction = [[CCEffectFunction alloc ] initWithName: @" lightingEffectFrag" body: effectBody inputs: @[input] returnType: @" vec4" ];
133
158
return [NSMutableArray arrayWithObject: fragmentFunction];
@@ -210,6 +235,8 @@ -(void)buildRenderPasses
210
235
}
211
236
212
237
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];
213
240
214
241
} copy]];
215
242
@@ -220,10 +247,12 @@ - (CCEffectPrepareStatus)prepareForRendering
220
247
{
221
248
CCEffectPrepareStatus result = CCEffectPrepareNothingToDo;
222
249
223
- NSUInteger newLightKey = [CCEffectLighting computeLightKey: _lights];
224
- if (newLightKey != _lightKey)
250
+ CCLightKey newLightKey = CCLightKeyMake (_lights);
251
+ if (!CCLightKeyCompare (newLightKey, _lightKey) ||
252
+ (_previousHasSpecular != self.hasSpecular ))
225
253
{
226
254
_lightKey = newLightKey;
255
+ _previousHasSpecular = self.hasSpecular ;
227
256
228
257
NSMutableArray *fragUniforms = [[NSMutableArray alloc ] initWithArray: @[[CCEffectUniform uniform: @" vec4" name: @" u_globalAmbientColor" value: [NSValue valueWithGLKVector4: GLKVector4Make (1 .0f , 1 .0f , 1 .0f , 1 .0f )]]]];
229
258
NSMutableArray *vertUniforms = [[NSMutableArray alloc ] initWithArray: @[[CCEffectUniform uniform: @" mat4" name: @" u_ndcToTangentSpace" value: [NSValue valueWithGLKMatrix4: GLKMatrix4Identity]]]];
@@ -244,7 +273,13 @@ - (CCEffectPrepareStatus)prepareForRendering
244
273
[varyings addObject: [CCEffectVarying varying: @" vec4" name: [NSString stringWithFormat: @" v_tangentSpaceLightDir%lu " , (unsigned long )lightIndex]]];
245
274
}
246
275
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];
248
283
NSMutableArray *vertFunctions = [CCEffectLighting buildVertexFunctionsWithLights: _lights];
249
284
250
285
[self buildEffectWithFragmentFunction: fragFunctions vertexFunctions: vertFunctions fragmentUniforms: fragUniforms vertexUniforms: vertUniforms varyings: varyings firstInStack: YES ];
@@ -254,26 +289,38 @@ - (CCEffectPrepareStatus)prepareForRendering
254
289
return result;
255
290
}
256
291
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)
258
300
{
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
+
263
305
for (NSUInteger lightIndex = 0 ; lightIndex < lights.count ; lightIndex++)
264
306
{
265
307
CCLightNode *light = lights[lightIndex];
266
308
if (light.type == CCLightPoint)
267
309
{
268
- lightKey |= (1 << ( lightIndex + CCEffectLightingPointOffset) );
310
+ lightKey. pointLightMask |= (1 << lightIndex);
269
311
}
270
312
else if (light.type == CCLightDirectional)
271
313
{
272
- lightKey |= (1 << ( lightIndex + CCEffectLightingDirectionalOffset) );
314
+ lightKey. directionalLightMask |= (1 << lightIndex);
273
315
}
274
316
}
275
317
return lightKey;
276
318
}
277
319
278
- @end
320
+ BOOL CCLightKeyCompare (CCLightKey a, CCLightKey b)
321
+ {
322
+ return (((a.pointLightMask ) == (b.pointLightMask )) &&
323
+ ((a.directionalLightMask ) == (b.directionalLightMask )));
324
+ }
325
+
279
326
0 commit comments