diff --git a/Compositor/HDR/hdr.xml b/Compositor/HDR/hdr.xml index 4ed349986..01e637c0a 100644 --- a/Compositor/HDR/hdr.xml +++ b/Compositor/HDR/hdr.xml @@ -8,14 +8,15 @@ + hdr-result 2d @@ -290,6 +298,10 @@ color2 gbuffer2 + + color3 + gbuffer3 + - lighting + shading quad - Effects/HDR/lighting + Effects/HDR/shading-opaque csm0 csm1 csm2 @@ -770,6 +786,10 @@ 3 + gbuffer3 + + + 4 depth-stencil @@ -808,7 +828,7 @@ water quad - Effects/HDR/water-lighting + Effects/HDR/water-shading 0 gbuffer0 diff --git a/Effects/Fallback/hdr-geometry.eff b/Effects/Fallback/hdr-geometry.eff deleted file mode 100644 index 1518cad22..000000000 --- a/Effects/Fallback/hdr-geometry.eff +++ /dev/null @@ -1,34 +0,0 @@ - - - Effects/Fallback/hdr-geometry - - hdr-geometry - - - - gequal - 1.0 - 0.0 - - - 0 - texture[0]/type - texture[0]/image - texture[0]/filter - texture[0]/wrap-s - texture[0]/wrap-t - - back - - Shaders/HDR/geometry.vert - Shaders/HDR/geometry.frag - Shaders/HDR/gbuffer-include.frag - - - color_tex - sampler-2d - 0 - - - - diff --git a/Effects/Fallback/hdr-shadow.eff b/Effects/Fallback/hdr-shadow.eff deleted file mode 100644 index a8667b927..000000000 --- a/Effects/Fallback/hdr-shadow.eff +++ /dev/null @@ -1,35 +0,0 @@ - - - Effects/Fallback/hdr-shadow - - hdr-shadow - - - 0 - texture[0]/type - texture[0]/image - texture[0]/filter - texture[0]/wrap-s - texture[0]/wrap-t - - 0 0 0 0 - back - - false - - - 1.1 - 4.0 - - - Shaders/HDR/geometry-shadow.vert - Shaders/HDR/geometry-shadow.frag - - - color_tex - sampler-2d - 0 - - - - diff --git a/Effects/HDR/ao.eff b/Effects/HDR/ao.eff deleted file mode 100644 index 50d81703b..000000000 --- a/Effects/HDR/ao.eff +++ /dev/null @@ -1,23 +0,0 @@ - - - Effects/HDR/ao - - - - Shaders/HDR/trivial.vert - Shaders/HDR/ao.frag - Shaders/HDR/gbuffer-include.frag - - - gbuffer0_tex - sampler-2d - 0 - - - depth_tex - sampler-2d - 1 - - - - diff --git a/Effects/HDR/atmos-aerial-perspective.eff b/Effects/HDR/atmos-aerial-perspective.eff index 96c90aefd..1ef48854e 100644 --- a/Effects/HDR/atmos-aerial-perspective.eff +++ b/Effects/HDR/atmos-aerial-perspective.eff @@ -4,10 +4,12 @@ - Shaders/HDR/trivial.vert - Shaders/HDR/atmos-aerial-perspective.frag - Shaders/HDR/atmos-include.frag - Shaders/HDR/gbuffer-include.frag + Shaders/HDR/quad.vert + Shaders/HDR/atmos_aerial_perspective.frag + Shaders/HDR/math.glsl + Shaders/HDR/pos_from_depth.glsl + Shaders/HDR/atmos.glsl + Shaders/HDR/atmos_spectral.glsl transmittance_lut diff --git a/Effects/HDR/atmos-sky-view.eff b/Effects/HDR/atmos-sky-view.eff index 93e427c4b..3a900b97e 100644 --- a/Effects/HDR/atmos-sky-view.eff +++ b/Effects/HDR/atmos-sky-view.eff @@ -4,9 +4,10 @@ - Shaders/HDR/trivial.vert - Shaders/HDR/atmos-sky-view.frag - Shaders/HDR/atmos-include.frag + Shaders/HDR/quad.vert + Shaders/HDR/atmos_sky_view.frag + Shaders/HDR/math.glsl + Shaders/HDR/atmos.glsl transmittance_lut diff --git a/Effects/HDR/atmos-transmittance.eff b/Effects/HDR/atmos-transmittance.eff index 76c8179d8..71664f33e 100644 --- a/Effects/HDR/atmos-transmittance.eff +++ b/Effects/HDR/atmos-transmittance.eff @@ -4,9 +4,10 @@ - Shaders/HDR/trivial.vert - Shaders/HDR/atmos-transmittance.frag - Shaders/HDR/atmos-include.frag + Shaders/HDR/quad.vert + Shaders/HDR/atmos_transmittance.frag + Shaders/HDR/math.glsl + Shaders/HDR/atmos.glsl diff --git a/Effects/HDR/bloom-threshold.eff b/Effects/HDR/bloom-threshold.eff index 96816aa4e..58c61d4cd 100644 --- a/Effects/HDR/bloom-threshold.eff +++ b/Effects/HDR/bloom-threshold.eff @@ -2,17 +2,17 @@ Effects/HDR/bloom-threshold + /sim/rendering/hdr/bloom-threshold /sim/rendering/hdr/exposure-compensation - /sim/rendering/hdr/bloom-threshold - Shaders/HDR/trivial.vert - Shaders/HDR/bloom-threshold.frag - Shaders/HDR/exposure-include.frag + Shaders/HDR/quad.vert + Shaders/HDR/bloom_threshold.frag + Shaders/HDR/exposure.glsl hdr_tex @@ -24,16 +24,17 @@ sampler-2d 1 - - exposure_compensation - float - exposure-compensation - bloom_threshold float bloom-threshold + + + exposure_compensation + float + exposure-compensation + diff --git a/Effects/HDR/blur.eff b/Effects/HDR/blur.eff index 19d96f307..5a1e463a3 100644 --- a/Effects/HDR/blur.eff +++ b/Effects/HDR/blur.eff @@ -7,7 +7,7 @@ - Shaders/HDR/trivial.vert + Shaders/HDR/quad.vert Shaders/HDR/blur.frag diff --git a/Effects/HDR/copy-prev-luminance.eff b/Effects/HDR/copy-prev-luminance.eff index 8230fcd87..1fed7544d 100644 --- a/Effects/HDR/copy-prev-luminance.eff +++ b/Effects/HDR/copy-prev-luminance.eff @@ -4,11 +4,11 @@ - Shaders/HDR/trivial-notexcoord.vert - Shaders/HDR/copy-prev-luminance.frag + Shaders/HDR/quad_notexcoord.vert + Shaders/HDR/copy_prev_luminance.frag - tex + lum_tex sampler-2d 0 diff --git a/Effects/HDR/envmap-copy.eff b/Effects/HDR/envmap-copy.eff index 646182287..d6aafc922 100644 --- a/Effects/HDR/envmap-copy.eff +++ b/Effects/HDR/envmap-copy.eff @@ -4,11 +4,11 @@ - Shaders/HDR/envmap-prefilter.vert - Shaders/HDR/envmap-copy.frag + Shaders/HDR/envmap.vert + Shaders/HDR/envmap_copy.frag - envmap + envmap_tex sampler-cube 0 diff --git a/Effects/HDR/envmap-prefilter.eff b/Effects/HDR/envmap-prefilter.eff index 20884a925..1162ee22c 100644 --- a/Effects/HDR/envmap-prefilter.eff +++ b/Effects/HDR/envmap-prefilter.eff @@ -4,15 +4,17 @@ 0.0 1 + 4 - Shaders/HDR/envmap-prefilter.vert - Shaders/HDR/envmap-prefilter.frag + Shaders/HDR/envmap.vert + Shaders/HDR/envmap_prefilter.frag + Shaders/HDR/math.glsl - envmap + envmap_tex sampler-cube 0 @@ -26,6 +28,11 @@ int num-samples + + mip_count + int + mip-count + diff --git a/Effects/HDR/gbuffer-debug-clear.eff b/Effects/HDR/gbuffer-debug-clear.eff index 96f9b43fd..6b4345f99 100644 --- a/Effects/HDR/gbuffer-debug-clear.eff +++ b/Effects/HDR/gbuffer-debug-clear.eff @@ -4,8 +4,8 @@ - Shaders/HDR/trivial.vert - Shaders/HDR/gbuffer-debug-clear.frag + Shaders/HDR/quad.vert + Shaders/HDR/debug_gbuffer_clear.frag diff --git a/Effects/HDR/gbuffer-debug-color.eff b/Effects/HDR/gbuffer-debug-color.eff index e4dd653b7..78fca6475 100644 --- a/Effects/HDR/gbuffer-debug-color.eff +++ b/Effects/HDR/gbuffer-debug-color.eff @@ -4,8 +4,8 @@ - Shaders/HDR/trivial-quad.vert - Shaders/HDR/gbuffer-debug-color.frag + Shaders/HDR/quad_matrix.vert + Shaders/HDR/debug_gbuffer_color.frag gbuffer1_tex diff --git a/Effects/HDR/gbuffer-debug-depth.eff b/Effects/HDR/gbuffer-debug-depth.eff index a59338a3e..4f0b7c481 100644 --- a/Effects/HDR/gbuffer-debug-depth.eff +++ b/Effects/HDR/gbuffer-debug-depth.eff @@ -4,9 +4,9 @@ - Shaders/HDR/trivial-quad.vert - Shaders/HDR/gbuffer-debug-depth.frag - Shaders/HDR/gbuffer-include.frag + Shaders/HDR/quad_matrix.vert + Shaders/HDR/debug_gbuffer_orm.frag + Shaders/HDR/pos_from_depth.glsl depth_tex diff --git a/Effects/HDR/gbuffer-debug-matid.eff b/Effects/HDR/gbuffer-debug-matid.eff index 3b9b4aea5..9aadcb439 100644 --- a/Effects/HDR/gbuffer-debug-matid.eff +++ b/Effects/HDR/gbuffer-debug-matid.eff @@ -4,8 +4,8 @@ - Shaders/HDR/trivial-quad.vert - Shaders/HDR/gbuffer-debug-matid.frag + Shaders/HDR/quad_matrix.vert + Shaders/HDR/debug_gbuffer_matid.frag gbuffer0_tex diff --git a/Effects/HDR/gbuffer-debug-normal.eff b/Effects/HDR/gbuffer-debug-normal.eff index 3a4a786e8..f770cf3b7 100644 --- a/Effects/HDR/gbuffer-debug-normal.eff +++ b/Effects/HDR/gbuffer-debug-normal.eff @@ -4,8 +4,8 @@ - Shaders/HDR/trivial-quad.vert - Shaders/HDR/gbuffer-debug-normal.frag + Shaders/HDR/quad_matrix.vert + Shaders/HDR/debug_gbuffer_normal.frag gbuffer0_tex diff --git a/Effects/HDR/gbuffer-debug-orm.eff b/Effects/HDR/gbuffer-debug-orm.eff index 72a56ab91..b11bbec49 100644 --- a/Effects/HDR/gbuffer-debug-orm.eff +++ b/Effects/HDR/gbuffer-debug-orm.eff @@ -4,8 +4,8 @@ - Shaders/HDR/trivial-quad.vert - Shaders/HDR/gbuffer-debug-orm.frag + Shaders/HDR/quad_matrix.vert + Shaders/HDR/debug_gbuffer_orm.frag gbuffer0_tex diff --git a/Effects/HDR/gtao-denoiser.eff b/Effects/HDR/gtao-denoiser.eff index dc894be70..6bd05b1c8 100644 --- a/Effects/HDR/gtao-denoiser.eff +++ b/Effects/HDR/gtao-denoiser.eff @@ -4,8 +4,8 @@ - Shaders/HDR/trivial-notexcoord.vert - Shaders/HDR/gtao-denoiser.frag + Shaders/HDR/quad_notexcoord.vert + Shaders/HDR/gtao_denoiser.frag ao_tex diff --git a/Effects/HDR/gtao.eff b/Effects/HDR/gtao.eff index 618730e50..e0e65f148 100644 --- a/Effects/HDR/gtao.eff +++ b/Effects/HDR/gtao.eff @@ -13,9 +13,11 @@ 8 - Shaders/HDR/trivial.vert + Shaders/HDR/quad.vert Shaders/HDR/gtao.frag - Shaders/HDR/gbuffer-include.frag + Shaders/HDR/math.glsl + Shaders/HDR/normal_encoding.glsl + Shaders/HDR/pos_from_depth.glsl gbuffer0_tex diff --git a/Effects/HDR/histogram-aggregate.eff b/Effects/HDR/histogram-aggregate.eff index d86b26961..66c206905 100644 --- a/Effects/HDR/histogram-aggregate.eff +++ b/Effects/HDR/histogram-aggregate.eff @@ -4,8 +4,8 @@ - Shaders/HDR/trivial-notexcoord.vert - Shaders/HDR/histogram-aggregate.frag + Shaders/HDR/quad_notexcoord.vert + Shaders/HDR/histogram_aggregate.frag partial_histogram_tex diff --git a/Effects/HDR/histogram-column.eff b/Effects/HDR/histogram-column.eff index 85668ab9a..2cac7205a 100644 --- a/Effects/HDR/histogram-column.eff +++ b/Effects/HDR/histogram-column.eff @@ -4,9 +4,10 @@ - Shaders/HDR/trivial-notexcoord.vert - Shaders/HDR/histogram-column.frag - Shaders/HDR/histogram-include.frag + Shaders/HDR/quad_notexcoord.vert + Shaders/HDR/histogram_column.frag + Shaders/HDR/color.glsl + Shaders/HDR/histogram.glsl hdr_tex diff --git a/Effects/HDR/histogram-luminance.eff b/Effects/HDR/histogram-luminance.eff index 68824c187..50f4275ef 100644 --- a/Effects/HDR/histogram-luminance.eff +++ b/Effects/HDR/histogram-luminance.eff @@ -4,9 +4,9 @@ - Shaders/HDR/trivial-notexcoord.vert - Shaders/HDR/histogram-luminance.frag - Shaders/HDR/histogram-include.frag + Shaders/HDR/quad_notexcoord.vert + Shaders/HDR/histogram_luminance.frag + Shaders/HDR/histogram.glsl histogram_tex diff --git a/Effects/HDR/postprocess.eff b/Effects/HDR/postprocess.eff index f23d14a6c..76b95fdb2 100644 --- a/Effects/HDR/postprocess.eff +++ b/Effects/HDR/postprocess.eff @@ -2,18 +2,20 @@ Effects/HDR/postprocess + /sim/rendering/hdr/bloom-magnitude + /sim/rendering/hdr/debug/display-ev100 /sim/rendering/hdr/exposure-compensation - /sim/rendering/hdr/bloom-magnitude - /sim/rendering/hdr/debug/display-ev100 - Shaders/HDR/trivial.vert + Shaders/HDR/quad.vert Shaders/HDR/postprocess.frag - Shaders/HDR/exposure-include.frag + Shaders/HDR/exposure.glsl + Shaders/HDR/aces.glsl + Shaders/HDR/color.glsl hdr_tex @@ -30,11 +32,6 @@ sampler-2d 4 - - exposure_compensation - float - exposure-compensation - bloom_magnitude float @@ -45,6 +42,12 @@ bool debug-ev100 + + + exposure_compensation + float + exposure-compensation + diff --git a/Effects/HDR/lighting.eff b/Effects/HDR/shading-opaque.eff similarity index 64% rename from Effects/HDR/lighting.eff rename to Effects/HDR/shading-opaque.eff index e93a4b24b..84122ff45 100644 --- a/Effects/HDR/lighting.eff +++ b/Effects/HDR/shading-opaque.eff @@ -1,7 +1,8 @@ - Effects/HDR/lighting + Effects/HDR/shading-opaque + Textures/PBR/dfg_lut.dds 2d @@ -11,9 +12,11 @@ clamp-to-edge normalized + /sim/rendering/hdr/ambient-occlusion/enabled + /sim/rendering/hdr/debug/show-shadow-cascades @@ -35,14 +38,22 @@ texture[8]/internal-format - Shaders/HDR/trivial.vert - Shaders/HDR/lighting.frag - Shaders/HDR/gbuffer-include.frag - Shaders/HDR/shadows-include.frag - Shaders/HDR/lighting-include.frag - Shaders/HDR/aerial-perspective-include.frag - Shaders/HDR/clustered-include.frag + Shaders/HDR/quad.vert + Shaders/HDR/shading_opaque.frag + Shaders/HDR/gbuffer_unpack.glsl + Shaders/HDR/normal_encoding.glsl + Shaders/HDR/pos_from_depth.glsl + Shaders/HDR/math.glsl + Shaders/HDR/shading_opaque.glsl + Shaders/HDR/surface.glsl + Shaders/HDR/ibl.glsl + Shaders/HDR/shadows.glsl + Shaders/HDR/gtao.glsl + Shaders/HDR/aerial_perspective.glsl + Shaders/HDR/atmos_spectral.glsl + Shaders/HDR/clustered.glsl + gbuffer0_tex sampler-2d @@ -59,10 +70,20 @@ 2 - depth_tex + gbuffer3_tex sampler-2d 3 + + + depth_tex + sampler-2d + 4 + + ao_tex sampler-2d @@ -73,36 +94,36 @@ bool ambient-occlusion-enabled - - debug_shadow_cascades - bool - show-shadow-cascades - - + shadow_tex sampler-2d-shadow 10 - - dfg_lut + debug_shadow_cascades + bool + show-shadow-cascades + + + + dfg_tex sampler-2d 8 - prefiltered_envmap + prefiltered_envmap_tex sampler-cube 9 - + - aerial_perspective_lut + aerial_perspective_tex sampler-2d 11 - transmittance_lut + transmittance_tex sampler-2d 12 diff --git a/Effects/HDR/smaa-blending-weight-calculation.eff b/Effects/HDR/smaa-blending-weight-calculation.eff index b39c02dc8..2a0fa4192 100644 --- a/Effects/HDR/smaa-blending-weight-calculation.eff +++ b/Effects/HDR/smaa-blending-weight-calculation.eff @@ -48,8 +48,8 @@ texture[2]/internal-format - Shaders/HDR/smaa-blending-weight-calculation.vert - Shaders/HDR/smaa-blending-weight-calculation.frag + Shaders/HDR/smaa_blending_weight_calculation.vert + Shaders/HDR/smaa_blending_weight_calculation.frag edges_tex diff --git a/Effects/HDR/smaa-edge-detection.eff b/Effects/HDR/smaa-edge-detection.eff index 9f56bbb83..ed54c6287 100644 --- a/Effects/HDR/smaa-edge-detection.eff +++ b/Effects/HDR/smaa-edge-detection.eff @@ -9,8 +9,8 @@ replace - Shaders/HDR/smaa-edge-detection.vert - Shaders/HDR/smaa-edge-detection.frag + Shaders/HDR/smaa_edge_detection.vert + Shaders/HDR/smaa_edge_detection.frag color_tex diff --git a/Effects/HDR/smaa-neighborhood-blending.eff b/Effects/HDR/smaa-neighborhood-blending.eff index 5e48b5dd8..3e6333073 100644 --- a/Effects/HDR/smaa-neighborhood-blending.eff +++ b/Effects/HDR/smaa-neighborhood-blending.eff @@ -4,8 +4,8 @@ - Shaders/HDR/smaa-neighborhood-blending.vert - Shaders/HDR/smaa-neighborhood-blending.frag + Shaders/HDR/smaa_neighborhood_blending.vert + Shaders/HDR/smaa_neighborhood_blending.frag color_tex diff --git a/Effects/HDR/trivial.eff b/Effects/HDR/trivial.eff index 1648f2f09..b79398c52 100644 --- a/Effects/HDR/trivial.eff +++ b/Effects/HDR/trivial.eff @@ -4,8 +4,8 @@ - Shaders/HDR/trivial.vert - Shaders/HDR/trivial.frag + Shaders/HDR/quad.vert + Shaders/HDR/quad.frag tex diff --git a/Effects/HDR/water-lighting.eff b/Effects/HDR/water-shading.eff similarity index 57% rename from Effects/HDR/water-lighting.eff rename to Effects/HDR/water-shading.eff index 221dfeb75..d0670c65e 100644 --- a/Effects/HDR/water-lighting.eff +++ b/Effects/HDR/water-shading.eff @@ -1,6 +1,6 @@ - Effects/HDR/water-lighting + Effects/HDR/water-shading @@ -8,10 +8,13 @@ 3 - Shaders/HDR/trivial.vert - Shaders/HDR/water-lighting.frag - Shaders/HDR/gbuffer-include.frag - Shaders/HDR/aerial-perspective-include.frag + Shaders/HDR/quad.vert + Shaders/HDR/water_shading.frag + Shaders/HDR/math.glsl + Shaders/HDR/normal_encoding.glsl + Shaders/HDR/pos_from_depth.glsl + Shaders/HDR/aerial_perspective.glsl + Shaders/HDR/atmos_spectral.glsl gbuffer0_tex @@ -23,24 +26,25 @@ sampler-2d 1 + + prefiltered_envmap_tex + sampler-cube + 9 + + depth_tex sampler-2d 3 + - prefiltered_envmap - sampler-cube - 9 - - - - aerial_perspective_lut + aerial_perspective_tex sampler-2d 11 - transmittance_lut + transmittance_tex sampler-2d 12 diff --git a/Effects/chrome.eff b/Effects/chrome.eff index c27164d73..cdd2d8552 100644 --- a/Effects/chrome.eff +++ b/Effects/chrome.eff @@ -83,12 +83,14 @@ opaque cull-face - Shaders/HDR/geometry-chrome.vert - Shaders/HDR/geometry-chrome.frag - Shaders/HDR/gbuffer-include.frag + Shaders/HDR/model_chrome.vert + Shaders/HDR/model_chrome.frag + Shaders/HDR/gbuffer_pack.glsl + Shaders/HDR/normal_encoding.glsl + hdr-shadow @@ -100,9 +102,10 @@ 4.0 - Shaders/HDR/geometry-shadow.vert - Shaders/HDR/geometry-shadow.frag + Shaders/HDR/model_shadow.vert + Shaders/HDR/model_shadow.frag + diff --git a/Effects/cloud-impostor.eff b/Effects/cloud-impostor.eff index 37b526d98..988fe4947 100644 --- a/Effects/cloud-impostor.eff +++ b/Effects/cloud-impostor.eff @@ -258,23 +258,25 @@ 1 transparent - Shaders/HDR/cloud-static.vert - Shaders/HDR/aerial-perspective-include.frag + Shaders/HDR/cloud_static.vert + Shaders/HDR/aerial_perspective.glsl + Shaders/HDR/atmos_spectral.glsl Shaders/HDR/3dcloud.frag + Shaders/HDR/aerial_perspective.glsl - baseTexture + base_tex sampler-2d 0 - + - aerial_perspective_lut + aerial_perspective_tex sampler-2d 11 - transmittance_lut + transmittance_tex sampler-2d 12 diff --git a/Effects/cloud-noctilucent.eff b/Effects/cloud-noctilucent.eff index ab049370f..d42fb1db9 100644 --- a/Effects/cloud-noctilucent.eff +++ b/Effects/cloud-noctilucent.eff @@ -178,23 +178,25 @@ 1 transparent - Shaders/HDR/cloud-static.vert - Shaders/HDR/aerial-perspective-include.frag + Shaders/HDR/cloud_static.vert + Shaders/HDR/aerial_perspective.glsl + Shaders/HDR/atmos_spectral.glsl Shaders/HDR/3dcloud.frag + Shaders/HDR/aerial_perspective.glsl - baseTexture + base_tex sampler-2d 0 - + - aerial_perspective_lut + aerial_perspective_tex sampler-2d 11 - transmittance_lut + transmittance_tex sampler-2d 12 diff --git a/Effects/cloud-static.eff b/Effects/cloud-static.eff index fcd85ec50..da0794bda 100644 --- a/Effects/cloud-static.eff +++ b/Effects/cloud-static.eff @@ -386,23 +386,25 @@ 1 transparent - Shaders/HDR/cloud-static.vert - Shaders/HDR/aerial-perspective-include.frag + Shaders/HDR/cloud_static.vert + Shaders/HDR/aerial_perspective.glsl + Shaders/HDR/atmos_spectral.glsl Shaders/HDR/3dcloud.frag + Shaders/HDR/aerial_perspective.glsl - baseTexture + base_tex sampler-2d 0 - + - aerial_perspective_lut + aerial_perspective_tex sampler-2d 11 - transmittance_lut + transmittance_tex sampler-2d 12 diff --git a/Effects/cloud.eff b/Effects/cloud.eff index 1cd17492e..e7ee2fad5 100644 --- a/Effects/cloud.eff +++ b/Effects/cloud.eff @@ -500,8 +500,10 @@ transparent Shaders/HDR/3dcloud.vert - Shaders/HDR/aerial-perspective-include.frag + Shaders/HDR/aerial_perspective.glsl + Shaders/HDR/atmos_spectral.glsl Shaders/HDR/3dcloud.frag + Shaders/HDR/aerial_perspective.glsl usrAttr1 10 @@ -512,7 +514,7 @@ - baseTexture + base_tex sampler-2d 0 @@ -526,14 +528,14 @@ float detail - + - aerial_perspective_lut + aerial_perspective_tex sampler-2d 11 - transmittance_lut + transmittance_tex sampler-2d 12 diff --git a/Effects/lfeat.eff b/Effects/lfeat.eff index 39655579e..22ea567b0 100644 --- a/Effects/lfeat.eff +++ b/Effects/lfeat.eff @@ -120,19 +120,21 @@ opaque back - Shaders/HDR/geometry-lfeat.vert - Shaders/HDR/geometry-lfeat.frag - Shaders/HDR/gbuffer-include.frag + Shaders/HDR/terrain_lfeat.vert + Shaders/HDR/terrain_lfeat.frag + Shaders/HDR/gbuffer_pack.glsl + Shaders/HDR/normal_encoding.glsl + Shaders/HDR/color.glsl color_tex sampler-2d 0 - - 2.0 - 1.0 - + + 2.0 + 1.0 + diff --git a/Effects/model-combined.eff b/Effects/model-combined.eff index 6572d17b7..d4c6abdd8 100644 --- a/Effects/model-combined.eff +++ b/Effects/model-combined.eff @@ -1338,9 +1338,11 @@ please see Docs/README.model-combined.eff for documentation back - Shaders/HDR/geometry-combined.vert - Shaders/HDR/geometry-combined.frag - Shaders/HDR/gbuffer-include.frag + Shaders/HDR/model_combined.vert + Shaders/HDR/model_combined.frag + Shaders/HDR/gbuffer_pack.glsl + Shaders/HDR/normal_encoding.glsl + Shaders/HDR/color.glsl color_tex diff --git a/Effects/model-default.eff b/Effects/model-default.eff index c32927a31..5942f9833 100644 --- a/Effects/model-default.eff +++ b/Effects/model-default.eff @@ -666,69 +666,71 @@ - - hdr-geometry - - - - gequal - 1.0 - 0.0 - - - always - 8 - replace - - - 0 - texture[0]/type - texture[0]/image - texture[0]/filter - texture[0]/wrap-s - texture[0]/wrap-t - - 0 - opaque - cull-face - - Shaders/HDR/geometry.vert - Shaders/HDR/geometry.frag - Shaders/HDR/gbuffer-include.frag - - - color_tex - sampler-2d - 0 - - - color_mode - int - material/color-mode - - - material_diffuse - float-vec4 - material/diffuse - - - + + hdr-geometry + + + + gequal + 1.0 + 0.0 + + + always + 8 + replace + + + 0 + texture[0]/type + texture[0]/image + texture[0]/filter + texture[0]/wrap-s + texture[0]/wrap-t + + 0 + opaque + cull-face + + Shaders/HDR/model_default.vert + Shaders/HDR/model_default.frag + Shaders/HDR/gbuffer_pack.glsl + Shaders/HDR/normal_encoding.glsl + Shaders/HDR/color.glsl + + + color_tex + sampler-2d + 0 + + + color_mode + int + material/color-mode + + + material_diffuse + float-vec4 + material/diffuse + + + - - hdr-shadow - - 0 0 0 0 - back - 0 - - 1.1 - 4.0 - - - Shaders/HDR/geometry-shadow.vert - Shaders/HDR/geometry-shadow.frag - - - + + hdr-shadow + + 0 0 0 0 + back + 0 + + 1.1 + 4.0 + + + Shaders/HDR/model_shadow.vert + Shaders/HDR/model_shadow.frag + + + diff --git a/Effects/model-pbr-transparent.eff b/Effects/model-pbr-transparent.eff index f2963bcf4..5b6d3e13f 100644 --- a/Effects/model-pbr-transparent.eff +++ b/Effects/model-pbr-transparent.eff @@ -5,18 +5,19 @@ Effects/model-pbr + + 1 + -1.0 + Textures/PBR/dfg_lut.dds - 2d + 2d linear linear clamp-to-edge clamp-to-edge normalized - - 1 - -1.0 @@ -76,7 +77,7 @@ 8 texture[8]/image - texture[8]/type + texture[8]/type texture[8]/filter texture[8]/mag-filter texture[8]/wrap-s @@ -87,12 +88,18 @@ transparent cull-face - Shaders/HDR/geometry-pbr-transparent.vert - Shaders/HDR/geometry-pbr-transparent.frag - Shaders/HDR/gbuffer-include.frag - Shaders/HDR/shadows-include.frag - Shaders/HDR/lighting-include.frag - Shaders/HDR/aerial-perspective-include.frag + Shaders/HDR/model_pbr_transparent.vert + Shaders/HDR/aerial_perspective.glsl + Shaders/HDR/model_pbr_transparent.frag + Shaders/HDR/color.glsl + Shaders/HDR/math.glsl + Shaders/HDR/shading_transparent.glsl + Shaders/HDR/surface.glsl + Shaders/HDR/ibl.glsl + Shaders/HDR/shadows.glsl + Shaders/HDR/aerial_perspective.glsl + Shaders/HDR/atmos_spectral.glsl + Shaders/HDR/clustered.glsl tangent 6 @@ -152,36 +159,36 @@ float alpha-cutoff - - - depth_tex - sampler-2d - 7 - + shadow_tex sampler-2d-shadow 10 - - dfg_lut + debug_shadow_cascades + bool + show-shadow-cascades + + + + dfg_tex sampler-2d 8 - prefiltered_envmap + prefiltered_envmap_tex sampler-cube 9 - + - aerial_perspective_lut + aerial_perspective_tex sampler-2d 11 - transmittance_lut + transmittance_tex sampler-2d 12 diff --git a/Effects/model-pbr.eff b/Effects/model-pbr.eff index f91eb37e2..8fc0dfb3c 100644 --- a/Effects/model-pbr.eff +++ b/Effects/model-pbr.eff @@ -89,9 +89,11 @@ opaque cull-face - Shaders/HDR/geometry-pbr.vert - Shaders/HDR/geometry-pbr.frag - Shaders/HDR/gbuffer-include.frag + Shaders/HDR/model_pbr.vert + Shaders/HDR/model_pbr.frag + Shaders/HDR/gbuffer_pack.glsl + Shaders/HDR/normal_encoding.glsl + Shaders/HDR/color.glsl tangent 6 @@ -160,8 +162,8 @@ 4.0 - Shaders/HDR/geometry-shadow.vert - Shaders/HDR/geometry-shadow.frag + Shaders/HDR/model_shadow.vert + Shaders/HDR/model_shadow.frag diff --git a/Effects/model-transparent.eff b/Effects/model-transparent.eff index 0ba8554be..cc692842f 100644 --- a/Effects/model-transparent.eff +++ b/Effects/model-transparent.eff @@ -9,7 +9,8 @@ DepthSortedBin false - + transparent + Textures/PBR/dfg_lut.dds 2d @@ -19,11 +20,6 @@ clamp-to-edge normalized - transparent - - 111 - DepthSortedBin - - - depth_tex - sampler-2d - 7 - + shadow_tex sampler-2d-shadow 10 - - dfg_lut + debug_shadow_cascades + bool + show-shadow-cascades + + + + dfg_tex sampler-2d 8 - prefiltered_envmap + prefiltered_envmap_tex sampler-cube 9 - + - aerial_perspective_lut + aerial_perspective_tex sampler-2d 11 - transmittance_lut + transmittance_tex sampler-2d 12 diff --git a/Effects/model-wingflex.eff b/Effects/model-wingflex.eff index 862a1b6e7..3c2c4bedf 100644 --- a/Effects/model-wingflex.eff +++ b/Effects/model-wingflex.eff @@ -1405,70 +1405,71 @@ - - hdr-geometry - - - + + hdr-geometry + + + gequal 1.0 0.0 - - + + always 8 replace - - + + 0 texture[0]/type texture[0]/image texture[0]/filter texture[0]/wrap-s texture[0]/wrap-t - - + + 1 texture[2]/type texture[2]/image texture[2]/filter texture[2]/wrap-s texture[2]/wrap-t - - back - - Shaders/HDR/geometry-combined.vert - Shaders/HDR/geometry-combined.frag - Shaders/HDR/gbuffer-include.frag - - + + back + + Shaders/HDR/model_combined.vert + Shaders/HDR/model_combined.frag + Shaders/HDR/gbuffer_pack.glsl + Shaders/HDR/normal_encoding.glsl + Shaders/HDR/color.glsl + + color_tex sampler-2d 0 - - + + normal_tex sampler-2d 1 - - + + normalmap_enabled int normalmap-enabled - - + + normalmap_dds int normalmap-dds - - + + normalmap_tiling float normalmap-tiling - - - - + + + false diff --git a/Effects/runway.eff b/Effects/runway.eff index a655b384b..35a6a1bde 100644 --- a/Effects/runway.eff +++ b/Effects/runway.eff @@ -925,9 +925,11 @@ opaque back - Shaders/HDR/geometry-runway.vert - Shaders/HDR/geometry-runway.frag - Shaders/HDR/gbuffer-include.frag + Shaders/HDR/terrain_runway.vert + Shaders/HDR/terrain_runway.frag + Shaders/HDR/gbuffer_pack.glsl + Shaders/HDR/normal_encoding.glsl + Shaders/HDR/color.glsl color_tex diff --git a/Effects/skydome.eff b/Effects/skydome.eff index f3adc3d83..63291f23f 100644 --- a/Effects/skydome.eff +++ b/Effects/skydome.eff @@ -314,6 +314,8 @@ Shaders/HDR/skydome.vert Shaders/HDR/skydome.frag + Shaders/HDR/math.glsl + Shaders/HDR/atmos_spectral.glsl sun_disk @@ -321,12 +323,12 @@ true - transmittance_lut + transmittance_tex sampler-2d 12 - sky_view_lut + sky_view_tex sampler-2d 13 @@ -342,6 +344,8 @@ Shaders/HDR/skydome.vert Shaders/HDR/skydome.frag + Shaders/HDR/math.glsl + Shaders/HDR/atmos_spectral.glsl sun_disk @@ -349,12 +353,12 @@ false - transmittance_lut + transmittance_tex sampler-2d 12 - sky_view_lut + sky_view_tex sampler-2d 13 diff --git a/Effects/terrain-default.eff b/Effects/terrain-default.eff index 5b4354c18..2e341320a 100644 --- a/Effects/terrain-default.eff +++ b/Effects/terrain-default.eff @@ -1695,9 +1695,11 @@ opaque back - Shaders/HDR/geometry-terrain.vert - Shaders/HDR/geometry-terrain.frag - Shaders/HDR/gbuffer-include.frag + Shaders/HDR/terrain_default.vert + Shaders/HDR/terrain_default.frag + Shaders/HDR/gbuffer_pack.glsl + Shaders/HDR/normal_encoding.glsl + Shaders/HDR/color.glsl color_tex diff --git a/Effects/water.eff b/Effects/water.eff index 66bc48143..24adddc16 100644 --- a/Effects/water.eff +++ b/Effects/water.eff @@ -1494,127 +1494,128 @@ - hdr-geometry - - - - gequal - 1.0 - 0.0 - - - always - 3 - replace - - 0 - back - - render-bin/bin-number - render-bin/bin-name - - - 0 - texture[2]/image - texture[2]/type - texture[2]/filter - texture[2]/wrap-s - texture[2]/wrap-t - texture[2]/internal-format - - - 1 - texture[3]/image - texture[3]/type - texture[3]/filter - texture[3]/wrap-s - texture[3]/wrap-t - texture[3]/internal-format - - - 2 - texture[6]/image - texture[6]/type - texture[6]/filter - texture[6]/wrap-s - texture[6]/wrap-t - texture[6]/internal-format - - - 3 - texture[8]/image - texture[8]/type - texture[8]/filter - texture[8]/wrap-s - texture[8]/wrap-t - texture[8]/internal-format - - - Shaders/HDR/geometry-water.vert - Shaders/HDR/geometry-water.frag - Shaders/HDR/gbuffer-include.frag - - - water_normalmap - sampler-2d - 0 - - - water_dudvmap - sampler-2d - 1 - - - perlin_normalmap - sampler-2d - 2 - - - water_colormap - sampler-2d - 3 - - - WindE - float - windE - - - WindN - float - windN - - - WaveFreq - float - WaveFreq - - - WaveAmp - float - WaveAmp - - - WaveSharp - float - WaveSharp - - - WaveAngle - float - WaveAngle - - - WaveFactor - float - WaveFactor - - - WaveDAngle - float - WaveDAngle - - + hdr-geometry + + + + gequal + 1.0 + 0.0 + + + always + 3 + replace + + 0 + back + + render-bin/bin-number + render-bin/bin-name + + + 0 + texture[2]/image + texture[2]/type + texture[2]/filter + texture[2]/wrap-s + texture[2]/wrap-t + texture[2]/internal-format + + + 1 + texture[3]/image + texture[3]/type + texture[3]/filter + texture[3]/wrap-s + texture[3]/wrap-t + texture[3]/internal-format + + + 2 + texture[6]/image + texture[6]/type + texture[6]/filter + texture[6]/wrap-s + texture[6]/wrap-t + texture[6]/internal-format + + + 3 + texture[8]/image + texture[8]/type + texture[8]/filter + texture[8]/wrap-s + texture[8]/wrap-t + texture[8]/internal-format + + + Shaders/HDR/water.vert + Shaders/HDR/water.frag + Shaders/HDR/normal_encoding.glsl + Shaders/HDR/color.glsl + + + water_normalmap + sampler-2d + 0 + + + water_dudvmap + sampler-2d + 1 + + + perlin_normalmap + sampler-2d + 2 + + + water_colormap + sampler-2d + 3 + + + WindE + float + windE + + + WindN + float + windN + + + WaveFreq + float + WaveFreq + + + WaveAmp + float + WaveAmp + + + WaveSharp + float + WaveSharp + + + WaveAngle + float + WaveAngle + + + WaveFactor + float + WaveFactor + + + WaveDAngle + float + WaveDAngle + + diff --git a/Effects/ws30.eff b/Effects/ws30.eff index 2776347af..ab771c9b2 100644 --- a/Effects/ws30.eff +++ b/Effects/ws30.eff @@ -1874,100 +1874,4 @@ - - hdr-geometry - - - - gequal - 1.0 - 0.0 - - - always - 9 - replace - - - transparent - transparent - smooth - back - - render-bin/bin-number - render-bin/bin-name - - - - - - 1 - texture[1]/image - nearest-mipmap-nearest - nearest-mipmap-nearest - texture[0]/wrap-s - texture[0]/wrap-t - texture[0]/internal-format - - - - 2 - texture[2]/image - texture[2]/filter - texture[2]/wrap-s - texture[2]/wrap-t - texture[2]/internal-format - - - - 3 - texture[3]/image - texture[3]/filter - texture[3]/wrap-s - texture[3]/wrap-t - texture[3]/internal-format - - - - 4 - texture[4]/image - texture[4]/filter - texture[4]/wrap-s - texture[4]/wrap-t - texture[4]/internal-format - - - - 6 - texture[6]/image - texture[6]/filter - texture[6]/wrap-s - texture[6]/wrap-t - texture[6]/internal-format - - - - Shaders/HDR/geometry.vert - Shaders/HDR/ws30.frag - Shaders/HDR/gbuffer-include.frag - - - - landclass - sampler-2d - 0 - - - atlas - sampler-2d - 1 - - - perlin - sampler-2d - 6 - - - - diff --git a/Shaders/HDR/3dcloud.frag b/Shaders/HDR/3dcloud.frag index d3998b735..d3d8798e0 100644 --- a/Shaders/HDR/3dcloud.frag +++ b/Shaders/HDR/3dcloud.frag @@ -1,24 +1,28 @@ #version 330 core -out vec4 fragColor; +layout(location = 0) out vec4 fragColor; -in vec2 texCoord; -in vec4 cloudColor; +in vec2 texcoord; +in vec4 cloud_color; +in vec4 ap_color; -uniform sampler2D baseTexture; +uniform sampler2D base_tex; uniform mat4 osg_ProjectionMatrix; uniform vec4 fg_Viewport; uniform vec3 fg_SunDirection; -const int STEPS = 8; - uniform float density = 30.0; uniform float max_sample_dist = 0.05; +const int STEPS = 8; + +// aerial_perspective.glsl +vec3 mix_aerial_perspective(vec3 color, vec4 ap); + void main() { - vec4 base = texture(baseTexture, texCoord); + vec4 base = texture(base_tex, texcoord); // Directly discard fragments below a threshold if (base.a < 0.02) @@ -43,8 +47,8 @@ void main() float T = 1.0; for (int i = 0; i < STEPS; ++i) { float t = (float(i) + 0.5) * dt; - vec2 uv_t = texCoord - sun_dir * t; - vec4 texel = texture(baseTexture, uv_t); + vec2 uv_t = texcoord - sun_dir * t; + vec4 texel = texture(base_tex, uv_t); // Beer-Lambert's law T *= exp(-texel.a * dt * density); } @@ -54,8 +58,10 @@ void main() // the perpendicular. float fade = smoothstep(0.1, 0.5, dot(vec3(0.0, 0.0, -1.0), fg_SunDirection)); - vec4 color = base * cloudColor; + vec4 color = base * cloud_color; color.rgb *= base.a * mix(1.0, T, fade); + color.rgb = mix_aerial_perspective(color.rgb, ap_color); + fragColor = color; } diff --git a/Shaders/HDR/3dcloud.vert b/Shaders/HDR/3dcloud.vert index 82bc0a8b2..74a9bf22e 100644 --- a/Shaders/HDR/3dcloud.vert +++ b/Shaders/HDR/3dcloud.vert @@ -1,13 +1,14 @@ #version 330 core layout(location = 0) in vec4 pos; -layout(location = 2) in vec4 vertexColor; -layout(location = 3) in vec4 multiTexCoord0; +layout(location = 2) in vec4 vertex_color; +layout(location = 3) in vec4 multitexcoord0; layout(location = 10) in vec4 usrAttr1; layout(location = 11) in vec4 usrAttr2; -out vec2 texCoord; -out vec4 cloudColor; +out vec2 texcoord; +out vec4 cloud_color; +out vec4 ap_color; uniform float range; uniform float detail_range; @@ -17,8 +18,8 @@ uniform mat4 osg_ModelViewProjectionMatrix; uniform mat4 osg_ViewMatrixInverse; uniform vec3 fg_SunDirectionWorld; -// aerial-perspective-include.frag -vec3 add_aerial_perspective(vec3 color, vec2 coord, float depth); +// aerial_perspective.glsl +vec4 get_aerial_perspective(vec2 coord, float depth); vec3 get_sun_radiance(vec3 p); void main() @@ -30,7 +31,7 @@ void main() float middle_factor = usrAttr2.g; float top_factor = usrAttr2.b; - texCoord = multiTexCoord0.st; + texcoord = multitexcoord0.st; // XXX: Should be sent as an uniform mat4 inverseModelViewMatrix = inverse(osg_ModelViewMatrix); @@ -52,20 +53,20 @@ void main() final_pos.xyz += pos.y * r; final_pos.xyz += pos.z * w; // Apply Z scaling to allow sprites to be squashed in the z-axis - final_pos.z = final_pos.z * vertexColor.w; + final_pos.z = final_pos.z * vertex_color.w; // Now shift the sprite to the correct position in the cloud. - final_pos.xyz += vertexColor.xyz; + final_pos.xyz += vertex_color.xyz; // Determine the position - used for fog and shading calculations - float fogCoord = length(vec3(osg_ModelViewMatrix * vec4(vertexColor.xyz, 1.0))); + float fogCoord = length(vec3(osg_ModelViewMatrix * vec4(vertex_color.xyz, 1.0))); float center_dist = length(vec3(osg_ModelViewMatrix * vec4(0.0, 0.0, 0.0, 1.0))); if ((fogCoord > detail_range) && (fogCoord > center_dist) && (shade_factor < 0.7)) { // More than detail_range away, so discard all sprites on opposite side of // cloud center by shifting them beyond the view fustrum gl_Position = vec4(0.0, 0.0, 10.0, 1.0); - cloudColor = vec4(0.0); + cloud_color = vec4(0.0); } else { gl_Position = osg_ModelViewProjectionMatrix * final_pos; @@ -91,26 +92,25 @@ void main() final_pos.z * 2.0 / cloud_height - 1.0)); } - cloudColor.rgb = shade * get_sun_radiance(final_world_pos.xyz); + cloud_color.rgb = shade * get_sun_radiance(final_world_pos.xyz); // Perspective division and scale to [0, 1] to get the screen position // of the vertex. vec2 coord = (gl_Position.xy / gl_Position.w) * 0.5 + 0.5; - cloudColor.rgb = add_aerial_perspective( - cloudColor.rgb, coord, length(final_view_pos)); + ap_color = get_aerial_perspective(coord, length(final_view_pos)); if ((fogCoord > (0.9 * detail_range)) && (fogCoord > center_dist) && (shade_factor < 0.7)) { // cloudlet is almost at the detail range, so fade it out. - cloudColor.a = 1.0 - smoothstep(0.9 * detail_range, detail_range, fogCoord); + cloud_color.a = 1.0 - smoothstep(0.9 * detail_range, detail_range, fogCoord); } else { // As we get within 100m of the sprite, it is faded out. // Equally at large distances it also fades out. - cloudColor.a = min(smoothstep(10.0, 100.0, fogCoord), + cloud_color.a = min(smoothstep(10.0, 100.0, fogCoord), 1.0 - smoothstep(0.9 * range, range, fogCoord)); } - cloudColor.a *= alpha_factor; + cloud_color.a *= alpha_factor; } } diff --git a/Shaders/HDR/aces.glsl b/Shaders/HDR/aces.glsl new file mode 100644 index 000000000..c28460cbd --- /dev/null +++ b/Shaders/HDR/aces.glsl @@ -0,0 +1,28 @@ +/* + * ACES tone mapping + * From 'Baking Lab' by MJP and David Neubelt + * Original by Stephen Hill + * https://github.com/TheRealMJP/BakingLab/blob/master/BakingLab/ACES.hlsl + * Licensed under the MIT license + */ + +#version 330 core + +// sRGB => XYZ => D65_2_D60 => AP1 => RRT_SAT +const mat3 ACESInputMat = mat3( + 0.59719, 0.07600, 0.02840, + 0.35458, 0.90834, 0.13383, + 0.04823, 0.01566, 0.83777); +// ODT_SAT => XYZ => D60_2_D65 => sRGB +const mat3 ACESOutputMat = mat3( + 1.60475, -0.10208, -0.00327, + -0.53108, 1.10813, -0.07276, + -0.07367, -0.00605, 1.07602); + +vec3 aces_fitted(vec3 color) +{ + vec3 v = ACESInputMat * color; + vec3 a = v * (v + 0.0245786) - 0.000090537; + vec3 b = v * (0.983729 * v + 0.4329510) + 0.238081; + return clamp(ACESOutputMat * (a / b), 0.0, 1.0); +} diff --git a/Shaders/HDR/aerial-perspective-include.frag b/Shaders/HDR/aerial_perspective.glsl similarity index 71% rename from Shaders/HDR/aerial-perspective-include.frag rename to Shaders/HDR/aerial_perspective.glsl index a56a0983f..f9200f56f 100644 --- a/Shaders/HDR/aerial-perspective-include.frag +++ b/Shaders/HDR/aerial_perspective.glsl @@ -1,7 +1,7 @@ #version 330 core -uniform sampler2D aerial_perspective_lut; -uniform sampler2D transmittance_lut; +uniform sampler2D aerial_perspective_tex; +uniform sampler2D transmittance_tex; uniform vec3 fg_SunDirectionWorld; uniform float fg_CameraDistanceToEarthCenter; @@ -16,25 +16,9 @@ const float AP_TEXEL_WIDTH = 1.0 / (AP_SLICE_COUNT * AP_SLICE_WIDTH_PIXELS); const float ATMOSPHERE_RADIUS = 6471e3; -//-- BEGIN spectral include - -// Extraterrestial Solar Irradiance Spectra, units W * m^-2 * nm^-1 -// https://www.nrel.gov/grid/solar-resource/spectra.html -const vec4 sun_spectral_irradiance = vec4(1.679, 1.828, 1.986, 1.307); - -const mat4x3 M = mat4x3( - 137.672389239975, -8.632904716299537, -1.7181567391931372, - 32.549094028629234, 91.29801417199785, -12.005406444382531, - -38.91428392614275, 34.31665471469816, 29.89044807197628, - 8.572844237945445, -11.103384660054624, 117.47585277566478 - ); - -vec3 linear_srgb_from_spectral_samples(vec4 L) -{ - return M * L; -} - -//-- END spectral include +// atmos_spectral.glsl +vec4 get_sun_spectral_irradiance(); +vec3 linear_srgb_from_spectral_samples(vec4 L); vec4 sample_aerial_perspective_slice(sampler2D lut, vec2 coord, float slice) { @@ -64,10 +48,19 @@ vec4 sample_aerial_perspective(sampler2D lut, vec2 coord, float depth) return color; } +vec4 get_aerial_perspective(vec2 coord, float depth) +{ + return sample_aerial_perspective(aerial_perspective_tex, coord, depth); +} + +vec3 mix_aerial_perspective(vec3 color, vec4 ap) +{ + return color * ap.a + ap.rgb; +} + vec3 add_aerial_perspective(vec3 color, vec2 coord, float depth) { - vec4 ap = sample_aerial_perspective(aerial_perspective_lut, coord, depth); - return color * ap.a + ap.rgb; + return mix_aerial_perspective(color, get_aerial_perspective(coord, depth)); } /* @@ -86,8 +79,16 @@ vec3 get_sun_radiance(vec3 p) float u = sun_cos_theta * 0.5 + 0.5; float v = clamp(normalized_altitude, 0.0, 1.0); - vec4 transmittance = texture(transmittance_lut, vec2(u, v)); + vec4 transmittance = texture(transmittance_tex, vec2(u, v)); - vec4 L = sun_spectral_irradiance * transmittance; + vec4 L = get_sun_spectral_irradiance() * transmittance; + return linear_srgb_from_spectral_samples(L); +} + +vec3 get_sun_radiance_sea_level() +{ + vec2 uv = vec2(fg_SunZenithCosTheta * 0.5 + 0.5, 0.0); + vec4 transmittance = texture(transmittance_tex, uv); + vec4 L = get_sun_spectral_irradiance() * transmittance; return linear_srgb_from_spectral_samples(L); } diff --git a/Shaders/HDR/ao.frag b/Shaders/HDR/ao.frag deleted file mode 100644 index cef44289d..000000000 --- a/Shaders/HDR/ao.frag +++ /dev/null @@ -1,73 +0,0 @@ -#version 330 core -#pragma optionNV (unroll all) - -out float fragColor; - -in vec2 texCoord; - -uniform sampler2D gbuffer0_tex; -uniform sampler2D depth_tex; - -uniform mat4 fg_ProjectionMatrix; - -const float RADIUS = 0.04; -const float BIAS = 0.05; -const float SCALE = 3.0; -const float MAX_DISTANCE = 0.08; -const float INTENSITY = 1.5; - -const vec2 kernel[4] = vec2[]( - vec2( 0.0, 1.0), // top - vec2( 1.0, 0.0), // right - vec2( 0.0, -1.0), // bottom - vec2(-1.0, 0.0)); // left - -vec3 decodeNormal(vec2 f); -vec3 positionFromDepth(vec2 pos, float depth); - -float rand(vec2 co) { - return fract(sin(dot(co.xy, vec2(12.9898,78.233))) * 43758.5453); -} - -float sampleAO(vec3 fragPos, vec3 normal, vec2 coords) -{ - float sampleDepth = texture(depth_tex, coords).r; - vec3 samplePoint = positionFromDepth(coords, sampleDepth); - - vec3 diff = samplePoint - fragPos; - float l = length(diff); - vec3 v = diff / l; - float d = l * SCALE; - - float ao = max(0.0, dot(normal, v) - BIAS) * (1.0 / (1.0 + d)); - ao *= smoothstep(MAX_DISTANCE, MAX_DISTANCE * 0.5, l); - return ao; -} - -void main() -{ - vec4 gbuffer0 = texture(gbuffer0_tex, texCoord); - float depth = texture(depth_tex, texCoord).r; - - 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)); - - const float sin45 = 0.707107; - - float occlusion = 0.0; - for (int i = 0; i < 4; ++i) { - vec2 k1 = reflect(kernel[i], randomVec) * RADIUS; - vec2 k2 = vec2(k1.x * sin45 - k1.y * sin45, k1.x * sin45 + k1.y * sin45); - occlusion += sampleAO(fragPos, normal, texCoord + k1); - occlusion += sampleAO(fragPos, normal, texCoord + k2 * 0.75); - occlusion += sampleAO(fragPos, normal, texCoord + k1 * 0.5); - occlusion += sampleAO(fragPos, normal, texCoord + k2 * 0.25); - } - occlusion /= 16.0; - - fragColor = clamp(1.0 - occlusion * INTENSITY, 0.0, 1.0); -} diff --git a/Shaders/HDR/atmos-include.frag b/Shaders/HDR/atmos.glsl similarity index 90% rename from Shaders/HDR/atmos-include.frag rename to Shaders/HDR/atmos.glsl index 991f9a4fe..8d40c2b0e 100644 --- a/Shaders/HDR/atmos-include.frag +++ b/Shaders/HDR/atmos.glsl @@ -1,14 +1,13 @@ #version 330 core -const float PI = 3.14159265358979323846; -const float INV_PI = 0.31830988618379067154; -const float INV_4PI = 0.25 * INV_PI; -const float PHASE_ISOTROPIC = INV_4PI; -const float RAYLEIGH_PHASE_SCALE = (3.0 / 16.0) * INV_PI; -const float g = 0.8; -const float gg = g*g; +// math.glsl +float M_PI(); +float M_1_PI(); +float M_1_4PI(); -const float ATMOSPHERE_RADIUS = 6471e3; +const float RAYLEIGH_PHASE_SCALE = 0.05968310365946075091; // 3/(16*pi) +const float HENYEY_ASYMMETRY = 0.8; +const float HENYEY_ASYMMETRY2 = HENYEY_ASYMMETRY*HENYEY_ASYMMETRY; // Rayleigh scattering coefficient at sea level, units m^-1 // "Rayleigh-scattering calculations for the terrestrial atmosphere" @@ -77,9 +76,19 @@ uniform float fg_EarthRadius; //------------------------------------------------------------------------------ +float get_earth_radius() +{ + return fg_EarthRadius; +} + +float get_atmosphere_radius() +{ + return 6471e3; // m +} + /* * Helper function to obtain the transmittance to the top of the atmosphere - * from Buffer A. + * from the precomputed transmittance LUT. */ vec4 transmittance_from_lut(sampler2D lut, float cos_theta, float normalized_altitude) { @@ -117,8 +126,8 @@ float molecular_phase_function(float cos_theta) */ float aerosol_phase_function(float cos_theta) { - float den = 1.0 + gg + 2.0 * g * cos_theta; - return INV_4PI * (1.0 - gg) / (den * sqrt(den)); + float den = 1.0 + HENYEY_ASYMMETRY2 + 2.0 * HENYEY_ASYMMETRY * cos_theta; + return M_1_4PI() * (1.0 - HENYEY_ASYMMETRY2) / (den * sqrt(den)); } /* @@ -132,7 +141,7 @@ vec4 get_multiple_scattering(sampler2D transmittance_lut, { // Solid angle subtended by the planet from a point at d distance // from the planet center. - float omega = 2.0 * PI * (1.0 - sqrt(d*d - fg_EarthRadius*fg_EarthRadius) / d); + float omega = 2.0 * M_PI() * (1.0 - sqrt(d*d - get_earth_radius()*fg_EarthRadius) / d); omega = max(0.0, omega); vec4 T_to_ground = transmittance_from_lut(transmittance_lut, cos_theta, 0.0); @@ -142,7 +151,7 @@ vec4 get_multiple_scattering(sampler2D transmittance_lut, transmittance_from_lut(transmittance_lut, 1.0, normalized_height); // 2nd order scattering from the ground - vec4 L_ground = PHASE_ISOTROPIC * omega * (ground_albedo * INV_PI) + vec4 L_ground = M_1_4PI() * omega * (ground_albedo * M_1_PI()) * T_to_ground * T_ground_to_sample * max(0.0, cos_theta); // Fit of Earth's multiple scattering coming from other points in the atmosphere @@ -230,11 +239,11 @@ vec4 compute_inscattering(in vec3 ray_origin, // 3. Any object within the atmosphere. float ray_altitude = length(ray_origin); // Handle the camera being underground - float earth_radius = min(ray_altitude, fg_EarthRadius); - float atmos_dist = ray_sphere_intersection(ray_origin, ray_dir, ATMOSPHERE_RADIUS); + float earth_radius = min(ray_altitude, get_earth_radius()); + float atmos_dist = ray_sphere_intersection(ray_origin, ray_dir, get_atmosphere_radius()); float ground_dist = ray_sphere_intersection(ray_origin, ray_dir, earth_radius); float t_d; - if (ray_altitude < ATMOSPHERE_RADIUS) { + if (ray_altitude < get_atmosphere_radius()) { // We are inside the atmosphere if (ground_dist < 0.0) { // No ground collision, use the distance to the outer atmosphere @@ -269,8 +278,8 @@ vec4 compute_inscattering(in vec3 ray_origin, float distance_to_earth_center = length(x_t); vec3 zenith_dir = x_t / distance_to_earth_center; - float altitude = distance_to_earth_center - fg_EarthRadius; - float normalized_altitude = altitude / (ATMOSPHERE_RADIUS - fg_EarthRadius); + float altitude = distance_to_earth_center - get_earth_radius(); + float normalized_altitude = altitude / (get_atmosphere_radius() - get_earth_radius()); float sample_cos_theta = dot(zenith_dir, sun_dir); diff --git a/Shaders/HDR/atmos-aerial-perspective.frag b/Shaders/HDR/atmos_aerial_perspective.frag similarity index 53% rename from Shaders/HDR/atmos-aerial-perspective.frag rename to Shaders/HDR/atmos_aerial_perspective.frag index 93f7d3427..00009f3af 100644 --- a/Shaders/HDR/atmos-aerial-perspective.frag +++ b/Shaders/HDR/atmos_aerial_perspective.frag @@ -1,17 +1,19 @@ -// Render the aerial perspective LUT, similar to -// "A Scalable and Production Ready Sky and Atmosphere Rendering Technique" -// by Sébastien Hillaire (2020). -// -// Unlike the paper, we are using a tiled 2D texture instead of a true 3D -// texture. For some reason the overhead of rendering to a texture many times -// (the depth of the 3D texture) seems to be too high, probably because OSG is -// not sharing state between those passes. +/* + * Render the aerial perspective LUT, similar to + * "A Scalable and Production Ready Sky and Atmosphere Rendering Technique" + * by Sébastien Hillaire (2020). + * + * Unlike the paper, we are using a tiled 2D texture instead of a true 3D + * texture. For some reason the overhead of rendering to a texture many times + * (the depth of the 3D texture) seems to be too high, probably because OSG is + * not sharing state between those passes. + */ #version 330 core -out vec4 fragColor; +layout(location = 0) out vec4 fragColor; -in vec2 texCoord; +in vec2 texcoord; uniform sampler2D transmittance_lut; @@ -23,10 +25,9 @@ const float AP_SLICE_COUNT = 32.0; const float AP_MAX_DEPTH = 128000.0; const int AERIAL_PERSPECTIVE_STEPS = 20; -// gbuffer-include.frag -vec3 positionFromDepth(vec2 pos, float depth); - -// atmos-include.frag +// pos_from_depth.glsl +vec3 get_view_space_from_depth(vec2 uv, float depth); +// atmos.glsl vec4 compute_inscattering(in vec3 ray_origin, in vec3 ray_dir, in float t_max, @@ -34,41 +35,23 @@ vec4 compute_inscattering(in vec3 ray_origin, in int steps, in sampler2D transmittance_lut, out vec4 transmittance); - -//-- BEGIN spectral include - -// Extraterrestial Solar Irradiance Spectra, units W * m^-2 * nm^-1 -// https://www.nrel.gov/grid/solar-resource/spectra.html -const vec4 sun_spectral_irradiance = vec4(1.679, 1.828, 1.986, 1.307); - -const mat4x3 M = mat4x3( - 137.672389239975, -8.632904716299537, -1.7181567391931372, - 32.549094028629234, 91.29801417199785, -12.005406444382531, - -38.91428392614275, 34.31665471469816, 29.89044807197628, - 8.572844237945445, -11.103384660054624, 117.47585277566478 - ); - -vec3 linear_srgb_from_spectral_samples(vec4 L) -{ - return M * L; -} - -//-- END spectral include - +// atmos_spectral.glsl +vec4 get_sun_spectral_irradiance(); +vec3 linear_srgb_from_spectral_samples(vec4 L); void main() { // Account for the depth slice we are currently in. Depth goes from 0 to // DEPTH_RANGE in a squared distribution. The first slice is not 0 since // that would waste a slice. - float x = texCoord.x * AP_SLICE_COUNT; + float x = texcoord.x * AP_SLICE_COUNT; float slice = ceil(x); float w = slice / AP_SLICE_COUNT; // [0,1] float depth = w*w * AP_MAX_DEPTH; - vec2 coord = vec2(fract(x), texCoord.y); + vec2 coord = vec2(fract(x), texcoord.y); - vec3 frag_pos = positionFromDepth(coord, 1.0); + vec3 frag_pos = get_view_space_from_depth(coord, 1.0); vec3 ray_dir = vec4(fg_ViewMatrixInverse * vec4(normalize(frag_pos), 0.0)).xyz; vec4 transmittance; @@ -80,7 +63,8 @@ void main() transmittance_lut, transmittance); // In-scattering - fragColor.rgb = linear_srgb_from_spectral_samples(L * sun_spectral_irradiance); + fragColor.rgb = linear_srgb_from_spectral_samples( + L * get_sun_spectral_irradiance()); // Transmittance fragColor.a = dot(transmittance, vec4(0.25)); } diff --git a/Shaders/HDR/atmos-sky-view.frag b/Shaders/HDR/atmos_sky_view.frag similarity index 84% rename from Shaders/HDR/atmos-sky-view.frag rename to Shaders/HDR/atmos_sky_view.frag index a6d2b1d2b..356643c51 100644 --- a/Shaders/HDR/atmos-sky-view.frag +++ b/Shaders/HDR/atmos_sky_view.frag @@ -1,17 +1,20 @@ #version 330 core -out vec4 fragColor; +layout(location = 0) out vec4 fragColor; -in vec2 texCoord; +in vec2 texcoord; uniform sampler2D transmittance_lut; + uniform float fg_SunZenithCosTheta; uniform float fg_CameraDistanceToEarthCenter; -const float PI = 3.14159265358979323846; const int SKY_STEPS = 32; -// atmos-include.frag +// math.glsl +float M_2PI(); +float M_PI_2(); +// atmos.glsl vec4 compute_inscattering(in vec3 ray_origin, in vec3 ray_dir, in float t_max, @@ -30,11 +33,11 @@ void main() 0.0, fg_SunZenithCosTheta); - float azimuth = 2.0 * PI * texCoord.x; // [0, 2pi] + float azimuth = M_2PI() * texcoord.x; // [0, 2pi] // Apply a non-linear transformation to the elevation to dedicate more // texels to the horizon, where having more detail matters. - float l = texCoord.y * 2.0 - 1.0; - float elev = l*l * sign(l) * PI * 0.5; // [-pi/2, pi/2] + float l = texcoord.y * 2.0 - 1.0; + float elev = l*l * sign(l) * M_PI_2(); // [-pi/2, pi/2] vec3 ray_dir = vec3(cos(elev) * cos(azimuth), cos(elev) * sin(azimuth), diff --git a/Shaders/HDR/atmos_spectral.glsl b/Shaders/HDR/atmos_spectral.glsl new file mode 100644 index 000000000..4f47bfdcb --- /dev/null +++ b/Shaders/HDR/atmos_spectral.glsl @@ -0,0 +1,22 @@ +#version 330 core + +// Extraterrestial Solar Irradiance Spectra, units W * m^-2 * nm^-1 +// https://www.nrel.gov/grid/solar-resource/spectra.html +const vec4 sun_spectral_irradiance = vec4(1.679, 1.828, 1.986, 1.307); + +const mat4x3 M = mat4x3( + 137.672389239975, -8.632904716299537, -1.7181567391931372, + 32.549094028629234, 91.29801417199785, -12.005406444382531, + -38.91428392614275, 34.31665471469816, 29.89044807197628, + 8.572844237945445, -11.103384660054624, 117.47585277566478 + ); + +vec4 get_sun_spectral_irradiance() +{ + return sun_spectral_irradiance; +} + +vec3 linear_srgb_from_spectral_samples(vec4 L) +{ + return M * L; +} diff --git a/Shaders/HDR/atmos-transmittance.frag b/Shaders/HDR/atmos_transmittance.frag similarity index 73% rename from Shaders/HDR/atmos-transmittance.frag rename to Shaders/HDR/atmos_transmittance.frag index dee2b22a1..379b7fcbe 100644 --- a/Shaders/HDR/atmos-transmittance.frag +++ b/Shaders/HDR/atmos_transmittance.frag @@ -1,15 +1,14 @@ #version 330 core -out vec4 fragColor; +layout(location = 0) out vec4 fragColor; -in vec2 texCoord; +in vec2 texcoord; -uniform float fg_EarthRadius; - -const float ATMOSPHERE_RADIUS = 6471e3; const int TRANSMITTANCE_STEPS = 40; -// atmos-include.frag +// atmos.glsl +float get_earth_radius(); +float get_atmosphere_radius(); float ray_sphere_intersection(vec3 ro, vec3 rd, float radius); void get_atmosphere_collision_coefficients(in float h, out vec4 aerosol_absorption, @@ -20,13 +19,15 @@ void get_atmosphere_collision_coefficients(in float h, void main() { - float sun_cos_theta = texCoord.x * 2.0 - 1.0; + float sun_cos_theta = texcoord.x * 2.0 - 1.0; vec3 sun_dir = vec3(-sqrt(1.0 - sun_cos_theta*sun_cos_theta), 0.0, sun_cos_theta); - float distance_to_earth_center = mix(fg_EarthRadius, ATMOSPHERE_RADIUS, texCoord.y); + float distance_to_earth_center = mix(get_earth_radius(), + get_atmosphere_radius(), + texcoord.y); vec3 ray_origin = vec3(0.0, 0.0, distance_to_earth_center); - float t_d = ray_sphere_intersection(ray_origin, sun_dir, ATMOSPHERE_RADIUS); + float t_d = ray_sphere_intersection(ray_origin, sun_dir, get_atmosphere_radius()); float dt = t_d / float(TRANSMITTANCE_STEPS); vec4 result = vec4(0.0); @@ -35,7 +36,7 @@ void main() float t = (float(i) + 0.5) * dt; vec3 x_t = ray_origin + sun_dir * t; - float altitude = length(x_t) - fg_EarthRadius; + float altitude = length(x_t) - get_earth_radius(); vec4 aerosol_absorption, aerosol_scattering; vec4 molecular_absorption, molecular_scattering; diff --git a/Shaders/HDR/bloom-threshold.frag b/Shaders/HDR/bloom-threshold.frag deleted file mode 100644 index e5a0bed5f..000000000 --- a/Shaders/HDR/bloom-threshold.frag +++ /dev/null @@ -1,24 +0,0 @@ -#version 330 core - -out vec3 fragColor; - -in vec2 texCoord; - -uniform sampler2D hdr_tex; -uniform sampler2D lum_tex; - -uniform float bloom_threshold; - -vec3 applyExposure(vec3 color, float avgLuminance, float threshold); - -void main() -{ - vec3 hdrColor = texture(hdr_tex, texCoord).rgb; - float avgLuminance = texelFetch(lum_tex, ivec2(0), 0).r; - - vec3 exposedHdrColor = applyExposure(hdrColor, avgLuminance, bloom_threshold); - if (dot(exposedHdrColor, vec3(0.333)) <= 0.001) - fragColor = vec3(0.0); - else - fragColor = exposedHdrColor; -} diff --git a/Shaders/HDR/bloom_threshold.frag b/Shaders/HDR/bloom_threshold.frag new file mode 100644 index 000000000..4140d75b7 --- /dev/null +++ b/Shaders/HDR/bloom_threshold.frag @@ -0,0 +1,25 @@ +#version 330 core + +layout(location = 0) out vec3 fragColor; + +in vec2 texcoord; + +uniform sampler2D hdr_tex; +uniform sampler2D lum_tex; + +uniform float bloom_threshold; + +// exposure.glsl +vec3 apply_exposure(vec3 color, float avg_lum, float threshold); + +void main() +{ + vec3 hdr_color = texture(hdr_tex, texcoord).rgb; + float avg_lum = texelFetch(lum_tex, ivec2(0), 0).r; + + vec3 exposed_hdr_color = apply_exposure(hdr_color, avg_lum, bloom_threshold); + if (dot(exposed_hdr_color, vec3(0.333)) <= 0.001) + fragColor = vec3(0.0); + else + fragColor = exposed_hdr_color; +} diff --git a/Shaders/HDR/blur.frag b/Shaders/HDR/blur.frag index e7b4c887a..de372e74e 100644 --- a/Shaders/HDR/blur.frag +++ b/Shaders/HDR/blur.frag @@ -1,8 +1,8 @@ #version 330 core -out vec4 fragColor; +layout(location = 0) out vec4 fragColor; -in vec2 texCoord; +in vec2 texcoord; uniform sampler2D tex; uniform sampler2D prev_pass_tex; @@ -15,19 +15,19 @@ void main() if (vertical) offset.x = 0.0; else offset.y = 0.0; - vec4 sum = texture(prev_pass_tex, texCoord); + vec4 sum = texture(prev_pass_tex, texcoord); - sum += texture(tex, texCoord - 4.0 * offset) * 0.0162162162; - sum += texture(tex, texCoord - 3.0 * offset) * 0.0540540541; - sum += texture(tex, texCoord - 2.0 * offset) * 0.1216216216; - sum += texture(tex, texCoord - 1.0 * offset) * 0.1945945946; + sum += texture(tex, texcoord - 4.0 * offset) * 0.0162162162; + sum += texture(tex, texcoord - 3.0 * offset) * 0.0540540541; + sum += texture(tex, texcoord - 2.0 * offset) * 0.1216216216; + sum += texture(tex, texcoord - 1.0 * offset) * 0.1945945946; - sum += texture(tex, texCoord) * 0.2270270270; + sum += texture(tex, texcoord) * 0.2270270270; - sum += texture(tex, texCoord + 1.0 * offset) * 0.1945945946; - sum += texture(tex, texCoord + 2.0 * offset) * 0.1216216216; - sum += texture(tex, texCoord + 3.0 * offset) * 0.0540540541; - sum += texture(tex, texCoord + 4.0 * offset) * 0.0162162162; + sum += texture(tex, texcoord + 1.0 * offset) * 0.1945945946; + sum += texture(tex, texcoord + 2.0 * offset) * 0.1216216216; + sum += texture(tex, texcoord + 3.0 * offset) * 0.0540540541; + sum += texture(tex, texcoord + 4.0 * offset) * 0.0162162162; fragColor = sum; } diff --git a/Shaders/HDR/cloud-static.vert b/Shaders/HDR/cloud_static.vert similarity index 80% rename from Shaders/HDR/cloud-static.vert rename to Shaders/HDR/cloud_static.vert index 80a14e857..c774995dd 100644 --- a/Shaders/HDR/cloud-static.vert +++ b/Shaders/HDR/cloud_static.vert @@ -1,11 +1,12 @@ #version 330 core layout(location = 0) in vec4 pos; -layout(location = 2) in vec4 vertexColor; -layout(location = 3) in vec4 multiTexCoord0; +layout(location = 2) in vec4 vertex_color; +layout(location = 3) in vec4 multitexcoord0; -out vec2 texCoord; -out vec4 cloudColor; +out vec2 texcoord; +out vec4 cloud_color; +out vec4 ap_color; uniform mat4 osg_ModelViewMatrix; uniform mat4 osg_ModelViewProjectionMatrix; @@ -15,13 +16,13 @@ uniform vec3 fg_SunDirectionWorld; const float shade = 0.8; const float cloud_height = 1000.0; -// aerial-perspective-include.frag -vec3 add_aerial_perspective(vec3 color, vec2 coord, float depth); +// aerial_perspective.glsl +vec4 get_aerial_perspective(vec2 coord, float depth); vec3 get_sun_radiance(vec3 p); void main() { - texCoord = multiTexCoord0.st; + texcoord = multitexcoord0.st; // XXX: Should be sent as an uniform mat4 inverseModelViewMatrix = inverse(osg_ModelViewMatrix); @@ -34,7 +35,7 @@ void main() final_pos.x = pos.x; final_pos.y = pos.y; final_pos.z = pos.z; - final_pos.xyz += vertexColor.xyz; + final_pos.xyz += vertex_color.xyz; gl_Position = osg_ModelViewProjectionMatrix * final_pos; @@ -59,16 +60,15 @@ void main() // Determine the shading based on a mixture from the backlight to the front vec3 backlight = shade * sun_radiance; - cloudColor.rgb = mix(backlight, sun_radiance, NdotL); + cloud_color.rgb = mix(backlight, sun_radiance, NdotL); // Perspective division and scale to [0, 1] to get the screen position // of the vertex. vec2 coord = (gl_Position.xy / gl_Position.w) * 0.5 + 0.5; - cloudColor.rgb = add_aerial_perspective( - cloudColor.rgb, coord, length(final_view_pos)); + ap_color = get_aerial_perspective(coord, length(final_view_pos)); // As we get within 100m of the sprite, it is faded out. Equally at large // distances it also fades out. - cloudColor.a = min(smoothstep(100.0, 250.0, fogCoord), + cloud_color.a = min(smoothstep(100.0, 250.0, fogCoord), 1.0 - smoothstep(70000.0, 75000.0, fogCoord)); } diff --git a/Shaders/HDR/clustered-include.frag b/Shaders/HDR/clustered.glsl similarity index 61% rename from Shaders/HDR/clustered-include.frag rename to Shaders/HDR/clustered.glsl index 2f778e7e8..9dc9738b5 100644 --- a/Shaders/HDR/clustered-include.frag +++ b/Shaders/HDR/clustered.glsl @@ -15,19 +15,11 @@ uniform float fg_ClusteredSliceBias; uniform int fg_ClusteredHorizontalTiles; uniform int fg_ClusteredVerticalTiles; -// lighting-include.frag -vec3 evaluateLight( - vec3 baseColor, - float metallic, - float roughness, - vec3 f0, - vec3 intensity, - float visibility, - vec3 n, - vec3 l, - vec3 v, - float NdotL, - float NdotV); +// surface.glsl +vec3 surface_eval_analytical( + vec3 base_color, float metallic, float roughness, vec3 f0, + vec3 light_intensity, float occlusion, + vec3 N, vec3 L, vec3 V); struct PointLight { vec3 position; @@ -105,37 +97,31 @@ float get_spot_angle_attenuation(vec3 l, vec3 light_dir, return pow(cd, exponent); } -vec3 get_contribution_from_scene_lights( - vec3 p, - vec3 base_color, - float metallic, - float roughness, - vec3 f0, - vec3 n, - vec3 v) +vec3 eval_scene_lights(vec3 base_color, float metallic, float roughness, vec3 f0, + vec3 P, vec3 N, vec3 V) { - int slice = int(max(log2(-p.z) * fg_ClusteredSliceScale + int slice = int(max(log2(-P.z) * fg_ClusteredSliceScale + fg_ClusteredSliceBias, 0.0)); - vec3 clusterCoords = vec3(floor(gl_FragCoord.xy / fg_ClusteredTileSize), - slice) + vec3(0.5); // Pixel center + vec3 cluster_coords = vec3(floor(gl_FragCoord.xy / fg_ClusteredTileSize), + slice) + vec3(0.5); // Pixel center // Normalize - clusterCoords /= vec3(fg_ClusteredHorizontalTiles, - fg_ClusteredVerticalTiles, - fg_ClusteredDepthSlices); + cluster_coords /= vec3(fg_ClusteredHorizontalTiles, + fg_ClusteredVerticalTiles, + fg_ClusteredDepthSlices); - vec3 cluster = texture(fg_Clusters, clusterCoords).rgb; - int lightIndex = int(cluster.r); - int pointCount = int(cluster.g); - int spotCount = int(cluster.b); + vec3 cluster = texture(fg_Clusters, cluster_coords).rgb; + int light_index = int(cluster.r); + int point_count = int(cluster.g); + int spot_count = int(cluster.b); vec3 color = vec3(0.0); - for (int i = 0; i < pointCount; ++i) { - int index = getIndex(lightIndex++); + for (int i = 0; i < point_count; ++i) { + int index = getIndex(light_index++); PointLight light = unpackPointLight(index); - vec3 to_light = light.position - p; - vec3 l = normalize(to_light); + vec3 to_light = light.position - P; + vec3 L = normalize(to_light); float attenuation = get_square_falloff_attenuation( to_light, 1.0 / light.range); @@ -144,46 +130,32 @@ vec3 get_contribution_from_scene_lights( vec3 intensity = light.color * light.intensity * attenuation; - float NdotL = max(dot(n, l), 0.0); - float NdotV = clamp(abs(dot(n, v)), 0.001, 1.0); - - color += evaluateLight(base_color, - metallic, - roughness, - f0, - intensity, - 1.0, - n, l, v, - NdotL, NdotV); + color += surface_eval_analytical( + base_color, metallic, roughness, f0, + intensity, 1.0, + N, L, V); } - for (int i = 0; i < spotCount; ++i) { - int index = getIndex(lightIndex++); + for (int i = 0; i < spot_count; ++i) { + int index = getIndex(light_index++); SpotLight light = unpackSpotLight(index); - vec3 to_light = light.position - p; - vec3 l = normalize(to_light); + vec3 to_light = light.position - P; + vec3 L = normalize(to_light); float attenuation = get_square_falloff_attenuation( to_light, 1.0 / light.range); attenuation *= get_spot_angle_attenuation( - l, light.direction, light.cos_cutoff, light.exponent); + L, light.direction, light.cos_cutoff, light.exponent); if (attenuation <= 0.0) continue; vec3 intensity = light.color * light.intensity * attenuation; - float NdotL = max(dot(n, l), 0.0); - float NdotV = clamp(abs(dot(n, v)), 0.001, 1.0); - - color += evaluateLight(base_color, - metallic, - roughness, - f0, - intensity, - 1.0, - n, l, v, - NdotL, NdotV); + color += surface_eval_analytical( + base_color, metallic, roughness, f0, + intensity, 1.0, + N, L, V); } return color; diff --git a/Shaders/HDR/color.glsl b/Shaders/HDR/color.glsl new file mode 100644 index 000000000..0e79860e5 --- /dev/null +++ b/Shaders/HDR/color.glsl @@ -0,0 +1,28 @@ +#version 330 core + +float linear_srgb_to_luminance(vec3 color) +{ + return dot(color, vec3(0.2125, 0.7154, 0.0721)); +} + +/* + * Transform an sRGB color to linear sRGB. + */ +vec3 eotf_inverse_sRGB(vec3 srgb) +{ + vec3 a = srgb / 12.92; + vec3 b = pow((srgb + 0.055) / 1.055, vec3(2.4)); + vec3 c = step(vec3(0.04045), srgb); + return mix(a, b, c); +} + +/* + * Transform a linear sRGB color to sRGB (gamma correction). + */ +vec3 eotf_sRGB(vec3 linear_srgb) +{ + vec3 a = 12.92 * linear_srgb; + vec3 b = 1.055 * pow(linear_srgb, vec3(1.0 / 2.4)) - 0.055; + vec3 c = step(vec3(0.0031308), linear_srgb); + return mix(a, b, c); +} diff --git a/Shaders/HDR/copy-prev-luminance.frag b/Shaders/HDR/copy-prev-luminance.frag deleted file mode 100644 index 048e6b4e2..000000000 --- a/Shaders/HDR/copy-prev-luminance.frag +++ /dev/null @@ -1,10 +0,0 @@ -#version 330 core - -out float prevLum; - -uniform sampler2D tex; - -void main() -{ - prevLum = texelFetch(tex, ivec2(0), 0).r; -} diff --git a/Shaders/HDR/copy_prev_luminance.frag b/Shaders/HDR/copy_prev_luminance.frag new file mode 100644 index 000000000..4f86e6a66 --- /dev/null +++ b/Shaders/HDR/copy_prev_luminance.frag @@ -0,0 +1,10 @@ +#version 330 core + +layout(location = 0) out float fragColor; + +uniform sampler2D lum_tex; + +void main() +{ + fragColor = texelFetch(lum_tex, ivec2(0), 0).r; +} diff --git a/Shaders/HDR/debug_gbuffer_clear.frag b/Shaders/HDR/debug_gbuffer_clear.frag new file mode 100644 index 000000000..f32f76c1b --- /dev/null +++ b/Shaders/HDR/debug_gbuffer_clear.frag @@ -0,0 +1,14 @@ +#version 330 core + +layout(location = 0) out vec4 out_gbuffer0; +layout(location = 1) out vec4 out_gbuffer1; +layout(location = 2) out vec4 out_gbuffer2; +layout(location = 3) out vec4 out_gbuffer3; + +void main() +{ + out_gbuffer0 = vec4(0.0); + out_gbuffer1 = vec4(0.0); + out_gbuffer2 = vec4(0.0); + out_gbuffer3 = vec4(0.0); +} diff --git a/Shaders/HDR/debug_gbuffer_color.frag b/Shaders/HDR/debug_gbuffer_color.frag new file mode 100644 index 000000000..32c92b35d --- /dev/null +++ b/Shaders/HDR/debug_gbuffer_color.frag @@ -0,0 +1,12 @@ +#version 330 core + +layout(location = 0) 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/debug_gbuffer_depth.frag b/Shaders/HDR/debug_gbuffer_depth.frag new file mode 100644 index 000000000..40faa2b0a --- /dev/null +++ b/Shaders/HDR/debug_gbuffer_depth.frag @@ -0,0 +1,16 @@ +#version 330 core + +layout(location = 0) out vec4 fragColor; + +in vec2 texcoord; + +uniform sampler2D depth_tex; + +// pos_from_depth.glsl +float linearize_depth(float depth); + +void main() +{ + float depth = texture(depth_tex, texcoord).r; + fragColor = vec4(vec3(linearize_depth(depth)), 1.0); +} diff --git a/Shaders/HDR/debug_gbuffer_matid.frag b/Shaders/HDR/debug_gbuffer_matid.frag new file mode 100644 index 000000000..25043e3b9 --- /dev/null +++ b/Shaders/HDR/debug_gbuffer_matid.frag @@ -0,0 +1,12 @@ +#version 330 core + +layout(location = 0) 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/debug_gbuffer_normal.frag b/Shaders/HDR/debug_gbuffer_normal.frag new file mode 100644 index 000000000..0be55d32b --- /dev/null +++ b/Shaders/HDR/debug_gbuffer_normal.frag @@ -0,0 +1,12 @@ +#version 330 core + +layout(location = 0) 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/debug_gbuffer_orm.frag b/Shaders/HDR/debug_gbuffer_orm.frag new file mode 100644 index 000000000..b4ea82f62 --- /dev/null +++ b/Shaders/HDR/debug_gbuffer_orm.frag @@ -0,0 +1,17 @@ +#version 330 core + +layout(location = 0) 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/envmap-copy.frag b/Shaders/HDR/envmap-copy.frag deleted file mode 100644 index 9acb8fec4..000000000 --- a/Shaders/HDR/envmap-copy.frag +++ /dev/null @@ -1,27 +0,0 @@ -#version 330 core - -layout(location = 0) out vec3 fragColor0; -layout(location = 1) out vec3 fragColor1; -layout(location = 2) out vec3 fragColor2; -layout(location = 3) out vec3 fragColor3; -layout(location = 4) out vec3 fragColor4; -layout(location = 5) out vec3 fragColor5; - -in vec3 cubemapCoord0; -in vec3 cubemapCoord1; -in vec3 cubemapCoord2; -in vec3 cubemapCoord3; -in vec3 cubemapCoord4; -in vec3 cubemapCoord5; - -uniform samplerCube envmap; - -void main() -{ - fragColor0 = textureLod(envmap, cubemapCoord0, 0.0).rgb; - fragColor1 = textureLod(envmap, cubemapCoord1, 0.0).rgb; - fragColor2 = textureLod(envmap, cubemapCoord2, 0.0).rgb; - fragColor3 = textureLod(envmap, cubemapCoord3, 0.0).rgb; - fragColor4 = textureLod(envmap, cubemapCoord4, 0.0).rgb; - fragColor5 = textureLod(envmap, cubemapCoord5, 0.0).rgb; -} diff --git a/Shaders/HDR/envmap-prefilter.frag b/Shaders/HDR/envmap-prefilter.frag deleted file mode 100644 index 7c672409f..000000000 --- a/Shaders/HDR/envmap-prefilter.frag +++ /dev/null @@ -1,107 +0,0 @@ -// Mostly based on 'Moving Frostbite to Physically Based Rendering' -// https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf - -#version 330 core - -layout(location = 0) out vec3 fragColor0; -layout(location = 1) out vec3 fragColor1; -layout(location = 2) out vec3 fragColor2; -layout(location = 3) out vec3 fragColor3; -layout(location = 4) out vec3 fragColor4; -layout(location = 5) out vec3 fragColor5; - -in vec3 cubemapCoord0; -in vec3 cubemapCoord1; -in vec3 cubemapCoord2; -in vec3 cubemapCoord3; -in vec3 cubemapCoord4; -in vec3 cubemapCoord5; - -uniform samplerCube envmap; -uniform float roughness; -uniform int num_samples; - -const float PI = 3.14159265359; -const float ENVMAP_SIZE = 128.0; -const float ENVMAP_MIP_COUNT = 4.0; - -float RadicalInverse_VdC(uint bits) -{ - bits = (bits << 16u) | (bits >> 16u); - bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); - bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); - bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); - bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); - return float(bits) * 2.3283064365386963e-10; // / 0x100000000 -} - -vec2 Hammersley(uint i, uint N) -{ - return vec2(float(i)/float(N), RadicalInverse_VdC(i)); -} - -vec3 ImportanceSampleGGX(vec2 Xi, vec3 n, float a) -{ - float phi = 2.0 * PI * Xi.x; - float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a*a - 1.0) * Xi.y)); - float sinTheta = sqrt(1.0 - cosTheta*cosTheta); - vec3 h; - h.x = sinTheta * cos(phi); - h.y = sinTheta * sin(phi); - h.z = cosTheta; - return h; -} - -float D_GGX(float NdotH, float a2) -{ - float f = (NdotH * a2 - NdotH) * NdotH + 1.0; - return a2 / (PI * f * f); -} - -vec3 prefilter(vec3 n) -{ - vec3 v = n; // n = v simplification - float a = roughness*roughness; - - vec3 prefilteredColor = vec3(0.0); - float totalWeight = 0.0; - - vec3 up = abs(n.z) < 0.999f ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); - vec3 tangent = normalize(cross(up, n)); - vec3 bitangent = cross(n, tangent); - mat3 tangentToWorld = mat3(tangent, bitangent, n); - - uint sample_count = uint(num_samples); - for (uint i = 0u; i < sample_count; ++i) { - vec2 Xi = Hammersley(i, sample_count); - vec3 h = tangentToWorld * ImportanceSampleGGX(Xi, n, a); - vec3 l = normalize(2.0 * dot(v, h) * h - v); - - float NdotL = max(dot(n, l), 0.0); - if (NdotL > 0.0) { - float NdotH = clamp(dot(n, h), 0.0, 1.0); - float VdotH = clamp(dot(v, h), 0.0, 1.0); - - float pdf = D_GGX(NdotH, a) * NdotH / (4.0 * VdotH); - float omegaS = 1.0 / (float(sample_count) * pdf); - float omegaP = 4.0 * PI / (6.0 * ENVMAP_SIZE * ENVMAP_SIZE); - float mipLevel = clamp(0.5 * log2(omegaS / omegaP) + 1.0, - 0.0, ENVMAP_MIP_COUNT); - - prefilteredColor += textureLod(envmap, l, mipLevel).rgb * NdotL; - totalWeight += NdotL; - } - } - - return prefilteredColor / totalWeight; -} - -void main() -{ - fragColor0 = prefilter(normalize(cubemapCoord0)); - fragColor1 = prefilter(normalize(cubemapCoord1)); - fragColor2 = prefilter(normalize(cubemapCoord2)); - fragColor3 = prefilter(normalize(cubemapCoord3)); - fragColor4 = prefilter(normalize(cubemapCoord4)); - fragColor5 = prefilter(normalize(cubemapCoord5)); -} diff --git a/Shaders/HDR/envmap-prefilter.vert b/Shaders/HDR/envmap-prefilter.vert deleted file mode 100644 index d5ca21245..000000000 --- a/Shaders/HDR/envmap-prefilter.vert +++ /dev/null @@ -1,24 +0,0 @@ -#version 330 core - -out vec3 cubemapCoord0; -out vec3 cubemapCoord1; -out vec3 cubemapCoord2; -out vec3 cubemapCoord3; -out vec3 cubemapCoord4; -out vec3 cubemapCoord5; - -void main() -{ - vec2 pos = vec2(gl_VertexID % 2, gl_VertexID / 2) * 4.0 - 1.0; - gl_Position = vec4(pos, 0.0, 1.0); - // Map the quad texture coordinates to a direction vector to sample - // the cubemap. This assumes that we are using the weird left-handed - // orientations given by the OpenGL spec. - // See https://www.khronos.org/opengl/wiki/Cubemap_Texture#Upload_and_orientation - cubemapCoord0 = vec3(1.0, -pos.y, -pos.x); - cubemapCoord1 = vec3(-1.0, -pos.y, pos.x); - cubemapCoord2 = vec3(pos.x, 1.0, pos.y); - cubemapCoord3 = vec3(pos.x, -1.0, -pos.y); - cubemapCoord4 = vec3(pos.x, -pos.y, 1.0); - cubemapCoord5 = vec3(-pos.x, -pos.y, -1.0); -} diff --git a/Shaders/HDR/envmap.vert b/Shaders/HDR/envmap.vert new file mode 100644 index 000000000..f795bca53 --- /dev/null +++ b/Shaders/HDR/envmap.vert @@ -0,0 +1,25 @@ +#version 330 core + +out vec3 cubemap_coord0; +out vec3 cubemap_coord1; +out vec3 cubemap_coord2; +out vec3 cubemap_coord3; +out vec3 cubemap_coord4; +out vec3 cubemap_coord5; + +void main() +{ + vec2 pos = vec2(gl_VertexID % 2, gl_VertexID / 2) * 4.0 - 1.0; + gl_Position = vec4(pos, 0.0, 1.0); + + // Map the quad texture coordinates to a direction vector to sample + // the cubemap. This assumes that we are using the weird left-handed + // orientations given by the OpenGL spec. + // See https://www.khronos.org/opengl/wiki/Cubemap_Texture#Upload_and_orientation + cubemap_coord0 = vec3( 1.0, -pos.y, -pos.x); + cubemap_coord1 = vec3(- 1.0, -pos.y, pos.x); + cubemap_coord2 = vec3( pos.x, 1.0, pos.y); + cubemap_coord3 = vec3( pos.x, - 1.0, -pos.y); + cubemap_coord4 = vec3( pos.x, -pos.y, 1.0); + cubemap_coord5 = vec3(-pos.x, -pos.y, - 1.0); +} diff --git a/Shaders/HDR/envmap_copy.frag b/Shaders/HDR/envmap_copy.frag new file mode 100644 index 000000000..3fdbbf066 --- /dev/null +++ b/Shaders/HDR/envmap_copy.frag @@ -0,0 +1,27 @@ +#version 330 core + +layout(location = 0) out vec3 fragColor0; +layout(location = 1) out vec3 fragColor1; +layout(location = 2) out vec3 fragColor2; +layout(location = 3) out vec3 fragColor3; +layout(location = 4) out vec3 fragColor4; +layout(location = 5) out vec3 fragColor5; + +in vec3 cubemap_coord0; +in vec3 cubemap_coord1; +in vec3 cubemap_coord2; +in vec3 cubemap_coord3; +in vec3 cubemap_coord4; +in vec3 cubemap_coord5; + +uniform samplerCube envmap_tex; + +void main() +{ + fragColor0 = textureLod(envmap_tex, cubemap_coord0, 0.0).rgb; + fragColor1 = textureLod(envmap_tex, cubemap_coord1, 0.0).rgb; + fragColor2 = textureLod(envmap_tex, cubemap_coord2, 0.0).rgb; + fragColor3 = textureLod(envmap_tex, cubemap_coord3, 0.0).rgb; + fragColor4 = textureLod(envmap_tex, cubemap_coord4, 0.0).rgb; + fragColor5 = textureLod(envmap_tex, cubemap_coord5, 0.0).rgb; +} diff --git a/Shaders/HDR/envmap_prefilter.frag b/Shaders/HDR/envmap_prefilter.frag new file mode 100644 index 000000000..dc6abd0d2 --- /dev/null +++ b/Shaders/HDR/envmap_prefilter.frag @@ -0,0 +1,110 @@ +/* + * Mostly based on 'Moving Frostbite to Physically Based Rendering' + * https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf + */ + +#version 330 core + +layout(location = 0) out vec3 fragColor0; +layout(location = 1) out vec3 fragColor1; +layout(location = 2) out vec3 fragColor2; +layout(location = 3) out vec3 fragColor3; +layout(location = 4) out vec3 fragColor4; +layout(location = 5) out vec3 fragColor5; + +in vec3 cubemap_coord0; +in vec3 cubemap_coord1; +in vec3 cubemap_coord2; +in vec3 cubemap_coord3; +in vec3 cubemap_coord4; +in vec3 cubemap_coord5; + +uniform samplerCube envmap_tex; +uniform float roughness; +uniform int num_samples; +uniform int mip_count; + +// math.glsl +float M_PI(); +float M_2PI(); +float M_4PI(); +float sqr(float x); + +float RadicalInverse_VdC(uint bits) +{ + bits = (bits << 16u) | (bits >> 16u); + bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); + bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); + bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); + bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); + return float(bits) * 2.3283064365386963e-10; // / 0x100000000 +} + +vec2 Hammersley(uint i, uint N) +{ + return vec2(float(i) / float(N), RadicalInverse_VdC(i)); +} + +vec3 ImportanceSampleGGX(vec2 Xi, vec3 n, float a) +{ + float phi = M_2PI() * Xi.x; + float cos_theta = sqrt((1.0 - Xi.y) / (1.0 + (sqr(a) - 1.0) * Xi.y)); + float sin_theta = sqrt(1.0 - sqr(cos_theta)); + return vec3(sin_theta * cos(phi), sin_theta * sin(phi), cos_theta); +} + +float D_GGX(float NdotH, float a2) +{ + float f = (NdotH * a2 - NdotH) * NdotH + 1.0; + return a2 / (M_PI() * f * f); +} + +vec3 prefilter(vec3 N) +{ + vec3 V = N; // n = v simplification + float a = sqr(roughness); + float envmap_size = float(textureSize(envmap_tex, 0).x); + + vec3 result = vec3(0.0); + float weight = 0.0; + + vec3 up = abs(N.z) < 0.999f ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); + vec3 T = normalize(cross(up, N)); + vec3 B = cross(N, T); + mat3 TBN = mat3(T, B, N); + + uint sample_count = uint(num_samples); + + for (uint i = 0u; i < sample_count; ++i) { + vec2 Xi = Hammersley(i, sample_count); + vec3 H = TBN * ImportanceSampleGGX(Xi, N, a); + vec3 L = normalize(2.0 * dot(V, H) * H - V); + + float NdotL = max(dot(N, L), 0.0); + if (NdotL > 0.0) { + float NdotH = clamp(dot(N, H), 0.0, 1.0); + float VdotH = clamp(dot(V, H), 0.0, 1.0); + + float pdf = D_GGX(NdotH, a) * NdotH / (4.0 * VdotH); + float omega_s = 1.0 / (float(sample_count) * pdf); + float omega_p = M_4PI() / (6.0 * envmap_size * envmap_size); + float miplevel = clamp(0.5 * log2(omega_s / omega_p) + 1.0, + 0.0, float(mip_count)); + + result += textureLod(envmap_tex, L, miplevel).rgb * NdotL; + weight += NdotL; + } + } + + return result / weight; +} + +void main() +{ + fragColor0 = prefilter(normalize(cubemap_coord0)); + fragColor1 = prefilter(normalize(cubemap_coord1)); + fragColor2 = prefilter(normalize(cubemap_coord2)); + fragColor3 = prefilter(normalize(cubemap_coord3)); + fragColor4 = prefilter(normalize(cubemap_coord4)); + fragColor5 = prefilter(normalize(cubemap_coord5)); +} diff --git a/Shaders/HDR/exposure-include.frag b/Shaders/HDR/exposure-include.frag deleted file mode 100644 index 630b5ebd2..000000000 --- a/Shaders/HDR/exposure-include.frag +++ /dev/null @@ -1,26 +0,0 @@ -#version 330 core - -uniform float exposure_compensation; - -const float one_over_log10 = 1.0 / log(10.0); - -float log10(float x) -{ - return one_over_log10 * log(x); -} - -// Exposure curve from 'Perceptual Effects in Real-time Tone Mapping'. -// http://resources.mpi-inf.mpg.de/hdr/peffects/krawczyk05sccg.pdf -float keyValue(float L) -{ - return 1.0 - 2.0 / (log10(L + 1.0) + 2.0); -} - -vec3 applyExposure(vec3 color, float avgLuminance, float threshold) -{ - avgLuminance = max(avgLuminance, 0.001); - float linearExposure = keyValue(avgLuminance) / avgLuminance; - float exposure = log2(max(linearExposure, 0.0001)); - exposure += exposure_compensation - threshold; - return color * exp2(exposure); -} diff --git a/Shaders/HDR/exposure.glsl b/Shaders/HDR/exposure.glsl new file mode 100644 index 000000000..4421d43c1 --- /dev/null +++ b/Shaders/HDR/exposure.glsl @@ -0,0 +1,28 @@ +#version 330 core + +uniform float exposure_compensation; + +const float one_over_log10 = 1.0 / log(10.0); + +float log10(float x) +{ + return one_over_log10 * log(x); +} + +/* + * Exposure curve from 'Perceptual Effects in Real-time Tone Mapping'. + * http://resources.mpi-inf.mpg.de/hdr/peffects/krawczyk05sccg.pdf + */ +float key_value(float L) +{ + return 1.0 - 2.0 / (log10(L + 1.0) + 2.0); +} + +vec3 apply_exposure(vec3 color, float avg_lum, float threshold) +{ + avg_lum = max(avg_lum, 0.001); + float linear_exposure = key_value(avg_lum) / avg_lum; + float exposure = log2(max(linear_exposure, 0.0001)); + exposure += exposure_compensation - threshold; + return color * exp2(exposure); +} diff --git a/Shaders/HDR/forward.frag b/Shaders/HDR/forward.frag deleted file mode 100644 index c6fe267d4..000000000 --- a/Shaders/HDR/forward.frag +++ /dev/null @@ -1,13 +0,0 @@ -#version 330 core - -layout(location = 0) out vec4 fragColor; - -in vec3 normalVS; -in vec2 texCoord; - -uniform sampler2D color_tex; - -void main() -{ - fragColor = texture(color_tex, texCoord); -} diff --git a/Shaders/HDR/forward.vert b/Shaders/HDR/forward.vert deleted file mode 100644 index 232eb73fe..000000000 --- a/Shaders/HDR/forward.vert +++ /dev/null @@ -1,18 +0,0 @@ -#version 330 core - -layout(location = 0) in vec4 pos; -layout(location = 1) in vec3 normal; -layout(location = 3) in vec4 multiTexCoord0; - -out vec3 normalVS; -out vec2 texCoord; - -uniform mat4 osg_ModelViewProjectionMatrix; -uniform mat3 osg_NormalMatrix; - -void main() -{ - gl_Position = osg_ModelViewProjectionMatrix * pos; - normalVS = normalize(osg_NormalMatrix * normal); - texCoord = multiTexCoord0.st; -} diff --git a/Shaders/HDR/fxaa.frag b/Shaders/HDR/fxaa.frag index cb169765a..64eb348ca 100644 --- a/Shaders/HDR/fxaa.frag +++ b/Shaders/HDR/fxaa.frag @@ -1,9 +1,9 @@ #version 330 core -out vec4 fragColor; +layout(location = 0) out vec4 fragColor; -in vec2 texCoord; -in vec4 posPos; +in vec2 texcoord; +in vec4 pos_pos; uniform sampler2D color_tex; @@ -15,11 +15,11 @@ void main() { vec2 rcpFrame = 1.0 / textureSize(color_tex, 0); - vec3 rgbNW = textureLod(color_tex, posPos.zw, 0.0).xyz; - vec3 rgbNE = textureLodOffset(color_tex, posPos.zw, 0.0, ivec2(1,0)).xyz; - vec3 rgbSW = textureLodOffset(color_tex, posPos.zw, 0.0, ivec2(0,1)).xyz; - vec3 rgbSE = textureLodOffset(color_tex, posPos.zw, 0.0, ivec2(1,1)).xyz; - vec3 rgbM = textureLod(color_tex, posPos.xy, 0.0).xyz; + vec3 rgbNW = textureLod(color_tex, pos_pos.zw, 0.0).xyz; + vec3 rgbNE = textureLodOffset(color_tex, pos_pos.zw, 0.0, ivec2(1,0)).xyz; + vec3 rgbSW = textureLodOffset(color_tex, pos_pos.zw, 0.0, ivec2(0,1)).xyz; + vec3 rgbSE = textureLodOffset(color_tex, pos_pos.zw, 0.0, ivec2(1,1)).xyz; + vec3 rgbM = textureLod(color_tex, pos_pos.xy, 0.0).xyz; const vec3 luma = vec3(0.299, 0.587, 0.114); float lumaNW = dot(rgbNW, luma); @@ -43,11 +43,11 @@ void main() dir * rcpDirMin)) * rcpFrame.xy; vec3 rgbA = 0.5 * ( - textureLod(color_tex, posPos.xy + dir * (1.0/3.0 - 0.5), 0.0).xyz + - textureLod(color_tex, posPos.xy + dir * (2.0/3.0 - 0.5), 0.0).xyz); + textureLod(color_tex, pos_pos.xy + dir * (1.0/3.0 - 0.5), 0.0).xyz + + textureLod(color_tex, pos_pos.xy + dir * (2.0/3.0 - 0.5), 0.0).xyz); vec3 rgbB = rgbA * 0.5 + 0.25 * ( - textureLod(color_tex, posPos.xy + dir * (0.0/3.0 - 0.5), 0.0).xyz + - textureLod(color_tex, posPos.xy + dir * (3.0/3.0 - 0.5), 0.0).xyz); + textureLod(color_tex, pos_pos.xy + dir * (0.0/3.0 - 0.5), 0.0).xyz + + textureLod(color_tex, pos_pos.xy + dir * (3.0/3.0 - 0.5), 0.0).xyz); float lumaB = dot(rgbB, luma); if((lumaB < lumaMin) || (lumaB > lumaMax)) diff --git a/Shaders/HDR/fxaa.vert b/Shaders/HDR/fxaa.vert index 436fe6837..a8982bdd6 100644 --- a/Shaders/HDR/fxaa.vert +++ b/Shaders/HDR/fxaa.vert @@ -1,7 +1,7 @@ #version 330 core -out vec2 texCoord; -out vec4 posPos; +out vec2 texcoord; +out vec4 pos_pos; uniform sampler2D color_tex; @@ -10,11 +10,11 @@ const float FXAA_SUBPIX_SHIFT = 1.0/4.0; void main() { vec2 pos = vec2(gl_VertexID % 2, gl_VertexID / 2) * 4.0 - 1.0; - texCoord = pos * 0.5 + 0.5; + texcoord = pos * 0.5 + 0.5; vec2 rcpFrame = 1.0 / textureSize(color_tex, 0); - posPos.xy = texCoord; - posPos.zw = texCoord - (rcpFrame * (0.5 + FXAA_SUBPIX_SHIFT)); + pos_pos.xy = texcoord; + pos_pos.zw = texcoord - (rcpFrame * (0.5 + FXAA_SUBPIX_SHIFT)); gl_Position = vec4(pos, 0.0, 1.0); } diff --git a/Shaders/HDR/gbuffer-debug-clear.frag b/Shaders/HDR/gbuffer-debug-clear.frag deleted file mode 100644 index 43cceed68..000000000 --- a/Shaders/HDR/gbuffer-debug-clear.frag +++ /dev/null @@ -1,12 +0,0 @@ -#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 deleted file mode 100644 index 0bfee3bb7..000000000 --- a/Shaders/HDR/gbuffer-debug-color.frag +++ /dev/null @@ -1,12 +0,0 @@ -#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-depth.frag b/Shaders/HDR/gbuffer-debug-depth.frag deleted file mode 100644 index bf2173eda..000000000 --- a/Shaders/HDR/gbuffer-debug-depth.frag +++ /dev/null @@ -1,15 +0,0 @@ -#version 330 core - -out vec4 fragColor; - -in vec2 texCoord; - -uniform sampler2D depth_tex; - -float linearizeDepth(float depth); - -void main() -{ - float depth = texture(depth_tex, texCoord).r; - fragColor = vec4(vec3(linearizeDepth(depth)), 1.0); -} diff --git a/Shaders/HDR/gbuffer-debug-matid.frag b/Shaders/HDR/gbuffer-debug-matid.frag deleted file mode 100644 index 0fb1ae95f..000000000 --- a/Shaders/HDR/gbuffer-debug-matid.frag +++ /dev/null @@ -1,12 +0,0 @@ -#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 deleted file mode 100644 index 39a61206b..000000000 --- a/Shaders/HDR/gbuffer-debug-normal.frag +++ /dev/null @@ -1,12 +0,0 @@ -#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 deleted file mode 100644 index 42f6c0122..000000000 --- a/Shaders/HDR/gbuffer-debug-orm.frag +++ /dev/null @@ -1,17 +0,0 @@ -#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 deleted file mode 100644 index 931ba2625..000000000 --- a/Shaders/HDR/gbuffer-include.frag +++ /dev/null @@ -1,65 +0,0 @@ -#version 330 core - -uniform mat4 fg_ProjectionMatrixInverse; -uniform vec2 fg_NearFar; - -// Octahedron normal encoding -// https://knarkowicz.wordpress.com/2014/04/16/octahedron-normal-vector-encoding/ -vec2 msign(vec2 v) -{ - return vec2((v.x >= 0.0) ? 1.0 : -1.0, - (v.y >= 0.0) ? 1.0 : -1.0); -} - -vec2 encodeNormal(vec3 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 -// buffer, also in the [0,1] range, return the view space position. -vec3 positionFromDepth(vec2 pos, float depth, mat4 projMatrixInverse) -{ - // We are using a reversed depth buffer. 1.0 corresponds to the near plane - // and 0.0 to the far plane. We convert this back to clip space by doing - // 1.0 - depth to undo the depth reversal - // 2.0 * depth - 1.0 to transform it to clip space [-1,1] - vec4 clipSpacePos = vec4(pos * 2.0 - 1.0, 1.0 - depth * 2.0, 1.0); - vec4 viewSpacePos = projMatrixInverse * clipSpacePos; - viewSpacePos.xyz /= viewSpacePos.w; - return viewSpacePos.xyz; -} - -vec3 positionFromDepth(vec2 pos, float depth) -{ - return positionFromDepth(pos, depth, fg_ProjectionMatrixInverse); -} - -// http://www.geeks3d.com/20091216/geexlab-how-to-visualize-the-depth-buffer-in-glsl/ -float linearizeDepth(float depth) -{ - float z = 1.0 - depth; // Undo the depth reversal - return 2.0 * fg_NearFar.x - / (fg_NearFar.y + fg_NearFar.x - z * (fg_NearFar.y - fg_NearFar.x)); -} - -vec3 decodeSRGB(vec3 screenRGB) -{ - vec3 a = screenRGB / 12.92; - vec3 b = pow((screenRGB + 0.055) / 1.055, vec3(2.4)); - vec3 c = step(vec3(0.04045), screenRGB); - return mix(a, b, c); -} diff --git a/Shaders/HDR/gbuffer_pack.glsl b/Shaders/HDR/gbuffer_pack.glsl new file mode 100644 index 000000000..b46335457 --- /dev/null +++ b/Shaders/HDR/gbuffer_pack.glsl @@ -0,0 +1,27 @@ +#version 330 core + +layout(location = 0) out vec4 out_gbuffer0; +layout(location = 1) out vec4 out_gbuffer1; +layout(location = 2) out vec4 out_gbuffer2; +layout(location = 3) out vec3 out_gbuffer3; + +// normal_encoding.glsl +vec2 encode_normal(vec3 n); + +/* + * Write the given surface properties to the G-buffer. + * See the HDR pipeline definition in $FG_ROOT/Compositor/HDR/hdr.xml for the + * G-buffer layout. + */ +void gbuffer_pack(vec3 normal, vec3 base_color, float metallic, float roughness, + float occlusion, vec3 emissive, uint mat_id) +{ + out_gbuffer0.rg = encode_normal(normal); + out_gbuffer0.b = roughness; + out_gbuffer0.a = float(mat_id) * (1.0 / 3.0); + out_gbuffer1.rgb = base_color; + out_gbuffer1.a = metallic; + out_gbuffer2.rgb = vec3(0.0); // unused + out_gbuffer2.a = occlusion; + out_gbuffer3.rgb = emissive; +} diff --git a/Shaders/HDR/gbuffer_unpack.glsl b/Shaders/HDR/gbuffer_unpack.glsl new file mode 100644 index 000000000..08d9400f5 --- /dev/null +++ b/Shaders/HDR/gbuffer_unpack.glsl @@ -0,0 +1,34 @@ +#version 330 core + +uniform sampler2D gbuffer0_tex; +uniform sampler2D gbuffer1_tex; +uniform sampler2D gbuffer2_tex; +uniform sampler2D gbuffer3_tex; + +// normal_encoding.glsl +vec3 decode_normal(vec2 f); + +/* + * Read the given surface properties from the G-Buffer. + * See the HDR pipeline definition in $FG_ROOT/Compositor/HDR/hdr.xml for the + * G-buffer layout. + */ +void gbuffer_unpack(in vec2 texcoord, + out vec3 normal, out vec3 base_color, out float metallic, + out float roughness, out float occlusion, out vec3 emissive, + out uint mat_id) +{ + vec4 gbuffer0 = texture(gbuffer0_tex, texcoord); + vec4 gbuffer1 = texture(gbuffer1_tex, texcoord); + vec4 gbuffer2 = texture(gbuffer2_tex, texcoord); + vec3 gbuffer3 = texture(gbuffer3_tex, texcoord).rgb; + + normal = decode_normal(gbuffer0.rg); + roughness = gbuffer0.b; + mat_id = uint(gbuffer0.a * 3.0); + base_color = gbuffer1.rgb; + metallic = gbuffer1.a; + // gbuffer2.rgb unused + occlusion = gbuffer2.a; + emissive = gbuffer3.rgb; +} diff --git a/Shaders/HDR/geometry-chrome.frag b/Shaders/HDR/geometry-chrome.frag deleted file mode 100644 index f0e1652f6..000000000 --- a/Shaders/HDR/geometry-chrome.frag +++ /dev/null @@ -1,23 +0,0 @@ -#version 330 core - -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() -{ - 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 deleted file mode 100644 index e41a4c9f2..000000000 --- a/Shaders/HDR/geometry-combined.frag +++ /dev/null @@ -1,42 +0,0 @@ -#version 330 core - -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 color_tex; -uniform sampler2D normal_tex; -uniform int normalmap_enabled; -uniform int normalmap_dds; -uniform float normalmap_tiling; - -const float DEFAULT_COMBINED_METALNESS = 0.0; -const float DEFAULT_COMBINED_ROUGHNESS = 0.1; - -vec2 encodeNormal(vec3 n); -vec3 decodeSRGB(vec3 screenRGB); - -void main() -{ - vec3 color = decodeSRGB(texture(color_tex, texCoord).rgb); - - vec3 normal = vec3(0.0, 0.0, 1.0); - if (normalmap_enabled > 0) { - normal = texture(normal_tex, texCoord * normalmap_tiling).rgb * 2.0 - 1.0; - // DDS has flipped normals - if (normalmap_dds > 0) - normal = -normal; - } - normal = normalize(TBN * normal); - - 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-lfeat.frag b/Shaders/HDR/geometry-lfeat.frag deleted file mode 100644 index 3ca633699..000000000 --- a/Shaders/HDR/geometry-lfeat.frag +++ /dev/null @@ -1,30 +0,0 @@ -#version 330 core - -layout(location = 0) out vec4 outGBuffer0; -layout(location = 1) out vec4 outGBuffer1; -layout(location = 2) out vec4 outGBuffer2; - -in vec3 normalVS; -in vec2 texCoord; - -uniform sampler2D color_tex; - -vec2 encodeNormal(vec3 n); -vec3 decodeSRGB(vec3 screenRGB); - -void main() -{ - vec4 texel = texture(color_tex, texCoord); - if (texel.a < 0.5) - discard; - - vec3 color = decodeSRGB(texel.rgb); - - outGBuffer0.rg = encodeNormal(normalVS); - outGBuffer0.b = 0.9; - outGBuffer0.a = 1.0; - outGBuffer1.rgb = color; - outGBuffer1.a = 0.0; - 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 deleted file mode 100644 index 895f6f5f8..000000000 --- a/Shaders/HDR/geometry-pbr-transparent.frag +++ /dev/null @@ -1,107 +0,0 @@ -#version 330 core - -out vec4 fragColor; - -in vec2 texCoord; -in mat3 TBN; -in vec3 ecPos; - -uniform sampler2D base_color_tex; -uniform sampler2D normal_tex; -uniform sampler2D orm_tex; -uniform sampler2D emissive_tex; -uniform vec4 base_color_factor; -uniform float metallic_factor; -uniform float roughness_factor; -uniform vec3 emissive_factor; -uniform float alpha_cutoff; - -uniform mat4 osg_ViewMatrixInverse; -uniform mat4 osg_ProjectionMatrix; -uniform vec4 fg_Viewport; -uniform vec3 fg_SunDirection; - -vec3 decodeSRGB(vec3 screenRGB); -float getShadowing(vec3 p, vec3 n, vec3 l, mat4 viewToClip); -vec3 getF0Reflectance(vec3 baseColor, float metallic); -vec3 evaluateLight( - vec3 baseColor, - float metallic, - float roughness, - vec3 f0, - vec3 intensity, - float visibility, - vec3 n, - vec3 l, - vec3 v, - float NdotL, - float NdotV); -vec3 evaluateIBL( - vec3 baseColor, - float metallic, - float roughness, - vec3 f0, - float visibility, - vec3 nWorldSpace, - float NdotV, - vec3 reflected); -vec3 add_aerial_perspective(vec3 color, vec2 coord, float depth); -vec3 get_sun_radiance(vec3 p); - -void main() -{ - vec4 baseColorTexel = texture(base_color_tex, texCoord); - vec4 baseColor = vec4(decodeSRGB(baseColorTexel.rgb), baseColorTexel.a) - * base_color_factor; - if (baseColor.a < alpha_cutoff) - discard; - - vec3 n = texture(normal_tex, texCoord).rgb * 2.0 - 1.0; - n = normalize(TBN * n); - - 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; - - vec3 v = normalize(-ecPos); - vec3 l = fg_SunDirection; - - float NdotL = dot(n, l); - float NdotV = clamp(abs(dot(n, v)), 0.001, 1.0); - - vec3 f0 = getF0Reflectance(baseColor.rgb, metallic); - - vec3 pos_world = (osg_ViewMatrixInverse * vec4(ecPos, 1.0)).xyz; - vec3 sun_radiance = get_sun_radiance(pos_world); - - float shadowFactor = getShadowing(ecPos, n, l, osg_ProjectionMatrix); - - vec3 color = evaluateLight(baseColor.rgb, - metallic, - roughness, - f0, - sun_radiance, - shadowFactor, - n, l, v, - NdotL, NdotV); - - vec3 worldNormal = (osg_ViewMatrixInverse * vec4(n, 0.0)).xyz; - vec3 worldReflected = (osg_ViewMatrixInverse * vec4(reflect(-v, n), 0.0)).xyz; - - color += evaluateIBL(baseColor.rgb, - metallic, - roughness, - f0, - occlusion, - worldNormal, - NdotV, - worldReflected); - - vec2 coord = (gl_FragCoord.xy - fg_Viewport.xy) / fg_Viewport.zw; - color = add_aerial_perspective(color, coord, length(ecPos)); - - fragColor = vec4(color, baseColor.a); -} diff --git a/Shaders/HDR/geometry-pbr.frag b/Shaders/HDR/geometry-pbr.frag deleted file mode 100644 index 32969ad72..000000000 --- a/Shaders/HDR/geometry-pbr.frag +++ /dev/null @@ -1,44 +0,0 @@ -#version 330 core - -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 orm_tex; -uniform sampler2D emissive_tex; -uniform vec4 base_color_factor; -uniform float metallic_factor; -uniform float roughness_factor; -uniform vec3 emissive_factor; - -vec2 encodeNormal(vec3 n); -vec3 decodeSRGB(vec3 screenRGB); - -void main() -{ - 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); - - 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-runway.frag b/Shaders/HDR/geometry-runway.frag deleted file mode 100644 index 53850669e..000000000 --- a/Shaders/HDR/geometry-runway.frag +++ /dev/null @@ -1,45 +0,0 @@ -#version 330 core - -layout(location = 0) out vec4 outGBuffer0; -layout(location = 1) out vec4 outGBuffer1; -layout(location = 2) out vec4 outGBuffer2; - -in vec3 rawpos; -in vec2 texCoord; -in mat3 TBN; - -uniform sampler2D color_tex; -uniform sampler2D normal_tex; -uniform sampler3D noise_tex; - -const float NORMAL_MAP_SCALE = 8.0; - -vec2 encodeNormal(vec3 n); -vec3 decodeSRGB(vec3 screenRGB); - -void main() -{ - vec4 texel = texture(color_tex, texCoord); - vec3 color = decodeSRGB(texel.rgb); - - vec3 normal_texel = texture(normal_tex, texCoord * NORMAL_MAP_SCALE).rgb; - vec3 normal = normalize(TBN * (normal_texel * 2.0 - 1.0)); - - vec3 noise_large = texture(noise_tex, rawpos * 0.0045).rgb; - vec3 noise_small = texture(noise_tex, rawpos).rgb; - - float mix_factor = noise_large.r * noise_large.g * noise_large.b * 350.0; - mix_factor = smoothstep(0.0, 1.0, mix_factor); - - color = mix(color, noise_small, 0.15); - - float roughness = mix(0.94, 0.98, mix_factor); - - outGBuffer0.rg = encodeNormal(normal); - outGBuffer0.b = roughness; - outGBuffer0.a = 1.0; - outGBuffer1.rgb = vec3(color); - outGBuffer1.a = 0.0; - outGBuffer2.rgb = vec3(0.0); - outGBuffer2.a = 1.0; -} diff --git a/Shaders/HDR/geometry-terrain.frag b/Shaders/HDR/geometry-terrain.frag deleted file mode 100644 index 180e2f869..000000000 --- a/Shaders/HDR/geometry-terrain.frag +++ /dev/null @@ -1,38 +0,0 @@ -#version 330 core - -layout(location = 0) out vec4 outGBuffer0; -layout(location = 1) out vec4 outGBuffer1; -layout(location = 2) out vec4 outGBuffer2; - -in vec3 normalVS; -in vec2 texCoord; -in vec2 orthophoto_texCoord; - -uniform sampler2D color_tex; -uniform sampler2D orthophoto_tex; - -uniform bool orthophotoAvailable; - -vec2 encodeNormal(vec3 n); -vec3 decodeSRGB(vec3 screenRGB); - -void main() -{ - vec3 texel = texture(color_tex, texCoord).rgb; - if (orthophotoAvailable) { - vec4 sat_texel = texture(orthophoto_tex, orthophoto_texCoord); - if (sat_texel.a > 0.0) { - texel.rgb = sat_texel.rgb; - } - } - - vec3 color = decodeSRGB(texel); - - outGBuffer0.rg = encodeNormal(normalVS); - outGBuffer0.b = 0.95; - outGBuffer0.a = 1.0; - outGBuffer1.rgb = color; - outGBuffer1.a = 0.0; - outGBuffer2.rgb = vec3(0.0); - outGBuffer2.a = 1.0; -} diff --git a/Shaders/HDR/geometry-terrain.vert b/Shaders/HDR/geometry-terrain.vert deleted file mode 100644 index 02f3253f1..000000000 --- a/Shaders/HDR/geometry-terrain.vert +++ /dev/null @@ -1,21 +0,0 @@ -#version 330 core - -layout(location = 0) in vec4 pos; -layout(location = 1) in vec3 normal; -layout(location = 3) in vec4 multiTexCoord0; -layout(location = 5) in vec4 multiTexCoord2; - -out vec3 normalVS; -out vec2 texCoord; -out vec2 orthophoto_texCoord; - -uniform mat4 osg_ModelViewProjectionMatrix; -uniform mat3 osg_NormalMatrix; - -void main() -{ - gl_Position = osg_ModelViewProjectionMatrix * pos; - normalVS = normalize(osg_NormalMatrix * normal); - texCoord = multiTexCoord0.st; - orthophoto_texCoord = multiTexCoord2.st; -} diff --git a/Shaders/HDR/geometry-transparent.frag b/Shaders/HDR/geometry-transparent.frag deleted file mode 100644 index ce21dc297..000000000 --- a/Shaders/HDR/geometry-transparent.frag +++ /dev/null @@ -1,92 +0,0 @@ -#version 330 core - -out vec4 fragColor; - -in vec3 normalVS; -in vec2 texCoord; -in vec4 materialColor; -in vec3 ecPos; - -uniform sampler2D color_tex; - -uniform mat4 osg_ViewMatrixInverse; -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); -float getShadowing(vec3 p, vec3 n, vec3 l, mat4 viewToClip); -vec3 getF0Reflectance(vec3 baseColor, float metallic); -vec3 evaluateLight( - vec3 baseColor, - float metallic, - float roughness, - vec3 f0, - vec3 intensity, - float visibility, - vec3 n, - vec3 l, - vec3 v, - float NdotL, - float NdotV); -vec3 evaluateIBL( - vec3 baseColor, - float metallic, - float roughness, - vec3 f0, - float visibility, - vec3 nWorldSpace, - float NdotV, - vec3 reflected); -vec3 add_aerial_perspective(vec3 color, vec2 coord, float depth); -vec3 get_sun_radiance(vec3 p); - -void main() -{ - vec4 baseColorTexel = texture(color_tex, texCoord); - vec3 baseColor = decodeSRGB(baseColorTexel.rgb) * materialColor.rgb; - float alpha = materialColor.a * baseColorTexel.a; - - vec3 n = normalize(normalVS); - vec3 v = normalize(-ecPos); - vec3 l = fg_SunDirection; - - float NdotL = dot(n, l); - float NdotV = clamp(abs(dot(n, v)), 0.001, 1.0); - - vec3 f0 = getF0Reflectance(baseColor.rgb, 0.0); - - vec3 pos_world = (osg_ViewMatrixInverse * vec4(ecPos, 1.0)).xyz; - vec3 sun_radiance = get_sun_radiance(pos_world); - - float shadowFactor = getShadowing(ecPos, n, l, osg_ProjectionMatrix); - - vec3 color = evaluateLight(baseColor, - DEFAULT_TRANSPARENT_METALNESS, - DEFAULT_TRANSPARENT_ROUGHNESS, - f0, - sun_radiance, - shadowFactor, - n, l, v, - NdotL, NdotV); - - vec3 worldNormal = (osg_ViewMatrixInverse * vec4(n, 0.0)).xyz; - vec3 worldReflected = (osg_ViewMatrixInverse * vec4(reflect(-v, n), 0.0)).xyz; - - color += evaluateIBL(baseColor, - DEFAULT_TRANSPARENT_METALNESS, - DEFAULT_TRANSPARENT_ROUGHNESS, - f0, - 1.0, - worldNormal, - NdotV, - worldReflected); - - vec2 coord = (gl_FragCoord.xy - fg_Viewport.xy) / fg_Viewport.zw; - color = add_aerial_perspective(color, coord, length(ecPos)); - - fragColor = vec4(color, alpha); -} diff --git a/Shaders/HDR/geometry-transparent.vert b/Shaders/HDR/geometry-transparent.vert deleted file mode 100644 index b39d617d3..000000000 --- a/Shaders/HDR/geometry-transparent.vert +++ /dev/null @@ -1,44 +0,0 @@ -#version 330 core - -#define MODE_OFF 0 -#define MODE_DIFFUSE 1 -#define MODE_AMBIENT_AND_DIFFUSE 2 - -layout(location = 0) in vec4 pos; -layout(location = 1) in vec3 normal; -layout(location = 2) in vec4 vertexColor; -layout(location = 3) in vec4 multiTexCoord0; - -out vec3 normalVS; -out vec2 texCoord; -out vec4 materialColor; -out vec3 ecPos; - -uniform int color_mode; -uniform vec4 material_diffuse; - -uniform mat4 osg_ModelViewMatrix; -uniform mat4 osg_ModelViewProjectionMatrix; -uniform mat3 osg_NormalMatrix; - -void main() -{ - gl_Position = osg_ModelViewProjectionMatrix * pos; - normalVS = normalize(osg_NormalMatrix * normal); - texCoord = multiTexCoord0.st; - ecPos = (osg_ModelViewMatrix * pos).xyz; - - // Legacy material handling - if (color_mode == MODE_DIFFUSE) - materialColor = vertexColor; - else if (color_mode == MODE_AMBIENT_AND_DIFFUSE) - materialColor = vertexColor; - else - materialColor = material_diffuse; - // Super hack: if diffuse material alpha is less than 1, assume a - // transparency animation is at work - if (material_diffuse.a < 1.0) - materialColor.a = material_diffuse.a; - else - materialColor.a = vertexColor.a; -} diff --git a/Shaders/HDR/geometry.frag b/Shaders/HDR/geometry.frag deleted file mode 100644 index 62792d8d0..000000000 --- a/Shaders/HDR/geometry.frag +++ /dev/null @@ -1,31 +0,0 @@ -#version 330 core - -layout(location = 0) out vec4 outGBuffer0; -layout(location = 1) out vec4 outGBuffer1; -layout(location = 2) out vec4 outGBuffer2; - -in vec3 normalVS; -in vec2 texCoord; -in vec4 materialColor; - -uniform sampler2D color_tex; - -const float DEFAULT_METALNESS = 0.0; -const float DEFAULT_ROUGHNESS = 0.5; - -vec2 encodeNormal(vec3 n); -vec3 decodeSRGB(vec3 screenRGB); - -void main() -{ - vec3 texel = texture(color_tex, texCoord).rgb; - vec3 color = decodeSRGB(texel) * materialColor.rgb; // Ignore transparency - - 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/gtao.frag b/Shaders/HDR/gtao.frag index 61cc8e54d..7a703453e 100644 --- a/Shaders/HDR/gtao.frag +++ b/Shaders/HDR/gtao.frag @@ -1,4 +1,4 @@ -/** +/* * An implementation of GTAO (Ground Truth Ambient Occlusion) * Based on 'Practical Real-Time Strategies for Accurate Indirect Occlusion' by * Jorge Jimenez et al. @@ -9,9 +9,9 @@ #version 330 core -out float fragColor; +layout(location = 0) out float fragColor; -in vec2 texCoord; +in vec2 texcoord; uniform sampler2D gbuffer0_tex; uniform sampler2D depth_tex; @@ -22,17 +22,20 @@ uniform vec4 fg_Viewport; uniform vec2 fg_PixelSize; uniform mat4 fg_ProjectionMatrix; -const float PI = 3.141592653; -const float PI_HALF = PI * 0.5; const float SLICE_COUNT = 3.0; const float DIRECTION_SAMPLE_COUNT = 4.0; -vec3 decodeNormal(vec2 f); -vec3 positionFromDepth(vec2 pos, float depth); +// math.glsl +float M_PI(); +float M_PI_2(); +// normal_encoding.glsl +vec3 decode_normal(vec2 f); +// pos_from_depth.glsl +vec3 get_view_space_from_depth(vec2 uv, float depth); void main() { - float depth = textureLod(depth_tex, texCoord, 0.0).r; + float depth = textureLod(depth_tex, texcoord, 0.0).r; // Ignore the background if (depth == 0.0) { fragColor = 0.0; @@ -42,17 +45,17 @@ void main() depth = clamp(depth * 1.00001, 0.0, 1.0); // View space normal - vec3 normal = decodeNormal(texture(gbuffer0_tex, texCoord).rg); + vec3 N = decode_normal(texture(gbuffer0_tex, texcoord).rg); // Fragment position in view space - vec3 pos = positionFromDepth(texCoord, depth); + vec3 P = get_view_space_from_depth(texcoord, depth); // View vector in view space - vec3 v = normalize(-pos); + vec3 V = normalize(-P); - float noiseDirection = 0.0625 * float( + float noise_dir = 0.0625 * float( ((int(gl_FragCoord.x) + int(gl_FragCoord.y) & 3) << 2) + (int(gl_FragCoord.x) & 3)); - float noiseOffset = 0.25 * float(int(gl_FragCoord.x) + int(gl_FragCoord.y) & 3); + float noise_offset = 0.25 * float(int(gl_FragCoord.x) + int(gl_FragCoord.y) & 3); // Transform the world space hemisphere radius to screen space pixels with // the following formula: @@ -61,63 +64,63 @@ void main() // 1 / tan(fovy / 2), so we can use that directly. // z_distance is the distance from the camera to the fragment, which is // just the positive z component of the view space fragment position. - float radiusPixels = world_radius * (fg_ProjectionMatrix[1][1] / abs(pos.z)) + float radius_pixels = world_radius * (fg_ProjectionMatrix[1][1] / abs(P.z)) * fg_Viewport.w * 0.5; float visibility = 0.0; for (float i = 0.0; i < SLICE_COUNT; ++i) { - float phi = ((i + noiseDirection) / SLICE_COUNT) * PI; - float cosPhi = cos(phi); - float sinPhi = sin(phi); - vec2 omega = vec2(cosPhi, sinPhi); + float phi = ((i + noise_dir) / SLICE_COUNT) * M_PI(); + float cos_phi = cos(phi); + float sin_phi = sin(phi); + vec2 omega = vec2(cos_phi, sin_phi); vec3 dir = vec3(omega, 0.0); - vec3 orthoDirection = dir - dot(dir, v) * v; - vec3 axis = normalize(cross(dir, v)); - vec3 projNormal = normal - axis * dot(normal, axis); - float projNormalLength = max(1e-5, length(projNormal)); + vec3 ortho_dir = dir - dot(dir, V) * V; + vec3 axis = normalize(cross(dir, V)); + vec3 proj_N = N - axis * dot(N, axis); + float proj_N_len = max(1e-5, length(proj_N)); - float sgnN = sign(dot(orthoDirection, projNormal)); - float cosN = clamp(dot(projNormal, v) / projNormalLength, 0.0, 1.0); + float sgnN = sign(dot(ortho_dir, proj_N)); + float cosN = clamp(dot(proj_N, V) / proj_N_len, 0.0, 1.0); float n = sgnN * acos(cosN); float hcos1 = -1.0, hcos2 = -1.0; for (float j = 0.0; j < DIRECTION_SAMPLE_COUNT; ++j) { - float s = (j + noiseOffset) / DIRECTION_SAMPLE_COUNT; - s += 1.2 / radiusPixels; - vec2 sOffset = s * radiusPixels * omega; - sOffset = round(sOffset) * fg_PixelSize; + float s = (j + noise_offset) / DIRECTION_SAMPLE_COUNT; + s += 1.2 / radius_pixels; + vec2 s_offset = s * radius_pixels * omega; + s_offset = round(s_offset) * fg_PixelSize; - vec2 sTexCoord1 = texCoord - sOffset; - float sDepth1 = textureLod(depth_tex, sTexCoord1, 0.0).r; - if (sDepth1 == 0.0) { + vec2 s_texcoord1 = texcoord - s_offset; + float s_depth1 = textureLod(depth_tex, s_texcoord1, 0.0).r; + if (s_depth1 == 0.0) { // Skip background continue; } - vec3 sPos1 = positionFromDepth(sTexCoord1, sDepth1); + vec3 s_pos1 = get_view_space_from_depth(s_texcoord1, s_depth1); - vec2 sTexCoord2 = texCoord + sOffset; - float sDepth2 = textureLod(depth_tex, sTexCoord2, 0.0).r; - if (sDepth2 == 0.0) { + vec2 s_texcoord2 = texcoord + s_offset; + float s_depth2 = textureLod(depth_tex, s_texcoord2, 0.0).r; + if (s_depth2 == 0.0) { // Skip background continue; } - vec3 sPos2 = positionFromDepth(sTexCoord2, sDepth2); + vec3 s_pos2 = get_view_space_from_depth(s_texcoord2, s_depth2); - vec3 sHorizon1 = sPos1 - pos; - vec3 sHorizon2 = sPos2 - pos; - float sHorizonLength1 = length(sHorizon1); - float sHorizonLength2 = length(sHorizon2); + vec3 s_horizon1 = s_pos1 - P; + vec3 s_horizon2 = s_pos2 - P; + float s_horizon1_len = length(s_horizon1); + float s_horizon2_len = length(s_horizon2); - float shcos1 = dot(sHorizon1 / sHorizonLength1, v); - float shcos2 = dot(sHorizon2 / sHorizonLength2, v); + float shcos1 = dot(s_horizon1 / s_horizon1_len, V); + float shcos2 = dot(s_horizon2 / s_horizon2_len, V); // Section 4.3: Bounding the sampling area // Attenuate samples that are further away - float weight1 = clamp((1.0 - sHorizonLength1 / world_radius) * 2.0, 0.0, 1.0); - float weight2 = clamp((1.0 - sHorizonLength2 / world_radius) * 2.0, 0.0, 1.0); + float weight1 = clamp((1.0 - s_horizon1_len / world_radius) * 2.0, 0.0, 1.0); + float weight2 = clamp((1.0 - s_horizon2_len / world_radius) * 2.0, 0.0, 1.0); shcos1 = mix(-1.0, shcos1, weight1); shcos2 = mix(-1.0, shcos2, weight2); @@ -125,15 +128,15 @@ void main() hcos2 = max(hcos2, shcos2); } - float h1 = n + max(-acos(hcos1) - n, -PI_HALF); - float h2 = n + min( acos(hcos2) - n, PI_HALF); + float h1 = n + max(-acos(hcos1) - n, -M_PI_2()); + float h2 = n + min( acos(hcos2) - n, M_PI_2()); float sinN = sin(n); float h1_2 = 2.0 * h1; float h2_2 = 2.0 * h2; float vd = 0.25 * ((cosN + h1_2 * sinN - cos(h1_2 - n)) + (cosN + h2_2 * sinN - cos(h2_2 - n))); - visibility += projNormalLength * vd; + visibility += proj_N_len * vd; } visibility /= float(SLICE_COUNT); diff --git a/Shaders/HDR/gtao.glsl b/Shaders/HDR/gtao.glsl new file mode 100644 index 000000000..b2304a722 --- /dev/null +++ b/Shaders/HDR/gtao.glsl @@ -0,0 +1,23 @@ +#version 330 core + +uniform sampler2D ao_tex; + +uniform bool ambient_occlusion_enabled; + +float GTAO_multibounce(float x, vec3 albedo) +{ + // Use luminance instead of albedo because colored multibounce looks bad + // Idea borrowed from Blender Eevee + float lum = dot(albedo, vec3(0.333)); + float a = 2.0404 * lum - 0.3324; + float b = -4.7951 * lum + 0.6417; + float c = 2.7552 * lum + 0.6903; + return max(x, ((x * a + b) * x + c) * x); +} + +float get_ambient_occlusion(vec2 uv, vec3 albedo) +{ + if (ambient_occlusion_enabled) + return GTAO_multibounce(texture(ao_tex, uv).r, albedo); + return 1.0; +} diff --git a/Shaders/HDR/gtao-denoiser.frag b/Shaders/HDR/gtao_denoiser.frag similarity index 91% rename from Shaders/HDR/gtao-denoiser.frag rename to Shaders/HDR/gtao_denoiser.frag index 59cfd28d9..0194bcaa0 100644 --- a/Shaders/HDR/gtao-denoiser.frag +++ b/Shaders/HDR/gtao_denoiser.frag @@ -1,6 +1,6 @@ #version 330 core -out float fragColor; +layout(location = 0) out float fragColor; uniform sampler2D ao_tex; @@ -9,7 +9,7 @@ void main() ivec2 coord = ivec2(gl_FragCoord.xy) - ivec2(2); float ao = 0.0; - ao += texelFetch(ao_tex, coord, 0).r; + ao += texelFetch(ao_tex, coord, 0).r; ao += texelFetch(ao_tex, coord + ivec2(1, 0), 0).r; ao += texelFetch(ao_tex, coord + ivec2(0, 1), 0).r; ao += texelFetch(ao_tex, coord + ivec2(1, 1), 0).r; diff --git a/Shaders/HDR/histogram-include.frag b/Shaders/HDR/histogram.glsl similarity index 94% rename from Shaders/HDR/histogram-include.frag rename to Shaders/HDR/histogram.glsl index 205c63408..1d7f502ff 100644 --- a/Shaders/HDR/histogram-include.frag +++ b/Shaders/HDR/histogram.glsl @@ -1,6 +1,6 @@ #version 330 core -const float NUM_BINS = 254.0; +const float NUM_BINS = 254.0; // 256 - 2 const float INV_NUM_BINS = 1.0 / NUM_BINS; const float MIN_LOG_LUM = -10.0; diff --git a/Shaders/HDR/histogram-aggregate.frag b/Shaders/HDR/histogram_aggregate.frag similarity index 91% rename from Shaders/HDR/histogram-aggregate.frag rename to Shaders/HDR/histogram_aggregate.frag index eae557df6..226acb5c3 100644 --- a/Shaders/HDR/histogram-aggregate.frag +++ b/Shaders/HDR/histogram_aggregate.frag @@ -1,6 +1,6 @@ #version 330 core -out uint fragHits; +layout(location = 0) out uint fragHits; uniform usampler2D partial_histogram_tex; diff --git a/Shaders/HDR/histogram-column.frag b/Shaders/HDR/histogram_column.frag similarity index 80% rename from Shaders/HDR/histogram-column.frag rename to Shaders/HDR/histogram_column.frag index 37aa85d51..bd3202ba0 100644 --- a/Shaders/HDR/histogram-column.frag +++ b/Shaders/HDR/histogram_column.frag @@ -1,16 +1,14 @@ #version 330 core -out uint fragHits; +layout(location = 0) out uint fragHits; uniform sampler2D hdr_tex; +// color.glsl +float linear_srgb_to_luminance(vec3 color); +// histogram.glsl uint luminance_to_bin_index(float luminance); -float srgb_to_luminance(vec3 color) -{ - return dot(color, vec3(0.2125, 0.7154, 0.0721)); -} - void main() { ivec2 hdr_tex_size = textureSize(hdr_tex, 0); @@ -22,7 +20,7 @@ void main() for (int row = 0; row < hdr_tex_size.y; ++row) { vec3 hdr_color = texelFetch(hdr_tex, ivec2(column, row), 0).rgb; // sRGB to relative luminance - float lum = srgb_to_luminance(hdr_color); + float lum = linear_srgb_to_luminance(hdr_color); // Get the bin index corresponding to the given pixel luminance uint pixel_bin = luminance_to_bin_index(lum); // Check if this pixel should go in the bin diff --git a/Shaders/HDR/histogram-luminance.frag b/Shaders/HDR/histogram_luminance.frag similarity index 94% rename from Shaders/HDR/histogram-luminance.frag rename to Shaders/HDR/histogram_luminance.frag index 3df7034e8..6e91bce4f 100644 --- a/Shaders/HDR/histogram-luminance.frag +++ b/Shaders/HDR/histogram_luminance.frag @@ -1,6 +1,6 @@ #version 330 core -out float fragLuminance; +layout(location = 0) out float fragLuminance; uniform usampler2D histogram_tex; uniform sampler2D prev_lum_tex; @@ -10,6 +10,7 @@ uniform float osg_DeltaFrameTime; // Higher values give faster eye adaptation times const float TAU = 1.1; +// histogram.glsl float bin_index_to_luminance(float bin); void main() diff --git a/Shaders/HDR/ibl.glsl b/Shaders/HDR/ibl.glsl new file mode 100644 index 000000000..8d3522338 --- /dev/null +++ b/Shaders/HDR/ibl.glsl @@ -0,0 +1,75 @@ +#version 330 core + +uniform sampler2D dfg_tex; +uniform samplerCube prefiltered_envmap_tex; + +const float MAX_PREFILTERED_LOD = 4.0; + +// math.glsl +float pow5(float x); + +vec3 get_reflected(vec3 N, vec3 V, mat4 view_matrix_inverse) +{ + return (view_matrix_inverse * vec4(reflect(-V, N), 0.0)).xyz; +} + +/* + * Fresnel term with included roughness to get a pleasant visual result. + * See https://seblagarde.wordpress.com/2011/08/17/hello-world/ + */ +vec3 F_Schlick_roughness(float NdotV, vec3 F0, float r) +{ + return F0 + (max(vec3(1.0 - r), F0) - F0) * pow5(max(1.0 - NdotV, 0.0)); +} + +/* + * Evaluate the indirect diffuse irradiance. + * + * To get better results we should be precomputing the irradiance into a cubemap + * or calculating spherical harmonics coefficients on the CPU. + * Sampling the roughness=1 mipmap level of the prefiltered specular map works + * fine too. :) + */ +vec3 ibl_eval_diffuse(vec3 N) +{ + int max_lod = int(MAX_PREFILTERED_LOD); + ivec2 s = textureSize(prefiltered_envmap_tex, max_lod); + float du = 1.0 / float(s.x); + float dv = 1.0 / float(s.y); + vec3 m0 = normalize(cross(N, vec3(0.0, 1.0, 0.0))); + vec3 m1 = cross(m0, N); + vec3 m0du = m0 * du; + vec3 m1dv = m1 * dv; + vec3 c; + c = textureLod(prefiltered_envmap_tex, N - m0du - m1dv, max_lod).rgb; + c += textureLod(prefiltered_envmap_tex, N + m0du - m1dv, max_lod).rgb; + c += textureLod(prefiltered_envmap_tex, N + m0du + m1dv, max_lod).rgb; + c += textureLod(prefiltered_envmap_tex, N - m0du + m1dv, max_lod).rgb; + return 0.25 * c; +} + +/* + * Evaluate the indirect specular. + * Sample from the prefiltered environment map. + */ +vec3 ibl_eval_specular(float NdotV, vec3 refl, float roughness, vec3 f) +{ + float lod = roughness * float(MAX_PREFILTERED_LOD); + vec3 prefiltered = textureLod(prefiltered_envmap_tex, refl, lod).rgb; + vec2 env_brdf = texture(dfg_tex, vec2(NdotV, roughness)).rg; + return prefiltered * (f * env_brdf.x + env_brdf.y); +} + +/* + * Evaluate the contribution of image-based lights, or indirect lighting. + */ +vec3 eval_ibl(vec3 base_color, float metallic, float roughness, vec3 f0, + float occlusion, vec3 ws_N, vec3 ws_refl, float NdotV) +{ + roughness = max(roughness, 0.002025); + vec3 F = F_Schlick_roughness(NdotV, f0, roughness); + vec3 specular = ibl_eval_specular(NdotV, ws_refl, roughness, F); + vec3 diffuse = ibl_eval_diffuse(ws_N) * base_color + * (vec3(1.0) - F) * (1.0 - metallic); + return (diffuse + specular) * occlusion; +} diff --git a/Shaders/HDR/lighting-include.frag b/Shaders/HDR/lighting-include.frag deleted file mode 100644 index f6dc46d8d..000000000 --- a/Shaders/HDR/lighting-include.frag +++ /dev/null @@ -1,185 +0,0 @@ -#version 330 core - -uniform sampler2D dfg_lut; -uniform samplerCube prefiltered_envmap; - -const float PI = 3.14159265359; -const float RECIPROCAL_PI = 0.31830988618; -const float DIELECTRIC_SPECULAR = 0.04; -const float MAX_PREFILTERED_LOD = 4.0; - -//------------------------------------------------------------------------------ -// BRDF utility functions - -/** - * Fresnel term with included roughness to get a pleasant visual result. - * See https://seblagarde.wordpress.com/2011/08/17/hello-world/ - */ -vec3 F_SchlickRoughness(float NdotV, vec3 F0, float r) -{ - return F0 + (max(vec3(1.0 - r), F0) - F0) * pow(max(1.0 - NdotV, 0.0), 5.0); -} - -/** - * Fresnel (specular F) - * Schlick's approximation for the Cook-Torrance BRDF. - */ -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 - * reparametrization of a=roughness*roughness - */ -float D_GGX(float NdotH, float a2) -{ - float f = (NdotH * a2 - NdotH) * NdotH + 1.0; - return a2 / (PI * f * f); -} - -/** - * Geometric attenuation (specular G) - * Smith-GGX formulation. - */ -float G_SmithGGX(float NdotV, float NdotL, float a2) -{ - float attV = 2.0 * NdotV / (NdotV + sqrt(a2 + (1.0 - a2) * (NdotV * NdotV))); - float attL = 2.0 * NdotL / (NdotL + sqrt(a2 + (1.0 - a2) * (NdotL * NdotL))); - return attV * attL; -} - -/** - * Basic Lambertian diffuse BRDF - */ -vec3 Fd_Lambert(vec3 c_diff) -{ - return c_diff * RECIPROCAL_PI; -} - -/** - * Get the fresnel reflectance at 0 degrees (light hitting the surface - * perpendicularly). - */ -vec3 getF0Reflectance(vec3 baseColor, float metallic) -{ - return mix(vec3(DIELECTRIC_SPECULAR), baseColor, metallic); -} - -//------------------------------------------------------------------------------ -// IBL evaluation - -/** - * Indirect diffuse irradiance - * To get better results we should be precomputing the irradiance into a cubemap - * or calculating spherical harmonics coefficients on the CPU. - * Sampling the roughness=1 mipmap level of the prefiltered specular map - * works too. :) - */ -vec3 evaluateDiffuseIrradianceIBL(vec3 n) -{ - int roughnessOneLevel = int(MAX_PREFILTERED_LOD); - ivec2 s = textureSize(prefiltered_envmap, roughnessOneLevel); - float du = 1.0 / float(s.x); - float dv = 1.0 / float(s.y); - vec3 m0 = normalize(cross(n, vec3(0.0, 1.0, 0.0))); - vec3 m1 = cross(m0, n); - vec3 m0du = m0 * du; - vec3 m1dv = m1 * dv; - - vec3 c; - c = textureLod(prefiltered_envmap, n - m0du - m1dv, roughnessOneLevel).rgb; - c += textureLod(prefiltered_envmap, n + m0du - m1dv, roughnessOneLevel).rgb; - c += textureLod(prefiltered_envmap, n + m0du + m1dv, roughnessOneLevel).rgb; - c += textureLod(prefiltered_envmap, n - m0du + m1dv, roughnessOneLevel).rgb; - return c * 0.25; -} - -/** - * Indirect specular (ambient specular) - * Sample from the prefiltered environment map. - */ -vec3 evaluateSpecularIBL(float NdotV, vec3 reflected, float roughness, vec3 f) -{ - vec3 prefilteredColor = textureLod(prefiltered_envmap, - reflected, - roughness * MAX_PREFILTERED_LOD).rgb; - vec2 envBRDF = texture(dfg_lut, vec2(NdotV, roughness)).rg; - return prefilteredColor * (f * envBRDF.x + envBRDF.y); -} - -vec3 evaluateIBL( - vec3 baseColor, - float metallic, - float roughness, - vec3 f0, // Use getF0Reflectance() to obtain this - float visibility, - vec3 nWorldSpace, // Normal in world space - float NdotV, // Must be positive and non-zero - vec3 reflected // Reflected vector in world space: reflect(-v, n) - ) -{ - vec3 f = F_SchlickRoughness(NdotV, f0, roughness); - - vec3 specular = evaluateSpecularIBL(NdotV, reflected, roughness, f); - vec3 diffuse = evaluateDiffuseIrradianceIBL(nWorldSpace) * baseColor - * (vec3(1.0) - f) * (1.0 - metallic); - - return (diffuse + specular) * visibility; -} - -//------------------------------------------------------------------------------ -// Analytical light source evaluation - -vec3 evaluateLight( - vec3 baseColor, - float metallic, - float roughness, - vec3 f0, // Use getF0Reflectance() to obtain this - vec3 intensity, - float visibility, - vec3 n, - vec3 l, - vec3 v, - float NdotL, // Must not be clamped to [0,1] - float NdotV // Must be positive and non-zero - ) -{ - // Skip fragments that are completely occluded or that are not facing the light - if (visibility <= 0.0 || NdotL <= 0.0) - return vec3(0.0); - - NdotL = clamp(NdotL, 0.001, 1.0); - - vec3 h = normalize(v + l); - float NdotH = clamp(dot(n, h), 0.0, 1.0); - float VdotH = clamp(dot(v, h), 0.0, 1.0); - - vec3 c_diff = mix(baseColor * (1.0 - DIELECTRIC_SPECULAR), vec3(0.0), metallic); - - // Avoid blown out lighting by capping the roughness to a non-zero value - float a = max(roughness * roughness, 0.001); - float a2 = a * a; - - vec3 F = F_Schlick(VdotH, f0); - float D = D_GGX(NdotH, a2); - float G = G_SmithGGX(NdotV, NdotL, a2); - - // Diffuse term: Lambertian diffuse model - vec3 f_diffuse = (vec3(1.0) - F) * Fd_Lambert(c_diff); - - // 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 * visibility * NdotL; - return color; -} diff --git a/Shaders/HDR/lighting.frag b/Shaders/HDR/lighting.frag deleted file mode 100644 index 257fa4e74..000000000 --- a/Shaders/HDR/lighting.frag +++ /dev/null @@ -1,136 +0,0 @@ -#version 330 core - -out vec3 fragColor; - -in vec2 texCoord; - -uniform sampler2D gbuffer0_tex; -uniform sampler2D gbuffer1_tex; -uniform sampler2D gbuffer2_tex; -uniform sampler2D depth_tex; -uniform sampler2D ao_tex; - -uniform bool ambient_occlusion_enabled; -uniform bool debug_shadow_cascades; - -uniform mat4 fg_ViewMatrixInverse; -uniform mat4 fg_ProjectionMatrix; -uniform vec3 fg_SunDirection; - -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, - vec3 f0, - vec3 intensity, - float visibility, - vec3 n, - vec3 l, - vec3 v, - float NdotL, - float NdotV); -vec3 evaluateIBL( - vec3 baseColor, - float metallic, - float roughness, - vec3 f0, - float visibility, - vec3 nWorldSpace, - float NdotV, - vec3 reflected); -vec3 add_aerial_perspective(vec3 color, vec2 coord, float depth); -vec3 get_sun_radiance(vec3 p); - -vec3 get_contribution_from_scene_lights( - vec3 p, - vec3 base_color, - float metallic, - float roughness, - vec3 f0, - vec3 n, - vec3 v); - -float GTAOMultiBounce(float x, vec3 albedo) -{ - // Use luminance instead of albedo because colored multibounce looks bad - // Idea borrowed from Blender Eevee - float lum = dot(albedo, vec3(0.333)); - float a = 2.0404 * lum - 0.3324; - float b = -4.7951 * lum + 0.6417; - float c = 2.7552 * lum + 0.6903; - return max(x, ((x * a + b) * x + c) * x); -} - -void main() -{ - vec4 gbuffer0 = texture(gbuffer0_tex, texCoord); - vec4 gbuffer1 = texture(gbuffer1_tex, texCoord); - vec4 gbuffer2 = texture(gbuffer2_tex, texCoord); - 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 l = fg_SunDirection; - - float NdotL = dot(n, l); - float NdotV = clamp(abs(dot(n, v)), 0.001, 1.0); - - vec3 f0 = getF0Reflectance(baseColor, metallic); - - vec3 pos_world = (fg_ViewMatrixInverse * vec4(pos, 1.0)).xyz; - vec3 sun_radiance = get_sun_radiance(pos_world); - - float shadowFactor = getShadowing(pos, n, l, fg_ProjectionMatrix); - - vec3 color = evaluateLight(baseColor, - metallic, - roughness, - f0, - sun_radiance, - shadowFactor, - n, l, v, - NdotL, NdotV); - - color += get_contribution_from_scene_lights(pos, - baseColor, - metallic, - roughness, - f0, n, v); - - float ao = occlusion; - if (ambient_occlusion_enabled) { - ao *= GTAOMultiBounce(texture(ao_tex, texCoord).r, baseColor); - } - - vec3 worldNormal = (fg_ViewMatrixInverse * vec4(n, 0.0)).xyz; - vec3 worldReflected = (fg_ViewMatrixInverse * vec4(reflect(-v, n), 0.0)).xyz; - - color += evaluateIBL(baseColor, - metallic, - roughness, - f0, - ao, - worldNormal, - NdotV, - worldNormal); - - color = add_aerial_perspective(color, texCoord, length(pos)); - - if (debug_shadow_cascades) - color *= debugShadowColor(pos, n, l); - - fragColor = color; -} diff --git a/Shaders/HDR/math.glsl b/Shaders/HDR/math.glsl new file mode 100644 index 000000000..21b545be3 --- /dev/null +++ b/Shaders/HDR/math.glsl @@ -0,0 +1,36 @@ +#version 330 core + +/* + * Due to how GLSL shader linking works, we cannot share #defines or constants + * across multiple shaders. As a workaround, we create functions that return + * the constants. There should be no performance impact due to this because the + * compiler inlines the function calls. + */ +float M_PI() { return 3.14159265358979323846; } // pi +float M_2PI() { return 6.28318530717958647692; } // 2*pi +float M_4PI() { return 12.5663706143591729539; } // 4*pi +float M_PI_2() { return 1.57079632679489661923; } // pi/2 +float M_PI_4() { return 0.78539816339744830962; } // pi/4 +float M_1_PI() { return 0.31830988618379067154; } // 1/pi +float M_1_4PI() { return 0.07957747154594766788; } // 1/(4*pi) + +float sqr(float x) { + return x * x; +} + +float saturate(float x) { + return clamp(x, 0.0, 1.0); +} + +float safe_sqrt(float x) { + return sqrt(max(x, 0.0)); +} + +float safe_acos(float x) { + return acos(clamp(x, -1.0, 1.0)); +} + +float pow5(float x) { + float x2 = x*x; + return x2 * x2 * x; +} diff --git a/Shaders/HDR/model_chrome.frag b/Shaders/HDR/model_chrome.frag new file mode 100644 index 000000000..bebd6d7ce --- /dev/null +++ b/Shaders/HDR/model_chrome.frag @@ -0,0 +1,15 @@ +#version 330 core + +in vec3 vN; + +const float CHROME_METALLIC = 1.0; +const float CHROME_ROUGHNESS = 0.1; + +// gbuffer_pack.glsl +void gbuffer_pack(vec3 normal, vec3 base_color, float metallic, float roughness, + float occlusion, vec3 emissive, uint mat_id); + +void main() +{ + gbuffer_pack(vN, vec3(1.0), CHROME_METALLIC, CHROME_ROUGHNESS, 1.0, vec3(0.0), 3u); +} diff --git a/Shaders/HDR/geometry-chrome.vert b/Shaders/HDR/model_chrome.vert similarity index 76% rename from Shaders/HDR/geometry-chrome.vert rename to Shaders/HDR/model_chrome.vert index 37063154c..8d65cc5a2 100644 --- a/Shaders/HDR/geometry-chrome.vert +++ b/Shaders/HDR/model_chrome.vert @@ -3,7 +3,7 @@ layout(location = 0) in vec4 pos; layout(location = 1) in vec3 normal; -out vec3 normalVS; +out vec3 vN; uniform mat4 osg_ModelViewProjectionMatrix; uniform mat3 osg_NormalMatrix; @@ -11,5 +11,5 @@ uniform mat3 osg_NormalMatrix; void main() { gl_Position = osg_ModelViewProjectionMatrix * pos; - normalVS = normalize(osg_NormalMatrix * normal); + vN = normalize(osg_NormalMatrix * normal); } diff --git a/Shaders/HDR/model_combined.frag b/Shaders/HDR/model_combined.frag new file mode 100644 index 000000000..63f12f054 --- /dev/null +++ b/Shaders/HDR/model_combined.frag @@ -0,0 +1,36 @@ +#version 330 core + +in vec2 texcoord; +in mat3 TBN; + +uniform sampler2D color_tex; +uniform sampler2D normal_tex; +uniform int normalmap_enabled; +uniform int normalmap_dds; +uniform float normalmap_tiling; + +const float COMBINED_METALLIC = 0.0; +const float COMBINED_ROUGHNESS = 0.1; + +// gbuffer_pack.glsl +void gbuffer_pack(vec3 normal, vec3 base_color, float metallic, float roughness, + float occlusion, vec3 emissive, uint mat_id); +// color.glsl +vec3 eotf_inverse_sRGB(vec3 srgb); + +void main() +{ + vec3 texel = texture(color_tex, texcoord).rgb; + vec3 color = eotf_inverse_sRGB(texel); + + vec3 normal = vec3(0.0, 0.0, 1.0); + if (normalmap_enabled > 0) { + normal = texture(normal_tex, texcoord * normalmap_tiling).rgb * 2.0 - 1.0; + // DDS has flipped normals + if (normalmap_dds > 0) + normal = -normal; + } + vec3 N = normalize(TBN * normal); + + gbuffer_pack(N, color, COMBINED_METALLIC, COMBINED_ROUGHNESS, 1.0, vec3(0.0), 3u); +} diff --git a/Shaders/HDR/geometry-combined.vert b/Shaders/HDR/model_combined.vert similarity index 87% rename from Shaders/HDR/geometry-combined.vert rename to Shaders/HDR/model_combined.vert index 2b9d8f144..fd85eedf9 100644 --- a/Shaders/HDR/geometry-combined.vert +++ b/Shaders/HDR/model_combined.vert @@ -2,11 +2,11 @@ layout(location = 0) in vec4 pos; layout(location = 1) in vec3 normal; -layout(location = 3) in vec4 multiTexCoord0; +layout(location = 3) in vec4 multitexcoord0; layout(location = 6) in vec3 tangent; layout(location = 7) in vec3 binormal; -out vec2 texCoord; +out vec2 texcoord; out mat3 TBN; uniform int normalmap_enabled; @@ -17,7 +17,7 @@ uniform mat3 osg_NormalMatrix; void main() { gl_Position = osg_ModelViewProjectionMatrix * pos; - texCoord = multiTexCoord0.st; + texcoord = multitexcoord0.st; vec3 N = normalize(normal); vec3 T, B; diff --git a/Shaders/HDR/model_default.frag b/Shaders/HDR/model_default.frag new file mode 100644 index 000000000..fc7a4a220 --- /dev/null +++ b/Shaders/HDR/model_default.frag @@ -0,0 +1,24 @@ +#version 330 core + +in vec3 vN; +in vec2 texcoord; +in vec4 material_color; + +uniform sampler2D color_tex; + +const float DEFAULT_METALLIC = 0.0; +const float DEFAULT_ROUGHNESS = 0.5; + +// gbuffer_pack.glsl +void gbuffer_pack(vec3 normal, vec3 base_color, float metallic, float roughness, + float occlusion, vec3 emissive, uint mat_id); +// color.glsl +vec3 eotf_inverse_sRGB(vec3 srgb); + +void main() +{ + vec3 texel = texture(color_tex, texcoord).rgb; + vec3 color = eotf_inverse_sRGB(texel) * material_color.rgb; + + gbuffer_pack(vN, color, DEFAULT_METALLIC, DEFAULT_ROUGHNESS, 1.0, vec3(0.0), 3u); +} diff --git a/Shaders/HDR/geometry.vert b/Shaders/HDR/model_default.vert similarity index 58% rename from Shaders/HDR/geometry.vert rename to Shaders/HDR/model_default.vert index 6284fd441..ebf6d3b18 100644 --- a/Shaders/HDR/geometry.vert +++ b/Shaders/HDR/model_default.vert @@ -6,12 +6,12 @@ layout(location = 0) in vec4 pos; layout(location = 1) in vec3 normal; -layout(location = 2) in vec4 vertexColor; -layout(location = 3) in vec4 multiTexCoord0; +layout(location = 2) in vec4 vertex_color; +layout(location = 3) in vec4 multitexcoord0; -out vec3 normalVS; -out vec2 texCoord; -out vec4 materialColor; +out vec3 vN; +out vec2 texcoord; +out vec4 material_color; uniform int color_mode; uniform vec4 material_diffuse; @@ -22,14 +22,14 @@ uniform mat3 osg_NormalMatrix; void main() { gl_Position = osg_ModelViewProjectionMatrix * pos; - normalVS = normalize(osg_NormalMatrix * normal); - texCoord = multiTexCoord0.st; + vN = normalize(osg_NormalMatrix * normal); + texcoord = multitexcoord0.st; // Legacy material handling if (color_mode == MODE_DIFFUSE) - materialColor = vertexColor; + material_color = vertex_color; else if (color_mode == MODE_AMBIENT_AND_DIFFUSE) - materialColor = vertexColor; + material_color = vertex_color; else - materialColor = material_diffuse; + material_color = material_diffuse; } diff --git a/Shaders/HDR/model_pbr.frag b/Shaders/HDR/model_pbr.frag new file mode 100644 index 000000000..8e2be762a --- /dev/null +++ b/Shaders/HDR/model_pbr.frag @@ -0,0 +1,38 @@ +#version 330 core + +in vec2 texcoord; +in mat3 TBN; + +uniform sampler2D base_color_tex; +uniform sampler2D normal_tex; +uniform sampler2D orm_tex; +uniform sampler2D emissive_tex; + +uniform vec4 base_color_factor; +uniform float metallic_factor; +uniform float roughness_factor; +uniform vec3 emissive_factor; + +// gbuffer_pack.glsl +void gbuffer_pack(vec3 normal, vec3 base_color, float metallic, float roughness, + float occlusion, vec3 emissive, uint mat_id); +// color.glsl +vec3 eotf_inverse_sRGB(vec3 srgb); + +void main() +{ + vec4 base_color_texel = texture(base_color_tex, texcoord); + vec3 base_color = eotf_inverse_sRGB(base_color_texel.rgb) * base_color_factor.rgb; + + vec3 normal = texture(normal_tex, texcoord).rgb * 2.0 - 1.0; + vec3 N = normalize(TBN * normal); + + 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; + + gbuffer_pack(N, base_color, metallic, roughness, occlusion, emissive, 3u); +} diff --git a/Shaders/HDR/geometry-pbr.vert b/Shaders/HDR/model_pbr.vert similarity index 80% rename from Shaders/HDR/geometry-pbr.vert rename to Shaders/HDR/model_pbr.vert index bbd2f50ed..804135f60 100644 --- a/Shaders/HDR/geometry-pbr.vert +++ b/Shaders/HDR/model_pbr.vert @@ -2,11 +2,11 @@ layout(location = 0) in vec4 pos; layout(location = 1) in vec3 normal; -layout(location = 3) in vec4 multiTexCoord0; +layout(location = 3) in vec4 multitexcoord0; layout(location = 6) in vec3 tangent; layout(location = 7) in vec3 binormal; -out vec2 texCoord; +out vec2 texcoord; out mat3 TBN; uniform mat4 osg_ModelViewProjectionMatrix; @@ -17,9 +17,9 @@ uniform bool flip_vertically; void main() { gl_Position = osg_ModelViewProjectionMatrix * pos; - texCoord = multiTexCoord0.st; + texcoord = multitexcoord0.st; if (flip_vertically) - texCoord.y = 1.0 - texCoord.y; + texcoord.y = 1.0 - texcoord.y; vec3 T = normalize(osg_NormalMatrix * tangent); vec3 B = normalize(osg_NormalMatrix * binormal); diff --git a/Shaders/HDR/model_pbr_transparent.frag b/Shaders/HDR/model_pbr_transparent.frag new file mode 100644 index 000000000..62164ad00 --- /dev/null +++ b/Shaders/HDR/model_pbr_transparent.frag @@ -0,0 +1,58 @@ +#version 330 core + +layout(location = 0) out vec4 fragColor; + +in vec3 vP; +in vec2 texcoord; +in mat3 TBN; +in vec4 ap_color; + +uniform sampler2D base_color_tex; +uniform sampler2D normal_tex; +uniform sampler2D orm_tex; +uniform sampler2D emissive_tex; + +uniform vec4 base_color_factor; +uniform float metallic_factor; +uniform float roughness_factor; +uniform vec3 emissive_factor; +uniform float alpha_cutoff; + +uniform mat4 osg_ViewMatrixInverse; +uniform mat4 osg_ProjectionMatrix; +uniform vec4 fg_Viewport; + +// color.glsl +vec3 eotf_inverse_sRGB(vec3 srgb); +// shading_transparent.glsl +vec3 eval_lights_transparent( + vec3 base_color, float metallic, float roughness, float occlusion, + vec3 P, vec3 N, vec3 V, vec2 uv, vec4 ap, + mat4 view_matrix_inverse); + +void main() +{ + vec4 base_color_texel = texture(base_color_tex, texcoord); + vec4 base_color = vec4(eotf_inverse_sRGB(base_color_texel.rgb), base_color_texel.a) + * base_color_factor; + if (base_color.a < alpha_cutoff) + discard; + + vec3 normal = texture(normal_tex, texcoord).rgb * 2.0 - 1.0; + vec3 N = normalize(TBN * normal); + + 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; + + vec3 V = normalize(-vP); + vec2 uv = (gl_FragCoord.xy - fg_Viewport.xy) / fg_Viewport.zw; + + vec3 color = eval_lights_transparent( + base_color.rgb, metallic, roughness, occlusion, + vP, N, V, uv, ap_color, osg_ViewMatrixInverse); + + fragColor = vec4(color, baseColor.a); +} diff --git a/Shaders/HDR/geometry-pbr-transparent.vert b/Shaders/HDR/model_pbr_transparent.vert similarity index 59% rename from Shaders/HDR/geometry-pbr-transparent.vert rename to Shaders/HDR/model_pbr_transparent.vert index 23179eb19..7a18b5933 100644 --- a/Shaders/HDR/geometry-pbr-transparent.vert +++ b/Shaders/HDR/model_pbr_transparent.vert @@ -2,13 +2,14 @@ layout(location = 0) in vec4 pos; layout(location = 1) in vec3 normal; -layout(location = 3) in vec4 multiTexCoord0; +layout(location = 3) in vec4 multitexcoord0; layout(location = 6) in vec3 tangent; layout(location = 7) in vec3 binormal; -out vec2 texCoord; +out vec3 vP; +out vec2 texcoord; out mat3 TBN; -out vec3 ecPos; +out vec4 ap_color; uniform mat4 osg_ModelViewMatrix; uniform mat4 osg_ModelViewProjectionMatrix; @@ -16,17 +17,22 @@ uniform mat3 osg_NormalMatrix; uniform bool flip_vertically; +// aerial_perspective.glsl +vec4 get_aerial_perspective(vec2 coord, float depth); + void main() { gl_Position = osg_ModelViewProjectionMatrix * pos; - texCoord = multiTexCoord0.st; + vP = (osg_ModelViewMatrix * pos).xyz; + texcoord = multitexcoord0.st; if (flip_vertically) - texCoord.y = 1.0 - texCoord.y; + texcoord.y = 1.0 - texcoord.y; vec3 T = normalize(osg_NormalMatrix * tangent); vec3 B = normalize(osg_NormalMatrix * binormal); vec3 N = normalize(osg_NormalMatrix * normal); TBN = mat3(T, B, N); - ecPos = (osg_ModelViewMatrix * pos).xyz; + vec2 coord = (gl_Position.xy / gl_Position.w) * 0.5 + 0.5; + ap_color = get_aerial_perspective(coord, length(vP)); } diff --git a/Shaders/HDR/geometry-shadow.frag b/Shaders/HDR/model_shadow.frag similarity index 60% rename from Shaders/HDR/geometry-shadow.frag rename to Shaders/HDR/model_shadow.frag index 90a8ff2ef..07d32c060 100644 --- a/Shaders/HDR/geometry-shadow.frag +++ b/Shaders/HDR/model_shadow.frag @@ -1,6 +1,6 @@ #version 330 core -out vec4 fragColor; +layout(location = 0) out vec4 fragColor; void main() { diff --git a/Shaders/HDR/geometry-shadow.vert b/Shaders/HDR/model_shadow.vert similarity index 100% rename from Shaders/HDR/geometry-shadow.vert rename to Shaders/HDR/model_shadow.vert diff --git a/Shaders/HDR/model_transparent.frag b/Shaders/HDR/model_transparent.frag new file mode 100644 index 000000000..43713688a --- /dev/null +++ b/Shaders/HDR/model_transparent.frag @@ -0,0 +1,41 @@ +#version 330 core + +layout(location = 0) out vec4 fragColor; + +in vec3 vN; +in vec3 vP; +in vec2 texcoord; +in vec4 material_color; +in vec4 ap_color; + +uniform sampler2D color_tex; + +uniform mat4 osg_ViewMatrixInverse; +uniform vec4 fg_Viewport; + +const float TRANSPARENT_METALLIC = 0.0; +const float TRANSPARENT_ROUGHNESS = 0.1; + +// color.glsl +vec3 eotf_inverse_sRGB(vec3 srgb); +// shading_transparent.glsl +vec3 eval_lights_transparent( + vec3 base_color, float metallic, float roughness, float occlusion, + vec3 P, vec3 N, vec3 V, vec2 uv, vec4 ap, + mat4 view_matrix_inverse); + +void main() +{ + vec4 texel = texture(color_tex, texcoord); + vec3 base_color = eotf_inverse_sRGB(texel.rgb) * material_color.rgb; + float alpha = material_color.a * texel.a; + + vec3 V = normalize(-vP); + vec2 uv = (gl_FragCoord.xy - fg_Viewport.xy) / fg_Viewport.zw; + + vec3 color = eval_lights_transparent( + base_color, TRANSPARENT_METALLIC, TRANSPARENT_ROUGHNESS, 1.0, + vP, vN, V, uv, ap_color, osg_ViewMatrixInverse); + + fragColor = vec4(color, alpha); +} diff --git a/Shaders/HDR/model_transparent.vert b/Shaders/HDR/model_transparent.vert new file mode 100644 index 000000000..42d9e3604 --- /dev/null +++ b/Shaders/HDR/model_transparent.vert @@ -0,0 +1,51 @@ +#version 330 core + +#define MODE_OFF 0 +#define MODE_DIFFUSE 1 +#define MODE_AMBIENT_AND_DIFFUSE 2 + +layout(location = 0) in vec4 pos; +layout(location = 1) in vec3 normal; +layout(location = 2) in vec4 vertex_color; +layout(location = 3) in vec4 multitexcoord0; + +out vec3 vN; +out vec3 vP; +out vec2 texcoord; +out vec4 material_color; +out vec4 ap_color; + +uniform int color_mode; +uniform vec4 material_diffuse; + +uniform mat4 osg_ModelViewMatrix; +uniform mat4 osg_ModelViewProjectionMatrix; +uniform mat3 osg_NormalMatrix; + +// aerial_perspective.glsl +vec4 get_aerial_perspective(vec2 coord, float depth); + +void main() +{ + gl_Position = osg_ModelViewProjectionMatrix * pos; + vN = normalize(osg_NormalMatrix * normal); + vP = (osg_ModelViewMatrix * pos).xyz; + texcoord = multitexcoord0.st; + + // Legacy material handling + if (color_mode == MODE_DIFFUSE) + material_color = vertex_color; + else if (color_mode == MODE_AMBIENT_AND_DIFFUSE) + material_color = vertex_color; + else + material_color = material_diffuse; + // Super hack: if diffuse material alpha is less than 1, assume a + // transparency animation is at work + if (material_diffuse.a < 1.0) + material_color.a = material_diffuse.a; + else + material_color.a = vertex_color.a; + + vec2 coord = (gl_Position.xy / gl_Position.w) * 0.5 + 0.5; + ap_color = get_aerial_perspective(coord, length(vP)); +} diff --git a/Shaders/HDR/normal_encoding.glsl b/Shaders/HDR/normal_encoding.glsl new file mode 100644 index 000000000..510403828 --- /dev/null +++ b/Shaders/HDR/normal_encoding.glsl @@ -0,0 +1,30 @@ +/* + * Normal vector encoding and decoding using octahedron normal encoding. + * https://knarkowicz.wordpress.com/2014/04/16/octahedron-normal-vector-encoding/ + */ + +#version 330 core + +vec2 msign(vec2 v) +{ + return vec2((v.x >= 0.0) ? 1.0 : -1.0, + (v.y >= 0.0) ? 1.0 : -1.0); +} + +vec2 encode_normal(vec3 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 decode_normal(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); +} diff --git a/Shaders/HDR/pos_from_depth.glsl b/Shaders/HDR/pos_from_depth.glsl new file mode 100644 index 000000000..bfd209963 --- /dev/null +++ b/Shaders/HDR/pos_from_depth.glsl @@ -0,0 +1,56 @@ +#version 330 core + +uniform sampler2D depth_tex; + +uniform vec2 fg_NearFar; +uniform mat4 fg_ViewMatrixInverse; +uniform mat4 fg_ProjectionMatrixInverse; + +/* + * Reconstruct the view space position from the depth buffer. Mostly used by + * fullscreen post-processing shaders. + * + * Given a 2D screen UV in the range [0,1] and a depth value from the depth + * buffer, also in the [0,1] range, return the view space position. + */ +vec3 get_view_space_from_depth(vec2 uv, float depth, mat4 proj_matrix_inverse) +{ + /* + * We are using a reversed depth buffer. 1.0 corresponds to the near plane + * and 0.0 to the far plane. We convert this back to NDC space by doing + * 1.0 - depth to undo the depth reversal + * 2.0 * depth - 1.0 to transform it to NDC space [-1,1] + */ + vec4 ndc_p = vec4(uv * 2.0 - 1.0, 1.0 - depth * 2.0, 1.0); + vec4 vs_p = proj_matrix_inverse * ndc_p; + return vs_p.xyz / vs_p.w; +} + +vec3 get_view_space_from_depth(vec2 uv, float depth) +{ + return get_view_space_from_depth(uv, depth, fg_ProjectionMatrixInverse); +} + +vec3 get_view_space_from_depth(vec2 uv) +{ + return get_view_space_from_depth(uv, texture(depth_tex, uv).r); +} + +vec3 get_world_space_from_depth(vec2 uv, float depth) +{ + vec4 vs_p = vec4(get_view_space_from_depth(uv, depth), 1.0); + return (fg_ViewMatrixInverse * vs_p).xyz; +} + +vec3 get_world_space_from_depth(vec2 uv) +{ + return get_world_space_from_depth(uv, texture(depth_tex, uv).r); +} + +float linearize_depth(float depth) +{ + // Undo the depth reversal + float z = 1.0 - depth; + return 2.0 * fg_NearFar.x + / (fg_NearFar.y + fg_NearFar.x - z * (fg_NearFar.y - fg_NearFar.x)); +} diff --git a/Shaders/HDR/postprocess.frag b/Shaders/HDR/postprocess.frag index cd9076bec..f3853c029 100644 --- a/Shaders/HDR/postprocess.frag +++ b/Shaders/HDR/postprocess.frag @@ -1,8 +1,8 @@ #version 330 core -out vec4 fragColor; +layout(location = 0) out vec4 fragColor; -in vec2 texCoord; +in vec2 texcoord; uniform sampler2D hdr_tex; uniform sampler2D lum_tex; @@ -13,65 +13,36 @@ uniform vec2 fg_BufferSize; uniform float bloom_magnitude; uniform bool debug_ev100; -vec3 applyExposure(vec3 color, float avgLuminance, float threshold); +// exposure.glsl +vec3 apply_exposure(vec3 color, float avg_lum, float threshold); +// aces.glsl +vec3 aces_fitted(vec3 color); +// color.glsl +vec3 eotf_sRGB(vec3 linear_srgb); -/** - * ACES tone mapping - * From 'Baking Lab' by MJP and David Neubelt - * Original by Stephen Hill - * https://github.com/TheRealMJP/BakingLab/blob/master/BakingLab/ACES.hlsl - * Licensed under the MIT license - */ -// sRGB => XYZ => D65_2_D60 => AP1 => RRT_SAT -const mat3 ACESInputMat = mat3( - 0.59719, 0.07600, 0.02840, - 0.35458, 0.90834, 0.13383, - 0.04823, 0.01566, 0.83777); -// ODT_SAT => XYZ => D60_2_D65 => sRGB -const mat3 ACESOutputMat = mat3( - 1.60475, -0.10208, -0.00327, - -0.53108, 1.10813, -0.07276, - -0.07367, -0.00605, 1.07602); - -vec3 ACESFitted(vec3 color) +vec3 get_debug_color(float value) { - vec3 v = ACESInputMat * color; - vec3 a = v * (v + 0.0245786) - 0.000090537; - vec3 b = v * (0.983729 * v + 0.4329510) + 0.238081; - return clamp(ACESOutputMat * (a / b), 0.0, 1.0); -} - -vec3 getDebugColor(float value) -{ - float level = value*3.14159265/2.0; + float level = value * 3.14159265 * 0.5; vec3 col; col.r = sin(level); - col.g = sin(level*2.0); + col.g = sin(level * 2.0); col.b = cos(level); return col; } -vec3 debugEV100(vec3 hdr, float avgLuminance) +vec3 get_ev100_color(vec3 hdr) { float level; - if (texCoord.y < 0.05) { + if (texcoord.y < 0.05) { const float w = 0.001; - if (texCoord.x >= (0.5 - w) && texCoord.x <= (0.5 + w)) + if (texcoord.x >= (0.5 - w) && texcoord.x <= (0.5 + w)) return vec3(1.0); - return getDebugColor(texCoord.x); + return get_debug_color(texcoord.x); } - float luminance = max(dot(hdr, vec3(0.299, 0.587, 0.114)), 0.0001); - float ev100 = log2(luminance * 8.0); + float lum = max(dot(hdr, vec3(0.299, 0.587, 0.114)), 0.0001); + float ev100 = log2(lum * 8.0); float norm = ev100 / 12.0 + 0.5; - return getDebugColor(norm); -} - -vec3 encodeSRGB(vec3 linearRGB) -{ - vec3 a = 12.92 * linearRGB; - vec3 b = 1.055 * pow(linearRGB, vec3(1.0 / 2.4)) - 0.055; - vec3 c = step(vec3(0.0031308), linearRGB); - return mix(a, b, c); + return get_debug_color(norm); } float rand2D(vec2 co) @@ -81,27 +52,27 @@ float rand2D(vec2 co) void main() { - vec3 hdrColor = texture(hdr_tex, texCoord).rgb; - float avgLuminance = texelFetch(lum_tex, ivec2(0), 0).r; + vec3 hdr_color = texture(hdr_tex, texcoord).rgb; + float avg_lum = texelFetch(lum_tex, ivec2(0), 0).r; // Exposure - vec3 exposedHdrColor = applyExposure(hdrColor, avgLuminance, 0.0); + vec3 exposed_hdr_color = apply_exposure(hdr_color, avg_lum, 0.0); if (debug_ev100) { - fragColor = vec4(debugEV100(exposedHdrColor, avgLuminance), 1.0); + fragColor = vec4(get_ev100_color(exposed_hdr_color), 1.0); return; } // Tonemap - vec3 color = ACESFitted(exposedHdrColor); + vec3 color = aces_fitted(exposed_hdr_color); // Gamma correction - color = encodeSRGB(color); + color = eotf_sRGB(color); // Bloom - vec3 bloom = texture(bloom_tex, texCoord).rgb; + vec3 bloom = texture(bloom_tex, texcoord).rgb; color += bloom.rgb * bloom_magnitude; // Dithering - color += mix(-0.5/255.0, 0.5/255.0, rand2D(texCoord)); + color += mix(-0.5/255.0, 0.5/255.0, rand2D(texcoord)); fragColor = vec4(color, 1.0); } diff --git a/Shaders/HDR/quad.frag b/Shaders/HDR/quad.frag new file mode 100644 index 000000000..77e77fcd1 --- /dev/null +++ b/Shaders/HDR/quad.frag @@ -0,0 +1,12 @@ +#version 330 core + +layout(location = 0) out vec4 fragColor; + +in vec2 texcoord; + +uniform sampler2D tex; + +void main() +{ + fragColor = texture(tex, texcoord); +} diff --git a/Shaders/HDR/trivial.vert b/Shaders/HDR/quad.vert similarity index 73% rename from Shaders/HDR/trivial.vert rename to Shaders/HDR/quad.vert index 3c89260eb..2ce2eb2db 100644 --- a/Shaders/HDR/trivial.vert +++ b/Shaders/HDR/quad.vert @@ -1,10 +1,10 @@ #version 330 core -out vec2 texCoord; +out vec2 texcoord; void main() { vec2 pos = vec2(gl_VertexID % 2, gl_VertexID / 2) * 4.0 - 1.0; - texCoord = pos * 0.5 + 0.5; + texcoord = pos * 0.5 + 0.5; gl_Position = vec4(pos, 0.0, 1.0); } diff --git a/Shaders/HDR/trivial-cubemap.vert b/Shaders/HDR/quad_cubemap.vert similarity index 59% rename from Shaders/HDR/trivial-cubemap.vert rename to Shaders/HDR/quad_cubemap.vert index 7fd222adc..03fe0e5f3 100644 --- a/Shaders/HDR/trivial-cubemap.vert +++ b/Shaders/HDR/quad_cubemap.vert @@ -1,40 +1,40 @@ #version 330 core layout(location = 0) in vec4 pos; -layout(location = 3) in vec4 multiTexCoord0; +layout(location = 3) in vec4 multitexcoord0; -out vec3 cubemapCoord; +out vec3 cubemap_coord; uniform mat4 osg_ModelViewProjectionMatrix; - uniform int fg_CubemapFace; void main() { gl_Position = osg_ModelViewProjectionMatrix * pos; - vec2 texCoord = multiTexCoord0.xy * 2.0 - 1.0; + vec2 texcoord = multitexcoord0.xy * 2.0 - 1.0; + // Map the quad texture coordinates to a direction vector to sample // the cubemap. This assumes that we are using the weird left-handed // orientations given by the OpenGL spec. // See https://www.khronos.org/opengl/wiki/Cubemap_Texture#Upload_and_orientation switch(fg_CubemapFace) { case 0: // +X - cubemapCoord = vec3(1.0, -texCoord.y, -texCoord.x); + cubemap_coord = vec3(1.0, -texcoord.y, -texcoord.x); break; case 1: // -X - cubemapCoord = vec3(-1.0, -texCoord.y, texCoord.x); + cubemap_coord = vec3(-1.0, -texcoord.y, texcoord.x); break; case 2: // +Y - cubemapCoord = vec3(texCoord.x, 1.0, texCoord.y); + cubemap_coord = vec3(texcoord.x, 1.0, texcoord.y); break; case 3: // -Y - cubemapCoord = vec3(texCoord.x, -1.0, -texCoord.y); + cubemap_coord = vec3(texcoord.x, -1.0, -texcoord.y); break; case 4: // +Z - cubemapCoord = vec3(texCoord.x, -texCoord.y, 1.0); + cubemap_coord = vec3(texcoord.x, -texcoord.y, 1.0); break; case 5: // -Z - cubemapCoord = vec3(-texCoord.x, -texCoord.y, -1.0); + cubemap_coord = vec3(-texcoord.x, -texcoord.y, -1.0); break; } } diff --git a/Shaders/HDR/trivial-quad.vert b/Shaders/HDR/quad_matrix.vert similarity index 63% rename from Shaders/HDR/trivial-quad.vert rename to Shaders/HDR/quad_matrix.vert index 518a8d13f..37bc5bc28 100644 --- a/Shaders/HDR/trivial-quad.vert +++ b/Shaders/HDR/quad_matrix.vert @@ -1,14 +1,14 @@ #version 330 core layout(location = 0) in vec4 pos; -layout(location = 3) in vec4 multiTexCoord0; +layout(location = 3) in vec4 multitexcoord0; -out vec2 texCoord; +out vec2 texcoord; uniform mat4 osg_ModelViewProjectionMatrix; void main() { gl_Position = osg_ModelViewProjectionMatrix * pos; - texCoord = multiTexCoord0.st; + texcoord = multitexcoord0.st; } diff --git a/Shaders/HDR/trivial-notexcoord.vert b/Shaders/HDR/quad_notexcoord.vert similarity index 100% rename from Shaders/HDR/trivial-notexcoord.vert rename to Shaders/HDR/quad_notexcoord.vert diff --git a/Shaders/HDR/shading_opaque.frag b/Shaders/HDR/shading_opaque.frag new file mode 100644 index 000000000..3a02eea3e --- /dev/null +++ b/Shaders/HDR/shading_opaque.frag @@ -0,0 +1,41 @@ +#version 330 core + +layout(location = 0) out vec3 fragColor; + +in vec2 texcoord; + +uniform mat4 fg_ViewMatrixInverse; +uniform mat4 fg_ProjectionMatrix; + +vec3 decodeNormal(vec2 f); +vec3 positionFromDepth(vec2 pos, float depth); + +// gbuffer_unpack.glsl +void gbuffer_unpack(in vec2 texcoord, + out vec3 normal, out vec3 base_color, out float metallic, + out float roughness, out float occlusion, out vec3 emissive, + out uint mat_id); +// shading_opaque.glsl +vec3 eval_lights( + vec3 base_color, float metallic, float roughness, float occlusion, + vec3 P, vec3 N, vec3 V, vec2 uv, + mat4 view_matrix_inverse, mat4 projection_matrix); +// pos_from_depth.glsl +vec3 get_view_space_from_depth(vec2 uv); + +void main() +{ + vec3 N, base_color, emissive; + float metallic, roughness, occlusion; + uint mat_id; + gbuffer_unpack(texcoord, N, base_color, metallic, roughness, + occlusion, emissive, mat_id); + + vec3 P = get_view_space_from_depth(texcoord); + vec3 V = normalize(-P); + + fragColor = eval_lights( + base_color, metallic, roughness, occlusion, + P, N, V, texcoord, + fg_ViewMatrixInverse, fg_ProjectionMatrix); +} diff --git a/Shaders/HDR/shading_opaque.glsl b/Shaders/HDR/shading_opaque.glsl new file mode 100644 index 000000000..fdb8156af --- /dev/null +++ b/Shaders/HDR/shading_opaque.glsl @@ -0,0 +1,66 @@ +#version 330 core + +uniform vec3 fg_SunDirection; + +// gtao.glsl +float get_ambient_occlusion(vec2 uv, vec3 albedo); +// shadowing.glsl +float get_shadowing(vec3 P, vec3 N, vec3 L); +float get_contact_shadow(vec3 P, vec3 L, mat4 projection_matrix); +vec3 debug_shadow_color(vec3 color, vec3 P, vec3 N, vec3 L); +// surface.glsl +vec3 f0_from_pbr(vec3 base_color, float metallic); +vec3 surface_eval_analytical( + vec3 base_color, float metallic, float roughness, vec3 f0, + vec3 light_intensity, float occlusion, + vec3 N, vec3 L, vec3 V); +// ibl.glsl +vec3 get_reflected(vec3 N, vec3 V, mat4 view_matrix_inverse); +vec3 eval_ibl(vec3 base_color, float metallic, float roughness, vec3 f0, + float occlusion, vec3 ws_N, vec3 ws_refl, float NdotV); +// aerial_perspective.glsl +vec3 add_aerial_perspective(vec3 color, vec2 coord, float depth); +vec3 get_sun_radiance(vec3 p); +// clustered.glsl +vec3 eval_scene_lights(vec3 base_color, float metallic, float roughness, vec3 f0, + vec3 P, vec3 N, vec3 V); + +vec3 eval_lights( + vec3 base_color, float metallic, float roughness, float occlusion, + vec3 P, vec3 N, vec3 V, vec2 uv, + mat4 view_matrix_inverse, mat4 projection_matrix) +{ + vec3 f0 = f0_from_pbr(base_color, metallic); + vec3 ws_P = (view_matrix_inverse * vec4(P, 1.0)).xyz; + + // Evaluate sunlight + vec3 sun_radiance = get_sun_radiance(ws_P); + float shadow_factor = get_shadowing(P, N, fg_SunDirection); + if (shadow_factor > 0.0) + shadow_factor *= get_contact_shadow(P, fg_SunDirection, projection_matrix); + vec3 color = surface_eval_analytical( + base_color, metallic, roughness, f0, + sun_radiance, shadow_factor, + N, fg_SunDirection, V); + + // Evaluate all scene lights + color += eval_scene_lights( + base_color, metallic, roughness, f0, + P, N, V); + + // Evaluate image-based lights + float ao = occlusion * get_ambient_occlusion(uv, base_color); + vec3 ws_N = (view_matrix_inverse * vec4(N, 0.0)).xyz; + vec3 ws_refl = get_reflected(N, V, view_matrix_inverse); + float NdotV = max(dot(N, V), 1e-4); + color += eval_ibl( + base_color, metallic, roughness, f0, + ao, ws_N, ws_refl, NdotV); + + // Add aerial perspective + color = add_aerial_perspective(color, uv, length(P)); + + color = debug_shadow_color(color, P, N, fg_SunDirection); + + return color; +} diff --git a/Shaders/HDR/shading_transparent.glsl b/Shaders/HDR/shading_transparent.glsl new file mode 100644 index 000000000..9353f8ea0 --- /dev/null +++ b/Shaders/HDR/shading_transparent.glsl @@ -0,0 +1,60 @@ +#version 330 core + +uniform vec3 fg_SunDirection; + +// shadowing.glsl +float get_shadowing(vec3 P, vec3 N, vec3 L); +vec3 debug_shadow_color(vec3 color, vec3 P, vec3 N, vec3 L); +// surface.glsl +vec3 f0_from_pbr(vec3 base_color, float metallic); +vec3 surface_eval_analytical( + vec3 base_color, float metallic, float roughness, vec3 f0, + vec3 light_intensity, float occlusion, + vec3 N, vec3 L, vec3 V); +// ibl.glsl +vec3 get_reflected(vec3 N, vec3 V, mat4 view_matrix_inverse); +vec3 eval_ibl(vec3 base_color, float metallic, float roughness, vec3 f0, + float occlusion, vec3 ws_N, vec3 ws_refl, float NdotV); +// aerial_perspective.glsl +vec3 mix_aerial_perspective(vec3 color, vec4 ap); +vec3 get_sun_radiance(vec3 p); +// clustered.glsl +vec3 eval_scene_lights(vec3 base_color, float metallic, float roughness, vec3 f0, + vec3 P, vec3 N, vec3 V); + +vec3 eval_lights_transparent( + vec3 base_color, float metallic, float roughness, float occlusion, + vec3 P, vec3 N, vec3 V, vec2 uv, vec4 ap, + mat4 view_matrix_inverse) +{ + vec3 f0 = f0_from_pbr(base_color, metallic); + vec3 ws_P = (view_matrix_inverse * vec4(P, 1.0)).xyz; + + // Evaluate sunlight + vec3 sun_radiance = get_sun_radiance(ws_P); + float shadow_factor = get_shadowing(P, N, fg_SunDirection); + vec3 color = surface_eval_analytical( + base_color, metallic, roughness, f0, + sun_radiance, shadow_factor, + N, fg_SunDirection, V); + + // Evaluate all scene lights + color += eval_scene_lights( + base_color, metallic, roughness, f0, + P, N, V); + + // Evaluate image-based lights + vec3 ws_N = (view_matrix_inverse * vec4(N, 0.0)).xyz; + vec3 ws_refl = get_reflected(N, V, view_matrix_inverse); + float NdotV = max(dot(N, V), 1e-4); + color += eval_ibl( + base_color, metallic, roughness, f0, + occlusion, ws_N, ws_refl, NdotV); + + // Add aerial perspective + color = mix_aerial_perspective(color, ap); + + color = debug_shadow_color(color, P, N, fg_SunDirection); + + return color; +} diff --git a/Shaders/HDR/shadows-include.frag b/Shaders/HDR/shadows-include.frag deleted file mode 100644 index befe1c07d..000000000 --- a/Shaders/HDR/shadows-include.frag +++ /dev/null @@ -1,244 +0,0 @@ -#version 330 core - -uniform sampler2D depth_tex; // For Screen Space Shadows -uniform sampler2DShadow shadow_tex; - -uniform mat4 fg_LightMatrix_csm0; -uniform mat4 fg_LightMatrix_csm1; -uniform mat4 fg_LightMatrix_csm2; -uniform mat4 fg_LightMatrix_csm3; - -const float NORMAL_BIAS = 0.02; -const float BAND_SIZE = 0.1; -const vec2 BAND_BOTTOM_LEFT = vec2(BAND_SIZE); -const vec2 BAND_TOP_RIGHT = vec2(1.0 - BAND_SIZE); -// Ideally these should be passed as an uniform, but we don't support uniform -// arrays yet -const vec2 uv_shifts[4] = vec2[4]( - vec2(0.0, 0.0), vec2(0.5, 0.0), - vec2(0.0, 0.5), vec2(0.5, 0.5)); -const vec2 uv_factor = vec2(0.5, 0.5); - -const float SSS_THICKNESS = 0.1; -const uint SSS_NUM_STEPS = 16u; -const float SSS_MAX_DISTANCE = 0.05; -const vec3 DITHER_MAGIC = vec3(0.06711056, 0.00583715, 52.9829189); - -float sampleMap(vec2 coord, vec2 offset, float depth) -{ - return texture(shadow_tex, vec3(coord + offset, depth)); -} - -// OptimizedPCF from https://github.com/TheRealMJP/Shadows -// Original by Ignacio Castaño for The Witness -// Released under The MIT License -float sampleOptimizedPCF(vec4 pos, vec2 mapSize) -{ - vec2 texelSize = vec2(1.0) / mapSize; - - vec2 offset = vec2(0.5); - vec2 uv = (pos.xy * mapSize) + offset; - vec2 base = (floor(uv) - offset) * texelSize; - vec2 st = fract(uv); - - vec3 uw = vec3(4.0 - 3.0 * st.x, 7.0, 1.0 + 3.0 * st.x); - vec3 vw = vec3(4.0 - 3.0 * st.y, 7.0, 1.0 + 3.0 * st.y); - - vec3 u = vec3((3.0 - 2.0 * st.x) / uw.x - 2.0, (3.0 + st.x) / uw.y, st.x / uw.z + 2.0); - vec3 v = vec3((3.0 - 2.0 * st.y) / vw.x - 2.0, (3.0 + st.y) / vw.y, st.y / vw.z + 2.0); - - u *= texelSize.x; - v *= texelSize.y; - - float depth = pos.z; - float sum = 0.0; - - sum += uw.x * vw.x * sampleMap(base, vec2(u.x, v.x), depth); - sum += uw.y * vw.x * sampleMap(base, vec2(u.y, v.x), depth); - sum += uw.z * vw.x * sampleMap(base, vec2(u.z, v.x), depth); - - sum += uw.x * vw.y * sampleMap(base, vec2(u.x, v.y), depth); - sum += uw.y * vw.y * sampleMap(base, vec2(u.y, v.y), depth); - sum += uw.z * vw.y * sampleMap(base, vec2(u.z, v.y), depth); - - sum += uw.x * vw.z * sampleMap(base, vec2(u.x, v.z), depth); - sum += uw.y * vw.z * sampleMap(base, vec2(u.y, v.z), depth); - sum += uw.z * vw.z * sampleMap(base, vec2(u.z, v.z), depth); - - return sum / 144.0; -} - -float sampleCascade(vec4 p, vec2 shift, vec2 mapSize) -{ - vec4 pos = p; - pos.xy *= uv_factor; - pos.xy += shift; - return sampleOptimizedPCF(pos, mapSize); -} - -float getBlendFactor(vec2 uv, vec2 bottomLeft, vec2 topRight) -{ - 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) -{ - vec2 r = step(bottomLeft, coords) - step(topRight, coords); - return bool(r.x * r.y); -} - -bool isInsideCascade(vec4 p) -{ - return checkWithinBounds(p.xy, vec2(0.0), vec2(1.0)) && ((p.z / p.w) <= 1.0); -} - -bool isInsideBand(vec4 p) -{ - return !checkWithinBounds(p.xy, BAND_BOTTOM_LEFT, BAND_TOP_RIGHT); -} - -/** - * Get the light space position of point p. - * Both p and n must be in view space. The light matrix is also assumed to - * transform from view space to light space. - */ -vec4 getLightSpacePosition(vec3 p, vec3 n, float NdotL, mat4 lightMatrix) -{ - float sinTheta = sqrt(1.0 - NdotL * NdotL); - vec3 offsetPos = p + n * (sinTheta * NORMAL_BIAS); - return lightMatrix * vec4(offsetPos, 1.0); -} - -/** - * Screen Space Shadows - * Implementation mostly from: - * https://panoskarabelas.com/posts/screen_space_shadows/ - * Marching done in screen space instead of in view space. - */ -float getContactShadow(vec3 p, vec3 l, mat4 viewToClip) -{ - // Ray start and end points in view space - vec3 viewRayStart = p; - vec3 viewRayEnd = viewRayStart + l * SSS_MAX_DISTANCE; - // To clip space - vec4 clipRayStart = viewToClip * vec4(viewRayStart, 1.0); - vec4 clipRayEnd = viewToClip * vec4(viewRayEnd, 1.0); - // Perspective divide - vec3 rayStart = clipRayStart.xyz / clipRayStart.w; - vec3 rayEnd = clipRayEnd.xyz / clipRayEnd.w; - // From [-1,1] to [0,1] to sample directly from textures - rayStart = rayStart * 0.5 + 0.5; - rayEnd = rayEnd * 0.5 + 0.5; - - vec3 ray = rayEnd - rayStart; - - float dither = fract(DITHER_MAGIC.z * fract(dot(gl_FragCoord.xy, DITHER_MAGIC.xy))); - - float dt = 1.0 / float(SSS_NUM_STEPS); - float t = dt * dither + dt; - - float shadow = 0.0; - - for (uint i = 0u; i < SSS_NUM_STEPS; ++i) { - vec3 samplePos = rayStart + ray * t; - // Reversed depth buffer, invert it - float sampleDepth = 1.0 - texture(depth_tex, samplePos.xy).r; - float dz = samplePos.z - sampleDepth; - if (dz > 0.00001 && dz < SSS_THICKNESS) { - shadow = 1.0; - 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; - } - - return 1.0 - shadow; -} - -/** - * Get shadowing factor for a given position. 1.0 corresponds to a fragment - * being completely lit, and 0.0 to a fragment being completely in shadow. - * Both p and n must be in view space. - * viewToClip transforms a point from view space to clip space. Used for SSS. - */ -float getShadowing(vec3 p, vec3 n, vec3 l, mat4 viewToClip) -{ - 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); - - vec2 mapSize = vec2(textureSize(shadow_tex, 0)); - float visibility = 1.0; - - for (int i = 0; i < 4; ++i) { - // Map-based cascade selection - // 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])) { - // Blend between cascades if the fragment is near the - // next cascade to avoid abrupt transitions. - 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 = 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/shadows.glsl b/Shaders/HDR/shadows.glsl new file mode 100644 index 000000000..ca6d93df4 --- /dev/null +++ b/Shaders/HDR/shadows.glsl @@ -0,0 +1,252 @@ +#version 330 core + +uniform sampler2DShadow shadow_tex; +uniform sampler2D depth_tex; // For Screen Space Shadows + +uniform bool debug_shadow_cascades; + +uniform mat4 fg_LightMatrix_csm0; +uniform mat4 fg_LightMatrix_csm1; +uniform mat4 fg_LightMatrix_csm2; +uniform mat4 fg_LightMatrix_csm3; + +const float NORMAL_BIAS = 0.02; +const float BAND_SIZE = 0.1; +const vec2 BAND_BOTTOM_LEFT = vec2(BAND_SIZE); +const vec2 BAND_TOP_RIGHT = vec2(1.0 - BAND_SIZE); + +// Ideally these should be passed as an uniform, but we don't support uniform +// arrays yet +const vec2 uv_shifts[4] = vec2[4]( + vec2(0.0, 0.0), vec2(0.5, 0.0), + vec2(0.0, 0.5), vec2(0.5, 0.5)); +const vec2 uv_factor = vec2(0.5, 0.5); + +// Screen Space Shadows parameters +const float SSS_THICKNESS = 0.1; +const uint SSS_NUM_STEPS = 16u; +const float SSS_MAX_DISTANCE = 0.05; +const vec3 DITHER_MAGIC = vec3(0.06711056, 0.00583715, 52.9829189); + +float sample_shadow_map(vec2 coord, vec2 offset, float depth) +{ + return texture(shadow_tex, vec3(coord + offset, depth)); +} + +/* + * OptimizedPCF from https://github.com/TheRealMJP/Shadows + * Original by Ignacio Castaño for The Witness + * Released under The MIT License + */ +float sample_optimized_PCF(vec4 pos, vec2 map_size) +{ + vec2 texel_size = vec2(1.0) / map_size; + + vec2 offset = vec2(0.5); + vec2 uv = (pos.xy * map_size) + offset; + vec2 base = (floor(uv) - offset) * texel_size; + vec2 st = fract(uv); + + vec3 uw = vec3(4.0 - 3.0 * st.x, 7.0, 1.0 + 3.0 * st.x); + vec3 vw = vec3(4.0 - 3.0 * st.y, 7.0, 1.0 + 3.0 * st.y); + + vec3 u = vec3((3.0 - 2.0 * st.x) / uw.x - 2.0, (3.0 + st.x) / uw.y, st.x / uw.z + 2.0); + vec3 v = vec3((3.0 - 2.0 * st.y) / vw.x - 2.0, (3.0 + st.y) / vw.y, st.y / vw.z + 2.0); + + u *= texel_size.x; + v *= texel_size.y; + + float depth = pos.z; + float sum = 0.0; + + sum += uw.x * vw.x * sample_shadow_map(base, vec2(u.x, v.x), depth); + sum += uw.y * vw.x * sample_shadow_map(base, vec2(u.y, v.x), depth); + sum += uw.z * vw.x * sample_shadow_map(base, vec2(u.z, v.x), depth); + + sum += uw.x * vw.y * sample_shadow_map(base, vec2(u.x, v.y), depth); + sum += uw.y * vw.y * sample_shadow_map(base, vec2(u.y, v.y), depth); + sum += uw.z * vw.y * sample_shadow_map(base, vec2(u.z, v.y), depth); + + sum += uw.x * vw.z * sample_shadow_map(base, vec2(u.x, v.z), depth); + sum += uw.y * vw.z * sample_shadow_map(base, vec2(u.y, v.z), depth); + sum += uw.z * vw.z * sample_shadow_map(base, vec2(u.z, v.z), depth); + + return sum / 144.0; +} + +float sample_cascade(vec4 P, vec2 shift, vec2 map_size) +{ + vec4 pos = P; + pos.xy *= uv_factor; + pos.xy += shift; + return sample_optimized_PCF(pos, map_size); +} + +float get_blend_factor(vec2 uv, vec2 bottom_left, vec2 top_right) +{ + vec2 s = smoothstep(vec2(0.0), bottom_left, uv) + - smoothstep(top_right, vec2(1.0), uv); + return 1.0 - s.x * s.y; +} + +bool check_within_bounds(vec2 uv, vec2 bottom_left, vec2 top_right) +{ + vec2 r = step(bottom_left, uv) - step(top_right, uv); + return bool(r.x * r.y); +} + +bool is_inside_cascade(vec4 P) +{ + return check_within_bounds(P.xy, vec2(0.0), vec2(1.0)) && ((P.z / P.w) <= 1.0); +} + +bool is_inside_band(vec4 P) +{ + return !check_within_bounds(P.xy, BAND_BOTTOM_LEFT, BAND_TOP_RIGHT); +} + +/* + * Get the light space position of point P. + * Both P and N must be in view space. The light matrix is also assumed to + * transform from view space to light space. + */ +vec4 get_light_space_position(vec3 P, vec3 N, float NdotL, mat4 light_matrix) +{ + float sin_theta = sqrt(1.0 - NdotL * NdotL); + vec3 offset_pos = P + N * (sin_theta * NORMAL_BIAS); + return light_matrix * vec4(offset_pos, 1.0); +} + +/* + * Screen Space Shadows + * Implementation mostly based on: + * https://panoskarabelas.com/posts/screen_space_shadows/ + * Marching done in screen space instead of in view space. + */ +float get_contact_shadow(vec3 P, vec3 L, mat4 projection_matrix) +{ + // Ray start and end points in view space + vec3 vs_ray_start = P; + vec3 vs_ray_end = vs_ray_start + L * SSS_MAX_DISTANCE; + // To clip space + vec4 cs_ray_start = projection_matrix * vec4(vs_ray_start, 1.0); + vec4 cs_ray_end = projection_matrix * vec4(vs_ray_end, 1.0); + // Perspective divide + vec3 ray_start = cs_ray_start.xyz / cs_ray_start.w; + vec3 ray_end = cs_ray_end.xyz / cs_ray_end.w; + // From [-1,1] to [0,1] to sample directly from textures + ray_start = ray_start * 0.5 + 0.5; + ray_end = ray_end * 0.5 + 0.5; + + vec3 ray_dir = ray_end - ray_start; + + float dither = fract(DITHER_MAGIC.z * fract(dot(gl_FragCoord.xy, DITHER_MAGIC.xy))); + + float dt = 1.0 / float(SSS_NUM_STEPS); + float t = dt * dither + dt; + + float shadow = 0.0; + + for (uint i = 0u; i < SSS_NUM_STEPS; ++i) { + vec3 sample_pos = ray_start + ray_dir * t; + // Reversed depth buffer, invert it + float sample_depth = 1.0 - texture(depth_tex, sample_pos.xy).r; + float dz = sample_pos.z - sample_depth; + if (dz > 0.00001 && dz < SSS_THICKNESS) { + shadow = 1.0; + vec2 screen_fade = smoothstep(vec2(0.0), vec2(0.07), sample_pos.xy) + - smoothstep(vec2(0.93), vec2(1.0), sample_pos.xy); + shadow *= screen_fade.x * screen_fade.y; + break; + } + t += dt; + } + + return 1.0 - shadow; +} + +/* + * Get the shadowing factor for a given position. 1.0 corresponds to a fragment + * being completely lit, and 0.0 to a fragment being completely in shadow. + * Both P and N must be in view space. + */ +float get_shadowing(vec3 P, vec3 N, vec3 L) +{ + float NdotL = clamp(dot(N, L), 0.0, 1.0); + + vec4 ls_P[4]; + ls_P[0] = get_light_space_position(P, N, NdotL, fg_LightMatrix_csm0); + ls_P[1] = get_light_space_position(P, N, NdotL, fg_LightMatrix_csm1); + ls_P[2] = get_light_space_position(P, N, NdotL, fg_LightMatrix_csm2); + ls_P[3] = get_light_space_position(P, N, NdotL, fg_LightMatrix_csm3); + + vec2 map_size = vec2(textureSize(shadow_tex, 0)); + float visibility = 1.0; + + for (int i = 0; i < 4; ++i) { + // Map-based cascade selection + // We test if we are inside the cascade bounds to find the tightest + // map that contains the fragment. + if (is_inside_cascade(ls_P[i])) { + if (is_inside_band(ls_P[i])) { + // Blend between cascades if the fragment is near the + // next cascade to avoid abrupt transitions. + float blend = get_blend_factor(ls_P[i].xy, + BAND_BOTTOM_LEFT, + BAND_TOP_RIGHT); + float cascade0 = sample_cascade(ls_P[i], + uv_shifts[i], + map_size); + float cascade1; + if (i == 3) { + // Handle special case of the last cascade + cascade1 = 1.0; + } else { + cascade1 = sample_cascade(ls_P[i+1], + uv_shifts[i+1], + map_size); + } + 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 = sample_cascade(ls_P[i], + uv_shifts[i], + map_size); + } + break; + } + } + visibility = clamp(visibility, 0.0, 1.0); + + return visibility; +} + +vec3 debug_shadow_color(vec3 color, vec3 P, vec3 N, vec3 L) +{ + if (!debug_shadow_cascades) + return color; + + float NdotL = clamp(dot(N, L), 0.0, 1.0); + + vec4 ls_P[4]; + ls_P[0] = get_light_space_position(P, N, NdotL, fg_LightMatrix_csm0); + ls_P[1] = get_light_space_position(P, N, NdotL, fg_LightMatrix_csm1); + ls_P[2] = get_light_space_position(P, N, NdotL, fg_LightMatrix_csm2); + ls_P[3] = get_light_space_position(P, N, NdotL, fg_LightMatrix_csm3); + + vec3 debug_color; + if (is_inside_cascade(ls_P[0])) + debug_color = vec3(1.0, 0.0, 0.0); + else if (is_inside_cascade(ls_P[1])) + debug_color = vec3(0.0, 1.0, 0.0); + else if (is_inside_cascade(ls_P[2])) + debug_color = vec3(0.0, 0.0, 1.0); + else if (is_inside_cascade(ls_P[3])) + debug_color = vec3(1.0, 0.0, 1.0); + else + debug_color = vec3(0.0); + + return color * debug_color; +} diff --git a/Shaders/HDR/skydome.frag b/Shaders/HDR/skydome.frag index 4d298c945..3c7116e74 100644 --- a/Shaders/HDR/skydome.frag +++ b/Shaders/HDR/skydome.frag @@ -1,61 +1,50 @@ #version 330 core -out vec4 fragColor; +layout(location = 0) out vec4 fragColor; -in vec3 v_ray_dir; -in vec3 v_ray_dir_view; +in vec3 ray_dir; +in vec3 ray_dir_view; uniform bool sun_disk; -uniform sampler2D sky_view_lut; -uniform sampler2D transmittance_lut; +uniform sampler2D sky_view_tex; +uniform sampler2D transmittance_tex; uniform vec3 fg_SunDirection; uniform float fg_CameraDistanceToEarthCenter; uniform float fg_EarthRadius; uniform vec3 fg_CameraViewUp; -const float PI = 3.14159265358979323846; const float ATMOSPHERE_RADIUS = 6471e3; const float sun_solid_angle = radians(0.545); // ~half a degree const float sun_cos_solid_angle = cos(sun_solid_angle); + // Limb darkening constants, sampled for // 630, 560, 490, 430 nanometers const vec4 u = vec4(1.0); const vec4 alpha = vec4(0.429, 0.502, 0.575, 0.643); -//-- BEGIN spectral include -// Extraterrestial Solar Irradiance Spectra, units W * m^-2 * nm^-1 -// https://www.nrel.gov/grid/solar-resource/spectra.html -const vec4 sun_spectral_irradiance = vec4(1.679, 1.828, 1.986, 1.307); - -const mat4x3 M = mat4x3( - 137.672389239975, -8.632904716299537, -1.7181567391931372, - 32.549094028629234, 91.29801417199785, -12.005406444382531, - -38.91428392614275, 34.31665471469816, 29.89044807197628, - 8.572844237945445, -11.103384660054624, 117.47585277566478); - -vec3 linear_srgb_from_spectral_samples(vec4 L) -{ - return M * L; -} -//-- END spectral include +// math.glsl +float M_PI(); +// atmos_spectral.glsl +vec4 get_sun_spectral_irradiance(); +vec3 linear_srgb_from_spectral_samples(vec4 L); void main() { - vec3 ray_dir = normalize(v_ray_dir); - float azimuth = atan(ray_dir.y, ray_dir.x) / PI * 0.5 + 0.5; + vec3 ray_dir = normalize(ray_dir); + float azimuth = atan(ray_dir.y, ray_dir.x) / M_PI() * 0.5 + 0.5; // Undo the non-linear transformation from the sky-view LUT float l = asin(ray_dir.z); - float elev = sqrt(abs(l) / (PI * 0.5)) * sign(l) * 0.5 + 0.5; + float elev = sqrt(abs(l) / (M_PI() * 0.5)) * sign(l) * 0.5 + 0.5; - vec4 sky_radiance = texture(sky_view_lut, vec2(azimuth, elev)); + vec4 sky_radiance = texture(sky_view_tex, vec2(azimuth, elev)); // When computing the sky texture we assumed an unitary light source. // Now multiply by the sun irradiance. - sky_radiance *= sun_spectral_irradiance; + sky_radiance *= get_sun_spectral_irradiance(); if (sun_disk) { // Render the Sun disk - vec3 ray_dir_view = normalize(v_ray_dir_view); + vec3 ray_dir_view = normalize(ray_dir_view); float cos_theta = dot(ray_dir_view, fg_SunDirection); if (cos_theta >= sun_cos_solid_angle) { @@ -67,7 +56,7 @@ void main() vec2 uv = vec2(sun_zenith_cos_theta * 0.5 + 0.5, clamp(normalized_altitude, 0.0, 1.0)); - vec4 transmittance = texture(transmittance_lut, uv); + vec4 transmittance = texture(transmittance_tex, uv); // Limb darkening // http://www.physics.hmc.edu/faculty/esin/a101/limbdarkening.pdf @@ -76,7 +65,7 @@ void main() float mu = sqrt(max(1.0 - center_to_edge*center_to_edge, 0.0)); vec4 factor = vec4(1.0) - u * (vec4(1.0) - pow(vec4(mu), alpha)); - vec4 sun_radiance = sun_spectral_irradiance * transmittance * factor; + vec4 sun_radiance = get_sun_spectral_irradiance() * transmittance * factor; sky_radiance += sun_radiance; } } diff --git a/Shaders/HDR/skydome.vert b/Shaders/HDR/skydome.vert index 6a00f9190..c2763cd5f 100644 --- a/Shaders/HDR/skydome.vert +++ b/Shaders/HDR/skydome.vert @@ -2,8 +2,8 @@ layout(location = 0) in vec4 pos; -out vec3 v_ray_dir; -out vec3 v_ray_dir_view; +out vec3 ray_dir; +out vec3 ray_dir_view; uniform mat4 osg_ModelViewMatrix; uniform mat4 osg_ModelViewProjectionMatrix; @@ -12,9 +12,9 @@ void main() { gl_Position = osg_ModelViewProjectionMatrix * pos; // Get the camera height (0 being the ground) - vec4 groundPoint = osg_ModelViewMatrix * vec4(0.0, 0.0, 0.0, 1.0); - float altitude = length(groundPoint); + vec4 ground_point = osg_ModelViewMatrix * vec4(0.0, 0.0, 0.0, 1.0); + float altitude = length(ground_point); // Compensate for the skydome being fixed on the ground - v_ray_dir = normalize(pos.xyz - vec3(0.0, 0.0, altitude)); - v_ray_dir_view = (osg_ModelViewMatrix * vec4(v_ray_dir, 0.0)).xyz; + ray_dir = normalize(pos.xyz - vec3(0.0, 0.0, altitude)); + ray_dir_view = (osg_ModelViewMatrix * vec4(ray_dir, 0.0)).xyz; } diff --git a/Shaders/HDR/smaa-blending-weight-calculation.frag b/Shaders/HDR/smaa_blending_weight_calculation.frag similarity index 94% rename from Shaders/HDR/smaa-blending-weight-calculation.frag rename to Shaders/HDR/smaa_blending_weight_calculation.frag index 4a9ab020d..452e58ca3 100644 --- a/Shaders/HDR/smaa-blending-weight-calculation.frag +++ b/Shaders/HDR/smaa_blending_weight_calculation.frag @@ -35,6 +35,20 @@ #version 330 core +layout(location = 0) out vec4 fragColor; + +in vec2 texcoord; +in vec2 pixcoord; +in vec4 v_offset[3]; + +uniform sampler2D edges_tex; +uniform sampler2D area_tex; +uniform sampler2D search_tex; + +uniform vec4 fg_Viewport; + +//------------------------------------------------------------------------------ + #define SMAA_THRESHOLD 0.1 #define SMAA_MAX_SEARCH_STEPS_DIAG 8 #define SMAA_CORNER_ROUNDING 25 @@ -50,20 +64,10 @@ #define SMAA_AREATEX_SELECT(sample) sample.rg #define SMAA_SEARCHTEX_SELECT(sample) sample.r -out vec4 fragColor; +//------------------------------------------------------------------------------ -in vec2 texCoord; -in vec2 pixCoord; -in vec4 vOffset[3]; - -uniform sampler2D edges_tex; -uniform sampler2D area_tex; -uniform sampler2D search_tex; - -uniform vec4 fg_Viewport; - -#define SMAA_RT_METRICS vec4(1.0 / fg_Viewport.z, 1.0 / fg_Viewport.w, fg_Viewport.z, fg_Viewport.w) #define mad(a, b, c) (a * b + c) +#define SMAA_RT_METRICS vec4(1.0 / fg_Viewport.z, 1.0 / fg_Viewport.w, fg_Viewport.z, fg_Viewport.w) #define saturate(a) clamp(a, 0.0, 1.0) #define round(v) floor(v + 0.5) #define SMAASampleLevelZeroOffset(tex, coord, offset) textureLodOffset(tex, coord, 0.0, offset) @@ -399,13 +403,13 @@ void main() vec4 weights = vec4(0.0, 0.0, 0.0, 0.0); - vec2 e = texture(edges_tex, texCoord).rg; + vec2 e = texture(edges_tex, texcoord).rg; if (e.g > 0.0) { // Edge at north #if !defined(SMAA_DISABLE_DIAG_DETECTION) // Diagonals have both north and west edges, so searching for them in // one of the boundaries is enough. - weights.rg = SMAACalculateDiagWeights(edges_tex, area_tex, texCoord, e, subsampleIndices); + weights.rg = SMAACalculateDiagWeights(edges_tex, area_tex, texcoord, e, subsampleIndices); // We give priority to diagonals, so if we find a diagonal we skip // horizontal/vertical processing. @@ -415,8 +419,8 @@ void main() // Find the distance to the left: vec3 coords; - coords.x = SMAASearchXLeft(edges_tex, search_tex, vOffset[0].xy, vOffset[2].x); - coords.y = vOffset[1].y; // vOffset[1].y = texCoord.y - 0.25 * SMAA_RT_METRICS.y (@CROSSING_OFFSET) + coords.x = SMAASearchXLeft(edges_tex, search_tex, v_offset[0].xy, v_offset[2].x); + coords.y = v_offset[1].y; // v_offset[1].y = texcoord.y - 0.25 * SMAA_RT_METRICS.y (@CROSSING_OFFSET) d.x = coords.x; // Now fetch the left crossing edges, two at a time using bilinear @@ -425,12 +429,12 @@ void main() float e1 = textureLod(edges_tex, coords.xy, 0.0).r; // Find the distance to the right: - coords.z = SMAASearchXRight(edges_tex, search_tex, vOffset[0].zw, vOffset[2].y); + coords.z = SMAASearchXRight(edges_tex, search_tex, v_offset[0].zw, v_offset[2].y); d.y = coords.z; // We want the distances to be in pixel units (doing this here allow to // better interleave arithmetic and memory accesses): - d = abs(round(mad(SMAA_RT_METRICS.zz, d, -pixCoord.xx))); + d = abs(round(mad(SMAA_RT_METRICS.zz, d, -pixcoord.xx))); // SMAAArea below needs a sqrt, as the areas texture is compressed // quadratically: @@ -444,7 +448,7 @@ void main() weights.rg = SMAAArea(area_tex, sqrt_d, e1, e2, subsampleIndices.y); // Fix corners: - coords.y = texCoord.y; + coords.y = texcoord.y; SMAADetectHorizontalCornerPattern(edges_tex, weights.rg, coords.xyzy, d); #if !defined(SMAA_DISABLE_DIAG_DETECTION) @@ -458,19 +462,19 @@ void main() // Find the distance to the top: vec3 coords; - coords.y = SMAASearchYUp(edges_tex, search_tex, vOffset[1].xy, vOffset[2].z); - coords.x = vOffset[0].x; // vOffset[1].x = texCoord.x - 0.25 * SMAA_RT_METRICS.x; + coords.y = SMAASearchYUp(edges_tex, search_tex, v_offset[1].xy, v_offset[2].z); + coords.x = v_offset[0].x; // v_offset[1].x = texcoord.x - 0.25 * SMAA_RT_METRICS.x; d.x = coords.y; // Fetch the top crossing edges: float e1 = textureLod(edges_tex, coords.xy, 0.0).g; // Find the distance to the bottom: - coords.z = SMAASearchYDown(edges_tex, search_tex, vOffset[1].zw, vOffset[2].w); + coords.z = SMAASearchYDown(edges_tex, search_tex, v_offset[1].zw, v_offset[2].w); d.y = coords.z; // We want the distances to be in pixel units: - d = abs(round(mad(SMAA_RT_METRICS.ww, d, -pixCoord.yy))); + d = abs(round(mad(SMAA_RT_METRICS.ww, d, -pixcoord.yy))); // SMAAArea below needs a sqrt, as the areas texture is compressed // quadratically: @@ -483,7 +487,7 @@ void main() weights.ba = SMAAArea(area_tex, sqrt_d, e1, e2, subsampleIndices.x); // Fix corners: - coords.x = texCoord.x; + coords.x = texcoord.x; SMAADetectVerticalCornerPattern(edges_tex, weights.ba, coords.xyxz, d); } diff --git a/Shaders/HDR/smaa-blending-weight-calculation.vert b/Shaders/HDR/smaa_blending_weight_calculation.vert similarity index 84% rename from Shaders/HDR/smaa-blending-weight-calculation.vert rename to Shaders/HDR/smaa_blending_weight_calculation.vert index 22493925c..ac0d78e03 100644 --- a/Shaders/HDR/smaa-blending-weight-calculation.vert +++ b/Shaders/HDR/smaa_blending_weight_calculation.vert @@ -35,32 +35,30 @@ #version 330 core -#define SMAA_MAX_SEARCH_STEPS 16 - -#define mad(a, b, c) (a * b + c) - -out vec2 texCoord; -out vec2 pixCoord; -out vec4 vOffset[3]; +out vec2 texcoord; +out vec2 pixcoord; +out vec4 v_offset[3]; uniform vec4 fg_Viewport; +#define mad(a, b, c) (a * b + c) #define SMAA_RT_METRICS vec4(1.0 / fg_Viewport.z, 1.0 / fg_Viewport.w, fg_Viewport.z, fg_Viewport.w) +#define SMAA_MAX_SEARCH_STEPS 16 void main() { vec2 pos = vec2(gl_VertexID % 2, gl_VertexID / 2) * 4.0 - 1.0; - texCoord = pos * 0.5 + 0.5; + texcoord = pos * 0.5 + 0.5; gl_Position = vec4(pos, 0.0, 1.0); - pixCoord = texCoord * SMAA_RT_METRICS.zw; + pixcoord = texcoord * SMAA_RT_METRICS.zw; // We will use these offsets for the searches later on (see @PSEUDO_GATHER4): - vOffset[0] = mad(SMAA_RT_METRICS.xyxy, vec4(-0.25, -0.125, 1.25, -0.125), texCoord.xyxy); - vOffset[1] = mad(SMAA_RT_METRICS.xyxy, vec4(-0.125,-0.25, -0.125, 1.25 ), texCoord.xyxy); + v_offset[0] = mad(SMAA_RT_METRICS.xyxy, vec4(-0.25, -0.125, 1.25, -0.125), texcoord.xyxy); + v_offset[1] = mad(SMAA_RT_METRICS.xyxy, vec4(-0.125,-0.25, -0.125, 1.25 ), texcoord.xyxy); // And these for the searches, they indicate the ends of the loops: - vOffset[2] = mad(SMAA_RT_METRICS.xxyy, + v_offset[2] = mad(SMAA_RT_METRICS.xxyy, vec4(-2.0, 2.0, -2.0, 2.0) * float(SMAA_MAX_SEARCH_STEPS), - vec4(vOffset[0].xz, vOffset[1].yw)); + vec4(v_offset[0].xz, v_offset[1].yw)); } diff --git a/Shaders/HDR/smaa-edge-detection.frag b/Shaders/HDR/smaa_edge_detection.frag similarity index 83% rename from Shaders/HDR/smaa-edge-detection.frag rename to Shaders/HDR/smaa_edge_detection.frag index ddbfa2465..8957e6a9d 100644 --- a/Shaders/HDR/smaa-edge-detection.frag +++ b/Shaders/HDR/smaa_edge_detection.frag @@ -35,16 +35,18 @@ #version 330 core -#define SMAA_THRESHOLD 0.1 -#define SMAA_LOCAL_CONTRAST_ADAPTATION_FACTOR 2.0 +layout(location = 0) out vec4 fragColor; -out vec4 fragColor; - -in vec2 texCoord; -in vec4 vOffset[3]; +in vec2 texcoord; +in vec4 v_offset[3]; uniform sampler2D color_tex; +//----------------------------------------------------------------------------- + +#define SMAA_THRESHOLD 0.1 +#define SMAA_LOCAL_CONTRAST_ADAPTATION_FACTOR 2.0 + //----------------------------------------------------------------------------- // Edge Detection Pixel Shaders (First Pass) @@ -60,10 +62,10 @@ void main() // Calculate lumas: vec3 weights = vec3(0.2126, 0.7152, 0.0722); - float L = dot(texture(color_tex, texCoord).rgb, weights); + float L = dot(texture(color_tex, texcoord).rgb, weights); - float Lleft = dot(texture(color_tex, vOffset[0].xy).rgb, weights); - float Ltop = dot(texture(color_tex, vOffset[0].zw).rgb, weights); + float Lleft = dot(texture(color_tex, v_offset[0].xy).rgb, weights); + float Ltop = dot(texture(color_tex, v_offset[0].zw).rgb, weights); // We do the usual threshold: vec4 delta; @@ -75,16 +77,16 @@ void main() discard; // Calculate right and bottom deltas: - float Lright = dot(texture(color_tex, vOffset[1].xy).rgb, weights); - float Lbottom = dot(texture(color_tex, vOffset[1].zw).rgb, weights); + float Lright = dot(texture(color_tex, v_offset[1].xy).rgb, weights); + float Lbottom = dot(texture(color_tex, v_offset[1].zw).rgb, weights); delta.zw = abs(L - vec2(Lright, Lbottom)); // Calculate the maximum delta in the direct neighborhood: vec2 maxDelta = max(delta.xy, delta.zw); // Calculate left-left and top-top deltas: - float Lleftleft = dot(texture(color_tex, vOffset[2].xy).rgb, weights); - float Ltoptop = dot(texture(color_tex, vOffset[2].zw).rgb, weights); + float Lleftleft = dot(texture(color_tex, v_offset[2].xy).rgb, weights); + float Ltoptop = dot(texture(color_tex, v_offset[2].zw).rgb, weights); delta.zw = abs(vec2(Lleft, Ltop) - vec2(Lleftleft, Ltoptop)); // Calculate the final maximum delta: diff --git a/Shaders/HDR/smaa-edge-detection.vert b/Shaders/HDR/smaa_edge_detection.vert similarity index 85% rename from Shaders/HDR/smaa-edge-detection.vert rename to Shaders/HDR/smaa_edge_detection.vert index bc5c5d3a2..15be06fbc 100644 --- a/Shaders/HDR/smaa-edge-detection.vert +++ b/Shaders/HDR/smaa_edge_detection.vert @@ -1,11 +1,11 @@ -/** +/* * Adaptation of SMAA (Enhanced Subpixel Morphological Antialiasing) * for FlightGear. * See http://www.iryoku.com/smaa/ for details. * Licensed under the MIT license, see below. */ -/** +/* * Copyright (C) 2013 Jorge Jimenez (jorge@iryoku.com) * Copyright (C) 2013 Jose I. Echevarria (joseignacioechevarria@gmail.com) * Copyright (C) 2013 Belen Masia (bmasia@unizar.es) @@ -35,22 +35,21 @@ #version 330 core -#define mad(a, b, c) (a * b + c) - -out vec2 texCoord; -out vec4 vOffset[3]; +out vec2 texcoord; +out vec4 v_offset[3]; uniform vec4 fg_Viewport; +#define mad(a, b, c) (a * b + c) #define SMAA_RT_METRICS vec4(1.0 / fg_Viewport.z, 1.0 / fg_Viewport.w, fg_Viewport.z, fg_Viewport.w) void main() { vec2 pos = vec2(gl_VertexID % 2, gl_VertexID / 2) * 4.0 - 1.0; - texCoord = pos * 0.5 + 0.5; + texcoord = pos * 0.5 + 0.5; gl_Position = vec4(pos, 0.0, 1.0); - vOffset[0] = mad(SMAA_RT_METRICS.xyxy, vec4(-1.0, 0.0, 0.0, -1.0), texCoord.xyxy); - vOffset[1] = mad(SMAA_RT_METRICS.xyxy, vec4( 1.0, 0.0, 0.0, 1.0), texCoord.xyxy); - vOffset[2] = mad(SMAA_RT_METRICS.xyxy, vec4(-2.0, 0.0, 0.0, -2.0), texCoord.xyxy); + v_offset[0] = mad(SMAA_RT_METRICS.xyxy, vec4(-1.0, 0.0, 0.0, -1.0), texcoord.xyxy); + v_offset[1] = mad(SMAA_RT_METRICS.xyxy, vec4( 1.0, 0.0, 0.0, 1.0), texcoord.xyxy); + v_offset[2] = mad(SMAA_RT_METRICS.xyxy, vec4(-2.0, 0.0, 0.0, -2.0), texcoord.xyxy); } diff --git a/Shaders/HDR/smaa-neighborhood-blending.frag b/Shaders/HDR/smaa_neighborhood_blending.frag similarity index 89% rename from Shaders/HDR/smaa-neighborhood-blending.frag rename to Shaders/HDR/smaa_neighborhood_blending.frag index 2ffc0eccc..3af71b276 100644 --- a/Shaders/HDR/smaa-neighborhood-blending.frag +++ b/Shaders/HDR/smaa_neighborhood_blending.frag @@ -35,18 +35,19 @@ #version 330 core -#define mad(a, b, c) (a * b + c) +layout(location = 0) out vec4 fragColor; -out vec4 fragColor; - -in vec2 texCoord; -in vec4 vOffset; +in vec2 texcoord; +in vec4 v_offset; uniform sampler2D color_tex; uniform sampler2D blend_tex; uniform vec4 fg_Viewport; +//------------------------------------------------------------------------------ + +#define mad(a, b, c) (a * b + c) #define SMAA_RT_METRICS vec4(1.0 / fg_Viewport.z, 1.0 / fg_Viewport.w, fg_Viewport.z, fg_Viewport.w) /** @@ -71,13 +72,13 @@ void main() // Fetch the blending weights for current pixel: vec4 a; - a.x = texture(blend_tex, vOffset.xy).a; // Right - a.y = texture(blend_tex, vOffset.zw).g; // Top - a.wz = texture(blend_tex, texCoord).xz; // Bottom / Left + a.x = texture(blend_tex, v_offset.xy).a; // Right + a.y = texture(blend_tex, v_offset.zw).g; // Top + a.wz = texture(blend_tex, texcoord).xz; // Bottom / Left // Is there any blending weight with a value greater than 0.0? if (dot(a, vec4(1.0, 1.0, 1.0, 1.0)) < 1e-5) { - color = textureLod(color_tex, texCoord, 0.0); + color = textureLod(color_tex, texcoord, 0.0); } else { bool h = max(a.x, a.z) > max(a.y, a.w); // max(horizontal) > max(vertical) @@ -89,7 +90,7 @@ void main() blendingWeight /= dot(blendingWeight, vec2(1.0, 1.0)); // Calculate the texture coordinates: - vec4 blendingCoord = mad(blendingOffset, vec4(SMAA_RT_METRICS.xy, -SMAA_RT_METRICS.xy), texCoord.xyxy); + vec4 blendingCoord = mad(blendingOffset, vec4(SMAA_RT_METRICS.xy, -SMAA_RT_METRICS.xy), texcoord.xyxy); // We exploit bilinear filtering to mix current pixel with the chosen // neighbor: diff --git a/Shaders/HDR/smaa-neighborhood-blending.vert b/Shaders/HDR/smaa_neighborhood_blending.vert similarity index 92% rename from Shaders/HDR/smaa-neighborhood-blending.vert rename to Shaders/HDR/smaa_neighborhood_blending.vert index 0ce4ee56b..49425356f 100644 --- a/Shaders/HDR/smaa-neighborhood-blending.vert +++ b/Shaders/HDR/smaa_neighborhood_blending.vert @@ -35,20 +35,19 @@ #version 330 core -#define mad(a, b, c) (a * b + c) - -out vec2 texCoord; -out vec4 vOffset; +out vec2 texcoord; +out vec4 v_offset; uniform vec4 fg_Viewport; +#define mad(a, b, c) (a * b + c) #define SMAA_RT_METRICS vec4(1.0 / fg_Viewport.z, 1.0 / fg_Viewport.w, fg_Viewport.z, fg_Viewport.w) void main() { vec2 pos = vec2(gl_VertexID % 2, gl_VertexID / 2) * 4.0 - 1.0; - texCoord = pos * 0.5 + 0.5; + texcoord = pos * 0.5 + 0.5; gl_Position = vec4(pos, 0.0, 1.0); - vOffset = mad(SMAA_RT_METRICS.xyxy, vec4(1.0, 0.0, 0.0, 1.0), texCoord.xyxy); + v_offset = mad(SMAA_RT_METRICS.xyxy, vec4(1.0, 0.0, 0.0, 1.0), texcoord.xyxy); } diff --git a/Shaders/HDR/surface.glsl b/Shaders/HDR/surface.glsl new file mode 100644 index 000000000..f4a8629f6 --- /dev/null +++ b/Shaders/HDR/surface.glsl @@ -0,0 +1,95 @@ +#version 330 core + +const float DIELECTRIC_SPECULAR = 0.04; + +// math.glsl +float M_PI(); +float M_1_PI(); +float sqr(float x); +float pow5(float x); + +/* + * Fresnel, Schlick's approximation. + */ +vec3 F_Schlick(float VdotH, vec3 f0) +{ + return f0 + (vec3(1.0) - f0) * pow5(clamp(1.0 - VdotH, 0.0, 1.0)); +} + +/* + * Fresnel, Schlick's approximation, monochromatic. + */ +float F_Schlick(float VdotH, float f0) +{ + return f0 + (1.0 - f0) * pow5(clamp(1.0 - VdotH, 0.0, 1.0)); +} + +/* + * Normal distribution function, Trowbridge-Reitz/GGX microfacet distribution. + */ +float D_GGX(float NdotH, float a2) +{ + float f = (NdotH * a2 - NdotH) * NdotH + 1.0; + return M_PI() * f * f; +} + +/* + * Geometric attenuation, Smith-GGX formulation. + */ +float G1_Smith_GGX(float NdotX, float a2) +{ + return NdotX + sqrt(NdotX * (NdotX - NdotX * a2) + a2); +} + +/* + * Get the Fresnel reflectance at 0 degrees (light hitting the surface + * perpendicularly) from PBR parameters. + */ +vec3 f0_from_pbr(vec3 base_color, float metallic) +{ + return mix(vec3(DIELECTRIC_SPECULAR), base_color, metallic); +} + +/* + * Evaluate the color of a standard PBR surface illuminated by an analytical + * light source. The evaluated BSDF consists of a specular lobe and a diffuse + * lobe. The specular lobe is the Cook-Torrance microfacet model, and the + * diffuse lobe is a simple Lambertian. + * + * Note that the calculations here do not match the literature. Brian Karis + * approach of refactoring by NdotX/NdotX has been used to optimize the code. + */ +vec3 surface_eval_analytical( + // Material + vec3 base_color, float metallic, float roughness, vec3 f0, + // Light + vec3 light_intensity, float occlusion, + // Vectors + vec3 N, vec3 L, vec3 V) +{ + float NdotL = dot(N, L); + // Skip fragments that are completely occluded or that are not facing the light + if (occlusion <= 0.0 || NdotL <= 0.0) + return vec3(0.0); + NdotL = max(NdotL, 1e-4); + + float a = max(sqr(roughness), 0.045); + float a2 = sqr(a); + + vec3 H = normalize(L + V); + float NdotV = max(dot(N, V), 1e-4); + float NdotH = max(dot(N, H), 1e-4); + float VdotH = max(dot(V, H), 1e-4); + + vec3 c_diff = mix(base_color * (1.0 - DIELECTRIC_SPECULAR), vec3(0.0), metallic); + + vec3 F = F_Schlick(VdotH, f0); + float G = G1_Smith_GGX(NdotV, a2) * G1_Smith_GGX(NdotL, a2); + float D = D_GGX(NdotH, a2); + + vec3 f_specular = (F * a2) / (D * G); + vec3 f_diffuse = (vec3(1.0) - F) * c_diff * M_1_PI(); + vec3 bsdf = f_diffuse + f_specular; + + return bsdf * light_intensity * occlusion * NdotL; +} diff --git a/Shaders/HDR/terrain_default.frag b/Shaders/HDR/terrain_default.frag new file mode 100644 index 000000000..8d44f4b1c --- /dev/null +++ b/Shaders/HDR/terrain_default.frag @@ -0,0 +1,34 @@ +#version 330 core + +in vec3 vN; +in vec2 texcoord; +in vec2 orthophoto_texcoord; + +uniform sampler2D color_tex; +uniform sampler2D orthophoto_tex; + +uniform bool orthophotoAvailable; + +const float TERRAIN_METALLIC = 0.0; +const float TERRAIN_ROUGHNESS = 0.95; + +// gbuffer_pack.glsl +void gbuffer_pack(vec3 normal, vec3 base_color, float metallic, float roughness, + float occlusion, vec3 emissive, uint mat_id); +// color.glsl +vec3 eotf_inverse_sRGB(vec3 srgb); + +void main() +{ + vec3 texel = texture(color_tex, texcoord).rgb; + if (orthophotoAvailable) { + vec4 sat_texel = texture(orthophoto_tex, orthophoto_texcoord); + if (sat_texel.a > 0.0) { + texel.rgb = sat_texel.rgb; + } + } + + vec3 color = eotf_inverse_sRGB(texel); + + gbuffer_pack(vN, color, TERRAIN_METALLIC, TERRAIN_ROUGHNESS, 1.0, vec3(0.0), 3u); +} diff --git a/Shaders/HDR/terrain_default.vert b/Shaders/HDR/terrain_default.vert new file mode 100644 index 000000000..fa7f66c27 --- /dev/null +++ b/Shaders/HDR/terrain_default.vert @@ -0,0 +1,21 @@ +#version 330 core + +layout(location = 0) in vec4 pos; +layout(location = 1) in vec3 normal; +layout(location = 3) in vec4 multitexcoord0; +layout(location = 5) in vec4 multitexcoord2; + +out vec3 vN; +out vec2 texcoord; +out vec2 orthophoto_texcoord; + +uniform mat4 osg_ModelViewProjectionMatrix; +uniform mat3 osg_NormalMatrix; + +void main() +{ + gl_Position = osg_ModelViewProjectionMatrix * pos; + vN = normalize(osg_NormalMatrix * normal); + texcoord = multitexcoord0.st; + orthophoto_texcoord = multitexcoord2.st; +} diff --git a/Shaders/HDR/terrain_lfeat.frag b/Shaders/HDR/terrain_lfeat.frag new file mode 100644 index 000000000..9f3c0b9b5 --- /dev/null +++ b/Shaders/HDR/terrain_lfeat.frag @@ -0,0 +1,23 @@ +#version 330 core + +in vec3 vN; +in vec2 texcoord; + +uniform sampler2D color_tex; + +// gbuffer_pack.glsl +void gbuffer_pack(vec3 normal, vec3 base_color, float metallic, float roughness, + float occlusion, vec3 emissive, uint mat_id); +// color.glsl +vec3 eotf_inverse_sRGB(vec3 srgb); + +void main() +{ + vec4 texel = texture(color_tex, texcoord); + if (texel.a < 0.5) + discard; + + vec3 color = eotf_inverse_sRGB(texel.rgb); + + gbuffer_pack(vN, color, 0.0, 0.9, 1.0, vec3(0.0), 3u); +} diff --git a/Shaders/HDR/geometry-lfeat.vert b/Shaders/HDR/terrain_lfeat.vert similarity index 58% rename from Shaders/HDR/geometry-lfeat.vert rename to Shaders/HDR/terrain_lfeat.vert index a45fbc704..e00961aee 100644 --- a/Shaders/HDR/geometry-lfeat.vert +++ b/Shaders/HDR/terrain_lfeat.vert @@ -2,11 +2,10 @@ layout(location = 0) in vec4 pos; layout(location = 1) in vec3 normal; -layout(location = 2) in vec4 vertexColor; -layout(location = 3) in vec4 multiTexCoord0; +layout(location = 3) in vec4 multitexcoord0; -out vec3 normalVS; -out vec2 texCoord; +out vec3 vN; +out vec2 texcoord; uniform mat4 osg_ModelViewProjectionMatrix; uniform mat3 osg_NormalMatrix; @@ -15,7 +14,8 @@ void main() { vec4 raised_pos = pos; raised_pos.z += 0.05; + gl_Position = osg_ModelViewProjectionMatrix * raised_pos; - normalVS = normalize(osg_NormalMatrix * normal); - texCoord = multiTexCoord0.st; + vN = normalize(osg_NormalMatrix * normal); + texcoord = multitexcoord0.st; } diff --git a/Shaders/HDR/terrain_runway.frag b/Shaders/HDR/terrain_runway.frag new file mode 100644 index 000000000..80421deca --- /dev/null +++ b/Shaders/HDR/terrain_runway.frag @@ -0,0 +1,38 @@ +#version 330 core + +in vec3 rawpos; +in vec2 texcoord; +in mat3 TBN; + +uniform sampler2D color_tex; +uniform sampler2D normal_tex; +uniform sampler3D noise_tex; + +const float NORMAL_MAP_SCALE = 8.0; + +// gbuffer_pack.glsl +void gbuffer_pack(vec3 normal, vec3 base_color, float metallic, float roughness, + float occlusion, vec3 emissive, uint mat_id); +// color.glsl +vec3 eotf_inverse_sRGB(vec3 srgb); + +void main() +{ + vec4 texel = texture(color_tex, texcoord); + vec3 color = eotf_inverse_sRGB(texel.rgb); + + vec3 normal = texture(normal_tex, texcoord * NORMAL_MAP_SCALE).rgb * 2.0 - 1.0; + vec3 N = normalize(TBN * normal); + + vec3 noise_large = texture(noise_tex, rawpos * 0.0045).rgb; + vec3 noise_small = texture(noise_tex, rawpos).rgb; + + float mix_factor = noise_large.r * noise_large.g * noise_large.b * 350.0; + mix_factor = smoothstep(0.0, 1.0, mix_factor); + + color = mix(color, noise_small, 0.15); + + float roughness = mix(0.94, 0.98, mix_factor); + + gbuffer_pack(N, color, 0.0, roughness, 1.0, vec3(0.0), 3u); +} diff --git a/Shaders/HDR/geometry-runway.vert b/Shaders/HDR/terrain_runway.vert similarity index 85% rename from Shaders/HDR/geometry-runway.vert rename to Shaders/HDR/terrain_runway.vert index b6e7d6bf0..0940f5b85 100644 --- a/Shaders/HDR/geometry-runway.vert +++ b/Shaders/HDR/terrain_runway.vert @@ -2,10 +2,10 @@ layout(location = 0) in vec4 pos; layout(location = 1) in vec3 normal; -layout(location = 3) in vec4 multiTexCoord0; +layout(location = 3) in vec4 multitexcoord0; out vec3 rawpos; -out vec2 texCoord; +out vec2 texcoord; out mat3 TBN; uniform mat4 osg_ModelViewProjectionMatrix; @@ -15,7 +15,7 @@ void main() { rawpos = pos.xyz / pos.w; gl_Position = osg_ModelViewProjectionMatrix * pos; - texCoord = multiTexCoord0.st; + texcoord = multitexcoord0.st; vec3 tangent = cross(normal, vec3(1.0, 0.0, 0.0)); vec3 binormal = cross(normal, tangent); diff --git a/Shaders/HDR/trivial.frag b/Shaders/HDR/trivial.frag deleted file mode 100644 index 3dad6644a..000000000 --- a/Shaders/HDR/trivial.frag +++ /dev/null @@ -1,12 +0,0 @@ -#version 330 core - -out vec4 fragColor; - -in vec2 texCoord; - -uniform sampler2D tex; - -void main() -{ - fragColor = texture(tex, texCoord); -} diff --git a/Shaders/HDR/water-lighting.frag b/Shaders/HDR/water-lighting.frag deleted file mode 100644 index f122f6116..000000000 --- a/Shaders/HDR/water-lighting.frag +++ /dev/null @@ -1,85 +0,0 @@ -#version 330 core - -out vec3 fragColor; - -in vec2 texCoord; - -uniform sampler2D gbuffer0_tex; -uniform sampler2D gbuffer1_tex; -uniform sampler2D depth_tex; -uniform samplerCube prefiltered_envmap; -uniform sampler2D transmittance_lut; - -uniform mat4 fg_ViewMatrixInverse; -uniform vec3 fg_SunDirection; -uniform float fg_SunZenithCosTheta; - -const float PI = 3.14159265359; -const float RECIPROCAL_PI = 0.31830988618; -const float MAX_PREFILTERED_LOD = 4.0; -const vec3 EXTRATERRESTRIAL_SOLAR_ILLUMINANCE = vec3(128.0); - -vec3 decodeNormal(vec2 f); -vec3 positionFromDepth(vec2 pos, float depth); -vec3 add_aerial_perspective(vec3 color, vec2 coord, float depth); - -float F_Schlick(float VdotH, float F0) -{ - return F0 + (1.0 - F0) * pow(clamp(1.0 - VdotH, 0.0, 1.0), 5.0); -} - -float D_GGX(float NdotH, float a2) -{ - float f = (NdotH * a2 - NdotH) * NdotH + 1.0; - return a2 / (PI * f * f); -} - -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 l = fg_SunDirection; - - vec3 reflected = reflect(-v, n); - vec3 worldNormal = (fg_ViewMatrixInverse * vec4(n, 0.0)).xyz; - vec3 worldReflected = (fg_ViewMatrixInverse * vec4(reflected, 0.0)).xyz; - - float NdotL = clamp(dot(n, l), 0.0, 1.0); - float NdotV = clamp(abs(dot(n, v)), 0.001, 1.0); - vec3 h = normalize(v + l); - float NdotH = clamp(dot(n, h), 0.0, 1.0); - - // Get transmittance from Sun to the sea surface (assume the water is - // always at sea level, i.e. normalizedAltitude = 0) - vec3 transmittance = texture(transmittance_lut, - vec2(fg_SunZenithCosTheta * 0.5 + 0.5, 0.0)).rgb; - vec3 sunIntensity = EXTRATERRESTRIAL_SOLAR_ILLUMINANCE * transmittance; - - const float f0 = 0.02; // For IOR=1.33 - float fresnel = F_Schlick(NdotV, f0); - - // Refracted light - vec3 Esky = textureLod(prefiltered_envmap, worldNormal, MAX_PREFILTERED_LOD).rgb; - vec3 refracted = seaColor * Esky * RECIPROCAL_PI; - - // Reflected sky light - vec3 reflection = textureLod(prefiltered_envmap, worldReflected, 1.0).rgb; - - vec3 color = mix(refracted, reflection, fresnel); - - // Add reflected Sun light - color += RECIPROCAL_PI * fresnel * D_GGX(NdotH, 0.001) * sunIntensity * NdotL; - - color = add_aerial_perspective(color, texCoord, length(pos)); - - fragColor = color; -} diff --git a/Shaders/HDR/geometry-water.frag b/Shaders/HDR/water.frag similarity index 97% rename from Shaders/HDR/geometry-water.frag rename to Shaders/HDR/water.frag index c32829761..3a1537b32 100644 --- a/Shaders/HDR/geometry-water.frag +++ b/Shaders/HDR/water.frag @@ -26,8 +26,10 @@ uniform float WaveDAngle; uniform float osg_SimulationTime; uniform vec3 fg_SunDirection; -vec2 encodeNormal(vec3 n); -vec3 decodeSRGB(vec3 screenRGB); +// normal_encoding.glsl +vec2 encode_normal(vec3 n); +// color.glsl +vec3 eotf_inverse_sRGB(vec3 srgb); void rotationmatrix(float angle, out mat4 rotmat) { @@ -208,8 +210,8 @@ void main() vec3 N = normalize(mix(N0, N1, mixFactor) * waveRoughness); - vec3 floorColor = decodeSRGB(texture(water_colormap, TopoUV).rgb); + vec3 floorColor = eotf_inverse_sRGB(texture(water_colormap, TopoUV).rgb); - outGBuffer0.rg = encodeNormal(TBN * N); + outGBuffer0.rg = encode_normal(TBN * N); outGBuffer1.rgb = floorColor; } diff --git a/Shaders/HDR/geometry-water.vert b/Shaders/HDR/water.vert similarity index 100% rename from Shaders/HDR/geometry-water.vert rename to Shaders/HDR/water.vert diff --git a/Shaders/HDR/water_shading.frag b/Shaders/HDR/water_shading.frag new file mode 100644 index 000000000..d69656bf5 --- /dev/null +++ b/Shaders/HDR/water_shading.frag @@ -0,0 +1,78 @@ +#version 330 core + +layout(location = 0) out vec3 fragColor; + +in vec2 texcoord; + +uniform sampler2D gbuffer0_tex; +uniform sampler2D gbuffer1_tex; +uniform samplerCube prefiltered_envmap_tex; + +uniform mat4 fg_ViewMatrixInverse; +uniform vec3 fg_SunDirection; + +const float MAX_PREFILTERED_LOD = 4.0; + +// math.glsl +float M_PI(); +float M_1_PI(); +// normal_encoding.glsl +vec3 decode_normal(vec2 f); +// pos_from_depth.glsl +vec3 get_view_space_from_depth(vec2 uv); +// aerial_perspective.glsl +vec3 add_aerial_perspective(vec3 color, vec2 coord, float depth); +vec3 get_sun_radiance_sea_level(); + +float F_Schlick(float VdotH, float F0) +{ + return F0 + (1.0 - F0) * pow(clamp(1.0 - VdotH, 0.0, 1.0), 5.0); +} + +float D_GGX(float NdotH, float a2) +{ + float f = (NdotH * a2 - NdotH) * NdotH + 1.0; + return a2 / (M_PI() * f * f); +} + +void main() +{ + vec4 gbuffer0 = texture(gbuffer0_tex, texcoord); + vec4 gbuffer1 = texture(gbuffer1_tex, texcoord); + + // Unpack G-Buffer + vec3 N = decode_normal(gbuffer0.rg); + vec3 sea_color = gbuffer1.rgb; + + vec3 P = get_view_space_from_depth(texcoord); + vec3 V = normalize(-P); + vec3 L = fg_SunDirection; + + vec3 refl = reflect(-V, N); + vec3 ws_N = (fg_ViewMatrixInverse * vec4(N, 0.0)).xyz; + vec3 ws_refl = (fg_ViewMatrixInverse * vec4(refl, 0.0)).xyz; + + vec3 H = normalize(L + V); + float NdotL = clamp(dot(N, L), 0.0, 1.0); + float NdotV = clamp(abs(dot(N, V)), 0.001, 1.0); + float NdotH = clamp(dot(N, H), 0.0, 1.0); + + const float f0 = 0.02; // For IOR=1.33 + float fresnel = F_Schlick(NdotV, f0); + + // Refracted light + vec3 Esky = textureLod(prefiltered_envmap_tex, ws_N, MAX_PREFILTERED_LOD).rgb; + vec3 refracted = sea_color * Esky * M_1_PI(); + // Reflected sky light + vec3 reflected = textureLod(prefiltered_envmap_tex, ws_refl, 1.0).rgb; + + vec3 color = mix(refracted, reflected, fresnel); + + // Add reflected Sun light + vec3 sun_intensity = get_sun_radiance_sea_level(); + color += M_1_PI() * fresnel * D_GGX(NdotH, 0.001) * sun_intensity * NdotL; + + color = add_aerial_perspective(color, texcoord, length(P)); + + fragColor = color; +} diff --git a/Shaders/HDR/ws30.frag b/Shaders/HDR/ws30.frag deleted file mode 100644 index b824668e9..000000000 --- a/Shaders/HDR/ws30.frag +++ /dev/null @@ -1,67 +0,0 @@ -#version 330 core - -layout(location = 0) out vec4 outGBuffer0; -layout(location = 1) out vec4 outGBuffer1; -layout(location = 2) out vec4 outGBuffer2; - -in vec3 normalVS; -in vec2 texCoord; - -uniform sampler2D landclass; -uniform sampler2DArray atlas; -uniform sampler2D perlin; - -// Passed from VPBTechnique, not the Effect -uniform float tile_width; -uniform float tile_height; -uniform vec4 dimensionsArray[128]; -uniform vec4 ambientArray[128]; -uniform vec4 diffuseArray[128]; -uniform vec4 specularArray[128]; - - -vec2 encodeNormal(vec3 n); -vec3 decodeSRGB(vec3 screenRGB); - -void main() -{ - vec3 texel; - - if (photoScenery) { - texel = decodeSRGB(texture(landclass, vec2(gl_TexCoord[0].s, 1.0 - gl_TexCoord[0].t)).rgb); - } else { - - // The Landclass for this particular fragment. This can be used to - // index into the atlas textures. - int lc = int(texture2D(landclass, gl_TexCoord[0].st).g * 255.0 + 0.5); - - color = ambientArray[lc] + diffuseArray[lc] * NdotL * gl_LightSource[0].diffuse; - specular = specularArray[lc]; - - // Different textures have different have different dimensions. - vec2 atlas_dimensions = dimensionsArray[lc].st; - vec2 atlas_scale = vec2(tile_width / atlas_dimensions.s, tile_height / atlas_dimensions.t ); - vec2 st = atlas_scale * gl_TexCoord[0].st; - - // Rotate texture using the perlin texture as a mask to reduce tiling - if (step(0.5, texture(perlin, atlas_scale * gl_TexCoord[0].st / 8.0).r) == 1.0) { - st = vec2(atlas_scale.s * gl_TexCoord[0].t, atlas_scale.t * gl_TexCoord[0].s); - } - - if (step(0.5, texture(perlin, - atlas_scale * gl_TexCoord[0].st / 16.0).r) == 1.0) { - st = -st; - } - - texel = decodeSRGB(texture(atlas, vec3(st, lc)).rgb); - } - - float specularity = clamp(dot(specular.rgb, vec3(0.333)), 0.0, 1.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; -}