glsl 與固管並存的 早期OpenGL

2021-07-27 01:14:02 字數 4559 閱讀 8555

glsl的hello world

這一節中包含乙個最基本的shader,它提供如下功能:頂點變換然後使用單一的顏色渲染圖元。

頂點shader

前面已經說過,頂點shader負責完成頂點變換。這裡將按照固定功能的方程完成頂點變換。

固定功能流水線中乙個頂點通過模型檢視矩陣以及投影矩陣進行變換,使用如下公式:

[cpp]view plain

copy

vtrans = projection * modelview *incomingvertex  

首先glsl需要訪問opengl狀態,獲得公式中的前兩個矩陣。前面講過,glsl可以獲取某些opengl狀態資訊的,這兩個矩陣當然包括在內。可以通過預先定義的一致變數來獲取它們:

[cpp]view plain

copy

uniform mat4 gl_modelviewmatrix;  

uniform mat4 gl_projectionmatrix;  

接下來需要得到輸入的頂點。通過預先定義的屬性變數,所有的頂點將可以乙個個傳入頂點shader中。

[cpp]view plain

copy

attribute vec4 gl_vertex;  

為了輸出變換後的頂點,shader必須寫入預先定義的vec4型變數gl_position中,注意這個變數沒有修飾符。

現在我們可以寫乙個僅僅進行頂點變換的頂點shader了。注意所有其他功能都將喪失,比如沒有光照計算。頂點shader必須有乙個main函式,如下面的**所示:

[cpp]view plain

copy

void

main()    

上面**中變換每個頂點時,投影矩陣都將乘上模型檢視矩陣,這顯然非常浪費時間,因為這些矩陣不是隨每個頂點變化的。注意這些矩陣是一致變數

glsl提供一些派生的矩陣,也就是說gl_modelviewprojectionmatrix是上面兩個矩陣的乘積,所以頂點shader也可以寫成下面這樣:

[cpp]view plain

copy

void

main()    

上面的操作能夠獲得和固定功能流水線相同的結果嗎?理論上是如此,但實際上對頂點變換操作的順序可能會不同。頂點變換通常在顯示卡中是高度優化的任務,所以有乙個利用了這種優化的特定函式用來處理這個任務。這個神奇的函式如下:

[cpp]view plain

copy

vec4 ftransform(

void

);  

使用這個函式的另乙個原因是float資料型別的精度限制。由於資料精度的限制,當使用不同的順序計算時,可能得到不同的結果,因此glsl提供這個函式保證獲得最佳效能的同時,還能得到與固定功能流水線相同的結果。

這個函式按照與固定功能相同的步驟對輸入頂點進行變換,然後返回變換後的頂點。所以shader可以重新寫成如下形式:

[cpp]view plain

copy

void

main()    

片斷shader

片斷shader也有預先定義的變數gl_fragcolor,可以向其中寫入片斷的顏色值。下面的**就是乙個片斷shader,將所有片斷繪製成淡藍色:

[cpp]view plain

copy

void

main()    

可以在此獲得本節例子的原始碼:

顏色shader

glsl可以讀取一些opengl狀態,在本節我們將學習如何訪問在opengl中設定的glcolor變數。

glsl有乙個屬性變數記錄當前顏色,也提供易變變數從頂點shader向片斷shader傳遞顏色值。

[cpp]view plain

copy

attribute vec4 gl_color;  

varying vec4 gl_frontcolor; // writable onthe vertex shader

varying vec4 gl_backcolor; // writable onthe vertex shader

varying vec4 gl_color; // readable on thefragment shader

變數使用思想如下:

1、opengl程式通過glcolor傳送顏色資訊。

2、頂點shader通過屬性gl_color接收顏色值。

3、頂點shader計算正面和反面的顏色,然後分別儲存在gl_frontcolor和gl_backcolor中。

4、片斷shader接收易變變數gl_color中儲存的插值產生的顏色,由當前圖元的方向決定顏色是gl_frontcolor還是gl_backcolor插值產生的。

