Browse Source

Editor: Added pathtracer to viewport. (#27643)

mrdoob 1 year ago
parent
commit
a646a64002
4 changed files with 123 additions and 4 deletions
  1. 5 1
      editor/index.html
  2. 2 2
      editor/js/Viewport.Controls.js
  3. 98 0
      editor/js/Viewport.Pathtracer.js
  4. 18 1
      editor/js/Viewport.js

+ 5 - 1
editor/index.html

@@ -58,7 +58,11 @@
 			{
 			{
 				"imports": {
 				"imports": {
 					"three": "../build/three.module.js",
 					"three": "../build/three.module.js",
-					"three/addons/": "../examples/jsm/"
+					"three/addons/": "../examples/jsm/",
+
+					"three/examples/": "../examples/",
+					"three-gpu-pathtracer": "https://unpkg.com/[email protected]/build/index.module.js",
+					"three-mesh-bvh": "https://unpkg.com/[email protected]/build/index.module.js"
 				}
 				}
 			}
 			}
 		</script>
 		</script>

+ 2 - 2
editor/js/Viewport.Controls.js

@@ -50,8 +50,8 @@ function ViewportControls( editor ) {
 	// shading
 	// shading
 
 
 	const shadingSelect = new UISelect();
 	const shadingSelect = new UISelect();
-	shadingSelect.setOptions( { 'default': 'default', 'normals': 'normals', 'wireframe': 'wireframe' } );
-	shadingSelect.setValue( 'default' );
+	shadingSelect.setOptions( { 'realistic': 'realistic', 'solid': 'solid', 'normals': 'normals', 'wireframe': 'wireframe' } );
+	shadingSelect.setValue( 'solid' );
 	shadingSelect.onChange( function () {
 	shadingSelect.onChange( function () {
 
 
 		editor.setViewportShading( this.getValue() );
 		editor.setViewportShading( this.getValue() );

+ 98 - 0
editor/js/Viewport.Pathtracer.js

@@ -0,0 +1,98 @@
+import { FullScreenQuad } from 'three/examples/jsm/postprocessing/Pass.js';
+import {
+	PathTracingSceneGenerator,
+	PathTracingRenderer,
+	PhysicalPathTracingMaterial
+} from 'three-gpu-pathtracer';
+
+function ViewportPathtracer( renderer ) {
+
+	let pathtracer = null;
+	let quad = null;
+
+	function init( scene, camera ) {
+
+		if ( pathtracer === null ) {
+
+			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: 5 // THREE.CustomBlending
+			} ) );
+
+		}
+
+		pathtracer.material.backgroundBlur = scene.backgroundBlurriness;
+		pathtracer.reset();
+
+		const generator = new PathTracingSceneGenerator();
+		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 );
+
+		if ( scene.environment && scene.environment.isTexture === true ) {
+
+			ptMaterial.envMapInfo.updateFrom( scene.environment );
+
+		}
+
+	}
+
+	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 };

+ 18 - 1
editor/js/Viewport.js

@@ -17,6 +17,7 @@ import { SetRotationCommand } from './commands/SetRotationCommand.js';
 import { SetScaleCommand } from './commands/SetScaleCommand.js';
 import { SetScaleCommand } from './commands/SetScaleCommand.js';
 
 
 import { RoomEnvironment } from 'three/addons/environments/RoomEnvironment.js';
 import { RoomEnvironment } from 'three/addons/environments/RoomEnvironment.js';
+import { ViewportPathtracer } from './Viewport.Pathtracer.js';
 
 
 function Viewport( editor ) {
 function Viewport( editor ) {
 
 
@@ -33,6 +34,7 @@ function Viewport( editor ) {
 
 
 	let renderer = null;
 	let renderer = null;
 	let pmremGenerator = null;
 	let pmremGenerator = null;
+	let pathtracer = null;
 
 
 	const camera = editor.camera;
 	const camera = editor.camera;
 	const scene = editor.scene;
 	const scene = editor.scene;
@@ -378,6 +380,8 @@ function Viewport( editor ) {
 		pmremGenerator = new THREE.PMREMGenerator( renderer );
 		pmremGenerator = new THREE.PMREMGenerator( renderer );
 		pmremGenerator.compileEquirectangularShader();
 		pmremGenerator.compileEquirectangularShader();
 
 
+		pathtracer = new ViewportPathtracer( renderer );
+
 		container.dom.appendChild( renderer.domElement );
 		container.dom.appendChild( renderer.domElement );
 
 
 		render();
 		render();
@@ -398,6 +402,8 @@ function Viewport( editor ) {
 
 
 	signals.cameraChanged.add( function () {
 	signals.cameraChanged.add( function () {
 
 
+		pathtracer.reset();
+
 		render();
 		render();
 
 
 	} );
 	} );
@@ -641,7 +647,11 @@ function Viewport( editor ) {
 
 
 		switch ( viewportShading ) {
 		switch ( viewportShading ) {
 
 
-			case 'default':
+			case 'realistic':
+				pathtracer.init( scene, camera );
+				break;
+
+			case 'solid':
 				scene.overrideMaterial = null;
 				scene.overrideMaterial = null;
 				break;
 				break;
 
 
@@ -668,6 +678,7 @@ function Viewport( editor ) {
 		updateAspectRatio();
 		updateAspectRatio();
 
 
 		renderer.setSize( container.dom.offsetWidth, container.dom.offsetHeight );
 		renderer.setSize( container.dom.offsetWidth, container.dom.offsetHeight );
+		pathtracer.setSize( container.dom.offsetWidth, container.dom.offsetHeight );
 
 
 		render();
 		render();
 
 
@@ -742,6 +753,12 @@ function Viewport( editor ) {
 
 
 		if ( needsUpdate === true ) render();
 		if ( needsUpdate === true ) render();
 
 
+		if ( editor.viewportShading === 'realistic' ) {
+
+			pathtracer.update();
+
+		}
+
 	}
 	}
 
 
 	//
 	//