OpenGL超級寶典筆記(n)PBO緩衝區

2021-08-28 14:03:53 字數 4023 閱讀 7340

前略好幾章都沒放上來,以後再補上吧。

之前一直使用gltools的glbatch來填充資料傳給shader,現在直接用自己的buffer來傳資料了。

不外乎幾步:

弄乙個buffer指標,其實弄乙個buffer陣列也可以了,陣列可以記得個數,指標可不能,容易出事兒

就這麼著吧,算是上一步弄了個buffer陣列,那陣列名就是乙個指標了,現在把指標傳給opengl來分配乙個buffer

unsigned

int n =1;

gluint buffers[n]

;glgenbuffer

(n, buffers)

;

接下來就是針對某乙個buffer來bind了,bind的時候要說明用處,比如

glbindbuffer

(gl_array_buffer, buffers[0]

);// 當然想寫成*buffers也可以

上面提及這種型別就是可以拿來放頂點啊,顏色啊,紋理座標啥的。

迄今為止見過的還有gl_texture_buffer,gl_uniform_buffer用完之後不想要了就要刪除,但是要保證buffer沒有被繫結為任何用途。

gldeletebuffers(1

, buffers)

;

另外,怎麼傳輸資料是個問題。

glbufferdata

(gl_pixel_pack_buffer, datasize, data, gl_dynamic_copy)

;

第乙個引數是繫結點(what?),第二個引數是用途。

不知道用啥的時候就用gl_dynamic_draw

使用glbufferdata之後原來緩衝區的所有東西會被刪除,重新進行填充。

如只想更新部分資料而不清空舊有,可以使用

void

glbuffersubdata

(glenum target, intptr offset, sizeiptr size,

const

void data*

);

為啥使用緩衝區。

在使用緩衝區的時代之前,要向opengl傳遞紋理需要通過cpu先把內容複製到ram,再在需要的時候,命令cpu把內容從ram傳給opengl。壞處有二:

使用緩衝區之後,這一過程變成了:cpu把內容交給pbo,而pbo是opengl管理的(也即是gpu管理),在需要的時候opengl直接通過dma(直接訪問)來讀取pbo,不需要經過cpu。這就是非同步過程,不影響cpu週期。

圖如下:

以上均整理自:

關於pack和unpack。

gl_pixel_pack_buffer模式下時,使用glreadpixels可以從幀快取讀取畫素寫到pbo。

gl_pixel_unpack_buffer模式下,使用gldrawpixels把畫素從pbo寫入幀快取。

使用void* glmapbuffer(target, access)可以獲得位址,如果找不到會返回nullptr。

target可能的值有:

access可能的值:

如果gpu正在操作這個buffer,glmapbuffer就會一直等待直到gpu同步完buffer資訊。為了避免這個無用的等待,最好就是使用空指標來呼叫glbufferdata,這會讓這塊空記憶體上啥都沒有,然後馬上呼叫glmapbuffer。這時,opengl會丟棄老的buffer,然後重新分配一塊新的記憶體給它。

注意

在使用完pbo之後,必須呼叫glunmapbuffer(),如果成功了,會返回乙個gl_true。

在分配的時候沒啥要注意的,如果是為紋理分配,那分配的空間就是長*寬*畫素大小。

從當前幀獲取畫素資料,使用glreadpixels

不使用pbo:

void

*data =

(void*)

malloc

(pixeldatasize)

;glreadbuffer

(gl_back_left)

;glreadpixels(0

,0,getwidth()

,getheight()

, gl_rgb, gl_unsigned_btye, pixeldata)

;

使用pbo:

glreadbuffer

(gl_back_left)

;glbindbuffer

(gl_pixel_pack_buffer, pixbuffobjs[0]

);glreadpixels(0

,0,getwidth()

,getheight()

, gl_rgb, gl_unsigned_byte,

null

);

這就把資料讀入了pbo。

使用pbo來做模糊效果。思路是儲存前面五幀來和當前幀做混合。

說一下主要套路:

setup階段

從硬碟讀出bmp紋理

申請6個texture,全都用bmp紋理初始化

申請乙個buffer並初始化,初始化的內容可以是空指標,但大小一定要指定

// 這個時候啥功能都可以,pack或者unpack都行

glbindbuffer

(gl_pixel_pack_buffer, g_bufferobjs[0]

);glbufferdata

(gl_pixel_pack_buffer, size, dataptr, gl_dynamic_draw)

;// 解綁

glbindbuffer

(gl_pixel_pack_buffer,0)

;

render階段

從螢幕把畫素打包到buffer

glbindbuffer

(gl_pixel_pack_buffer, g_bufferobjs[0]

);glreadpixels(0

,0, screenwidth, screenheight, gl_rgb, gl_unsigned_byte,

nullptr);

glbindbuffer

(gl_pixel_pack_buffer,

*g_bufferobjs)

;

這個時候buffer裡面已經是慢慢的螢幕資訊啦!接下來要從buffer裡面把資訊寫入到texture。先把buffer先切到解包模式,才能寫入到texture或者螢幕,然後切換到目標texture,寫入,最後解綁buffer。

glbindbuffer

(gl_pixel_unpack_buffer,

*g_bufferobjs)

;glactivetexture

(gl_texture0 +

getblurtarget0()

);// 當資料是nullptr的時候,就讀緩衝區~

glteximage2d

(gl_texture_2d,

0, gl_rgb, screenwidth, screenheight,

0, gl_unsigned_byte,

null

);

最後一步是改寫shader。片段shader要去讀0~5號sampler,然後把結果疊加起來!

讀書筆記 OpenGL超級寶典

對於某些函式的理解 glclear和glclearcolor glclearcolor指定glclear清除特定緩衝區時使用的值。glflush 讓所有已傳送的命令盡快的由實際的繪製引擎執行。glviewport 前兩個引數指的是左下角。glpushmatrix glrotatef glbegin和...

OpenGL 3D 超級寶典學習筆記

2d笛卡兒座標 由乙個x座標和乙個y座標構成,x座標測量水平方向的位置,而y座標則測試垂直方向的位置,原點 x 0,y 0 兩根軸從負無窮擴充套件到正無窮,兩軸垂直相交。視口viewport 裁剪區域的高度與寬度一般不與視窗的寬度與高度相匹配,因此座標系統從邏輯笛卡兒座標對映到物理螢幕畫素座標,這種...

openGL超級寶典 筆記 8 1緩衝區

特性 緩衝區儲存在gpu視訊記憶體中,可提供高速高效的訪問視訊記憶體的方式。作用 可以將資料從乙個渲染管線移動到另乙個渲染管線 gpu視訊記憶體中 可以從乙個物件繫結到另乙個物件.可以將gpu中資料移動到合適位置,不需cpu介入。如pbo移動資料到texture中 緩衝區的建立,binding,刪除...