日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

OPenGL中的缓冲区对象

發(fā)布時(shí)間:2025/3/14 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 OPenGL中的缓冲区对象 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

引自:http://blog.csdn.net/mzyang272/article/details/7655464

在許多OpenGL操作中,我們都向OpenGL發(fā)送一大塊數(shù)據(jù),例如向它傳遞需要處理的頂點(diǎn)數(shù)組數(shù)據(jù)。傳輸這種數(shù)據(jù)可能非常簡(jiǎn)單,例如把數(shù)據(jù)從系統(tǒng)的內(nèi)存中復(fù)制到圖形卡。但是,由于OpenGL是按照客戶機(jī)-服務(wù)器模式設(shè)計(jì)的,在OpenGL需要數(shù)據(jù)的任何時(shí)候,都必須把數(shù)據(jù)從客戶機(jī)內(nèi)存?zhèn)鬏數(shù)椒?wù)器。如果數(shù)據(jù)并沒有修改,或者客戶機(jī)和服務(wù)器位于不同的計(jì)算機(jī)(分布式渲染),數(shù)據(jù)的傳輸可能會(huì)比較緩慢,或者是冗余的。

OpenGL 1.5版本增加了緩沖區(qū)對(duì)象(buffer object),允許應(yīng)用程序顯式地指定把哪些數(shù)據(jù)存儲(chǔ)在圖形服務(wù)器中。

當(dāng)前版本的OpenGL中使用了很多不同類型的緩沖區(qū)對(duì)象:

從OpenGL 1.5開始,數(shù)組中的頂點(diǎn)數(shù)據(jù)可以存儲(chǔ)在服務(wù)器端緩沖區(qū)對(duì)象中。

在OpenGL 2.1中,加入了在緩沖區(qū)對(duì)象中存儲(chǔ)像素?cái)?shù)據(jù)(例如,紋理貼圖或像素塊)的支持。

OpenGL 3.1增加了統(tǒng)一緩沖對(duì)象(uniform buffer object)以存儲(chǔ)成塊的、用于著色器的統(tǒng)一變量數(shù)據(jù)。

讀者還會(huì)發(fā)現(xiàn)OpenGL中有很多其他的功能用到了術(shù)語(yǔ)“對(duì)象”,但是這些功能并不都適用于存儲(chǔ)塊數(shù)據(jù)。例如,(OpenGL 1.1引入的)紋理對(duì)象只是封裝了和紋理貼圖相關(guān)聯(lián)的各種狀態(tài)設(shè)置。同樣,OpenGL 3.0中增加的頂點(diǎn)數(shù)組對(duì)象,封裝了和使用頂點(diǎn)數(shù)組相關(guān)的狀態(tài)參數(shù)。這些類型的對(duì)象允許我們使用較少的函數(shù)調(diào)用就能夠修改大量的狀態(tài)設(shè)置。為了使性能最大化,只要習(xí)慣它們的操作,就應(yīng)該盡可能地嘗試使用它們。

注意:通過對(duì)象的名字來引用它,其名字是一個(gè)無符號(hào)的整型標(biāo)識(shí)符。從OpenGL 3.1開始,所有的名字必須由OpenGL使用glGen*()函數(shù)之一來生成,不再接受用戶定義的名字。

創(chuàng)建緩沖區(qū)對(duì)象

任何非零的無符號(hào)整數(shù)都可以作為緩沖區(qū)對(duì)象的標(biāo)識(shí)符使用。可以任意選擇一個(gè)有代表性的值,也可以讓OpenGL負(fù)責(zé)分配和管理這些標(biāo)識(shí)符。這兩種做法有什么區(qū)別呢?讓OpenGL分配標(biāo)識(shí)符可以保證避免重復(fù)使用已被使用的緩沖區(qū)對(duì)象標(biāo)識(shí)符,從而消除無意修改數(shù)據(jù)的風(fēng)險(xiǎn)。

為了讓OpenGL分配緩沖區(qū)對(duì)象標(biāo)識(shí)符,可以調(diào)用glGenBuffers()函數(shù)。

void?glGenBuffers(GLsizei?n,?GLuint?*buffers);?

在buffers數(shù)組中返回n個(gè)當(dāng)前未使用的名稱,表示緩沖區(qū)對(duì)象。在buffers數(shù)組中返回的名稱并不需要是連續(xù)的整數(shù)。

