allow customizing gfx.show
See original GitHub issueIn #376 we realized that gfx.show
can massively simplify the examples and reduce boilerplate. Indeed, it reduces the current hello world example to:
import pygfx as gfx
cube = gfx.Mesh(
gfx.box_geometry(200, 200, 200),
gfx.MeshPhongMaterial(color=(1, 1, 0, 1))
)
gfx.show(cube)
Which is much more concise than the current example in the guide. (Although I must admit that this background doesn’t feel very easy on the eyes.)
Thinking this a bit further, a nice addition here would be to be able to supply a custom animate
function. The problem with that is that the animate
function needs access to the renderer
and potentially the controller
to allow the scene to update correctly. To avoid this, I want to propose a before_render
function that the default animate
executes before rendering if present. With it, the rotating cube example could become:
import pygfx as gfx
cube = gfx.Mesh(
gfx.box_geometry(200, 200, 200),
gfx.MeshPhongMaterial(color=(1, 1, 0, 1))
)
def animate():
rot = gfx.linalg.Quaternion().set_from_euler(
gfx.linalg.Euler(0.005, 0.01)
)
cube.rotation.multiply(rot)
gfx.show(cube, before_render=animate)
That said, we could go all the way and allow customizing all parts of the pipeline by wrapping show
into a dataclass and then only creating those elements that haven’t been set explicitly. Picking up the name from #376 (Display), we could do:
import pygfx as gfx
cube = gfx.Mesh(
gfx.box_geometry(200, 200, 200),
gfx.MeshPhongMaterial(color=(1, 1, 0, 1))
)
def animate():
rot = gfx.linalg.Quaternion().set_from_euler(
gfx.linalg.Euler(0.005, 0.01)
)
cube.rotation.multiply(rot)
# run the application
display = gfx.Display()
display.on_before_render = animate
display.show(cube)
Where display
could be customized further, e.g., by setting your own display.canvas = wgpu.gui.offscreen.WgpuCanvas()
, etc. What do you think?
Issue Analytics
- State:
- Created 10 months ago
- Comments:7 (3 by maintainers)
Top GitHub Comments
I agree that we need to make it easy to tweak show. Ideally it would be a smooth scale where you can use all defaults, or define all stuff yourself, and everything in between.
For the lights, it checks if lights are present in the scene, and only adds default lights if there are none. We could do something similar for the background. And also use a more subtle default background 😄
I like the
before_render
callback.I think what’s left is canvas, camera, and controller. These could simply be optional arguments to
gfx.show()
. E.g.I think I’d prefer this over a
Display
object because it avoids introducing another class/concept. Unless I miss a case where having an object has an advantage.I would have gone for a shade of gray. Especially when working in the evening it would be nice to not be greeted by a bright white screen when writing code 😃