當前位置:網站首頁>LearnOpenGL學習筆記——高級數據

LearnOpenGL學習筆記——高級數據

2022-05-15 04:40:29風物長宜放眼量~

高級數據

我們在OpenGL中大量使用緩沖來存儲數據已經有很長時間了。操作緩沖其實還有更有意思的方式,而且使用紋理將大量輸出傳入著色器也有更有趣的方法。這一節中,我們將討論一些更有意思的緩沖函數,以及我們該如何使用紋理來存儲大量的數據(紋理部分還沒有完成)。

OpenGL中的緩沖只是一個管理特定內存塊的對象,沒有其它更多的功能了。在我們將它綁定到一個緩沖目標(Buffer Target)時,我們才賦予了其意義。當我們綁定一個緩沖到GL_ARRAY_BUFFER時,它就是一個頂點數組緩沖,但我們也可以很容易地將其綁定到GL_ELEMENT_ARRAY_BUFFER。OpenGL內部會為每個目標儲存一個緩沖,並且會根據目標的不同,以不同的方式處理緩沖。

到目前為止,我們一直是調用glBufferData函數來填充緩沖對象所管理的內存,這個函數會分配一塊內存,並將數據添加到這塊內存中。如果我們將它的data參數設置為NULL,那麼這個函數將只會分配內存,但不進行填充。這在我們需要預留(Reserve)特定大小的內存,之後回到這個緩沖一點一點填充的時候會很有用。

除了使用一次函數調用填充整個緩沖之外,我們也可以使用glBufferSubData,填充緩沖的特定區域。這個函數需要一個緩沖目標、一個偏移量、數據的大小和數據本身作為它的參數。這個函數不同的地方在於,我們可以提供一個偏移量,指定從何處開始填充這個緩沖。這能够讓我們插入或者更新緩沖內存的某一部分。要注意的是,緩沖需要有足够的已分配內存,所以對一個緩沖調用glBufferSubData之前必須要先調用glBufferData。

glBufferSubData(GL_ARRAY_BUFFER, 24, sizeof(data), &data); // 範圍: [24, 24 + sizeof(data)]

將數據導入緩沖的另外一種方法是,請求緩沖內存的指針,直接將數據複制到緩沖當中。通過調用glMapBuffer函數,OpenGL會返回當前綁定緩沖的內存指針,供我們操作:

float data[] = {
    
  0.5f, 1.0f, -0.35f
  ...
};
glBindBuffer(GL_ARRAY_BUFFER, buffer);
// 獲取指針
void *ptr = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
// 複制數據到內存
memcpy(ptr, data, sizeof(data));
// 記得告訴OpenGL我們不再需要這個指針了
glUnmapBuffer(GL_ARRAY_BUFFER);

當我們使用glUnmapBuffer函數,告訴OpenGL我們已經完成指針操作之後,OpenGL就會知道你已經完成了。在解除映射(Unmapping)之後,指針將會不再可用,並且如果OpenGL能够成功將您的數據映射到緩沖中,這個函數將會返回GL_TRUE。如果要直接映射數據到緩沖,而不事先將其存儲到臨時內存中,glMapBuffer這個函數會很有用。比如說,你可以從文件中讀取數據,並直接將它們複制到緩沖內存中。

分批頂點屬性

通過使用glVertexAttribPointer,我們能够指定頂點數組緩沖內容的屬性布局。在頂點數組緩沖中,我們對屬性進行了交錯(Interleave)處理,也就是說,我們將每一個頂點的比特置、法線和/或紋理坐標緊密放置在一起。既然我們現在已經對緩沖有了更多的了解,我們可以采取另一種方式。

我們可以做的是,將每一種屬性類型的向量數據打包(Batch)為一個大的區塊,而不是對它們進行交錯儲存。與交錯布局123123123123不同,我們將采用分批(Batched)的方式111122223333。

當從文件中加載頂點數據的時候,你通常獲取到的是一個比特置數組、一個法線數組和/或一個紋理坐標數組。我們需要花點力氣才能將這些數組轉化為一個大的交錯數據數組。使用分批的方式會是更簡單的解决方案,我們可以很容易使用glBufferSubData函數實現:

float positions[] = {
     ... }; float normals[] = {
     ... }; float tex[] = {
     ... };
// 填充緩沖
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(positions), &positions);
glBufferSubData(GL_ARRAY_BUFFER, sizeof(positions), sizeof(normals), &normals);
glBufferSubData(GL_ARRAY_BUFFER, sizeof(positions) + sizeof(normals), sizeof(tex), &tex);

這樣子我們就能直接將屬性數組作為一個整體傳遞給緩沖,而不需要事先處理它們了。我們仍可以將它們合並為一個大的數組,再使用glBufferData來填充緩沖,但對於這種工作,使用glBufferSubData會更合適一點。

我們還需要更新頂點屬性指針來反映這些改變:

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);  
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)(sizeof(positions)));  
glVertexAttribPointer(
  2, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)(sizeof(positions) + sizeof(normals)));

這給了我們設置頂點屬性的另一種方法。使用哪種方法都不會對OpenGL有什麼立刻的好處,它只是設置頂點屬性的一種更整潔的方式。具體使用的方法將完全取决於你的喜好與程序類型。

複制緩沖

當你的緩沖已經填充好數據之後,你可能會想與其它的緩沖共享其中的數據,或者想要將緩沖的內容複制到另一個緩沖當中。glCopyBufferSubData能够讓我們相對容易地從一個緩沖中複制數據到另一個緩沖中。這個函數的原型如下:

void glCopyBufferSubData(GLenum readtarget, GLenum writetarget, GLintptr readoffset,GLintptr writeoffset, GLsizeiptr size);

readtarget和writetarget參數需要填入複制源和複制目標的緩沖目標。比如說,我們可以將VERTEX_ARRAY_BUFFER緩沖複制到VERTEX_ELEMENT_ARRAY_BUFFER緩沖,分別將這些緩沖目標設置為讀和寫的目標。當前綁定到這些緩沖目標的緩沖將會被影響到。

但如果我們想讀寫數據的兩個不同緩沖都為頂點數組緩沖該怎麼辦呢?我們不能同時將兩個緩沖綁定到同一個緩沖目標上。正是出於這個原因,OpenGL提供給我們另外兩個緩沖目標,叫做GL_COPY_READ_BUFFER和GL_COPY_WRITE_BUFFER。我們接下來就可以將需要的緩沖綁定到這兩個緩沖目標上,並將這兩個目標作為readtarget和writetarget參數。

接下來glCopyBufferSubData會從readtarget中讀取size大小的數據,並將其寫入writetarget緩沖的writeoffset偏移量處。下面這個例子展示了如何複制兩個頂點數組緩沖:

float vertexData[] = {
     ... };
glBindBuffer(GL_COPY_READ_BUFFER, vbo1);
glBindBuffer(GL_COPY_WRITE_BUFFER, vbo2);
glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, sizeof(vertexData));

我們也可以只將writetarget緩沖綁定為新的緩沖目標類型之一:

float vertexData[] = {
     ... };
glBindBuffer(GL_ARRAY_BUFFER, vbo1);
glBindBuffer(GL_COPY_WRITE_BUFFER, vbo2);
glCopyBufferSubData(GL_ARRAY_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, sizeof(vertexData));

有了這些關於如何操作緩沖的額外知識,我們已經能够以更有意思的方式使用它們了。當你越深入OpenGL時,這些新的緩沖方法將會變得更加有用。

知識點總結:

1.glBufferSubData可以用來填充緩沖區域
2.glMapBuffer函數可以請求緩沖內存,直接複制數據到緩沖中。記得glUnmapBuffer緩沖指針。
3.可以分批處理數據或者說將屬性數組作為一個整體傳遞給緩沖(通過glBufferSubData填充緩沖,並使用glVertexAttribPointer綁定)
4.可以使用glCopyBufferSubData複制緩沖數據到另一個緩沖中

https://learnopengl-cn.github.io/04%20Advanced%20OpenGL/07%20Advanced%20Data/

版權聲明
本文為[風物長宜放眼量~]所創,轉載請帶上原文鏈接,感謝
https://cht.chowdera.com/2022/135/202205142159252773.html

隨機推薦