Search code examples
javaopengllibgdx

LibGDX OpenGL issue


I have next two shaders: vertex shader:

/// fragment shader
#version 130

in vec2 vs_uv;

out vec4 fs_color;

uniform sampler2D u_source;
uniform sampler2D u_map;

void main() {
    fs_color = vec4(vs_uv, 0, 1);
}

/// vertex shader
#version 130

out vec2 vs_uv;

void main() {
    const vec4 vertices[4] = {
        vec4(-1, -1, 0, 1),
        vec4(-1, 1, 0, 0),
        vec4(1, 1, 1, 0),
        vec4(1, -1, 1, 1)
    };

    vec4 description = vertices[gl_VertexID];
    gl_Position = vec4(description.xy, 0, 1);
    vs_uv = description.zw;
}

Obviously, it renders a full-screen gradient-filled rectangle. I created a program with this two shaders and rendered 4 vertices into framebuffer and return rendered color texture from it:

public Texture apply(Texture source, Texture map) {
    m_renderBuffer.begin();
    Gdx.gl20.glClear(Gdx.gl20.GL_COLOR_BUFFER_BIT);
    m_program.begin();
    m_program.setUniformi(m_sourceLocation, 0);
    m_program.setUniformi(m_mapLocation, 1);
    Gdx.gl20.glDrawArrays(Gdx.gl20.GL_TRIANGLE_FAN, 0, 4);
    m_program.end();
    m_renderBuffer.end();

    return m_renderBuffer.getColorBufferTexture();
}

I draw rendered texture with a SpriteBatch:

m_lightSpriteBatch.begin();
m_lightSpriteBatch.draw(lightTexture, 0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
m_lightSpriteBatch.end();

It works well and renders gradient-filled rectangle as I want. When I bind two textures (passed as parameters for apply method - source and map) after meginning of the program:

m_program.begin();
source.bind(0);
map.bind(1);
...

It renders crap even considering what I use no textures in the shader's code! preview

  1. texture rendered with no texture bindings
  2. source texture
  3. "crappy" rendered texture
  4. map texture

Solution

  • The OpenGL spec states that rendering the attached texture of a frame buffer onto its own frame buffer produces undefined results. Or "crap", in your words. :) I guess this shows that at least on this particular GPU, you can't even bind the texture, much less sample from it.

    Typically, if you need do something like this, you need two FrameBuffers, and you can ping pong between them.