From a20c00cd492b0119c0c4c4d8e8d17ca0cb458721 Mon Sep 17 00:00:00 2001 From: "Ben Houston (Clara.io)" Date: Thu, 2 Jun 2016 00:02:13 -0400 Subject: [PATCH] ClearCoat for MeshPhysicalMaterial (#9038) * clear coat implementation. * add physical variations to examples. * add example file for physical materials * adjust clearcoat range to 0-1 as original. * switch example color to gray from yellow. --- examples/files.js | 1 + .../webgl_materials_variations_physical.html | 243 ++++++++++++++++++ src/materials/MeshPhysicalMaterial.js | 6 + src/renderers/WebGLRenderer.js | 3 + .../ShaderChunk/lights_physical_fragment.glsl | 6 +- .../lights_physical_pars_fragment.glsl | 22 +- .../shaders/ShaderChunk/lights_template.glsl | 8 +- src/renderers/shaders/ShaderLib.js | 5 +- .../shaders/ShaderLib/meshphysical_frag.glsl | 5 + 9 files changed, 291 insertions(+), 8 deletions(-) create mode 100644 examples/webgl_materials_variations_physical.html diff --git a/examples/files.js b/examples/files.js index 5fc48a7b9a..3736decc85 100644 --- a/examples/files.js +++ b/examples/files.js @@ -151,6 +151,7 @@ var files = { "webgl_materials_variations_lambert", "webgl_materials_variations_phong", "webgl_materials_variations_standard", + "webgl_materials_variations_physical", "webgl_materials_video", "webgl_materials_wireframe", "webgl_mirror", diff --git a/examples/webgl_materials_variations_physical.html b/examples/webgl_materials_variations_physical.html new file mode 100644 index 0000000000..2a42000906 --- /dev/null +++ b/examples/webgl_materials_variations_physical.html @@ -0,0 +1,243 @@ + + + + three.js webgl - materials + + + + + + +
+
three.js - Physical Material Variations by Ben Houston.
+ + + + + + + + + + + diff --git a/src/materials/MeshPhysicalMaterial.js b/src/materials/MeshPhysicalMaterial.js index 581737c51f..021b0bd8d8 100644 --- a/src/materials/MeshPhysicalMaterial.js +++ b/src/materials/MeshPhysicalMaterial.js @@ -16,6 +16,9 @@ THREE.MeshPhysicalMaterial = function ( parameters ) { this.reflectivity = 0.5; // maps to F0 = 0.04 + this.clearCoat = 0.0; + this.clearCoatRoughness = 0.0; + this.setValues( parameters ); }; @@ -31,6 +34,9 @@ THREE.MeshPhysicalMaterial.prototype.copy = function ( source ) { this.reflectivity = source.reflectivity; + this.clearCoat = source.clearCoat; + this.clearCoatRoughness = source.clearCoatRoughness; + return this; }; diff --git a/src/renderers/WebGLRenderer.js b/src/renderers/WebGLRenderer.js index c03a04ecca..6d0261f001 100644 --- a/src/renderers/WebGLRenderer.js +++ b/src/renderers/WebGLRenderer.js @@ -2152,6 +2152,9 @@ THREE.WebGLRenderer = function ( parameters ) { function refreshUniformsPhysical ( uniforms, material ) { + uniforms.clearCoat.value = material.clearCoat; + uniforms.clearCoatRoughness.value = material.clearCoatRoughness; + refreshUniformsStandard( uniforms, material ); } diff --git a/src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl b/src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl index d3d372a776..c72658008d 100644 --- a/src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl +++ b/src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl @@ -2,7 +2,9 @@ PhysicalMaterial material; material.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor ); material.specularRoughness = clamp( roughnessFactor, 0.04, 1.0 ); #ifdef STANDARD - material.specularColor = mix( vec3( 0.04 ), diffuseColor.rgb, metalnessFactor ); + material.specularColor = mix( vec3( DEFAULT_SPECULAR_COEFFICIENT ), diffuseColor.rgb, metalnessFactor ); #else - material.specularColor = mix( vec3( 0.16 * pow2( reflectivity ) ), diffuseColor.rgb, metalnessFactor ); + material.specularColor = mix( vec3( MAXIMUM_SPECULAR_COEFFICIENT * pow2( reflectivity ) ), diffuseColor.rgb, metalnessFactor ); + material.clearCoat = saturate( clearCoat ); // Burley clearcoat model + material.clearCoatRoughness = clamp( clearCoatRoughness, 0.04, 1.0 ); #endif diff --git a/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl b/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl index 3be46e7642..8044e1f40b 100644 --- a/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl +++ b/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl @@ -5,11 +5,15 @@ struct PhysicalMaterial { vec3 specularColor; #ifndef STANDARD - // future + float clearCoat; + float clearCoatRoughness; #endif }; +#define MAXIMUM_SPECULAR_COEFFICIENT 0.16 +#define DEFAULT_SPECULAR_COEFFICIENT 0.04 + void RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) { float dotNL = saturate( dot( geometry.normal, directLight.direction ) ); @@ -22,9 +26,14 @@ void RE_Direct_Physical( const in IncidentLight directLight, const in GeometricC #endif + reflectedLight.directSpecular += irradiance * BRDF_Specular_GGX( directLight, geometry, material.specularColor, material.specularRoughness ); reflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor ); - reflectedLight.directSpecular += irradiance * BRDF_Specular_GGX( directLight, geometry, material.specularColor, material.specularRoughness ); + #ifndef STANDARD + + reflectedLight.directSpecular += irradiance * material.clearCoat * BRDF_Specular_GGX( directLight, geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness ); + + #endif } @@ -34,10 +43,16 @@ void RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricCo } -void RE_IndirectSpecular_Physical( const in vec3 radiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) { +void RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 clearCoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) { reflectedLight.indirectSpecular += radiance * BRDF_Specular_GGX_Environment( geometry, material.specularColor, material.specularRoughness ); + #ifndef STANDARD + + reflectedLight.indirectSpecular += clearCoatRadiance * material.clearCoat * BRDF_Specular_GGX_Environment( geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness ); + + #endif + } #define RE_Direct RE_Direct_Physical @@ -45,6 +60,7 @@ void RE_IndirectSpecular_Physical( const in vec3 radiance, const in GeometricCon #define RE_IndirectSpecular RE_IndirectSpecular_Physical #define Material_BlinnShininessExponent( material ) GGXRoughnessToBlinnExponent( material.specularRoughness ) +#define Material_ClearCoat_BlinnShininessExponent( material ) GGXRoughnessToBlinnExponent( material.clearCoatRoughness ) // ref: http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr_v2.pdf float computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) { diff --git a/src/renderers/shaders/ShaderChunk/lights_template.glsl b/src/renderers/shaders/ShaderChunk/lights_template.glsl index 80f81526cb..0b8576da97 100644 --- a/src/renderers/shaders/ShaderChunk/lights_template.glsl +++ b/src/renderers/shaders/ShaderChunk/lights_template.glsl @@ -125,6 +125,12 @@ IncidentLight directLight; // TODO, replace 8 with the real maxMIPLevel vec3 radiance = getLightProbeIndirectRadiance( /*specularLightProbe,*/ geometry, Material_BlinnShininessExponent( material ), 8 ); - RE_IndirectSpecular( radiance, geometry, material, reflectedLight ); + #ifndef STANDARD + vec3 clearCoatRadiance = getLightProbeIndirectRadiance( /*specularLightProbe,*/ geometry, Material_ClearCoat_BlinnShininessExponent( material ), 8 ); + #else + vec3 clearCoatRadiance = vec3( 0.0 ); + #endif + + RE_IndirectSpecular( radiance, clearCoatRadiance, geometry, material, reflectedLight ); #endif diff --git a/src/renderers/shaders/ShaderLib.js b/src/renderers/shaders/ShaderLib.js index 1c586fa487..8ec1abc8fa 100644 --- a/src/renderers/shaders/ShaderLib.js +++ b/src/renderers/shaders/ShaderLib.js @@ -93,7 +93,7 @@ THREE.ShaderLib = { "emissive" : { value: new THREE.Color( 0x000000 ) }, "roughness": { value: 0.5 }, "metalness": { value: 0 }, - "envMapIntensity" : { value: 1 } // temporary + "envMapIntensity" : { value: 1 }, // temporary } ] ), @@ -218,7 +218,8 @@ THREE.ShaderLib[ 'physical' ] = { THREE.ShaderLib[ 'standard' ].uniforms, { - // future + "clearCoat": { value: 0 }, + "clearCoatRoughness": { value: 0 } } ] ), diff --git a/src/renderers/shaders/ShaderLib/meshphysical_frag.glsl b/src/renderers/shaders/ShaderLib/meshphysical_frag.glsl index fbe8500379..fc8e140d6b 100644 --- a/src/renderers/shaders/ShaderLib/meshphysical_frag.glsl +++ b/src/renderers/shaders/ShaderLib/meshphysical_frag.glsl @@ -6,6 +6,11 @@ uniform float roughness; uniform float metalness; uniform float opacity; +#ifndef STANDARD + uniform float clearCoat; + uniform float clearCoatRoughness; +#endif + uniform float envMapIntensity; // temporary varying vec3 vViewPosition; -- GitLab