From 179bf03cafb024f5e9c1c035b6071ffaa30d9be0 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Mon, 25 Nov 2019 12:58:54 -0800 Subject: [PATCH] implement absorption --- samples/materials/sandboxLit.mat | 2 ++ shaders/src/common_lighting.fs | 5 ++++- shaders/src/light_indirect.fs | 28 ++++++++++++++++++++++------ shaders/src/material_inputs.fs | 8 ++++++-- shaders/src/shading_lit.fs | 8 ++++++++ 5 files changed, 42 insertions(+), 9 deletions(-) diff --git a/samples/materials/sandboxLit.mat b/samples/materials/sandboxLit.mat index abac5d3d74..0bf58f75a7 100644 --- a/samples/materials/sandboxLit.mat +++ b/samples/materials/sandboxLit.mat @@ -38,6 +38,8 @@ material { fragment { void material(inout MaterialInputs material) { prepareMaterial(material); + //material.absorption = -log(vec3(1.0, 0.7, 0.1)) / 4.0; + //material.thickness = 1.0; material.baseColor.rgb = materialParams.baseColor; material.roughness = materialParams.roughness; material.metallic = materialParams.metallic; diff --git a/shaders/src/common_lighting.fs b/shaders/src/common_lighting.fs index 259b703f64..5346ddc513 100644 --- a/shaders/src/common_lighting.fs +++ b/shaders/src/common_lighting.fs @@ -25,8 +25,10 @@ struct PixelParams { float anisotropy; #endif -#if defined(SHADING_MODEL_SUBSURFACE) +#if defined(SHADING_MODEL_SUBSURFACE) || defined(HAS_REFRACTION) float thickness; +#endif +#if defined(SHADING_MODEL_SUBSURFACE) vec3 subsurfaceColor; float subsurfacePower; #endif @@ -38,6 +40,7 @@ struct PixelParams { #if defined(HAS_REFRACTION) float eta; float transmission; + vec3 absorption; #endif }; diff --git a/shaders/src/light_indirect.fs b/shaders/src/light_indirect.fs index 1f138df766..10d8d21179 100644 --- a/shaders/src/light_indirect.fs +++ b/shaders/src/light_indirect.fs @@ -333,9 +333,13 @@ void evaluateSubsurfaceIBL(const PixelParams pixel, const vec3 diffuseIrradiance } #if defined(HAS_REFRACTION) -void applyRefraction(const PixelParams pixel, const vec3 n, vec3 Fd, vec3 Fr, inout vec3 color) { - float eta = pixel.eta; - vec3 v = -shading_view; +void applyRefraction(const PixelParams pixel, const vec3 n0, vec3 Fd, vec3 Fr, inout vec3 color) { + float eta0 = pixel.eta; + vec3 r = -shading_view; + +#if defined(MATERIAL_HAS_ABSORPTION) && !defined(MATERIAL_HAS_THICKNESS) + vec3 T = 1.0 - pixel.absorption; +#endif // for a sphere, with local refraction (i.e. screen space) //const float thickness = 1.0; @@ -354,9 +358,16 @@ void applyRefraction(const PixelParams pixel, const vec3 n, vec3 Fd, vec3 Fr, in //vec3 p = d * r; // sample screen space here // for a sphere, with light at infinity (i.e. cubemap) - vec3 r = refract(v, n, eta); - vec3 n2 = -normalize(dot(-n, r) * r + n * 0.5); - r = refract(r, n2, 1.0 / eta); + r = refract(r, n0, eta0); + +#if defined(MATERIAL_HAS_ABSORPTION) && defined(MATERIAL_HAS_THICKNESS) + float d = pixel.thickness * dot(-n0, r); + vec3 T = exp(-pixel.absorption * d); +#endif + + vec3 n1 = -normalize(dot(-n0, r) * r + n0 * 0.5); + float eta1 = 1.0 / eta0; + r = refract(r, n1, eta1); // for a slab, with light at infinity (i.e. cubemap) // r = refract(v, n, eta); @@ -366,6 +377,11 @@ void applyRefraction(const PixelParams pixel, const vec3 n, vec3 Fd, vec3 Fr, in // when reading from the cubemap, we are not pre-exposed so we apply iblLuminance // which is not the case when we'll read from the screen-space buffer vec3 Ft = prefilteredRadiance(r, pixel.perceptualRoughness) * frameUniforms.iblLuminance; + +#if defined(MATERIAL_HAS_ABSORPTION) + Ft *= T; +#endif + Fr *= frameUniforms.iblLuminance; Fd *= frameUniforms.iblLuminance; diff --git a/shaders/src/material_inputs.fs b/shaders/src/material_inputs.fs index 58e441d6f9..b1a3907816 100644 --- a/shaders/src/material_inputs.fs +++ b/shaders/src/material_inputs.fs @@ -29,8 +29,10 @@ struct MaterialInputs { float anisotropy; vec3 anisotropyDirection; -#if defined(SHADING_MODEL_SUBSURFACE) +#if defined(SHADING_MODEL_SUBSURFACE) || defined(HAS_REFRACTION) float thickness; +#endif +#if defined(SHADING_MODEL_SUBSURFACE) float subsurfacePower; vec3 subsurfaceColor; #endif @@ -92,8 +94,10 @@ void initMaterial(out MaterialInputs material) { material.anisotropyDirection = vec3(1.0, 0.0, 0.0); #endif -#if defined(SHADING_MODEL_SUBSURFACE) +#if defined(SHADING_MODEL_SUBSURFACE) || defined(HAS_REFRACTION) material.thickness = 0.5; +#endif +#if defined(SHADING_MODEL_SUBSURFACE) material.subsurfacePower = 12.234; material.subsurfaceColor = vec3(1.0); #endif diff --git a/shaders/src/shading_lit.fs b/shaders/src/shading_lit.fs index 266f3ed962..878c102d2c 100644 --- a/shaders/src/shading_lit.fs +++ b/shaders/src/shading_lit.fs @@ -91,6 +91,14 @@ void getCommonPixelParams(const MaterialInputs material, inout PixelParams pixel #else pixel.transmission = 1.0; #endif +#if defined(MATERIAL_HAS_ABSORPTION) + pixel.absorption = saturate(material.absorption); +#else + pixel.absorption = vec3(0.0); +#endif +#if defined(MATERIAL_HAS_THICKNESS) + pixel.thickness = max(0.0, material.thickness); +#endif #endif }