Skip to content

Commit 453a9ef

Browse files
committed
Implemented [CCShader shaderNamed:] for metal.
1 parent 6ce398b commit 453a9ef

File tree

2 files changed

+142
-17
lines changed

2 files changed

+142
-17
lines changed
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/*
2+
* cocos2d for iPhone: http://www.cocos2d-iphone.org
3+
*
4+
* Copyright (c) 2013 Apportable Inc.
5+
* Copyright (c) 2013-2014 Cocos2D Authors
6+
*
7+
* Permission is hereby granted, free of charge, to any person obtaining a copy
8+
* of this software and associated documentation files (the "Software"), to deal
9+
* in the Software without restriction, including without limitation the rights
10+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
* copies of the Software, and to permit persons to whom the Software is
12+
* furnished to do so, subject to the following conditions:
13+
*
14+
* The above copyright notice and this permission notice shall be included in
15+
* all copies or substantial portions of the Software.
16+
*
17+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23+
* THE SOFTWARE.
24+
*/
25+
26+
#include <metal_stdlib>
27+
#include <simd/simd.h>
28+
29+
#include "CCRendererSharedTypes.h"
30+
31+
using namespace metal;
32+
33+
34+
static constant float SQRT_3 = 1.73205080756888;
35+
36+
static float2 rotate(float2 v, float t){
37+
const float2x2 m1 = float2x2(float2(1.0, 0.0), float2(0.0, 1.0));
38+
const float2x2 m2 = float2x2(float2(-0.5, SQRT_3*0.5), float2(-SQRT_3*0.5, -0.5));
39+
const float2x2 m = m1*(1.0 - t) + m2*t;
40+
const float det = m[0][0]*m[1][1] - m[1][0]*m[0][1];
41+
return m*v/det;
42+
}
43+
44+
static float tri_dist(float2 uv){
45+
return max(uv.y, abs(uv.x)*SQRT_3*0.5 - uv.y*0.5);
46+
}
47+
48+
fragment half4
49+
TrippyTrianglesFS(
50+
const CCFragData in [[stage_in]],
51+
const device CCGlobalUniforms *cc_DefaultGlobals [[buffer(1)]]
52+
){
53+
const float3x3 RECT_TO_TRI = float3x3(
54+
float3(2.0*SQRT_3, 0.0, 0.0),
55+
float3(-SQRT_3, -3.0, 0.0),
56+
float3(-SQRT_3, 1.0, 1.0)
57+
);
58+
59+
const float3x3 TRI_TO_RECT = float3x3(
60+
float3(SQRT_3/6.0, 0.0, 0.0),
61+
float3(-1.0/6.0, -1.0/3.0, 0.0),
62+
float3(2.0/3.0, 1.0/3.0, 1.0)
63+
);
64+
65+
float scale = 32.0;
66+
float2 uv = in.position.xy/(scale*in.position.w);
67+
68+
// Some fun pointless distortion.
69+
float t1 = cc_DefaultGlobals->time[0]/10.0;
70+
uv = float2(uv.x + 5.0*sin(t1 + uv.y/10.0), uv.y + 5.0*sin(1.3*t1 + uv.x/10.0));
71+
72+
// Some fun pointless rotation.
73+
float2 rot = float2(cos(t1), sin(t1));
74+
uv = float2x2(float2(rot.x, rot.y), float2(-rot.y, rot.x))*uv;
75+
76+
// Convert to rectangular UVs and reflect over y=x
77+
float2 rect = (TRI_TO_RECT*float3(uv, 1.0)).xy;
78+
float2 wrap = rect - floor(rect);
79+
float2 flip = float2(max(wrap.x, wrap.y), min(wrap.x, wrap.y));
80+
81+
// Convert back to screen space
82+
float2 uv2 = (RECT_TO_TRI*float3(flip, 1.0)).xy;
83+
84+
float2 t2 = cc_DefaultGlobals->time[0]*float2(1.0, 1.3);
85+
float phase = dot(sin(uv/5.0 + t2), float2(1.0))/4.0;
86+
87+
// Rotate the UVs of the triangles.
88+
float t3 = fmod(cc_DefaultGlobals->time[0]/16.0 + phase, 1.0);
89+
float d = tri_dist(rotate(uv2, t3));
90+
91+
// Trace the d = 1.0 contour! \o/
92+
half fw = fwidth(d)*0.5;
93+
half mask = smoothstep(1.0 - fw, 1.0 + fw, d);
94+
// float mask = step(d, 1.0);
95+
96+
float t4 = 0.0;//pow(abs(2.0*mod(t3 + 0.95, 1.0) - 1.0), 3.0);
97+
half3 color1 = half3(t4, t4, 0.0);
98+
half3 color2 = half3(1.0, 1.0 - t3, 0.0);
99+
half3 color = mix(color1, color2, mask);
100+
return half4(color, 1.0);
101+
}

cocos2d/CCShader.m

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -169,22 +169,40 @@ @implementation CCShaderCache
169169

