将Sampler2D与着色器一起使用的问题

时间:2015-03-14 14:01:36

标签: opengl shader lwjgl fbo

!我知道有更简单的方法来绘制到屏幕而不是这个,但我需要以这种特定的方式做到这一点!

我通过fbo绘制纹理。 然后我使用着色器将其重新绘制到屏幕上,使用sampler2D(纹理)并使着色器将gl_fragColor设置为片段着色器所在的特定点处的sampler2D的颜色。

我遇到的问题是显示缓冲区(着色器正在绘制fbo)只是一个纯蓝色,即使我用蓝色背景为fbo绘制白色方块。

我的代码:

主渲染循环:

while(!Display.isCloseRequested()){
        //Drawing on the fbo a blue background and white square
        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboID);
        glColor3f(0,0,1);
        drawQuad(0,0,WIDTH,HEIGHT);
        glColor3f(1,1,1);
        drawQuad(0,0,50,50);

        //Trying to draw the texture from the previous fbo
        //on to the display buffer with a fragment shader,
        //however it only draws a blue background, no white square.

        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

        GL13.glActiveTexture(GL13.GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D,texID);
        glUseProgram(shaderProgram);
        glUniform1i(glGetUniformLocation(shaderProgram, "tex"), 0);
        glUniform1f(glGetUniformLocation(shaderProgram, "width"), WIDTH);
        glUniform1f(glGetUniformLocation(shaderProgram, "height"), HEIGHT);

        glBegin(GL_QUADS); {
            glVertex2f(0, 0);
            glVertex2f(0, HEIGHT);
            glVertex2f(WIDTH, HEIGHT);
            glVertex2f(WIDTH, 0);
        } glEnd();
        glUseProgram(0);

        Display.update();
    }

我的着色器:

uniform sampler2D tex;
uniform float width;
uniform float height;

void main() {
    vec4 color = texture2D( tex, gl_FragCoord.xy / vec2(width, height));
    gl_FragColor = color;
}

fbo的init方法:

    texID=glGenTextures();
    fboID=glGenFramebuffersEXT();

    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboID);
    glBindTexture(GL_TEXTURE_2D, texID);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, WIDTH, HEIGHT, 0,GL_RGBA, GL_INT, (java.nio.ByteBuffer) null);
    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,GL_COLOR_ATTACHMENT0_EXT,GL_TEXTURE_2D, texID, 0);
    glBindTexture(GL_TEXTURE_2D, 0);
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

我认为发生这种情况的一个原因可能是因为我没有正确地将Sampler2D传递给着色器但我不确定如何解决它。

如果有任何可以说明为什么会发生这种情况或如何解决它(或者甚至只是正确方向上的一点),我们将不胜感激!

(对不起英文不好!)

1 个答案:

答案 0 :(得分:1)

您已将来电转置为glUniform1i (...)glUseProgram (...)

执行glUniform1i(glGetUniformLocation(shaderProgram, "tex"), 0);时,当前活动的程序 0 ,实际上应该会产生以下错误:

  如果没有当前的程序对象,则生成

GL_INVALID_OPERATION

如果你交换上面提到的两行,那应该可以解决你的问题。将来,当某些东西不起作用时,你应该检查glGetError (...)


更新 :既然修复了原始问题,就不会正确设置纹理缩小过滤器。

要设置枚举,您必须使用glTexParameteri (...)glTexParameterf (...)将解释作为浮点数传递的值,GL_LINEAR 0x2601 )具有类型GLenum(32位无符号整数)。幸运的是,所有核心OpenGL枚举仅使用较低的16位,因此它们可以精确地表示为32位浮点数(可以表示最多2 24 的所有整数),但是你可以看到为什么你不想要将整数常量转换为浮点数。

因此,以下行:

glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

需要:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

更新2 :使用texture2D (...)时必须使用标准化纹理坐标。

gl_FragCoord.xy的范围为[ 0 width]和[ 0 height],超出了标准化范围任何大于 1x1 的帧缓冲区的范围。要解决这个问题,你必须除以宽度和高度。

texelFetch (...)允许您使用非标准化坐标,但它需要GLSL 1.30,您必须将gl_FragCoord.xy强制转换为ivec2才能使用它。如果你画的尺寸不同于窗户的FBO,也可能会给你带来不便。