Skip to content
Merged
Show file tree
Hide file tree
Changes from 63 commits
Commits
Show all changes
85 commits
Select commit Hold shift + click to select a range
5450878
Add wrappers for full-scene compute raycasting
gkjohnson Feb 17, 2026
80d9297
Add functions
gkjohnson Feb 17, 2026
728d428
Update Fns
gkjohnson Feb 17, 2026
7455a34
Updates
gkjohnson Feb 18, 2026
9def446
Updates
gkjohnson Feb 18, 2026
d9999f7
Small fixes
gkjohnson Feb 18, 2026
4b096b6
Fix member name, paren
gkjohnson Feb 18, 2026
43838ce
Fix buffer types
gkjohnson Feb 18, 2026
0f71720
Fix switch statement
gkjohnson Feb 18, 2026
6e5cd11
Other fixes
gkjohnson Feb 18, 2026
4ddfd78
Fixes
gkjohnson Feb 18, 2026
01118fd
More fixes
gkjohnson Feb 18, 2026
2a85e75
Fix variable use
gkjohnson Feb 18, 2026
cc4e5ca
Fix stride
gkjohnson Feb 18, 2026
8193940
Add indirect buffer support
gkjohnson Feb 18, 2026
65f986c
comments
gkjohnson Feb 18, 2026
380b550
Add intersection function
gkjohnson Feb 18, 2026
3813704
Separate functions
gkjohnson Feb 18, 2026
86f60b4
Updates
gkjohnson Feb 18, 2026
f0bfafe
comments
gkjohnson Feb 18, 2026
7003d3c
update three-mesh-bvh
gkjohnson Feb 19, 2026
a9be061
Adjust WebGPUPathtracer
gkjohnson Feb 19, 2026
41fd208
Pass bvh compute fns to megakernelpathtracer
gkjohnson Feb 19, 2026
696cf08
Add temp dispose function
gkjohnson Feb 19, 2026
0472c13
add comment
gkjohnson Feb 19, 2026
dbaeae4
Update
gkjohnson Feb 19, 2026
ee41ab1
Get a basic version working
gkjohnson Feb 19, 2026
361a54a
Fix multiroot bvhs
gkjohnson Feb 19, 2026
fa4463e
Cleanup
gkjohnson Feb 19, 2026
f0eff98
Updates
gkjohnson Feb 19, 2026
6a49319
Add output for object index
gkjohnson Feb 19, 2026
4363359
Updates
gkjohnson Feb 19, 2026
86e5ea0
clean up
gkjohnson Feb 19, 2026
42f30e2
More cleanup
gkjohnson Feb 19, 2026
c3816e8
Cleanup
gkjohnson Feb 19, 2026
e73117a
Cleanup
gkjohnson Feb 19, 2026
9e03595
Move attributes to a wgslstruct definition
gkjohnson Feb 19, 2026
809ef0a
Cleanup
gkjohnson Feb 20, 2026
80e8959
Add material support
gkjohnson Feb 20, 2026
c51a6c9
Cleanup
gkjohnson Feb 20, 2026
fa67477
Add a node proxy mechanism
gkjohnson Feb 20, 2026
b771782
Get wavefront pathtracer working
gkjohnson Feb 20, 2026
d459bd1
Initial indirect bvh handling
gkjohnson Feb 20, 2026
a1c9d14
Fix SAH case
gkjohnson Feb 20, 2026
34acdf2
Cleanup
gkjohnson Feb 20, 2026
09b5fe8
Updates
gkjohnson Feb 20, 2026
00013d6
Move NodeProxy
gkjohnson Feb 21, 2026
87518f4
Merge remote-tracking branch 'origin/webgpu-pathtracer' into scene-ra…
gkjohnson Feb 21, 2026
d20dcde
Rename computeFns
gkjohnson Feb 21, 2026
9d133b9
Move node to folder
gkjohnson Feb 21, 2026
7c97449
Proxy improvements
gkjohnson Feb 21, 2026
08a5fab
Add a wgslFnTagNode
gkjohnson Feb 21, 2026
e2ab877
Remove deprecated "clock"
gkjohnson Feb 21, 2026
13c7f7a
Use built-in struct definition calculation
gkjohnson Feb 21, 2026
10b9ef9
Remove unnecessary wgslstruct
gkjohnson Feb 21, 2026
2b8396d
Add lang arg
gkjohnson Feb 21, 2026
18547f4
Add support for includes, constants
gkjohnson Feb 21, 2026
9d02fe3
Use the tag function
gkjohnson Feb 22, 2026
15d21af
Pass attribute sizes
gkjohnson Feb 22, 2026
d2995cb
WGSLFnTagNode simplification
gkjohnson Feb 22, 2026
d1aed18
Simplification
gkjohnson Feb 22, 2026
0ce323f
Simplification
gkjohnson Feb 22, 2026
68c8f03
Fix up transforms
gkjohnson Feb 22, 2026
a48309e
Rename classes
gkjohnson Feb 22, 2026
2da88d9
Simplification
gkjohnson Feb 22, 2026
7fde608
Add comments
gkjohnson Feb 22, 2026
dae28f5
Move structs internally
gkjohnson Feb 22, 2026
fb71782
Simplify constants
gkjohnson Feb 22, 2026
25480cd
Simplify ray struct usage
gkjohnson Feb 22, 2026
228fbf3
Fix bvh compute data transform struct reference
gkjohnson Feb 22, 2026
c7bdc22
Add wgslTagCode
gkjohnson Feb 23, 2026
5135976
Deduplicate code
gkjohnson Feb 23, 2026
a9db555
Add shim for allowing structs to be passed to storage nodes
gkjohnson Feb 23, 2026
6e0d3ae
Add "getShapecastFn" impl
gkjohnson Feb 23, 2026
fef5d63
Switch to use the shapecast creation function for raycast
gkjohnson Feb 23, 2026
cb31eda
Fixups
gkjohnson Feb 23, 2026
51ce751
Move pathtracer compute data
gkjohnson Feb 23, 2026
8cf5a2a
comments
gkjohnson Feb 23, 2026
e919513
Fix instances
gkjohnson Feb 23, 2026
33b2b91
Make proxy call-able
gkjohnson Feb 24, 2026
d9fc765
Add glsl variants of the code tag functions
gkjohnson Feb 24, 2026
a6fd8ea
Adjust proxy node
gkjohnson Feb 25, 2026
855925a
Remove unnecessary "writeOffset"
gkjohnson Feb 25, 2026
53ecd95
Update ObjectBVH, fix BatchedMesh instance bug
gkjohnson Feb 25, 2026
f5371e0
Improve bvh update
gkjohnson Feb 25, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
"rollup": "^2.70.0",
"simple-git": "^3.10.0",
"three": "^0.183.1",
"three-mesh-bvh": "^0.9.5",
"three-mesh-bvh": "^0.9.8",
"typescript": "^5.9.2",
"vite": "^6.2.2",
"yargs": "^17.5.1"
Expand Down
41 changes: 4 additions & 37 deletions src/webgpu/MegaKernelPathTracer.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ function* renderTask() {
renderer,
camera,
kernel,
geometry,
bounces,

tiles,
Expand All @@ -22,13 +21,6 @@ function* renderTask() {
kernel.outputTarget = outputTarget;
kernel.sampleCountTarget = sampleCountTarget;

kernel.geom_index = geometry.index;
kernel.geom_position = geometry.position;
kernel.geom_normals = geometry.normal;
kernel.geom_material_index = geometry.materialIndex;
kernel.bvh = geometry.bvh;
kernel.materials = geometry.materials;

kernel.bounces = bounces;
kernel.inverseProjectionMatrix.copy( camera.projectionMatrixInverse );
kernel.cameraToModelMatrix.copy( camera.matrixWorld );
Expand Down Expand Up @@ -77,17 +69,6 @@ export class MegaKernelPathTracer {
this.bounces = 7;
this.tiles = new Vector2( 2, 2 );

// geometry fields
this.geometry = {
bvh: null,
index: null,
position: null,
normal: null,

materialIndex: null,
materials: null,
};

// targets
this.outputTarget = new StorageTexture( 1, 1, );
this.outputTarget.format = RGBAFormat;
Expand Down Expand Up @@ -118,23 +99,10 @@ export class MegaKernelPathTracer {

}

setGeometryData( geometry ) {

for ( const propName in geometry ) {

const prop = this.geometry[ propName ];
if ( prop === undefined ) {

console.error( `Invalid property name in geometry data: ${propName}` );
continue;
setBVHData( bvhData ) {

}

// TODO: cannot dispose at the moment
// prop.dispose();
this.geometry[ propName ] = geometry[ propName ];

}
this.kernel.bvhData = bvhData;
this.reset();

}

Expand Down Expand Up @@ -223,7 +191,6 @@ export class MegaKernelPathTracer {
this.samples = 0;
this._task = null;


const { width, height } = sampleCountTarget;
const dispatchSize = sampleCountClearKernel.getDispatchSize( width, height );

Expand All @@ -240,7 +207,7 @@ export class MegaKernelPathTracer {

update() {

if ( ! this.camera ) {
if ( ! this.camera || ! this.kernel ) {

return;

Expand Down
20 changes: 4 additions & 16 deletions src/webgpu/WaveFrontPathTracer.js
Original file line number Diff line number Diff line change
Expand Up @@ -225,23 +225,11 @@ export class WaveFrontPathTracer {

}

setGeometryData( geometry ) {
setBVHData( bvhData ) {

for ( const propName in geometry ) {

const prop = this.geometry[ propName ];
if ( prop === undefined ) {

console.error( `Invalid property name in geometry data: ${propName}` );
continue;

}

// TODO: cannot dispose at the moment
// prop.dispose();
this.geometry[ propName ] = geometry[ propName ];

}
this.rayIntersectionKernel.bvhData = bvhData;
this.hitProcessKernel.bvhData = bvhData;
this.reset();

}

Expand Down
130 changes: 25 additions & 105 deletions src/webgpu/WebGPUPathTracer.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { Color, StorageBufferAttribute, PerspectiveCamera, Scene, Vector2, Clock } from 'three/webgpu';
import { PathTracingSceneGenerator } from '../core/PathTracingSceneGenerator.js';
import { Vector2, Scene, PerspectiveCamera } from 'three/webgpu';
import { MeshBVH, SAH } from 'three-mesh-bvh';
import { FullScreenQuad } from 'three/examples/jsm/postprocessing/Pass.js';
import { RenderToScreenNodeMaterial } from './materials/RenderToScreenMaterial.js';
import { MegaKernelPathTracer } from './MegaKernelPathTracer.js';
import { WaveFrontPathTracer } from './WaveFrontPathTracer.js';
import { ObjectBVH } from './lib/ObjectBVH.js';
import { PathtracerBVHComputeData } from './lib/PathtracerBVHComputeData.js';

const _resolution = new Vector2();
export class WebGPUPathTracer {
Expand All @@ -24,19 +26,16 @@ export class WebGPUPathTracer {

this._pathTracer.dispose();
this._pathTracer = value ? new MegaKernelPathTracer( this._renderer ) : new WaveFrontPathTracer( this._renderer );
this._generator = new PathTracingSceneGenerator();
this._pathTracer.setBVHData( this._bvhData );
this.setCamera( this.camera );

}

constructor( renderer ) {

// members
this._renderer = renderer;
this._generator = new PathTracingSceneGenerator();
// this._pathTracer = new MegaKernelPathTracer( renderer );
this._pathTracer = new WaveFrontPathTracer( renderer );
this._queueReset = false;
this._clock = new Clock();
this._pathTracer = new MegaKernelPathTracer( renderer );

// options
this.renderScale = 1;
Expand All @@ -54,11 +53,25 @@ export class WebGPUPathTracer {
scene.updateMatrixWorld( true );
camera.updateMatrixWorld();

const generator = this._generator;
generator.setObjects( scene );
// Build BVH for each mesh geometry
scene.traverse( child => {

const result = generator.generate();
return this._updateFromResults( scene, camera, result );
if ( child.isMesh && ! child.geometry.boundsTree ) {

child.geometry.boundsTree = new MeshBVH( child.geometry, { strategy: SAH, maxLeafSize: 5 } );

}

} );

// Build TLAS and compute functions
const objectBVH = new ObjectBVH( scene, { strategy: SAH } );
const bvhData = new PathtracerBVHComputeData( objectBVH );
bvhData.update();

this._bvhData = bvhData;
this._pathTracer.setBVHData( bvhData );
this.setCamera( camera );

}

Expand All @@ -85,80 +98,6 @@ export class WebGPUPathTracer {

}

_updateFromResults( scene, camera, results ) {

const {
materials,
geometry,
bvh,
bvhChanged,
needsMaterialIndexUpdate,
} = results;

const pathTracer = this._pathTracer;

const newGeometryData = {};

if ( bvhChanged ) {

// dereference a new index attribute if we're using indirect storage
const dereferencedIndexAttr = geometry.index.clone();
const indirectBuffer = bvh._indirectBuffer;
if ( indirectBuffer ) {

dereferenceIndex( geometry, indirectBuffer, dereferencedIndexAttr );

}

const newIndex = new StorageBufferAttribute( dereferencedIndexAttr.array, 3 );
newIndex.name = 'Geometry Index';
newGeometryData.index = newIndex;

const newPosition = new StorageBufferAttribute( geometry.attributes.position.array, 3 );
newPosition.name = 'Geometry Positions';
newGeometryData.position = newPosition;

const newNormals = new StorageBufferAttribute( geometry.attributes.normal.array, 3 );
newNormals.name = 'Geometry Normals';
newGeometryData.normal = newNormals;

const newBvhRoots = new StorageBufferAttribute( new Float32Array( bvh._roots[ 0 ] ), 8 );
newBvhRoots.name = 'BVH Roots';
newGeometryData.bvh = newBvhRoots;

}

if ( needsMaterialIndexUpdate ) {

const newMaterialIndex = new StorageBufferAttribute( geometry.attributes.materialIndex.array, 1 );
newMaterialIndex.name = 'Material Index';
newGeometryData.materialIndex = newMaterialIndex;

}

const newMaterialsData = new Float32Array( materials.length * 3 );
const defaultColor = new Color();
for ( let i = 0; i < materials.length; i ++ ) {

const material = materials[ i ];
const color = material.color ?? defaultColor;
// Make sure those are in linear-sRGB space
newMaterialsData[ 3 * i + 0 ] = color.r;
newMaterialsData[ 3 * i + 1 ] = color.g;
newMaterialsData[ 3 * i + 2 ] = color.b;

}

const newMaterialsBuffer = new StorageBufferAttribute( newMaterialsData, 3 );
newMaterialsBuffer.name = 'Material Data';
newGeometryData.materials = newMaterialsBuffer;

pathTracer.setGeometryData( newGeometryData );

this.setCamera( camera );

}

renderSample() {

if ( ! this._renderer._initialized ) {
Expand Down Expand Up @@ -216,22 +155,3 @@ export class WebGPUPathTracer {
}

}

// TODO: Expose in three-mesh-bvh?
function dereferenceIndex( geometry, indirectBuffer, target ) {

const unpacked = target.array;
const indexArray = geometry.index ? geometry.index.array : null;
for ( let i = 0, l = indirectBuffer.length; i < l; i ++ ) {

const i3 = 3 * i;
const v3 = 3 * indirectBuffer[ i ];
for ( let c = 0; c < 3; c ++ ) {

unpacked[ i3 + c ] = indexArray ? indexArray[ v3 + c ] : v3 + c;

}

}

}
Loading