Note
Go to the end to download the full example code.
Fullscreen Postprocessing 2
Example showing post-processing effects by modifying the flusher object.
This example is a placeholder for how post-processing could work if we’d provide an API for it.
Note: this example makes heavy use of private variables and makes assumptions about how the RenderFlusher works that may not hold in the future.
import numpy as np
import imageio.v3 as iio
from wgpu.gui.auto import WgpuCanvas, run
import pygfx as gfx
raise RuntimeError("Post-processing needs to be redesigned")
canvas = WgpuCanvas()
renderer = gfx.renderers.WgpuRenderer(canvas)
scene = gfx.Scene()
im = iio.imread("imageio:bricks.jpg").astype(np.float32) / 255
tex = gfx.Texture(im, dim=2).get_view(filter="linear", address_mode="repeat")
geometry = gfx.box_geometry(200, 200, 200)
geometry.texcoords.data[:] *= 2 # smaller bricks
material = gfx.MeshPhongMaterial(map=tex, color=(1, 0, 0, 0.2))
cube = gfx.Mesh(geometry, material)
scene.add(cube)
camera = gfx.PerspectiveCamera(70, 16 / 9)
camera.position.z = 400
class MyRenderFlusher(gfx.renderers.wgpu._renderutils.RenderFlusher):
uniform_type = dict(
size="2xf4",
sigma="f4",
support="i4",
amplitude="f4",
)
def __init__(self, device):
super().__init__(device)
self._shader[
"tex_coord_map"
] = """
let a = u_render.amplitude;
tex_coord.x = tex_coord.x + sin(tex_coord.y * 20.0) * a;
"""
self._uniform_data["amplitude"] = 0.02
renderer._flusher = MyRenderFlusher(renderer.device)
def animate():
rot = gfx.linalg.Quaternion().set_from_euler(gfx.linalg.Euler(0.005, 0.01))
cube.rotation.multiply(rot)
renderer.render(scene, camera)
canvas.request_draw()
if __name__ == "__main__":
canvas.request_draw(animate)
run()