返回的名稱被標(biāo)記為已使用,以便分配給緩沖區(qū)對(duì)象。但是,當(dāng)它們被綁定之后,它們只獲得一個(gè)合法的狀態(tài)。

零是一個(gè)被保留的緩沖區(qū)對(duì)象名稱,從來不會(huì)被glGenBuffers()作為緩沖區(qū)對(duì)象返回。

還可以調(diào)用glIsBuffer()函數(shù),判斷一個(gè)標(biāo)識(shí)符是否是一個(gè)當(dāng)前被使用的緩沖區(qū)對(duì)象的標(biāo)識(shí)符。

GLboolean glIsBuffer(GLuint buffer);

如果buffer是一個(gè)已經(jīng)綁定的緩沖區(qū)對(duì)象的名稱,而且還沒有刪除,這個(gè)函數(shù)返回GL_TRUE。

如果buffer為0或者它不是一個(gè)緩沖區(qū)對(duì)象的名稱,這個(gè)函數(shù)返回GL_FALSE。

激活緩沖區(qū)對(duì)象

為了激活緩沖區(qū)對(duì)象,首先需要將它綁定。綁定緩沖區(qū)對(duì)象表示選擇未來的操作(對(duì)數(shù)據(jù)進(jìn)行初始化或者使用緩沖區(qū)對(duì)象進(jìn)行渲染)將影響哪個(gè)緩沖區(qū)對(duì)象。也就是說,如果應(yīng)用程序有多個(gè)緩沖區(qū)對(duì)象,就需要多次調(diào)用glBindBuffer()函數(shù):一次用于初始化緩沖區(qū)對(duì)象以及它的數(shù)據(jù),以后的調(diào)用要么選擇用于渲染的緩沖區(qū)對(duì)象,要么對(duì)緩沖區(qū)對(duì)象的數(shù)據(jù)進(jìn)行更新。

為了禁用緩沖區(qū)對(duì)象,可以用0作為緩沖區(qū)對(duì)象的標(biāo)識(shí)符來調(diào)用glBindBuffer()函數(shù)。這將把OpenGL切換為默認(rèn)的不使用緩沖區(qū)對(duì)象的模式。

void?glBindBuffer(GLenum?target,?GLuint?buffer);?

指定了當(dāng)前的活動(dòng)緩沖區(qū)對(duì)象。target必須設(shè)置為GL_ARRAY_BUFFER、GL_ELEMENT_ARRAY_BUFFER、GL_PIXEL_PACK_BUFFER、GL_PIXEL_UNPACK_BUFFER、GL_COPY_READ_BUFFER、GL_COPY_WRITE_BUFFER、GL_TRANSFORM_ FEEDBACK_ BUFFER或者GL_UNIFORM_BUFFER。buffer指定了將要綁定的緩沖區(qū)對(duì)象

glBindBuffer()完成3個(gè)任務(wù)之一:①當(dāng)buffer是一個(gè)首次使用的非零無符號(hào)整數(shù)時(shí),它就創(chuàng)建一個(gè)新的緩沖區(qū)對(duì)象,并把buffer分配給這個(gè)緩沖區(qū)對(duì)象,作為它的名稱。②當(dāng)綁定到一個(gè)以前創(chuàng)建的緩沖區(qū)對(duì)象時(shí),這個(gè)緩沖區(qū)對(duì)象便成為活動(dòng)的緩沖區(qū)對(duì)象。③當(dāng)綁定到一個(gè)值為零的buffer時(shí),OpenGL就會(huì)停止使用緩沖區(qū)對(duì)象。

用數(shù)據(jù)分配和初始化緩沖區(qū)對(duì)象

一旦綁定了一個(gè)緩沖區(qū)對(duì)象,就需要保留空間以存儲(chǔ)數(shù)據(jù),這是通過調(diào)用glBufferData()函數(shù)實(shí)現(xiàn)的。

void?glBufferData(GLenum?target,?GLsizeiptr?size,?const?GLvoid?*data, ?GLenum?usage);?

分配size個(gè)存儲(chǔ)單位(通常是字節(jié))的OpenGL服務(wù)器內(nèi)存,用于存儲(chǔ)頂點(diǎn)數(shù)據(jù)或索引。以前所有與當(dāng)前綁定對(duì)象相關(guān)聯(lián)的數(shù)據(jù)都將刪除。

