2
0
Эх сурвалжийг харах

GLTFLoader: Add KHR_materials_volume and KHR_materials_ior extensions support (#22117)

* GLTFLoader: Add KHR_materials_volume and KHR_materials_ior extensions support

* Update example screenshot
Takahiro 4 жил өмнө
parent
commit
361a46cbeb

+ 3 - 0
docs/examples/en/loaders/GLTFLoader.html

@@ -30,8 +30,11 @@
 		<ul>
 			<li>KHR_draco_mesh_compression</li>
 			<li>KHR_materials_clearcoat</li>
+			<li>KHR_materials_ior</li>
 			<li>KHR_materials_pbrSpecularGlossiness</li>
+			<li>KHR_materials_transmission</li>
 			<li>KHR_materials_unlit</li>
+			<li>KHR_materials_volume</li>
 			<li>KHR_mesh_quantization</li>
 			<li>KHR_lights_punctual<sup>1</sup></li>
 			<li>KHR_texture_basisu</li>

+ 3 - 0
docs/examples/zh/loaders/GLTFLoader.html

@@ -28,8 +28,11 @@
 		<ul>
 			<li>KHR_draco_mesh_compression</li>
 			<li>KHR_materials_clearcoat</li>
+			<li>KHR_materials_ior</li>
 			<li>KHR_materials_pbrSpecularGlossiness</li>
+			<li>KHR_materials_transmission</li>
 			<li>KHR_materials_unlit</li>
+			<li>KHR_materials_volume</li>
 			<li>KHR_mesh_quantization</li>
 			<li>KHR_lights_punctual<sup>1</sup></li>
 			<li>KHR_texture_basisu</li>

+ 119 - 0
examples/jsm/loaders/GLTFLoader.js

@@ -99,6 +99,18 @@ class GLTFLoader extends Loader {
 
 		} );
 
