在前面文章中讲述了Cocos2d-x引擎OpenGL渲染准备Shader方面,本文主要讲解使用LayerColor来讲述OpenGL的渲染过程。

1、LayerColor对象创建

添加LayerColor元素到游戏中:

auto layerColor = LayerColor::create(Color4B(, , , ), , );
layerColor->setPosition(,);

下面是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创建并初始化成功后, (使用create方法创建的对象,需要)将该对象加热自动内存管理

在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 = ;i<sizeof(_squareVertices) / sizeof( _squareVertices[]); 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 = ; i < ; ++i)
{
Vec4 pos;
pos.x = _squareVertices[i].x;
pos.y =_squareVertices[i].y;
pos.z = _positionZ;
pos.w = ;
_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 = ;
for (auto &renderqueue : _renderGroups){
renderqueue.sort();
}
visitRenderQueue(_renderGroups[]);
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 = ; 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,, GL_FLOAT, GL_FALSE, , _noMVPVertices);
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR,, GL_FLOAT, GL_FALSE, , _squareColors); GL::blendFunc( _blendFunc.src, _blendFunc.dst);
glDrawArrays(GL_TRIANGLE_STRIP, , );
CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(,);
}

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)的更多相关文章

  1. 基于Cocos2d-x学习OpenGL ES 2.0系列——OpenGL ES渲染之Shader准备(7)

    Cocos2d-x底层图形绘制是使用OpenGL ES协议的.OpenGL ES是什么呢? OpenGL ES(OpenGl for Embedded System)是OpenGL三维图形API的子集 ...

  2. 基于Cocos2d-x学习OpenGL ES 2.0系列——纹理贴图(6)

    在上一篇文章中,我们介绍了如何绘制一个立方体,里面涉及的知识点有VBO(Vertex Buffer Object).IBO(Index Buffer Object)和MVP(Modile-View-P ...

  3. 基于Cocos2d-x学习OpenGL ES 2.0系列——使用VBO索引(4)

    在上一篇文章中,我们介绍了uniform和模型-视图-投影变换,相信大家对于OpenGL ES 2.0应该有一点感觉了.在这篇文章中,我们不再画三角形了,改为画四边形.下篇教程,我们就可以画立方体了, ...

  4. 基于Cocos2d-x学习OpenGL ES 2.0系列——你的第一个三角形(1)

    前言 在本系列教程中,我会以当下最流行的2D引擎Cocos2d-x为基础,介绍OpenGL ES 2.0的一些基本用法.本系列教程的宗旨是OpenGL扫盲,让大家在使用Cocos2d-x过程中,知其然 ...

  5. 基于Cocos2d-x学习OpenGL ES 2.0系列——编写自己的shader(2)

    在上篇文章中,我给大家介绍了如何在Cocos2d-x里面绘制一个三角形,当时我们使用的是Cocos2d-x引擎自带的shader和一些辅助函数.在本文中,我将演示一下如何编写自己的shader,同时, ...

  6. 基于Cocos2d-x学习OpenGL ES 2.0系列——你的第一个立方体(5)

    在上篇文章中,我们介绍了VBO索引的使用,使用VBO索引可以有效地减少顶点个数,优化内存,提高程序效率. 本教程将带领大家一起走进3D--绘制一个立方体.其实画立方体本质上和画三角形没什么区别,所有的 ...

  7. 基于Cocos2d-x学习OpenGL ES 2.0系列——初识MVP(3)

    在上一篇文章中,我在介绍vertex shader的时候挖了一个坑:CC_MVPMatrix.它其实是一个uniform,每一个Cocos2d-x预定义的shader都包含有这个uniform,但是如 ...

  8. Beginning OpenGL ES 2.0 with GLKit Part 1

    Update 10/24/12: If you’d like a new version of this tutorial fully updated for iOS 6 and Xcode 4.5, ...

  9. Android OpenGL ES(一)OpenGL ES介绍

    在学习Android OpenGL ES开发之前,你必须具备Java 语言开发经验和一些Android开发的基本知识,但并不需要有图形开发的经验,本教程也会涉及到一些基本的线性几何知识,如矢量,矩阵运 ...

随机推荐

  1. Java代码编写的30条建议

    1) 类名首字母应该大写.字段.方法以及对象(句柄)的首字母应小写.对于所有标识符,其中包含的所有单词都应紧靠在一起,而且大写中间单词的首字母.例如: ThisIsAClassName thisIsM ...

  2. [mmc]Linux下MMC/SD/SDIO的识别与操作

    转自:http://blog.csdn.net/skdkjzz/article/details/38927943 我们知道host在扫描卡的过程中,其识别的顺序为SDIO  SD MMC,并且从它的注 ...

  3. Spring Boot 更换 Banner

    Spring 启动时,会有一个Banner图案,这个图案是可以更换的 . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ ...

  4. linux中hive无法使用删除键或无反应

    用的工具secureCRT连接linux服务器的,登录到hive中后无法使用删除键. 修改如下: 会话选项 -> 终端|仿真 ->  选择终端为linux.

  5. windows 搭建 subversion+TortoiseSVN

    1.版本 (a)Apache 2.2.25:httpd-2.2.25-win32-x86-no_ssl.msi (b)Subversion:Setup-Subversion-1.8.5.msi (c) ...

  6. js学习笔记29----拖拽

    原理:先计算鼠标与拖拽目标的左侧距离 跟 上面距离,再计算拖动后的位置. 示例代码: <!DOCTYPE html> <html lang="en"> &l ...

  7. 《FPGA全程进阶---实战演练》第三章之PCB设计之电感、磁珠和零欧姆电阻

    2.电感.磁珠和零欧姆电阻的区别 电感:电感是储能元件,多用于电源滤波回路.LC振荡电路.中低频滤波电路等,其应用频率很少超过50MHz.对电感而言,其感抗值和频率成正比.XL = 2πfL来说明,其 ...

  8. Office 2013 标点符号自动变成calibri字体

    在字体设置中,已经设置西文字体为“(使用中文字体)”,结果office 2013还是自动将输入的英文符号自动变成calibri字体. 举例:输入以下一段话 好好学习,天天向上. 中文字体中后面跟着标点 ...

  9. 【F12】网络面板

    使用网络面板了解请求和下载的资源文件并优化网页加载性能 (1)网络面板基础 测量资源加载时间 使用 Network 面板测量您的网站网络性能. Network 面板记录页面上每个网络操作的相关信息,包 ...

  10. 【LeetCode】Validate Binary Search Tree 二叉查找树的推断

    题目: Given a binary tree, determine if it is a valid binary search tree (BST). 知识点:BST的特点: 1.一个节点的左子树 ...