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 );