Repository navigation
Why render hooks are a trait
A render hook is a struct that conforms to RenderHooks, and the renderer takes it as a generic parameter. A function field on each object cannot keep state, and a trait object does not exist in Mojo. A generic trait parameter keeps state and costs nothing when no hook is given.
three.js puts a function on each object: mesh.onBeforeRender = function (renderer, scene, camera, geometry, material, group) { ... }. The function is a closure. It can hold a counter, a list or a reference to another object. The renderer calls it for each object that it draws.
A struct field in Mojo can hold a thin function. A thin function captures nothing, so it cannot count, log or collect. A capturing closure has a type that the compiler makes for that closure only, so a list of objects cannot hold closures of different types.
The objects of a scene live in lists of plain values, such as scene.meshes. A field of a closure type on Mesh would make every mesh a different type. See Why the scene graph is an array.
A language with trait objects stores a pointer and a table of functions, and calls through the table. Mojo 1.1 has no such type. A trait in Mojo is a bound on a generic parameter. The compiler makes one copy of the function for each type that it is called with.
The renderer takes one hooks value for the whole frame: render_with[C: Camera, H: RenderHooks](hooks, scene, assets, camera). The hooks struct holds the state. Each method receives the RenderItem, which names the node, the geometry and the material. A hook that runs for one object only compares the node.
-
RenderHooksgives every method a body that does nothing. A struct replaces only the methods that it needs. -
renderpassesNoHooks. Its calls do no work, so a frame with no hooks costs the same as before. - The hooks value is
mut, so a hook can count or collect without a global.
A sort compares two items and keeps no state. three.js passes a comparator for setOpaqueSort and setTransparentSort. A thin function does the same job, so RenderSort is a thin function type, and set_opaque_sort stores it in a field.
The renderer prepares the whole frame, and then both rasterizers draw it. The CPU draws it in bands on many threads, and the GPU draws it in one launch. There is no point between two objects where a hook can run. So the before hooks run after the frame is prepared and before it is drawn, and the after hooks run after it is drawn. To change what an object looks like, change the scene or the assets between frames.
Tutorials
How-to
Reference
- Scene graph
- Rotations
- Cameras
- Geometry
- Geometry addons
- Lofts and clipping groups
- Sculptor
- Procedural generators
- Meshes and assets
- Lines
- Points and sprites
- Helpers
- Scene objects
- Animated objects
- Raycasting
- Curves and paths
- Animation
- Skinning
- Materials
- Node materials
- TSL functions
- Lights
- Lighting addons
- Fog
- Textures
- Renderer
- Renderer hooks and material flags
- Rasterization
- GPU backend
- Render target
- Post-processing
- GPU computation
- Compute nodes
- Progressive light map
- Gaussian splats
- Voxel global illumination
- SVG renderer
- Image files
- Image decode queue
- Model files
- More model files
- Exporters
- Scene JSON
- Windowing and controls
- Math
- Norm consumers
- Math addons
- Units
- Coverage tool
- Commands
- Examples
- Benchmarks
- Extensions
- Shared physics
- Physics query snapshots
- Continuous collision
- Tick force restoration
- Water
- Animals
- Buildings
- CARLA
- Femur
- Tibia
- Fibula
- Patella
- Knee
- Muscles
- Vessels
- Lymph
- Nerves
- Integument
- Leg
- Foot
- Pelvis
- Torso
- Arm
- Hand
- Head
- Genome
- Game humanoid
- Humanoid fidelity
- Audio-aligned game faces
- Converted assets
- Mesh quality
- Segment inertia
Explanation
- Software rasterizer
- Scene graph as an array
- Linear color
- Normals are not colors
- Perspective correction
- Fixed-point coverage
- Per-fragment shading
- Mipmaps
- Sorted transparency
- Types and checks
- Render hooks as a trait
- Shared CPU and GPU code
- Bands and threads
- PNG structure
- Extensions beside the port
- CUDA teardown hang
- Mojo compiler hang