GLImageProcessing多个过滤器?

时间:2011-06-21 13:18:09

标签: iphone opengl-es filter

我在这里已经阅读了这个问题:Can example "GLImageProcessing" work with multi filters但是,我仍然不明白如何编辑GLImageProcessing的示例代码以支持多个过滤器。这是我现在在Imaging.c的drawGL中所做的代码

任何帮助?

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 个答案:

答案 0 :(得分: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);

答案 1 :(得分: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();    
}