Skip to content

Commit e921db7

Browse files
author
Thayer J Andrews
committed
CCEffectGlass / Refraction - Update glass and refraction to fix NDC to world space computation
This fixes issues that came up when these effects were forced to render to an intermediate render target.
1 parent 9660068 commit e921db7

File tree

2 files changed

+104
-68
lines changed

2 files changed

+104
-68
lines changed

cocos2d/CCEffectGlass.m

Lines changed: 59 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -46,26 +46,34 @@ -(id)initWithShininess:(float)shininess refraction:(float)refraction refractionE
4646

4747
-(id)initWithShininess:(float)shininess refraction:(float)refraction refractionEnvironment:(CCSprite *)refractionEnvironment reflectionEnvironment:(CCSprite *)reflectionEnvironment normalMap:(CCSpriteFrame *)normalMap
4848
{
49-
NSArray *uniforms = @[
50-
[CCEffectUniform uniform:@"float" name:@"u_refraction" value:[NSNumber numberWithFloat:1.0f]],
51-
52-
[CCEffectUniform uniform:@"float" name:@"u_shininess" value:[NSNumber numberWithFloat:1.0f]],
53-
[CCEffectUniform uniform:@"float" name:@"u_fresnelBias" value:[NSNumber numberWithFloat:0.0f]],
54-
[CCEffectUniform uniform:@"float" name:@"u_fresnelPower" value:[NSNumber numberWithFloat:0.0f]],
55-
56-
[CCEffectUniform uniform:@"sampler2D" name:@"u_refractEnvMap" value:(NSValue*)[CCTexture none]],
57-
[CCEffectUniform uniform:@"mat4" name:@"u_screenToRefractEnv" value:[NSValue valueWithGLKMatrix4:GLKMatrix4Identity]],
58-
[CCEffectUniform uniform:@"vec2" name:@"u_refractTangent" value:[NSValue valueWithGLKVector2:GLKVector2Make(1.0f, 0.0f)]],
59-
[CCEffectUniform uniform:@"vec2" name:@"u_refractBinormal" value:[NSValue valueWithGLKVector2:GLKVector2Make(0.0f, 1.0f)]],
60-
61-
[CCEffectUniform uniform:@"sampler2D" name:@"u_reflectEnvMap" value:(NSValue*)[CCTexture none]],
62-
[CCEffectUniform uniform:@"mat4" name:@"u_screenToReflectEnv" value:[NSValue valueWithGLKMatrix4:GLKMatrix4Identity]],
63-
[CCEffectUniform uniform:@"vec2" name:@"u_reflectTangent" value:[NSValue valueWithGLKVector2:GLKVector2Make(1.0f, 0.0f)]],
64-
[CCEffectUniform uniform:@"vec2" name:@"u_reflectBinormal" value:[NSValue valueWithGLKVector2:GLKVector2Make(0.0f, 1.0f)]],
65-
49+
NSArray *fragUniforms = @[
50+
[CCEffectUniform uniform:@"float" name:@"u_refraction" value:[NSNumber numberWithFloat:1.0f]],
51+
52+
[CCEffectUniform uniform:@"float" name:@"u_shininess" value:[NSNumber numberWithFloat:1.0f]],
53+
[CCEffectUniform uniform:@"float" name:@"u_fresnelBias" value:[NSNumber numberWithFloat:0.0f]],
54+
[CCEffectUniform uniform:@"float" name:@"u_fresnelPower" value:[NSNumber numberWithFloat:0.0f]],
55+
56+
[CCEffectUniform uniform:@"sampler2D" name:@"u_refractEnvMap" value:(NSValue*)[CCTexture none]],
57+
[CCEffectUniform uniform:@"vec2" name:@"u_refractTangent" value:[NSValue valueWithGLKVector2:GLKVector2Make(1.0f, 0.0f)]],
58+
[CCEffectUniform uniform:@"vec2" name:@"u_refractBinormal" value:[NSValue valueWithGLKVector2:GLKVector2Make(0.0f, 1.0f)]],
59+
60+
[CCEffectUniform uniform:@"sampler2D" name:@"u_reflectEnvMap" value:(NSValue*)[CCTexture none]],
61+
[CCEffectUniform uniform:@"vec2" name:@"u_reflectTangent" value:[NSValue valueWithGLKVector2:GLKVector2Make(1.0f, 0.0f)]],
62+
[CCEffectUniform uniform:@"vec2" name:@"u_reflectBinormal" value:[NSValue valueWithGLKVector2:GLKVector2Make(0.0f, 1.0f)]],
63+
64+
];
65+
66+
NSArray *vertUniforms = @[
67+
[CCEffectUniform uniform:@"mat4" name:@"u_ndcToReflectEnv" value:[NSValue valueWithGLKMatrix4:GLKMatrix4Identity]],
68+
[CCEffectUniform uniform:@"mat4" name:@"u_ndcToRefractEnv" value:[NSValue valueWithGLKMatrix4:GLKMatrix4Identity]]
69+
];
70+
71+
NSArray *varyings = @[
72+
[CCEffectVarying varying:@"vec2" name:@"v_refractEnvSpaceTexCoords"],
73+
[CCEffectVarying varying:@"vec2" name:@"v_reflectEnvSpaceTexCoords"]
6674
];
6775

68-
if((self = [super initWithFragmentUniforms:uniforms vertexUniforms:nil varyings:nil]))
76+
if((self = [super initWithFragmentUniforms:fragUniforms vertexUniforms:vertUniforms varyings:varyings]))
6977
{
7078
_refraction = refraction;
7179
_conditionedRefraction = CCEffectUtilsConditionRefraction(refraction);
@@ -110,18 +118,13 @@ -(void)buildFragmentFunctions
110118
vec4 tangentSpaceNormal = normalMap * 2.0 - 1.0;
111119

112120

113-
114-
// Compute environment space texture coordinates from the screen space
115-
// fragment position.
116-
vec4 refractEnvSpaceTexCoords = u_screenToRefractEnv * gl_FragCoord;
117-
118121
// Convert the normal vector from tangent space to environment space
119122
vec3 refractNormal = normalize(vec3(u_refractTangent * tangentSpaceNormal.x + u_refractBinormal * tangentSpaceNormal.y, tangentSpaceNormal.z));
120-
vec3 refractOffset = refract(vec3(0,0,1), refractNormal, 1.0) * u_refraction;
123+
vec2 refractOffset = refract(vec3(0,0,1), refractNormal, 1.0).xy * u_refraction;
121124

122125
// Perturb the screen space texture coordinate by the scaled normal
123126
// vector.
124-
vec2 refractTexCoords = refractEnvSpaceTexCoords.xy + refractOffset.xy;
127+
vec2 refractTexCoords = v_refractEnvSpaceTexCoords + refractOffset;
125128

126129
// This is positive if refractTexCoords is in [0..1] and negative otherwise.
127130
vec2 compare = 0.5 - abs(refractTexCoords - 0.5);
@@ -131,19 +134,15 @@ -(void)buildFragmentFunctions
131134

132135

133136

134-
// Compute environment space texture coordinates from the screen space
135-
// fragment position.
136-
vec4 reflectEnvSpaceTexCoords = u_screenToReflectEnv * gl_FragCoord;
137-
138137
// Convert the normal vector from tangent space to environment space
139138
vec3 reflectNormal = normalize(vec3(u_reflectTangent * tangentSpaceNormal.x + u_reflectBinormal * tangentSpaceNormal.y, tangentSpaceNormal.z));
140139

141140
float nDotV = dot(reflectNormal, vec3(0,0,1));
142-
vec3 reflectOffset = reflectNormal * pow(1.0 - nDotV, 3.0) / 8.0;
141+
vec2 reflectOffset = reflectNormal.xy * pow(1.0 - nDotV, 3.0) / 8.0;
143142

144143
// Perturb the screen space texture coordinate by the scaled normal
145144
// vector.
146-
vec2 reflectTexCoords = reflectEnvSpaceTexCoords.xy + reflectOffset.xy;
145+
vec2 reflectTexCoords = v_reflectEnvSpaceTexCoords + reflectOffset;
147146

148147
// Feed the resulting coordinates through cos() so they reflect when
149148
// they would otherwise be outside of [0..1].
@@ -169,10 +168,32 @@ -(void)buildFragmentFunctions
169168
return primaryColor + refraction + reflection;
170169
);
171170

172-
CCEffectFunction* fragmentFunction = [[CCEffectFunction alloc] initWithName:@"glassEffect" body:effectBody inputs:@[input] returnType:@"vec4"];
171+
CCEffectFunction* fragmentFunction = [[CCEffectFunction alloc] initWithName:@"glassEffectFrag" body:effectBody inputs:@[input] returnType:@"vec4"];
173172
[self.fragmentFunctions addObject:fragmentFunction];
174173
}
175174

175+
-(void)buildVertexFunctions
176+
{
177+
self.vertexFunctions = [[NSMutableArray alloc] init];
178+
179+
NSString* effectBody = CC_GLSL(
180+
// Compute environment space texture coordinates from the vertex positions.
181+
182+
// Reflect space coords
183+
vec4 reflectEnvSpaceTexCoords = u_ndcToReflectEnv * cc_Position;
184+
v_reflectEnvSpaceTexCoords = reflectEnvSpaceTexCoords.xy;
185+
186+
// Refract space coords
187+
vec4 refractEnvSpaceTexCoords = u_ndcToRefractEnv * cc_Position;
188+
v_refractEnvSpaceTexCoords = refractEnvSpaceTexCoords.xy;
189+
190+
return cc_Position;
191+
);
192+
193+
CCEffectFunction *vertexFunction = [[CCEffectFunction alloc] initWithName:@"glassEffectVtx" body:effectBody inputs:nil returnType:@"vec4"];
194+
[self.vertexFunctions addObject:vertexFunction];
195+
}
196+
176197
-(void)buildRenderPasses
177198
{
178199
__weak CCEffectGlass *weakSelf = self;
@@ -206,32 +227,23 @@ -(void)buildRenderPasses
206227
pass.shaderUniforms[weakSelf.uniformTranslationTable[@"u_refractEnvMap"]] = weakSelf.refractionEnvironment.texture ?: [CCTexture none];
207228
pass.shaderUniforms[weakSelf.uniformTranslationTable[@"u_reflectEnvMap"]] = weakSelf.reflectionEnvironment.texture ?: [CCTexture none];
208229

209-
210-
CGFloat scale = [CCDirector sharedDirector].contentScaleFactor;
211-
CGAffineTransform screenToWorld = CGAffineTransformMake(1.0f / scale, 0.0f, 0.0f, 1.0f / scale, 0.0f, 0.0f);
212-
213-
214-
215-
// Setup the screen space to refract environment space matrix.
230+
// Setup the NDC space to refract environment space matrix.
216231
CGAffineTransform worldToRefractEnvTexture = CCEffectUtilsWorldToEnvironmentTransform(weakSelf.refractionEnvironment);
217-
CGAffineTransform screenToRefractEnvTexture = CGAffineTransformConcat(screenToWorld, worldToRefractEnvTexture);
218-
pass.shaderUniforms[weakSelf.uniformTranslationTable[@"u_screenToRefractEnv"]] = [NSValue valueWithGLKMatrix4:CCEffectUtilsMat4FromAffineTransform(screenToRefractEnvTexture)];
232+
GLKMatrix4 ndcToRefractEnvTextureMat = GLKMatrix4Multiply(CCEffectUtilsMat4FromAffineTransform(worldToRefractEnvTexture), pass.ndcToWorld);
233+
pass.shaderUniforms[weakSelf.uniformTranslationTable[@"u_ndcToRefractEnv"]] = [NSValue valueWithGLKMatrix4:ndcToRefractEnvTextureMat];
219234

220-
// Setup the screen space to reflect environment space matrix.
235+
// Setup the NDC space to reflect environment space matrix.
221236
CGAffineTransform worldToReflectEnvTexture = CCEffectUtilsWorldToEnvironmentTransform(weakSelf.reflectionEnvironment);
222-
CGAffineTransform screenToReflectEnvTexture = CGAffineTransformConcat(screenToWorld, worldToReflectEnvTexture);
223-
pass.shaderUniforms[weakSelf.uniformTranslationTable[@"u_screenToReflectEnv"]] = [NSValue valueWithGLKMatrix4:CCEffectUtilsMat4FromAffineTransform(screenToReflectEnvTexture)];
237+
GLKMatrix4 ndcToReflectEnvTextureMat = GLKMatrix4Multiply(CCEffectUtilsMat4FromAffineTransform(worldToReflectEnvTexture), pass.ndcToWorld);
238+
pass.shaderUniforms[weakSelf.uniformTranslationTable[@"u_ndcToReflectEnv"]] = [NSValue valueWithGLKMatrix4:ndcToReflectEnvTextureMat];
224239

225240
// Setup the tangent and binormal vectors for the refraction environment
226241
GLKVector4 refractTangent = CCEffectUtilsTangentInEnvironmentSpace(pass.transform, CCEffectUtilsMat4FromAffineTransform(worldToRefractEnvTexture));
227242
GLKVector4 refractNormal = GLKVector4Make(0.0f, 0.0f, 1.0f, 1.0f);
228243
GLKVector4 refractBinormal = GLKVector4CrossProduct(refractNormal, refractTangent);
229-
230244
pass.shaderUniforms[weakSelf.uniformTranslationTable[@"u_refractTangent"]] = [NSValue valueWithGLKVector2:GLKVector2Make(refractTangent.x, refractTangent.y)];
231245
pass.shaderUniforms[weakSelf.uniformTranslationTable[@"u_refractBinormal"]] = [NSValue valueWithGLKVector2:GLKVector2Make(refractBinormal.x, refractBinormal.y)];
232246

233-
234-
235247
// Setup the tangent and binormal vectors for the reflection environment.
236248
GLKVector4 reflectTangent = CCEffectUtilsTangentInEnvironmentSpace(pass.transform, CCEffectUtilsMat4FromAffineTransform(worldToReflectEnvTexture));
237249
GLKVector4 reflectNormal = GLKVector4Make(0.0f, 0.0f, 1.0f, 1.0f);

0 commit comments

Comments
 (0)