Skip to content

Commit 8fffb13

Browse files
author
Thayer J Andrews
committed
CCEffectLighting - Handle absent normal maps the right way
If a normal map is missing from the affected sprite, generate a shader that just hardcodes the normal vector to vec3(0,0,1) (coming straight out of the scene towards the viewer). This also cleans up the "do I need to regenerate the shader now?" logic a bit.
1 parent 67698b2 commit 8fffb13

File tree

1 file changed

+42
-22
lines changed

1 file changed

+42
-22
lines changed

cocos2d/CCEffectLighting.m

Lines changed: 42 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)