cocos2dx 3.x ccPositionTextureColor_vert与ccPositionTextureColor_noMVP_vert

在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矩阵。

时间: 2024-12-21 23:28:28

cocos2dx 3.x ccPositionTextureColor_vert与ccPositionTextureColor_noMVP_vert的相关文章

[cocos2dx]2.2到3.1(3.0)升级帮助

摘要: cocos2dx 是一款优秀的多平台,专为2D游戏设计的引擎. 在活跃的开源社区的推进下, 越发稳定和强大. 2.x -> 3.x的更新幅度很大, 性能的提升和功能的丰富也非常明显. 但在享受进步的同时,也要承受迁徙之苦. 本文主要是总结自己迁徙的经历, 以防大家走弯路. 博客: http://www.cnblogs.com/jhzhu 邮箱: [email protected] 作者: 知明所以 时间: 2014-06-22 基础准备 进入正题 语法更新 obj-c式命名 ==> c

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

Cocos2d-x底层图形绘制是使用OpenGL ES协议的.OpenGL ES是什么呢? OpenGL ES(OpenGl for Embedded System)是OpenGL三维图形API的子集,针对手机.Pad和游戏主机等嵌入式设备而设计.该API由Khronos集团定义推广,Khronos是一个图形软硬件行业协会,该协会主要关注图形和多媒体方面的开放标准.OpenGL ES是OpenGL三维图形API的子集,针对手机.Pad和游戏主机等嵌入式设备而设计.Cocos2d-x底层图形渲染使

用cocos2d-x 实现UV动画--实现篇

用cocos2d-x 实现UV动画--实现篇 UVSprite uv动画是指通过在程序运行时动态改变纹理坐标,实现动态效果的纹理动画,使用uv动画可以实现水流动,火焰燃烧等效果. 本文由liangneo原创,转载请保留原文地址 :http://blog.csdn.net/liangneo/article/details/42583533 1.分析 我们需要的是一个具uv动画的sprite,最简单合理的方式是让你UVSprite直接继承于CCSprite,另外我们还需要两个变量来控制U或V方面是否

cocos2d-x 精灵添加描边效果

学习cocos2d-x 以来一直对里面的shader部分感兴趣,今天正好花了点时间来研究一下精灵的描边效果. 主要参考了子龙山人大神的TestCpp里面例子并结合自己的理解,实现相对比较简单.主要是根据引擎内部自带的shader相关代码来实现的. 好了废话不多说看代码: 1.首先需要打开CCShaderCache.cpp文件修改里面部分代码,添加我们描边的效果. 在此枚举值里面加入:kShaderType_LabelOutline 2.然后在 voidShaderCache::loadDefau

cocos2dx spine之二 :spine变色

cocos2dx版本为3.10 1.具体原理和代码可以参考博文<利用shader改变图片色相Hue>,下面的代码根据该博文进行整理优化. 基本原理就是将RGB值转换为HSL值后加上输入的HSL值,再转换为RGB值. 2.spine变色的思路有三种: ①spine::SkeletonAnimation调用shader ②读取spine对应的atlas文件,分析该文件得到所需的png图片,将该图片读入内存,修改内存中像素颜色,然后生成texture赋值给spine中的spAtlas->pag

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

转自:http://www.tuicool.com/articles/U3URRrI 项目中经常会遇到将一张图像处理成灰色的需求,为了节省资源,一般不会让美术再做一套同样的灰度图,通常会通过代码处理让图片变灰.网上也有很多用shader处理图片变灰的方法,这些方法确实也实现了让图片变灰的需求,但是android平台从后台切换回来的时候,shader被释放,导致图片位置错乱.关键在于从android后台切换回来的时候需要重新加载shader.我们看一下cocos2dx原生的shader处理方式,我

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

本节主要讲利用cocos2dx机制实现opengl es shader脚本的绘制 这里先看下最终效果:                      这里分别实现了灰度效果及残影的效果. 一.绘制基类 这里主要参考了cocos2dx源码中 RenderTexture 的实现,有兴趣的可以了解下. 绘制基类RenderShader主要实现以下方法: //****************************************************************** // 文件名:

Cocos2dx引擎11-OpenGLES渲染之Shader准备

Cocos2dx底层图形绘制是使用OpenGL ES协议的.OpenGL ES是什么呢? OpenGL ES(OpenGl for Embedded System)是OpenGL三维图形API的子集,针对手机,PDA和游戏主机等嵌入式设备而设计.该API有Khronos集团定义推广,Khronos是一个图形软硬件行业协会,该协会主要关注图形和多媒体方面的开放标准. OpenGL ES是从OpenGL剪裁或定制过来了,去除了glBegin/glEnd,四边形(GL_QUADS),多边形(GL_PO

Cocos2d-x山西推倒胡+扣点房卡麻将下载架设教程

1.数据库还原修改后台数据库jeefwtwo 表:sys_user8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92 密码(123456)修改游戏数据库 QPPlatformDB表:DataBaseInfo  SQL的地址端口账号密码表:GameRoomInfo  修改服务器的机器标示 PS,搭建的源码必须完整,本文测试源码来自 Cocos2d-x山西推倒胡+扣点房卡麻将maliwl.com 2.执行脚本每个脚本都要执