[solved] Scaling the Panda3D game window

Hello,

I would like to render a game at 320x180 pixels and then scale it - unfiltered - to a 1280x720 window.

Is this easily possible in Panda3d?

Thanks!

EDIT: find the solution in viewtopic.php?p=106082#p106082

You want to create a 320 x 180 fbo, and then make a fullscreen fbo which uses the previous fbos colortexture. You can set the Magfilter to nearest to avoid any filtering, i.e. “my_tex.set_magfilter(SamplerState.FT_nearest)”

Thank you for the hint, tobspr.

In the documentation I couldn’t make heads or tails of Creating_Windows_and_Buffers but Low-Level_Render_to_Texture might have allowed me to render to a texturebuffer. Is that ok? Or will that have drawbacks as opposed to using an actual “framebuffer object”?

from pandac.PandaModules import loadPrcFileData
loadPrcFileData("", "win-size 960 540")
loadPrcFileData("", "show-frame-rate-meter t")

from direct.showbase.ShowBase import ShowBase
from panda3d.core import NodePath
from panda3d.core import SamplerState

class MyApp(ShowBase):

  def __init__(self):
    ShowBase.__init__(self)

    smallbuffer = base.win.makeTextureBuffer("Small Buffer", 16, 9)
    smallbuffer.setSort(-100)

    smalltexture = smallbuffer.getTexture()
    smalltexture.set_magfilter(SamplerState.FT_nearest)

    smallscene = NodePath("Small Scene")
    smallscene = self.loader.loadModel("environment")

    smallcamera = base.makeCamera(smallbuffer)
    smallcamera.reparentTo(smallscene)

    #smallscene.reparentTo(self.render)

app = MyApp()
app.run()

If it’s fine, could somebody hint me towards rendering a buffer to the window? I find render-to-texture threads and documentation but no render-from-texture info.

That looks about right. “framebuffer object” is an OpenGL term - Panda will implement the texture buffer using a framebuffer object on the back-end.

The next step would be creating a quad and parenting that to render2d to show its contents to the window:

card = CardMaker("card")
card.set_frame_fullscreen_quad()
card.set_uv_range(smalltexture)

card_path = render2d.attach_new_node(card.generate())
card_path.set_texture(smalltexture)

# You probably also want to set the wrap mode.
smalltexture.set_wrap_u(SamplerState.WM_clamp)
smalltexture.set_wrap_v(SamplerState.WM_clamp)

Thanks rdb! Thanks to your code it is complete:

from pandac.PandaModules import loadPrcFileData
loadPrcFileData("", "win-size 640 640")
loadPrcFileData("", "show-frame-rate-meter t")

from direct.showbase.ShowBase import ShowBase
from panda3d.core import NodePath, CardMaker, SamplerState

class LowRezGame(ShowBase):

  def __init__(self):
    ShowBase.__init__(self)

    smallbuffer = base.win.makeTextureBuffer("Small Buffer", 64, 64)
    smallbuffer.setSort(-100)

    smalltexture = smallbuffer.getTexture()
    smalltexture.set_magfilter(SamplerState.FT_nearest)

    smallscene = NodePath("Small Scene")
    smallscene = self.loader.loadModel("environment")

    smallcamera = base.makeCamera(smallbuffer)
    smallcamera.reparentTo(smallscene)

    smalltexture.set_wrap_u(SamplerState.WM_clamp)
    smalltexture.set_wrap_v(SamplerState.WM_clamp)

    card = CardMaker("card")
    card.set_frame_fullscreen_quad()
    card.set_uv_range(smalltexture)
    
    card_path = render2d.attach_new_node(card.generate())
    card_path.set_texture(smalltexture)
    
app = LowRezGame()
app.run()

set_wrap_u/set_wrap_v doesn’t seem to make a noticeable difference though (at least in a static scene in 1.9.1).

Here’s a version of the scene without set_magfilter(SamplerState.FT_nearest) applied:

By the way, I wanted to achieve this to have a render suitable for the lowrezjam 64x64 resolution game jam on itch.io. I will probably not use it but I’ll share this thread on their forum.