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,把它應用到一個茶壺模型時候,得到的結果可能如
那再讓我試一下別的效果,把z的計算進項如下計算,結果可能如下
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