From b8f6aec772d78e82246858c2c61fbc7d17b3c796 Mon Sep 17 00:00:00 2001 From: "shensi.zxd" Date: Tue, 1 Mar 2022 17:28:46 +0800 Subject: [PATCH 01/15] feat: support clearcoat --- packages/controls/src/OrbitControl.ts | 2 +- packages/core/src/material/PBRMaterial.ts | 94 ++++++++++++++++++- packages/core/src/shaderlib/common.glsl | 4 + packages/core/src/shaderlib/normal_get.glsl | 48 ++++++++++ packages/core/src/shaderlib/pbr/brdf.glsl | 14 ++- .../pbr/direct_irradiance_frag_define.glsl | 15 ++- .../src/shaderlib/pbr/ibl_frag_define.glsl | 4 +- packages/core/src/shaderlib/pbr/pbr_frag.glsl | 30 +++++- .../src/shaderlib/pbr/pbr_frag_define.glsl | 29 ++++++ .../core/src/shaderlib/pbr/pbr_helper.glsl | 27 ++++-- .../extensions/KHR_materials_clearcoat.ts | 36 +++++++ .../loader/src/gltf/parser/MaterialParser.ts | 6 +- 12 files changed, 281 insertions(+), 28 deletions(-) diff --git a/packages/controls/src/OrbitControl.ts b/packages/controls/src/OrbitControl.ts index e68e0fe2aa..b3ede278c4 100644 --- a/packages/controls/src/OrbitControl.ts +++ b/packages/controls/src/OrbitControl.ts @@ -400,7 +400,7 @@ export class OrbitControl extends Script { */ pan(deltaX: number, deltaY: number) { // perspective only - const position: Vector3 = this.camera.position; + const position: Vector3 = this.camera.transform.position; position.cloneTo(this._vPan); this._vPan.subtract(this.target); let targetDistance = this._vPan.length(); diff --git a/packages/core/src/material/PBRMaterial.ts b/packages/core/src/material/PBRMaterial.ts index 3074529797..a35652dc2b 100644 --- a/packages/core/src/material/PBRMaterial.ts +++ b/packages/core/src/material/PBRMaterial.ts @@ -10,9 +10,14 @@ export class PBRMaterial extends PBRBaseMaterial { private static _metallicProp = Shader.getPropertyByName("u_metal"); private static _roughnessProp = Shader.getPropertyByName("u_roughness"); private static _metallicRoughnessTextureProp = Shader.getPropertyByName("u_metallicRoughnessSampler"); + private static _clearcoatProp = Shader.getPropertyByName("u_clearcoat"); + private static _clearcoatTextureProp = Shader.getPropertyByName("u_clearcoatTexture"); + private static _clearcoatRoughnessProp = Shader.getPropertyByName("u_clearcoatRoughness"); + private static _clearcoatRoughnessTextureProp = Shader.getPropertyByName("u_clearcoatRoughnessTexture"); + private static _clearcoatNormalTextureProp = Shader.getPropertyByName("u_clearcoatNormalTexture"); /** - * Metallic. + * Metallic, default 1. */ get metallic(): number { return this.shaderData.getFloat(PBRMaterial._metallicProp); @@ -23,7 +28,7 @@ export class PBRMaterial extends PBRBaseMaterial { } /** - * Roughness. + * Roughness, default 1. */ get roughness(): number { return this.shaderData.getFloat(PBRMaterial._roughnessProp); @@ -50,14 +55,95 @@ export class PBRMaterial extends PBRBaseMaterial { } } + /** + * The clearcoat layer intensity, default 0. + */ + get clearcoat(): number { + return this.shaderData.getFloat(PBRMaterial._clearcoatProp); + } + + set clearcoat(value: number) { + this.shaderData.setFloat(PBRMaterial._clearcoatProp, value); + + if (value === 0) { + this.shaderData.disableMacro("CLEARCOAT"); + } else { + this.shaderData.enableMacro("CLEARCOAT"); + } + } + + /** + * The clearcoat layer intensity texture. + */ + get clearcoatTexture(): Texture2D { + return this.shaderData.getTexture(PBRMaterial._clearcoatTextureProp); + } + + set clearcoatTexture(value: Texture2D) { + this.shaderData.setTexture(PBRMaterial._clearcoatTextureProp, value); + + if (value) { + this.shaderData.enableMacro("HAS_CLEARCOATTEXTURE"); + } else { + this.shaderData.disableMacro("HAS_CLEARCOATTEXTURE"); + } + } + + /** + * The clearcoat layer roughness, default 0. + */ + get clearcoatRoughness(): number { + return this.shaderData.getFloat(PBRMaterial._clearcoatRoughnessProp); + } + + set clearcoatRoughness(value: number) { + this.shaderData.setFloat(PBRMaterial._clearcoatRoughnessProp, value); + } + + /** + * The clearcoat layer roughness texture. + */ + get clearcoatRoughnessTexture(): Texture2D { + return this.shaderData.getTexture(PBRMaterial._clearcoatRoughnessTextureProp); + } + + set clearcoatRoughnessTexture(value: Texture2D) { + this.shaderData.setTexture(PBRMaterial._clearcoatRoughnessTextureProp, value); + + if (value) { + this.shaderData.enableMacro("HAS_CLEARCOATROUGHNESSTEXTURE"); + } else { + this.shaderData.disableMacro("HAS_CLEARCOATROUGHNESSTEXTURE"); + } + } + + /** + * The clearcoat normal map texture. + */ + get clearcoatNormalTexture(): Texture2D { + return this.shaderData.getTexture(PBRMaterial._clearcoatNormalTextureProp); + } + + set clearcoatNormalTexture(value: Texture2D) { + this.shaderData.setTexture(PBRMaterial._clearcoatNormalTextureProp, value); + + if (value) { + this.shaderData.enableMacro("HAS_CLEARCOATNORMALTEXTURE"); + } else { + this.shaderData.disableMacro("HAS_CLEARCOATNORMALTEXTURE"); + } + } + /** * Create a pbr metallic-roughness workflow material instance. * @param engine - Engine to which the material belongs */ constructor(engine: Engine) { super(engine, Shader.find("pbr")); - this.shaderData.setFloat(PBRMaterial._metallicProp, 1.0); - this.shaderData.setFloat(PBRMaterial._roughnessProp, 1.0); + this.shaderData.setFloat(PBRMaterial._metallicProp, 1); + this.shaderData.setFloat(PBRMaterial._roughnessProp, 1); + this.shaderData.setFloat(PBRMaterial._clearcoatProp, 0); + this.shaderData.setFloat(PBRMaterial._clearcoatRoughnessProp, 0); } /** diff --git a/packages/core/src/shaderlib/common.glsl b/packages/core/src/shaderlib/common.glsl index 026ff80b34..615638debf 100644 --- a/packages/core/src/shaderlib/common.glsl +++ b/packages/core/src/shaderlib/common.glsl @@ -6,6 +6,10 @@ #define saturate( a ) clamp( a, 0.0, 1.0 ) #define whiteCompliment(a) ( 1.0 - saturate( a ) ) +float pow2(float x ) { + return x * x; +} + vec4 RGBMToLinear(vec4 value, float maxRange ) { return vec4( value.rgb * value.a * maxRange, 1.0 ); } diff --git a/packages/core/src/shaderlib/normal_get.glsl b/packages/core/src/shaderlib/normal_get.glsl index b7b2223d71..69424b350e 100644 --- a/packages/core/src/shaderlib/normal_get.glsl +++ b/packages/core/src/shaderlib/normal_get.glsl @@ -45,3 +45,51 @@ vec3 getNormal() return n; } + +vec3 getClearcoatNormal() +{ + #ifdef HAS_CLEARCOATNORMALTEXTURE + #ifndef O3_HAS_TANGENT + #ifdef HAS_DERIVATIVES + vec3 pos_dx = dFdx(v_pos); + vec3 pos_dy = dFdy(v_pos); + vec3 tex_dx = dFdx(vec3(v_uv, 0.0)); + vec3 tex_dy = dFdy(vec3(v_uv, 0.0)); + vec3 t = (tex_dy.t * pos_dx - tex_dx.t * pos_dy) / (tex_dx.s * tex_dy.t - tex_dy.s * tex_dx.t); + #ifdef O3_HAS_NORMAL + vec3 ng = normalize(v_normal); + #else + vec3 ng = normalize( cross(pos_dx, pos_dy) ); + #endif + t = normalize(t - ng * dot(ng, t)); + vec3 b = normalize(cross(ng, t)); + mat3 tbn = mat3(t, b, ng); + #else + #ifdef O3_HAS_NORMAL + vec3 ng = normalize(v_normal); + #else + vec3 ng = vec3(0.0, 0.0, 1.0); + #endif + mat3 tbn = mat3(vec3(0.0), vec3(0.0), ng); + #endif + #else + mat3 tbn = v_TBN; + #endif + vec3 n = texture2D(u_clearcoatNormalTexture, v_uv ).rgb; + n = normalize(tbn * ((2.0 * n - 1.0) * vec3(u_normalIntensity, u_normalIntensity, 1.0))); + #else + #ifdef O3_HAS_NORMAL + vec3 n = normalize(v_normal); + #elif defined(HAS_DERIVATIVES) + vec3 pos_dx = dFdx(v_pos); + vec3 pos_dy = dFdy(v_pos); + vec3 n = normalize( cross(pos_dx, pos_dy) ); + #else + vec3 n= vec3(0.0,0.0,1.0); + #endif + #endif + + n *= float( gl_FrontFacing ) * 2.0 - 1.0; + + return n; +} \ No newline at end of file diff --git a/packages/core/src/shaderlib/pbr/brdf.glsl b/packages/core/src/shaderlib/pbr/brdf.glsl index 4026207888..1a87d0047f 100644 --- a/packages/core/src/shaderlib/pbr/brdf.glsl +++ b/packages/core/src/shaderlib/pbr/brdf.glsl @@ -39,15 +39,15 @@ float D_GGX(float alpha, float dotNH ) { } // GGX Distribution, Schlick Fresnel, GGX-Smith Visibility -vec3 BRDF_Specular_GGX(vec3 incidentDirection, GeometricContext geometry, vec3 specularColor, float roughness ) { +vec3 BRDF_Specular_GGX(vec3 incidentDirection, vec3 viewDir, vec3 normal, vec3 specularColor, float roughness ) { float alpha = pow2( roughness ); // UE4's roughness - vec3 halfDir = normalize( incidentDirection + geometry.viewDir ); + vec3 halfDir = normalize( incidentDirection + viewDir ); - float dotNL = saturate( dot( geometry.normal, incidentDirection ) ); - float dotNV = saturate( dot( geometry.normal, geometry.viewDir ) ); - float dotNH = saturate( dot( geometry.normal, halfDir ) ); + float dotNL = saturate( dot( normal, incidentDirection ) ); + float dotNV = saturate( dot( normal, viewDir ) ); + float dotNH = saturate( dot( normal, halfDir ) ); float dotLH = saturate( dot( incidentDirection, halfDir ) ); vec3 F = F_Schlick( specularColor, dotLH ); @@ -59,3 +59,7 @@ vec3 BRDF_Specular_GGX(vec3 incidentDirection, GeometricContext geometry, vec3 s return F * ( G * D ); } + +vec3 BRDF_Diffuse_Lambert(vec3 diffuseColor ) { + return RECIPROCAL_PI * diffuseColor; +} diff --git a/packages/core/src/shaderlib/pbr/direct_irradiance_frag_define.glsl b/packages/core/src/shaderlib/pbr/direct_irradiance_frag_define.glsl index 152150dd30..883556d70d 100644 --- a/packages/core/src/shaderlib/pbr/direct_irradiance_frag_define.glsl +++ b/packages/core/src/shaderlib/pbr/direct_irradiance_frag_define.glsl @@ -4,9 +4,18 @@ void addDirectRadiance(vec3 incidentDirection, vec3 color, GeometricContext geom vec3 irradiance = dotNL * color; irradiance *= PI; - reflectedLight.directSpecular += irradiance * BRDF_Specular_GGX( incidentDirection, geometry, material.specularColor, material.roughness); - - reflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor ); + #ifdef CLEARCOAT + float ccDotNL = saturate( dot( geometry.clearcoatNormal, incidentDirection ) ); + vec3 ccIrradiance = ccDotNL * color; + float clearcoatDHR = material.clearcoat * clearcoatDHRApprox( material.clearcoatRoughness, ccDotNL ); + reflectedLight.directSpecular += ccIrradiance * material.clearcoat * BRDF_Specular_GGX( incidentDirection, geometry.viewDir, geometry.clearcoatNormal, vec3( 0.04 ), material.clearcoatRoughness ); + #else + float clearcoatDHR = 0.0; + #endif + + reflectedLight.directSpecular += ( 1.0 - clearcoatDHR ) * irradiance * BRDF_Specular_GGX( incidentDirection, geometry.viewDir, geometry.normal, material.specularColor, material.roughness); + + reflectedLight.directDiffuse += ( 1.0 - clearcoatDHR ) * irradiance * BRDF_Diffuse_Lambert( material.diffuseColor ); } diff --git a/packages/core/src/shaderlib/pbr/ibl_frag_define.glsl b/packages/core/src/shaderlib/pbr/ibl_frag_define.glsl index 1a4a3ff8ff..2b523ceefa 100644 --- a/packages/core/src/shaderlib/pbr/ibl_frag_define.glsl +++ b/packages/core/src/shaderlib/pbr/ibl_frag_define.glsl @@ -42,7 +42,7 @@ float getSpecularMIPLevel(float roughness, int maxMIPLevel ) { return roughness * float(maxMIPLevel); } -vec3 getLightProbeRadiance(GeometricContext geometry, float roughness, int maxMIPLevel, float specularIntensity) { +vec3 getLightProbeRadiance(vec3 viewDir, vec3 normal, float roughness, int maxMIPLevel, float specularIntensity) { #ifndef O3_USE_SPECULAR_ENV @@ -50,7 +50,7 @@ vec3 getLightProbeRadiance(GeometricContext geometry, float roughness, int maxMI #else - vec3 reflectVec = reflect( -geometry.viewDir, geometry.normal ); + vec3 reflectVec = reflect( -viewDir, normal ); float specularMIPLevel = getSpecularMIPLevel(roughness, maxMIPLevel ); diff --git a/packages/core/src/shaderlib/pbr/pbr_frag.glsl b/packages/core/src/shaderlib/pbr/pbr_frag.glsl index be129ebba1..ead29a58d4 100644 --- a/packages/core/src/shaderlib/pbr/pbr_frag.glsl +++ b/packages/core/src/shaderlib/pbr/pbr_frag.glsl @@ -1,4 +1,11 @@ -GeometricContext geometry = GeometricContext(v_pos, getNormal(), normalize(u_cameraPos - v_pos)); +GeometricContext geometry; +geometry.position = v_pos; +geometry.normal = getNormal(); +geometry.viewDir = normalize(u_cameraPos - v_pos); +#ifdef CLEARCOAT + geometry.clearcoatNormal = getClearcoatNormal(); +#endif + PhysicalMaterial material = getPhysicalMaterial(u_baseColor, u_metal, u_roughness, u_specularColor, u_glossiness, u_alphaCutoff); ReflectedLight reflectedLight = ReflectedLight( vec3( 0 ), vec3( 0 ), vec3( 0 ), vec3( 0 ) ); float dotNV = saturate( dot( geometry.normal, geometry.viewDir ) ); @@ -21,8 +28,25 @@ addTotalDirectRadiance(geometry, material, reflectedLight); reflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor ); // IBL specular -vec3 radiance = getLightProbeRadiance( geometry, material.roughness, int(u_envMapLight.mipMapLevel), u_envMapLight.specularIntensity); -reflectedLight.indirectSpecular += radiance * envBRDFApprox(material.specularColor, material.roughness, dotNV ); +vec3 radiance = getLightProbeRadiance(geometry.viewDir, geometry.normal, material.roughness, int(u_envMapLight.mipMapLevel), u_envMapLight.specularIntensity); +vec3 clearcoatRadiance = vec3(0); + +#ifdef CLEARCOAT + clearcoatRadiance = getLightProbeRadiance( geometry.viewDir, geometry.clearcoatNormal, material.clearcoatRoughness, int(u_envMapLight.mipMapLevel), u_envMapLight.specularIntensity ); +#endif + +#ifdef CLEARCOAT + float ccDotNV = saturate( dot( geometry.clearcoatNormal, geometry.viewDir ) ); + reflectedLight.indirectSpecular += clearcoatRadiance * material.clearcoat * envBRDFApprox(vec3( 0.04 ), material.clearcoatRoughness, dotNV); + float ccDotNL = ccDotNV; + float clearcoatDHR = material.clearcoat * clearcoatDHRApprox( material.clearcoatRoughness, ccDotNL ); +#else + float clearcoatDHR = 0.0; +#endif + +float clearcoatInv = 1.0 - clearcoatDHR; +reflectedLight.indirectSpecular += clearcoatInv * radiance * envBRDFApprox(material.specularColor, material.roughness, dotNV ); + // Occlusion #ifdef HAS_OCCLUSIONMAP diff --git a/packages/core/src/shaderlib/pbr/pbr_frag_define.glsl b/packages/core/src/shaderlib/pbr/pbr_frag_define.glsl index 6ddb7d742c..9e1bd900ad 100644 --- a/packages/core/src/shaderlib/pbr/pbr_frag_define.glsl +++ b/packages/core/src/shaderlib/pbr/pbr_frag_define.glsl @@ -7,6 +7,11 @@ uniform vec3 u_specularColor; uniform float u_glossiness; uniform vec3 u_emissiveColor; +#ifdef CLEARCOAT + uniform float u_clearcoat; + uniform float u_clearcoatRoughness; +#endif + uniform float u_normalIntensity; uniform float u_occlusionStrength; @@ -36,6 +41,19 @@ uniform float u_occlusionStrength; uniform sampler2D u_occlusionSampler; #endif +#ifdef HAS_CLEARCOATTEXTURE + uniform sampler2D u_clearcoatTexture; +#endif + +#ifdef HAS_CLEARCOATROUGHNESSTEXTURE + uniform sampler2D u_clearcoatRoughnessTexture; +#endif + +#ifdef HAS_CLEARCOATNORMALTEXTURE + uniform sampler2D u_clearcoatNormalTexture; +#endif + + struct ReflectedLight { vec3 directDiffuse; @@ -43,14 +61,25 @@ struct ReflectedLight { vec3 indirectDiffuse; vec3 indirectSpecular; }; + struct GeometricContext { vec3 position; vec3 normal; vec3 viewDir; + #ifdef CLEARCOAT + vec3 clearcoatNormal; + #endif + }; + struct PhysicalMaterial { vec3 diffuseColor; float roughness; vec3 specularColor; float opacity; + #ifdef CLEARCOAT + float clearcoat; + float clearcoatRoughness; + #endif + }; diff --git a/packages/core/src/shaderlib/pbr/pbr_helper.glsl b/packages/core/src/shaderlib/pbr/pbr_helper.glsl index 5d626fbc8f..0aca1c0aa5 100644 --- a/packages/core/src/shaderlib/pbr/pbr_helper.glsl +++ b/packages/core/src/shaderlib/pbr/pbr_helper.glsl @@ -1,19 +1,14 @@ #include -float pow2(float x ) { - return x * x; -} - -vec3 BRDF_Diffuse_Lambert(vec3 diffuseColor ) { - return RECIPROCAL_PI * diffuseColor; -} - - float computeSpecularOcclusion(float ambientOcclusion, float roughness, float dotNV ) { return saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion ); } +float clearcoatDHRApprox(float roughness, float dotNL) { + return 0.04 + 0.96 * ( pow( 1.0 - dotNL, 5.0 ) * pow( 1.0 - roughness, 2.0 ) ); +} + PhysicalMaterial getPhysicalMaterial( vec4 diffuseColor, float metal, @@ -67,6 +62,20 @@ PhysicalMaterial getPhysicalMaterial( material.roughness = clamp( 1.0 - glossiness, 0.04, 1.0 ); #endif + #ifdef CLEARCOAT + material.clearcoat = u_clearcoat; + material.clearcoatRoughness = u_clearcoatRoughness; + #ifdef HAS_CLEARCOATTEXTURE + material.clearcoat *= texture2D( u_clearcoatTexture, v_uv ).r; + #endif + #ifdef HAS_CLEARCOATROUGHNESSTEXTURE + material.clearcoatRoughness *= texture2D( u_clearcoatRoughnessTexture, v_uv ).g; + #endif + material.clearcoat = saturate( material.clearcoat ); + material.clearcoatRoughness = clamp( material.clearcoatRoughness, 0.005, 1.0 ); + #endif + + material.opacity = diffuseColor.a; return material; diff --git a/packages/loader/src/gltf/extensions/KHR_materials_clearcoat.ts b/packages/loader/src/gltf/extensions/KHR_materials_clearcoat.ts index e69de29bb2..4d92337e6c 100644 --- a/packages/loader/src/gltf/extensions/KHR_materials_clearcoat.ts +++ b/packages/loader/src/gltf/extensions/KHR_materials_clearcoat.ts @@ -0,0 +1,36 @@ +import { PBRMaterial } from "@oasis-engine/core"; +import { GLTFResource } from "../GLTFResource"; +import { MaterialParser } from "../parser/MaterialParser"; +import { registerExtension } from "../parser/Parser"; +import { ExtensionParser } from "./ExtensionParser"; +import { IKHRMaterialsClearcoat } from "./Schema"; + +@registerExtension("KHR_materials_clearcoat") +class KHR_materials_clearcoat extends ExtensionParser { + parseEngineResource(schema: IKHRMaterialsClearcoat, material: PBRMaterial, context: GLTFResource): void { + const { textures } = context; + const { + clearcoatFactor = 0, + clearcoatTexture, + clearcoatRoughnessFactor = 0, + clearcoatRoughnessTexture, + clearcoatNormalTexture + } = schema; + + material.clearcoat = clearcoatFactor; + material.clearcoatRoughness = clearcoatRoughnessFactor; + + if (clearcoatTexture) { + material.clearcoatTexture = textures[clearcoatTexture.index]; + MaterialParser._parseTextureTransform(material, clearcoatTexture.extensions, context); + } + if (clearcoatRoughnessTexture) { + material.clearcoatRoughnessTexture = textures[clearcoatRoughnessTexture.index]; + MaterialParser._parseTextureTransform(material, clearcoatRoughnessTexture.extensions, context); + } + if (clearcoatNormalTexture) { + material.clearcoatNormalTexture = textures[clearcoatNormalTexture.index]; + MaterialParser._parseTextureTransform(material, clearcoatNormalTexture.extensions, context); + } + } +} diff --git a/packages/loader/src/gltf/parser/MaterialParser.ts b/packages/loader/src/gltf/parser/MaterialParser.ts index 6ab5d02737..9b8a6a4011 100644 --- a/packages/loader/src/gltf/parser/MaterialParser.ts +++ b/packages/loader/src/gltf/parser/MaterialParser.ts @@ -33,7 +33,7 @@ export class MaterialParser extends Parser { name = "" } = gltf.materials[i]; - const { KHR_materials_unlit, KHR_materials_pbrSpecularGlossiness } = extensions; + const { KHR_materials_unlit, KHR_materials_pbrSpecularGlossiness, KHR_materials_clearcoat } = extensions; let material: UnlitMaterial | PBRMaterial | PBRSpecularMaterial = null; @@ -53,6 +53,10 @@ export class MaterialParser extends Parser { material.name = name; + if (KHR_materials_clearcoat) { + Parser.parseEngineResource("KHR_materials_clearcoat", KHR_materials_clearcoat, material, context); + } + if (pbrMetallicRoughness) { const { baseColorFactor, baseColorTexture, metallicFactor, roughnessFactor, metallicRoughnessTexture } = pbrMetallicRoughness; From 9147bd1e3215c314d3149813f36b3043ed8523a5 Mon Sep 17 00:00:00 2001 From: "shensi.zxd" Date: Wed, 2 Mar 2022 18:28:41 +0800 Subject: [PATCH 02/15] refactor: code prettier --- .../pbr/direct_irradiance_frag_define.glsl | 10 ++-- packages/core/src/shaderlib/pbr/pbr_frag.glsl | 21 ++++----- .../src/shaderlib/pbr/pbr_frag_define.glsl | 9 ++-- .../core/src/shaderlib/pbr/pbr_helper.glsl | 47 +++++++++++-------- 4 files changed, 46 insertions(+), 41 deletions(-) diff --git a/packages/core/src/shaderlib/pbr/direct_irradiance_frag_define.glsl b/packages/core/src/shaderlib/pbr/direct_irradiance_frag_define.glsl index 883556d70d..df73112e6f 100644 --- a/packages/core/src/shaderlib/pbr/direct_irradiance_frag_define.glsl +++ b/packages/core/src/shaderlib/pbr/direct_irradiance_frag_define.glsl @@ -1,4 +1,4 @@ -void addDirectRadiance(vec3 incidentDirection, vec3 color, GeometricContext geometry, PhysicalMaterial material, inout ReflectedLight reflectedLight) { +void addDirectRadiance(vec3 incidentDirection, vec3 color, Geometry geometry, Material material, inout ReflectedLight reflectedLight) { float dotNL = saturate( dot( geometry.normal, incidentDirection ) ); vec3 irradiance = dotNL * color; @@ -21,7 +21,7 @@ void addDirectRadiance(vec3 incidentDirection, vec3 color, GeometricContext geom #ifdef O3_DIRECT_LIGHT_COUNT - void addDirectionalDirectLightRadiance(DirectLight directionalLight, GeometricContext geometry, PhysicalMaterial material, inout ReflectedLight reflectedLight) { + void addDirectionalDirectLightRadiance(DirectLight directionalLight, Geometry geometry, Material material, inout ReflectedLight reflectedLight) { vec3 color = directionalLight.color; vec3 direction = -directionalLight.direction; @@ -33,7 +33,7 @@ void addDirectRadiance(vec3 incidentDirection, vec3 color, GeometricContext geom #ifdef O3_POINT_LIGHT_COUNT - void addPointDirectLightRadiance(PointLight pointLight, GeometricContext geometry, PhysicalMaterial material, inout ReflectedLight reflectedLight) { + void addPointDirectLightRadiance(PointLight pointLight, Geometry geometry, Material material, inout ReflectedLight reflectedLight) { vec3 lVector = pointLight.position - geometry.position; vec3 direction = normalize( lVector ); @@ -51,7 +51,7 @@ void addDirectRadiance(vec3 incidentDirection, vec3 color, GeometricContext geom #ifdef O3_SPOT_LIGHT_COUNT - void addSpotDirectLightRadiance(SpotLight spotLight, GeometricContext geometry, PhysicalMaterial material, inout ReflectedLight reflectedLight) { + void addSpotDirectLightRadiance(SpotLight spotLight, Geometry geometry, Material material, inout ReflectedLight reflectedLight) { vec3 lVector = spotLight.position - geometry.position; vec3 direction = normalize( lVector ); @@ -72,7 +72,7 @@ void addDirectRadiance(vec3 incidentDirection, vec3 color, GeometricContext geom #endif -void addTotalDirectRadiance(GeometricContext geometry, PhysicalMaterial material, inout ReflectedLight reflectedLight){ +void addTotalDirectRadiance(Geometry geometry, Material material, inout ReflectedLight reflectedLight){ #ifdef O3_DIRECT_LIGHT_COUNT DirectLight directionalLight; diff --git a/packages/core/src/shaderlib/pbr/pbr_frag.glsl b/packages/core/src/shaderlib/pbr/pbr_frag.glsl index ead29a58d4..47232a8117 100644 --- a/packages/core/src/shaderlib/pbr/pbr_frag.glsl +++ b/packages/core/src/shaderlib/pbr/pbr_frag.glsl @@ -1,14 +1,9 @@ -GeometricContext geometry; -geometry.position = v_pos; -geometry.normal = getNormal(); -geometry.viewDir = normalize(u_cameraPos - v_pos); -#ifdef CLEARCOAT - geometry.clearcoatNormal = getClearcoatNormal(); -#endif +Geometry geometry; +Material material; +ReflectedLight reflectedLight; -PhysicalMaterial material = getPhysicalMaterial(u_baseColor, u_metal, u_roughness, u_specularColor, u_glossiness, u_alphaCutoff); -ReflectedLight reflectedLight = ReflectedLight( vec3( 0 ), vec3( 0 ), vec3( 0 ), vec3( 0 ) ); -float dotNV = saturate( dot( geometry.normal, geometry.viewDir ) ); +initGeometry(geometry); +initMaterial(material); // Direct Light addTotalDirectRadiance(geometry, material, reflectedLight); @@ -37,7 +32,7 @@ vec3 clearcoatRadiance = vec3(0); #ifdef CLEARCOAT float ccDotNV = saturate( dot( geometry.clearcoatNormal, geometry.viewDir ) ); - reflectedLight.indirectSpecular += clearcoatRadiance * material.clearcoat * envBRDFApprox(vec3( 0.04 ), material.clearcoatRoughness, dotNV); + reflectedLight.indirectSpecular += clearcoatRadiance * material.clearcoat * envBRDFApprox(vec3( 0.04 ), material.clearcoatRoughness, geometry.dotNV); float ccDotNL = ccDotNV; float clearcoatDHR = material.clearcoat * clearcoatDHRApprox( material.clearcoatRoughness, ccDotNL ); #else @@ -45,7 +40,7 @@ vec3 clearcoatRadiance = vec3(0); #endif float clearcoatInv = 1.0 - clearcoatDHR; -reflectedLight.indirectSpecular += clearcoatInv * radiance * envBRDFApprox(material.specularColor, material.roughness, dotNV ); +reflectedLight.indirectSpecular += clearcoatInv * radiance * envBRDFApprox(material.specularColor, material.roughness, geometry.dotNV ); // Occlusion @@ -53,7 +48,7 @@ reflectedLight.indirectSpecular += clearcoatInv * radiance * envBRDFApprox(mater float ambientOcclusion = (texture2D(u_occlusionSampler, v_uv).r - 1.0) * u_occlusionStrength + 1.0; reflectedLight.indirectDiffuse *= ambientOcclusion; #ifdef O3_USE_SPECULAR_ENV - reflectedLight.indirectSpecular *= computeSpecularOcclusion(ambientOcclusion, material.roughness, dotNV); + reflectedLight.indirectSpecular *= computeSpecularOcclusion(ambientOcclusion, material.roughness, geometry.dotNV); #endif #endif diff --git a/packages/core/src/shaderlib/pbr/pbr_frag_define.glsl b/packages/core/src/shaderlib/pbr/pbr_frag_define.glsl index 9e1bd900ad..d37023a220 100644 --- a/packages/core/src/shaderlib/pbr/pbr_frag_define.glsl +++ b/packages/core/src/shaderlib/pbr/pbr_frag_define.glsl @@ -1,5 +1,4 @@ uniform float u_alphaCutoff; - uniform vec4 u_baseColor; uniform float u_metal; uniform float u_roughness; @@ -16,6 +15,7 @@ uniform float u_normalIntensity; uniform float u_occlusionStrength; +// Texture #ifdef HAS_BASECOLORMAP uniform sampler2D u_baseColorSampler; #endif @@ -55,6 +55,7 @@ uniform float u_occlusionStrength; +// Runtime struct ReflectedLight { vec3 directDiffuse; vec3 directSpecular; @@ -62,17 +63,19 @@ struct ReflectedLight { vec3 indirectSpecular; }; -struct GeometricContext { +struct Geometry { vec3 position; vec3 normal; vec3 viewDir; + float dotNV; + #ifdef CLEARCOAT vec3 clearcoatNormal; #endif }; -struct PhysicalMaterial { +struct Material { vec3 diffuseColor; float roughness; vec3 specularColor; diff --git a/packages/core/src/shaderlib/pbr/pbr_helper.glsl b/packages/core/src/shaderlib/pbr/pbr_helper.glsl index 0aca1c0aa5..267c10e8ee 100644 --- a/packages/core/src/shaderlib/pbr/pbr_helper.glsl +++ b/packages/core/src/shaderlib/pbr/pbr_helper.glsl @@ -9,31 +9,40 @@ float clearcoatDHRApprox(float roughness, float dotNL) { return 0.04 + 0.96 * ( pow( 1.0 - dotNL, 5.0 ) * pow( 1.0 - roughness, 2.0 ) ); } -PhysicalMaterial getPhysicalMaterial( - vec4 diffuseColor, - float metal, - float roughness, - vec3 specularColor, - float glossiness, - float alphaCutoff - ){ - PhysicalMaterial material; +void initGeometry(out Geometry geometry){ + geometry.position = v_pos; + geometry.normal = getNormal(); + geometry.viewDir = normalize(u_cameraPos - v_pos); + geometry.dotNV = saturate( dot(geometry.normal, geometry.viewDir) ); + + #ifdef CLEARCOAT + geometry.clearcoatNormal = getClearcoatNormal(); + #endif +} + +void initMaterial(out Material material){ + vec4 baseColor = u_baseColor; + float metal = u_metal; + float roughness = u_roughness; + vec3 specularColor = u_specularColor; + float glossiness = u_glossiness; + float alphaCutoff = u_alphaCutoff; #ifdef HAS_BASECOLORMAP - vec4 baseColor = texture2D(u_baseColorSampler, v_uv); + vec4 baseTextureColor = texture2D(u_baseColorSampler, v_uv); #ifndef OASIS_COLORSPACE_GAMMA - baseColor = gammaToLinear(baseColor); + baseTextureColor = gammaToLinear(baseTextureColor); #endif - diffuseColor *= baseColor; + baseColor *= baseTextureColor; #endif #ifdef O3_HAS_VERTEXCOLOR - diffuseColor *= v_color; + baseColor *= v_color; #endif #ifdef ALPHA_CUTOFF - if( diffuseColor.a < alphaCutoff ) { + if( baseColor.a < alphaCutoff ) { discard; } #endif @@ -52,12 +61,12 @@ PhysicalMaterial getPhysicalMaterial( #ifdef IS_METALLIC_WORKFLOW - material.diffuseColor = diffuseColor.rgb * ( 1.0 - metal ); - material.specularColor = mix( vec3( 0.04), diffuseColor.rgb, metal ); + material.diffuseColor = baseColor.rgb * ( 1.0 - metal ); + material.specularColor = mix( vec3( 0.04), baseColor.rgb, metal ); material.roughness = clamp( roughness, 0.04, 1.0 ); #else float specularStrength = max( max( specularColor.r, specularColor.g ), specularColor.b ); - material.diffuseColor = diffuseColor.rgb * ( 1.0 - specularStrength ); + material.diffuseColor = baseColor.rgb * ( 1.0 - specularStrength ); material.specularColor = specularColor; material.roughness = clamp( 1.0 - glossiness, 0.04, 1.0 ); #endif @@ -76,9 +85,7 @@ PhysicalMaterial getPhysicalMaterial( #endif - material.opacity = diffuseColor.a; - return material; - + material.opacity = baseColor.a; } // direct + indirect From a970dc68b4cfcdf425c63aaaf52c969393b7a284 Mon Sep 17 00:00:00 2001 From: "shensi.zxd" Date: Thu, 3 Mar 2022 14:22:28 +0800 Subject: [PATCH 03/15] perf: normal function override --- .../core/src/shaderlib/begin_normal_vert.glsl | 12 ++- .../src/shaderlib/mobile_blinnphong_frag.glsl | 7 +- packages/core/src/shaderlib/normal_get.glsl | 78 ++++--------------- packages/core/src/shaderlib/normal_share.glsl | 19 ++--- packages/core/src/shaderlib/normal_vert.glsl | 17 ++-- .../core/src/shaderlib/pbr/pbr_helper.glsl | 18 ++++- 6 files changed, 57 insertions(+), 94 deletions(-) diff --git a/packages/core/src/shaderlib/begin_normal_vert.glsl b/packages/core/src/shaderlib/begin_normal_vert.glsl index 1f0b8d165b..c7d1a3553b 100644 --- a/packages/core/src/shaderlib/begin_normal_vert.glsl +++ b/packages/core/src/shaderlib/begin_normal_vert.glsl @@ -1,11 +1,9 @@ +#ifndef OMIT_NORMAL #ifdef O3_HAS_NORMAL + vec3 normal = vec3( NORMAL ); + #endif - vec3 normal = vec3( NORMAL ); - - #if defined( O3_HAS_TANGENT ) && defined( O3_NORMAL_TEXTURE ) - + #ifdef O3_HAS_TANGENT vec4 tangent = vec4( TANGENT ); - - #endif - #endif +#endif \ No newline at end of file diff --git a/packages/core/src/shaderlib/mobile_blinnphong_frag.glsl b/packages/core/src/shaderlib/mobile_blinnphong_frag.glsl index 3b2b08c78f..d0d9de454b 100644 --- a/packages/core/src/shaderlib/mobile_blinnphong_frag.glsl +++ b/packages/core/src/shaderlib/mobile_blinnphong_frag.glsl @@ -1,4 +1,9 @@ - vec3 N = getNormal(); + vec3 N = getNormal( + #ifdef O3_NORMAL_TEXTURE + u_normalTexture, + u_normalIntensity + #endif + ); vec3 lightDiffuse = vec3( 0.0, 0.0, 0.0 ); vec3 lightSpecular = vec3( 0.0, 0.0, 0.0 ); diff --git a/packages/core/src/shaderlib/normal_get.glsl b/packages/core/src/shaderlib/normal_get.glsl index 69424b350e..e6fe635d07 100644 --- a/packages/core/src/shaderlib/normal_get.glsl +++ b/packages/core/src/shaderlib/normal_get.glsl @@ -1,55 +1,24 @@ -vec3 getNormal() -{ - #ifdef O3_NORMAL_TEXTURE - #ifndef O3_HAS_TANGENT - #ifdef HAS_DERIVATIVES - vec3 pos_dx = dFdx(v_pos); - vec3 pos_dy = dFdy(v_pos); - vec3 tex_dx = dFdx(vec3(v_uv, 0.0)); - vec3 tex_dy = dFdy(vec3(v_uv, 0.0)); - vec3 t = (tex_dy.t * pos_dx - tex_dx.t * pos_dy) / (tex_dx.s * tex_dy.t - tex_dy.s * tex_dx.t); - #ifdef O3_HAS_NORMAL - vec3 ng = normalize(v_normal); - #else - vec3 ng = normalize( cross(pos_dx, pos_dy) ); - #endif - t = normalize(t - ng * dot(ng, t)); - vec3 b = normalize(cross(ng, t)); - mat3 tbn = mat3(t, b, ng); - #else - #ifdef O3_HAS_NORMAL - vec3 ng = normalize(v_normal); - #else - vec3 ng = vec3(0.0, 0.0, 1.0); - #endif - mat3 tbn = mat3(vec3(0.0), vec3(0.0), ng); - #endif - #else - mat3 tbn = v_TBN; - #endif - vec3 n = texture2D(u_normalTexture, v_uv ).rgb; - n = normalize(tbn * ((2.0 * n - 1.0) * vec3(u_normalIntensity, u_normalIntensity, 1.0))); - #else +vec3 getNormal(){ + vec3 normal = vec3(0, 0, 1); + #ifdef O3_HAS_NORMAL - vec3 n = normalize(v_normal); + normal = normalize(v_normal); #elif defined(HAS_DERIVATIVES) vec3 pos_dx = dFdx(v_pos); vec3 pos_dy = dFdy(v_pos); - vec3 n = normalize( cross(pos_dx, pos_dy) ); - #else - vec3 n= vec3(0.0,0.0,1.0); + normal = normalize( cross(pos_dx, pos_dy) ); #endif - #endif - n *= float( gl_FrontFacing ) * 2.0 - 1.0; - - return n; + normal *= float( gl_FrontFacing ) * 2.0 - 1.0; + return normal; } -vec3 getClearcoatNormal() +vec3 getNormal(sampler2D normalTexture, float normalIntensity) { - #ifdef HAS_CLEARCOATNORMALTEXTURE - #ifndef O3_HAS_TANGENT + + #if defined(O3_HAS_NORMAL) && defined(O3_HAS_TANGENT) && defined( O3_NORMAL_TEXTURE ) + mat3 tbn = v_TBN; + #else #ifdef HAS_DERIVATIVES vec3 pos_dx = dFdx(v_pos); vec3 pos_dy = dFdy(v_pos); @@ -72,24 +41,11 @@ vec3 getClearcoatNormal() #endif mat3 tbn = mat3(vec3(0.0), vec3(0.0), ng); #endif - #else - mat3 tbn = v_TBN; - #endif - vec3 n = texture2D(u_clearcoatNormalTexture, v_uv ).rgb; - n = normalize(tbn * ((2.0 * n - 1.0) * vec3(u_normalIntensity, u_normalIntensity, 1.0))); - #else - #ifdef O3_HAS_NORMAL - vec3 n = normalize(v_normal); - #elif defined(HAS_DERIVATIVES) - vec3 pos_dx = dFdx(v_pos); - vec3 pos_dy = dFdy(v_pos); - vec3 n = normalize( cross(pos_dx, pos_dy) ); - #else - vec3 n= vec3(0.0,0.0,1.0); #endif - #endif - n *= float( gl_FrontFacing ) * 2.0 - 1.0; + vec3 normal = texture2D(normalTexture, v_uv ).rgb; + normal = normalize(tbn * ((2.0 * normal - 1.0) * vec3(normalIntensity, normalIntensity, 1.0))); + normal *= float( gl_FrontFacing ) * 2.0 - 1.0; - return n; -} \ No newline at end of file + return normal; +} diff --git a/packages/core/src/shaderlib/normal_share.glsl b/packages/core/src/shaderlib/normal_share.glsl index d21d9322bc..094be54d11 100644 --- a/packages/core/src/shaderlib/normal_share.glsl +++ b/packages/core/src/shaderlib/normal_share.glsl @@ -1,13 +1,8 @@ -#ifdef O3_HAS_NORMAL - - #if defined( O3_HAS_TANGENT ) && defined( O3_NORMAL_TEXTURE ) - - varying mat3 v_TBN; - - #else - - varying vec3 v_normal; - +#ifndef OMIT_NORMAL + #ifdef O3_HAS_NORMAL + varying vec3 v_normal; + #if defined( O3_HAS_TANGENT ) && defined( O3_NORMAL_TEXTURE ) + varying mat3 v_TBN; + #endif #endif - -#endif +#endif \ No newline at end of file diff --git a/packages/core/src/shaderlib/normal_vert.glsl b/packages/core/src/shaderlib/normal_vert.glsl index 938ce04cac..03a42c72dc 100644 --- a/packages/core/src/shaderlib/normal_vert.glsl +++ b/packages/core/src/shaderlib/normal_vert.glsl @@ -1,16 +1,13 @@ +#ifndef OMIT_NORMAL #ifdef O3_HAS_NORMAL + v_normal = normalize( mat3(u_normalMat) * normal ); #if defined( O3_HAS_TANGENT ) && defined( O3_NORMAL_TEXTURE ) + vec3 normalW = normalize( mat3(u_normalMat) * normal.xyz ); + vec3 tangentW = normalize( mat3(u_normalMat) * tangent.xyz ); + vec3 bitangentW = cross( normalW, tangentW ) * tangent.w; - vec3 normalW = normalize( mat3(u_normalMat) * normal.xyz ); - vec3 tangentW = normalize( mat3(u_normalMat) * tangent.xyz ); - vec3 bitangentW = cross( normalW, tangentW ) * tangent.w; - v_TBN = mat3( tangentW, bitangentW, normalW ); - - #else - - v_normal = normalize( mat3(u_normalMat) * normal ); - + v_TBN = mat3( tangentW, bitangentW, normalW ); #endif - #endif +#endif \ No newline at end of file diff --git a/packages/core/src/shaderlib/pbr/pbr_helper.glsl b/packages/core/src/shaderlib/pbr/pbr_helper.glsl index 267c10e8ee..e0fc9fb32e 100644 --- a/packages/core/src/shaderlib/pbr/pbr_helper.glsl +++ b/packages/core/src/shaderlib/pbr/pbr_helper.glsl @@ -11,13 +11,25 @@ float clearcoatDHRApprox(float roughness, float dotNL) { void initGeometry(out Geometry geometry){ geometry.position = v_pos; - geometry.normal = getNormal(); geometry.viewDir = normalize(u_cameraPos - v_pos); - geometry.dotNV = saturate( dot(geometry.normal, geometry.viewDir) ); + + geometry.normal = getNormal( + #ifdef O3_NORMAL_TEXTURE + u_normalTexture, + u_normalIntensity + #endif + ); #ifdef CLEARCOAT - geometry.clearcoatNormal = getClearcoatNormal(); + geometry.clearcoatNormal = getNormal( + #ifdef HAS_CLEARCOATNORMALTEXTURE + u_clearcoatNormalTexture, + u_normalIntensity + #endif + ); #endif + + geometry.dotNV = saturate( dot(geometry.normal, geometry.viewDir) ); } void initMaterial(out Material material){ From c3a9dc81f2bac5ad8a82e9d695a285be8b8f1f87 Mon Sep 17 00:00:00 2001 From: "shensi.zxd" Date: Thu, 3 Mar 2022 16:56:16 +0800 Subject: [PATCH 04/15] perf: code format --- packages/core/src/shaderlib/pbr/pbr_frag.glsl | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/core/src/shaderlib/pbr/pbr_frag.glsl b/packages/core/src/shaderlib/pbr/pbr_frag.glsl index 47232a8117..499d4e3bb9 100644 --- a/packages/core/src/shaderlib/pbr/pbr_frag.glsl +++ b/packages/core/src/shaderlib/pbr/pbr_frag.glsl @@ -24,13 +24,10 @@ reflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.di // IBL specular vec3 radiance = getLightProbeRadiance(geometry.viewDir, geometry.normal, material.roughness, int(u_envMapLight.mipMapLevel), u_envMapLight.specularIntensity); -vec3 clearcoatRadiance = vec3(0); #ifdef CLEARCOAT - clearcoatRadiance = getLightProbeRadiance( geometry.viewDir, geometry.clearcoatNormal, material.clearcoatRoughness, int(u_envMapLight.mipMapLevel), u_envMapLight.specularIntensity ); -#endif + vec3 clearcoatRadiance = getLightProbeRadiance( geometry.viewDir, geometry.clearcoatNormal, material.clearcoatRoughness, int(u_envMapLight.mipMapLevel), u_envMapLight.specularIntensity ); -#ifdef CLEARCOAT float ccDotNV = saturate( dot( geometry.clearcoatNormal, geometry.viewDir ) ); reflectedLight.indirectSpecular += clearcoatRadiance * material.clearcoat * envBRDFApprox(vec3( 0.04 ), material.clearcoatRoughness, geometry.dotNV); float ccDotNL = ccDotNV; From 3b833e895c088dcf30e86a140ac495755fd9e7f1 Mon Sep 17 00:00:00 2001 From: "shensi.zxd" Date: Thu, 3 Mar 2022 19:58:52 +0800 Subject: [PATCH 05/15] fix: use linear color space in gltf --- packages/core/src/shaderlib/pbr/pbr_helper.glsl | 3 +++ .../KHR_materials_pbrSpecularGlossiness.ts | 13 +++++++++++-- packages/loader/src/gltf/parser/MaterialParser.ts | 13 +++++++++++-- 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/packages/core/src/shaderlib/pbr/pbr_helper.glsl b/packages/core/src/shaderlib/pbr/pbr_helper.glsl index e0fc9fb32e..9a92b3ae6b 100644 --- a/packages/core/src/shaderlib/pbr/pbr_helper.glsl +++ b/packages/core/src/shaderlib/pbr/pbr_helper.glsl @@ -67,6 +67,9 @@ void initMaterial(out Material material){ #ifdef HAS_SPECULARGLOSSINESSMAP vec4 specularGlossinessColor = texture2D(u_specularGlossinessSampler, v_uv ); + #ifndef OASIS_COLORSPACE_GAMMA + specularGlossinessColor = gammaToLinear(specularGlossinessColor); + #endif specularColor *= specularGlossinessColor.rgb; glossiness *= specularGlossinessColor.a; #endif diff --git a/packages/loader/src/gltf/extensions/KHR_materials_pbrSpecularGlossiness.ts b/packages/loader/src/gltf/extensions/KHR_materials_pbrSpecularGlossiness.ts index fd78e27579..6faeef7983 100644 --- a/packages/loader/src/gltf/extensions/KHR_materials_pbrSpecularGlossiness.ts +++ b/packages/loader/src/gltf/extensions/KHR_materials_pbrSpecularGlossiness.ts @@ -14,7 +14,12 @@ class KHR_materials_pbrSpecularGlossiness extends ExtensionParser { const { diffuseFactor, diffuseTexture, specularFactor, glossinessFactor, specularGlossinessTexture } = schema; if (diffuseFactor) { - material.baseColor = new Color(...diffuseFactor); + material.baseColor = new Color( + Color.linearToGammaSpace(diffuseFactor[0]), + Color.linearToGammaSpace(diffuseFactor[1]), + Color.linearToGammaSpace(diffuseFactor[2]), + diffuseFactor[3] + ); } if (diffuseTexture) { @@ -23,7 +28,11 @@ class KHR_materials_pbrSpecularGlossiness extends ExtensionParser { } if (specularFactor) { - material.specularColor = new Color(...specularFactor); + material.specularColor = new Color( + Color.linearToGammaSpace(specularFactor[0]), + Color.linearToGammaSpace(specularFactor[1]), + Color.linearToGammaSpace(specularFactor[2]) + ); } if (glossinessFactor !== undefined) { diff --git a/packages/loader/src/gltf/parser/MaterialParser.ts b/packages/loader/src/gltf/parser/MaterialParser.ts index 9b8a6a4011..e58f6a6d7c 100644 --- a/packages/loader/src/gltf/parser/MaterialParser.ts +++ b/packages/loader/src/gltf/parser/MaterialParser.ts @@ -62,7 +62,12 @@ export class MaterialParser extends Parser { pbrMetallicRoughness; if (baseColorFactor) { - material.baseColor = new Color(...baseColorFactor); + material.baseColor = new Color( + Color.linearToGammaSpace(baseColorFactor[0]), + Color.linearToGammaSpace(baseColorFactor[1]), + Color.linearToGammaSpace(baseColorFactor[2]), + baseColorFactor[3] + ); } if (baseColorTexture) { material.baseTexture = textures[baseColorTexture.index]; @@ -89,7 +94,11 @@ export class MaterialParser extends Parser { } if (emissiveFactor) { - m.emissiveColor = new Color(...emissiveFactor); + m.emissiveColor = new Color( + Color.linearToGammaSpace(emissiveFactor[0]), + Color.linearToGammaSpace(emissiveFactor[1]), + Color.linearToGammaSpace(emissiveFactor[2]) + ); } if (normalTexture) { From 3100e37da9fdc97bdb5e0d33bfc1b3fd744a3bca Mon Sep 17 00:00:00 2001 From: "shensi.zxd" Date: Fri, 4 Mar 2022 11:30:51 +0800 Subject: [PATCH 06/15] fix: use ccDotNV instead of dotNV --- packages/core/src/shaderlib/pbr/pbr_frag.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/shaderlib/pbr/pbr_frag.glsl b/packages/core/src/shaderlib/pbr/pbr_frag.glsl index 499d4e3bb9..0694aab615 100644 --- a/packages/core/src/shaderlib/pbr/pbr_frag.glsl +++ b/packages/core/src/shaderlib/pbr/pbr_frag.glsl @@ -29,7 +29,7 @@ vec3 radiance = getLightProbeRadiance(geometry.viewDir, geometry.normal, materia vec3 clearcoatRadiance = getLightProbeRadiance( geometry.viewDir, geometry.clearcoatNormal, material.clearcoatRoughness, int(u_envMapLight.mipMapLevel), u_envMapLight.specularIntensity ); float ccDotNV = saturate( dot( geometry.clearcoatNormal, geometry.viewDir ) ); - reflectedLight.indirectSpecular += clearcoatRadiance * material.clearcoat * envBRDFApprox(vec3( 0.04 ), material.clearcoatRoughness, geometry.dotNV); + reflectedLight.indirectSpecular += clearcoatRadiance * material.clearcoat * envBRDFApprox(vec3( 0.04 ), material.clearcoatRoughness, ccDotNV); float ccDotNL = ccDotNV; float clearcoatDHR = material.clearcoat * clearcoatDHRApprox( material.clearcoatRoughness, ccDotNL ); #else From b25780d0564c3ea2d47f42f15df33ea238087e9c Mon Sep 17 00:00:00 2001 From: "shensi.zxd" Date: Fri, 4 Mar 2022 16:40:37 +0800 Subject: [PATCH 07/15] refactor: use new clearcoat fresnel technique --- packages/core/src/shaderlib/pbr/brdf.glsl | 4 ++++ .../pbr/direct_irradiance_frag_define.glsl | 22 +++++++++---------- packages/core/src/shaderlib/pbr/pbr_frag.glsl | 12 ++++------ .../src/shaderlib/pbr/pbr_frag_define.glsl | 1 + .../core/src/shaderlib/pbr/pbr_helper.glsl | 5 +---- 5 files changed, 20 insertions(+), 24 deletions(-) diff --git a/packages/core/src/shaderlib/pbr/brdf.glsl b/packages/core/src/shaderlib/pbr/brdf.glsl index 1a87d0047f..e88bcfe381 100644 --- a/packages/core/src/shaderlib/pbr/brdf.glsl +++ b/packages/core/src/shaderlib/pbr/brdf.glsl @@ -1,3 +1,7 @@ +float F_Schlick(float dotLH) { + return 0.04 + 0.96 * (pow(1.0 - dotLH, 5.0)); +} + vec3 F_Schlick(vec3 specularColor, float dotLH ) { // Original approximation by Christophe Schlick '94 diff --git a/packages/core/src/shaderlib/pbr/direct_irradiance_frag_define.glsl b/packages/core/src/shaderlib/pbr/direct_irradiance_frag_define.glsl index df73112e6f..27ff5bbaad 100644 --- a/packages/core/src/shaderlib/pbr/direct_irradiance_frag_define.glsl +++ b/packages/core/src/shaderlib/pbr/direct_irradiance_frag_define.glsl @@ -1,21 +1,19 @@ void addDirectRadiance(vec3 incidentDirection, vec3 color, Geometry geometry, Material material, inout ReflectedLight reflectedLight) { - float dotNL = saturate( dot( geometry.normal, incidentDirection ) ); + float attenuation = 1.0; - vec3 irradiance = dotNL * color; - irradiance *= PI; - #ifdef CLEARCOAT - float ccDotNL = saturate( dot( geometry.clearcoatNormal, incidentDirection ) ); - vec3 ccIrradiance = ccDotNL * color; - float clearcoatDHR = material.clearcoat * clearcoatDHRApprox( material.clearcoatRoughness, ccDotNL ); - reflectedLight.directSpecular += ccIrradiance * material.clearcoat * BRDF_Specular_GGX( incidentDirection, geometry.viewDir, geometry.clearcoatNormal, vec3( 0.04 ), material.clearcoatRoughness ); - #else - float clearcoatDHR = 0.0; + float clearcoatDotNL = saturate( dot( geometry.clearcoatNormal, incidentDirection ) ); + vec3 clearcoatIrradiance = clearcoatDotNL * color; + + reflectedLight.directSpecular += material.clearcoat * clearcoatIrradiance * BRDF_Specular_GGX( incidentDirection, geometry.viewDir, geometry.clearcoatNormal, vec3( 0.04 ), material.clearcoatRoughness ); + attenuation -= material.clearcoat * F_Schlick(geometry.clearcoatDotNV); #endif - reflectedLight.directSpecular += ( 1.0 - clearcoatDHR ) * irradiance * BRDF_Specular_GGX( incidentDirection, geometry.viewDir, geometry.normal, material.specularColor, material.roughness); + float dotNL = saturate( dot( geometry.normal, incidentDirection ) ); + vec3 irradiance = dotNL * color * PI; - reflectedLight.directDiffuse += ( 1.0 - clearcoatDHR ) * irradiance * BRDF_Diffuse_Lambert( material.diffuseColor ); + reflectedLight.directSpecular += attenuation * irradiance * BRDF_Specular_GGX( incidentDirection, geometry.viewDir, geometry.normal, material.specularColor, material.roughness); + reflectedLight.directDiffuse += attenuation * irradiance * BRDF_Diffuse_Lambert( material.diffuseColor ); } diff --git a/packages/core/src/shaderlib/pbr/pbr_frag.glsl b/packages/core/src/shaderlib/pbr/pbr_frag.glsl index 0694aab615..3ee86e5363 100644 --- a/packages/core/src/shaderlib/pbr/pbr_frag.glsl +++ b/packages/core/src/shaderlib/pbr/pbr_frag.glsl @@ -24,20 +24,16 @@ reflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.di // IBL specular vec3 radiance = getLightProbeRadiance(geometry.viewDir, geometry.normal, material.roughness, int(u_envMapLight.mipMapLevel), u_envMapLight.specularIntensity); +float radianceAttenuation = 1.0; #ifdef CLEARCOAT vec3 clearcoatRadiance = getLightProbeRadiance( geometry.viewDir, geometry.clearcoatNormal, material.clearcoatRoughness, int(u_envMapLight.mipMapLevel), u_envMapLight.specularIntensity ); - float ccDotNV = saturate( dot( geometry.clearcoatNormal, geometry.viewDir ) ); - reflectedLight.indirectSpecular += clearcoatRadiance * material.clearcoat * envBRDFApprox(vec3( 0.04 ), material.clearcoatRoughness, ccDotNV); - float ccDotNL = ccDotNV; - float clearcoatDHR = material.clearcoat * clearcoatDHRApprox( material.clearcoatRoughness, ccDotNL ); -#else - float clearcoatDHR = 0.0; + reflectedLight.indirectSpecular += clearcoatRadiance * material.clearcoat * envBRDFApprox(vec3( 0.04 ), material.clearcoatRoughness, geometry.clearcoatDotNV); + radianceAttenuation -= material.clearcoat * F_Schlick(geometry.clearcoatDotNV); #endif -float clearcoatInv = 1.0 - clearcoatDHR; -reflectedLight.indirectSpecular += clearcoatInv * radiance * envBRDFApprox(material.specularColor, material.roughness, geometry.dotNV ); +reflectedLight.indirectSpecular += radianceAttenuation * radiance * envBRDFApprox(material.specularColor, material.roughness, geometry.dotNV ); // Occlusion diff --git a/packages/core/src/shaderlib/pbr/pbr_frag_define.glsl b/packages/core/src/shaderlib/pbr/pbr_frag_define.glsl index d37023a220..249afe9977 100644 --- a/packages/core/src/shaderlib/pbr/pbr_frag_define.glsl +++ b/packages/core/src/shaderlib/pbr/pbr_frag_define.glsl @@ -71,6 +71,7 @@ struct Geometry { #ifdef CLEARCOAT vec3 clearcoatNormal; + float clearcoatDotNV; #endif }; diff --git a/packages/core/src/shaderlib/pbr/pbr_helper.glsl b/packages/core/src/shaderlib/pbr/pbr_helper.glsl index 9a92b3ae6b..80bf592ff7 100644 --- a/packages/core/src/shaderlib/pbr/pbr_helper.glsl +++ b/packages/core/src/shaderlib/pbr/pbr_helper.glsl @@ -5,10 +5,6 @@ float computeSpecularOcclusion(float ambientOcclusion, float roughness, float do return saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion ); } -float clearcoatDHRApprox(float roughness, float dotNL) { - return 0.04 + 0.96 * ( pow( 1.0 - dotNL, 5.0 ) * pow( 1.0 - roughness, 2.0 ) ); -} - void initGeometry(out Geometry geometry){ geometry.position = v_pos; geometry.viewDir = normalize(u_cameraPos - v_pos); @@ -27,6 +23,7 @@ void initGeometry(out Geometry geometry){ u_normalIntensity #endif ); + geometry.clearcoatDotNV = saturate( dot(geometry.clearcoatNormal, geometry.viewDir) ); #endif geometry.dotNV = saturate( dot(geometry.normal, geometry.viewDir) ); From 9eb8c1a96354ec5d710edb37ec202c45b23bb659 Mon Sep 17 00:00:00 2001 From: "shensi.zxd" Date: Fri, 4 Mar 2022 17:24:38 +0800 Subject: [PATCH 08/15] feat: add specular anti aliasing --- packages/core/src/shaderlib/pbr/pbr_frag.glsl | 2 +- .../core/src/shaderlib/pbr/pbr_helper.glsl | 38 ++++++++++++------- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/packages/core/src/shaderlib/pbr/pbr_frag.glsl b/packages/core/src/shaderlib/pbr/pbr_frag.glsl index 3ee86e5363..2b1409c3f4 100644 --- a/packages/core/src/shaderlib/pbr/pbr_frag.glsl +++ b/packages/core/src/shaderlib/pbr/pbr_frag.glsl @@ -3,7 +3,7 @@ Material material; ReflectedLight reflectedLight; initGeometry(geometry); -initMaterial(material); +initMaterial(material, geometry); // Direct Light addTotalDirectRadiance(geometry, material, reflectedLight); diff --git a/packages/core/src/shaderlib/pbr/pbr_helper.glsl b/packages/core/src/shaderlib/pbr/pbr_helper.glsl index 80bf592ff7..1374290eee 100644 --- a/packages/core/src/shaderlib/pbr/pbr_helper.glsl +++ b/packages/core/src/shaderlib/pbr/pbr_helper.glsl @@ -5,6 +5,15 @@ float computeSpecularOcclusion(float ambientOcclusion, float roughness, float do return saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion ); } +float getAARoughnessFactor(vec3 normal) { + #ifdef HAS_DERIVATIVES + vec3 dxy = max( abs(dFdx(normal)), abs(dFdy(normal)) ); + return max( max(dxy.x, dxy.y), dxy.z ); + #else + return 0.0; + #endif +} + void initGeometry(out Geometry geometry){ geometry.position = v_pos; geometry.viewDir = normalize(u_cameraPos - v_pos); @@ -29,7 +38,7 @@ void initGeometry(out Geometry geometry){ geometry.dotNV = saturate( dot(geometry.normal, geometry.viewDir) ); } -void initMaterial(out Material material){ +void initMaterial(out Material material, const in Geometry geometry){ vec4 baseColor = u_baseColor; float metal = u_metal; float roughness = u_roughness; @@ -75,28 +84,29 @@ void initMaterial(out Material material){ #ifdef IS_METALLIC_WORKFLOW material.diffuseColor = baseColor.rgb * ( 1.0 - metal ); material.specularColor = mix( vec3( 0.04), baseColor.rgb, metal ); - material.roughness = clamp( roughness, 0.04, 1.0 ); + material.roughness = roughness; #else float specularStrength = max( max( specularColor.r, specularColor.g ), specularColor.b ); material.diffuseColor = baseColor.rgb * ( 1.0 - specularStrength ); material.specularColor = specularColor; - material.roughness = clamp( 1.0 - glossiness, 0.04, 1.0 ); + material.roughness = 1.0 - glossiness; #endif + material.roughness = max(material.roughness, getAARoughnessFactor(geometry.normal)); + #ifdef CLEARCOAT - material.clearcoat = u_clearcoat; - material.clearcoatRoughness = u_clearcoatRoughness; - #ifdef HAS_CLEARCOATTEXTURE - material.clearcoat *= texture2D( u_clearcoatTexture, v_uv ).r; - #endif - #ifdef HAS_CLEARCOATROUGHNESSTEXTURE - material.clearcoatRoughness *= texture2D( u_clearcoatRoughnessTexture, v_uv ).g; - #endif - material.clearcoat = saturate( material.clearcoat ); - material.clearcoatRoughness = clamp( material.clearcoatRoughness, 0.005, 1.0 ); + material.clearcoat = u_clearcoat; + material.clearcoatRoughness = u_clearcoatRoughness; + #ifdef HAS_CLEARCOATTEXTURE + material.clearcoat *= texture2D( u_clearcoatTexture, v_uv ).r; + #endif + #ifdef HAS_CLEARCOATROUGHNESSTEXTURE + material.clearcoatRoughness *= texture2D( u_clearcoatRoughnessTexture, v_uv ).g; + #endif + material.clearcoat = saturate( material.clearcoat ); + material.clearcoatRoughness = max(material.clearcoatRoughness, getAARoughnessFactor(geometry.clearcoatNormal)); #endif - material.opacity = baseColor.a; } From e611a1bfb8bf8e5d528edfadc13dcd87ad3a4aae Mon Sep 17 00:00:00 2001 From: "shensi.zxd" Date: Fri, 4 Mar 2022 17:59:49 +0800 Subject: [PATCH 09/15] ci: build error --- packages/controls/src/FreeControl.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/controls/src/FreeControl.ts b/packages/controls/src/FreeControl.ts index 52d42353e3..53cab157cd 100644 --- a/packages/controls/src/FreeControl.ts +++ b/packages/controls/src/FreeControl.ts @@ -281,7 +281,7 @@ export class FreeControl extends Script { */ updateSpherical(): void { this._v3Cache.setValue(0, 0, -1); - Vector3.transformByQuat(this._v3Cache, this.camera.rotation, this._v3Cache); + Vector3.transformByQuat(this._v3Cache, this.camera.transform.rotationQuaternion, this._v3Cache); this._spherical.setFromVec3(this._v3Cache); this._theta = this._spherical.theta; this._phi = this._spherical.phi; From d5a51186cbe2cf83ae70ab75c9f78ce0d9a87485 Mon Sep 17 00:00:00 2001 From: "shensi.zxd" Date: Thu, 10 Mar 2022 15:01:53 +0800 Subject: [PATCH 10/15] refactor: implements clearcoat in pbr base material --- packages/core/src/material/PBRBaseMaterial.ts | 90 ++++++++++++++++++- packages/core/src/material/PBRMaterial.ts | 86 ------------------ 2 files changed, 89 insertions(+), 87 deletions(-) diff --git a/packages/core/src/material/PBRBaseMaterial.ts b/packages/core/src/material/PBRBaseMaterial.ts index f9a2a38848..848dacdd15 100644 --- a/packages/core/src/material/PBRBaseMaterial.ts +++ b/packages/core/src/material/PBRBaseMaterial.ts @@ -15,10 +15,15 @@ export abstract class PBRBaseMaterial extends BaseMaterial { private static _normalTextureProp = Shader.getPropertyByName("u_normalTexture"); private static _normalTextureIntensityProp = Shader.getPropertyByName("u_normalIntensity"); private static _occlusionTextureIntensityProp = Shader.getPropertyByName("u_occlusionStrength"); - private static _emissiveTextureProp = Shader.getPropertyByName("u_emissiveSampler"); private static _occlusionTextureProp = Shader.getPropertyByName("u_occlusionSampler"); + private static _clearcoatProp = Shader.getPropertyByName("u_clearcoat"); + private static _clearcoatTextureProp = Shader.getPropertyByName("u_clearcoatTexture"); + private static _clearcoatRoughnessProp = Shader.getPropertyByName("u_clearcoatRoughness"); + private static _clearcoatRoughnessTextureProp = Shader.getPropertyByName("u_clearcoatRoughnessTexture"); + private static _clearcoatNormalTextureProp = Shader.getPropertyByName("u_clearcoatNormalTexture"); + /** * Base color. */ @@ -148,6 +153,86 @@ export abstract class PBRBaseMaterial extends BaseMaterial { } } + + /** + * The clearcoat layer intensity, default 0. + */ + get clearcoat(): number { + return this.shaderData.getFloat(PBRBaseMaterial._clearcoatProp); + } + + set clearcoat(value: number) { + this.shaderData.setFloat(PBRBaseMaterial._clearcoatProp, value); + + if (value === 0) { + this.shaderData.disableMacro("CLEARCOAT"); + } else { + this.shaderData.enableMacro("CLEARCOAT"); + } + } + + /** + * The clearcoat layer intensity texture. + */ + get clearcoatTexture(): Texture2D { + return this.shaderData.getTexture(PBRBaseMaterial._clearcoatTextureProp); + } + + set clearcoatTexture(value: Texture2D) { + this.shaderData.setTexture(PBRBaseMaterial._clearcoatTextureProp, value); + + if (value) { + this.shaderData.enableMacro("HAS_CLEARCOATTEXTURE"); + } else { + this.shaderData.disableMacro("HAS_CLEARCOATTEXTURE"); + } + } + + /** + * The clearcoat layer roughness, default 0. + */ + get clearcoatRoughness(): number { + return this.shaderData.getFloat(PBRBaseMaterial._clearcoatRoughnessProp); + } + + set clearcoatRoughness(value: number) { + this.shaderData.setFloat(PBRBaseMaterial._clearcoatRoughnessProp, value); + } + + /** + * The clearcoat layer roughness texture. + */ + get clearcoatRoughnessTexture(): Texture2D { + return this.shaderData.getTexture(PBRBaseMaterial._clearcoatRoughnessTextureProp); + } + + set clearcoatRoughnessTexture(value: Texture2D) { + this.shaderData.setTexture(PBRBaseMaterial._clearcoatRoughnessTextureProp, value); + + if (value) { + this.shaderData.enableMacro("HAS_CLEARCOATROUGHNESSTEXTURE"); + } else { + this.shaderData.disableMacro("HAS_CLEARCOATROUGHNESSTEXTURE"); + } + } + + /** + * The clearcoat normal map texture. + */ + get clearcoatNormalTexture(): Texture2D { + return this.shaderData.getTexture(PBRBaseMaterial._clearcoatNormalTextureProp); + } + + set clearcoatNormalTexture(value: Texture2D) { + this.shaderData.setTexture(PBRBaseMaterial._clearcoatNormalTextureProp, value); + + if (value) { + this.shaderData.enableMacro("HAS_CLEARCOATNORMALTEXTURE"); + } else { + this.shaderData.disableMacro("HAS_CLEARCOATNORMALTEXTURE"); + } + } + /** * Create a pbr base material instance. * @param engine - Engine to which the material belongs @@ -167,5 +252,8 @@ export abstract class PBRBaseMaterial extends BaseMaterial { shaderData.setFloat(PBRBaseMaterial._normalTextureIntensityProp, 1); shaderData.setFloat(PBRBaseMaterial._occlusionTextureIntensityProp, 1); + + this.shaderData.setFloat(PBRBaseMaterial._clearcoatProp, 0); + this.shaderData.setFloat(PBRBaseMaterial._clearcoatRoughnessProp, 0); } } diff --git a/packages/core/src/material/PBRMaterial.ts b/packages/core/src/material/PBRMaterial.ts index a35652dc2b..f14c649779 100644 --- a/packages/core/src/material/PBRMaterial.ts +++ b/packages/core/src/material/PBRMaterial.ts @@ -10,11 +10,6 @@ export class PBRMaterial extends PBRBaseMaterial { private static _metallicProp = Shader.getPropertyByName("u_metal"); private static _roughnessProp = Shader.getPropertyByName("u_roughness"); private static _metallicRoughnessTextureProp = Shader.getPropertyByName("u_metallicRoughnessSampler"); - private static _clearcoatProp = Shader.getPropertyByName("u_clearcoat"); - private static _clearcoatTextureProp = Shader.getPropertyByName("u_clearcoatTexture"); - private static _clearcoatRoughnessProp = Shader.getPropertyByName("u_clearcoatRoughness"); - private static _clearcoatRoughnessTextureProp = Shader.getPropertyByName("u_clearcoatRoughnessTexture"); - private static _clearcoatNormalTextureProp = Shader.getPropertyByName("u_clearcoatNormalTexture"); /** * Metallic, default 1. @@ -55,85 +50,6 @@ export class PBRMaterial extends PBRBaseMaterial { } } - /** - * The clearcoat layer intensity, default 0. - */ - get clearcoat(): number { - return this.shaderData.getFloat(PBRMaterial._clearcoatProp); - } - - set clearcoat(value: number) { - this.shaderData.setFloat(PBRMaterial._clearcoatProp, value); - - if (value === 0) { - this.shaderData.disableMacro("CLEARCOAT"); - } else { - this.shaderData.enableMacro("CLEARCOAT"); - } - } - - /** - * The clearcoat layer intensity texture. - */ - get clearcoatTexture(): Texture2D { - return this.shaderData.getTexture(PBRMaterial._clearcoatTextureProp); - } - - set clearcoatTexture(value: Texture2D) { - this.shaderData.setTexture(PBRMaterial._clearcoatTextureProp, value); - - if (value) { - this.shaderData.enableMacro("HAS_CLEARCOATTEXTURE"); - } else { - this.shaderData.disableMacro("HAS_CLEARCOATTEXTURE"); - } - } - - /** - * The clearcoat layer roughness, default 0. - */ - get clearcoatRoughness(): number { - return this.shaderData.getFloat(PBRMaterial._clearcoatRoughnessProp); - } - - set clearcoatRoughness(value: number) { - this.shaderData.setFloat(PBRMaterial._clearcoatRoughnessProp, value); - } - - /** - * The clearcoat layer roughness texture. - */ - get clearcoatRoughnessTexture(): Texture2D { - return this.shaderData.getTexture(PBRMaterial._clearcoatRoughnessTextureProp); - } - - set clearcoatRoughnessTexture(value: Texture2D) { - this.shaderData.setTexture(PBRMaterial._clearcoatRoughnessTextureProp, value); - - if (value) { - this.shaderData.enableMacro("HAS_CLEARCOATROUGHNESSTEXTURE"); - } else { - this.shaderData.disableMacro("HAS_CLEARCOATROUGHNESSTEXTURE"); - } - } - - /** - * The clearcoat normal map texture. - */ - get clearcoatNormalTexture(): Texture2D { - return this.shaderData.getTexture(PBRMaterial._clearcoatNormalTextureProp); - } - - set clearcoatNormalTexture(value: Texture2D) { - this.shaderData.setTexture(PBRMaterial._clearcoatNormalTextureProp, value); - - if (value) { - this.shaderData.enableMacro("HAS_CLEARCOATNORMALTEXTURE"); - } else { - this.shaderData.disableMacro("HAS_CLEARCOATNORMALTEXTURE"); - } - } - /** * Create a pbr metallic-roughness workflow material instance. * @param engine - Engine to which the material belongs @@ -142,8 +58,6 @@ export class PBRMaterial extends PBRBaseMaterial { super(engine, Shader.find("pbr")); this.shaderData.setFloat(PBRMaterial._metallicProp, 1); this.shaderData.setFloat(PBRMaterial._roughnessProp, 1); - this.shaderData.setFloat(PBRMaterial._clearcoatProp, 0); - this.shaderData.setFloat(PBRMaterial._clearcoatRoughnessProp, 0); } /** From 448ce1a16e0a6a95366752cd8480125ca5347872 Mon Sep 17 00:00:00 2001 From: "shensi.zxd" Date: Thu, 10 Mar 2022 18:04:45 +0800 Subject: [PATCH 11/15] refactor: code format --- packages/core/src/material/PBRBaseMaterial.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/core/src/material/PBRBaseMaterial.ts b/packages/core/src/material/PBRBaseMaterial.ts index 848dacdd15..58a922cee6 100644 --- a/packages/core/src/material/PBRBaseMaterial.ts +++ b/packages/core/src/material/PBRBaseMaterial.ts @@ -153,11 +153,10 @@ export abstract class PBRBaseMaterial extends BaseMaterial { } } - /** * The clearcoat layer intensity, default 0. */ - get clearcoat(): number { + get clearcoat(): number { return this.shaderData.getFloat(PBRBaseMaterial._clearcoatProp); } @@ -253,7 +252,7 @@ export abstract class PBRBaseMaterial extends BaseMaterial { shaderData.setFloat(PBRBaseMaterial._normalTextureIntensityProp, 1); shaderData.setFloat(PBRBaseMaterial._occlusionTextureIntensityProp, 1); - this.shaderData.setFloat(PBRBaseMaterial._clearcoatProp, 0); - this.shaderData.setFloat(PBRBaseMaterial._clearcoatRoughnessProp, 0); + shaderData.setFloat(PBRBaseMaterial._clearcoatProp, 0); + shaderData.setFloat(PBRBaseMaterial._clearcoatRoughnessProp, 0); } } From fe024f048ac2a2d80c895b4f63ea33f2baf2c10a Mon Sep 17 00:00:00 2001 From: "shensi.zxd" Date: Fri, 11 Mar 2022 23:34:26 +0800 Subject: [PATCH 12/15] feat: support pbr sheen --- packages/core/src/material/PBRBaseMaterial.ts | 98 +++++++++++++++++++ packages/core/src/shaderlib/pbr/brdf.glsl | 28 ++++++ .../pbr/direct_irradiance_frag_define.glsl | 13 ++- packages/core/src/shaderlib/pbr/pbr_frag.glsl | 28 +++--- .../src/shaderlib/pbr/pbr_frag_define.glsl | 20 ++++ .../core/src/shaderlib/pbr/pbr_helper.glsl | 41 ++++++-- .../gltf/extensions/KHR_materials_sheen.ts | 36 +++++++ .../loader/src/gltf/parser/MaterialParser.ts | 7 +- 8 files changed, 247 insertions(+), 24 deletions(-) diff --git a/packages/core/src/material/PBRBaseMaterial.ts b/packages/core/src/material/PBRBaseMaterial.ts index 58a922cee6..ddb60a3333 100644 --- a/packages/core/src/material/PBRBaseMaterial.ts +++ b/packages/core/src/material/PBRBaseMaterial.ts @@ -24,6 +24,13 @@ export abstract class PBRBaseMaterial extends BaseMaterial { private static _clearcoatRoughnessTextureProp = Shader.getPropertyByName("u_clearcoatRoughnessTexture"); private static _clearcoatNormalTextureProp = Shader.getPropertyByName("u_clearcoatNormalTexture"); + private static _sheenColor = Shader.getPropertyByName("u_sheenColor"); + private static _sheenColorTexture = Shader.getPropertyByName("u_sheenColorTexture"); + private static _sheenRoughness = Shader.getPropertyByName("u_sheenRoughness"); + private static _sheenRoughnessTexture = Shader.getPropertyByName("u_sheenRoughnessTexture"); + + private _sheenEnabled: boolean = false; + /** * Base color. */ @@ -232,6 +239,84 @@ export abstract class PBRBaseMaterial extends BaseMaterial { } } + /** + * Sheen enabled. + * @remark + */ + get sheenEnabled(): boolean { + return this._sheenEnabled; + } + + set sheenEnabled(value: boolean) { + this._sheenEnabled = value; + + if (value) { + this.shaderData.enableMacro("SHEEN"); + } else { + this.shaderData.disableMacro("SHEEN"); + } + } + + /** + * Sheen color, default [0,0,0]. + */ + get sheenColor(): Color { + return this.shaderData.getColor(PBRBaseMaterial._sheenColor); + } + + set sheenColor(value: Color) { + const baseColor = this.shaderData.getColor(PBRBaseMaterial._sheenColor); + + if (value !== baseColor) { + value.cloneTo(baseColor); + } + } + + /** + * The sheen color texture. + */ + get sheenColorTexture(): Texture2D { + return this.shaderData.getTexture(PBRBaseMaterial._sheenColorTexture); + } + + set sheenColorTexture(value: Texture2D) { + this.shaderData.setTexture(PBRBaseMaterial._sheenColorTexture, value); + + if (value) { + this.shaderData.enableMacro("HAS_SHEENCOLORTEXTURE"); + } else { + this.shaderData.disableMacro("HAS_SHEENCOLORTEXTURE"); + } + } + + /** + * Sheen roughness, default 0. + */ + get sheenRoughness(): number { + return this.shaderData.getFloat(PBRBaseMaterial._sheenRoughness); + } + + set sheenRoughness(value: number) { + this.shaderData.setFloat(PBRBaseMaterial._sheenRoughness, value); + } + + /** + * The sheen roughness texture. + */ + get sheenRoughnessTexture(): Texture2D { + return this.shaderData.getTexture(PBRBaseMaterial._sheenRoughnessTexture); + } + + set sheenRoughnessTexture(value: Texture2D) { + this.shaderData.setTexture(PBRBaseMaterial._sheenRoughnessTexture, value); + + if (value) { + this.shaderData.enableMacro("HAS_SHEENROUGHNESSTEXTURE"); + } else { + this.shaderData.disableMacro("HAS_SHEENROUGHNESSTEXTURE"); + } + } + /** * Create a pbr base material instance. * @param engine - Engine to which the material belongs @@ -254,5 +339,18 @@ export abstract class PBRBaseMaterial extends BaseMaterial { shaderData.setFloat(PBRBaseMaterial._clearcoatProp, 0); shaderData.setFloat(PBRBaseMaterial._clearcoatRoughnessProp, 0); + + shaderData.setColor(PBRBaseMaterial._sheenColor, new Color(0, 0, 0, 1)); + shaderData.setFloat(PBRBaseMaterial._sheenRoughness, 0); + } + + /** + * @override + * Clone to the target material. + * @param target - target material + */ + cloneTo(target: PBRBaseMaterial): void { + super.cloneTo(target); + target._sheenEnabled = this._sheenEnabled; } } diff --git a/packages/core/src/shaderlib/pbr/brdf.glsl b/packages/core/src/shaderlib/pbr/brdf.glsl index e88bcfe381..ba5bb7dbf2 100644 --- a/packages/core/src/shaderlib/pbr/brdf.glsl +++ b/packages/core/src/shaderlib/pbr/brdf.glsl @@ -67,3 +67,31 @@ vec3 BRDF_Specular_GGX(vec3 incidentDirection, vec3 viewDir, vec3 normal, vec3 s vec3 BRDF_Diffuse_Lambert(vec3 diffuseColor ) { return RECIPROCAL_PI * diffuseColor; } + + +#ifdef SHEEN + float D_Charlie(float roughness, float NoH) { + float alpha = pow2( roughness ); + // Estevez and Kulla 2017, "Production Friendly Microfacet Sheen BRDF" + float invAlpha = 1.0 / roughness; + float cos2h = NoH * NoH; + float sin2h = max(1.0 - cos2h, 0.0078125); // 2^(-14/2), so sin2h^2 > 0 in fp16 + + return (2.0 + invAlpha) * pow(sin2h, invAlpha * 0.5) / (2.0 * PI); + } + + float V_Neubelt(float NoV, float NoL) { + // Neubelt and Pettineo 2013, "Crafting a Next-gen Material Pipeline for The Order: 1886" + return saturate(1.0 / (4.0 * (NoL + NoV - NoL * NoV))); + } + + vec3 BRDF_Specular_Sheen(vec3 lightDir, Geometry geometry, vec3 sheenColor, float sheenRoughness ) { + vec3 halfDir = normalize( lightDir + geometry.viewDir ); + float dotNL = saturate( dot( geometry.normal, lightDir ) ); + float dotNH = saturate( dot( geometry.normal, halfDir ) ); + float D = D_Charlie( sheenRoughness, dotNH ); + float V = V_Neubelt( geometry.dotNV, dotNL ); + + return sheenColor * ( D * V ); + } +#endif \ No newline at end of file diff --git a/packages/core/src/shaderlib/pbr/direct_irradiance_frag_define.glsl b/packages/core/src/shaderlib/pbr/direct_irradiance_frag_define.glsl index 27ff5bbaad..17fee6919c 100644 --- a/packages/core/src/shaderlib/pbr/direct_irradiance_frag_define.glsl +++ b/packages/core/src/shaderlib/pbr/direct_irradiance_frag_define.glsl @@ -1,17 +1,20 @@ void addDirectRadiance(vec3 incidentDirection, vec3 color, Geometry geometry, Material material, inout ReflectedLight reflectedLight) { - float attenuation = 1.0; + float dotNL = saturate( dot( geometry.normal, incidentDirection ) ); + vec3 irradiance = dotNL * color * PI; #ifdef CLEARCOAT float clearcoatDotNL = saturate( dot( geometry.clearcoatNormal, incidentDirection ) ); vec3 clearcoatIrradiance = clearcoatDotNL * color; reflectedLight.directSpecular += material.clearcoat * clearcoatIrradiance * BRDF_Specular_GGX( incidentDirection, geometry.viewDir, geometry.clearcoatNormal, vec3( 0.04 ), material.clearcoatRoughness ); - attenuation -= material.clearcoat * F_Schlick(geometry.clearcoatDotNV); + #endif + + + #ifdef SHEEN + reflectedLight.directSpecular += material.clearcoatAttenuation * irradiance * BRDF_Specular_Sheen(incidentDirection, geometry, material.sheenColor, material.sheenRoughness); #endif - float dotNL = saturate( dot( geometry.normal, incidentDirection ) ); - vec3 irradiance = dotNL * color * PI; - + float attenuation = material.clearcoatAttenuation * material.sheenAttenuation; reflectedLight.directSpecular += attenuation * irradiance * BRDF_Specular_GGX( incidentDirection, geometry.viewDir, geometry.normal, material.specularColor, material.roughness); reflectedLight.directDiffuse += attenuation * irradiance * BRDF_Diffuse_Lambert( material.diffuseColor ); diff --git a/packages/core/src/shaderlib/pbr/pbr_frag.glsl b/packages/core/src/shaderlib/pbr/pbr_frag.glsl index 2b1409c3f4..c2d87b3083 100644 --- a/packages/core/src/shaderlib/pbr/pbr_frag.glsl +++ b/packages/core/src/shaderlib/pbr/pbr_frag.glsl @@ -5,10 +5,10 @@ ReflectedLight reflectedLight; initGeometry(geometry); initMaterial(material, geometry); -// Direct Light +/** ------ Direct Light ------ */ addTotalDirectRadiance(geometry, material, reflectedLight); -// IBL diffuse +/** ------ IBL irradiance ------ */ #ifdef O3_USE_SH vec3 irradiance = getLightProbeIrradiance(u_env_sh, geometry.normal); #ifdef OASIS_COLORSPACE_GAMMA @@ -22,40 +22,44 @@ addTotalDirectRadiance(geometry, material, reflectedLight); reflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor ); -// IBL specular +/** ------ IBL radiance ------ */ vec3 radiance = getLightProbeRadiance(geometry.viewDir, geometry.normal, material.roughness, int(u_envMapLight.mipMapLevel), u_envMapLight.specularIntensity); -float radianceAttenuation = 1.0; #ifdef CLEARCOAT vec3 clearcoatRadiance = getLightProbeRadiance( geometry.viewDir, geometry.clearcoatNormal, material.clearcoatRoughness, int(u_envMapLight.mipMapLevel), u_envMapLight.specularIntensity ); - reflectedLight.indirectSpecular += clearcoatRadiance * material.clearcoat * envBRDFApprox(vec3( 0.04 ), material.clearcoatRoughness, geometry.clearcoatDotNV); - radianceAttenuation -= material.clearcoat * F_Schlick(geometry.clearcoatDotNV); #endif -reflectedLight.indirectSpecular += radianceAttenuation * radiance * envBRDFApprox(material.specularColor, material.roughness, geometry.dotNV ); +#ifdef SHEEN + float sheenAlbedoScaling = getSheenAlbedoScaling(material.sheenColor); + reflectedLight.indirectSpecular += material.clearcoatAttenuation * radiance * envBRDFApprox(material.sheenColor, material.sheenRoughness, geometry.dotNV ); +#endif + +// attenuation(total) = attenuation(clearcoat + sheen) +float attenuation = material.clearcoatAttenuation * material.sheenAttenuation; +reflectedLight.indirectSpecular += attenuation * radiance * envBRDFApprox(material.specularColor, material.roughness, geometry.dotNV ); -// Occlusion +/** ------ occlusion ------ */ #ifdef HAS_OCCLUSIONMAP float ambientOcclusion = (texture2D(u_occlusionSampler, v_uv).r - 1.0) * u_occlusionStrength + 1.0; reflectedLight.indirectDiffuse *= ambientOcclusion; #ifdef O3_USE_SPECULAR_ENV - reflectedLight.indirectSpecular *= computeSpecularOcclusion(ambientOcclusion, material.roughness, geometry.dotNV); + reflectedLight.indirectSpecular *= attenuation * computeSpecularOcclusion(ambientOcclusion, material.roughness, geometry.dotNV); #endif #endif -// Emissive +/** ------ emissive ------ */ vec3 emissiveRadiance = u_emissiveColor; #ifdef HAS_EMISSIVEMAP vec4 emissiveColor = texture2D(u_emissiveSampler, v_uv); #ifndef OASIS_COLORSPACE_GAMMA emissiveColor = gammaToLinear(emissiveColor); #endif - emissiveRadiance *= emissiveColor.rgb; + emissiveRadiance *= attenuation * emissiveColor.rgb; #endif -// Total +/** ------ Total ------ */ vec3 totalRadiance = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + diff --git a/packages/core/src/shaderlib/pbr/pbr_frag_define.glsl b/packages/core/src/shaderlib/pbr/pbr_frag_define.glsl index 249afe9977..4eea4a22a6 100644 --- a/packages/core/src/shaderlib/pbr/pbr_frag_define.glsl +++ b/packages/core/src/shaderlib/pbr/pbr_frag_define.glsl @@ -11,6 +11,11 @@ uniform vec3 u_emissiveColor; uniform float u_clearcoatRoughness; #endif +#ifdef SHEEN + uniform vec3 u_sheenColor; + uniform float u_sheenRoughness; +#endif + uniform float u_normalIntensity; uniform float u_occlusionStrength; @@ -53,6 +58,13 @@ uniform float u_occlusionStrength; uniform sampler2D u_clearcoatNormalTexture; #endif +#ifdef HAS_SHEENCOLORTEXTURE + uniform sampler2D u_sheenColorTexture; +#endif + +#ifdef HAS_SHEENROUGHNESSTEXTURE + uniform sampler2D u_sheenRoughnessTexture; +#endif // Runtime @@ -81,9 +93,17 @@ struct Material { float roughness; vec3 specularColor; float opacity; + float clearcoatAttenuation; + float sheenAttenuation; + #ifdef CLEARCOAT float clearcoat; float clearcoatRoughness; #endif + + #ifdef SHEEN + vec3 sheenColor; + float sheenRoughness; + #endif }; diff --git a/packages/core/src/shaderlib/pbr/pbr_helper.glsl b/packages/core/src/shaderlib/pbr/pbr_helper.glsl index 1374290eee..8ce17dcfae 100644 --- a/packages/core/src/shaderlib/pbr/pbr_helper.glsl +++ b/packages/core/src/shaderlib/pbr/pbr_helper.glsl @@ -1,5 +1,9 @@ #include +// direct + indirect +#include +#include +#include float computeSpecularOcclusion(float ambientOcclusion, float roughness, float dotNV ) { return saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion ); @@ -14,6 +18,11 @@ float getAARoughnessFactor(vec3 normal) { #endif } +float getSheenAlbedoScaling(vec3 sheenColor){ + // https://drive.google.com/file/d/1T0D1VSyR4AllqIJTQAraEIzjlb5h4FKH/view?usp=sharing + return 1.0 - 0.157 * max( max(sheenColor.r, sheenColor.g), sheenColor.b ); +} + void initGeometry(out Geometry geometry){ geometry.position = v_pos; geometry.viewDir = normalize(u_cameraPos - v_pos); @@ -105,12 +114,32 @@ void initMaterial(out Material material, const in Geometry geometry){ #endif material.clearcoat = saturate( material.clearcoat ); material.clearcoatRoughness = max(material.clearcoatRoughness, getAARoughnessFactor(geometry.clearcoatNormal)); + material.clearcoatAttenuation = 1.0 - material.clearcoat * F_Schlick(geometry.clearcoatDotNV); + #else + material.clearcoatAttenuation = 1.0; #endif - material.opacity = baseColor.a; -} + #ifdef SHEEN + material.sheenColor = u_sheenColor; -// direct + indirect -#include -#include -#include \ No newline at end of file + #ifdef HAS_SHEENCOLORTEXTURE + vec4 sheenColorTextureValue = texture2D( u_sheenColorTexture, v_uv ); + #ifndef OASIS_COLORSPACE_GAMMA + sheenColorTextureValue = gammaToLinear(sheenColorTextureValue); + #endif + material.sheenColor *= sheenColorTextureValue.rgb; + #endif + + material.sheenRoughness = max( u_sheenRoughness, 0.01 ); + + #ifdef HAS_SHEENROUGHNESSTEXTURE + material.sheenRoughness *= texture2D( u_sheenRoughnessTexture, v_uv ).a; + #endif + + material.sheenAttenuation = getSheenAlbedoScaling(material.sheenColor); + #else + material.sheenAttenuation = 1.0; + #endif + + material.opacity = baseColor.a; +} \ No newline at end of file diff --git a/packages/loader/src/gltf/extensions/KHR_materials_sheen.ts b/packages/loader/src/gltf/extensions/KHR_materials_sheen.ts index e69de29bb2..10cc8cb09f 100644 --- a/packages/loader/src/gltf/extensions/KHR_materials_sheen.ts +++ b/packages/loader/src/gltf/extensions/KHR_materials_sheen.ts @@ -0,0 +1,36 @@ +import { PBRMaterial } from "@oasis-engine/core"; +import { Color } from "@oasis-engine/math"; +import { GLTFResource } from "../GLTFResource"; +import { MaterialParser } from "../parser/MaterialParser"; +import { registerExtension } from "../parser/Parser"; +import { ExtensionParser } from "./ExtensionParser"; +import { IKHRMaterialsSheen } from "./Schema"; + +@registerExtension("KHR_materials_sheen") +class KHR_materials_sheen extends ExtensionParser { + parseEngineResource(schema: IKHRMaterialsSheen, material: PBRMaterial, context: GLTFResource): void { + const { textures } = context; + const { sheenColorFactor, sheenColorTexture, sheenRoughnessFactor = 0, sheenRoughnessTexture } = schema; + + if (sheenColorFactor) { + material.sheenEnabled = true; + material.sheenColor = new Color( + Color.linearToGammaSpace(sheenColorFactor[0]), + Color.linearToGammaSpace(sheenColorFactor[1]), + Color.linearToGammaSpace(sheenColorFactor[2]) + ); + } + + if (sheenColorTexture) { + material.sheenColorTexture = textures[sheenColorTexture.index]; + MaterialParser._parseTextureTransform(material, sheenColorTexture.extensions, context); + } + + material.sheenRoughness = sheenRoughnessFactor; + + if (sheenRoughnessTexture) { + material.sheenRoughnessTexture = textures[sheenRoughnessTexture.index]; + MaterialParser._parseTextureTransform(material, sheenRoughnessTexture.extensions, context); + } + } +} diff --git a/packages/loader/src/gltf/parser/MaterialParser.ts b/packages/loader/src/gltf/parser/MaterialParser.ts index e58f6a6d7c..6a9284b085 100644 --- a/packages/loader/src/gltf/parser/MaterialParser.ts +++ b/packages/loader/src/gltf/parser/MaterialParser.ts @@ -33,7 +33,8 @@ export class MaterialParser extends Parser { name = "" } = gltf.materials[i]; - const { KHR_materials_unlit, KHR_materials_pbrSpecularGlossiness, KHR_materials_clearcoat } = extensions; + const { KHR_materials_unlit, KHR_materials_pbrSpecularGlossiness, KHR_materials_clearcoat, KHR_materials_sheen } = + extensions; let material: UnlitMaterial | PBRMaterial | PBRSpecularMaterial = null; @@ -57,6 +58,10 @@ export class MaterialParser extends Parser { Parser.parseEngineResource("KHR_materials_clearcoat", KHR_materials_clearcoat, material, context); } + if (KHR_materials_sheen) { + Parser.parseEngineResource("KHR_materials_sheen", KHR_materials_sheen, material, context); + } + if (pbrMetallicRoughness) { const { baseColorFactor, baseColorTexture, metallicFactor, roughnessFactor, metallicRoughnessTexture } = pbrMetallicRoughness; From 8db3f5f378212c400d8c7e7dcf88c91bbcd89064 Mon Sep 17 00:00:00 2001 From: "shensi.zxd" Date: Tue, 15 Mar 2022 17:10:56 +0800 Subject: [PATCH 13/15] refactor: add sheen environment brdf approxmation --- .../core/src/shaderlib/pbr/ibl_frag_define.glsl | 13 ++++++++++++- packages/core/src/shaderlib/pbr/pbr_frag.glsl | 4 ++-- .../core/src/shaderlib/pbr/pbr_frag_define.glsl | 1 + packages/core/src/shaderlib/pbr/pbr_helper.glsl | 8 ++++---- 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/packages/core/src/shaderlib/pbr/ibl_frag_define.glsl b/packages/core/src/shaderlib/pbr/ibl_frag_define.glsl index 2b523ceefa..84f37e7921 100644 --- a/packages/core/src/shaderlib/pbr/ibl_frag_define.glsl +++ b/packages/core/src/shaderlib/pbr/ibl_frag_define.glsl @@ -75,4 +75,15 @@ vec3 getLightProbeRadiance(vec3 viewDir, vec3 normal, float roughness, int maxMI #endif -} \ No newline at end of file +} + +#ifdef SHEEN + // https://drive.google.com/file/d/1T0D1VSyR4AllqIJTQAraEIzjlb5h4FKH + float envBRDFApprox_Sheen( float dotNV, float roughness) { + float r2 = pow2(roughness); + float a = roughness < 0.25 ? -339.2 * r2 + 161.4 * roughness - 25.9 : -8.48 * r2 + 14.3 * roughness - 9.95; + float b = roughness < 0.25 ? 44.0 * r2 - 23.7 * roughness + 3.26 : 1.97 * r2 - 3.27 * roughness + 0.72; + float DG = exp( a * dotNV + b ) + ( roughness < 0.25 ? 0.0 : 0.1 * ( roughness - 0.25 ) ); + return saturate( DG ); + } +#endif \ No newline at end of file diff --git a/packages/core/src/shaderlib/pbr/pbr_frag.glsl b/packages/core/src/shaderlib/pbr/pbr_frag.glsl index c2d87b3083..f0899dbeab 100644 --- a/packages/core/src/shaderlib/pbr/pbr_frag.glsl +++ b/packages/core/src/shaderlib/pbr/pbr_frag.glsl @@ -31,8 +31,8 @@ vec3 radiance = getLightProbeRadiance(geometry.viewDir, geometry.normal, materia #endif #ifdef SHEEN - float sheenAlbedoScaling = getSheenAlbedoScaling(material.sheenColor); - reflectedLight.indirectSpecular += material.clearcoatAttenuation * radiance * envBRDFApprox(material.sheenColor, material.sheenRoughness, geometry.dotNV ); + vec3 sheenRadiance = getLightProbeRadiance(geometry.viewDir, geometry.normal, material.sheenRoughness, int(u_envMapLight.mipMapLevel), u_envMapLight.specularIntensity ); + reflectedLight.indirectSpecular += material.clearcoatAttenuation * sheenRadiance * material.sheenColor * material.sheenEnvBRDF; #endif // attenuation(total) = attenuation(clearcoat + sheen) diff --git a/packages/core/src/shaderlib/pbr/pbr_frag_define.glsl b/packages/core/src/shaderlib/pbr/pbr_frag_define.glsl index 4eea4a22a6..e9b539fdf1 100644 --- a/packages/core/src/shaderlib/pbr/pbr_frag_define.glsl +++ b/packages/core/src/shaderlib/pbr/pbr_frag_define.glsl @@ -104,6 +104,7 @@ struct Material { #ifdef SHEEN vec3 sheenColor; float sheenRoughness; + float sheenEnvBRDF; #endif }; diff --git a/packages/core/src/shaderlib/pbr/pbr_helper.glsl b/packages/core/src/shaderlib/pbr/pbr_helper.glsl index 8ce17dcfae..b90cbec10d 100644 --- a/packages/core/src/shaderlib/pbr/pbr_helper.glsl +++ b/packages/core/src/shaderlib/pbr/pbr_helper.glsl @@ -18,9 +18,8 @@ float getAARoughnessFactor(vec3 normal) { #endif } -float getSheenAlbedoScaling(vec3 sheenColor){ - // https://drive.google.com/file/d/1T0D1VSyR4AllqIJTQAraEIzjlb5h4FKH/view?usp=sharing - return 1.0 - 0.157 * max( max(sheenColor.r, sheenColor.g), sheenColor.b ); +float getSheenAlbedoScaling(vec3 sheenColor, float sheenEnvBRDF){ + return 1.0 - sheenEnvBRDF * max( max(sheenColor.r, sheenColor.g), sheenColor.b ); } void initGeometry(out Geometry geometry){ @@ -136,7 +135,8 @@ void initMaterial(out Material material, const in Geometry geometry){ material.sheenRoughness *= texture2D( u_sheenRoughnessTexture, v_uv ).a; #endif - material.sheenAttenuation = getSheenAlbedoScaling(material.sheenColor); + material.sheenEnvBRDF = envBRDFApprox_Sheen(geometry.dotNV, material.sheenRoughness ); + material.sheenAttenuation = getSheenAlbedoScaling(material.sheenColor, material.sheenEnvBRDF); #else material.sheenAttenuation = 1.0; #endif From c4b3f60697fd516b05ab27a8296b10fc8eca154a Mon Sep 17 00:00:00 2001 From: "shensi.zxd" Date: Wed, 16 Mar 2022 16:23:05 +0800 Subject: [PATCH 14/15] feat: support pbr ior --- packages/core/src/material/PBRBaseMaterial.ts | 14 ++++++++++++++ .../core/src/shaderlib/pbr/pbr_frag_define.glsl | 1 + packages/core/src/shaderlib/pbr/pbr_helper.glsl | 7 ++++++- .../src/gltf/extensions/KHR_materials_ior.ts | 14 ++++++++++++++ packages/loader/src/gltf/parser/MaterialParser.ts | 13 +++++++++++-- 5 files changed, 46 insertions(+), 3 deletions(-) diff --git a/packages/core/src/material/PBRBaseMaterial.ts b/packages/core/src/material/PBRBaseMaterial.ts index ddb60a3333..4ee8b51883 100644 --- a/packages/core/src/material/PBRBaseMaterial.ts +++ b/packages/core/src/material/PBRBaseMaterial.ts @@ -8,6 +8,7 @@ import { BaseMaterial } from "./BaseMaterial"; * PBR (Physically-Based Rendering) Material. */ export abstract class PBRBaseMaterial extends BaseMaterial { + private static _iorProp = Shader.getPropertyByName("u_ior"); private static _baseColorProp = Shader.getPropertyByName("u_baseColor"); private static _emissiveColorProp = Shader.getPropertyByName("u_emissiveColor"); private static _tilingOffsetProp = Shader.getPropertyByName("u_tilingOffset"); @@ -31,6 +32,18 @@ export abstract class PBRBaseMaterial extends BaseMaterial { private _sheenEnabled: boolean = false; + /** + * Index of refraction of the material, default 1.5 . + * @remarks It influence the F0 of dielectric materials. + */ + get ior(): number { + return this.shaderData.getFloat(PBRBaseMaterial._iorProp); + } + + set ior(value: number) { + this.shaderData.setFloat(PBRBaseMaterial._iorProp, value); + } + /** * Base color. */ @@ -330,6 +343,7 @@ export abstract class PBRBaseMaterial extends BaseMaterial { shaderData.enableMacro("O3_NEED_WORLDPOS"); shaderData.enableMacro("O3_NEED_TILINGOFFSET"); + shaderData.setFloat(PBRBaseMaterial._iorProp, 1.5); shaderData.setColor(PBRBaseMaterial._baseColorProp, new Color(1, 1, 1, 1)); shaderData.setColor(PBRBaseMaterial._emissiveColorProp, new Color(0, 0, 0, 1)); shaderData.setVector4(PBRBaseMaterial._tilingOffsetProp, new Vector4(1, 1, 0, 0)); diff --git a/packages/core/src/shaderlib/pbr/pbr_frag_define.glsl b/packages/core/src/shaderlib/pbr/pbr_frag_define.glsl index e9b539fdf1..3b45da3ac7 100644 --- a/packages/core/src/shaderlib/pbr/pbr_frag_define.glsl +++ b/packages/core/src/shaderlib/pbr/pbr_frag_define.glsl @@ -1,4 +1,5 @@ uniform float u_alphaCutoff; +uniform float u_ior; uniform vec4 u_baseColor; uniform float u_metal; uniform float u_roughness; diff --git a/packages/core/src/shaderlib/pbr/pbr_helper.glsl b/packages/core/src/shaderlib/pbr/pbr_helper.glsl index b90cbec10d..d79a226c38 100644 --- a/packages/core/src/shaderlib/pbr/pbr_helper.glsl +++ b/packages/core/src/shaderlib/pbr/pbr_helper.glsl @@ -22,6 +22,10 @@ float getSheenAlbedoScaling(vec3 sheenColor, float sheenEnvBRDF){ return 1.0 - sheenEnvBRDF * max( max(sheenColor.r, sheenColor.g), sheenColor.b ); } +float getF0(float ior, float outsideIor){ + return pow2( (ior - outsideIor) / (ior + outsideIor) ); +} + void initGeometry(out Geometry geometry){ geometry.position = v_pos; geometry.viewDir = normalize(u_cameraPos - v_pos); @@ -53,6 +57,7 @@ void initMaterial(out Material material, const in Geometry geometry){ vec3 specularColor = u_specularColor; float glossiness = u_glossiness; float alphaCutoff = u_alphaCutoff; + float F0 = getF0(u_ior, 1.0); #ifdef HAS_BASECOLORMAP vec4 baseTextureColor = texture2D(u_baseColorSampler, v_uv); @@ -91,7 +96,7 @@ void initMaterial(out Material material, const in Geometry geometry){ #ifdef IS_METALLIC_WORKFLOW material.diffuseColor = baseColor.rgb * ( 1.0 - metal ); - material.specularColor = mix( vec3( 0.04), baseColor.rgb, metal ); + material.specularColor = mix( vec3(F0), baseColor.rgb, metal ); material.roughness = roughness; #else float specularStrength = max( max( specularColor.r, specularColor.g ), specularColor.b ); diff --git a/packages/loader/src/gltf/extensions/KHR_materials_ior.ts b/packages/loader/src/gltf/extensions/KHR_materials_ior.ts index e69de29bb2..25e7a84d32 100644 --- a/packages/loader/src/gltf/extensions/KHR_materials_ior.ts +++ b/packages/loader/src/gltf/extensions/KHR_materials_ior.ts @@ -0,0 +1,14 @@ +import { PBRBaseMaterial } from "@oasis-engine/core"; +import { GLTFResource } from "../GLTFResource"; +import { registerExtension } from "../parser/Parser"; +import { ExtensionParser } from "./ExtensionParser"; +import { IKHRMaterialsIor } from "./Schema"; + +@registerExtension("KHR_materials_ior") +class KHR_materials_ior extends ExtensionParser { + parseEngineResource(schema: IKHRMaterialsIor, material: PBRBaseMaterial, context: GLTFResource): void { + const { ior = 1.5 } = schema; + + material.ior = ior; + } +} diff --git a/packages/loader/src/gltf/parser/MaterialParser.ts b/packages/loader/src/gltf/parser/MaterialParser.ts index 6a9284b085..1ce9ac7e3a 100644 --- a/packages/loader/src/gltf/parser/MaterialParser.ts +++ b/packages/loader/src/gltf/parser/MaterialParser.ts @@ -33,8 +33,13 @@ export class MaterialParser extends Parser { name = "" } = gltf.materials[i]; - const { KHR_materials_unlit, KHR_materials_pbrSpecularGlossiness, KHR_materials_clearcoat, KHR_materials_sheen } = - extensions; + const { + KHR_materials_unlit, + KHR_materials_pbrSpecularGlossiness, + KHR_materials_clearcoat, + KHR_materials_sheen, + KHR_materials_ior + } = extensions; let material: UnlitMaterial | PBRMaterial | PBRSpecularMaterial = null; @@ -62,6 +67,10 @@ export class MaterialParser extends Parser { Parser.parseEngineResource("KHR_materials_sheen", KHR_materials_sheen, material, context); } + if (KHR_materials_ior) { + Parser.parseEngineResource("KHR_materials_ior", KHR_materials_ior, material, context); + } + if (pbrMetallicRoughness) { const { baseColorFactor, baseColorTexture, metallicFactor, roughnessFactor, metallicRoughnessTexture } = pbrMetallicRoughness; From 23bf4587b83982161b112049ed4184be7e3edbd6 Mon Sep 17 00:00:00 2001 From: "shensi.zxd" Date: Wed, 16 Mar 2022 17:48:34 +0800 Subject: [PATCH 15/15] refactor: ior influence metallic-roughness workflow only --- packages/core/src/material/PBRBaseMaterial.ts | 14 ------------- packages/core/src/material/PBRMaterial.ts | 21 +++++++++++++++++-- .../src/gltf/extensions/KHR_materials_ior.ts | 4 ++-- 3 files changed, 21 insertions(+), 18 deletions(-) diff --git a/packages/core/src/material/PBRBaseMaterial.ts b/packages/core/src/material/PBRBaseMaterial.ts index 4ee8b51883..ddb60a3333 100644 --- a/packages/core/src/material/PBRBaseMaterial.ts +++ b/packages/core/src/material/PBRBaseMaterial.ts @@ -8,7 +8,6 @@ import { BaseMaterial } from "./BaseMaterial"; * PBR (Physically-Based Rendering) Material. */ export abstract class PBRBaseMaterial extends BaseMaterial { - private static _iorProp = Shader.getPropertyByName("u_ior"); private static _baseColorProp = Shader.getPropertyByName("u_baseColor"); private static _emissiveColorProp = Shader.getPropertyByName("u_emissiveColor"); private static _tilingOffsetProp = Shader.getPropertyByName("u_tilingOffset"); @@ -32,18 +31,6 @@ export abstract class PBRBaseMaterial extends BaseMaterial { private _sheenEnabled: boolean = false; - /** - * Index of refraction of the material, default 1.5 . - * @remarks It influence the F0 of dielectric materials. - */ - get ior(): number { - return this.shaderData.getFloat(PBRBaseMaterial._iorProp); - } - - set ior(value: number) { - this.shaderData.setFloat(PBRBaseMaterial._iorProp, value); - } - /** * Base color. */ @@ -343,7 +330,6 @@ export abstract class PBRBaseMaterial extends BaseMaterial { shaderData.enableMacro("O3_NEED_WORLDPOS"); shaderData.enableMacro("O3_NEED_TILINGOFFSET"); - shaderData.setFloat(PBRBaseMaterial._iorProp, 1.5); shaderData.setColor(PBRBaseMaterial._baseColorProp, new Color(1, 1, 1, 1)); shaderData.setColor(PBRBaseMaterial._emissiveColorProp, new Color(0, 0, 0, 1)); shaderData.setVector4(PBRBaseMaterial._tilingOffsetProp, new Vector4(1, 1, 0, 0)); diff --git a/packages/core/src/material/PBRMaterial.ts b/packages/core/src/material/PBRMaterial.ts index f14c649779..e1ddc11e25 100644 --- a/packages/core/src/material/PBRMaterial.ts +++ b/packages/core/src/material/PBRMaterial.ts @@ -10,6 +10,7 @@ export class PBRMaterial extends PBRBaseMaterial { private static _metallicProp = Shader.getPropertyByName("u_metal"); private static _roughnessProp = Shader.getPropertyByName("u_roughness"); private static _metallicRoughnessTextureProp = Shader.getPropertyByName("u_metallicRoughnessSampler"); + private static _iorProp = Shader.getPropertyByName("u_ior"); /** * Metallic, default 1. @@ -50,14 +51,30 @@ export class PBRMaterial extends PBRBaseMaterial { } } + /** + * Index of refraction of the material, default 1.5 . + * @remarks It influence the F0 of dielectric materials. + */ + get ior(): number { + return this.shaderData.getFloat(PBRMaterial._iorProp); + } + + set ior(value: number) { + this.shaderData.setFloat(PBRMaterial._iorProp, value); + } + /** * Create a pbr metallic-roughness workflow material instance. * @param engine - Engine to which the material belongs */ constructor(engine: Engine) { super(engine, Shader.find("pbr")); - this.shaderData.setFloat(PBRMaterial._metallicProp, 1); - this.shaderData.setFloat(PBRMaterial._roughnessProp, 1); + + const shaderData = this.shaderData; + + shaderData.setFloat(PBRMaterial._metallicProp, 1); + shaderData.setFloat(PBRMaterial._roughnessProp, 1); + shaderData.setFloat(PBRMaterial._iorProp, 1.5); } /** diff --git a/packages/loader/src/gltf/extensions/KHR_materials_ior.ts b/packages/loader/src/gltf/extensions/KHR_materials_ior.ts index 25e7a84d32..d81e0f1731 100644 --- a/packages/loader/src/gltf/extensions/KHR_materials_ior.ts +++ b/packages/loader/src/gltf/extensions/KHR_materials_ior.ts @@ -1,4 +1,4 @@ -import { PBRBaseMaterial } from "@oasis-engine/core"; +import { PBRMaterial } from "@oasis-engine/core"; import { GLTFResource } from "../GLTFResource"; import { registerExtension } from "../parser/Parser"; import { ExtensionParser } from "./ExtensionParser"; @@ -6,7 +6,7 @@ import { IKHRMaterialsIor } from "./Schema"; @registerExtension("KHR_materials_ior") class KHR_materials_ior extends ExtensionParser { - parseEngineResource(schema: IKHRMaterialsIor, material: PBRBaseMaterial, context: GLTFResource): void { + parseEngineResource(schema: IKHRMaterialsIor, material: PBRMaterial, context: GLTFResource): void { const { ior = 1.5 } = schema; material.ior = ior;