Search code examples
javaopengllwjgl

OpenGL (LWJGL): Render to Texture not working


I've got some code that's supposed to render text to a texture so that I don't have to render each character each draw step, and can instead use the rendered texture. However, my code does not as it's supposed to, and the texture is left blank. After a few hours of trying different things, I cannot figure it out, and so I bring the question to you.

I'm fairly certain the problem is somewhere in this code chunk below, but if you think it's not, I'll gladly post whatever other samples of code you would like. I just really want to get this done already. The exact problem is that the created texture is blank, and never is rendered to (it seems like). I've tried just drawing one massive quad on it, and that didn't seem to work either.

Edit: After flipping the buffer, I can get some color to be rendered to the texture, but it's all just one color (which makes me think it's only sampling one pixel), and I can't figure out how to get the actual image I want to render to show on it.

public Text(String text, int x, int y, Font font, float size, GUIComponent parent, Binding binding) {
    super(null, x, y, font.getStringWidth(size, text), font.getStringHeight(size), parent, binding, false);
    this.text = text;
    this.font = font;
    this.width = font.getStringWidth(size, text);
    this.height = font.getStringHeight(size);
    int fbo = glGenFramebuffers();
    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
    int tex = glGenTextures();
    glBindTexture(GL_TEXTURE_2D, tex);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0);
    IntBuffer intBuffer = BufferUtils.createIntBuffer(1);
    intBuffer.put(GL_COLOR_ATTACHMENT0);
    intBuffer.flip();
    glDrawBuffers(intBuffer);
    if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
        throw new RuntimeException("Something really bad happened");
    }
    //RENDER
    RenderUtil.recalibrate(width, height, 1.0f); //Does glViewport(width, height), and some matrix stuff
    Camera.updateShader("textshader", "projection", false); //Update projection matrix
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);
    int width = 0;
    float f = this.width / 1.0f;
    int charWidth = 0;
    for (char c : text.toCharArray()) {
        font.bind(0, c % 256); // calls glBindTexture, this works, have tested
        //ResourceManager.getTexture("grassroadedger1").bind(0, 0);
        charWidth = font.getCharWidth(size, c);
        //float[] verts = new float[] { -1f, 1f, 1f, 1f, 1f, -1f, -1f, -1f };
        float[] verts = new float[] { -1.0f + (width / f), 1.0f, 1.0f + ((width + charWidth) / f), 1.0f, 1.0f + ((width + charWidth) / f), -1.0f, -1.0f + (width / f), -1.0f };
        width += charWidth;
        glBindBuffer(GL_ARRAY_BUFFER, vertexPointer);
        glBufferSubData(GL_ARRAY_BUFFER, 0, RenderUtil.createBuffer(verts));
        glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, 0);

        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, RenderUtil.getIndicesPointer());
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

        glBindBuffer(GL_ARRAY_BUFFER, 0);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    }
    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(1);
    //END
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    glBindTexture(GL_TEXTURE_2D, 0);
    RenderUtil.recalibrate(Window.getWidth(), Window.getHeight(), LuminaEngine.getGlobalImageScale());
    this.setTexture(new Texture(tex, "text_"+size+"_"+text));
}

FragmentShader

    #version 330 core
    in vec2 uv;

    layout(location = 0) out vec4 color;

    uniform sampler2D sampler;

    void main(){

        color = texture2D( sampler, uv );
    }

Vertex Shader

    #version 330 core

    layout(location = 0) in vec3 vertices;
    layout(location = 1) in vec2 textures;

    out vec2 uv;

    uniform mat4 projection;

    void main(){

         gl_Position =  projection * vec4(vertices,1);

         uv = textures;
    }

Edit: After flipping the intBuffer for drawBuffers, I can get some things to appear, mostly just a big blue square. Progress nonetheless


Solution

  • You never defined an array of generic vertex attribute data for the texture coordinates (in vec2 textures;).

    Add something like this to your code:

    int texCoordBuffer;
    glGenBuffers(1, texCoordBuffer);
    
    float[] texCoord = new float[] { 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f };
    
    glBindBuffer(GL_ARRAY_BUFFER, texCoordBuffer);
    glBufferData(GL_ARRAY_BUFFER, RenderUtil.createBuffer(texCoord), GL_STATIC_DRAW);
    
    int tax_attr_i = 1; // layout(location = 1) in vec2 textures;
    glVertexAttribPointer(tax_attr_i, 2, GL_FLOAT, false, 0, 0);