【cocos2d-x 2.x 学习与应用总结】14: 自定义shader绘制混合颜色的矩形

前端之家收集整理的这篇文章主要介绍了【cocos2d-x 2.x 学习与应用总结】14: 自定义shader绘制混合颜色的矩形前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

前言

本文介绍了如何在cocos2d-x中使用自定义shader来实现混合颜色矩形的绘制。文中继续使用前一篇文章中定义的CustomDrawNode类来实现绘制过程,在其基础上派生出ColorfulRectangle类,使用一对新的shader。

绘制的效果图如下所示:

绘制的实现

关于CustomDrawNode类的实现这里不再介绍,详情请参考前一篇文章《使用CCGLProgram实现自定义绘制》。下面给出着色器源码和彩色矩形绘制类ColorfulRectangle的实现:

1.顶点着色器: colorful_rect_vert.glsl

#ifdef GL_ES
precision mediump float;
#endif

attribute   vec2    custom_a_position;      // 顶点位置
attribute   vec4    custom_a_color;         // 顶点颜色

varying     vec4    v_color;                // 输出变量到片段着色器

void main()
{
    vec4 pos    = vec4(custom_a_position,0,1);
    gl_Position = CC_MVPMatrix * pos;
    v_color     = custom_a_color;
}

2. 片段着色器:colorful_rect_frag.glsl

#ifdef GL_ES
precision mediump float;
#endif

varying     vec4    v_color;        // 从顶点shader中输入的颜色

void main()
{
    gl_FragColor = v_color; 
}

3. ColorfulRectangle的实现

// .h
class ColorfulRectangle : public CustomDrawNode
{
public:
    static ColorfulRectangle* create(const char *vs,const char *fs);
    void draw() override;
    void customSetupBeforeLink() override;      // 模板方法请参见CustomDrawNode的实现
    void customUniformsUpdate() override;       // 模板方法请参见CustomDrawNode的实现

protected:

    // 顶点数组结构,两个float类型的顶点位置和四个float表示的顶点颜色。
    struct V2F_C4F
    {
        GLfloat x,y;
        GLfloat r,g,b,a;
    };

    ColorfulRectangle() : _attribPosition(0),_attribColor(1)
    {
        for ( size_t i = 0; i < 4; ++i )
        {
            _randomColor4f[i][0] = CCRANDOM_0_1();      // 顶点使用随机颜色值分量 r
            _randomColor4f[i][1] = CCRANDOM_0_1();      // 顶点使用随机颜色值分量 g
            _randomColor4f[i][2] = CCRANDOM_0_1();      // 顶点使用随机颜色值分量 b
        }
    }

    const attribute     _attribPosition;            // 绑定顶点着色器中custom_a_position变量
    const attribute     _attribColor;               // 绑定顶点着色器中custom_a_color变量

    GLfloat             _randomColor4f[4][3];       // 四个顶点颜色变量
};


// .cpp
// 使用shader文件名来创建一个ColorfulRectangle对象
ColorfulRectangle* ColorfulRectangle::create(const char *vs,const char *fs)
{
    auto self = new ColorfulRectangle;
    if (self && self->initWithShaders(vs,fs))  // 调用CustomDrawNode的initWithShaders()方法
    {
        self->autorelease();
        return self;
    }
    return nullptr;
}

// 绘制方法
void ColorfulRectangle::draw()
{
    CC_NODE_DRAW_SETUP();                   // 调用program->use(),为预定义的uniform赋值

    // 定义矩形的宽高和位置
    auto size = CocosWindow::size();
    auto center = CocosWindow::center();
    GLfloat width = size.width / 2;
    GLfloat height = size.height / 2;
    GLfloat x = center.x - width / 2;
    GLfloat y = center.y - height / 2;

    // 顶点数组,两个位置分量(x,y) + 4个颜色分量,color.rgb使用随机值,color.a使用1,不透明
    V2F_C4F vertexes[] =
    {
        x,y,_randomColor4f[0][0],_randomColor4f[0][1],_randomColor4f[0][2],1,x + width,_randomColor4f[1][0],_randomColor4f[1][1],_randomColor4f[1][2],x,y + height,_randomColor4f[2][0],_randomColor4f[2][1],_randomColor4f[2][2],_randomColor4f[3][0],_randomColor4f[3][1],_randomColor4f[3][2],};

    // 启用顶点数组
    glEnableVertexAttribArray(_attribPosition);
    glEnableVertexAttribArray(_attribColor);

    // 上传顶点数组值到OpenGL服务器
    glVertexAttribPointer(_attribPosition,2,GL_FLOAT,false,sizeof(V2F_C4F),&vertexes[0].x);
    glVertexAttribPointer(_attribColor,4,&vertexes[0].r);

    // 绘制
    glDrawArrays(GL_TRIANGLE_STRIP,4);

    CC_INCREMENT_GL_DRAWS(1);
}

void ColorfulRectangle::customSetupBeforeLink()
{
    // 在shader program link之前,绑定shader中的attribute.
    getShaderProgram()->addAttribute("custom_a_position",_attribPosition);
    getShaderProgram()->addAttribute("custom_a_color",_attribColor);
}

void ColorfulRectangle::customUniformsUpdate()
{
    // nothing.
}

4. 测试代码

测试代码在CustomDrawNode::loadUI()方法中:

auto colorRectangle = ColorfulRectangle::create("shaders/colorful_rect_vert.glsl","shaders/colorful_rect_frag.glsl");
addChild(colorRectangle);

遇到的问题

犯了一个低级错误,调试了半天才发现。

在colorRectangle的构造函数中,错误的把两个attribute的绑定常量都初始化为0,导致在draw方法中在使用glVertexAttribPointer(location,…)时候,顶点位置被颜色覆盖,绘制的结果就只有一个点,而不是矩形。

ColorfulRectangle() : _attribPosition(0),_attribColor(0)           // 第二个常量应该为:_attribColor(1)
{
    for ( size_t i = 0; i < 4; ++i )
    {
        _randomColor4f[i][0] = CCRANDOM_0_1();
        _randomColor4f[i][1] = CCRANDOM_0_1();
        _randomColor4f[i][2] = CCRANDOM_0_1();
    }
}

// 如果两个常量都是0,绑定attribute的时候顶点位置的绑定就被颜色覆盖了。
void ColorfulRectangle::customSetupBeforeLink()
{
    getShaderProgram()->addAttribute("custom_a_position",_attribPosition);     // 0
    getShaderProgram()->addAttribute("custom_a_color",_attribColor);           // alse 0,no no no.
}

源码

CustomDrawNodePage.h

CustomDrawNodePage.cpp


作者水平有限,对相关知识的理解和总结难免有错误,还望给予指正,非常感谢!

在这里也能看到这篇文章github博客,CSDN博客,欢迎访问

猜你在找的Cocos2d-x相关文章