5、片斷shader根據易變變數gl_color設定gl_fragcolor。

前 面說過頂點shader和片斷shader中傳遞的易變變數要有相同的名字,但這裡是個例外,頂點shader中的gl_frontcolor和 gl_backcolor會根據圖元的方向,自動轉變為片斷shader中的gl_color。還要注意屬性變數gl_color和易變變數 gl_color沒有衝突,因為前者只存在於頂點shader,後者只存在於片斷shader。

下面是頂點shader的例子,只計算了正面顏色:

[cpp]view plain

copy

void

main()    

片斷shader更加簡單:

[cpp]view plain

copy

void

main()    

基於glew的源**:

扁平shader(flatten shader)

著色器程式設計讓我們可以探索一些新效果,本節的例子展示了用奇怪的方法操作頂點得到的效果。

首先我們要得到乙個扁平的3d模型,只需要在應用模型檢視變換時將模型頂點的z座標設為0就行了。下面是頂點shader的**:

[cpp]view plain

copy

void

main(

void

)    

我們先將gl_vertex變數複製到乙個區域性變數v中。gl_vertex是乙個glsl提供的屬性變數,所以在頂點shader中它是唯讀的。

片斷shader與「glsl中的hello world」一節相同,就只用設定一種顏色。

乙個扁平的茶壺效果如下:

更進一步,我們需要在z座標上使用乙個正弦函式。將z座標作為x座標的函式,這樣茶杯將呈現波浪的效果:

[cpp]view plain

copy

void

main(

void

)    

最後我們需要加入一些頂點動畫效果。為了達到這個目的我們需要增加乙個變數記錄變化的時間,或者幀數。乙個頂點shader是無法記錄不同頂點值的,更不用 說記錄不同的幀了。所以我們需要在opengl程式中定義這個變數,然後作為一致變數傳遞給shader。假設在opengl程式中有乙個名為time的 幀計數器,在shader中有個同名的一致變數。

頂點shader的**如下:

[cpp]view plain

copy

uniform 

float

time;  

void

main(

void

)    

在有關一致變數的小節講過,在opengl程式中需要兩個步驟:

·setup: 獲取一致變數的儲存位置

·render: 更新一致變數

設定(setup)步驟只有一條語句:

[cpp]view plain

copy

loc =glgetuniformlocation(p,

"time"

);  

這裡p是程式的控制代碼,time與頂點shader中定義的一致變數名稱相同。變數loc是glint型別的,必須定義在下面的渲染(render)函式也可以訪問到的地方。渲染函式如下所示:

[cpp]view plain

copy

void

renderscene(

void

)    

函式中的變數time在程式一開始初始化,然後每幀都會進行自增運算。

本節的glew源**:

GROUP CONCAT與LIMIT並存的技巧

我於去年12月初在論壇求教了高手後知道了答案,這個是在培訓中學不到的,呵呵。在使用了group concat後,如果不使用group by,會將所有的資料合併在一起,並且limit是沒有任何效果的。當時我的需求很簡單 我有一萬條文章資料要進行替換,我想每次替換一百條。當然,也有朋友說可以在mysql...

早繫結的問題與動態繫結

物件可以作為自己的類或者作為它的基類 父類 的物件來使用。還能通過基類的位址來操作它。取乙個物件的位址 指標或引用 並將其作為基類的位址來處理,稱為向上型別轉換。也就是說,父類引用或指標可以指向子類物件,通過父類指標或引用操作子類物件。class human class dog public hum...

C 中的委託與事件並存的理由

問題 有了委託為什麼還要有事件?理論上,事件能完成的事情委託完全可以勝任,但是我們思考的這一方面是功能性,我們必須從他們各自的特點分析。委託鏈的特點讓事件能夠被多個訂閱方訂閱,事件是帶上了event關鍵字的委託,在用reflector反編譯事件原始碼時,我 們看到事件成員的可訪問性被始終設定為pri...