Skip to content

Commit 7eee454

Browse files
author
Thayer J Andrews
committed
CCEffects - Improve padding support
Effects can now inform the effect renderer how they are using the different texture coordinate sets so the renderer can correctly decide how to transform the texture coordinates when padding is requested.
1 parent d8ba36e commit 7eee454

File tree

3 files changed

+180
-65
lines changed

3 files changed

+180
-65
lines changed

cocos2d/CCEffect.m

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,9 +214,19 @@ -(NSString*)declaration
214214
@implementation CCEffectRenderPass
215215

216216
-(id)init
217+
{
218+
return [self initWithIndex:0];
219+
}
220+
221+
-(id)initWithIndex:(NSUInteger)indexInEffect
217222
{
218223
if((self = [super init]))
219224
{
225+
_indexInEffect = indexInEffect;
226+
227+
_texCoord1Mapping = CCEffectTexCoordMapPreviousPassTex;
228+
_texCoord2Mapping = CCEffectTexCoordMapCustomTex;
229+
220230
_beginBlocks = @[[^(CCEffectRenderPass *pass, CCTexture *previousPassTexture){} copy]];
221231
_endBlocks = @[[^(CCEffectRenderPass *pass){} copy]];
222232

cocos2d/CCEffectRenderer.m

Lines changed: 157 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,39 @@
2020
#import "CCTexture_Private.h"
2121

2222

23+
typedef NS_ENUM(NSUInteger, CCEffectTexCoordSource)
24+
{
25+
CCEffectTexCoordSource1 = 0,
26+
CCEffectTexCoordSource2 = 1,
27+
CCEffectTexCoordConstant = 2
28+
};
29+
2330
typedef NS_ENUM(NSUInteger, CCEffectTexCoordTransform)
2431
{
25-
CCEffectTexCoordNoChange = 0,
26-
CCEffectTexCoordOverwrite = 1,
27-
CCEffectTexCoordPad = 2,
32+
CCEffectTexCoordTransformNone = 0,
33+
CCEffectTexCoordTransformPad = 1
2834
};
2935

36+
typedef struct _CCEffectTexCoordFunc
37+
{
38+
CCEffectTexCoordSource source;
39+
CCEffectTexCoordTransform transform;
40+
41+
} CCEffectTexCoordFunc;
42+
43+
static const CCEffectTexCoordFunc CCEffectTexCoordOverwrite = { CCEffectTexCoordConstant, CCEffectTexCoordTransformNone };
44+
static const CCEffectTexCoordFunc CCEffectTexCoord1Untransformed = { CCEffectTexCoordSource1, CCEffectTexCoordTransformNone };
45+
static const CCEffectTexCoordFunc CCEffectTexCoord1Padded = { CCEffectTexCoordSource1, CCEffectTexCoordTransformPad };
46+
static const CCEffectTexCoordFunc CCEffectTexCoord2Untransformed = { CCEffectTexCoordSource2, CCEffectTexCoordTransformNone };
47+
static const CCEffectTexCoordFunc CCEffectTexCoord2Padded = { CCEffectTexCoordSource2, CCEffectTexCoordTransformPad };
48+
3049

31-
static CCSpriteVertexes padVertices(const CCSpriteVertexes *input, CGSize padding, CCEffectTexCoordTransform texCoordTransform);
32-
static CCVertex padVertex(CCVertex input, GLKVector2 positionOffset);
33-
static CCVertex padVertexAndTexCoords(CCVertex input, GLKVector2 positionOffset, GLKVector2 texCoord1Offset, GLKVector2 texCoord2Offset);
34-
static CCVertex padVertexAndOverwriteTexCoords(CCVertex input, GLKVector2 positionOffset, GLKVector2 texCoord1, GLKVector2 texCoord2);
50+
static CCEffectTexCoordFunc selectTexCoordFunc(CCEffectTexCoordMapping mapping, CCEffectTexCoordSource source, BOOL fromIntermediate, BOOL padMainTexCoords);
51+
static CCSpriteVertexes padVertices(const CCSpriteVertexes *input, CGSize padding, CCEffectTexCoordFunc tc1, CCEffectTexCoordFunc tc2);
52+
static GLKVector4 padVertexPosition(GLKVector4 input, GLKVector2 positionOffset);
53+
static GLKVector2 transformTexCoords(CCEffectTexCoordTransform tcTransform, GLKVector2 padding, GLKVector2 input);
54+
static GLKVector2 selectTexCoordSource(CCEffectTexCoordSource tcSource, GLKVector2 tc1, GLKVector2 tc2, GLKVector2 tcConst);
55+
static GLKVector2 selectTexCoordPadding(CCEffectTexCoordSource tcSource, GLKVector2 tc1Padding, GLKVector2 tc2Padding);
3556

3657

3758
@interface CCEffectRenderTarget : NSObject
@@ -191,6 +212,7 @@ -(void)drawSprite:(CCSprite *)sprite withEffect:(CCEffect *)effect uniforms:(NSM
191212
extraPassCount = 1;
192213
}
193214

215+
BOOL padMainTexCoords = YES;
194216
CCEffectRenderTarget *previousPassRT = nil;
195217
for(NSUInteger i = 0; i < (effectPassCount + extraPassCount); i++)
196218
{
@@ -228,6 +250,11 @@ -(void)drawSprite:(CCSprite *)sprite withEffect:(CCEffect *)effect uniforms:(NSM
228250
renderPass.renderer = renderer;
229251
renderPass.renderPassId = i;
230252

253+
if (fromIntermediate && (renderPass.indexInEffect == 0))
254+
{
255+
padMainTexCoords = NO;
256+
}
257+
231258
// The different render sources and destinations and how we need to handle padding.
232259
// When the source of a render pass is the original sprite, we need to pad both the
233260
// vertex positions and texture coordinates to make the rendered geometry larger without
@@ -237,12 +264,15 @@ -(void)drawSprite:(CCSprite *)sprite withEffect:(CCEffect *)effect uniforms:(NSM
237264
//
238265
// - First pass directly into FB : Pad vertices and texture coordinates
239266
// - First pass into intermediate RT : Pad vertices and texture coordinates, add padding to RT, adjust ortho matrix
240-
// - Later pass into FB : Pad vertices but not texture coordiates
241-
// - Later pass into intermediate RT : Pad vertices but not texture coordinates, add padding to RT, adjust ortho matrix
267+
// - Later pass into FB : Pad vertices, overwrite texture coordiates so they are lower-left (0,0) upper right (1, 1)
268+
// - Later pass into intermediate RT : Pad vertices, overwrite texture coordiates so they are lower-left (0,0) upper right (1, 1), add padding to RT, adjust ortho matrix
242269
//
243-
CCEffectTexCoordTransform texCoordTransform = (fromIntermediate) ? CCEffectTexCoordOverwrite : CCEffectTexCoordPad;
244270

245-
renderPass.verts = padVertices(sprite.vertexes, effect.padding, texCoordTransform);
271+
CCEffectTexCoordFunc tc1 = selectTexCoordFunc(renderPass.texCoord1Mapping, CCEffectTexCoordSource1, fromIntermediate, padMainTexCoords);
272+
CCEffectTexCoordFunc tc2 = selectTexCoordFunc(renderPass.texCoord2Mapping, CCEffectTexCoordSource2, fromIntermediate, padMainTexCoords);
273+
274+
renderPass.verts = padVertices(sprite.vertexes, effect.padding, tc1, tc2);
275+
246276
renderPass.texCoord1Center = GLKVector2Make((sprite.vertexes->tr.texCoord1.s + sprite.vertexes->bl.texCoord1.s) * 0.5f, (sprite.vertexes->tr.texCoord1.t + sprite.vertexes->bl.texCoord1.t) * 0.5f);
247277
renderPass.texCoord1Extents = GLKVector2Make((sprite.vertexes->tr.texCoord1.s - sprite.vertexes->bl.texCoord1.s) * 0.5f, (sprite.vertexes->tr.texCoord1.t - sprite.vertexes->bl.texCoord1.t) * 0.5f);
248278
renderPass.texCoord2Center = GLKVector2Make((sprite.vertexes->tr.texCoord2.s + sprite.vertexes->bl.texCoord2.s) * 0.5f, (sprite.vertexes->tr.texCoord2.t + sprite.vertexes->bl.texCoord2.t) * 0.5f);
@@ -376,80 +406,142 @@ - (void)freeAllRenderTargets
376406

377407
@end
378408

379-
CCSpriteVertexes padVertices(const CCSpriteVertexes *input, CGSize padding, CCEffectTexCoordTransform texCoordTransform)
409+
410+
CCEffectTexCoordFunc selectTexCoordFunc(CCEffectTexCoordMapping mapping, CCEffectTexCoordSource source, BOOL fromIntermediate, BOOL padMainTexCoords)
380411
{
381-
CCSpriteVertexes output;
382-
if (texCoordTransform == CCEffectTexCoordNoChange)
412+
CCEffectTexCoordFunc func;
413+
if (mapping == CCEffectTexCoordMapMainTex)
383414
{
384-
output.bl = padVertex(input->bl, GLKVector2Make(-padding.width, -padding.height));
385-
output.br = padVertex(input->br, GLKVector2Make( padding.width, -padding.height));
386-
output.tr = padVertex(input->tr, GLKVector2Make( padding.width, padding.height));
387-
output.tl = padVertex(input->tl, GLKVector2Make(-padding.width, padding.height));
415+
if (padMainTexCoords)
416+
{
417+
func = CCEffectTexCoord1Padded;
418+
}
419+
else
420+
{
421+
func = CCEffectTexCoordOverwrite;
422+
}
388423
}
389-
else if (texCoordTransform == CCEffectTexCoordOverwrite)
424+
else if (mapping == CCEffectTexCoordMapPreviousPassTex)
390425
{
391-
output.bl = padVertexAndOverwriteTexCoords(input->bl, GLKVector2Make(-padding.width, -padding.height), GLKVector2Make(0.0f, 0.0f), GLKVector2Make(0.0f, 0.0f));
392-
output.br = padVertexAndOverwriteTexCoords(input->br, GLKVector2Make( padding.width, -padding.height), GLKVector2Make(1.0f, 0.0f), GLKVector2Make(1.0f, 0.0f));
393-
output.tr = padVertexAndOverwriteTexCoords(input->tr, GLKVector2Make( padding.width, padding.height), GLKVector2Make(1.0f, 1.0f), GLKVector2Make(1.0f, 1.0f));
394-
output.tl = padVertexAndOverwriteTexCoords(input->tl, GLKVector2Make(-padding.width, padding.height), GLKVector2Make(0.0f, 1.0f), GLKVector2Make(0.0f, 1.0f));
426+
if (fromIntermediate)
427+
{
428+
func = CCEffectTexCoordOverwrite;
429+
}
430+
else
431+
{
432+
func = CCEffectTexCoord1Padded;
433+
}
395434
}
396-
else if (texCoordTransform == CCEffectTexCoordPad)
435+
else if (mapping == CCEffectTexCoordMapCustomTex)
397436
{
398-
GLKVector2 texCoord1Step = GLKVector2Make(padding.width * (input->br.texCoord1.s - input->bl.texCoord1.s) / (input->br.position.x - input->bl.position.x),
399-
padding.height * (input->tl.texCoord1.t - input->bl.texCoord1.t) / (input->tl.position.y - input->bl.position.y));
400-
GLKVector2 texCoord2Step = GLKVector2Make(padding.width * (input->br.texCoord2.s - input->bl.texCoord2.s) / (input->br.position.x - input->bl.position.x),
401-
padding.height * (input->tl.texCoord2.t - input->bl.texCoord2.t) / (input->tl.position.y - input->bl.position.y));
402-
403-
output.bl = padVertexAndTexCoords(input->bl, GLKVector2Make(-padding.width, -padding.height), GLKVector2Make(-texCoord1Step.x, -texCoord1Step.y), GLKVector2Make(-texCoord2Step.x, -texCoord2Step.y));
404-
output.br = padVertexAndTexCoords(input->br, GLKVector2Make( padding.width, -padding.height), GLKVector2Make( texCoord1Step.x, -texCoord1Step.y), GLKVector2Make( texCoord2Step.x, -texCoord2Step.y));
405-
output.tr = padVertexAndTexCoords(input->tr, GLKVector2Make( padding.width, padding.height), GLKVector2Make( texCoord1Step.x, texCoord1Step.y), GLKVector2Make( texCoord2Step.x, texCoord2Step.y));
406-
output.tl = padVertexAndTexCoords(input->tl, GLKVector2Make(-padding.width, padding.height), GLKVector2Make(-texCoord1Step.x, texCoord1Step.y), GLKVector2Make(-texCoord2Step.x, texCoord2Step.y));
437+
func.source = source;
438+
func.transform = CCEffectTexCoordTransformPad;
407439
}
408-
return output;
440+
else
441+
{
442+
func.source = source;
443+
func.transform = CCEffectTexCoordTransformNone;
444+
}
445+
return func;
409446
}
410447

411-
CCVertex padVertex(CCVertex input, GLKVector2 positionOffset)
448+
CCSpriteVertexes padVertices(const CCSpriteVertexes *input, CGSize padding, CCEffectTexCoordFunc tc1, CCEffectTexCoordFunc tc2)
412449
{
413-
CCVertex output;
414-
output.position.x = input.position.x + positionOffset.x;
415-
output.position.y = input.position.y + positionOffset.y;
416-
output.position.z = input.position.z;
417-
output.position.w = input.position.w;
418-
output.texCoord1 = input.texCoord1;
419-
output.texCoord2 = input.texCoord2;
420-
output.color = input.color;
450+
GLKVector2 tc1Padding = GLKVector2Make(padding.width * (input->br.texCoord1.s - input->bl.texCoord1.s) / (input->br.position.x - input->bl.position.x),
451+
padding.height * (input->tl.texCoord1.t - input->bl.texCoord1.t) / (input->tl.position.y - input->bl.position.y));
452+
GLKVector2 tc2Padding = GLKVector2Make(padding.width * (input->br.texCoord2.s - input->bl.texCoord2.s) / (input->br.position.x - input->bl.position.x),
453+
padding.height * (input->tl.texCoord2.t - input->bl.texCoord2.t) / (input->tl.position.y - input->bl.position.y));
454+
455+
456+
CCSpriteVertexes output;
457+
458+
output.bl.position = padVertexPosition(input->bl.position, GLKVector2Make(-padding.width, -padding.height));
459+
output.bl.texCoord1 = transformTexCoords(tc1.transform, selectTexCoordPadding(tc1.source, GLKVector2Make(-tc1Padding.x, -tc1Padding.y), GLKVector2Make(-tc2Padding.x, -tc2Padding.y)), selectTexCoordSource(tc1.source, input->bl.texCoord1, input->bl.texCoord2, GLKVector2Make(0.0f, 0.0f)));
460+
output.bl.texCoord2 = transformTexCoords(tc2.transform, selectTexCoordPadding(tc2.source, GLKVector2Make(-tc1Padding.x, -tc1Padding.y), GLKVector2Make(-tc2Padding.x, -tc2Padding.y)), selectTexCoordSource(tc2.source, input->bl.texCoord1, input->bl.texCoord2, GLKVector2Make(0.0f, 0.0f)));
461+
output.bl.color = input->bl.color;
462+
463+
output.br.position = padVertexPosition(input->br.position, GLKVector2Make( padding.width, -padding.height));
464+
output.br.texCoord1 = transformTexCoords(tc1.transform, selectTexCoordPadding(tc1.source, GLKVector2Make( tc1Padding.x, -tc1Padding.y), GLKVector2Make( tc2Padding.x, -tc2Padding.y)), selectTexCoordSource(tc1.source, input->br.texCoord1, input->br.texCoord2, GLKVector2Make(1.0f, 0.0f)));
465+
output.br.texCoord2 = transformTexCoords(tc2.transform, selectTexCoordPadding(tc2.source, GLKVector2Make( tc1Padding.x, -tc1Padding.y), GLKVector2Make( tc2Padding.x, -tc2Padding.y)), selectTexCoordSource(tc2.source, input->br.texCoord1, input->br.texCoord2, GLKVector2Make(1.0f, 0.0f)));
466+
output.br.color = input->br.color;
421467

468+
output.tr.position = padVertexPosition(input->tr.position, GLKVector2Make( padding.width, padding.height));
469+
output.tr.texCoord1 = transformTexCoords(tc1.transform, selectTexCoordPadding(tc1.source, GLKVector2Make( tc1Padding.x, tc1Padding.y), GLKVector2Make( tc2Padding.x, tc2Padding.y)), selectTexCoordSource(tc1.source, input->tr.texCoord1, input->tr.texCoord2, GLKVector2Make(1.0f, 1.0f)));
470+
output.tr.texCoord2 = transformTexCoords(tc2.transform, selectTexCoordPadding(tc2.source, GLKVector2Make( tc1Padding.x, tc1Padding.y), GLKVector2Make( tc2Padding.x, tc2Padding.y)), selectTexCoordSource(tc2.source, input->tr.texCoord1, input->tr.texCoord2, GLKVector2Make(1.0f, 1.0f)));
471+
output.tr.color = input->tr.color;
472+
473+
output.tl.position = padVertexPosition(input->tl.position, GLKVector2Make(-padding.width, padding.height));
474+
output.tl.texCoord1 = transformTexCoords(tc1.transform, selectTexCoordPadding(tc1.source, GLKVector2Make(-tc1Padding.x, tc1Padding.y), GLKVector2Make(-tc2Padding.x, tc2Padding.y)), selectTexCoordSource(tc1.source, input->tl.texCoord1, input->tl.texCoord2, GLKVector2Make(0.0f, 1.0f)));
475+
output.tl.texCoord2 = transformTexCoords(tc2.transform, selectTexCoordPadding(tc2.source, GLKVector2Make(-tc1Padding.x, tc1Padding.y), GLKVector2Make(-tc2Padding.x, tc2Padding.y)), selectTexCoordSource(tc2.source, input->tl.texCoord1, input->tl.texCoord2, GLKVector2Make(0.0f, 1.0f)));
476+
output.tl.color = input->tl.color;
477+
422478
return output;
423479
}
424480

425-
CCVertex padVertexAndTexCoords(CCVertex input, GLKVector2 positionOffset, GLKVector2 texCoord1Offset, GLKVector2 texCoord2Offset)
481+
GLKVector4 padVertexPosition(GLKVector4 input, GLKVector2 positionOffset)
426482
{
427-
CCVertex output;
428-
output.position.x = input.position.x + positionOffset.x;
429-
output.position.y = input.position.y + positionOffset.y;
430-
output.position.z = input.position.z;
431-
output.position.w = input.position.w;
432-
output.texCoord1.s = input.texCoord1.s + texCoord1Offset.x;
433-
output.texCoord1.t = input.texCoord1.t + texCoord1Offset.y;
434-
output.texCoord2.s = input.texCoord2.s + texCoord2Offset.x;
435-
output.texCoord2.t = input.texCoord2.t + texCoord2Offset.y;
436-
output.color = input.color;
437-
483+
GLKVector4 output;
484+
output.x = input.x + positionOffset.x;
485+
output.y = input.y + positionOffset.y;
486+
output.z = input.z;
487+
output.w = input.w;
438488
return output;
439489
}
440490

441-
CCVertex padVertexAndOverwriteTexCoords(CCVertex input, GLKVector2 positionOffset, GLKVector2 texCoord1, GLKVector2 texCoord2)
491+
GLKVector2 transformTexCoords(CCEffectTexCoordTransform tcTransform, GLKVector2 padding, GLKVector2 input)
442492
{
443-
CCVertex output;
444-
output.position.x = input.position.x + positionOffset.x;
445-
output.position.y = input.position.y + positionOffset.y;
446-
output.position.z = input.position.z;
447-
output.position.w = input.position.w;
448-
output.texCoord1 = texCoord1;
449-
output.texCoord2 = texCoord2;
450-
output.color = input.color;
451-
493+
GLKVector2 output;
494+
if (tcTransform == CCEffectTexCoordTransformPad)
495+
{
496+
output.x = input.x + padding.x;
497+
output.y = input.y + padding.y;
498+
}
499+
else
500+
{
501+
output = input;
502+
}
452503
return output;
453504
}
454505

506+
GLKVector2 selectTexCoordSource(CCEffectTexCoordSource tcSource, GLKVector2 tc1, GLKVector2 tc2, GLKVector2 tcConst)
507+
{
508+
GLKVector2 output;
509+
switch (tcSource)
510+
{
511+
case CCEffectTexCoordConstant:
512+
output = tcConst;
513+
break;
514+
case CCEffectTexCoordSource1:
515+
output = tc1;
516+
break;
517+
case CCEffectTexCoordSource2:
518+
output = tc2;
519+
break;
520+
default:
521+
NSCAssert(0, @"Invalid texture coordinate source.");
522+
break;
523+
}
524+
return output;
525+
}
526+
527+
GLKVector2 selectTexCoordPadding(CCEffectTexCoordSource tcSource, GLKVector2 tc1Padding, GLKVector2 tc2Padding)
528+
{
529+
GLKVector2 output;
530+
switch (tcSource)
531+
{
532+
case CCEffectTexCoordConstant:
533+
output = GLKVector2Make(0.0f, 0.0f);
534+
break;
535+
case CCEffectTexCoordSource1:
536+
output = tc1Padding;
537+
break;
538+
case CCEffectTexCoordSource2:
539+
output = tc2Padding;
540+
break;
541+
default:
542+
NSCAssert(0, @"Invalid texture coordinate source.");
543+
break;
544+
}
545+
return output;
546+
}
455547

cocos2d/CCEffect_Private.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,14 @@ typedef NS_ENUM(NSUInteger, CCEffectPrepareStatus)
3535
CCEffectPrepareSuccess = 2,
3636
};
3737

38+
typedef NS_ENUM(NSUInteger, CCEffectTexCoordMapping)
39+
{
40+
CCEffectTexCoordMapMainTex = 0,
41+
CCEffectTexCoordMapPreviousPassTex = 1,
42+
CCEffectTexCoordMapCustomTex = 2,
43+
CCEffectTexCoordMapCustomTexNoTransform = 3
44+
};
45+
3846
@interface CCEffectFunction : NSObject
3947

4048
@property (nonatomic, readonly) NSString* body;
@@ -98,13 +106,16 @@ typedef void (^CCEffectRenderPassEndBlock)(CCEffectRenderPass *pass);
98106
// Note to self: I don't like this pattern, refactor it. I think there should be a CCRenderPass that is used by CCEffect instead. NOTE: convert this to a CCRnderPassProtocol
99107
@interface CCEffectRenderPass : NSObject
100108

109+
@property (nonatomic, readonly) NSUInteger indexInEffect;
101110
@property (nonatomic, assign) NSInteger renderPassId;
102111
@property (nonatomic, strong) CCRenderer* renderer;
103112
@property (nonatomic, assign) CCSpriteVertexes verts;
104113
@property (nonatomic, assign) GLKMatrix4 transform;
105114
@property (nonatomic, assign) GLKMatrix4 ndcToWorld;
115+
@property (nonatomic, assign) CCEffectTexCoordMapping texCoord1Mapping;
106116
@property (nonatomic, assign) GLKVector2 texCoord1Center;
107117
@property (nonatomic, assign) GLKVector2 texCoord1Extents;
118+
@property (nonatomic, assign) CCEffectTexCoordMapping texCoord2Mapping;
108119
@property (nonatomic, assign) GLKVector2 texCoord2Center;
109120
@property (nonatomic, assign) GLKVector2 texCoord2Extents;
110121
@property (nonatomic, strong) CCBlendMode* blendMode;
@@ -116,6 +127,8 @@ typedef void (^CCEffectRenderPassEndBlock)(CCEffectRenderPass *pass);
116127
@property (nonatomic, copy) NSArray* endBlocks;
117128
@property (nonatomic, copy) NSString *debugLabel;
118129

130+
-(id)initWithIndex:(NSUInteger)indexInEffect;
131+
119132
-(void)begin:(CCTexture *)previousPassTexture;
120133
-(void)update;
121134
-(void)end;

0 commit comments

Comments
 (0)