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

 

  普通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_BITGL_DEPTH_BUFFER_BITGL_STENCIL_BUFFER_BIT或它們的位組合進行對應緩存的清空操做。it

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

       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);
}

 

  二、讀寫錯誤

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

相關文章
相關標籤/搜索