在 cocos2d 中将额外的 N 个纹理传递给自定义着色器

Pass additional N textures to a custom shader in cocos2d

我想将 N 个纹理传递给自定义着色器。当我上网冲浪时,我得到的最佳选择是重写 Sprite::draw() 函数并将 CustomCommand 对象添加到绘制池中。

CPP 文件:

void SpriteSub::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags) {

    m_cmdCustom.init(_globalZOrder, transform, flags);
    m_cmdCustom.func = CC_CALLBACK_0(SpriteSub::onDraw, this, transform, flags);
    renderer->addCommand(&m_cmdCustom);

    Sprite::draw(renderer, transform, flags);

}

void SpriteSub::onDraw(const Mat4 &transform, uint32_t /*flags*/) {

    this->getGLProgram()->use();

    auto wwProgram = m_shader->getProgram();

    auto texBall0 = Director::getInstance()->getTextureCache()->addImage("ball.png")->getName();
    GLuint locTexIcon0 = glGetUniformLocation(wwProgram, "texBall0");
    glUniform1i(locTexIcon0, 0);
    //glActiveTexture(GL_TEXTURE0 + 0); glBindTexture(GL_TEXTURE_2D, texBall0);
    //glActiveTexture(GL_TEXTURE0 + 0);
    GL::bindTexture2D(texBall0);

}

帧着色器:

    #ifdef GL_ES
    precision lowp float;
    #endif

    varying vec4 v_fragmentColor;
    varying vec2 v_texCoord;

    uniform sampler2D texBall0;
    uniform sampler2D texBall1;
    //uniform sampler2D texBall2;
    //uniform sampler2D texBall3;
    //uniform sampler2D texBall4;
    //uniform sampler2D texBall5;

    void main()
    {

        float t = 0.7f;

        //gl_FragColor = texture2D(CC_Texture0, v_texCoord);

        //this is just a sample code
        gl_FragColor = texture2D(texBall0, v_texCoord) * t;
        gl_FragColor += texture2D(texBall1, v_texCoord) * (t-1);

        //some code that uses the other textures...

    }   

上面的着色器只是一个示例,并不是我正在使用的实际代码。现在,我只需要在单个着色器中成功传递多个纹理来处理它们的像素。

目前,我无法显示传递的纹理。应该怎么做才能实现这一目标? SpriteSub::draw() 中的 Sprite::draw() 是否取消了来自 onDraw() 的 gl 命令?

'解决了!

您甚至不需要覆盖绘图或添加 CustomCommand 到渲染队列。

步骤:

1.) 使用您使用自定义着色器创建的 GLProgram 对象创建一个 GLProgramState

2.) 使用GLProgramState::setUniformTexture("uniformVarName", tex2D)定位统一变量并传递纹理名称。

3.) 调用 sprite->setGLProgramState(programState) 而不是 sprite->setGLProgram(program);

中共文件:

m_shader = GLProgram::createWithByteArrays(ccPositionTextureColor_noMVP_vert, shader_frag);
m_shader->retain();

auto shaderState = GLProgramState::getOrCreateWithGLProgram(m_shader);

auto textureCache = Director::getInstance()->getTextureCache();
auto img0 = textureCache->addImage("icon_tex0.png")->getName();
auto img1 = textureCache->addImage("icon_tex1.png")->getName();
auto img2 = textureCache->addImage("icon_tex2.png")->getName();
auto img3 = textureCache->addImage("icon_tex3.png")->getName();
auto img4 = textureCache->addImage("icon_tex4.png")->getName();
auto img5 = textureCache->addImage("icon_tex5.png")->getName();

shaderState->setUniformTexture("texIcon0", img0);
shaderState->setUniformTexture("texIcon1", img1);
shaderState->setUniformTexture("texIcon2", img2);
shaderState->setUniformTexture("texIcon3", img3);
shaderState->setUniformTexture("texIcon4", img4);
shaderState->setUniformTexture("texIcon5", img5);

//this->setGLProgram(m_shader);
this->setGLProgramState(shaderState);

片段着色器:

    #ifdef GL_ES
    precision lowp float;
    #endif

    varying vec4 v_fragmentColor;
    varying vec2 v_texCoord;

    uniform sampler2D texIcon0;
    uniform sampler2D texIcon1;
    uniform sampler2D texIcon2;
    uniform sampler2D texIcon3;
    uniform sampler2D texIcon4;
    uniform sampler2D texIcon5;

    void main()
    {

        int numTex = 6;
        float fWeight = 1.0f/float(length);

        //gl_FragColor = texture2D(CC_Texture0, v_texCoord);
        gl_FragColor += texture2D(texIcon0, v_texCoord) * fWeight;
        gl_FragColor += texture2D(texIcon1, v_texCoord) * fWeight;
        gl_FragColor += texture2D(texIcon2, v_texCoord) * fWeight;
        gl_FragColor += texture2D(texIcon3, v_texCoord) * fWeight;
        gl_FragColor += texture2D(texIcon4, v_texCoord) * fWeight;
        gl_FragColor += texture2D(texIcon5, v_texCoord) * fWeight;


    }   

来源: