首页 > 编程语言 >Cocos2dx渲染---从DrawNode切入

Cocos2dx渲染---从DrawNode切入

时间:2022-11-03 12:22:43浏览次数:44  
标签:Cocos2dx BUFFER T2F --- DrawNode V2F C4B ARRAY GL

一、先从画一条线开始

1.drawLine使用方法

    auto scene = Scene::create();
    Director::getInstance()->runWithScene(scene);
    auto node = DrawNode::create();
    //传入两个定点与线的颜色
    node->drawLine(Vec2(1,1),Vec2(1,222),Color4F(222,1,1,1));
    scene->addChild(node);

2.进入drawLine

//主要是告诉有几个定点以及定点的位置
void DrawNode::drawLine(const Vec2 &origin, const Vec2 &destination, const Color4F &color)
{
    ensureCapacityGLLine(2);
    V2F_C4B_T2F *point = (V2F_C4B_T2F*)(_bufferGLLine + _bufferCountGLLine);
    V2F_C4B_T2F a = {origin, Color4B(color), Tex2F(0.0, 0.0)};
    V2F_C4B_T2F b = {destination, Color4B(color), Tex2F(0.0, 0.0)};
    *point = a;
    *(point+1) = b;
    _bufferCountGLLine += 2;
    _dirtyGLLine = true;
}

3.渲染准备

bool DrawNode::init()
{
    _blendFunc = BlendFunc::ALPHA_PREMULTIPLIED;

    setGLProgramState(GLProgramState::getOrCreateWithGLProgramName(GLProgram::SHADER_NAME_POSITION_LENGTH_TEXTURE_COLOR));
    
    ensureCapacity(512);
    ensureCapacityGLPoint(64);
    ensureCapacityGLLine(256);
    
    if (Configuration::getInstance()->supportsShareableVAO())
    {
        //创建一个VAO顶点数组对象:可以被绑定,任何随后的定点属性都会存储在这个_vao中
        glGenVertexArrays(1, &_vao);
        GL::bindVAO(_vao);
        //创建一个VBO顶点缓冲对象:可以在显存里面存储大量的定点,使用的好处是可以一次性的发送一大批数据到显卡上。
        glGenBuffers(1, &_vbo);
        //把创建的缓冲绑定到GL_ARRAY_BUFFER上面,从这一刻起,使用的任何(在GL_ARRAY_BUFFER目标上的)缓冲调用都会用来配置当前绑定的缓冲(VBO)
        glBindBuffer(GL_ARRAY_BUFFER, _vbo);
        //把定义的定点数据复制到内存
        glBufferData(GL_ARRAY_BUFFER, sizeof(V2F_C4B_T2F)* _bufferCapacity, _buffer, GL_STREAM_DRAW);
        // vertex
        //启用定点属性
        glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_POSITION);
        //如何解析定点数据
        //参数1:配置的定点属性,与顶点着色器有关
        //参数2:一个属性的大小
        //参数3:数据类型
        //参数4:GL_TRUE的话,数据都会被转化为0-1之间或者有符号的-1-1之间
        //参数5:两个定点之间的距离
        //参数6:最后一个参数的类型是void*,所以需要我们进行这个奇怪的强制类型转换。
        //它表示位置数据在缓冲中起始位置的偏移量(Offset)。
        glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(V2F_C4B_T2F), (GLvoid *)offsetof(V2F_C4B_T2F, vertices));
        // color
        glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_COLOR);
        glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(V2F_C4B_T2F), (GLvoid *)offsetof(V2F_C4B_T2F, colors));
        // texcoord
        glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_TEX_COORD);
        glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORD, 2, GL_FLOAT, GL_FALSE, sizeof(V2F_C4B_T2F), (GLvoid *)offsetof(V2F_C4B_T2F, texCoords));
        
        /*
        * 
        */
        
        //省略删除
    }
    else
    {
        glGenBuffers(1, &_vbo);
        glBindBuffer(GL_ARRAY_BUFFER, _vbo);
        glBufferData(GL_ARRAY_BUFFER, sizeof(V2F_C4B_T2F)* _bufferCapacity, _buffer, GL_STREAM_DRAW);
        
        glGenBuffers(1, &_vboGLLine);
        glBindBuffer(GL_ARRAY_BUFFER, _vboGLLine);
        glBufferData(GL_ARRAY_BUFFER, sizeof(V2F_C4B_T2F)*_bufferCapacityGLLine, _bufferGLLine, GL_STREAM_DRAW);
        
        glGenBuffers(1, &_vboGLPoint);
        glBindBuffer(GL_ARRAY_BUFFER, _vboGLPoint);
        glBufferData(GL_ARRAY_BUFFER, sizeof(V2F_C4B_T2F)*_bufferCapacityGLPoint, _bufferGLPoint, GL_STREAM_DRAW);

        glBindBuffer(GL_ARRAY_BUFFER, 0);
    }
    
    CHECK_GL_ERROR_DEBUG();
    
    _dirty = true;
    _dirtyGLLine = true;
    _dirtyGLPoint = true;
    
