cocos2dx 3.2 使用 setUniformLocationWith4f 遇到问题

原图

效果图

不知道还有没有bug

#ifndef _CoScale9_H_
#define _CoScale9_H_

#include "cocos2d.h"
USING_NS_CC;


//#ifndef CC_TEXTURE_ATLAS_USE_VAO
//    #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) || (CC_TARGET_PLATFORM == CC_PLATFORM_MAC)
//        #define CC_TEXTURE_ATLAS_USE_VAO 1
//    #else
//        /* Some Windows display adapter driver cannot support VAO. */
//        /* Some android devices cannot support VAO very well, so we disable it by default for android platform. */
//        /* Blackberry also doesn't support this feature. */
//        #define CC_TEXTURE_ATLAS_USE_VAO 0
//    #endif
//#endif
// 注意记得找到 CC_TEXTURE_ATLAS_USE_VAO 把 0 设置为 1
// 纹理必须是2的幂次方
// 纹理不能旋转 (TexturePacker Allow rotation 去掉)
//////////////////////////////////////////////////////////////////////////
class CoScale9 : public Node
{
public:
    CREATE_FUNC(CoScale9);

public:
    virtual void cleanup() override
    {
        glDeleteBuffers(1, &mVBO);
        glDeleteBuffers(1, &mIBO);
        glDeleteVertexArrays(1, &mVAO);
        CC_SAFE_RELEASE(mFrame);
        Node::cleanup();
    } // cleanup

    virtual bool init() override
    {
        mVAO = 0;
        mVBO = 0;
        mIBO = 0;
        mFrame = 0;
        if ( !Node::init() )
            return false;
        //////////////////////////////////////////////////////////////////////////
        // vertex shader
        static const char* vert = "                            \n\
            attribute vec4 aPosition;                        \n\
            attribute vec2 aTexCoord;                        \n\
                                                            \n\
            varying vec4 vColor;                            \n\
            varying vec2 vTexCoord;                            \n\
                                                            \n\
            uniform vec4 uColor;                            \n\
            uniform vec4 uTexScale;                            \n\
            uniform vec4 uPosScale;                            \n\
            void main()                                        \n\
            {                                                \n\
                vec4 posC = aPosition;                        \n\
                posC.x = posC.x * uPosScale.z;                \n\
                posC.y = posC.y * uPosScale.w;                \n\
                                                            \n\
                gl_Position = CC_MVPMatrix * posC;            \n\
                vec2 texC = aTexCoord;                        \n\
                texC = texC * uTexScale.zw + uTexScale.xy;    \n\
                vTexCoord = texC;                            \n\
                vColor = uColor;                            \n\
            }";
        // fragment shader
        static const char* frag = "                            \n\
            #ifdef GL_ES                                    \n\
                precision mediump float;                    \n\
            #endif                                            \n\
            uniform vec4 uInsets;                            \n\
            varying vec4 vColor;                            \n\
            varying vec2 vTexCoord;                            \n\
                                                            \n\
            void main()                                        \n\
            {                                                \n\
                vec2 texC = vTexCoord;                        \n\
                texC.x = texC.x - uInsets.x;                    \n\
                texC.y = texC.y - uInsets.y;                    \n\
                texC.x = mod(texC.x, uInsets.z);            \n\
                texC.y = mod(texC.y, uInsets.w);            \n\
                texC.x = texC.x + uInsets.x;                \n\
                texC.y = texC.y + uInsets.y;                \n\
                vec4 col = texture2D(CC_Texture0, texC);    \n\
                gl_FragColor = vColor*col;                    \n\
            }";
        // 创建着色器程序
        auto program = new GLProgram;
        program->initWithByteArrays(vert, frag);
        program->link();
        program->updateUniforms();
        program->autorelease();
        this->setGLProgram(program);
        // set uniform
        GLint uColorLoc = glGetUniformLocation(program->getProgram(), "uColor");
        glUniform4f(uColorLoc, 1, 1, 1, 1);
        CHECK_GL_ERROR_DEBUG();
        GLint uTexScaleLoc = glGetUniformLocation(program->getProgram(), "uTexScale");
        glUniform4f(uTexScaleLoc, 0, 0, 1, 1);
        CHECK_GL_ERROR_DEBUG();
        GLint uPosScaleLoc = glGetUniformLocation(program->getProgram(), "uPosScale");
        glUniform4f(uPosScaleLoc, 0, 0, 1, 1);
        CHECK_GL_ERROR_DEBUG();
        GLint uInsetsLocation = glGetUniformLocation(program->getProgram(), "uInsets");
        glUniform4f(uInsetsLocation, 0, 0, 1, 1);
        CHECK_GL_ERROR_DEBUG();

        GLint positionLoc = glGetAttribLocation(program->getProgram(), "aPosition");
        GLint texCoordLoc = glGetAttribLocation(program->getProgram(), "aTexCoord");
        //////////////////////////////////////////////////////////////////////////
        // 创建Vertex Array Object
        glGenVertexArrays(1, &mVAO);
        glBindVertexArray(mVAO);
        CHECK_GL_ERROR_DEBUG();

        // 创建统一 VBO
        typedef struct {
            float position;
            float texCoord;
        } Vertex;

        float unit = 0.5f;
        Vertex datas] = {
            {{-unit, -unit, 0}, {0, 1}},
            {{ unit, -unit, 0}, {1, 1}},
            {{-unit,  unit, 0}, {0, 0}},
            {{ unit,  unit, 0}, {1, 0}},
        }; // datas

