Skip to content

Commit 78af1e6

Browse files
author
Thayer J Andrews
committed
CCEffectLighting - Initial support for multiple lights
This doesn't support non-point lights yet nor does it support changes to the lights array after initialization.
1 parent bccb7eb commit 78af1e6

File tree

1 file changed

+66
-50
lines changed

1 file changed

+66
-50
lines changed

cocos2d/CCEffectLighting.m

Lines changed: 66 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -33,21 +33,7 @@ -(id)init
3333

3434
-(id)initWithLights:(NSArray *)lights
3535
{
36-
NSArray *fragUniforms = @[
37-
[CCEffectUniform uniform:@"vec4" name:@"u_lightColor" value:[NSValue valueWithGLKVector4:GLKVector4Make(1.0f, 1.0f, 1.0f, 1.0f)]],
38-
[CCEffectUniform uniform:@"vec4" name:@"u_globalAmbientColor" value:[NSValue valueWithGLKVector4:GLKVector4Make(1.0f, 1.0f, 1.0f, 1.0f)]],
39-
];
40-
41-
NSArray *vertUniforms = @[
42-
[CCEffectUniform uniform:@"mat4" name:@"u_ndcToTangentSpace" value:[NSValue valueWithGLKMatrix4:GLKMatrix4Identity]],
43-
[CCEffectUniform uniform:@"vec4" name:@"u_lightVector" value:[NSValue valueWithGLKVector2:GLKVector2Make(0.0f, 0.0f)]]
44-
];
45-
46-
NSArray *varyings = @[
47-
[CCEffectVarying varying:@"vec4" name:@"v_tangentSpaceLightDir"]
48-
];
49-
50-
if((self = [super initWithFragmentUniforms:fragUniforms vertexUniforms:vertUniforms varyings:varyings]))
36+
if((self = [super init]))
5137
{
5238
self.debugName = @"CCEffectLighting";
5339

@@ -59,11 +45,29 @@ -(id)initWithLights:(NSArray *)lights
5945
{
6046
_lights = [[NSMutableArray alloc] init];
6147
}
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+
[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)]]];
57+
[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)]]];
58+
59+
[varyings addObject:[CCEffectVarying varying:@"vec4" name:[NSString stringWithFormat:@"v_tangentSpaceLightDir%lu", (unsigned long)lightIndex]]];
60+
}
61+
62+
NSMutableArray *fragFunctions = [CCEffectLighting buildFragmentFunctionsWithLights:lights];
63+
NSMutableArray *vertFunctions = [CCEffectLighting buildVertexFunctionsWithLights:lights];
64+
65+
[self buildEffectWithFragmentFunction:fragFunctions vertexFunctions:vertFunctions fragmentUniforms:fragUniforms vertexUniforms:vertUniforms varyings:varyings firstInStack:YES];
6266
}
6367
return self;
6468
}
6569

66-
+(id)effectWithLight:(NSArray *)lights
70+
+(id)effectWithLights:(NSArray *)lights
6771
{
6872
return [[self alloc] initWithLights:lights];
6973
}
@@ -84,47 +88,53 @@ -(void)removeAllLights
8488
}
8589

8690

87-
-(void)buildFragmentFunctions
91+
+(NSMutableArray *)buildFragmentFunctionsWithLights:(NSArray*)lights
8892
{
89-
self.fragmentFunctions = [[NSMutableArray alloc] init];
90-
9193
CCEffectFunctionInput *input = [[CCEffectFunctionInput alloc] initWithType:@"vec4" name:@"inputValue" initialSnippet:CCEffectDefaultInitialInputSnippet snippet:CCEffectDefaultInputSnippet];
9294

93-
NSString* effectBody = CC_GLSL(
94-
// Index the normal map and expand the color value from [0..1] to [-1..1]
95-
vec4 normalMap = texture2D(cc_NormalMapTexture, cc_FragTexCoord2);
96-
vec4 tangentSpaceNormal = normalMap * 2.0 - 1.0;
97-
98-
vec4 lightContribution = u_lightColor * dot(tangentSpaceNormal, v_tangentSpaceLightDir);
99-
if (normalMap.a > 0.0)
100-
{
101-
return inputValue * (lightContribution + u_globalAmbientColor);
102-
}
103-
else
104-
{
105-
return vec4(0,0,0,1);
106-
}
107-
);
95+
NSMutableString *effectBody = [[NSMutableString alloc] init];
96+
[effectBody appendString:CC_GLSL(
97+
// Index the normal map and expand the color value from [0..1] to [-1..1]
98+
vec4 normalMap = texture2D(cc_NormalMapTexture, cc_FragTexCoord2);
99+
vec4 tangentSpaceNormal = normalMap * 2.0 - 1.0;
100+
101+
if (normalMap.a == 0.0)
102+
{
103+
return vec4(0,0,0,0);
104+
}
105+
vec4 resultColor = u_globalAmbientColor;
106+
)];
107+
108+
for (NSUInteger lightIndex = 0; lightIndex < lights.count; lightIndex++)
109+
{
110+
[effectBody appendFormat:@"resultColor += u_lightColor%lu * dot(tangentSpaceNormal, v_tangentSpaceLightDir%lu);\n", (unsigned long)lightIndex, (unsigned long)lightIndex];
111+
}
112+
[effectBody appendString:@"return resultColor * inputValue;\n"];
108113

109114
CCEffectFunction* fragmentFunction = [[CCEffectFunction alloc] initWithName:@"lightingEffectFrag" body:effectBody inputs:@[input] returnType:@"vec4"];
110-
[self.fragmentFunctions addObject:fragmentFunction];
115+
return [NSMutableArray arrayWithObject:fragmentFunction];
111116
}
112117

