OpenGL 中關於ImageTexture使用中遇到的兩個問題 —— 快速清空 與 讀寫錯誤


 

  普通Texture無法在一個pass中完成讀和寫,且無法操作一個給定位置的數據,所以只能使用ImageTexture,使用時遇到了兩個問題:

  1、快速清空

  ImageTexture 使用的是一張普通的 texture 紋理,texture 被包裝為ImageTexture,故可以直接將texture清空即可。

    texture的清空方法:

    a、傳值給texture(CPU-->GPU)、

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()分別設置清空后顏色緩存、深度緩存和模板緩存中的默認值。

    在每一幀渲染前,調用glClear()並傳入GL_COLOR_BUFFER_BITGL_DEPTH_BUFFER_BITGL_STENCIL_BUFFER_BIT或它們的位組合進行對應緩存的清空操作。

    或者:在OpenGL3.0中支持了  void glClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value)。

       buffer可以傳入GL_COLORGL_DEPTHGL_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);
}

 

  2、讀寫錯誤

    我需要計算場景的一張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之間不是完全順序執行的,會同時執行,導致出現並行讀寫錯誤。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM