I tested Xcode 7 with but my cocos2d 2.1 games crash on simulator or on devices:
ccShader_PositionColorLenghtTexture_frag.h
2015-06-15 22:36:13.319 NanoWar[18789:456971] cocos2d: ERROR: 0:12: '' : syntax error: #extension must always be before any non-preprocessor tokens
and
cocos2d: ERROR: 0:26: Invalid call of undeclared identifier 'fwidth'
This class crash the game
#extension GL_OES_standard_derivatives : enable
#ifdef GL_ES
varying mediump vec4 v_color;
varying mediump vec2 v_texcoord;
#else
varying vec4 v_color;
varying vec2 v_texcoord;
#endif
void main()
{
#ifdef GL_OES_standard_derivatives
#if defined GL_OES_standard_derivatives
gl_FragColor = v_color*smoothstep(0.0, length(fwidth(v_texcoord)), 1.0 - length(v_texcoord));
#else
gl_FragColor = v_color*step(0.0, 1.0 - length(v_texcoord));
#endif
#endif
}
I'm "rae" on forum.cocos2d-objc.org and I might as well put my answer here as well, since all roads lead to StackOverflow. :-)
If you are using an older release of Cocos 2D, this may help. I edited CCGLProgram.m to change the beginning of the -(BOOL)compileShader: method thusly:
#define EXTENSION_STRING "#extension GL_OES_standard_derivatives : enable"
static NSString * g_extensionStr = @EXTENSION_STRING;
- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type byteArray:(const GLchar *)source
{
GLint status;
if (!source)
return NO;
// BEGIN workaround for Xcode 7 bug
BOOL hasExtension = NO;
NSString *sourceStr = [NSString stringWithUTF8String:source];
if([sourceStr rangeOfString:g_extensionStr].location != NSNotFound) {
hasExtension = YES;
NSArray *strs = [sourceStr componentsSeparatedByString:g_extensionStr];
assert(strs.count == 2);
sourceStr = [strs componentsJoinedByString:@"\n"];
source = (GLchar *)[sourceStr UTF8String];
}
const GLchar *sources[] = {
(hasExtension ? EXTENSION_STRING "\n" : ""),
#ifdef __CC_PLATFORM_IOS
(type == GL_VERTEX_SHADER ? "precision highp float;\n" : "precision mediump float;\n"),
#endif
"uniform mat4 CC_PMatrix;\n"
"uniform mat4 CC_MVMatrix;\n"
"uniform mat4 CC_MVPMatrix;\n"
"uniform vec4 CC_Time;\n"
"uniform vec4 CC_SinTime;\n"
"uniform vec4 CC_CosTime;\n"
"uniform vec4 CC_Random01;\n"
"//CC INCLUDES END\n\n",
source,
};
// END workaround for Xcode 7 bug
It's a hack, but it works for up to Xcode 7 beta 2. Hope this is helpful to someone googling for this.
Reid
The accepted answer did not work for me, but this did.
Go to the file named CCGLProgram.m
Replace the entire method named - (BOOL)compileShader:(CLuint *)shader type(GLenum)typebyteArray:(const GLchar *)source
with this method
#define _IPHONE9_0 [[[UIDevice currentDevice] systemVersion] floatValue] == 9.000
#define EXTENSION_STRING "#extension GL_OES_standard_derivatives : enable"
static NSString * g_extensionStr = @EXTENSION_STRING;
- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type byteArray:(const GLchar *)source
{
GLint status;
if (!source)
return NO;
#ifdef _IPHONE9_0
NSLog(@"USING IOS9 shaders");
// BEGIN workaround for Xcode 7 ios9----
BOOL hasExtension = NO;
NSString *sourceStr = [NSString stringWithUTF8String:source];
if([sourceStr containsString:g_extensionStr]) {
hasExtension = YES;
NSArray *strs = [sourceStr componentsSeparatedByString:g_extensionStr];
assert(strs.count == 2);
sourceStr = [strs componentsJoinedByString:@"\n"];
source = (GLchar *)[sourceStr UTF8String];
}
const GLchar *sources[] = {
(hasExtension ? EXTENSION_STRING "\n" : ""),
#ifdef __CC_PLATFORM_IOS
(type == GL_VERTEX_SHADER ? "precision highp float;\n" : "precision mediump float;\n"),
#endif
"uniform mat4 CC_PMatrix;\n"
"uniform mat4 CC_MVMatrix;\n"
"uniform mat4 CC_MVPMatrix;\n"
"uniform vec4 CC_Time;\n"
"uniform vec4 CC_SinTime;\n"
"uniform vec4 CC_CosTime;\n"
"uniform vec4 CC_Random01;\n"
"//CC INCLUDES END\n\n",
source,
};
#else
NSLog(@"USING IOS8 shaders");
const GLchar *sources[] = {
#ifdef __CC_PLATFORM_IOS
(type == GL_VERTEX_SHADER ? "precision highp float;\n" : "precision mediump float;\n"),
#endif
"uniform mat4 CC_PMatrix;\n"
"uniform mat4 CC_MVMatrix;\n"
"uniform mat4 CC_MVPMatrix;\n"
"uniform vec4 CC_Time;\n"
"uniform vec4 CC_SinTime;\n"
"uniform vec4 CC_CosTime;\n"
"uniform vec4 CC_Random01;\n"
"//CC INCLUDES END\n\n",
source,
};
#endif
*shader = glCreateShader(type);
glShaderSource(*shader, sizeof(sources)/sizeof(*sources), sources, NULL);
glCompileShader(*shader);
glGetShaderiv(*shader, GL_COMPILE_STATUS, &status);
if( ! status ) {
GLsizei length;
glGetShaderiv(*shader, GL_SHADER_SOURCE_LENGTH, &length);
GLchar src[length];
glGetShaderSource(*shader, length, NULL, src);
CCLOG(@"cocos2d: ERROR: Failed to compile shader:\n%s", src);
if( type == GL_VERTEX_SHADER )
CCLOG(@"cocos2d: %@", [self vertexShaderLog] );
else
CCLOG(@"cocos2d: %@", [self fragmentShaderLog] );
abort();
}
return ( status == GL_TRUE );
}
Using the accepted answer above, but for newer versions of cocos2d:
In CCShader.m replace the lines
static GLint
CompileShaderSources(GLenum type, NSArray *sources)
{
with
#define EXTENSION_STRING "#extension GL_OES_standard_derivatives : enable"
static NSString * g_extensionStr = @EXTENSION_STRING;
static NSArray * PrependExtensionIfNeeded(NSArray *sources)
{
NSMutableArray *mutableSources = [NSMutableArray array];
BOOL hasExtension = NO;
for (NSString *source in sources)
{
NSString *newSource = [source copy];
if([source rangeOfString:g_extensionStr].location != NSNotFound)
{
hasExtension = YES;
NSArray *strs = [source componentsSeparatedByString:g_extensionStr];
newSource = [strs componentsJoinedByString:@"\n"];
}
[mutableSources addObject:newSource];
}
if (hasExtension)
{
NSMutableString *firstSource = [NSMutableString stringWithString:[mutableSources firstObject]];
[firstSource insertString:[NSString stringWithFormat:@"%@\n", g_extensionStr] atIndex:0];
[mutableSources replaceObjectAtIndex:0 withObject:firstSource];
}
return mutableSources;
}
static GLint
CompileShaderSources(GLenum type, NSArray *sources)
{
sources = PrependExtensionIfNeeded(sources);
NOTE: Wanted to write this as a comment but don't have enough reputation to write a comment, hence writing this as an answer:
The fix described by Reid does fix the issue. However it crashes on iOS 7 devices, because it uses containsString
method which is only available in iOS 8 and above
A simple change to the following line fixes the issue:
if([sourceStr containsString:g_extensionStr]) {
needs to be changed to:
NSRange range = [sourceStr rangeOfString:g_extensionStr];
if(range.length > 0) {
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With