Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Examples: Update examples to use WebGLPathTracer and three-gpu-pathter v0.0.21 #28233

Merged
merged 2 commits into from
Apr 29, 2024
Merged
Changes from all commits
Commits
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
192 changes: 61 additions & 131 deletions examples/webgl_renderer_pathtracer.html
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@
"three": "../build/three.module.js",
"three/addons/": "./jsm/",
"three/examples/": "./",
"three-gpu-pathtracer": "https://cdn.jsdelivr.net/npm/three-gpu-pathtracer@0.0.20/build/index.module.js",
"three-mesh-bvh": "https://cdn.jsdelivr.net/npm/three-mesh-bvh@0.7.3/build/index.module.js"
"three-gpu-pathtracer": "https://cdn.jsdelivr.net/npm/three-gpu-pathtracer@0.0.21/build/index.module.js",
"three-mesh-bvh": "https://cdn.jsdelivr.net/npm/three-mesh-bvh@0.7.4/build/index.module.js"
}
}
</script>
Expand All @@ -60,14 +60,12 @@
import { RGBELoader } from 'three/addons/loaders/RGBELoader.js';
import { LDrawLoader } from 'three/addons/loaders/LDrawLoader.js';
import { LDrawUtils } from 'three/addons/utils/LDrawUtils.js';
import { FullScreenQuad } from 'three/addons/postprocessing/Pass.js';

import { PhysicalPathTracingMaterial, PathTracingRenderer, MaterialReducer, BlurredEnvMapGenerator, PathTracingSceneGenerator, GradientEquirectTexture } from 'three-gpu-pathtracer';
import { WebGLPathTracer, BlurredEnvMapGenerator, GradientEquirectTexture } from 'three-gpu-pathtracer';

let progressBarDiv, samplesEl;
let camera, scene, renderer, controls, gui;
let pathTracer, sceneInfo, fsQuad, floor;
let delaySamples = 0;
let pathTracer, floor, gradientMap;

const params = {
enable: true,
Expand All @@ -89,50 +87,39 @@
};

init();
render();

function init() {

camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.set( 150, 200, 250 );

// initialize the renderer
renderer = new THREE.WebGLRenderer( { antialias: true, preserveDrawingBuffer: true, premultipliedAlpha: false } );
renderer = new THREE.WebGLRenderer( { antialias: true, alpha: true, preserveDrawingBuffer: true, premultipliedAlpha: false } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.setClearColor( 0xdddddd );
document.body.appendChild( renderer.domElement );

const gradientMap = new GradientEquirectTexture();
gradientMap = new GradientEquirectTexture();
gradientMap.topColor.set( 0xeeeeee );
gradientMap.bottomColor.set( 0xeaeaea );
gradientMap.update();

// initialize the pathtracer
pathTracer = new PathTracingRenderer( renderer );
pathTracer.camera = camera;
pathTracer.alpha = true;
pathTracer = new WebGLPathTracer( renderer );
pathTracer.filterGlossyFactor = 1;
pathTracer.minSamples = 3;
pathTracer.renderScale = params.resolutionScale;
pathTracer.tiles.set( params.tiles, params.tiles );
pathTracer.material = new PhysicalPathTracingMaterial( {
filterGlossyFactor: 0.5,
backgroundMap: gradientMap,
} );
pathTracer.material.setDefine( 'FEATURE_MIS', 1 );

fsQuad = new FullScreenQuad( new THREE.MeshBasicMaterial( {
map: pathTracer.target.texture,
blending: THREE.CustomBlending
} ) );

// scene
scene = new THREE.Scene();
scene.background = gradientMap;

controls = new OrbitControls( camera, renderer.domElement );
controls.addEventListener( 'change', () => {

delaySamples = 5;
pathTracer.reset();
pathTracer.updateCamera();

} );

Expand Down Expand Up @@ -161,7 +148,7 @@
progressBarDiv.innerText = 'Loading...';

let model = null;
let envMap = null;
let environment = null;

updateProgressBar( 0 );
showProgressBar();
Expand All @@ -173,12 +160,22 @@
.loadAsync( 'models/7140-1-X-wingFighter.mpd_Packed.mpd', onProgress )
.then( function ( legoGroup ) {

// Convert from LDraw coordinates: rotate 180 degrees around OX
legoGroup = LDrawUtils.mergeObject( legoGroup );
legoGroup.rotation.x = Math.PI;
legoGroup.updateMatrixWorld();
model = legoGroup;

// adjust the materials to use transmission, be a bit shinier
legoGroup.traverse( c => {

// hide the line segments
if ( c.isLineSegments ) {

c.visible = false;

}

// adjust the materials to use transmission, be a bit shinier
if ( c.material ) {

c.material.roughness *= 0.25;
Expand All @@ -190,6 +187,7 @@

newMaterial.opacity = 1.0;
newMaterial.transmission = 1.0;
newMaterial.thickness = 1.0;
newMaterial.ior = 1.4;
newMaterial.roughness = oldMaterial.roughness;
newMaterial.metalness = 0.0;
Expand All @@ -207,12 +205,6 @@

} );

model = new THREE.Group();
model.add( legoGroup );

// Convert from LDraw coordinates: rotate 180 degrees around OX
model.updateMatrixWorld();

} )
.catch( onError );

Expand All @@ -225,16 +217,19 @@
const envMapGenerator = new BlurredEnvMapGenerator( renderer );
const blurredEnvMap = envMapGenerator.generate( tex, 0 );

scene.environment = blurredEnvMap;
envMap = blurredEnvMap;
environment = blurredEnvMap;

} );
} )
.catch( onError );

await Promise.all( [ envMapPromise, ldrawPromise ] );

hideProgressBar();
document.body.classList.add( 'checkerboard' );

