码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2015-05-05 23:37:57      阅读:150      评论:0      收藏:0      [点我收藏+]

标签:

前面文章中讲述了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方法:

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)为画四边形;

 

来源网址:http://blog.csdn.net/xinchuantao/article/details/40504803

 

 

 

 

 

 

 

 

 

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

标签:

原文地址:http://www.cnblogs.com/yyxt/p/4480576.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!