Problem creating a one-component floating point texture buffer

I’m trying to create a one_component floating point texture buffer (aka GL_R32F), but the FBO created is not at all what I expected.

When I print the FBProperties I used to create the texture buffer (using buffer.get_fb_properties()) I got what I configured :

float_color color_bits=32 red_bits=32  2d_texture generatorBuffer

However once the buffer is actually used, the actual FBProperties (and the actual texture format) is completely wrong, I get a three-components buffer and with half-float values :

float_color color_bits=48 red_bits=16 green_bits=16 blue_bits=16 force_hardware force_software  2d_texture

Looking at the code, my interpretation is that the GraphicStateGuardian looks only at the total number of bits to configure the FBO and not the number of color channels, and so when one request a total number of 32 bits the code allocate a 48 bits FBO with three components as it fits the bill. But I could also be doing something completely wrong :slight_smile:

This may be a fairly easy one to fix. Could you show the code using which you are creating the buffer? Thanks!

This code should the the same thing as my application (I’m not home and my laptop does not seem to like floating point texture buffers).

from panda3d.core import FrameBufferProperties, GraphicsPipe, WindowProperties, NodePath, loadPrcFileData
from direct.task import Task
import direct.directbase.DirectStart

size=256
mybuffer=None

def check_generation(task):
    texture = mybuffer.get_texture()
    if texture.has_ram_image():
        print("Got:", mybuffer.get_fb_properties(), texture)
        return Task.done
    else:
        return Task.cont

props = FrameBufferProperties()
props.set_float_color(True)
props.set_rgba_bits(32, 0, 0, 0)
mybuffer = base.win.make_texture_buffer("generatorBuffer", size, size, to_ram=True, fbp=props)
mycamera = base.makeCamera(mybuffer)
myscene = NodePath("My Scene")
mycamera.reparentTo(myscene)

print("Requested:", mybuffer.get_fb_properties())

taskMgr.add(check_generation, 'check_generation', sort = -10000)

base.run()

All right, this problem occurs due to the to_ram flag which causes a renderbuffer to be created instead of a texture, which uses a different format selection mechanism.

I’ve checked in a fix:

Thanks a lot for the clear test case!

It works nice, at least for the buffer :slight_smile:

If I print the texture just after creating the buffer, I get a 1-component texture :

Requested: float_color color_bits=32 red_bits=32  2d_texture generatorBuffer
  2-d, 256 x 256 pixels, each 1 floats, r32, compression off
  sampler wrap(u=clamp, v=clamp, w=repeat, border=0 0 0 1) filter(min=default, mag=default, aniso=0) lod(min=-1000, max=1000, bias=0)  no ram image

Then, once the texture is uploaded to ram, the actual buffer is indeed a R32F buffer, but the texture has been switched to a 3-components texture :

Got: float_color color_bits=32 red_bits=32 force_hardware force_software  2d_texture 
  2-d, 256 x 256 pixels, each 3 floats, rgb, compression off
  sampler wrap(u=clamp, v=clamp, w=repeat, border=0 0 0 1) filter(min=linear, mag=linear, aniso=0) lod(min=-1000, max=1000, bias=0)  786432 bytes in ram, compression off

And the texture size is indeed 256x256x3 32bits float

Even stranger, the output of

print(texture.get_format(), Texture.formatFormat(texture.get_format()))

is

7 rgb

Which does not match with the texture size.

It’s probably missing something in framebuffer_copy_to_ram. I’ll take a look.

I think I’ve fixed this one as well:

Please give it a try!

Almost there :slight_smile:

The texture has the right format and size in memory, in my application I get now the correct values and there are no longer huge rounding errors that were caused, I guess, by the hidden conversion to rgb.

But, for the sake of completeness, I tried RG32F and RGB32F buffer and in those cases I get an error when I try to read the texture values using TexturePeeker :

:gobj(error): Unsupported texture peeker format: rgb32

Thanks for your patience! I think I’ve got a fix for that one as well.

Tested all four possibilities and they all work fine :slight_smile: Thank you for your really fast support !