1717#import " CCEffect_Private.h"
1818#import " CCSprite_Private.h"
1919
20+ static const NSUInteger CCEffectLightingMaxLightCount = 16 ;
21+
2022@interface CCEffectLighting ()
2123
2224@property (nonatomic , strong ) NSMutableArray *lights;
25+ @property (nonatomic , assign ) NSUInteger lightKey;
2326
2427@end
2528
@@ -45,31 +48,7 @@ -(id)initWithLights:(NSArray *)lights
4548 {
4649 _lights = [[NSMutableArray alloc ] init ];
4750 }
48-
49-
50- NSMutableArray *fragUniforms = [[NSMutableArray alloc ] initWithArray: @[[CCEffectUniform uniform: @" vec4" name: @" u_globalAmbientColor" value: [NSValue valueWithGLKVector4: GLKVector4Make (1 .0f , 1 .0f , 1 .0f , 1 .0f )]]]];
51- NSMutableArray *vertUniforms = [[NSMutableArray alloc ] initWithArray: @[[CCEffectUniform uniform: @" mat4" name: @" u_ndcToTangentSpace" value: [NSValue valueWithGLKMatrix4: GLKMatrix4Identity]]]];
52- NSMutableArray *varyings = [[NSMutableArray alloc ] init ];
53-
54- for (NSUInteger lightIndex = 0 ; lightIndex < lights.count ; lightIndex++)
55- {
56- CCLightNode *light = lights[lightIndex];
57-
58- [vertUniforms addObject: [CCEffectUniform uniform: @" vec4" name: [NSString stringWithFormat: @" u_lightVector%lu " , (unsigned long )lightIndex] value: [NSValue valueWithGLKVector4: GLKVector4Make (0 .0f , 0 .0f , 0 .0f , 1 .0f )]]];
59- [fragUniforms addObject: [CCEffectUniform uniform: @" vec4" name: [NSString stringWithFormat: @" u_lightColor%lu " , (unsigned long )lightIndex] value: [NSValue valueWithGLKVector4: GLKVector4Make (1 .0f , 1 .0f , 1 .0f , 1 .0f )]]];
60-
61- if (light.type != CCLightDirectional)
62- {
63- [fragUniforms addObject: [CCEffectUniform uniform: @" float" name: [NSString stringWithFormat: @" u_lightFalloff%lu " , (unsigned long )lightIndex] value: [NSNumber numberWithFloat: 1 .0f ]]];
64- }
65-
66- [varyings addObject: [CCEffectVarying varying: @" vec4" name: [NSString stringWithFormat: @" v_tangentSpaceLightDir%lu " , (unsigned long )lightIndex]]];
67- }
68-
69- NSMutableArray *fragFunctions = [CCEffectLighting buildFragmentFunctionsWithLights: lights];
70- NSMutableArray *vertFunctions = [CCEffectLighting buildVertexFunctionsWithLights: lights];
71-
72- [self buildEffectWithFragmentFunction: fragFunctions vertexFunctions: vertFunctions fragmentUniforms: fragUniforms vertexUniforms: vertUniforms varyings: varyings firstInStack: YES ];
51+ _lightKey = 0 ;
7352 }
7453 return self;
7554}
@@ -81,11 +60,14 @@ +(id)effectWithLights:(NSArray *)lights
8160
8261-(void )addLight : (CCLightNode *)light
8362{
63+ NSAssert (_lights.count < 16 , @" CCEffectLighting only supports 16 lights." );
64+ NSAssert (![_lights containsObject: light], @" Adding a light to effect that is already here." );
8465 [_lights addObject: light];
8566}
8667
8768-(void )removeLight : (CCLightNode *)light
8869{
70+ NSAssert ([_lights containsObject: light], @" Removing a light from effect that is not here." );
8971 [_lights removeObject: light];
9072}
9173
@@ -221,5 +203,64 @@ -(void)buildRenderPasses
221203 self.renderPasses = @[pass0];
222204}
223205
206+ - (CCEffectPrepareStatus)prepareForRendering
207+ {
208+ CCEffectPrepareStatus result = CCEffectPrepareNothingToDo;
209+
210+ NSUInteger newLightKey = [CCEffectLighting computeLightKey: _lights];
211+ if (newLightKey != _lightKey)
212+ {
213+ _lightKey = newLightKey;
214+
215+ NSMutableArray *fragUniforms = [[NSMutableArray alloc ] initWithArray: @[[CCEffectUniform uniform: @" vec4" name: @" u_globalAmbientColor" value: [NSValue valueWithGLKVector4: GLKVector4Make (1 .0f , 1 .0f , 1 .0f , 1 .0f )]]]];
216+ NSMutableArray *vertUniforms = [[NSMutableArray alloc ] initWithArray: @[[CCEffectUniform uniform: @" mat4" name: @" u_ndcToTangentSpace" value: [NSValue valueWithGLKMatrix4: GLKMatrix4Identity]]]];
217+ NSMutableArray *varyings = [[NSMutableArray alloc ] init ];
218+
219+ for (NSUInteger lightIndex = 0 ; lightIndex < _lights.count ; lightIndex++)
220+ {
221+ CCLightNode *light = _lights[lightIndex];
222+
223+ [vertUniforms addObject: [CCEffectUniform uniform: @" vec4" name: [NSString stringWithFormat: @" u_lightVector%lu " , (unsigned long )lightIndex] value: [NSValue valueWithGLKVector4: GLKVector4Make (0 .0f , 0 .0f , 0 .0f , 1 .0f )]]];
224+ [fragUniforms addObject: [CCEffectUniform uniform: @" vec4" name: [NSString stringWithFormat: @" u_lightColor%lu " , (unsigned long )lightIndex] value: [NSValue valueWithGLKVector4: GLKVector4Make (1 .0f , 1 .0f , 1 .0f , 1 .0f )]]];
225+
226+ if (light.type != CCLightDirectional)
227+ {
228+ [fragUniforms addObject: [CCEffectUniform uniform: @" float" name: [NSString stringWithFormat: @" u_lightFalloff%lu " , (unsigned long )lightIndex] value: [NSNumber numberWithFloat: 1 .0f ]]];
229+ }
230+
231+ [varyings addObject: [CCEffectVarying varying: @" vec4" name: [NSString stringWithFormat: @" v_tangentSpaceLightDir%lu " , (unsigned long )lightIndex]]];
232+ }
233+
234+ NSMutableArray *fragFunctions = [CCEffectLighting buildFragmentFunctionsWithLights: _lights];
235+ NSMutableArray *vertFunctions = [CCEffectLighting buildVertexFunctionsWithLights: _lights];
236+
237+ [self buildEffectWithFragmentFunction: fragFunctions vertexFunctions: vertFunctions fragmentUniforms: fragUniforms vertexUniforms: vertUniforms varyings: varyings firstInStack: YES ];
238+
239+ result = CCEffectPrepareSuccess;
240+ }
241+ return result;
242+ }
243+
244+ +(NSUInteger )computeLightKey : (NSArray *)lights
245+ {
246+ static const NSUInteger CCEffectLightingPointOffset = 0 ;
247+ static const NSUInteger CCEffectLightingDirectionalOffset = CCEffectLightingMaxLightCount;
248+
249+ NSUInteger lightKey = 0 ;
250+ for (NSUInteger lightIndex = 0 ; lightIndex < lights.count ; lightIndex++)
251+ {
252+ CCLightNode *light = lights[lightIndex];
253+ if (light.type == CCLightPoint)
254+ {
255+ lightKey |= (1 << (lightIndex + CCEffectLightingPointOffset));
256+ }
257+ else if (light.type == CCLightDirectional)
258+ {
259+ lightKey |= (1 << (lightIndex + CCEffectLightingDirectionalOffset));
260+ }
261+ }
262+ return lightKey;
263+ }
264+
224265@end
225266
0 commit comments