#if CC_ENABLE_CACHE_TEXTURE_DATA
    // Need to listen the event only when not use batchnode, because it will use VBO
    auto listener = EventListenerCustom::create(EVENT_RENDERER_RECREATED, [this](EventCustom* event){
   /** listen the event that renderer was recreated on Android/WP8 */
        this->init();
    });

    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
#endif
    
    return true;
}

4.渲染

(1).draw

void DrawNode::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
{
    if(_bufferCount)
    {
        _customCommand.init(_globalZOrder, transform, flags);
        _customCommand.func = CC_CALLBACK_0(DrawNode::onDraw, this, transform, flags);
        renderer->addCommand(&_customCommand);
    }
    
    if(_bufferCountGLPoint)
    {
        _customCommandGLPoint.init(_globalZOrder, transform, flags);
        _customCommandGLPoint.func = CC_CALLBACK_0(DrawNode::onDrawGLPoint, this, transform, flags);
        renderer->addCommand(&_customCommandGLPoint);
    }
    
    if(_bufferCountGLLine)
    {
    	//这里可以看到,用的是custom自定义的渲染指令
        _customCommandGLLine.init(_globalZOrder, transform, flags);
        _customCommandGLLine.func = CC_CALLBACK_0(DrawNode::onDrawGLLine, this, transform, flags);
        renderer->addCommand(&_customCommandGLLine);
    }
}

(2).onDrawGLLine

void DrawNode::onDrawGLLine(const Mat4 &transform, uint32_t /*flags*/)
{
    //使用默认的着色器
    auto glProgram = GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_LENGTH_TEXTURE_COLOR);
    glProgram->use();
    glProgram->setUniformsForBuiltins(transform);
    glProgram->setUniformLocationWith1f(glProgram->getUniformLocation("u_alpha"), _displayedOpacity / 255.0);

    //设置混合模式
    GL::blendFunc(_blendFunc.src, _blendFunc.dst);

    if (_dirtyGLLine)
    {
        glBindBuffer(GL_ARRAY_BUFFER, _vboGLLine);
        glBufferData(GL_ARRAY_BUFFER, sizeof(V2F_C4B_T2F)*_bufferCapacityGLLine, _bufferGLLine, GL_STREAM_DRAW);
        _dirtyGLLine = false;
    }
    if (Configuration::getInstance()->supportsShareableVAO())
    {
        //绑定vao
        GL::bindVAO(_vaoGLLine);
    }
    else
    {
        glBindBuffer(GL_ARRAY_BUFFER, _vboGLLine);
        GL::enableVertexAttribs(GL::VERTEX_ATTRIB_FLAG_POS_COLOR_TEX);
        // vertex
        glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(V2F_C4B_T2F), (GLvoid *)offsetof(V2F_C4B_T2F, vertices));
        // color
        glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(V2F_C4B_T2F), (GLvoid *)offsetof(V2F_C4B_T2F, colors));
        // texcoord
        glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORD, 2, GL_FLOAT, GL_FALSE, sizeof(V2F_C4B_T2F), (GLvoid *)offsetof(V2F_C4B_T2F, texCoords));
    }

    //设置线的宽度
    glLineWidth(_lineWidth);
    //绘制GL_LINES
    glDrawArrays(GL_LINES, 0, _bufferCountGLLine);

    //解绑vao
    if (Configuration::getInstance()->supportsShareableVAO())
    {
        GL::bindVAO(0);
    }
    
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    //添加本次渲染的信息 3个顶点信息与一次drawCall
    CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1,_bufferCountGLLine);
    
    CHECK_GL_ERROR_DEBUG();
}