        glGenBuffers(1, &mVBO);
        glBindBuffer(GL_ARRAY_BUFFER, mVBO);
        glBufferData(GL_ARRAY_BUFFER, sizeof(datas), datas, GL_STATIC_DRAW);
        CHECK_GL_ERROR_DEBUG();
        //指定将要绘制的顶点数据
        glEnableVertexAttribArray(positionLoc);
        glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, position));
        CHECK_GL_ERROR_DEBUG();
        //指定每一个顶点的纹理坐标
        glEnableVertexAttribArray(texCoordLoc);
        glVertexAttribPointer(texCoordLoc, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, texCoord));
        CHECK_GL_ERROR_DEBUG();

        // 创建顶点索引
        GLubyte indices]={0,1,2, 2,3,1};
        glGenBuffers(1, &mIBO);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIBO);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
        CHECK_GL_ERROR_DEBUG();
        return true;
    } // init

    void setSpriteFrameByName(const std::string& name, float l, float t, float r, float b)
    {
        SpriteFrame* frame = SpriteFrameCache::getInstance()->getSpriteFrameByName(name);
        setSpriteFrame(frame, l, t, r, b);
    }

    void setSpriteFrame(SpriteFrame* frame, float l, float t, float r, float b)
    {
        CC_SAFE_RETAIN(frame);
        CC_SAFE_RELEASE(mFrame);
        mFrame            = frame;
        mOriginRect        = mFrame->getRect();
        mLeftPadding    = l;
        mTopPadding        = t;
        mRightPadding    = r;
        mBottomPadding    = b;

        mHCenterPadding    = mOriginRect.size.width - mLeftPadding - mRightPadding;
        mVCenterPadding    = mOriginRect.size.height - mTopPadding - mBottomPadding;

        setInnerSize(mHCenterPadding, mVCenterPadding);

        GL::bindTexture2D(mFrame->getTexture()->getName());
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
    }

    void setInnerSize(float width, float height)
    {
        mInnerWidth     = width;
        mInnerHeight = height;
        Node::setContentSize(Size(mInnerWidth+mLeftPadding+mRightPadding, mInnerHeight+mTopPadding+mBottomPadding));
    }

    virtual void setContentSize(const Size& size) override
    {
        setInnerSize(size.width - mLeftPadding - mRightPadding, size.height - mTopPadding - mBottomPadding);
    }

    float getLeftPadding() const 
    {
        return mLeftPadding;
    }

    float getTopPadding() const 
    {
        return mTopPadding;
    }

    float getRightPadding() const
    {
        return mRightPadding;
    }

    float getBottomPadding() const
    {
        return mBottomPadding;
    }

    virtual void visit(Renderer *renderer, const Mat4& parentTransform, uint32_t parentFlags) override
    {
        if (mFrame == nullptr)
            return;
        if (getContentSize().width == 0 || getContentSize().height == 0)
            return;
        mCustomCommand.init(_globalZOrder);
        mCustomCommand.func = CC_CALLBACK_0(CoScale9::onDraw, this);
        renderer->addCommand(&mCustomCommand);
        Node::visit(renderer, parentTransform, parentFlags);
    } // visit

