Nico van Bentum
Nico van Bentum

Reputation: 347

OpenGL - Render to single channel texture?

I'm trying to render to a single channel texture attached to a framebuffer but its not working. I create the texture using a sized format:

glCreateTextures(GL_TEXTURE_2D, 1, &entityTexture);
glTextureStorage2D(entityTexture, 1, GL_R32F, viewport.size.x, viewport.size.y);
glTextureParameteri(entityTexture, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTextureParameteri(entityTexture, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

UPDATE: I then attach it to my framebuffer together with some others:

std::array<GLenum, 4> colorAttachments = { 
    GL_COLOR_ATTACHMENT0, 
    GL_COLOR_ATTACHMENT1, 
    GL_COLOR_ATTACHMENT2, 
    GL_COLOR_ATTACHMENT3,
};

glNamedFramebufferDrawBuffers(GBuffer, static_cast<GLsizei>(colorAttachments.size()), colorAttachments.data());

Inside the shader I write up top:

layout(location = 0) out vec4 gNormal;
layout(location = 1) out vec4 gColor;
layout(location = 2) out vec4 gMetallicRoughness;
layout(location = 3) out float gEntityID;

And then write some random test value to it in the fragment shader (drawing a bunch of meshes):

gEntityID = 12.3;

When I check in RenderDoc the image turns up black with a value of 0. Does all this check out in terms of API usage?

Upvotes: 2

Views: 1068

Answers (2)

Nico van Bentum
Nico van Bentum

Reputation: 347

Changing to layout(location = 3) out vec4 gEntityID; and assigning a vec4 with alpha 1.0 and the single channel value to the red component seems to have done it.

Upvotes: 1

Nicol Bolas
Nicol Bolas

Reputation: 473352

This has nothing to do with rendering to a single-channel texture. Your code for routing color outputs to buffers is non-functional.

glNamedFramebufferDrawBuffers(GBuffer, 1, GL_COLOR_ATTACHMENT3);

That's not how glDrawBuffers or its DSA equivalent work. Indeed, you should have gotten a compile error, because you tried to pass a prvalue integer literal (GL_COLOR_ATTACHMENT3) to a function that takes a pointer.

Even if we fix your function so that it passes a single-element array:

GLenum attachments[1] = {GL_COLOR_ATTACHMENT3};
glNamedFramebufferDrawBuffers(GBuffer, 1, attachments);

That still doesn't work.

You pass glDrawBuffers an array. The indices of this array are the color numbers you set into your fragment shader. So location = 3 on the fragment shader output means to look at the 4th element of the array passed to glDrawBuffers to figure out which attachment binding point gets used. You only passed one element, since the size you gave was 1. The other elements of the array are set to GL_NONE.

So nothing gets written to.

What you (maybe?) want is this:

GLenum attachments[4] = {<attach>, <attach>, <attach>, GL_COLOR_ATTACHMENT3};
glNamedFramebufferDrawBuffers(GBuffer, 4, attachments);

Where <attach> are the first three attachment points.

Upvotes: 2

Related Questions