Repository navigation
GPU computation
render/computation.mojo steps float images with GLSL fragment shaders. It is three.js's GPUComputationRenderer from examples/jsm/misc/. A simulation keeps its state in the images, for example the positions and velocities of a flock, and runs one step a frame.

examples/ripples.mojo draws this picture.
var computation = GPUComputationRenderer(64, 64)
var position = computation.add_variable("position", MOVE, start^)
var velocity = computation.add_variable("velocity", STEER, computation.create_texture())
computation.set_variable_dependencies(position, [position, velocity])
computation.set_variable_dependencies(velocity, [position, velocity])
computation.init()
# For each frame:
computation.compute()
var map = assets.textures.add(computation.current_texture(position))A variable is an image of size_x by size_y texels, four floats for each texel, and the shader that computes its next state. add_variable(name, shader, initial) adds one and returns its place. create_texture() returns an image of zeros for a start.
set_variable_dependencies(variable, dependencies) says which images the shader reads. A variable that reads its own last image lists itself. init() declares a sampler2D for each dependency, named after it, and defines resolution as the image size. Then it compiles each shader with the GLSL subset.
Set a shader's other uniforms on programs[variable] after init, for example programs[velocity].set_uniform("delta", 0.016).
A shader finds its texel as three.js's shaders do, and writes gl_FragColor:
void main() {
vec2 uv = gl_FragCoord.xy / resolution.xy;
vec4 p = texture2D( position, uv );
vec4 v = texture2D( velocity, uv );
gl_FragColor = vec4( p.xyz + v.xyz * 0.016, p.w );
}All four numbers are kept as they are. They are not clamped and not premultiplied. A read gets the texel that its coordinate falls in, as three.js's NearestFilter does. The variable's wrap_s and wrap_t say what a coordinate past an edge reads. They are CLAMP unless set. A texel that the shader throws away with discard keeps its value.
compute() runs each variable's shader once, at every texel. Each variable reads the images as they were before the step. So a variable that runs after another in the same step reads the other's old image, as in three.js.
current_image(variable) returns an image now. alternate_image(variable) returns the image before the last step. The images lie row by row from the bottom, so texel (x, y) starts at (y * size_x + x) * 4. current_texture(variable) returns a float texture for a material to read.
GpuComputation.compute(computation) in render/gpu.mojo runs a step on the device, one launch for each variable. The host and the device run the same function at each texel, compute_texel, so the images agree to the float. tests/test_gpu.mojo checks this.
- The images are float lists. three.js keeps them in render targets.
- Only
FloatTypeandNearestFilterare ported.setDataTypeand a linear filter are not. -
initraises when a shader is refused. three.js returns an error string for a missing dependency. Here a dependency that is not a variable raises inset_variable_dependencies. -
gl_FragCoord.wis one. three.js's is one over the clip-spacew, which is also one on its full-screen quad.
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