Skip to content

Commit ce25941

Browse files
committed
Merge pull request #997 from thayerandrews/develop
CCEffects - Fixes for environment mapping effects and CCRenderTexture
2 parents 9c93263 + ec06df3 commit ce25941

9 files changed

+165
-76
lines changed

cocos2d/CCEffectGlass.m

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -230,30 +230,53 @@ -(void)buildRenderPasses
230230
pass.shaderUniforms[weakSelf.uniformTranslationTable[@"u_refractEnvMap"]] = weakSelf.refractionEnvironment.texture ?: [CCTexture none];
231231
pass.shaderUniforms[weakSelf.uniformTranslationTable[@"u_reflectEnvMap"]] = weakSelf.reflectionEnvironment.texture ?: [CCTexture none];
232232

233-
// Setup the NDC space to refract environment space matrix.
234-
CGAffineTransform worldToRefractEnvTexture = CCEffectUtilsWorldToEnvironmentTransform(weakSelf.refractionEnvironment);
235-
GLKMatrix4 ndcToRefractEnvTextureMat = GLKMatrix4Multiply(CCEffectUtilsMat4FromAffineTransform(worldToRefractEnvTexture), pass.ndcToWorld);
236-
pass.shaderUniforms[weakSelf.uniformTranslationTable[@"u_ndcToRefractEnv"]] = [NSValue valueWithGLKMatrix4:ndcToRefractEnvTextureMat];
237233

238-
// Setup the NDC space to reflect environment space matrix.
239-
CGAffineTransform worldToReflectEnvTexture = CCEffectUtilsWorldToEnvironmentTransform(weakSelf.reflectionEnvironment);
240-
GLKMatrix4 ndcToReflectEnvTextureMat = GLKMatrix4Multiply(CCEffectUtilsMat4FromAffineTransform(worldToReflectEnvTexture), pass.ndcToWorld);
241-
pass.shaderUniforms[weakSelf.uniformTranslationTable[@"u_ndcToReflectEnv"]] = [NSValue valueWithGLKMatrix4:ndcToReflectEnvTextureMat];
234+
235+
// Get the transform from the affected node's local coordinates to the environment node.
236+
GLKMatrix4 effectNodeToRefractEnvNode = CCEffectUtilsTransformFromNodeToNode(pass.node, weakSelf.refractionEnvironment, nil);
237+
238+
// Concatenate the node to environment transform with the environment node to environment texture transform.
239+
// The result takes us from the affected node's coordinates to the environment's texture coordinates. We need
240+
// this when computing the tangent and normal vectors below.
241+
GLKMatrix4 effectNodeToRefractEnvTexture = GLKMatrix4Multiply(CCEffectUtilsMat4FromAffineTransform(weakSelf.refractionEnvironment.nodeToTextureTransform), effectNodeToRefractEnvNode);
242+
243+
// Concatenate the node to environment texture transform together with the transform from NDC to local node
244+
// coordinates. (NDC == normalized device coordinates == render target coordinates that are normalized to the
245+
// range 0..1). The shader uses this to map from NDC directly to environment texture coordinates.
246+
GLKMatrix4 ndcToRefractEnvTexture = GLKMatrix4Multiply(effectNodeToRefractEnvTexture, pass.ndcToNodeLocal);
247+
pass.shaderUniforms[weakSelf.uniformTranslationTable[@"u_ndcToRefractEnv"]] = [NSValue valueWithGLKMatrix4:ndcToRefractEnvTexture];
242248

