Cocos2dx引擎12-OpenGLES渲染之LayerColor

在前面微博中讲述了Cocos2dx引擎OpenGL渲染准备Shader方面,本博客中将使用LayerColor来讲述OpenGL的渲染过程。

1、LayerColor对象创建

添加LayerColor元素到游戏中:

autolayerColor = LayerColor::create(Color4B(255, 0, 0, 255), 100, 100);
layerColor->setPosition(100,100);
this->addChild(layerColor);

下面是LayerColor::create方法:

LayerColor* LayerColor::create(const Color4B& color, GLfloat width, GLfloat height)
{
    LayerColor * layer = new LayerColor();
    if( layer &&layer->initWithColor(color,width,height)) {
        layer->autorelease();
        return layer;
    }
    CC_SAFE_DELETE(layer);
    return nullptr;
}

1、使用new操作符创建新LayerColor对象

2、使用initWithColor方法初始化新建的LayerColor对象

3、LayerColor创建并初始化成功后,将该对象加热自动内存管理

在LayerColor::initWithColor方法中:

boolLayerColor::initWithColor(const Color4B& color, GLfloat w, GLfloat h){
    if (Layer::init()){
        _blendFunc =BlendFunc::ALPHA_NON_PREMULTIPLIED;
        _displayedColor.r = _realColor.r =color.r;
        _displayedColor.g = _realColor.g =color.g;
        _displayedColor.b = _realColor.b =color.b;
        _displayedOpacity = _realOpacity =color.a;
        for (size_t i = 0;i<sizeof(_squareVertices) / sizeof( _squareVertices[0]); i++ )
        {
            _squareVertices[i].x = 0.0f;
            _squareVertices[i].y = 0.0f;
        }

        updateColor();
        setContentSize(Size(w, h));

       setGLProgramState(GLProgramState::getOrCreateWithGLProgramName(GLProgram::SHADER_NAME_POSITION_COLOR_NO_MVP));
        return true;
    }
    return false;
}

1、调用Layer::init()方法,该方法的主要作用设置默认大小,其实在下面会重新设置LayerColor大小

2、设置混合模式为_blendFunc =BlendFunc::ALPHA_NON_PREMULTIPLIED

3、设置四个顶点的颜色

4、设置四个顶点的坐标,并设置Layer的大小

5、设置LayerColor渲染所使用Shader程序对应的GLProgramState

LayerColor其实是一个四边形,OpenGL会以四边形的方式渲染LayerColor,故需要设置四边形的顶点坐标&顶点颜色;所有的GLProgramState都会保持在GLProgramStateCache::_glProgramStates中,首次获取该GLProgramState时会新建GLProgramState对象,然后将该对象插入到GLProgramStateCache::_glProgramStates中。

2、LayerColor渲染

首先先看一下游戏的Function调用流程:

Application::run()
{
    ……
DisplayLinkDirector::mainLoop()
    ……
}
DisplayLinkDirector::mainLoop()
{
    ……
Director::drawScene()
……
……
}
Director::drawScene()
{
    ……
Node::visit(…)
    ……
Renderer::render()
……
}
Node::visit(…)
{
    ……
    LayerColor::draw(…)
……
}

LayerColor::draw(…)方法如下:

voidLayerColor::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
{
    _customCommand.init(_globalZOrder);
    _customCommand.func =CC_CALLBACK_0(LayerColor::onDraw, this, transform, flags);
   renderer->addCommand(&_customCommand);

    for(int i = 0; i < 4; ++i)
    {
        Vec4 pos;
        pos.x = _squareVertices[i].x; pos.y =_squareVertices[i].y; pos.z = _positionZ;
        pos.w = 1;
       _modelViewTransform.transformVector(&pos);
        _noMVPVertices[i] =Vec3(pos.x,pos.y,pos.z)/pos.w;
    }
}

1、初始化_customCommand对象,_customCommand是一个渲染指令

2、设置_customCommand的回调函数为LayerColor::onDraw

3、将该LayerColor的渲染指令_customCommand加入到渲染队列中

4、分别将四个顶点坐标通过模型视图矩阵转换

Renderer::addCommand(…)方法如下:

voidRenderer::addCommand(RenderCommand* command)
{
    int renderQueue =_commandGroupStack.top();
    addCommand(command, renderQueue);
}
voidRenderer::addCommand(RenderCommand* command, int renderQueue)
{
    _renderGroups[renderQueue].push_back(command);
}

1、 获取_commandGroupStack的堆栈,其实_commandGroupStack存储的是_renderGroups数组的位置编号

2、 将新的渲染命令加入_renderGroups[renderQueue]堆栈中

Renderer::render()方法如下:

voidRenderer::render()
{
    _isRendering = true;

    if (_glViewAssigned)
    {
        _drawnBatches = _drawnVertices = 0;
        for (auto &renderqueue : _renderGroups){
            renderqueue.sort();
        }
        visitRenderQueue(_renderGroups[0]);
        flush();
    }
    clean();
    _isRendering = false;
}

