Cocos2d 2.1 和 Xcode 7 iOS 9 崩溃 ccShader
Coco2d 2.1 and Xcode 7 iOS 9 crash ccShader
我测试了 Xcode 7,但我的 cocos2d 2.1 游戏在模拟器或设备上崩溃:
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
和
cocos2d: ERROR: 0:26: Invalid call of undeclared identifier 'fwidth'
这 class 导致游戏崩溃
#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
}
我 "rae" 在 forum.cocos2d-objc.org 上,我不妨也把我的答案放在这里,因为条条大路通 Whosebug。 :-)
如果您使用的是 Cocos 2D 的旧版本,这可能会有所帮助。我编辑 CCGLProgram.m 以更改 -(BOOL)compileShader: 方法的开头:
#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
这是一个 hack,但它最多适用于 Xcode 7 beta 2。希望这对谷歌搜索的人有所帮助。
里德
使用上面接受的答案,但对于 cocos2d 的较新版本:
在CCShader.m替换行
static GLint
CompileShaderSources(GLenum type, NSArray *sources)
{
和
#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);
注意:想将其写为评论但没有足够的声誉来写评论,因此将其写为答案:
描述的修复确实解决了这个问题。但是它在 iOS 7 设备上崩溃,因为它使用 containsString
方法,该方法仅在 iOS 8 及更高版本
中可用
对以下行进行简单更改即可解决问题:
if([sourceStr containsString:g_extensionStr]) {
需要改为:
NSRange range = [sourceStr rangeOfString:g_extensionStr];
if(range.length > 0) {
已接受的答案对我不起作用,但这个答案对我有用。
转到名为 CCGLProgram.m
的文件
替换名为 - (BOOL)compileShader:(CLuint *)shader type(GLenum)typebyteArray:(const GLchar *)source
的整个方法
用这个方法
#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 );
}
我测试了 Xcode 7,但我的 cocos2d 2.1 游戏在模拟器或设备上崩溃:
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
和
cocos2d: ERROR: 0:26: Invalid call of undeclared identifier 'fwidth'
这 class 导致游戏崩溃
#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
}
我 "rae" 在 forum.cocos2d-objc.org 上,我不妨也把我的答案放在这里,因为条条大路通 Whosebug。 :-)
如果您使用的是 Cocos 2D 的旧版本,这可能会有所帮助。我编辑 CCGLProgram.m 以更改 -(BOOL)compileShader: 方法的开头:
#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
这是一个 hack,但它最多适用于 Xcode 7 beta 2。希望这对谷歌搜索的人有所帮助。
里德
使用上面接受的答案,但对于 cocos2d 的较新版本:
在CCShader.m替换行
static GLint
CompileShaderSources(GLenum type, NSArray *sources)
{
和
#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);
注意:想将其写为评论但没有足够的声誉来写评论,因此将其写为答案:
containsString
方法,该方法仅在 iOS 8 及更高版本
对以下行进行简单更改即可解决问题:
if([sourceStr containsString:g_extensionStr]) {
需要改为:
NSRange range = [sourceStr rangeOfString:g_extensionStr];
if(range.length > 0) {
已接受的答案对我不起作用,但这个答案对我有用。
转到名为 CCGLProgram.m
替换名为 - (BOOL)compileShader:(CLuint *)shader type(GLenum)typebyteArray:(const GLchar *)source
用这个方法
#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 );
}