243249
// Setup the tangent and binormal vectors for the refraction environment
244-
GLKVector4 refractTangent = CCEffectUtilsTangentInEnvironmentSpace(pass.transform, CCEffectUtilsMat4FromAffineTransform(worldToRefractEnvTexture));
250+
GLKVector4 refractTangent = GLKVector4Normalize(GLKMatrix4MultiplyVector4(effectNodeToRefractEnvTexture, GLKVector4Make(1.0f, 0.0f, 0.0f, 0.0f)));
245251
GLKVector4 refractNormal = GLKVector4Make(0.0f, 0.0f, 1.0f, 1.0f);
246252
GLKVector4 refractBinormal = GLKVector4CrossProduct(refractNormal, refractTangent);
247253
pass.shaderUniforms[weakSelf.uniformTranslationTable[@"u_refractTangent"]] = [NSValue valueWithGLKVector2:GLKVector2Make(refractTangent.x, refractTangent.y)];
248254
pass.shaderUniforms[weakSelf.uniformTranslationTable[@"u_refractBinormal"]] = [NSValue valueWithGLKVector2:GLKVector2Make(refractBinormal.x, refractBinormal.y)];
249255

250-
// Setup the tangent and binormal vectors for the reflection environment.
251-
GLKVector4 reflectTangent = CCEffectUtilsTangentInEnvironmentSpace(pass.transform, CCEffectUtilsMat4FromAffineTransform(worldToReflectEnvTexture));
256+
257+
258+
// Get the transform from the affected node's local coordinates to the environment node.
259+
GLKMatrix4 effectNodeToReflectEnvNode = CCEffectUtilsTransformFromNodeToNode(pass.node, weakSelf.reflectionEnvironment, nil);
260+
261+
// Concatenate the node to environment transform with the environment node to environment texture transform.
262+
// The result takes us from the affected node's coordinates to the environment's texture coordinates. We need
263+
// this when computing the tangent and normal vectors below.
264+
GLKMatrix4 effectNodeToReflectEnvTexture = GLKMatrix4Multiply(CCEffectUtilsMat4FromAffineTransform(weakSelf.reflectionEnvironment.nodeToTextureTransform), effectNodeToReflectEnvNode);
265+
266+
// Concatenate the node to environment texture transform together with the transform from NDC to local node
267+
// coordinates. (NDC == normalized device coordinates == render target coordinates that are normalized to the
268+
// range 0..1). The shader uses this to map from NDC directly to environment texture coordinates.
269+
GLKMatrix4 ndcToReflectEnvTexture = GLKMatrix4Multiply(effectNodeToReflectEnvTexture, pass.ndcToNodeLocal);
270+
pass.shaderUniforms[weakSelf.uniformTranslationTable[@"u_ndcToReflectEnv"]] = [NSValue valueWithGLKMatrix4:ndcToReflectEnvTexture];
271+
272+
// Setup the tangent and binormal vectors for the reflection environment
273+
GLKVector4 reflectTangent = GLKVector4Normalize(GLKMatrix4MultiplyVector4(effectNodeToReflectEnvTexture, GLKVector4Make(1.0f, 0.0f, 0.0f, 0.0f)));
252274
GLKVector4 reflectNormal = GLKVector4Make(0.0f, 0.0f, 1.0f, 1.0f);
253275
GLKVector4 reflectBinormal = GLKVector4CrossProduct(reflectNormal, reflectTangent);
254276
pass.shaderUniforms[weakSelf.uniformTranslationTable[@"u_reflectTangent"]] = [NSValue valueWithGLKVector2:GLKVector2Make(reflectTangent.x, reflectTangent.y)];
255277
pass.shaderUniforms[weakSelf.uniformTranslationTable[@"u_reflectBinormal"]] = [NSValue valueWithGLKVector2:GLKVector2Make(reflectBinormal.x, reflectBinormal.y)];
256-
278+
279+
257280
} copy]];
258281

259282
self.renderPasses = @[pass0];

cocos2d/CCEffectReflection.m

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,8 @@ -(void)buildFragmentFunctions
139139

140140
float fresnel = max(u_fresnelBias + (1.0 - u_fresnelBias) * pow((1.0 - nDotV), u_fresnelPower), 0.0);
141141

142-
// If the refracted texture coordinates are within the bounds of the environment map
143-
// blend the primary color with the refracted environment. Multiplying by the normal
142+
// If the reflected texture coordinates are within the bounds of the environment map
143+
// blend the primary color with the reflected environment. Multiplying by the normal
144144
// map alpha also allows the effect to be disabled for specific pixels.
145145
primaryColor += normalMap.a * fresnel * u_shininess * texture2D(u_envMap, reflectTexCoords);
146146
return primaryColor;
@@ -198,26 +198,28 @@ -(void)buildRenderPasses
198198

