2011-06-21 127 views
3

我在這裏讀過這個問題:Can example "GLImageProcessing" work with multi filters但是,我仍然不明白如何編輯GLImageProcessing的示例代碼來支持多個過濾器。這裏是我現在在ImageGL的drawGL中做的代碼。GLImageProcessing多個過濾器?

任何幫助?

void drawGL(int wide, int high, float val, int mode) 
{ 
    GLuint ResultFBO; 
    GLuint ResultTexture; 
    static int prevmode = -1; 
    typedef void (*procfunc)(V2fT2f *, float); 

    typedef struct { 
     procfunc func; 
     procfunc degen; 
    } Filter; 

    const Filter filter[] = { 
     { brightness    }, 
     { contrast    }, 
     { extrapolate, greyscale }, 
     { hue     }, 
     { extrapolate, blur  }, // The blur could be exaggerated by downsampling to half size 
    }; 
#define NUM_FILTERS (sizeof(filter)/sizeof(filter[0])) 
    rt_assert(mode < NUM_FILTERS); 


    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    glOrthof(0, wide, 0, high, -1, 1); 
    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 
    glScalef(wide, high, 1); 

    glBindTexture(GL_TEXTURE_2D, Input.texID); 

    // Remember the FBO being used for the display framebuffer 
    glGetIntegerv(GL_FRAMEBUFFER_BINDING_OES, (GLint *)&SystemFBO); 

    // Create the texture and the FBO the will hold the result of applying the first filter 
    glGenTextures(1, &ResultTexture); 
    glBindTexture(GL_TEXTURE_2D, ResultTexture); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, wide, high, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); 
    glGenFramebuffersOES(1, &ResultFBO); 
    glBindFramebufferOES(GL_FRAMEBUFFER_OES, ResultFBO); 
    glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, ResultTexture, 0); 

    // bind the result FBO 
    glBindFramebufferOES(GL_FRAMEBUFFER_OES, ResultFBO); 


    // apply 1st filter 
    glViewport(0, 0, wide, high); 
    filter[mode].func(flipquad, val); 

    // restore original frame buffer object 
    glBindFramebufferOES(GL_FRAMEBUFFER_OES, SystemFBO); 

    // use ResultTexture as input for the 2nd filter 
    glBindTexture(GL_TEXTURE_2D, ResultTexture); 

    // apply 2nd filter 
    glViewport(0, 0, wide, high); 
    filter[2].func(flipquad, val); 

    glCheckError(); 
} 

回答

2

您可以通過兩個緩衝區之間交替擴展該方案:

GLuint stageTextures[2]; 
glGenTextures(2, stageTextures); 

glBindTexture(GL_TEXTURE_2D, stageTexture[0]); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, wide, high, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); 

glBindTexture(GL_TEXTURE_2D, stageTexture[1]); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, wide, high, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); 

GLuint stageFBO[2]; 
glGenFramebuffersOES(2, stageFB0); 

glBindFramebufferOES(GL_FRAMEBUFFER_OES, stageFBO[0]); 
glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, stageTexture[0], 0);  

glBindFramebufferOES(GL_FRAMEBUFFER_OES, stageFBO[1]); 
glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, stageTexture[1], 0);  

// bind stage 1, sourcing stage 0 
glBindFramebufferOES(GL_FRAMEBUFFER_OES, stageFBO[1]); 
glBindTexture(GL_TEXTURE_2D, stageTexture[0]); 

// apply 1st filter 
glViewport(0, 0, wide, high); 
filter[mode].func(flipquad, val); 

glBindTexture(GL_TEXTURE_2D, 0); // must unbind texture before FBO with that texture attached can be bound 


// bind stage 0, sourcing stage 1 
glBindFramebufferOES(GL_FRAMEBUFFER_OES, stageFBO[0]); 
glBindTexture(GL_TEXTURE_2D, stageTexture[1]); 

// apply 2nd filter 
glViewport(0, 0, wide, high); 
filter[mode].func(flipquad, val); 

glBindTexture(GL_TEXTURE_2D, 0); // must unbind texture before FBO with that texture attached can be bound 

// bind stage 1, sourcing stage 0 
glBindFramebufferOES(GL_FRAMEBUFFER_OES, stageFBO[1]); 
glBindTexture(GL_TEXTURE_2D, stageTexture[0]); 

// apply 3rd filter 
glViewport(0, 0, wide, high); 
filter[mode].func(flipquad, val); 

glBindTexture(GL_TEXTURE_2D, 0); // must unbind texture before FBO with that texture attached can be bound 

// and so on. finally 

// Bind SystemFBO so the screen is the target, sourcing stage 0/1 
// (depending on if a even or odd number of filters involved) 
glBindFramebufferOES(GL_FRAMEBUFFER_OES, SystemFBO); 
glBindTexture(GL_TEXTURE_2D, stageTexture[...]); // set to follow the scheme above 

// apply n-th filter 
glViewport(0, 0, wide, high); 
filter[mode].func(flipquad, val); 
+0

那麼究竟該去哪裏呢?我從「//記住用於顯示幀緩衝區的FBO」開始取代所有內容,然後放在我的代碼中,但仍然沒有運氣。 – Flipper

+1

在最後一步中,您必須繪製到屏幕上,而不是幀緩衝區。我編輯了這個代碼示例。 – datenwolf

+0

當我第一次加載它時,我仍然會看到一個黑色的黑色圖像,然後當我將滑塊向左移動到黑色時,它就會變成白色。在像Hue這樣的其他設置中,圖像在那裏,但顯示兩次......其中一個被翻轉。任何想法發生了什麼? – Flipper

1

我能多個過濾器結合起來,這裏是基於這裏提出的建議,完整的方法。

void drawGL(int wide, int high, float val, int mode) 
{ 

    static int prevmode = -1; 
    typedef void (*procfunc)(V2fT2f *, float); 

    typedef struct { 
      procfunc func; 
      procfunc degen; 
    } Filter; 

    const Filter filter[] = { 
      { brightness    }, 
      { contrast    }, 
      { extrapolate, greyscale }, 
      { hue     }, 
      { extrapolate, blur  },  // The blur could be exaggerated by downsampling to half size 
    }; 
    #define NUM_FILTERS (sizeof(filter)/sizeof(filter[0])) 
    rt_assert(mode < NUM_FILTERS); 

    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    glOrthof(0, wide, 0, high, -1, 1); 
    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 
    glScalef(wide, high, 1); 

glGetIntegerv(GL_FRAMEBUFFER_BINDING_OES, (GLint *)&SystemFBO); 
// Create the texture and the FBO the will hold the result of applying the first filter 
glGenTextures(1, &ResultTexture.texID); 
glBindTexture(GL_TEXTURE_2D, ResultTexture.texID); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, wide, high, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); 
glGenFramebuffersOES(1, &ResultTextureFBO); 
glBindFramebufferOES(GL_FRAMEBUFFER_OES, ResultTextureFBO); 
glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, ResultTexture.texID, 0); 

glBindFramebufferOES(GL_FRAMEBUFFER_OES, ResultTextureFBO); 
glBindTexture(GL_TEXTURE_2D, Input.texID); 

    glViewport(0, 0, wide, high); 
brightness(flipquad, val); 
    glCheckError(); 

glBindFramebufferOES(GL_FRAMEBUFFER_OES, SystemFBO); 
glBindTexture(GL_TEXTURE_2D, ResultTexture.texID); 

    glViewport(0, 0, wide, high); 
hue(fullquad, val); 
    glCheckError();  
}