123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- import * as THREE from 'three';
- import { FullScreenQuad } from 'three/examples/jsm/postprocessing/Pass.js';
- import {
- PathTracingSceneGenerator,
- PathTracingRenderer,
- PhysicalPathTracingMaterial
- } from 'three-gpu-pathtracer';
- function buildColorTexture( color ) {
- const data = new Uint8Array( [ color.r * 255, color.g * 255, color.b * 255, 255 ] );
- const texture = new THREE.DataTexture( data, 1, 1, THREE.RGBAFormat );
- texture.needsUpdate = true;
- return texture;
- }
- function ViewportPathtracer( renderer ) {
- let generator = null;
- let pathtracer = null;
- let quad = null;
- let hdr = null;
- function init( scene, camera ) {
- if ( pathtracer === null ) {
- generator = new PathTracingSceneGenerator();
- pathtracer = new PathTracingRenderer( renderer );
- pathtracer.setSize( renderer.domElement.offsetWidth, renderer.domElement.offsetHeight );
- pathtracer.alpha = true;
- pathtracer.camera = camera;
- pathtracer.material = new PhysicalPathTracingMaterial();
- pathtracer.tiles.set( 3, 4 );
- quad = new FullScreenQuad( new THREE.MeshBasicMaterial( {
- map: pathtracer.target.texture,
- blending: THREE.CustomBlending
- } ) );
- }
- pathtracer.material.backgroundBlur = scene.backgroundBlurriness;
- pathtracer.reset();
- // TOFIX: If the scene is empty the generator crashes so we render a tiny cube (:
- if ( scene.children.length === 0 ) {
- scene = new THREE.Mesh( new THREE.BoxGeometry( 0.0001, 0.0001, 0.0001 ) );
- }
- const { bvh, textures, materials, lights } = generator.generate( scene );
- const ptGeometry = bvh.geometry;
- const ptMaterial = pathtracer.material;
- ptMaterial.bvh.updateFrom( bvh );
- ptMaterial.attributesArray.updateFrom(
- ptGeometry.attributes.normal,
- ptGeometry.attributes.tangent,
- ptGeometry.attributes.uv,
- ptGeometry.attributes.color,
- );
- ptMaterial.materialIndexAttribute.updateFrom( ptGeometry.attributes.materialIndex );
- ptMaterial.textures.setTextures( renderer, 2048, 2048, textures );
- ptMaterial.materials.updateFrom( materials, textures );
- ptMaterial.lights.updateFrom( lights );
- //
- const background = scene.background;
- if ( background ) {
- if ( background.isTexture ) {
- ptMaterial.backgroundMap = background;
- } else if ( background.isColor ) {
- ptMaterial.backgroundMap = buildColorTexture( background );
- }
- } else {
- ptMaterial.backgroundMap = buildColorTexture( new THREE.Color( 0x000000 ) );
- }
- //
- const environment = scene.environment;
- if ( environment && environment.isTexture === true ) {
- // Avoid calling envMapInfo() with the same hdr
- if ( scene.environment !== hdr ) {
- ptMaterial.envMapInfo.updateFrom( scene.environment );
- hdr = scene.environment;
- }
- } else {
- ptMaterial.envMapInfo.updateFrom( buildColorTexture( new THREE.Color( 0xffffff ) ) );
- }
- }
- function setSize( width, height ) {
- if ( pathtracer === null ) return;
- pathtracer.setSize( width, height );
- pathtracer.reset();
- }
- function update() {
- if ( pathtracer === null ) return;
- pathtracer.update();
- renderer.autoClear = false;
- quad.render( renderer );
- renderer.autoClear = true;
- }
- function reset() {
- if ( pathtracer === null ) return;
- pathtracer.reset();
- }
- return {
- init: init,
- setSize: setSize,
- update: update,
- reset: reset
- };
- }
- export { ViewportPathtracer };
|