diff --git a/docs/api/en/materials/MeshPhysicalMaterial.html b/docs/api/en/materials/MeshPhysicalMaterial.html
index 2dfe825208ca6a..11c370c6f0c810 100644
--- a/docs/api/en/materials/MeshPhysicalMaterial.html
+++ b/docs/api/en/materials/MeshPhysicalMaterial.html
@@ -29,6 +29,9 @@
[name]
Advanced reflectivity: More flexible reflectivity for non-metallic materials.
+
+ Refraction: Mixed indirect reflections and refractions.
+
@@ -61,7 +64,8 @@
Examples
[example:webgl_materials_variations_physical materials / variations / physical]
[example:webgl_materials_physical_clearcoat materials / physical / clearcoat]
[example:webgl_materials_physical_reflectivity materials / physical / reflectivity]
- [example:webgl_materials_physical_transmission materials / physical / transmission]
+ [example:webgl_materials_physical_transmission materials / physical / transmission]
+ [example:webgl_materials_physical_refraction materials / physical / refraction]
Constructor
@@ -132,6 +136,12 @@ [property:Float reflectivity]
This models the reflectivity of non-metallic materials. It has no effect when [page:MeshStandardMaterial.metalness metalness] is *1.0*
+ [property:Float refraction]
+
+ The portion of light that's refracted instead of diffusely reflected, from *0.0* to *1.0*. Default is *0.0*,
+ which means the diffuse component is fully preserved.
+
+
[property:Float sheen]
The intensity of the sheen layer, from *0.0* to *1.0*. Default is *0.0*.
diff --git a/docs/api/zh/materials/MeshPhysicalMaterial.html b/docs/api/zh/materials/MeshPhysicalMaterial.html
index 8c08cd04d8b7f2..48b6283c55143f 100644
--- a/docs/api/zh/materials/MeshPhysicalMaterial.html
+++ b/docs/api/zh/materials/MeshPhysicalMaterial.html
@@ -29,6 +29,9 @@
物理网格材质([name])
Advanced reflectivity: More flexible reflectivity for non-metallic materials.
+
+ Refraction: Mixed indirect reflections and refractions.
+
@@ -62,7 +65,8 @@
例子
[example:webgl_materials_variations_physical materials / variations / physical]
[example:webgl_materials_physical_clearcoat materials / physical / clearcoat]
[example:webgl_materials_physical_reflectivity materials / physical / reflectivity]
- [example:webgl_materials_physical_transmission materials / physical / transmission]
+ [example:webgl_materials_physical_transmission materials / physical / transmission]
+ [example:webgl_materials_physical_refraction materials / physical / refraction]
构造函数(Constructor)
@@ -129,6 +133,11 @@ [property:Float reflectivity]
这模拟了非金属材质的反射率。当[page:MeshStandardMaterial]为*1.0*时,此属性无效。
+ [property:Float refraction]
+
+ 控制材质中漫反射部分有多少被折射取代,范围为*0.0*到*1.0*。默认值为*0.0*,即保留全部漫反射部分。
+
+
[property:Float sheen]
The intensity of the sheen layer, from *0.0* to *1.0*. Default is *0.0*.
diff --git a/src/materials/MeshPhysicalMaterial.js b/src/materials/MeshPhysicalMaterial.js
index 2eef9bd7f12859..4072c4622cefba 100644
--- a/src/materials/MeshPhysicalMaterial.js
+++ b/src/materials/MeshPhysicalMaterial.js
@@ -33,6 +33,8 @@ import * as MathUtils from '../math/MathUtils.js';
* specularIntensityMap: new THREE.Texture( ),
* specularColor: ,
* specularColorMap: new THREE.Texture( )
+ *
+ * refraction: ,
* }
*/
@@ -92,6 +94,7 @@ class MeshPhysicalMaterial extends MeshStandardMaterial {
this._sheen = 0.0;
this._clearcoat = 0;
this._transmission = 0;
+ this._refraction = 0.0;
this.setValues( parameters );
@@ -151,6 +154,24 @@ class MeshPhysicalMaterial extends MeshStandardMaterial {
}
+ get refraction() {
+
+ return this._refraction;
+
+ }
+
+ set refraction( value ) {
+
+ if ( this._refraction > 0 !== value > 0 ) {
+
+ this.version ++;
+
+ }
+
+ this._refraction = value;
+
+ }
+
copy( source ) {
super.copy( source );
@@ -185,6 +206,8 @@ class MeshPhysicalMaterial extends MeshStandardMaterial {
this.attenuationDistance = source.attenuationDistance;
this.attenuationColor.copy( source.attenuationColor );
+ this.refraction = source.refraction;
+
this.specularIntensity = source.specularIntensity;
this.specularIntensityMap = source.specularIntensityMap;
this.specularColor.copy( source.specularColor );
diff --git a/src/renderers/shaders/ShaderChunk/envmap_physical_pars_fragment.glsl.js b/src/renderers/shaders/ShaderChunk/envmap_physical_pars_fragment.glsl.js
index 57e6eff13a55a5..53527f95575b99 100644
--- a/src/renderers/shaders/ShaderChunk/envmap_physical_pars_fragment.glsl.js
+++ b/src/renderers/shaders/ShaderChunk/envmap_physical_pars_fragment.glsl.js
@@ -1,11 +1,7 @@
export default /* glsl */`
#if defined( USE_ENVMAP )
- #ifdef ENVMAP_MODE_REFRACTION
-
- uniform float refractionRatio;
-
- #endif
+ uniform float refractionRatio;
vec3 getIBLIrradiance( const in vec3 normal ) {
@@ -25,36 +21,47 @@ export default /* glsl */`
}
- vec3 getIBLRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness ) {
+ vec3 getIBLRadiance( const in vec3 outVec, const in float roughness ) {
#if defined( ENVMAP_TYPE_CUBE_UV )
- vec3 reflectVec;
+ vec3 worldOutVec = inverseTransformDirection( outVec, viewMatrix );
- #ifdef ENVMAP_MODE_REFLECTION
+ vec4 envMapColor = textureCubeUV( envMap, worldOutVec, roughness );
- reflectVec = reflect( - viewDir, normal );
+ return envMapColor.rgb * envMapIntensity;
- // Mixing the reflection with the normal is more accurate and keeps rough objects from gathering light from behind their tangent plane.
- reflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );
+ #else
- #else
+ return vec3( 0.0 );
- reflectVec = refract( - viewDir, normal, refractionRatio );
+ #endif
- #endif
+ }
- reflectVec = inverseTransformDirection( reflectVec, viewMatrix );
+ vec3 getIBLRadianceReflection( const in vec3 viewDir, const in vec3 normal, const in float roughness ) {
- vec4 envMapColor = textureCubeUV( envMap, reflectVec, roughness );
+ vec3 reflectVec = reflect( -viewDir, normal );
- return envMapColor.rgb * envMapIntensity;
+ // Mixing the reflection with the normal is more accurate and keeps rough objects from gathering light from behind their tangent plane.
+ reflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );
- #else
+ return getIBLRadiance(reflectVec, roughness);
- return vec3( 0.0 );
+ }
- #endif
+ vec3 refract2(vec3 viewVec, vec3 Normal, float ior) {
+ float vn = dot(viewVec, Normal);
+ float k = 1.0 - ior * ior * (1.0 - vn * vn);
+ vec3 refrVec = ior * viewVec - (ior * vn + sqrt(k)) * Normal;
+ return refrVec;
+ }
+
+ vec3 getIBLRadianceRefraction( const in vec3 viewDir, const in vec3 normal, const in float roughness ) {
+
+ vec3 refractVec = refract2( -viewDir, normal, refractionRatio );
+
+ return getIBLRadiance(refractVec, roughness);
}
diff --git a/src/renderers/shaders/ShaderChunk/lights_fragment_begin.glsl.js b/src/renderers/shaders/ShaderChunk/lights_fragment_begin.glsl.js
index 73f521f62fad37..f38fa5516a51b1 100644
--- a/src/renderers/shaders/ShaderChunk/lights_fragment_begin.glsl.js
+++ b/src/renderers/shaders/ShaderChunk/lights_fragment_begin.glsl.js
@@ -173,7 +173,14 @@ IncidentLight directLight;
#if defined( RE_IndirectSpecular )
vec3 radiance = vec3( 0.0 );
+
vec3 clearcoatRadiance = vec3( 0.0 );
+ #ifdef USE_REFRACTION
+
+ vec3 radianceRefraction = vec3( 0.0 );
+
+ #endif
+
#endif
`;
diff --git a/src/renderers/shaders/ShaderChunk/lights_fragment_end.glsl.js b/src/renderers/shaders/ShaderChunk/lights_fragment_end.glsl.js
index 673a3484530e39..7bd0ed95929104 100644
--- a/src/renderers/shaders/ShaderChunk/lights_fragment_end.glsl.js
+++ b/src/renderers/shaders/ShaderChunk/lights_fragment_end.glsl.js
@@ -9,6 +9,9 @@ export default /* glsl */`
RE_IndirectSpecular(
radiance,
+#ifdef USE_REFRACTION
+ radianceRefraction,
+#endif
iblIrradiance,
clearcoatRadiance,
splitGeoNormal,
diff --git a/src/renderers/shaders/ShaderChunk/lights_fragment_maps.glsl.js b/src/renderers/shaders/ShaderChunk/lights_fragment_maps.glsl.js
index ac62088f0b55b0..7305aedccfeb40 100644
--- a/src/renderers/shaders/ShaderChunk/lights_fragment_maps.glsl.js
+++ b/src/renderers/shaders/ShaderChunk/lights_fragment_maps.glsl.js
@@ -26,11 +26,33 @@ export default /* glsl */`
#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )
- radiance += getIBLRadiance( geometry.viewDir, splitGeoNormal, material.roughness );
+ #ifdef ENVMAP_MODE_REFLECTION
+
+ radiance += getIBLRadianceReflection( geometry.viewDir, splitGeoNormal, material.roughness );
+
+ #ifdef USE_REFRACTION
+
+ radianceRefraction += getIBLRadianceRefraction( geometry.viewDir, splitGeoNormal, material.roughness );
+
+ #endif
+
+ #else
+
+ radiance += getIBLRadianceRefraction( geometry.viewDir, splitGeoNormal, material.roughness );
+
+ #endif
#ifdef USE_CLEARCOAT
- clearcoatRadiance += getIBLRadiance( geometry.viewDir, splitGeoClearcoatNormal, material.clearcoatRoughness );
+ #ifdef ENVMAP_MODE_REFLECTION
+
+ clearcoatRadiance += getIBLRadianceReflection( geometry.viewDir, splitGeoClearcoatNormal, material.clearcoatRoughness );
+
+ #else
+
+ clearcoatRadiance += getIBLRadianceRefraction( geometry.viewDir, splitGeoClearcoatNormal, material.clearcoatRoughness );
+
+ #endif
#endif
diff --git a/src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl.js b/src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl.js
index 4a0a6f7d7d1316..1b3dfe57103d73 100644
--- a/src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl.js
+++ b/src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl.js
@@ -91,5 +91,11 @@ material.roughness = min( material.roughness, 1.0 );
#endif
+#endif
+
+#ifdef USE_REFRACTION
+
+ material.refraction = refraction;
+
#endif
`;
diff --git a/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js b/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js
index 4862928a6aea93..df4de52f2bf1d6 100644
--- a/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js
+++ b/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js
@@ -18,6 +18,10 @@ struct PhysicalMaterial {
float sheenRoughness;
#endif
+ #ifdef USE_REFRACTION
+ float refraction;
+ #endif
+
};
// temporary
@@ -179,6 +183,9 @@ void RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricCo
void RE_IndirectSpecular_Physical(
const in vec3 radiance,
+#ifdef USE_REFRACTION
+ const in vec3 radianceRefraction,
+#endif
const in vec3 irradiance,
const in vec3 clearcoatRadiance,
const in vec3 normal,
@@ -215,7 +222,15 @@ void RE_IndirectSpecular_Physical(
reflectedLight.indirectSpecular += radiance * singleScattering;
reflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;
- reflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;
+ vec3 indirectDiffuse = diffuse * cosineWeightedIrradiance;
+
+ #ifdef USE_REFRACTION
+
+ indirectDiffuse = mix(indirectDiffuse, radianceRefraction * material.diffuseColor, material.refraction);
+
+ #endif
+
+ reflectedLight.indirectDiffuse += indirectDiffuse;
}
diff --git a/src/renderers/shaders/ShaderLib.js b/src/renderers/shaders/ShaderLib.js
index 59df621f21ed71..38111f3793e217 100644
--- a/src/renderers/shaders/ShaderLib.js
+++ b/src/renderers/shaders/ShaderLib.js
@@ -309,6 +309,7 @@ ShaderLib.physical = {
thicknessMap: { value: null },
attenuationDistance: { value: 0 },
attenuationColor: { value: new Color( 0x000000 ) },
+ refraction: { value: 0 },
specularIntensity: { value: 0 },
specularIntensityMap: { value: null },
specularColor: { value: new Color( 1, 1, 1 ) },
diff --git a/src/renderers/shaders/ShaderLib/meshphysical.glsl.js b/src/renderers/shaders/ShaderLib/meshphysical.glsl.js
index b73648fbd783e9..555beb8eda6034 100644
--- a/src/renderers/shaders/ShaderLib/meshphysical.glsl.js
+++ b/src/renderers/shaders/ShaderLib/meshphysical.glsl.js
@@ -106,6 +106,10 @@ uniform float opacity;
#endif
#endif
+#ifdef USE_REFRACTION
+ uniform float refraction;
+#endif
+
varying vec3 vViewPosition;
#include
diff --git a/src/renderers/webgl/WebGLMaterials.js b/src/renderers/webgl/WebGLMaterials.js
index 845eccbb043ee5..b0619b806871e2 100644
--- a/src/renderers/webgl/WebGLMaterials.js
+++ b/src/renderers/webgl/WebGLMaterials.js
@@ -676,6 +676,12 @@ function WebGLMaterials( properties ) {
}
+ if ( material.refraction > 0 ) {
+
+ uniforms.refraction.value = material.refraction;
+
+ }
+
uniforms.specularIntensity.value = material.specularIntensity;
uniforms.specularColor.value.copy( material.specularColor );
diff --git a/src/renderers/webgl/WebGLProgram.js b/src/renderers/webgl/WebGLProgram.js
index 4a9b88257e9fdb..bca52b1f7b9ed5 100644
--- a/src/renderers/webgl/WebGLProgram.js
+++ b/src/renderers/webgl/WebGLProgram.js
@@ -627,6 +627,8 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) {
parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '',
parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '',
+ parameters.refraction ? '#define USE_REFRACTION' : '',
+
parameters.vertexTangents ? '#define USE_TANGENT' : '',
parameters.vertexColors || parameters.instancingColor ? '#define USE_COLOR' : '',
parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '',
diff --git a/src/renderers/webgl/WebGLPrograms.js b/src/renderers/webgl/WebGLPrograms.js
index 18ecb583dca914..7cc7af8f829428 100644
--- a/src/renderers/webgl/WebGLPrograms.js
+++ b/src/renderers/webgl/WebGLPrograms.js
@@ -224,6 +224,8 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities
transmissionMap: !! material.transmissionMap,
thicknessMap: !! material.thicknessMap,
+ refraction: material.refraction > 0,
+
combine: material.combine,
vertexTangents: ( !! material.normalMap && !! object.geometry && !! object.geometry.attributes.tangent ),
@@ -489,6 +491,8 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities
_programLayers.enable( 21 );
if ( parameters.lowerNormalMap )
_programLayers.enable( 22 );
+ if ( parameters.refraction )
+ _programLayers.enable( 23 );
array.push( _programLayers.mask );