1、将_isRendering该帧是否渲染标志设为true

2、遍历_renderGroups,并对RenderQueue进行排序

3、真正的渲染部分,其实在_renderGroups中只目前只存在一个渲染集合

4、刷新OpenGL中参数

5、将_renderGroups能够所有CommandClean

RenderQueue::sort()渲染命令排序方法:

voidRenderQueue::sort()
{
      std::sort(std::begin(_queueNegZ),std::end(_queueNegZ), compareRenderCommand);
    std::sort(std::begin(_queuePosZ), std::end(_queuePosZ),compareRenderCommand);
}
staticbool compareRenderCommand(RenderCommand* a, RenderCommand* b)
{
    return a->getGlobalOrder() < b->getGlobalOrder();
}

1、将Command中元素Z坐标小于0的Command集合,按照重小到大排序

2、将Command中元素Z坐标大于0的Command集合,按照重小到大排序

Renderer::visitRenderQueue方法如下:

voidRenderer::visitRenderQueue(const RenderQueue& queue)
{
    ssize_t size = queue.size();

    for (ssize_t index = 0; index < size; ++index){
        auto command = queue[index];
        auto commandType = command->getType();
        if(RenderCommand::Type::QUAD_COMMAND ==commandType) {
           ……
        }else if(RenderCommand::Type::GROUP_COMMAND== commandType) {
            ……
        }else if(RenderCommand::Type::CUSTOM_COMMAND== commandType) {
            ……
        }else if(RenderCommand::Type::BATCH_COMMAND ==commandType) {
            ……
        }else if (RenderCommand::Type::MESH_COMMAND== commandType) {
            ……
      }
    }
}

1、获取RenderQueue长度

2、遍历RenderQueue列表,并对不同类型的渲染Command分别处理

3、当渲染Commad类型为QUAD_COMMAND时

4、当渲染Commad类型为GROUP_COMMAND时

5、当渲染Commad类型为CUSTOM_COMMAND时

6、当渲染Commad类型为BATCH_COMMAND时

7、当渲染Commad类型为MESH_COMMAND时

由于篇幅有限,每种渲染的具体流程后续会分别讨论,由于LayerColor使用的是CustomCommand,下面会分析CustomCommand的具体渲染方法

elseif(RenderCommand::Type::CUSTOM_COMMAND == commandType)
{
    flush();
    auto cmd = static_cast<CustomCommand*>(command);
    cmd->execute();
}

1、更新OpenGL参数,每次渲染前都需执行的操作,作用是将OpenGL参数设置为默认状态

2、请强制转换类型,并执行渲染Command

voidCustomCommand::execute()
{
    if(func) {
        func();
    }
}

判断func是否为空,若func不为空,执行该方法;func是一个回调函数,在添加LayerColor渲染命时指定,如:_customCommand.func= CC_CALLBACK_0(LayerColor::onDraw, this, transform, flags)

LayerColor真正的渲染部分:

voidLayerColor::onDraw(const Mat4& transform, uint32_t flags)
{
    getGLProgram()->use();
    getGLProgram()->setUniformsForBuiltins(transform);

GL::enableVertexAttribs( GL::VERTEX_ATTRIB_FLAG_POSITION| GL::VERTEX_ATTRIB_FLAG_COLOR );

    glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION,3, GL_FLOAT, GL_FALSE, 0, _noMVPVertices);
    glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR,4, GL_FLOAT, GL_FALSE, 0, _squareColors);

    GL::blendFunc( _blendFunc.src, _blendFunc.dst);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1,4);
}

1、使用对应的Shader程序

2、设置对应的Uniforms 矩阵

3、使能OpenGL中顶点数组和颜色数组功能

4、设置四边形的四个顶点和颜色

5、设置混合模式

6、glDrawArrays画四边形

LayerColor其实是一个有颜色的四边形,渲染LayerColor只需要在正确的位置画一个有颜色的四边形即可;Cocos2dx使用渲染方式是OpenGL ES(Windows平台不同),在OpenGL ES中并没有直接画四边形的方法,故需要借助画三角形的方法画四边形,如glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)为画四边形;

时间: 2024-10-16 14:02:17

Cocos2dx引擎12-OpenGLES渲染之LayerColor的相关文章

基于Cocos2d-x学习OpenGL ES 2.0系列——OpenGL ES渲染之LayerColor(8)

在前面文章中讲述了Cocos2d-x引擎OpenGL渲染准备Shader方面,本文主要讲解使用LayerColor来讲述OpenGL的渲染过程. 1.LayerColor对象创建 添加LayerColor元素到游戏中: autolayerColor = LayerColor::create(Color4B(255, 0, 0, 255), 100, 100); layerColor->setPosition(100,100); 下面是LayerColor::create方法: LayerColo

