在上篇文章中,我给大家介绍了如何在cocos2d-x里面绘制一个三角形,当时我们使用的是cocos2d-x引擎自带的shader和一些辅助函数。在本文中,我将演示一下如何编写自己的shader,同时,我们还会介绍VBO(顶点缓冲区对象)和VAO(顶点数组对象)的基本用法。
在编写自己的shader之前,我觉得有必要提一下OpenGL渲染管线。 理解OpenGL渲染管线,对于学习OpenGL非常重要。下面是OpenGL渲染管线的示意图:(图中淡蓝色区域是可以编程的阶段)
此图是从wiki中拿过来的,OpenGL的渲染管线主要包括:
-
准备顶点数据(通过VBO、VAO和Vertex attribute来传递数据给OpenGL)
-
顶点处理(这里主要由Vertex Shader来完成,从上图中可以看出,它还包括可选的Tessellation和Geometry shader阶段)
-
顶点后处理(主要包括Clipping,顶点坐标归一化和viewport变换)
-
Primitive组装(比如3点组装成一个3角形)
-
光栅化成一个个像素
-
使用Fragment shader来处理这些像素
-
采样处理(主要包括Scissor Test,Depth Test,Blending,Stencil Test等)
更详细的信息可以参考本网站推荐的阅读材料和Wiki。
编写你的第一个Vertex Shader
首先是创建一个文件,把它命名为myVertextShader.vert,并输入下列代码:
1 2 3 4 5 6 7 8 9 10 |
attribute vec4 a_position; a_color; varying v_fragmentColor; void main() { gl_Position = CC_MVPMatrix * a_position; v_fragmentColor = a_color; } |
gl_FragColor = v_fragmentColor; } |
@H_404_164@
//create my own program auto program = new GLProgram; program->initWithFilenames("myVertextShader.vert", "myFragmentShader.frag"); link(); //set uniform locations updateUniforms(); |
@H_404_164@
//创建和绑定vao glGenVertexArrays(1, &vao;); glBindVertexArray(vao); //创建和绑定vbo glGenBuffers(vertexVBO;); glBindBuffer(GL_ARRAY_BUFFER, vertexVBO); size = Director::getInstance()->getVisibleSize(); float vertercies[] = { 0,//第一个点的坐标 size.width, //第二个点的坐标 width / 2,210)!important">height}; //第三个点的坐标 color[] = { 1}; glBufferData(sizeof(vertercies),210)!important">vertercies,210)!important">GL_STATIC_DRAW); //获取vertex attribute "a_position"的入口点 GLuint positionLocation = glGetAttribLocation(getProgram(),152)!important">"a_position"); //打开入a_position入口点 glEnableVertexAttribArray(positionLocation); //传递顶点数据给a_position,注意最后一个参数是数组的偏移了。 glVertexAttribPointer(positionLocation,210)!important">GL_FLOAT,210)!important">GL_FALSE, (GLvoid*)0); //set for color colorVBO;); colorVBO); color),210)!important">color,210)!important">GL_STATIC_DRAW); colorLocation = "a_color"); colorLocation); colorLocation,152)!important">4,117)!important">//for safty glBindVertexArray(0); 0); |
@H_404_164@
"a_position"); positionLocation); |
@H_404_164@
glProgram = getGLProgram(); glProgram->use(); //set uniform values,the order of the line is very important setUniformsForBuiltins(); getWinSize(); //use vao,因为vao记录了每一个顶点属性和缓冲区的状态,所以只需要绑定就可以使用了 vao); glDrawArrays(GL_TRIANGLES,152)!important">3); 0); CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(3); CHECK_GL_ERROR_DEBUG(); |
@H_404_164@