shader可以让我自由的实现新的效果,这个例子显示了通过shader程序以一种奇特的方式处理顶点。
首先,我们在模型视图变换前把z坐标设置为0来把3d模型压扁。顶点shader为:
void main(void) { vec4 v = vec4(gl_Vertex); v.z = 0.0; gl_Position = gl_ModelViewProjectionMatrix * v; }
首先把gl_vertex赋给一个局部变量,gl_vertex是GLSL提供的一个属性变量,因此他在顶点shader是只读的,因此需要通过把他赋给一个局部变量v来修改(应用程序)输入的顶点值。
片元shader只是用来设置颜色,因此可以像像前面提到的helloworld里面的一样。
这里在顶点程序里把z值设为0,把它应用到一个茶壶模型时候,得到的结果可能如下图
void main(void) { vec4 v = vec4(gl_Vertex); v.z = sin(5.0*v.x )*0.25; gl_Position = gl_ModelViewProjectionMatrix * v; }
好了,下面我们准备加一些顶点动画,首先我们需要一个变量来跟踪当前的时间,顶点程序做不了这些,因此我们需要在opengl应用程序里定义这个变量,并通过uniform变量传给顶点shader。假设在应用程序里有一个时间变量,而在顶点shader里有一个相同名字的uniform变量,那么顶点shader变成这样:
uniform float time; void main(void) { vec4 v = vec4(gl_Vertex); v.z = sin(5.0*v.x + time*0.01)*0.25; gl_Position = gl_ModelViewProjectionMatrix * v; }
正如上面提到的属性变量,应用程序段有两个步骤:
建立:获取属性变量的位置
渲染:更新属性变量
建立阶段:loc = glGetUniformLocationARB(p,"time");
这里p是顶点shader的句柄,time是uniform变量,loc是GLint类型,应定义在某个渲染阶段可以访问到的位置。
渲染函数可能会像这样:
void renderScene(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); gluLookAt(0.0,0.0,5.0, 0.0,0.0,0.0, 0.0f,1.0f,0.0f); glUniform1fARB(loc, time); glutSolidTeapot(1); time+=0.01; glutSwapBuffers(); }
这里time变量在初始化的时候给予的初值,每一帧进行更新。
工程的代码可以在这里下载flatten