target可以是GL_ARRAY_BUFFER(表示頂點(diǎn)數(shù)據(jù))、GL_ELEMENT_ARRAY_BUFFER(表示索引數(shù)據(jù))、G L _ P I X E L _ U N PACK_BUFEER( 表示傳遞給O p e n G L 的像素?cái)?shù)據(jù)) 或GL_PIXEL_PACK_BUFFER(表示從OpenGL獲取的像素?cái)?shù)據(jù))、GL_COPY_READ_BUFFER 和GL_COPY_WRITE_BUFFER(表示在緩沖區(qū)之間復(fù)制數(shù)據(jù))、GL_TEXTURE_BUFFER(表示作為紋理緩沖區(qū)存儲(chǔ)的紋理數(shù)據(jù))、GL_TRANSFORM_FEEDBACK_BUFFER(表示執(zhí)行一個(gè)變換反饋著色器的結(jié)果),或者GL_UNIFORM_BUFFER(表示統(tǒng)一變量值)。

size是存儲(chǔ)相關(guān)數(shù)據(jù)所需要的內(nèi)存數(shù)量。這個(gè)值通常是數(shù)據(jù)元素的個(gè)數(shù)乘以它們各自的存儲(chǔ)長(zhǎng)度。

data可以是一個(gè)指向客戶機(jī)內(nèi)存的指針(用于初始化緩沖區(qū)對(duì)象),也可以是NULL。如果它傳遞的是一個(gè)有效的指針,size個(gè)單位的存儲(chǔ)空間就從客戶機(jī)復(fù)制到服務(wù)器。如果它傳遞的是NULL,這個(gè)函數(shù)將會(huì)保留size個(gè)單位的存儲(chǔ)空間供以后使用,但不會(huì)對(duì)它進(jìn)行初始化。

usage提供了一個(gè)提示, 就是數(shù)據(jù)在分配之后將如何進(jìn)行讀取和寫入。它的有效值包括GL_STREAM_DRAW、GL_STREAM_READ、GL_STREAM_COPY、GL_STATIC_DRAW、GL_STATIC_READ、GL_STATIC_COPY、GL_DYNAMIC_DRAW、GL_DYNAMIC_READ、GL_DYNAMIC_COPY。

如果請(qǐng)求分配的內(nèi)存數(shù)量超過了服務(wù)器能夠分配的內(nèi)存, g l B u f f e r D a t a ( ) 將返回GL_OUT_OF_MEMORY。如果usage并不是允許使用的值之一,這個(gè)函數(shù)就返回GL_INVALID_VALUE。glBufferData()首先在OpenGL服務(wù)器中分配內(nèi)存以存儲(chǔ)數(shù)據(jù)。如果請(qǐng)求的內(nèi)存太多,它會(huì)設(shè)置GL_OUT_OF_MEMORY錯(cuò)誤。如果成功分配了存儲(chǔ)空間,并且data參數(shù)的值不是NULL,size個(gè)存儲(chǔ)單位(通常是字節(jié))就從客戶機(jī)的內(nèi)存復(fù)制到這個(gè)緩沖區(qū)對(duì)象。但是,如果需要在創(chuàng)建了緩沖區(qū)對(duì)象之后的某個(gè)時(shí)刻動(dòng)態(tài)地加載數(shù)據(jù),可以把data參數(shù)設(shè)置為NULL,為數(shù)據(jù)保留適當(dāng)?shù)拇鎯?chǔ)空間,但不對(duì)它進(jìn)行初始化。

glBufferData()的最后一個(gè)參數(shù)usage是向OpenGL提供的一個(gè)性能提示。根據(jù)usage參數(shù)指定的值,
OpenGL可能會(huì)對(duì)數(shù)據(jù)進(jìn)行優(yōu)化,進(jìn)一步提高性能。它也可以選擇忽略這個(gè)提示。在緩沖區(qū)對(duì)象數(shù)據(jù)
上,可以進(jìn)行3種類型的操作:

1) 繪圖:客戶機(jī)指定了用于渲染的數(shù)據(jù)。

2) 讀取:從OpenGL緩沖區(qū)讀取(例如幀緩沖區(qū))數(shù)據(jù)值,并且在應(yīng)用程序中用于各種與渲染并不直接相關(guān)的計(jì)算過程。

3) 復(fù)制:從OpenGL緩沖區(qū)讀取數(shù)據(jù)值,作為用于渲染的數(shù)據(jù)。

另外,根據(jù)數(shù)據(jù)更新的頻率,有幾種不同的操作提示描述了數(shù)據(jù)的讀取頻率或在渲染中使用的頻率:

