From 9f39644199e89e1f16b3e89624f84656f512fe58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Garc=C3=ADa=20Li=C3=B1=C3=A1n?= Date: Thu, 26 Aug 2021 22:51:46 +0200 Subject: [PATCH] HDR: Optimize the G-Buffer and do not separate the occlusion texture - The G-Buffer layout has been redesigned to be 96 bits per pixel. There are 24 unused bits that can be used for extra material parameters later (like clearcoat). - Add better debug views for the G-Buffer. - Use octahedron normal encoding. This yields the same results as the previous method but uses 16 bits less. - Use rg11fb10f for the environment mapping cubemaps. - Tweak the shadow mapping parameters and add a colored debug mode. - Only render shadow maps for objects that inherit from model-default.eff or model-pbr.eff instead of having a fallback Effect. Now transparent objects should be ignored (if they are marked as such with model-transparent or similar). - Remove the separate occlusion texture. Now the PBR Effect expects a single texture where R=occlusion, G=roughness and B=metallic. --- Compositor/HDR/hdr.xml | 146 +++++++++++++++------- Effects/HDR/ao.eff | 4 +- Effects/HDR/gbuffer-debug-clear.eff | 12 ++ Effects/HDR/gbuffer-debug-color.eff | 17 +++ Effects/HDR/gbuffer-debug-matid.eff | 17 +++ Effects/HDR/gbuffer-debug-normal.eff | 17 +++ Effects/HDR/gbuffer-debug-orm.eff | 27 ++++ Effects/HDR/lighting.eff | 8 ++ Effects/model-default.eff | 17 +++ Effects/model-pbr-transparent.eff | 18 +-- Effects/model-pbr.eff | 43 ++++--- Effects/schemes.xml | 12 -- Shaders/HDR/ao.frag | 14 ++- Shaders/HDR/gbuffer-debug-clear.frag | 12 ++ Shaders/HDR/gbuffer-debug-color.frag | 12 ++ Shaders/HDR/gbuffer-debug-matid.frag | 12 ++ Shaders/HDR/gbuffer-debug-normal.frag | 12 ++ Shaders/HDR/gbuffer-debug-orm.frag | 17 +++ Shaders/HDR/gbuffer-include.frag | 34 ++--- Shaders/HDR/geometry-chrome.frag | 19 ++- Shaders/HDR/geometry-combined.frag | 21 ++-- Shaders/HDR/geometry-pbr-transparent.frag | 15 +-- Shaders/HDR/geometry-pbr.frag | 35 +++--- Shaders/HDR/geometry-shadow.frag | 11 +- Shaders/HDR/geometry-shadow.vert | 4 - Shaders/HDR/geometry-transparent.frag | 9 +- Shaders/HDR/geometry-water.frag | 9 +- Shaders/HDR/geometry.frag | 23 ++-- Shaders/HDR/lighting-include.frag | 20 +-- Shaders/HDR/lighting.frag | 39 +++--- Shaders/HDR/shadows-include.frag | 71 ++++++++--- Shaders/HDR/water-lighting.frag | 11 +- Shaders/HDR/ws30.frag | 21 ++-- defaults.xml | 3 +- 34 files changed, 509 insertions(+), 253 deletions(-) create mode 100644 Effects/HDR/gbuffer-debug-clear.eff create mode 100644 Effects/HDR/gbuffer-debug-color.eff create mode 100644 Effects/HDR/gbuffer-debug-matid.eff create mode 100644 Effects/HDR/gbuffer-debug-normal.eff create mode 100644 Effects/HDR/gbuffer-debug-orm.eff create mode 100644 Shaders/HDR/gbuffer-debug-clear.frag create mode 100644 Shaders/HDR/gbuffer-debug-color.frag create mode 100644 Shaders/HDR/gbuffer-debug-matid.frag create mode 100644 Shaders/HDR/gbuffer-debug-normal.frag create mode 100644 Shaders/HDR/gbuffer-debug-orm.frag diff --git a/Compositor/HDR/hdr.xml b/Compositor/HDR/hdr.xml index d5b0d7e38..9a790fa06 100644 --- a/Compositor/HDR/hdr.xml +++ b/Compositor/HDR/hdr.xml @@ -7,29 +7,42 @@ true gbuffer0 2d screen screen - rgba8 + rgb10-a2 gbuffer1 2d screen screen - rg16f + rgba8 gbuffer2 @@ -116,7 +129,7 @@ cubemap 128 128 - rgb16f + r11f-g11f-b10f linear-mipmap-linear linear clamp-to-edge @@ -128,7 +141,7 @@ cubemap 128 128 - rgb16f + r11f-g11f-b10f linear-mipmap-linear linear clamp-to-edge @@ -157,7 +170,7 @@ 2d 1024 1024 - r16f + r32f linear-mipmap-nearest nearest 10 @@ -167,7 +180,7 @@ 2d 1 1 - r16f + r32f nearest nearest @@ -176,7 +189,7 @@ 2d 1 1 - r16f + r32f nearest nearest @@ -260,6 +273,31 @@ + + + debug-clear-gbuffer + quad + Effects/HDR/gbuffer-debug-clear + + /sim/rendering/hdr/debug/show-gbuffer + + + color0 + gbuffer0 + + + color1 + gbuffer1 + + + color2 + gbuffer2 + + + - debug-albedo - Effects/HDR/trivial + debug-color + Effects/HDR/gbuffer-debug-color 0.0 0.0 0.2 0.2 - - 0 - gbuffer0 - - - - debug-normals - Effects/HDR/trivial - - 0.8 - 0.0 - 0.2 - 0.2 - 0 gbuffer1 - debug-materials - Effects/HDR/trivial + debug-normals + Effects/HDR/gbuffer-debug-normal + + 0.8 + 0.0 + 0.2 + 0.2 + + + 0 + gbuffer0 + + + + debug-orm + Effects/HDR/gbuffer-debug-orm 0.0 0.8 @@ -1236,9 +1274,31 @@ 0 + gbuffer0 + + + 1 + gbuffer1 + + + 2 gbuffer2 + + debug-matid + Effects/HDR/gbuffer-debug-matid + + 0.0 + 0.57 + 0.2 + 0.2 + + + 0 + gbuffer0 + + debug-depth Effects/HDR/visualize-depth diff --git a/Effects/HDR/ao.eff b/Effects/HDR/ao.eff index a6bc1892f..50d81703b 100644 --- a/Effects/HDR/ao.eff +++ b/Effects/HDR/ao.eff @@ -9,12 +9,12 @@ Shaders/HDR/gbuffer-include.frag - depth_tex + gbuffer0_tex sampler-2d 0 - normal_tex + depth_tex sampler-2d 1 diff --git a/Effects/HDR/gbuffer-debug-clear.eff b/Effects/HDR/gbuffer-debug-clear.eff new file mode 100644 index 000000000..96f9b43fd --- /dev/null +++ b/Effects/HDR/gbuffer-debug-clear.eff @@ -0,0 +1,12 @@ + + + Effects/HDR/gbuffer-debug-clear + + + + Shaders/HDR/trivial.vert + Shaders/HDR/gbuffer-debug-clear.frag + + + + diff --git a/Effects/HDR/gbuffer-debug-color.eff b/Effects/HDR/gbuffer-debug-color.eff new file mode 100644 index 000000000..871244348 --- /dev/null +++ b/Effects/HDR/gbuffer-debug-color.eff @@ -0,0 +1,17 @@ + + + Effects/HDR/gbuffer-debug-color + + + + Shaders/HDR/trivial.vert + Shaders/HDR/gbuffer-debug-color.frag + + + gbuffer1_tex + sampler-2d + 0 + + + + diff --git a/Effects/HDR/gbuffer-debug-matid.eff b/Effects/HDR/gbuffer-debug-matid.eff new file mode 100644 index 000000000..8df7ebe07 --- /dev/null +++ b/Effects/HDR/gbuffer-debug-matid.eff @@ -0,0 +1,17 @@ + + + Effects/HDR/gbuffer-debug-matid + + + + Shaders/HDR/trivial.vert + Shaders/HDR/gbuffer-debug-matid.frag + + + gbuffer0_tex + sampler-2d + 0 + + + + diff --git a/Effects/HDR/gbuffer-debug-normal.eff b/Effects/HDR/gbuffer-debug-normal.eff new file mode 100644 index 000000000..804f18830 --- /dev/null +++ b/Effects/HDR/gbuffer-debug-normal.eff @@ -0,0 +1,17 @@ + + + Effects/HDR/gbuffer-debug-normal + + + + Shaders/HDR/trivial.vert + Shaders/HDR/gbuffer-debug-normal.frag + + + gbuffer0_tex + sampler-2d + 0 + + + + diff --git a/Effects/HDR/gbuffer-debug-orm.eff b/Effects/HDR/gbuffer-debug-orm.eff new file mode 100644 index 000000000..88efaf252 --- /dev/null +++ b/Effects/HDR/gbuffer-debug-orm.eff @@ -0,0 +1,27 @@ + + + Effects/HDR/gbuffer-debug-orm + + + + Shaders/HDR/trivial.vert + Shaders/HDR/gbuffer-debug-orm.frag + + + gbuffer0_tex + sampler-2d + 0 + + + gbuffer1_tex + sampler-2d + 1 + + + gbuffer2_tex + sampler-2d + 2 + + + + diff --git a/Effects/HDR/lighting.eff b/Effects/HDR/lighting.eff index 7f37913fa..2facb399a 100644 --- a/Effects/HDR/lighting.eff +++ b/Effects/HDR/lighting.eff @@ -11,6 +11,9 @@ clamp-to-edge normalized + + /sim/rendering/hdr/debug/show-shadow-cascades + @@ -61,6 +64,11 @@ sampler-2d 7 + + debug_shadow_cascades + bool + show-shadow-cascades + shadow_tex diff --git a/Effects/model-default.eff b/Effects/model-default.eff index c77024a0d..f93f37d0c 100644 --- a/Effects/model-default.eff +++ b/Effects/model-default.eff @@ -699,4 +699,21 @@ + + hdr-shadow + + 0 0 0 0 + back + 0 + + 1.1 + 4.0 + + + Shaders/HDR/geometry-shadow.vert + Shaders/HDR/geometry-shadow.frag + + + + diff --git a/Effects/model-pbr-transparent.eff b/Effects/model-pbr-transparent.eff index dde0e6068..cfece1d81 100644 --- a/Effects/model-pbr-transparent.eff +++ b/Effects/model-pbr-transparent.eff @@ -68,15 +68,6 @@ texture[3]/wrap-s texture[3]/wrap-t - - 4 - texture[4]/type - texture[4]/image - texture[4]/filter - texture[4]/mag-filter - texture[4]/wrap-s - texture[4]/wrap-t - 8 texture[8]/image @@ -117,19 +108,14 @@ 1 - metallic_roughness_tex + orm_tex sampler-2d 2 - - occlusion_tex - sampler-2d - 3 - emissive_tex sampler-2d - 4 + 3 base_color_factor diff --git a/Effects/model-pbr.eff b/Effects/model-pbr.eff index 54e84d219..ecaf5b05f 100644 --- a/Effects/model-pbr.eff +++ b/Effects/model-pbr.eff @@ -12,18 +12,14 @@ null-normalmap - + white 1.0 1.0 - - - white - - + white 0.0 0.0 0.0 @@ -88,15 +84,6 @@ texture[3]/wrap-s texture[3]/wrap-t - - 4 - texture[4]/type - texture[4]/image - texture[4]/filter - texture[0]/mag-filter - texture[4]/wrap-s - texture[4]/wrap-t - 0 opaque cull-face @@ -124,19 +111,14 @@ 1 - metallic_roughness_tex + orm_tex sampler-2d 2 - - occlusion_tex - sampler-2d - 3 - emissive_tex sampler-2d - 4 + 3 base_color_factor @@ -165,4 +147,21 @@ + + + hdr-shadow + + 0 0 0 0 + back + 0 + + 1.1 + 4.0 + + + Shaders/HDR/geometry-shadow.vert + Shaders/HDR/geometry-shadow.frag + + + diff --git a/Effects/schemes.xml b/Effects/schemes.xml index da6655ddc..556ff2066 100644 --- a/Effects/schemes.xml +++ b/Effects/schemes.xml @@ -5,16 +5,4 @@ classic-shadow Effects/Fallback/classic-shadow - - - - - hdr-shadow - Effects/Fallback/hdr-shadow - diff --git a/Shaders/HDR/ao.frag b/Shaders/HDR/ao.frag index d96d6a9c7..cef44289d 100644 --- a/Shaders/HDR/ao.frag +++ b/Shaders/HDR/ao.frag @@ -5,8 +5,8 @@ out float fragColor; in vec2 texCoord; +uniform sampler2D gbuffer0_tex; uniform sampler2D depth_tex; -uniform sampler2D normal_tex; uniform mat4 fg_ProjectionMatrix; @@ -22,11 +22,11 @@ const vec2 kernel[4] = vec2[]( vec2( 0.0, -1.0), // bottom vec2(-1.0, 0.0)); // left +vec3 decodeNormal(vec2 f); vec3 positionFromDepth(vec2 pos, float depth); -vec3 decodeNormal(vec2 enc); float rand(vec2 co) { - return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453); + return fract(sin(dot(co.xy, vec2(12.9898,78.233))) * 43758.5453); } float sampleAO(vec3 fragPos, vec3 normal, vec2 coords) @@ -46,10 +46,12 @@ float sampleAO(vec3 fragPos, vec3 normal, vec2 coords) void main() { - float fragDepth = texture(depth_tex, texCoord).r; - vec3 fragPos = positionFromDepth(texCoord, fragDepth); + vec4 gbuffer0 = texture(gbuffer0_tex, texCoord); + float depth = texture(depth_tex, texCoord).r; - vec3 normal = normalize(decodeNormal(texture(normal_tex, texCoord).rg)); + vec3 normal = decodeNormal(gbuffer0.rg); + + vec3 fragPos = positionFromDepth(texCoord, depth); vec2 randomVec = normalize(vec2(rand(texCoord) * 2.0 - 1.0, rand(texCoord+1.0) * 2.0 - 1.0)); diff --git a/Shaders/HDR/gbuffer-debug-clear.frag b/Shaders/HDR/gbuffer-debug-clear.frag new file mode 100644 index 000000000..43cceed68 --- /dev/null +++ b/Shaders/HDR/gbuffer-debug-clear.frag @@ -0,0 +1,12 @@ +#version 330 core + +layout(location = 0) out vec4 outGBuffer0; +layout(location = 1) out vec4 outGBuffer1; +layout(location = 2) out vec4 outGBuffer2; + +void main() +{ + outGBuffer0 = vec4(0.0); + outGBuffer1 = vec4(0.0); + outGBuffer2 = vec4(0.0); +} diff --git a/Shaders/HDR/gbuffer-debug-color.frag b/Shaders/HDR/gbuffer-debug-color.frag new file mode 100644 index 000000000..0bfee3bb7 --- /dev/null +++ b/Shaders/HDR/gbuffer-debug-color.frag @@ -0,0 +1,12 @@ +#version 330 core + +out vec4 fragColor; + +in vec2 texCoord; + +uniform sampler2D gbuffer1_tex; + +void main() +{ + fragColor = vec4(texture(gbuffer1_tex, texCoord).rgb, 1.0); +} diff --git a/Shaders/HDR/gbuffer-debug-matid.frag b/Shaders/HDR/gbuffer-debug-matid.frag new file mode 100644 index 000000000..0fb1ae95f --- /dev/null +++ b/Shaders/HDR/gbuffer-debug-matid.frag @@ -0,0 +1,12 @@ +#version 330 core + +out vec4 fragColor; + +in vec2 texCoord; + +uniform sampler2D gbuffer0_tex; + +void main() +{ + fragColor = vec4(vec3(texture(gbuffer0_tex, texCoord).a), 1.0); +} diff --git a/Shaders/HDR/gbuffer-debug-normal.frag b/Shaders/HDR/gbuffer-debug-normal.frag new file mode 100644 index 000000000..39a61206b --- /dev/null +++ b/Shaders/HDR/gbuffer-debug-normal.frag @@ -0,0 +1,12 @@ +#version 330 core + +out vec4 fragColor; + +in vec2 texCoord; + +uniform sampler2D gbuffer0_tex; + +void main() +{ + fragColor = vec4(texture(gbuffer0_tex, texCoord).rg, 0.0, 1.0); +} diff --git a/Shaders/HDR/gbuffer-debug-orm.frag b/Shaders/HDR/gbuffer-debug-orm.frag new file mode 100644 index 000000000..42f6c0122 --- /dev/null +++ b/Shaders/HDR/gbuffer-debug-orm.frag @@ -0,0 +1,17 @@ +#version 330 core + +out vec4 fragColor; + +in vec2 texCoord; + +uniform sampler2D gbuffer0_tex; +uniform sampler2D gbuffer1_tex; +uniform sampler2D gbuffer2_tex; + +void main() +{ + fragColor = vec4(texture(gbuffer2_tex, texCoord).a, + texture(gbuffer0_tex, texCoord).b, + texture(gbuffer1_tex, texCoord).a, + 1.0); +} diff --git a/Shaders/HDR/gbuffer-include.frag b/Shaders/HDR/gbuffer-include.frag index de3266427..d6d6426e3 100644 --- a/Shaders/HDR/gbuffer-include.frag +++ b/Shaders/HDR/gbuffer-include.frag @@ -3,24 +3,30 @@ uniform mat4 fg_ProjectionMatrixInverse; uniform vec2 fg_NearFar; -// https://aras-p.info/texts/CompactNormalStorage.html -// Method #4: Spheremap Transform -// Lambert Azimuthal Equal-Area projection -vec2 encodeNormal(vec3 n) +// Octahedron normal encoding +// https://knarkowicz.wordpress.com/2014/04/16/octahedron-normal-vector-encoding/ +vec2 msign(vec2 v) { - float p = sqrt(n.z * 8.0 + 8.0); - return vec2(n.xy / p + 0.5); + return vec2((v.x >= 0.0) ? 1.0 : -1.0, + (v.y >= 0.0) ? 1.0 : -1.0); } -vec3 decodeNormal(vec2 enc) +vec2 encodeNormal(vec3 n) { - vec2 fenc = enc * 4.0 - 2.0; - float f = dot(fenc, fenc); - float g = sqrt(1.0 - f * 0.25); - vec3 n; - n.xy = fenc * g; - n.z = 1.0 - f * 0.5; - return n; + n /= (abs(n.x) + abs(n.y) + abs(n.z)); + n.xy = (n.z >= 0) ? n.xy : (1.0 - abs(n.yx)) * msign(n.xy); + n.xy = n.xy * 0.5 + 0.5; + return n.xy; +} + +vec3 decodeNormal(vec2 f) +{ + f = f * 2.0 - 1.0; + vec3 n = vec3(f, 1.0 - abs(f.x) - abs(f.y)); + float t = max(-n.z, 0.0); + n.x += (n.x > 0.0) ? -t : t; + n.y += (n.y > 0.0) ? -t : t; + return normalize(n); } // Given a 2D coordinate in the range [0,1] and a depth value from a depth diff --git a/Shaders/HDR/geometry-chrome.frag b/Shaders/HDR/geometry-chrome.frag index 810094057..f0e1652f6 100644 --- a/Shaders/HDR/geometry-chrome.frag +++ b/Shaders/HDR/geometry-chrome.frag @@ -1,16 +1,23 @@ #version 330 core -layout(location = 0) out vec4 gbuffer0; -layout(location = 1) out vec2 gbuffer1; -layout(location = 2) out vec4 gbuffer2; +layout(location = 0) out vec4 outGBuffer0; +layout(location = 1) out vec4 outGBuffer1; +layout(location = 2) out vec4 outGBuffer2; in vec3 normalVS; +const float CHROME_METALNESS = 1.0; +const float CHROME_ROUGHNESS = 0.1; + vec2 encodeNormal(vec3 n); void main() { - gbuffer0 = vec4(1.0); - gbuffer1 = encodeNormal(normalVS); - gbuffer2 = vec4(1.0, 0.1, 0.0, 0.0); + outGBuffer0.rg = encodeNormal(normalVS); + outGBuffer0.b = CHROME_ROUGHNESS; + outGBuffer0.a = 1.0; + outGBuffer1.rgb = vec3(1.0); + outGBuffer1.a = CHROME_METALNESS; + outGBuffer2.rgb = vec3(0.0); + outGBuffer2.a = 1.0; } diff --git a/Shaders/HDR/geometry-combined.frag b/Shaders/HDR/geometry-combined.frag index 73988d684..e41a4c9f2 100644 --- a/Shaders/HDR/geometry-combined.frag +++ b/Shaders/HDR/geometry-combined.frag @@ -1,8 +1,8 @@ #version 330 core -layout(location = 0) out vec4 gbuffer0; -layout(location = 1) out vec2 gbuffer1; -layout(location = 2) out vec4 gbuffer2; +layout(location = 0) out vec4 outGBuffer0; +layout(location = 1) out vec4 outGBuffer1; +layout(location = 2) out vec4 outGBuffer2; in vec2 texCoord; in mat3 TBN; @@ -21,8 +21,7 @@ vec3 decodeSRGB(vec3 screenRGB); void main() { - gbuffer0.rgb = decodeSRGB(texture(color_tex, texCoord).rgb); - gbuffer0.a = 1.0; + vec3 color = decodeSRGB(texture(color_tex, texCoord).rgb); vec3 normal = vec3(0.0, 0.0, 1.0); if (normalmap_enabled > 0) { @@ -32,10 +31,12 @@ void main() normal = -normal; } normal = normalize(TBN * normal); - gbuffer1 = encodeNormal(normal); - gbuffer2 = vec4(DEFAULT_COMBINED_METALNESS, - DEFAULT_COMBINED_ROUGHNESS, - 0.0, - 0.0); + outGBuffer0.rg = encodeNormal(normal); + outGBuffer0.b = DEFAULT_COMBINED_ROUGHNESS; + outGBuffer0.a = 1.0; + outGBuffer1.rgb = color; + outGBuffer1.a = DEFAULT_COMBINED_METALNESS; + outGBuffer2.rgb = vec3(0.0); + outGBuffer2.a = 1.0; } diff --git a/Shaders/HDR/geometry-pbr-transparent.frag b/Shaders/HDR/geometry-pbr-transparent.frag index 418150ff0..09d89dd1d 100644 --- a/Shaders/HDR/geometry-pbr-transparent.frag +++ b/Shaders/HDR/geometry-pbr-transparent.frag @@ -8,8 +8,7 @@ in vec3 ecPos; uniform sampler2D base_color_tex; uniform sampler2D normal_tex; -uniform sampler2D metallic_roughness_tex; -uniform sampler2D occlusion_tex; +uniform sampler2D orm_tex; uniform sampler2D emissive_tex; uniform vec4 base_color_factor; uniform float metallic_factor; @@ -29,8 +28,6 @@ vec3 evaluateLight( vec3 baseColor, float metallic, float roughness, - float clearcoat, - float clearcoatRoughness, vec3 f0, vec3 intensity, float occlusion, @@ -59,13 +56,13 @@ void main() if (baseColor.a < alpha_cutoff) discard; - float occlusion = texture(occlusion_tex, texCoord).r; vec3 n = texture(normal_tex, texCoord).rgb * 2.0 - 1.0; n = normalize(TBN * n); - vec4 metallicRoughness = texture(metallic_roughness_tex, texCoord); - float metallic = metallicRoughness.r * metallic_factor; - float roughness = metallicRoughness.g * roughness_factor; + vec3 orm = texture(orm_tex, texCoord).rgb; + float occlusion = orm.r; + float roughness = orm.g * roughness_factor; + float metallic = orm.b * metallic_factor; vec3 emissive = texture(emissive_tex, texCoord).rgb * emissive_factor; @@ -83,8 +80,6 @@ void main() vec3 color = evaluateLight(baseColor.rgb, metallic, roughness, - 0.0, - 0.0, f0, sunIlluminance, shadowFactor, diff --git a/Shaders/HDR/geometry-pbr.frag b/Shaders/HDR/geometry-pbr.frag index 7f9b70116..32969ad72 100644 --- a/Shaders/HDR/geometry-pbr.frag +++ b/Shaders/HDR/geometry-pbr.frag @@ -1,16 +1,15 @@ #version 330 core -layout(location = 0) out vec4 gbuffer0; -layout(location = 1) out vec2 gbuffer1; -layout(location = 2) out vec4 gbuffer2; +layout(location = 0) out vec4 outGBuffer0; +layout(location = 1) out vec4 outGBuffer1; +layout(location = 2) out vec4 outGBuffer2; in vec2 texCoord; in mat3 TBN; uniform sampler2D base_color_tex; uniform sampler2D normal_tex; -uniform sampler2D metallic_roughness_tex; -uniform sampler2D occlusion_tex; +uniform sampler2D orm_tex; uniform sampler2D emissive_tex; uniform vec4 base_color_factor; uniform float metallic_factor; @@ -22,22 +21,24 @@ vec3 decodeSRGB(vec3 screenRGB); void main() { - vec4 baseColorTexel = texture(base_color_tex, texCoord); - vec4 baseColor = vec4(decodeSRGB(baseColorTexel.rgb), baseColorTexel.a) - * base_color_factor; - gbuffer0.rgb = baseColor.rgb; - - float occlusion = texture(occlusion_tex, texCoord).r; - gbuffer0.a = occlusion; + vec3 baseColorTexel = texture(base_color_tex, texCoord).rgb; // Ignore alpha + vec3 baseColor = decodeSRGB(baseColorTexel.rgb) * base_color_factor.rgb; vec3 normal = texture(normal_tex, texCoord).rgb * 2.0 - 1.0; normal = normalize(TBN * normal); - gbuffer1 = encodeNormal(normal); - vec4 metallicRoughness = texture(metallic_roughness_tex, texCoord); - float metallic = metallicRoughness.r * metallic_factor; - float roughness = metallicRoughness.g * roughness_factor; - gbuffer2 = vec4(metallic, roughness, 0.0, 0.0); + vec3 orm = texture(orm_tex, texCoord).rgb; + float occlusion = orm.r; + float roughness = orm.g * roughness_factor; + float metallic = orm.b * metallic_factor; vec3 emissive = texture(emissive_tex, texCoord).rgb * emissive_factor; + + outGBuffer0.rg = encodeNormal(normal); + outGBuffer0.b = roughness; + outGBuffer0.a = 1.0; + outGBuffer1.rgb = baseColor; + outGBuffer1.a = metallic; + outGBuffer2.rgb = vec3(0.0); + outGBuffer2.a = occlusion; } diff --git a/Shaders/HDR/geometry-shadow.frag b/Shaders/HDR/geometry-shadow.frag index 3947b8df7..90a8ff2ef 100644 --- a/Shaders/HDR/geometry-shadow.frag +++ b/Shaders/HDR/geometry-shadow.frag @@ -1,17 +1,8 @@ #version 330 core -layout(location = 0) out vec4 fragColor; - -in vec2 texCoord; - -uniform sampler2D color_tex; - -const float ALPHA_THRESHOLD = 0.5; +out vec4 fragColor; void main() { fragColor = vec4(1.0); - float alpha = texture(color_tex, texCoord).a; - if (alpha <= ALPHA_THRESHOLD) - discard; } diff --git a/Shaders/HDR/geometry-shadow.vert b/Shaders/HDR/geometry-shadow.vert index 518a8d13f..3cc1a3edb 100644 --- a/Shaders/HDR/geometry-shadow.vert +++ b/Shaders/HDR/geometry-shadow.vert @@ -1,14 +1,10 @@ #version 330 core layout(location = 0) in vec4 pos; -layout(location = 3) in vec4 multiTexCoord0; - -out vec2 texCoord; uniform mat4 osg_ModelViewProjectionMatrix; void main() { gl_Position = osg_ModelViewProjectionMatrix * pos; - texCoord = multiTexCoord0.st; } diff --git a/Shaders/HDR/geometry-transparent.frag b/Shaders/HDR/geometry-transparent.frag index d7d993fe3..6bc201d3f 100644 --- a/Shaders/HDR/geometry-transparent.frag +++ b/Shaders/HDR/geometry-transparent.frag @@ -14,6 +14,7 @@ uniform mat4 osg_ProjectionMatrix; uniform vec4 fg_Viewport; uniform vec3 fg_SunDirection; +const float DEFAULT_TRANSPARENT_METALNESS = 0.0; const float DEFAULT_TRANSPARENT_ROUGHNESS = 0.1; vec3 decodeSRGB(vec3 screenRGB); @@ -23,8 +24,6 @@ vec3 evaluateLight( vec3 baseColor, float metallic, float roughness, - float clearcoat, - float clearcoatRoughness, vec3 f0, vec3 intensity, float occlusion, @@ -64,10 +63,8 @@ void main() float shadowFactor = getShadowing(ecPos, n, l, osg_ProjectionMatrix); vec3 color = evaluateLight(baseColor, - 0.0, + DEFAULT_TRANSPARENT_METALNESS, DEFAULT_TRANSPARENT_ROUGHNESS, - 0.0, - 0.0, f0, sunIlluminance, shadowFactor, @@ -78,7 +75,7 @@ void main() vec3 worldReflected = (osg_ViewMatrixInverse * vec4(reflect(-v, n), 0.0)).xyz; color += evaluateIBL(baseColor, - 0.0, + DEFAULT_TRANSPARENT_METALNESS, DEFAULT_TRANSPARENT_ROUGHNESS, f0, 1.0, diff --git a/Shaders/HDR/geometry-water.frag b/Shaders/HDR/geometry-water.frag index 51a911435..c32829761 100644 --- a/Shaders/HDR/geometry-water.frag +++ b/Shaders/HDR/geometry-water.frag @@ -1,7 +1,7 @@ #version 330 core -layout(location = 0) out vec4 gbuffer0; -layout(location = 1) out vec2 gbuffer1; +layout(location = 0) out vec4 outGBuffer0; +layout(location = 1) out vec4 outGBuffer1; in vec4 waterTex1; in vec4 waterTex2; @@ -207,8 +207,9 @@ void main() N0.g += (ddy + ddy1 + ddy2 + ddy3); vec3 N = normalize(mix(N0, N1, mixFactor) * waveRoughness); - gbuffer1 = encodeNormal(TBN * N); vec3 floorColor = decodeSRGB(texture(water_colormap, TopoUV).rgb); - gbuffer0.rgb = floorColor; + + outGBuffer0.rg = encodeNormal(TBN * N); + outGBuffer1.rgb = floorColor; } diff --git a/Shaders/HDR/geometry.frag b/Shaders/HDR/geometry.frag index 211ddf04f..62792d8d0 100644 --- a/Shaders/HDR/geometry.frag +++ b/Shaders/HDR/geometry.frag @@ -1,8 +1,8 @@ #version 330 core -layout(location = 0) out vec4 gbuffer0; -layout(location = 1) out vec2 gbuffer1; -layout(location = 2) out vec4 gbuffer2; +layout(location = 0) out vec4 outGBuffer0; +layout(location = 1) out vec4 outGBuffer1; +layout(location = 2) out vec4 outGBuffer2; in vec3 normalVS; in vec2 texCoord; @@ -11,7 +11,7 @@ in vec4 materialColor; uniform sampler2D color_tex; const float DEFAULT_METALNESS = 0.0; -const float DEFAULT_ROUGHNESS = 0.8; +const float DEFAULT_ROUGHNESS = 0.5; vec2 encodeNormal(vec3 n); vec3 decodeSRGB(vec3 screenRGB); @@ -20,11 +20,12 @@ void main() { vec3 texel = texture(color_tex, texCoord).rgb; vec3 color = decodeSRGB(texel) * materialColor.rgb; // Ignore transparency - gbuffer0.rgb = color; - gbuffer0.a = 1.0; - gbuffer1 = encodeNormal(normalVS); - gbuffer2 = vec4(DEFAULT_METALNESS, - DEFAULT_ROUGHNESS, - 0.0, - 0.0); + + outGBuffer0.rg = encodeNormal(normalVS); + outGBuffer0.b = DEFAULT_ROUGHNESS; + outGBuffer0.a = 1.0; + outGBuffer1.rgb = color; + outGBuffer1.a = DEFAULT_METALNESS; + outGBuffer2.rgb = vec3(0.0); + outGBuffer2.a = 1.0; } diff --git a/Shaders/HDR/lighting-include.frag b/Shaders/HDR/lighting-include.frag index 09e62bbdd..08a6a19ac 100644 --- a/Shaders/HDR/lighting-include.frag +++ b/Shaders/HDR/lighting-include.frag @@ -29,6 +29,11 @@ vec3 F_Schlick(float VdotH, vec3 F0) return F0 + (vec3(1.0) - F0) * pow(clamp(1.0 - VdotH, 0.0, 1.0), 5.0); } +float F_Schlick(float VdotH, float F0) +{ + return F0 + (1.0 - F0) * pow(clamp(1.0 - VdotH, 0.0, 1.0), 5.0); +} + /** * Normal distribution function (NDF) (specular D) * Trowbridge-Reitz/GGX microfacet distribution. Includes Disney's @@ -137,8 +142,6 @@ vec3 evaluateLight( vec3 baseColor, float metallic, float roughness, - float clearcoat, - float clearcoatRoughness, vec3 f0, // Use getF0Reflectance() to obtain this vec3 intensity, float occlusion, @@ -169,14 +172,13 @@ vec3 evaluateLight( float D = D_GGX(NdotH, a2); float G = G_SmithGGX(NdotV, NdotL, a2); - // Diffuse term - // Lambertian diffuse model - vec3 diffuse = (vec3(1.0) - F) * Fd_Lambert(c_diff); - // Specular term - // Cook-Torrance specular microfacet model - vec3 specular = ((D * G) * F) / (4.0 * NdotV * NdotL); + // Diffuse term: Lambertian diffuse model + vec3 f_diffuse = (vec3(1.0) - F) * Fd_Lambert(c_diff); - vec3 material = diffuse + specular; + // Specular term: Cook-Torrance specular microfacet model + vec3 f_specular = ((D * G) * F) / (4.0 * NdotV * NdotL); + + vec3 material = f_diffuse + f_specular; vec3 color = material * intensity * occlusion; return color; diff --git a/Shaders/HDR/lighting.frag b/Shaders/HDR/lighting.frag index c83619b5a..8b11b05f2 100644 --- a/Shaders/HDR/lighting.frag +++ b/Shaders/HDR/lighting.frag @@ -1,6 +1,6 @@ #version 330 core -out vec3 fragHdrColor; +out vec3 fragColor; in vec2 texCoord; @@ -10,20 +10,21 @@ uniform sampler2D gbuffer2_tex; uniform sampler2D depth_tex; uniform sampler2D ao_tex; +uniform bool debug_shadow_cascades; + uniform mat4 fg_ViewMatrixInverse; uniform mat4 fg_ProjectionMatrix; uniform vec3 fg_SunDirection; -vec3 decodeNormal(vec2 enc); +vec3 decodeNormal(vec2 f); vec3 positionFromDepth(vec2 pos, float depth); float getShadowing(vec3 p, vec3 n, vec3 l, mat4 viewToClip); +vec3 debugShadowColor(vec3 p, vec3 n, vec3 l); vec3 getF0Reflectance(vec3 baseColor, float metallic); vec3 evaluateLight( vec3 baseColor, float metallic, float roughness, - float clearcoat, - float clearcoatRoughness, vec3 f0, vec3 intensity, float occlusion, @@ -46,26 +47,27 @@ vec3 getSunIntensity(); void main() { - float depth = texture(depth_tex, texCoord).r; vec4 gbuffer0 = texture(gbuffer0_tex, texCoord); - vec2 gbuffer1 = texture(gbuffer1_tex, texCoord).rg; + vec4 gbuffer1 = texture(gbuffer1_tex, texCoord); vec4 gbuffer2 = texture(gbuffer2_tex, texCoord); - float ao = texture(ao_tex, texCoord).r; + float depth = texture(depth_tex, texCoord).r; + + // Unpack G-Buffer + vec3 n = decodeNormal(gbuffer0.rg); + float roughness = gbuffer0.b; + uint matId = uint(gbuffer0.a * 4.0); + vec3 baseColor = gbuffer1.rgb; + float metallic = gbuffer1.a; + float occlusion = gbuffer2.a; vec3 pos = positionFromDepth(texCoord, depth); vec3 v = normalize(-pos); - vec3 n = decodeNormal(gbuffer1); vec3 l = fg_SunDirection; float NdotL = dot(n, l); float NdotV = clamp(abs(dot(n, v)), 0.001, 1.0); - vec3 baseColor = gbuffer0.rgb; - float cavity = gbuffer0.a; - float metallic = gbuffer2.r; - float roughness = gbuffer2.g; - float clearcoat = gbuffer2.b; - float clearcoatRoughness = gbuffer2.a; + float ao = texture(ao_tex, texCoord).r; vec3 f0 = getF0Reflectance(baseColor, metallic); @@ -75,15 +77,13 @@ void main() vec3 color = evaluateLight(baseColor, metallic, roughness, - clearcoat, - clearcoatRoughness, f0, sunIlluminance, shadowFactor, n, l, v, NdotL, NdotV); - float ambientOcclusion = ao * cavity; + float ambientOcclusion = ao * occlusion; vec3 worldNormal = (fg_ViewMatrixInverse * vec4(n, 0.0)).xyz; vec3 worldReflected = (fg_ViewMatrixInverse * vec4(reflect(-v, n), 0.0)).xyz; @@ -98,5 +98,8 @@ void main() color = addAerialPerspective(color, texCoord, length(pos)); - fragHdrColor = color; + if (debug_shadow_cascades) + color *= debugShadowColor(pos, n, l); + + fragColor = color; } diff --git a/Shaders/HDR/shadows-include.frag b/Shaders/HDR/shadows-include.frag index c43911dc2..befe1c07d 100644 --- a/Shaders/HDR/shadows-include.frag +++ b/Shaders/HDR/shadows-include.frag @@ -20,7 +20,7 @@ const vec2 uv_shifts[4] = vec2[4]( const vec2 uv_factor = vec2(0.5, 0.5); const float SSS_THICKNESS = 0.1; -const uint SSS_NUM_STEPS = 32u; +const uint SSS_NUM_STEPS = 16u; const float SSS_MAX_DISTANCE = 0.05; const vec3 DITHER_MAGIC = vec3(0.06711056, 0.00583715, 52.9829189); @@ -76,14 +76,11 @@ float sampleCascade(vec4 p, vec2 shift, vec2 mapSize) return sampleOptimizedPCF(pos, mapSize); } -float sampleAndBlendBand(vec4 p1, vec4 p2, vec2 s1, vec2 s2, vec2 mapSize) +float getBlendFactor(vec2 uv, vec2 bottomLeft, vec2 topRight) { - vec2 s = smoothstep(vec2(0.0), BAND_BOTTOM_LEFT, p1.xy) - - smoothstep(BAND_TOP_RIGHT, vec2(1.0), p1.xy); - float blend = 1.0 - s.x * s.y; - return mix(sampleCascade(p1, s1, mapSize), - sampleCascade(p2, s2, mapSize), - blend); + vec2 s = smoothstep(vec2(0.0), bottomLeft, uv) + - smoothstep(topRight, vec2(1.0), uv); + return 1.0 - s.x * s.y; } bool checkWithinBounds(vec2 coords, vec2 bottomLeft, vec2 topRight) @@ -151,7 +148,9 @@ float getContactShadow(vec3 p, vec3 l, mat4 viewToClip) float dz = samplePos.z - sampleDepth; if (dz > 0.00001 && dz < SSS_THICKNESS) { shadow = 1.0; - // TODO: Add screen fading + vec2 screenFade = smoothstep(vec2(0.0), vec2(0.07), samplePos.xy) + - smoothstep(vec2(0.93), vec2(1.0), samplePos.xy); + shadow *= screenFade.x * screenFade.y; break; } t += dt; @@ -184,30 +183,62 @@ float getShadowing(vec3 p, vec3 n, vec3 l, mat4 viewToClip) // We test if we are inside the cascade bounds to find the tightest // map that contains the fragment. if (isInsideCascade(lightSpacePos[i])) { - if (isInsideBand(lightSpacePos[i]) && ((i+1) < 4)) { + if (isInsideBand(lightSpacePos[i])) { // Blend between cascades if the fragment is near the // next cascade to avoid abrupt transitions. - visibility = clamp(sampleAndBlendBand(lightSpacePos[i], - lightSpacePos[i+1], - uv_shifts[i], - uv_shifts[i+1], - mapSize), - 0.0, 1.0); + float blend = getBlendFactor(lightSpacePos[i].xy, + BAND_BOTTOM_LEFT, + BAND_TOP_RIGHT); + float cascade0 = sampleCascade(lightSpacePos[i], + uv_shifts[i], + mapSize); + float cascade1; + if (i == 3) { + // Handle special case of the last cascade + cascade1 = 1.0; + } else { + cascade1 = sampleCascade(lightSpacePos[i+1], + uv_shifts[i+1], + mapSize); + } + visibility = mix(cascade0, cascade1, blend); } else { // We are far away from the borders of the cascade, so // we skip the blending to avoid the performance cost // of sampling the shadow map twice. - visibility = clamp(sampleCascade(lightSpacePos[i], - uv_shifts[i], - mapSize), - 0.0, 1.0); + visibility = sampleCascade(lightSpacePos[i], + uv_shifts[i], + mapSize); } break; } } + visibility = clamp(visibility, 0.0, 1.0); if (visibility > 0.0) visibility *= getContactShadow(p, l, viewToClip); return visibility; } + +vec3 debugShadowColor(vec3 p, vec3 n, vec3 l) +{ + float NdotL = clamp(dot(n, l), 0.0, 1.0); + + vec4 lightSpacePos[4]; + lightSpacePos[0] = getLightSpacePosition(p, n, NdotL, fg_LightMatrix_csm0); + lightSpacePos[1] = getLightSpacePosition(p, n, NdotL, fg_LightMatrix_csm1); + lightSpacePos[2] = getLightSpacePosition(p, n, NdotL, fg_LightMatrix_csm2); + lightSpacePos[3] = getLightSpacePosition(p, n, NdotL, fg_LightMatrix_csm3); + + if (isInsideCascade(lightSpacePos[0])) + return vec3(1.0, 0.0, 0.0); + else if (isInsideCascade(lightSpacePos[1])) + return vec3(0.0, 1.0, 0.0); + else if (isInsideCascade(lightSpacePos[2])) + return vec3(0.0, 0.0, 1.0); + else if (isInsideCascade(lightSpacePos[3])) + return vec3(1.0, 0.0, 1.0); + + return vec3(0.0); +} diff --git a/Shaders/HDR/water-lighting.frag b/Shaders/HDR/water-lighting.frag index 6daf36453..2cd279426 100644 --- a/Shaders/HDR/water-lighting.frag +++ b/Shaders/HDR/water-lighting.frag @@ -19,7 +19,7 @@ const float RECIPROCAL_PI = 0.31830988618; const float MAX_PREFILTERED_LOD = 4.0; const vec3 EXTRATERRESTRIAL_SOLAR_ILLUMINANCE = vec3(128.0); -vec3 decodeNormal(vec2 enc); +vec3 decodeNormal(vec2 f); vec3 positionFromDepth(vec2 pos, float depth); vec3 addAerialPerspective(vec3 color, vec2 coord, float depth); @@ -36,11 +36,17 @@ float D_GGX(float NdotH, float a2) void main() { + vec4 gbuffer0 = texture(gbuffer0_tex, texCoord); + vec4 gbuffer1 = texture(gbuffer1_tex, texCoord); float depth = texture(depth_tex, texCoord).r; + + // Unpack G-Buffer + vec3 n = decodeNormal(gbuffer0.rg); + vec3 seaColor = gbuffer1.rgb; + vec3 pos = positionFromDepth(texCoord, depth); vec3 v = normalize(-pos); - vec3 n = decodeNormal(texture(gbuffer1_tex, texCoord).rg); vec3 l = fg_SunDirection; vec3 reflected = reflect(-v, n); @@ -62,7 +68,6 @@ void main() float fresnel = F_Schlick(NdotV, f0); // Refracted light - vec3 seaColor = texture(gbuffer0_tex, texCoord).rgb; vec3 Esky = textureLod(prefiltered_envmap, worldNormal, MAX_PREFILTERED_LOD).rgb; vec3 refracted = seaColor * Esky * RECIPROCAL_PI; diff --git a/Shaders/HDR/ws30.frag b/Shaders/HDR/ws30.frag index 86554caff..ff0be9861 100644 --- a/Shaders/HDR/ws30.frag +++ b/Shaders/HDR/ws30.frag @@ -1,8 +1,8 @@ #version 330 core -layout(location = 0) out vec4 gbuffer0; -layout(location = 1) out vec2 gbuffer1; -layout(location = 2) out vec4 gbuffer2; +layout(location = 0) out vec4 outGBuffer0; +layout(location = 1) out vec4 outGBuffer1; +layout(location = 2) out vec4 outGBuffer2; in vec3 normalVS; in vec2 texCoord; @@ -44,11 +44,14 @@ void main() st = -st; } - vec3 texel = texture(atlas, vec3(st, lc)).rgb; - - gbuffer0.rgb = decodeSRGB(texel); - gbuffer0.a = 1.0; - gbuffer1 = encodeNormal(normalVS); + vec3 texel = decodeSRGB(texture(atlas, vec3(st, lc)).rgb); float specularity = clamp(dot(specular.rgb, vec3(0.333)), 0.0, 1.0); - gbuffer2 = vec4(0.0, 1.0-specularity, 0.0, 0.0); + + outGBuffer0.rg = encodeNormal(normalVS); + outGBuffer0.b = 1.0 - specularity; + outGBuffer0.a = 1.0; + outGBuffer1.rgb = texel; + outGBuffer1.a = 0.0; + outGBuffer2.rgb = vec3(0.0); + outGBuffer2.a = 1.0; } diff --git a/defaults.xml b/defaults.xml index abb9c8c86..96a55bc58 100644 --- a/defaults.xml +++ b/defaults.xml @@ -389,8 +389,9 @@ Started September 2000 by David Megginson, david@megginson.com 0.5 8.0 - false false + false + false true