二、看看其他图形

1.点

void DrawNode::drawPoint(const Vec2& position, const float pointSize, const Color4F &color)
{
    ensureCapacityGLPoint(1);
    
    V2F_C4B_T2F *point = (V2F_C4B_T2F*)(_bufferGLPoint + _bufferCountGLPoint);
    V2F_C4B_T2F a = {position, Color4B(color), Tex2F(pointSize,0)};
    *point = a;
    
    _bufferCountGLPoint += 1;
    _dirtyGLPoint = true;
}

可以看到drawPoint用的是_bufferGLPoint,对应的VAO是_vaoGLPoint,所以渲染的方法对应使用的vao、vbo是:

void DrawNode::onDrawGLPoint(const Mat4 &transform, uint32_t /*flags*/)
{
    auto glProgram = GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_COLOR_TEXASPOINTSIZE);
    glProgram->use();
    glProgram->setUniformsForBuiltins(transform);
    glProgram->setUniformLocationWith1f(glProgram->getUniformLocation("u_alpha"), _displayedOpacity / 255.0);

    GL::blendFunc(_blendFunc.src, _blendFunc.dst);

    if (_dirtyGLPoint)
    {
        glBindBuffer(GL_ARRAY_BUFFER, _vboGLPoint);
        glBufferData(GL_ARRAY_BUFFER, sizeof(V2F_C4B_T2F)*_bufferCapacityGLPoint, _bufferGLPoint, GL_STREAM_DRAW);
        
        _dirtyGLPoint = false;
    }
    
    if (Configuration::getInstance()->supportsShareableVAO())
    {
        GL::bindVAO(_vaoGLPoint);
    }
    else
    {
        glBindBuffer(GL_ARRAY_BUFFER, _vboGLPoint);
        GL::enableVertexAttribs( GL::VERTEX_ATTRIB_FLAG_POS_COLOR_TEX);
        glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(V2F_C4B_T2F), (GLvoid *)offsetof(V2F_C4B_T2F, vertices));
        glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(V2F_C4B_T2F), (GLvoid *)offsetof(V2F_C4B_T2F, colors));
        glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORD, 2, GL_FLOAT, GL_FALSE, sizeof(V2F_C4B_T2F), (GLvoid *)offsetof(V2F_C4B_T2F, texCoords));
    }
    
    glDrawArrays(GL_POINTS, 0, _bufferCountGLPoint);
    
    if (Configuration::getInstance()->supportsShareableVAO())
    {
        GL::bindVAO(0);
    }
    
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    
    CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1,_bufferCountGLPoint);
    CHECK_GL_ERROR_DEBUG();
}

2.其他,例如drawDot

