Search code examples
javaopengllwjgl

Framebuffers can't store floating point numbers


I've tried to implement deferred shading but the gbuffer can't store any floating point numbers. The edges from the lighting is VERY rough since the framebuffer can't store negative components for the normals eventhough i passed in the correct internal format and data type.

Example picture of the rough edges

Texture generation:

    public TextureResource(int width, int height, int filter, int internalFormat, int format, boolean clamp, int dataType, ByteBuffer data) {
    id = glGenTextures();
    glBindTexture(GL_TEXTURE_2D, id);
    glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, dataType, data);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
    if(clamp) {
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    }
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
    glBindTexture(GL_TEXTURE_2D, 0);
}

Framebuffer generation:

this.width = width;
    this.height = height;
    this.attachments = attachments;
    boolean hasDepth = false;
    IntBuffer drawBuffers = Util.createIntBuffer(attachments.length);
    assert(attachments.length <= MAX_ATTACHMENTS);
    framebuffer = glGenFramebuffers();
    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
    for(int i = 0; i < attachments.length; i++) {
        if(attachments[i].getAttachmentType() == GL_DEPTH_ATTACHMENT) {
            drawBuffers.put(GL_NONE);
            hasDepth = true;
        } else {
            drawBuffers.put(attachments[i].getAttachmentType());
        }
        if(attachments[i].getAttachmentType() == GL_NONE) {
            continue;
        }
        attachments[i].createTexture(width, height);
        glFramebufferTexture2D(GL_FRAMEBUFFER, attachments[i].getAttachmentType(), GL_TEXTURE_2D, attachments[i].getTexture().getId(), 0);
    }
    if(!hasDepth) {
        renderbuffer = glGenRenderbuffers();
        glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
        glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer);
    }
    drawBuffers.flip();
    glDrawBuffers(drawBuffers);
    if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
        System.err.println("Framebuffer creation failed!");
        System.exit(1);
    }

GBuffer:

super(width, height, new FramebufferAttachment(GL_COLOR_ATTACHMENT1, GL_NEAREST, GL_RGB32F, GL_RGB, false, GL_FLOAT),
                         new FramebufferAttachment(GL_COLOR_ATTACHMENT0, GL_NEAREST, GL_RGB32F, GL_RGB, false, GL_FLOAT),
                         new FramebufferAttachment(GL_COLOR_ATTACHMENT2, GL_NEAREST, GL_RGB, GL_RGB, false, GL_UNSIGNED_BYTE));

Geometry pass fragment shader:

    #version 330 core

in vec3 worldPos0;
in vec2 texCoord0;
in vec3 normal0;

layout (location = 0) out vec3 gWorldPos;
layout (location = 1) out vec3 gNormal;
layout (location = 2) out vec3 gColor;

uniform sampler2D diffuse;

void main() {
    gWorldPos = worldPos0;
    gNormal = normalize(normal0);
    gColor = texture(diffuse, texCoord0).xyz;
}

Solution

  • It's because it is 3.3 core. OpenGL standard somewhat contradicts itself on the matter of what format are renderable, some implementations actually support RGBxF formats. OpenGL 4.4 specs declare them renderable.

    Ifit is really needed, I think is it possible to map integer values to floating point. Ofc you still have limited amount of values, but you can implement negative and fraction values, while having limited range