Skip to content

Commit 8d92892

Browse files
committed
Add a basic example
1 parent 98d69f8 commit 8d92892

File tree

2 files changed

+209
-0
lines changed

2 files changed

+209
-0
lines changed

example/basic.html

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<html>
2+
<head>
3+
<title>Basic Path Tracing Example</title>
4+
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
5+
6+
<style>
7+
html, body {
8+
margin: 0;
9+
padding: 0;
10+
background-color: #111;
11+
}
12+
13+
#info {
14+
position: absolute;
15+
bottom: 0;
16+
left: 0;
17+
font-family: 'Courier New', Courier, monospace;
18+
color: white;
19+
pointer-events: none;
20+
}
21+
22+
#samples, #credits {
23+
24+
opacity: 0.5;
25+
background-color: rgba( 0.0, 0.0, 0.0, 0.5 );
26+
padding: 5px;
27+
display: inline-block;
28+
29+
}
30+
31+
#loading {
32+
position: absolute;
33+
left: 50%;
34+
top: 50%;
35+
transform: translate(-50%, -50%);
36+
color: white;
37+
font-family: 'Courier New', Courier, monospace;
38+
}
39+
</style>
40+
41+
</head>
42+
<body>
43+
<div id="loading">LOADING</div>
44+
<div id="info">
45+
<div>
46+
<div id="samples">--</div>
47+
</div>
48+
<div>
49+
<div id="credits">Model by "nyancube" on Sketchfab.</div>
50+
</div>
51+
</div>
52+
<script src="./basic.js" type="module"></script>
53+
</body>
54+
</html>

example/basic.js

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
import * as THREE from 'three';
2+
import { FullScreenQuad } from 'three/examples/jsm/postprocessing/Pass.js';
3+
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
4+
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
5+
import { PathTracingRenderer, PhysicalPathTracingMaterial, PhysicalCamera } from '../src/index.js';
6+
import { PathTracingSceneWorker } from '../src/workers/PathTracingSceneWorker.js';
7+
import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader.js';
8+
9+
let renderer, controls, pathTracer, blitQuad, camera, scene, samplesEl;
10+
11+
let tiles = 1;
12+
let resolutionScale = 1;
13+
14+
// adjust performance parameters for mobile
15+
const aspectRatio = window.innerWidth / window.innerHeight;
16+
if ( aspectRatio < 0.65 ) {
17+
18+
resolutionScale *= 0.5;
19+
tiles = 2;
20+
21+
}
22+
23+
init();
24+
25+
async function init() {
26+
27+
samplesEl = document.getElementById( 'samples' );
28+
29+
// init renderer, camera, controls, scene
30+
renderer = new THREE.WebGLRenderer( { antialias: true } );
31+
renderer.toneMapping = THREE.ACESFilmicToneMapping;
32+
renderer.outputEncoding = THREE.sRGBEncoding;
33+
renderer.setClearColor( 0, 0 );
34+
document.body.appendChild( renderer.domElement );
35+
36+
camera = new PhysicalCamera( 75, 1, 0.025, 500 );
37+
camera.position.set( 8, 9, 24 );
38+
39+
controls = new OrbitControls( camera, renderer.domElement );
40+
controls.target.y = 10;
41+
controls.update();
42+
43+
scene = new THREE.Scene();
44+
45+
// init path tracer
46+
pathTracer = new PathTracingRenderer( renderer );
47+
pathTracer.material = new PhysicalPathTracingMaterial();
48+
pathTracer.material.filterGlossyFactor = 0.5;
49+
pathTracer.material.backgroundBlur = 0.05;
50+
pathTracer.tiles.set( tiles, tiles );
51+
pathTracer.camera = camera;
52+
53+
blitQuad = new FullScreenQuad( new THREE.MeshBasicMaterial( {
54+
map: pathTracer.target.texture,
55+
blending: THREE.CustomBlending,
56+
} ) );
57+
58+
controls.addEventListener( 'change', () => {
59+
60+
pathTracer.reset();
61+
62+
} );
63+
64+
// load the envmap and model
65+
const envMapPromise = new RGBELoader()
66+
.loadAsync( 'https://raw.githubusercontent.com/gkjohnson/3d-demo-data/master/hdri/chinese_garden_1k.hdr' )
67+
.then( texture => {
68+
69+
texture.mapping = THREE.EquirectangularReflectionMapping;
70+
scene.background = texture;
71+
scene.environment = texture;
72+
pathTracer.material.envMapInfo.updateFrom( texture );
73+
74+
} );
75+
76+
const generator = new PathTracingSceneWorker();
77+
const gltfPromise = new GLTFLoader()
78+
.loadAsync( 'https://raw.githubusercontent.com/gkjohnson/3d-demo-data/main/models/terrarium-robots/scene.gltf' )
79+
.then( gltf => {
80+
81+
return generator.generate( gltf.scene );
82+
83+
} )
84+
.then( result => {
85+
86+
scene.add( result.scene );
87+
88+
const { bvh, textures, materials } = result;
89+
const geometry = bvh.geometry;
90+
const material = pathTracer.material;
91+
92+
material.bvh.updateFrom( bvh );
93+
material.normalAttribute.updateFrom( geometry.attributes.normal );
94+
material.tangentAttribute.updateFrom( geometry.attributes.tangent );
95+
material.uvAttribute.updateFrom( geometry.attributes.uv );
96+
material.materialIndexAttribute.updateFrom( geometry.attributes.materialIndex );
97+
material.textures.setTextures( renderer, 2048, 2048, textures );
98+
material.materials.updateFrom( materials, textures );
99+
100+
generator.dispose();
101+
102+
} );
103+
104+
// wait for the scene to be rady
105+
await Promise.all( [ gltfPromise, envMapPromise ] );
106+
107+
document.getElementById( 'loading' ).remove();
108+
window.addEventListener( 'resize', onResize );
109+
110+
onResize();
111+
animate();
112+
113+
}
114+
115+
function onResize() {
116+
117+
// update rendering resolution
118+
const w = window.innerWidth;
119+
const h = window.innerHeight;
120+
const scale = resolutionScale;
121+
const dpr = window.devicePixelRatio;
122+
123+
pathTracer.setSize( w * scale * dpr, h * scale * dpr );
124+
pathTracer.reset();
125+
126+
renderer.setSize( w, h );
127+
renderer.setPixelRatio( window.devicePixelRatio * scale );
128+
129+
const aspect = w / h;
130+
camera.aspect = aspect;
131+
camera.updateProjectionMatrix();
132+
133+
}
134+
135+
function animate() {
136+
137+
requestAnimationFrame( animate );
138+
139+
camera.updateMatrixWorld();
140+
pathTracer.update();
141+
142+
if ( pathTracer.samples < 1 ) {
143+
144+
renderer.render( scene, camera );
145+
146+
}
147+
148+
renderer.autoClear = false;
149+
blitQuad.material.map = pathTracer.target.texture;
150+
blitQuad.render( renderer );
151+
renderer.autoClear = true;
152+
153+
samplesEl.innerText = `Samples: ${ Math.floor( pathTracer.samples ) }`;
154+
155+
}

0 commit comments

Comments
 (0)