原贴: cocos2D-X源码分析之从cocos2D-X学习OpenGL(3)----BATCH_COMMAND

上一篇介绍了QUAD_COMMAND渲染命令,顺带介绍了VAO和VBO,这一篇介绍批处理渲染命令BatchCommand,批处理命令的处理在Render中比较简单

 else if(commandType == RenderCommand::Type:: BATCH_COMMAND)
{
//将之前缓存的绘制
flush();
auto cmd = static_cast<BatchCommand*>(command);
//调用命令
cmd->execute()
}

首先调用flush将之前缓存的VBO绘制出来,然后调用命令自己的执行函数,这个过程和CUSTOM_COMMAND是一样的,不同的是这里的execute调用的是BatchCommand确定的绘制函数,CUSTOM_COMMAND调用是传入的func函数,这里看一下BatchCommand的execute函数。

 void BatchCommand::execute()
{
//设置渲染材质
//shader
_shader->use();
//先取得MV和P,然后将MV和P相乘得到MVP,即模型视图投影矩阵
_shader->setUniformsForBuiltins(_mv);
//选择纹理单元,建立一个绑定到目标纹理的有名称的纹理
GL::bindTexture2D(_textureID);
//混合
GL::blendFunc(_blendType.src, _blendType.dst);
//绘制
_textureAtlas->drawQuads();
}

首先介绍其中一个重要的概念MVP,MVP即模型(Model)、视图(View)、投影(Projection)。

模型矩阵:所有物体都处于世界空间中,所以绘制和做变换的前提是把物体由模型空间转换到世界空间中,而这个转换就需要乘以模型矩阵。

视图矩阵:下一步需要把世界空间转换到相机空间或者是视角空间中,这需要乘以视图矩阵。

投影矩阵:最后需要将3d的立方体投影到一个2d平面上,需要从观察坐标系到齐次坐标系,需要乘以投影矩阵。整个过程如下图所示:

setUniformsForBuiltins函数

 void GLProgram::setUniformsForBuiltins(const kmMat4 &matrixMV)
{
//通过flag中的变量判断是否使用了相关的矩阵,这些标志变量在updateUniforms被设置
kmMat4 matrixP; kmGLGetMatrix(KM_GL_PROJECTION, &matrixP); if(_flags.usesP)
setUniformLocationWithMatrix4fv(_uniforms[UNIFORM_P_MATRIX], matrixP.mat, ); if(_flags.usesMV)
setUniformLocationWithMatrix4fv(_uniforms[UNIFORM_MV_MATRIX], matrixMV.mat, ); if(_flags.usesMVP) {
kmMat4 matrixMVP;
kmMat4Multiply(&matrixMVP, &matrixP, &matrixMV);
setUniformLocationWithMatrix4fv(_uniforms[UNIFORM_MVP_MATRIX], matrixMVP.mat, );
} if(_flags.usesTime) {
Director *director = Director::getInstance();
//这里不会使用真实的每帧时间去设置,那样太耗费效率
float time = director->getTotalFrames() * director->getAnimationInterval(); setUniformLocationWith4f(_uniforms[GLProgram::UNIFORM_TIME], time/10.0, time, time*, time*);
setUniformLocationWith4f(_uniforms[GLProgram::UNIFORM_SIN_TIME], time/8.0, time/4.0, time/2.0, sinf(time));
setUniformLocationWith4f(_uniforms[GLProgram::UNIFORM_COS_TIME], time/8.0, time/4.0, time/2.0, cosf(time));
} if(_flags.usesRandom)
setUniformLocationWith4f(_uniforms[GLProgram::UNIFORM_RANDOM01], CCRANDOM_0_1(), CCRANDOM_0_1(), CCRANDOM_0_1(), CCRANDOM_0_1());
}

这个函数里,有一个频繁出现的变量名uniforms,uniform是一种和着色器相关的,它必须被声明为全局变量,用于整个图元批次向保持不变的着色器传递数据,对于顶点着色器来说,可能最普遍的统一值就是变换矩阵,它通过调用glUniformXXXX系列函数向着色器传递数据,这里这个函数被封装了,调用setUniformLocationXXXX系列函数可以设置uniforms,这个函数首先通过调用updateUniformLocation函数判断这个uniforms的值是否确实被更新(在一个hash表里存上曾经设置过的键值对),如果确实需要被更新再调用glUniformXXXX更新这个uniforms,节约效率

bindTexture2DN函数主要是调用glActiveTexture和glBindTexture做贴图的绑定

 void bindTexture2DN(GLuint textureUnit, GLuint textureId)
{
#if CC_ENABLE_GL_STATE_CACHE
//做缓存,那么就不用为相同的textureId重复调用了
CCASSERT(textureUnit < kMaxActiveTexture, "textureUnit is too big");
if (s_currentBoundTexture[textureUnit] != textureId)
{
s_currentBoundTexture[textureUnit] = textureId;
activeTexture(GL_TEXTURE0 + textureUnit);
glBindTexture(GL_TEXTURE_2D, textureId);
}
#else glActiveTexture(GL_TEXTURE0 + textureUnit);
glBindTexture(GL_TEXTURE_2D, textureId);
#endif
}

glActiveTexture选择一个纹理单元,线面的纹理函数将作用于该纹理单元上,参数为符号常量GL_TEXTUREi ,i的取值范围为0~N-1,N是opengl实现支持的最大纹理单元数,这里,因为批处理只有一个纹理,所以textureUnit一直是0,由于使用缓存,只会被调用一次

glBindTexture建立一个绑定到目标纹理的有名称的纹理。比如把一个贴图绑定到一个形状上。