void DrawNode::drawDot(const Vec2 &pos, float radius, const Color4F &color)
{
    unsigned int vertex_count = 2*3;
    ensureCapacity(vertex_count);
    
    V2F_C4B_T2F a = {Vec2(pos.x - radius, pos.y - radius), Color4B(color), Tex2F(-1.0, -1.0) };
    V2F_C4B_T2F b = {Vec2(pos.x - radius, pos.y + radius), Color4B(color), Tex2F(-1.0,  1.0) };
    V2F_C4B_T2F c = {Vec2(pos.x + radius, pos.y + radius), Color4B(color), Tex2F( 1.0,  1.0) };
    V2F_C4B_T2F d = {Vec2(pos.x + radius, pos.y - radius), Color4B(color), Tex2F( 1.0, -1.0) };
    
    V2F_C4B_T2F_Triangle *triangles = (V2F_C4B_T2F_Triangle *)(_buffer + _bufferCount);
    V2F_C4B_T2F_Triangle triangle0 = {a, b, c};
    V2F_C4B_T2F_Triangle triangle1 = {a, c, d};
    triangles[0] = triangle0;
    triangles[1] = triangle1;
    
    _bufferCount += vertex_count;
    
    _dirty = true;
}

用的数据块是_buffer,对应的是_vao。


如有问题,及时指出。

标签:Cocos2dx,BUFFER,T2F,---,DrawNode,V2F,C4B,ARRAY,GL
From: https://www.cnblogs.com/hahazoe/p/16854052.html

相关文章

  • 2022-11-03
    大级别:1D下跌结束,预期转2D下跌   中级别:黄色2H两波上涨,第一波级别40F,第二波级别10F。如果第二波级别还没扩大到至少40F,不背驰,等做多;如果第二波级别扩大到至少40F,背......
  • Set-UID
    ......
  • UD6KB100-ASEMI新能源专用整流桥UD6KB100
    编辑:llUD6KB100-ASEMI新能源专用整流桥UD6KB100型号:UD6KB100品牌:ASEMI封装:D3K正向电流:6A反向电压:1000V引脚数量:4芯片个数:4芯片尺寸:88MIL漏电流:>10ua恢复时间:>2000ns浪涌电流......
  • Python3-环境篇-01-Python3安装
     1.在python官网下载合适的python(windows)​编辑我这里下载了截至目前最新的3.10.2版本,推荐下载下方的稳定版本​编辑2选择合适的版本​编辑3安装Python(我这里默认安装路径,......
  • ORA-03113: end-of-file on communication channel Serial number: 5
    ORA-03113:end-of-fileoncommunicationchannel ProcessID:41880  SessionID:762Serialnumber:5---step1: 查看Alert日志 1.1Alter日志的路径查看[orac......
  • 集成无线收发器和 8 位 RISC MCU 的 SOC 芯片CI2454/CI2451参数-遥控玩具汽车方案
    前面小编给大家介绍了一款集成无线收发器和8位RISC(精简指令集)MCU的SOC芯片-CI2454/CI2451,今天就来讲讲它的优劣势和应用方案。优势1、它拥有RISC精简指令集架构,可以......
  • Halcon实用系列-识别二维条码
    在做项目时,之前使用的是某康的智能读码器,综合考虑成本,可通过相机拍照来读取图片的二维码,我这边用Halcon来实现。Halcon代码如下:1*创建模型2create_data_code_2d_m......
  • iperf---网络测试工具使用方法
    iperf3是iperf的3.0版本,是一款网络性能测试工具,在网络中单向传输数据流,根据需要调整传输速率和数据流大小,也可以根据需要报告带宽、延迟抖动和数据包丢失。它支持调节各种......
  • ASEMI代理LSIC2SD120A05-力特Sic肖特基二极管
    编辑:llASEMI代理LSIC2SD120A05-力特Sic肖特基二极管型号:LSIC2SD120A05品牌:LITTELFUSE/力特封装:TO-220-2L特性:Sic肖特基二极管正向电流:5A反向耐压:1200V恢复时间:35ns......
  • element的el-checkbox-group复选框全选
    <el-checkboxv-model="checkAll":indeterminate="isIndeterminate"@change="handleCheckAllChange">全选......