Shader曆程——資料傳遞

來源:互聯網
上載者:User
“前文再續,書接上一回”。。。。大鬧西遊看多了^_^
作為一個圖形應用程式的一部分,shader定義了這個程式的圖形渲染指令。但要讓系統按照我們的設計去渲染圖形,我們還需要把必要的資料傳遞給shader。shader是由gpu來負責執行的,那麼資料如何能按照我們的要求傳入shader,由gpu來擷取呢?
首先我們來粗略地瞭解一下shader中的資料類型吧。因為處理器不一樣,shader也有一些自己特有的資料類型。
純量資料型別有float, int, bool;
向量資料類型有vec2, vec3, vec4,即2、3、4維向量,其中的分量可以是三種純量資料型別中的任何一種),然後是矩陣,同樣也有2、3、4維;
採樣器資料類型有6種:sampler1D,sampler2D,sampler3D,samplerCube,sampler1DShadow和sampler2DShadow。它們的功能是用於紋理採樣;
此外,還有跟c/c++一樣的“結構體”,“數組”等。
shader中的資料可以分為如何三類:
1. Attribute類型。這一類資料是shader中變化頻率最快的,它由應用程式傳遞到vertex shader,為每一頂點指定,一般是描述頂點的屬性,如座標、顏色、法線等。在opengl中,glVertex, glNormal等指令都會把這類資料傳遞給vertex shader。
2. Uniform類型。這一資料的變化頻率相對比較低,一般來說全域的渲染屬性就屬於這一類資料,如光源的參數、視點的位置等,它們對於所有頂點來說都是一樣的。
3. Varying類型。這種類型用於從vertex shader往pixel shader傳遞資料,vertex shader的計算結果通過它們流入到pixel shader環節。
此外,GLSL還有一些內建的uniform和常量類型資料,它們以gl_打頭,如uniform mat4 gl_ModelViewMatrix,const int gl_MaxLights = 8 等。在定義自己的變數時需要注意命名衝突的問題。
以上是GLSL中資料類型的粗略介紹,詳細的內容大家可以參考一下《OpenGL Shading Language, Second Edition》一書,感興趣的朋友可以向我索取。下面我們轉入今天的核心話題:資料傳遞。
對於第1種資料類型——Attribute,OpenGL使用常規的頂點設定指令來傳遞相關資料,如前面我們提到的glVertex, glNormal等指令。比如glVertex,在指定了頂點的座標之後,內建資料變數gl_Vertex(attribute vec4 gl_Vertex;)的值會被修改為glVertex指令所指定的值,然後這個值可以由vertex shader中的代碼所使用。不過這僅限於系統內建的資料,對於可程式化的圖形流水線來說,要製造出精美複雜的渲染效果僅僅靠這一些內建的資料是不夠的,通常情況下我們需要傳入一些具有其他含義的資料給shader,這些資料將存入由OpenGL為其預留的空間。我們來看看下面的指令。
指令void glVertexAttrib{1|2|3|4}{s|f|d}(GLuint index, TYPE v) 可以用來指定自訂的attribute資料。這跟OpenGL的其他頂點屬性指令在使用上是一樣的。其中的index指定了存入的位置(我們可以這麼認為),vertex shader可以從這些位置把資料讀取出來。另外,還有一些類似的指令,提供了對數群組類型、單位化(即絕對值不超過1.0)資料的傳遞,如下:
void glVertexAttrib{1|2|3}{s|f|d}v(GLuint index, const TYPE *v) [數群組類型]
void glVertexAttrib4{b|s|i|f|d|ub|us|ui}v(GLuint index, const TYPE *v)[數群組類型]
void glVertexAttrib4Nub(GLuint index, TYPE v) [單位化]
void glVertexAttrib4N{b|s|i|f|d|ub|us|ui}v(GLuint index, const TYPE *v)[單位化]
更為通用的一種指令是
void glVertexAttribPointer(GLuint index,
GLint size,
GLenum type,
GLboolean normalized,
GLsizei stride,
const GLvoid *pointer)
這條指令需要如下指令來配合使用
void glEnableVertexAttribArray(GLuint index)[開啟該vertex attribute array]
void glDisableVertexAttribArray(GLuint index)[關閉該vertex attribute array]
實際上它們跟開啟和關閉OpenGL用戶端狀態的使用方法是一樣的。
OK,到此我們已經完成了一半的工作,在啟動繪圖指令之後(如glDawXxxx系列),應用程式便會把資料傳遞給shader。剩下的一半工作就是shader如何來訪問傳入的資料。
第一種方案是所有的工作都由GLSL的連結器自動來完成,然後向OpenGL查詢需要訪問的資料。[用得較少,書中未詳細說明,在此略過.....]。
第二種方案是綁定,即由應用程式明確的表示把哪些索引(儲存位置)綁定到哪些變數(名稱),這樣,在shader中直接引用變數的名稱就可以了,如下:
void glBindAttribLocation(GLuint program, GLuint index, const GLchar *name)
該指令把某個shader程式(program)中的index(儲存位置)與變數name(變數名稱)綁定。這樣,程式通過把資料存放區到index指定的位置,綁定之後,shader就可以通過name來訪問,跟普通變數的使用方式一樣。與之相對應的還有一條查詢指令,用於查詢shader中某個變數所對應的儲存區索引位置:
GLint glGetAttribLocation(GLuint program, const GLchar *name)
綁定指令可以將一個位置綁定到多個變數,即別名機制,就如同c++裡可以建立引用一樣;但是一個變數不能對應到多個索引位置,這一點比較容易理解;同時,並非所有的綁定都會生效。如果shader中沒有使用某個變數,而這個變數被使用了綁定指令,則它是處於非啟用狀態的,對於這樣的變數GLSL在處理過程中會把它最佳化掉。通過指令
void glGetActiveAttrib(GLuint program,
GLuint index,
GLsizei bufSize,
GLsizei *length,
GLint *size,
GLenum *type,
GLchar *name)
可以查詢變數的啟用狀態。這是Attribute類型的資料傳遞方式。
對於Uniform資料,沒有“綁定”,而是通過查詢對應變數對應的索引位置來設定。使用方式與Attribute類似,對應於下面一組指令:
void glUniform{1|2|3|4}{f|i}(GLint location, TYPE v)[指定普通變數]
void glUniform{1|2|3|4}{f|i}v(GLint location, GLuint count, const TYPE v)[指定陣列變數]
void glUniformMatrix{2|3|4}fv(GLint location, GLuint count, GLboolean transpose, const GLfloat *v)[指定矩陣變數]
GLint glGetUniformLocation(GLuint program, const GLchar *name)[查詢]
void glGetUniformfv(GLuint program, GLint location, GLfloat *params)[查詢數組]
void glGetUniformiv(GLuint program, GLint location, GLint *params)[查詢數組]
void glGetActiveUniform(GLuint program,
GLuint index,
GLsizei bufSize,
GLsizei *length,
GLint *size,
GLenum *type,
GLchar *name)[查詢啟用的變數]
需要注意一點的是,與Attribute類型不同,Uniform可以定義結構體變數,而結構體變數是無法直接查詢的,只能查詢到它的成員。比如,A是一個結構體,那麼glGetUniformLocation( program, "A" )是無效的,而glGetUniformLocation( program, "A.b" )是有效(b是A的一個成員變數)。其他的與Attribute類型基本一致。
對於採樣器類型,則有其專用的指令:glUniform1i 和 glUniform1iv。實際就是把對應的紋理單元編號傳遞給shader。
以上就是關於資料傳遞的主要內容。還有一些特殊的情況,用得相對較少,在後續涉及到的時候再跟大家一起討論。好了,我該繼續學習去了,之後再跟大家一起分享我的學習成果^_^

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.