在cocos2dx 2.x中,如果我们要对sprite更换片段shader,写成:

myProgram->initWithByteArrays(ccPositionTextureColor_vert, myFragSource);

但是到3.x中,上面做法会导致显示出来的sprite坐标不对。

于是看3.x代码,发现在3.x中,Sprite的默认shader不再是kCCShader_PositionTextureColor(即

GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR),而是改成了GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR_NO_MVP(见Sprite::initWithTexture(...)函数实现)。

因此应该用:

myProgram->initWithByteArrays(ccPositionTextureColor_noMVP_vert, myFragSource);

显示就正常了。

对比一下ccPositionTextureColor_vert和ccPositionTextureColor_noMVP_vert的代码:

const char* ccPositionTextureColor_vert = STRINGIFY(

attribute vec4 a_position;

attribute vec2 a_texCoord;

attribute vec4 a_color;

\n#ifdef GL_ES\n

varying lowp vec4 v_fragmentColor;

varying mediump vec2 v_texCoord;

\n#else\n

varying vec4 v_fragmentColor;

varying vec2 v_texCoord;

\n#endif\n

void main()

{

gl_Position = CC_MVPMatrix * a_position;

v_fragmentColor = a_color;

v_texCoord = a_texCoord;

}

);

const char* ccPositionTextureColor_noMVP_vert = STRINGIFY(

attribute vec4 a_position;

attribute vec2 a_texCoord;

attribute vec4 a_color;

\n#ifdef GL_ES\n

varying lowp vec4 v_fragmentColor;

varying mediump vec2 v_texCoord;

\n#else\n

varying vec4 v_fragmentColor;

varying vec2 v_texCoord;

\n#endif\n

void main()

{

gl_Position = CC_PMatrix * a_position;

v_fragmentColor = a_color;

v_texCoord = a_texCoord;

}

);

可见唯一区别就是顶点坐标a_position乘的矩阵不同,ccPositionTextureColor_vert中乘的是CC_MVPMatrix,ccPositionTextureColor_noMVP_vert中乘的是CC_PMatrix。

于是就明白了:

在2.x的立即模式中,传入shader的顶点坐标为局部坐标,所以需要在shader中乘以MVP矩阵来求屏幕坐标。

在3.x的command模式中,传入shader的顶点坐标已预先转化成了世界坐标(即已乘过MV矩阵),所以在shader中就只乘P矩阵即可。

于是引出两个问题:

问题1,为什么command模式下,sprite要预先转化成世界坐标?

  因为如果所有顶点都转化到了相同的空间(比如世界空间),那么它们的变换矩阵M就同一了(可以作为一个uniform变量),于是这些顶点可以一次性提交,从而减少了draw call数量。这也正是command机制的目的所在。不过需要注意的是,3.x中也并非所有的节点都使用了noMVP的形式,因为并不是所有渲染对象都如sprite这样顶点数很少适合展平做batch -- 假设有几个MV矩阵不同的顶点数很多的mesh,如果也像处理sprite一样进行展平一次性提交,虽然draw call数量下来了,可是cpu做顶点变换的开销却会大幅增加,其结果很可能反而不如多用几个draw call,但把顶点变换转移到gpu(shader)中去做效率高。所以在对一个节点更换shader的时候,要注意看一下其默认shader是有MVP还是noMVP。

问题2,sprite预先转化成世界坐标的代码在哪?

  在void Renderer::visitRenderQueue(const RenderQueue& queue)中的if ( RenderCommand::Type::QUAD_COMMAND == commandType )分支中有一句fillQuads(cmd)。fillQuads(...)的实现如下:

void Renderer::fillQuads(const QuadCommand *cmd)

{

memcpy(_quadVerts + _numberQuads * 4, cmd->getQuads(), sizeof(V3F_C4B_T2F_Quad) * cmd->getQuadCount());

const Mat4& modelView = cmd->getModelView();

for(ssize_t i=0; i< cmd->getQuadCount() * 4; ++i)

{

V3F_C4B_T2F *q = &_quadVerts[i + _numberQuads * 4];

Vec3 *vec1 = (Vec3*)&q->vertices;

modelView.transformPoint(vec1);

}

_numberQuads += cmd->getQuadCount();

}

其中的for循环就是在对quads顶点数组中的每个坐标乘以MV矩阵。

