GLSL - 片段着色器(模糊)-> 黑屏

5
我已经努力尝试让这个工作在过去几天中,但我真的开始变得绝望了。如果您有任何建议,我将非常感激。
我一直在尝试做以下事情:
- 将场景渲染到FBO - 使用glsl着色器模糊附加的纹理 - 将结果纹理渲染到屏幕对齐的四边形上
问题是:
如果我启用片段着色器(水平模糊),我确实会在我的四边形上获得一个模糊的图像,但仅在第一帧或更多时,之后就全黑了。
我怀疑我传递纹理给我的着色器的方式有问题:
    horizontalBlurVertex.enable();

    horizontalBlurFragment.enable();

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, fboTexture);
    glUniform1i(glGetUniformLocation(horizontalBlurFragment.program, "RTScene"), 0);

编辑:

还有一条信息: 如果我删除glUniform1i(glGetUniformLocation(horizontalBlurFragment.program,“RTScene”),0);我得到完全相同的结果。这意味着我的着色器根本没有获得任何纹理数据。

来源:

顶点着色器:

varying vec2 vTexCoord;

void main(void)
{
   gl_FrontColor = gl_Color;
   gl_Position = ftransform();

   vec2 Pos;
   Pos = sign(gl_Vertex.xy);

   gl_Position = vec4(Pos, 0.0, 1.0);

   vTexCoord = Pos * 0.5 + 0.5;
}

片段着色器:

uniform sampler2D RTScene;
varying vec2 vTexCoord;

const float blurSize = 1.0/800.0;
const float weightSum = 70.0 + 2.0 * (1.0 + 8.0 + 28.0 + 56.0);

void main(void)
{
   vec4 sum = vec4(0.0);

   sum += texture2D(RTScene, vec2(vTexCoord.x - 4.0*blurSize, vTexCoord.y)) * 1.0 / weightSum;
   sum += texture2D(RTScene, vec2(vTexCoord.x - 3.0*blurSize, vTexCoord.y)) * 8.0 / weightSum;
   sum += texture2D(RTScene, vec2(vTexCoord.x - 2.0*blurSize, vTexCoord.y)) * 28.0 / weightSum;
   sum += texture2D(RTScene, vec2(vTexCoord.x - blurSize, vTexCoord.y)) * 56.0 / weightSum;
   sum += texture2D(RTScene, vec2(vTexCoord.x, vTexCoord.y)) * 70.0 / weightSum;
   sum += texture2D(RTScene, vec2(vTexCoord.x + blurSize, vTexCoord.y)) * 56.0 / weightSum;
   sum += texture2D(RTScene, vec2(vTexCoord.x + 2.0*blurSize, vTexCoord.y)) * 28.0 / weightSum;
   sum += texture2D(RTScene, vec2(vTexCoord.x + 3.0*blurSize, vTexCoord.y)) * 8.0 / weightSum;
   sum += texture2D(RTScene, vec2(vTexCoord.x + 4.0*blurSize, vTexCoord.y)) * 1.0 / weightSum;

   gl_FragColor = sum;
}

渲染到帧缓冲对象:

//handels
    GLuint fbo, fboTexture, fboDepthbuffer;

    // generate namespace for the frame buffer, colorbuffer and depthbuffer
    glGenFramebuffersEXT(1, &fbo);
    glGenTextures(1, &fboTexture);
    glGenRenderbuffersEXT(1, &fboDepthbuffer);

    //switch to our fbo so we can bind stuff to it
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);

    //create the colorbuffer texture and attach it to the frame buffer
    glGenTextures(1, &fboTexture);
    glBindTexture(GL_TEXTURE_2D, fboTexture);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, fboTexture, 0);

    // create a render buffer as our depthbuffer and attach it
    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fboDepthbuffer);
    glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, width, height);
    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fboDepthbuffer);

    // Go back to regular frame buffer rendering
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

    glBindTexture(GL_TEXTURE_2D, 0);
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
        glPushAttrib(GL_VIEWPORT_BIT);
            glViewport(0, 0, width, height);
            glPushMatrix();
                glBegin(GL_QUADS);
                    glNormal3f(0.0, 0.0, 1.0);

                    glColor3f(1.0f, 1.0f, 0.0f);
                    glVertex3f(-0.1, 0.1, -1.0);

                    glColor3f(1.0f, 0.0f, 0.0f);
                    glVertex3f(0.1, 0.1, -1.0);

                    glColor3f(0.0f, 1.0f, 0.0f);
                    glVertex3f(0.1, -0.1, -1.0);

                    glColor3f(0.0f, 0.0f, 1.0f);
                    glVertex3f(-0.1, -0.1, -1.0);
                glEnd();
            glPopMatrix();
        glPopAttrib();
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

(这里不会发布我的ShaderLoader源代码,因为使用更简单的着色器(切换颜色等)完全可以正常工作)

如果您认为错误出现在其他地方,我很乐意发布一些额外的代码。


我不熟悉OpenFrameworks,但您需要在调用glUniform*之前调用glUseProgram。我不知道enable()是否会这样做。 - pmr
是的,那正是它所做的。就像我说的,没有统一参数的着色器也可以正常工作...不过还是感谢您花时间阅读所有这些内容。 - Oradon
这有点奇怪。绑定着色器需要一个程序,该程序是附加已编译的着色器对象并链接后的结果。我不明白两个看似无关的“enable()”调用如何实现这一点。 - pmr
当然有一个load()函数,编译/链接/生成程序对象等等... enable()只是调用glUseProgramObjectARB(program);。但再次强调ShaderLoader本身似乎工作正常。我得到了一个模糊的图像(第一帧),并且可以使用各种着色器,我只是在努力将纹理传递给我的着色器... - Oradon
啊,我觉得你没有使用正确的纹理坐标。请使用glMultiTexCoord0而不是顶点坐标。 - pmr
我尝试了glMultiTexCoord2f(GL_TEXTURE0, s, t),我想这就是你的意思。结果完全相同:第一帧呈现场景的图像水平模糊(如预期),之后是漆黑的屏幕... - Oradon
1个回答

1
问题已解决!
原来我愚蠢地在每一帧中都创建了我的fbo...现在完美地运行了。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接