170170
-(id)createSharedDataForKey:(id<NSCopying>)key
171171
{
172-
#warning TODO Need Metal path here.
173172
NSString *shaderName = (NSString *)key;
174173

175-
NSString *fragmentName = [shaderName stringByAppendingPathExtension:@"fsh"];
176-
NSString *fragmentPath = [[CCFileUtils sharedFileUtils] fullPathForFilename:fragmentName];
177-
NSAssert(fragmentPath, @"Failed to find '%@'.", fragmentName);
178-
NSString *fragmentSource = [NSString stringWithContentsOfFile:fragmentPath encoding:NSUTF8StringEncoding error:nil];
179-
180-
NSString *vertexName = [shaderName stringByAppendingPathExtension:@"vsh"];
181-
NSString *vertexPath = [[CCFileUtils sharedFileUtils] fullPathForFilename:vertexName];
182-
NSString *vertexSource = (vertexPath ? [NSString stringWithContentsOfFile:vertexPath encoding:NSUTF8StringEncoding error:nil] : CCDefaultVShader);
183-
184-
CCShader *shader = [[CCShader alloc] initWithVertexShaderSource:vertexSource fragmentShaderSource:fragmentSource];
185-
shader.debugName = @"shaderName";
186-
187-
return shader;
174+
#if __CC_METAL_SUPPORTED_AND_ENABLED
175+
if([CCConfiguration sharedConfiguration].graphicsAPI == CCGraphicsAPIMetal){
176+
id<MTLLibrary> library = [CCMetalContext currentContext].library;
177+
178+
NSString *fragmentName = [shaderName stringByAppendingString:@"FS"];
179+
id<MTLFunction> fragmentFunction = [library newFunctionWithName:fragmentName];
180+
NSAssert(fragmentFunction, @"CCShader: Fragment function named %@ not found in the default library.", fragmentName);
181+
182+
NSString *vertexName = [shaderName stringByAppendingPathExtension:@"VS"];
183+
id<MTLFunction> vertexFunction = ([library newFunctionWithName:vertexName] ?: [library newFunctionWithName:@"CCVertexFunctionDefault"]);
184+
185+
CCShader *shader = [[CCShader alloc] initWithMetalVertexFunction:vertexFunction fragmentFunction:fragmentFunction];
186+
shader.debugName = shaderName;
187+
188+
return shader;
189+
} else
190+
#endif
191+
{
192+
NSString *fragmentName = [shaderName stringByAppendingPathExtension:@"fsh"];
193+
NSString *fragmentPath = [[CCFileUtils sharedFileUtils] fullPathForFilename:fragmentName];
194+
NSAssert(fragmentPath, @"Failed to find '%@'.", fragmentName);
195+
NSString *fragmentSource = [NSString stringWithContentsOfFile:fragmentPath encoding:NSUTF8StringEncoding error:nil];
196+
197+
NSString *vertexName = [shaderName stringByAppendingPathExtension:@"vsh"];
198+
NSString *vertexPath = [[CCFileUtils sharedFileUtils] fullPathForFilename:vertexName];
199+
NSString *vertexSource = (vertexPath ? [NSString stringWithContentsOfFile:vertexPath encoding:NSUTF8StringEncoding error:nil] : CCDefaultVShader);
200+
201+
CCShader *shader = [[CCShader alloc] initWithVertexShaderSource:vertexSource fragmentShaderSource:fragmentSource];
202+
shader.debugName = shaderName;
203+
204+
return shader;
205+
}
188206
}
189207

190208
-(id)createPublicObjectForSharedData:(id)data
@@ -657,7 +675,14 @@ - (void)dealloc
657675

658676
-(instancetype)copyWithZone:(NSZone *)zone
659677
{
660-
return [[CCShader allocWithZone:zone] initWithGLProgram:_program uniformSetters:_uniformSetters ownsProgram:NO];
678+
#if __CC_METAL_SUPPORTED_AND_ENABLED
679+
if([CCConfiguration sharedConfiguration].graphicsAPI == CCGraphicsAPIMetal){
680+
return [[CCShader allocWithZone:zone] initWithMetalVertexFunction:_vertexFunction fragmentFunction:_fragmentFunction];
681+
} else
682+
#endif
683+
{
684+
return [[CCShader allocWithZone:zone] initWithGLProgram:_program uniformSetters:_uniformSetters ownsProgram:NO];
685+
}
661686
}
662687

663688
static CCShaderCache *CC_SHADER_CACHE = nil;
@@ -672,6 +697,7 @@ +(void)initialize
672697
if(self != [CCShader class]) return;
673698

674699
NSAssert([CCConfiguration sharedConfiguration].graphicsAPI != CCGraphicsAPIInvalid, @"Graphics API not configured.");
700+
CC_SHADER_CACHE = [[CCShaderCache alloc] init];
675701

676702
#if __CC_METAL_SUPPORTED_AND_ENABLED
677703
if([CCConfiguration sharedConfiguration].graphicsAPI == CCGraphicsAPIMetal){
@@ -694,8 +720,6 @@ +(void)initialize
694720
} else
695721
#endif
696722
{
697-
CC_SHADER_CACHE = [[CCShaderCache alloc] init];
698-
699723
// Setup the builtin shaders.
700724
CC_SHADER_POS_COLOR = [[self alloc] initWithFragmentShaderSource:@"void main(){gl_FragColor = cc_FragColor;}"];
701725
CC_SHADER_POS_COLOR.debugName = @"CCPositionColorShader";

0 commit comments

Comments
 (0)