+		this.register( function ( parser ) {
+
+			return new GLTFMaterialsVolumeExtension( parser );
+
+		} );
+
+		this.register( function ( parser ) {
+
+			return new GLTFMaterialsIorExtension( parser );
+
+		} );
+
 		this.register( function ( parser ) {
 
 			return new GLTFLightsExtension( parser );
@@ -407,9 +419,11 @@ const EXTENSIONS = {
 	KHR_DRACO_MESH_COMPRESSION: 'KHR_draco_mesh_compression',
 	KHR_LIGHTS_PUNCTUAL: 'KHR_lights_punctual',
 	KHR_MATERIALS_CLEARCOAT: 'KHR_materials_clearcoat',
+	KHR_MATERIALS_IOR: 'KHR_materials_ior',
 	KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS: 'KHR_materials_pbrSpecularGlossiness',
 	KHR_MATERIALS_TRANSMISSION: 'KHR_materials_transmission',
 	KHR_MATERIALS_UNLIT: 'KHR_materials_unlit',
+	KHR_MATERIALS_VOLUME: 'KHR_materials_volume',
 	KHR_TEXTURE_BASISU: 'KHR_texture_basisu',
 	KHR_TEXTURE_TRANSFORM: 'KHR_texture_transform',
 	KHR_MESH_QUANTIZATION: 'KHR_mesh_quantization',
@@ -742,6 +756,111 @@ class GLTFMaterialsTransmissionExtension {
 
 }
 
+/**
+ * Materials Volume Extension
+ *
+ * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_volume
+ */
+class GLTFMaterialsVolumeExtension {
+
+	constructor( parser ) {
+
+		this.parser = parser;
+		this.name = EXTENSIONS.KHR_MATERIALS_VOLUME;
+
+	}
+
+	getMaterialType( materialIndex ) {
+
+		const parser = this.parser;
+		const materialDef = parser.json.materials[ materialIndex ];
+
+		if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null;
+
+		return MeshPhysicalMaterial;
+
+	}
+
+	extendMaterialParams( materialIndex, materialParams ) {
+
+		const parser = this.parser;
+		const materialDef = parser.json.materials[ materialIndex ];
+
+		if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) {
+
+			return Promise.resolve();
+
+		}
+
+		const pending = [];
+
+		const extension = materialDef.extensions[ this.name ];
+
+		materialParams.thickness = extension.thicknessFactor !== undefined ? extension.thicknessFactor : 0;
+
+		if ( extension.thicknessTexture !== undefined ) {
+
+			pending.push( parser.assignTexture( materialParams, 'thicknessMap', extension.thicknessTexture ) );
+
+		}
+
+		materialParams.attenuationDistance = extension.attenuationDistance || 0;
+
+		const colorArray = extension.attenuationColor || [ 1, 1, 1 ];
+		materialParams.attenuationColor = new Color( colorArray[ 0 ], colorArray[ 1 ], colorArray[ 2 ] );
+
+		return Promise.all( pending );
+
+	}
+
+}
+
+/**
+ * Materials ior Extension
+ *
+ * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_ior
+ */
+class GLTFMaterialsIorExtension {
+
+	constructor( parser ) {
+
+		this.parser = parser;
+		this.name = EXTENSIONS.KHR_MATERIALS_IOR;
+
+	}
+
+	getMaterialType( materialIndex ) {
+
+		const parser = this.parser;
+		const materialDef = parser.json.materials[ materialIndex ];
+
+		if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null;
+
+		return MeshPhysicalMaterial;
+
+	}
+
+	extendMaterialParams( materialIndex, materialParams ) {
+
+		const parser = this.parser;
+		const materialDef = parser.json.materials[ materialIndex ];
+
+		if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) {
+
+			return Promise.resolve();
+
+		}
+
+		const extension = materialDef.extensions[ this.name ];
+
+		materialParams.ior = extension.ior !== undefined ? extension.ior : 1.5;
+
+		return Promise.resolve();
+
+	}
+
+}
+
 /**
  * BasisU Texture Extension
  *

BIN
examples/models/gltf/IridescentDishWithOlives.glb


BIN
examples/models/gltf/TransmissionTest.glb


BIN
examples/screenshots/webgl_loader_gltf_transmission.jpg


+ 21 - 14
examples/webgl_loader_gltf_transmission.html

@@ -10,8 +10,7 @@
 	<body>
 		<div id="info">
 			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - GLTFLoader + <a href="https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_transmission" target="_blank" rel="noopener">KHR_materials_transmission</a> extension<br />
-			<a href="https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0/TransmissionTest" target="_blank" rel="noopener">Transmission Test</a> by
-			<a href="https://www.adobe.com/" target="_blank" rel="noopener">Adobe, Inc</a><br />
+			Iridescent Dish With Olives by <a href="https://github.com/echadwick-wayfair" target="_blank" rel="noopener">Eric Chadwick</a><br />
 			<a href="https://hdrihaven.com/hdri/?h=quarry_01" target="_blank" rel="noopener">Quarry</a> by <a href="https://hdrihaven.com/" target="_blank" rel="noopener">HDRI Haven</a>
 		</div>
 
@@ -23,18 +22,20 @@
 			import { GLTFLoader } from './jsm/loaders/GLTFLoader.js';
 			import { RGBELoader } from './jsm/loaders/RGBELoader.js';
 
-			let camera, scene, renderer;
+			let camera, scene, renderer, clock, mixer;
 
 			init();
-			render();
+			animate();
 
 			function init() {
 
+				clock = new THREE.Clock();
+
 				const container = document.createElement( 'div' );
 				document.body.appendChild( container );
 
 				camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.25, 20 );
-				camera.position.set( 0, 0, 2.0 );
+				camera.position.set( 0, 0.5, 0.7 );
 
 				scene = new THREE.Scene();
 
@@ -51,15 +52,15 @@
 						texture.dispose();
 						pmremGenerator.dispose();
 
-						render();
-
 						// model
 
 						const loader = new GLTFLoader().setPath( 'models/gltf/' );
-						loader.load( 'TransmissionTest.glb', function ( gltf ) {
+						loader.load( 'IridescentDishWithOlives.glb', function ( gltf ) {
 
+							mixer = new THREE.AnimationMixer( gltf.scene );
+							mixer.clipAction( gltf.animations[ 0 ] ).play();
 							scene.add( gltf.scene );
-							render();
+							animate();
 
 						} );
 
@@ -77,10 +78,8 @@
 				pmremGenerator.compileEquirectangularShader();
 
 				const controls = new OrbitControls( camera, renderer.domElement );
-				controls.addEventListener( 'change', render ); // use if there is no animation loop
-				controls.minDistance = 1;
+				controls.minDistance = 0.5;
 				controls.maxDistance = 10;
-				controls.target.set( 0, 0.0, - 0.2 );
 				controls.update();
 
 				window.addEventListener( 'resize', onWindowResize );
@@ -94,12 +93,20 @@
 
 				renderer.setSize( window.innerWidth, window.innerHeight );
 
-				render();
-
 			}
 
 			//
 
+			function animate() {
+
+				requestAnimationFrame( animate );
+
+				if ( mixer ) mixer.update( clock.getDelta() );
+
+				render();
+
+			}
+
 			function render() {
 
 				renderer.render( scene, camera );