From 809165ee0f0ceb096720b6cdfeeea56cfb9df7b4 Mon Sep 17 00:00:00 2001 From: Jim Eckerlein Date: Wed, 18 Nov 2020 11:41:31 +0100 Subject: [PATCH] Re-enable transmission --- src/material.js | 25 +++++++++++++++++++++++++ src/rendering_parameters.js | 1 + src/shaders/functions.glsl | 6 ++++++ src/shaders/ibl.glsl | 25 +++++++++++++++++++++++++ src/shaders/pbr.frag | 35 +++++++++++++++++++++++++++++++++++ src/shaders/punctual.glsl | 14 ++++++++++++++ 6 files changed, 106 insertions(+) diff --git a/src/material.js b/src/material.js index 9abdd67a..bf9cd5a0 100644 --- a/src/material.js +++ b/src/material.js @@ -335,6 +335,21 @@ class gltfMaterial extends GltfObject this.properties.set("u_SheenColorFactor", sheenColor); this.properties.set("u_SheenRoughness", sheenRoughness); } + + // KHR Extension: Transmission + if (this.extensions.KHR_materials_transmission !== undefined) + { + let transmission = this.extensions.KHR_materials_transmission.transmission; + + if (transmission === undefined) + { + transmission = 0.0; + } + + this.defines.push("MATERIAL_TRANSMISSION 1"); + + this.properties.set("u_Transmission", transmission); + } } initGlForMembers(this, gltf); @@ -404,6 +419,11 @@ class gltfMaterial extends GltfObject { this.fromJsonSheen(jsonExtensions.KHR_materials_sheen); } + + if(jsonExtensions.KHR_materials_transmission !== undefined) + { + this.fromJsonTransmission(jsonExtensions.KHR_materials_transmission); + } } fromJsonMetallicRoughness(jsonMetallicRoughness) @@ -473,6 +493,11 @@ class gltfMaterial extends GltfObject this.colorIntensityTexture = colorIntensityTexture; } } + + fromJsonTransmission(jsonTransmission) + { + jsonTransmission; + } } export { gltfMaterial }; diff --git a/src/rendering_parameters.js b/src/rendering_parameters.js index e47c3e1e..272d7ae5 100644 --- a/src/rendering_parameters.js +++ b/src/rendering_parameters.js @@ -60,6 +60,7 @@ const DebugOutput = SPECULAR: "Specular", CLEARCOAT: "ClearCoat", SHEEN: "Sheen", + TRANSMISSION: "Transmission", ALPHA: "Alpha", F0: "F0" }; diff --git a/src/shaders/functions.glsl b/src/shaders/functions.glsl index 3bd2f133..f070bd66 100644 --- a/src/shaders/functions.glsl +++ b/src/shaders/functions.glsl @@ -44,3 +44,9 @@ float clampedDot(vec3 x, vec3 y) { return clamp(dot(x, y), 0.0, 1.0); } + +vec3 transmissionAbsorption(vec3 v, vec3 n, float ior, float thickness, vec3 absorptionColor) +{ + vec3 r = refract(-v, n, 1.0 / ior); + return exp(-absorptionColor * thickness * dot(-n, r)); +} diff --git a/src/shaders/ibl.glsl b/src/shaders/ibl.glsl index b6892ffe..9019e1d8 100644 --- a/src/shaders/ibl.glsl +++ b/src/shaders/ibl.glsl @@ -18,6 +18,31 @@ vec3 getIBLRadianceGGX(vec3 n, vec3 v, float perceptualRoughness, vec3 specularC return specularLight * (specularColor * brdf.x + brdf.y); } +vec3 getIBLRadianceTransmission(vec3 n, vec3 v, float perceptualRoughness, float ior, vec3 baseColor) +{ + // Sample GGX LUT. + float NdotV = clampedDot(n, v); + vec2 brdfSamplePoint = clamp(vec2(NdotV, perceptualRoughness), vec2(0.0, 0.0), vec2(1.0, 1.0)); + vec2 brdf = texture(u_GGXLUT, brdfSamplePoint).rg; + + // Sample GGX environment map. + float lod = clamp(perceptualRoughness * float(u_MipCount), 0.0, float(u_MipCount)); + + // Approximate double refraction by assuming a solid sphere beneath the point. + vec3 r = refract(-v, n, 1.0 / ior); + vec3 m = 2.0 * dot(-n, r) * r + n; + vec3 rr = -refract(-r, m, ior); + + vec4 specularSample = textureLod(u_GGXEnvSampler, rr, lod); + vec3 specularLight = specularSample.rgb; + +#ifndef USE_HDR + specularLight = sRGBToLinear(specularLight); +#endif + + return specularLight * (brdf.x + brdf.y); +} + vec3 getIBLRadianceLambertian(vec3 n, vec3 diffuseColor) { vec3 diffuseLight = texture(u_LambertianEnvSampler, n).rgb; diff --git a/src/shaders/pbr.frag b/src/shaders/pbr.frag index e259c680..fa796999 100644 --- a/src/shaders/pbr.frag +++ b/src/shaders/pbr.frag @@ -48,6 +48,9 @@ uniform float u_SheenRoughness; uniform float u_ClearcoatFactor; uniform float u_ClearcoatRoughnessFactor; +// Transmission +uniform float u_Transmission; + // Alpha mode uniform float u_AlphaCutoff; @@ -76,6 +79,8 @@ struct MaterialInfo float clearcoatFactor; vec3 clearcoatNormal; float clearcoatRoughness; + + float transmission; }; // Get normal, tangent and bitangent vectors. @@ -207,6 +212,14 @@ MaterialInfo getSheenInfo(MaterialInfo info) return info; } +#ifdef MATERIAL_TRANSMISSION +MaterialInfo getTransmissionInfo(MaterialInfo info) +{ + info.transmission = u_Transmission; + return info; +} +#endif + MaterialInfo getClearCoatInfo(MaterialInfo info, NormalInfo normalInfo) { info.clearcoatFactor = u_ClearcoatFactor; @@ -282,6 +295,9 @@ void main() materialInfo = getClearCoatInfo(materialInfo, normalInfo); #endif +#ifdef MATERIAL_TRANSMISSION + materialInfo = getTransmissionInfo(materialInfo); +#endif materialInfo.perceptualRoughness = clamp(materialInfo.perceptualRoughness, 0.0, 1.0); materialInfo.metallic = clamp(materialInfo.metallic, 0.0, 1.0); @@ -303,6 +319,7 @@ void main() vec3 f_emissive = vec3(0.0); vec3 f_clearcoat = vec3(0.0); vec3 f_sheen = vec3(0.0); + vec3 f_transmission = vec3(0.0); // Calculate lighting contribution from image based lighting source (IBL) #ifdef USE_IBL @@ -325,6 +342,10 @@ void main() f_diffuse = mix(f_diffuse, f_diffuse * ao, u_OcclusionStrength); #endif +#ifdef MATERIAL_TRANSMISSION + f_transmission += getIBLRadianceTransmission(n, v, materialInfo.perceptualRoughness, ior, materialInfo.baseColor); +#endif + #ifdef USE_PUNCTUAL for (int i = 0; i < LIGHT_COUNT; ++i) { @@ -377,6 +398,10 @@ void main() materialInfo.clearcoatF0, materialInfo.clearcoatF90, materialInfo.clearcoatRoughness); #endif } + + #ifdef MATERIAL_TRANSMISSION + f_transmission += intensity * getPunctualRadianceTransmission(n, v, l, materialInfo.alphaRoughness, ior, materialInfo.f0); + #endif } #endif // !USE_PUNCTUAL @@ -399,6 +424,12 @@ void main() clearcoatFresnel = F_Schlick(materialInfo.clearcoatF0, materialInfo.clearcoatF90, clampedDot(materialInfo.clearcoatNormal, v)); #endif + #ifdef MATERIAL_TRANSMISSION + vec3 diffuse = mix(f_diffuse, f_transmission, materialInfo.transmission); + #else + vec3 diffuse = f_diffuse; + #endif + color = (f_emissive + f_diffuse + f_specular + (1.0 - reflectance) * f_sheen) * (1.0 - clearcoatFactor * clearcoatFresnel) + f_clearcoat * clearcoatFactor; #ifndef DEBUG_OUTPUT // no debug @@ -485,6 +516,10 @@ void main() g_finalColor.rgb = vec3(baseColor.a); #endif + + #ifdef DEBUG_FTRANSMISSION + g_finalColor.rgb = linearTosRGB(f_transmission); + #endif g_finalColor.a = 1.0; #endif // !DEBUG_OUTPUT diff --git a/src/shaders/punctual.glsl b/src/shaders/punctual.glsl index c999f2be..e85c27e3 100644 --- a/src/shaders/punctual.glsl +++ b/src/shaders/punctual.glsl @@ -47,6 +47,20 @@ float getSpotAttenuation(vec3 pointToLight, vec3 spotDirection, float outerConeC return 0.0; } + +vec3 getPunctualRadianceTransmission(vec3 n, vec3 v, vec3 l, float alphaRoughness, float ior, vec3 f0) +{ + vec3 r = refract(-v, n, 1.0 / ior); + vec3 h = normalize(l - r); + float NdotL = clampedDot(-n, l); + float NdotV = clampedDot(n, -r); + + float Vis = V_GGX(clampedDot(-n, l), NdotV, alphaRoughness); + float D = D_GGX(clampedDot(r, l), alphaRoughness); + + return NdotL * f0 * Vis * D; +} + vec3 getPunctualRadianceClearCoat(vec3 clearcoatNormal, vec3 v, vec3 l, vec3 h, float VdotH, vec3 f0, vec3 f90, float clearcoatRoughness) { float NdotL = clampedDot(clearcoatNormal, l);