流模式:緩沖區(qū)對(duì)象中的數(shù)據(jù)常常需要更新,但是在繪圖或其他操作中使用這些數(shù)據(jù)的次數(shù)較少。

靜態(tài)模式:緩沖區(qū)對(duì)象中的數(shù)據(jù)只指定1次,但是這些數(shù)據(jù)被使用的頻率很高。

動(dòng)態(tài)模式:緩沖區(qū)對(duì)象中的數(shù)據(jù)不僅常常需要進(jìn)行更新,而且使用頻率也非常高。

usage參數(shù)可能使用的值見表2-6。

表2-6 glBufferData()的usage參數(shù)的值


更新緩沖區(qū)對(duì)象的數(shù)據(jù)值
?

有兩種方法可以更新存儲(chǔ)在緩沖區(qū)對(duì)象中的數(shù)據(jù)。第一種方法假設(shè)我們已經(jīng)在應(yīng)用程序的一個(gè)緩沖區(qū)中準(zhǔn)備了相同類型的數(shù)據(jù)。glBufferSubData()將用我們提供的數(shù)據(jù)替換被綁定的緩沖區(qū)對(duì)象的一些數(shù)據(jù)子集

void?glBufferSubData(GLenum?target,?GLintptr?offset,?GLsizeiptr?size, ?const?GLvoid?*data);?

用data指向的數(shù)據(jù)更新與target相關(guān)聯(lián)的當(dāng)前綁定緩沖區(qū)對(duì)象中從offset(以字節(jié)為單位)開始的size個(gè)字節(jié)數(shù)據(jù)。target必須是GL_ARRAY_BUFFER、GL_ELEMENT_ ARRAY_BUFFER、GL_PIXEL_UNPACK_BUFFER、GL_PIXEL_PACK_BUFFER、GL_COPY_READ_BUFFER、G L _ C O P Y _ W R I T E _ B U F F E R 、G L _ T R A N S F O R M _ F E E D B A C K _ B U F F E R 或GL_UNIFORM_BUFFER。

如果size小于0或者size+offset大于緩沖區(qū)對(duì)象創(chuàng)建時(shí)所指定的大小,glBufferSubData()將產(chǎn)生一個(gè)GL_INVALID_VALUE錯(cuò)誤。

第二種方法允許我們更靈活地選擇需要更新的數(shù)據(jù)。glMapBuffer()返回一個(gè)指向緩沖區(qū)對(duì)象的指針,可以在這個(gè)緩沖區(qū)對(duì)象中寫入新值(或簡(jiǎn)單地讀取數(shù)據(jù),這取決于內(nèi)存訪問權(quán)限),就像對(duì)數(shù)組進(jìn)行賦值一樣。在完成了對(duì)緩沖區(qū)對(duì)象的數(shù)據(jù)更新之后,可以調(diào)用glUnmapBuffer(),表示已經(jīng)完成了對(duì)數(shù)據(jù)的更新。

glMapBuffer()提供了對(duì)緩沖區(qū)對(duì)象中包含的整個(gè)數(shù)據(jù)集合的訪問。如果需要修改緩沖區(qū)中的大多數(shù)數(shù)據(jù),這種方法很有用,但是,如果有一個(gè)很大的緩沖區(qū)并且只需要更新很小的一部分值,這種方法效率很低。

GLvoid?*glMapBuffer(GLenum?target,?GLenum?access);?

返回一個(gè)指針,指向與t a rg e t 相關(guān)聯(lián)的當(dāng)前綁定緩沖區(qū)對(duì)象的數(shù)據(jù)存儲(chǔ)。t a rg e t 可以是GL_ARRAY_BUFFER、GL_ELEMENT_ARRAY_BUFFER、GL_PIXEL_PACK_BUFFER、GL_PIXEL_UNPACK_BUFFER、GL_COPY_READ_BUFFER、GL_COPY_WRITE_BUFFER、GL_TRANSFORM_FEEDBACK_BUFFER或GL_UNIFORM_BUFFER。a c c e s s 必須是GL_READ_ONLY、GL_WRITE_ONLY或GL_READ_WRITE之一,表示客戶可以對(duì)數(shù)據(jù)進(jìn)行的操作。

如果這個(gè)緩沖區(qū)無法被映射(把OpenGL錯(cuò)誤狀態(tài)設(shè)置為GL_OUT_OF_MEMORY)或者它以前已經(jīng)被映射(把OpenGL錯(cuò)誤狀態(tài)設(shè)置為GL_INVALID_OPERATION),glMapBuffer()將返回NULL。

