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矩阵。
cocos2dx 3.x ccPositionTextureColor_vert与ccPositionTextureColor_noMVP_vert的更多相关文章
- [cocos2dx]2.2到3.1(3.0)升级帮助
摘要: cocos2dx 是一款优秀的多平台,专为2D游戏设计的引擎. 在活跃的开源社区的推进下, 越发稳定和强大. 2.x -> 3.x的更新幅度很大, 性能的提升和功能的丰富也非常明显. 但 ...
- cocos2dx spine之二 :spine变色
cocos2dx版本为3.10 1.具体原理和代码可以参考博文<利用shader改变图片色相Hue>,下面的代码根据该博文进行整理优化. 基本原理就是将RGB值转换为HSL值后加上输入的H ...
- cocos2dx shader实现灰度图android后台切换回来导致图像偏移的问题
转自:http://www.tuicool.com/articles/U3URRrI 项目中经常会遇到将一张图像处理成灰色的需求,为了节省资源,一般不会让美术再做一套同样的灰度图,通常会通过代码处理让 ...
- 通过cocos2d-x的CCGLProgram和CCShaderCache的实现来分析OpenGL ES中的Shader编程
在OpenGL ES中,Shader是着色器,包括两种:顶点着色器(Vertex Shader)和片元着色器(Fragment Shader).每个program对象有且仅有一个Vertex Shad ...
- Cocos2d-x shader学习1: 灰度shader
灰度shader 最近在学习shader,就把cocos2d-x 3.x版本中的很简单也很常用的灰度shader拿出来学习一下. #ifdef GL_ES precision mediump floa ...
- cocos2dx - shader实现任意动画的残影效果
本节主要讲利用cocos2dx机制实现opengl es shader脚本的绘制 这里先看下最终效果: 这里分别实现了灰度效果及残影的效果. 一.绘制基类 这 ...
- 基于Cocos2d-x学习OpenGL ES 2.0系列——OpenGL ES渲染之Shader准备(7)
Cocos2d-x底层图形绘制是使用OpenGL ES协议的.OpenGL ES是什么呢? OpenGL ES(OpenGl for Embedded System)是OpenGL三维图形API的子集 ...
- cocos2dx调用浏览器打开网址
安卓端cocos2dx/platform/android路径下CCApplication.h: virtual void openURL(const char* pszUrl); CCApplicat ...
- 使用“Cocos引擎”创建的cpp工程如何在VS中调试Cocos2d-x源码
前段时间Cocos2d-x更新了一个Cocos引擎,这是一个集合源码,IDE,Studio这一家老小的整合包,我们可以使用这个Cocos引擎来创建我们的项目. 在Cocos2d-x被整合到Cocos引 ...
随机推荐
- java 读取本地的json文件
首先,要先去下载相关的jar包,否则你是无法做到的. 在百度或者谷歌里面输入java json jar包下载就行了(共7个包). xom-1.1.jar ezmorph-1.0.6.jar json ...
- MySQL监控、性能分析——工具篇
https://blog.csdn.net/leamonjxl/article/details/6431444 MySQL越来越被更多企业接受,随着企业发展,MySQL存储数据日益膨胀,MySQL的性 ...
- mac 连接windows 共享内容
mac 连接windows 共享内容 一:场景 在win7上下载了一个5G左右的系统文件,想弄到mac上,本打算用使用U盘,把文件从win7copy到mac电脑上: 可是U盘的分区是fat的,大于4G ...
- HDU 4620 Fruit Ninja Extreme 暴搜
题目大意:题目就是描述的水果忍者. N表示以下共有 N种切水果的方式. M表示有M个水果需要你切. W表示两次连续连击之间最大的间隔时间. 然后下N行描述的是 N种切发 第一个数字C表示这种切法可以切 ...
- 总结js(1)
已经一个月没敲代码了,工作难找,挺烦. 先总结一下javascript吧. 1.js概述 2.语法结构 3.类型.值和变量 4.表达式和运算符 5.语句 6.对象 7.数组 8.函数 9.类和模块 1 ...
- gradle 项目转成maven项目
找到一个个子项目目录下的build.gradle文件,在文件开头添加以下内容: apply plugin: 'java' apply plugin: 'maven' compileJava.optio ...
- 算法笔记_191:历届试题 大臣的旅费(Java)
目录 1 问题描述 2 解决方案 1 问题描述 问题描述 很久以前,T王国空前繁荣.为了更好地管理国家,王国修建了大量的快速路,用于连接首都和王国内的各大城市. 为节省经费,T国的大臣们经过思考, ...
- spring boot 环境搭建
1.开发工具 https://spring.io/tools/sts/all 2.demo https://start.spring.io 3.下载maven https://maven.apache ...
- java 多态的好处
/* 对象的多态性. class 动物{} class 猫 extends 动物{} class 狗 extends 动物{} 猫 x = new 猫(); 动物 x = new 猫();//一个对象 ...
- LoadRunner如何监控Linux系统资源
LoadRunner如何监控Linux系统资源 一 简述:LoadRunner监控Linux资源时弹出如下错误: Monitor name :UNIX Resources. Cannot initia ...