199199
pass.shaderUniforms[weakSelf.uniformTranslationTable[@"u_envMap"]] = weakSelf.environment.texture ?: [CCTexture none];
200200

201-
// Get the transform from world space to environment texture space. This is
202-
// concatenated with the current transform to move from local node space to
203-
// environment texture space.
204-
CGAffineTransform worldToReflectEnvTexture = CCEffectUtilsWorldToEnvironmentTransform(weakSelf.environment);
205201

206-
// Setup the tangent and binormal vectors for the refraction environment
207-
GLKVector4 reflectTangent = CCEffectUtilsTangentInEnvironmentSpace(pass.transform, CCEffectUtilsMat4FromAffineTransform(worldToReflectEnvTexture));
202+
// Get the transform from the affected node's local coordinates to the environment node.
203+
GLKMatrix4 effectNodeToReflectEnvNode = CCEffectUtilsTransformFromNodeToNode(pass.node, weakSelf.environment, nil);
204+
205+
// Concatenate the node to environment transform with the environment node to environment texture transform.
206+
// The result takes us from the affected node's coordinates to the environment's texture coordinates. We need
207+
// this when computing the tangent and normal vectors below.
208+
GLKMatrix4 effectNodeToReflectEnvTexture = GLKMatrix4Multiply(CCEffectUtilsMat4FromAffineTransform(weakSelf.environment.nodeToTextureTransform), effectNodeToReflectEnvNode);
209+
210+
// Concatenate the node to environment texture transform together with the transform from NDC to local node
211+
// coordinates. (NDC == normalized device coordinates == render target coordinates that are normalized to the
212+
// range 0..1). The shader uses this to map from NDC directly to environment texture coordinates.
213+
GLKMatrix4 ndcToReflectEnvTexture = GLKMatrix4Multiply(effectNodeToReflectEnvTexture, pass.ndcToNodeLocal);
214+
pass.shaderUniforms[weakSelf.uniformTranslationTable[@"u_ndcToEnv"]] = [NSValue valueWithGLKMatrix4:ndcToReflectEnvTexture];
215+
216+
// Setup the tangent and binormal vectors for the reflection environment
217+
GLKVector4 reflectTangent = GLKVector4Normalize(GLKMatrix4MultiplyVector4(effectNodeToReflectEnvTexture, GLKVector4Make(1.0f, 0.0f, 0.0f, 0.0f)));
208218
GLKVector4 reflectNormal = GLKVector4Make(0.0f, 0.0f, 1.0f, 1.0f);
209219
GLKVector4 reflectBinormal = GLKVector4CrossProduct(reflectNormal, reflectTangent);
210220
pass.shaderUniforms[weakSelf.uniformTranslationTable[@"u_tangent"]] = [NSValue valueWithGLKVector2:GLKVector2Make(reflectTangent.x, reflectTangent.y)];
211221
pass.shaderUniforms[weakSelf.uniformTranslationTable[@"u_binormal"]] = [NSValue valueWithGLKVector2:GLKVector2Make(reflectBinormal.x, reflectBinormal.y)];
212222

213-
// Setup the transform from normalized device coordinates (NDC, which is the space our vertex
214-
// positions are in) to environment texture space. We use this to compute environment texture
215-
// coordinates in the vertex shader.s
216-
GLKMatrix4 worldToReflectEnvTextureMat = CCEffectUtilsMat4FromAffineTransform(worldToReflectEnvTexture);
217-
GLKMatrix4 ndcToReflectEnvTextureMat = GLKMatrix4Multiply(worldToReflectEnvTextureMat, pass.ndcToWorld);
218-
219-
pass.shaderUniforms[weakSelf.uniformTranslationTable[@"u_ndcToEnv"]] = [NSValue valueWithGLKMatrix4:ndcToReflectEnvTextureMat];
220-
221223
} copy]];
222224