在完成了對(duì)數(shù)據(jù)存儲(chǔ)的訪問之后,可以調(diào)用glUnmapBuffer()取消對(duì)這個(gè)緩沖區(qū)的映射。

GLboolean?glUnmapBuffer(GLenum?target);?

表示對(duì)當(dāng)前綁定緩沖區(qū)對(duì)象的更新已經(jīng)完成, 并且這個(gè)緩沖區(qū)可以釋放。t a rg e t 必須是GL_ARRAY_BUFFER、GL_ELEMENT_ARRAY_BUFFER、GL_PIXEL_PACK_BUFFER,GL_PIXEL_UNPACK_BUFFER、GL_COPY_READ_BUFFER、GL_COPY_WRITE_BUFFER、GL_TRANSFORM_FEEDBACK_BUFFER或GL_UNIFORM_BUFFER。

下面是一個(gè)簡(jiǎn)單的例子,說明了如何選擇性地更新數(shù)據(jù)元素。我們將使用glMapBuffer()獲取一個(gè)指向緩沖區(qū)對(duì)象中的數(shù)據(jù)(這些數(shù)據(jù)包含了三維的位置坐標(biāo))的指針,然后,只更新z坐標(biāo)。

GLfloat* data; data = (GLfloat*) glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE); if (data != (GLfloat*) NULL) { for( i = 0; i < 8; ++i ) data[3*i+2] *= 2.0; /* Modify Z values */ glUnmapBuffer(GL_ARRAY_BUFFER); } else { /* Handle not being able to update data */ }

如果只需要更新緩沖區(qū)中相對(duì)較少的值(與值的總體數(shù)目相比),或者更新一個(gè)很大的緩沖區(qū)對(duì)象中的很小的連續(xù)范圍的值,使用glMapBufferRange()效率更高。它允許只修改所需的范圍內(nèi)的數(shù)據(jù)值。

GLvoid *glMapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);

?

返回一個(gè)指針, 指向與t a rg e t 相關(guān)聯(lián)的當(dāng)前綁定緩沖區(qū)對(duì)象的數(shù)據(jù)存儲(chǔ)。t a rg e t 可以是GL_ARRAY_BUFFER、GL_ELEMENT_ARRAY_BUFFER、GL_PIXEL_PACK_BUFFER、GL_PIXEL_UNPACK_BUFFER、GL_COPY_READ_BUFFER、GL_COPY_WRITE_BUFFER、GL_TRANSFORM_FEEDBACK_BUFFER或GL_UNIFORM_BUFFER。offset和length指定了映射的范圍。access是GL_MAP_READ_BIT和GL_MAP_WRITE_BIT的一個(gè)位掩碼組合,表示客戶可以對(duì)數(shù)據(jù)進(jìn)行的操作;也可以是GL_MAP_INVALIDATE_RANGE_BIT、GL_MAP_INVALIDATE_BUFFER_BIT、GL_MAP_FLUSH_EXPLICIT_BIT或GL_MAP_UNSYNCHRONIZED_BIT,它們針對(duì)OpenGL應(yīng)該如何管理緩沖區(qū)中的數(shù)據(jù)給出提示。

如果發(fā)生錯(cuò)誤,glMapBufferRange()將返回NULL。如果offset或length為負(fù)值,或者offset+length比緩沖區(qū)的大小還要大,將會(huì)產(chǎn)生GL_INVALID_VALUE。如果不能獲取足夠的內(nèi)存來映射緩沖區(qū),將會(huì)產(chǎn)生G L _ O U T _ O F _ M E M O RY錯(cuò)誤。如果發(fā)生如下的任何一種情況, 將會(huì)產(chǎn)生GL_INVALID_OPERATION: 緩沖區(qū)已經(jīng)映射; a c c e s s 沒有GL_MAP_READ_BIT或G L _ M A P _ W R I T E _ B I T 設(shè)置; a c c e s s 擁有G L _ M A P _ R E A D _ B I T 設(shè)置, 并且GL_MAP_INVALIDATE_RANGE_BIT、GL_MAP_INVALIDATE_BUFFER_BIT或GL_MAP_UNSYNCHRONIZED_BIT中的任何一個(gè)也設(shè)置了;access中的GL_MAP_WRITE_BIT和GL_MAP_FLUSH_EXPLICIT_BIT都設(shè)置了。

