RANDOM_PCG: ObjectUncorrelated pseudo random samples. Converges slowest but never shows structured artifacts.
RANDOM_SOBOL: ObjectSobol low discrepancy samples, scrambled per pixel. Converges faster than RANDOM_PCG.
RANDOM_BLUE_DITHER: ObjectThe same Sobol sequence for every pixel, offset by a blue noise dither so early frames read as smooth grain rather than clumped noise. The default.
TRANSMISSIVE_BACKGROUND_ENVIRONMENT: numberSample the environment map, so glass shows what is behind it.
TRANSMISSIVE_BACKGROUND_OVERLAY: numberSet the opacity from the transmitted light intensity, tinted by the environment lighting.
TRANSMISSIVE_BACKGROUND_TRANSPARENT: numberAttenuate the background by the transmitted light, so glass renders against transparency.
Produces a PMREM prefiltered, optionally downsampled equirectangular copy of an environment map. Blurring removes the small bright details that make an environment slow to converge.
constructor( renderer: WebGPURenderer )dispose(): voidFrees every GPU resource held by the generator.
async generate(
texture: Texture,
blur = 0: number,
width = null: number,
height = null: number
): Promise<Texture>Renders a blurred copy of the given environment map. The source texture is left untouched.
Note
The returned texture is owned by the caller and must be disposed.
Upscales a path traced image to the drawing buffer size with FSR. Pass one to "WebGPUPathTracer.setUpscaler".
The "Upscaler" class is passed in rather than imported so it does not become a dependency.
import { Upscaler } from '@pmndrs/upscaler';
pathTracer.setUpscaler( new FSRUpscaler( { Upscaler } ) );constructor(
{
// The `Upscaler` class from `@pmndrs/upscaler`.
Upscaler: function,
sharpness?: number,
}
)Every field below can also be assigned after construction.
init( renderer: WebGPURenderer ): voidupscale( source: Texture, camera: Camera ): TextureUpscales a texture to the renderer's drawing buffer size.
Runs Open Image Denoise over a path traced image. Pass one to "WebGPUPathTracer.setDenoiser", or drive it directly with "denoise".
"initUNetFromURL" and the weights are passed in rather than imported so neither the library nor the network files become a dependency.
import { initUNetFromURL } from 'oidn-web';
pathTracer.setDenoiser( new OIDNDenoiser( { initUNetFromURL, auxWeightsUrl } ) );Weights come from the oidn-weights repository, where the "_small" and "_large" variants trade quality against download size and per tile cost.
texture: ExternalTexture | nullThe denoised result, or null until the first tile has been produced.
complete: booleanWhether a pass has finished. Stays true until reset.
running: booleanWhether a pass is running. The work is spread over several frames.
constructor(
{
initUNetFromURL: function,
// Weights for the guided model.
auxWeightsUrl: string,
// Weights for the color only model, needed only when
// `useAuxiliaryBuffers` is `false`.
colorWeightsUrl?: string,
useAuxiliaryBuffers?: boolean,
maxTileSize?: number | null,
// `false` pins every tile to `maxTileSize`. An object tunes
// the adaptive sizing.
dynamicTile?: DynamicTileSetting | null,
}
)Every field below can also be assigned after construction.
init( renderer: WebGPURenderer ): voidsetScene( scene: Scene, camera: Camera ): voidupdate( target: Texture ): Texture | nullRenders the auxiliary buffers and starts a pass. Safe to call every frame.
async denoise(
color: Texture,
albedo = null: Texture | null,
normal = null: Texture | null
): voidRuns a pass unless one is already running or finished. The optional albedo and normal buffers guide the filter and select the guided model. Both hold [0,1] values, with normals mapped so a flat normal is (0.5, 0.5, 1).
reset(): voidDrops any running pass and the last result. Call it whenever the image changes, such as when the camera moves.
Progressive path tracer running on WebGPU. Call WebGPUPathTracer#setScene once, then WebGPUPathTracer#renderSample every frame to accumulate samples into the canvas.
The scene is captured when setScene is called, so changes to geometry, materials, lights, or
the environment afterward require the matching update* function. Any change that invalidates
the accumulated image restarts it.
// Fired once every pixel has reached `maxSamples` and an attached denoiser has finished. Fires
// again after a reset, or after `maxSamples` is raised, once the render has caught up.
{ type: 'complete' }maxBounces: number = 15Maximum number of times a ray can scatter before the path is terminated. Higher values resolve more indirect light at the cost of speed.
frameBudget: number = 250000Number of path slots dispatched per WebGPUPathTracer#renderSample call, independent of resolution. Raising it trades frame rate for convergence speed.
maxTransparentBounces: number = 5Maximum number of alpha tested surfaces a ray can pass through. Counted separately from WebGPUPathTracer#maxBounces so foliage and cutouts cannot exhaust the bounce budget.
maxSamples: number = 0Stops accumulating once every pixel reaches this many samples. A denoiser only runs once the
render has stopped, so it has no effect while this is 0.
Note
0 renders indefinitely.
complete: booleanWhether every pixel has reached WebGPUPathTracer#maxSamples and an attached denoiser has finished, as of the last measurement. Always false while rendering indefinitely.
transmissiveBackground: number = TRANSMISSIVE_BACKGROUND_OVERLAYHow the background is treated behind transmissive surfaces. One of
TRANSMISSIVE_BACKGROUND_OVERLAY, TRANSMISSIVE_BACKGROUND_ENVIRONMENT, or
TRANSMISSIVE_BACKGROUND_TRANSPARENT.
filterGlossyFactor: number = 1Blurs sharp reflections seen through rough surfaces to suppress fireflies. Higher values remove more noise and more detail.
Note
0 disables the filter.
multipleImportanceSampling: boolean = trueWhether to combine light sampling and bsdf sampling with MIS. Disabling it makes lights noticeably noisier.
clampDirect: number = 0Upper bound on the contribution of a directly lit path segment, for suppressing fireflies.
Note
0 disables the clamp. Clamping darkens the image and biases the result.
clampIndirect: number = 10Upper bound on the contribution of an indirectly lit path segment, for suppressing fireflies.
Note
0 disables the clamp. Clamping darkens the image and biases the result.
readonly target: Texture | nullThe render target the accumulated samples are written into.
readonly fadeState: numberProgress of the fade from the low resolution preview to the full render, from 0 to 1.
readonly lowResTarget: TextureThe low resolution preview rendered while WebGPUPathTracer#renderDelay elapses.
readonly lowResMode: booleanWhether the tracer is currently rendering the low resolution preview.
readonly textureAtlas: AtlasTextureThe atlas every scene texture is packed into for the kernels to sample.
minSamples: number = 1Samples every pixel must reach before the full resolution render is faded in.
renderDelay: number = 500Milliseconds to show the low resolution preview for after a reset.
fadeDuration: number = 500Milliseconds taken to cross fade from the preview to the full render.
dynamicLowRes: boolean = trueWhether to render a low resolution preview while the camera is moving.
lowResScale: number = 0.1Resolution of the low resolution preview, as a fraction of the render size.
renderScale: number = 1Resolution the path tracer renders at, as a fraction of the canvas size. Lowering it converges faster at the cost of detail, and pairs with an upscaler.
synchronizeRenderSize: boolean = trueWhether to track the canvas size automatically. Set to false to drive the render
size with WebGPUPathTracer#setSize.
renderToCanvas: boolean = trueWhether WebGPUPathTracer#renderSample draws the result to the current render
target, the canvas by default. Set to false to only accumulate, as when baking to a
texture read through WebGPUPathTracer#target.
generateMissingAttributes: boolean = trueWhether to generate the attributes in WebGPUPathTracer#commonAttributes on geometry that is missing them when the scene is set.
commonAttributes: Array<string> = [ 'normal', 'tangent' ]Vertex attributes every geometry is expected to provide.
stableNoise: boolean = trueWhether to restart the random sequence on reset so a given camera always produces the same image.
pause: boolean = falseWhether to stop accumulating samples. The last image keeps being presented.
constructor( renderer: WebGPURenderer )async getSampleCountsAsync(): Promise<SampleCounts>Measures the per pixel sample counts. Use min for convergence checks and avg to display.
Note
The wavefront backend reduces the counts on the GPU and reads them back, so only call this when the numbers are needed.
setMultipleImportanceSampling( value: boolean ): voidsetDenoiser( denoiser: OIDNDenoiser | null ): voidAttaches a denoiser, run once the render settles and displayed in place of the raw image. Settings live on the instance. Pass null to remove it.
setUpscaler( upscaler: FSRUpscaler | null ): voidAttaches an upscaler, run before the image is presented so the render can happen below the canvas resolution. Settings live on the instance. Pass null to remove it.
setScene( scene: Scene, camera: Camera ): voidCaptures the scene and camera and builds the acceleration structures the kernels trace
against. Call this once, then use the update* functions for later changes.
Note
Geometry BVHs are built synchronously, so this blocks for large scenes.
setRandom( random: Object ): voidReplaces the random number generator and recompiles the kernels.
setCamera( camera: Camera ): voidReplaces the camera the rays are generated from. Cameras with a getCameraRayFn, such as
PhysicalCamera and EquirectCamera, provide their own ray generation.
updateMaterials(): voidRe-reads the material properties and textures from the scene. Call after changing any material.
updateTransforms(): voidRe-reads the world matrices from the scene. Call after moving any object.
Note
Changing geometry requires WebGPUPathTracer#setScene instead, since the BVH must be rebuilt.
updateCamera(): voidRe-reads the camera transform and projection. Call after moving the camera.
updateEnvironment(): voidRe-reads scene.environment and scene.background, along with their intensity, rotation,
and blur.
updateLights(): voidRe-collects the lights in the scene. Call after adding, removing, or changing one.
setSize( x: number, y: number ): voidSets the resolution the path tracer renders at. Only used when
WebGPUPathTracer#synchronizeRenderSize is false.
reset(): voidDiscards the accumulated image and starts over. The update* functions call this for you.
renderSample(): voidAccumulates one round of samples and presents the result to the canvas. Call once per frame.
renderDebugBounds(
{
// Count the top level object bounding boxes.
displayTLAS = true: boolean,
// Count the per object geometry bounding boxes.
displayBLAS = true: boolean,
// Only count boxes in front of the nearest hit, so occluded
// boxes do not contribute. Culling and material transparency
// are honored.
stopAtSurface = false: boolean,
// Node count that saturates to full heat.
saturationCount = 64: number,
}
): voidDraws a heatmap of how many BVH bounding boxes each camera ray intersects, for diagnosing box overlap and traversal cost. Hotter pixels traverse more nodes.
renderTextureAtlas( layer = 0: number ): voidDraws one layer of the texture atlas to the canvas, for debugging texture packing.
renderSampleDensity(): voidDraws a heatmap of the per pixel sample counts, for spotting pixels that converge slowly.
Note
Measures on every call and draws with the previous result, since the readback lands a frame later.
dispose(): voidFrees every GPU resource held by the tracer, including any attached denoiser and upscaler.
getRenderTime(): numberMilliseconds elapsed since the last reset.
min: numberLowest sample count of any pixel.
max: numberHighest sample count of any pixel.
avg: numberMean sample count across the image.
samplesPerSecond: numberMean samples accumulated per second since the last reset.