(转)cocos2dx 3.x ccPositionTextureColor_vert与ccPositionTextureColor_noMVP_vert
来源:互联网 发布:前端ajax请求php文件 编辑:程序博客网 时间:2024/05/23 00:07
引用http://www.cnblogs.com/wantnon/p/4190341.html
在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
- Cocos2dx 学习随笔(一) Cocos2dx 3.x 读取plist文件 ValueVector 与 ValueMap的使用
- cocos2dx 2.x与cocos2dx 3.x类库用法对比
- cocos2dx 3.x关于json数据的解析(转)
- cocos2dx-3.x(二)、坐标系
- cocos2dx 3.x学习笔记(一)
- 认识 Cocos2dx 3.x
- cocos2dx 3.x api
- 【cocos2dx 3.x】画线
- 【cocos2dx 3.x】CCSpriteBatchNode
- cocos2dx-3.x Note
- cocos2dx 3.x 自学笔记 <二> cocos2dx 中注册触摸事件touchEvent 2.x 与 3.x
- cocos2dx 3.X 中 json 文件生成与读取
- cocos2dx 3.x lua环境配置与代码调试
- cocos2dx 2.x到cocos2dx 3.x的一些改变
- cocos2dx 3.x 相机机制
- cocos2dx 3.x 异步加载
- cocos2dx 3.x 读取csv
- phtoshop切图的几种方式
- 简析TCP的三次握手与四次分手
- 牛客网 剑指Offer,一些值得记住的小题(一)
- Java 杂
- 20170305MFC02_滚动条&数值控制&进度条
- (转)cocos2dx 3.x ccPositionTextureColor_vert与ccPositionTextureColor_noMVP_vert
- static的用法
- 关于运行期异常:Failed to instantiate [java.util.List]: Specified class is an interface
- 微信红包>200发放
- Vue之props属性
- zybo板运行linux系统过程中的问题整理
- jQuery中map()方法
- 动态规划入门
- 为你的博文构建目录