【cocos2d-x 2.x 学习与应用总结】13: 借助CCGLProgram实现自定义绘制

【cocos2d-x 2.x 学习与应用总结】13: 借助CCGLProgram实现自定义绘制,第1张

概述前言 本文总结了如何借助CCGLProgram来实现自定义绘制的节点类,使用自定义的顶点着色器和片段着色器,实现一个绘制彩色矩形的节点类。 绘制的效果图如下所示: 思路及实现 思路 目标是:实现一个可绘制对象A,绘制出一个彩色的矩形。 首先, 要能实现绘制,那么A就要能够加入到节点树之中,这样引擎在遍历节点树进行绘制的时候,它才能够被绘制出来。怎样才能被加入到节点树?成为Node的子类, 然后ad 前言

本文总结了如何借助CCGLProgram来实现自定义绘制的节点类,使用自定义的顶点着色器和片段着色器,实现一个绘制彩色矩形的节点类。

绘制的效果图如下所示:

思路及实现 思路

目标是:实现一个可绘制对象A,绘制出一个彩色的矩形。

首先,要能实现绘制,那么A就要能够加入到节点树之中,这样引擎在遍历节点树进行绘制的时候,它才能够被绘制出来。怎样才能被加入到节点树?成为Node的子类,然后addChild即可。

其次,要实现自定义绘制,就要重写Node::draw()方法,并且在draw调用之前,创建好顶点shader和片段shader,以及准备好shader program,完成shader中变量的绑定和值传递。

思路清楚后,开始写代码。

实现 第1步: 自定义节点类CustomDrawNode继承自CCNode

CustomDrawNode作为一个自定义绘制节点类的父类的角色,具体的自定义绘制类继承CustomDrawNode. 它定义了绘制逻辑的骨架,具体的绘制 *** 作延迟到不同的子类来完成,可以扩展出各种绘制 *** 作,恩,这是模板方法设计模式的思路。

// .hclass CustomDrawNode : public cocos2d::CCNode{public:    static CustomDrawNode* create(const char *vsfilename,const char *fsfilename);    bool initWithShaders(const char *vsfilename,const char *fsfilename);    virtual voID customSetupBeforelink() {}    virtual voID updateCustomUniforms() {}protected:    CustomDrawNode() {}};// .cpp// create方法,使用initWithShaders来完成初始化CustomDrawNode* CustomDrawNode::create(const char *vsfilename,const char *fsfilename){    CustomDrawNode *self = new CustomDrawNode;    if (self && self->initWithShaders(vsfilename,fsfilename))     {        self->autorelease();        return self;    }    return nullptr;}bool CustomDrawNode::initWithShaders(const char *vs,const char *fs){    if (CCNode::init())     {        // 创建并设置CCGLProgram.        CCGLProgram *program = new CCGLProgram;        program->initWithVertexShaderfilename(vs,fs);        setShaderProgram(program);        program->release();        customSetupBeforelink();        // 完成shader中attribute的绑定等任务        program->link();                // 链接shader program        program->updateUniforms();      // 绑定预定义的8个uniform        updateCustomUniforms();         // 给shader中变量传值        return true;    }    return false;}

CustomDrawNode的创建通过指定一对着色器文件名,内部使用CCGLProgram来创建着色器程序

CustomDrawNode预留模板方法接口,让具体的子类来控制着色器程序的变量绑定及传值

customSetupBeforelink: 在程序链接之前,实现绑定一些attribute等 *** 作

updateCustomUniforms: 在程序链接之后,获取program中一些uniform的位置,并未绘制做准备,向OpenGL服务器传值等 *** 作

实现 第2步: 定义绘制矩形类CustomrectangleNode继承CustomDrawNode

下面就开始定义要绘制的矩形类了,定义一个类叫CustomrectangleNode,它继承CustomDrawNode,并且根据自己使用的shader来实现父类预留的模板方法接口。

CustomrectangleNode的具体实现取决于其使用的shader,因此首先要确定shader。因为我只想绘制一个彩色的矩形,shader很简单:

顶点着色器

#ifdef GL_ESprecision mediump float;#endifattribute   vec4    custom_a_position;                  // 为了区别于cocos预定义的shader中的a_position,名字起的繁琐一些。voID main(){    gl_position = CC_MVPMatrix * custom_a_position;     // 使用cocos预定义的投影矩阵}

片段着色器

#ifdef GL_ESprecision mediump float;#endifuniform     vec4    custom_u_color;                 // 区别于cocos预定义的u_colorvoID main(){    gl_Fragcolor = custom_u_color; }

