Cocos2d-x 着色器
Cocos2d-x 着色器
声明:本文使用的是cocos2d-x-3.17的代码
文章中的提到的测试代码下载地址https://gitee.com/Kyle12/Cocos2dRenderStudy
着色器GLProgram
Cocos2d-x 3中所有的渲染都使用了可编程管线,通过着色器进行渲染。Cocos2d-x底层使用的是OpenGL,对应的着色器语言为GLSL。Cocos2d-x中使用的GLSL语言版本为1.0,应该是为了跨平台,适用更多的设备,所以没有使用高版本。Cocos2d-x只支持顶点着色器和片元着色器,不支持细分着色器、几何着色器、计算着色器。
GLProgram
Cocos2d通过类GLProgram封装了OpenGL中的着色器。
着色器编译
点着色器和片元着色器都是通过函数GLProgram::compileShader编译的,在编译前会在着色器字符串前面加上Cocos2d-x内部定义的Uniform值,内容如下:
static const char * COCOS2D_SHADER_UNIFORMS = "uniform mat4 CC_PMatrix;\n" "uniform mat4 CC_MultiViewPMatrix[4];\n" "uniform mat4 CC_MVMatrix;\n" "uniform mat4 CC_MVPMatrix;\n" "uniform mat4 CC_MultiViewMVPMatrix[4];\n" "uniform mat3 CC_NormalMatrix;\n" "uniform vec4 CC_Time;\n" "uniform vec4 CC_SinTime;\n" "uniform vec4 CC_CosTime;\n" "uniform vec4 CC_Random01;\n" "uniform sampler2D CC_Texture0;\n" "uniform sampler2D CC_Texture1;\n" "uniform sampler2D CC_Texture2;\n" "uniform sampler2D CC_Texture3;\n" "//CC INCLUDES END\n\n"; |
这些Uniform值会在所有的顶点着色器和片源着色器中定义,使用着色器绘制前通过函数GLProgram::setUniformsForBuiltins设置。
这些Uniform值中的矩阵(Matrix)命名,前面的M代表模型变换,V代表视图变换,P代表投影变换。CC_Pmatrix按照正常逻辑应该说投影矩阵,但实际上CC_Pmatrix并不是,CC_Pmatrix实际上是视图投影矩阵,也就是VPMatrix;CC_MVMatrix也不是模型视图矩阵,而是模型矩阵MMatrix。这里是Cocos2d本身命名错误的,自己编写着色器程序时要注意。
着色器链接
着色器通过函数GLProgram::link进行链接,在链接前会通过函数GLProgram::bindPredefinedVertexAttribs设置顶点着色器中顶点属性的location,著通过OpenGL函数glBindAttribLocation设置。设置的顶点属性有:
const char* GLProgram::ATTRIBUTE_NAME_COLOR = "a_color"; const char* GLProgram::ATTRIBUTE_NAME_POSITION = "a_position"; const char* GLProgram::ATTRIBUTE_NAME_TEX_COORD = "a_texCoord"; const char* GLProgram::ATTRIBUTE_NAME_TEX_COORD1 = "a_texCoord1"; const char* GLProgram::ATTRIBUTE_NAME_TEX_COORD2 = "a_texCoord2"; const char* GLProgram::ATTRIBUTE_NAME_TEX_COORD3 = "a_texCoord3"; const char* GLProgram::ATTRIBUTE_NAME_NORMAL = "a_normal"; |
之所以要设置顶点属性的location是因为系统中定义好的着色器其相同的顶点属性location值将相同,方便缓存设置输入。例如顶点位置属性a_position绑定为0,不管哪个系统着色器程序设置缓存顶点位置输入时都使用location=0,不用通过glGetAttribLocation获取location。所以如果要编写一个shader给Cocos2d中的对象使用,那么顶点属性的名字也需要用以上名字。
着色器链接成功后会通过GLProgram::parseVertexAttribs获取程序中使用了的顶点属性,存储在_vertexAttribs中;通过函数GLProgram::parseUniforms获取用户自己定义的Uniform值,存在_userUniforms中。这里不包括编译阶段系统添加的Uniform值,系添加的Uniform值完全由系统自己设置赋值,可以直接在Shader中使用。
GLProgram结构
GLProgramCache
GLProgramCache是一个用来缓存GLProgram的类,防止重复创建,和Director一样是单例模式。
函数GLProgramCache::loadDefaultGLPrograms加载系统中默认创建的着色器程序。
可以以通过函数GLProgramCache::getGLProgram获取已缓存的着色器程序。
GLProgramState
实际使用着色器时并不会直接使用GLProgram,而是使用GLProgramState。GLProgramState主要作用是设置顶点属性和Uniform值,GLProgramState结构如下:
同样为了防止GLProgramState重复创建,类GLProgramStateCache会缓存已创建的GLProgramState。
绘制状态RenderState
绘制的时候会需要设置绘制的状态,如是否开启深度比较,是否使用融合,使用的融合函数等等。这些控制主要通过类RenderState控制,RenderState结构如下:
绘制时如果要使用模板,需要通过类StencilStateManager控制,Cocos2d中的裁剪节点ClippingNode就使用了模板控制裁剪。
顶点缓存和索引缓存
顶点缓存通过类VertexBuffer表示,索引缓存由类IndexBuffer表示。对于顶点缓存来说还会由顶点属性来表示顶点缓存中各个数据的作用。VertexBuffer中并不存储顶点属性,类VertexData就是用来存储顶点缓存与顶点属对应的关系。VertexBuffer、IndexBuffer、VertexData三者的结构如下:
顶点属性
对于着色器程序GLProgram程序会有顶点属性,这个属性由顶点着色器的输入决定。对于顶点缓存也会有顶点属性,这个属性由顶点缓存的结构决定。当需要用着色器绘制某个缓存时,着色器的顶点属性必须要与顶点缓存的顶点属性对应之后才能绘制。
例子
Sprite着色器绘制
通过自己编写的着色器程序来绘制Cocos2d中的Sprite,实现一些特殊的效果。自己编写的着色器程序需要主义以下两点:1、对应顶点着色器的输入顶点的位置名字必须为“a_position”,纹理坐标的位置名字必须为“a_texCoord”,因为编写的程序是要绘制Cocos2d创建的缓存,缓存的顶点属性是固定的,需要通过名字匹配;2、是Sprite绘制使用的是TrianglesCommand,为了合并Draw Call,会提前进行模型变换再绘制,所以只需要用CC_PMatrix(视图投影矩阵)对点进行变换。
以下例子实现Sprite绘制成椭圆,并且给Sprite添加了青色作为底色。
完整代码:SpriteShaderScene.cpp/SpriteShaderScene.h,对于程序菜单“Test GLProgram Shader”->“Sprite Custom Shader”。
完全自定义着色器
Cocos2d中可以重写Node节点,并提供了CustomCommand绘制命令,利用这两点可以很容易用自己的着色器和缓存进行绘制。
以下例子通过着色器绘制了一个砖墙,这里没有用图片纹理,而是完全由着色器完成绘制。
完整代码:CustomShaderScene.cpp/CustomShaderScene.h,对于程序菜单“Test GLProgram Shader”->“Custom Shader”。
Shadertoy
Shadertoy是一个网站,里面由很多分享的shader程序。Shadertoy上的着色器都是偏远着色器,简单修改一下就可以运行在Cocos2d中。
以下火焰的例子就是从shadertoy上的程序,地址为:https://www.shadertoy.com/view/XsXSWS
完整代码: ShaderToyScene.cpp/ShaderToyScene.h,对于程序菜单“Test GLProgram Shader”->“ShaderToy Test”。
Cocos2d-x 着色器相关推荐
- OpenGL ES渲染管线与着色器
转自:http://blog.csdn.net/kesalin/article/details/8223649 [OpenGL ES 02]OpenGL ES渲染管线与着色器 罗朝辉 (http:// ...
- [OpenGL ES 02]OpenGL ES渲染管线与着色器
http://blog.csdn.net/kesalin/article/details/8223649 罗朝辉 (http://blog.csdn.net/kesalin) 本文遵循"署名 ...
- cocos2d-x与着色器设计--入门篇(游云凌天原创)
http://blog.csdn.net/danjinxiangsi/article/details/43949955 着色器(Shader)应用与计算机图形学领域,指一组提供计算机图形资源在渲染时执 ...
- Turing渲染着色器网格技术分析
Turing渲染着色器网格技术分析 图灵体系结构通过使用 网格着色器 引入了一种新的可编程几何着色管道.新的着色器将计算编程模型引入到图形管道中,因为协同使用线程在芯片上直接生成紧凑网格( meshl ...
- Learn OpenGL (三):着色器
GLSL 着色器是使用一种叫GLSL的类C语言写成的.GLSL是为图形计算量身定制的,它包含一些针对向量和矩阵操作的有用特性. 着色器的开头总是要声明版本,接着是输入和输出变量.uniform和mai ...
- Blender着色器纹理材质创作教程含源文件 Shader Forge
本Blender视频课程是一个正在进行的关于为Cycles渲染引擎构建材质(着色器)的系列.只要有足够的时间和努力,物质性就能给CG场景注入这样的生命. 本课程是一个正在进行的关于为Cycles渲染引 ...
- UE4材质着色器全面学习教程
你会学到什么 通过所有着色器类型和设计的实际演示,学习创建材质 要求 对虚幻的基本理解会有所帮助 了解纹理的一般知识(不仅限于UE4)也很有用 描述 在这个系列中,我将带你设置大量不同的材料,教你如何 ...
- 学习编写Unity计算着色器 Learn to Write Unity Compute Shaders
利用图形处理器的力量 你会学到: 如何编写Unity计算着色器 如何在后处理图像过滤器中使用ComputeShaders 如何使用ComputeShaders进行粒子效果和群集 如何使用Structu ...
- 从头开始学习Unity着色器
MP4 |视频:h264,1280×720 |音频:AAC,44.1 KHz,2 Ch 语言:英语+中英文字幕(根据原英文字幕机译更准确)|时长:56节课(4h 26m) |大小解压后:2.89 GB ...
- Unity初学Shadergraph创建着色器学习教程
MP4 |视频:h264,1280×720 |音频:AAC,44.1 KHz,2 Ch 语言:英语+中英文字幕(根据原英文字幕机译更准确) |时长:51节课(4h 44m) |大小解压后:2.55 G ...
最新文章
- 【iCore组合式双核心开发板教程】【快速使用手册】
- linux命令:nslookup 、tar、route , tracert, traceroute, netstat、write、mesg、touch
- JavaScript 私有成员
- Syntax error, parameterized types are only available if source level is 1.5 or greater
- bzoj4589-Hard Nim【FWT】
- Wicket模型的干净方法
- linux删除了mount目录,Linux记录-分区(df/fdisk/mount/umount/fuser)
- codeforces George and Job
- Mysql索引成本计算规则 Optimizer Trace
- 曾经辉煌无限,如今员工持续大量流失,集团目前仅剩10余人
- Windows 2003 Server R2 x64 IIS6.0 eWebEditor无法显示的问题
- AcWing 2. 01背包问题(01背包模板)
- 3. 盒子模型与兼容性
- c语言编写过几天是星期几,计算任何一天是星期几的C语言源代码.
- JSON数据实际应用
- 自动驾驶岗位常见面试笔试题
- Aras Innovator: Catagoy, Itemtype, Item, Relationship的视图
- 单模光纤最大传输距离为多少_单模光纤的最长传输距离是多少?单模光纤和多模光纤的区别在于什么?...
- 文明重启服务器维护中怎么办,【FAQ】文明重启常见问题大全
- 网格顶点法向量从世界坐标到切空间坐标转换:法向贴图高低模烘焙