使用glMapBufferRange(),可以通過在access中設(shè)置額外的位來指定可選的提示。這些標(biāo)志描述了在映射之前OpenGL服務(wù)器需要如何保護(hù)緩沖區(qū)中原有的數(shù)據(jù)。這個(gè)提示用來幫助OpenGL實(shí)現(xiàn)確定需要保留哪些數(shù)據(jù)值,以及保持這些數(shù)據(jù)的任何內(nèi)部拷貝正確和一致需要達(dá)到多長(zhǎng)時(shí)間。

正如表2-7中所述,當(dāng)使用glMapBufferRange()映射一個(gè)緩沖區(qū)的時(shí)候,若在access標(biāo)志中指定了GL_MAP_FLUSH_EXPLICIT_BIT,應(yīng)該通過調(diào)用glFlushMappedBufferRange()向OpenGL表明映射緩沖區(qū)中的范圍需要修改。

表2-7 glMapBufferRange()的access參數(shù)值

?


GLvoid?glFlushMappedBufferRange(GLenum?target,?GLintptr?offset,GLsizeiptr?length);?
?

表示一個(gè)緩沖區(qū)范圍中的值已經(jīng)修改,這可能引發(fā)OpenGL服務(wù)器更新緩沖區(qū)對(duì)象的緩存版本。target必須是如下值之一:GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER、GL_PIXEL_PACK_BUFFER、GL_PIXEL_UNPACK_BUFFER、GL_COPY_READ_BUFFER、GL_COPY_WRITE_BUFFER, GL_TRANSFORM_FEEDBACK_BUFFER或GL_UNIFORM_BUFFER。offset和length指定了映射緩沖區(qū)區(qū)域的范圍,它們相對(duì)于緩沖區(qū)映射范圍的開始處。

如果o f f s e t 或l e n g t h 為負(fù)值, 或者o f f s e t + l e n g t h 比映射區(qū)域的大小還要大, 將會(huì)產(chǎn)生GL_INVALID_VALUE。如果沒有緩沖區(qū)綁定到target(例如,在glBindBuffer()調(diào)用中,0指定為綁定到target的緩沖區(qū)),或者如果綁定到target的緩沖區(qū)沒有映射,或者如果它映射了卻沒有設(shè)置GL_MAP_FLUSH_EXPLICIT_BIT,將會(huì)產(chǎn)生一個(gè)GL_INVALID_OPERATION錯(cuò)誤。

在緩沖區(qū)對(duì)象之間復(fù)制數(shù)據(jù)

有時(shí)候,我們可能需要把數(shù)據(jù)從一個(gè)緩沖區(qū)對(duì)象復(fù)制到另一個(gè)緩沖區(qū)對(duì)象。在OpenGL 3.1以前的版本中,這個(gè)過程分兩步:

1) 把數(shù)據(jù)從緩沖區(qū)對(duì)象復(fù)制到應(yīng)用程序的內(nèi)存中。可以通過以下兩種方法之一來做到:映射緩沖區(qū)并將其復(fù)制到本地內(nèi)存緩沖區(qū)中,或者調(diào)用glGetBufferSubData()從服務(wù)器復(fù)制數(shù)據(jù)。

2) 通過綁定到新的對(duì)象,然后使用glBufferData()發(fā)送新的數(shù)據(jù)(或者如果只是替換一個(gè)子集,使用glBufferSubData()),來更新另一個(gè)緩沖區(qū)對(duì)象中的數(shù)據(jù)。也可以映射緩沖區(qū),然后把數(shù)據(jù)從一個(gè)本地內(nèi)存緩沖區(qū)復(fù)制到映射的緩沖區(qū)。

在OpenGL 3.1中,glCopyBufferSubData()命令復(fù)制數(shù)據(jù),而不需要迫使數(shù)據(jù)在應(yīng)用程序的內(nèi)存中做短暫停留。

void glCopyBufferSubData(GLenum readbuffer, GLenum writebuffer, GLintptr readoffset, GLintptr writeoffset, GLsizeiptr size);

?

把數(shù)據(jù)從與readbuffer相關(guān)聯(lián)的緩沖區(qū)對(duì)象復(fù)制到綁定到writebuffer的緩沖區(qū)對(duì)象。readbuffer和writebuffer必須是如下的值之一: GL_ARRAY_BUFFER, GL_COPY_READ_BUFFER、GL_COPY_WRITE_BUFFER、GL_ELEMENT_ARRAY_BUFFER, GL_PIXEL_PACK_BUFFER、GL_PIXEL_UNPACK_BUFFER、GL_TEXTURE_BUFFER、GL_TRANSFORM_ FEEDBACK_BUFFER或GL_UNIFORM_BUFFER。