顶点shader中定义了一个attribute, 片段shader中定义了一个uniform,这些对于了解绘制过程足够了。下面是CustomrectangleNode的实现:

// 成员变量的类型 attribute 和 uniform是在别的文件里定义的。// cocos_include.htypedef gluint  uniform;typedef gluint  attribute;// CustomrectangleNode.hclass CustomrectangleNode : public CustomDrawNode{public:    static CustomrectangleNode* create(const char *vs,const char *fs);    voID draw() overrIDe;    voID customSetupBeforelink() overrIDe;    voID updateCustomUniforms() overrIDe;protected:    CustomrectangleNode() : _attribposition(0),_uniformcolor(0) {}    const attribute     _attribposition;    uniform             _uniformcolor;};// CustomrectangleNode.cpp// 创建方法,通过父类接口来初始化CustomrectangleNode* CustomrectangleNode::create(const char *vs,const char *fs){    auto self = new CustomrectangleNode;    if (self && self->initWithShaders(vs,fs))     {        self->autorelease();        return self;    }    return nullptr;}// 模板方法接口1voID CustomrectangleNode::customSetupBeforelink(){    // 在链接程序之前,绑定顶点shader中唯一的attribute: custom_a_position.     getShaderProgram()->addAttribute("custom_a_position",_attribposition);}// 模板方法接口2voID CustomrectangleNode::updateCustomUniforms(){    // 程序链接之后,获得顶点着色器中唯一的uniform:custom_u_color    _uniformcolor = glGetUniformlocation(getShaderProgram()->getProgram(),"custom_u_color");    // 随机颜色    getShaderProgram()->setUniformlocationWith4f(        _uniformcolor,CCRANDOM_0_1(),CCRANDOM_0_1());}// 开始绘制voID CustomrectangleNode::draw(){    // 调用program->use(),为预定义的uniform传值    CC_NODE_DRAW_SETUP();    // 定义矩形顶点坐标,中心定位在屏幕中心,宽高是窗口一半。    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;    GLfloat vertexes[] =     {        x,y,x+wIDth,x,y+height,};    // 启用顶点数组,并传值    glEnab@R_403_5622@texAttribarray(_attribposition);    glVertexAttribPointer(_attribposition,2,GL_float,false,sizeof(GL_float) * 2,vertexes);    // 使用这四个顶点绘制两个三角形    glDrawArrays(GL_TRIANGLE_STRIP,0,4);    // 关闭顶点数组    // gldisab@R_403_5622@texAttribarray(_attribposition); 不注释掉这句的话,绘制会有点问题: 绘制完矩形之后,按钮什么的没有绘制。还没发现是咋回事    // 增加draw call次数    CC_INCREMENT_GL_DRAWS(1);}

好了,CustomrectangleNode定义完成了,

CustomrectangleNode重写了父类定义的模板方法customSetupBeforelink(),在其中中绑定了顶点着色器中的attribute: custom_a_position,

CustomrectangleNode重写了父类定义的模板方法updateCustomUniforms,在其中绑定了片段着色器中的uniform:custom_u_color,并且给其赋值一个随机的颜色向量。

CustomrectangleNode重写了Node的draw()方法, 定义了顶点数组,并且把数组传给顶点shader中的custom_a_position,最终实现了矩形的绘制。

下面是测试代码:

创建一个CustomrectangleNode,并且把它addChild()到节点树即可。

voID CustomDrawNodePage::onEnterState(){    // add test cases.    _createFuncs.clear();    _createFuncs.insert(_createFuncs.begin(),{ std::bind(&CustomrectangleNode::create,"shaders/custom_rectangle_vert.glsl","shaders/custom_rectangle_frag.glsl"),});    loadUI();}voID CustomDrawNodePage::loadUI(){    auto node = _createFuncs[_testIndex](); // CustomrectangleNode::create("shaders/custom_rectangle_vert.glsl","shaders/custom_rectangle_frag.glsl") ADD_CHILD(node);}
源码

CustomDrawNodePage.h

CustomDrawNodePage.cpp

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

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

总结

以上是内存溢出为你收集整理的【cocos2d-x 2.x 学习与应用总结】13: 借助CCGLProgram实现自定义绘制全部内容,希望文章能够帮你解决【cocos2d-x 2.x 学习与应用总结】13: 借助CCGLProgram实现自定义绘制所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://www.outofmemory.cn/web/1076755.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-26
下一篇 2022-05-26

发表评论

登录后才能评论

评论列表(0条)

保存