Browse Source

Improve MeshPhysicalMaterial transmission support Part2 (#21975)

* Improve MeshPhysicalMaterial transmission

* Update screenshots

* WebGLRenderer: Use HalfFloatType for transmissionRenderTarget

* Update screenshots
Takahiro 4 years ago
parent
commit
6d6a324278

BIN
examples/screenshots/webgl_loader_gltf_transmission.jpg


BIN
examples/screenshots/webgl_materials_physical_transmission.jpg


+ 8 - 0
src/renderers/WebGLRenderer.js

@@ -1274,6 +1274,7 @@ function WebGLRenderer( parameters = {} ) {
 
 			_transmissionRenderTarget = new renderTargetType( 1024, 1024, {
 				generateMipmaps: true,
+				type: utils.convert( HalfFloatType ) !== null ? HalfFloatType : UnsignedByteType,
 				minFilter: LinearMipmapLinearFilter,
 				magFilter: NearestFilter,
 				wrapS: ClampToEdgeWrapping,
@@ -1286,8 +1287,15 @@ function WebGLRenderer( parameters = {} ) {
 		_this.setRenderTarget( _transmissionRenderTarget );
 		_this.clear();
 
+		// Turn off the features which can affect the frag color for opaque objects pass.
+		// Otherwise they are applied twice in opaque objects pass and transmission objects pass.
+		const currentToneMapping = _this.toneMapping;
+		_this.toneMapping = NoToneMapping;
+
 		renderObjects( opaqueObjects, scene, camera );
 
+		_this.toneMapping = currentToneMapping;
+
 		textures.updateMultisampleRenderTarget( _transmissionRenderTarget );
 		textures.updateRenderTargetMipmap( _transmissionRenderTarget );
 

+ 2 - 2
src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl.js

@@ -11,11 +11,11 @@ material.specularRoughness = min( material.specularRoughness, 1.0 );
 
 #ifdef REFLECTIVITY
 
-	material.specularColor = mix( vec3( MAXIMUM_SPECULAR_COEFFICIENT * pow2( reflectivity ) ), rawDiffuseColor, metalnessFactor );
+	material.specularColor = mix( vec3( MAXIMUM_SPECULAR_COEFFICIENT * pow2( reflectivity ) ), diffuseColor.rgb, metalnessFactor );
 
 #else
 
-	material.specularColor = mix( vec3( DEFAULT_SPECULAR_COEFFICIENT ), rawDiffuseColor, metalnessFactor );
+	material.specularColor = mix( vec3( DEFAULT_SPECULAR_COEFFICIENT ), diffuseColor.rgb, metalnessFactor );
 
 #endif
 

+ 8 - 11
src/renderers/shaders/ShaderChunk/transmission_fragment.glsl.js

@@ -1,9 +1,12 @@
 export default /* glsl */`
 #ifdef USE_TRANSMISSION
 
+	float transmissionFactor = transmission;
+	float thicknessFactor = thickness;
+
 	#ifdef USE_TRANSMISSIONMAP
 
-		totalTransmission *= texture2D( transmissionMap, vUv ).r;
+		transmissionFactor *= texture2D( transmissionMap, vUv ).r;
 
 	#endif
 
@@ -15,19 +18,13 @@ export default /* glsl */`
 
 	vec3 pos = vWorldPosition.xyz / vWorldPosition.w;
 	vec3 v = normalize( cameraPosition - pos );
-	vec3 viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );
 	float ior = ( 1.0 + 0.4 * reflectivity ) / ( 1.0 - 0.4 * reflectivity );
 
-	// From https://google.github.io/filament/Filament.html#materialsystem/parameterization/remapping
-	vec3 f0 = vec3( pow( ior - 1.0, 2.0 ) / pow( ior + 1.0, 2.0 ) );
-	vec3 f90 = vec3( 1.0 );
-
-	vec3 f_transmission = totalTransmission * getIBLVolumeRefraction(
-		normal, v, viewDir, roughnessFactor, diffuseColor.rgb, f0, f90,
+	vec3 transmission = transmissionFactor * getIBLVolumeRefraction(
+		normal, v, roughnessFactor, material.diffuseColor, totalSpecular,
 		pos, modelMatrix, viewMatrix, projectionMatrix, ior, thicknessFactor,
-		attenuationColor, attenuationDistance);
-
-	diffuseColor.rgb = mix( diffuseColor.rgb, f_transmission, totalTransmission );
+		attenuationColor, attenuationDistance );
 
+	totalDiffuse = mix( totalDiffuse, transmission, transmissionFactor );
 #endif
 `;

+ 3 - 6
src/renderers/shaders/ShaderChunk/transmission_pars_fragment.glsl.js

@@ -61,8 +61,9 @@ export default /* glsl */`
 		}
 	}
 
-	vec3 getIBLVolumeRefraction(vec3 n, vec3 v, vec3 viewDir, float perceptualRoughness, vec3 baseColor, vec3 f0, vec3 f90,
-		vec3 position, mat4 modelMatrix, mat4 viewMatrix, mat4 projMatrix, float ior, float thickness, vec3 attenuationColor, float attenuationDistance) {
+	vec3 getIBLVolumeRefraction(vec3 n, vec3 v, float perceptualRoughness, vec3 baseColor, vec3 specularColor,
+		vec3 position, mat4 modelMatrix, mat4 viewMatrix, mat4 projMatrix, float ior, float thickness,
+		vec3 attenuationColor, float attenuationDistance) {
 		vec3 transmissionRay = getVolumeTransmissionRay(n, v, thickness, ior, modelMatrix);
 		vec3 refractedRayExit = position + transmissionRay;
 
@@ -77,10 +78,6 @@ export default /* glsl */`
 
 		vec3 attenuatedColor = applyVolumeAttenuation(transmittedLight, length(transmissionRay), attenuationColor, attenuationDistance);
 
-		float NdotV = saturate(dot(n, viewDir));
-		vec2 brdf = integrateSpecularBRDF(NdotV, perceptualRoughness);
-		vec3 specularColor = f0 * brdf.x + f90 * brdf.y;
-
 		return (1.0 - specularColor) * attenuatedColor * baseColor;
 	}
 #endif

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

@@ -83,11 +83,6 @@ void main() {
 	ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );
 	vec3 totalEmissiveRadiance = emissive;
 
-	#ifdef USE_TRANSMISSION
-		float totalTransmission = transmission;
-		float thicknessFactor = thickness;
-	#endif
-
 	#include <logdepthbuf_fragment>
 	#include <map_fragment>
 	#include <color_fragment>
@@ -101,10 +96,6 @@ void main() {
 	#include <clearcoat_normal_fragment_maps>
 	#include <emissivemap_fragment>
 
-	vec3 rawDiffuseColor = diffuseColor.rgb;
-
-	#include <transmission_fragment>
-
 	// accumulation
 	#include <lights_physical_fragment>
 	#include <lights_fragment_begin>
@@ -114,7 +105,12 @@ void main() {
 	// modulation
 	#include <aomap_fragment>
 
-	vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;
+	vec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse;
+	vec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular;
+
+	#include <transmission_fragment>
+
+	vec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance;
 
 	gl_FragColor = vec4( outgoingLight, diffuseColor.a );