diff --git a/package.json b/package.json index 9ef5fc61c06f55..dc55038b277894 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@oppentech/three", - "version": "0.115.5", + "version": "0.115.6", "description": "JavaScript 3D library", "main": "build/three.js", "module": "build/three.module.js", diff --git a/src/materials/MeshPhysicalMaterial.js b/src/materials/MeshPhysicalMaterial.js index bb787ac0042420..e5c452ac155c2f 100644 --- a/src/materials/MeshPhysicalMaterial.js +++ b/src/materials/MeshPhysicalMaterial.js @@ -46,6 +46,7 @@ function MeshPhysicalMaterial( parameters ) { this.sheen = null; // null will disable sheen bsdf this.transparency = 0.0; + this.refraction = 0.0; this.setValues( parameters ); @@ -72,6 +73,7 @@ MeshPhysicalMaterial.prototype.copy = function ( source ) { this.clearcoatRoughness = source.clearcoatRoughness; this.clearcoatRoughnessMap = source.clearcoatRoughnessMap; this.clearcoatNormalMap = source.clearcoatNormalMap; + this.refraction = source.refraction; this.clearcoatNormalScale.copy( source.clearcoatNormalScale ); this.reflectivity = source.reflectivity; diff --git a/src/renderers/WebGLRenderer.js b/src/renderers/WebGLRenderer.js index de6bdc406de299..52030f644fec84 100644 --- a/src/renderers/WebGLRenderer.js +++ b/src/renderers/WebGLRenderer.js @@ -2024,6 +2024,7 @@ function WebGLRenderer( parameters ) { uniforms.reflectivity.value = material.reflectivity; uniforms.refractionRatio.value = material.refractionRatio; + uniforms.refraction.value = material.refraction; uniforms.maxMipLevel.value = properties.get( envMap ).__maxMipLevel || 0; 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 92f58a1bf81a76..832a0b8144563e 100644 --- a/src/renderers/shaders/ShaderChunk/envmap_physical_pars_fragment.glsl.js +++ b/src/renderers/shaders/ShaderChunk/envmap_physical_pars_fragment.glsl.js @@ -1,9 +1,7 @@ export default /* glsl */` #if defined( USE_ENVMAP ) - #ifdef ENVMAP_MODE_REFRACTION - uniform float refractionRatio; - #endif + uniform float refractionRatio; vec3 getLightProbeIndirectIrradiance( /*const in SpecularLightProbe specularLightProbe,*/ const in vec3 geoNormal, const in int maxMIPLevel ) { @@ -56,36 +54,23 @@ export default /* glsl */` } - vec3 getLightProbeIndirectRadiance( /*const in SpecularLightProbe specularLightProbe,*/ const in vec3 viewDir, const in vec3 normal, const in float roughness, const in int maxMIPLevel ) { + vec3 getLightProbeIndirectRadiance( const in vec3 outVec, const in float roughness, const in int maxMIPLevel ) { - #ifdef ENVMAP_MODE_REFLECTION - - vec3 reflectVec = reflect( -viewDir, normal ); - - // 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 - - vec3 reflectVec = refract( -viewDir, normal, refractionRatio ); - - #endif - - reflectVec = inverseTransformDirection( reflectVec, viewMatrix ); + vec3 worldOutVec = inverseTransformDirection( outVec, viewMatrix ); float specularMIPLevel = getSpecularMIPLevel( roughness, maxMIPLevel ); #ifdef ENVMAP_TYPE_CUBE - vec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz ); + vec3 queryWorldOutVec = vec3( flipEnvMap * worldOutVec.x, worldOutVec.yz ); #ifdef TEXTURE_LOD_EXT - vec4 envMapColor = textureCubeLodEXT( envMap, queryReflectVec, specularMIPLevel ); + vec4 envMapColor = textureCubeLodEXT( envMap, queryWorldOutVec, specularMIPLevel ); #else - vec4 envMapColor = textureCube( envMap, queryReflectVec, specularMIPLevel ); + vec4 envMapColor = textureCube( envMap, queryWorldOutVec, specularMIPLevel ); #endif @@ -93,13 +78,13 @@ export default /* glsl */` #elif defined( ENVMAP_TYPE_CUBE_UV ) - vec4 envMapColor = textureCubeUV( envMap, reflectVec, roughness ); + vec4 envMapColor = textureCubeUV( envMap, worldOutVec, roughness ); #elif defined( ENVMAP_TYPE_EQUIREC ) vec2 sampleUV; - sampleUV.y = asin( clamp( reflectVec.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5; - sampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5; + sampleUV.y = asin( clamp( worldOutVec.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5; + sampleUV.x = atan( worldOutVec.z, worldOutVec.x ) * RECIPROCAL_PI2 + 0.5; #ifdef TEXTURE_LOD_EXT @@ -115,15 +100,15 @@ export default /* glsl */` #elif defined( ENVMAP_TYPE_SPHERE ) - vec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0,0.0,1.0 ) ); + vec3 viewOutVec = normalize( ( viewMatrix * vec4( worldOutVec, 0.0 ) ).xyz + vec3( 0.0,0.0,1.0 ) ); #ifdef TEXTURE_LOD_EXT - vec4 envMapColor = texture2DLodEXT( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel ); + vec4 envMapColor = texture2DLodEXT( envMap, viewOutVec.xy * 0.5 + 0.5, specularMIPLevel ); #else - vec4 envMapColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel ); + vec4 envMapColor = texture2D( envMap, viewOutVec.xy * 0.5 + 0.5, specularMIPLevel ); #endif @@ -135,5 +120,31 @@ export default /* glsl */` } + vec3 getLightProbeIndirectRadianceReflection( /*const in SpecularLightProbe specularLightProbe,*/ const in vec3 viewDir, const in vec3 normal, const in float roughness, const in int maxMIPLevel ) { + + vec3 reflectVec = reflect( -viewDir, normal ); + + // 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) ); + + return getLightProbeIndirectRadiance(reflectVec, roughness, maxMIPLevel); + + } + + 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 getLightProbeIndirectRadianceRefraction( /*const in SpecularLightProbe specularLightProbe,*/ const in vec3 viewDir, const in vec3 normal, const in float roughness, const in int maxMIPLevel ) { + + vec3 refractVec = refract2( -viewDir, normal, refractionRatio ); + + return getLightProbeIndirectRadiance(refractVec, roughness, maxMIPLevel); + + } + #endif `; diff --git a/src/renderers/shaders/ShaderChunk/lights_fragment_begin.glsl.js b/src/renderers/shaders/ShaderChunk/lights_fragment_begin.glsl.js index 26c30bf2507807..180a12ac6943c5 100644 --- a/src/renderers/shaders/ShaderChunk/lights_fragment_begin.glsl.js +++ b/src/renderers/shaders/ShaderChunk/lights_fragment_begin.glsl.js @@ -165,6 +165,7 @@ IncidentLight directLight; #if defined( RE_IndirectSpecular ) vec3 radiance = vec3( 0.0 ); + vec3 radianceRefraction = vec3( 0.0 ); vec3 clearcoatRadiance = vec3( 0.0 ); #endif diff --git a/src/renderers/shaders/ShaderChunk/lights_fragment_end.glsl.js b/src/renderers/shaders/ShaderChunk/lights_fragment_end.glsl.js index 4be3940024b973..1a3769c5c2eddc 100644 --- a/src/renderers/shaders/ShaderChunk/lights_fragment_end.glsl.js +++ b/src/renderers/shaders/ShaderChunk/lights_fragment_end.glsl.js @@ -15,5 +15,11 @@ export default /* glsl */` geometry, material, reflectedLight ); +#endif + +#ifdef ENVMAP_MODE_REFLECTION + +reflectedLight.indirectDiffuse = mix(reflectedLight.indirectDiffuse, radianceRefraction * diffuseColor.rgb, refraction); + #endif `; diff --git a/src/renderers/shaders/ShaderChunk/lights_fragment_maps.glsl.js b/src/renderers/shaders/ShaderChunk/lights_fragment_maps.glsl.js index 4c86132d0f2ebe..2bb3511c18e4f2 100644 --- a/src/renderers/shaders/ShaderChunk/lights_fragment_maps.glsl.js +++ b/src/renderers/shaders/ShaderChunk/lights_fragment_maps.glsl.js @@ -26,11 +26,28 @@ export default /* glsl */` #if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular ) - radiance += getLightProbeIndirectRadiance( /*specularLightProbe,*/ geometry.viewDir, splitGeoNormal, material.specularRoughness, maxMipLevel ); + #ifdef ENVMAP_MODE_REFLECTION + + radiance += getLightProbeIndirectRadianceReflection( /*specularLightProbe,*/ geometry.viewDir, splitGeoNormal, material.specularRoughness, maxMipLevel ); + radianceRefraction += getLightProbeIndirectRadianceRefraction( /*specularLightProbe,*/ geometry.viewDir, splitGeoNormal, material.specularRoughness, maxMipLevel ); + + #else + + radiance += getLightProbeIndirectRadianceRefraction( /*specularLightProbe,*/ geometry.viewDir, splitGeoNormal, material.specularRoughness, maxMipLevel ); + + #endif #ifdef CLEARCOAT - clearcoatRadiance += getLightProbeIndirectRadiance( /*specularLightProbe,*/ geometry.viewDir, splitGeoClearcoatNormal, material.clearcoatRoughness, maxMipLevel ); + #ifdef ENVMAP_MODE_REFLECTION + + clearcoatRadiance += getLightProbeIndirectRadianceReflection( /*specularLightProbe,*/ geometry.viewDir, splitGeoClearcoatNormal, material.clearcoatRoughness, maxMipLevel ); + + #else + + clearcoatRadiance += getLightProbeIndirectRadianceRefraction( /*specularLightProbe,*/ geometry.viewDir, splitGeoClearcoatNormal, material.clearcoatRoughness, maxMipLevel ); + + #endif #endif diff --git a/src/renderers/shaders/ShaderLib/meshphysical_frag.glsl.js b/src/renderers/shaders/ShaderLib/meshphysical_frag.glsl.js index 529867b4833beb..bd89c61ee93685 100644 --- a/src/renderers/shaders/ShaderLib/meshphysical_frag.glsl.js +++ b/src/renderers/shaders/ShaderLib/meshphysical_frag.glsl.js @@ -12,6 +12,7 @@ uniform vec3 emissive; uniform float roughness; uniform float metalness; uniform float opacity; +uniform float refraction; #ifdef TRANSPARENCY uniform float transparency; diff --git a/src/renderers/shaders/UniformsLib.js b/src/renderers/shaders/UniformsLib.js index 8b29f2c6cbf76a..c2e8e1fa237c27 100644 --- a/src/renderers/shaders/UniformsLib.js +++ b/src/renderers/shaders/UniformsLib.js @@ -33,6 +33,7 @@ var UniformsLib = { flipEnvMap: { value: - 1 }, reflectivity: { value: 1.0 }, refractionRatio: { value: 0.98 }, + refraction: { value: 0.0 }, maxMipLevel: { value: 0 } },