223225
self.renderPasses = @[pass0];

cocos2d/CCEffectRefraction.m

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -161,26 +161,27 @@ -(void)buildRenderPasses
161161
pass.shaderUniforms[weakSelf.uniformTranslationTable[@"u_refraction"]] = [NSNumber numberWithFloat:weakSelf.conditionedRefraction];
162162
pass.shaderUniforms[weakSelf.uniformTranslationTable[@"u_envMap"]] = weakSelf.environment.texture ?: [CCTexture none];
163163

164-
// Get the transform from world space to environment texture space. This is
165-
// concatenated with the current transform to move from local node space to
166-
// environment texture space.
167-
CGAffineTransform worldToRefractEnvTexture = CCEffectUtilsWorldToEnvironmentTransform(weakSelf.environment);
164+
// Get the transform from the affected node's local coordinates to the environment node.
165+
GLKMatrix4 effectNodeToRefractEnvNode = CCEffectUtilsTransformFromNodeToNode(pass.node, weakSelf.environment, nil);
166+
167+
// Concatenate the node to environment transform with the environment node to environment texture transform.
168+
// The result takes us from the affected node's coordinates to the environment's texture coordinates. We need
169+
// this when computing the tangent and normal vectors below.
170+
GLKMatrix4 effectNodeToRefractEnvTexture = GLKMatrix4Multiply(CCEffectUtilsMat4FromAffineTransform(weakSelf.environment.nodeToTextureTransform), effectNodeToRefractEnvNode);
171+
172+
// Concatenate the node to environment texture transform together with the transform from NDC to local node
173+
// coordinates. (NDC == normalized device coordinates == render target coordinates that are normalized to the
174+
// range 0..1). The shader uses this to map from NDC directly to environment texture coordinates.
175+
GLKMatrix4 ndcToRefractEnvTexture = GLKMatrix4Multiply(effectNodeToRefractEnvTexture, pass.ndcToNodeLocal);
176+
pass.shaderUniforms[weakSelf.uniformTranslationTable[@"u_ndcToEnv"]] = [NSValue valueWithGLKMatrix4:ndcToRefractEnvTexture];
168177

169178
// Setup the tangent and binormal vectors for the refraction environment
170-
GLKVector4 refractTangent = CCEffectUtilsTangentInEnvironmentSpace(pass.transform, CCEffectUtilsMat4FromAffineTransform(worldToRefractEnvTexture));
179+
GLKVector4 refractTangent = GLKVector4Normalize(GLKMatrix4MultiplyVector4(effectNodeToRefractEnvTexture, GLKVector4Make(1.0f, 0.0f, 0.0f, 0.0f)));
171180
GLKVector4 refractNormal = GLKVector4Make(0.0f, 0.0f, 1.0f, 1.0f);
172181
GLKVector4 refractBinormal = GLKVector4CrossProduct(refractNormal, refractTangent);
173182
pass.shaderUniforms[weakSelf.uniformTranslationTable[@"u_tangent"]] = [NSValue valueWithGLKVector2:GLKVector2Make(refractTangent.x, refractTangent.y)];
174183
pass.shaderUniforms[weakSelf.uniformTranslationTable[@"u_binormal"]] = [NSValue valueWithGLKVector2:GLKVector2Make(refractBinormal.x, refractBinormal.y)];
175184

176-
// Setup the transform from normalized device coordinates (NDC, which is the space our vertex
177-
// positions are in) to environment texture space. We use this to compute environment texture
178-
// coordinates in the vertex shader.s
179-
GLKMatrix4 worldToRefractEnvTextureMat = CCEffectUtilsMat4FromAffineTransform(worldToRefractEnvTexture);
180-
GLKMatrix4 ndcToRefractEnvTextureMat = GLKMatrix4Multiply(worldToRefractEnvTextureMat, pass.ndcToWorld);
181-
182-
pass.shaderUniforms[weakSelf.uniformTranslationTable[@"u_ndcToEnv"]] = [NSValue valueWithGLKMatrix4:ndcToRefractEnvTextureMat];
183-
184185
} copy]];
185186

