panda3d icon indicating copy to clipboard operation
panda3d copied to clipboard

Allow specification of buffer format for GraphicsOutput.add_render_texture()

Open Clockwork-Muse opened this issue 4 years ago • 2 comments

Description

When doing calling GraphicsOutput.add_render_texture(), one of the options is to specify an auxiliary bitplane to render additional buffers to (such as normals or other information). The catch is that it uses whatever format is specified via FrameBufferProperties during the creation of the GraphicsOutput for the main buffer, which may not be the format desired for these auxiliary buffers. It would be handy to include an extra parameter to take an override for auxiliary buffers;

void GraphicsOutput::
add_render_texture(Texture *tex, RenderTextureMode mode,
                   RenderTexturePlane plane, const FrameBufferProperties *fbp) {

// ...
  } else if (plane == RTP_color) {
    _fb_properties.setup_color_texture(tex);
    tex->set_match_framebuffer_format(true);
  } else if (plane == RTP_aux_rgba_0 ||
             plane == RTP_aux_rgba_1 ||
             plane == RTP_aux_rgba_2 ||
             plane == RTP_aux_rgba_3) {
    const FrameBufferProperties& fb = fbp == nullptr ? _fb_properties : *fbp;
    fb.setup_color_texture(tex);
    tex->set_match_framebuffer_format(true);
  } 
// ....

Use Case

This would allow shaders rendering to more than one buffer to specify individual formats for each one.

I'm not actually sure whether this is completely legal/compliant to OpenGL/Vulkan spec; however the current code does allow for float/half float auxiliary buffers that doesn't match whatever the main buffer is being rendered to.

Clockwork-Muse avatar Apr 06 '21 22:04 Clockwork-Muse

Yes, currently we offer three formats for auxiliary targets: rgba, hrgba (half float) and float, this is clearly very limiting.

Firstly, it would be better if the render-texture process could work with a list of color targets, for example:

fbprops = FrameBufferProperties()
fbprops.add_color_target(16, 16, 16, 0, float=True, clear=True)
fbprops.add_color_target(16, 0, 0, 0, int=True, clear=False)

buffer = engine.make_output(..., fbprops=fbprops)
buffer.color_targets[0].clear_color = (1, 0, 0, 1)
buffer.color_targets[0].bind(texture, RTM_copy_ram)
print(buffer.color_targets[1].format) # F_r16i

Secondly, I think it is awkward that we have the dichotomy between specifying formats using a texture format vs via FrameBufferProperties. This creates unnecessary complexity where we have to translate between the two, and is less predictable for users. Perhaps it should be possible to just directly pass a texture format enum into these calls instead of a bit count:

fbprops.add_color_target(Texture.F_rgb16i, clear=True)

rdb avatar Apr 08 '21 09:04 rdb

Even better!

Clockwork-Muse avatar Apr 08 '21 15:04 Clockwork-Muse