readoffset和size指定了復(fù)制到目標(biāo)緩沖區(qū)對(duì)象中的數(shù)據(jù)的數(shù)量,會(huì)從writeoffset開始替換同樣大小的數(shù)據(jù)。

下面的情形會(huì)導(dǎo)致GL_INVALID_VALUE錯(cuò)誤:readoffset、writeoffset或size為負(fù)值;readoffset +size超過了綁定到readbuffer的緩沖區(qū)對(duì)象的范圍;writeoffset + size超過了綁定到writebuffer的緩沖區(qū)對(duì)象的范圍;如果readbuffer和writebuffer綁定到同一個(gè)對(duì)象,并且readoffset和size所指定的區(qū)域與writeoffset和size所確定的區(qū)域有交叉。

如果readbuffer或writebuffer中的任意一個(gè)綁定為0,或者任意一個(gè)緩沖區(qū)是當(dāng)前映射的,將會(huì)產(chǎn)生L_INVALID_OPERATION錯(cuò)誤。

清除緩沖區(qū)對(duì)象

完成了對(duì)緩沖區(qū)對(duì)象的操作之后,可以釋放它的資源,并使它的標(biāo)識(shí)符可以由其他緩沖區(qū)對(duì)象使用。為此,可以調(diào)用glDeleteBuffers()。被刪除的當(dāng)前綁定緩沖區(qū)對(duì)象的所有綁定都將重置為零。

void?glDeleteBuffers(GLsizei?n,?const?GLuint?*buffers);?

刪除n個(gè)緩沖區(qū)對(duì)象,它們的名稱就是buffers數(shù)組的元素。釋放的緩沖區(qū)對(duì)象可以被復(fù)用(例如,通過調(diào)用glGenBuffers())。

如果一個(gè)緩沖區(qū)對(duì)象是在綁定時(shí)刪除的,這個(gè)對(duì)象的所有綁定都重置為默認(rèn)的緩沖區(qū)對(duì)象,就像以0作為指定的緩沖區(qū)對(duì)象參數(shù)調(diào)用了glBindBuffer()一樣。如果試圖刪除不存在的緩沖區(qū)對(duì)象或名稱為0的緩沖區(qū)對(duì)象,這個(gè)操作將被忽略,并不會(huì)產(chǎn)生錯(cuò)誤。

使用緩沖區(qū)對(duì)象存儲(chǔ)頂點(diǎn)數(shù)組數(shù)據(jù)

要在緩沖區(qū)對(duì)象中存儲(chǔ)頂點(diǎn)數(shù)組數(shù)據(jù),需要給應(yīng)用程序添加如下步驟

1) 生成緩沖區(qū)對(duì)象標(biāo)識(shí)符(這個(gè)步驟是可選的)。

2) 綁定一個(gè)緩沖區(qū)對(duì)象,確定它是用于存儲(chǔ)頂點(diǎn)數(shù)據(jù)還是索引。

3) 請(qǐng)求數(shù)據(jù)的存儲(chǔ)空間,并且對(duì)這些數(shù)據(jù)元素進(jìn)行初始化(后一個(gè)步驟可選)。

4) 指定相對(duì)于緩沖區(qū)起始位置的偏移量,對(duì)諸如glVertexPointer()這樣的頂點(diǎn)數(shù)組函數(shù)進(jìn)行初始化。

5) 綁定適當(dāng)?shù)木彌_區(qū)對(duì)象,用于渲染。

6) 使用適當(dāng)?shù)捻旤c(diǎn)數(shù)組渲染函數(shù)進(jìn)行渲染,例如glDrawArrays()或glDrawElements()。

如果想初始化多個(gè)緩沖區(qū)對(duì)象,就需要為每個(gè)緩沖區(qū)對(duì)象重復(fù)步驟2)~4)。

頂點(diǎn)數(shù)組數(shù)據(jù)的所有“格式”都適用于緩沖區(qū)對(duì)象。如第2.6.2節(jié)所述,頂點(diǎn)、顏色、光照法線或其他任何類型的相關(guān)聯(lián)頂點(diǎn)數(shù)據(jù)都可以存儲(chǔ)在緩沖區(qū)對(duì)象中。另外,第2.6.6節(jié)所描述的混合頂點(diǎn)數(shù)組數(shù)據(jù)也可以存儲(chǔ)在緩沖區(qū)對(duì)象中。不論是哪種情況,我們都將創(chuàng)建一個(gè)緩沖區(qū)對(duì)象,保存所有作為頂點(diǎn)數(shù)組使用的數(shù)據(jù)。

