Skip to content

Commit ccdd423

Browse files
committed
Got a basic distance field effect working (still tinkering with unfiroms)
1 parent 488417c commit ccdd423

File tree

7 files changed

+238
-140
lines changed

7 files changed

+238
-140
lines changed

Resources/Images/output.png

-6.27 KB
Loading

cocos2d-ios.xcodeproj/project.pbxproj

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,10 @@
328328
D27451AB19AD430A006DA0A1 /* CCEffectDropShadow.h in Headers */ = {isa = PBXBuildFile; fileRef = D27451A819AD430A006DA0A1 /* CCEffectDropShadow.h */; };
329329
D27451AC19AD430A006DA0A1 /* CCEffectDropShadow.m in Sources */ = {isa = PBXBuildFile; fileRef = D27451A919AD430A006DA0A1 /* CCEffectDropShadow.m */; };
330330
D27451AD19AD430A006DA0A1 /* CCEffectDropShadow.m in Sources */ = {isa = PBXBuildFile; fileRef = D27451A919AD430A006DA0A1 /* CCEffectDropShadow.m */; };
331+
D27451B719AE5517006DA0A1 /* CCEffectDistanceField.h in Headers */ = {isa = PBXBuildFile; fileRef = D27451B519AE5517006DA0A1 /* CCEffectDistanceField.h */; };
332+
D27451B819AE5517006DA0A1 /* CCEffectDistanceField.m in Sources */ = {isa = PBXBuildFile; fileRef = D27451B619AE5517006DA0A1 /* CCEffectDistanceField.m */; };
333+
D27451BD19AEC84C006DA0A1 /* CCEffectDistanceField.m in Sources */ = {isa = PBXBuildFile; fileRef = D27451B619AE5517006DA0A1 /* CCEffectDistanceField.m */; };
334+
D27451BE19AEC84F006DA0A1 /* CCEffectDistanceField.h in Headers */ = {isa = PBXBuildFile; fileRef = D27451B519AE5517006DA0A1 /* CCEffectDistanceField.h */; };
331335
D285ECF0192EA92A009F4E88 /* CCGLView.h in Headers */ = {isa = PBXBuildFile; fileRef = D285ECEE192EA92A009F4E88 /* CCGLView.h */; };
332336
D285ECF1192EA92A009F4E88 /* CCGLView.m in Sources */ = {isa = PBXBuildFile; fileRef = D285ECEF192EA92A009F4E88 /* CCGLView.m */; };
333337
D285ECF8192EF5B2009F4E88 /* CCDirectorAndroid.h in Headers */ = {isa = PBXBuildFile; fileRef = D285ECF6192EF5B2009F4E88 /* CCDirectorAndroid.h */; };
@@ -1053,6 +1057,8 @@
10531057
D272032118FC89A000B100FF /* CCEffectStack.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCEffectStack.m; sourceTree = "<group>"; };
10541058
D27451A819AD430A006DA0A1 /* CCEffectDropShadow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCEffectDropShadow.h; sourceTree = "<group>"; };
10551059
D27451A919AD430A006DA0A1 /* CCEffectDropShadow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCEffectDropShadow.m; sourceTree = "<group>"; };
1060+
D27451B519AE5517006DA0A1 /* CCEffectDistanceField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCEffectDistanceField.h; sourceTree = "<group>"; };
1061+
D27451B619AE5517006DA0A1 /* CCEffectDistanceField.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCEffectDistanceField.m; sourceTree = "<group>"; };
10561062
D285ECEE192EA92A009F4E88 /* CCGLView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CCGLView.h; path = Android/CCGLView.h; sourceTree = "<group>"; };
10571063
D285ECEF192EA92A009F4E88 /* CCGLView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CCGLView.m; path = Android/CCGLView.m; sourceTree = "<group>"; };
10581064
D285ECF6192EF5B2009F4E88 /* CCDirectorAndroid.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CCDirectorAndroid.h; path = Android/CCDirectorAndroid.h; sourceTree = "<group>"; };
@@ -1795,6 +1801,7 @@
17951801
D272031618FC897D00B100FF /* Effects */ = {
17961802
isa = PBXGroup;
17971803
children = (
1804+
D27451B419AE54C0006DA0A1 /* DistanceFields */,
17981805
D3903B081995285B003AA81A /* CCEffectBlur.h */,
17991806
D3903B091995285B003AA81A /* CCEffectBlur.m */,
18001807
D268FE151980791300ECBCD0 /* CCEffectRefraction.h */,
@@ -1832,6 +1839,15 @@
18321839
name = Effects;
18331840
sourceTree = "<group>";
18341841
};
1842+
D27451B419AE54C0006DA0A1 /* DistanceFields */ = {
1843+
isa = PBXGroup;
1844+
children = (
1845+
D27451B519AE5517006DA0A1 /* CCEffectDistanceField.h */,
1846+
D27451B619AE5517006DA0A1 /* CCEffectDistanceField.m */,
1847+
);
1848+
name = DistanceFields;
1849+
sourceTree = "<group>";
1850+
};
18351851
D285ECED192E7E06009F4E88 /* Android */ = {
18361852
isa = PBXGroup;
18371853
children = (
@@ -2027,6 +2043,7 @@
20272043
50F29F6F102053370046CA73 /* base64.h in Headers */,
20282044
D31C795219994197007921E1 /* CCMetalSupport_Private.h in Headers */,
20292045
50F2A105102094550046CA73 /* ZipUtils.h in Headers */,
2046+
D27451B719AE5517006DA0A1 /* CCEffectDistanceField.h in Headers */,
20302047
50CFAC391023660000175934 /* CCTMXXMLParser.h in Headers */,
20312048
50316AA610291280003ACFE7 /* CCRenderTexture.h in Headers */,
20322049
B7D273171822F4AA0054849B /* CCBSequenceProperty.h in Headers */,
@@ -2268,6 +2285,7 @@
22682285
D2FEB686194F6C9E00FC0574 /* CCBuilderReader.h in Headers */,
22692286
D2FEB687194F6C9E00FC0574 /* CCAppDelegate.h in Headers */,
22702287
D2FEB688194F6C9E00FC0574 /* CCShader.h in Headers */,
2288+
D27451BE19AEC84F006DA0A1 /* CCEffectDistanceField.h in Headers */,
22712289
D2FEB689194F6C9E00FC0574 /* CCES2Renderer.h in Headers */,
22722290
D268FE1E1980791400ECBCD0 /* CCEffectUtils.h in Headers */,
22732291
D2FEB68A194F6C9E00FC0574 /* OALAudioTrackNotifications.h in Headers */,
@@ -2582,6 +2600,7 @@
25822600
D2DDB0A519805E8400233D80 /* CCQuaternion.m in Sources */,
25832601
D36D31B718BD3CAA00E45F08 /* CCProgressNode.m in Sources */,
25842602
B7705FDD1831A07B0043CC67 /* OALSimpleAudio.m in Sources */,
2603+
D27451B819AE5517006DA0A1 /* CCEffectDistanceField.m in Sources */,
25852604
A0DA0BC415BCDCA200E80A92 /* CCDrawNode.m in Sources */,
25862605
B7705FF31831A07B0043CC67 /* ALWrapper.m in Sources */,
25872606
B7705FF91831A07B0043CC67 /* OALSuspendHandler.m in Sources */,
@@ -2676,6 +2695,7 @@
26762695
D2FEB6E0194F6C9E00FC0574 /* CCParallaxNode.m in Sources */,
26772696
D2FEB6E1194F6C9E00FC0574 /* CCActionManager.m in Sources */,
26782697
D2FEB6E2194F6C9E00FC0574 /* CCAppDelegate.m in Sources */,
2698+
D27451BD19AEC84C006DA0A1 /* CCEffectDistanceField.m in Sources */,
26792699
D2FEB6E3194F6C9E00FC0574 /* CCBReader.m in Sources */,
26802700
D2FEB6E5194F6C9E00FC0574 /* base64.c in Sources */,
26812701
D2FEB6E6194F6C9E00FC0574 /* OALAudioTrackNotifications.m in Sources */,

cocos2d-ui-tests/tests/CCEffectsTest.m

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,36 @@ -(id)init
1616
return self;
1717
}
1818

19+
-(void)setupDistanceFieldEffectTest
20+
{
21+
self.subTitle = @"Distance Field Effect Test";
22+
23+
// CCNodeColor* environment = [CCNodeColor nodeWithColor:[CCColor whiteColor]];
24+
CCSprite *environment = [CCSprite spriteWithImageNamed:@"Images/MountainPanorama.jpg"];
25+
environment.positionType = CCPositionTypeNormalized;
26+
environment.anchorPoint = ccp(0.5, 0.5);
27+
environment.position = ccp(0.5f, 0.5f);
28+
29+
[self.contentNode addChild:environment];
30+
31+
CCColor *glowColor = [CCColor colorWithRed:0.0 green:0.0 blue:1.0 alpha:1.0];
32+
CCEffectDistanceField* effect = [CCEffectDistanceField effectWithGlowColor:glowColor];
33+
34+
CCSprite *sampleSprite = [CCSprite spriteWithImageNamed:@"Images/output.png"];
35+
sampleSprite.position = ccp(0.5, 0.5);
36+
sampleSprite.positionType = CCPositionTypeNormalized;
37+
sampleSprite.effect = effect;
38+
sampleSprite.scale = 2.0f;
39+
40+
CCNodeColor* node = [[CCNodeColor alloc] initWithColor:[CCColor redColor]];
41+
// node.contentSizeInPoints = CGSizeMake(25, 25);
42+
node.contentSize = CGSizeMake(6, 6);
43+
node.position = ccp(10.0, 50.0);
44+
45+
[self.contentNode addChild:node];
46+
[self.contentNode addChild:sampleSprite];
47+
}
48+
1949
-(void)setupDropShadowEffectTest
2050
{
2151
self.subTitle = @"DropShadow Effect Test";
@@ -758,31 +788,4 @@ -(void)renderTextureHelper:(CCNode *)stage size:(CGSize)size
758788
[node addChild:sprite];
759789
}
760790

761-
// Distance fields - work in progress
762-
763-
// WIP
764-
//-(void)setupOuterGlowEffectTest_dist
765-
//{
766-
// self.subTitle = @"OuterGlow Effect Test";
767-
//
768-
// // CCNodeColor* environment = [CCNodeColor nodeWithColor:[CCColor whiteColor]];
769-
// CCSprite *environment = [CCSprite spriteWithImageNamed:@"Images/MountainPanorama.jpg"];
770-
// environment.positionType = CCPositionTypeNormalized;
771-
// environment.anchorPoint = ccp(0.5, 0.5);
772-
// environment.position = ccp(0.5f, 0.5f);
773-
//
774-
// [self.contentNode addChild:environment];
775-
//
776-
// CCColor *glowColor = [CCColor colorWithRed:0.0 green:0.0 blue:1.0 alpha:0.5];
777-
// CCEffectOuterGlow* effect = [CCEffectOuterGlow effectWithGlowColor:glowColor];
778-
//
779-
// CCSprite *sampleSprite = [CCSprite spriteWithImageNamed:@"Images/output.png"];
780-
// sampleSprite.position = ccp(0.5, 0.5);
781-
// sampleSprite.positionType = CCPositionTypeNormalized;
782-
// sampleSprite.effect = effect;
783-
// sampleSprite.scale = 2.0f;
784-
//
785-
// [self.contentNode addChild:sampleSprite];
786-
//}
787-
788791
@end

cocos2d/CCEffectOuterGlow_dist.h renamed to cocos2d/CCEffectDistanceField.h

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//
2-
// CCEffectOuterGlow.h
2+
// CCEffectDistanceField.h
33
// cocos2d-ios
44
//
55
// Created by Oleg Osin on 8/8/14.
@@ -9,11 +9,11 @@
99
#import "CCEffect.h"
1010

1111
/**
12-
* CCEffectOuterGlow create a drop shadow.
12+
* CCEffectDistanceField create a drop shadow.
1313
*
1414
*/
1515

16-
@interface CCEffectOuterGlow : CCEffect
16+
@interface CCEffectDistanceField : CCEffect
1717

1818
/// -----------------------------------------------------------------------
1919
/// @name Accessing Effect Attributes
@@ -22,39 +22,47 @@
2222
/** Color of the shadow,
2323
* [CCColor blackColor] will result in an opaque black drop shadow.
2424
*/
25-
@property (nonatomic) CCColor* glowColor;
25+
@property (nonatomic, strong) CCColor* glowColor;
26+
@property (nonatomic, strong) CCColor* fillColor;
27+
@property (nonatomic, strong) CCColor* outlineColor;
28+
29+
@property (nonatomic) BOOL glow;
30+
@property (nonatomic) BOOL outline;
31+
@property (nonatomic) float outlineInnerWidth;
32+
@property (nonatomic) float outlineOuterWidth;
33+
@property (nonatomic) GLKVector2 glowOffset;
2634

2735
/// -----------------------------------------------------------------------
28-
/// @name Initializing a CCEffectOuterGlow object
36+
/// @name Initializing a CCEffectDistanceField object
2937
/// -----------------------------------------------------------------------
3038

3139
/**
32-
* Initializes a CCEffectOuterGlow object with a (5, -5) black drop shadow offset .
40+
* Initializes a CCEffectDistanceField object with a (5, -5) black drop shadow offset .
3341
*
34-
* @return The CCEffectOuterGlow object.
42+
* @return The CCEffectDistanceField object.
3543
*/
3644
-(id)init;
3745

3846
/**
39-
* Initializes a CCEffectOuterGlow object with the supplied parameters.
47+
* Initializes a CCEffectDistanceField object with the supplied parameters.
4048
*
4149
* @param glowColor Color of the glow, a [CCColor blackColor] will result in an opaque black drop shadow.
4250
*
43-
* @return The CCEffectOuterGlow object.
51+
* @return The CCEffectDistanceField object.
4452
*/
4553
-(id)initWithGlowColor:(CCColor*)glowColor;
4654

4755

4856
/// -----------------------------------------------------------------------
49-
/// @name Creating a CCEffectOuterGlow object
57+
/// @name Creating a CCEffectDistanceField object
5058
/// -----------------------------------------------------------------------
5159

5260
/**
53-
* Initializes a CCEffectOuterGlow object with the supplied parameters.
61+
* Initializes a CCEffectDistanceField object with the supplied parameters.
5462
*
5563
* @param glowColor Color of the glow, a [CCColor blackColor] will result in an opaque black drop shadow.
5664
*
57-
* @return The CCEffectOuterGlow object.
65+
* @return The CCEffectDistanceField object.
5866
*/
5967
+(id)effectWithGlowColor:(CCColor*)glowColor;
6068

cocos2d/CCEffectDistanceField.m

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
//
2+
// CCEffectDistanceField.m
3+
// cocos2d-ios
4+
//
5+
// Created by Oleg Osin on 8/8/14.
6+
//
7+
//
8+
9+
#import "CCEffectDistanceField.h"
10+
11+
#import "CCEffectDistanceField.h"
12+
#import "CCEffect_Private.h"
13+
#import "CCRenderer.h"
14+
#import "CCTexture.h"
15+
16+
@implementation CCEffectDistanceField
17+
18+
-(id)init
19+
{
20+
return [self initWithGlowColor:[CCColor blackColor]];
21+
}
22+
23+
-(id)initWithGlowColor:(CCColor*)glowColor
24+
{
25+
NSArray *uniforms = @[
26+
[CCEffectUniform uniform:@"vec4" name:@"u_glowColor" value:[NSValue valueWithGLKVector4:glowColor.glkVector4]],
27+
[CCEffectUniform uniform:@"vec4" name:@"u_fillColor" value:[NSValue valueWithGLKVector4:[CCColor blackColor].glkVector4]],
28+
[CCEffectUniform uniform:@"vec4" name:@"u_outlineColor" value:[NSValue valueWithGLKVector4:[CCColor redColor].glkVector4]],
29+
[CCEffectUniform uniform:@"float" name:@"u_outline" value:[NSNumber numberWithFloat:1.0f]],
30+
[CCEffectUniform uniform:@"float" name:@"u_glow" value:[NSNumber numberWithFloat:1.0f]],
31+
[CCEffectUniform uniform:@"vec2" name:@"u_glowOffset" value:[NSValue valueWithGLKVector2:GLKVector2Make(0.0, 0.0)]],
32+
[CCEffectUniform uniform:@"vec2" name:@"u_outlineOuterWidth" value:[NSValue valueWithGLKVector2:GLKVector2Make(0.5, 1.0)]],
33+
[CCEffectUniform uniform:@"vec2" name:@"u_outlineInnerWidth" value:[NSValue valueWithGLKVector2:GLKVector2Make(0.4, 0.42)]],
34+
];
35+
36+
if((self = [super initWithFragmentUniforms:uniforms vertexUniforms:nil varyings:nil]))
37+
{
38+
_outlineInnerWidth = 0.08;
39+
_outlineOuterWidth = 0.08;
40+
_glow = YES;
41+
_outline = YES;
42+
_glowOffset = GLKVector2Make(0.0f, 0.0f);
43+
_glowColor = glowColor;
44+
_fillColor = [CCColor blackColor];
45+
_outlineColor = [CCColor redColor];
46+
47+
self.debugName = @"CCEffectDistanceField";
48+
}
49+
return self;
50+
}
51+
52+
+(id)effectWithGlowColor:(CCColor*)glowColor
53+
{
54+
return [[self alloc] initWithGlowColor:glowColor];
55+
}
56+
57+
-(void)buildFragmentFunctions
58+
{
59+
self.fragmentFunctions = [[NSMutableArray alloc] init];
60+
61+
NSString* effectBody = CC_GLSL(
62+
vec4 outputColor = u_fillColor;
63+
outputColor.a = 1.0;
64+
float distAlphaMask = texture2D(cc_MainTexture, cc_FragTexCoord1).r;
65+
66+
// 0.5 == center(edge), < 0.5 == outside, > 0.5 == inside
67+
float min0 = u_outlineOuterWidth.x;
68+
float max0 = u_outlineOuterWidth.y;
69+
float min1 = u_outlineInnerWidth.x;
70+
float max1 = u_outlineInnerWidth.y;
71+
if(u_outline == 1.0 && distAlphaMask >= min0 && distAlphaMask <= max1)//outline
72+
{
73+
float oFactor = 1.0;
74+
if(distAlphaMask <= min1)
75+
{
76+
oFactor = smoothstep(min0, min1, distAlphaMask);
77+
}
78+
else
79+
{
80+
oFactor = smoothstep(max1, max0, distAlphaMask);
81+
}
82+
83+
outputColor = mix(outputColor, u_outlineColor, oFactor);
84+
}
85+
86+
float center = 0.5;
87+
float transition = fwidth(distAlphaMask) * 1.0;
88+
89+
float min = center - transition;
90+
float max = center + transition;
91+
92+
// soft edges
93+
outputColor.a *= smoothstep(min, max, distAlphaMask);
94+
95+
// glow
96+
if(u_glow == 1.0)
97+
{
98+
vec4 glowTexel = texture2D(cc_MainTexture, cc_FragTexCoord1 - u_glowOffset);
99+
// min -= 0.2;
100+
// max += 0.2;
101+
102+
min = 0.3;
103+
max = 0.5;
104+
105+
vec4 glowc = u_glowColor * smoothstep(min, max, glowTexel.r);
106+
107+
outputColor = mix(glowc, outputColor, outputColor.a);
108+
}
109+
110+
return outputColor;
111+
112+
);
113+
114+
CCEffectFunction* fragmentFunction = [[CCEffectFunction alloc] initWithName:@"outerGlowEffect"
115+
body:effectBody inputs:nil returnType:@"vec4"];
116+
[self.fragmentFunctions addObject:fragmentFunction];
117+
}
118+
119+
-(void)buildRenderPasses
120+
{
121+
__weak CCEffectDistanceField *weakSelf = self;
122+
123+
CCEffectRenderPass *pass0 = [[CCEffectRenderPass alloc] init];
124+
pass0.debugLabel = @"CCEffectDistanceField pass 0";
125+
pass0.shader = self.shader;
126+
pass0.blendMode = [CCBlendMode premultipliedAlphaMode];
127+
pass0.beginBlocks = @[[^(CCEffectRenderPass *pass, CCTexture *previousPassTexture) {
128+
129+
pass.shaderUniforms[CCShaderUniformMainTexture] = previousPassTexture;
130+
pass.shaderUniforms[CCShaderUniformPreviousPassTexture] = previousPassTexture;
131+
132+
pass.shaderUniforms[weakSelf.uniformTranslationTable[@"u_glowColor"]] = [NSValue valueWithGLKVector4:weakSelf.glowColor.glkVector4];
133+
pass.shaderUniforms[weakSelf.uniformTranslationTable[@"u_fillColor"]] = [NSValue valueWithGLKVector4:weakSelf.fillColor.glkVector4];
134+
pass.shaderUniforms[weakSelf.uniformTranslationTable[@"u_outlineColor"]] = [NSValue valueWithGLKVector4:weakSelf.outlineColor.glkVector4];
135+
136+
// 0.5 == center(edge), < 0.5 == outside, > 0.5 == inside
137+
float innerMin = 0.5;
138+
float innerMax = (0.5 * _outlineInnerWidth) + innerMin;
139+
pass.shaderUniforms[weakSelf.uniformTranslationTable[@"u_outlineInnerWidth"]] = [NSValue valueWithGLKVector2:GLKVector2Make(innerMin, innerMax)];
140+
141+
float outerMin = (0.5 * (1.0 - _outlineOuterWidth));
142+
float outerMax = 0.5;
143+
pass.shaderUniforms[weakSelf.uniformTranslationTable[@"u_outlineOuterWidth"]] = [NSValue valueWithGLKVector2:GLKVector2Make(outerMin, outerMax)];
144+
145+
pass.shaderUniforms[weakSelf.uniformTranslationTable[@"u_outline"]] = _outline ? [NSNumber numberWithFloat:1.0f] : [NSNumber numberWithFloat:0.0f];
146+
pass.shaderUniforms[weakSelf.uniformTranslationTable[@"u_glow"]] = _glow ? [NSNumber numberWithFloat:1.0f] : [NSNumber numberWithFloat:0.0f];
147+
148+
GLKVector2 offset = GLKVector2Make(weakSelf.glowOffset.x / previousPassTexture.contentSize.width, weakSelf.glowOffset.y / previousPassTexture.contentSize.height);
149+
pass.shaderUniforms[weakSelf.uniformTranslationTable[@"u_glowOffset"]] = [NSValue valueWithGLKVector2:offset];
150+
151+
} copy]];
152+
153+
self.renderPasses = @[pass0];
154+
}
155+
156+
-(void)setOutlineInnerWidth:(float)outlineInnerWidth
157+
{
158+
_outlineInnerWidth = clampf(_outlineInnerWidth, 0.0f, 1.0f);
159+
}
160+
161+
-(void)setOutlineOuterWidth:(float)outlineOuterWidth
162+
{
163+
_outlineOuterWidth = clampf(_outlineOuterWidth, 0.0f, 1.0f);
164+
}
165+
166+
167+
@end

0 commit comments

Comments
 (0)