Using MRT, but drawing in only one texture

Hello. I have a framebuffer with two color attachments (textures) and one depth/stencil attachment. The first color attachment has RGBA8 internal format and the second has R32I. I’m using multiple render targets in my scene, because I want to implement mouse picking, so I render the scene normally to the first texture and I output an ID as an int to the second texture.

But only some objects have shaders that write to the second texture. For example, this is the fragment shader for one of the objects that do write to the second texture:

#version 430 core

in vec3 v_texture_coordinate;

layout (location = 0) out vec4 fragment_color;
layout (location = 1) out int entity_id;

uniform samplerCube u_skybox;

void main() {
    fragment_color = texture(u_skybox, v_texture_coordinate);
    entity_id = -1;
}

And this is a fragment shader that doesn’t:

#version 430 core

in vec3 v_color;

layout (location = 0) out vec4 fragment_color;
// No second location

void main() {
    fragment_color = vec4(v_color, 1.0);
}

Both fragment shaders are used to draw to that framebuffer with two color attachments.

In the C++ code I use glReadPixels with the mouse coordinates to read the int value from the second texture and I print that value every frame.

int second_attachment = 1;
int hovered_object = my_framebuffer->read_pixel(second_attachment, x, y);
SPDLOG_DEBUG("Hovered ID: {}", hovered_object);

Now, on my Linux laptop with an Intel GPU and Mesa 20.0.8, when I hover my mouse on an object (front) that doesn’t output to the second texture, but there is an another object (back) behind the first one that does output to the second texture, I see the ID of the back object printed. This is what I expect to happen, since the front object doesn’t write to the second texture (it uses the second fragment shader from above).
But on my other computer (Linux too, but NVIDIA GPU and NVIDIA 470.74) when I do the same thing as above, I see garbage values printed, as if the front object which shouldn’t write to the second texture does write to it.

My question is:
Is what I’m doing undefined behavior? (The fact that I use objects that don’t write to the second texture.)

Thank you in advance!

Yes. Fragment shaders are not what decides which outputs are written. That is defined by the draw buffers state for the current framebuffer. Assuming you did not change this state between draw calls, every fragment will always provide data to those color buffers.

Even if that data wasn’t generated by the fragment shader; such data will be undefined.

You can use write masks to turn off writing, but I would strongly suggest sorting by such write masks (ie: first draw all objects that write only one value, then draw all objects that write both values), as modifying their state is not performance friendly.

1 Like

I understand now. I fixed it. Thank you!