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

Implement KHR_materials_transmission.

Don McCurdy 5 жил өмнө
parent
commit
473e973314

+ 57 - 0
examples/js/loaders/GLTFLoader.js

@@ -19,6 +19,7 @@ THREE.GLTFLoader = ( function () {
 		this.ktx2Loader = null;
 
 		this.pluginCallbacks = [];
+
 		this.register( function ( parser ) {
 
 			return new GLTFMaterialsClearcoatExtension( parser );
@@ -30,6 +31,12 @@ THREE.GLTFLoader = ( function () {
 
 		} );
 
+		this.register( function ( parser ) {
+
+			return new GLTFMaterialsTransmissionExtension( parser );
+
+		} );
+
 	}
 
 	GLTFLoader.prototype = Object.assign( Object.create( THREE.Loader.prototype ), {
@@ -332,6 +339,7 @@ THREE.GLTFLoader = ( function () {
 		KHR_LIGHTS_PUNCTUAL: 'KHR_lights_punctual',
 		KHR_MATERIALS_CLEARCOAT: 'KHR_materials_clearcoat',
 		KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS: 'KHR_materials_pbrSpecularGlossiness',
+		KHR_MATERIALS_TRANSMISSION: 'KHR_materials_transmission',
 		KHR_MATERIALS_UNLIT: 'KHR_materials_unlit',
 		KHR_TEXTURE_BASISU: 'KHR_texture_basisu',
 		KHR_TEXTURE_TRANSFORM: 'KHR_texture_transform',
@@ -551,6 +559,55 @@ THREE.GLTFLoader = ( function () {
 
 	};
 
+	/**
+	 * Transmission Materials Extension
+	 *
+	 * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_transmission
+	 */
+	function GLTFMaterialsTransmissionExtension( parser ) {
+
+		this.parser = parser;
+		this.name = EXTENSIONS.KHR_MATERIALS_TRANSMISSION;
+
+	}
+
+	GLTFMaterialsTransmissionExtension.prototype.getMaterialType = function ( /* materialIndex */ ) {
+
+		return THREE.MeshPhysicalMaterial;
+
+	};
+
+	GLTFMaterialsTransmissionExtension.prototype.extendMaterialParams = function ( materialIndex, materialParams ) {
+
+		var parser = this.parser;
+		var materialDef = parser.json.materials[ materialIndex ];
+
+		if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) {
+
+			return Promise.resolve();
+
+		}
+
+		var pending = [];
+
+		var extension = materialDef.extensions[ this.name ];
+
+		if ( extension.transmissionFactor !== undefined ) {
+
+			materialParams.transmission = extension.transmissionFactor;
+
+		}
+
+		if ( extension.transmissionTexture !== undefined ) {
+
+			pending.push( parser.assignTexture( materialParams, 'transmissionMap', extension.transmissionTexture ) );
+
+		}
+
+		return Promise.all( pending );
+
+	};
+
 	/**
 	 * BasisU Texture Extension
 	 *

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

@@ -84,6 +84,7 @@ var GLTFLoader = ( function () {
 		this.ktx2Loader = null;
 
 		this.pluginCallbacks = [];
+
 		this.register( function ( parser ) {
 
 			return new GLTFMaterialsClearcoatExtension( parser );
@@ -95,6 +96,12 @@ var GLTFLoader = ( function () {
 
 		} );
 
+		this.register( function ( parser ) {
+
+			return new GLTFMaterialsTransmissionExtension( parser );
+
+		} );
+
 	}
 
 	GLTFLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
@@ -397,6 +404,7 @@ var GLTFLoader = ( function () {
 		KHR_LIGHTS_PUNCTUAL: 'KHR_lights_punctual',
 		KHR_MATERIALS_CLEARCOAT: 'KHR_materials_clearcoat',
 		KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS: 'KHR_materials_pbrSpecularGlossiness',
+		KHR_MATERIALS_TRANSMISSION: 'KHR_materials_transmission',
 		KHR_MATERIALS_UNLIT: 'KHR_materials_unlit',
 		KHR_TEXTURE_BASISU: 'KHR_texture_basisu',
 		KHR_TEXTURE_TRANSFORM: 'KHR_texture_transform',
@@ -616,6 +624,55 @@ var GLTFLoader = ( function () {
 
 	};
 
+	/**
+	 * Transmission Materials Extension
+	 *
+	 * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_transmission
+	 */
+	function GLTFMaterialsTransmissionExtension( parser ) {
+
+		this.parser = parser;
+		this.name = EXTENSIONS.KHR_MATERIALS_TRANSMISSION;
+
+	}
+
+	GLTFMaterialsTransmissionExtension.prototype.getMaterialType = function ( /* materialIndex */ ) {
+
+		return MeshPhysicalMaterial;
+
+	};
+
+	GLTFMaterialsTransmissionExtension.prototype.extendMaterialParams = function ( materialIndex, materialParams ) {
+
+		var parser = this.parser;
+		var materialDef = parser.json.materials[ materialIndex ];
+
+		if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) {
+
+			return Promise.resolve();
+
+		}
+
+		var pending = [];
+
+		var extension = materialDef.extensions[ this.name ];
+
+		if ( extension.transmissionFactor !== undefined ) {
+
+			materialParams.transmission = extension.transmissionFactor;
+
+		}
+
+		if ( extension.transmissionTexture !== undefined ) {
+
+			pending.push( parser.assignTexture( materialParams, 'transmissionMap', extension.transmissionTexture ) );
+
+		}
+
+		return Promise.all( pending );
+
+	};
+
 	/**
 	 * BasisU Texture Extension
 	 *

BIN
examples/models/gltf/Transmission.glb


+ 11 - 0
examples/webgl_loader_gltf_extensions.html

@@ -32,6 +32,17 @@
 			var clock = new THREE.Clock();
 
 			var scenes = {
+				Transmission: {
+					name: 'Transmission',
+					url: './models/gltf/Transmission.glb',
+					author: 'Adobe',
+					authorURL: 'https://www.adobe.com/',
+					cameraPos: new THREE.Vector3( 1, 0, -1.5 ),
+					objectPosition: new THREE.Vector3( 0, -0.5, 0 ),
+					objectRotation: new THREE.Euler( 0, Math.PI, 0 ),
+					extensions: [ 'glTF-MaterialsTransmission' ],
+					addEnvMap: true
+				},
 				Boombox: {
 					name: 'BoomBox (PBR)',
 					url: './models/gltf/BoomBox/%s/BoomBox.gltf',

+ 3 - 0
src/loaders/MaterialLoader.js

@@ -280,6 +280,9 @@ MaterialLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
 		if ( json.clearcoatNormalMap !== undefined ) material.clearcoatNormalMap = getTexture( json.clearcoatNormalMap );
 		if ( json.clearcoatNormalScale !== undefined ) material.clearcoatNormalScale = new Vector2().fromArray( json.clearcoatNormalScale );
 
+		if ( json.transmission !== undefined ) material.transmission = json.transmission;
+		if ( json.transmissionMap !== undefined ) material.transmissionMap = getTexture( json.transmissionMap );
+
 		return material;
 
 	},

+ 2 - 1
src/materials/MeshPhysicalMaterial.d.ts

@@ -34,6 +34,7 @@ export class MeshPhysicalMaterial extends MeshStandardMaterial {
 
 	sheen: Color | null;
 
-	transparency: number;
+	transmission: number;
+	transmissionMap: Texture | null;
 
 }

+ 6 - 3
src/materials/MeshPhysicalMaterial.js

@@ -17,7 +17,8 @@ import { Color } from '../math/Color.js';
  *
  *  sheen: <Color>,
  *
- *  transparency: <float>
+ *  transmission: <float>,
+ *  transmissionMap: new THREE.Texture( <Image> )
  * }
  */
 
@@ -45,7 +46,8 @@ function MeshPhysicalMaterial( parameters ) {
 
 	this.sheen = null; // null will disable sheen bsdf
 
-	this.transparency = 0.0;
+	this.transmission = 0.0;
+	this.transmissionMap = null;
 
 	this.setValues( parameters );
 
@@ -86,7 +88,8 @@ MeshPhysicalMaterial.prototype.copy = function ( source ) {
 
 	}
 
-	this.transparency = source.transparency;
+	this.transmission = source.transmission;
+	this.transmissionMap = source.transmissionMap;
 
 	return this;
 

+ 4 - 0
src/renderers/shaders/ShaderChunk.js

@@ -86,6 +86,8 @@ import specularmap_fragment from './ShaderChunk/specularmap_fragment.glsl.js';
 import specularmap_pars_fragment from './ShaderChunk/specularmap_pars_fragment.glsl.js';
 import tonemapping_fragment from './ShaderChunk/tonemapping_fragment.glsl.js';
 import tonemapping_pars_fragment from './ShaderChunk/tonemapping_pars_fragment.glsl.js';
+import transmissionmap_fragment from './ShaderChunk/transmissionmap_fragment.glsl.js';
+import transmissionmap_pars_fragment from './ShaderChunk/transmissionmap_pars_fragment.glsl.js';
 import uv_pars_fragment from './ShaderChunk/uv_pars_fragment.glsl.js';
 import uv_pars_vertex from './ShaderChunk/uv_pars_vertex.glsl.js';
 import uv_vertex from './ShaderChunk/uv_vertex.glsl.js';
@@ -216,6 +218,8 @@ export const ShaderChunk = {
 	specularmap_pars_fragment: specularmap_pars_fragment,
 	tonemapping_fragment: tonemapping_fragment,
 	tonemapping_pars_fragment: tonemapping_pars_fragment,
+	transmissionmap_fragment: transmissionmap_fragment,
+	transmissionmap_pars_fragment: transmissionmap_pars_fragment,
 	uv_pars_fragment: uv_pars_fragment,
 	uv_pars_vertex: uv_pars_vertex,
 	uv_vertex: uv_vertex,

+ 7 - 0
src/renderers/shaders/ShaderChunk/transmissionmap_fragment.glsl.js

@@ -0,0 +1,7 @@
+export default /* glsl */`
+#ifdef USE_TRANSMISSIONMAP
+
+	totalTransmission *= texture2D( transmissionMap, vUv ).r;
+
+#endif
+`;

+ 7 - 0
src/renderers/shaders/ShaderChunk/transmissionmap_pars_fragment.glsl.js

@@ -0,0 +1,7 @@
+export default /* glsl */`
+#ifdef USE_TRANSMISSIONMAP
+
+	uniform sampler2D transmissionMap;
+
+#endif
+`;

+ 2 - 1
src/renderers/shaders/ShaderLib.js

@@ -303,7 +303,8 @@ ShaderLib.physical = {
 			clearcoatNormalScale: { value: new Vector2( 1, 1 ) },
 			clearcoatNormalMap: { value: null },
 			sheen: { value: new Color( 0x000000 ) },
-			transparency: { value: 0 },
+			transmission: { value: 0 },
+			transmissionMap: { value: null },
 		}
 	] ),
 

+ 12 - 6
src/renderers/shaders/ShaderLib/meshphysical_frag.glsl.js

@@ -4,7 +4,7 @@ export default /* glsl */`
 #ifdef PHYSICAL
 	#define REFLECTIVITY
 	#define CLEARCOAT
-	#define TRANSPARENCY
+	#define TRANSMISSION
 #endif
 
 uniform vec3 diffuse;
@@ -13,8 +13,8 @@ uniform float roughness;
 uniform float metalness;
 uniform float opacity;
 
-#ifdef TRANSPARENCY
-	uniform float transparency;
+#ifdef TRANSMISSION
+	uniform float transmission;
 #endif
 
 #ifdef REFLECTIVITY
@@ -56,6 +56,7 @@ varying vec3 vViewPosition;
 #include <aomap_pars_fragment>
 #include <lightmap_pars_fragment>
 #include <emissivemap_pars_fragment>
+#include <transmissionmap_pars_fragment>
 #include <bsdfs>
 #include <cube_uv_reflection_fragment>
 #include <envmap_common_pars_fragment>
@@ -80,6 +81,10 @@ void main() {
 	ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );
 	vec3 totalEmissiveRadiance = emissive;
 
+	#ifdef TRANSMISSION
+		float totalTransmission = transmission;
+	#endif
+
 	#include <logdepthbuf_fragment>
 	#include <map_fragment>
 	#include <color_fragment>
@@ -92,6 +97,7 @@ void main() {
 	#include <clearcoat_normal_fragment_begin>
 	#include <clearcoat_normal_fragment_maps>
 	#include <emissivemap_fragment>
+	#include <transmissionmap_fragment>
 
 	// accumulation
 	#include <lights_physical_fragment>
@@ -104,9 +110,9 @@ void main() {
 
 	vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;
 
-	// this is a stub for the transparency model
-	#ifdef TRANSPARENCY
-		diffuseColor.a *= saturate( 1. - transparency + linearToRelativeLuminance( reflectedLight.directSpecular + reflectedLight.indirectSpecular ) );
+	// this is a stub for the transmission model
+	#ifdef TRANSMISSION
+		diffuseColor.a *= saturate( 1. - totalTransmission + linearToRelativeLuminance( reflectedLight.directSpecular + reflectedLight.indirectSpecular ) );
 	#endif
 
 	gl_FragColor = vec4( outgoingLight, diffuseColor.a );

+ 7 - 1
src/renderers/webgl/WebGLMaterials.js

@@ -566,7 +566,13 @@ function WebGLMaterials( properties ) {
 
 		}
 
-		uniforms.transparency.value = material.transparency;
+		uniforms.transmission.value = material.transmission;
+
+		if ( material.transmissionMap ) {
+
+			uniforms.transmissionMap.value = material.transmissionMap;
+
+		}
 
 	}
 

+ 2 - 0
src/renderers/webgl/WebGLProgram.js

@@ -475,6 +475,7 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) {
 			parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
 			parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
 			parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
+			parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '',
 
 			parameters.vertexTangents ? '#define USE_TANGENT' : '',
 			parameters.vertexColors ? '#define USE_COLOR' : '',
@@ -604,6 +605,7 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) {
 			parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
 
 			parameters.sheen ? '#define USE_SHEEN' : '',
+			parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '',
 
 			parameters.vertexTangents ? '#define USE_TANGENT' : '',
 			parameters.vertexColors ? '#define USE_COLOR' : '',

+ 5 - 3
src/renderers/webgl/WebGLPrograms.js

@@ -50,7 +50,7 @@ function WebGLPrograms( renderer, extensions, capabilities, bindingStates ) {
 		"numDirLightShadows", "numPointLightShadows", "numSpotLightShadows",
 		"shadowMapEnabled", "shadowMapType", "toneMapping", 'physicallyCorrectLights',
 		"alphaTest", "doubleSided", "flipSided", "numClippingPlanes", "numClipIntersection", "depthPacking", "dithering",
-		"sheen"
+		"sheen", "transmissionMap"
 	];
 
 	function allocateBones( object ) {
@@ -206,12 +206,14 @@ function WebGLPrograms( renderer, extensions, capabilities, bindingStates ) {
 
 			sheen: !! material.sheen,
 
+			transmissionMap: !! material.transmissionMap,
+
 			combine: material.combine,
 
 			vertexTangents: ( material.normalMap && material.vertexTangents ),
 			vertexColors: material.vertexColors,
-			vertexUvs: !! material.map || !! material.bumpMap || !! material.normalMap || !! material.specularMap || !! material.alphaMap || !! material.emissiveMap || !! material.roughnessMap || !! material.metalnessMap || !! material.clearcoatMap || !! material.clearcoatRoughnessMap || !! material.clearcoatNormalMap || !! material.displacementMap,
-			uvsVertexOnly: ! ( !! material.map || !! material.bumpMap || !! material.normalMap || !! material.specularMap || !! material.alphaMap || !! material.emissiveMap || !! material.roughnessMap || !! material.metalnessMap || !! material.clearcoatNormalMap ) && !! material.displacementMap,
+			vertexUvs: !! material.map || !! material.bumpMap || !! material.normalMap || !! material.specularMap || !! material.alphaMap || !! material.emissiveMap || !! material.roughnessMap || !! material.metalnessMap || !! material.clearcoatMap || !! material.clearcoatRoughnessMap || !! material.clearcoatNormalMap || !! material.displacementMap || !! material.transmissionMap,
+			uvsVertexOnly: ! ( !! material.map || !! material.bumpMap || !! material.normalMap || !! material.specularMap || !! material.alphaMap || !! material.emissiveMap || !! material.roughnessMap || !! material.metalnessMap || !! material.clearcoatNormalMap || !! material.transmissionMap ) && !! material.displacementMap,
 
 			fog: !! fog,
 			useFog: material.fog,