0
votes

! I am aware that there are easier ways to draw to the screen than this, but i need to do it this specific way !

I am drawing to a texture through a fbo. I am then using a shader to re-draw it onto the screen, doing so with a sampler2D (of the texture) and having the shader set gl_fragColor to the color of the sampler2D at the specific point the fragment shader is at.

The issue i am having is that the display buffer (which the shader is drawing the fbo to) is only a solid blue, even though i draw a white squares to the fbo with a blue background.

My Code:

Main Render Loop:

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

My Shader:

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

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

Init method for the fbo:

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

I think one reason why this is happening could be becuase i am not correctly passing the Sampler2D to the shader but i not sure how to fix it.

If any could tell why this is happening or how to fix it (or even just a point in the right direction) it would be much appreciated!

(Sorry for any bad English!)

1
Fixed pipelilne, i.e., functions like glBegin)/glEnd() doesnt mixes with programmatically pipeline (shaders). You cant use both at same timeAmadeus
@Amadeus: Yes you can, you just cannot use those functions in a core profile. It really has nothing to do with fixed-function operation; immediate mode was deprecated in OpenGL 3.0 and removed in 3.1. Of course the fixed-function pipeline was also deprecated and removed at the same time, so you might easily equate the two things as the same.Andon M. Coleman
@AndonM.Coleman Yes you can, but it can or can not render to screen, which gives you bugs that are difficult to findAmadeus
That would be true if glBegin (...), glEnd (...) and friends were part of the fixed-function pipeline, but they are not. They exist outside of the render pipeline altogether, they package vertex state together and define primitive topology before the first stage (vertex processing) even starts. An example of something that was part of the fixed-function pipeline would be vertex lighting, that used to be applied during vertex transform.Andon M. Coleman

1 Answers

1
votes

You have transposed your calls to glUniform1i (...) and glUseProgram (...).

At the time that glUniform1i(glGetUniformLocation(shaderProgram, "tex"), 0); is executed, the currently active program is 0 and that should in fact be generating the following error:

GL_INVALID_OPERATION is generated if there is no current program object.

If you swap the two lines mentioned above, that should fix your problem. In the future you should make a point of checking glGetError (...) when something does not work.


UPDATE: Now that the original problem is fixed, you are not setting the texture minification filter correctly.

To set enumerants, you must use glTexParameteri (...). glTexParameterf (...) is going to interpret the value passed as a floating-point number and GL_LINEAR (0x2601) has type GLenum (32-bit unsigned integer). Fortunately all core OpenGL enums only use the lower 16-bits so they can be expressed precisely as 32-bit floats (can express all integers up to 224), but you can see why you would not want to convert an integer constant to a float.

Therefore, the following line:

glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

Needs to be:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

UPDATE 2: You must use normalized texture coordinates when using texture2D (...).

gl_FragCoord.xy has the range [0, width] and [0, height], which is outside the normalized range for any framebuffer larger than 1x1. To fix that, you must divide by width and height.

texelFetch (...) allows you to use unnormalized coordinates, but it requires GLSL 1.30 and you would have to cast gl_FragCoord.xy to ivec2 to use it. It may also prove inconvenient if you ever draw into an FBO that has different dimensions than your window.