就像在客戶機(jī)的內(nèi)存中指定內(nèi)存地址一樣(OpenGL應(yīng)該在客戶機(jī)的內(nèi)存中訪問頂點(diǎn)數(shù)組數(shù)據(jù)),需要根據(jù)機(jī)器單位(通常是字節(jié))指定緩沖區(qū)對(duì)象中數(shù)據(jù)的偏移量。為了幫助讀者理解偏移量的計(jì)算,我們將使用下面這個(gè)宏來簡(jiǎn)化偏移量的表達(dá)形式:

#define?BUFFER_OFFSET(bytes)?((GLubyte*)?NULL?+?(bytes))?

例如,如果每個(gè)頂點(diǎn)的顏色和位置數(shù)據(jù)是浮點(diǎn)類型,也許它們可以用下面這個(gè)數(shù)組來表示:

GLfloat vertexData[][6] = { { R0, G0, B0, X0, Y0, Z0 }, { R1, G1, B1, X1, Y1, Z1 }, ... { Rn, Gn, Bn, Xn, Yn, Zn } };

這個(gè)數(shù)組用于初始化緩沖區(qū)對(duì)象,可以用兩個(gè)獨(dú)立的頂點(diǎn)數(shù)組調(diào)用來指定數(shù)據(jù),其中一個(gè)表示顏色,另一個(gè)表示頂點(diǎn):

glColorPointer(3, GL_FLOAT, 6*sizeof(GLfloat),BUFFER_OFFSET(0)); glVertexPointer(3, GL_FLOAT, 6*sizeof(GLfloat), BUFFER_OFFSET(3*sizeof(GLfloat)); glEnableClientState(GL_COLOR_ARRAY); glEnableClientState(GL_VERTEX_ARRAY);

相反, 由于v e r t e x D a t a 中的數(shù)據(jù)與一個(gè)混合頂點(diǎn)數(shù)組的格式相匹配, 因此可以使用glInterleavedArrays()來指定頂點(diǎn)數(shù)組數(shù)據(jù):

glInterleavedArrays(GL_C3F_V3F,?0,?BUFFER_OFFSET(0));?

示例程序2-17綜合了所有這些內(nèi)容,演示了如何使用包含頂點(diǎn)數(shù)據(jù)的緩沖區(qū)對(duì)象。這個(gè)例子創(chuàng)建了兩個(gè)緩沖區(qū)對(duì)象,一個(gè)包含頂點(diǎn)數(shù)據(jù),另一個(gè)包含索引數(shù)據(jù)。

示例程序2-17 在緩沖區(qū)對(duì)象中使用頂點(diǎn)數(shù)據(jù)

#define VERTICES 0 #define INDICES 1 #define NUM_BUFFERS 2 GLuint buffers[NUM_BUFFERS]; GLfloat vertices[][3] = { { -1.0, -1.0, -1.0 }, { 1.0, -1.0, -1.0 }, { 1.0, 1.0, -1.0 }, { -1.0, 1.0, -1.0 }, { -1.0, -1.0, 1.0 }, { 1.0, -1.0, 1.0 }, { 1.0, 1.0, 1.0 }, { -1.0, 1.0, 1.0 } }; GLubyte indices[][4] = { { 0, 1, 2, 3 }, { 4, 7, 6, 5 }, { 0, 4, 5, 1 }, { 3, 2, 6, 7 }, { 0, 3, 7, 4 }, { 1, 5, 6, 2 } }; glGenBuffers(NUM_BUFFERS, buffers); glBindBuffer(GL_ARRAY_BUFFER, buffers[VERTICES]); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); glVertexPointer(3, GL_FLOAT, 0, BUFFER_OFFSET(0)); glEnableClientState(GL_VERTEX_ARRAY); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[INDICES]); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices GL_STATIC_DRAW); glDrawElements(GL_QUADS, 24, GL_UNSIGNED_BYTE, BUFFER_OFFSET(0));

?

?

轉(zhuǎn)載于:https://www.cnblogs.com/Anita9002/p/4980653.html

總結(jié)

以上是生活随笔為你收集整理的OPenGL中的缓冲区对象的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。