最后调用的绘制函数和上一篇介绍的类似,另外关于shader和混合的问题,将在后面单独开文章介绍

在引擎中使用BatchCommand这个命令的地方有两处ParticleBatchNode和SpriteBatchNode,使用方法很简单。

 _batchCommand.init(
_globalZOrder,
_shaderProgram,
_blendFunc,
_textureAtlas,
transform);
renderer->addCommand(&_batchCommand);

需要说明的是,在3.0之后的版本中,由于添加了auto-batch功能,ParticleBatchNode和SpriteBatchNode的节约效率的功能已经不那么明显,但是3.0之前的版本中,把精灵放在SpriteBatchNode父节点上和将粒子系统放在ParticleBatchNode,是能够把相同的精灵批处理,对于相同的贴图只调用一次绘制函数,还是对提升效率很有帮助的。

如有错误,欢迎指出

下一篇介绍图形渲染

[转帖]cocos2D-X源码分析之从cocos2D-X学习OpenGL(3)----BATCH_COMMAND的更多相关文章

  1. vlc源码分析(七) 调试学习HLS协议

    HTTP Live Streaming(HLS)是苹果公司提出来的流媒体传输协议.与RTP协议不同的是,HLS可以穿透某些允许HTTP协议通过的防火墙. 一.HLS播放模式 (1) 点播模式(Vide ...

  2. jQuery源码分析_工具方法(学习笔记)

    expando:生成唯一JQ字符串(内部使用) noConflict():防止冲突 isReady:DOM是否加载完成(内部) readyWait:等待多少文件的计数器(内部) holdReady() ...

  3. Django-restframework 之认证源码分析

    Django-restframework 源码分析之认证 前言 最近学习了 django 的一个 restframework 框架,对于里面的执行流程产生了兴趣,经过昨天一晚上初步搞清楚了执行流程(部 ...

  4. NIO-SocketChannel源码分析

    目录 NIO-SocketChannel源码分析 目录 前言 ServerSocketChannelImpl 创建ServerSocketChannel 绑定和监听 接收 SocketChannelI ...

  5. NIO-FileChannel源码分析

    目录 NIO-FileChannel源码分析 目录 前言 RandomAccessFile 接口 创建实例 获取文件通道 FileChannelImpl 创建 写文件 读文件 修改起始位置 获取文件长 ...

  6. NIO-WindowsSelectorImpl源码分析

    目录 NIO-WindowsSelectorImpl源码分析 目录 前言 初始化WindowsSelectorProvider 创建WindowsSelectorImpl WindowsSelecto ...

  7. NIO-EPollSelectorIpml源码分析

    目录 NIO-EPollSelectorIpml源码分析 目录 前言 初始化EPollSelectorProvider 创建EPollSelectorImpl EPollSelectorImpl结构 ...

  8. 精尽 MyBatis 源码分析 - 整体架构

    该系列文档是本人在学习 Mybatis 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释(Mybatis源码分析 GitHub 地址.Mybatis-Spring 源码分析 GitHub ...

  9. 干货分享之spring框架源码分析02-(对象创建or生命周期)

    记录并分享一下本人学习spring源码的过程,有什么问题或者补充会持续更新.欢迎大家指正! 环境: spring5.X + idea 之前分析了Spring读取xml文件的所有信息封装成beanDef ...

随机推荐

  1. taro 引用相对路径图片

    直接将相对路径放在src属性中,不起作用, 需要先import进来,最好把图片放到服务器上,然后直接写http路径 错误写法: <Image src="./images/front.p ...

  2. fis3 scss 版本报错

    fis3 scss编译需要安装的node版本为4.x,node版本高了fis会报错.如下图所示:

  3. &quot;高可用方案工具包&quot; high availability toolkit 1.2 公布了。version 1.2 新增了 负载均衡 load balance 的技术实现

    "高可用方案工具包"  high availability toolkit 1.2 公布了. version 1.2 新增了 负载均衡 load balance 的技术实现. 项目 ...

  4. SDUT 1157-小鼠迷宫问题(BFS&amp;DFS)

    小鼠迷宫问题 nid=24#time" title="C.C++.go.haskell.lua.pascal Time Limit1500ms Memory Limit 65536 ...

  5. assert语句(assert用来判断语句的真假)

    # -*- coding: utf-8 -*- #python 27 #xiaodeng #Python学习手册 868 #assert语句(assert用来判断语句的真假) #案例 mylist=[ ...

  6. eclipse+cygwin+cdt搭建c/c++开发环境

    Cygwin 是一个用于 Windows 的类 UNIX shell 环境. 它由两个组件组成:一个 UNIX API 库,它模拟 UNIX 操作系统提供的许多特性:以及 Bash shell 的改写 ...

  7. BIND9源码分析之acl 的实现

    BIND配置中一大堆一大堆的acl,什么allow-query, allow-recursion, allow-update还有view的match-clients等等等等. acl中的主要存储的就是 ...

  8. HDUOJ---A + B Again

    A + B Again Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  9. 如何用python轻松破解wifi密码( 源码 )

    摘要: 我得说明下这个东西一点都不高端,甚至看起来有点糟糕.而且用的是单线程~,因为过几天要搬家了,于是.. 环境准备 python2.7 凑合的linux 差不多的无线网卡 pywifi模块 弱口令 ...

  10. CSS:关于CSS Hack

    CSS Hack由于不同厂商的浏览器,如Internet Explorer,Safari,Mozilla Firefox,Chrome 等,或者是同一厂商的浏览器的不同版本,如IE6和IE7,对CSS ...