From d787f9a7fc5e86e2b8d0587cd3dba64723a8c067 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Sun, 13 Sep 2026 12:10:51 -0700 Subject: [PATCH 1/9] Update Theme --- leenkx/blender/theme/BlenderLeenkxTheme.xml | 365 ++++++++++++++++++++ 1 file changed, 365 insertions(+) diff --git a/leenkx/blender/theme/BlenderLeenkxTheme.xml b/leenkx/blender/theme/BlenderLeenkxTheme.xml index 9d242007..235c6293 100644 --- a/leenkx/blender/theme/BlenderLeenkxTheme.xml +++ b/leenkx/blender/theme/BlenderLeenkxTheme.xml @@ -548,6 +548,24 @@ transform="#dfdf2a" outline_width="1" object_origin_size="6" + vertex_bevel="#2ae0e0" + edge_bevel="#2ae0e0" + edge_seam="#df2a2a" + edge_sharp="#2adf85" + edge_crease="#800000" + freestyle_edge_mark="#2adf2a4d" + freestyle_face_mark="#2adf2a4d" + active_spline="#000000" + face_dot_selected="#2adf8533" + text_keyframe="#dfdf2a" + handle_free="#dfdf2a" + handle_sel_free="#dfdf2a" + handle_auto="#df2a2a" + handle_sel_auto="#df2a2a" + handle_vect="#852adf" + handle_sel_vect="#852adf" + handle_align="#2adf2a" + handle_sel_align="#2adf2a" > + + + + + + + + @@ -577,6 +613,31 @@ vertex_select="#df852a" vertex_active="#fdf6e3" vertex_size="6" + frame_current="#2ae0e0" + preview_range="#df852a66" + dopesheet_channel="#2ae0e080" + dopesheet_subchannel="#07364280" + channel_group="#07364237" + active_channels_group="#2adf8567" + channels="#002b3699" + channels_selected="#2adf2a44" + channels_region="#002b36" + handle_free="#dfdf2a" + handle_sel_free="#dfdf2a" + handle_auto="#df2a2a" + handle_sel_auto="#df2a2a" + handle_vect="#852adf" + handle_sel_vect="#852adf" + handle_align="#2adf2a" + handle_sel_align="#2adf2a" + handle_auto_clamped="#800000" + handle_sel_auto_clamped="#800000" + handle_vertex="#586e75" + handle_vertex_select="#df852a" + handle_vertex_size="5" + time_scrub_background="#001114ff" + time_marker_line="#fdf6e380" + time_marker_line_selected="#fdf6e3ff" > + + + + + + + + @@ -606,7 +686,18 @@ header="#073642b3" header_text="#fdf6e3" header_text_hi="#fdf6e3" + button="#002b3600" + navigation_bar="#001a22ff" + tab_back="#001a22ff" > + + + + @@ -628,6 +719,15 @@ tweak_duplicate="#df2a2a" keyframe_border="#586e75ff" keyframe_border_selected="#586e75ff" + frame_current="#2ae0e0" + preview_range="#df852a66" + dopesheet_channel="#2ae0e080" + dopesheet_subchannel="#07364280" + channels="#002b3699" + channels_selected="#2adf2a44" + time_scrub_background="#001114ff" + time_marker_line="#fdf6e380" + time_marker_line_selected="#fdf6e3ff" > + + + + + + + + @@ -654,6 +773,31 @@ anim_interpolation_constant="#df852acc" anim_interpolation_other="#2adf85b3" simulated_frames="#800000ff" + frame_current="#2ae0e0" + preview_range="#df852a66" + dopesheet_channel="#2ae0e080" + dopesheet_subchannel="#07364280" + channel_group="#07364237" + active_channels_group="#2adf8567" + channels="#002b3699" + channels_selected="#2adf2a44" + keyframe="#fdf6e3" + keyframe_selected="#dfdf2a" + keyframe_extreme="#800000" + keyframe_extreme_selected="#df2a2a" + keyframe_breakdown="#2adf85" + keyframe_breakdown_selected="#2ae0e0" + keyframe_jitter="#2adf2a" + keyframe_jitter_selected="#2adf2a" + keyframe_movehold="#657b83" + keyframe_movehold_selected="#dfdf2a" + keyframe_generated="#586e75" + keyframe_generated_selected="#dfdf2a" + long_key="#fdf6e31f" + long_key_selected="#df852a99" + time_scrub_background="#001114ff" + time_marker_line="#fdf6e380" + time_marker_line_selected="#fdf6e3ff" > + + + + + + + + @@ -693,6 +856,13 @@ uv_shadow="#586e75ff" metadatabg="#001a22" metadatatext="#fdf6e3" + face_dot_selected="#2ae0e03c" + handle_free="#dfdf2a" + handle_sel_free="#dfdf2a" + handle_auto="#df2a2a" + handle_sel_auto="#df2a2a" + handle_align="#2adf2a" + handle_sel_align="#2adf2a" > + + + + + + + + @@ -732,6 +920,19 @@ row_alternate="#93a1a105" text_strip_cursor="#2ae0e0ff" selected_text="#fdf6e34d" + frame_current="#2ae0e0" + preview_range="#df852a66" + keyframe="#fdf6e3" + keyframe_selected="#dfdf2a" + keyframe_breakdown="#2adf85" + keyframe_breakdown_selected="#2ae0e0" + keyframe_movehold="#657b83" + keyframe_movehold_selected="#dfdf2a" + keyframe_generated="#586e75" + keyframe_generated_selected="#dfdf2a" + time_scrub_background="#001114ff" + time_marker_line="#fdf6e380" + time_marker_line_selected="#fdf6e3ff" > + + + + + + + + @@ -760,7 +980,18 @@ header="#073642b3" header_text="#fdf6e3" header_text_hi="#fdf6e3" + button="#002b3600" + navigation_bar="#001a22ff" + tab_back="#001a22ff" > + + + + @@ -789,7 +1020,18 @@ header="#073642b3" header_text="#fdf6e3" header_text_hi="#fdf6e3" + button="#002b3600" + navigation_bar="#001a22ff" + tab_back="#001a22ff" > + + + + @@ -837,7 +1079,18 @@ header="#073642b3" header_text="#fdf6e3" header_text_hi="#fdf6e3" + button="#002b3600" + navigation_bar="#001a22ff" + tab_back="#001a22ff" > + + + + @@ -861,7 +1114,18 @@ header="#073642b3" header_text="#fdf6e3" header_text_hi="#fdf6e3" + button="#002b3600" + navigation_bar="#001a22ff" + tab_back="#001a22ff" > + + + + @@ -889,7 +1153,18 @@ header="#073642b3" header_text="#fdf6e3" header_text_hi="#fdf6e3" + button="#002b3600" + navigation_bar="#001a22ff" + tab_back="#001a22ff" > + + + + @@ -907,7 +1182,18 @@ header="#073642b3" header_text="#fdf6e3" header_text_hi="#fdf6e3" + button="#002b3600" + navigation_bar="#001a22ff" + tab_back="#001a22ff" > + + + + @@ -930,7 +1216,18 @@ header="#073642b3" header_text="#fdf6e3" header_text_hi="#fdf6e3" + button="#002b3600" + navigation_bar="#001a22ff" + tab_back="#001a22ff" > + + + + @@ -950,6 +1247,22 @@ path_keyframe_after="#2ae0e080" metadatabg="#001a22" metadatatext="#fdf6e3" + strips="#fdf6e31f" + strips_selected="#df852a99" + handle_free="#dfdf2a" + handle_sel_free="#dfdf2a" + handle_auto="#df2a2a" + handle_sel_auto="#df2a2a" + handle_align="#2adf2a" + handle_sel_align="#2adf2a" + handle_auto_clamped="#800000" + handle_sel_auto_clamped="#800000" + handle_vertex="#586e75" + handle_vertex_select="#df852a" + handle_vertex_size="5" + time_scrub_background="#001114ff" + time_marker_line="#fdf6e380" + time_marker_line_selected="#fdf6e3ff" > + + + + + + + + @@ -976,7 +1308,18 @@ header="#073642b3" header_text="#fdf6e3" header_text_hi="#fdf6e3" + button="#002b3600" + navigation_bar="#001a22ff" + tab_back="#001a22ff" > + + + + @@ -992,7 +1335,18 @@ header="#073642b3" header_text="#fdf6e3" header_text_hi="#fdf6e3" + button="#002b3600" + navigation_bar="#001a22ff" + tab_back="#001a22ff" > + + + + @@ -1010,7 +1364,18 @@ header="#073642b3" header_text="#fdf6e3" header_text_hi="#fdf6e3" + button="#002b3600" + navigation_bar="#001a22ff" + tab_back="#001a22ff" > + + + + From 635f8f6645745c106b46925b1edf08a96b3dd74a Mon Sep 17 00:00:00 2001 From: Onek8 Date: Sun, 13 Sep 2026 20:18:00 -0700 Subject: [PATCH 2/9] SSRS WebGL Fix --- leenkx/Sources/leenkx/renderpath/Inc.hx | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/leenkx/Sources/leenkx/renderpath/Inc.hx b/leenkx/Sources/leenkx/renderpath/Inc.hx index b779b1cb..2b40b484 100644 --- a/leenkx/Sources/leenkx/renderpath/Inc.hx +++ b/leenkx/Sources/leenkx/renderpath/Inc.hx @@ -669,11 +669,20 @@ class Inc { #end #if rp_ssrs + #if (!kha_opengl) + path.setDepthFrom("accum", "gbuffer1"); // Unbind depth so we can read it + #end path.bindTarget("_main", "gbufferD"); #end path.drawMeshes("translucent"); + #if rp_ssrs + #if (!kha_opengl) + path.setDepthFrom("accum", "gbuffer0"); // Re-bind depth + #end + #end + #if rp_render_to_texture { path.setTarget(target); From 67d5e6b2c7fe8355f653e01e6bb1f889c97a57ed Mon Sep 17 00:00:00 2001 From: Onek8 Date: Sun, 13 Sep 2026 21:52:13 -0700 Subject: [PATCH 3/9] SSRS Fix --- leenkx/Sources/leenkx/renderpath/Inc.hx | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/leenkx/Sources/leenkx/renderpath/Inc.hx b/leenkx/Sources/leenkx/renderpath/Inc.hx index 2b40b484..38c4e76f 100644 --- a/leenkx/Sources/leenkx/renderpath/Inc.hx +++ b/leenkx/Sources/leenkx/renderpath/Inc.hx @@ -669,20 +669,13 @@ class Inc { #end #if rp_ssrs - #if (!kha_opengl) - path.setDepthFrom("accum", "gbuffer1"); // Unbind depth so we can read it - #end + #if kha_opengl path.bindTarget("_main", "gbufferD"); #end + #end path.drawMeshes("translucent"); - #if rp_ssrs - #if (!kha_opengl) - path.setDepthFrom("accum", "gbuffer0"); // Re-bind depth - #end - #end - #if rp_render_to_texture { path.setTarget(target); From 73e4a0ad30caed819035d2448877527ed95001dc Mon Sep 17 00:00:00 2001 From: Onek8 Date: Sun, 13 Sep 2026 23:34:36 -0700 Subject: [PATCH 4/9] Scene Gamma / Exposure --- .../compositor_pass/compositor_pass.frag.glsl | 14 +++++++++++--- leenkx/Sources/leenkx/renderpath/Postprocess.hx | 9 +++++++++ leenkx/blender/lnx/make_renderpath.py | 2 ++ leenkx/blender/lnx/write_data.py | 1 + 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/leenkx/Shaders/compositor_pass/compositor_pass.frag.glsl b/leenkx/Shaders/compositor_pass/compositor_pass.frag.glsl index 8118432e..b7d9d7ba 100644 --- a/leenkx/Shaders/compositor_pass/compositor_pass.frag.glsl +++ b/leenkx/Shaders/compositor_pass/compositor_pass.frag.glsl @@ -69,6 +69,7 @@ uniform vec4 PPComp15; uniform vec4 PPComp16; uniform vec4 PPComp18; uniform vec4 PPComp19; +uniform vec4 PPComp20; #endif // #ifdef _CPos @@ -499,14 +500,15 @@ void main() { #ifdef _CExposure #ifdef _CPostprocess - fragColor.rgb+=fragColor.rgb*PPComp8.x; + fragColor.rgb *= pow(2.0, PPComp8.x); #else - fragColor.rgb+= fragColor.rgb*compoExposureStrength; + fragColor.rgb *= pow(2.0, compoExposureStrength); #endif #endif #ifdef _CPostprocess fragColor.rgb *= ComputeEV(0.0); + fragColor.rgb *= pow(2.0, PPComp20.x); // exposure and gamma #endif #ifdef _AutoExposure @@ -582,7 +584,9 @@ fragColor.rgb = min(fragColor.rgb, 65504 * 0.5); fragColor.rgb = tonemapAgXFull(fragColor.rgb); } //else { fragColor.rgb = vec3(0,1,0); //ERROR} #endif - +#ifdef _CGamma + fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / PPComp20.y)); +#endif #else #ifdef _CToneFilmic fragColor.rgb = tonemapFilmic(fragColor.rgb); // With gamma @@ -615,6 +619,10 @@ fragColor.rgb = min(fragColor.rgb, 65504 * 0.5); #endif #endif +#ifdef _CGamma + fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / compoGammaStrength)); +#endif + #ifdef _CBW // fragColor.rgb = vec3(clamp(dot(fragColor.rgb, fragColor.rgb), 0.0, 1.0)); fragColor.rgb = vec3((fragColor.r * 0.3 + fragColor.g * 0.59 + fragColor.b * 0.11) / 3.0) * 2.5; diff --git a/leenkx/Sources/leenkx/renderpath/Postprocess.hx b/leenkx/Sources/leenkx/renderpath/Postprocess.hx index 83fe4e91..b758490a 100644 --- a/leenkx/Sources/leenkx/renderpath/Postprocess.hx +++ b/leenkx/Sources/leenkx/renderpath/Postprocess.hx @@ -116,6 +116,11 @@ class Postprocess { 1 //0: Exposure ]; + public static var scene_color_uniforms = [ + 0.0, //0: Scene Exposure + 1.0 //1: Scene Gamma + ]; + public static var auto_exposure_uniforms = [ 1, //0: Auto Exposure Strength 1 //1: Auto Exposure Speed @@ -406,6 +411,10 @@ class Postprocess { v.x = auto_focus[0]; v.y = auto_focus[1]; v.z = auto_focus[2]; + case "_PPComp20": + v = iron.object.Uniforms.helpVec; + v.x = scene_color_uniforms[0]; // Scene Exposure + v.y = scene_color_uniforms[1]; // Scene Gamma } return v; diff --git a/leenkx/blender/lnx/make_renderpath.py b/leenkx/blender/lnx/make_renderpath.py index 6eee2aca..8d8f3fce 100644 --- a/leenkx/blender/lnx/make_renderpath.py +++ b/leenkx/blender/lnx/make_renderpath.py @@ -267,6 +267,8 @@ def build(): wrd.compo_defs += '_CSharpen' if lnx.utils.get_active_scene().view_settings.exposure != 0.0: wrd.compo_defs += '_CExposure' + if lnx.utils.get_active_scene().view_settings.gamma != 1.0: + wrd.compo_defs += '_CGamma' if rpdat.lnx_fog: wrd.compo_defs += '_CFog' compo_depth = True diff --git a/leenkx/blender/lnx/write_data.py b/leenkx/blender/lnx/write_data.py index aadb4d95..8bccdbdf 100644 --- a/leenkx/blender/lnx/write_data.py +++ b/leenkx/blender/lnx/write_data.py @@ -1009,6 +1009,7 @@ const vec3 compoSharpenColor = vec3(""" + str(round(rpdat.lnx_sharpen_color[0] * if lnx.utils.get_active_scene().view_settings.exposure != 0.0: f.write( """const float compoExposureStrength = """ + str(round(lnx.utils.get_active_scene().view_settings.exposure * 100) / 100) + """; +const float compoGammaStrength = """ + str(round(lnx.utils.get_active_scene().view_settings.gamma * 100) / 100) + """; """) if rpdat.lnx_fog: From 56d1b0e4a7f01c4b71eba137e33c4c8586cb4fe2 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 16 Sep 2026 12:40:39 -0700 Subject: [PATCH 5/9] Forward / Mobile / Solid --- .../deferred_light/deferred_light.frag.glsl | 24 +-- .../deferred_light.frag.glsl | 117 +++++++++-- .../deferred_light_mobile.json | 13 -- leenkx/Shaders/std/light_mobile.glsl | 190 +++++++++++++++--- leenkx/Sources/iron/object/LightObject.hx | 12 +- leenkx/Sources/leenkx/renderpath/Inc.hx | 8 +- .../leenkx/renderpath/RenderPathDeferred.hx | 17 ++ leenkx/blender/lnx/make_renderpath.py | 1 + leenkx/blender/lnx/material/make_cluster.py | 8 +- leenkx/blender/lnx/material/mat_utils.py | 2 +- leenkx/blender/lnx/props_renderpath.py | 2 +- 11 files changed, 306 insertions(+), 88 deletions(-) diff --git a/leenkx/Shaders/deferred_light/deferred_light.frag.glsl b/leenkx/Shaders/deferred_light/deferred_light.frag.glsl index ae4bba58..61f39501 100644 --- a/leenkx/Shaders/deferred_light/deferred_light.frag.glsl +++ b/leenkx/Shaders/deferred_light/deferred_light.frag.glsl @@ -907,26 +907,10 @@ tileBounds = vec4(0.0, 0.0, 1.0, 1.0); fragColor.rgb += cLightCol * sssStrengthCL * SSSSTransmittance(LWVPSpotArray[li], p, n, cLightDir, lightPlane.y, shadowMapAtlas, sssColorCL, sssRadiusCL, tileBoundsSpotArray[li]); #endif #else - if (li == 0) fragColor.rgb += cLightCol * sssStrengthCL * SSSSTransmittance(LWVPSpotArray[0], p, n, cLightDir, lightPlane.y, shadowMapSpot[0], sssColorCL, sssRadiusCL - #ifdef _ShadowMapAtlas - , vec4(0.0, 0.0, 1.0, 1.0) - #endif - ); - else if (li == 1) fragColor.rgb += cLightCol * sssStrengthCL * SSSSTransmittance(LWVPSpotArray[1], p, n, cLightDir, lightPlane.y, shadowMapSpot[1], sssColorCL, sssRadiusCL - #ifdef _ShadowMapAtlas - , vec4(0.0, 0.0, 1.0, 1.0) - #endif - ); - else if (li == 2) fragColor.rgb += cLightCol * sssStrengthCL * SSSSTransmittance(LWVPSpotArray[2], p, n, cLightDir, lightPlane.y, shadowMapSpot[2], sssColorCL, sssRadiusCL - #ifdef _ShadowMapAtlas - , vec4(0.0, 0.0, 1.0, 1.0) - #endif - ); - else if (li == 3) fragColor.rgb += cLightCol * sssStrengthCL * SSSSTransmittance(LWVPSpotArray[3], p, n, cLightDir, lightPlane.y, shadowMapSpot[3], sssColorCL, sssRadiusCL - #ifdef _ShadowMapAtlas - , vec4(0.0, 0.0, 1.0, 1.0) - #endif - ); + if (li == 0) fragColor.rgb += cLightCol * sssStrengthCL * SSSSTransmittance(LWVPSpotArray[0], p, n, cLightDir, lightPlane.y, shadowMapSpot[0], sssColorCL, sssRadiusCL); + else if (li == 1) fragColor.rgb += cLightCol * sssStrengthCL * SSSSTransmittance(LWVPSpotArray[1], p, n, cLightDir, lightPlane.y, shadowMapSpot[1], sssColorCL, sssRadiusCL); + else if (li == 2) fragColor.rgb += cLightCol * sssStrengthCL * SSSSTransmittance(LWVPSpotArray[2], p, n, cLightDir, lightPlane.y, shadowMapSpot[2], sssColorCL, sssRadiusCL); + else if (li == 3) fragColor.rgb += cLightCol * sssStrengthCL * SSSSTransmittance(LWVPSpotArray[3], p, n, cLightDir, lightPlane.y, shadowMapSpot[3], sssColorCL, sssRadiusCL); #endif } else { #ifdef _ShadowMapAtlas diff --git a/leenkx/Shaders/deferred_light_mobile/deferred_light.frag.glsl b/leenkx/Shaders/deferred_light_mobile/deferred_light.frag.glsl index 75512780..aa86595f 100644 --- a/leenkx/Shaders/deferred_light_mobile/deferred_light.frag.glsl +++ b/leenkx/Shaders/deferred_light_mobile/deferred_light.frag.glsl @@ -56,9 +56,15 @@ uniform vec2 cameraPlane; #ifdef _SinglePoint #ifdef _Spot //!uniform sampler2DShadow shadowMapSpot[1]; + #ifdef _ShadowMapTransparent + //!uniform sampler2D shadowMapSpotTransparent[1]; + #endif //!uniform mat4 LWVPSpotArray[1]; #else //!uniform samplerCubeShadow shadowMapPoint[1]; + #ifdef _ShadowMapTransparent + //!uniform samplerCube shadowMapPointTransparent[1]; + #endif //!uniform vec2 lightProj; #endif #endif @@ -66,26 +72,41 @@ uniform vec2 cameraPlane; #ifdef _ShadowMapAtlas #ifdef _SingleAtlas uniform sampler2DShadow shadowMapAtlas; + #ifdef _ShadowMapTransparent + uniform sampler2D shadowMapAtlasTransparent; + #endif #endif #endif #ifdef _ShadowMapAtlas #ifndef _SingleAtlas //!uniform sampler2DShadow shadowMapAtlasPoint; + #ifdef _ShadowMapTransparent + //!uniform sampler2D shadowMapAtlasPointTransparent; #endif - //!uniform vec4 pointLightDataArray[4]; + #endif + //!uniform vec4 pointLightDataArray[maxLightsCluster * 6]; #else //!uniform samplerCubeShadow shadowMapPoint[4]; + #ifdef _ShadowMapTransparent + //!uniform samplerCube shadowMapPointTransparent[4]; + #endif #endif //!uniform vec2 lightProj; #ifdef _Spot #ifdef _ShadowMapAtlas #ifndef _SingleAtlas //!uniform sampler2DShadow shadowMapAtlasSpot; + #ifdef _ShadowMapTransparent + //!uniform sampler2D shadowMapAtlasSpotTransparent; + #endif #endif #else - //!uniform sampler2DShadow shadowMapSpot[4]; + //!uniform sampler2DShadow shadowMapSpot[maxLightsCluster]; + #ifdef _ShadowMapTransparent + //!uniform sampler2D shadowMapSpotTransparent[maxLightsCluster]; #endif - //!uniform mat4 LWVPSpotArray[4]; + #endif + //!uniform mat4 LWVPSpotArray[maxLightsCluster]; #endif #endif #endif @@ -97,10 +118,16 @@ uniform vec3 sunCol; #ifdef _ShadowMapAtlas #ifndef _SingleAtlas uniform sampler2DShadow shadowMapAtlasSun; + #ifdef _ShadowMapTransparent + uniform sampler2D shadowMapAtlasSunTransparent; + #endif #endif //!uniform vec4 tileBoundsSunArray[maxLights * shadowmapCascades]; #else uniform sampler2DShadow shadowMap; + #ifdef _ShadowMapTransparent + uniform sampler2D shadowMapTransparent; + #endif #endif uniform float shadowsBias; #ifdef _CSM @@ -167,10 +194,11 @@ void main() { vec4 g1 = textureLod(gbuffer1, texCoord, 0.0); // Basecolor.rgb, spec/occ vec2 occspec = unpackFloat2(g1.a); - vec3 albedo = surfaceAlbedo(g1.rgb, metallic); // g1.rgb - basecolor - vec3 f0 = surfaceF0(g1.rgb, metallic); + vec3 basecolor = min(g1.rgb, vec3(2.0)); + vec3 albedo = surfaceAlbedo(basecolor, metallic); + vec3 f0 = surfaceF0(basecolor, metallic); #ifdef _ExtBRDF - f0 = mix(f0, min(g1.rgb, vec3(2.0)), vec3(matp6.y, matp6.z, matp6.w)); + f0 = mix(f0, basecolor, vec3(matp6.y, matp6.z, matp6.w)); #endif float depth = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0; @@ -206,7 +234,7 @@ void main() { envl /= PI; #endif #else - vec3 envl = vec3(1.0); + vec3 envl = vec3(0.0); #endif #ifdef _Rad @@ -227,13 +255,23 @@ void main() { #endif #endif +#ifdef _Brdf + vec3 F = f0 * envBRDF.x + envBRDF.y; +#else + vec3 F = f0; +#endif + envl.rgb *= diffuseIBL(albedo, roughness, f0, dotNV); +#ifdef _Brdf + envl.rgb *= 1.0 - F; +#endif + #ifdef _Rad // Indirect specular - envl.rgb += prefilteredColor * (f0 * envBRDF.x + envBRDF.y) * 1.5 * occspec.y; + envl.rgb += prefilteredColor * F; #else #ifdef _EnvCol - envl.rgb += backgroundCol * surfaceF0(g1.rgb, metallic); // f0 + envl.rgb += backgroundCol * F; #endif #endif @@ -281,7 +319,12 @@ void main() { float transmittance = 1.0 - transF; #ifdef _Rad if (matp2.z > 0.0 && transmittance > 0.0) { - vec3 refrDir = transmissionIBLDirection(n, v, matp3.x); + vec3 refrDir; + if (matp3.y > 0.5) { + refrDir = reflect(-v, n); + } else { + refrDir = transmissionIBLDirection(n, v, matp3.x); + } float transLod = getMipFromRoughness(matp2.w, envmapNumMipmaps); vec3 transColor = textureLod(senvmapRadiance, envMapEquirect(refrDir), transLod).rgb; @@ -337,7 +380,7 @@ void main() { float sdotNH = max(0.0, dot(n, sh)); float sdotVH = max(0.0, dot(v, sh)); float sdotNL = max(0.0, dot(n, sunDir)); - float svisibility = 1.0; + vec3 svisibility = vec3(1.0); #ifdef _Anisotropy vec3 sdirect; if (abs(matp0.x) > 0.001 && dot(wTangent, wTangent) > 0.001) { @@ -385,29 +428,59 @@ void main() { #ifdef _CSM svisibility = shadowTestCascade( #ifdef _ShadowMapAtlas + #ifdef _ShadowMapTransparent + #ifndef _SingleAtlas + shadowMapAtlasSun, shadowMapAtlasSunTransparent + #else + shadowMapAtlas, shadowMapAtlasTransparent + #endif + #else #ifndef _SingleAtlas shadowMapAtlasSun #else shadowMapAtlas #endif + #endif #else - shadowMap + #ifdef _ShadowMapTransparent + shadowMap, shadowMapTransparent + #else + shadowMap + #endif + #endif + , eye, p + n * shadowsBias * 2, shadowsBias + #ifdef _ShadowMapTransparent + , false #endif - , eye, p + n * shadowsBias * 10, shadowsBias ); #else - vec4 lPos = LWVP * vec4(p + n * shadowsBias * 100, 1.0); + vec4 lPos = LWVP * vec4(p + n * shadowsBias * 2, 1.0); if (lPos.w > 0.0) svisibility = shadowTest( #ifdef _ShadowMapAtlas + #ifdef _ShadowMapTransparent + #ifndef _SingleAtlas + shadowMapAtlasSun, shadowMapAtlasSunTransparent + #else + shadowMapAtlas, shadowMapAtlasTransparent + #endif + #else #ifndef _SingleAtlas shadowMapAtlasSun #else shadowMapAtlas #endif + #endif #else - shadowMap + #ifdef _ShadowMapTransparent + shadowMap, shadowMapTransparent + #else + shadowMap + #endif #endif , lPos.xyz / lPos.w, shadowsBias + #ifdef _ShadowMapTransparent + , false + #endif ); #endif #endif @@ -415,11 +488,18 @@ void main() { fragColor.rgb += sdirect * svisibility * sunCol; #endif +#ifdef _ShadowMapAtlas +tileBounds = vec4(0.0, 0.0, 1.0, 1.0); +#endif + #ifdef _SinglePoint fragColor.rgb += sampleLight( p, n, v, dotNV, pointPos, pointCol, albedo, roughness, occspec.y, f0 #ifdef _ShadowMap , 0, pointBias, true + #ifdef _ShadowMapTransparent + , false + #endif #endif #ifdef _Spot , true, spotData.x, spotData.y, spotDir, spotData.zw, spotRight // TODO: Test! @@ -472,12 +552,15 @@ void main() { #ifdef _ShadowMap // light index, shadow bias, cast_shadows , li, lightsArray[li * 3 + 2].x, lightsArray[li * 3 + 2].z != 0.0 + #ifdef _ShadowMapTransparent + , false + #endif #endif #ifdef _Spot , lightsArray[li * 3 + 2].y != 0.0 , lightsArray[li * 3 + 2].y // spot size (cutoff) - , lightsArraySpot[li].w // spot blend (exponent) - , lightsArraySpot[li].xyz // spotDir + , lightsArraySpot[li * 2].w // spot blend (exponent) + , lightsArraySpot[li * 2].xyz // spotDir , vec2(lightsArray[li * 3].w, lightsArray[li * 3 + 1].w) // scale , lightsArraySpot[li * 2 + 1].xyz // right #endif diff --git a/leenkx/Shaders/deferred_light_mobile/deferred_light_mobile.json b/leenkx/Shaders/deferred_light_mobile/deferred_light_mobile.json index efa0f9ce..1c02511a 100644 --- a/leenkx/Shaders/deferred_light_mobile/deferred_light_mobile.json +++ b/leenkx/Shaders/deferred_light_mobile/deferred_light_mobile.json @@ -122,11 +122,6 @@ "link": "_inverseViewProjectionMatrixRight", "ifdef": ["_VRStereo"] }, - { - "name": "invVP", - "link": "_viewProjectionMatrix", - "ifdef": ["_SSRS"] - }, { "name": "smSizeUniform", "link": "_shadowMapSize", @@ -137,14 +132,6 @@ "link": "_lightPlane", "ifdef": ["_SSS"] }, - { - "name": "VP", - "link": "_viewProjectionMatrix", - "ifdef": ["_SSRS"] - }, - { - "ifdef": ["_SMSizeUniform"] - }, { "name": "lightProj", "link": "_lightPlaneProj", diff --git a/leenkx/Shaders/std/light_mobile.glsl b/leenkx/Shaders/std/light_mobile.glsl index 58878fd8..41aeacc3 100644 --- a/leenkx/Shaders/std/light_mobile.glsl +++ b/leenkx/Shaders/std/light_mobile.glsl @@ -14,15 +14,24 @@ #ifdef _SinglePoint #ifdef _Spot uniform sampler2DShadow shadowMapSpot[1]; + #ifdef _ShadowMapTransparent + uniform sampler2D shadowMapSpotTransparent[1]; + #endif uniform mat4 LWVPSpotArray[1]; #else uniform samplerCubeShadow shadowMapPoint[1]; + #ifdef _ShadowMapTransparent + uniform samplerCube shadowMapPointTransparent[1]; + #endif uniform vec2 lightProj; #endif #endif #ifdef _Clusters #ifdef _SingleAtlas //!uniform sampler2DShadow shadowMapAtlas; + #ifdef _ShadowMapTransparent + //!uniform sampler2D shadowMapAtlasTransparent; + #endif #endif #ifndef _SinglePoint uniform vec2 lightProj; @@ -30,17 +39,29 @@ #ifdef _ShadowMapAtlas #ifndef _SingleAtlas uniform sampler2DShadow shadowMapAtlasPoint; + #ifdef _ShadowMapTransparent + uniform sampler2D shadowMapAtlasPointTransparent; + #endif #endif #else uniform samplerCubeShadow shadowMapPoint[4]; + #ifdef _ShadowMapTransparent + uniform samplerCube shadowMapPointTransparent[4]; + #endif #endif #ifdef _Spot #ifdef _ShadowMapAtlas #ifndef _SingleAtlas uniform sampler2DShadow shadowMapAtlasSpot; + #ifdef _ShadowMapTransparent + uniform sampler2D shadowMapAtlasSpotTransparent; + #endif #endif #else uniform sampler2DShadow shadowMapSpot[maxLightsCluster]; + #ifdef _ShadowMapTransparent + uniform sampler2D shadowMapSpotTransparent[maxLightsCluster]; + #endif #endif uniform mat4 LWVPSpotArray[maxLightsCluster]; #endif @@ -51,6 +72,9 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co const vec3 albedo, const float rough, const float spec, const vec3 f0 #ifdef _ShadowMap , int index, float bias, bool receiveShadow + #ifdef _ShadowMapTransparent + , bool transparent + #endif #endif #ifdef _Spot , bool isSpot, float spotSize, float spotBlend, vec3 spotDir, vec2 scale, vec3 right @@ -121,26 +145,77 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co #ifdef _ShadowMap if (receiveShadow) { #ifdef _SinglePoint - vec4 lPos = LWVPSpotArray[0] * vec4(p + n * bias * 10, 1.0); - direct *= shadowTest(shadowMapSpot[0], lPos.xyz / lPos.w, bias); + vec4 lPos = LWVPSpotArray[0] * vec4(p + n * bias * 10, 1.0); + direct *= shadowTest(shadowMapSpot[0], + #ifdef _ShadowMapTransparent + shadowMapSpotTransparent[0], + #endif + lPos.xyz / lPos.w, bias + #ifdef _ShadowMapTransparent + , transparent + #endif + ); #endif #ifdef _Clusters vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0); #ifdef _ShadowMapAtlas - tileBounds = tileBoundsSpotArray[index]; - direct *= shadowTest( - #ifndef _SingleAtlas - shadowMapAtlasSpot - #else - shadowMapAtlas + tileBounds = tileBoundsSpotArray[index]; + direct *= shadowTest( + #ifdef _ShadowMapTransparent + #ifndef _SingleAtlas + shadowMapAtlasSpot, shadowMapAtlasSpotTransparent + #else + shadowMapAtlas, shadowMapAtlasTransparent + #endif + #else + #ifndef _SingleAtlas + shadowMapAtlasSpot + #else + shadowMapAtlas + #endif + #endif + , lPos.xyz / lPos.w, bias + #ifdef _ShadowMapTransparent + , transparent + #endif + ); + #else + if (index == 0) direct *= shadowTest(shadowMapSpot[0], + #ifdef _ShadowMapTransparent + shadowMapSpotTransparent[0], #endif - , lPos.xyz / lPos.w, bias - ); - #else - if (index == 0) direct *= shadowTest(shadowMapSpot[0], lPos.xyz / lPos.w, bias); - else if (index == 1) direct *= shadowTest(shadowMapSpot[1], lPos.xyz / lPos.w, bias); - else if (index == 2) direct *= shadowTest(shadowMapSpot[2], lPos.xyz / lPos.w, bias); - else if (index == 3) direct *= shadowTest(shadowMapSpot[3], lPos.xyz / lPos.w, bias); + lPos.xyz / lPos.w, bias + #ifdef _ShadowMapTransparent + , transparent + #endif + ); + else if (index == 1) direct *= shadowTest(shadowMapSpot[1], + #ifdef _ShadowMapTransparent + shadowMapSpotTransparent[1], + #endif + lPos.xyz / lPos.w, bias + #ifdef _ShadowMapTransparent + , transparent + #endif + ); + else if (index == 2) direct *= shadowTest(shadowMapSpot[2], + #ifdef _ShadowMapTransparent + shadowMapSpotTransparent[2], + #endif + lPos.xyz / lPos.w, bias + #ifdef _ShadowMapTransparent + , transparent + #endif + ); + else if (index == 3) direct *= shadowTest(shadowMapSpot[3], + #ifdef _ShadowMapTransparent + shadowMapSpotTransparent[3], + #endif + lPos.xyz / lPos.w, bias + #ifdef _ShadowMapTransparent + , transparent + #endif + ); #endif #endif } @@ -153,25 +228,76 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co if (receiveShadow) { #ifdef _SinglePoint - #ifndef _Spot - direct *= PCFCube(shadowMapPoint[0], ld, -l, bias, lightProj, n); + #ifndef _Spot + direct *= PCFCube(shadowMapPoint[0], + #ifdef _ShadowMapTransparent + shadowMapPointTransparent[0], #endif + ld, -l, bias, lightProj, n + #ifdef _ShadowMapTransparent + , transparent #endif + ); + #endif + #endif #ifdef _Clusters #ifdef _ShadowMapAtlas - direct *= PCFFakeCube( - #ifndef _SingleAtlas - shadowMapAtlasPoint - #else - shadowMapAtlas - #endif - , ld, -l, bias, lightProj, n, index - ); + direct *= PCFFakeCube( + #ifdef _ShadowMapTransparent + #ifndef _SingleAtlas + shadowMapAtlasPoint, shadowMapAtlasPointTransparent #else - if (index == 0) direct *= PCFCube(shadowMapPoint[0], ld, -l, bias, lightProj, n); - else if (index == 1) direct *= PCFCube(shadowMapPoint[1], ld, -l, bias, lightProj, n); - else if (index == 2) direct *= PCFCube(shadowMapPoint[2], ld, -l, bias, lightProj, n); - else if (index == 3) direct *= PCFCube(shadowMapPoint[3], ld, -l, bias, lightProj, n); + shadowMapAtlas, shadowMapAtlasTransparent + #endif + #else + #ifndef _SingleAtlas + shadowMapAtlasPoint + #else + shadowMapAtlas + #endif + #endif + , ld, -l, bias, lightProj, n, index + #ifdef _ShadowMapTransparent + , transparent + #endif + ); + #else + if (index == 0) direct *= PCFCube(shadowMapPoint[0], + #ifdef _ShadowMapTransparent + shadowMapPointTransparent[0], + #endif + ld, -l, bias, lightProj, n + #ifdef _ShadowMapTransparent + , transparent + #endif + ); + else if (index == 1) direct *= PCFCube(shadowMapPoint[1], + #ifdef _ShadowMapTransparent + shadowMapPointTransparent[1], + #endif + ld, -l, bias, lightProj, n + #ifdef _ShadowMapTransparent + , transparent + #endif + ); + else if (index == 2) direct *= PCFCube(shadowMapPoint[2], + #ifdef _ShadowMapTransparent + shadowMapPointTransparent[2], + #endif + ld, -l, bias, lightProj, n + #ifdef _ShadowMapTransparent + , transparent + #endif + ); + else if (index == 3) direct *= PCFCube(shadowMapPoint[3], + #ifdef _ShadowMapTransparent + shadowMapPointTransparent[3], + #endif + ld, -l, bias, lightProj, n + #ifdef _ShadowMapTransparent + , transparent + #endif + ); #endif #endif } @@ -186,6 +312,9 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co const vec3 albedo, const float rough, const float spec, const vec3 f0 #ifdef _ShadowMap , int index, float bias, bool receiveShadow + #ifdef _ShadowMapTransparent + , bool transparent + #endif #endif #ifdef _Spot , bool isSpot, float spotSize, float spotBlend, vec3 spotDir, vec2 scale, vec3 right @@ -194,6 +323,9 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co return sampleLight(p, n, v, dotNV, lp, lightCol, albedo, rough, spec, f0 #ifdef _ShadowMap , index, bias, receiveShadow + #ifdef _ShadowMapTransparent + , transparent + #endif #endif #ifdef _Spot , isSpot, spotSize, spotBlend, spotDir, scale, right diff --git a/leenkx/Sources/iron/object/LightObject.hx b/leenkx/Sources/iron/object/LightObject.hx index 3c25324d..da6a8d79 100644 --- a/leenkx/Sources/iron/object/LightObject.hx +++ b/leenkx/Sources/iron/object/LightObject.hx @@ -90,8 +90,16 @@ class LightObject extends Object { #if lnx_spot if (data.raw.type == "spot"){ - this.size = data.raw.spot_size; - this.blend = data.raw.spot_blend; + this.size = 0.0; + this.blend = 0.0; + if (data.raw.spot_size != null) { + var s: kha.FastFloat = data.raw.spot_size; + this.size = s; + } + if (data.raw.spot_blend != null) { + var b: kha.FastFloat = data.raw.spot_blend; + this.blend = b; + } } #end diff --git a/leenkx/Sources/leenkx/renderpath/Inc.hx b/leenkx/Sources/leenkx/renderpath/Inc.hx index 38c4e76f..de585e18 100644 --- a/leenkx/Sources/leenkx/renderpath/Inc.hx +++ b/leenkx/Sources/leenkx/renderpath/Inc.hx @@ -1316,7 +1316,11 @@ class ShadowMapAtlas { function new(light: LightObject, transparent: Bool) { + #if lnx_shadowmap_atlas_single_map + var maxTileSize = Std.int(Math.max(Inc.getCubeSize(), Inc.getCascadeSize())); + #else var maxTileSize = shadowMapAtlasSize(light); + #end this.target = shadowMapAtlasName(light.data.raw.type, transparent); this.sizew = this.sizeh = this.baseTileSizeConst = maxTileSize; this.depth = getSubdivisions(); @@ -1420,8 +1424,8 @@ class ShadowMapAtlas { public static inline function shadowMapAtlasName(type: String, transparent: Bool): String { #if lnx_shadowmap_atlas_single_map - return "shadowMapAtlas"; - #else + return transparent ? "shadowMapAtlasTransparent" : "shadowMapAtlas"; + #else switch (type) { case "point": return transparent ? "shadowMapAtlasPointTransparent" : "shadowMapAtlasPoint"; diff --git a/leenkx/Sources/leenkx/renderpath/RenderPathDeferred.hx b/leenkx/Sources/leenkx/renderpath/RenderPathDeferred.hx index 948ae5e9..fa6a32de 100644 --- a/leenkx/Sources/leenkx/renderpath/RenderPathDeferred.hx +++ b/leenkx/Sources/leenkx/renderpath/RenderPathDeferred.hx @@ -560,6 +560,7 @@ class RenderPathDeferred { @:access(iron.RenderPath) public static function commands() { path.setTarget("gbuffer0"); // Only clear gbuffer0 + //path.setTarget("gbuffer0", ["gbuffer1"]); #if (rp_background == "Clear") { path.clearTarget(-1, 1.0); @@ -649,7 +650,11 @@ class RenderPathDeferred { { if (leenkx.data.Config.raw.rp_ssao != false) { path.setTarget("singlea"); + #if rp_ssao_half + path.bindTarget("half", "gbufferD"); + #else path.bindTarget("_main", "gbufferD"); + #end path.bindTarget("gbuffer0", "gbuffer0"); path.drawShader("shader_datas/ssao_pass/ssao_pass"); @@ -670,7 +675,11 @@ class RenderPathDeferred { { if (leenkx.data.Config.raw.rp_ssgi != false) { path.setTarget("ssgi_a"); + #if rp_ssgi_half + path.bindTarget("half", "gbufferD"); + #else path.bindTarget("_main", "gbufferD"); + #end path.bindTarget("gbuffer0", "gbuffer0"); path.bindTarget("gbuffer1", "gbuffer1"); #if rp_gbuffer_emission @@ -684,13 +693,21 @@ class RenderPathDeferred { path.setTarget("ssgi_b"); path.bindTarget("ssgi_a", "tex"); path.bindTarget("gbuffer0", "gbuffer0"); + #if rp_ssgi_half + path.bindTarget("half", "gbufferD"); + #else path.bindTarget("_main", "gbufferD"); + #end path.drawShader("shader_datas/ssgi_blur_pass/ssgi_blur_pass_x"); path.setTarget("ssgi_a"); path.bindTarget("ssgi_b", "tex"); path.bindTarget("gbuffer0", "gbuffer0"); + #if rp_ssgi_half + path.bindTarget("half", "gbufferD"); + #else path.bindTarget("_main", "gbufferD"); + #end path.drawShader("shader_datas/ssgi_blur_pass/ssgi_blur_pass_y"); } } diff --git a/leenkx/blender/lnx/make_renderpath.py b/leenkx/blender/lnx/make_renderpath.py index 8d8f3fce..f8b5e31a 100644 --- a/leenkx/blender/lnx/make_renderpath.py +++ b/leenkx/blender/lnx/make_renderpath.py @@ -343,6 +343,7 @@ def build(): wrd.world_defs += '_FSR1_{0}'.format(rpdat.rp_fsr1) assets.add_shader_pass('fsr1_easu_pass') assets.add_shader_pass('fsr1_rcas_pass') + assets.add_shader_pass('copy_pass') if rpdat.rp_ssao: assets.add_khafile_def('rp_ssao') diff --git a/leenkx/blender/lnx/material/make_cluster.py b/leenkx/blender/lnx/material/make_cluster.py index d46148b1..88983950 100644 --- a/leenkx/blender/lnx/material/make_cluster.py +++ b/leenkx/blender/lnx/material/make_cluster.py @@ -46,9 +46,11 @@ def write(vert: shader.Shader, frag: shader.Shader): if is_transparent_shadows: frag.add_uniform('samplerCube shadowMapPointTransparent[4]', included=True) - if not '_VoxelAOvar' in wrd.world_defs and not '_VoxelGI' in wrd.world_defs or ((parse_opacity or '_VoxelShadow' in wrd.world_defs) and ('_VoxelAOvar' in wrd.world_defs or '_VoxelGI' in wrd.world_defs)): - vert.add_out('vec4 wvpposition') - vert.write('wvpposition = gl_Position;') + #if not '_VoxelAOvar' in wrd.world_defs and not '_VoxelGI' in wrd.world_defs or ((parse_opacity or '_VoxelShadow' in wrd.world_defs) and ('_VoxelAOvar' in wrd.world_defs or '_VoxelGI' in wrd.world_defs)): + #vert.add_out('vec4 wvpposition') + #vert.write('wvpposition = gl_Position;') + vert.add_out('vec4 wvpposition') + vert.write('wvpposition = gl_Position;') # wvpposition.z / wvpposition.w frag.write('float viewz = linearize(gl_FragCoord.z, cameraProj);') frag.write('int clusterI = getClusterI((wvpposition.xy / wvpposition.w) * 0.5 + 0.5, viewz, cameraPlane);') diff --git a/leenkx/blender/lnx/material/mat_utils.py b/leenkx/blender/lnx/material/mat_utils.py index 25f5ac8e..ca9c64a9 100644 --- a/leenkx/blender/lnx/material/mat_utils.py +++ b/leenkx/blender/lnx/material/mat_utils.py @@ -51,7 +51,7 @@ def get_rpasses(material): ar.append('translucent') elif is_transluc(material) and not material.lnx_discard and not material.lnx_blending and rpdat.rp_ss_refraction: ar.append('refraction') - if rpdat.rp_voxels != "Off" and has_voxels: + if rpdat.rp_voxels != "Off" and has_voxels and rpdat.lnx_material_model == 'Full': ar.append('voxel') if rpdat.rp_renderer == 'Forward' and rpdat.rp_depthprepass and not material.lnx_blending and not material.lnx_particle_flag: ar.append('depth') diff --git a/leenkx/blender/lnx/props_renderpath.py b/leenkx/blender/lnx/props_renderpath.py index c90080b3..45952d09 100644 --- a/leenkx/blender/lnx/props_renderpath.py +++ b/leenkx/blender/lnx/props_renderpath.py @@ -347,7 +347,7 @@ class LnxRPListItem(bpy.types.PropertyGroup): name="Max Lights Shadows", description="Max number of rendered shadow maps that can be visible in the screen. Always equal or lower than Max Lights", default='16') rp_shadowmap_atlas: BoolProperty(name="Shadow Map Atlasing", description="Group shadow maps of lights of the same type in the same texture", default=False, update=update_renderpath) rp_shadowmap_atlas_auto: BoolProperty(name="Automatic Atlasing", description="Automatically compute atlas sizes based on max lights and shadow map sizes", default=True, update=update_renderpath) - rp_shadowmap_atlas_single_map: BoolProperty(name="Shadow Map Atlas single map", description="Use a single texture for all different light types.", default=False, update=update_renderpath) + rp_shadowmap_atlas_single_map: BoolProperty(name="Shadow Map Atlas single map", description="Use a single texture for all different light types.", default=True, update=update_renderpath) rp_shadowmap_atlas_lod: BoolProperty(name="Shadow Map Atlas LOD (Experimental)", description="When enabled, the size of the shadow map will be determined on runtime based on the distance of the light to the camera", default=False, update=update_renderpath) rp_shadowmap_transparent: BoolProperty(name="Transparency", description="Enable shadows for transparent objects", default=True, update=update_renderpath) rp_shadowmap_atlas_lod_subdivisions: EnumProperty( From f1d8522f519eb495b0982fef885af6ac917f45ea Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 16 Sep 2026 16:04:32 -0700 Subject: [PATCH 6/9] Bloom Isnan Isinf --- leenkx/Shaders/bloom_pass/downsample_pass.frag.glsl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/leenkx/Shaders/bloom_pass/downsample_pass.frag.glsl b/leenkx/Shaders/bloom_pass/downsample_pass.frag.glsl index 925af66e..44932d2f 100644 --- a/leenkx/Shaders/bloom_pass/downsample_pass.frag.glsl +++ b/leenkx/Shaders/bloom_pass/downsample_pass.frag.glsl @@ -48,6 +48,10 @@ void main() { } if (currentMipLevel == 0) { + if (any(isnan(fragColor.rgb)) || any(isinf(fragColor.rgb))) { + fragColor.rgb = vec3(0.0); + } + // https://catlikecoding.com/unity/tutorials/advanced-rendering/bloom/#3.2 // https://catlikecoding.com/unity/tutorials/advanced-rendering/bloom/#3.4 From af9a259fbb4832efb9c53145f4e51e3baf6b38d5 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 16 Sep 2026 17:36:31 -0700 Subject: [PATCH 7/9] Water Sun Direction --- leenkx/Shaders/water_pass/water_pass.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/leenkx/Shaders/water_pass/water_pass.json b/leenkx/Shaders/water_pass/water_pass.json index 7e884e05..07257b65 100644 --- a/leenkx/Shaders/water_pass/water_pass.json +++ b/leenkx/Shaders/water_pass/water_pass.json @@ -34,7 +34,7 @@ }, { "name": "ld", - "link": "_lightDirection" + "link": "_sunDirection" }, { "name": "invVP", From 0bb4bceb577e4168097942ee6c578a78faec28cf Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 16 Sep 2026 18:12:12 -0700 Subject: [PATCH 8/9] Water Foam Fix --- leenkx/Shaders/water_pass/water_pass.frag.glsl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/leenkx/Shaders/water_pass/water_pass.frag.glsl b/leenkx/Shaders/water_pass/water_pass.frag.glsl index 2c21f25c..efe72a37 100644 --- a/leenkx/Shaders/water_pass/water_pass.frag.glsl +++ b/leenkx/Shaders/water_pass/water_pass.frag.glsl @@ -151,6 +151,7 @@ void main() { } // Displace surface + float geomZ = p.z; // undisplaced depth for foam/fog tests p.z += (sin(p.x * 10.0 / waterDisplace + speed) * cos(p.y * 10.0 / waterDisplace + speed) + sin(p.x * 20.0 / waterDisplace + speed * 1.3) * cos(p.y * 20.0 / waterDisplace + speed * 1.3) * 0.5) / 50.0 * waterDisplace; @@ -229,13 +230,13 @@ void main() { float specAmount = pow(max(dot(n2, h), 0.0), 200.0) * (200.0 + 8.0) / (PI * 8.0); fragColor.rgb += specAmount * (isSky ? 0.3 : 1.0) * horizonFactor; // Depth fog - blend toward waterColor with depth, faded at horizon - float depthFog = clamp(-(p.z - waterLevel) * waterDensity, 0.0, 0.9); + float depthFog = clamp(-(geomZ - waterLevel) * waterDensity, 0.0, 0.9); fragColor.rgb = mix(fragColor.rgb, waterColor, depthFog * horizonFactor); // Alpha fades smoothly at horizon instead of hard cut - fragColor.a = isSky ? horizonFactor : clamp(abs(p.z - waterLevel) * 5.0, 0.0, 1.0); + fragColor.a = isSky ? horizonFactor : clamp(abs(geomZ - waterLevel) * 5.0, 0.0, 1.0); // Foam - based on actual geometry depth below water surface - float fd = isSky ? 1.0 : abs(p.z - waterLevel); + float fd = isSky ? 1.0 : abs(geomZ - waterLevel); if (fd < 0.1) { // Based on foam by Owen Deery // http://fire-face.com/personal/water From fca51c7e61fdfd577ebc893538e76148a60ec91a Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 16 Sep 2026 22:44:16 -0700 Subject: [PATCH 9/9] Water Level/Reflectopm --- leenkx/Shaders/water_pass/water_pass.frag.glsl | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/leenkx/Shaders/water_pass/water_pass.frag.glsl b/leenkx/Shaders/water_pass/water_pass.frag.glsl index efe72a37..bce540ca 100644 --- a/leenkx/Shaders/water_pass/water_pass.frag.glsl +++ b/leenkx/Shaders/water_pass/water_pass.frag.glsl @@ -228,12 +228,16 @@ void main() { // Blinn-Phong specular using half-vector, faded at horizon vec3 h = normalize(v + ld); float specAmount = pow(max(dot(n2, h), 0.0), 200.0) * (200.0 + 8.0) / (PI * 8.0); - fragColor.rgb += specAmount * (isSky ? 0.3 : 1.0) * horizonFactor; + fragColor.rgb += specAmount * (isSky ? 0.3 : 1.0); // Depth fog - blend toward waterColor with depth, faded at horizon float depthFog = clamp(-(geomZ - waterLevel) * waterDensity, 0.0, 0.9); fragColor.rgb = mix(fragColor.rgb, waterColor, depthFog * horizonFactor); // Alpha fades smoothly at horizon instead of hard cut - fragColor.a = isSky ? horizonFactor : clamp(abs(geomZ - waterLevel) * 5.0, 0.0, 1.0); + // Skydome sits 3.5 below the camera (_skydomeMatrix), so its horizon + // appears where the ray z reaches -3.5 / domeRadius + float farPlane = cameraProj.y / (1.0 - cameraProj.x); + float horizonFade = clamp((-3.5 / (farPlane * 0.95) - vray.z) * 20.0, 0.0, 1.0); + fragColor.a = isSky ? horizonFade : clamp(abs(geomZ - waterLevel) * 5.0, 0.0, 1.0); // Foam - based on actual geometry depth below water surface float fd = isSky ? 1.0 : abs(geomZ - waterLevel);