Vertex Attributes and Layouts in OpenGL

P5

簡單來說,Opengl管線的工作流程就是為我們的顯卡提供數(shù)據(jù),然后存儲在GPU上的內(nèi)存里。GPU內(nèi)存包含了我們想要繪制的所有數(shù)據(jù)。然后我們使用shader(在GPU上執(zhí)行的一種程序),讀取這部分數(shù)據(jù),然后在屏幕上顯示下來。

有代表性的是,我們實際上繪制圖形使用的是一個Vertex buffer,即存儲在GPU上的一部分內(nèi)存buffer。當shader實際上開始讀取Vertex buffer時,它需要知道buffer的布局layout,比如說buffer里面有什么,是以答對浮點數(shù),這些浮點數(shù)決定著每個頂點的位置。你也有像坐標、紋理、法線之類的東西。

我們必須告訴opengl里面有什么,它是如何布局的,因為如果我們不這樣做。然后opengl就會說,這只是一堆字節(jié),就和C++一樣(比如我寫了一個float我給它分配一些東西,我們就知道內(nèi)存里有一個浮點數(shù),因為我告訴c++這是一個浮點數(shù),如果我用void把它賦值給整數(shù),如果我把它賦值給Int指針,如果我取流的內(nèi)存地址,并將其賦給結(jié)束指針,然后取消它的引用,我就會獲得完全不同的東西,因為它interpreting memory不同)在這里也是同樣。

告訴Opengl每流的12個字節(jié)是3個4字節(jié)的浮點數(shù),這是我的位置,接下來的8個字節(jié)是我的紋理坐標,一個浮點數(shù)x一個浮點數(shù)給y或者是u和v,如果你想像這樣子調(diào)用它。我們需要一個方法告訴opengl,這是我們的內(nèi)存布局,這是確切的整個頂點屬性指針能為我們做的,這是一個函數(shù),在opengl里面叫glVertex(),一個真指針。

在著色器那邊,你也需要去i匹配上布局,這布局是你用C++類定義在cpu里面的。

頂點

一個頂點和位置無關(guān),頂點就只是一個在幾何體上的點,人們在視覺上對他們的看法顯然是由它的位置決定。所以如果我畫一個三角形,你就會這樣啊三個頂點,但頂點不是位置,一個頂點不是一個位置,一個頂點可以包含比一個位置更多的東西,所以入如果你告訴我有一個頂點,它是0.5 0.5,這并沒有告訴我任何事情。因為你是在說明我說的頂點位置的意思,很多人像這樣子,但是它們是明顯錯誤的。因為頂點可以包含比一個位置要多很多的數(shù)據(jù),盡管它通常用來包含位置,所以我是想說清楚,當我說頂點位置時,如果我說了一個頂點,我的意思是這一整個點的數(shù)據(jù)組成了這個頂點,它可以包括這個位置的紋理,坐標,法線,顏色,按法線切線,所有這些東西都可以在一個頂點里面,所以只是位置,如果你只是參考位置,你應(yīng)該叫它位置頂點。所以這就是為什么我這里獲取這個浮點數(shù)作為位置而不是頂點,因為那一刻它們只是位置,盡管我往里面加了東西。


位置.png

我們這里有三個頂點,然后我們生成了一個緩存,綁定,然后把它放進去,或者我應(yīng)該說復(fù)制這些位置到這個實際的緩存里面,我們這里已經(jīng)通過指明一個指針向它定義了,它們有多大,這就是我們做的。


image.png

opengl是不知道的,如果你看這代碼,我們可以清楚看到,我們每個頂點有兩個浮點數(shù),這就是x和y的位置,opengl是不知道的,這對你來說是很明顯的,因為你是在看著代碼,opengl是不知道發(fā)生了說明,但如果我們突然引入了第三個坐標。換一句話說,如果我想要一個三維坐標系,而不是像我們這里獲取的二維的,如果我這樣做,你是能知道明白的,那opengl是如何知道明白的呢?

所以我們獲取的是說明,這我們需要告訴opengl布局,這就是我們要做的,如果我們往下翻一下。我們綁定了緩存,我們填了數(shù)據(jù)進去,在你填數(shù)據(jù)進去之前你不需要這樣做,在你可以做之后也不用這樣做,你可以想什么時候做就什么時候做只要這個buffer is actually bind。

當我們能夠告訴Opengl我們buffer的布局是什么,

glVertexAttribPointer()

基本上我們的著色器讀取這些東西,通過一個索引。Its picture likes array,但是類型和數(shù)組might be different,這就是索引。關(guān)于你實際引用屬性的索引。所有的這些東西,通過維持屬性,當我提高過,一個頂點的組成比只是位置要多,位置,紋理,坐標,法線,顏色無論哪一樣?xùn)|西,像一個位置都是一個屬性。所以這個索引只是告訴我們,嘿,這個屬性是什么索引。

