Get Screenshot as Float image

im attempting to do a simulation , in which i render the main scene into a seperate display region , using the render to texture method i then attach a shader to the texture quad that calculates the distance from objects in the scene to the camera , i then use this distance to perform other calculations , i now have the distance plus 3 other float values , i wish to create an image where each pixel contains that pixels distance and the other values associated with it , note , i expect all these values as floats, i have managed to save the image using
tex = self.dr.getScreenshot()
data = tex.getRamImage()

image = np.frombuffer(data, np.uint8)
image.shape = (tex.getYSize(), tex.getXSize(), tex.getNumComponents())
image = np.flipud(image)
this works but the pixels are either 255 or 0 which makes sense
(ive tried setting np.uint8 to np.float32 and float , i get cannot reshape array into shape of the tex size) clearly im missing something
how do i aquire the image as a float as i expect the fragment shader to be outputing float values in each channel

When you configure the texture for the render to texture frame buffer you have to configure it to have float components, otherwise the buffer will be 4x8bits components and the output value of your fragment shader will be clamped between 0…1 (i.e. 0…255)

you can use something like :

    props = FrameBufferProperties()
    props.set_srgb_color(False)
    props.set_float_color(True)
    props.set_rgba_bits(32, 32, 32, 32)
    buffer = base.win.make_texture_buffer("renderBuffer", width, height, to_ram=True, fbp=props)

Then you can use the data from the texture in numpy :

        data = buffer.get_texture().getRamImage()
        np_buffer = numpy.frombuffer(data, numpy.float32)
        np_buffer.shape = (height, width, texture.getNumComponents())

thanks for the quick reply really appriciate it,
so this makes sense , im new to this so just wondering how to get the shader to render to the buffer as i cannot set the shader on the grpahicsBuffer nor its texture
the easy way using filter manager returns a quad how do i do this going the grpahics buffer way
thank you

Actually, if you’re not using the window to render anything visible you could configure the frame buffer to have float32 components using prc configuration.

Otherwise you can render into a buffer using something like :

       root = NodePath("root")
        cam = base.makeCamera(win=buffer)
        cam.reparent_to(root)
        lens = OrthographicLens()
        lens.setFilmSize(2, 2)
        lens.setFilmOffset(0, 0)
        lens.setNearFar(-1000, 1000)
        cam.node().setLens(lens)
        cm = CardMaker("quad")
        cm.setFrameFullscreenQuad()
        quad = root.attach_new_node(cm.generate())

        quad.set_shader(your_shader)

Disclaimer: I copied snippet from my own code and FilterManager so it may not work out of the box :slight_smile: You can look at FilterManager (especially renderQuadInto)

iv managed to make this work using what you have showed me here , and some examples from the firefly demo ,
Did something like this
bufferCam = self.makeCamera(buffer)
temp_node = NodePath(PandaNode(“temp node”))
temp_node.setShader(MyShader)
temp_node.set_shader_input(“var name”,var)
bufferCam.node().setInitialState(temp_node.getState())

this does what i want in that it attaches the shader to the cam and what the cam sees