Cocos2dx引擎11-OpenGLES渲染之Shader准备

Cocos2dx底层图形绘制是使用OpenGL ES协议的.OpenGL ES是什么呢? OpenGL ES(OpenGl for Embedded System)是OpenGL三维图形API的子集,针对手机,PDA和游戏主机等嵌入式设备而设计.该API有Khronos集团定义推广,Khronos是一个图形软硬件行业协会,该协会主要关注图形和多媒体方面的开放标准. OpenGL ES是从OpenGL剪裁或定制过来了,去除了glBegin/glEnd,四边形(GL_QUADS),多边形(GL_PO

Cocos2d-x 3.x 图形学渲染系列二十八

笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,国家专利发明人;已出版书籍:<手把手教你架构3D游戏引擎>电子工业出版社和<Unity3D实战核心技术详解>电子工业出版社等. CSDN视频网址:http://edu.csdn.net/lecturer/144 昨天,刚从丈母娘家回来,继续博客的更新,接着Cocos2d-x 3.x图形学渲染系列二十七继续系列二十八的编写. 接下来读取FBX模型文件信息,首先要做的是把读取的模型信息进行归类并

Cocos2d-x 3.x 图形学渲染系列十五

笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,国家专利发明人;已出版书籍:<手把手教你架构3D游戏引擎>电子工业出版社和<Unity3D实战核心技术详解>电子工业出版社等. 在游戏开发中或者是游戏程序员招聘中,都有关于图形学或者引擎高级程序职位.凡是涉及到这些职位的招聘,对于此职位的开发人员都需要会Shader编程或者说GPU编程,同时他们的薪资也是比较高的.目前国内掌握图形学编程的人不是很多,物以稀为贵.Shader编程的主要目的是协

Cocos2dx引擎优化(1) ---音效系统

Cocos2dx提供的音频库位于CocosDenshion中,其接口由SimpleAudioEngine定义,提供了基本的背景音乐和音效播放. SimpleAudioEngine的实现是夸平台的, 在windows平台上由mci相关API实现; 在android平台上透过JNI,调用android sdk 中的AudioPlayer实现;而在IOS平台上由Cocoa sdk里的Core-Audio实现.但SimpleAudioEngine并不适用于大部分游戏情境,它在Android上的实现需要直

第1部分: 游戏引擎介绍, 渲染和构造3D世界

原文作者:Jake Simpson译者: 向海Email:[email protected] ------------------------------------------------------------第1部分: 游戏引擎介绍, 渲染和构造3D世界 介绍 自Doom游戏时代以来我们已经走了很远. DOOM不只是一款伟大的游戏,它同时也开创了一种新的游戏编程模式: 游戏 "引擎". 这种模块化,可伸缩和扩展的设计观念可以让游戏玩家和程序设计者深入到游戏核心,用新的模型,场景和

Cocos2d-x学习笔记(十六)--------&gt;Cocos2d-x引擎中的网格地图

网格地图 2D游戏网格地图介绍: 在网格地图游戏中,地图由称为"瓷砖"(tile)的一小组图片相互排列组成.这些图片放在一个整体的网格中.得到一个令人信服的游戏场景.网格地图技术为开发者提供了很多便利,使用很少的网格图片元素,就可以组成非常大的场景地图,而且这些大场景并不会浪费硬件资源.而且根据网格元素的不同,可以得到多种多样的场景地图. 网格地图主要分为两大类: 第一类是90度网格地图(Orthogonal Tilemap),这类地图都是使用正方形或者长方形的瓷砖(Tile)组成的,

Android Cocos2dx引擎 prv.ccz/plist/so等优化缓存文件,手把手ida教你逆向project反编译apk库等文件

前段时间在 Android play 上看到一个非常牛逼的 3D 动态天气预报,效果真的非常炫.二话不说动手 dex2jar.bat/apktool 发现这并没 有什么卵用,在核心的地方看见 native 字段果断放弃了治疗,立刻转向 so 的逆向project.发现了cocos2dx so 引擎,搜噶.我就说 嘛这么炫酷的效果, Android 源代码是做不了的.即使达到了这样的程度,预计性能也特别不好.由于那个动态效果是不会循环播放 的,也就是不会反复.是自己绘制的依据资源文件,在反编译的

Cocos2d-x 3.x 图形学渲染系列二十七

笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,国家专利发明人;已出版书籍:<手把手教你架构3D游戏引擎>电子工业出版社和<Unity3D实战核心技术详解>电子工业出版社等. CSDN视频网址:http://edu.csdn.net/lecturer/144 笔者以前在游戏公司开发大型MMOARPG游戏时,游戏中使用的模型为了防止产品发布后被破解,程序再做模型导出插件时对模型进行了加密处理.针对模型加密的方式非常多,通常的做法是通过已经编