private:
    void setCenterTexRange()
    {
        setTexRange(
            mOriginRect.origin.x + mLeftPadding,
            mOriginRect.origin.y + mTopPadding,
            mHCenterPadding,
            mVCenterPadding);
    }

    void setLeftTexRange()
    {
        setTexRange(
            mOriginRect.origin.x,
            mOriginRect.origin.y+ mTopPadding,
            mLeftPadding,
            mVCenterPadding);
    }
    void setRightTexRange()
    {
        setTexRange(
            mOriginRect.origin.x+mOriginRect.size.width - mRightPadding,
            mOriginRect.origin.y+ mTopPadding,
            mRightPadding,
            mVCenterPadding);
    }
    void setTopTexRange()
    {
        setTexRange(
            mOriginRect.origin.x+mLeftPadding,
            mOriginRect.origin.y,
            mHCenterPadding,
            mTopPadding);
    }

    void setBottomTexRange()
    {
        setTexRange(
            mOriginRect.origin.x+mLeftPadding,
            mOriginRect.origin.y+mOriginRect.size.height - mBottomPadding,
            mHCenterPadding,
            mBottomPadding);
    }

    void setLeftTopTexRange()
    {
        setTexRange(
            mOriginRect.origin.x,
            mOriginRect.origin.y,
            mLeftPadding,
            mTopPadding);
    }

    void setRightTopTexRange()
    {
        setTexRange(
            mOriginRect.origin.x+mOriginRect.size.width - mRightPadding,
            mOriginRect.origin.y,
            mRightPadding,
            mTopPadding);
    }

    void setRightBottomTexRange()
    {
        setTexRange(
            mOriginRect.origin.x+mOriginRect.size.width - mRightPadding,
            mOriginRect.origin.y+mOriginRect.size.height - mBottomPadding,
            mRightPadding,
            mBottomPadding);
    }

    void setLeftBottomTexRange()
    {
        setTexRange(
            mOriginRect.origin.x,
            mOriginRect.origin.y+mOriginRect.size.height - mBottomPadding,
            mLeftPadding,
            mBottomPadding);
    }

    void setTexRange(float tX, float tY, float tW, float tH)
    {
        Size oSize = mFrame->getTexture()->getContentSize();
        float invSx = 1 / oSize.width;
        float invSy = 1 / oSize.height;
        float x = tX*invSx;
        float y = tY*invSy;
        float w = tW*invSx;
        float h = tH*invSy;

        auto program = getGLProgram();
        GLint uInsetsLocation = glGetUniformLocation(program->getProgram(), "uInsets");
        glUniform4f(uInsetsLocation, x, y, w, h);
        CHECK_GL_ERROR_DEBUG();
    }

    void setTextureRect(float x, float y, float w, float h)
    {
        auto program = getGLProgram();
        //////////////////////////////////////////////////////////////////////////
        // 计算纹理坐标
        float atlasWidth = (float)mFrame->getTexture()->getPixelsWide();
        float atlasHeight = (float)mFrame->getTexture()->getPixelsHigh();

        float texX    = x / atlasWidth;
        float texY    = y / atlasHeight;
        float texW    = w / atlasWidth;
        float texH    = h / atlasHeight;

        GLint uTexScaleLoc = glGetUniformLocation(program->getProgram(), "uTexScale");
        glUniform4f(uTexScaleLoc, texX, texY, texW, texH);
        CHECK_GL_ERROR_DEBUG();

        //////////////////////////////////////////////////////////////////////////
        static Size winSize = Director::getInstance()->getWinSize();
        GLint uPosScaleLoc = glGetUniformLocation(program->getProgram(), "uPosScale");
        glUniform4f(uPosScaleLoc, 0, 0, w, h);
        CHECK_GL_ERROR_DEBUG();
    }

    // opengl 绘制
    void onDraw()
    {
        Director::getInstance()->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
        
        //use vao,因为vao记录了每一个顶点属性和缓冲区的状态,所以只需要绑定就可以使用了
        //(还要绑定buffer,不然报错)
        glBindVertexArray(mVAO);
        glBindBuffer(GL_ARRAY_BUFFER, mVBO);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIBO);
        CHECK_GL_ERROR_DEBUG();

        //获得当前shader
        auto glProgram = getGLProgram();
        //使用shader
        glProgram->use();

        // 绑定纹理
        GL::bindTexture2D(mFrame->getTexture()->getName());
        
        // 绘制
        const Mat4 &mat = this->getNodeToWorldTransform();
        Mat4 matT;

        // center
        Director::getInstance()->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, mat);
        glProgram->setUniformsForBuiltins();
        setCenterTexRange();
        setTextureRect(mOriginRect.origin.x+mLeftPadding, mOriginRect.origin.y+mTopPadding, mInnerWidth, mInnerHeight);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, (GLvoid*)0);
        CHECK_GL_ERROR_DEBUG();

        // left
        matT.set(mat);
        matT.translate(-(mLeftPadding+mInnerWidth)/2, 0, 0);
        Director::getInstance()->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, matT);
        glProgram->setUniformsForBuiltins();
        setLeftTexRange();
        setTextureRect(mOriginRect.origin.x+0, mOriginRect.origin.y+mTopPadding, mLeftPadding, mInnerHeight);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, (GLvoid*)0);

        // top
        matT.set(mat);
        matT.translate(0, (mTopPadding+mInnerHeight)/2, 0);
        Director::getInstance()->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, matT);
        glProgram->setUniformsForBuiltins();
        setTopTexRange();
        setTextureRect(mOriginRect.origin.x+mLeftPadding, mOriginRect.origin.y, mInnerWidth, mTopPadding);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, (GLvoid*)0);

        // right
        matT.set(mat);
        matT.translate((mRightPadding+mInnerWidth)/2, 0, 0);
        Director::getInstance()->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, matT);
        glProgram->setUniformsForBuiltins();
        setRightTexRange();
        setTextureRect(mOriginRect.origin.x+mOriginRect.size.width-mRightPadding, mOriginRect.origin.y+mTopPadding, mRightPadding, mInnerHeight);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, (GLvoid*)0);

        // bottom
        matT.set(mat);
        matT.translate(0, -(mBottomPadding+mInnerHeight)/2, 0);
        Director::getInstance()->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, matT);
        glProgram->setUniformsForBuiltins();
        setBottomTexRange();
        setTextureRect(mOriginRect.origin.x+mLeftPadding, mOriginRect.origin.y+mOriginRect.size.height-mBottomPadding, mInnerWidth, mBottomPadding);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, (GLvoid*)0);

        // right top
        matT.set(mat);
        matT.translate((mRightPadding+mInnerWidth)/2, (mTopPadding+mInnerHeight)/2, 0);
        Director::getInstance()->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, matT);
        glProgram->setUniformsForBuiltins();
        setRightTopTexRange();
        setTextureRect(mOriginRect.origin.x+mOriginRect.size.width-mRightPadding, mOriginRect.origin.y+0, mRightPadding, mTopPadding);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, (GLvoid*)0);

        // left top
        matT.set(mat);
        matT.translate(-(mLeftPadding+mInnerWidth)/2, (mTopPadding+mInnerHeight)/2, 0);
        Director::getInstance()->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, matT);
        glProgram->setUniformsForBuiltins();
        setLeftTopTexRange();
        setTextureRect(mOriginRect.origin.x+0, mOriginRect.origin.y+0, mLeftPadding, mTopPadding);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, (GLvoid*)0);

        // right bottom
        matT.set(mat);
        matT.translate((mRightPadding+mInnerWidth)/2, -(mBottomPadding+mInnerHeight)/2, 0);
        Director::getInstance()->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, matT);
        glProgram->setUniformsForBuiltins();
        setRightBottomTexRange();
        setTextureRect(
            mOriginRect.origin.x+mOriginRect.size.width-mRightPadding,
            mOriginRect.origin.y+mOriginRect.size.height-mBottomPadding, 
            mRightPadding, 
            mBottomPadding);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, (GLvoid*)0);

        // left bottom
        matT.set(mat);
        matT.translate(-(mLeftPadding+mInnerWidth)/2, -(mBottomPadding+mInnerHeight)/2, 0);
        Director::getInstance()->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, matT);
        glProgram->setUniformsForBuiltins();
        setLeftBottomTexRange();
        setTextureRect(
            mOriginRect.origin.x,
            mOriginRect.origin.y+mOriginRect.size.height-mBottomPadding, 
            mLeftPadding, 
            mBottomPadding);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, (GLvoid*)0);

        glBindVertexArray(0);
        CHECK_GL_ERROR_DEBUG();

        // 提示用
        CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, 6);
        Director::getInstance()->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);        
    } // onDraw

private:
    CustomCommand mCustomCommand;
    GLuint    mVAO;
    GLuint    mVBO;
    GLuint    mIBO;

    Rect            mOriginRect;
    SpriteFrame*    mFrame;

    float    mLeftPadding;
    float    mTopPadding;
    float    mRightPadding;
    float    mBottomPadding;
    float    mHCenterPadding;
    float    mVCenterPadding;

    float    mInnerWidth;
    float    mInnerHeight;
}; // CoScale9

#endif // _CoScale9_H_


```