普通Texture沒法在一個pass中完成讀和寫,且沒法操做一個給定位置的數據,因此只能使用ImageTexture,使用時遇到了兩個問題:緩存
一、快速清空this
ImageTexture 使用的是一張普通的 texture 紋理,texture 被包裝爲ImageTexture,故能夠直接將texture清空便可。spa
texture的清空方法:code
a、傳值給texture(CPU-->GPU)、blog
void Transfer2Texture(float* data) { glBindTexture(GL_TEXTURE_2D, this->textureID); if (channels == 1) glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_R, GL_FLOAT, data); if (channels == 2) glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RG, GL_FLOAT, data); if (channels == 3) glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_FLOAT, data); if (channels == 4) glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_FLOAT, data); glBindTexture(GL_TEXTURE_2D, 0); }
b、綁定到FBO內存
初始化時,調用glClearColor()
、glClearDepth()
及glClearStencil()
分別設置清空後顏色緩存、深度緩存和模板緩存中的默認值。ci
在每一幀渲染前,調用glClear()
並傳入GL_COLOR_BUFFER_BIT
、GL_DEPTH_BUFFER_BIT
、GL_STENCIL_BUFFER_BIT
或它們的位組合進行對應緩存的清空操做。it
或者:在OpenGL3.0中支持了 void glClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value)。io
buffer
能夠傳入GL_COLOR
、GL_DEPTH
或GL_STENCIL
,以指明咱們要清空哪一種緩存;模板
value
指明瞭清空後的默認值;
drawbuffer
用於多輸出緩存的狀況。
以上方法這裏都不適用:a方法須要CPU-->GPU傳輸數據很慢;b方法,texture已經被綁定封裝給ImageTexture,可能不能再綁定到FBO
後來查詢到能夠直接對ImageTexture清空數據!
c、直接清空ImageTexture
OpenGL須要版本4.4以上
void WKS::ImageTexture::InitData() { if (this->channels == 1) glClearTexImage(this->textureID, 0, GL_R, GL_FLOAT, NULL); if (this->channels == 2) glClearTexImage(this->textureID, 0, GL_RG, GL_FLOAT, NULL); if (this->channels == 3) glClearTexImage(this->textureID, 0, GL_RGB, GL_FLOAT, NULL); if (this->channels == 4) glClearTexImage(this->textureID, 0, GL_RGBA, GL_FLOAT, NULL); }
二、讀寫錯誤
我須要計算場景的一張occlusion mask,一個像素對應多個物體(大於等於2個物體)則置 1, 不然置爲 0
故須要使用一張ImageTexture,當出現兩個不一樣的物體ID則發現重疊了,故須要一個pass中的讀和寫同時存的操做。打印這張mask後發現,遮擋區域(1的位置)基本符合,可是會出現一些零星的 0 值,並且相機不移動時,mask也會變更(零星的0值會隨機出如今其它位置)。我感受是出現並行讀寫錯誤,可是OpenGL渲染場景是一個一個mesh繪製的,每渲染一個mesh是須要CPU向GPU發送一個Draw的命令的,故mesh之間應該自己就是有順序關係的,不會同時執行出現錯誤。但我後來仍是嘗試着在每一個mesh draw後面加了一個glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT) ——針對image 讀寫的內存屏障,結果問題解決了,太意外了!由此我猜測mesh Draw之間不是徹底順序執行的,會同時執行,致使出現並行讀寫錯誤。