186187
self.renderPasses = @[pass0];

cocos2d/CCEffectRenderer.m

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
#import "CCDirector.h"
1212
#import "CCEffect.h"
1313
#import "CCEffectStack.h"
14+
#import "CCEffectUtils.h"
1415
#import "CCTexture.h"
15-
#import "ccUtils.h"
1616

1717
#import "CCEffect_Private.h"
1818
#import "CCRenderer_Private.h"
@@ -249,6 +249,7 @@ -(void)drawSprite:(CCSprite *)sprite withEffect:(CCEffect *)effect uniforms:(NSM
249249
}
250250
renderPass.renderer = renderer;
251251
renderPass.renderPassId = i;
252+
renderPass.node = sprite;
252253

253254
if (fromIntermediate && (renderPass.indexInEffect == 0))
254255
{
@@ -288,10 +289,7 @@ -(void)drawSprite:(CCSprite *)sprite withEffect:(CCEffect *)effect uniforms:(NSM
288289
if (toFramebuffer)
289290
{
290291
renderPass.transform = *transform;
291-
292-
GLKMatrix4 ndcToWorldMat;
293-
[renderer.globalShaderUniforms[CCShaderUniformProjectionInv] getValue:&ndcToWorldMat];
294-
renderPass.ndcToWorld = ndcToWorldMat;
292+
renderPass.ndcToNodeLocal = GLKMatrix4Invert(*transform, nil);
295293

296294
[renderPass begin:previousPassTexture];
297295
[renderPass update];
@@ -305,15 +303,8 @@ -(void)drawSprite:(CCSprite *)sprite withEffect:(CCEffect *)effect uniforms:(NSM
305303
GLKMatrix4 invRenderTargetProjection = GLKMatrix4Invert(renderTargetProjection, &inverted);
306304
NSAssert(inverted, @"Unable to invert matrix.");
307305

308-
GLKMatrix4 invGlobalProjection;
309-
[renderer.globalShaderUniforms[CCShaderUniformProjectionInv] getValue:&invGlobalProjection];
310-
311-
GLKMatrix4 ndcToNodeMat = invRenderTargetProjection;
312-
GLKMatrix4 nodeToWorldMat = GLKMatrix4Multiply(invGlobalProjection, *transform);
313-
GLKMatrix4 ndcToWorldMat = GLKMatrix4Multiply(nodeToWorldMat, ndcToNodeMat);
314-
315306
renderPass.transform = renderTargetProjection;
316-
renderPass.ndcToWorld = ndcToWorldMat;
307+
renderPass.ndcToNodeLocal = invRenderTargetProjection;
317308

318309
CGSize rtSize = CGSizeMake((_contentSize.width + 2 * effect.padding.width) * _contentScale, (_contentSize.height + 2 * effect.padding.height) * _contentScale);
319310
rtSize.width = (rtSize.width <= 1.0f) ? 1.0f : rtSize.width;

cocos2d/CCEffectUtils.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,11 @@
88

99
#import "CCSprite.h"
1010

11+
GLKMatrix4 CCEffectUtilsTransformFromNodeToNode(CCNode *first, CCNode *second, BOOL *isPossible);
1112

12-
CGAffineTransform CCEffectUtilsWorldToEnvironmentTransform(CCSprite *environment);
13-
GLKVector4 CCEffectUtilsTangentInEnvironmentSpace(GLKMatrix4 effectToWorldMat, GLKMatrix4 worldToEnvMat);
1413
GLKMatrix4 CCEffectUtilsMat4FromAffineTransform(CGAffineTransform at);
1514
float CCEffectUtilsConditionRefraction(float refraction);
1615
float CCEffectUtilsConditionShininess(float shininess);
1716
float CCEffectUtilsConditionFresnelBias(float bias);
1817
float CCEffectUtilsConditionFresnelPower(float power);
19-
18+
void CCEffectUtilsPrintMatrix(NSString *label, GLKMatrix4 matrix);

0 commit comments

Comments
 (0)