cocos2dx 3.x ccPositionTextureColor_vert与ccPositionTextureColor_noMVP_vert相关推荐

  1. cocos2dx spine之二 :spine变色

    cocos2dx版本为3.10 1.具体原理和代码可以参考博文<利用shader改变图片色相Hue>,下面的代码根据该博文进行整理优化. 基本原理就是将RGB值转换为HSL值后加上输入的H ...

  2. cocos2d-x 3.10 PageView BUG

    cocos2d-x 3.10 PageView 拖动滚动到下一个单元,没事件,3.11有修复. 转载于:https://www.cnblogs.com/qianwang/p/6106324.html

  3. cocos2d-x 音效中断问题

    做跑酷重吃金币播音效时,播放其它音效会使得音效所有中断,最后发现时音效上限的问题,2.2.3默认的似乎是5个音效,改动成50后问题解决. 在java中的org.cocos2dx.lib包下有一个Coc ...

  4. [转]cocos2d-x

    Cocos2d-x 是一个支持多平台的 2D 手机游戏引擎,使用 C++ 开发,基于OpenGL ES,基于Cocos2d-iphone,支持 WOPhone, iOS 4.1, Android 2. ...

  5. 怎样用cocos2d-x做一个基于地图块的游戏(Part One)

    怎样用cocos2d-X做一个基于地图块的游戏 (Part One) 在这个分为上下两部分的教程中,我们将介绍如何使用Cocos2D-X和地图编辑器做一款基于地图块的游戏.在这个简单的地图块游戏里,一 ...

  6. 解决cocos2dx 3.x 导入cocostudio的ui界面出现错位问题

    笔者今天发现导入cocostudio的ui界面时,会有部分控件出现错位的现象,后来我看了一下源码,发现是部分控件是没有继承 Layout类,导致不能设置控件位置造成,原因可以看看cocos2dx 源码 ...

  7. 如何将cocos2d-x程序分别移植到ios,android,windowsphone三个手机平台上

    作者:方格子 链接:https://www.zhihu.com/question/21505500/answer/22152464 来源:知乎 著作权归作者所有.商业转载请联系作者获得授权,非商业转载 ...

  8. Adobe源码泄漏?3行代码搞定,Flash动画无缝导入Android/iOS/cocos2dx(二)

    [注] iOS代码已重构,效率提升90%,200层动画不卡.[2016.10.27] 上一篇 点此阅读 简要介绍了FlashToAnimation的功能,也就是将flash动画无缝导入到Android ...

  9. Adobe源码泄漏?3行代码搞定,Flash动画无缝导入Android/iOS/cocos2dx(一)

    [注] iOS代码已重构,效率提升90%,200层动画不卡.[2016.10.27] 项目介绍 项目名称:FlashAnimationToMobile 源码. 使用方法点这里. 这是一个把flash中 ...

最新文章

  1. python基础代码库-python基础:一个非常简单且详细的多线程代码
  2. XML在JAVA项目中的作用
  3. 链路层 ---《TCP/IP协议》卷一
  4. 二:Go编程语言规范-类型
  5. html三张图片的轮播代码_vue写了个轮播图
  6. Python学习中出现的一些问题
  7. 大一计算机应用的实验报告,大一《计算机应用基础》实验报告1.doc
  8. iOS 11 适配集锦
  9. 使用kafka消息队列中间件实现跨进程,跨服务器的高并发消息通讯
  10. 使用PInvoke.NET插件为托管代码添加Win32 API签名
  11. bmi055六轴传感器获取数据
  12. 我的第一篇博客——开篇
  13. 【CVPR 2021】Unsupervised Multi-Source Domain Adaptation for Person Re-Identification (UMSDA)
  14. vue+js练手前端项目->游戏平台(贪吃蛇、俄罗斯方块、飞机大战、飞翔的小鸟、2048、五子棋)
  15. 【Mysql系列】如何实现王者荣耀排名
  16. 关灯后灯常亮、微亮、闪烁——多种原因分析
  17. 学习笔记5--高精地图技术
  18. 1998ieee圆周率c语言,华人留学生开发首个古汉语编程语言,实现易经算命、圆周率计算,Github获赞14.7k...
  19. 使用CDS view进行S4HANA的OData开发
  20. Angular4 Angular HttpClient

热门文章

  1. CYQ.DBImport 数据库反向工程及批量导数据库工具 V1.0 发布
  2. 纯js制作的弹球游戏
  3. 十九、Android Activity初探
  4. IE6下绝对定位的DIV被相对定位的DIV挡住的问题
  5. 10款无需编程的App DIY开发工具
  6. 动态性能视图v$lock访问很慢的解决办法
  7. 用!important解决IE和Mozilla的布局差别(转)
  8. MySQL 如何创建索引?怎么优化?
  9. 徐科:做IC不外乎PPA,但需要成百上千的专家合作 投入数千万
  10. System V IPC