// set environment map
scene.environment = environment;

// Adjust camera
const bbox = new THREE.Box3().setFromObject( model );
const size = bbox.getSize( new THREE.Vector3() );
Expand All @@ -244,84 +239,49 @@
controls.position0.set( 2.3, 1, 2 ).multiplyScalar( radius ).add( controls.target0 );
controls.reset();

// add the model
scene.add( model );

// add floor
floor = new THREE.Mesh(
new THREE.PlaneGeometry(),
new THREE.MeshStandardMaterial( {
side: THREE.DoubleSide,
roughness: 0.01,
metalness: 1,
roughness: params.roughness,
metalness: params.metalness,
map: generateRadialFloorTexture( 1024 ),
transparent: true,
} ),
);
floor.scale.setScalar( 2500 );
floor.rotation.x = - Math.PI / 2;
floor.position.y = bbox.min.y;
model.add( floor );
model.updateMatrixWorld();

// de-duplicate and reduce the number of materials used in place
const reducer = new MaterialReducer();
reducer.process( model );
scene.add( floor );

// reset the progress bar to display bvh generation
progressBarDiv.innerText = 'Generating BVH...';
updateProgressBar( 0 );

const generator = new PathTracingSceneGenerator();
const result = generator.generate( model );

// add the model to the scene
sceneInfo = result;
model.traverse( c => {

if ( c.isLineSegments ) {

c.visible = false;

}

} );
scene.add( model );

// update the material
const { bvh, textures, materials } = result;
const geometry = bvh.geometry;
const material = pathTracer.material;

material.bvh.updateFrom( bvh );
material.attributesArray.updateFrom(
geometry.attributes.normal,
geometry.attributes.tangent,
geometry.attributes.uv,
geometry.attributes.color,
);
material.materialIndexAttribute.updateFrom( geometry.attributes.materialIndex );
material.textures.setTextures( renderer, 2048, 2048, textures );
material.materials.updateFrom( materials, textures );
pathTracer.material.envMapInfo.updateFrom( envMap );
pathTracer.reset();
pathTracer.setScene( scene, camera );
render();

}

function onWindowResize() {

const w = window.innerWidth;
const h = window.innerHeight;
const scale = params.resolutionScale;
const dpr = window.devicePixelRatio;

pathTracer.setSize( w * scale * dpr, h * scale * dpr );
pathTracer.reset();

renderer.setSize( w, h );
renderer.setPixelRatio( window.devicePixelRatio * scale );
renderer.setPixelRatio( dpr );

const aspect = w / h;
camera.aspect = aspect;
camera.updateProjectionMatrix();

pathTracer.updateCamera();

}

function createGUI() {
Expand All @@ -338,25 +298,31 @@
gui.add( params, 'toneMapping' );
gui.add( params, 'transparentBackground' ).onChange( v => {

pathTracer.material.backgroundAlpha = v ? 0 : 1;
renderer.setClearAlpha( v ? 0 : 1 );
scene.background = v ? null : gradientMap;
pathTracer.updateEnvironment();

} );
gui.add( params, 'resolutionScale', 0.1, 1.0, 0.1 ).onChange( v => {

pathTracer.renderScale = v;
pathTracer.reset();

} );
gui.add( params, 'resolutionScale', 0.1, 1.0, 0.1 ).onChange( onWindowResize );
gui.add( params, 'tiles', 1, 3, 1 ).onChange( v => {
gui.add( params, 'tiles', 1, 6, 1 ).onChange( v => {

pathTracer.tiles.set( v, v );

} );
gui.add( params, 'roughness', 0, 1 ).name( 'floor roughness' ).onChange( () => {
gui.add( params, 'roughness', 0, 1 ).name( 'floor roughness' ).onChange( v => {

pathTracer.reset();
floor.material.roughness = v;
pathTracer.updateMaterials();

} );
gui.add( params, 'metalness', 0, 1 ).name( 'floor metalness' ).onChange( () => {
gui.add( params, 'metalness', 0, 1 ).name( 'floor metalness' ).onChange( v => {

pathTracer.reset();
floor.material.metalness = v;
pathTracer.updateMaterials();

} );
gui.add( params, 'download' ).name( 'download image' );
Expand All @@ -370,7 +336,6 @@
renderFolder.$children.appendChild( samplesEl );
renderFolder.open();


}

//
Expand All @@ -379,49 +344,14 @@

requestAnimationFrame( render );

if ( ! sceneInfo ) {

return;

}

renderer.toneMapping = params.toneMapping ? THREE.ACESFilmicToneMapping : THREE.NoToneMapping;

if ( pathTracer.samples < 1.0 || ! params.enable ) {

renderer.render( scene, camera );

}
const samples = Math.floor( pathTracer.samples );
samplesEl.innerText = `samples: ${ samples }`;

if ( params.enable && delaySamples === 0 ) {

const samples = Math.floor( pathTracer.samples );
samplesEl.innerText = `samples: ${ samples }`;

floor.material.roughness = params.roughness;
floor.material.metalness = params.metalness;

pathTracer.material.materials.updateFrom( sceneInfo.materials, sceneInfo.textures );
pathTracer.material.filterGlossyFactor = 1;
pathTracer.material.physicalCamera.updateFrom( camera );

camera.updateMatrixWorld();

if ( ! params.pause || pathTracer.samples < 1 ) {

pathTracer.update();

}

renderer.autoClear = false;
fsQuad.render( renderer );
renderer.autoClear = true;

} else if ( delaySamples > 0 ) {

delaySamples --;

}
pathTracer.enablePathTracing = params.enable;
pathTracer.pausePathTracing = params.pause;
pathTracer.renderSample();

samplesEl.innerText = `samples: ${ Math.floor( pathTracer.samples ) }`;

Expand Down
Loading