Offscreen Rendering using Panda3D

In this post, we will explore a 3D rendering and game development library named Panda3D. One advantage of Panda3D is that the license is quite permissive (BSD-3-Clause) so that it can be used even for commercial applications without worrying about releasing our own code.

There may be a situation where we don’t need to render the scene onto a window and render it into an image in memory instead. Panda3D supports this use case, but I found that there is no complete example that can be used as a reference. Therefore, I would like share what I found while trying to perform offscreen rendering using Panda3D.

Installing Panda3D

We will assume that we are developing with Python3. Install Panda3D by running the command below:

pip install panda3d

Code

Here is an example of the basic steps required to draw to an offscreen buffer.

IMG_W = 640
IMG_H = 480

# Create offscreen window so that no window will be opened
base = ShowBase(fStartDirect=True, windowType='offscreen')

# Create frame buffer properties
fb_prop = FrameBufferProperties()
fb_prop.setRgbColor(True)
# Only render RGB with 8 bit for each channel, no alpha channel
fb_prop.setRgbaBits(8, 8, 8, 0)
fb_prop.setDepthBits(24)

# Create window properties
win_prop = WindowProperties.size(IMG_W, IMG_H)

# Create window (offscreen)
window = base.graphicsEngine.makeOutput(base.pipe, "cameraview", 0, fb_prop, win_prop, GraphicsPipe.BFRefuseWindow)

# Create display region
# This is the actual region used where the image will be rendered
disp_region = window.makeDisplayRegion()


…
…
…
# Load the model, add lighting, etc,
# Create a camera object, etc
…
…
…

# Assign a camera for the region
disp_region.setCamera(cam_obj)

# Create the texture where the frame will be rendered
# This is the RGB/RGBA buffer which stores the rendered data
bgr_tex = Texture()
window.addRenderTexture(bgr_tex, GraphicsOutput.RTMCopyRam, GraphicsOutput.RTPColor)



# Now we can render the frame manually
base.graphicsEngine.renderFrame()

# Get the frame data as numpy array
bgr_img = np.frombuffer(bgr_tex.getRamImage(), dtype=np.uint8)
bgr_img.shape = (bgr_tex.getYSize(), bgr_tex.getXSize(), bgr_tex.getNumComponents())

# Do as you wish with the frame
…
…
…

Add a Comment

Your email address will not be published. Required fields are marked *