在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]2.2到3.1(3.0)升级帮助

    摘要: cocos2dx 是一款优秀的多平台,专为2D游戏设计的引擎. 在活跃的开源社区的推进下, 越发稳定和强大. 2.x -> 3.x的更新幅度很大, 性能的提升和功能的丰富也非常明显. 但 ...

  2. cocos2dx spine之二 :spine变色

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

  3. cocos2dx shader实现灰度图android后台切换回来导致图像偏移的问题

    转自:http://www.tuicool.com/articles/U3URRrI 项目中经常会遇到将一张图像处理成灰色的需求,为了节省资源,一般不会让美术再做一套同样的灰度图,通常会通过代码处理让 ...

  4. 通过cocos2d-x的CCGLProgram和CCShaderCache的实现来分析OpenGL ES中的Shader编程

    在OpenGL ES中,Shader是着色器,包括两种:顶点着色器(Vertex Shader)和片元着色器(Fragment Shader).每个program对象有且仅有一个Vertex Shad ...

  5. Cocos2d-x shader学习1: 灰度shader

    灰度shader 最近在学习shader,就把cocos2d-x 3.x版本中的很简单也很常用的灰度shader拿出来学习一下. #ifdef GL_ES precision mediump floa ...

  6. cocos2dx - shader实现任意动画的残影效果

    本节主要讲利用cocos2dx机制实现opengl es shader脚本的绘制 这里先看下最终效果:                      这里分别实现了灰度效果及残影的效果. 一.绘制基类 这 ...

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

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

  8. cocos2dx调用浏览器打开网址

    安卓端cocos2dx/platform/android路径下CCApplication.h: virtual void openURL(const char* pszUrl); CCApplicat ...

  9. 使用“Cocos引擎”创建的cpp工程如何在VS中调试Cocos2d-x源码

    前段时间Cocos2d-x更新了一个Cocos引擎,这是一个集合源码,IDE,Studio这一家老小的整合包,我们可以使用这个Cocos引擎来创建我们的项目. 在Cocos2d-x被整合到Cocos引 ...

随机推荐

  1. idea中dependencies中总是有红色波浪线(缺少dependency)的解决办法

    使用IDEA进行maven开发时,将新项目import进工作空间时,Maven Projects栏中的dependencies中总是有红色波浪线,如下图: 但是这些jar在我本地的maven仓库中实际 ...

  2. Shader Object及Program操作API

    Shader Object及Program操作API Program:  1. GLuint glCreateProgram( void );//创建 2. void glDeleteProgram( ...

  3. poj 2391 (Floyd+最大流+二分)

    题意:有n块草地,一些奶牛在草地上吃草,草地间有m条路,一些草地上有避雨点,每个避雨点能容纳的奶牛是有限的,给出通过每条路的时间,问最少需要多少时间能让所有奶牛进入一个避雨点. 两个避雨点间可以相互到 ...

  4. 在 Java SE 6 中监视和诊断性能问题

    Java™ Platform, Standard Edition 6 (Java SE) 专注于提升性能,提供的增强工具可以管理和监视应用程序以及诊断常见的问题.本文将介绍 Java SE 平台中监视 ...

  5. Stage3d AGAL GPU处理照片 旧照片效果 sepia || pixelbender

    如果看不到下边的flash,请更新flash player到最新版本. 利用AGAL实现旧照片效果,大家可以对照一下之前一篇文章,关于图像处理(pixelbender).硬件处理肯定会更快,但这里无法 ...

  6. ibatis 批量更新(一)

      1.4.2.3 批量修改 支持单个动态更新.批量动态更新 <update id="updateCONSULT_SCHEDULEDynamic" parameterClas ...

  7. python之函数用法isinstance()

    # -*- coding: utf-8 -*- #python 27 #xiaodeng #python之函数用法isinstance() #isinstance() #说明:返回一个布尔值,判断数据 ...

  8. HeidiSQL数据库mysql/sql-server连接工具

    HeidiSQL,是一款可以显示表在存储中占得空间,体积小的mysql.sql-server连接工具! 下载地址: https://www.heidisql.com/download.php 中文版: ...

  9. hihoCoder 1014 Trie树 (Trie)

    #1014 : Trie树 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描写叙述 小Hi和小Ho是一对好朋友.出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮 ...

  10. HDUOJ----(2612)Find a way

    Find a way Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...