近期在准备新的书稿,涉及到了着色器的基础部分,所以在此特地记录一个简单案例的实现——类似水纹效果。
准备工作:1>用3DMax做一个多顶点的长方体,需要更改顶点数。(长度分段及宽度分段等)
2>随便找一张纹理图。
由于cocos2d-x底层是封装的OpenGL ES,所以如果有基础的话,只需要将OpenGL ES的套路在cocos2d-x中套即可,只是将变量名换了一下而已。
下面简要概述一下着色器语言的开发流程以及注意事项,尤其是第一次写着色器时踩过的坑,需要特别注意了。
(1)创建精灵,并绑定着色器,具体代码如下所示。
auto breast = Sprite3D::create("breast.obj","pic.png"); auto shader_l = GLProgram::createWithFilenames("b_vert.vert","b_frag.frag"); state_l = GLProgramState::create(shader_l); state_l->setUniformFloat("uStartAngle",0.1);<span style="white-space:pre"> </span> //传开始的角度给顶点着色器 state_l->setUniformFloat("uWidthSpan",20.0); //将宽度传给顶点着色器 breast->setGLProgramState(state_l); long offest_l = 0; auto attributeCount_l = breast->getMesh()->getMeshVertexAttribCount(); //获得网格包含顶点数量 for(auto i = 0; i< attributeCount_l; i++) <span style="font-family: Arial,Helvetica,sans-serif;">//循环获得顶点的属性</span> { auto meshAttribute_l = breast->getMesh()->getMeshVertexAttribute(i); state_l->setVertexAttribPointer( s_attributeNames[meshAttribute_l.vertexAttrib],//顶点属性的名字 meshAttribute_l.size,//每个顶点中需要更新的元素个数 meshAttribute_l.type,//表示数组中每个元素的数据类型 GL_FALSE,//顶点数据是否在传递之前归一化 breast->getMesh()->getVertexSizeInBytes(),//两个连续元素之间的偏移字节数 (void*)offest_l //偏移量 ); offest_l += meshAttribute_l.attribSizeBytes; }(2)然后就是定时回调update方法改变起始角度即可。具体代码如下。
void My3DLayer::update(float delta) { offest_l += 0.15; state_l->setUniformFloat("uStartAngle",offest_l); state_l->setUniformFloat("uWidthSpan",20.0); }(3)下面先介绍一下顶点着色器的写法以及注意事项,先贴出代码,如下。
attribute vec3 a_position; attribute vec2 a_texCoord; uniform float uStartAngle; uniform float uWidthSpan; varying vec2 v_textureCoord; void main() { float angleSpan = 4.0 * 3.1415926; float startX = -uWidthSpan / 2.0; float currentAngle = uStartAngle + ((a_position.x - startX)/uWidthSpan) * angleSpan; float ty = sin(currentAngle) * 3.0; gl_Position = CC_MVPMatrix * vec4(a_position.x,ty,a_position.z,1); v_textureCoord = a_texCoord; v_textureCoord.y = (1.0 - a_texCoord.y);<span style="white-space:pre"> </span>//纹理取点的y坐标置反,(使用OpenGL ES的取纹理方式) }注:由于cocos2d-x引擎内部封装了一些OpenGL ES的一些内建变量并隐藏的声明了一些变量,需要特别注意,在后面需要将这些变量总体列出来,以备以后查阅。
(4)顶点着色器将顶点纹理图的坐标传递给片元着色器,片元着色器负责更改颜色,由于此案例比较基础,并未实现真正的水纹效果,后期再进行更改。具体代码如下。
precision mediump float; varying vec2 v_textureCoord; void main() { gl_FragColor = texture2D(CC_Texture0,v_textureCoord); //texture2D为OpenGL ES内部的方法 }(5)大体框架就是这样,下面列一下暂时用到的cocos2d-x引擎给提供的内建变量,如果后期用到更多的变量,在进行添加。具体图示如下。
a_position : 为顶点在节点坐标系的位置
a_texCoord : 为纹理坐标
a_normal : 为法线方向
CC_PMatrix : 为投影矩阵(P为projection)
CC_MVPMatrix : 为变换总矩阵
CC_NormalMatrix : 为法线矩阵
CC_Texture0 : 为第一个纹理图
基本变换矩阵:sprite->getNodeToWorldTransform()
最后贴一个波涛汹涌的效果图。。。
至此,结束。