假設(shè)一下,我有三個屬性,我又位置,紋理,法線,我需要說我像位置在index0,紋理在Index1,然后法線在index2 所以當我開始從gpu那邊,從著色器那邊開始讀取時,我會到達緩存,我可以簡單地引用它們,通過嘿index2放在這里,我知道這是我的法線,因為這是我定義的布局,這就是一個索引。它只是在你緩存里面的實際索引。size這里可能會引起誤解,你可以看到這里很清楚地說明了它必須是1,2,3,4所以這與字節(jié)大小或者內(nèi)存實際占有無關(guān)。它基本就是一個數(shù)目,所以我的意思是當這里我們指定類型,像我們實際用的頂點位置GL_FLOAT,這就是有多少浮點數(shù)要提供的數(shù)字。所以這里很明顯,每個頂點我們有兩個浮點數(shù),所以這里的大小會是2,因為我們bascally有了兩浮點數(shù)的頂點組件,這代表了位置,如果我們切換到了三維坐標系統(tǒng),就像我之前提到的,我們要將它設(shè)置成3。我剛才解釋的基本上是數(shù)據(jù)類型,我們提供GL_FLOAT是我們想要的。

normolized這又一點點難辦,我們不需要真的擔心這些,尤其是如果我們在解決浮點數(shù),因為它們已經(jīng)是標準的,但它實際是用來。(我們剛才說,我們指定了一個字節(jié),在0到255之間,因為這是顏色的值,在我們著色器里面這需要作為一個浮點數(shù)轉(zhuǎn)換成0-1之間。這就是shader實際為我們做的,這不是某樣?xùn)|西的例子,你可以自己在cpu上面試一下,你也可以讓opengl做) GL_FALSE

stride和pointer這是大部分人比較疑惑的。在文檔的描述,stride是連續(xù)通用頂點屬性之間的字節(jié)偏移量。實際上,stride就是每個頂點之間的字節(jié)數(shù)量。所以,再說一次現(xiàn)在再我們的例子里面,如果我們有一個位置,紋理,法線,我們就說位置他是一個三維頂點組件,然后紋理是二維,然后法線又是三維的。我們有3個float,12字節(jié),2float給紋理,8字節(jié),有12字節(jié)給了法線,所以32字節(jié)就是我們的stride,因為實際上,這是每個頂點的大小,這是很重要的,因為如果Opengl也會調(diào)用步幅,如果我們想從一個頂點跳到下一個頂點,例如,我想看index1,所以是從0開始,0是我們的第一個頂點,我想要跳到第二個頂點也就是Index1我需要在緩存里走32字節(jié)。所以我們有一個指針,指向緩存的開始,然后我走32字節(jié),我到了下一個頂點的開始,這就是stride。

pointer另一方面,這是對第一個組件的偏移。pointer就是一個指針,在實際的屬性里面,所以它已經(jīng)在頂點的空間里面了。你不用擔心你有多少個頂點,假裝你只有一個頂點,我有一個頂點,然后里面我有位置、紋理、坐標和法線。這就是那些東西在字節(jié)里面的每一個偏移,對于位置來說它的偏移是0,因為我們緩存的第一個字節(jié),我們頂點的第一個字節(jié),就是位置,然后我們往前走12字節(jié),我們到達了紋理坐標的開始,所以紋理坐標屬性這個值就應(yīng)該是12,因為從開始的地方到這里是12字節(jié)。最后8字節(jié)是我們到頂點的法線,所以20字節(jié)從開始到頂點法線,因此頂點法線屬性指針的這個值就應(yīng)該是20?,F(xiàn)在,代替剛才寫的像0,12,20這些東西,可能有點迷惑,不僅如此如果你重新排列你的布局或者別的你必須重新計算或手動操作的,有一個宏叫g(shù)eneral demonstrated???C++里面給提供了計算便宜的宏。你可以在一個結(jié)構(gòu)體或類里面找到并使用它,你可以像stride一樣,你可以用宏之類的東西來自動完成這些工作。所以你不用往里面加像12,32這樣的值。我只是向你解釋這是什么。

把緩存綁定起來,這是很重要的,我將寫glVertexAttribPointer(),第一個參數(shù)是index

現(xiàn)在,這是一個簡單的例子,我們只有位置,所以首先我們只有一個頂點屬性,所以我們只需要調(diào)用這個函數(shù)1次,因為我們指定一個單一屬性索引,當然會是0,因為這是第一個屬性,size記住size是組件數(shù)目2,Type ,不管我們是否希望它們被規(guī)范化它們已經(jīng)是流了,它們已經(jīng)在我們想要的空間里了,所以GL_FALSE,接下來是stride。sizeof(float)2。 指針是數(shù)字,(const void)8

這就是我們需要實現(xiàn)頂點屬性glEnableV,,這是禁止生成頂點屬性的,回到我們的代碼里,我喜歡在我寫指針前這樣做,它不會實際影響到opengl。當然作為哦狀態(tài)機,它不是要檢查它是否被啟用。

image.png

image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容