Cocos2d-x 着色器

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wlk1229/article/details/84109234

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实际上是视图投影矩阵,也就是VPMatrixCC_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、IndexBufferVertexData三者的结构如下:

 

顶点属性

对于着色器程序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”。

 

猜你喜欢

转载自blog.csdn.net/wlk1229/article/details/84109234
今日推荐