困惑为啥这个着色器不能在 Cocos2d 中工作

Posted

技术标签:

【中文标题】困惑为啥这个着色器不能在 Cocos2d 中工作【英文标题】:Confused why this shader isn't working in Cocos2d困惑为什么这个着色器不能在 Cocos2d 中工作 【发布时间】:2012-10-27 00:55:03 【问题描述】:

我正在尝试调整 this 关于着色器的教程以在我的游戏中工作,然后我将使用 glsl 来获得我想要的效果。

我用 Box2D 创建了一个 Cocos2d 2.x 项目。 Box2D 模板给了我一个PhysicsSprite 类,这就是我不使用CCSprite 的原因。这是我的初始化方法:

-(id) init

    if( (self=[super init])) 

        s = [[CCDirector sharedDirector] winSize];

        // enable events

        self.isTouchEnabled = YES;
        self.isAccelerometerEnabled = YES;

        // init physics
        [self initPhysics];

        //Init shader effects.
        [self initShaderEffects];

        ball = [PhysicsSprite spriteWithFile:@"Ball.png"];
        ball.position = ccp(s.width/2, s.height/2);
        b_body = [self createCirBody:10 andSpr:ball];
        [ball setPhysicsBody:b_body];
        [self addChild:ball];

        b_body->SetLinearVelocity(b2Vec2(1.5f,0));

        [self scheduleUpdate];
    
    return self;

如果排除 [self initShaderEffects]; 行,我已经测试了代码,到目前为止它可以工作,我得到一个移动的球。这是我的initShaderEffects(与教程基本相同,除了我使用ball 而不是sprite 并且我将fragmentSource 初始化更改为使用非弃用方法):

-(void)initShaderEffects 
    const GLchar *fragmentSource = (GLchar*)[[NSString stringWithContentsOfFile:@"MyCustomShader.fsh" encoding:NSUTF8StringEncoding error:nil] UTF8String];
    ball.shaderProgram = [[CCGLProgram alloc] initWithVertexShaderByteArray:ccPositionTextureA8Color_vert fragmentShaderByteArray:fragmentSource];
    [ball.shaderProgram addAttribute:kCCAttributeNamePosition index:kCCVertexAttrib_Position];
    [ball.shaderProgram addAttribute:kCCAttributeNameTexCoord index:kCCVertexAttrib_TexCoords];
    [ball.shaderProgram link];
    [ball.shaderProgram updateUniforms];

    colorRampUniformLocation = glGetUniformLocation(ball.shaderProgram->program_, "u_colorRampTexture"); //EXC_BAD_ACCESS
    glUniform1i(colorRampUniformLocation, 1);

    colorRampTexture = [[CCTextureCache sharedTextureCache] addImage:@"x2.png"];
    [colorRampTexture setAliasTexParameters];

    [ball.shaderProgram use];
    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, [colorRampTexture name]);
    glActiveTexture(GL_TEXTURE0);


最后这里是我直接从教程中复制的着色器“MyCustomShader.fsh”:

#ifdef GL_ES
precision mediump float;
#endif

// 1
varying vec2 v_texCoord;
uniform sampler2D u_texture;
uniform sampler2D u_colorRampTexture;

void main()
 // 2
    vec3 normalColor = texture2D(u_texture, v_texCoord).rgb;

    // 3
    float rampedR = texture2D(u_colorRampTexture, vec2(normalColor.r, 0)).r;
    float rampedG = texture2D(u_colorRampTexture, vec2(normalColor.g, 0)).g;
    float rampedB = texture2D(u_colorRampTexture, vec2(normalColor.b, 0)).b;

    // 4
    gl_FragColor = vec4(rampedR, rampedG, rampedB, 1);

此代码在我的initShaderEffects 方法中有注释EXC_BAD_ACCESS 的行上给了我EXC_BAD_ACCESS。我发现着色器很困难,如果有人能告诉我哪里出错了,我将不胜感激。

【问题讨论】:

请确保将“MyCustomShader.fsh”添加到“项目目标”=>“构建阶段”的“复制边界资源”部分。如果在调试器中检查 fragmentSource 和 ball.shaderProgram 的值没有帮助。 @IgorPchelko:这是问题的一部分。检查错误日志:NSLog(@"%@",ball.shaderProgram.fragmentShaderLog) got (null)。摆脱了 colorRampUniformLocation = ...glUniform1i... 做了一些事情,但颜色为橙色(例如未更改为蓝色)。 我在您的代码中发现了另一个问题:initShaderEffects 在“球”创建之前执行。您应该使用“[self initShaderEffects];”移动行在“[self addChild:ball];”行之后。 @IgorPchelko:非常感谢,如果您将其作为您的答案,我将非常乐意接受。 :D 【参考方案1】:

请确保将“MyCustomShader.fsh”添加到“项目目标”=>“构建阶段”的“复制边界资源”部分。如果在调试器中检查 fragmentSource 和 ball.shaderProgram 的值没有帮助。

我在您的代码中发现了另一个问题:initShaderEffects 在“球”创建之前执行。您应该使用“[self initShaderEffects];”移动行在“[self addChild:ball];”行之后。

【讨论】:

以上是关于困惑为啥这个着色器不能在 Cocos2d 中工作的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Xcode 不能识别这些着色器?

OpenGL:为啥我不能将单个浮点数从顶点着色器传递到片段着色器?

为啥我可以有 OpenGL 着色器类,但不能有 VAO 类?

如何在 cocos2d 中创建色相(饱和度)选择器

在片段着色器中,为啥我不能使用平面输入整数来索引 sampler2D 的统一数组?

为啥调用 glCreateShader 时这个 OpenGL 着色器分段错误?