113-
-(void)buildVertexFunctions
118+
+(NSMutableArray *)buildVertexFunctionsWithLights:(NSArray*)lights
114119
{
115-
self.vertexFunctions = [[NSMutableArray alloc] init];
116-
117-
NSString* effectBody = CC_GLSL(
118-
// Compute the tangent space lighting direction vector for each
119-
// vertex. cc_Position was transformed on the CPU so we need to
120-
// back it out from NDC (normalized device coords) to tangent
121-
// space before using it to compute the light direction.
122-
v_tangentSpaceLightDir = normalize(u_lightVector - u_ndcToTangentSpace * cc_Position);
123-
return cc_Position;
124-
);
120+
NSMutableString *effectBody = [[NSMutableString alloc] init];
121+
for (NSUInteger lightIndex = 0; lightIndex < lights.count; lightIndex++)
122+
{
123+
CCLightNode *light = lights[lightIndex];
124+
125+
if (light.type == CCLightNodeDirectional)
126+
{
127+
[effectBody appendFormat:@"v_tangentSpaceLightDir%lu = u_lightVector%lu;", (unsigned long)lightIndex, (unsigned long)lightIndex];
128+
}
129+
else
130+
{
131+
[effectBody appendFormat:@"v_tangentSpaceLightDir%lu = normalize(u_lightVector%lu - u_ndcToTangentSpace * cc_Position);", (unsigned long)lightIndex, (unsigned long)lightIndex];
132+
}
133+
}
134+
[effectBody appendString:@"return cc_Position;"];
125135

126136
CCEffectFunction *vertexFunction = [[CCEffectFunction alloc] initWithName:@"lightingEffectVtx" body:effectBody inputs:nil returnType:@"vec4"];
127-
[self.vertexFunctions addObject:vertexFunction];
137+
return [NSMutableArray arrayWithObject:vertexFunction];
128138
}
129139

130140
-(void)buildRenderPasses
@@ -146,8 +156,10 @@ -(void)buildRenderPasses
146156
pass.shaderUniforms[weakSelf.uniformTranslationTable[@"u_ndcToTangentSpace"]] = [NSValue valueWithGLKMatrix4:pass.ndcToNodeLocal];
147157

148158
GLKVector4 globalAmbientColor = GLKVector4Make(0.0f, 0.0f, 0.0f, 1.0f);
149-
for (CCLightNode *light in weakSelf.lights)
159+
for (NSUInteger lightIndex = 0; lightIndex < weakSelf.lights.count; lightIndex++)
150160
{
161+
CCLightNode *light = weakSelf.lights[lightIndex];
162+
151163
// Add this light's ambient contribution to the global ambient light color.
152164
globalAmbientColor = GLKVector4Add(globalAmbientColor, GLKVector4MultiplyScalar(light.ambientColor.glkVector4, light.ambientIntensity));
153165

@@ -157,10 +169,14 @@ -(void)buildRenderPasses
157169
// Compute the light's position in the effect node's coordinate system.
158170
GLKVector4 lightPosition = GLKMatrix4MultiplyVector4(lightNodeToEffectNode, GLKVector4Make(light.anchorPointInPoints.x, light.anchorPointInPoints.y, 500.0f, 1.0f));
159171

172+
// Compute the real light color based on color and intensity.
160173
GLKVector4 lightColor = GLKVector4MultiplyScalar(light.color.glkVector4, light.intensity);
161174

162-
pass.shaderUniforms[weakSelf.uniformTranslationTable[@"u_lightColor"]] = [NSValue valueWithGLKVector4:lightColor];
163-
pass.shaderUniforms[weakSelf.uniformTranslationTable[@"u_lightVector"]] = [NSValue valueWithGLKVector4:lightPosition];
175+
NSString *lightColorLabel = [NSString stringWithFormat:@"u_lightColor%lu", (unsigned long)lightIndex];
176+
NSString *lightVectorLabel = [NSString stringWithFormat:@"u_lightVector%lu", (unsigned long)lightIndex];
177+
178+
pass.shaderUniforms[weakSelf.uniformTranslationTable[lightColorLabel]] = [NSValue valueWithGLKVector4:lightColor];
179+
pass.shaderUniforms[weakSelf.uniformTranslationTable[lightVectorLabel]] = [NSValue valueWithGLKVector4:lightPosition];
164180
}
165181

166182
pass.shaderUniforms[weakSelf.uniformTranslationTable[@"u_globalAmbientColor"]] = [NSValue valueWithGLKVector4:globalAmbientColor];

0 commit comments

Comments
 (0)