From abe17870ce7aeb8334112de2b777695e47a21ea0 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Mon, 7 Apr 2025 14:38:30 +0000 Subject: [PATCH 001/136] Update leenkx/Shaders/std/conetrace.glsl --- leenkx/Shaders/std/conetrace.glsl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/leenkx/Shaders/std/conetrace.glsl b/leenkx/Shaders/std/conetrace.glsl index 4e7ddb6..295c8b6 100644 --- a/leenkx/Shaders/std/conetrace.glsl +++ b/leenkx/Shaders/std/conetrace.glsl @@ -166,7 +166,7 @@ vec4 traceDiffuse(const vec3 origin, const vec3 normal, const sampler3D voxels, } vec4 traceSpecular(const vec3 origin, const vec3 normal, const sampler3D voxels, const sampler3D voxelsSDF, const vec3 viewDir, const float roughness, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel, const vec2 velocity) { - vec3 specularDir = reflect(-viewDir, normal); + vec3 specularDir = reflect(normalize(-viewDir), normal); vec3 P = origin + specularDir * ((BayerMatrix8[int(pixel.x + velocity.x) % 8][int(pixel.y + velocity.y) % 8] - 0.5)) * voxelgiStep; vec4 amount = traceCone(voxels, voxelsSDF, P, normal, specularDir, 0, true, roughness, voxelgiStep, clipmaps); @@ -176,9 +176,9 @@ vec4 traceSpecular(const vec3 origin, const vec3 normal, const sampler3D voxels, return amount * voxelgiOcc; } -vec4 traceRefraction(const vec3 origin, const vec3 normal, sampler3D voxels, sampler3D voxelsSDF, const vec3 viewDir, const float ior, const float roughness, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel, const vec2 velocity) { - const float transmittance = 1.0; - vec3 refractionDir = refract(-viewDir, normal, 1.0 / ior); +vec4 traceRefraction(const vec3 origin, const vec3 normal, sampler3D voxels, sampler3D voxelsSDF, const vec3 viewDir, const float ior, const float roughness, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel, const vec2 velocity, const float opacity) { + const float transmittance = 1.0 - opacity; + vec3 refractionDir = refract(normalize(-viewDir), normal, 1.0 / ior); vec3 P = origin + refractionDir * (BayerMatrix8[int(pixel.x + velocity.x) % 8][int(pixel.y + velocity.y) % 8] - 0.5) * voxelgiStep; vec4 amount = transmittance * traceCone(voxels, voxelsSDF, P, normal, refractionDir, 0, true, roughness, voxelgiStep, clipmaps); @@ -328,8 +328,8 @@ float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const v } -float traceShadow(const vec3 origin, const vec3 normal, const sampler3D voxels, const sampler3D voxelsSDF, const vec3 dir, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel) { - vec3 P = origin + dir * (BayerMatrix8[int(pixel.x) % 8][int(pixel.y) % 8] - 0.5) * voxelgiStep; +float traceShadow(const vec3 origin, const vec3 normal, const sampler3D voxels, const sampler3D voxelsSDF, const vec3 dir, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel, const vec2 velocity) { + vec3 P = origin + dir * (BayerMatrix8[int(pixel.x + velocity.x) % 8][int(pixel.y + velocity.y) % 8] - 0.5) * voxelgiStep; float amount = traceConeShadow(voxels, voxelsSDF, P, normal, dir, DIFFUSE_CONE_APERTURE, voxelgiStep, clipmaps); amount = clamp(amount, 0.0, 1.0); return amount * voxelgiOcc; From 5153cff7906d1d1e46d2b73522391751bd26e797 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Mon, 7 Apr 2025 14:41:53 +0000 Subject: [PATCH 002/136] Update leenkx/Shaders/std/shadows.glsl --- leenkx/Shaders/std/shadows.glsl | 36 +-------------------------------- 1 file changed, 1 insertion(+), 35 deletions(-) diff --git a/leenkx/Shaders/std/shadows.glsl b/leenkx/Shaders/std/shadows.glsl index d994eff..4944d3b 100644 --- a/leenkx/Shaders/std/shadows.glsl +++ b/leenkx/Shaders/std/shadows.glsl @@ -87,40 +87,6 @@ float lpToDepth(vec3 lp, const vec2 lightProj) { return zcomp * 0.5 + 0.5; } -#ifndef _ShadowMapAtlas -vec3 PCFCube(samplerCubeShadow shadowMapCube, samplerCube shadowMapCubeTransparent, vec3 lp, vec3 ml, float bias, vec2 lightProj, vec3 n, const bool transparent) { - const float s = shadowmapCubePcfSize; - float compare = lpToDepth(lp, lightProj) - bias * 1.5; - ml = ml + n * bias * 20; - #ifdef _InvY - ml.y = -ml.y; - #endif - - float shadowFactor = 0.0; - shadowFactor = texture(shadowMapCube, vec4(ml, compare)); - shadowFactor += texture(shadowMapCube, vec4(ml + vec3(s, s, s), compare)); - shadowFactor += texture(shadowMapCube, vec4(ml + vec3(-s, s, s), compare)); - shadowFactor += texture(shadowMapCube, vec4(ml + vec3(s, -s, s), compare)); - shadowFactor += texture(shadowMapCube, vec4(ml + vec3(s, s, -s), compare)); - shadowFactor += texture(shadowMapCube, vec4(ml + vec3(-s, -s, s), compare)); - shadowFactor += texture(shadowMapCube, vec4(ml + vec3(s, -s, -s), compare)); - shadowFactor += texture(shadowMapCube, vec4(ml + vec3(-s, s, -s), compare)); - shadowFactor += texture(shadowMapCube, vec4(ml + vec3(-s, -s, -s), compare)); - shadowFactor /= 9.0; - - vec3 result = vec3(shadowFactor); - - if (transparent == false) { - vec4 shadowmap_transparent = texture(shadowMapCubeTransparent, ml); - if (shadowmap_transparent.a < compare) - result *= shadowmap_transparent.rgb; - } - - return result; -} -#endif - -#ifdef _ShadowMapAtlas vec3 PCFCube(samplerCubeShadow shadowMapCube, samplerCube shadowMapCubeTransparent, const vec3 lp, vec3 ml, const float bias, const vec2 lightProj, const vec3 n, const bool transparent) { const float s = shadowmapCubePcfSize; // TODO: incorrect... float compare = lpToDepth(lp, lightProj) - bias * 1.5; @@ -149,7 +115,7 @@ vec3 PCFCube(samplerCubeShadow shadowMapCube, samplerCube shadowMapCubeTranspare return result; } - +#ifdef _ShadowMapAtlas // transform "out-of-bounds" coordinates to the correct face/coordinate system // https://www.khronos.org/opengl/wiki/File:CubeMapAxes.png vec2 transformOffsetedUV(const int faceIndex, out int newFaceIndex, vec2 uv) { From 5303ad3ac6974a0ea4774d9b5e3d459071f0333f Mon Sep 17 00:00:00 2001 From: Onek8 Date: Mon, 7 Apr 2025 14:44:14 +0000 Subject: [PATCH 003/136] Update leenkx/Shaders/ssrefr_pass/ssrefr_pass.frag.glsl --- .../Shaders/ssrefr_pass/ssrefr_pass.frag.glsl | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/leenkx/Shaders/ssrefr_pass/ssrefr_pass.frag.glsl b/leenkx/Shaders/ssrefr_pass/ssrefr_pass.frag.glsl index ed70110..bdedd67 100644 --- a/leenkx/Shaders/ssrefr_pass/ssrefr_pass.frag.glsl +++ b/leenkx/Shaders/ssrefr_pass/ssrefr_pass.frag.glsl @@ -57,14 +57,17 @@ vec4 binarySearch(vec3 dir) { } vec4 rayCast(vec3 dir) { - float ddepth; - dir *= ss_refractionRayStep; - for (int i = 0; i < maxSteps; i++) { - hitCoord += dir; - ddepth = getDeltaDepth(hitCoord); - if (ddepth > 0.0) return binarySearch(dir); - } - return vec4(texCoord, 0.0, 1.0); + float ddepth; + dir *= ss_refractionRayStep; + for (int i = 0; i < maxSteps; i++) { + hitCoord += dir; + ddepth = getDeltaDepth(hitCoord); + if (ddepth > 0.0) + return binarySearch(dir); + } + // No hit — fallback to projecting the ray to UV space + vec2 fallbackUV = getProjectedCoord(hitCoord); + return vec4(fallbackUV, 0.0, 0.5); // We set .w lower to indicate fallback } void main() { @@ -74,7 +77,7 @@ void main() { float ior = gr.x; float opac = gr.y; float d = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0; - if (d == 0.0 || d == 1.0 || opac == 1.0 || ior == 1.0) { + if (d == 0.0 || opac == 1.0 || ior == 1.0) { fragColor.rgb = textureLod(tex1, texCoord, 0.0).rgb; return; } From bc4a31d415a067808871c74ea627a4f42d84f246 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Mon, 7 Apr 2025 14:47:58 +0000 Subject: [PATCH 004/136] Update leenkx/Shaders/voxel_resolve_ao/voxel_resolve_ao.comp.glsl --- leenkx/Shaders/voxel_resolve_ao/voxel_resolve_ao.comp.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/leenkx/Shaders/voxel_resolve_ao/voxel_resolve_ao.comp.glsl b/leenkx/Shaders/voxel_resolve_ao/voxel_resolve_ao.comp.glsl index 6abf9d1..9c22bdb 100644 --- a/leenkx/Shaders/voxel_resolve_ao/voxel_resolve_ao.comp.glsl +++ b/leenkx/Shaders/voxel_resolve_ao/voxel_resolve_ao.comp.glsl @@ -33,7 +33,7 @@ layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in; uniform sampler3D voxels; uniform sampler2D gbufferD; uniform sampler2D gbuffer0; -uniform layout(r8) image2D voxels_ao; +uniform layout(r16) image2D voxels_ao; uniform float clipmaps[voxelgiClipmapCount * 10]; uniform mat4 InvVP; From af2850e20c012561eb6d208cce870779299a2dbf Mon Sep 17 00:00:00 2001 From: Onek8 Date: Mon, 7 Apr 2025 14:49:37 +0000 Subject: [PATCH 005/136] Update leenkx/Shaders/voxel_resolve_diffuse/voxel_resolve_diffuse.comp.glsl --- .../voxel_resolve_diffuse/voxel_resolve_diffuse.comp.glsl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/leenkx/Shaders/voxel_resolve_diffuse/voxel_resolve_diffuse.comp.glsl b/leenkx/Shaders/voxel_resolve_diffuse/voxel_resolve_diffuse.comp.glsl index 4d19a88..711e4af 100644 --- a/leenkx/Shaders/voxel_resolve_diffuse/voxel_resolve_diffuse.comp.glsl +++ b/leenkx/Shaders/voxel_resolve_diffuse/voxel_resolve_diffuse.comp.glsl @@ -33,7 +33,7 @@ layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in; uniform sampler3D voxels; uniform sampler2D gbufferD; uniform sampler2D gbuffer0; -uniform layout(rgba8) image2D voxels_diffuse; +uniform layout(rgba16) image2D voxels_diffuse; uniform float clipmaps[voxelgiClipmapCount * 10]; uniform mat4 InvVP; @@ -46,7 +46,7 @@ void main() { const vec2 pixel = gl_GlobalInvocationID.xy; vec2 uv = (pixel + 0.5) / postprocess_resolution; #ifdef _InvY - uv.y = 1.0 - uv.y + uv.y = 1.0 - uv.y; #endif float depth = textureLod(gbufferD, uv, 0.0).r * 2.0 - 1.0; From ee73823206c20bc889aafe3332f43f00980b2758 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Mon, 7 Apr 2025 15:17:43 +0000 Subject: [PATCH 006/136] Update leenkx/Shaders/voxel_resolve_specular/voxel_resolve_specular.comp.glsl --- .../voxel_resolve_specular/voxel_resolve_specular.comp.glsl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/leenkx/Shaders/voxel_resolve_specular/voxel_resolve_specular.comp.glsl b/leenkx/Shaders/voxel_resolve_specular/voxel_resolve_specular.comp.glsl index 771b7a0..6fd662d 100644 --- a/leenkx/Shaders/voxel_resolve_specular/voxel_resolve_specular.comp.glsl +++ b/leenkx/Shaders/voxel_resolve_specular/voxel_resolve_specular.comp.glsl @@ -34,7 +34,7 @@ uniform sampler2D gbufferD; uniform sampler2D gbuffer0; uniform sampler3D voxels; uniform sampler3D voxelsSDF; -uniform layout(rgba8) image2D voxels_specular; +uniform layout(rgba16) image2D voxels_specular; uniform float clipmaps[voxelgiClipmapCount * 10]; uniform mat4 InvVP; @@ -71,7 +71,7 @@ void main() { vec2 velocity = -textureLod(sveloc, uv, 0.0).rg; - vec3 color = traceSpecular(P, n, voxels, voxelsSDF, normalize(eye - P), g0.z, clipmaps, pixel, velocity).rgb; + vec3 color = traceSpecular(P, n, voxels, voxelsSDF, normalize(eye - P), g0.z * g0.z, clipmaps, pixel, velocity).rgb; imageStore(voxels_specular, ivec2(pixel), vec4(color, 1.0)); } From ae63b252c60be7085cc638c3479bd4ebbcda43e0 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Mon, 7 Apr 2025 15:19:03 +0000 Subject: [PATCH 007/136] Update leenkx/Shaders/voxel_sdf_jumpflood/voxel_sdf_jumpflood.comp.glsl --- .../Shaders/voxel_sdf_jumpflood/voxel_sdf_jumpflood.comp.glsl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/leenkx/Shaders/voxel_sdf_jumpflood/voxel_sdf_jumpflood.comp.glsl b/leenkx/Shaders/voxel_sdf_jumpflood/voxel_sdf_jumpflood.comp.glsl index d224df6..5e6a0ea 100644 --- a/leenkx/Shaders/voxel_sdf_jumpflood/voxel_sdf_jumpflood.comp.glsl +++ b/leenkx/Shaders/voxel_sdf_jumpflood/voxel_sdf_jumpflood.comp.glsl @@ -23,8 +23,8 @@ THE SOFTWARE. #include "compiled.inc" -uniform layout(r16) image3D input_sdf; -uniform layout(r16) image3D output_sdf; +uniform layout(r8) image3D input_sdf; +uniform layout(r8) image3D output_sdf; uniform float jump_size; uniform int clipmapLevel; From 8d4ac7251ace68bc96f4742fdab5a86f0a09a492 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Mon, 7 Apr 2025 15:22:49 +0000 Subject: [PATCH 008/136] Update leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl --- .../Shaders/voxel_temporal/voxel_temporal.comp.glsl | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl b/leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl index c62ca70..6c70b3b 100644 --- a/leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl +++ b/leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl @@ -46,15 +46,15 @@ uniform layout(r32ui) uimage3D voxels; uniform layout(r32ui) uimage3D voxelsLight; uniform layout(rgba8) image3D voxelsB; uniform layout(rgba8) image3D voxelsOut; -uniform layout(r16) image3D SDF; +uniform layout(r8) image3D SDF; #else #ifdef _VoxelAOvar #ifdef _VoxelShadow -uniform layout(r16) image3D SDF; +uniform layout(r8) image3D SDF; #endif uniform layout(r32ui) uimage3D voxels; -uniform layout(r16) image3D voxelsB; -uniform layout(r16) image3D voxelsOut; +uniform layout(r8) image3D voxelsB; +uniform layout(r8) image3D voxelsOut; #endif #endif @@ -80,7 +80,6 @@ void main() { light.r = float(imageLoad(voxelsLight, src)) / 255; light.g = float(imageLoad(voxelsLight, src + ivec3(0, 0, voxelgiResolution.x))) / 255; light.b = float(imageLoad(voxelsLight, src + ivec3(0, 0, voxelgiResolution.x * 2))) / 255; - light /= 3; #endif for (int i = 0; i < 6 + DIFFUSE_CONE_COUNT; i++) @@ -125,7 +124,7 @@ void main() { envl.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 10))) / 255; envl.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 11))) / 255; envl /= 3; - envl *= 100; + //clipmap to world vec3 wposition = (gl_GlobalInvocationID.xyz + 0.5) / voxelgiResolution.x; @@ -137,7 +136,7 @@ void main() { radiance = basecol; vec4 trace = traceDiffuse(wposition, wnormal, voxelsSampler, clipmaps); vec3 indirect = trace.rgb + envl.rgb * (1.0 - trace.a); - radiance.rgb *= light + indirect; + radiance.rgb *= light / PI + indirect; radiance.rgb += emission.rgb; #else From 6a25b3c5d7d5750a3c7ad4aa98338177f2f7299e Mon Sep 17 00:00:00 2001 From: Onek8 Date: Mon, 7 Apr 2025 15:28:46 +0000 Subject: [PATCH 009/136] Update leenkx/Shaders/deferred_light/deferred_light.frag.glsl --- leenkx/Shaders/deferred_light/deferred_light.frag.glsl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/leenkx/Shaders/deferred_light/deferred_light.frag.glsl b/leenkx/Shaders/deferred_light/deferred_light.frag.glsl index 61f94c1..a4700dc 100644 --- a/leenkx/Shaders/deferred_light/deferred_light.frag.glsl +++ b/leenkx/Shaders/deferred_light/deferred_light.frag.glsl @@ -20,7 +20,7 @@ uniform sampler2D gbuffer0; uniform sampler2D gbuffer1; #ifdef _gbuffer2 - uniform sampler2D gbuffer2; + //!uniform sampler2D gbuffer2; #endif #ifdef _EmissionShaded uniform sampler2D gbufferEmission; @@ -286,7 +286,7 @@ void main() { #ifdef _VoxelGI vec4 indirect_diffuse = textureLod(voxels_diffuse, texCoord, 0.0); - fragColor.rgb = (indirect_diffuse.rgb * albedo + envl.rgb * (1.0 - indirect_diffuse.a)) * voxelgiDiff; + fragColor.rgb = (indirect_diffuse.rgb + envl.rgb * (1.0 - indirect_diffuse.a)) * albedo * voxelgiDiff; if(roughness < 1.0 && occspec.y > 0.0) fragColor.rgb += textureLod(voxels_specular, texCoord, 0.0).rgb * occspec.y * voxelgiRefl; #endif @@ -380,7 +380,7 @@ void main() { #endif #ifdef _VoxelShadow - svisibility *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, sunDir, clipmaps, gl_FragCoord.xy).r) * voxelgiShad; + svisibility *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, sunDir, clipmaps, gl_FragCoord.xy, g2.rg).r) * voxelgiShad; #endif #ifdef _SSRS From 001be2f8da2c28e0396e6a6421c6f4a7ffd646a3 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Mon, 7 Apr 2025 15:35:22 +0000 Subject: [PATCH 010/136] Update leenkx/Sources/leenkx/renderpath/Inc.hx --- leenkx/Sources/leenkx/renderpath/Inc.hx | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/leenkx/Sources/leenkx/renderpath/Inc.hx b/leenkx/Sources/leenkx/renderpath/Inc.hx index 345a25b..69087f3 100644 --- a/leenkx/Sources/leenkx/renderpath/Inc.hx +++ b/leenkx/Sources/leenkx/renderpath/Inc.hx @@ -77,6 +77,9 @@ class Inc { #if (rp_voxels == "Voxel GI") static var voxel_sh5:kha.compute.Shader = null; static var voxel_ta5:kha.compute.TextureUnit; + static var voxel_te5:kha.compute.TextureUnit; + static var voxel_tf5:kha.compute.TextureUnit; + static var voxel_tg5:kha.compute.TextureUnit; static var voxel_ca5:kha.compute.ConstantLocation; static var voxel_cb5:kha.compute.ConstantLocation; static var voxel_cc5:kha.compute.ConstantLocation; @@ -677,7 +680,7 @@ class Inc { } else { if (t.name == "voxelsSDF" || t.name == "voxelsSDFtmp") { - t.format = "R16"; + t.format = "R8"; t.width = res; t.height = res * Main.voxelgiClipmapCount; t.depth = res; @@ -686,7 +689,7 @@ class Inc { #if (rp_voxels == "Voxel AO") { if (t.name == "voxelsOut" || t.name == "voxelsOutB") { - t.format = "R16"; + t.format = "R8"; t.width = res * (6 + 16); t.height = res * Main.voxelgiClipmapCount; t.depth = res; @@ -892,7 +895,9 @@ class Inc { { voxel_sh5 = path.getComputeShader("voxel_light"); voxel_ta5 = voxel_sh5.getTextureUnit("voxelsLight"); - + voxel_te5 = voxel_sh5.getTextureUnit("voxels"); + voxel_tf5 = voxel_sh5.getTextureUnit("voxelsSampler"); + voxel_tg5 = voxel_sh5.getTextureUnit("voxelsSDFSampler"); voxel_ca5 = voxel_sh5.getConstantLocation("clipmaps"); voxel_cb5 = voxel_sh5.getConstantLocation("clipmapLevel"); @@ -1213,7 +1218,7 @@ class Inc { kha.compute.Compute.setSampledTexture(voxel_td4, rts.get("voxelsSDF").image); kha.compute.Compute.setTexture(voxel_te4, rts.get("voxels_specular").image, kha.compute.Access.Write); - //kha.compute.Compute.setSampledTexture(voxel_tf4, rts.get("gbuffer2").image); + kha.compute.Compute.setSampledTexture(voxel_tf4, rts.get("gbuffer2").image); var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); for (i in 0...Main.voxelgiClipmapCount) { @@ -1288,7 +1293,9 @@ class Inc { kha.compute.Compute.setShader(voxel_sh5); kha.compute.Compute.setTexture(voxel_ta5, rts.get("voxelsLight").image, kha.compute.Access.Write); - + kha.compute.Compute.setTexture(voxel_te5, rts.get("voxels").image, kha.compute.Access.Read); + kha.compute.Compute.setSampledTexture(voxel_tf5, rts.get("voxelsOut").image); + kha.compute.Compute.setSampledTexture(voxel_tg5, rts.get("voxelsSDF").image); var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); for (i in 0...Main.voxelgiClipmapCount) { fa[i * 10] = clipmaps[i].voxelSize; From 7ae3bbe496ddf4104de54dac6aff0c211ebd6c37 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Mon, 7 Apr 2025 15:39:38 +0000 Subject: [PATCH 011/136] Update leenkx/Sources/leenkx/renderpath/RenderPathDeferred.hx --- .../Sources/leenkx/renderpath/RenderPathDeferred.hx | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/leenkx/Sources/leenkx/renderpath/RenderPathDeferred.hx b/leenkx/Sources/leenkx/renderpath/RenderPathDeferred.hx index 0f9a14c..75a519e 100644 --- a/leenkx/Sources/leenkx/renderpath/RenderPathDeferred.hx +++ b/leenkx/Sources/leenkx/renderpath/RenderPathDeferred.hx @@ -368,7 +368,7 @@ class RenderPathDeferred { t.scale = Inc.getSuperSampling(); path.createRenderTarget(t); - // holds background depth + // holds background color var t = new RenderTargetRaw(); t.name = "refr"; t.width = 0; @@ -473,6 +473,13 @@ class RenderPathDeferred { } #end + #if rp_ssrefr + { + path.setTarget("gbuffer_refraction"); + path.clearTarget(0xffffff00); + } + #end + RenderPathCreator.setTargetMeshes(); #if rp_dynres @@ -837,7 +844,7 @@ class RenderPathDeferred { { path.bindTarget("voxelsOut", "voxels"); path.bindTarget("voxelsSDF", "voxelsSDF"); - path.bindTarget("gbuffer2", "sveloc"); + path.bindTarget("gbuffer2", "gbuffer2"); } #end From 5244b1b3e8e07b10a2de61b8d2a085cf9b524bd4 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Mon, 7 Apr 2025 15:41:41 +0000 Subject: [PATCH 012/136] Update leenkx/Sources/leenkx/renderpath/RenderPathForward.hx --- leenkx/Sources/leenkx/renderpath/RenderPathForward.hx | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/leenkx/Sources/leenkx/renderpath/RenderPathForward.hx b/leenkx/Sources/leenkx/renderpath/RenderPathForward.hx index 01e19ea..59b6183 100644 --- a/leenkx/Sources/leenkx/renderpath/RenderPathForward.hx +++ b/leenkx/Sources/leenkx/renderpath/RenderPathForward.hx @@ -522,6 +522,17 @@ class RenderPathForward { path.setTarget("lbuffer0", ["lbuffer1", "gbuffer_refraction"]); + #if rp_shadowmap + { + #if lnx_shadowmap_atlas + Inc.bindShadowMapAtlas(); + #else + Inc.bindShadowMap(); + #end + } + #end + + #if (rp_voxels != "Off") path.bindTarget("voxelsOut", "voxels"); path.bindTarget("voxelsSDF", "voxelsSDF"); From 519039b8b604b462285f02b024f060fa40eeb049 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Mon, 7 Apr 2025 15:45:04 +0000 Subject: [PATCH 013/136] Update leenkx/Shaders/std/light.glsl --- leenkx/Shaders/std/light.glsl | 483 +++++++++++++++++----------------- 1 file changed, 244 insertions(+), 239 deletions(-) diff --git a/leenkx/Shaders/std/light.glsl b/leenkx/Shaders/std/light.glsl index 9e1182e..e5e2416 100644 --- a/leenkx/Shaders/std/light.glsl +++ b/leenkx/Shaders/std/light.glsl @@ -1,239 +1,244 @@ -#ifndef _LIGHT_GLSL_ -#define _LIGHT_GLSL_ - -#include "compiled.inc" -#include "std/brdf.glsl" -#include "std/math.glsl" -#ifdef _ShadowMap -#include "std/shadows.glsl" -#endif -#ifdef _VoxelShadow -#include "std/conetrace.glsl" -//!uniform sampler2D voxels_shadows; -#endif -#ifdef _LTC -#include "std/ltc.glsl" -#endif -#ifdef _LightIES -#include "std/ies.glsl" -#endif -#ifdef _SSRS -#include "std/ssrs.glsl" -#endif -#ifdef _Spot -#include "std/light_common.glsl" -#endif - -#ifdef _ShadowMap - #ifdef _SinglePoint - #ifdef _Spot - #ifndef _LTC - uniform sampler2DShadow shadowMapSpot[1]; - uniform sampler2D shadowMapSpotTransparent[1]; - uniform mat4 LWVPSpot[1]; - #endif - #else - uniform samplerCubeShadow shadowMapPoint[1]; - uniform samplerCube shadowMapPointTransparent[1]; - uniform vec2 lightProj; - #endif - #endif - #ifdef _Clusters - #ifdef _SingleAtlas - //!uniform sampler2DShadow shadowMapAtlas; - //!uniform sampler2D shadowMapAtlasTransparent; - #endif - uniform vec2 lightProj; - #ifdef _ShadowMapAtlas - #ifndef _SingleAtlas - uniform sampler2DShadow shadowMapAtlasPoint; - uniform sampler2D shadowMapAtlasPointTransparent; - #endif - #else - uniform samplerCubeShadow shadowMapPoint[4]; - uniform samplerCube shadowMapPointTransparent[4]; - #endif - #ifdef _Spot - #ifdef _ShadowMapAtlas - #ifndef _SingleAtlas - uniform sampler2DShadow shadowMapAtlasSpot; - uniform sampler2D shadowMapAtlasSpotTransparent; - #endif - #else - uniform sampler2DShadow shadowMapSpot[4]; - uniform sampler2D shadowMapSpotTransparent[4]; - #endif - uniform mat4 LWVPSpotArray[maxLightsCluster]; - #endif - #endif -#endif - -#ifdef _LTC -uniform vec3 lightArea0; -uniform vec3 lightArea1; -uniform vec3 lightArea2; -uniform vec3 lightArea3; -uniform sampler2D sltcMat; -uniform sampler2D sltcMag; -#ifdef _ShadowMap -#ifndef _Spot - #ifdef _SinglePoint - uniform sampler2DShadow shadowMapSpot[1]; - uniform sampler2D shadowMapSpotTransparent[1]; - uniform mat4 LWVPSpot[1]; - #endif - #ifdef _Clusters - uniform sampler2DShadow shadowMapSpot[maxLightsCluster]; - uniform sampler2D shadowMapSpotTransparent[maxLightsCluster]; - uniform mat4 LWVPSpotArray[maxLightsCluster]; - #endif - #endif -#endif -#endif - -vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, const vec3 lp, const vec3 lightCol, - const vec3 albedo, const float rough, const float spec, const vec3 f0 - #ifdef _ShadowMap - , int index, float bias, bool receiveShadow, bool transparent - #endif - #ifdef _Spot - , const bool isSpot, const float spotSize, float spotBlend, vec3 spotDir, vec2 scale, vec3 right - #endif - #ifdef _VoxelShadow - , sampler3D voxels, sampler3D voxelsSDF, float clipmaps[10 * voxelgiClipmapCount] - #endif - #ifdef _MicroShadowing - , float occ - #endif - #ifdef _SSRS - , sampler2D gbufferD, mat4 invVP, vec3 eye - #endif - ) { - vec3 ld = lp - p; - vec3 l = normalize(ld); - vec3 h = normalize(v + l); - float dotNH = max(0.0, dot(n, h)); - float dotVH = max(0.0, dot(v, h)); - float dotNL = max(0.0, dot(n, l)); - - #ifdef _LTC - float theta = acos(dotNV); - vec2 tuv = vec2(rough, theta / (0.5 * PI)); - tuv = tuv * LUT_SCALE + LUT_BIAS; - vec4 t = textureLod(sltcMat, tuv, 0.0); - mat3 invM = mat3( - vec3(1.0, 0.0, t.y), - vec3(0.0, t.z, 0.0), - vec3(t.w, 0.0, t.x)); - float ltcspec = ltcEvaluate(n, v, dotNV, p, invM, lightArea0, lightArea1, lightArea2, lightArea3); - ltcspec *= textureLod(sltcMag, tuv, 0.0).a; - float ltcdiff = ltcEvaluate(n, v, dotNV, p, mat3(1.0), lightArea0, lightArea1, lightArea2, lightArea3); - vec3 direct = albedo * ltcdiff + ltcspec * spec * 0.05; - #else - vec3 direct = lambertDiffuseBRDF(albedo, dotNL) + - specularBRDF(f0, rough, dotNL, dotNH, dotNV, dotVH) * spec; - #endif - - direct *= attenuate(distance(p, lp)); - direct *= lightCol; - - #ifdef _MicroShadowing - direct *= clamp(dotNL + 2.0 * occ * occ - 1.0, 0.0, 1.0); - #endif - - #ifdef _SSRS - direct *= traceShadowSS(l, p, gbufferD, invVP, eye); - #endif - - #ifdef _VoxelShadow - direct *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, l, clipmaps, gl_FragCoord.xy).r) * voxelgiShad; - #endif - - #ifdef _LTC - #ifdef _ShadowMap - if (receiveShadow) { - #ifdef _SinglePoint - vec4 lPos = LWVPSpotArray[0] * vec4(p + n * bias * 10, 1.0); - direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent); - #endif - #ifdef _Clusters - vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0); - if (index == 0) direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent); - else if (index == 1) direct *= shadowTest(shadowMapSpot[1], shadowMapSpotTransparent[1], lPos.xyz / lPos.w, bias, transparent); - else if (index == 2) direct *= shadowTest(shadowMapSpot[2], shadowMapSpotTransparent[2], lPos.xyz / lPos.w, bias, transparent); - else if (index == 3) direct *= shadowTest(shadowMapSpot[3], shadowMapSpotTransparent[3], lPos.xyz / lPos.w, bias, transparent); - #endif - } - #endif - return direct; - #endif - - #ifdef _Spot - if (isSpot) { - direct *= spotlightMask(l, spotDir, right, scale, spotSize, spotBlend); - - #ifdef _ShadowMap - if (receiveShadow) { - #ifdef _SinglePoint - vec4 lPos = LWVPSpot[0] * vec4(p + n * bias * 10, 1.0); - direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent); - #endif - #ifdef _Clusters - vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0); - #ifdef _ShadowMapAtlas - direct *= shadowTest( - #ifndef _SingleAtlas - shadowMapAtlasSpot, shadowMapAtlasSpotTransparent - #else - shadowMapAtlas, shadowMapAtlasTransparent - #endif - , lPos.xyz / lPos.w, bias, transparent - ); - #else - if (index == 0) direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent); - else if (index == 1) direct *= shadowTest(shadowMapSpot[1], shadowMapSpotTransparent[1], lPos.xyz / lPos.w, bias, transparent); - else if (index == 2) direct *= shadowTest(shadowMapSpot[2], shadowMapSpotTransparent[2], lPos.xyz / lPos.w, bias, transparent); - else if (index == 3) direct *= shadowTest(shadowMapSpot[3], shadowMapSpotTransparent[3], lPos.xyz / lPos.w, bias, transparent); - #endif - #endif - } - #endif - return direct; - } - #endif - - #ifdef _LightIES - direct *= iesAttenuation(-l); - #endif - - #ifdef _ShadowMap - if (receiveShadow) { - #ifdef _SinglePoint - #ifndef _Spot - direct *= PCFCube(shadowMapPoint[0], shadowMapPointTransparent[0], ld, -l, bias, lightProj, n, transparent); - #endif - #endif - #ifdef _Clusters - #ifdef _ShadowMapAtlas - direct *= PCFFakeCube( - #ifndef _SingleAtlas - shadowMapAtlasPoint, shadowMapAtlasPointTransparent - #else - shadowMapAtlas, shadowMapAtlasTransparent - #endif - , ld, -l, bias, lightProj, n, index, transparent - ); - #else - if (index == 0) direct *= PCFCube(shadowMapPoint[0], shadowMapPointTransparent[0], ld, -l, bias, lightProj, n, transparent); - else if (index == 1) direct *= PCFCube(shadowMapPoint[1], shadowMapPointTransparent[1], ld, -l, bias, lightProj, n, transparent); - else if (index == 2) direct *= PCFCube(shadowMapPoint[2], shadowMapPointTransparent[2], ld, -l, bias, lightProj, n, transparent); - else if (index == 3) direct *= PCFCube(shadowMapPoint[3], shadowMapPointTransparent[3], ld, -l, bias, lightProj, n, transparent); - #endif - #endif - } - #endif - - return direct; -} - -#endif +#ifndef _LIGHT_GLSL_ +#define _LIGHT_GLSL_ + +#include "compiled.inc" +#include "std/brdf.glsl" +#include "std/math.glsl" +#ifdef _ShadowMap +#include "std/shadows.glsl" +#endif +#ifdef _VoxelShadow +#include "std/conetrace.glsl" +uniform sampler2D gbuffer2; +#else +#ifdef _VoxelGI +uniform sampler2D gbuffer2; +#endif +#endif +#ifdef _LTC +#include "std/ltc.glsl" +#endif +#ifdef _LightIES +#include "std/ies.glsl" +#endif +#ifdef _SSRS +#include "std/ssrs.glsl" +#endif +#ifdef _Spot +#include "std/light_common.glsl" +#endif + +#ifdef _ShadowMap + #ifdef _SinglePoint + #ifdef _Spot + #ifndef _LTC + uniform sampler2DShadow shadowMapSpot[1]; + uniform sampler2D shadowMapSpotTransparent[1]; + uniform mat4 LWVPSpot[1]; + #endif + #else + uniform samplerCubeShadow shadowMapPoint[1]; + uniform samplerCube shadowMapPointTransparent[1]; + uniform vec2 lightProj; + #endif + #endif + #ifdef _Clusters + #ifdef _SingleAtlas + //!uniform sampler2DShadow shadowMapAtlas; + //!uniform sampler2D shadowMapAtlasTransparent; + #endif + uniform vec2 lightProj; + #ifdef _ShadowMapAtlas + #ifndef _SingleAtlas + uniform sampler2DShadow shadowMapAtlasPoint; + uniform sampler2D shadowMapAtlasPointTransparent; + #endif + #else + uniform samplerCubeShadow shadowMapPoint[4]; + uniform samplerCube shadowMapPointTransparent[4]; + #endif + #ifdef _Spot + #ifdef _ShadowMapAtlas + #ifndef _SingleAtlas + uniform sampler2DShadow shadowMapAtlasSpot; + uniform sampler2D shadowMapAtlasSpotTransparent; + #endif + #else + uniform sampler2DShadow shadowMapSpot[4]; + uniform sampler2D shadowMapSpotTransparent[4]; + #endif + uniform mat4 LWVPSpotArray[maxLightsCluster]; + #endif + #endif +#endif + +#ifdef _LTC +uniform vec3 lightArea0; +uniform vec3 lightArea1; +uniform vec3 lightArea2; +uniform vec3 lightArea3; +uniform sampler2D sltcMat; +uniform sampler2D sltcMag; +#ifdef _ShadowMap +#ifndef _Spot + #ifdef _SinglePoint + uniform sampler2DShadow shadowMapSpot[1]; + uniform sampler2D shadowMapSpotTransparent[1]; + uniform mat4 LWVPSpot[1]; + #endif + #ifdef _Clusters + uniform sampler2DShadow shadowMapSpot[maxLightsCluster]; + uniform sampler2D shadowMapSpotTransparent[maxLightsCluster]; + uniform mat4 LWVPSpotArray[maxLightsCluster]; + #endif + #endif +#endif +#endif + +vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, const vec3 lp, const vec3 lightCol, + const vec3 albedo, const float rough, const float spec, const vec3 f0 + #ifdef _ShadowMap + , int index, float bias, bool receiveShadow, bool transparent + #endif + #ifdef _Spot + , const bool isSpot, const float spotSize, float spotBlend, vec3 spotDir, vec2 scale, vec3 right + #endif + #ifdef _VoxelShadow + , sampler3D voxels, sampler3D voxelsSDF, float clipmaps[10 * voxelgiClipmapCount] + #endif + #ifdef _MicroShadowing + , float occ + #endif + #ifdef _SSRS + , sampler2D gbufferD, mat4 invVP, vec3 eye + #endif + ) { + vec3 ld = lp - p; + vec3 l = normalize(ld); + vec3 h = normalize(v + l); + float dotNH = max(0.0, dot(n, h)); + float dotVH = max(0.0, dot(v, h)); + float dotNL = max(0.0, dot(n, l)); + + #ifdef _LTC + float theta = acos(dotNV); + vec2 tuv = vec2(rough, theta / (0.5 * PI)); + tuv = tuv * LUT_SCALE + LUT_BIAS; + vec4 t = textureLod(sltcMat, tuv, 0.0); + mat3 invM = mat3( + vec3(1.0, 0.0, t.y), + vec3(0.0, t.z, 0.0), + vec3(t.w, 0.0, t.x)); + float ltcspec = ltcEvaluate(n, v, dotNV, p, invM, lightArea0, lightArea1, lightArea2, lightArea3); + ltcspec *= textureLod(sltcMag, tuv, 0.0).a; + float ltcdiff = ltcEvaluate(n, v, dotNV, p, mat3(1.0), lightArea0, lightArea1, lightArea2, lightArea3); + vec3 direct = albedo * ltcdiff + ltcspec * spec * 0.05; + #else + vec3 direct = lambertDiffuseBRDF(albedo, dotNL) + + specularBRDF(f0, rough, dotNL, dotNH, dotNV, dotVH) * spec; + #endif + + direct *= attenuate(distance(p, lp)); + direct *= lightCol; + + #ifdef _MicroShadowing + direct *= clamp(dotNL + 2.0 * occ * occ - 1.0, 0.0, 1.0); + #endif + + #ifdef _SSRS + direct *= traceShadowSS(l, p, gbufferD, invVP, eye); + #endif + + #ifdef _VoxelShadow + vec4 g2 = textureLod(gbuffer2, gl_FragCoord.xy, 0.0); + direct *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, l, clipmaps, gl_FragCoord.xy, g2.rg).r) * voxelgiShad; + #endif + + #ifdef _LTC + #ifdef _ShadowMap + if (receiveShadow) { + #ifdef _SinglePoint + vec4 lPos = LWVPSpotArray[0] * vec4(p + n * bias * 10, 1.0); + direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent); + #endif + #ifdef _Clusters + vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0); + if (index == 0) direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent); + else if (index == 1) direct *= shadowTest(shadowMapSpot[1], shadowMapSpotTransparent[1], lPos.xyz / lPos.w, bias, transparent); + else if (index == 2) direct *= shadowTest(shadowMapSpot[2], shadowMapSpotTransparent[2], lPos.xyz / lPos.w, bias, transparent); + else if (index == 3) direct *= shadowTest(shadowMapSpot[3], shadowMapSpotTransparent[3], lPos.xyz / lPos.w, bias, transparent); + #endif + } + #endif + return direct; + #endif + + #ifdef _Spot + if (isSpot) { + direct *= spotlightMask(l, spotDir, right, scale, spotSize, spotBlend); + + #ifdef _ShadowMap + if (receiveShadow) { + #ifdef _SinglePoint + vec4 lPos = LWVPSpot[0] * vec4(p + n * bias * 10, 1.0); + direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent); + #endif + #ifdef _Clusters + vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0); + #ifdef _ShadowMapAtlas + direct *= shadowTest( + #ifndef _SingleAtlas + shadowMapAtlasSpot, shadowMapAtlasSpotTransparent + #else + shadowMapAtlas, shadowMapAtlasTransparent + #endif + , lPos.xyz / lPos.w, bias, transparent + ); + #else + if (index == 0) direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent); + else if (index == 1) direct *= shadowTest(shadowMapSpot[1], shadowMapSpotTransparent[1], lPos.xyz / lPos.w, bias, transparent); + else if (index == 2) direct *= shadowTest(shadowMapSpot[2], shadowMapSpotTransparent[2], lPos.xyz / lPos.w, bias, transparent); + else if (index == 3) direct *= shadowTest(shadowMapSpot[3], shadowMapSpotTransparent[3], lPos.xyz / lPos.w, bias, transparent); + #endif + #endif + } + #endif + return direct; + } + #endif + + #ifdef _LightIES + direct *= iesAttenuation(-l); + #endif + + #ifdef _ShadowMap + if (receiveShadow) { + #ifdef _SinglePoint + #ifndef _Spot + direct *= PCFCube(shadowMapPoint[0], shadowMapPointTransparent[0], ld, -l, bias, lightProj, n, transparent); + #endif + #endif + #ifdef _Clusters + #ifdef _ShadowMapAtlas + direct *= PCFFakeCube( + #ifndef _SingleAtlas + shadowMapAtlasPoint, shadowMapAtlasPointTransparent + #else + shadowMapAtlas, shadowMapAtlasTransparent + #endif + , ld, -l, bias, lightProj, n, index, transparent + ); + #else + if (index == 0) direct *= PCFCube(shadowMapPoint[0], shadowMapPointTransparent[0], ld, -l, bias, lightProj, n, transparent); + else if (index == 1) direct *= PCFCube(shadowMapPoint[1], shadowMapPointTransparent[1], ld, -l, bias, lightProj, n, transparent); + else if (index == 2) direct *= PCFCube(shadowMapPoint[2], shadowMapPointTransparent[2], ld, -l, bias, lightProj, n, transparent); + else if (index == 3) direct *= PCFCube(shadowMapPoint[3], shadowMapPointTransparent[3], ld, -l, bias, lightProj, n, transparent); + #endif + #endif + } + #endif + + return direct; +} + +#endif From 61fd48a12ff5a526256827662bec97a9bc8e4307 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Mon, 7 Apr 2025 15:47:22 +0000 Subject: [PATCH 014/136] Update leenkx/Shaders/ssr_pass/ssr_pass.frag.glsl --- leenkx/Shaders/ssr_pass/ssr_pass.frag.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/leenkx/Shaders/ssr_pass/ssr_pass.frag.glsl b/leenkx/Shaders/ssr_pass/ssr_pass.frag.glsl index 84aa2fa..138056a 100644 --- a/leenkx/Shaders/ssr_pass/ssr_pass.frag.glsl +++ b/leenkx/Shaders/ssr_pass/ssr_pass.frag.glsl @@ -92,7 +92,7 @@ void main() { vec3 viewNormal = V3 * n; vec3 viewPos = getPosView(viewRay, d, cameraProj); - vec3 reflected = reflect(viewPos, viewNormal); + vec3 reflected = reflect(normalize(viewPos), viewNormal); hitCoord = viewPos; #ifdef _CPostprocess From 03967c7a2b44808619762b6baeba21040fe91b70 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Mon, 7 Apr 2025 15:50:41 +0000 Subject: [PATCH 015/136] Update leenkx/Sources/leenkx/system/Starter.hx --- leenkx/Sources/leenkx/system/Starter.hx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/leenkx/Sources/leenkx/system/Starter.hx b/leenkx/Sources/leenkx/system/Starter.hx index 7700804..cb1f9d9 100644 --- a/leenkx/Sources/leenkx/system/Starter.hx +++ b/leenkx/Sources/leenkx/system/Starter.hx @@ -41,7 +41,11 @@ class Starter { try { #end - kha.System.start({title: Main.projectName, width: c.window_w, height: c.window_h, window: {mode: windowMode, windowFeatures: windowFeatures}, framebuffer: {samplesPerPixel: c.window_msaa, verticalSync: c.window_vsync}}, function(window: kha.Window) { + kha.System.start({title: Main.projectName, width: c.window_w, height: c.window_h, window: { + #if arm_render_viewport + visible: false, + #end + mode: windowMode, windowFeatures: windowFeatures}, framebuffer: {samplesPerPixel: c.window_msaa, verticalSync: c.window_vsync}}, function(window: kha.Window) { iron.App.init(function() { #if lnx_loadscreen From 86661c101235cc55c89f9ef42dd9f7be31b6535e Mon Sep 17 00:00:00 2001 From: Onek8 Date: Mon, 7 Apr 2025 16:04:17 +0000 Subject: [PATCH 016/136] Update leenkx/Shaders/voxel_light/voxel_light.comp.glsl --- .../Shaders/voxel_light/voxel_light.comp.glsl | 89 +++++++++---------- 1 file changed, 44 insertions(+), 45 deletions(-) diff --git a/leenkx/Shaders/voxel_light/voxel_light.comp.glsl b/leenkx/Shaders/voxel_light/voxel_light.comp.glsl index 8d4515f..005a3c1 100644 --- a/leenkx/Shaders/voxel_light/voxel_light.comp.glsl +++ b/leenkx/Shaders/voxel_light/voxel_light.comp.glsl @@ -33,6 +33,7 @@ uniform layout(r32ui) uimage3D voxelsLight; #ifdef _ShadowMap uniform sampler2DShadow shadowMap; +uniform sampler2D shadowMapTransparent; uniform sampler2DShadow shadowMapSpot; #ifdef _ShadowMapAtlas uniform sampler2DShadow shadowMapPoint; @@ -86,53 +87,51 @@ float lpToDepth(vec3 lp, const vec2 lightProj) { void main() { int res = voxelgiResolution.x; + for (int i = 0; i < 6; i++) { + ivec3 dst = ivec3(gl_GlobalInvocationID.xyz); + vec3 P = (gl_GlobalInvocationID.xyz + 0.5) / voxelgiResolution; + P = P * 2.0 - 1.0; - ivec3 dst = ivec3(gl_GlobalInvocationID.xyz); - dst.y += clipmapLevel * res; - - vec3 P = (gl_GlobalInvocationID.xyz + 0.5) / voxelgiResolution; - P = P * 2.0 - 1.0; - P *= clipmaps[int(clipmapLevel * 10)]; - P *= voxelgiResolution; - P += vec3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)]); - - vec3 visibility; - vec3 lp = lightPos - P; - vec3 l; - if (lightType == 0) { l = lightDir; visibility = vec3(1.0); } - else { l = normalize(lp); visibility = vec3(attenuate(distance(P, lightPos))); } + float visibility; + vec3 lp = lightPos - P; + vec3 l; + if (lightType == 0) { l = lightDir; visibility = 1.0; } + else { l = normalize(lp); visibility = attenuate(distance(P, lightPos)); } #ifdef _ShadowMap - if (lightShadow == 1) { - vec4 lightPosition = LVP * vec4(P, 1.0); - vec3 lPos = lightPosition.xyz / lightPosition.w; - visibility = texture(shadowMap, vec3(lPos.xy, lPos.z - shadowsBias)).rrr; - } - else if (lightShadow == 2) { - vec4 lightPosition = LVP * vec4(P, 1.0); - vec3 lPos = lightPosition.xyz / lightPosition.w; - visibility *= texture(shadowMapSpot, vec3(lPos.xy, lPos.z - shadowsBias)).r; - } - else if (lightShadow == 3) { - #ifdef _ShadowMapAtlas - int faceIndex = 0; - const int lightIndex = index * 6; - const vec2 uv = sampleCube(-l, faceIndex); - vec4 pointLightTile = pointLightDataArray[lightIndex + faceIndex]; // x: tile X offset, y: tile Y offset, z: tile size relative to atlas - vec2 uvtiled = pointLightTile.z * uv + pointLightTile.xy; - #ifdef _FlipY - uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system - #endif - visibility *= texture(shadowMapPoint, vec3(uvtiled, lpToDepth(lp, lightProj) - shadowsBias)).r; - #else - visibility *= texture(shadowMapPoint, vec4(-l, lpToDepth(lp, lightProj) - shadowsBias)).r; - #endif - } -#endif + if (lightShadow == 1) { + vec4 lightPosition = LVP * vec4(P, 1.0); + vec3 lPos = lightPosition.xyz / lightPosition.w; + visibility = texture(shadowMap, vec3(lPos.xy, lPos.z - shadowsBias)).r; + } + else if (lightShadow == 2) { + vec4 lightPosition = LVP * vec4(P, 1.0); + vec3 lPos = lightPosition.xyz / lightPosition.w; + visibility *= texture(shadowMapSpot, vec3(lPos.xy, lPos.z - shadowsBias)).r; + } + else if (lightShadow == 3) { + #ifdef _ShadowMapAtlas + int faceIndex = 0; + const int lightIndex = index * 6; + const vec2 uv = sampleCube(-l, faceIndex); + vec4 pointLightTile = pointLightDataArray[lightIndex + faceIndex]; // x: tile X offset, y: tile Y offset, z: tile size relative to atlas + vec2 uvtiled = pointLightTile.z * uv + pointLightTile.xy; + #ifdef _FlipY + uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system + #endif + visibility *= texture(shadowMapPoint, vec3(uvtiled, lpToDepth(lp, lightProj) - shadowsBias)).r; + #else + visibility *= texture(shadowMapPoint, vec4(-l, lpToDepth(lp, lightProj) - shadowsBias)).r; + #endif + } + #endif + vec3 uvw_light = (P - vec3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)])) / (float(clipmaps[int(clipmapLevel * 10)]) * voxelgiResolution); + uvw_light = (uvw_light * 0.5 + 0.5); + if (any(notEqual(uvw_light, clamp(uvw_light, 0.0, 1.0)))) return; + vec3 writecoords_light = floor(uvw_light * voxelgiResolution); - vec3 light = visibility * lightColor; - - imageAtomicAdd(voxelsLight, dst + ivec3(0, 0, 0), uint(light.r * 255)); - imageAtomicAdd(voxelsLight, dst + ivec3(0, 0, voxelgiResolution.x), uint(light.g * 255)); - imageAtomicAdd(voxelsLight, dst + ivec3(0, 0, voxelgiResolution.x * 2), uint(light.b * 255)); + imageAtomicMax(voxelsLight, ivec3(writecoords_light), uint(visibility * lightColor.r * 255)); + imageAtomicMax(voxelsLight, ivec3(writecoords_light) + ivec3(0, 0, voxelgiResolution.x), uint(visibility * lightColor.g * 255)); + imageAtomicMax(voxelsLight, ivec3(writecoords_light) + ivec3(0, 0, voxelgiResolution.x * 2), uint(visibility * lightColor.b * 255)); + } } From 79553927aa1b609fd061084e59028445060602e4 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Mon, 7 Apr 2025 16:06:53 +0000 Subject: [PATCH 017/136] Update leenkx/Shaders/water_pass/water_pass.frag.glsl --- .../Shaders/water_pass/water_pass.frag.glsl | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/leenkx/Shaders/water_pass/water_pass.frag.glsl b/leenkx/Shaders/water_pass/water_pass.frag.glsl index 2bf016b..cda7537 100644 --- a/leenkx/Shaders/water_pass/water_pass.frag.glsl +++ b/leenkx/Shaders/water_pass/water_pass.frag.glsl @@ -75,16 +75,17 @@ vec4 binarySearch(vec3 dir) { } vec4 rayCast(vec3 dir) { - #ifdef _CPostprocess - dir *= PPComp9.x; - #else - dir *= ssrRayStep; - #endif - for (int i = 0; i < maxSteps; i++) { - hitCoord += dir; - if (getDeltaDepth(hitCoord) > 0.0) return binarySearch(dir); - } - return vec4(0.0); + float ddepth; + dir *= ss_refractionRayStep; + for (int i = 0; i < maxSteps; i++) { + hitCoord += dir; + ddepth = getDeltaDepth(hitCoord); + if (ddepth > 0.0) + return binarySearch(dir); + } + // No hit — fallback to projecting the ray to UV space + vec2 fallbackUV = getProjectedCoord(hitCoord); + return vec4(fallbackUV, 0.0, 0.5); // We set .w lower to indicate fallback } #endif //SSR From 4625fdb6b2199ce01ac7ccbb37e3064862c736aa Mon Sep 17 00:00:00 2001 From: Onek8 Date: Mon, 7 Apr 2025 16:13:16 +0000 Subject: [PATCH 018/136] Update leenkx/blender/lnx/material/make_cluster.py --- leenkx/blender/lnx/material/make_cluster.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/leenkx/blender/lnx/material/make_cluster.py b/leenkx/blender/lnx/material/make_cluster.py index ce8ccd5..7e21c93 100644 --- a/leenkx/blender/lnx/material/make_cluster.py +++ b/leenkx/blender/lnx/material/make_cluster.py @@ -104,8 +104,7 @@ def write(vert: shader.Shader, frag: shader.Shader): if '_SSRS' in wrd.world_defs: frag.add_uniform('mat4 invVP', '_inverseViewProjectionMatrix') frag.add_uniform('vec3 eye', '_cameraPosition') - frag.add_uniform('sampler2D gbufferD', link='_gbufferD', top=True) - frag.write(', gbufferD, invVP, eye') + frag.write(', wposition.z, inVP, eye') frag.write(');') frag.write('}') # for numLights From 9fa399371a9edff4248a36e3c48e740f512f91f3 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Mon, 7 Apr 2025 16:25:06 +0000 Subject: [PATCH 019/136] Update leenkx/blender/lnx/material/make_mesh.py --- leenkx/blender/lnx/material/make_mesh.py | 52 +++++++++++++----------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/leenkx/blender/lnx/material/make_mesh.py b/leenkx/blender/lnx/material/make_mesh.py index dc92084..600c16e 100644 --- a/leenkx/blender/lnx/material/make_mesh.py +++ b/leenkx/blender/lnx/material/make_mesh.py @@ -609,9 +609,11 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): frag.write_attrib('float dotNV = max(dot(n, vVec), 0.0);') sh = tese if tese is not None else vert + sh.add_uniform('mat4 W', '_worldMatrix') + sh.write_attrib('vec3 wposition = vec4(W * spos).xyz;') sh.add_out('vec3 eyeDir') sh.add_uniform('vec3 eye', '_cameraPosition') - sh.write('eyeDir = eye - spos.xyz;') + sh.write('eyeDir = eye - wposition;') frag.add_include('std/light.glsl') is_shadows = '_ShadowMap' in wrd.world_defs @@ -666,33 +668,37 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): frag.write('envl *= envmapStrength * occlusion;') if '_VoxelAOvar' in wrd.world_defs or '_VoxelGI' in wrd.world_defs: - if parse_opacity or '_VoxelShadow' in wrd.world_defs: - frag.add_include('std/conetrace.glsl') - frag.add_uniform('sampler3D voxels') - frag.add_uniform('sampler3D voxelsSDF') - frag.add_uniform('vec3 eye', "_cameraPosition") - frag.add_uniform('float clipmaps[10 * voxelgiClipmapCount]', '_clipmaps') + frag.add_include('std/conetrace.glsl') + frag.add_uniform('sampler3D voxels') + frag.add_uniform('sampler3D voxelsSDF') + frag.add_uniform('vec3 eye', '_cameraPosition') + frag.add_uniform('float clipmaps[10 * voxelgiClipmapCount]', '_clipmaps') vert.add_out('vec4 wvpposition') vert.write('wvpposition = gl_Position;') frag.write('vec2 texCoord = (wvpposition.xy / wvpposition.w) * 0.5 + 0.5;') - if '_VoxelAOvar' in wrd.world_defs and not parse_opacity: - frag.add_uniform("sampler2D voxels_ao"); - frag.write('envl *= textureLod(voxels_ao, texCoord, 0.0).rrr;') + if '_VoxelGI' in wrd.world_defs or '_VoxelShadow' in wrd.world_defs or '_VoxelRefract' in wrd.world_defs: + frag.add_uniform('sampler2D gbuffer2', included=True) + frag.write('vec2 velocity = -textureLod(gbuffer2, gl_FragCoord.xy, 0.0).rg;') + + if '_VoxelAOvar' in wrd.world_defs: + if parse_opacity: + frag.write('envl *= 1.0 - traceAO(wposition, n, voxels, clipmaps);') + else: + frag.add_uniform("sampler2D voxels_ao"); + frag.write('envl *= textureLod(voxels_ao, texCoord, 0.0).rrr;') if '_VoxelGI' in wrd.world_defs: frag.write('vec3 indirect = vec3(0.0);') else: frag.write('vec3 indirect = envl;') - + if '_VoxelGI' in wrd.world_defs: if parse_opacity: - frag.write('vec4 trace = traceDiffuse(wposition, wnormal, voxels, clipmaps);') - frag.write('indirect = ((trace.rgb * albedo + envl * (1.0 - trace.a)) * voxelgiDiff);') - frag.write('if (roughness < 1.0 && specular > 0.0){') - frag.add_uniform('sampler2D sveloc') - frag.write(' vec2 velocity = -textureLod(sveloc, gl_FragCoord.xy, 0.0).rg;') - frag.write(' indirect += traceSpecular(wposition, n, voxels, voxelsSDF, vVec, roughness, clipmaps, gl_FragCoord.xy, velocity).rgb * specular * voxelgiRefl;}') + frag.write('vec4 indirect_diffuse = traceDiffuse(wposition, n, voxels, clipmaps);') + frag.write('indirect = (indirect_diffuse.rgb * albedo + envl.rgb * (1.0 - indirect_diffuse.a)) * voxelgiDiff;') + frag.write('if (roughness < 1.0 && specular > 0.0) {') + frag.write(' indirect += traceSpecular(wposition, n, voxels, voxelsSDF, vVec, roughness * roughness, clipmaps, gl_FragCoord.xy, velocity).rgb * specular * voxelgiRefl; }') else: frag.add_uniform("sampler2D voxels_diffuse") frag.add_uniform("sampler2D voxels_specular") @@ -746,7 +752,7 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): else: frag.write(f'svisibility = PCF({shadowmap_sun}, {shadowmap_sun_tr}, lPos.xy, lPos.z - shadowsBias, smSize, false);') if '_VoxelShadow' in wrd.world_defs: - frag.write('svisibility *= (1.0 - traceShadow(wposition, n, voxels, voxelsSDF, sunDir, clipmaps, gl_FragCoord.xy).r) * voxelgiShad;') + frag.write('svisibility *= (1.0 - traceShadow(wposition, n, voxels, voxelsSDF, sunDir, clipmaps, gl_FragCoord.xy, velocity).r) * voxelgiShad;') frag.write('}') # receiveShadow frag.write('direct += (lambertDiffuseBRDF(albedo, sdotNL) + specularBRDF(f0, roughness, sdotNL, sdotNH, dotNV, sdotVH) * specular) * sunCol * svisibility;') # sun @@ -784,10 +790,9 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): if '_MicroShadowing' in wrd.world_defs: frag.write(', occlusion') if '_SSRS' in wrd.world_defs: - frag.add_uniform('sampler2D gbufferD', top=True) frag.add_uniform('mat4 invVP', '_inverseViewProjectionMatrix') frag.add_uniform('vec3 eye', '_cameraPosition') - frag.write(', gbufferD, invVP, eye') + frag.write(', wposition.z, inVP, eye') frag.write(');') if '_Clusters' in wrd.world_defs: @@ -800,10 +805,9 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): if '_VoxelRefract' in wrd.world_defs and parse_opacity: frag.write('if (opacity < 1.0) {') - frag.write(' vec2 velocity = -textureLod(sveloc, gl_FragCoord.xy, 0.0).rg;') - frag.write(' vec3 refraction = traceRefraction(wposition, n, voxels, voxelsSDF, vVec, ior, roughness, clipmaps, gl_FragCoord.xy,velocity).rgb;') - frag.write(' indirect = mix(refraction, indirect, opacity) * voxelgiRefr;') - frag.write(' direct = mix(refraction, direct, opacity) * voxelgiRefr;') + frag.write(' vec3 refraction = traceRefraction(wposition, n, voxels, voxelsSDF, vVec, ior, roughness, clipmaps, gl_FragCoord.xy, velocity, opacity).rgb * voxelgiRefr;') + frag.write(' indirect = mix(refraction, indirect, opacity);') + frag.write(' direct = mix(refraction, direct, opacity);') frag.write('}') def _write_material_attribs_default(frag: shader.Shader, parse_opacity: bool): From 304a497565259908f4a04dace0a785583f9f873a Mon Sep 17 00:00:00 2001 From: Onek8 Date: Mon, 7 Apr 2025 16:27:25 +0000 Subject: [PATCH 020/136] Update leenkx/blender/lnx/make_renderpath.py --- leenkx/blender/lnx/make_renderpath.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/leenkx/blender/lnx/make_renderpath.py b/leenkx/blender/lnx/make_renderpath.py index 5576c99..bb2dca6 100644 --- a/leenkx/blender/lnx/make_renderpath.py +++ b/leenkx/blender/lnx/make_renderpath.py @@ -452,7 +452,7 @@ def build(): if ignoreIrr: wrd.world_defs += '_IgnoreIrr' - gbuffer2 = '_Veloc' in wrd.world_defs or '_IgnoreIrr' in wrd.world_defs + gbuffer2 = '_Veloc' in wrd.world_defs or '_IgnoreIrr' in wrd.world_defs or '_VoxelGI' in wrd.world_defs or '_VoxelShadow' in wrd.world_defs if gbuffer2: assets.add_khafile_def('rp_gbuffer2') wrd.world_defs += '_gbuffer2' From 41c1459c4ef63c3c3c607324567df7bfaf57377d Mon Sep 17 00:00:00 2001 From: Onek8 Date: Mon, 7 Apr 2025 16:34:12 +0000 Subject: [PATCH 021/136] Update leenkx/blender/lnx/material/make_voxel.py --- leenkx/blender/lnx/material/make_voxel.py | 1019 +++++++++++---------- 1 file changed, 511 insertions(+), 508 deletions(-) diff --git a/leenkx/blender/lnx/material/make_voxel.py b/leenkx/blender/lnx/material/make_voxel.py index 553df86..42c88b3 100644 --- a/leenkx/blender/lnx/material/make_voxel.py +++ b/leenkx/blender/lnx/material/make_voxel.py @@ -1,508 +1,511 @@ -""" -Copyright (c) 2024 Turánszki János - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -""" -import bpy - -import lnx.utils -import lnx.assets as assets -import lnx.material.cycles as cycles -import lnx.material.mat_state as mat_state -import lnx.material.mat_utils as mat_utils -import lnx.material.make_particle as make_particle -import lnx.make_state as state - -if lnx.is_reload(__name__): - lnx.utils = lnx.reload_module(lnx.utils) - assets = lnx.reload_module(assets) - mat_state = lnx.reload_module(mat_state) -else: - lnx.enable_reload(__name__) - -def make(context_id): - rpdat = lnx.utils.get_rp() - if rpdat.rp_voxels == 'Voxel GI': - con = make_gi(context_id) - else: - con = make_ao(context_id) - - assets.vs_equal(con, assets.shader_cons['voxel_vert']) - assets.fs_equal(con, assets.shader_cons['voxel_frag']) - assets.gs_equal(con, assets.shader_cons['voxel_geom']) - - return con - -def make_gi(context_id): - con_voxel = mat_state.data.add_context({ 'name': context_id, 'depth_write': False, 'compare_mode': 'always', 'cull_mode': 'none', 'color_write_red': False, 'color_write_green': False, 'color_write_blue': False, 'color_write_alpha': False, 'conservative_raster': True }) - wrd = bpy.data.worlds['Lnx'] - - vert = con_voxel.make_vert() - frag = con_voxel.make_frag() - geom = con_voxel.make_geom() - tesc = None - tese = None - geom.ins = vert.outs - frag.ins = geom.outs - - vert.add_include('compiled.inc') - geom.add_include('compiled.inc') - frag.add_include('compiled.inc') - frag.add_include('std/math.glsl') - frag.add_include('std/imageatomic.glsl') - frag.add_include('std/gbuffer.glsl') - frag.add_include('std/brdf.glsl') - - rpdat = lnx.utils.get_rp() - frag.add_uniform('layout(r32ui) uimage3D voxels') - - frag.write('vec3 n;') - frag.write('vec3 wposition;') - frag.write('vec3 basecol;') - frag.write('float roughness;') # - frag.write('float metallic;') # - frag.write('float occlusion;') # - frag.write('float specular;') # - frag.write('vec3 emissionCol = vec3(0.0);') - blend = mat_state.material.lnx_blending - parse_opacity = blend or mat_utils.is_transluc(mat_state.material) - if parse_opacity: - frag.write('float opacity;') - frag.write('float ior;') - else: - frag.write('float opacity = 1.0;') - - frag.write('float dotNV = 0.0;') - cycles.parse(mat_state.nodes, con_voxel, vert, frag, geom, tesc, tese, parse_opacity=parse_opacity, parse_displacement=False, basecol_only=True) - - # Voxelized particles - particle = mat_state.material.lnx_particle_flag - if particle and rpdat.lnx_particles == 'On': - # make_particle.write(vert, particle_info=cycles.particle_info) - frag.write_pre = True - frag.write('const float p_index = 0;') - frag.write('const float p_age = 0;') - frag.write('const float p_lifetime = 0;') - frag.write('const vec3 p_location = vec3(0);') - frag.write('const float p_size = 0;') - frag.write('const vec3 p_velocity = vec3(0);') - frag.write('const vec3 p_angular_velocity = vec3(0);') - frag.write_pre = False - - export_mpos = frag.contains('mposition') and not frag.contains('vec3 mposition') - if export_mpos: - vert.add_out('vec3 mpositionGeom') - vert.write_pre = True - vert.write('mpositionGeom = pos.xyz;') - vert.write_pre = False - - export_bpos = frag.contains('bposition') and not frag.contains('vec3 bposition') - if export_bpos: - vert.add_out('vec3 bpositionGeom') - vert.add_uniform('vec3 dim', link='_dim') - vert.add_uniform('vec3 hdim', link='_halfDim') - vert.write_pre = True - vert.write('bpositionGeom = (pos.xyz + hdim) / dim;') - vert.write_pre = False - - vert.add_uniform('mat4 W', '_worldMatrix') - vert.add_uniform('mat3 N', '_normalMatrix') - vert.add_out('vec3 voxpositionGeom') - vert.add_out('vec3 voxnormalGeom') - - if con_voxel.is_elem('col'): - vert.add_out('vec3 vcolorGeom') - vert.write('vcolorGeom = col.rgb;') - - if con_voxel.is_elem('tex'): - vert.add_out('vec2 texCoordGeom') - vert.write('texCoordGeom = tex;') - - vert.write('voxpositionGeom = vec3(W * vec4(pos.xyz, 1.0));') - vert.write('voxnormalGeom = normalize(N * vec3(nor.xy, pos.w));') - - geom.add_out('vec4 voxposition[3]') - geom.add_out('vec3 P') - geom.add_out('vec3 voxnormal') - geom.add_out('vec4 lightPosition') - geom.add_out('vec4 spotPosition') - geom.add_out('vec4 wvpposition') - - if con_voxel.is_elem('col'): - geom.add_out('vec3 vcolor') - if con_voxel.is_elem('tex'): - geom.add_out('vec2 texCoord') - if export_mpos: - geom.add_out('vec3 mposition') - if export_bpos: - geom.add_out('vec3 bposition') - - geom.add_uniform('float clipmaps[voxelgiClipmapCount * 10]', '_clipmaps') - geom.add_uniform('int clipmapLevel', '_clipmapLevel') - - geom.write('vec3 facenormal = abs(voxnormalGeom[0] + voxnormalGeom[1] + voxnormalGeom[2]);') - geom.write('uint maxi = facenormal[1] > facenormal[0] ? 1 : 0;') - geom.write('maxi = facenormal[2] > facenormal[maxi] ? 2 : maxi;') - - geom.write('for (uint i = 0; i < 3; ++i) {') - geom.write(' voxposition[i].xyz = (voxpositionGeom[i] - vec3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)])) / (float(clipmaps[int(clipmapLevel * 10)]));') - geom.write(' if (maxi == 0)') - geom.write(' {') - geom.write(' voxposition[i].xyz = voxposition[i].zyx;') - geom.write(' }') - geom.write(' else if (maxi == 1)') - geom.write(' {') - geom.write(' voxposition[i].xyz = voxposition[i].xzy;') - geom.write(' }') - geom.write('}') - - geom.write('for (uint i = 0; i < 3; ++i) {') - geom.write(' voxposition[i].xy /= voxelgiResolution.xy;') - geom.write(' voxposition[i].zw = vec2(1.0);') - geom.write(' P = voxpositionGeom[i];') - geom.write(' voxnormal = voxnormalGeom[i];') - if con_voxel.is_elem('col'): - geom.write('vcolor = vcolorGeom[i];') - if con_voxel.is_elem('tex'): - geom.write('texCoord = texCoordGeom[i];') - if export_mpos: - geom.write('mposition = mpositionGeom[i];') - if export_bpos: - geom.write('bposition = bpositionGeom[i];') - geom.write(' gl_Position = voxposition[i];') - geom.write(' EmitVertex();') - geom.write('}') - geom.write('EndPrimitive();') - - frag.add_uniform('float clipmaps[voxelgiClipmapCount * 10]', '_clipmaps') - frag.add_uniform('int clipmapLevel', '_clipmapLevel') - - frag.write('vec3 uvw = (P - vec3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)])) / (float(clipmaps[int(clipmapLevel * 10)]) * voxelgiResolution);') - frag.write('uvw = (uvw * 0.5 + 0.5);') - frag.write('if(any(notEqual(uvw, clamp(uvw, 0.0, 1.0)))) return;') - frag.write('vec3 writecoords = floor(uvw * voxelgiResolution);') - frag.write_attrib('vec3 N = normalize(voxnormal);') - frag.write('vec3 aniso_direction = N;') - frag.write('uvec3 face_offsets = uvec3(') - frag.write(' aniso_direction.x > 0 ? 0 : 1,') - frag.write(' aniso_direction.y > 0 ? 2 : 3,') - frag.write(' aniso_direction.z > 0 ? 4 : 5') - frag.write(' ) * voxelgiResolution;') - frag.write('vec3 direction_weights = abs(N);') - - frag.write('vec3 albedo = surfaceAlbedo(basecol, metallic);') - frag.write('vec3 f0 = surfaceF0(basecol, metallic);') - - frag.add_uniform('vec3 eye', '_cameraPosition') - frag.write('vec3 eyeDir = eye - wposition;') - - if '_Brdf' in wrd.world_defs: - frag.add_uniform('sampler2D senvmapBrdf', link='$brdf.png') - frag.write('vec2 envBRDF = texelFetch(senvmapBrdf, ivec2(vec2(dotNV, 1.0 - roughness) * 256.0), 0).xy;') - - if '_Irr' in wrd.world_defs: - frag.add_include('std/shirr.glsl') - frag.add_uniform('vec4 shirr[7]', link='_envmapIrradiance') - frag.write('vec3 envl = shIrradiance(n, shirr);') - if '_EnvTex' in wrd.world_defs: - frag.write('envl /= PI;') - else: - frag.write('vec3 envl = vec3(0.0);') - - if '_Rad' in wrd.world_defs: - frag.add_uniform('sampler2D senvmapRadiance', link='_envmapRadiance') - frag.add_uniform('int envmapNumMipmaps', link='_envmapNumMipmaps') - frag.write('vec3 reflectionWorld = reflect(-eyeDir, n);') - frag.write('float lod = getMipFromRoughness(roughness, envmapNumMipmaps);') - frag.write('vec3 prefilteredColor = textureLod(senvmapRadiance, envMapEquirect(reflectionWorld), lod).rgb;') - - if '_EnvLDR' in wrd.world_defs: - frag.write('envl = pow(envl, vec3(2.2));') - if '_Rad' in wrd.world_defs: - frag.write('prefilteredColor = pow(prefilteredColor, vec3(2.2));') - - frag.write('envl *= albedo;') - - if '_Brdf' in wrd.world_defs: - frag.write('envl.rgb *= 1.0 - (f0 * envBRDF.x + envBRDF.y);') - if '_Rad' in wrd.world_defs: - frag.write('envl += prefilteredColor * (f0 * envBRDF.x + envBRDF.y);') - elif '_EnvCol' in wrd.world_defs: - frag.add_uniform('vec3 backgroundCol', link='_backgroundCol') - frag.write('envl += backgroundCol * (f0 * envBRDF.x + envBRDF.y);') - - frag.add_uniform('float envmapStrength', link='_envmapStrength') - frag.write('envl *= envmapStrength * occlusion;') - - frag.write('if (direction_weights.x > 0) {') - frag.write(' vec4 basecol_direction = vec4(min(basecol * direction_weights.x, vec3(1.0)), 1.0);') - frag.write(' vec3 emission_direction = emissionCol * direction_weights.x;') - frag.write(' vec2 normal_direction = encode_oct(N * direction_weights.x) * 0.5 + 0.5;') - frag.write(' vec3 envl_direction = envl * direction_weights.x;') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, 0)), uint(basecol_direction.r * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x)), uint(basecol_direction.g * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 2)), uint(basecol_direction.b * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 3)), uint(basecol_direction.a * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 4)), uint(emission_direction.r * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 5)), uint(emission_direction.g * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 6)), uint(emission_direction.b * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 7)), uint(normal_direction.r * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 8)), uint(normal_direction.g * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 9)), uint(envl_direction.r * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 10)), uint(envl_direction.g * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 11)), uint(envl_direction.b * 255));') - frag.write('}') - - frag.write('if (direction_weights.y > 0) {') - frag.write(' vec4 basecol_direction = vec4(min(basecol * direction_weights.y, vec3(1.0)), 1.0);') - frag.write(' vec3 emission_direction = emissionCol * direction_weights.y;') - frag.write(' vec2 normal_direction = encode_oct(N * direction_weights.y) * 0.5 + 0.5;') - frag.write(' vec3 envl_direction = envl * direction_weights.y;') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, 0)), uint(basecol_direction.r * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x)), uint(basecol_direction.g * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 2)), uint(basecol_direction.b * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 3)), uint(basecol_direction.a * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 4)), uint(emission_direction.r * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 5)), uint(emission_direction.g * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 6)), uint(emission_direction.b * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 7)), uint(normal_direction.r * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 8)), uint(normal_direction.g * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 9)), uint(envl_direction.r * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 10)), uint(envl_direction.g * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 11)), uint(envl_direction.b * 255));') - frag.write('}') - - frag.write('if (direction_weights.z > 0) {') - frag.write(' vec4 basecol_direction = vec4(min(basecol * direction_weights.z, vec3(1.0)), 1.0);') - frag.write(' vec3 emission_direction = emissionCol * direction_weights.z;') - frag.write(' vec2 normal_direction = encode_oct(n * direction_weights.z) * 0.5 + 0.5;') - frag.write(' vec3 envl_direction = envl * direction_weights.z;') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, 0)), uint(basecol_direction.r * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x)), uint(basecol_direction.g * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 2)), uint(basecol_direction.b * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 3)), uint(basecol_direction.a * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 4)), uint(emission_direction.r * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 5)), uint(emission_direction.g * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 6)), uint(emission_direction.b * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 7)), uint(normal_direction.r * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 8)), uint(normal_direction.g * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 9)), uint(envl_direction.r * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 10)), uint(envl_direction.g * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 11)), uint(envl_direction.b * 255));') - frag.write('}') - - return con_voxel - - -def make_ao(context_id): - con_voxel = mat_state.data.add_context({ 'name': context_id, 'depth_write': False, 'compare_mode': 'always', 'cull_mode': 'none', 'color_writes_red': [False], 'color_writes_green': [False], 'color_writes_blue': [False], 'color_writes_alpha': [False], 'conservative_raster': False }) - wrd = bpy.data.worlds['Lnx'] - rpdat = lnx.utils.get_rp() - - vert = con_voxel.make_vert() - frag = con_voxel.make_frag() - geom = con_voxel.make_geom() - tesc = None - tese = None - - geom.ins = vert.outs - frag.ins = geom.outs - - frag.add_include('compiled.inc') - geom.add_include('compiled.inc') - frag.add_include('std/math.glsl') - frag.add_include('std/imageatomic.glsl') - frag.write_header('#extension GL_ARB_shader_image_load_store : enable') - - vert.add_include('compiled.inc') - vert.add_uniform('mat4 W', '_worldMatrix') - vert.add_uniform('mat3 N', '_normalMatrix') - - geom.add_uniform('float clipmaps[voxelgiClipmapCount * 10]', '_clipmaps') - geom.add_uniform('int clipmapLevel', '_clipmapLevel') - - frag.add_uniform('float clipmaps[voxelgiClipmapCount * 10]', '_clipmaps') - frag.add_uniform('int clipmapLevel', '_clipmapLevel') - - """ - if lnx.utils.get_gapi() == 'direct3d11': - for e in con_voxel.data['vertex_elements']: - if e['name'] == 'nor': - con_voxel.data['vertex_elements'].remove(e) - break - - vert.write('uniform float4x4 W;') - vert.write('uniform float3x3 N;') - vert.write('struct SPIRV_Cross_Input {') - vert.write(' float4 pos : TEXCOORD0;') - vert.write(' float3 nor : NORMAL;') - vert.write('};') - vert.write('struct SPIRV_Cross_Output {') - vert.write(' float4 svpos : SV_POSITION;') - vert.write(' float3 svnor : NORMAL;') - vert.write('};') - vert.write('SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input) {') - vert.write(' SPIRV_Cross_Output stage_output;') - vert.write(' stage_output.svpos.xyz = mul(float4(stage_input.pos.xyz, 1.0), W).xyz;') - vert.write(' stage_output.svpos.w = 1.0;') - vert.write(' stage_output.svnor.xyz = normalize(mul(float3(nor.xy, pos.w), N).xyz);') - vert.write(' return stage_output;') - vert.write('}') - - geom.write('uniform float clipmaps[voxelgiClipmapCount * 10];') - geom.write('uniform int clipmapLevel;') - geom.write('struct SPIRV_Cross_Input {') - geom.write(' float4 svpos : SV_POSITION;') - geom.write(' float3 svnor : NORMAL;') - geom.write('};') - geom.write('struct SPIRV_Cross_Output {') - geom.write(' float3 wpos : TEXCOORD0;') - geom.write(' float3 wnor : NORMAL;') - geom.write('};') - geom.write('[maxvertexcount(3)]') - geom.write('void main(triangle SPIRV_Cross_Input stage_input[3], inout TriangleStream output) {') - geom.write(' float3 p1 = stage_input[1].svpos.xyz - stage_input[0].svpos.xyz;') - geom.write(' float3 p2 = stage_input[2].svpos.xyz - stage_input[0].svpos.xyz;') - geom.write(' float3 p = abs(cross(p1, p2));') - geom.write(' for (int i = 0; i < 3; ++i) {') - geom.write(' SPIRV_Cross_Output stage_output;') - geom.write(' stage_output.wpos = (stage_input[i].svpos.xyz + float3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)])) / (float(clipmaps[clipmapLevel * 10]) * voxelgiResolution);') - geom.write(' stage_output.wnor = stage_input[i].svnor.xyz;') - geom.write(' if (p.z > p.x && p.z > p.y) {') - geom.write(' stage_output.svpos = float4(stage_input[i].svpos.x, stage_input[i].svpos.y, 0.0, 1.0);') - geom.write(' }') - geom.write(' else if (p.x > p.y && p.x > p.z) {') - geom.write(' stage_output.svpos = float4(stage_input[i].svpos.y, stage_input[i].svpos.z, 0.0, 1.0);') - geom.write(' }') - geom.write(' else {') - geom.write(' stage_output.svpos = float4(stage_input[i].svpos.x, stage_input[i].svpos.z, 0.0, 1.0);') - geom.write(' }') - geom.write(' output.Append(stage_output);') - geom.write(' }') - geom.write('}') - - frag.add_uniform('layout(r8) writeonly image3D voxels') - frag.write('RWTexture3D voxels;') - frag.write('uniform float clipmaps[voxelgiClipmapCount * 10];') - frag.write('uniform int clipmapLevel;') - - frag.write('struct SPIRV_Cross_Input {') - frag.write(' float3 wpos : TEXCOORD0;') - frag.write(' float3 wnor : NORMAL;') - frag.write('};') - frag.write('struct SPIRV_Cross_Output { float4 FragColor : SV_TARGET0; };') - frag.write('void main(SPIRV_Cross_Input stage_input) {') - frag.write(' float3 uvw = (stage_input.wpos.xyz - float3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)])) / (float(clipmaps[int(clipmapLevel * 10)]) * voxelgiResolution);') - frag.write(' uvw = uvw * 0.5 + 0.5;') - frag.write(' if(any(!saturate(uvw))) return;') - frag.write(' uvw = floor(uvw * voxelgiResolution);') - frag.write(' uint3 face_offsets = uint3(') - frag.write(' stage_input.wnor.x > 0 ? 0 : 1,') - frag.write(' stage_input.wnor.y > 0 ? 2 : 3,') - frag.write(' stage_input.wnor.z > 0 ? 4 : 5') - frag.write(' ) * voxelgiResolution;') - frag.write(' float3 direction_weights = abs(stage_input.wnor);') - - frag.write(' if (direction_weights.x > 0.0) {') - frag.write(' float opac_direction = direction_weights.x;') - frag.write(' voxels[uvw + int3(face_offsets.x, 0, 0))] = float4(opac_direction);') - frag.write(' }') - - frag.write(' if (direction_weights.y > 0.0) {') - frag.write(' float opac_direction = direction_weights.y;') - frag.write(' voxels[uvw + int3(face_offsets.y, 0, 0))] = float4(opac_direction);') - frag.write(' }') - - frag.write(' if (direction_weights.z > 0.0) {') - frag.write(' float opac_direction = direction_weights.z;') - frag.write(' voxels[uvw + int3(face_offsets.z, 0, 0))] = float4(opac_direction);') - frag.write(' }') - frag.write('}') - else: - """ - frag.add_uniform('layout(r32ui) uimage3D voxels') - - vert.add_out('vec3 voxpositionGeom') - vert.add_out('vec3 voxnormalGeom') - - vert.write('voxpositionGeom = vec3(W * vec4(pos.xyz, 1.0));') - vert.write('voxnormalGeom = normalize(N * vec3(nor.xy, pos.w));') - - geom.add_out('vec4 voxposition[3]') - geom.add_out('vec3 P') - geom.add_out('vec3 voxnormal') - geom.add_uniform('float clipmaps[voxelgiClipmapCount * 10]', '_clipmaps') - geom.add_uniform('int clipmapLevel', '_clipmapLevel') - - geom.write('vec3 facenormal = abs(voxnormalGeom[0] + voxnormalGeom[1] + voxnormalGeom[2]);') - geom.write('uint maxi = facenormal[1] > facenormal[0] ? 1 : 0;') - geom.write('maxi = facenormal[2] > facenormal[maxi] ? 2 : maxi;') - - geom.write('for (uint i = 0; i < 3; ++i) {') - geom.write(' voxposition[i].xyz = (voxpositionGeom[i] - vec3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)])) / (float(clipmaps[int(clipmapLevel * 10)]));') - geom.write(' if (maxi == 0)') - geom.write(' {') - geom.write(' voxposition[i].xyz = voxposition[i].zyx;') - geom.write(' }') - geom.write(' else if (maxi == 1)') - geom.write(' {') - geom.write(' voxposition[i].xyz = voxposition[i].xzy;') - geom.write(' }') - geom.write('}') - - geom.write('for (uint i = 0; i < 3; ++i) {') - geom.write(' voxposition[i].xy /= voxelgiResolution.xy;') - geom.write(' voxposition[i].zw = vec2(1.0);') - geom.write(' P = voxpositionGeom[i];') - geom.write(' voxnormal = voxnormalGeom[i];') - geom.write(' gl_Position = voxposition[i];') - geom.write(' EmitVertex();') - geom.write('}') - geom.write('EndPrimitive();') - - - frag.add_uniform('float clipmaps[voxelgiClipmapCount * 10]', '_clipmaps') - frag.add_uniform('int clipmapLevel', '_clipmapLevel') - - frag.write('vec3 uvw = (P - vec3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)])) / (float(clipmaps[int(clipmapLevel * 10)]) * voxelgiResolution);') - frag.write('uvw = (uvw * 0.5 + 0.5);') - frag.write('if(any(notEqual(uvw, clamp(uvw, 0.0, 1.0)))) return;') - frag.write('vec3 writecoords = floor(uvw * voxelgiResolution);') - frag.write_attrib('vec3 N = normalize(voxnormal);') - frag.write('vec3 aniso_direction = N;') - frag.write('uvec3 face_offsets = uvec3(') - frag.write(' aniso_direction.x > 0 ? 0 : 1,') - frag.write(' aniso_direction.y > 0 ? 2 : 3,') - frag.write(' aniso_direction.z > 0 ? 4 : 5') - frag.write(' ) * voxelgiResolution;') - frag.write('vec3 direction_weights = abs(N);') - - frag.write('if (direction_weights.x > 0) {') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, 0)), uint(direction_weights.x * 255));') - frag.write('}') - - frag.write('if (direction_weights.y > 0) {') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, 0)), uint(direction_weights.y * 255));') - frag.write('}') - - frag.write('if (direction_weights.z > 0) {') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, 0)), uint(direction_weights.z * 255));') - frag.write('}') - - return con_voxel +""" +Copyright (c) 2024 Turánszki János + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +""" +import bpy + +import lnx.utils +import lnx.assets as assets +import lnx.material.cycles as cycles +import lnx.material.mat_state as mat_state +import lnx.material.mat_utils as mat_utils +import lnx.material.make_particle as make_particle +import lnx.make_state as state + +if lnx.is_reload(__name__): + lnx.utils = lnx.reload_module(lnx.utils) + assets = lnx.reload_module(assets) + mat_state = lnx.reload_module(mat_state) +else: + lnx.enable_reload(__name__) + +def make(context_id): + rpdat = lnx.utils.get_rp() + if rpdat.rp_voxels == 'Voxel GI': + con = make_gi(context_id) + else: + con = make_ao(context_id) + + assets.vs_equal(con, assets.shader_cons['voxel_vert']) + assets.fs_equal(con, assets.shader_cons['voxel_frag']) + assets.gs_equal(con, assets.shader_cons['voxel_geom']) + + return con + +def make_gi(context_id): + con_voxel = mat_state.data.add_context({ 'name': context_id, 'depth_write': False, 'compare_mode': 'always', 'cull_mode': 'none', 'color_write_red': False, 'color_write_green': False, 'color_write_blue': False, 'color_write_alpha': False, 'conservative_raster': True }) + wrd = bpy.data.worlds['Lnx'] + + vert = con_voxel.make_vert() + frag = con_voxel.make_frag() + geom = con_voxel.make_geom() + tesc = None + tese = None + geom.ins = vert.outs + frag.ins = geom.outs + + vert.add_include('compiled.inc') + geom.add_include('compiled.inc') + frag.add_include('compiled.inc') + frag.add_include('std/math.glsl') + frag.add_include('std/imageatomic.glsl') + frag.add_include('std/gbuffer.glsl') + frag.add_include('std/brdf.glsl') + + rpdat = lnx.utils.get_rp() + frag.add_uniform('layout(r32ui) uimage3D voxels') + + frag.write('vec3 n;') + frag.write('vec3 wposition;') + frag.write('vec3 basecol;') + frag.write('float roughness;') # + frag.write('float metallic;') # + frag.write('float occlusion;') # + frag.write('float specular;') # + frag.write('vec3 emissionCol = vec3(0.0);') + blend = mat_state.material.lnx_blending + parse_opacity = blend or mat_utils.is_transluc(mat_state.material) + if parse_opacity: + frag.write('float opacity;') + frag.write('float ior;') + else: + frag.write('float opacity = 1.0;') + + frag.write('float dotNV = 0.0;') + cycles.parse(mat_state.nodes, con_voxel, vert, frag, geom, tesc, tese, parse_opacity=parse_opacity, parse_displacement=False, basecol_only=True) + + # Voxelized particles + particle = mat_state.material.lnx_particle_flag + if particle and rpdat.lnx_particles == 'On': + # make_particle.write(vert, particle_info=cycles.particle_info) + frag.write_pre = True + frag.write('const float p_index = 0;') + frag.write('const float p_age = 0;') + frag.write('const float p_lifetime = 0;') + frag.write('const vec3 p_location = vec3(0);') + frag.write('const float p_size = 0;') + frag.write('const vec3 p_velocity = vec3(0);') + frag.write('const vec3 p_angular_velocity = vec3(0);') + frag.write_pre = False + + export_mpos = frag.contains('mposition') and not frag.contains('vec3 mposition') + if export_mpos: + vert.add_out('vec3 mpositionGeom') + vert.write_pre = True + vert.write('mpositionGeom = pos.xyz;') + vert.write_pre = False + + export_bpos = frag.contains('bposition') and not frag.contains('vec3 bposition') + if export_bpos: + vert.add_out('vec3 bpositionGeom') + vert.add_uniform('vec3 dim', link='_dim') + vert.add_uniform('vec3 hdim', link='_halfDim') + vert.write_pre = True + vert.write('bpositionGeom = (pos.xyz + hdim) / dim;') + vert.write_pre = False + + vert.add_uniform('mat4 W', '_worldMatrix') + vert.add_uniform('mat3 N', '_normalMatrix') + vert.add_out('vec3 voxpositionGeom') + vert.add_out('vec3 voxnormalGeom') + + if con_voxel.is_elem('col'): + vert.add_out('vec3 vcolorGeom') + vert.write('vcolorGeom = col.rgb;') + + if con_voxel.is_elem('tex'): + vert.add_out('vec2 texCoordGeom') + vert.write('texCoordGeom = tex;') + + vert.write('voxpositionGeom = vec3(W * vec4(pos.xyz, 1.0));') + vert.write('voxnormalGeom = normalize(N * vec3(nor.xy, pos.w));') + + geom.add_out('vec4 voxposition[3]') + geom.add_out('vec3 P') + geom.add_out('vec3 voxnormal') + geom.add_out('vec4 lightPosition') + geom.add_out('vec4 spotPosition') + geom.add_out('vec4 wvpposition') + geom.add_out('vec3 eyeDir') + + if con_voxel.is_elem('col'): + geom.add_out('vec3 vcolor') + if con_voxel.is_elem('tex'): + geom.add_out('vec2 texCoord') + if export_mpos: + geom.add_out('vec3 mposition') + if export_bpos: + geom.add_out('vec3 bposition') + + geom.add_uniform('float clipmaps[voxelgiClipmapCount * 10]', '_clipmaps') + geom.add_uniform('int clipmapLevel', '_clipmapLevel') + + geom.write('vec3 facenormal = abs(voxnormalGeom[0] + voxnormalGeom[1] + voxnormalGeom[2]);') + geom.write('uint maxi = facenormal[1] > facenormal[0] ? 1 : 0;') + geom.write('maxi = facenormal[2] > facenormal[maxi] ? 2 : maxi;') + + geom.write('for (uint i = 0; i < 3; ++i) {') + geom.write(' voxposition[i].xyz = (voxpositionGeom[i] - vec3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)])) / (float(clipmaps[int(clipmapLevel * 10)]));') + geom.write(' if (maxi == 0)') + geom.write(' {') + geom.write(' voxposition[i].xyz = voxposition[i].zyx;') + geom.write(' }') + geom.write(' else if (maxi == 1)') + geom.write(' {') + geom.write(' voxposition[i].xyz = voxposition[i].xzy;') + geom.write(' }') + geom.write('}') + + geom.write('for (uint i = 0; i < 3; ++i) {') + geom.write(' voxposition[i].xy /= voxelgiResolution.xy;') + geom.write(' voxposition[i].zw = vec2(1.0);') + geom.write(' P = voxpositionGeom[i];') + geom.write(' voxnormal = voxnormalGeom[i];') + if con_voxel.is_elem('col'): + geom.write('vcolor = vcolorGeom[i];') + if con_voxel.is_elem('tex'): + geom.write('texCoord = texCoordGeom[i];') + if export_mpos: + geom.write('mposition = mpositionGeom[i];') + if export_bpos: + geom.write('bposition = bpositionGeom[i];') + geom.write(' eyeDir = eyeDirGeom[i];') + geom.write(' gl_Position = voxposition[i];') + geom.write(' EmitVertex();') + geom.write('}') + geom.write('EndPrimitive();') + + frag.add_uniform('float clipmaps[voxelgiClipmapCount * 10]', '_clipmaps') + frag.add_uniform('int clipmapLevel', '_clipmapLevel') + + frag.write('vec3 uvw = (P - vec3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)])) / (float(clipmaps[int(clipmapLevel * 10)]) * voxelgiResolution);') + frag.write('uvw = (uvw * 0.5 + 0.5);') + frag.write('if(any(notEqual(uvw, clamp(uvw, 0.0, 1.0)))) return;') + frag.write('vec3 writecoords = floor(uvw * voxelgiResolution);') + frag.write_attrib('vec3 N = normalize(voxnormal);') + frag.write('vec3 aniso_direction = N;') + frag.write('uvec3 face_offsets = uvec3(') + frag.write(' aniso_direction.x > 0 ? 0 : 1,') + frag.write(' aniso_direction.y > 0 ? 2 : 3,') + frag.write(' aniso_direction.z > 0 ? 4 : 5') + frag.write(' ) * voxelgiResolution;') + frag.write('vec3 direction_weights = abs(N);') + + frag.write('vec3 albedo = surfaceAlbedo(basecol, metallic);') + frag.write('vec3 f0 = surfaceF0(basecol, metallic);') + + vert.add_uniform('vec3 eye', '_cameraPosition') + vert.add_out('vec3 eyeDirGeom') + vert.write('eyeDirGeom = eye - pos.xyz;') + + if '_Brdf' in wrd.world_defs: + frag.add_uniform('sampler2D senvmapBrdf', link='$brdf.png') + frag.write('vec2 envBRDF = texelFetch(senvmapBrdf, ivec2(vec2(dotNV, 1.0 - roughness) * 256.0), 0).xy;') + + if '_Irr' in wrd.world_defs: + frag.add_include('std/shirr.glsl') + frag.add_uniform('vec4 shirr[7]', link='_envmapIrradiance') + frag.write('vec3 envl = shIrradiance(voxnormal, shirr);') + if '_EnvTex' in wrd.world_defs: + frag.write('envl /= PI;') + else: + frag.write('vec3 envl = vec3(0.0);') + + if '_Rad' in wrd.world_defs: + frag.add_uniform('sampler2D senvmapRadiance', link='_envmapRadiance') + frag.add_uniform('int envmapNumMipmaps', link='_envmapNumMipmaps') + frag.write('vec3 reflectionWorld = reflect(-normalize(eyeDir), voxnormal);') + frag.write('float lod = getMipFromRoughness(roughness, envmapNumMipmaps);') + frag.write('vec3 prefilteredColor = textureLod(senvmapRadiance, envMapEquirect(reflectionWorld), lod).rgb;') + + if '_EnvLDR' in wrd.world_defs: + frag.write('envl = pow(envl, vec3(2.2));') + if '_Rad' in wrd.world_defs: + frag.write('prefilteredColor = pow(prefilteredColor, vec3(2.2));') + + frag.write('envl *= albedo;') + + if '_Brdf' in wrd.world_defs: + frag.write('envl.rgb *= 1.0 - (f0 * envBRDF.x + envBRDF.y);') + if '_Rad' in wrd.world_defs: + frag.write('envl += prefilteredColor * (f0 * envBRDF.x + envBRDF.y);') + elif '_EnvCol' in wrd.world_defs: + frag.add_uniform('vec3 backgroundCol', link='_backgroundCol') + frag.write('envl += backgroundCol * (f0 * envBRDF.x + envBRDF.y);') + + frag.add_uniform('float envmapStrength', link='_envmapStrength') + frag.write('envl *= envmapStrength * occlusion;') + + frag.write('if (direction_weights.x > 0) {') + frag.write(' vec4 basecol_direction = vec4(basecol * direction_weights.x, 1.0);') + frag.write(' vec3 emission_direction = emissionCol * direction_weights.x;') + frag.write(' vec2 normal_direction = encode_oct(N * direction_weights.x) * 0.5 + 0.5;') + frag.write(' vec3 envl_direction = envl * direction_weights.x;') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, 0)), uint(basecol_direction.r * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x)), uint(basecol_direction.g * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 2)), uint(basecol_direction.b * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 3)), uint(basecol_direction.a * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 4)), uint(emission_direction.r * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 5)), uint(emission_direction.g * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 6)), uint(emission_direction.b * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 7)), uint(normal_direction.r * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 8)), uint(normal_direction.g * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 9)), uint(envl_direction.r * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 10)), uint(envl_direction.g * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 11)), uint(envl_direction.b * 255));') + frag.write('}') + + frag.write('if (direction_weights.y > 0) {') + frag.write(' vec4 basecol_direction = vec4(basecol * direction_weights.y, 1.0);') + frag.write(' vec3 emission_direction = emissionCol * direction_weights.y;') + frag.write(' vec2 normal_direction = encode_oct(N * direction_weights.y) * 0.5 + 0.5;') + frag.write(' vec3 envl_direction = envl * direction_weights.y;') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, 0)), uint(basecol_direction.r * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x)), uint(basecol_direction.g * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 2)), uint(basecol_direction.b * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 3)), uint(basecol_direction.a * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 4)), uint(emission_direction.r * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 5)), uint(emission_direction.g * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 6)), uint(emission_direction.b * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 7)), uint(normal_direction.r * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 8)), uint(normal_direction.g * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 9)), uint(envl_direction.r * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 10)), uint(envl_direction.g * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 11)), uint(envl_direction.b * 255));') + frag.write('}') + + frag.write('if (direction_weights.z > 0) {') + frag.write(' vec4 basecol_direction = vec4(basecol * direction_weights.z, 1.0);') + frag.write(' vec3 emission_direction = emissionCol * direction_weights.z;') + frag.write(' vec2 normal_direction = encode_oct(n * direction_weights.z) * 0.5 + 0.5;') + frag.write(' vec3 envl_direction = envl * direction_weights.z;') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, 0)), uint(basecol_direction.r * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x)), uint(basecol_direction.g * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 2)), uint(basecol_direction.b * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 3)), uint(basecol_direction.a * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 4)), uint(emission_direction.r * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 5)), uint(emission_direction.g * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 6)), uint(emission_direction.b * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 7)), uint(normal_direction.r * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 8)), uint(normal_direction.g * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 9)), uint(envl_direction.r * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 10)), uint(envl_direction.g * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 11)), uint(envl_direction.b * 255));') + frag.write('}') + + return con_voxel + + +def make_ao(context_id): + con_voxel = mat_state.data.add_context({ 'name': context_id, 'depth_write': False, 'compare_mode': 'always', 'cull_mode': 'none', 'color_writes_red': [False], 'color_writes_green': [False], 'color_writes_blue': [False], 'color_writes_alpha': [False], 'conservative_raster': False }) + wrd = bpy.data.worlds['Lnx'] + rpdat = lnx.utils.get_rp() + + vert = con_voxel.make_vert() + frag = con_voxel.make_frag() + geom = con_voxel.make_geom() + tesc = None + tese = None + + geom.ins = vert.outs + frag.ins = geom.outs + + frag.add_include('compiled.inc') + geom.add_include('compiled.inc') + frag.add_include('std/math.glsl') + frag.add_include('std/imageatomic.glsl') + frag.write_header('#extension GL_ARB_shader_image_load_store : enable') + + vert.add_include('compiled.inc') + vert.add_uniform('mat4 W', '_worldMatrix') + vert.add_uniform('mat3 N', '_normalMatrix') + + geom.add_uniform('float clipmaps[voxelgiClipmapCount * 10]', '_clipmaps') + geom.add_uniform('int clipmapLevel', '_clipmapLevel') + + frag.add_uniform('float clipmaps[voxelgiClipmapCount * 10]', '_clipmaps') + frag.add_uniform('int clipmapLevel', '_clipmapLevel') + + """ + if lnx.utils.get_gapi() == 'direct3d11': + for e in con_voxel.data['vertex_elements']: + if e['name'] == 'nor': + con_voxel.data['vertex_elements'].remove(e) + break + + vert.write('uniform float4x4 W;') + vert.write('uniform float3x3 N;') + vert.write('struct SPIRV_Cross_Input {') + vert.write(' float4 pos : TEXCOORD0;') + vert.write(' float3 nor : NORMAL;') + vert.write('};') + vert.write('struct SPIRV_Cross_Output {') + vert.write(' float4 svpos : SV_POSITION;') + vert.write(' float3 svnor : NORMAL;') + vert.write('};') + vert.write('SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input) {') + vert.write(' SPIRV_Cross_Output stage_output;') + vert.write(' stage_output.svpos.xyz = mul(float4(stage_input.pos.xyz, 1.0), W).xyz;') + vert.write(' stage_output.svpos.w = 1.0;') + vert.write(' stage_output.svnor.xyz = normalize(mul(float3(nor.xy, pos.w), N).xyz);') + vert.write(' return stage_output;') + vert.write('}') + + geom.write('uniform float clipmaps[voxelgiClipmapCount * 10];') + geom.write('uniform int clipmapLevel;') + geom.write('struct SPIRV_Cross_Input {') + geom.write(' float4 svpos : SV_POSITION;') + geom.write(' float3 svnor : NORMAL;') + geom.write('};') + geom.write('struct SPIRV_Cross_Output {') + geom.write(' float3 wpos : TEXCOORD0;') + geom.write(' float3 wnor : NORMAL;') + geom.write('};') + geom.write('[maxvertexcount(3)]') + geom.write('void main(triangle SPIRV_Cross_Input stage_input[3], inout TriangleStream output) {') + geom.write(' float3 p1 = stage_input[1].svpos.xyz - stage_input[0].svpos.xyz;') + geom.write(' float3 p2 = stage_input[2].svpos.xyz - stage_input[0].svpos.xyz;') + geom.write(' float3 p = abs(cross(p1, p2));') + geom.write(' for (int i = 0; i < 3; ++i) {') + geom.write(' SPIRV_Cross_Output stage_output;') + geom.write(' stage_output.wpos = (stage_input[i].svpos.xyz + float3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)])) / (float(clipmaps[clipmapLevel * 10]) * voxelgiResolution);') + geom.write(' stage_output.wnor = stage_input[i].svnor.xyz;') + geom.write(' if (p.z > p.x && p.z > p.y) {') + geom.write(' stage_output.svpos = float4(stage_input[i].svpos.x, stage_input[i].svpos.y, 0.0, 1.0);') + geom.write(' }') + geom.write(' else if (p.x > p.y && p.x > p.z) {') + geom.write(' stage_output.svpos = float4(stage_input[i].svpos.y, stage_input[i].svpos.z, 0.0, 1.0);') + geom.write(' }') + geom.write(' else {') + geom.write(' stage_output.svpos = float4(stage_input[i].svpos.x, stage_input[i].svpos.z, 0.0, 1.0);') + geom.write(' }') + geom.write(' output.Append(stage_output);') + geom.write(' }') + geom.write('}') + + frag.add_uniform('layout(r8) writeonly image3D voxels') + frag.write('RWTexture3D voxels;') + frag.write('uniform float clipmaps[voxelgiClipmapCount * 10];') + frag.write('uniform int clipmapLevel;') + + frag.write('struct SPIRV_Cross_Input {') + frag.write(' float3 wpos : TEXCOORD0;') + frag.write(' float3 wnor : NORMAL;') + frag.write('};') + frag.write('struct SPIRV_Cross_Output { float4 FragColor : SV_TARGET0; };') + frag.write('void main(SPIRV_Cross_Input stage_input) {') + frag.write(' float3 uvw = (stage_input.wpos.xyz - float3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)])) / (float(clipmaps[int(clipmapLevel * 10)]) * voxelgiResolution);') + frag.write(' uvw = uvw * 0.5 + 0.5;') + frag.write(' if(any(!saturate(uvw))) return;') + frag.write(' uvw = floor(uvw * voxelgiResolution);') + frag.write(' uint3 face_offsets = uint3(') + frag.write(' stage_input.wnor.x > 0 ? 0 : 1,') + frag.write(' stage_input.wnor.y > 0 ? 2 : 3,') + frag.write(' stage_input.wnor.z > 0 ? 4 : 5') + frag.write(' ) * voxelgiResolution;') + frag.write(' float3 direction_weights = abs(stage_input.wnor);') + + frag.write(' if (direction_weights.x > 0.0) {') + frag.write(' float opac_direction = direction_weights.x;') + frag.write(' voxels[uvw + int3(face_offsets.x, 0, 0))] = float4(opac_direction);') + frag.write(' }') + + frag.write(' if (direction_weights.y > 0.0) {') + frag.write(' float opac_direction = direction_weights.y;') + frag.write(' voxels[uvw + int3(face_offsets.y, 0, 0))] = float4(opac_direction);') + frag.write(' }') + + frag.write(' if (direction_weights.z > 0.0) {') + frag.write(' float opac_direction = direction_weights.z;') + frag.write(' voxels[uvw + int3(face_offsets.z, 0, 0))] = float4(opac_direction);') + frag.write(' }') + frag.write('}') + else: + """ + frag.add_uniform('layout(r32ui) uimage3D voxels') + + vert.add_out('vec3 voxpositionGeom') + vert.add_out('vec3 voxnormalGeom') + + vert.write('voxpositionGeom = vec3(W * vec4(pos.xyz, 1.0));') + vert.write('voxnormalGeom = normalize(N * vec3(nor.xy, pos.w));') + + geom.add_out('vec4 voxposition[3]') + geom.add_out('vec3 P') + geom.add_out('vec3 voxnormal') + geom.add_uniform('float clipmaps[voxelgiClipmapCount * 10]', '_clipmaps') + geom.add_uniform('int clipmapLevel', '_clipmapLevel') + + geom.write('vec3 facenormal = abs(voxnormalGeom[0] + voxnormalGeom[1] + voxnormalGeom[2]);') + geom.write('uint maxi = facenormal[1] > facenormal[0] ? 1 : 0;') + geom.write('maxi = facenormal[2] > facenormal[maxi] ? 2 : maxi;') + + geom.write('for (uint i = 0; i < 3; ++i) {') + geom.write(' voxposition[i].xyz = (voxpositionGeom[i] - vec3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)])) / (float(clipmaps[int(clipmapLevel * 10)]));') + geom.write(' if (maxi == 0)') + geom.write(' {') + geom.write(' voxposition[i].xyz = voxposition[i].zyx;') + geom.write(' }') + geom.write(' else if (maxi == 1)') + geom.write(' {') + geom.write(' voxposition[i].xyz = voxposition[i].xzy;') + geom.write(' }') + geom.write('}') + + geom.write('for (uint i = 0; i < 3; ++i) {') + geom.write(' voxposition[i].xy /= voxelgiResolution.xy;') + geom.write(' voxposition[i].zw = vec2(1.0);') + geom.write(' P = voxpositionGeom[i];') + geom.write(' voxnormal = voxnormalGeom[i];') + geom.write(' gl_Position = voxposition[i];') + geom.write(' EmitVertex();') + geom.write('}') + geom.write('EndPrimitive();') + + + frag.add_uniform('float clipmaps[voxelgiClipmapCount * 10]', '_clipmaps') + frag.add_uniform('int clipmapLevel', '_clipmapLevel') + + frag.write('vec3 uvw = (P - vec3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)])) / (float(clipmaps[int(clipmapLevel * 10)]) * voxelgiResolution);') + frag.write('uvw = (uvw * 0.5 + 0.5);') + frag.write('if(any(notEqual(uvw, clamp(uvw, 0.0, 1.0)))) return;') + frag.write('vec3 writecoords = floor(uvw * voxelgiResolution);') + frag.write_attrib('vec3 N = normalize(voxnormal);') + frag.write('vec3 aniso_direction = N;') + frag.write('uvec3 face_offsets = uvec3(') + frag.write(' aniso_direction.x > 0 ? 0 : 1,') + frag.write(' aniso_direction.y > 0 ? 2 : 3,') + frag.write(' aniso_direction.z > 0 ? 4 : 5') + frag.write(' ) * voxelgiResolution;') + frag.write('vec3 direction_weights = abs(N);') + + frag.write('if (direction_weights.x > 0) {') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, 0)), uint(direction_weights.x * 255));') + frag.write('}') + + frag.write('if (direction_weights.y > 0) {') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, 0)), uint(direction_weights.y * 255));') + frag.write('}') + + frag.write('if (direction_weights.z > 0) {') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, 0)), uint(direction_weights.z * 255));') + frag.write('}') + + return con_voxel From 5d78eabf94fbd3894d5f4c07f1120d296b831a71 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Mon, 7 Apr 2025 16:39:49 +0000 Subject: [PATCH 022/136] Update leenkx/blender/lnx/material/cycles_nodes/nodes_texture.py --- leenkx/blender/lnx/material/cycles_nodes/nodes_texture.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/leenkx/blender/lnx/material/cycles_nodes/nodes_texture.py b/leenkx/blender/lnx/material/cycles_nodes/nodes_texture.py index 7170309..e90627d 100644 --- a/leenkx/blender/lnx/material/cycles_nodes/nodes_texture.py +++ b/leenkx/blender/lnx/material/cycles_nodes/nodes_texture.py @@ -331,9 +331,6 @@ def parse_sky_hosekwilkie(node: bpy.types.ShaderNodeTexSky, state: ParserState) world = state.world curshader = state.curshader - # Match to cycles - world.lnx_envtex_strength *= 0.1 - assets.add_khafile_def('lnx_hosek') curshader.add_uniform('vec3 A', link="_hosekA") curshader.add_uniform('vec3 B', link="_hosekB") From 6b8585c81a83c6f355f26fa1e888a024db93dc71 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Mon, 7 Apr 2025 16:43:01 +0000 Subject: [PATCH 023/136] Update leenkx/blender/lnx/props_renderpath.py --- leenkx/blender/lnx/props_renderpath.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/leenkx/blender/lnx/props_renderpath.py b/leenkx/blender/lnx/props_renderpath.py index ee3fa75..30d5942 100644 --- a/leenkx/blender/lnx/props_renderpath.py +++ b/leenkx/blender/lnx/props_renderpath.py @@ -65,7 +65,7 @@ def update_preset(self, context): rpdat.rp_background = 'World' rpdat.rp_stereo = False rpdat.rp_voxelgi_resolution = '32' - rpdat.lnx_voxelgi_size = 0.25 + rpdat.lnx_voxelgi_size = 0.125 rpdat.rp_voxels = 'Voxel AO' rpdat.rp_render_to_texture = True rpdat.rp_supersampling = '1' @@ -142,8 +142,8 @@ def update_preset(self, context): rpdat.rp_stereo = False rpdat.rp_voxels = 'Voxel GI' rpdat.rp_voxelgi_resolution = '64' - rpdat.lnx_voxelgi_size = 0.25 - rpdat.lnx_voxelgi_step = 0.25 + rpdat.lnx_voxelgi_size = 0.125 + rpdat.lnx_voxelgi_step = 0.01 rpdat.lnx_voxelgi_revoxelize = False rpdat.lnx_voxelgi_camera = False rpdat.rp_voxelgi_emission = False @@ -531,7 +531,7 @@ class LnxRPListItem(bpy.types.PropertyGroup): lnx_voxelgi_shad: FloatProperty(name="Shadows", description="Contrast for voxels shadows", default=1.0, update=assets.invalidate_shader_cache) lnx_voxelgi_occ: FloatProperty(name="Occlusion", description="", default=1.0, update=assets.invalidate_shader_cache) lnx_voxelgi_size: FloatProperty(name="Size", description="Voxel size", default=0.25, update=assets.invalidate_shader_cache) - lnx_voxelgi_step: FloatProperty(name="Step", description="Step size", default=0.25, update=assets.invalidate_shader_cache) + lnx_voxelgi_step: FloatProperty(name="Step", description="Step size", default=1.0, update=assets.invalidate_shader_cache) lnx_voxelgi_range: FloatProperty(name="Range", description="Maximum range", default=100.0, update=assets.invalidate_shader_cache) lnx_voxelgi_offset: FloatProperty(name="Offset", description="Multiplicative Offset for dealing with self occlusion", default=1.0, update=assets.invalidate_shader_cache) lnx_voxelgi_aperture: FloatProperty(name="Aperture", description="Cone aperture for shadow trace", default=0.0, update=assets.invalidate_shader_cache) From 02259985be7a3812616cd591996dc134f1504241 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Mon, 7 Apr 2025 16:46:33 +0000 Subject: [PATCH 024/136] Update leenkx/blender/lnx/props.py --- leenkx/blender/lnx/props.py | 1 + 1 file changed, 1 insertion(+) diff --git a/leenkx/blender/lnx/props.py b/leenkx/blender/lnx/props.py index 98655d2..429aa48 100644 --- a/leenkx/blender/lnx/props.py +++ b/leenkx/blender/lnx/props.py @@ -287,6 +287,7 @@ def init_properties(): name="Assertion Level", description="Ignore all assertions below this level (assertions are turned off completely for published builds)", default='Warning', update=assets.invalidate_compiler_cache) bpy.types.World.lnx_assert_quit = BoolProperty(name="Quit On Assertion Fail", description="Whether to close the game when an 'Error' level assertion fails", default=False, update=assets.invalidate_compiler_cache) bpy.types.World.lnx_live_patch = BoolProperty(name="Live Patch", description="Live patching for Krom", default=False) + bpy.types.World.lnx_render_viewport = BoolProperty(name="Viewport Render", description="Viewport rendering", default=False) bpy.types.World.lnx_clear_on_compile = BoolProperty(name="Clear Console", description="Clears the system console on compile", default=False) bpy.types.World.lnx_play_camera = EnumProperty( items=[('Scene', 'Scene', 'Scene'), From 07f59224fc317550586661b0ae50b8779159d3ee Mon Sep 17 00:00:00 2001 From: Onek8 Date: Mon, 7 Apr 2025 16:50:46 +0000 Subject: [PATCH 025/136] Update leenkx/blender/lnx/write_data.py --- leenkx/blender/lnx/write_data.py | 33 ++++++++------------------------ 1 file changed, 8 insertions(+), 25 deletions(-) diff --git a/leenkx/blender/lnx/write_data.py b/leenkx/blender/lnx/write_data.py index 9164514..8c752ff 100644 --- a/leenkx/blender/lnx/write_data.py +++ b/leenkx/blender/lnx/write_data.py @@ -207,6 +207,8 @@ project.addSources('Sources'); # get instantiated khafile.write("""project.addParameter("--macro include('leenkx.logicnode')");\n""") + if wrd.lnx_render_viewport: + assets.add_khafile_def('lnx_render_viewport') import_traits = list(set(import_traits)) for i in range(0, len(import_traits)): khafile.write("project.addParameter('" + import_traits[i] + "');\n") @@ -624,32 +626,13 @@ def write_compiledglsl(defs, make_variants): idx_emission = 2 idx_refraction = 2 - if '_gbuffer2' in wrd.world_defs: - f.write('#define GBUF_IDX_2 2\n') - idx_emission += 1 - idx_refraction += 1 - - # Special case for WebGL with both TAA and SSRefraction - webgl_with_taa_refr = ('_kha_webgl' in wrd.world_defs and - ('_SSRefraction' in wrd.world_defs or '_VoxelRefract' in wrd.world_defs) and - ('_TAA' in wrd.world_defs or '_SMAA' in wrd.world_defs)) - - if webgl_with_taa_refr: - # WebGL needs refraction to come before emission for correct rendering - if '_SSRefraction' in wrd.world_defs or '_VoxelRefract' in wrd.world_defs: - f.write(f'#define GBUF_IDX_REFRACTION {idx_emission}\n') - idx_emission += 1 - - if '_EmissionShaded' in wrd.world_defs: - f.write(f'#define GBUF_IDX_EMISSION {idx_emission}\n') - else: - # Standard order for all other platforms - if '_EmissionShaded' in wrd.world_defs: - f.write(f'#define GBUF_IDX_EMISSION {idx_emission}\n') - idx_refraction += 1 - if '_SSRefraction' in wrd.world_defs or '_VoxelRefract' in wrd.world_defs: - f.write(f'#define GBUF_IDX_REFRACTION {idx_refraction}\n') + if '_EmissionShaded' in wrd.world_defs: + f.write(f'#define GBUF_IDX_EMISSION {idx_emission}\n') + idx_refraction += 1 + + if '_SSRefraction' in wrd.world_defs or '_VoxelRefract' in wrd.world_defs: + f.write(f'#define GBUF_IDX_REFRACTION {idx_refraction}\n') f.write("""#if defined(HLSL) || defined(METAL) #define _InvY From 95f0ecfc542462dd86a11684f1187760425967a4 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Mon, 7 Apr 2025 17:07:52 +0000 Subject: [PATCH 026/136] Update leenkx/Sources/leenkx/system/Starter.hx --- leenkx/Sources/leenkx/system/Starter.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/leenkx/Sources/leenkx/system/Starter.hx b/leenkx/Sources/leenkx/system/Starter.hx index cb1f9d9..1d2ad02 100644 --- a/leenkx/Sources/leenkx/system/Starter.hx +++ b/leenkx/Sources/leenkx/system/Starter.hx @@ -42,7 +42,7 @@ class Starter { #end kha.System.start({title: Main.projectName, width: c.window_w, height: c.window_h, window: { - #if arm_render_viewport + #if lnx_render_viewport visible: false, #end mode: windowMode, windowFeatures: windowFeatures}, framebuffer: {samplesPerPixel: c.window_msaa, verticalSync: c.window_vsync}}, function(window: kha.Window) { From a2d03cfe6e4b6de2b7afc44cc2c34c2193d756db Mon Sep 17 00:00:00 2001 From: Onek8 Date: Mon, 7 Apr 2025 17:26:00 +0000 Subject: [PATCH 027/136] Update leenkx/Shaders/std/light.glsl --- leenkx/Shaders/std/light.glsl | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/leenkx/Shaders/std/light.glsl b/leenkx/Shaders/std/light.glsl index e5e2416..649af61 100644 --- a/leenkx/Shaders/std/light.glsl +++ b/leenkx/Shaders/std/light.glsl @@ -9,11 +9,9 @@ #endif #ifdef _VoxelShadow #include "std/conetrace.glsl" -uniform sampler2D gbuffer2; -#else -#ifdef _VoxelGI -uniform sampler2D gbuffer2; #endif +#ifdef _gbuffer2 +uniform sampler2D gbuffer2; #endif #ifdef _LTC #include "std/ltc.glsl" From bf7b4416ec16759402cfa7a762ca0631d9c325f2 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Mon, 7 Apr 2025 17:29:09 +0000 Subject: [PATCH 028/136] Update leenkx/blender/lnx/make_renderpath.py --- leenkx/blender/lnx/make_renderpath.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/leenkx/blender/lnx/make_renderpath.py b/leenkx/blender/lnx/make_renderpath.py index bb2dca6..7e5b707 100644 --- a/leenkx/blender/lnx/make_renderpath.py +++ b/leenkx/blender/lnx/make_renderpath.py @@ -302,8 +302,8 @@ def build(): assets.add_khafile_def('rp_ssgi={0}'.format(rpdat.rp_ssgi)) if rpdat.rp_ssgi != 'Off': - wrd.world_defs += '_SSAO' if rpdat.rp_ssgi == 'SSAO': + wrd.world_defs += '_SSAO' assets.add_shader_pass('ssao_pass') assets.add_shader_pass('blur_edge_pass') else: From 0979cd976f17e240999415b2d936156db1336137 Mon Sep 17 00:00:00 2001 From: LeenkxTeam Date: Fri, 11 Apr 2025 22:20:24 +0000 Subject: [PATCH 029/136] Update leenkx/blender/lnx/write_data.py --- leenkx/blender/lnx/write_data.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/leenkx/blender/lnx/write_data.py b/leenkx/blender/lnx/write_data.py index aa07825..f92cea4 100644 --- a/leenkx/blender/lnx/write_data.py +++ b/leenkx/blender/lnx/write_data.py @@ -626,6 +626,11 @@ def write_compiledglsl(defs, make_variants): idx_emission = 2 idx_refraction = 2 + + if '_gbuffer2' in wrd.world_defs: + f.write('#define GBUF_IDX_2 2\n') + idx_emission += 1 + idx_refraction += 1 if '_EmissionShaded' in wrd.world_defs: f.write(f'#define GBUF_IDX_EMISSION {idx_emission}\n') From 1d705d2ca2d247044e3ba32481b00d13552f653f Mon Sep 17 00:00:00 2001 From: Onek8 Date: Sat, 12 Apr 2025 08:48:33 +0000 Subject: [PATCH 030/136] Update leenkx/blender/lnx/material/make_cluster.py --- leenkx/blender/lnx/material/make_cluster.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/leenkx/blender/lnx/material/make_cluster.py b/leenkx/blender/lnx/material/make_cluster.py index 7e21c93..ed3ac3e 100644 --- a/leenkx/blender/lnx/material/make_cluster.py +++ b/leenkx/blender/lnx/material/make_cluster.py @@ -102,9 +102,10 @@ def write(vert: shader.Shader, frag: shader.Shader): if '_MicroShadowing' in wrd.world_defs and not is_mobile: frag.write('\t, occlusion') if '_SSRS' in wrd.world_defs: + frag.add_uniform('sampler2D gbufferD', top=True) frag.add_uniform('mat4 invVP', '_inverseViewProjectionMatrix') frag.add_uniform('vec3 eye', '_cameraPosition') - frag.write(', wposition.z, inVP, eye') + frag.write(', wposition.z, invVP, eye') frag.write(');') frag.write('}') # for numLights From 96f4e2977818e0e7b1a366abcc3baa5ad1c2809a Mon Sep 17 00:00:00 2001 From: Onek8 Date: Sat, 12 Apr 2025 08:49:04 +0000 Subject: [PATCH 031/136] Update leenkx/blender/lnx/material/make_mesh.py --- leenkx/blender/lnx/material/make_mesh.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/leenkx/blender/lnx/material/make_mesh.py b/leenkx/blender/lnx/material/make_mesh.py index 600c16e..0dd13c0 100644 --- a/leenkx/blender/lnx/material/make_mesh.py +++ b/leenkx/blender/lnx/material/make_mesh.py @@ -790,9 +790,10 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): if '_MicroShadowing' in wrd.world_defs: frag.write(', occlusion') if '_SSRS' in wrd.world_defs: + frag.add_uniform('sampler2D gbufferD', top=True) frag.add_uniform('mat4 invVP', '_inverseViewProjectionMatrix') frag.add_uniform('vec3 eye', '_cameraPosition') - frag.write(', wposition.z, inVP, eye') + frag.write(', wposition.z, invVP, eye') frag.write(');') if '_Clusters' in wrd.world_defs: From d88e1f0f426adc5e92aa9ae4c8e5122d36a3c132 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Fri, 18 Apr 2025 22:52:03 +0000 Subject: [PATCH 032/136] Update leenkx/blender/lnx/material/make_cluster.py --- leenkx/blender/lnx/material/make_cluster.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/leenkx/blender/lnx/material/make_cluster.py b/leenkx/blender/lnx/material/make_cluster.py index ed3ac3e..23e79f7 100644 --- a/leenkx/blender/lnx/material/make_cluster.py +++ b/leenkx/blender/lnx/material/make_cluster.py @@ -105,7 +105,7 @@ def write(vert: shader.Shader, frag: shader.Shader): frag.add_uniform('sampler2D gbufferD', top=True) frag.add_uniform('mat4 invVP', '_inverseViewProjectionMatrix') frag.add_uniform('vec3 eye', '_cameraPosition') - frag.write(', wposition.z, invVP, eye') + frag.write(', gbufferD, invVP, eye') frag.write(');') frag.write('}') # for numLights From 9bf83bc49ffff6b297b5051d1304aa0515edca8a Mon Sep 17 00:00:00 2001 From: Onek8 Date: Fri, 18 Apr 2025 22:52:53 +0000 Subject: [PATCH 033/136] Update leenkx/blender/lnx/material/make_mesh.py --- leenkx/blender/lnx/material/make_mesh.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/leenkx/blender/lnx/material/make_mesh.py b/leenkx/blender/lnx/material/make_mesh.py index 0dd13c0..3df06bf 100644 --- a/leenkx/blender/lnx/material/make_mesh.py +++ b/leenkx/blender/lnx/material/make_mesh.py @@ -793,7 +793,7 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): frag.add_uniform('sampler2D gbufferD', top=True) frag.add_uniform('mat4 invVP', '_inverseViewProjectionMatrix') frag.add_uniform('vec3 eye', '_cameraPosition') - frag.write(', wposition.z, invVP, eye') + frag.write(', gbufferD, invVP, eye') frag.write(');') if '_Clusters' in wrd.world_defs: From 99f687b10cdd8e796b39898730de8c3627f3b078 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Tue, 20 May 2025 23:55:32 +0000 Subject: [PATCH 034/136] Update leenkx/Shaders/std/constants.glsl --- leenkx/Shaders/std/{voxels_constants.glsl => constants.glsl} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename leenkx/Shaders/std/{voxels_constants.glsl => constants.glsl} (100%) diff --git a/leenkx/Shaders/std/voxels_constants.glsl b/leenkx/Shaders/std/constants.glsl similarity index 100% rename from leenkx/Shaders/std/voxels_constants.glsl rename to leenkx/Shaders/std/constants.glsl From 76628fc0109786c67d232400fb03122d0b0fdbff Mon Sep 17 00:00:00 2001 From: Onek8 Date: Tue, 20 May 2025 23:57:25 +0000 Subject: [PATCH 035/136] Add leenkx/Shaders/std/aabb.glsl --- leenkx/Shaders/std/aabb.glsl | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 leenkx/Shaders/std/aabb.glsl diff --git a/leenkx/Shaders/std/aabb.glsl b/leenkx/Shaders/std/aabb.glsl new file mode 100644 index 0000000..2743684 --- /dev/null +++ b/leenkx/Shaders/std/aabb.glsl @@ -0,0 +1,18 @@ +#ifndef _AABB_GLSL +#define _AABB_GLSL + +bool IntersectAABB(vec3[2] a, vec3[2] b) { + const float EPSILON = 0.001; // Small tolerance to prevent false negatives + if (abs(a[0].x - b[0].x) > (a[1].x + b[1].x + EPSILON)) return false; + if (abs(a[0].y - b[0].y) > (a[1].y + b[1].y + EPSILON)) return false; + if (abs(a[0].z - b[0].z) > (a[1].z + b[1].z + EPSILON)) return false; + return true; +} + +void AABBfromMinMax(inout vec3[2] aabb, vec3 _min, vec3 _max) +{ + aabb[0] = (_min + _max) * 0.5f; + aabb[1] = abs(_max - aabb[0]); +} + +#endif \ No newline at end of file From 6b423038d4a7229243ecea7fbca821e9bc8deff1 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 21 May 2025 00:00:02 +0000 Subject: [PATCH 036/136] Delete leenkx/Shaders/voxel_light/voxel_light.comp.glsl --- .../Shaders/voxel_light/voxel_light.comp.glsl | 137 ------------------ 1 file changed, 137 deletions(-) delete mode 100644 leenkx/Shaders/voxel_light/voxel_light.comp.glsl diff --git a/leenkx/Shaders/voxel_light/voxel_light.comp.glsl b/leenkx/Shaders/voxel_light/voxel_light.comp.glsl deleted file mode 100644 index 005a3c1..0000000 --- a/leenkx/Shaders/voxel_light/voxel_light.comp.glsl +++ /dev/null @@ -1,137 +0,0 @@ -#version 450 - -layout (local_size_x = 8, local_size_y = 8, local_size_z = 8) in; - -#include "compiled.inc" -#include "std/math.glsl" -#include "std/gbuffer.glsl" -#include "std/imageatomic.glsl" -#ifdef _VoxelShadow -#include "std/conetrace.glsl" -#endif - -uniform vec3 lightPos; -uniform vec3 lightColor; -uniform int lightType; -uniform vec3 lightDir; -uniform vec2 spotData; -#ifdef _ShadowMap -uniform int lightShadow; -uniform vec2 lightProj; -uniform float shadowsBias; -uniform mat4 LVP; -#ifdef _ShadowMapAtlas -uniform int index; -uniform vec4 pointLightDataArray[maxLightsCluster * 6]; -#endif -#endif - -uniform float clipmaps[voxelgiClipmapCount * 10]; -uniform int clipmapLevel; - -uniform layout(r32ui) uimage3D voxelsLight; - -#ifdef _ShadowMap -uniform sampler2DShadow shadowMap; -uniform sampler2D shadowMapTransparent; -uniform sampler2DShadow shadowMapSpot; -#ifdef _ShadowMapAtlas -uniform sampler2DShadow shadowMapPoint; -#else -uniform samplerCubeShadow shadowMapPoint; -#endif -#endif - -#ifdef _ShadowMapAtlas -// https://www.khronos.org/registry/OpenGL/specs/gl/glspec20.pdf // p:168 -// https://www.gamedev.net/forums/topic/687535-implementing-a-cube-map-lookup-function/5337472/ -vec2 sampleCube(vec3 dir, out int faceIndex) { - vec3 dirAbs = abs(dir); - float ma; - vec2 uv; - if(dirAbs.z >= dirAbs.x && dirAbs.z >= dirAbs.y) { - faceIndex = dir.z < 0.0 ? 5 : 4; - ma = 0.5 / dirAbs.z; - uv = vec2(dir.z < 0.0 ? -dir.x : dir.x, -dir.y); - } - else if(dirAbs.y >= dirAbs.x) { - faceIndex = dir.y < 0.0 ? 3 : 2; - ma = 0.5 / dirAbs.y; - uv = vec2(dir.x, dir.y < 0.0 ? -dir.z : dir.z); - } - else { - faceIndex = dir.x < 0.0 ? 1 : 0; - ma = 0.5 / dirAbs.x; - uv = vec2(dir.x < 0.0 ? dir.z : -dir.z, -dir.y); - } - // downscale uv a little to hide seams - // transform coordinates from clip space to texture space - #ifndef _FlipY - return uv * 0.9976 * ma + 0.5; - #else - #ifdef HLSL - return uv * 0.9976 * ma + 0.5; - #else - return vec2(uv.x * ma, uv.y * -ma) * 0.9976 + 0.5; - #endif - #endif -} -#endif - -float lpToDepth(vec3 lp, const vec2 lightProj) { - lp = abs(lp); - float zcomp = max(lp.x, max(lp.y, lp.z)); - zcomp = lightProj.x - lightProj.y / zcomp; - return zcomp * 0.5 + 0.5; -} - -void main() { - int res = voxelgiResolution.x; - for (int i = 0; i < 6; i++) { - ivec3 dst = ivec3(gl_GlobalInvocationID.xyz); - vec3 P = (gl_GlobalInvocationID.xyz + 0.5) / voxelgiResolution; - P = P * 2.0 - 1.0; - - float visibility; - vec3 lp = lightPos - P; - vec3 l; - if (lightType == 0) { l = lightDir; visibility = 1.0; } - else { l = normalize(lp); visibility = attenuate(distance(P, lightPos)); } - -#ifdef _ShadowMap - if (lightShadow == 1) { - vec4 lightPosition = LVP * vec4(P, 1.0); - vec3 lPos = lightPosition.xyz / lightPosition.w; - visibility = texture(shadowMap, vec3(lPos.xy, lPos.z - shadowsBias)).r; - } - else if (lightShadow == 2) { - vec4 lightPosition = LVP * vec4(P, 1.0); - vec3 lPos = lightPosition.xyz / lightPosition.w; - visibility *= texture(shadowMapSpot, vec3(lPos.xy, lPos.z - shadowsBias)).r; - } - else if (lightShadow == 3) { - #ifdef _ShadowMapAtlas - int faceIndex = 0; - const int lightIndex = index * 6; - const vec2 uv = sampleCube(-l, faceIndex); - vec4 pointLightTile = pointLightDataArray[lightIndex + faceIndex]; // x: tile X offset, y: tile Y offset, z: tile size relative to atlas - vec2 uvtiled = pointLightTile.z * uv + pointLightTile.xy; - #ifdef _FlipY - uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system - #endif - visibility *= texture(shadowMapPoint, vec3(uvtiled, lpToDepth(lp, lightProj) - shadowsBias)).r; - #else - visibility *= texture(shadowMapPoint, vec4(-l, lpToDepth(lp, lightProj) - shadowsBias)).r; - #endif - } - #endif - vec3 uvw_light = (P - vec3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)])) / (float(clipmaps[int(clipmapLevel * 10)]) * voxelgiResolution); - uvw_light = (uvw_light * 0.5 + 0.5); - if (any(notEqual(uvw_light, clamp(uvw_light, 0.0, 1.0)))) return; - vec3 writecoords_light = floor(uvw_light * voxelgiResolution); - - imageAtomicMax(voxelsLight, ivec3(writecoords_light), uint(visibility * lightColor.r * 255)); - imageAtomicMax(voxelsLight, ivec3(writecoords_light) + ivec3(0, 0, voxelgiResolution.x), uint(visibility * lightColor.g * 255)); - imageAtomicMax(voxelsLight, ivec3(writecoords_light) + ivec3(0, 0, voxelgiResolution.x * 2), uint(visibility * lightColor.b * 255)); - } -} From 392d12a816e9f3c3e9f96cd08a69e3f14ccdc699 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 21 May 2025 00:00:32 +0000 Subject: [PATCH 037/136] Delete leenkx/Shaders/voxel_resolve_refraction/voxel_resolve_refraction.comp.glsl --- .../voxel_resolve_refraction.comp.glsl | 79 ------------------- 1 file changed, 79 deletions(-) delete mode 100644 leenkx/Shaders/voxel_resolve_refraction/voxel_resolve_refraction.comp.glsl diff --git a/leenkx/Shaders/voxel_resolve_refraction/voxel_resolve_refraction.comp.glsl b/leenkx/Shaders/voxel_resolve_refraction/voxel_resolve_refraction.comp.glsl deleted file mode 100644 index c74ebae..0000000 --- a/leenkx/Shaders/voxel_resolve_refraction/voxel_resolve_refraction.comp.glsl +++ /dev/null @@ -1,79 +0,0 @@ -/* -Copyright (c) 2024 Turánszki János - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - */ - -#version 450 - -layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in; - -#include "compiled.inc" -#include "std/math.glsl" -#include "std/gbuffer.glsl" -#include "std/imageatomic.glsl" -#include "std/conetrace.glsl" - -uniform sampler2D gbufferD; -uniform sampler2D gbuffer0; -uniform sampler3D voxels; -uniform sampler3D voxelsSDF; -uniform sampler2D gbuffer_refraction; -uniform layout(rgba8) image2D voxels_refraction; - -uniform float clipmaps[voxelgiClipmapCount * 10]; -uniform mat4 InvVP; -uniform vec2 cameraProj; -uniform vec3 eye; -uniform vec3 eyeLook; -uniform vec2 postprocess_resolution; - -void main() { - const vec2 pixel = gl_GlobalInvocationID.xy; - vec2 uv = (pixel + 0.5) / postprocess_resolution; - #ifdef _InvY - uv.y = 1.0 - uv.y - #endif - - float depth = textureLod(gbufferD, uv, 0.0).r * 2.0 - 1.0; - if (depth == 0) return; - - vec2 ior_opac = textureLod(gbuffer_refraction, uv, 0.0).xy; - - float x = uv.x * 2 - 1; - float y = uv.y * 2 - 1; - vec4 v = vec4(x, y, 1.0, 1.0); - v = vec4(InvVP * v); - v.xyz /= v.w; - vec3 viewRay = v.xyz - eye; - - vec3 P = getPos(eye, eyeLook, normalize(viewRay), depth, cameraProj); - - vec4 g0 = textureLod(gbuffer0, uv, 0.0); - vec3 n; - n.z = 1.0 - abs(g0.x) - abs(g0.y); - n.xy = n.z >= 0.0 ? g0.xy : octahedronWrap(g0.xy); - n = normalize(n); - - vec3 color = vec3(0.0); - if(ior_opac.y < 1.0) - color = traceRefraction(P, n, voxels, voxelsSDF, normalize(eye - P), ior_opac.x, g0.b, clipmaps, pixel).rgb; - - imageStore(voxels_refraction, ivec2(pixel), vec4(color, 1.0)); -} From ce3c1cea6a23d7933b45ad38935cbb99bbbacb32 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 21 May 2025 00:00:40 +0000 Subject: [PATCH 038/136] Delete leenkx/Shaders/voxel_resolve_shadows/voxel_resolve_shadows.comp.glsl --- .../voxel_resolve_shadows.comp.glsl | 75 ------------------- 1 file changed, 75 deletions(-) delete mode 100644 leenkx/Shaders/voxel_resolve_shadows/voxel_resolve_shadows.comp.glsl diff --git a/leenkx/Shaders/voxel_resolve_shadows/voxel_resolve_shadows.comp.glsl b/leenkx/Shaders/voxel_resolve_shadows/voxel_resolve_shadows.comp.glsl deleted file mode 100644 index d1e095f..0000000 --- a/leenkx/Shaders/voxel_resolve_shadows/voxel_resolve_shadows.comp.glsl +++ /dev/null @@ -1,75 +0,0 @@ -/* -Copyright (c) 2024 Turánszki János - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - */ - -#version 450 - -layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in; - -#include "compiled.inc" -#include "std/math.glsl" -#include "std/gbuffer.glsl" -#include "std/imageatomic.glsl" -#include "std/conetrace.glsl" - -uniform sampler3D voxels; -uniform sampler3D voxelsSDF; -uniform sampler2D gbufferD; -uniform sampler2D gbuffer0; -uniform layout(r16) image2D voxels_shadows; - -uniform float clipmaps[voxelgiClipmapCount * 10]; -uniform mat4 InvVP; -uniform vec2 cameraProj; -uniform vec3 eye; -uniform vec3 eyeLook; -uniform vec2 postprocess_resolution; -uniform vec3 lPos; - -void main() { - const vec2 pixel = gl_GlobalInvocationID.xy; - vec2 uv = (pixel + 0.5) / postprocess_resolution; - #ifdef _InvY - uv.y = 1.0 - uv.y; - #endif - - float depth = textureLod(gbufferD, uv, 0.0).r * 2.0 - 1.0; - if (depth == 0) return; - - float x = uv.x * 2 - 1; - float y = uv.y * 2 - 1; - vec4 v = vec4(x, y, 1.0, 1.0); - v = vec4(InvVP * v); - v.xyz /= v.w; - vec3 viewRay = v.xyz - eye; - - vec3 P = getPos(eye, eyeLook, normalize(viewRay), depth, cameraProj); - - vec4 g0 = textureLod(gbuffer0, uv, 0.0); - vec3 n; - n.z = 1.0 - abs(g0.x) - abs(g0.y); - n.xy = n.z >= 0.0 ? g0.xy : octahedronWrap(g0.xy); - n = normalize(n); - - float occ = 1.0 - traceShadow(P, n, voxels, voxelsSDF, normalize(lPos - P), clipmaps, pixel); - - imageStore(voxels_shadows, ivec2(pixel), vec4(occ)); -} From 08261a9335b2bdcccd89d9757ce269174dbe4ebe Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 21 May 2025 00:16:55 +0000 Subject: [PATCH 039/136] Update leenkx/Shaders/blur_edge_pass/blur_edge_pass.frag.glsl --- .../Shaders/blur_edge_pass/blur_edge_pass.frag.glsl | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/leenkx/Shaders/blur_edge_pass/blur_edge_pass.frag.glsl b/leenkx/Shaders/blur_edge_pass/blur_edge_pass.frag.glsl index 20bea60..23a6dbf 100644 --- a/leenkx/Shaders/blur_edge_pass/blur_edge_pass.frag.glsl +++ b/leenkx/Shaders/blur_edge_pass/blur_edge_pass.frag.glsl @@ -10,10 +10,18 @@ uniform sampler2D gbuffer0; uniform vec2 dirInv; // texStep in vec2 texCoord; -out float fragColor; +out vec3 fragColor; // const float blurWeights[5] = float[] (0.227027, 0.1945946, 0.1216216, 0.054054, 0.016216); -const float blurWeights[10] = float[] (0.132572, 0.125472, 0.106373, 0.08078, 0.05495, 0.033482, 0.018275, 0.008934, 0.003912, 0.001535); +// const float blurWeights[10] = float[] (0.132572, 0.125472, 0.106373, 0.08078, 0.05495, 0.033482, 0.018275, 0.008934, 0.003912, 0.001535); + +const float blurWeights[16] = float[]( + 0.072572, 0.065472, 0.056373, 0.040780, + 0.024950, 0.013482, 0.008275, 0.003934, + 0.001912, 0.000535, 0.132572, 0.125472, + 0.106373, 0.080780, 0.054950, 0.033482 +); + const float discardThreshold = 0.95; void main() { From 08614512d75e1382c3f91ed5b5717fe7eaeb09fa Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 21 May 2025 00:19:31 +0000 Subject: [PATCH 040/136] Update leenkx/Shaders/blur_edge_pass/blur_edge_pass.frag.glsl --- leenkx/Shaders/blur_edge_pass/blur_edge_pass.frag.glsl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/leenkx/Shaders/blur_edge_pass/blur_edge_pass.frag.glsl b/leenkx/Shaders/blur_edge_pass/blur_edge_pass.frag.glsl index 23a6dbf..1344157 100644 --- a/leenkx/Shaders/blur_edge_pass/blur_edge_pass.frag.glsl +++ b/leenkx/Shaders/blur_edge_pass/blur_edge_pass.frag.glsl @@ -27,22 +27,22 @@ const float discardThreshold = 0.95; void main() { vec3 nor = getNor(textureLod(gbuffer0, texCoord, 0.0).rg); - fragColor = textureLod(tex, texCoord, 0.0).r * blurWeights[0]; + fragColor = textureLod(tex, texCoord, 0.0).rgb * blurWeights[0]; float weight = blurWeights[0]; - for (int i = 1; i < 8; ++i) { + for (int i = 1; i < 16; ++i) { float posadd = i;// + 0.5; vec3 nor2 = getNor(textureLod(gbuffer0, texCoord + i * dirInv, 0.0).rg); - float influenceFactor = step(discardThreshold, dot(nor2, nor)); - float col = textureLod(tex, texCoord + posadd * dirInv, 0.0).r; + float influenceFactor = smoothstep(0.5, discardThreshold, dot(nor2, nor)); + vec3 col = textureLod(tex, texCoord + posadd * dirInv, 0.0).rgb; float w = blurWeights[i] * influenceFactor; fragColor += col * w; weight += w; nor2 = getNor(textureLod(gbuffer0, texCoord - i * dirInv, 0.0).rg); influenceFactor = step(discardThreshold, dot(nor2, nor)); - col = textureLod(tex, texCoord - posadd * dirInv, 0.0).r; + col = textureLod(tex, texCoord - posadd * dirInv, 0.0).rgb; w = blurWeights[i] * influenceFactor; fragColor += col * w; weight += w; From 0eafd14ae26a81a62ca3d5150fec0a590af57d57 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 21 May 2025 00:40:56 +0000 Subject: [PATCH 041/136] Update leenkx/Shaders/deferred_light/deferred_light.frag.glsl --- .../deferred_light/deferred_light.frag.glsl | 47 ++++++++++--------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/leenkx/Shaders/deferred_light/deferred_light.frag.glsl b/leenkx/Shaders/deferred_light/deferred_light.frag.glsl index a4700dc..b819d0e 100644 --- a/leenkx/Shaders/deferred_light/deferred_light.frag.glsl +++ b/leenkx/Shaders/deferred_light/deferred_light.frag.glsl @@ -56,6 +56,10 @@ uniform vec3 backgroundCol; #ifdef _SSAO uniform sampler2D ssaotex; +#else +#ifdef _SSGI +uniform sampler2D ssaotex; +#endif #endif #ifdef _SSS @@ -233,9 +237,12 @@ void main() { #ifdef _Brdf vec2 envBRDF = texelFetch(senvmapBrdf, ivec2(vec2(dotNV, 1.0 - roughness) * 256.0), 0).xy; + vec3 F = f0 * envBRDF.x + envBRDF.y; #endif - // Envmap +#ifndef _VoxelGI +#ifndef _VoxelAOvar +// Envmap #ifdef _Irr vec3 envl = shIrradiance(n, shirr); @@ -271,33 +278,33 @@ void main() { envl.rgb *= albedo; #ifdef _Brdf - envl.rgb *= 1.0 - (f0 * envBRDF.x + envBRDF.y); //LV: We should take refracted light into account + envl.rgb *= 1.0 - F; #endif #ifdef _Rad // Indirect specular - envl.rgb += prefilteredColor * (f0 * envBRDF.x + envBRDF.y); //LV: Removed "1.5 * occspec.y". Specular should be weighted only by FV LUT + envl.rgb += prefilteredColor * F; #else #ifdef _EnvCol - envl.rgb += backgroundCol * (f0 * envBRDF.x + envBRDF.y); //LV: Eh, what's the point of weighting it only by F0? + envl.rgb += backgroundCol * F; #endif #endif envl.rgb *= envmapStrength * occspec.x; + fragColor.rgb = envl; +#endif +#endif + #ifdef _VoxelGI - vec4 indirect_diffuse = textureLod(voxels_diffuse, texCoord, 0.0); - fragColor.rgb = (indirect_diffuse.rgb + envl.rgb * (1.0 - indirect_diffuse.a)) * albedo * voxelgiDiff; + fragColor.rgb = textureLod(voxels_diffuse, texCoord, 0.0).rgb * voxelgiDiff; if(roughness < 1.0 && occspec.y > 0.0) - fragColor.rgb += textureLod(voxels_specular, texCoord, 0.0).rgb * occspec.y * voxelgiRefl; + fragColor.rgb += textureLod(voxels_specular, texCoord, 0.0).rgb * F * voxelgiRefl; #endif #ifdef _VoxelAOvar - envl.rgb *= textureLod(voxels_ao, texCoord, 0.0).r; + fragColor.rgb = textureLod(voxels_ao, texCoord, 0.0).rgb * voxelgiOcc; #endif -#ifndef _VoxelGI - fragColor.rgb = envl; -#endif // Show voxels // vec3 origin = vec3(texCoord * 2.0 - 1.0, 0.99); // vec3 direction = vec3(0.0, 0.0, -1.0); @@ -317,6 +324,10 @@ void main() { // #else fragColor.rgb *= textureLod(ssaotex, texCoord, 0.0).r; // #endif +#else +#ifdef _SSGI + fragColor.rgb += textureLod(ssaotex, texCoord, 0.0).rgb; +#endif #endif #ifdef _EmissionShadeless @@ -343,7 +354,7 @@ void main() { float sdotVH = max(0.0, dot(v, sh)); float sdotNL = max(0.0, dot(n, sunDir)); vec3 svisibility = vec3(1.0); - vec3 sdirect = lambertDiffuseBRDF(albedo, sdotNL) + + vec3 sdirect = lambertDiffuseBRDF(albedo, sdotNL) + specularBRDF(f0, roughness, sdotNL, sdotNH, dotNV, sdotVH) * occspec.y; #ifdef _ShadowMap @@ -445,7 +456,7 @@ void main() { , true, spotData.x, spotData.y, spotDir, spotData.zw, spotRight #endif #ifdef _VoxelShadow - , voxels, voxelsSDF, clipmaps + , voxels, voxelsSDF, clipmaps, -g2.rg #endif #ifdef _MicroShadowing , occspec.x @@ -503,7 +514,7 @@ void main() { , lightsArraySpot[li * 2 + 1].xyz // right #endif #ifdef _VoxelShadow - , voxels, voxelsSDF, clipmaps + , voxels, voxelsSDF, clipmaps, -g2.rg #endif #ifdef _MicroShadowing , occspec.x @@ -515,13 +526,5 @@ void main() { } #endif // _Clusters -/* -#ifdef _VoxelRefract -if(opac < 1.0) { - vec3 refraction = traceRefraction(p, n, voxels, v, ior, roughness, eye) * voxelgiRefr; - fragColor.rgb = mix(refraction, fragColor.rgb, opac); -} -#endif -*/ fragColor.a = 1.0; // Mark as opaque } From 3926a7f83e4060c723752aed3018f3ffeb419233 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 21 May 2025 00:42:00 +0000 Subject: [PATCH 042/136] Update leenkx/Shaders/deferred_light/deferred_light.json --- leenkx/Shaders/deferred_light/deferred_light.json | 5 ----- 1 file changed, 5 deletions(-) diff --git a/leenkx/Shaders/deferred_light/deferred_light.json b/leenkx/Shaders/deferred_light/deferred_light.json index bcbdf1d..7018e73 100644 --- a/leenkx/Shaders/deferred_light/deferred_light.json +++ b/leenkx/Shaders/deferred_light/deferred_light.json @@ -11,11 +11,6 @@ "name": "eye", "link": "_cameraPosition" }, - { - "name": "voxelBlend", - "link": "_voxelBlend", - "ifdef": ["_VoxelTemporal"] - }, { "name": "eyeLook", "link": "_cameraLook" From ea69511e67d0c44969bad78529031385c06cda2c Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 21 May 2025 00:47:22 +0000 Subject: [PATCH 043/136] Update leenkx/Shaders/ssgi_pass/ssgi_pass.frag.glsl --- leenkx/Shaders/ssgi_pass/ssgi_pass.frag.glsl | 559 ++++++++++++++++--- 1 file changed, 479 insertions(+), 80 deletions(-) diff --git a/leenkx/Shaders/ssgi_pass/ssgi_pass.frag.glsl b/leenkx/Shaders/ssgi_pass/ssgi_pass.frag.glsl index 694e0f2..96de299 100644 --- a/leenkx/Shaders/ssgi_pass/ssgi_pass.frag.glsl +++ b/leenkx/Shaders/ssgi_pass/ssgi_pass.frag.glsl @@ -1,107 +1,506 @@ #version 450 #include "compiled.inc" -#include "std/math.glsl" #include "std/gbuffer.glsl" +#include "std/brdf.glsl" +#include "std/math.glsl" +#ifdef _Clusters +#include "std/clusters.glsl" +#endif +#ifdef _ShadowMap +#include "std/shadows.glsl" +#endif +#ifdef _LTC +#include "std/ltc.glsl" +#endif +#ifdef _LightIES +#include "std/ies.glsl" +#endif +#ifdef _Spot +#include "std/light_common.glsl" +#endif +#include "std/constants.glsl" +uniform sampler2D gbuffer0; +uniform sampler2D gbuffer1; uniform sampler2D gbufferD; -uniform sampler2D gbuffer0; // Normal -// #ifdef _RTGI -// uniform sampler2D gbuffer1; // Basecol -// #endif -uniform mat4 P; -uniform mat3 V3; - +#ifdef _EmissionShaded +uniform sampler2D gbufferEmission; +#endif +uniform sampler2D sveloc; uniform vec2 cameraProj; +uniform vec3 eye; +uniform vec3 eyeLook; +uniform vec2 screenSize; +uniform mat4 invVP; -const float angleMix = 0.5f; -#ifdef _SSGICone9 -const float strength = 2.0 * (1.0 / ssgiStrength); -#else -const float strength = 2.0 * (1.0 / ssgiStrength) * 1.8; +in vec2 texCoord; +in vec3 viewRay; +out vec3 fragColor; + +float metallic; +uint matid; + +#ifdef _SMSizeUniform +//!uniform vec2 smSizeUniform; #endif -in vec3 viewRay; -in vec2 texCoord; -out float fragColor; - -vec3 hitCoord; -vec2 coord; -float depth; -// #ifdef _RTGI -// vec3 col = vec3(0.0); -// #endif -vec3 vpos; - -vec2 getProjectedCoord(vec3 hitCoord) { - vec4 projectedCoord = P * vec4(hitCoord, 1.0); - projectedCoord.xy /= projectedCoord.w; - projectedCoord.xy = projectedCoord.xy * 0.5 + 0.5; - #ifdef _InvY - projectedCoord.y = 1.0 - projectedCoord.y; +#ifdef _Clusters +uniform vec4 lightsArray[maxLights * 3]; + #ifdef _Spot + uniform vec4 lightsArraySpot[maxLights * 2]; #endif - return projectedCoord.xy; -} +uniform sampler2D clustersData; +uniform vec2 cameraPlane; +#endif -float getDeltaDepth(vec3 hitCoord) { - coord = getProjectedCoord(hitCoord); - depth = textureLod(gbufferD, coord, 0.0).r * 2.0 - 1.0; - vec3 p = getPosView(viewRay, depth, cameraProj); - return p.z - hitCoord.z; -} +#ifdef _SinglePoint // Fast path for single light +uniform vec3 pointPos; +uniform vec3 pointCol; + #ifdef _ShadowMap + uniform float pointBias; + #endif + #ifdef _Spot + uniform vec3 spotDir; + uniform vec3 spotRight; + uniform vec4 spotData; + #endif +#endif -void rayCast(vec3 dir) { - hitCoord = vpos; - dir *= ssgiRayStep * 2; - float dist = 0.15; - for (int i = 0; i < ssgiMaxSteps; i++) { - hitCoord += dir; - float delta = getDeltaDepth(hitCoord); - if (delta > 0.0 && delta < 0.2) { - dist = distance(vpos, hitCoord); - break; +#ifdef _CPostprocess + uniform vec3 PPComp12; +#endif + +#ifdef _ShadowMap + #ifdef _SinglePoint + #ifdef _Spot + #ifndef _LTC + uniform sampler2DShadow shadowMapSpot[1]; + uniform sampler2D shadowMapSpotTransparent[1]; + uniform mat4 LWVPSpot[1]; + #endif + #else + uniform samplerCubeShadow shadowMapPoint[1]; + uniform samplerCube shadowMapPointTransparent[1]; + uniform vec2 lightProj; + #endif + #endif + #ifdef _Clusters + #ifdef _SingleAtlas + uniform sampler2DShadow shadowMapAtlas; + uniform sampler2D shadowMapAtlasTransparent; + #endif + uniform vec2 lightProj; + #ifdef _ShadowMapAtlas + #ifndef _SingleAtlas + uniform sampler2DShadow shadowMapAtlasPoint; + uniform sampler2D shadowMapAtlasPointTransparent; + //!uniform vec4 pointLightDataArray[maxLightsCluster * 6]; + #else + uniform samplerCubeShadow shadowMapPoint[4]; + uniform samplerCube shadowMapPointTransparent[4]; + #endif + #endif + #ifdef _Spot + #ifdef _ShadowMapAtlas + #ifndef _SingleAtlas + uniform sampler2DShadow shadowMapAtlasSpot; + uniform sampler2D shadowMapAtlasSpotTransparent; + #endif + #else + uniform sampler2DShadow shadowMapSpot[4]; + uniform sampler2D shadowMapSpotTransparent[4]; + #endif + uniform mat4 LWVPSpotArray[maxLightsCluster]; + #endif + #endif +#endif + +#ifdef _LTC +uniform vec3 lightArea0; +uniform vec3 lightArea1; +uniform vec3 lightArea2; +uniform vec3 lightArea3; +uniform sampler2D sltcMat; +uniform sampler2D sltcMag; +#ifdef _ShadowMap +#ifndef _Spot + #ifdef _SinglePoint + uniform sampler2DShadow shadowMapSpot[1]; + uniform sampler2D shadowMapSpotTransparent[1]; + uniform mat4 LWVPSpot[1]; + #endif + #ifdef _Clusters + uniform sampler2DShadow shadowMapSpot[maxLightsCluster]; + uniform mat4 LWVPSpotArray[maxLightsCluster]; + #endif +#endif +#endif +#endif + +#ifdef _Sun +uniform vec3 sunDir; +uniform vec3 sunCol; + #ifdef _ShadowMap + #ifdef _ShadowMapAtlas + #ifndef _SingleAtlas + uniform sampler2DShadow shadowMapAtlasSun; + uniform sampler2D shadowMapAtlasSunTransparent; + #endif + #else + uniform sampler2DShadow shadowMap; + uniform sampler2D shadowMapTransparent; + #endif + uniform float shadowsBias; + #ifdef _CSM + //!uniform vec4 casData[shadowmapCascades * 4 + 4]; + #else + uniform mat4 LWVP; + #endif + #endif // _ShadowMap +#endif + +vec3 sampleLight(const vec3 p, const vec3 n, const vec3 lp, const vec3 lightCol + #ifdef _ShadowMap + , int index, float bias, bool receiveShadow, bool transparent + #endif + #ifdef _Spot + , const bool isSpot, const float spotSize, float spotBlend, vec3 spotDir, vec2 scale, vec3 right + #endif + ) { + + vec3 ld = lp - p; + vec3 l = normalize(ld); + + vec3 visibility = lightCol; + visibility *= attenuate(distance(p, lp)); + + #ifdef _LTC + #ifdef _ShadowMap + if (receiveShadow) { + #ifdef _SinglePoint + vec4 lPos = LWVPSpotArray[0] * vec4(p + n * bias * 10, 1.0); + visibility *= shadowTest(shadowMapSpot[0], + shadowMapSpotTransparent[0], + lPos.xyz / lPos.w, bias, transparent); + #endif + #ifdef _Clusters + vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0); + if (index == 0) visibility *= shadowTest(shadowMapSpot[0], + shadowMapSpotTransparent[0], + lPos.xyz / lPos.w, bias, transparent); + else if (index == 1) visibility *= shadowTest(shadowMapSpot[1], + shadowMapSpotTransparent[1], + , lPos.xyz / lPos.w, bias, transparent); + else if (index == 2) visibility *= shadowTest(shadowMapSpot[2], + shadowMapSpotTransparent[2], + lPos.xyz / lPos.w, bias, transparent); + else if (index == 3) visibility *= shadowTest(shadowMapSpot[3], + shadowMapSpotTransparent[3], + lPos.xyz / lPos.w, bias, transparent); + #endif } + #endif + return visibility; + #endif + + #ifdef _Spot + if (isSpot) { + visibility *= spotlightMask(l, spotDir, right, scale, spotSize, spotBlend); + + #ifdef _ShadowMap + if (receiveShadow) { + #ifdef _SinglePoint + vec4 lPos = LWVPSpot[0] * vec4(p + n * bias * 10, 1.0); + visibility *= shadowTest(shadowMapSpot[0], + shadowMapSpotTransparent[0], + lPos.xyz / lPos.w, bias, transparent); + #endif + #ifdef _Clusters + vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0); + #ifdef _ShadowMapAtlas + visibility *= shadowTest( + #ifndef _SingleAtlas + shadowMapAtlasSpot, shadowMapAtlasSpotTransparent + #else + shadowMapAtlas, shadowMapAtlasTransparent + #endif + , lPos.xyz / lPos.w, bias, transparent + ); + #else + if (index == 0) visibility *= shadowTest(shadowMapSpot[0], + shadowMapSpotTransparent[0], + lPos.xyz / lPos.w, bias, transparent); + else if (index == 1) visibility *= shadowTest(shadowMapSpot[1], + shadowMapSpotTransparent[1], + lPos.xyz / lPos.w, bias, transparent); + else if (index == 2) visibility *= shadowTest(shadowMapSpot[2], + shadowMapSpotTransparent[2], + lPos.xyz / lPos.w, bias, transparent); + else if (index == 3) visibility *= shadowTest(shadowMapSpot[3], + shadowMapSpotTransparent[3], + lPos.xyz / lPos.w, bias, transparent); + #endif + #endif + } + #endif + return visibility; } - fragColor += dist; - // #ifdef _RTGI - // col += textureLod(gbuffer1, coord, 0.0).rgb * ((ssgiRayStep * ssgiMaxSteps) - dist); - // #endif + #endif + + #ifdef _LightIES + visibility *= iesAttenuation(-l); + #endif + + #ifdef _ShadowMap + if (receiveShadow) { + #ifdef _SinglePoint + #ifndef _Spot + visibility *= PCFCube(shadowMapPoint[0], + shadowMapPointTransparent[0], + ld, -l, bias, lightProj, n, transparent); + #endif + #endif + #ifdef _Clusters + #ifdef _ShadowMapAtlas + visibility *= PCFFakeCube( + #ifndef _SingleAtlas + shadowMapAtlasPoint, shadowMapAtlasPointTransparent + #else + shadowMapAtlas, shadowMapAtlasTransparent + #endif + , ld, -l, bias, lightProj, n, index, transparent + ); + #else + if (index == 0) visibility *= PCFCube(shadowMapPoint[0], + shadowMapPointTransparent[0], + ld, -l, bias, lightProj, n, transparent); + else if (index == 1) visibility *= PCFCube(shadowMapPoint[1], + shadowMapPointTransparent[1], + ld, -l, bias, lightProj, n, transparent); + else if (index == 2) visibility *= PCFCube(shadowMapPoint[2], + shadowMapPointTransparent[2], + ld, -l, bias, lightProj, n, transparent); + else if (index == 3) visibility *= PCFCube(shadowMapPoint[3], + shadowMapPointTransparent[3], + ld, -l, bias, lightProj, n, transparent); + #endif + #endif + } + #endif + + return visibility; } -vec3 tangent(const vec3 n) { - vec3 t1 = cross(n, vec3(0, 0, 1)); - vec3 t2 = cross(n, vec3(0, 1, 0)); - if (length(t1) > length(t2)) return normalize(t1); - else return normalize(t2); +vec3 getVisibility(vec3 p, vec3 n, float depth, vec2 uv) { + vec3 visibility = vec3(0.0); +#ifdef _Sun + #ifdef _ShadowMap + #ifdef _CSM + visibility = shadowTestCascade( + #ifdef _ShadowMapAtlas + #ifndef _SingleAtlas + shadowMapAtlasSun, shadowMapAtlasSunTransparent + #else + shadowMapAtlas, shadowMapAtlasTransparent + #endif + #else + shadowMap, shadowMapTransparent + #endif + , eye, p + n * shadowsBias * 10, shadowsBias, false + ); + #else + vec4 lPos = LWVP * vec4(p + n * shadowsBias * 100, 1.0); + if (lPos.w > 0.0) { + visibility = shadowTest( + #ifdef _ShadowMapAtlas + #ifndef _SingleAtlas + shadowMapAtlasSun, shadowMapAtlasSunTransparent + #else + shadowMapAtlas, shadowMapAtlasTransparent + #endif + #else + shadowMap, shadowMapTransparent + #endif + , lPos.xyz / lPos.w, shadowsBias, false + ); + } + #endif + #endif +#endif + +#ifdef _SinglePoint + visibility += sampleLight( + p, n, pointPos, pointCol + #ifdef _ShadowMap + , 0, pointBias, true, false + #endif + #ifdef _Spot + , true, spotData.x, spotData.y, spotDir, spotData.zw, spotRight + #endif + ); +#endif + +#ifdef _Clusters + float viewz = linearize(depth, cameraProj); + int clusterI = getClusterI(uv, viewz, cameraPlane); + int numLights = int(texelFetch(clustersData, ivec2(clusterI, 0), 0).r * 255); + + #ifdef HLSL + viewz += textureLod(clustersData, vec2(0.0), 0.0).r * 1e-9; // TODO: krafix bug, needs to generate sampler + #endif + + #ifdef _Spot + int numSpots = int(texelFetch(clustersData, ivec2(clusterI, 1 + maxLightsCluster), 0).r * 255); + int numPoints = numLights - numSpots; + #endif + + for (int i = 0; i < min(numLights, maxLightsCluster); i++) { + int li = int(texelFetch(clustersData, ivec2(clusterI, i + 1), 0).r * 255); + visibility += sampleLight( + p, + n, + lightsArray[li * 3].xyz, // lp + lightsArray[li * 3 + 1].xyz // lightCol + #ifdef _ShadowMap + // light index, shadow bias, cast_shadows + , li, lightsArray[li * 3 + 2].x, lightsArray[li * 3 + 2].z != 0.0, false + #endif + #ifdef _Spot + , lightsArray[li * 3 + 2].y != 0.0 + , lightsArray[li * 3 + 2].y // spot size (cutoff) + , 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 + ); + } +#endif // _Clusters + return visibility; } +vec3 getWorldPos(vec2 uv, float depth) { + vec4 pos = invVP * vec4(uv * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0); + return pos.xyz / pos.w; +} + +vec3 getNormal(vec2 uv) { + vec4 g0 = textureLod(gbuffer0, uv, 0.0); + vec2 enc = g0.rg; + vec3 n; + n.z = 1.0 - abs(enc.x) - abs(enc.y); + n.xy = n.z >= 0.0 ? enc.xy : octahedronWrap(enc.xy); + return normalize(n); +} + +vec3 calculateIndirectLight(vec2 uv, vec3 pos, vec3 normal, float depth) { + // Simplified visibility - replace with your full visibility function if needed + vec3 sampleColor = textureLod(gbuffer1, uv, 0.0).rgb * getVisibility(pos, normal, depth, uv); + + #ifdef _EmissionShadeless + if (matid == 1) { // pure emissive material, color stored in basecol + sampleColor += textureLod(gbuffer1, uv, 0.0).rgb; + } + #endif + #ifdef _EmissionShaded + #ifdef _EmissionShadeless + else { + #endif + vec3 sampleEmission = textureLod(gbufferEmission, uv, 0.0).rgb; + sampleColor += sampleEmission; // Emission should be added directly + #ifdef _EmissionShadeless + } + #endif + #endif + + return sampleColor; +} + +// Improved sampling parameters +const float GOLDEN_ANGLE = 2.39996323; +const float MAX_DEPTH_DIFFERENCE = 0.9; // More conservative depth threshold +const float SAMPLE_BIAS = 0.01; // Small offset to avoid self-occlusion + void main() { - fragColor = 0; - vec4 g0 = textureLod(gbuffer0, texCoord, 0.0); - float d = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0; + float depth = textureLod(gbufferD, texCoord, 0.0).r; + if (depth >= 1.0) { + fragColor = vec3(0.0); + return; + } + + vec4 g0 = textureLod(gbuffer0, texCoord, 0.0); // Normal.xy, roughness, metallic/matid + unpackFloatInt16(g0.a, metallic, matid); + + vec2 velocity = -textureLod(sveloc, texCoord, 0.0).rg; - vec2 enc = g0.rg; vec3 n; - n.z = 1.0 - abs(enc.x) - abs(enc.y); - n.xy = n.z >= 0.0 ? enc.xy : octahedronWrap(enc.xy); - n = normalize(V3 * n); + n.z = 1.0 - abs(g0.x) - abs(g0.y); + n.xy = n.z >= 0.0 ? g0.xy : octahedronWrap(g0.xy); + n = normalize(n); - vpos = getPosView(viewRay, d, cameraProj); + vec3 pos = getWorldPos(texCoord, depth); + vec3 normal = getNormal(texCoord); + vec3 centerColor = textureLod(gbuffer1, texCoord, 0.0).rgb; - rayCast(n); - vec3 o1 = normalize(tangent(n)); - vec3 o2 = (cross(o1, n)); - vec3 c1 = 0.5f * (o1 + o2); - vec3 c2 = 0.5f * (o1 - o2); - rayCast(mix(n, o1, angleMix)); - rayCast(mix(n, o2, angleMix)); - rayCast(mix(n, -c1, angleMix)); - rayCast(mix(n, -c2, angleMix)); + float radius = ssaoRadius; - #ifdef _SSGICone9 - rayCast(mix(n, -o1, angleMix)); - rayCast(mix(n, -o2, angleMix)); - rayCast(mix(n, c1, angleMix)); - rayCast(mix(n, c2, angleMix)); + vec3 gi = vec3(0.0); + float totalWeight = 0.0; + float angle = fract(sin(dot(texCoord, vec2(12.9898, 78.233))) * 100.0); + + for (int i = 0; i < ssgiSamples; i++) { + // Use quasi-random sequence for better coverage + float r = sqrt((float(i) + 0.5) / float(ssgiSamples)) * radius; + float a = (float(i) * GOLDEN_ANGLE) + angle; + + vec2 offset = vec2(cos(a), sin(a)) * r * radius; + vec2 sampleUV = clamp(texCoord + offset * (BayerMatrix8[int(gl_FragCoord.x + velocity.x) % 8][int(gl_FragCoord.y + velocity.y) % 8] - 0.5) / screenSize, vec2(0.001), vec2(0.999)); + + float sampleDepth = textureLod(gbufferD, sampleUV, 0.0).r; + if (sampleDepth >= 1.0) continue; + + vec3 samplePos = getWorldPos(sampleUV, sampleDepth); + vec3 sampleNormal = getNormal(sampleUV); + + // Apply small bias to sample position to avoid self-occlusion + samplePos += sampleNormal * SAMPLE_BIAS; + + vec3 dir = pos - samplePos; + float dist = length(dir); + + if (abs(pos.z - samplePos.z) > MAX_DEPTH_DIFFERENCE) continue;; + + vec3 sampleColor = calculateIndirectLight(sampleUV, samplePos, sampleNormal, sampleDepth); + float weight = 1.0 / (1.0 + dist * dist * 2.0) * max(dot(sampleNormal, n), 0.0); + + gi += sampleColor * weight; + totalWeight += weight; + } + + // Normalize and apply intensity + if (totalWeight > 0.0) { + gi /= totalWeight; + #ifdef _CPostprocess + gi *= PPComp12.x; + #else + gi *= ssaoStrength; + #endif + } + + #ifdef _EmissionShadeless + if (matid == 1) { // pure emissive material, color stored in basecol + gi += textureLod(gbuffer1, texCoord, 0.0).rgb; + } #endif + #ifdef _EmissionShaded + #ifdef _EmissionShadeless + else { + #endif + gi += textureLod(gbufferEmission, texCoord, 0.0).rgb; + #ifdef _EmissionShadeless + } + #endif + #endif + fragColor = gi / (gi + vec3(1.0)); // Reinhard tone mapping } From 915118617d87d5aa463fa4db0aeab77520e84859 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 21 May 2025 00:50:45 +0000 Subject: [PATCH 044/136] Update leenkx/Shaders/ssgi_pass/ssgi_pass.json --- leenkx/Shaders/ssgi_pass/ssgi_pass.json | 174 +++++++++++++++++++++++- 1 file changed, 171 insertions(+), 3 deletions(-) diff --git a/leenkx/Shaders/ssgi_pass/ssgi_pass.json b/leenkx/Shaders/ssgi_pass/ssgi_pass.json index a249a03..24e2649 100644 --- a/leenkx/Shaders/ssgi_pass/ssgi_pass.json +++ b/leenkx/Shaders/ssgi_pass/ssgi_pass.json @@ -6,6 +6,10 @@ "compare_mode": "always", "cull_mode": "none", "links": [ + { + "name": "invVP", + "link": "_inverseViewProjectionMatrix" + }, { "name": "P", "link": "_projectionMatrix" @@ -15,16 +19,180 @@ "link": "_viewMatrix3" }, { - "name": "invP", - "link": "_inverseProjectionMatrix" + "name": "eye", + "link": "_cameraPosition" + }, + { + "name": "eyeLook", + "link": "_cameraLook" }, { "name": "cameraProj", "link": "_cameraPlaneProj" + + }, + { + "name": "screenSize", + "link": "_screenSize" + }, + { + "name": "PPComp12", + "link": "_PPComp12", + "ifdef": ["_CPostprocess"] + }, + { + "name": "lightsArraySpot", + "link": "_lightsArraySpot", + "ifdef": ["_Clusters", "_Spot"] + }, + { + "name": "lightsArray", + "link": "_lightsArray", + "ifdef": ["_Clusters"] + }, + { + "name": "clustersData", + "link": "_clustersData", + "ifdef": ["_Clusters"] + }, + { + "name": "cameraPlane", + "link": "_cameraPlane", + "ifdef": ["_Clusters"] + }, + { + "name": "sunDir", + "link": "_sunDirection", + "ifdef": ["_Sun"] + }, + { + "name": "sunCol", + "link": "_sunColor", + "ifdef": ["_Sun"] + }, + { + "name": "shadowsBias", + "link": "_sunShadowsBias", + "ifdef": ["_Sun", "_ShadowMap"] + }, + { + "name": "LWVP", + "link": "_biasLightWorldViewProjectionMatrixSun", + "ifndef": ["_CSM"], + "ifdef": ["_Sun", "_ShadowMap"] + }, + { + "name": "casData", + "link": "_cascadeData", + "ifdef": ["_Sun", "_ShadowMap", "_CSM"] + }, + { + "name": "lightArea0", + "link": "_lightArea0", + "ifdef": ["_LTC"] + }, + { + "name": "lightArea1", + "link": "_lightArea1", + "ifdef": ["_LTC"] + }, + { + "name": "lightArea2", + "link": "_lightArea2", + "ifdef": ["_LTC"] + }, + { + "name": "lightArea3", + "link": "_lightArea3", + "ifdef": ["_LTC"] + }, + { + "name": "sltcMat", + "link": "_ltcMat", + "ifdef": ["_LTC"] + }, + { + "name": "sltcMag", + "link": "_ltcMag", + "ifdef": ["_LTC"] + }, + { + "name": "smSizeUniform", + "link": "_shadowMapSize", + "ifdef": ["_SMSizeUniform"] + }, + { + "name": "lightProj", + "link": "_lightPlaneProj", + "ifdef": ["_ShadowMap"] + }, + { + "name": "pointPos", + "link": "_pointPosition", + "ifdef": ["_SinglePoint"] + }, + { + "name": "pointCol", + "link": "_pointColor", + "ifdef": ["_SinglePoint"] + }, + { + "name": "pointBias", + "link": "_pointShadowsBias", + "ifdef": ["_SinglePoint", "_ShadowMap"] + }, + { + "name": "spotDir", + "link": "_spotDirection", + "ifdef": ["_SinglePoint", "_Spot"] + }, + { + "name": "spotData", + "link": "_spotData", + "ifdef": ["_SinglePoint", "_Spot"] + }, + { + "name": "spotRight", + "link": "_spotRight", + "ifdef": ["_SinglePoint", "_Spot"] + }, + { + "name": "LWVPSpotArray", + "link": "_biasLightWorldViewProjectionMatrixSpotArray", + "ifdef": ["_Clusters", "_ShadowMap", "_Spot"] + }, + { + "name": "pointLightDataArray", + "link": "_pointLightsAtlasArray", + "ifdef": ["_Clusters", "_ShadowMap", "_ShadowMapAtlas"] + }, + { + "name": "LWVPSpot[0]", + "link": "_biasLightWorldViewProjectionMatrixSpot0", + "ifndef": ["_ShadowMapAtlas"], + "ifdef": ["_LTC", "_ShadowMap"] + }, + { + "name": "LWVPSpot[1]", + "link": "_biasLightWorldViewProjectionMatrixSpot1", + "ifndef": ["_ShadowMapAtlas"], + "ifdef": ["_LTC", "_ShadowMap"] + }, + { + "name": "LWVPSpot[2]", + "link": "_biasLightWorldViewProjectionMatrixSpot2", + "ifndef": ["_ShadowMapAtlas"], + "ifdef": ["_LTC", "_ShadowMap"] + }, + { + "name": "LWVPSpot[3]", + "link": "_biasLightWorldViewProjectionMatrixSpot3", + "ifndef": ["_ShadowMapAtlas"], + "ifdef": ["_LTC", "_ShadowMap"] } ], "texture_params": [], - "vertex_shader": "../include/pass_viewray2.vert.glsl", + "vertex_shader": "../include/pass_viewray.vert.glsl", "fragment_shader": "ssgi_pass.frag.glsl" } ] From f8d0e67f33cb351dca5049e339d75682db628e24 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 21 May 2025 00:51:33 +0000 Subject: [PATCH 045/136] Update leenkx/Shaders/ssr_pass/ssr_pass.frag.glsl --- leenkx/Shaders/ssr_pass/ssr_pass.frag.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/leenkx/Shaders/ssr_pass/ssr_pass.frag.glsl b/leenkx/Shaders/ssr_pass/ssr_pass.frag.glsl index 138056a..84aa2fa 100644 --- a/leenkx/Shaders/ssr_pass/ssr_pass.frag.glsl +++ b/leenkx/Shaders/ssr_pass/ssr_pass.frag.glsl @@ -92,7 +92,7 @@ void main() { vec3 viewNormal = V3 * n; vec3 viewPos = getPosView(viewRay, d, cameraProj); - vec3 reflected = reflect(normalize(viewPos), viewNormal); + vec3 reflected = reflect(viewPos, viewNormal); hitCoord = viewPos; #ifdef _CPostprocess From a5b512f20b7a438b3760e9f5c215c849769e8910 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 21 May 2025 00:55:14 +0000 Subject: [PATCH 046/136] Update leenkx/Shaders/ssrefr_pass/ssrefr_pass.frag.glsl --- leenkx/Shaders/ssrefr_pass/ssrefr_pass.frag.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/leenkx/Shaders/ssrefr_pass/ssrefr_pass.frag.glsl b/leenkx/Shaders/ssrefr_pass/ssrefr_pass.frag.glsl index bdedd67..b4c3c38 100644 --- a/leenkx/Shaders/ssrefr_pass/ssrefr_pass.frag.glsl +++ b/leenkx/Shaders/ssrefr_pass/ssrefr_pass.frag.glsl @@ -89,7 +89,7 @@ void main() { vec3 viewNormal = V3 * n; vec3 viewPos = getPosView(viewRay, d, cameraProj); - vec3 refracted = refract(normalize(viewPos), viewNormal, 1.0 / ior); + vec3 refracted = refract(viewPos, viewNormal, 1.0 / ior); hitCoord = viewPos; vec3 dir = refracted * (1.0 - rand(texCoord) * ss_refractionJitter * roughness) * 2.0; From 27540ac7e9a73b4975cba47ce81b3e891f3172ed Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 21 May 2025 01:01:47 +0000 Subject: [PATCH 047/136] Update leenkx/Shaders/std/conetrace.glsl --- leenkx/Shaders/std/conetrace.glsl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/leenkx/Shaders/std/conetrace.glsl b/leenkx/Shaders/std/conetrace.glsl index 295c8b6..4d1d1d6 100644 --- a/leenkx/Shaders/std/conetrace.glsl +++ b/leenkx/Shaders/std/conetrace.glsl @@ -22,7 +22,7 @@ THE SOFTWARE. #ifndef _CONETRACE_GLSL_ #define _CONETRACE_GLSL_ -#include "std/voxels_constants.glsl" +#include "std/constants.glsl" // References // https://github.com/Friduric/voxel-cone-tracing @@ -166,7 +166,7 @@ vec4 traceDiffuse(const vec3 origin, const vec3 normal, const sampler3D voxels, } vec4 traceSpecular(const vec3 origin, const vec3 normal, const sampler3D voxels, const sampler3D voxelsSDF, const vec3 viewDir, const float roughness, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel, const vec2 velocity) { - vec3 specularDir = reflect(normalize(-viewDir), normal); + vec3 specularDir = reflect(-viewDir, normal); vec3 P = origin + specularDir * ((BayerMatrix8[int(pixel.x + velocity.x) % 8][int(pixel.y + velocity.y) % 8] - 0.5)) * voxelgiStep; vec4 amount = traceCone(voxels, voxelsSDF, P, normal, specularDir, 0, true, roughness, voxelgiStep, clipmaps); @@ -177,8 +177,8 @@ vec4 traceSpecular(const vec3 origin, const vec3 normal, const sampler3D voxels, } vec4 traceRefraction(const vec3 origin, const vec3 normal, sampler3D voxels, sampler3D voxelsSDF, const vec3 viewDir, const float ior, const float roughness, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel, const vec2 velocity, const float opacity) { - const float transmittance = 1.0 - opacity; - vec3 refractionDir = refract(normalize(-viewDir), normal, 1.0 / ior); + const float transmittance = 1.0; + vec3 refractionDir = refract(-viewDir, normal, 1.0 / ior); vec3 P = origin + refractionDir * (BayerMatrix8[int(pixel.x + velocity.x) % 8][int(pixel.y + velocity.y) % 8] - 0.5) * voxelgiStep; vec4 amount = transmittance * traceCone(voxels, voxelsSDF, P, normal, refractionDir, 0, true, roughness, voxelgiStep, clipmaps); @@ -330,7 +330,7 @@ float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const v float traceShadow(const vec3 origin, const vec3 normal, const sampler3D voxels, const sampler3D voxelsSDF, const vec3 dir, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel, const vec2 velocity) { vec3 P = origin + dir * (BayerMatrix8[int(pixel.x + velocity.x) % 8][int(pixel.y + velocity.y) % 8] - 0.5) * voxelgiStep; - float amount = traceConeShadow(voxels, voxelsSDF, P, normal, dir, DIFFUSE_CONE_APERTURE, voxelgiStep, clipmaps); + float amount = traceConeShadow(voxels, voxelsSDF, P, normal, dir, SHADOW_CONE_APERTURE, voxelgiStep, clipmaps); amount = clamp(amount, 0.0, 1.0); return amount * voxelgiOcc; } From ab7edaa9e3eafe244724e43135bda0b70231f42d Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 21 May 2025 01:02:56 +0000 Subject: [PATCH 048/136] Update leenkx/Shaders/std/constants.glsl --- leenkx/Shaders/std/constants.glsl | 43 ++++++++++++++++--------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/leenkx/Shaders/std/constants.glsl b/leenkx/Shaders/std/constants.glsl index 5b82305..d0309cc 100644 --- a/leenkx/Shaders/std/constants.glsl +++ b/leenkx/Shaders/std/constants.glsl @@ -1,16 +1,13 @@ /* Copyright (c) 2024 Turánszki János - Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,28 +18,32 @@ THE SOFTWARE. */ const int DIFFUSE_CONE_COUNT = 16; -const float DIFFUSE_CONE_APERTURE = radians(45.0); + +const float SHADOW_CONE_APERTURE = radians(15.0); + +const float DIFFUSE_CONE_APERTURE = 0.872665; const vec3 DIFFUSE_CONE_DIRECTIONS[16] = { - vec3(0.0000, 0.0000, 1.0000), // Central direction - vec3(0.3827, 0.0000, 0.9239), // Ring 1 - vec3(-0.3827, 0.0000, 0.9239), - vec3(0.0000, 0.3827, 0.9239), - vec3(0.0000, -0.3827, 0.9239), - vec3(0.2706, 0.2706, 0.9239), // Ring 2 - vec3(-0.2706, 0.2706, 0.9239), - vec3(0.2706, -0.2706, 0.9239), - vec3(-0.2706, -0.2706, 0.9239), - vec3(0.1802, 0.3604, 0.9239), // Ring 3 - vec3(-0.1802, 0.3604, 0.9239), - vec3(0.1802, -0.3604, 0.9239), - vec3(-0.1802, -0.3604, 0.9239), - vec3(0.3604, 0.1802, 0.9239), - vec3(-0.3604, 0.1802, 0.9239), - vec3(0.3604, -0.1802, 0.9239) + vec3( 0.000000, 0.000000, 1.000000), + vec3( 0.525731, 0.000000, 0.850651), + vec3(-0.525731, 0.000000, 0.850651), + vec3( 0.000000, 0.525731, 0.850651), + vec3( 0.000000, -0.525731, 0.850651), + vec3( 0.309017, 0.809017, 0.500000), + vec3(-0.309017, 0.809017, 0.500000), + vec3( 0.309017, -0.809017, 0.500000), + vec3(-0.309017, -0.809017, 0.500000), + vec3( 0.809017, 0.309017, 0.500000), + vec3( 0.809017, -0.309017, 0.500000), + vec3(-0.809017, 0.309017, 0.500000), + vec3(-0.809017, -0.309017, 0.500000), + vec3( 0.000000, 0.000000, -1.000000), + vec3( 0.525731, 0.000000, -0.850651), + vec3(-0.525731, 0.000000, -0.850651) }; + const float BayerMatrix8[8][8] = { { 1.0 / 65.0, 49.0 / 65.0, 13.0 / 65.0, 61.0 / 65.0, 4.0 / 65.0, 52.0 / 65.0, 16.0 / 65.0, 64.0 / 65.0 }, @@ -53,4 +54,4 @@ const float BayerMatrix8[8][8] = { 35.0 / 65.0, 19.0 / 65.0, 47.0 / 65.0, 31.0 / 65.0, 34.0 / 65.0, 18.0 / 65.0, 46.0 / 65.0, 30.0 / 65.0 }, { 11.0 / 65.0, 59.0 / 65.0, 7.0 / 65.0, 55.0 / 65.0, 10.0 / 65.0, 58.0 / 65.0, 6.0 / 65.0, 54.0 / 65.0 }, { 43.0 / 65.0, 27.0 / 65.0, 39.0 / 65.0, 23.0 / 65.0, 42.0 / 65.0, 26.0 / 65.0, 38.0 / 65.0, 22.0 / 65.0 } -}; +}; \ No newline at end of file From 27b4ec42a85bffa3294f1db55fb3109cc0ff9d93 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 21 May 2025 01:04:30 +0000 Subject: [PATCH 049/136] Update leenkx/Shaders/std/light.glsl --- leenkx/Shaders/std/light.glsl | 140 ++++++++++++++++++++++++++++++++-- 1 file changed, 133 insertions(+), 7 deletions(-) diff --git a/leenkx/Shaders/std/light.glsl b/leenkx/Shaders/std/light.glsl index 649af61..6232239 100644 --- a/leenkx/Shaders/std/light.glsl +++ b/leenkx/Shaders/std/light.glsl @@ -10,9 +10,6 @@ #ifdef _VoxelShadow #include "std/conetrace.glsl" #endif -#ifdef _gbuffer2 -uniform sampler2D gbuffer2; -#endif #ifdef _LTC #include "std/ltc.glsl" #endif @@ -89,7 +86,7 @@ uniform sampler2D sltcMag; uniform sampler2D shadowMapSpotTransparent[maxLightsCluster]; uniform mat4 LWVPSpotArray[maxLightsCluster]; #endif - #endif +#endif #endif #endif @@ -102,7 +99,7 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co , const bool isSpot, const float spotSize, float spotBlend, vec3 spotDir, vec2 scale, vec3 right #endif #ifdef _VoxelShadow - , sampler3D voxels, sampler3D voxelsSDF, float clipmaps[10 * voxelgiClipmapCount] + , sampler3D voxels, sampler3D voxelsSDF, float clipmaps[10 * voxelgiClipmapCount], vec2 velocity #endif #ifdef _MicroShadowing , float occ @@ -148,8 +145,12 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co #endif #ifdef _VoxelShadow - vec4 g2 = textureLod(gbuffer2, gl_FragCoord.xy, 0.0); - direct *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, l, clipmaps, gl_FragCoord.xy, g2.rg).r) * voxelgiShad; + vec3 lightDir = l; + #ifdef _Spot + if(isSpot) + lightDir = spotDir; + #endif + direct *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, lightDir, clipmaps, gl_FragCoord.xy, velocity).r) * voxelgiShad; #endif #ifdef _LTC @@ -239,4 +240,129 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co return direct; } +#ifdef _VoxelGI +vec3 sampleLightVoxels(const vec3 p, const vec3 n, const vec3 v, const float dotNV, const vec3 lp, const vec3 lightCol, + const vec3 albedo, const float rough, const float spec, const vec3 f0 + #ifdef _ShadowMap + , int index, float bias, bool receiveShadow, bool transparent + #endif + #ifdef _Spot + , const bool isSpot, const float spotSize, float spotBlend, vec3 spotDir, vec2 scale, vec3 right + #endif + ) { + vec3 ld = lp - p; + vec3 l = normalize(ld); + vec3 h = normalize(v + l); + float dotNH = max(0.0, dot(n, h)); + float dotVH = max(0.0, dot(v, h)); + float dotNL = max(0.0, dot(n, l)); + + #ifdef _LTC + float theta = acos(dotNV); + vec2 tuv = vec2(rough, theta / (0.5 * PI)); + tuv = tuv * LUT_SCALE + LUT_BIAS; + vec4 t = textureLod(sltcMat, tuv, 0.0); + mat3 invM = mat3( + vec3(1.0, 0.0, t.y), + vec3(0.0, t.z, 0.0), + vec3(t.w, 0.0, t.x)); + float ltcspec = ltcEvaluate(n, v, dotNV, p, invM, lightArea0, lightArea1, lightArea2, lightArea3); + ltcspec *= textureLod(sltcMag, tuv, 0.0).a; + float ltcdiff = ltcEvaluate(n, v, dotNV, p, mat3(1.0), lightArea0, lightArea1, lightArea2, lightArea3); + vec3 direct = albedo * ltcdiff + ltcspec * spec * 0.05; + #else + vec3 direct = lambertDiffuseBRDF(albedo, dotNL) + + specularBRDF(f0, rough, dotNL, dotNH, dotNV, dotVH) * spec; + #endif + + direct *= attenuate(distance(p, lp)); + direct *= lightCol; + + #ifdef _LTC + #ifdef _ShadowMap + if (receiveShadow) { + #ifdef _SinglePoint + vec4 lPos = LWVPSpotArray[0] * vec4(p + n * bias * 10, 1.0); + direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent); + #endif + #ifdef _Clusters + vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0); + if (index == 0) direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent); + else if (index == 1) direct *= shadowTest(shadowMapSpot[1], shadowMapSpotTransparent[1], lPos.xyz / lPos.w, bias, transparent); + else if (index == 2) direct *= shadowTest(shadowMapSpot[2], shadowMapSpotTransparent[2], lPos.xyz / lPos.w, bias, transparent); + else if (index == 3) direct *= shadowTest(shadowMapSpot[3], shadowMapSpotTransparent[3], lPos.xyz / lPos.w, bias, transparent); + #endif + } + #endif + return direct; + #endif + + #ifdef _Spot + if (isSpot) { + direct *= spotlightMask(l, spotDir, right, scale, spotSize, spotBlend); + + #ifdef _ShadowMap + if (receiveShadow) { + #ifdef _SinglePoint + vec4 lPos = LWVPSpot[0] * vec4(p + n * bias * 10, 1.0); + direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent); + #endif + #ifdef _Clusters + vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0); + #ifdef _ShadowMapAtlas + direct *= shadowTest( + #ifndef _SingleAtlas + shadowMapAtlasSpot, shadowMapAtlasSpotTransparent + #else + shadowMapAtlas, shadowMapAtlasTransparent + #endif + , lPos.xyz / lPos.w, bias, transparent + ); + #else + if (index == 0) direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent); + else if (index == 1) direct *= shadowTest(shadowMapSpot[1], shadowMapSpotTransparent[1], lPos.xyz / lPos.w, bias, transparent); + else if (index == 2) direct *= shadowTest(shadowMapSpot[2], shadowMapSpotTransparent[2], lPos.xyz / lPos.w, bias, transparent); + else if (index == 3) direct *= shadowTest(shadowMapSpot[3], shadowMapSpotTransparent[3], lPos.xyz / lPos.w, bias, transparent); + #endif + #endif + } + #endif + return direct; + } + #endif + + #ifdef _LightIES + direct *= iesAttenuation(-l); + #endif + + #ifdef _ShadowMap + if (receiveShadow) { + #ifdef _SinglePoint + #ifndef _Spot + direct *= PCFCube(shadowMapPoint[0], shadowMapPointTransparent[0], ld, -l, bias, lightProj, n, transparent); + #endif + #endif + #ifdef _Clusters + #ifdef _ShadowMapAtlas + direct *= PCFFakeCube( + #ifndef _SingleAtlas + shadowMapAtlasPoint, shadowMapAtlasPointTransparent + #else + shadowMapAtlas, shadowMapAtlasTransparent + #endif + , ld, -l, bias, lightProj, n, index, transparent + ); + #else + if (index == 0) direct *= PCFCube(shadowMapPoint[0], shadowMapPointTransparent[0], ld, -l, bias, lightProj, n, transparent); + else if (index == 1) direct *= PCFCube(shadowMapPoint[1], shadowMapPointTransparent[1], ld, -l, bias, lightProj, n, transparent); + else if (index == 2) direct *= PCFCube(shadowMapPoint[2], shadowMapPointTransparent[2], ld, -l, bias, lightProj, n, transparent); + else if (index == 3) direct *= PCFCube(shadowMapPoint[3], shadowMapPointTransparent[3], ld, -l, bias, lightProj, n, transparent); + #endif + #endif + } + #endif + + return direct; +} +#endif #endif From bd5afc797d4e528cf3d897f21f806b79b962bb35 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 21 May 2025 01:05:37 +0000 Subject: [PATCH 050/136] Update leenkx/Shaders/std/shadows.glsl --- leenkx/Shaders/std/shadows.glsl | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/leenkx/Shaders/std/shadows.glsl b/leenkx/Shaders/std/shadows.glsl index 4944d3b..3ee7b23 100644 --- a/leenkx/Shaders/std/shadows.glsl +++ b/leenkx/Shaders/std/shadows.glsl @@ -236,12 +236,14 @@ vec3 PCFFakeCube(sampler2DShadow shadowMap, sampler2D shadowMapTransparent, cons #endif result.x += texture(shadowMap, vec3(uvtiled, compare)); - uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(-1.0, 1.0) / smSize))); - pointLightTile = pointLightDataArray[lightIndex + newFaceIndex]; - uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy; - #ifdef _FlipY - uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system + #ifdef _ShadowMapTransparent + if (transparent == false) { + vec4 shadowmap_transparent = texture(shadowMapTransparent, uvtiled); + if (shadowmap_transparent.a < compare) + result *= shadowmap_transparent.rgb; + } #endif + result.x += texture(shadowMap, vec3(uvtiled, compare)); uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(0.0, -1.0) / smSize))); From 74389ba76a15fa17a46facd956fbba18c444ef04 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 21 May 2025 02:01:35 +0000 Subject: [PATCH 051/136] Add leenkx/Shaders/voxel_light.comp.glsl --- leenkx/Shaders/voxel_light.comp.glsl | 135 +++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 leenkx/Shaders/voxel_light.comp.glsl diff --git a/leenkx/Shaders/voxel_light.comp.glsl b/leenkx/Shaders/voxel_light.comp.glsl new file mode 100644 index 0000000..3fbdd82 --- /dev/null +++ b/leenkx/Shaders/voxel_light.comp.glsl @@ -0,0 +1,135 @@ +#version 450 + +layout (local_size_x = 8, local_size_y = 8, local_size_z = 8) in; + +#include "compiled.inc" +#include "std/math.glsl" +#include "std/gbuffer.glsl" +#include "std/imageatomic.glsl" +#ifdef _VoxelShadow +#include "std/conetrace.glsl" +#endif + +uniform vec3 lightPos; +uniform vec3 lightColor; +uniform int lightType; +uniform vec3 lightDir; +uniform vec2 spotData; +#ifdef _ShadowMap +uniform int lightShadow; +uniform vec2 lightProj; +uniform float shadowsBias; +uniform mat4 LVP; +#ifdef _ShadowMapAtlas +uniform int index; +uniform vec4 pointLightDataArray[maxLightsCluster * 6]; +#endif +#endif + +uniform float clipmaps[voxelgiClipmapCount * 10]; +uniform int clipmapLevel; + +uniform layout(r32ui) uimage3D voxelsLight; + +#ifdef _ShadowMap +uniform sampler2DShadow shadowMap; +uniform sampler2D shadowMapTransparent; +uniform sampler2DShadow shadowMapSpot; +#ifdef _ShadowMapAtlas +uniform sampler2DShadow shadowMapPoint; +#else +uniform samplerCubeShadow shadowMapPoint; +#endif +#endif + +#ifdef _ShadowMapAtlas +// https://www.khronos.org/registry/OpenGL/specs/gl/glspec20.pdf // p:168 +// https://www.gamedev.net/forums/topic/687535-implementing-a-cube-map-lookup-function/5337472/ +vec2 sampleCube(vec3 dir, out int faceIndex) { + vec3 dirAbs = abs(dir); + float ma; + vec2 uv; + if(dirAbs.z >= dirAbs.x && dirAbs.z >= dirAbs.y) { + faceIndex = dir.z < 0.0 ? 5 : 4; + ma = 0.5 / dirAbs.z; + uv = vec2(dir.z < 0.0 ? -dir.x : dir.x, -dir.y); + } + else if(dirAbs.y >= dirAbs.x) { + faceIndex = dir.y < 0.0 ? 3 : 2; + ma = 0.5 / dirAbs.y; + uv = vec2(dir.x, dir.y < 0.0 ? -dir.z : dir.z); + } + else { + faceIndex = dir.x < 0.0 ? 1 : 0; + ma = 0.5 / dirAbs.x; + uv = vec2(dir.x < 0.0 ? dir.z : -dir.z, -dir.y); + } + // downscale uv a little to hide seams + // transform coordinates from clip space to texture space + #ifndef _FlipY + return uv * 0.9976 * ma + 0.5; + #else + #ifdef HLSL + return uv * 0.9976 * ma + 0.5; + #else + return vec2(uv.x * ma, uv.y * -ma) * 0.9976 + 0.5; + #endif + #endif +} +#endif + +float lpToDepth(vec3 lp, const vec2 lightProj) { + lp = abs(lp); + float zcomp = max(lp.x, max(lp.y, lp.z)); + zcomp = lightProj.x - lightProj.y / zcomp; + return zcomp * 0.5 + 0.5; +} + +void main() { + int res = voxelgiResolution.x; + ivec3 dst = ivec3(gl_GlobalInvocationID.xyz); + + vec3 wposition = (gl_GlobalInvocationID.xyz + 0.5) / voxelgiResolution.x; + wposition = wposition * 2.0 - 1.0; + wposition *= float(clipmaps[int(clipmapLevel * 10)]); + wposition *= voxelgiResolution.x; + wposition += vec3(clipmaps[clipmapLevel * 10 + 4], clipmaps[clipmapLevel * 10 + 5], clipmaps[clipmapLevel * 10 + 6]); + + float visibility; + vec3 lp = lightPos -wposition; + vec3 l; + if (lightType == 0) { l = lightDir; visibility = 1.0; } + else { l = normalize(lp); visibility = attenuate(distance(wposition, lightPos)); } + +#ifdef _ShadowMap + if (lightShadow == 1) { + vec4 lightPosition = LVP * vec4(wposition, 1.0); + vec3 lPos = lightPosition.xyz / lightPosition.w; + visibility = texture(shadowMap, vec3(lPos.xy, lPos.z - shadowsBias)).r; + } + else if (lightShadow == 2) { + vec4 lightPosition = LVP * vec4(wposition, 1.0); + vec3 lPos = lightPosition.xyz / lightPosition.w; + visibility *= texture(shadowMapSpot, vec3(lPos.xy, lPos.z - shadowsBias)).r; + } + else if (lightShadow == 3) { + #ifdef _ShadowMapAtlas + int faceIndex = 0; + const int lightIndex = index * 6; + const vec2 uv = sampleCube(-l, faceIndex); + vec4 pointLightTile = pointLightDataArray[lightIndex + faceIndex]; // x: tile X offset, y: tile Y offset, z: tile size relative to atlas + vec2 uvtiled = pointLightTile.z * uv + pointLightTile.xy; + #ifdef _FlipY + uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system + #endif + visibility *= texture(shadowMapPoint, vec3(uvtiled, lpToDepth(lp, lightProj) - shadowsBias)).r; + #else + visibility *= texture(shadowMapPoint, vec4(-l, lpToDepth(lp, lightProj) - shadowsBias)).r; + #endif + } +#endif + + imageAtomicAdd(voxelsLight, dst, uint(visibility * lightColor.r * 255)); + imageAtomicAdd(voxelsLight, dst + ivec3(0, 0, voxelgiResolution.x), uint(visibility * lightColor.g * 255)); + imageAtomicAdd(voxelsLight, dst + ivec3(0, 0, voxelgiResolution.x * 2), uint(visibility * lightColor.b * 255)); +} From dab915b60d07946379d364bd465f165e1f27688b Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 21 May 2025 02:01:43 +0000 Subject: [PATCH 052/136] Delete leenkx/Shaders/voxel_light.comp.glsl --- leenkx/Shaders/voxel_light.comp.glsl | 135 --------------------------- 1 file changed, 135 deletions(-) delete mode 100644 leenkx/Shaders/voxel_light.comp.glsl diff --git a/leenkx/Shaders/voxel_light.comp.glsl b/leenkx/Shaders/voxel_light.comp.glsl deleted file mode 100644 index 3fbdd82..0000000 --- a/leenkx/Shaders/voxel_light.comp.glsl +++ /dev/null @@ -1,135 +0,0 @@ -#version 450 - -layout (local_size_x = 8, local_size_y = 8, local_size_z = 8) in; - -#include "compiled.inc" -#include "std/math.glsl" -#include "std/gbuffer.glsl" -#include "std/imageatomic.glsl" -#ifdef _VoxelShadow -#include "std/conetrace.glsl" -#endif - -uniform vec3 lightPos; -uniform vec3 lightColor; -uniform int lightType; -uniform vec3 lightDir; -uniform vec2 spotData; -#ifdef _ShadowMap -uniform int lightShadow; -uniform vec2 lightProj; -uniform float shadowsBias; -uniform mat4 LVP; -#ifdef _ShadowMapAtlas -uniform int index; -uniform vec4 pointLightDataArray[maxLightsCluster * 6]; -#endif -#endif - -uniform float clipmaps[voxelgiClipmapCount * 10]; -uniform int clipmapLevel; - -uniform layout(r32ui) uimage3D voxelsLight; - -#ifdef _ShadowMap -uniform sampler2DShadow shadowMap; -uniform sampler2D shadowMapTransparent; -uniform sampler2DShadow shadowMapSpot; -#ifdef _ShadowMapAtlas -uniform sampler2DShadow shadowMapPoint; -#else -uniform samplerCubeShadow shadowMapPoint; -#endif -#endif - -#ifdef _ShadowMapAtlas -// https://www.khronos.org/registry/OpenGL/specs/gl/glspec20.pdf // p:168 -// https://www.gamedev.net/forums/topic/687535-implementing-a-cube-map-lookup-function/5337472/ -vec2 sampleCube(vec3 dir, out int faceIndex) { - vec3 dirAbs = abs(dir); - float ma; - vec2 uv; - if(dirAbs.z >= dirAbs.x && dirAbs.z >= dirAbs.y) { - faceIndex = dir.z < 0.0 ? 5 : 4; - ma = 0.5 / dirAbs.z; - uv = vec2(dir.z < 0.0 ? -dir.x : dir.x, -dir.y); - } - else if(dirAbs.y >= dirAbs.x) { - faceIndex = dir.y < 0.0 ? 3 : 2; - ma = 0.5 / dirAbs.y; - uv = vec2(dir.x, dir.y < 0.0 ? -dir.z : dir.z); - } - else { - faceIndex = dir.x < 0.0 ? 1 : 0; - ma = 0.5 / dirAbs.x; - uv = vec2(dir.x < 0.0 ? dir.z : -dir.z, -dir.y); - } - // downscale uv a little to hide seams - // transform coordinates from clip space to texture space - #ifndef _FlipY - return uv * 0.9976 * ma + 0.5; - #else - #ifdef HLSL - return uv * 0.9976 * ma + 0.5; - #else - return vec2(uv.x * ma, uv.y * -ma) * 0.9976 + 0.5; - #endif - #endif -} -#endif - -float lpToDepth(vec3 lp, const vec2 lightProj) { - lp = abs(lp); - float zcomp = max(lp.x, max(lp.y, lp.z)); - zcomp = lightProj.x - lightProj.y / zcomp; - return zcomp * 0.5 + 0.5; -} - -void main() { - int res = voxelgiResolution.x; - ivec3 dst = ivec3(gl_GlobalInvocationID.xyz); - - vec3 wposition = (gl_GlobalInvocationID.xyz + 0.5) / voxelgiResolution.x; - wposition = wposition * 2.0 - 1.0; - wposition *= float(clipmaps[int(clipmapLevel * 10)]); - wposition *= voxelgiResolution.x; - wposition += vec3(clipmaps[clipmapLevel * 10 + 4], clipmaps[clipmapLevel * 10 + 5], clipmaps[clipmapLevel * 10 + 6]); - - float visibility; - vec3 lp = lightPos -wposition; - vec3 l; - if (lightType == 0) { l = lightDir; visibility = 1.0; } - else { l = normalize(lp); visibility = attenuate(distance(wposition, lightPos)); } - -#ifdef _ShadowMap - if (lightShadow == 1) { - vec4 lightPosition = LVP * vec4(wposition, 1.0); - vec3 lPos = lightPosition.xyz / lightPosition.w; - visibility = texture(shadowMap, vec3(lPos.xy, lPos.z - shadowsBias)).r; - } - else if (lightShadow == 2) { - vec4 lightPosition = LVP * vec4(wposition, 1.0); - vec3 lPos = lightPosition.xyz / lightPosition.w; - visibility *= texture(shadowMapSpot, vec3(lPos.xy, lPos.z - shadowsBias)).r; - } - else if (lightShadow == 3) { - #ifdef _ShadowMapAtlas - int faceIndex = 0; - const int lightIndex = index * 6; - const vec2 uv = sampleCube(-l, faceIndex); - vec4 pointLightTile = pointLightDataArray[lightIndex + faceIndex]; // x: tile X offset, y: tile Y offset, z: tile size relative to atlas - vec2 uvtiled = pointLightTile.z * uv + pointLightTile.xy; - #ifdef _FlipY - uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system - #endif - visibility *= texture(shadowMapPoint, vec3(uvtiled, lpToDepth(lp, lightProj) - shadowsBias)).r; - #else - visibility *= texture(shadowMapPoint, vec4(-l, lpToDepth(lp, lightProj) - shadowsBias)).r; - #endif - } -#endif - - imageAtomicAdd(voxelsLight, dst, uint(visibility * lightColor.r * 255)); - imageAtomicAdd(voxelsLight, dst + ivec3(0, 0, voxelgiResolution.x), uint(visibility * lightColor.g * 255)); - imageAtomicAdd(voxelsLight, dst + ivec3(0, 0, voxelgiResolution.x * 2), uint(visibility * lightColor.b * 255)); -} From d7e076fb5682bee0732080d995aa0f04353a53e7 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 21 May 2025 02:02:05 +0000 Subject: [PATCH 053/136] Add leenkx/Shaders/voxel_light/voxel_light.comp.glsl --- .../Shaders/voxel_light/voxel_light.comp.glsl | 135 ++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 leenkx/Shaders/voxel_light/voxel_light.comp.glsl diff --git a/leenkx/Shaders/voxel_light/voxel_light.comp.glsl b/leenkx/Shaders/voxel_light/voxel_light.comp.glsl new file mode 100644 index 0000000..3fbdd82 --- /dev/null +++ b/leenkx/Shaders/voxel_light/voxel_light.comp.glsl @@ -0,0 +1,135 @@ +#version 450 + +layout (local_size_x = 8, local_size_y = 8, local_size_z = 8) in; + +#include "compiled.inc" +#include "std/math.glsl" +#include "std/gbuffer.glsl" +#include "std/imageatomic.glsl" +#ifdef _VoxelShadow +#include "std/conetrace.glsl" +#endif + +uniform vec3 lightPos; +uniform vec3 lightColor; +uniform int lightType; +uniform vec3 lightDir; +uniform vec2 spotData; +#ifdef _ShadowMap +uniform int lightShadow; +uniform vec2 lightProj; +uniform float shadowsBias; +uniform mat4 LVP; +#ifdef _ShadowMapAtlas +uniform int index; +uniform vec4 pointLightDataArray[maxLightsCluster * 6]; +#endif +#endif + +uniform float clipmaps[voxelgiClipmapCount * 10]; +uniform int clipmapLevel; + +uniform layout(r32ui) uimage3D voxelsLight; + +#ifdef _ShadowMap +uniform sampler2DShadow shadowMap; +uniform sampler2D shadowMapTransparent; +uniform sampler2DShadow shadowMapSpot; +#ifdef _ShadowMapAtlas +uniform sampler2DShadow shadowMapPoint; +#else +uniform samplerCubeShadow shadowMapPoint; +#endif +#endif + +#ifdef _ShadowMapAtlas +// https://www.khronos.org/registry/OpenGL/specs/gl/glspec20.pdf // p:168 +// https://www.gamedev.net/forums/topic/687535-implementing-a-cube-map-lookup-function/5337472/ +vec2 sampleCube(vec3 dir, out int faceIndex) { + vec3 dirAbs = abs(dir); + float ma; + vec2 uv; + if(dirAbs.z >= dirAbs.x && dirAbs.z >= dirAbs.y) { + faceIndex = dir.z < 0.0 ? 5 : 4; + ma = 0.5 / dirAbs.z; + uv = vec2(dir.z < 0.0 ? -dir.x : dir.x, -dir.y); + } + else if(dirAbs.y >= dirAbs.x) { + faceIndex = dir.y < 0.0 ? 3 : 2; + ma = 0.5 / dirAbs.y; + uv = vec2(dir.x, dir.y < 0.0 ? -dir.z : dir.z); + } + else { + faceIndex = dir.x < 0.0 ? 1 : 0; + ma = 0.5 / dirAbs.x; + uv = vec2(dir.x < 0.0 ? dir.z : -dir.z, -dir.y); + } + // downscale uv a little to hide seams + // transform coordinates from clip space to texture space + #ifndef _FlipY + return uv * 0.9976 * ma + 0.5; + #else + #ifdef HLSL + return uv * 0.9976 * ma + 0.5; + #else + return vec2(uv.x * ma, uv.y * -ma) * 0.9976 + 0.5; + #endif + #endif +} +#endif + +float lpToDepth(vec3 lp, const vec2 lightProj) { + lp = abs(lp); + float zcomp = max(lp.x, max(lp.y, lp.z)); + zcomp = lightProj.x - lightProj.y / zcomp; + return zcomp * 0.5 + 0.5; +} + +void main() { + int res = voxelgiResolution.x; + ivec3 dst = ivec3(gl_GlobalInvocationID.xyz); + + vec3 wposition = (gl_GlobalInvocationID.xyz + 0.5) / voxelgiResolution.x; + wposition = wposition * 2.0 - 1.0; + wposition *= float(clipmaps[int(clipmapLevel * 10)]); + wposition *= voxelgiResolution.x; + wposition += vec3(clipmaps[clipmapLevel * 10 + 4], clipmaps[clipmapLevel * 10 + 5], clipmaps[clipmapLevel * 10 + 6]); + + float visibility; + vec3 lp = lightPos -wposition; + vec3 l; + if (lightType == 0) { l = lightDir; visibility = 1.0; } + else { l = normalize(lp); visibility = attenuate(distance(wposition, lightPos)); } + +#ifdef _ShadowMap + if (lightShadow == 1) { + vec4 lightPosition = LVP * vec4(wposition, 1.0); + vec3 lPos = lightPosition.xyz / lightPosition.w; + visibility = texture(shadowMap, vec3(lPos.xy, lPos.z - shadowsBias)).r; + } + else if (lightShadow == 2) { + vec4 lightPosition = LVP * vec4(wposition, 1.0); + vec3 lPos = lightPosition.xyz / lightPosition.w; + visibility *= texture(shadowMapSpot, vec3(lPos.xy, lPos.z - shadowsBias)).r; + } + else if (lightShadow == 3) { + #ifdef _ShadowMapAtlas + int faceIndex = 0; + const int lightIndex = index * 6; + const vec2 uv = sampleCube(-l, faceIndex); + vec4 pointLightTile = pointLightDataArray[lightIndex + faceIndex]; // x: tile X offset, y: tile Y offset, z: tile size relative to atlas + vec2 uvtiled = pointLightTile.z * uv + pointLightTile.xy; + #ifdef _FlipY + uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system + #endif + visibility *= texture(shadowMapPoint, vec3(uvtiled, lpToDepth(lp, lightProj) - shadowsBias)).r; + #else + visibility *= texture(shadowMapPoint, vec4(-l, lpToDepth(lp, lightProj) - shadowsBias)).r; + #endif + } +#endif + + imageAtomicAdd(voxelsLight, dst, uint(visibility * lightColor.r * 255)); + imageAtomicAdd(voxelsLight, dst + ivec3(0, 0, voxelgiResolution.x), uint(visibility * lightColor.g * 255)); + imageAtomicAdd(voxelsLight, dst + ivec3(0, 0, voxelgiResolution.x * 2), uint(visibility * lightColor.b * 255)); +} From 7f7878aaa6a88e2dd82074c89a2baa97126a5b2c Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 21 May 2025 02:05:33 +0000 Subject: [PATCH 054/136] Update leenkx/Shaders/voxel_offsetprev/voxel_offsetprev.comp.glsl --- .../voxel_offsetprev/voxel_offsetprev.comp.glsl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/leenkx/Shaders/voxel_offsetprev/voxel_offsetprev.comp.glsl b/leenkx/Shaders/voxel_offsetprev/voxel_offsetprev.comp.glsl index bf6ac52..098284f 100644 --- a/leenkx/Shaders/voxel_offsetprev/voxel_offsetprev.comp.glsl +++ b/leenkx/Shaders/voxel_offsetprev/voxel_offsetprev.comp.glsl @@ -27,14 +27,14 @@ layout (local_size_x = 8, local_size_y = 8, local_size_z = 8) in; #include "std/math.glsl" #include "std/gbuffer.glsl" #include "std/imageatomic.glsl" -#include "std/voxels_constants.glsl" +#include "std/constants.glsl" #ifdef _VoxelGI -uniform layout(rgba8) image3D voxelsB; -uniform layout(rgba8) image3D voxelsOut; +uniform layout(rgba16f) image3D voxelsB; +uniform layout(rgba16f) image3D voxelsOut; #else -uniform layout(r16) image3D voxelsB; -uniform layout(r16) image3D voxelsOut; +uniform layout(r16f) image3D voxelsB; +uniform layout(r16f) image3D voxelsOut; #endif uniform int clipmapLevel; From 23af038a16633649a10739307b547330f4f17994 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 21 May 2025 02:07:21 +0000 Subject: [PATCH 055/136] Update leenkx/Shaders/voxel_resolve_ao/voxel_resolve_ao.comp.glsl --- .../voxel_resolve_ao.comp.glsl | 119 ++++++++++++++++-- 1 file changed, 109 insertions(+), 10 deletions(-) diff --git a/leenkx/Shaders/voxel_resolve_ao/voxel_resolve_ao.comp.glsl b/leenkx/Shaders/voxel_resolve_ao/voxel_resolve_ao.comp.glsl index 9c22bdb..d1425e9 100644 --- a/leenkx/Shaders/voxel_resolve_ao/voxel_resolve_ao.comp.glsl +++ b/leenkx/Shaders/voxel_resolve_ao/voxel_resolve_ao.comp.glsl @@ -29,19 +29,38 @@ layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in; #include "std/gbuffer.glsl" #include "std/imageatomic.glsl" #include "std/conetrace.glsl" +#include "std/brdf.glsl" +#include "std/shirr.glsl" uniform sampler3D voxels; uniform sampler2D gbufferD; uniform sampler2D gbuffer0; -uniform layout(r16) image2D voxels_ao; +uniform layout(rgba8) image2D voxels_ao; uniform float clipmaps[voxelgiClipmapCount * 10]; uniform mat4 InvVP; -uniform vec2 cameraProj; uniform vec3 eye; -uniform vec3 eyeLook; uniform vec2 postprocess_resolution; +uniform sampler2D gbuffer1; +#ifdef _gbuffer2 +uniform sampler2D gbuffer2; +#endif +uniform float envmapStrength; +#ifdef _Irr +uniform float shirr[7 * 4]; +#endif +#ifdef _Brdf +uniform sampler2D senvmapBrdf; +#endif +#ifdef _Rad +uniform sampler2D senvmapRadiance; +uniform int envmapNumMipmaps; +#endif +#ifdef _EnvCol +uniform vec3 backgroundCol; +#endif + void main() { const vec2 pixel = gl_GlobalInvocationID.xy; vec2 uv = (pixel + 0.5) / postprocess_resolution; @@ -54,12 +73,11 @@ void main() { float x = uv.x * 2 - 1; float y = uv.y * 2 - 1; - vec4 v = vec4(x, y, 1.0, 1.0); - v = vec4(InvVP * v); - v.xyz /= v.w; - vec3 viewRay = v.xyz - eye; + vec4 clipPos = vec4(x, y, depth, 1.0); + vec4 worldPos = InvVP * clipPos; + vec3 P = worldPos.xyz / worldPos.w; - vec3 P = getPos(eye, eyeLook, normalize(viewRay), depth, cameraProj); + vec3 v = normalize(eye - P); vec4 g0 = textureLod(gbuffer0, uv, 0.0); vec3 n; @@ -67,7 +85,88 @@ void main() { n.xy = n.z >= 0.0 ? g0.xy : octahedronWrap(g0.xy); n = normalize(n); - float occ = 1.0 - traceAO(P, n, voxels, clipmaps); + float roughness = g0.b; + float metallic; + uint matid; + unpackFloatInt16(g0.a, metallic, matid); - imageStore(voxels_ao, ivec2(pixel), vec4(occ)); + vec4 g1 = textureLod(gbuffer1, uv, 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); + float dotNV = max(dot(n, v), 0.0); + +#ifdef _gbuffer2 + vec4 g2 = textureLod(gbuffer2, uv, 0.0); +#endif + +#ifdef _MicroShadowing + occspec.x = mix(1.0, occspec.x, dotNV); // AO Fresnel +#endif + +#ifdef _Brdf + vec2 envBRDF = texelFetch(senvmapBrdf, ivec2(vec2(dotNV, 1.0 - roughness) * 256.0), 0).xy; +#endif + + // Envmap +#ifdef _Irr + vec4 shPacked[7]; + for (int i = 0; i < 7; i++) { + int base = i * 4; + shPacked[i] = vec4( + shirr[base], + shirr[base + 1], + shirr[base + 2], + shirr[base + 3] + ); + } + vec3 envl = shIrradiance(n, shPacked); + + #ifdef _gbuffer2 + if (g2.b < 0.5) { + envl = envl; + } else { + envl = vec3(0.0); + } + #endif + + #ifdef _EnvTex + envl /= PI; + #endif +#else + vec3 envl = vec3(0.0); +#endif + +#ifdef _Rad + vec3 reflectionWorld = reflect(-v, n); + float lod = getMipFromRoughness(roughness, envmapNumMipmaps); + vec3 prefilteredColor = textureLod(senvmapRadiance, envMapEquirect(reflectionWorld), lod).rgb; +#endif + +#ifdef _EnvLDR + envl.rgb = pow(envl.rgb, vec3(2.2)); + #ifdef _Rad + prefilteredColor = pow(prefilteredColor, vec3(2.2)); + #endif +#endif + + envl.rgb *= albedo; + +#ifdef _Brdf + envl.rgb *= 1.0 - (f0 * envBRDF.x + envBRDF.y); //LV: We should take refracted light into account +#endif + +#ifdef _Rad // Indirect specular + envl.rgb += prefilteredColor * (f0 * envBRDF.x + envBRDF.y); //LV: Removed "1.5 * occspec.y". Specular should be weighted only by FV LUT +#else + #ifdef _EnvCol + envl.rgb += backgroundCol * (f0 * envBRDF.x + envBRDF.y); //LV: Eh, what's the point of weighting it only by F0? + #endif +#endif + + envl.rgb *= envmapStrength * occspec.x; + + vec3 occ = envl * (1.0 - traceAO(P, n, voxels, clipmaps)); + + imageStore(voxels_ao, ivec2(pixel), vec4(occ, 1.0)); } From 25cf758a330e41cd050d675c87dee50aa33272a1 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 21 May 2025 02:08:50 +0000 Subject: [PATCH 056/136] Update leenkx/Shaders/voxel_resolve_diffuse/voxel_resolve_diffuse.comp.glsl --- .../voxel_resolve_diffuse.comp.glsl | 125 ++++++++++++++++-- 1 file changed, 113 insertions(+), 12 deletions(-) diff --git a/leenkx/Shaders/voxel_resolve_diffuse/voxel_resolve_diffuse.comp.glsl b/leenkx/Shaders/voxel_resolve_diffuse/voxel_resolve_diffuse.comp.glsl index 711e4af..75d5c3d 100644 --- a/leenkx/Shaders/voxel_resolve_diffuse/voxel_resolve_diffuse.comp.glsl +++ b/leenkx/Shaders/voxel_resolve_diffuse/voxel_resolve_diffuse.comp.glsl @@ -29,19 +29,38 @@ layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in; #include "std/gbuffer.glsl" #include "std/imageatomic.glsl" #include "std/conetrace.glsl" +#include "std/brdf.glsl" +#include "std/shirr.glsl" uniform sampler3D voxels; uniform sampler2D gbufferD; uniform sampler2D gbuffer0; -uniform layout(rgba16) image2D voxels_diffuse; +uniform layout(rgba8) image2D voxels_diffuse; uniform float clipmaps[voxelgiClipmapCount * 10]; uniform mat4 InvVP; -uniform vec2 cameraProj; uniform vec3 eye; -uniform vec3 eyeLook; uniform vec2 postprocess_resolution; +uniform sampler2D gbuffer1; +#ifdef _gbuffer2 +uniform sampler2D gbuffer2; +#endif +uniform float envmapStrength; +#ifdef _Irr +uniform float shirr[7 * 4]; +#endif +#ifdef _Brdf +uniform sampler2D senvmapBrdf; +#endif +#ifdef _Rad +uniform sampler2D senvmapRadiance; +uniform int envmapNumMipmaps; +#endif +#ifdef _EnvCol +uniform vec3 backgroundCol; +#endif + void main() { const vec2 pixel = gl_GlobalInvocationID.xy; vec2 uv = (pixel + 0.5) / postprocess_resolution; @@ -50,16 +69,14 @@ void main() { #endif float depth = textureLod(gbufferD, uv, 0.0).r * 2.0 - 1.0; - if (depth == 0) return; + if (depth == 0.0) return; float x = uv.x * 2 - 1; float y = uv.y * 2 - 1; - vec4 v = vec4(x, y, 1.0, 1.0); - v = vec4(InvVP * v); - v.xyz /= v.w; - vec3 viewRay = v.xyz - eye; - - vec3 P = getPos(eye, eyeLook, normalize(viewRay), depth, cameraProj); + vec4 clipPos = vec4(x, y, depth, 1.0); + vec4 worldPos = InvVP * clipPos; + vec3 P = worldPos.xyz / worldPos.w; + vec3 v = normalize(eye - P); vec4 g0 = textureLod(gbuffer0, uv, 0.0); vec3 n; @@ -67,7 +84,91 @@ void main() { n.xy = n.z >= 0.0 ? g0.xy : octahedronWrap(g0.xy); n = normalize(n); - vec4 color = traceDiffuse(P, n, voxels, clipmaps); + float roughness = g0.b; + float metallic; + uint matid; + unpackFloatInt16(g0.a, metallic, matid); - imageStore(voxels_diffuse, ivec2(pixel), color); + vec4 g1 = textureLod(gbuffer1, uv, 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); + float dotNV = max(dot(n, v), 0.0); + +#ifdef _gbuffer2 + vec4 g2 = textureLod(gbuffer2, uv, 0.0); +#endif + +#ifdef _MicroShadowing + occspec.x = mix(1.0, occspec.x, dotNV); // AO Fresnel +#endif + +#ifdef _Brdf + vec2 envBRDF = texelFetch(senvmapBrdf, ivec2(vec2(dotNV, 1.0 - roughness) * 256.0), 0).xy; + vec3 F = f0 * envBRDF.x + envBRDF.y; +#endif + + // Envmap +#ifdef _Irr + vec4 shPacked[7]; + for (int i = 0; i < 7; i++) { + int base = i * 4; + shPacked[i] = vec4( + shirr[base], + shirr[base + 1], + shirr[base + 2], + shirr[base + 3] + ); + } + vec3 envl = shIrradiance(n, shPacked); + + #ifdef _gbuffer2 + if (g2.b < 0.5) { + envl = envl; + } else { + envl = vec3(0.0); + } + #endif + + #ifdef _EnvTex + envl /= PI; + #endif +#else + vec3 envl = vec3(0.0); +#endif + +#ifdef _Rad + vec3 reflectionWorld = reflect(-v, n); + float lod = getMipFromRoughness(roughness, envmapNumMipmaps); + vec3 prefilteredColor = textureLod(senvmapRadiance, envMapEquirect(reflectionWorld), lod).rgb; +#endif + +#ifdef _EnvLDR + envl.rgb = pow(envl.rgb, vec3(2.2)); + #ifdef _Rad + prefilteredColor = pow(prefilteredColor, vec3(2.2)); + #endif +#endif + + envl.rgb *= albedo; + +#ifdef _Brdf + envl.rgb *= 1.0 - F; //LV: We should take refracted light into account +#endif + +#ifdef _Rad // Indirect specular + envl.rgb += prefilteredColor * F; //LV: Removed "1.5 * occspec.y". Specular should be weighted only by FV LUT +#else + #ifdef _EnvCol + envl.rgb += backgroundCol * F; //LV: Eh, what's the point of weighting it only by F0? + #endif +#endif + + envl.rgb *= envmapStrength * occspec.x; + + vec4 trace = traceDiffuse(P, n, voxels, clipmaps); + vec3 color = trace.rgb * albedo * (1.0 - F); + color += envl * (1.0 - trace.a); + + imageStore(voxels_diffuse, ivec2(pixel), vec4(color, 1.0)); } From 413435268893f9954c041b73deb1bde35aef999f Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 21 May 2025 02:10:21 +0000 Subject: [PATCH 057/136] Update leenkx/Shaders/voxel_resolve_specular/voxel_resolve_specular.comp.glsl --- .../voxel_resolve_specular.comp.glsl | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/leenkx/Shaders/voxel_resolve_specular/voxel_resolve_specular.comp.glsl b/leenkx/Shaders/voxel_resolve_specular/voxel_resolve_specular.comp.glsl index 6fd662d..30c07f2 100644 --- a/leenkx/Shaders/voxel_resolve_specular/voxel_resolve_specular.comp.glsl +++ b/leenkx/Shaders/voxel_resolve_specular/voxel_resolve_specular.comp.glsl @@ -29,18 +29,17 @@ layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in; #include "std/gbuffer.glsl" #include "std/imageatomic.glsl" #include "std/conetrace.glsl" +#include "std/brdf.glsl" uniform sampler2D gbufferD; uniform sampler2D gbuffer0; uniform sampler3D voxels; uniform sampler3D voxelsSDF; -uniform layout(rgba16) image2D voxels_specular; +uniform layout(rgba8) image2D voxels_specular; uniform float clipmaps[voxelgiClipmapCount * 10]; uniform mat4 InvVP; -uniform vec2 cameraProj; uniform vec3 eye; -uniform vec3 eyeLook; uniform vec2 postprocess_resolution; uniform sampler2D sveloc; @@ -56,12 +55,10 @@ void main() { float x = uv.x * 2 - 1; float y = uv.y * 2 - 1; - vec4 v = vec4(x, y, 1.0, 1.0); - v = vec4(InvVP * v); - v.xyz /= v.w; + vec4 clipPos = vec4(x, y, depth, 1.0); + vec4 worldPos = InvVP * clipPos; + vec3 P = worldPos.xyz / worldPos.w; - vec3 viewRay = v.xyz - eye; - vec3 P = getPos(eye, eyeLook, normalize(viewRay), depth, cameraProj); vec4 g0 = textureLod(gbuffer0, uv, 0.0); vec3 n; @@ -71,7 +68,7 @@ void main() { vec2 velocity = -textureLod(sveloc, uv, 0.0).rg; - vec3 color = traceSpecular(P, n, voxels, voxelsSDF, normalize(eye - P), g0.z * g0.z, clipmaps, pixel, velocity).rgb; + vec3 color = traceSpecular(P, n, voxels, voxelsSDF, normalize(eye - P), g0.z * g0.z, clipmaps, pixel, velocity).rgb * voxelgiRefl; imageStore(voxels_specular, ivec2(pixel), vec4(color, 1.0)); } From 29e4993f06e7598ab21416d93eb74724140505ef Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 21 May 2025 16:05:53 +0000 Subject: [PATCH 058/136] Update leenkx/Shaders/voxel_sdf_jumpflood/voxel_sdf_jumpflood.comp.glsl --- .../Shaders/voxel_sdf_jumpflood/voxel_sdf_jumpflood.comp.glsl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/leenkx/Shaders/voxel_sdf_jumpflood/voxel_sdf_jumpflood.comp.glsl b/leenkx/Shaders/voxel_sdf_jumpflood/voxel_sdf_jumpflood.comp.glsl index 5e6a0ea..9bd624d 100644 --- a/leenkx/Shaders/voxel_sdf_jumpflood/voxel_sdf_jumpflood.comp.glsl +++ b/leenkx/Shaders/voxel_sdf_jumpflood/voxel_sdf_jumpflood.comp.glsl @@ -23,8 +23,8 @@ THE SOFTWARE. #include "compiled.inc" -uniform layout(r8) image3D input_sdf; -uniform layout(r8) image3D output_sdf; +uniform layout(r16f) image3D input_sdf; +uniform layout(r16f) image3D output_sdf; uniform float jump_size; uniform int clipmapLevel; From b8ca4be56a6db1222384cb549945cd9db0263ac1 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 21 May 2025 16:08:14 +0000 Subject: [PATCH 059/136] Update leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl --- .../voxel_temporal/voxel_temporal.comp.glsl | 111 +++++++++--------- 1 file changed, 58 insertions(+), 53 deletions(-) diff --git a/leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl b/leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl index 6c70b3b..7a89be0 100644 --- a/leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl +++ b/leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl @@ -41,20 +41,21 @@ uniform vec2 lightProj; uniform float shadowsBias; uniform mat4 LVP; #endif +uniform float envmapStrength; uniform sampler3D voxelsSampler; uniform layout(r32ui) uimage3D voxels; uniform layout(r32ui) uimage3D voxelsLight; -uniform layout(rgba8) image3D voxelsB; -uniform layout(rgba8) image3D voxelsOut; -uniform layout(r8) image3D SDF; +uniform layout(rgba16f) image3D voxelsB; +uniform layout(rgba16f) image3D voxelsOut; +uniform layout(r16f) image3D SDF; #else #ifdef _VoxelAOvar #ifdef _VoxelShadow -uniform layout(r8) image3D SDF; +uniform layout(r16f) image3D SDF; #endif uniform layout(r32ui) uimage3D voxels; -uniform layout(r8) image3D voxelsB; -uniform layout(r8) image3D voxelsOut; +uniform layout(r16f) image3D voxelsB; +uniform layout(r16f) image3D voxelsOut; #endif #endif @@ -74,14 +75,6 @@ void main() { #endif #endif - ivec3 src = ivec3(gl_GlobalInvocationID.xyz); - #ifdef _VoxelGI - vec3 light = vec3(0.0); - light.r = float(imageLoad(voxelsLight, src)) / 255; - light.g = float(imageLoad(voxelsLight, src + ivec3(0, 0, voxelgiResolution.x))) / 255; - light.b = float(imageLoad(voxelsLight, src + ivec3(0, 0, voxelgiResolution.x * 2))) / 255; - #endif - for (int i = 0; i < 6 + DIFFUSE_CONE_COUNT; i++) { #ifdef _VoxelGI @@ -90,7 +83,7 @@ void main() { float aniso_colors[6]; #endif - src = ivec3(gl_GlobalInvocationID.xyz); + ivec3 src = ivec3(gl_GlobalInvocationID.xyz); src.x += i * res; ivec3 dst = src; dst.y += clipmapLevel * res; @@ -103,44 +96,58 @@ void main() { if (i < 6) { #ifdef _VoxelGI - vec4 basecol = vec4(0.0); - basecol.r = float(imageLoad(voxels, src)) / 255; - basecol.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x))) / 255; - basecol.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 2))) / 255; - basecol.a = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 3))) / 255; - basecol /= 4; - vec3 emission = vec3(0.0); - emission.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 4))) / 255; - emission.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 5))) / 255; - emission.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 6))) / 255; - emission /= 3; - vec3 N = vec3(0.0); - N.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 7))) / 255; - N.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 8))) / 255; - N /= 2; - vec3 wnormal = decode_oct(N.rg * 2 - 1); - vec3 envl = vec3(0.0); - envl.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 9))) / 255; - envl.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 10))) / 255; - envl.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 11))) / 255; - envl /= 3; + int count = int(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 15))); + if (count > 0) { + vec4 basecol = vec4(0.0); + basecol.r = float(imageLoad(voxels, src)) / 255; + basecol.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x))) / 255; + basecol.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 2))) / 255; + basecol.a = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 3))) / 255; + basecol /= count; + vec3 emission = vec3(0.0); + emission.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 4))) / 255; + emission.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 5))) / 255; + emission.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 6))) / 255; + emission /= count; + // Retrieve encoded normal (stored in 8-bit format) + vec3 N = vec3(0.0); + N.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 7))) / 255.0; + N.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 8))) / 255.0; + N /= count; + // Decode octahedral normal + N = decode_oct(N.rg * 2.0 - 1.0); + vec3 envl = vec3(0.0); + envl.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 9))) / 255; + envl.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 10))) / 255; + envl.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 11))) / 255; + envl /= count; + envl *= envmapStrength; + vec3 light = vec3(0.0); + light.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 12))) / 255; + light.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 13))) / 255; + light.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 14))) / 255; + light /= count; - //clipmap to world - vec3 wposition = (gl_GlobalInvocationID.xyz + 0.5) / voxelgiResolution.x; - wposition = wposition * 2.0 - 1.0; - wposition *= float(clipmaps[int(clipmapLevel * 10)]); - wposition *= voxelgiResolution.x; - wposition += vec3(clipmaps[clipmapLevel * 10 + 4], clipmaps[clipmapLevel * 10 + 5], clipmaps[clipmapLevel * 10 + 6]); - - radiance = basecol; - vec4 trace = traceDiffuse(wposition, wnormal, voxelsSampler, clipmaps); - vec3 indirect = trace.rgb + envl.rgb * (1.0 - trace.a); - radiance.rgb *= light / PI + indirect; - radiance.rgb += emission.rgb; + //clipmap to world + vec3 P = (gl_GlobalInvocationID.xyz + 0.5) / voxelgiResolution.x; + P = P * 2.0 - 1.0; + P *= float(clipmaps[int(clipmapLevel * 10)]); + P *= voxelgiResolution.x; + P += vec3(clipmaps[clipmapLevel * 10 + 4], clipmaps[clipmapLevel * 10 + 5], clipmaps[clipmapLevel * 10 + 6]); + radiance = basecol; + vec4 trace = traceDiffuse(P, N, voxelsSampler, clipmaps); + vec3 indirect = trace.rgb + envl.rgb * (1.0 - trace.a); + radiance.rgb *= light + indirect; + radiance.rgb += emission.rgb; + } #else - opac = float(imageLoad(voxels, src)) / 255; + int count = int(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x))); + if (count > 0) { + opac = float(imageLoad(voxels, src)) / 255; + opac /= count; + } #endif #ifdef _VoxelGI @@ -206,15 +213,13 @@ void main() { vec4 sam = aniso_colors[face_offsets.x] * direction_weights.x + aniso_colors[face_offsets.y] * direction_weights.y + - aniso_colors[face_offsets.z] * direction_weights.z - ; + aniso_colors[face_offsets.z] * direction_weights.z; radiance = sam; #else float sam = aniso_colors[face_offsets.x] * direction_weights.x + aniso_colors[face_offsets.y] * direction_weights.y + - aniso_colors[face_offsets.z] * direction_weights.z - ; + aniso_colors[face_offsets.z] * direction_weights.z; opac = sam; #endif } From 9ef9f5a6378696dfeb26dd7f52b40c8ab28f91d0 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 21 May 2025 16:15:50 +0000 Subject: [PATCH 060/136] Update leenkx/Sources/leenkx/renderpath/Inc.hx --- leenkx/Sources/leenkx/renderpath/Inc.hx | 424 ++++++++---------------- 1 file changed, 139 insertions(+), 285 deletions(-) diff --git a/leenkx/Sources/leenkx/renderpath/Inc.hx b/leenkx/Sources/leenkx/renderpath/Inc.hx index 69087f3..3f084a4 100644 --- a/leenkx/Sources/leenkx/renderpath/Inc.hx +++ b/leenkx/Sources/leenkx/renderpath/Inc.hx @@ -31,13 +31,13 @@ class Inc { static var m = iron.math.Mat4.identity(); static var voxel_ca1:kha.compute.ConstantLocation; static var voxel_cb1:kha.compute.ConstantLocation; + static var voxel_cc1:kha.compute.ConstantLocation; #if (rp_voxels == "Voxel GI") static var voxel_td1:kha.compute.TextureUnit; static var voxel_te1:kha.compute.TextureUnit; - static var voxel_tf1:kha.compute.TextureUnit; #else #if lnx_voxelgi_shadows - static var voxel_tf1:kha.compute.TextureUnit; + static var voxel_te1:kha.compute.TextureUnit; #end #end #if (lnx_voxelgi_shadows || rp_voxels == "Voxel GI") @@ -53,12 +53,28 @@ class Inc { static var voxel_tb3:kha.compute.TextureUnit; static var voxel_tc3:kha.compute.TextureUnit; static var voxel_td3:kha.compute.TextureUnit; + static var voxel_te3:kha.compute.TextureUnit; + static var voxel_tf3:kha.compute.TextureUnit; + #if lnx_brdf + static var voxel_tg3:kha.compute.TextureUnit; + #end + #if lnx_radiance + static var voxel_th3:kha.compute.TextureUnit; + #end static var voxel_ca3:kha.compute.ConstantLocation; static var voxel_cb3:kha.compute.ConstantLocation; static var voxel_cc3:kha.compute.ConstantLocation; static var voxel_cd3:kha.compute.ConstantLocation; static var voxel_ce3:kha.compute.ConstantLocation; + #if lnx_irradiance static var voxel_cf3:kha.compute.ConstantLocation; + #end + #if lnx_radiance + static var voxel_cg3:kha.compute.ConstantLocation; + #end + #if lnx_envcol + static var voxel_ch3:kha.compute.ConstantLocation; + #end #if (rp_voxels == "Voxel GI") static var voxel_sh4:kha.compute.Shader = null; static var voxel_ta4:kha.compute.TextureUnit; @@ -71,36 +87,6 @@ class Inc { static var voxel_cb4:kha.compute.ConstantLocation; static var voxel_cc4:kha.compute.ConstantLocation; static var voxel_cd4:kha.compute.ConstantLocation; - static var voxel_ce4:kha.compute.ConstantLocation; - static var voxel_cf4:kha.compute.ConstantLocation; - #end - #if (rp_voxels == "Voxel GI") - static var voxel_sh5:kha.compute.Shader = null; - static var voxel_ta5:kha.compute.TextureUnit; - static var voxel_te5:kha.compute.TextureUnit; - static var voxel_tf5:kha.compute.TextureUnit; - static var voxel_tg5:kha.compute.TextureUnit; - static var voxel_ca5:kha.compute.ConstantLocation; - static var voxel_cb5:kha.compute.ConstantLocation; - static var voxel_cc5:kha.compute.ConstantLocation; - static var voxel_cd5:kha.compute.ConstantLocation; - static var voxel_ce5:kha.compute.ConstantLocation; - static var voxel_cf5:kha.compute.ConstantLocation; - static var voxel_cg5:kha.compute.ConstantLocation; - #if rp_shadowmap - static var voxel_tb5:kha.compute.TextureUnit; - static var voxel_tc5:kha.compute.TextureUnit; - static var voxel_td5:kha.compute.TextureUnit; - static var voxel_ch5:kha.compute.ConstantLocation; - static var voxel_ci5:kha.compute.ConstantLocation; - static var voxel_cj5:kha.compute.ConstantLocation; - static var voxel_ck5:kha.compute.ConstantLocation; - static var voxel_cl5:kha.compute.ConstantLocation; - static var voxel_cm5:kha.compute.ConstantLocation; - #if lnx_shadowmap_atlas - static var m2 = iron.math.Mat4.identity(); - #end - #end #end #end //rp_voxels @@ -401,7 +387,7 @@ class Inc { #if lnx_debug endShadowsLogicProfile(); #end - #end // rp_shadowmap + #end } #else public static function bindShadowMap() { @@ -585,7 +571,7 @@ class Inc { t.width = 0; t.height = 0; t.displayp = getDisplayp(); - t.format = "R32"; + t.format = "R16"; t.scale = getSuperSampling(); t.depth_buffer = "main"; path.createRenderTarget(t); @@ -675,12 +661,11 @@ class Inc { t.width = 0; t.height = 0; t.displayp = getDisplayp(); - //t.scale = Inc.getSuperSampling(); - t.format = t.name == "voxels_ao" ? "R8" : "RGBA32"; + t.format = "RGBA32"; } else { if (t.name == "voxelsSDF" || t.name == "voxelsSDFtmp") { - t.format = "R8"; + t.format = "R16"; t.width = res; t.height = res * Main.voxelgiClipmapCount; t.depth = res; @@ -689,37 +674,31 @@ class Inc { #if (rp_voxels == "Voxel AO") { if (t.name == "voxelsOut" || t.name == "voxelsOutB") { - t.format = "R8"; + t.format = "R16"; t.width = res * (6 + 16); t.height = res * Main.voxelgiClipmapCount; t.depth = res; } else { - t.format = "R32"; + t.format = "R32UI"; t.width = res * 6; t.height = res; - t.depth = res; + t.depth = res * 2; } } #else { if (t.name == "voxelsOut" || t.name == "voxelsOutB") { - t.format = "RGBA32"; + t.format = "RGBA64"; t.width = res * (6 + 16); t.height = res * Main.voxelgiClipmapCount; t.depth = res; } - else if (t.name == "voxelsLight") { - t.format = "R32"; - t.width = res; - t.height = res; - t.depth = res * 3; - } else { - t.format = "R32"; + t.format = "R32UI"; t.width = res * 6; t.height = res; - t.depth = res * 12; + t.depth = res * 16; } } #end @@ -827,14 +806,14 @@ class Inc { voxel_ca1 = voxel_sh1.getConstantLocation("clipmaps"); voxel_cb1 = voxel_sh1.getConstantLocation("clipmapLevel"); + voxel_cc1 = voxel_sh1.getConstantLocation("envmapStrength"); #if (rp_voxels == "Voxel GI") voxel_td1 = voxel_sh1.getTextureUnit("voxelsSampler"); - voxel_te1 = voxel_sh1.getTextureUnit("voxelsLight"); - voxel_tf1 = voxel_sh1.getTextureUnit("SDF"); + voxel_te1 = voxel_sh1.getTextureUnit("SDF"); #else #if lnx_voxelgi_shadows - voxel_tf1 = voxel_sh1.getTextureUnit("SDF"); + voxel_te1 = voxel_sh1.getTextureUnit("SDF"); #end #end } @@ -865,12 +844,28 @@ class Inc { #else voxel_td3 = voxel_sh3.getTextureUnit("voxels_diffuse"); #end - voxel_ca3 = voxel_sh3.getConstantLocation("clipmaps"); + voxel_te3 = voxel_sh3.getTextureUnit("gbuffer1"); + voxel_tf3 = voxel_sh3.getTextureUnit("gbuffer2"); + #if lnx_brdf + voxel_tg3 = voxel_sh3.getTextureUnit("senvmapBrdf"); + #end + #if lnx_radiance + voxel_th3 = voxel_sh3.getTextureUnit("senvmapRadiance"); + #end + voxel_ca3 = voxel_sh3.getConstantLocation("clipmaps"); voxel_cb3 = voxel_sh3.getConstantLocation("InvVP"); - voxel_cc3 = voxel_sh3.getConstantLocation("cameraProj"); - voxel_cd3 = voxel_sh3.getConstantLocation("eye"); - voxel_ce3 = voxel_sh3.getConstantLocation("eyeLook"); - voxel_cf3 = voxel_sh3.getConstantLocation("postprocess_resolution"); + voxel_cc3 = voxel_sh3.getConstantLocation("eye"); + voxel_cd3 = voxel_sh3.getConstantLocation("postprocess_resolution"); + voxel_ce3 = voxel_sh3.getConstantLocation("envmapStrength"); + #if lnx_irradiance + voxel_cf3 = voxel_sh3.getConstantLocation("shirr"); + #end + #if lnx_radiance + voxel_cg3 = voxel_sh3.getConstantLocation("envmapNumMipmaps"); + #end + #if lnx_envcol + voxel_ch3 = voxel_sh3.getConstantLocation("backgroundCol"); + #end } #if (rp_voxels == "Voxel GI") if (voxel_sh4 == null) @@ -884,42 +879,8 @@ class Inc { voxel_tf4 = voxel_sh4.getTextureUnit("sveloc"); voxel_ca4 = voxel_sh4.getConstantLocation("clipmaps"); voxel_cb4 = voxel_sh4.getConstantLocation("InvVP"); - voxel_cc4 = voxel_sh4.getConstantLocation("cameraProj"); - voxel_cd4 = voxel_sh4.getConstantLocation("eye"); - voxel_ce4 = voxel_sh4.getConstantLocation("eyeLook"); - voxel_cf4 = voxel_sh4.getConstantLocation("postprocess_resolution"); - } - #end - #if (rp_voxels == "Voxel GI") - if (voxel_sh5 == null) - { - voxel_sh5 = path.getComputeShader("voxel_light"); - voxel_ta5 = voxel_sh5.getTextureUnit("voxelsLight"); - voxel_te5 = voxel_sh5.getTextureUnit("voxels"); - voxel_tf5 = voxel_sh5.getTextureUnit("voxelsSampler"); - voxel_tg5 = voxel_sh5.getTextureUnit("voxelsSDFSampler"); - voxel_ca5 = voxel_sh5.getConstantLocation("clipmaps"); - voxel_cb5 = voxel_sh5.getConstantLocation("clipmapLevel"); - - voxel_cc5 = voxel_sh5.getConstantLocation("lightPos"); - voxel_cd5 = voxel_sh5.getConstantLocation("lightColor"); - voxel_ce5 = voxel_sh5.getConstantLocation("lightType"); - voxel_cf5 = voxel_sh5.getConstantLocation("lightDir"); - voxel_cg5 = voxel_sh5.getConstantLocation("spotData"); - #if rp_shadowmap - voxel_tb5 = voxel_sh5.getTextureUnit("shadowMap"); - voxel_tc5 = voxel_sh5.getTextureUnit("shadowMapSpot"); - voxel_td5 = voxel_sh5.getTextureUnit("shadowMapPoint"); - - voxel_ch5 = voxel_sh5.getConstantLocation("lightShadow"); - voxel_ci5 = voxel_sh5.getConstantLocation("lightProj"); - voxel_cj5 = voxel_sh5.getConstantLocation("LVP"); - voxel_ck5 = voxel_sh5.getConstantLocation("shadowsBias"); - #if lnx_shadowmap_atlas - voxel_cl5 = voxel_sh5.getConstantLocation("index"); - voxel_cm5 = voxel_sh5.getConstantLocation("pointLightDataArray"); - #end - #end + voxel_cc4 = voxel_sh4.getConstantLocation("eye"); + voxel_cd4 = voxel_sh4.getConstantLocation("postprocess_resolution"); } #end } @@ -970,11 +931,10 @@ class Inc { kha.compute.Compute.setTexture(voxel_tc1, rts.get("voxelsOut").image, kha.compute.Access.Write); #if (rp_voxels == "Voxel GI") kha.compute.Compute.setSampledTexture(voxel_td1, rts.get("voxelsOutB").image); - kha.compute.Compute.setTexture(voxel_te1, rts.get("voxelsLight").image, kha.compute.Access.Read); - kha.compute.Compute.setTexture(voxel_tf1, rts.get("voxelsSDF").image, kha.compute.Access.Write); + kha.compute.Compute.setTexture(voxel_te1, rts.get("voxelsSDF").image, kha.compute.Access.Write); #else #if lnx_voxelgi_shadows - kha.compute.Compute.setTexture(voxel_tf1, rts.get("voxelsSDF").image, kha.compute.Access.Write); + kha.compute.Compute.setTexture(voxel_te1, rts.get("voxelsSDF").image, kha.compute.Access.Write); #end #end @@ -996,6 +956,8 @@ class Inc { kha.compute.Compute.setInt(voxel_cb1, iron.RenderPath.clipmapLevel); + kha.compute.Compute.setFloat(voxel_cc1, iron.Scene.active.world == null ? 0.0 : iron.Scene.active.world.probe.raw.strength); + kha.compute.Compute.compute(Std.int(res / 8), Std.int(res / 8), Std.int(res / 8)); } @@ -1048,6 +1010,7 @@ class Inc { } } #end + #if (rp_voxels == "Voxel AO") public static function resolveAO() { var rts = path.renderTargets; @@ -1060,13 +1023,20 @@ class Inc { kha.compute.Compute.setSampledTexture(voxel_ta3, rts.get("voxelsOut").image); kha.compute.Compute.setSampledTexture(voxel_tb3, rts.get("half").image); - #if lnx_deferred kha.compute.Compute.setSampledTexture(voxel_tc3, rts.get("gbuffer0").image); - #else - kha.compute.Compute.setSampledTexture(voxel_tc3, rts.get("lbuffer1").image); - #end kha.compute.Compute.setTexture(voxel_td3, rts.get("voxels_ao").image, kha.compute.Access.Write); + kha.compute.Compute.setSampledTexture(voxel_te3, rts.get("gbuffer1").image); + #if rp_gbuffer2 + kha.compute.Compute.setSampledTexture(voxel_tf3, rts.get("gbuffer2").image); + #end + #if lnx_brdf + kha.compute.Compute.setSampledTexture(voxel_tg3, iron.Scene.active.embedded.get("brdf.png")); + #end + #if lnx_radiance + kha.compute.Compute.setSampledTexture(voxel_th3, iron.Scene.active.world.probe.radiance); + #end + var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); for (i in 0...Main.voxelgiClipmapCount) { fa[i * 10] = clipmaps[i].voxelSize; @@ -1093,18 +1063,7 @@ class Inc { kha.compute.Compute.setMatrix(voxel_cb3, m.self); - var near = camera.data.raw.near_plane; - var far = camera.data.raw.far_plane; - var v = new iron.math.Vec2(); - v.x = far / (far - near); - v.y = (-far * near) / (far - near); - - kha.compute.Compute.setFloat2(voxel_cc3, v.x, v.y); - - - kha.compute.Compute.setFloat3(voxel_cd3, camera.transform.worldx(), camera.transform.worldy(), camera.transform.worldz()); - var eyeLook = camera.lookWorld().normalize(); - kha.compute.Compute.setFloat3(voxel_ce3, eyeLook.x, eyeLook.y, eyeLook.z); + kha.compute.Compute.setFloat3(voxel_cc3, camera.transform.worldx(), camera.transform.worldy(), camera.transform.worldz()); var width = iron.App.w(); var height = iron.App.h(); @@ -1119,7 +1078,32 @@ class Inc { width = Std.int(dp * Inc.getSuperSampling()); } } - kha.compute.Compute.setFloat2(voxel_cf3, width, height); + kha.compute.Compute.setFloat2(voxel_cd3, width, height); + + kha.compute.Compute.setFloat(voxel_ce3, iron.Scene.active.world == null ? 0.0 : iron.Scene.active.world.probe.raw.strength); + #if lnx_irradiance + var irradiance = iron.Scene.active.world == null ? + iron.data.WorldData.getEmptyIrradiance() : + iron.Scene.active.world.probe.irradiance; + kha.compute.Compute.setFloats(voxel_cf3, irradiance); + #end + #if lnx_radiance + kha.compute.Compute.setFloat(voxel_cg3, iron.Scene.active.world != null ? iron.Scene.active.world.probe.raw.radiance_mipmaps + 1 - 2 : 1); + #end + + #if lnx_envcol + var x: kha.FastFloat = 0.0; + var y: kha.FastFloat = 0.0; + var z: kha.FastFloat = 0.0; + + if (camera.data.raw.clear_color != null) { + x = camera.data.raw.clear_color[0]; + y = camera.data.raw.clear_color[1]; + z = camera.data.raw.clear_color[2]; + } + + kha.compute.Compute.setFloat3(voxel_ch3, x, y, z); + #end kha.compute.Compute.compute(Std.int((width + 7) / 8), Std.int((height + 7) / 8), 1); } @@ -1135,12 +1119,18 @@ class Inc { kha.compute.Compute.setSampledTexture(voxel_ta3, rts.get("voxelsOut").image); kha.compute.Compute.setSampledTexture(voxel_tb3, rts.get("half").image); - #if lnx_deferred kha.compute.Compute.setSampledTexture(voxel_tc3, rts.get("gbuffer0").image); - #else - kha.compute.Compute.setSampledTexture(voxel_tc3, rts.get("lbuffer1").image); - #end kha.compute.Compute.setTexture(voxel_td3, rts.get("voxels_diffuse").image, kha.compute.Access.Write); + kha.compute.Compute.setSampledTexture(voxel_te3, rts.get("gbuffer1").image); + #if rp_gbuffer2 + kha.compute.Compute.setSampledTexture(voxel_tf3, rts.get("gbuffer2").image); + #end + #if lnx_brdf + kha.compute.Compute.setSampledTexture(voxel_tg3, iron.Scene.active.embedded.get("brdf.png")); + #end + #if lnx_radiance + kha.compute.Compute.setSampledTexture(voxel_th3, iron.Scene.active.world.probe.radiance); + #end var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); for (i in 0...Main.voxelgiClipmapCount) { @@ -1168,18 +1158,7 @@ class Inc { kha.compute.Compute.setMatrix(voxel_cb3, m.self); - var near = camera.data.raw.near_plane; - var far = camera.data.raw.far_plane; - var v = new iron.math.Vec2(); - v.x = far / (far - near); - v.y = (-far * near) / (far - near); - - kha.compute.Compute.setFloat2(voxel_cc3, v.x, v.y); - - - kha.compute.Compute.setFloat3(voxel_cd3, camera.transform.worldx(), camera.transform.worldy(), camera.transform.worldz()); - var eyeLook = camera.lookWorld().normalize(); - kha.compute.Compute.setFloat3(voxel_ce3, eyeLook.x, eyeLook.y, eyeLook.z); + kha.compute.Compute.setFloat3(voxel_cc3, camera.transform.worldx(), camera.transform.worldy(), camera.transform.worldz()); var width = iron.App.w(); var height = iron.App.h(); @@ -1194,7 +1173,32 @@ class Inc { width = Std.int(dp * Inc.getSuperSampling()); } } - kha.compute.Compute.setFloat2(voxel_cf3, width, height); + kha.compute.Compute.setFloat2(voxel_cd3, width, height); + + kha.compute.Compute.setFloat(voxel_ce3, iron.Scene.active.world == null ? 0.0 : iron.Scene.active.world.probe.raw.strength); + #if lnx_irradiance + var irradiance = iron.Scene.active.world == null ? + iron.data.WorldData.getEmptyIrradiance() : + iron.Scene.active.world.probe.irradiance; + kha.compute.Compute.setFloats(voxel_cf3, irradiance); + #end + #if lnx_radiance + kha.compute.Compute.setFloat(voxel_cg3, iron.Scene.active.world != null ? iron.Scene.active.world.probe.raw.radiance_mipmaps + 1 - 2 : 1); + #end + + #if lnx_envcol + var x: kha.FastFloat = 0.0; + var y: kha.FastFloat = 0.0; + var z: kha.FastFloat = 0.0; + + if (camera.data.raw.clear_color != null) { + x = camera.data.raw.clear_color[0]; + y = camera.data.raw.clear_color[1]; + z = camera.data.raw.clear_color[2]; + } + + kha.compute.Compute.setFloat3(voxel_ch3, x, y, z); + #end kha.compute.Compute.compute(Std.int((width + 7) / 8), Std.int((height + 7) / 8), 1); } @@ -1210,13 +1214,12 @@ class Inc { kha.compute.Compute.setSampledTexture(voxel_ta4, rts.get("voxelsOut").image); kha.compute.Compute.setSampledTexture(voxel_tb4, rts.get("half").image); - #if lnx_deferred kha.compute.Compute.setSampledTexture(voxel_tc4, rts.get("gbuffer0").image); - #else - kha.compute.Compute.setSampledTexture(voxel_tc4, rts.get("lbuffer1").image); - #end kha.compute.Compute.setSampledTexture(voxel_td4, rts.get("voxelsSDF").image); kha.compute.Compute.setTexture(voxel_te4, rts.get("voxels_specular").image, kha.compute.Access.Write); + #if rp_gbuffer2 + kha.compute.Compute.setSampledTexture(voxel_tf4, rts.get("gbuffer2").image); + #end kha.compute.Compute.setSampledTexture(voxel_tf4, rts.get("gbuffer2").image); @@ -1246,18 +1249,7 @@ class Inc { kha.compute.Compute.setMatrix(voxel_cb4, m.self); - var near = camera.data.raw.near_plane; - var far = camera.data.raw.far_plane; - var v = new iron.math.Vec2(); - v.x = far / (far - near); - v.y = (-far * near) / (far - near); - - kha.compute.Compute.setFloat2(voxel_cc4, v.x, v.y); - - - kha.compute.Compute.setFloat3(voxel_cd4, camera.transform.worldx(), camera.transform.worldy(), camera.transform.worldz()); - var eyeLook = camera.lookWorld().normalize(); - kha.compute.Compute.setFloat3(voxel_ce4, eyeLook.x, eyeLook.y, eyeLook.z); + kha.compute.Compute.setFloat3(voxel_cc4, camera.transform.worldx(), camera.transform.worldy(), camera.transform.worldz()); var width = iron.App.w(); var height = iron.App.h(); @@ -1272,148 +1264,10 @@ class Inc { width = Std.int(dp * Inc.getSuperSampling()); } } - kha.compute.Compute.setFloat2(voxel_cf4, width, height); + kha.compute.Compute.setFloat2(voxel_cd4, width, height); kha.compute.Compute.compute(Std.int((width + 7) / 8), Std.int((height + 7) / 8), 1); } - public static function computeVoxelsLight() { - var rts = path.renderTargets; - var res = iron.RenderPath.getVoxelRes(); - var camera = iron.Scene.active.camera; - var clipmaps = iron.RenderPath.clipmaps; - var clipmap = clipmaps[iron.RenderPath.clipmapLevel]; - var lights = iron.Scene.active.lights; - - pointIndex = spotIndex = 0; - for (i in 0...lights.length) { - var l = lights[i]; - if (!l.visible) continue; - path.light = l; - - kha.compute.Compute.setShader(voxel_sh5); - - kha.compute.Compute.setTexture(voxel_ta5, rts.get("voxelsLight").image, kha.compute.Access.Write); - kha.compute.Compute.setTexture(voxel_te5, rts.get("voxels").image, kha.compute.Access.Read); - kha.compute.Compute.setSampledTexture(voxel_tf5, rts.get("voxelsOut").image); - kha.compute.Compute.setSampledTexture(voxel_tg5, rts.get("voxelsSDF").image); - var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); - for (i in 0...Main.voxelgiClipmapCount) { - fa[i * 10] = clipmaps[i].voxelSize; - fa[i * 10 + 1] = clipmaps[i].extents.x; - fa[i * 10 + 2] = clipmaps[i].extents.y; - fa[i * 10 + 3] = clipmaps[i].extents.z; - fa[i * 10 + 4] = clipmaps[i].center.x; - fa[i * 10 + 5] = clipmaps[i].center.y; - fa[i * 10 + 6] = clipmaps[i].center.z; - fa[i * 10 + 7] = clipmaps[i].offset_prev.x; - fa[i * 10 + 8] = clipmaps[i].offset_prev.y; - fa[i * 10 + 9] = clipmaps[i].offset_prev.z; - } - - kha.compute.Compute.setFloats(voxel_ca5, fa); - - kha.compute.Compute.setInt(voxel_cb5, iron.RenderPath.clipmapLevel); - - #if rp_shadowmap - if (l.data.raw.type == "sun") { - #if lnx_shadowmap_atlas - #if lnx_shadowmap_atlas_single_map - kha.compute.Compute.setSampledTexture(voxel_tb5, rts.get("shadowMapAtlas").image); - #else - kha.compute.Compute.setSampledTexture(voxel_tb5, rts.get("shadowMapAtlasSun").image); - #end - #else - kha.compute.Compute.setSampledTexture(voxel_tb5, rts.get("shadowMap").image); - #end - kha.compute.Compute.setInt(voxel_ch5, 1); // lightShadow - } - else if (l.data.raw.type == "spot" || l.data.raw.type == "area") { - #if lnx_shadowmap_atlas - #if lnx_shadowmap_atlas_single_map - kha.compute.Compute.setSampledTexture(voxel_tc5, rts.get("shadowMapAtlas").image); - #else - kha.compute.Compute.setSampledTexture(voxel_tc5, rts.get("shadowMapAtlasSpot").image); - #end - #else - kha.compute.Compute.setSampledTexture(voxel_tc5, rts.get("shadowMapSpot[" + spotIndex + "]").image); - spotIndex++; - #end - kha.compute.Compute.setInt(voxel_ch5, 2); - } - else { - #if lnx_shadowmap_atlas - #if lnx_shadowmap_atlas_single_map - kha.compute.Compute.setSampledTexture(voxel_td5, rts.get("shadowMapAtlas").image); - #else - kha.compute.Compute.setSampledTexture(voxel_td5, rts.get("shadowMapAtlasPoint").image); - kha.compute.Compute.setInt(voxel_cl5, i); - kha.compute.Compute.setFloats(voxel_cm5, iron.object.LightObject.pointLightsData); - #end - #else - kha.compute.Compute.setSampledCubeMap(voxel_td5, rts.get("shadowMapPoint[" + pointIndex + "]").cubeMap); - pointIndex++; - #end - kha.compute.Compute.setInt(voxel_ch5, 3); - } - - // lightProj - var near = l.data.raw.near_plane; - var far = l.data.raw.far_plane; - var a:kha.FastFloat = far + near; - var b:kha.FastFloat = far - near; - var f2:kha.FastFloat = 2.0; - var c:kha.FastFloat = f2 * far * near; - var vx:kha.FastFloat = a / b; - var vy:kha.FastFloat = c / b; - kha.compute.Compute.setFloat2(voxel_ci5, vx, vy); - // LVP - m.setFrom(l.VP); - m.multmat(iron.object.Uniforms.biasMat); - #if lnx_shadowmap_atlas - if (l.data.raw.type == "sun") - { - // tile matrix - m.setIdentity(); - // scale [0-1] coords to [0-tilescale] - m2._00 = l.tileScale[0]; - m2._11 = l.tileScale[0]; - // offset coordinate start from [0, 0] to [tile-start-x, tile-start-y] - m2._30 = l.tileOffsetX[0]; - m2._31 = l.tileOffsetY[0]; - m.multmat(m2); - #if (!kha_opengl) - m2.setIdentity(); - m2._11 = -1.0; - m2._31 = 1.0; - m.multmat(m2); - #end - } - #end - kha.compute.Compute.setMatrix(voxel_cj5, m.self); - // shadowsBias - kha.compute.Compute.setFloat(voxel_ck5, l.data.raw.shadows_bias); - #end // rp_shadowmap - - // lightPos - kha.compute.Compute.setFloat3(voxel_cc5, l.transform.worldx(), l.transform.worldy(), l.transform.worldz()); - // lightCol - var f = l.data.raw.strength; - kha.compute.Compute.setFloat3(voxel_cd5, l.data.raw.color[0] * f, l.data.raw.color[1] * f, l.data.raw.color[2] * f); - // lightType - kha.compute.Compute.setInt(voxel_ce5, iron.data.LightData.typeToInt(l.data.raw.type)); - // lightDir - var v = l.look(); - kha.compute.Compute.setFloat3(voxel_cf5, v.x, v.y, v.z); - // spotData - if (l.data.raw.type == "spot") { - var vx = l.data.raw.spot_size; - var vy = vx - l.data.raw.spot_blend; - kha.compute.Compute.setFloat2(voxel_cg5, vx, vy); - } - - kha.compute.Compute.compute(Std.int(res / 8), Std.int(res / 8), Std.int(res / 8)); - } - } #end // GI #end // Voxels } From 436b7fac02ad24424922e49235ad437a36ca81a0 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 21 May 2025 16:21:05 +0000 Subject: [PATCH 061/136] Update leenkx/Sources/leenkx/renderpath/RenderPathDeferred.hx --- .../leenkx/renderpath/RenderPathDeferred.hx | 331 +++++++++++------- 1 file changed, 201 insertions(+), 130 deletions(-) diff --git a/leenkx/Sources/leenkx/renderpath/RenderPathDeferred.hx b/leenkx/Sources/leenkx/renderpath/RenderPathDeferred.hx index 75a519e..caf8b68 100644 --- a/leenkx/Sources/leenkx/renderpath/RenderPathDeferred.hx +++ b/leenkx/Sources/leenkx/renderpath/RenderPathDeferred.hx @@ -15,6 +15,11 @@ class RenderPathDeferred { static var bloomUpsampler: Upsampler; #end + #if (rp_ssgi == "SSGI") + static var ssgitex = "singleb"; + static var ssgitexb = "singleb"; + #end + public static inline function setTargetMeshes() { //Always keep the order of render targets the same as defined in compiled.inc path.setTarget("gbuffer0", [ @@ -57,12 +62,11 @@ class RenderPathDeferred { Inc.initGI("voxels"); Inc.initGI("voxelsOut"); Inc.initGI("voxelsOutB"); - #if (lnx_voxelgi_shadows || rp_voxels == "Voxel GI") + #if (rp_voxels == "Voxel GI" || lnx_voxelgi_shadows) Inc.initGI("voxelsSDF"); Inc.initGI("voxelsSDFtmp"); #end #if (rp_voxels == "Voxel GI") - Inc.initGI("voxelsLight"); Inc.initGI("voxels_diffuse"); Inc.initGI("voxels_specular"); #else @@ -195,16 +199,26 @@ class RenderPathDeferred { path.loadShader("shader_datas/blur_edge_pass/blur_edge_pass_x"); path.loadShader("shader_datas/blur_edge_pass/blur_edge_pass_y"); } + #elseif (rp_ssgi == "SSGI") + { + path.loadShader("shader_datas/ssgi_pass/ssgi_pass"); + path.loadShader("shader_datas/blur_edge_pass/blur_edge_pass_x"); + path.loadShader("shader_datas/blur_edge_pass/blur_edge_pass_y"); + } #end - #if ((rp_ssgi != "Off") || rp_volumetriclight) + #if (rp_ssgi != "Off") { var t = new RenderTargetRaw(); t.name = "singlea"; t.width = 0; t.height = 0; t.displayp = Inc.getDisplayp(); + #if (rp_ssgi == "SSGI") + t.format = "RGBA32"; + #else t.format = "R8"; + #end t.scale = Inc.getSuperSampling(); #if rp_ssgi_half t.scale *= 0.5; @@ -216,6 +230,38 @@ class RenderPathDeferred { t.width = 0; t.height = 0; t.displayp = Inc.getDisplayp(); + #if (rp_ssgi == "SSGI") + t.format = "RGBA32"; + #else + t.format = "R8"; + #end + t.scale = Inc.getSuperSampling(); + #if rp_ssgi_half + t.scale *= 0.5; + #end + path.createRenderTarget(t); + } + #end + + #if rp_volumetriclight + { + var t = new RenderTargetRaw(); + t.name = "volumetrica"; + t.width = 0; + t.height = 0; + t.displayp = Inc.getDisplayp(); + t.format = "R8"; + t.scale = Inc.getSuperSampling(); + #if rp_ssgi_half // Do we keep this ? + t.scale *= 0.5; + #end + path.createRenderTarget(t); + + var t = new RenderTargetRaw(); + t.name = "volumetricb"; + t.width = 0; + t.height = 0; + t.displayp = Inc.getDisplayp(); t.format = "R8"; t.scale = Inc.getSuperSampling(); #if rp_ssgi_half @@ -358,6 +404,7 @@ class RenderPathDeferred { path.loadShader("shader_datas/ssrefr_pass/ssrefr_pass"); path.loadShader("shader_datas/copy_pass/copy_pass"); + path.createDepthBuffer("refraction", "DEPTH24"); // holds background depth var t = new RenderTargetRaw(); t.name = "gbufferD1"; @@ -473,13 +520,6 @@ class RenderPathDeferred { } #end - #if rp_ssrefr - { - path.setTarget("gbuffer_refraction"); - path.clearTarget(0xffffff00); - } - #end - RenderPathCreator.setTargetMeshes(); #if rp_dynres @@ -524,30 +564,16 @@ class RenderPathDeferred { path.drawShader("shader_datas/downsample_depth/downsample_depth"); #end - #if ((rp_ssgi == "RTGI") || (rp_ssgi == "RTAO")) - { - if (leenkx.data.Config.raw.rp_ssgi != false) { - path.setTarget("singlea"); - #if rp_ssgi_half - path.bindTarget("half", "gbufferD"); - #else - path.bindTarget("_main", "gbufferD"); - #end - path.bindTarget("gbuffer0", "gbuffer0"); - path.drawShader("shader_datas/ssgi_pass/ssgi_pass"); + #if (rp_shadowmap) + // atlasing is exclusive for now + #if lnx_shadowmap_atlas + Inc.drawShadowMapAtlas(); + #else + Inc.drawShadowMap(); + #end + #end - path.setTarget("singleb"); - path.bindTarget("singlea", "tex"); - path.bindTarget("gbuffer0", "gbuffer0"); - path.drawShader("shader_datas/blur_edge_pass/blur_edge_pass_x"); - - path.setTarget("singlea"); - path.bindTarget("singleb", "tex"); - path.bindTarget("gbuffer0", "gbuffer0"); - path.drawShader("shader_datas/blur_edge_pass/blur_edge_pass_y"); - } - } - #elseif (rp_ssgi == "SSAO") + #if (rp_ssgi == "SSAO") { if (leenkx.data.Config.raw.rp_ssgi != false) { path.setTarget("singlea"); @@ -566,15 +592,43 @@ class RenderPathDeferred { path.drawShader("shader_datas/blur_edge_pass/blur_edge_pass_y"); } } - #end + #elseif (rp_ssgi == "SSGI") + { + if (leenkx.data.Config.raw.rp_ssgi != false) { + path.setTarget("singlea"); + path.bindTarget("_main", "gbufferD"); + path.bindTarget("gbuffer0", "gbuffer0"); + path.bindTarget("gbuffer1", "gbuffer1"); + #if rp_gbuffer_emission + { + path.bindTarget("gbuffer_emission", "gbufferEmission"); + } + #end + #if rp_gbuffer2 + path.bindTarget("gbuffer2", "sveloc"); + #end + #if rp_shadowmap + { + #if lnx_shadowmap_atlas + Inc.bindShadowMapAtlas(); + #else + Inc.bindShadowMap(); + #end + } + #end - #if (rp_shadowmap) - // atlasing is exclusive for now - #if lnx_shadowmap_atlas - Inc.drawShadowMapAtlas(); - #else - Inc.drawShadowMap(); - #end + path.drawShader("shader_datas/ssgi_pass/ssgi_pass"); + path.setTarget("singleb"); + path.bindTarget("singlea", "tex"); + path.bindTarget("gbuffer0", "gbuffer0"); + path.drawShader("shader_datas/blur_edge_pass/blur_edge_pass_x"); + + path.setTarget("singlea"); + path.bindTarget("singleb", "tex"); + path.bindTarget("gbuffer0", "gbuffer0"); + path.drawShader("shader_datas/blur_edge_pass/blur_edge_pass_y"); + } + } #end // Voxels @@ -587,9 +641,6 @@ class RenderPathDeferred { if (iron.RenderPath.pre_clear == true) { - #if (rp_voxels == "Voxel GI") - path.clearImage("voxelsLight", 0x00000000); - #end path.clearImage("voxels", 0x00000000); path.clearImage("voxelsOut", 0x00000000); path.clearImage("voxelsOutB", 0x00000000); @@ -601,22 +652,26 @@ class RenderPathDeferred { } else { - #if (rp_voxels == "Voxel GI") - path.clearImage("voxelsLight", 0x00000000); - #end path.clearImage("voxels", 0x00000000); Inc.computeVoxelsOffsetPrev(); } path.setTarget(""); + path.bindTarget("voxels", "voxels"); + #if rp_shadowmap + { + #if lnx_shadowmap_atlas + Inc.bindShadowMapAtlas(); + #else + Inc.bindShadowMap(); + #end + } + #end + var res = iron.RenderPath.getVoxelRes(); path.setViewport(res, res); - path.bindTarget("voxels", "voxels"); path.drawMeshes("voxel"); - #if (rp_voxels == "Voxel GI") - Inc.computeVoxelsLight(); - #end Inc.computeVoxelsTemporal(); @@ -632,6 +687,10 @@ class RenderPathDeferred { #else path.clearImage("voxels_ao", 0x00000000); #end + #if lnx_voxelgi_shadows + path.bindTarget("voxelsOut", "voxels"); + path.bindTarget("voxelsSDF", "voxelsSDF"); + #end } } #end @@ -767,15 +826,9 @@ class RenderPathDeferred { } #end - #if (rp_translucency && !rp_ssrefr) - { - Inc.drawTranslucency("tex"); - } - #end - #if rp_volumetriclight { - path.setTarget("singlea"); + path.setTarget("volumetrica"); path.bindTarget("_main", "gbufferD"); #if lnx_shadowmap_atlas Inc.bindShadowMapAtlas(); @@ -784,85 +837,16 @@ class RenderPathDeferred { #end path.drawShader("shader_datas/volumetric_light/volumetric_light"); - path.setTarget("singleb"); - path.bindTarget("singlea", "tex"); + path.setTarget("volumetricb"); + path.bindTarget("volumetrica", "tex"); path.drawShader("shader_datas/blur_bilat_pass/blur_bilat_pass_x"); path.setTarget("tex"); - path.bindTarget("singleb", "tex"); + path.bindTarget("volumetricb", "tex"); path.drawShader("shader_datas/blur_bilat_blend_pass/blur_bilat_blend_pass_y"); } #end - #if rp_bloom - { - inline Inc.drawBloom("tex", bloomDownsampler, bloomUpsampler); - } - #end - - #if rp_sss - { - #if (!kha_opengl) - path.setDepthFrom("tex", "gbuffer1"); // Unbind depth so we can read it - #end - - path.setTarget("buf"); - path.bindTarget("tex", "tex"); - path.bindTarget("_main", "gbufferD"); - path.bindTarget("gbuffer0", "gbuffer0"); - path.drawShader("shader_datas/sss_pass/sss_pass_x"); - - path.setTarget("tex"); - path.bindTarget("buf", "tex"); - path.bindTarget("_main", "gbufferD"); - path.bindTarget("gbuffer0", "gbuffer0"); - path.drawShader("shader_datas/sss_pass/sss_pass_y"); - - #if (!kha_opengl) - path.setDepthFrom("tex", "gbuffer0"); - #end - } - #end - - #if rp_ssrefr - { - if (leenkx.data.Config.raw.rp_ssrefr != false) - { - //save depth - path.setTarget("gbufferD1"); - path.bindTarget("_main", "tex"); - path.drawShader("shader_datas/copy_pass/copy_pass"); - - //save background color - path.setTarget("refr"); - path.bindTarget("tex", "tex"); - path.drawShader("shader_datas/copy_pass/copy_pass"); - - path.setTarget("gbuffer0", ["tex", "gbuffer_refraction"]); - - #if (rp_voxels != "Off") - { - path.bindTarget("voxelsOut", "voxels"); - path.bindTarget("voxelsSDF", "voxelsSDF"); - path.bindTarget("gbuffer2", "gbuffer2"); - } - #end - - path.drawMeshes("refraction"); - - path.setTarget("tex"); - path.bindTarget("tex", "tex"); - path.bindTarget("refr", "tex1"); - path.bindTarget("_main", "gbufferD"); - path.bindTarget("gbufferD1", "gbufferD1"); - path.bindTarget("gbuffer0", "gbuffer0"); - path.bindTarget("gbuffer_refraction", "gbuffer_refraction"); - - path.drawShader("shader_datas/ssrefr_pass/ssrefr_pass"); - } - } - #end - #if rp_ssr { if (leenkx.data.Config.raw.rp_ssr != false) { @@ -907,6 +891,87 @@ class RenderPathDeferred { } #end + #if rp_sss + { + #if (!kha_opengl) + path.setDepthFrom("tex", "gbuffer1"); // Unbind depth so we can read it + #end + + path.setTarget("buf"); + path.bindTarget("tex", "tex"); + path.bindTarget("_main", "gbufferD"); + path.bindTarget("gbuffer0", "gbuffer0"); + path.drawShader("shader_datas/sss_pass/sss_pass_x"); + + path.setTarget("tex"); + path.bindTarget("buf", "tex"); + path.bindTarget("_main", "gbufferD"); + path.bindTarget("gbuffer0", "gbuffer0"); + path.drawShader("shader_datas/sss_pass/sss_pass_y"); + + #if (!kha_opengl) + path.setDepthFrom("tex", "gbuffer0"); + #end + } + #end + + #if (rp_translucency && !rp_ssrefr) + { + Inc.drawTranslucency("tex"); + } + #end + + #if rp_ssrefr + { + if (leenkx.data.Config.raw.rp_ssrefr != false) + { + //save depth + path.setTarget("gbufferD1"); + path.bindTarget("_main", "tex"); + path.drawShader("shader_datas/copy_pass/copy_pass"); + + //save background color + path.setTarget("refr"); + path.bindTarget("tex", "tex"); + path.drawShader("shader_datas/copy_pass/copy_pass"); + + path.setTarget("gbuffer0", ["tex", "gbuffer_refraction"]); + + #if rp_shadowmap + { + #if lnx_shadowmap_atlas + Inc.bindShadowMapAtlas(); + #else + Inc.bindShadowMap(); + #end + } + #end + + #if (rp_voxels != "Off") + { + path.bindTarget("voxelsOut", "voxels"); + path.bindTarget("voxelsSDF", "voxelsSDF"); + #if rp_gbuffer2 + path.bindTarget("gbuffer2", "gbuffer2"); + #end + } + #end + + path.drawMeshes("refraction"); + + path.setTarget("tex"); + path.bindTarget("tex", "tex"); + path.bindTarget("refr", "tex1"); + path.bindTarget("_main", "gbufferD"); + path.bindTarget("gbufferD1", "gbufferD1"); + path.bindTarget("gbuffer0", "gbuffer0"); + path.bindTarget("gbuffer_refraction", "gbuffer_refraction"); + + path.drawShader("shader_datas/ssrefr_pass/ssrefr_pass"); + } + } + #end + #if ((rp_motionblur == "Camera") || (rp_motionblur == "Object")) { if (leenkx.data.Config.raw.rp_motionblur != false) { @@ -971,6 +1036,12 @@ class RenderPathDeferred { } #end + #if rp_bloom + { + inline Inc.drawBloom("tex", bloomDownsampler, bloomUpsampler); + } + #end + #if (rp_supersampling == 4) var framebuffer = "buf"; #else From 8b5a77c001804db96075749a90c19c75079ed019 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 21 May 2025 16:23:20 +0000 Subject: [PATCH 062/136] Update leenkx/Sources/leenkx/renderpath/RenderPathForward.hx --- .../leenkx/renderpath/RenderPathForward.hx | 106 ++++++++++-------- 1 file changed, 58 insertions(+), 48 deletions(-) diff --git a/leenkx/Sources/leenkx/renderpath/RenderPathForward.hx b/leenkx/Sources/leenkx/renderpath/RenderPathForward.hx index 59b6183..70152f4 100644 --- a/leenkx/Sources/leenkx/renderpath/RenderPathForward.hx +++ b/leenkx/Sources/leenkx/renderpath/RenderPathForward.hx @@ -142,7 +142,7 @@ class RenderPathForward { t.width = 0; t.height = 0; t.displayp = Inc.getDisplayp(); - t.format = "R32"; + t.format = "DEPTH24"; t.scale = Inc.getSuperSampling(); path.createRenderTarget(t); @@ -204,13 +204,6 @@ class RenderPathForward { Inc.initGI("voxelsSDF"); Inc.initGI("voxelsSDFtmp"); #end - #if (rp_voxels == "Voxel GI") - Inc.initGI("voxelsLight"); - Inc.initGI("voxels_diffuse"); - Inc.initGI("voxels_specular"); - #else - Inc.initGI("voxels_ao"); - #end iron.RenderPath.clipmaps = new Array(); for (i in 0...Main.voxelgiClipmapCount) { var clipmap = new iron.object.Clipmap(); @@ -257,18 +250,25 @@ class RenderPathForward { #end #end - #if rp_volumetriclight + #if (rp_volumetriclight || rp_ssgi != "Off") { + #if (rp_volumetriclight) path.loadShader("shader_datas/volumetric_light/volumetric_light"); path.loadShader("shader_datas/blur_bilat_pass/blur_bilat_pass_x"); path.loadShader("shader_datas/blur_bilat_blend_pass/blur_bilat_blend_pass_y"); + #end + var t = new RenderTargetRaw(); t.name = "singlea"; t.width = 0; t.height = 0; t.displayp = Inc.getDisplayp(); + #if (rp_ssgi == "SSGI") + t.format = "RGBA32"; + #else t.format = "R8"; + #end t.scale = Inc.getSuperSampling(); path.createRenderTarget(t); @@ -277,7 +277,11 @@ class RenderPathForward { t.width = 0; t.height = 0; t.displayp = Inc.getDisplayp(); + #if (rp_ssgi == "SSGI") + t.format = "RGBA32"; + #else t.format = "R8"; + #end t.scale = Inc.getSuperSampling(); path.createRenderTarget(t); } @@ -315,7 +319,6 @@ class RenderPathForward { path.createRenderTarget(t); } #end - #if rp_ssr { @@ -374,9 +377,6 @@ class RenderPathForward { if (iron.RenderPath.pre_clear == true) { - #if (rp_voxels == "Voxel GI") - path.clearImage("voxelsLight", 0x00000000); - #end path.clearImage("voxels", 0x00000000); path.clearImage("voxelsOut", 0x00000000); path.clearImage("voxelsOutB", 0x00000000); @@ -388,9 +388,6 @@ class RenderPathForward { } else { - #if (rp_voxels == "Voxel GI") - path.clearImage("voxelsLight", 0x00000000); - #end path.clearImage("voxels", 0x00000000); Inc.computeVoxelsOffsetPrev(); } @@ -402,25 +399,11 @@ class RenderPathForward { path.bindTarget("voxels", "voxels"); path.drawMeshes("voxel"); - #if (rp_voxels == "Voxel GI") - Inc.computeVoxelsLight(); - #end Inc.computeVoxelsTemporal(); #if (lnx_voxelgi_shadows || (rp_voxels == "Voxel GI")) Inc.computeVoxelsSDF(); #end - - if (iron.RenderPath.res_pre_clear == true) - { - iron.RenderPath.res_pre_clear = false; - #if (rp_voxels == "Voxel GI") - path.clearImage("voxels_diffuse", 0x00000000); - path.clearImage("voxels_specular", 0x00000000); - #else - path.clearImage("voxels_ao", 0x00000000); - #end - } } #end @@ -449,13 +432,6 @@ class RenderPathForward { } #end - #if rp_ssrefr - { - path.setTarget("gbuffer_refraction"); - path.clearTarget(0xffffff00); - } - #end - RenderPathCreator.setTargetMeshes(); #if rp_shadowmap @@ -472,17 +448,8 @@ class RenderPathForward { #if (rp_voxels != "Off") if (leenkx.data.Config.raw.rp_gi != false) { - #if (rp_voxels == "Voxel AO") - Inc.resolveAO(); - path.bindTarget("voxels_ao", "voxels_ao"); - #else - Inc.resolveDiffuse(); - Inc.resolveSpecular(); - path.bindTarget("voxels_diffuse", "voxels_diffuse"); - path.bindTarget("voxels_specular", "voxels_specular"); - #end - #if lnx_voxelgi_shadows path.bindTarget("voxelsOut", "voxels"); + #if (lnx_voxelgi_shadows || rp_voxels == "Voxel GI") path.bindTarget("voxelsSDF", "voxelsSDF"); #end } @@ -532,7 +499,6 @@ class RenderPathForward { } #end - #if (rp_voxels != "Off") path.bindTarget("voxelsOut", "voxels"); path.bindTarget("voxelsSDF", "voxelsSDF"); @@ -588,6 +554,50 @@ class RenderPathForward { } #end + #if rp_ssrefr + { + if (leenkx.data.Config.raw.rp_ssrefr != false) + { + path.setTarget("gbufferD1"); + path.bindTarget("_main", "tex"); + path.drawShader("shader_datas/copy_pass/copy_pass"); + + path.setTarget("refr"); + path.bindTarget("lbuffer0", "tex"); + path.drawShader("shader_datas/copy_pass/copy_pass"); + + path.setTarget("lbuffer0", ["lbuffer1", "gbuffer_refraction"]); + + #if rp_shadowmap + { + #if lnx_shadowmap_atlas + Inc.bindShadowMapAtlas(); + #else + Inc.bindShadowMap(); + #end + } + #end + + #if (rp_voxels != "Off") + path.bindTarget("voxelsOut", "voxels"); + path.bindTarget("voxelsSDF", "voxelsSDF"); + #end + + path.drawMeshes("refraction"); + + path.setTarget("lbuffer0"); + path.bindTarget("lbuffer0", "tex"); + path.bindTarget("refr", "tex1"); + path.bindTarget("_main", "gbufferD"); + path.bindTarget("gbufferD1", "gbufferD1"); + path.bindTarget("lbuffer1", "gbuffer0"); + path.bindTarget("gbuffer_refraction", "gbuffer_refraction"); + + path.drawShader("shader_datas/ssrefr_pass/ssrefr_pass"); + } + } + #end + #if rp_bloom { inline Inc.drawBloom("lbuffer0", bloomDownsampler, bloomUpsampler); From 09eee93ac9689e516fbc12b120dc315866e52e82 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 21 May 2025 16:25:58 +0000 Subject: [PATCH 063/136] Update leenkx/Sources/iron/object/Uniforms.hx --- leenkx/Sources/iron/object/Uniforms.hx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/leenkx/Sources/iron/object/Uniforms.hx b/leenkx/Sources/iron/object/Uniforms.hx index 022a777..da7c918 100644 --- a/leenkx/Sources/iron/object/Uniforms.hx +++ b/leenkx/Sources/iron/object/Uniforms.hx @@ -181,11 +181,15 @@ class Uniforms { // Multiple voxel volumes, always set params g.setImageTexture(context.textureUnits[j], rt.image); // image2D/3D if (rt.raw.name.startsWith("voxels_")) { - g.setTextureParameters(context.textureUnits[j], TextureAddressing.Clamp, TextureAddressing.Clamp, TextureFilter.LinearFilter, TextureFilter.LinearFilter, MipMapFilter.NoMipFilter); + g.setTextureParameters(context.textureUnits[j], TextureAddressing.Clamp, TextureAddressing.Clamp, TextureFilter.LinearFilter, TextureFilter.LinearFilter, MipMapFilter.LinearMipFilter); + } + else if (rt.raw.name.startsWith("voxelsSDF")) + { + g.setTexture3DParameters(context.textureUnits[j], TextureAddressing.Clamp, TextureAddressing.Clamp, TextureAddressing.Clamp, TextureFilter.PointFilter, TextureFilter.PointFilter, MipMapFilter.NoMipFilter); } else if (rt.raw.name.startsWith("voxels")) { - g.setTexture3DParameters(context.textureUnits[j], TextureAddressing.Clamp, TextureAddressing.Clamp, TextureAddressing.Clamp, TextureFilter.LinearFilter, TextureFilter.LinearFilter, MipMapFilter.NoMipFilter); + g.setTexture3DParameters(context.textureUnits[j], TextureAddressing.Clamp, TextureAddressing.Clamp, TextureAddressing.Clamp, TextureFilter.LinearFilter, TextureFilter.LinearFilter, MipMapFilter.PointMipFilter); } else { From 538c364f33139bb87aefe6a59d7688a86600866c Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 21 May 2025 22:26:58 +0000 Subject: [PATCH 064/136] Update leenkx/blender/lnx/make_renderpath.py --- leenkx/blender/lnx/make_renderpath.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/leenkx/blender/lnx/make_renderpath.py b/leenkx/blender/lnx/make_renderpath.py index fc1af0e..c456c5a 100644 --- a/leenkx/blender/lnx/make_renderpath.py +++ b/leenkx/blender/lnx/make_renderpath.py @@ -58,6 +58,9 @@ def add_world_defs(): if rpdat.rp_shadowmap_cascades != '1': wrd.world_defs += '_CSM' assets.add_khafile_def('lnx_csm') + if rpdat.rp_shadowmap_transparent: + wrd.world_defs += '_ShadowMapTransparent' + assets.add_khafile_def('rp_shadowmap_transparent') if rpdat.rp_shadowmap_atlas: assets.add_khafile_def('lnx_shadowmap_atlas') wrd.world_defs += '_ShadowMapAtlas' @@ -118,17 +121,15 @@ def add_world_defs(): if rpdat.lnx_voxelgi_shadows and (point_lights > 0 or '_Sun' in wrd.world_defs): wrd.world_defs += '_VoxelShadow' assets.add_khafile_def('lnx_voxelgi_shadows') - #assets.add_shader_external(lnx.utils.get_sdk_path() + '/leenkx/Shaders/voxel_resolve_shadows/voxel_resolve_shadows.comp.glsl') if voxelgi: - assets.add_shader_external(lnx.utils.get_sdk_path() + '/leenkx/Shaders/voxel_light/voxel_light.comp.glsl') assets.add_shader_external(lnx.utils.get_sdk_path() + '/leenkx/Shaders/voxel_resolve_diffuse/voxel_resolve_diffuse.comp.glsl') assets.add_shader_external(lnx.utils.get_sdk_path() + '/leenkx/Shaders/voxel_resolve_specular/voxel_resolve_specular.comp.glsl') + assets.add_shader_external(lnx.utils.get_sdk_path() + '/leenkx/Shaders/voxel_light/voxel_light.comp.glsl') wrd.world_defs += '_VoxelGI' if rpdat.lnx_voxelgi_refract: wrd.world_defs += '_VoxelRefract' assets.add_khafile_def('lnx_voxelgi_refract') - #assets.add_shader_external(lnx.utils.get_sdk_path() + '/leenkx/Shaders/voxel_resolve_refraction/voxel_resolve_refraction.comp.glsl') elif voxelao: assets.add_shader_external(lnx.utils.get_sdk_path() + '/leenkx/Shaders/voxel_resolve_ao/voxel_resolve_ao.comp.glsl') @@ -310,6 +311,10 @@ def build(): wrd.world_defs += '_SSAO' assets.add_shader_pass('ssao_pass') assets.add_shader_pass('blur_edge_pass') + elif rpdat.rp_ssgi == 'SSGI': + wrd.world_defs += '_SSGI' + assets.add_shader_pass('ssgi_pass') + assets.add_shader_pass('blur_edge_pass') else: assets.add_shader_pass('ssgi_pass') assets.add_shader_pass('blur_edge_pass') @@ -456,7 +461,8 @@ def build(): if ignoreIrr: wrd.world_defs += '_IgnoreIrr' - gbuffer2 = '_Veloc' in wrd.world_defs or '_IgnoreIrr' in wrd.world_defs or '_VoxelGI' in wrd.world_defs or '_VoxelShadow' in wrd.world_defs + gbuffer2 = '_Veloc' in wrd.world_defs or '_IgnoreIrr' in wrd.world_defs or '_VoxelGI' in wrd.world_defs or '_VoxelShadow' in wrd.world_defs or '_SSGI' in wrd.world_defs + if gbuffer2: assets.add_khafile_def('rp_gbuffer2') wrd.world_defs += '_gbuffer2' From 8b084156ff076691bf88fec57be6171b8cf516ff Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 21 May 2025 22:29:40 +0000 Subject: [PATCH 065/136] Update leenkx/blender/lnx/make_world.py --- leenkx/blender/lnx/make_world.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/leenkx/blender/lnx/make_world.py b/leenkx/blender/lnx/make_world.py index 001624b..ebe197a 100644 --- a/leenkx/blender/lnx/make_world.py +++ b/leenkx/blender/lnx/make_world.py @@ -190,6 +190,7 @@ def build_node_tree(world: bpy.types.World, frag: Shader, vert: Shader, con: Sha world.lnx_envtex_color = [col[0], col[1], col[2], 1.0] world.lnx_envtex_strength = 1.0 world.world_defs += '_EnvCol' + assets.add_khafile_def("lnx_envcol") # Clouds enabled if rpdat.lnx_clouds and world.lnx_use_clouds: @@ -271,6 +272,7 @@ def parse_surface(world: bpy.types.World, node_surface: bpy.types.Node, frag: Sh # Append irradiance define if rpdat.lnx_irradiance and not solid_mat: wrd.world_defs += '_Irr' + assets.add_khafile_def("lnx_irradiance") # Extract environment strength # Todo: follow/parse strength input @@ -284,6 +286,7 @@ def parse_surface(world: bpy.types.World, node_surface: bpy.types.Node, frag: Sh solid_mat = rpdat.lnx_material_model == 'Solid' if rpdat.lnx_irradiance and not solid_mat: world.world_defs += '_Irr' + assets.add_khafile_def("lnx_irradiance") world.lnx_envtex_color = node_surface.inputs[0].default_value world.lnx_envtex_strength = 1.0 From b7bbe403482c1eebe250f64bb83c9ea697a30149 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 21 May 2025 22:33:01 +0000 Subject: [PATCH 066/136] Update leenkx/blender/lnx/material/make_cluster.py --- leenkx/blender/lnx/material/make_cluster.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/leenkx/blender/lnx/material/make_cluster.py b/leenkx/blender/lnx/material/make_cluster.py index 23e79f7..b3fdd25 100644 --- a/leenkx/blender/lnx/material/make_cluster.py +++ b/leenkx/blender/lnx/material/make_cluster.py @@ -98,14 +98,13 @@ def write(vert: shader.Shader, frag: shader.Shader): frag.write('\t, vec2(lightsArray[li * 3].w, lightsArray[li * 3 + 1].w)') # scale frag.write('\t, lightsArraySpot[li * 2 + 1].xyz') # right if '_VoxelShadow' in wrd.world_defs: - frag.write(', voxels, voxelsSDF, clipmaps') + frag.write(', voxels, voxelsSDF, clipmaps, velocity') if '_MicroShadowing' in wrd.world_defs and not is_mobile: frag.write('\t, occlusion') if '_SSRS' in wrd.world_defs: - frag.add_uniform('sampler2D gbufferD', top=True) frag.add_uniform('mat4 invVP', '_inverseViewProjectionMatrix') frag.add_uniform('vec3 eye', '_cameraPosition') - frag.write(', gbufferD, invVP, eye') + frag.write(', wposition.z, invVP, eye') frag.write(');') frag.write('}') # for numLights From dab9a3842478705a1ca4233a6128ab3f34c3a91c Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 21 May 2025 22:37:15 +0000 Subject: [PATCH 067/136] Update leenkx/blender/lnx/material/make_mesh.py --- leenkx/blender/lnx/material/make_mesh.py | 85 +++++++++++++----------- 1 file changed, 47 insertions(+), 38 deletions(-) diff --git a/leenkx/blender/lnx/material/make_mesh.py b/leenkx/blender/lnx/material/make_mesh.py index 3df06bf..db6d899 100644 --- a/leenkx/blender/lnx/material/make_mesh.py +++ b/leenkx/blender/lnx/material/make_mesh.py @@ -557,7 +557,7 @@ def make_forward(con_mesh): frag.write('fragColor[0] = vec4(direct + indirect, packFloat2(occlusion, specular));') frag.write('fragColor[1] = vec4(n.xy, roughness, metallic);') if rpdat.rp_ss_refraction or rpdat.lnx_voxelgi_refract: - frag.write(f'fragColor[2] = vec4(1.0, 1.0, 0.0, 1.0);') + frag.write(f'fragColor[2] = vec4(1.0, 1.0, 0.0, 0.0);') else: frag.add_out('vec4 fragColor[1]') @@ -609,11 +609,40 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): frag.write_attrib('float dotNV = max(dot(n, vVec), 0.0);') sh = tese if tese is not None else vert - sh.add_uniform('mat4 W', '_worldMatrix') - sh.write_attrib('vec3 wposition = vec4(W * spos).xyz;') sh.add_out('vec3 eyeDir') sh.add_uniform('vec3 eye', '_cameraPosition') sh.write('eyeDir = eye - wposition;') + if '_VoxelGI' in wrd.world_defs or '_VoxelShadow' in wrd.world_defs: + if '_gbuffer2' in wrd.world_defs: + if '_Veloc' in wrd.world_defs: + if tese is None: + vert.add_uniform('mat4 prevWVP', link='_prevWorldViewProjectionMatrix') + vert.add_out('vec4 wvpposition') + vert.add_out('vec4 prevwvpposition') + vert.write('wvpposition = gl_Position;') + if is_displacement: + vert.add_uniform('mat4 invW', link='_inverseWorldMatrix') + vert.write('prevwvpposition = prevWVP * (invW * vec4(wposition, 1.0));') + else: + vert.write('prevwvpposition = prevWVP * spos;') + else: + tese.add_out('vec4 wvpposition') + tese.add_out('vec4 prevwvpposition') + tese.write('wvpposition = gl_Position;') + if is_displacement: + tese.add_uniform('mat4 invW', link='_inverseWorldMatrix') + tese.add_uniform('mat4 prevWVP', '_prevWorldViewProjectionMatrix') + tese.write('prevwvpposition = prevWVP * (invW * vec4(wposition, 1.0));') + else: + vert.add_uniform('mat4 prevW', link='_prevWorldMatrix') + vert.add_out('vec3 prevwposition') + vert.write('prevwposition = vec4(prevW * spos).xyz;') + tese.add_uniform('mat4 prevVP', '_prevViewProjectionMatrix') + make_tess.interpolate(tese, 'prevwposition', 3) + tese.write('prevwvpposition = prevVP * vec4(prevwposition, 1.0);') + frag.write('vec2 posa = (wvpposition.xy / wvpposition.w) * 0.5 + 0.5;') + frag.write('vec2 posb = (prevwvpposition.xy / prevwvpposition.w) * 0.5 + 0.5;') + frag.write('vec2 velocity = -vec2(posa - posb);') frag.add_include('std/light.glsl') is_shadows = '_ShadowMap' in wrd.world_defs @@ -632,6 +661,7 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): if '_Brdf' in wrd.world_defs: frag.add_uniform('sampler2D senvmapBrdf', link='$brdf.png') frag.write('vec2 envBRDF = texelFetch(senvmapBrdf, ivec2(vec2(dotNV, 1.0 - roughness) * 256.0), 0).xy;') + frag.write('vec3 F = f0 * envBRDF.x + envBRDF.y;') if '_Irr' in wrd.world_defs: frag.add_include('std/shirr.glsl') @@ -657,12 +687,12 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): frag.write('envl *= albedo;') if '_Brdf' in wrd.world_defs: - frag.write('envl.rgb *= 1.0 - (f0 * envBRDF.x + envBRDF.y);') + frag.write('envl.rgb *= 1.0 - F;') if '_Rad' in wrd.world_defs: - frag.write('envl += prefilteredColor * (f0 * envBRDF.x + envBRDF.y);') + frag.write('envl += prefilteredColor * F;') elif '_EnvCol' in wrd.world_defs: frag.add_uniform('vec3 backgroundCol', link='_backgroundCol') - frag.write('envl += backgroundCol * (f0 * envBRDF.x + envBRDF.y);') + frag.write('envl += backgroundCol * F;') frag.add_uniform('float envmapStrength', link='_envmapStrength') frag.write('envl *= envmapStrength * occlusion;') @@ -671,22 +701,10 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): frag.add_include('std/conetrace.glsl') frag.add_uniform('sampler3D voxels') frag.add_uniform('sampler3D voxelsSDF') - frag.add_uniform('vec3 eye', '_cameraPosition') frag.add_uniform('float clipmaps[10 * voxelgiClipmapCount]', '_clipmaps') - vert.add_out('vec4 wvpposition') - vert.write('wvpposition = gl_Position;') - frag.write('vec2 texCoord = (wvpposition.xy / wvpposition.w) * 0.5 + 0.5;') - - if '_VoxelGI' in wrd.world_defs or '_VoxelShadow' in wrd.world_defs or '_VoxelRefract' in wrd.world_defs: - frag.add_uniform('sampler2D gbuffer2', included=True) - frag.write('vec2 velocity = -textureLod(gbuffer2, gl_FragCoord.xy, 0.0).rg;') if '_VoxelAOvar' in wrd.world_defs: - if parse_opacity: - frag.write('envl *= 1.0 - traceAO(wposition, n, voxels, clipmaps);') - else: - frag.add_uniform("sampler2D voxels_ao"); - frag.write('envl *= textureLod(voxels_ao, texCoord, 0.0).rrr;') + frag.write('envl *= (1.0 - traceAO(wposition, n, voxels, clipmaps));') if '_VoxelGI' in wrd.world_defs: frag.write('vec3 indirect = vec3(0.0);') @@ -694,18 +712,11 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): frag.write('vec3 indirect = envl;') if '_VoxelGI' in wrd.world_defs: - if parse_opacity: - frag.write('vec4 indirect_diffuse = traceDiffuse(wposition, n, voxels, clipmaps);') - frag.write('indirect = (indirect_diffuse.rgb * albedo + envl.rgb * (1.0 - indirect_diffuse.a)) * voxelgiDiff;') - frag.write('if (roughness < 1.0 && specular > 0.0) {') - frag.write(' indirect += traceSpecular(wposition, n, voxels, voxelsSDF, vVec, roughness * roughness, clipmaps, gl_FragCoord.xy, velocity).rgb * specular * voxelgiRefl; }') - else: - frag.add_uniform("sampler2D voxels_diffuse") - frag.add_uniform("sampler2D voxels_specular") - frag.write("indirect = textureLod(voxels_diffuse, texCoord, 0.0).rgb * albedo * voxelgiDiff;") - frag.write("if (roughness < 1.0 && specular > 0.0)") - frag.write(" indirect += textureLod(voxels_specular, texCoord, 0.0).rgb * specular * voxelgiRefl;") - + frag.write('vec4 diffuse_indirect = traceDiffuse(wposition, n, voxels, clipmaps);') + frag.write('indirect = (diffuse_indirect.rgb * albedo * (1.0 - F) + envl * (1.0 - diffuse_indirect.a)) * voxelgiDiff;') + frag.write('if (roughness < 1.0 && specular > 0.0) {') + frag.write(' indirect += traceSpecular(wposition, n, voxels, voxelsSDF, vVec, roughness * roughness, clipmaps, gl_FragCoord.xy, velocity).rgb * F * voxelgiRefl;') + frag.write('}') frag.write('vec3 direct = vec3(0.0);') if '_Sun' in wrd.world_defs: @@ -730,7 +741,6 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): frag.write(f'svisibility = shadowTestCascade({shadowmap_sun}, {shadowmap_sun_tr}, eye, wposition + n * shadowsBias * 10, shadowsBias, true);') else: frag.write(f'svisibility = shadowTestCascade({shadowmap_sun}, {shadowmap_sun_tr}, eye, wposition + n * shadowsBias * 10, shadowsBias, false);') - else: if tese is not None: tese.add_out('vec4 lightPosition') @@ -744,7 +754,7 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): else: vert.add_out('vec4 lightPosition') vert.add_uniform('mat4 LWVP', '_biasLightWorldViewProjectionMatrixSun') - vert.write('lightPosition = LWVP * lightPosition;') + vert.write('lightPosition = LWVP * pos;') frag.write('vec3 lPos = lightPosition.xyz / lightPosition.w;') frag.write('const vec2 smSize = shadowmapSize;') if parse_opacity: @@ -786,14 +796,13 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): if '_Spot' in wrd.world_defs: frag.write(', true, spotData.x, spotData.y, spotDir, spotData.zw, spotRight') if '_VoxelShadow' in wrd.world_defs: - frag.write(', voxels, voxelsSDF, clipmaps') + frag.write(', voxels, voxelsSDF, clipmaps, velocity') if '_MicroShadowing' in wrd.world_defs: frag.write(', occlusion') if '_SSRS' in wrd.world_defs: - frag.add_uniform('sampler2D gbufferD', top=True) frag.add_uniform('mat4 invVP', '_inverseViewProjectionMatrix') frag.add_uniform('vec3 eye', '_cameraPosition') - frag.write(', gbufferD, invVP, eye') + frag.write(', wposition.z, invVP, eye') frag.write(');') if '_Clusters' in wrd.world_defs: @@ -806,7 +815,7 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): if '_VoxelRefract' in wrd.world_defs and parse_opacity: frag.write('if (opacity < 1.0) {') - frag.write(' vec3 refraction = traceRefraction(wposition, n, voxels, voxelsSDF, vVec, ior, roughness, clipmaps, gl_FragCoord.xy, velocity, opacity).rgb * voxelgiRefr;') + frag.write(' vec3 refraction = traceRefraction(wposition, n, voxels, voxelsSDF, vVec, ior, roughness * roughness, clipmaps, gl_FragCoord.xy, velocity, opacity).rgb * (1.0 - F) * voxelgiRefr;') frag.write(' indirect = mix(refraction, indirect, opacity);') frag.write(' direct = mix(refraction, direct, opacity);') frag.write('}') @@ -822,4 +831,4 @@ def _write_material_attribs_default(frag: shader.Shader, parse_opacity: bool): frag.write('vec3 emissionCol;') if parse_opacity: frag.write('float opacity;') - frag.write('float ior;') + frag.write('float ior = 1.45;') From 210d5ea532cf128b1aa329a4571bf6349b9200f3 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 21 May 2025 22:39:52 +0000 Subject: [PATCH 068/136] Update leenkx/blender/lnx/material/make_finalize.py --- leenkx/blender/lnx/material/make_finalize.py | 321 ++++++++++--------- 1 file changed, 166 insertions(+), 155 deletions(-) diff --git a/leenkx/blender/lnx/material/make_finalize.py b/leenkx/blender/lnx/material/make_finalize.py index afdca57..d549fff 100644 --- a/leenkx/blender/lnx/material/make_finalize.py +++ b/leenkx/blender/lnx/material/make_finalize.py @@ -1,155 +1,166 @@ -import bpy - -import lnx -import lnx.material.mat_state as mat_state -import lnx.material.make_tess as make_tess -from lnx.material.shader import ShaderContext - -if lnx.is_reload(__name__): - mat_state = lnx.reload_module(mat_state) - make_tess = lnx.reload_module(make_tess) - lnx.material.shader = lnx.reload_module(lnx.material.shader) - from lnx.material.shader import ShaderContext -else: - lnx.enable_reload(__name__) - - -def make(con_mesh: ShaderContext): - vert = con_mesh.vert - frag = con_mesh.frag - geom = con_mesh.geom - tesc = con_mesh.tesc - tese = con_mesh.tese - - # Additional values referenced in cycles - # TODO: enable from cycles.py - if frag.contains('dotNV') and not frag.contains('float dotNV'): - frag.write_init('float dotNV = max(dot(n, vVec), 0.0);') - - # n is not always defined yet (in some shadowmap shaders e.g.) - if not frag.contains('vec3 n'): - vert.add_out('vec3 wnormal') - billboard = mat_state.material.lnx_billboard - if billboard == 'spherical': - vert.add_uniform('mat3 N', '_normalMatrixSphere') - elif billboard == 'cylindrical': - vert.add_uniform('mat3 N', '_normalMatrixCylinder') - else: - vert.add_uniform('mat3 N', '_normalMatrix') - vert.write_attrib('wnormal = normalize(N * vec3(nor.xy, pos.w));') - frag.write_attrib('vec3 n = normalize(wnormal);') - - # If not yet added, add nor vertex data - vertex_elems = con_mesh.data['vertex_elements'] - has_normals = False - for elem in vertex_elems: - if elem['name'] == 'nor': - has_normals = True - break - if not has_normals: - vertex_elems.append({'name': 'nor', 'data': 'short2norm'}) - - write_wpos = False - if frag.contains('vVec') and not frag.contains('vec3 vVec'): - if tese is not None: - tese.add_out('vec3 eyeDir') - tese.add_uniform('vec3 eye', '_cameraPosition') - tese.write('eyeDir = eye - wposition;') - - else: - if not vert.contains('wposition'): - write_wpos = True - vert.add_out('vec3 eyeDir') - vert.add_uniform('vec3 eye', '_cameraPosition') - vert.write('eyeDir = eye - wposition;') - frag.write_attrib('vec3 vVec = normalize(eyeDir);') - - export_wpos = False - if frag.contains('wposition') and not frag.contains('vec3 wposition'): - export_wpos = True - if tese is not None: - export_wpos = True - if vert.contains('wposition'): - write_wpos = True - - if export_wpos: - vert.add_uniform('mat4 W', '_worldMatrix') - vert.add_out('vec3 wposition') - vert.write('wposition = vec4(W * spos).xyz;') - elif write_wpos: - vert.add_uniform('mat4 W', '_worldMatrix') - vert.write_attrib('vec3 wposition = vec4(W * spos).xyz;') - - frag_mpos = (frag.contains('mposition') and not frag.contains('vec3 mposition')) or vert.contains('mposition') - if frag_mpos: - vert.add_out('vec3 mposition') - vert.add_uniform('float posUnpack', link='_posUnpack') - vert.write_attrib('mposition = spos.xyz * posUnpack;') - - if tese is not None: - if frag_mpos: - make_tess.interpolate(tese, 'mposition', 3, declare_out=True) - elif tese.contains('mposition') and not tese.contains('vec3 mposition'): - vert.add_out('vec3 mposition') - vert.write_pre = True - vert.add_uniform('float posUnpack', link='_posUnpack') - vert.write('mposition = spos.xyz * posUnpack;') - vert.write_pre = False - make_tess.interpolate(tese, 'mposition', 3, declare_out=False) - - frag_bpos = (frag.contains('bposition') and not frag.contains('vec3 bposition')) or vert.contains('bposition') - if frag_bpos: - vert.add_out('vec3 bposition') - vert.add_uniform('vec3 dim', link='_dim') - vert.add_uniform('vec3 hdim', link='_halfDim') - vert.add_uniform('float posUnpack', link='_posUnpack') - vert.write_attrib('bposition = (spos.xyz * posUnpack + hdim) / dim;') - vert.write_attrib('if (dim.z == 0) bposition.z = 0;') - vert.write_attrib('if (dim.y == 0) bposition.y = 0;') - vert.write_attrib('if (dim.x == 0) bposition.x = 0;') - - if tese is not None: - if frag_bpos: - make_tess.interpolate(tese, 'bposition', 3, declare_out=True) - elif tese.contains('bposition') and not tese.contains('vec3 bposition'): - vert.add_out('vec3 bposition') - vert.add_uniform('vec3 dim', link='_dim') - vert.add_uniform('vec3 hdim', link='_halfDim') - vert.add_uniform('float posUnpack', link='_posUnpack') - vert.write_attrib('bposition = (spos.xyz * posUnpack + hdim) / dim;') - make_tess.interpolate(tese, 'bposition', 3, declare_out=False) - - frag_wtan = (frag.contains('wtangent') and not frag.contains('vec3 wtangent')) or vert.contains('wtangent') - if frag_wtan: - # Indicate we want tang attrib in finalizer to prevent TBN generation - con_mesh.add_elem('tex', 'short2norm') - con_mesh.add_elem('tang', 'short4norm') - vert.add_out('vec3 wtangent') - vert.write_pre = True - vert.write('wtangent = normalize(N * tang.xyz);') - vert.write_pre = False - - if tese is not None: - if frag_wtan: - make_tess.interpolate(tese, 'wtangent', 3, declare_out=True) - elif tese.contains('wtangent') and not tese.contains('vec3 wtangent'): - vert.add_out('vec3 wtangent') - vert.write_pre = True - vert.write('wtangent = normalize(N * tang.xyz);') - vert.write_pre = False - make_tess.interpolate(tese, 'wtangent', 3, declare_out=False) - - if frag.contains('vVecCam'): - vert.add_out('vec3 eyeDirCam') - vert.add_uniform('mat4 WV', '_worldViewMatrix') - vert.write('eyeDirCam = vec4(WV * spos).xyz; eyeDirCam.z *= -1;') - frag.write_attrib('vec3 vVecCam = normalize(eyeDirCam);') - - if frag.contains('nAttr'): - vert.add_out('vec3 nAttr') - vert.write_attrib('nAttr = vec3(nor.xy, pos.w);') - - wrd = bpy.data.worlds['Lnx'] - if '_Legacy' in wrd.world_defs: - frag.replace('sampler2DShadow', 'sampler2D') - frag.replace('samplerCubeShadow', 'samplerCube') +import bpy + +import lnx +import lnx.material.mat_state as mat_state +import lnx.material.make_tess as make_tess +from lnx.material.shader import ShaderContext + +if lnx.is_reload(__name__): + mat_state = lnx.reload_module(mat_state) + make_tess = lnx.reload_module(make_tess) + lnx.material.shader = lnx.reload_module(lnx.material.shader) + from lnx.material.shader import ShaderContext +else: + lnx.enable_reload(__name__) + + +def make(con_mesh: ShaderContext): + vert = con_mesh.vert + frag = con_mesh.frag + geom = con_mesh.geom + tesc = con_mesh.tesc + tese = con_mesh.tese + + # Additional values referenced in cycles + # TODO: enable from cycles.py + if frag.contains('dotNV') and not frag.contains('float dotNV'): + frag.write_init('float dotNV = max(dot(n, vVec), 0.0);') + + # n is not always defined yet (in some shadowmap shaders e.g.) + if not frag.contains('vec3 n'): + vert.add_out('vec3 wnormal') + billboard = mat_state.material.lnx_billboard + if billboard == 'spherical': + vert.add_uniform('mat3 N', '_normalMatrixSphere') + elif billboard == 'cylindrical': + vert.add_uniform('mat3 N', '_normalMatrixCylinder') + else: + vert.add_uniform('mat3 N', '_normalMatrix') + vert.write_attrib('wnormal = normalize(N * vec3(nor.xy, pos.w));') + frag.write_attrib('vec3 n = normalize(wnormal);') + + # If not yet added, add nor vertex data + vertex_elems = con_mesh.data['vertex_elements'] + has_normals = False + for elem in vertex_elems: + if elem['name'] == 'nor': + has_normals = True + break + if not has_normals: + vertex_elems.append({'name': 'nor', 'data': 'short2norm'}) + + write_wpos = False + export_wpos = False + if frag.contains('wposition') and not frag.contains('vec3 wposition'): + export_wpos = True + if tese is not None: + export_wpos = True + if vert.contains('wposition'): + write_wpos = True + + + + + if frag.contains('vVec') and not frag.contains('vec3 vVec'): + if tese is not None: + tese.add_out('vec3 eyeDir') + tese.add_uniform('vec3 eye', '_cameraPosition') + tese.write('eyeDir = eye - wposition;') + + else: + if not vert.contains('wposition'): + write_wpos = True + vert.add_out('vec3 eyeDir') + vert.add_uniform('vec3 eye', '_cameraPosition') + vert.write('eyeDir = eye - wposition;') + frag.write_attrib('vec3 vVec = normalize(eyeDir);') + + export_wpos = False + if frag.contains('wposition') and not frag.contains('vec3 wposition'): + export_wpos = True + if tese is not None: + export_wpos = True + if vert.contains('wposition'): + write_wpos = True + + if export_wpos: + vert.add_uniform('mat4 W', '_worldMatrix') + vert.add_out('vec3 wposition') + vert.write('wposition = vec4(W * spos).xyz;') + elif write_wpos: + vert.add_uniform('mat4 W', '_worldMatrix') + vert.write_attrib('vec3 wposition = vec4(W * spos).xyz;') + + frag_mpos = (frag.contains('mposition') and not frag.contains('vec3 mposition')) or vert.contains('mposition') + if frag_mpos: + vert.add_out('vec3 mposition') + vert.add_uniform('float posUnpack', link='_posUnpack') + vert.write_attrib('mposition = spos.xyz * posUnpack;') + + if tese is not None: + if frag_mpos: + make_tess.interpolate(tese, 'mposition', 3, declare_out=True) + elif tese.contains('mposition') and not tese.contains('vec3 mposition'): + vert.add_out('vec3 mposition') + vert.write_pre = True + vert.add_uniform('float posUnpack', link='_posUnpack') + vert.write('mposition = spos.xyz * posUnpack;') + vert.write_pre = False + make_tess.interpolate(tese, 'mposition', 3, declare_out=False) + + frag_bpos = (frag.contains('bposition') and not frag.contains('vec3 bposition')) or vert.contains('bposition') + if frag_bpos: + vert.add_out('vec3 bposition') + vert.add_uniform('vec3 dim', link='_dim') + vert.add_uniform('vec3 hdim', link='_halfDim') + vert.add_uniform('float posUnpack', link='_posUnpack') + vert.write_attrib('bposition = (spos.xyz * posUnpack + hdim) / dim;') + vert.write_attrib('if (dim.z == 0) bposition.z = 0;') + vert.write_attrib('if (dim.y == 0) bposition.y = 0;') + vert.write_attrib('if (dim.x == 0) bposition.x = 0;') + + if tese is not None: + if frag_bpos: + make_tess.interpolate(tese, 'bposition', 3, declare_out=True) + elif tese.contains('bposition') and not tese.contains('vec3 bposition'): + vert.add_out('vec3 bposition') + vert.add_uniform('vec3 dim', link='_dim') + vert.add_uniform('vec3 hdim', link='_halfDim') + vert.add_uniform('float posUnpack', link='_posUnpack') + vert.write_attrib('bposition = (spos.xyz * posUnpack + hdim) / dim;') + make_tess.interpolate(tese, 'bposition', 3, declare_out=False) + + frag_wtan = (frag.contains('wtangent') and not frag.contains('vec3 wtangent')) or vert.contains('wtangent') + if frag_wtan: + # Indicate we want tang attrib in finalizer to prevent TBN generation + con_mesh.add_elem('tex', 'short2norm') + con_mesh.add_elem('tang', 'short4norm') + vert.add_out('vec3 wtangent') + vert.write_pre = True + vert.write('wtangent = normalize(N * tang.xyz);') + vert.write_pre = False + + if tese is not None: + if frag_wtan: + make_tess.interpolate(tese, 'wtangent', 3, declare_out=True) + elif tese.contains('wtangent') and not tese.contains('vec3 wtangent'): + vert.add_out('vec3 wtangent') + vert.write_pre = True + vert.write('wtangent = normalize(N * tang.xyz);') + vert.write_pre = False + make_tess.interpolate(tese, 'wtangent', 3, declare_out=False) + + if frag.contains('vVecCam'): + vert.add_out('vec3 eyeDirCam') + vert.add_uniform('mat4 WV', '_worldViewMatrix') + vert.write('eyeDirCam = vec4(WV * spos).xyz; eyeDirCam.z *= -1;') + frag.write_attrib('vec3 vVecCam = normalize(eyeDirCam);') + + if frag.contains('nAttr'): + vert.add_out('vec3 nAttr') + vert.write_attrib('nAttr = vec3(nor.xy, pos.w);') + + wrd = bpy.data.worlds['Lnx'] + if '_Legacy' in wrd.world_defs: + frag.replace('sampler2DShadow', 'sampler2D') + frag.replace('samplerCubeShadow', 'samplerCube') From 36cbc934ba94d6d2c971af739aa66672cbec76d0 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 21 May 2025 22:42:11 +0000 Subject: [PATCH 069/136] Update leenkx/blender/lnx/material/make_finalize.py --- leenkx/blender/lnx/material/make_finalize.py | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/leenkx/blender/lnx/material/make_finalize.py b/leenkx/blender/lnx/material/make_finalize.py index d549fff..9760e3c 100644 --- a/leenkx/blender/lnx/material/make_finalize.py +++ b/leenkx/blender/lnx/material/make_finalize.py @@ -75,14 +75,6 @@ def make(con_mesh: ShaderContext): vert.write('eyeDir = eye - wposition;') frag.write_attrib('vec3 vVec = normalize(eyeDir);') - export_wpos = False - if frag.contains('wposition') and not frag.contains('vec3 wposition'): - export_wpos = True - if tese is not None: - export_wpos = True - if vert.contains('wposition'): - write_wpos = True - if export_wpos: vert.add_uniform('mat4 W', '_worldMatrix') vert.add_out('vec3 wposition') @@ -91,6 +83,9 @@ def make(con_mesh: ShaderContext): vert.add_uniform('mat4 W', '_worldMatrix') vert.write_attrib('vec3 wposition = vec4(W * spos).xyz;') + if frag.contains('dotNV') and not frag.contains('float dotNV'): + frag.write_attrib('float dotNV = max(dot(n, vVec), 0.0);') + frag_mpos = (frag.contains('mposition') and not frag.contains('vec3 mposition')) or vert.contains('mposition') if frag_mpos: vert.add_out('vec3 mposition') From c4c0e2beaa1f8b4be2a3346bb7dcfc91c636ec85 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 21 May 2025 22:43:18 +0000 Subject: [PATCH 070/136] Delete leenkx/blender/lnx/material/make_refraction_buffer.py --- .../lnx/material/make_refraction_buffer.py | 49 ------------------- 1 file changed, 49 deletions(-) delete mode 100644 leenkx/blender/lnx/material/make_refraction_buffer.py diff --git a/leenkx/blender/lnx/material/make_refraction_buffer.py b/leenkx/blender/lnx/material/make_refraction_buffer.py deleted file mode 100644 index 06e76bc..0000000 --- a/leenkx/blender/lnx/material/make_refraction_buffer.py +++ /dev/null @@ -1,49 +0,0 @@ -import bpy - -import lnx -import lnx.material.cycles as cycles -import lnx.material.mat_state as mat_state -import lnx.material.mat_utils as mat_utils -import lnx.material.make_mesh as make_mesh -import lnx.material.make_finalize as make_finalize -import lnx.assets as assets - -if lnx.is_reload(__name__): - cycles = lnx.reload_module(cycles) - mat_state = lnx.reload_module(mat_state) - make_mesh = lnx.reload_module(make_mesh) - make_finalize = lnx.reload_module(make_finalize) - assets = lnx.reload_module(assets) -else: - lnx.enable_reload(__name__) - - -def make(context_id): - con_refraction_buffer = mat_state.data.add_context({ 'name': context_id, 'depth_write': False, 'compare_mode': 'less', 'cull_mode': 'clockwise' }) - - lnx_discard = mat_state.material.lnx_discard - blend = mat_state.material.lnx_blending - parse_opacity = blend or mat_utils.is_transluc(mat_state.material) or lnx_discard - - make_mesh.make_base(con_refraction_buffer, parse_opacity) - - vert = con_refraction_buffer.vert - frag = con_refraction_buffer.frag - - frag.add_out('vec4 fragColor') - - # Remove fragColor = ...; - frag.main = frag.main[:frag.main.rfind('fragColor')] - frag.write('\n') - - if parse_opacity: - frag.write('fragColor = vec4(ior, opacity, 0.0, 1.0);') - else: - frag.write('fragColor = vec4(1.0, 1.0, 0.0, 1.0);') - - make_finalize.make(con_refraction_buffer) - - # assets.vs_equal(con_refract, assets.shader_cons['transluc_vert']) # shader_cons has no transluc yet - # assets.fs_equal(con_refract, assets.shader_cons['transluc_frag']) - - return con_refraction_buffer From e98bfb125d714b1e81b17d7d0a90605800f72362 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 21 May 2025 22:47:03 +0000 Subject: [PATCH 071/136] Update leenkx/blender/lnx/material/make_shader.py --- leenkx/blender/lnx/material/make_shader.py | 894 +++++++++++++++++---- 1 file changed, 717 insertions(+), 177 deletions(-) diff --git a/leenkx/blender/lnx/material/make_shader.py b/leenkx/blender/lnx/material/make_shader.py index 89f4fe9..f7755fc 100644 --- a/leenkx/blender/lnx/material/make_shader.py +++ b/leenkx/blender/lnx/material/make_shader.py @@ -1,226 +1,766 @@ -import os -import subprocess -from typing import Dict, List, Tuple +""" +Copyright (c) 2024 Turánszki János +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +""" import bpy -from bpy.types import Material -from bpy.types import Object -import lnx.api +import lnx.utils import lnx.assets as assets -import lnx.exporter -import lnx.log as log import lnx.material.cycles as cycles -import lnx.material.make_decal as make_decal -import lnx.material.make_depth as make_depth -import lnx.material.make_mesh as make_mesh -import lnx.material.make_overlay as make_overlay -import lnx.material.make_transluc as make_transluc -import lnx.material.make_refract as make_refract -import lnx.material.make_voxel as make_voxel import lnx.material.mat_state as mat_state import lnx.material.mat_utils as mat_utils -from lnx.material.shader import Shader, ShaderContext, ShaderData -import lnx.utils +import lnx.material.make_particle as make_particle +import lnx.make_state as state if lnx.is_reload(__name__): - lnx.api = lnx.reload_module(lnx.api) - assets = lnx.reload_module(assets) - lnx.exporter = lnx.reload_module(lnx.exporter) - log = lnx.reload_module(log) - cycles = lnx.reload_module(cycles) - make_decal = lnx.reload_module(make_decal) - make_depth = lnx.reload_module(make_depth) - make_mesh = lnx.reload_module(make_mesh) - make_overlay = lnx.reload_module(make_overlay) - make_transluc = lnx.reload_module(make_transluc) - make_voxel = lnx.reload_module(make_voxel) - mat_state = lnx.reload_module(mat_state) - mat_utils = lnx.reload_module(mat_utils) - lnx.material.shader = lnx.reload_module(lnx.material.shader) - from lnx.material.shader import Shader, ShaderContext, ShaderData lnx.utils = lnx.reload_module(lnx.utils) + assets = lnx.reload_module(assets) + mat_state = lnx.reload_module(mat_state) else: lnx.enable_reload(__name__) -rpass_hook = None +def make(context_id): + rpdat = lnx.utils.get_rp() + if rpdat.rp_voxels == 'Voxel GI': + con = make_gi(context_id) + else: + con = make_ao(context_id) + + assets.vs_equal(con, assets.shader_cons['voxel_vert']) + assets.fs_equal(con, assets.shader_cons['voxel_frag']) + assets.gs_equal(con, assets.shader_cons['voxel_geom']) + + return con + +def make_gi(context_id): + con_voxel = mat_state.data.add_context({ 'name': context_id, 'depth_write': False, 'compare_mode': 'always', 'cull_mode': 'none', 'color_write_red': False, 'color_write_green': False, 'color_write_blue': False, 'color_write_alpha': False, 'conservative_raster': True }) + wrd = bpy.data.worlds['Lnx'] + + vert = con_voxel.make_vert() + frag = con_voxel.make_frag() + geom = con_voxel.make_geom() + tesc = None + tese = None + geom.ins = vert.outs + frag.ins = geom.outs + + vert.add_include('compiled.inc') + geom.add_include('compiled.inc') + frag.add_include('compiled.inc') + frag.add_include('std/math.glsl') + frag.add_include('std/imageatomic.glsl') + frag.add_include('std/gbuffer.glsl') + frag.add_include('std/brdf.glsl') + frag.add_include('std/aabb.glsl') + + rpdat = lnx.utils.get_rp() + frag.add_uniform('layout(r32ui) uimage3D voxels') + + frag.write('vec3 n;') + frag.write('vec3 wposition;') + frag.write('vec3 basecol;') + frag.write('float roughness;') # + frag.write('float metallic;') # + frag.write('float occlusion;') # + frag.write('float specular;') # + frag.write('vec3 emissionCol = vec3(0.0);') + blend = mat_state.material.lnx_blending + parse_opacity = blend or mat_utils.is_transluc(mat_state.material) + if parse_opacity: + frag.write('float opacity;') + frag.write('float ior;') + else: + frag.write('float opacity = 1.0;') + + cycles.parse(mat_state.nodes, con_voxel, vert, frag, geom, tesc, tese, parse_opacity=parse_opacity, parse_displacement=False, basecol_only=True) + + # Voxelized particles + particle = mat_state.material.lnx_particle_flag + if particle and rpdat.lnx_particles == 'On': + # make_particle.write(vert, particle_info=cycles.particle_info) + frag.write_pre = True + frag.write('const float p_index = 0;') + frag.write('const float p_age = 0;') + frag.write('const float p_lifetime = 0;') + frag.write('const vec3 p_location = vec3(0);') + frag.write('const float p_size = 0;') + frag.write('const vec3 p_velocity = vec3(0);') + frag.write('const vec3 p_angular_velocity = vec3(0);') + frag.write_pre = False + + export_mpos = frag.contains('mposition') and not frag.contains('vec3 mposition') + if export_mpos: + vert.add_out('vec3 mpositionGeom') + vert.write_pre = True + vert.write('mpositionGeom = pos.xyz;') + vert.write_pre = False + + export_bpos = frag.contains('bposition') and not frag.contains('vec3 bposition') + if export_bpos: + vert.add_out('vec3 bpositionGeom') + vert.add_uniform('vec3 dim', link='_dim') + vert.add_uniform('vec3 hdim', link='_halfDim') + vert.write_pre = True + vert.write('bpositionGeom = (pos.xyz + hdim) / dim;') + vert.write_pre = False + + vert.add_uniform('mat4 W', '_worldMatrix') + vert.add_uniform('mat3 N', '_normalMatrix') + vert.add_out('vec3 voxpositionGeom') + vert.add_out('vec3 voxnormalGeom') + + if con_voxel.is_elem('col'): + vert.add_out('vec3 vcolorGeom') + vert.write('vcolorGeom = col.rgb;') + + if con_voxel.is_elem('tex'): + vert.add_out('vec2 texCoordGeom') + vert.write('texCoordGeom = tex;') + + vert.write('voxpositionGeom = vec3(W * vec4(pos.xyz, 1.0));') + vert.write('voxnormalGeom = normalize(N * vec3(nor.xy, pos.w));') + + geom.add_out('vec4 voxposition[3]') + geom.add_out('vec3 P') + geom.add_out('vec3 voxnormal') + geom.add_out('vec4 lightPosition') + geom.add_out('vec4 wvpposition') + geom.add_out('vec3 eyeDir') + geom.add_out('vec3 aabb_min') + geom.add_out('vec3 aabb_max') + + if con_voxel.is_elem('col'): + geom.add_out('vec3 vcolor') + if con_voxel.is_elem('tex'): + geom.add_out('vec2 texCoord') + if export_mpos: + geom.add_out('vec3 mposition') + if export_bpos: + geom.add_out('vec3 bposition') + + geom.add_uniform('float clipmaps[voxelgiClipmapCount * 10]', '_clipmaps') + geom.add_uniform('int clipmapLevel', '_clipmapLevel') + + geom.write('vec3 facenormal = abs(voxnormalGeom[0] + voxnormalGeom[1] + voxnormalGeom[2]);') + geom.write('uint maxi = facenormal[1] > facenormal[0] ? 1 : 0;') + geom.write('maxi = facenormal[2] > facenormal[maxi] ? 2 : maxi;') + + geom.write('aabb_min = min(voxpositionGeom[0].xyz, min(voxpositionGeom[1].xyz, voxpositionGeom[2].xyz));') + geom.write('aabb_max = max(voxpositionGeom[0].xyz, max(voxpositionGeom[1].xyz, voxpositionGeom[2].xyz));') + + geom.write('for (uint i = 0; i < 3; ++i) {') + geom.write(' voxposition[i].xyz = (voxpositionGeom[i] - vec3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)])) / (float(clipmaps[int(clipmapLevel * 10)]));') + geom.write(' if (maxi == 0)') + geom.write(' {') + geom.write(' voxposition[i].xyz = voxposition[i].zyx;') + geom.write(' }') + geom.write(' else if (maxi == 1)') + geom.write(' {') + geom.write(' voxposition[i].xyz = voxposition[i].xzy;') + geom.write(' }') + geom.write('}') + + geom.write('vec2 side0N = normalize(voxposition[1].xy - voxposition[0].xy);') + geom.write('vec2 side1N = normalize(voxposition[2].xy - voxposition[1].xy);') + geom.write('vec2 side2N = normalize(voxposition[0].xy - voxposition[2].xy);') + geom.write('voxposition[0].xy += normalize(side2N - side0N);') + geom.write('voxposition[1].xy += normalize(side0N - side1N);') + geom.write('voxposition[2].xy += normalize(side1N - side2N);') + + geom.write('for (uint i = 0; i < 3; ++i) {') + geom.write(' voxposition[i].xy /= voxelgiResolution.xy;') + geom.write(' voxposition[i].zw = vec2(1.0);') + geom.write(' P = voxpositionGeom[i];') + geom.write(' voxnormal = voxnormalGeom[i];') + if con_voxel.is_elem('col'): + geom.write('vcolor = vcolorGeom[i];') + if con_voxel.is_elem('tex'): + geom.write('texCoord = texCoordGeom[i];') + if export_mpos: + geom.write('mposition = mpositionGeom[i];') + if export_bpos: + geom.write('bposition = bpositionGeom[i];') + geom.write(' eyeDir = eyeDirGeom[i];') + if '_Sun' in wrd.world_defs and not '_CSM' in wrd.world_defs and '_ShadowMap' in wrd.world_defs: + geom.write(' lightPosition = lightPositionGeom[i];') + if '_Clusters' in wrd.world_defs and '_ShadowMap' in wrd.world_defs: + geom.write(' wvpposition = wvppositionGeom[i];') + geom.write(' gl_Position = voxposition[i];') + geom.write(' EmitVertex();') + geom.write('}') + geom.write('EndPrimitive();') + + frag.add_uniform('float clipmaps[voxelgiClipmapCount * 10]', '_clipmaps') + frag.add_uniform('int clipmapLevel', '_clipmapLevel') + + frag.write('vec3 uvw = (P - vec3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)])) / (float(clipmaps[int(clipmapLevel * 10)]) * voxelgiResolution);') + frag.write('uvw = (uvw * 0.5 + 0.5);') + + frag.write('if(any(notEqual(uvw, clamp(uvw, 0.0, 1.0)))) return;') + frag.write('vec3 writecoords = floor(uvw * voxelgiResolution);') + frag.write_attrib('vec3 N = normalize(voxnormal);') + frag.write('vec3 aniso_direction = N;') + frag.write('uvec3 face_offsets = uvec3(') + frag.write(' aniso_direction.x > 0 ? 0 : 1,') + frag.write(' aniso_direction.y > 0 ? 2 : 3,') + frag.write(' aniso_direction.z > 0 ? 4 : 5') + frag.write(' ) * voxelgiResolution;') + frag.write('vec3 direction_weights = abs(N);') + + frag.write('vec3 clipmap_pixel = uvw * voxelgiResolution;') + frag.write('vec3 clipmap_uvw_center = (clipmap_pixel + 0.5) / voxelgiResolution;') + frag.write('vec3 voxel_center = clipmap_uvw_center * 2.0 - 1.0;') + frag.write('float voxel_size = float(clipmaps[int(clipmapLevel * 10)]);') + frag.write('voxel_center *= voxel_size;') + frag.write('voxel_center *= voxelgiResolution.x;') + frag.write('voxel_center += vec3(') + frag.write(' clipmaps[clipmapLevel * 10 + 4],') + frag.write(' clipmaps[clipmapLevel * 10 + 5],') + frag.write(' clipmaps[clipmapLevel * 10 + 6]);') + + frag.write('vec3 voxel_aabb[2];') + frag.write('voxel_aabb[0] = voxel_center;') + frag.write('voxel_aabb[1] = vec3(voxel_size);') + frag.write('vec3 triangle_aabb[2];') + frag.write('AABBfromMinMax(triangle_aabb, aabb_min, aabb_max);') + frag.write('if (!IntersectAABB(voxel_aabb, triangle_aabb))') + frag.write(' return;') + + frag.write('vec3 albedo = surfaceAlbedo(basecol, metallic);') + frag.write('vec3 f0 = surfaceF0(basecol, metallic);') + + vert.add_uniform('vec3 eye', '_cameraPosition') + vert.add_out('vec3 eyeDirGeom') + vert.write('eyeDirGeom = eye - voxpositionGeom;') + frag.write_attrib('vec3 vVec = normalize(eyeDir);') + frag.write_attrib('float dotNV = max(dot(N, vVec), 0.0);') + + if '_Brdf' in wrd.world_defs: + frag.add_uniform('sampler2D senvmapBrdf', link='$brdf.png') + frag.write('vec2 envBRDF = texelFetch(senvmapBrdf, ivec2(vec2(dotNV, 1.0 - roughness) * 256.0), 0).xy;') + + if '_Irr' in wrd.world_defs: + frag.add_include('std/shirr.glsl') + frag.add_uniform('vec4 shirr[7]', link='_envmapIrradiance') + frag.write('vec3 envl = shIrradiance(N, shirr);') + if '_EnvTex' in wrd.world_defs: + frag.write('envl /= PI;') + else: + frag.write('vec3 envl = vec3(0.0);') + + if '_Rad' in wrd.world_defs: + frag.add_uniform('sampler2D senvmapRadiance', link='_envmapRadiance') + frag.add_uniform('int envmapNumMipmaps', link='_envmapNumMipmaps') + frag.write('vec3 reflectionWorld = reflect(-vVec, N);') + frag.write('float lod = getMipFromRoughness(roughness, envmapNumMipmaps);') + frag.write('vec3 prefilteredColor = textureLod(senvmapRadiance, envMapEquirect(reflectionWorld), lod).rgb;') + + if '_EnvLDR' in wrd.world_defs: + frag.write('envl = pow(envl, vec3(2.2));') + if '_Rad' in wrd.world_defs: + frag.write('prefilteredColor = pow(prefilteredColor, vec3(2.2));') + + frag.write('envl *= albedo;') + + if '_Brdf' in wrd.world_defs: + frag.write('envl.rgb *= 1.0 - (f0 * envBRDF.x + envBRDF.y);') + if '_Rad' in wrd.world_defs: + frag.write('envl += prefilteredColor * (f0 * envBRDF.x + envBRDF.y);') + elif '_EnvCol' in wrd.world_defs: + frag.add_uniform('vec3 backgroundCol', link='_backgroundCol') + frag.write('envl += backgroundCol * (f0 * envBRDF.x + envBRDF.y);') + + frag.add_uniform('float envmapStrength', link='_envmapStrength') + frag.write('envl *= envmapStrength * occlusion;') + + frag.add_include('std/light.glsl') + is_shadows = '_ShadowMap' in wrd.world_defs + is_shadows_atlas = '_ShadowMapAtlas' in wrd.world_defs + is_single_atlas = is_shadows_atlas and '_SingleAtlas' in wrd.world_defs + shadowmap_sun = 'shadowMap' + shadowmap_sun_tr = 'shadowMapTransparent' + if is_shadows_atlas: + shadowmap_sun = 'shadowMapAtlasSun' if not is_single_atlas else 'shadowMapAtlas' + shadowmap_sun_tr = 'shadowMapAtlasSunTransparent' if not is_single_atlas else 'shadowMapAtlasTransparent' + frag.add_uniform('vec2 smSizeUniform', '_shadowMapSize', included=True) + + frag.write('vec3 direct = vec3(0.0);') + + if '_Sun' in wrd.world_defs: + frag.add_uniform('vec3 sunCol', '_sunColor') + frag.add_uniform('vec3 sunDir', '_sunDirection') + frag.write('vec3 svisibility = vec3(1.0);') + frag.write('vec3 sh = normalize(vVec + sunDir);') + frag.write('float sdotNL = dot(N, sunDir);') + frag.write('float sdotNH = dot(N, sh);') + frag.write('float sdotVH = dot(vVec, sh);') + if is_shadows: + frag.add_uniform('bool receiveShadow') + frag.add_uniform(f'sampler2DShadow {shadowmap_sun}', top=True) + frag.add_uniform(f'sampler2D {shadowmap_sun_tr}', top=True) + frag.add_uniform('float shadowsBias', '_sunShadowsBias') + frag.write('if (receiveShadow) {') + if '_CSM' in wrd.world_defs: + frag.add_include('std/shadows.glsl') + frag.add_uniform('vec4 casData[shadowmapCascades * 4 + 4]', '_cascadeData', included=True) + frag.add_uniform('vec3 eye', '_cameraPosition') + if parse_opacity: + frag.write(f'svisibility = shadowTestCascade({shadowmap_sun},') + frag.write(f'{shadowmap_sun_tr},') + frag.write('eye, P + N * shadowsBias * 10, shadowsBias, true);') + else: + frag.write(f'svisibility = shadowTestCascade({shadowmap_sun},') + frag.write(f'{shadowmap_sun_tr},') + frag.write('eye, P + N * shadowsBias * 10, shadowsBias, false);') + else: + vert.add_out('vec4 lightPositionGeom') + vert.add_uniform('mat4 LWVP', '_biasLightWorldViewProjectionMatrixSun') + vert.write('lightPositionGeom = LWVP * vec4(pos.xyz, 1.0);') + frag.write('vec3 lPos = lightPosition.xyz / lightPosition.w;') + frag.write('const vec2 smSize = shadowmapSize;') + if parse_opacity: + frag.write(f'svisibility = PCF({shadowmap_sun},') + frag.write(f'{shadowmap_sun_tr},') + frag.write('lPos.xy, lPos.z - shadowsBias, smSize, true);') + else: + frag.write(f'svisibility = PCF({shadowmap_sun},') + frag.write(f'{shadowmap_sun_tr},') + frag.write('lPos.xy, lPos.z - shadowsBias, smSize, false);') + frag.write('}') + frag.write('direct += (lambertDiffuseBRDF(albedo, sdotNL) + specularBRDF(f0, roughness, sdotNL, sdotNH, dotNV, sdotVH) * specular) * sunCol * svisibility;') + + if '_SinglePoint' in wrd.world_defs: + frag.add_uniform('vec3 pointPos', link='_pointPosition') + frag.add_uniform('vec3 pointCol', link='_pointColor') + if '_Spot' in wrd.world_defs: + frag.add_uniform('vec3 spotDir', link='_spotDirection') + frag.add_uniform('vec3 spotRight', link='_spotRight') + frag.add_uniform('vec4 spotData', link='_spotData') + if is_shadows: + frag.add_uniform('bool receiveShadow') + frag.add_uniform('float pointBias', link='_pointShadowsBias') + if '_Spot' in wrd.world_defs: + # Skip world matrix, already in world-space + frag.add_uniform('mat4 LWVPSpot[1]', link='_biasLightViewProjectionMatrixSpotArray', included=True) + frag.add_uniform('sampler2DShadow shadowMapSpot[1]', included=True) + frag.add_uniform('sampler2D shadowMapSpotTransparent[1]', included=True) + else: + frag.add_uniform('vec2 lightProj', link='_lightPlaneProj', included=True) + frag.add_uniform('samplerCubeShadow shadowMapPoint[1]', included=True) + frag.add_uniform('samplerCube shadowMapPointTransparent[1]', included=True) + frag.write('direct += sampleLightVoxels(') + frag.write(' P, N, vVec, dotNV, pointPos, pointCol, albedo, roughness, specular, f0') + if is_shadows: + if parse_opacity: + frag.write(', 0, pointBias, receiveShadow, opacity != 1.0') + else: + frag.write(', 0, pointBias, receiveShadow, false') + if '_Spot' in wrd.world_defs: + frag.write(', true, spotData.x, spotData.y, spotDir, spotData.zw, spotRight') + frag.write(');') + + if '_Clusters' in wrd.world_defs: + frag.add_include_front('std/clusters.glsl') + frag.add_uniform('vec2 cameraProj', link='_cameraPlaneProj') + frag.add_uniform('vec2 cameraPlane', link='_cameraPlane') + frag.add_uniform('vec4 lightsArray[maxLights * 3]', link='_lightsArray') + frag.add_uniform('sampler2D clustersData', link='_clustersData') + if is_shadows: + frag.add_uniform('bool receiveShadow') + frag.add_uniform('vec2 lightProj', link='_lightPlaneProj', included=True) + if is_shadows_atlas: + if not is_single_atlas: + frag.add_uniform('sampler2DShadow shadowMapAtlasPoint', included=True) + frag.add_uniform('sampler2D shadowMapAtlasPointTransparent', included=True) + else: + frag.add_uniform('sampler2DShadow shadowMapAtlas', top=True) + frag.add_uniform('sampler2D shadowMapAtlasTransparent', top=True) + frag.add_uniform('vec4 pointLightDataArray[maxLightsCluster]', link='_pointLightsAtlasArray', included=True) + else: + frag.add_uniform('samplerCubeShadow shadowMapPoint[4]', included=True) + frag.add_uniform('samplerCube shadowMapPointTransparent[4]', included=True) + + vert.add_out('vec4 wvppositionGeom') + vert.add_uniform('mat4 VP', '_viewProjectionMatrix') + vert.write('wvppositionGeom = VP * vec4(voxpositionGeom, 1.0);') + # wvpposition.z / wvpposition.w + frag.write('float viewz = linearize((wvpposition.z / wvpposition.w) * 0.5 + 0.5, cameraProj);') + frag.write('int clusterI = getClusterI((wvpposition.xy / wvpposition.w) * 0.5 + 0.5, viewz, cameraPlane);') + frag.write('int numLights = int(texelFetch(clustersData, ivec2(clusterI, 0), 0).r * 255);') + + frag.write('#ifdef HLSL') + frag.write('viewz += texture(clustersData, vec2(0.0)).r * 1e-9;') # TODO: krafix bug, needs to generate sampler + frag.write('#endif') + + if '_Spot' in wrd.world_defs: + frag.add_uniform('vec4 lightsArraySpot[maxLights * 2]', link='_lightsArraySpot') + frag.write('int numSpots = int(texelFetch(clustersData, ivec2(clusterI, 1 + maxLightsCluster), 0).r * 255);') + frag.write('int numPoints = numLights - numSpots;') + if is_shadows: + if is_shadows_atlas: + if not is_single_atlas: + frag.add_uniform('sampler2DShadow shadowMapAtlasSpot', included=True) + frag.add_uniform('sampler2D shadowMapAtlasSpotTransparent', included=True) + else: + frag.add_uniform('sampler2DShadow shadowMapAtlas', top=True) + frag.add_uniform('sampler2D shadowMapAtlasTransparent', top=True) + else: + frag.add_uniform('sampler2DShadow shadowMapSpot[4]', included=True) + frag.add_uniform('sampler2D shadowMapSpotTransparent[4]', included=True) + frag.add_uniform('mat4 LWVPSpotArray[maxLightsCluster]', link='_biasLightWorldViewProjectionMatrixSpotArray', included=True) + + frag.write('for (int i = 0; i < min(numLights, maxLightsCluster); i++) {') + frag.write('int li = int(texelFetch(clustersData, ivec2(clusterI, i + 1), 0).r * 255);') + frag.write('direct += sampleLightVoxels(') + frag.write(' P,') + frag.write(' N,') + frag.write(' vVec,') + frag.write(' dotNV,') + frag.write(' lightsArray[li * 3].xyz,') # lp + frag.write(' lightsArray[li * 3 + 1].xyz,') # lightCol + frag.write(' albedo,') + frag.write(' roughness,') + frag.write(' specular,') + frag.write(' f0') + + if is_shadows: + if parse_opacity: + frag.write('\t, li, lightsArray[li * 3 + 2].x, lightsArray[li * 3 + 2].z != 0.0, opacity != 1.0') # bias + else: + frag.write('\t, li, lightsArray[li * 3 + 2].x, lightsArray[li * 3 + 2].z != 0.0, false') # bias + if '_Spot' in wrd.world_defs: + frag.write('\t, lightsArray[li * 3 + 2].y != 0.0') + frag.write('\t, lightsArray[li * 3 + 2].y') # spot size (cutoff) + frag.write('\t, lightsArraySpot[li * 2].w') # spot blend (exponent) + frag.write('\t, lightsArraySpot[li * 2].xyz') # spotDir + frag.write('\t, vec2(lightsArray[li * 3].w, lightsArray[li * 3 + 1].w)') # scale + frag.write('\t, lightsArraySpot[li * 2 + 1].xyz') # right + frag.write(' );') + frag.write('}') + + frag.write('if (direction_weights.x > 0.0) {') + frag.write(' vec4 basecol_direction = vec4(basecol, opacity) * direction_weights.x;') + frag.write(' vec3 emission_direction = emissionCol * direction_weights.x;') + frag.write(' vec2 encoded_normal = encode_oct(N) * 0.5 + 0.5;') + frag.write(' vec2 normal_direction = encoded_normal * direction_weights.x;') + frag.write(' vec3 envl_direction = envl * direction_weights.x;') + frag.write(' vec3 light_direction = direct * direction_weights.x;') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, 0)), uint(basecol_direction.r * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x)), uint(basecol_direction.g * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 2)), uint(basecol_direction.b * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 3)), uint(basecol_direction.a * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 4)), uint(emission_direction.r * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 5)), uint(emission_direction.g * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 6)), uint(emission_direction.b * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 7)), uint(normal_direction.r * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 8)), uint(normal_direction.g * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 9)), uint(envl_direction.r * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 10)), uint(envl_direction.g * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 11)), uint(envl_direction.b * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 12)), uint(light_direction.r * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 13)), uint(light_direction.g * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 14)), uint(light_direction.b * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 15)), uint(1));') + frag.write('}') + + frag.write('if (direction_weights.y > 0.0) {') + frag.write(' vec4 basecol_direction = vec4(basecol, opacity) * direction_weights.y;') + frag.write(' vec3 emission_direction = emissionCol * direction_weights.y;') + frag.write(' vec2 encoded_normal = encode_oct(N) * 0.5 + 0.5;') + frag.write(' vec2 normal_direction = encoded_normal * direction_weights.y;') + frag.write(' vec3 envl_direction = envl * direction_weights.y;') + frag.write(' vec3 light_direction = direct * direction_weights.y;') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, 0)), uint(basecol_direction.r * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x)), uint(basecol_direction.g * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 2)), uint(basecol_direction.b * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 3)), uint(basecol_direction.a * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 4)), uint(emission_direction.r * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 5)), uint(emission_direction.g * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 6)), uint(emission_direction.b * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 7)), uint(normal_direction.r * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 8)), uint(normal_direction.g * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 9)), uint(envl_direction.r * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 10)), uint(envl_direction.g * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 11)), uint(envl_direction.b * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 12)), uint(light_direction.r * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 13)), uint(light_direction.g * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 14)), uint(light_direction.b * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 15)), uint(1));') + frag.write('}') + + frag.write('if (direction_weights.z > 0.0) {') + frag.write(' vec4 basecol_direction = vec4(basecol, opacity) * direction_weights.z;') + frag.write(' vec3 emission_direction = emissionCol * direction_weights.z;') + frag.write(' vec2 encoded_normal = encode_oct(N) * 0.5 + 0.5;') + frag.write(' vec2 normal_direction = encoded_normal * direction_weights.z;') + frag.write(' vec3 envl_direction = envl * direction_weights.z;') + frag.write(' vec3 light_direction = direct * direction_weights.z;') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, 0)), uint(basecol_direction.r * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x)), uint(basecol_direction.g * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 2)), uint(basecol_direction.b * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 3)), uint(basecol_direction.a * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 4)), uint(emission_direction.r * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 5)), uint(emission_direction.g * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 6)), uint(emission_direction.b * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 7)), uint(normal_direction.r * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 8)), uint(normal_direction.g * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 9)), uint(envl_direction.r * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 10)), uint(envl_direction.g * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 11)), uint(envl_direction.b * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 12)), uint(light_direction.r * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 13)), uint(light_direction.g * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 14)), uint(light_direction.b * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 15)), uint(1));') + frag.write('}') + + return con_voxel -def build(material: Material, mat_users: Dict[Material, List[Object]], mat_lnxusers) -> Tuple: - mat_state.mat_users = mat_users - mat_state.mat_lnxusers = mat_lnxusers - mat_state.material = material - mat_state.nodes = material.node_tree.nodes - mat_state.data = ShaderData(material) - mat_state.output_node = cycles.node_by_type(mat_state.nodes, 'OUTPUT_MATERIAL') - if mat_state.output_node is None: - # Place empty material output to keep compiler happy.. - mat_state.output_node = mat_state.nodes.new('ShaderNodeOutputMaterial') - +def make_ao(context_id): + con_voxel = mat_state.data.add_context({ 'name': context_id, 'depth_write': False, 'compare_mode': 'always', 'cull_mode': 'none', 'color_writes_red': [False], 'color_writes_green': [False], 'color_writes_blue': [False], 'color_writes_alpha': [False], 'conservative_raster': False }) wrd = bpy.data.worlds['Lnx'] rpdat = lnx.utils.get_rp() - rpasses = mat_utils.get_rpasses(material) - matname = lnx.utils.safesrc(lnx.utils.asset_name(material)) - rel_path = lnx.utils.build_dir() + '/compiled/Shaders/' - full_path = lnx.utils.get_fp() + '/' + rel_path - if not os.path.exists(full_path): - os.makedirs(full_path) - make_instancing_and_skinning(material, mat_users) + vert = con_voxel.make_vert() + frag = con_voxel.make_frag() + geom = con_voxel.make_geom() + tesc = None + tese = None - bind_constants = dict() - bind_textures = dict() + geom.ins = vert.outs + frag.ins = geom.outs - for rp in rpasses: - car = [] - bind_constants[rp] = car - mat_state.bind_constants = car - tar = [] - bind_textures[rp] = tar - mat_state.bind_textures = tar + frag.add_include('compiled.inc') + geom.add_include('compiled.inc') + frag.add_include('std/math.glsl') + frag.add_include('std/imageatomic.glsl') + frag.add_include('std/aabb.glsl') + frag.write_header('#extension GL_ARB_shader_image_load_store : enable') - con = None + vert.add_include('compiled.inc') + vert.add_uniform('mat4 W', '_worldMatrix') + vert.add_uniform('mat3 N', '_normalMatrix') - if rpdat.rp_driver != 'Leenkx' and lnx.api.drivers[rpdat.rp_driver]['make_rpass'] is not None: - con = lnx.api.drivers[rpdat.rp_driver]['make_rpass'](rp) + geom.add_uniform('float clipmaps[voxelgiClipmapCount * 10]', '_clipmaps') + geom.add_uniform('int clipmapLevel', '_clipmapLevel') - if con is not None: - pass + frag.add_uniform('float clipmaps[voxelgiClipmapCount * 10]', '_clipmaps') + frag.add_uniform('int clipmapLevel', '_clipmapLevel') - elif rp == 'mesh': - con = make_mesh.make(rp, rpasses) + """ + if lnx.utils.get_gapi() == 'direct3d11': + for e in con_voxel.data['vertex_elements']: + if e['name'] == 'nor': + con_voxel.data['vertex_elements'].remove(e) + break - elif rp == 'shadowmap': - con = make_depth.make(rp, rpasses, shadowmap=True) + vert.write('uniform float4x4 W;') + vert.write('uniform float3x3 N;') + vert.write('struct SPIRV_Cross_Input {') + vert.write(' float4 pos : TEXCOORD0;') + vert.write(' float3 nor : NORMAL;') + vert.write('};') + vert.write('struct SPIRV_Cross_Output {') + vert.write(' float4 svpos : SV_POSITION;') + vert.write(' float3 svnor : NORMAL;') + vert.write('};') + vert.write('SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input) {') + vert.write(' SPIRV_Cross_Output stage_output;') + vert.write(' stage_output.svpos.xyz = mul(float4(stage_input.pos.xyz, 1.0), W).xyz;') + vert.write(' stage_output.svpos.w = 1.0;') + vert.write(' stage_output.svnor.xyz = normalize(mul(float3(nor.xy, pos.w), N).xyz);') + vert.write(' return stage_output;') + vert.write('}') - elif rp == 'shadowmap_transparent': - con = make_depth.make(rp, rpasses, shadowmap=True, shadowmap_transparent=True) + geom.write('uniform float clipmaps[voxelgiClipmapCount * 10];') + geom.write('uniform int clipmapLevel;') + geom.write('struct SPIRV_Cross_Input {') + geom.write(' float4 svpos : SV_POSITION;') + geom.write(' float3 svnor : NORMAL;') + geom.write('};') + geom.write('struct SPIRV_Cross_Output {') + geom.write(' float3 wpos : TEXCOORD0;') + geom.write(' float3 wnor : NORMAL;') + geom.write('};') + geom.write('[maxvertexcount(3)]') + geom.write('void main(triangle SPIRV_Cross_Input stage_input[3], inout TriangleStream output) {') + geom.write(' float3 p1 = stage_input[1].svpos.xyz - stage_input[0].svpos.xyz;') + geom.write(' float3 p2 = stage_input[2].svpos.xyz - stage_input[0].svpos.xyz;') + geom.write(' float3 p = abs(cross(p1, p2));') + geom.write(' for (int i = 0; i < 3; ++i) {') + geom.write(' SPIRV_Cross_Output stage_output;') + geom.write(' stage_output.wpos = (stage_input[i].svpos.xyz + float3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)])) / (float(clipmaps[clipmapLevel * 10]) * voxelgiResolution);') + geom.write(' stage_output.wnor = stage_input[i].svnor.xyz;') + geom.write(' if (p.z > p.x && p.z > p.y) {') + geom.write(' stage_output.svpos = float4(stage_input[i].svpos.x, stage_input[i].svpos.y, 0.0, 1.0);') + geom.write(' }') + geom.write(' else if (p.x > p.y && p.x > p.z) {') + geom.write(' stage_output.svpos = float4(stage_input[i].svpos.y, stage_input[i].svpos.z, 0.0, 1.0);') + geom.write(' }') + geom.write(' else {') + geom.write(' stage_output.svpos = float4(stage_input[i].svpos.x, stage_input[i].svpos.z, 0.0, 1.0);') + geom.write(' }') + geom.write(' output.Append(stage_output);') + geom.write(' }') + geom.write('}') - elif rp == 'translucent': - con = make_transluc.make(rp) + frag.add_uniform('layout(r8) writeonly image3D voxels') + frag.write('RWTexture3D voxels;') + frag.write('uniform float clipmaps[voxelgiClipmapCount * 10];') + frag.write('uniform int clipmapLevel;') - elif rp == 'refraction': - con = make_refract.make(rp) + frag.write('struct SPIRV_Cross_Input {') + frag.write(' float3 wpos : TEXCOORD0;') + frag.write(' float3 wnor : NORMAL;') + frag.write('};') + frag.write('struct SPIRV_Cross_Output { float4 FragColor : SV_TARGET0; };') + frag.write('void main(SPIRV_Cross_Input stage_input) {') + frag.write(' float3 uvw = (stage_input.wpos.xyz - float3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)])) / (float(clipmaps[int(clipmapLevel * 10)]) * voxelgiResolution);') + frag.write(' uvw = uvw * 0.5 + 0.5;') + frag.write(' if(any(!saturate(uvw))) return;') + frag.write(' uvw = floor(uvw * voxelgiResolution);') + frag.write(' uint3 face_offsets = uint3(') + frag.write(' stage_input.wnor.x > 0 ? 0 : 1,') + frag.write(' stage_input.wnor.y > 0 ? 2 : 3,') + frag.write(' stage_input.wnor.z > 0 ? 4 : 5') + frag.write(' ) * voxelgiResolution;') + frag.write(' float3 direction_weights = abs(stage_input.wnor);') - elif rp == 'overlay': - con = make_overlay.make(rp) + frag.write(' if (direction_weights.x > 0.0) {') + frag.write(' float opac_direction = direction_weights.x;') + frag.write(' voxels[uvw + int3(face_offsets.x, 0, 0))] = float4(opac_direction);') + frag.write(' }') - elif rp == 'decal': - con = make_decal.make(rp) + frag.write(' if (direction_weights.y > 0.0) {') + frag.write(' float opac_direction = direction_weights.y;') + frag.write(' voxels[uvw + int3(face_offsets.y, 0, 0))] = float4(opac_direction);') + frag.write(' }') - elif rp == 'depth': - con = make_depth.make(rp, rpasses) - - elif rp == 'voxel': - con = make_voxel.make(rp) - - elif rpass_hook is not None: - con = rpass_hook(rp) - - write_shaders(rel_path, con, rp, matname) - - shader_data_name = matname + '_data' - - if wrd.lnx_single_data_file: - if 'shader_datas' not in lnx.exporter.current_output: - lnx.exporter.current_output['shader_datas'] = [] - lnx.exporter.current_output['shader_datas'].append(mat_state.data.get()['shader_datas'][0]) + frag.write(' if (direction_weights.z > 0.0) {') + frag.write(' float opac_direction = direction_weights.z;') + frag.write(' voxels[uvw + int3(face_offsets.z, 0, 0))] = float4(opac_direction);') + frag.write(' }') + frag.write('}') else: - lnx.utils.write_lnx(full_path + '/' + matname + '_data.lnx', mat_state.data.get()) - shader_data_path = lnx.utils.get_fp_build() + '/compiled/Shaders/' + shader_data_name + '.lnx' - assets.add_shader_data(shader_data_path) + """ + frag.add_uniform('layout(r32ui) uimage3D voxels') - return rpasses, mat_state.data, shader_data_name, bind_constants, bind_textures + vert.add_out('vec3 voxpositionGeom') + vert.add_out('vec3 voxnormalGeom') + vert.write('voxpositionGeom = vec3(W * vec4(pos.xyz, 1.0));') + vert.write('voxnormalGeom = normalize(N * vec3(nor.xy, pos.w));') -def write_shaders(rel_path: str, con: ShaderContext, rpass: str, matname: str) -> None: - keep_cache = mat_state.material.lnx_cached - write_shader(rel_path, con.vert, 'vert', rpass, matname, keep_cache=keep_cache) - write_shader(rel_path, con.frag, 'frag', rpass, matname, keep_cache=keep_cache) - write_shader(rel_path, con.geom, 'geom', rpass, matname, keep_cache=keep_cache) - write_shader(rel_path, con.tesc, 'tesc', rpass, matname, keep_cache=keep_cache) - write_shader(rel_path, con.tese, 'tese', rpass, matname, keep_cache=keep_cache) + geom.add_out('vec4 voxposition[3]') + geom.add_out('vec3 P') + geom.add_out('vec3 voxnormal') + geom.add_out('vec3 aabb_min') + geom.add_out('vec3 aabb_max') + geom.add_uniform('float clipmaps[voxelgiClipmapCount * 10]', '_clipmaps') + geom.add_uniform('int clipmapLevel', '_clipmapLevel') -def write_shader(rel_path: str, shader: Shader, ext: str, rpass: str, matname: str, keep_cache=True) -> None: - if shader is None or shader.is_linked: - return + geom.write('aabb_min = min(voxpositionGeom[0].xyz, min(voxpositionGeom[1].xyz, voxpositionGeom[2].xyz));') + geom.write('aabb_max = max(voxpositionGeom[0].xyz, max(voxpositionGeom[1].xyz, voxpositionGeom[2].xyz));') - # TODO: blend context - if rpass == 'mesh' and mat_state.material.lnx_blending: - rpass = 'blend' + geom.write('vec3 facenormal = abs(voxnormalGeom[0] + voxnormalGeom[1] + voxnormalGeom[2]);') + geom.write('uint maxi = facenormal[1] > facenormal[0] ? 1 : 0;') + geom.write('maxi = facenormal[2] > facenormal[maxi] ? 2 : maxi;') - file_ext = '.glsl' - if shader.noprocessing: - # Use hlsl directly - hlsl_dir = lnx.utils.build_dir() + '/compiled/Hlsl/' - if not os.path.exists(hlsl_dir): - os.makedirs(hlsl_dir) - file_ext = '.hlsl' - rel_path = rel_path.replace('/compiled/Shaders/', '/compiled/Hlsl/') + geom.write('for (uint i = 0; i < 3; ++i) {') + geom.write(' voxposition[i].xyz = (voxpositionGeom[i] - vec3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)])) / (float(clipmaps[int(clipmapLevel * 10)]));') + geom.write(' if (maxi == 0)') + geom.write(' {') + geom.write(' voxposition[i].xyz = voxposition[i].zyx;') + geom.write(' }') + geom.write(' else if (maxi == 1)') + geom.write(' {') + geom.write(' voxposition[i].xyz = voxposition[i].xzy;') + geom.write(' }') + geom.write('}') - shader_file = matname + '_' + rpass + '.' + ext + file_ext - shader_path = lnx.utils.get_fp() + '/' + rel_path + '/' + shader_file - assets.add_shader(shader_path) - if not os.path.isfile(shader_path) or not keep_cache: - with open(shader_path, 'w') as f: - f.write(shader.get()) + geom.write('vec2 side0N = normalize(voxposition[1].xy - voxposition[0].xy);') + geom.write('vec2 side1N = normalize(voxposition[2].xy - voxposition[1].xy);') + geom.write('vec2 side2N = normalize(voxposition[0].xy - voxposition[2].xy);') + geom.write('voxposition[0].xy += normalize(side2N - side0N);') + geom.write('voxposition[1].xy += normalize(side0N - side1N);') + geom.write('voxposition[2].xy += normalize(side1N - side2N);') - if shader.noprocessing: - cwd = os.getcwd() - os.chdir(lnx.utils.get_fp() + '/' + rel_path) - hlslbin_path = lnx.utils.get_sdk_path() + '/lib/leenkx_tools/hlslbin/hlslbin.exe' - prof = 'vs_5_0' if ext == 'vert' else 'ps_5_0' if ext == 'frag' else 'gs_5_0' - # noprocessing flag - gets renamed to .d3d11 - args = [hlslbin_path.replace('/', '\\').replace('\\\\', '\\'), shader_file, shader_file[:-4] + 'glsl', prof] - if ext == 'vert': - args.append('-i') - args.append('pos') - proc = subprocess.call(args) - os.chdir(cwd) + geom.write('for (uint i = 0; i < 3; ++i) {') + geom.write(' voxposition[i].xy /= voxelgiResolution.xy;') + geom.write(' voxposition[i].zw = vec2(1.0);') + geom.write(' P = voxpositionGeom[i];') + geom.write(' voxnormal = voxnormalGeom[i];') + geom.write(' gl_Position = voxposition[i];') + geom.write(' EmitVertex();') + geom.write('}') + geom.write('EndPrimitive();') + frag.add_uniform('float clipmaps[voxelgiClipmapCount * 10]', '_clipmaps') + frag.add_uniform('int clipmapLevel', '_clipmapLevel') -def make_instancing_and_skinning(mat: Material, mat_users: Dict[Material, List[Object]]) -> None: - """Build material with instancing or skinning if enabled. - If the material is a custom material, only validation checks for instancing are performed.""" - global_elems = [] - if mat_users is not None and mat in mat_users: - # Whether there are both an instanced object and a not instanced object with this material - instancing_usage = [False, False] - mat_state.uses_instancing = False + frag.write('vec3 uvw = (P - vec3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)])) / (float(clipmaps[int(clipmapLevel * 10)]) * voxelgiResolution);') + frag.write('uvw = (uvw * 0.5 + 0.5);') + frag.write('if(any(notEqual(uvw, clamp(uvw, 0.0, 1.0)))) return;') + frag.write('vec3 writecoords = floor(uvw * voxelgiResolution);') + frag.write_attrib('vec3 N = normalize(voxnormal);') + frag.write('vec3 aniso_direction = N;') + frag.write('uvec3 face_offsets = uvec3(') + frag.write(' aniso_direction.x > 0 ? 0 : 1,') + frag.write(' aniso_direction.y > 0 ? 2 : 3,') + frag.write(' aniso_direction.z > 0 ? 4 : 5') + frag.write(' ) * voxelgiResolution;') + frag.write('vec3 direction_weights = abs(N);') - for bo in mat_users[mat]: - if mat.lnx_custom_material == '': - # Morph Targets - if lnx.utils.export_morph_targets(bo): - global_elems.append({'name': 'morph', 'data': 'short2norm'}) - # GPU Skinning - if lnx.utils.export_bone_data(bo): - global_elems.append({'name': 'bone', 'data': 'short4norm'}) - global_elems.append({'name': 'weight', 'data': 'short4norm'}) + frag.write('vec3 clipmap_pixel = uvw * voxelgiResolution;') + frag.write('vec3 clipmap_uvw_center = (clipmap_pixel + 0.5) / voxelgiResolution;') + frag.write('vec3 voxel_center = clipmap_uvw_center * 2.0 - 1.0;') + frag.write('float voxel_size = float(clipmaps[int(clipmapLevel * 10)]);') + frag.write('voxel_center *= voxel_size;') + frag.write('voxel_center *= voxelgiResolution.x;') + frag.write('voxel_center += vec3(') + frag.write(' clipmaps[clipmapLevel * 10 + 4],') + frag.write(' clipmaps[clipmapLevel * 10 + 5],') + frag.write(' clipmaps[clipmapLevel * 10 + 6]);') - # Instancing - inst = bo.lnx_instanced - if inst != 'Off' or mat.lnx_particle_flag: - instancing_usage[0] = True - mat_state.uses_instancing = True + frag.write('vec3 voxel_aabb[2];') + frag.write('voxel_aabb[0] = voxel_center;') + frag.write('voxel_aabb[1] = vec3(voxel_size);') + frag.write('vec3 triangle_aabb[2];') + frag.write('AABBfromMinMax(triangle_aabb, aabb_min, aabb_max);') + frag.write('if (!IntersectAABB(voxel_aabb, triangle_aabb))') + frag.write(' return;') - if mat.lnx_custom_material == '': - global_elems.append({'name': 'ipos', 'data': 'float3'}) - if 'Rot' in inst: - global_elems.append({'name': 'irot', 'data': 'float3'}) - #HACK: checking `mat.arm_particle_flag` to force appending 'iscl' to the particle's vertex shader - if 'Scale' in inst or mat.arm_particle_flag: - global_elems.append({'name': 'iscl', 'data': 'float3'}) + frag.write('if (direction_weights.x > 0.0) {') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, 0)), uint(direction_weights.x * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x)), uint(1));') + frag.write('}') - elif inst == 'Off': - # Ignore children of instanced objects, they are instanced even when set to 'Off' - instancing_usage[1] = bo.parent is None or bo.parent.lnx_instanced == 'Off' + frag.write('if (direction_weights.y > 0.0) {') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, 0)), uint(direction_weights.y * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x)), uint(1));') + frag.write('}') - if instancing_usage[0] and instancing_usage[1]: - # Display a warning for invalid instancing configurations - # See https://github.com/leenkx3d/leenkx/issues/2072 - log.warn(f'Material "{mat.name}" has both instanced and not instanced objects, objects might flicker!') + frag.write('if (direction_weights.z > 0.0) {') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, 0)), uint(direction_weights.z * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x)), uint(1));') + frag.write('}') - if mat.lnx_custom_material == '': - mat_state.data.global_elems = global_elems + return con_voxel From 99806b8069ed04b24856f2594a4499f19f991226 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 21 May 2025 22:51:16 +0000 Subject: [PATCH 072/136] revert e98bfb125d714b1e81b17d7d0a90605800f72362 revert Update leenkx/blender/lnx/material/make_shader.py --- leenkx/blender/lnx/material/make_shader.py | 892 ++++----------------- 1 file changed, 176 insertions(+), 716 deletions(-) diff --git a/leenkx/blender/lnx/material/make_shader.py b/leenkx/blender/lnx/material/make_shader.py index f7755fc..89f4fe9 100644 --- a/leenkx/blender/lnx/material/make_shader.py +++ b/leenkx/blender/lnx/material/make_shader.py @@ -1,766 +1,226 @@ -""" -Copyright (c) 2024 Turánszki János +import os +import subprocess +from typing import Dict, List, Tuple -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -""" import bpy +from bpy.types import Material +from bpy.types import Object -import lnx.utils +import lnx.api import lnx.assets as assets +import lnx.exporter +import lnx.log as log import lnx.material.cycles as cycles +import lnx.material.make_decal as make_decal +import lnx.material.make_depth as make_depth +import lnx.material.make_mesh as make_mesh +import lnx.material.make_overlay as make_overlay +import lnx.material.make_transluc as make_transluc +import lnx.material.make_refract as make_refract +import lnx.material.make_voxel as make_voxel import lnx.material.mat_state as mat_state import lnx.material.mat_utils as mat_utils -import lnx.material.make_particle as make_particle -import lnx.make_state as state +from lnx.material.shader import Shader, ShaderContext, ShaderData +import lnx.utils if lnx.is_reload(__name__): - lnx.utils = lnx.reload_module(lnx.utils) + lnx.api = lnx.reload_module(lnx.api) assets = lnx.reload_module(assets) + lnx.exporter = lnx.reload_module(lnx.exporter) + log = lnx.reload_module(log) + cycles = lnx.reload_module(cycles) + make_decal = lnx.reload_module(make_decal) + make_depth = lnx.reload_module(make_depth) + make_mesh = lnx.reload_module(make_mesh) + make_overlay = lnx.reload_module(make_overlay) + make_transluc = lnx.reload_module(make_transluc) + make_voxel = lnx.reload_module(make_voxel) mat_state = lnx.reload_module(mat_state) + mat_utils = lnx.reload_module(mat_utils) + lnx.material.shader = lnx.reload_module(lnx.material.shader) + from lnx.material.shader import Shader, ShaderContext, ShaderData + lnx.utils = lnx.reload_module(lnx.utils) else: lnx.enable_reload(__name__) -def make(context_id): - rpdat = lnx.utils.get_rp() - if rpdat.rp_voxels == 'Voxel GI': - con = make_gi(context_id) - else: - con = make_ao(context_id) - - assets.vs_equal(con, assets.shader_cons['voxel_vert']) - assets.fs_equal(con, assets.shader_cons['voxel_frag']) - assets.gs_equal(con, assets.shader_cons['voxel_geom']) - - return con - -def make_gi(context_id): - con_voxel = mat_state.data.add_context({ 'name': context_id, 'depth_write': False, 'compare_mode': 'always', 'cull_mode': 'none', 'color_write_red': False, 'color_write_green': False, 'color_write_blue': False, 'color_write_alpha': False, 'conservative_raster': True }) - wrd = bpy.data.worlds['Lnx'] - - vert = con_voxel.make_vert() - frag = con_voxel.make_frag() - geom = con_voxel.make_geom() - tesc = None - tese = None - geom.ins = vert.outs - frag.ins = geom.outs - - vert.add_include('compiled.inc') - geom.add_include('compiled.inc') - frag.add_include('compiled.inc') - frag.add_include('std/math.glsl') - frag.add_include('std/imageatomic.glsl') - frag.add_include('std/gbuffer.glsl') - frag.add_include('std/brdf.glsl') - frag.add_include('std/aabb.glsl') - - rpdat = lnx.utils.get_rp() - frag.add_uniform('layout(r32ui) uimage3D voxels') - - frag.write('vec3 n;') - frag.write('vec3 wposition;') - frag.write('vec3 basecol;') - frag.write('float roughness;') # - frag.write('float metallic;') # - frag.write('float occlusion;') # - frag.write('float specular;') # - frag.write('vec3 emissionCol = vec3(0.0);') - blend = mat_state.material.lnx_blending - parse_opacity = blend or mat_utils.is_transluc(mat_state.material) - if parse_opacity: - frag.write('float opacity;') - frag.write('float ior;') - else: - frag.write('float opacity = 1.0;') - - cycles.parse(mat_state.nodes, con_voxel, vert, frag, geom, tesc, tese, parse_opacity=parse_opacity, parse_displacement=False, basecol_only=True) - - # Voxelized particles - particle = mat_state.material.lnx_particle_flag - if particle and rpdat.lnx_particles == 'On': - # make_particle.write(vert, particle_info=cycles.particle_info) - frag.write_pre = True - frag.write('const float p_index = 0;') - frag.write('const float p_age = 0;') - frag.write('const float p_lifetime = 0;') - frag.write('const vec3 p_location = vec3(0);') - frag.write('const float p_size = 0;') - frag.write('const vec3 p_velocity = vec3(0);') - frag.write('const vec3 p_angular_velocity = vec3(0);') - frag.write_pre = False - - export_mpos = frag.contains('mposition') and not frag.contains('vec3 mposition') - if export_mpos: - vert.add_out('vec3 mpositionGeom') - vert.write_pre = True - vert.write('mpositionGeom = pos.xyz;') - vert.write_pre = False - - export_bpos = frag.contains('bposition') and not frag.contains('vec3 bposition') - if export_bpos: - vert.add_out('vec3 bpositionGeom') - vert.add_uniform('vec3 dim', link='_dim') - vert.add_uniform('vec3 hdim', link='_halfDim') - vert.write_pre = True - vert.write('bpositionGeom = (pos.xyz + hdim) / dim;') - vert.write_pre = False - - vert.add_uniform('mat4 W', '_worldMatrix') - vert.add_uniform('mat3 N', '_normalMatrix') - vert.add_out('vec3 voxpositionGeom') - vert.add_out('vec3 voxnormalGeom') - - if con_voxel.is_elem('col'): - vert.add_out('vec3 vcolorGeom') - vert.write('vcolorGeom = col.rgb;') - - if con_voxel.is_elem('tex'): - vert.add_out('vec2 texCoordGeom') - vert.write('texCoordGeom = tex;') - - vert.write('voxpositionGeom = vec3(W * vec4(pos.xyz, 1.0));') - vert.write('voxnormalGeom = normalize(N * vec3(nor.xy, pos.w));') - - geom.add_out('vec4 voxposition[3]') - geom.add_out('vec3 P') - geom.add_out('vec3 voxnormal') - geom.add_out('vec4 lightPosition') - geom.add_out('vec4 wvpposition') - geom.add_out('vec3 eyeDir') - geom.add_out('vec3 aabb_min') - geom.add_out('vec3 aabb_max') - - if con_voxel.is_elem('col'): - geom.add_out('vec3 vcolor') - if con_voxel.is_elem('tex'): - geom.add_out('vec2 texCoord') - if export_mpos: - geom.add_out('vec3 mposition') - if export_bpos: - geom.add_out('vec3 bposition') - - geom.add_uniform('float clipmaps[voxelgiClipmapCount * 10]', '_clipmaps') - geom.add_uniform('int clipmapLevel', '_clipmapLevel') - - geom.write('vec3 facenormal = abs(voxnormalGeom[0] + voxnormalGeom[1] + voxnormalGeom[2]);') - geom.write('uint maxi = facenormal[1] > facenormal[0] ? 1 : 0;') - geom.write('maxi = facenormal[2] > facenormal[maxi] ? 2 : maxi;') - - geom.write('aabb_min = min(voxpositionGeom[0].xyz, min(voxpositionGeom[1].xyz, voxpositionGeom[2].xyz));') - geom.write('aabb_max = max(voxpositionGeom[0].xyz, max(voxpositionGeom[1].xyz, voxpositionGeom[2].xyz));') - - geom.write('for (uint i = 0; i < 3; ++i) {') - geom.write(' voxposition[i].xyz = (voxpositionGeom[i] - vec3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)])) / (float(clipmaps[int(clipmapLevel * 10)]));') - geom.write(' if (maxi == 0)') - geom.write(' {') - geom.write(' voxposition[i].xyz = voxposition[i].zyx;') - geom.write(' }') - geom.write(' else if (maxi == 1)') - geom.write(' {') - geom.write(' voxposition[i].xyz = voxposition[i].xzy;') - geom.write(' }') - geom.write('}') - - geom.write('vec2 side0N = normalize(voxposition[1].xy - voxposition[0].xy);') - geom.write('vec2 side1N = normalize(voxposition[2].xy - voxposition[1].xy);') - geom.write('vec2 side2N = normalize(voxposition[0].xy - voxposition[2].xy);') - geom.write('voxposition[0].xy += normalize(side2N - side0N);') - geom.write('voxposition[1].xy += normalize(side0N - side1N);') - geom.write('voxposition[2].xy += normalize(side1N - side2N);') - - geom.write('for (uint i = 0; i < 3; ++i) {') - geom.write(' voxposition[i].xy /= voxelgiResolution.xy;') - geom.write(' voxposition[i].zw = vec2(1.0);') - geom.write(' P = voxpositionGeom[i];') - geom.write(' voxnormal = voxnormalGeom[i];') - if con_voxel.is_elem('col'): - geom.write('vcolor = vcolorGeom[i];') - if con_voxel.is_elem('tex'): - geom.write('texCoord = texCoordGeom[i];') - if export_mpos: - geom.write('mposition = mpositionGeom[i];') - if export_bpos: - geom.write('bposition = bpositionGeom[i];') - geom.write(' eyeDir = eyeDirGeom[i];') - if '_Sun' in wrd.world_defs and not '_CSM' in wrd.world_defs and '_ShadowMap' in wrd.world_defs: - geom.write(' lightPosition = lightPositionGeom[i];') - if '_Clusters' in wrd.world_defs and '_ShadowMap' in wrd.world_defs: - geom.write(' wvpposition = wvppositionGeom[i];') - geom.write(' gl_Position = voxposition[i];') - geom.write(' EmitVertex();') - geom.write('}') - geom.write('EndPrimitive();') - - frag.add_uniform('float clipmaps[voxelgiClipmapCount * 10]', '_clipmaps') - frag.add_uniform('int clipmapLevel', '_clipmapLevel') - - frag.write('vec3 uvw = (P - vec3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)])) / (float(clipmaps[int(clipmapLevel * 10)]) * voxelgiResolution);') - frag.write('uvw = (uvw * 0.5 + 0.5);') - - frag.write('if(any(notEqual(uvw, clamp(uvw, 0.0, 1.0)))) return;') - frag.write('vec3 writecoords = floor(uvw * voxelgiResolution);') - frag.write_attrib('vec3 N = normalize(voxnormal);') - frag.write('vec3 aniso_direction = N;') - frag.write('uvec3 face_offsets = uvec3(') - frag.write(' aniso_direction.x > 0 ? 0 : 1,') - frag.write(' aniso_direction.y > 0 ? 2 : 3,') - frag.write(' aniso_direction.z > 0 ? 4 : 5') - frag.write(' ) * voxelgiResolution;') - frag.write('vec3 direction_weights = abs(N);') - - frag.write('vec3 clipmap_pixel = uvw * voxelgiResolution;') - frag.write('vec3 clipmap_uvw_center = (clipmap_pixel + 0.5) / voxelgiResolution;') - frag.write('vec3 voxel_center = clipmap_uvw_center * 2.0 - 1.0;') - frag.write('float voxel_size = float(clipmaps[int(clipmapLevel * 10)]);') - frag.write('voxel_center *= voxel_size;') - frag.write('voxel_center *= voxelgiResolution.x;') - frag.write('voxel_center += vec3(') - frag.write(' clipmaps[clipmapLevel * 10 + 4],') - frag.write(' clipmaps[clipmapLevel * 10 + 5],') - frag.write(' clipmaps[clipmapLevel * 10 + 6]);') - - frag.write('vec3 voxel_aabb[2];') - frag.write('voxel_aabb[0] = voxel_center;') - frag.write('voxel_aabb[1] = vec3(voxel_size);') - frag.write('vec3 triangle_aabb[2];') - frag.write('AABBfromMinMax(triangle_aabb, aabb_min, aabb_max);') - frag.write('if (!IntersectAABB(voxel_aabb, triangle_aabb))') - frag.write(' return;') - - frag.write('vec3 albedo = surfaceAlbedo(basecol, metallic);') - frag.write('vec3 f0 = surfaceF0(basecol, metallic);') - - vert.add_uniform('vec3 eye', '_cameraPosition') - vert.add_out('vec3 eyeDirGeom') - vert.write('eyeDirGeom = eye - voxpositionGeom;') - frag.write_attrib('vec3 vVec = normalize(eyeDir);') - frag.write_attrib('float dotNV = max(dot(N, vVec), 0.0);') - - if '_Brdf' in wrd.world_defs: - frag.add_uniform('sampler2D senvmapBrdf', link='$brdf.png') - frag.write('vec2 envBRDF = texelFetch(senvmapBrdf, ivec2(vec2(dotNV, 1.0 - roughness) * 256.0), 0).xy;') - - if '_Irr' in wrd.world_defs: - frag.add_include('std/shirr.glsl') - frag.add_uniform('vec4 shirr[7]', link='_envmapIrradiance') - frag.write('vec3 envl = shIrradiance(N, shirr);') - if '_EnvTex' in wrd.world_defs: - frag.write('envl /= PI;') - else: - frag.write('vec3 envl = vec3(0.0);') - - if '_Rad' in wrd.world_defs: - frag.add_uniform('sampler2D senvmapRadiance', link='_envmapRadiance') - frag.add_uniform('int envmapNumMipmaps', link='_envmapNumMipmaps') - frag.write('vec3 reflectionWorld = reflect(-vVec, N);') - frag.write('float lod = getMipFromRoughness(roughness, envmapNumMipmaps);') - frag.write('vec3 prefilteredColor = textureLod(senvmapRadiance, envMapEquirect(reflectionWorld), lod).rgb;') - - if '_EnvLDR' in wrd.world_defs: - frag.write('envl = pow(envl, vec3(2.2));') - if '_Rad' in wrd.world_defs: - frag.write('prefilteredColor = pow(prefilteredColor, vec3(2.2));') - - frag.write('envl *= albedo;') - - if '_Brdf' in wrd.world_defs: - frag.write('envl.rgb *= 1.0 - (f0 * envBRDF.x + envBRDF.y);') - if '_Rad' in wrd.world_defs: - frag.write('envl += prefilteredColor * (f0 * envBRDF.x + envBRDF.y);') - elif '_EnvCol' in wrd.world_defs: - frag.add_uniform('vec3 backgroundCol', link='_backgroundCol') - frag.write('envl += backgroundCol * (f0 * envBRDF.x + envBRDF.y);') - - frag.add_uniform('float envmapStrength', link='_envmapStrength') - frag.write('envl *= envmapStrength * occlusion;') - - frag.add_include('std/light.glsl') - is_shadows = '_ShadowMap' in wrd.world_defs - is_shadows_atlas = '_ShadowMapAtlas' in wrd.world_defs - is_single_atlas = is_shadows_atlas and '_SingleAtlas' in wrd.world_defs - shadowmap_sun = 'shadowMap' - shadowmap_sun_tr = 'shadowMapTransparent' - if is_shadows_atlas: - shadowmap_sun = 'shadowMapAtlasSun' if not is_single_atlas else 'shadowMapAtlas' - shadowmap_sun_tr = 'shadowMapAtlasSunTransparent' if not is_single_atlas else 'shadowMapAtlasTransparent' - frag.add_uniform('vec2 smSizeUniform', '_shadowMapSize', included=True) - - frag.write('vec3 direct = vec3(0.0);') - - if '_Sun' in wrd.world_defs: - frag.add_uniform('vec3 sunCol', '_sunColor') - frag.add_uniform('vec3 sunDir', '_sunDirection') - frag.write('vec3 svisibility = vec3(1.0);') - frag.write('vec3 sh = normalize(vVec + sunDir);') - frag.write('float sdotNL = dot(N, sunDir);') - frag.write('float sdotNH = dot(N, sh);') - frag.write('float sdotVH = dot(vVec, sh);') - if is_shadows: - frag.add_uniform('bool receiveShadow') - frag.add_uniform(f'sampler2DShadow {shadowmap_sun}', top=True) - frag.add_uniform(f'sampler2D {shadowmap_sun_tr}', top=True) - frag.add_uniform('float shadowsBias', '_sunShadowsBias') - frag.write('if (receiveShadow) {') - if '_CSM' in wrd.world_defs: - frag.add_include('std/shadows.glsl') - frag.add_uniform('vec4 casData[shadowmapCascades * 4 + 4]', '_cascadeData', included=True) - frag.add_uniform('vec3 eye', '_cameraPosition') - if parse_opacity: - frag.write(f'svisibility = shadowTestCascade({shadowmap_sun},') - frag.write(f'{shadowmap_sun_tr},') - frag.write('eye, P + N * shadowsBias * 10, shadowsBias, true);') - else: - frag.write(f'svisibility = shadowTestCascade({shadowmap_sun},') - frag.write(f'{shadowmap_sun_tr},') - frag.write('eye, P + N * shadowsBias * 10, shadowsBias, false);') - else: - vert.add_out('vec4 lightPositionGeom') - vert.add_uniform('mat4 LWVP', '_biasLightWorldViewProjectionMatrixSun') - vert.write('lightPositionGeom = LWVP * vec4(pos.xyz, 1.0);') - frag.write('vec3 lPos = lightPosition.xyz / lightPosition.w;') - frag.write('const vec2 smSize = shadowmapSize;') - if parse_opacity: - frag.write(f'svisibility = PCF({shadowmap_sun},') - frag.write(f'{shadowmap_sun_tr},') - frag.write('lPos.xy, lPos.z - shadowsBias, smSize, true);') - else: - frag.write(f'svisibility = PCF({shadowmap_sun},') - frag.write(f'{shadowmap_sun_tr},') - frag.write('lPos.xy, lPos.z - shadowsBias, smSize, false);') - frag.write('}') - frag.write('direct += (lambertDiffuseBRDF(albedo, sdotNL) + specularBRDF(f0, roughness, sdotNL, sdotNH, dotNV, sdotVH) * specular) * sunCol * svisibility;') - - if '_SinglePoint' in wrd.world_defs: - frag.add_uniform('vec3 pointPos', link='_pointPosition') - frag.add_uniform('vec3 pointCol', link='_pointColor') - if '_Spot' in wrd.world_defs: - frag.add_uniform('vec3 spotDir', link='_spotDirection') - frag.add_uniform('vec3 spotRight', link='_spotRight') - frag.add_uniform('vec4 spotData', link='_spotData') - if is_shadows: - frag.add_uniform('bool receiveShadow') - frag.add_uniform('float pointBias', link='_pointShadowsBias') - if '_Spot' in wrd.world_defs: - # Skip world matrix, already in world-space - frag.add_uniform('mat4 LWVPSpot[1]', link='_biasLightViewProjectionMatrixSpotArray', included=True) - frag.add_uniform('sampler2DShadow shadowMapSpot[1]', included=True) - frag.add_uniform('sampler2D shadowMapSpotTransparent[1]', included=True) - else: - frag.add_uniform('vec2 lightProj', link='_lightPlaneProj', included=True) - frag.add_uniform('samplerCubeShadow shadowMapPoint[1]', included=True) - frag.add_uniform('samplerCube shadowMapPointTransparent[1]', included=True) - frag.write('direct += sampleLightVoxels(') - frag.write(' P, N, vVec, dotNV, pointPos, pointCol, albedo, roughness, specular, f0') - if is_shadows: - if parse_opacity: - frag.write(', 0, pointBias, receiveShadow, opacity != 1.0') - else: - frag.write(', 0, pointBias, receiveShadow, false') - if '_Spot' in wrd.world_defs: - frag.write(', true, spotData.x, spotData.y, spotDir, spotData.zw, spotRight') - frag.write(');') - - if '_Clusters' in wrd.world_defs: - frag.add_include_front('std/clusters.glsl') - frag.add_uniform('vec2 cameraProj', link='_cameraPlaneProj') - frag.add_uniform('vec2 cameraPlane', link='_cameraPlane') - frag.add_uniform('vec4 lightsArray[maxLights * 3]', link='_lightsArray') - frag.add_uniform('sampler2D clustersData', link='_clustersData') - if is_shadows: - frag.add_uniform('bool receiveShadow') - frag.add_uniform('vec2 lightProj', link='_lightPlaneProj', included=True) - if is_shadows_atlas: - if not is_single_atlas: - frag.add_uniform('sampler2DShadow shadowMapAtlasPoint', included=True) - frag.add_uniform('sampler2D shadowMapAtlasPointTransparent', included=True) - else: - frag.add_uniform('sampler2DShadow shadowMapAtlas', top=True) - frag.add_uniform('sampler2D shadowMapAtlasTransparent', top=True) - frag.add_uniform('vec4 pointLightDataArray[maxLightsCluster]', link='_pointLightsAtlasArray', included=True) - else: - frag.add_uniform('samplerCubeShadow shadowMapPoint[4]', included=True) - frag.add_uniform('samplerCube shadowMapPointTransparent[4]', included=True) - - vert.add_out('vec4 wvppositionGeom') - vert.add_uniform('mat4 VP', '_viewProjectionMatrix') - vert.write('wvppositionGeom = VP * vec4(voxpositionGeom, 1.0);') - # wvpposition.z / wvpposition.w - frag.write('float viewz = linearize((wvpposition.z / wvpposition.w) * 0.5 + 0.5, cameraProj);') - frag.write('int clusterI = getClusterI((wvpposition.xy / wvpposition.w) * 0.5 + 0.5, viewz, cameraPlane);') - frag.write('int numLights = int(texelFetch(clustersData, ivec2(clusterI, 0), 0).r * 255);') - - frag.write('#ifdef HLSL') - frag.write('viewz += texture(clustersData, vec2(0.0)).r * 1e-9;') # TODO: krafix bug, needs to generate sampler - frag.write('#endif') - - if '_Spot' in wrd.world_defs: - frag.add_uniform('vec4 lightsArraySpot[maxLights * 2]', link='_lightsArraySpot') - frag.write('int numSpots = int(texelFetch(clustersData, ivec2(clusterI, 1 + maxLightsCluster), 0).r * 255);') - frag.write('int numPoints = numLights - numSpots;') - if is_shadows: - if is_shadows_atlas: - if not is_single_atlas: - frag.add_uniform('sampler2DShadow shadowMapAtlasSpot', included=True) - frag.add_uniform('sampler2D shadowMapAtlasSpotTransparent', included=True) - else: - frag.add_uniform('sampler2DShadow shadowMapAtlas', top=True) - frag.add_uniform('sampler2D shadowMapAtlasTransparent', top=True) - else: - frag.add_uniform('sampler2DShadow shadowMapSpot[4]', included=True) - frag.add_uniform('sampler2D shadowMapSpotTransparent[4]', included=True) - frag.add_uniform('mat4 LWVPSpotArray[maxLightsCluster]', link='_biasLightWorldViewProjectionMatrixSpotArray', included=True) - - frag.write('for (int i = 0; i < min(numLights, maxLightsCluster); i++) {') - frag.write('int li = int(texelFetch(clustersData, ivec2(clusterI, i + 1), 0).r * 255);') - frag.write('direct += sampleLightVoxels(') - frag.write(' P,') - frag.write(' N,') - frag.write(' vVec,') - frag.write(' dotNV,') - frag.write(' lightsArray[li * 3].xyz,') # lp - frag.write(' lightsArray[li * 3 + 1].xyz,') # lightCol - frag.write(' albedo,') - frag.write(' roughness,') - frag.write(' specular,') - frag.write(' f0') - - if is_shadows: - if parse_opacity: - frag.write('\t, li, lightsArray[li * 3 + 2].x, lightsArray[li * 3 + 2].z != 0.0, opacity != 1.0') # bias - else: - frag.write('\t, li, lightsArray[li * 3 + 2].x, lightsArray[li * 3 + 2].z != 0.0, false') # bias - if '_Spot' in wrd.world_defs: - frag.write('\t, lightsArray[li * 3 + 2].y != 0.0') - frag.write('\t, lightsArray[li * 3 + 2].y') # spot size (cutoff) - frag.write('\t, lightsArraySpot[li * 2].w') # spot blend (exponent) - frag.write('\t, lightsArraySpot[li * 2].xyz') # spotDir - frag.write('\t, vec2(lightsArray[li * 3].w, lightsArray[li * 3 + 1].w)') # scale - frag.write('\t, lightsArraySpot[li * 2 + 1].xyz') # right - frag.write(' );') - frag.write('}') - - frag.write('if (direction_weights.x > 0.0) {') - frag.write(' vec4 basecol_direction = vec4(basecol, opacity) * direction_weights.x;') - frag.write(' vec3 emission_direction = emissionCol * direction_weights.x;') - frag.write(' vec2 encoded_normal = encode_oct(N) * 0.5 + 0.5;') - frag.write(' vec2 normal_direction = encoded_normal * direction_weights.x;') - frag.write(' vec3 envl_direction = envl * direction_weights.x;') - frag.write(' vec3 light_direction = direct * direction_weights.x;') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, 0)), uint(basecol_direction.r * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x)), uint(basecol_direction.g * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 2)), uint(basecol_direction.b * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 3)), uint(basecol_direction.a * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 4)), uint(emission_direction.r * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 5)), uint(emission_direction.g * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 6)), uint(emission_direction.b * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 7)), uint(normal_direction.r * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 8)), uint(normal_direction.g * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 9)), uint(envl_direction.r * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 10)), uint(envl_direction.g * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 11)), uint(envl_direction.b * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 12)), uint(light_direction.r * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 13)), uint(light_direction.g * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 14)), uint(light_direction.b * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 15)), uint(1));') - frag.write('}') - - frag.write('if (direction_weights.y > 0.0) {') - frag.write(' vec4 basecol_direction = vec4(basecol, opacity) * direction_weights.y;') - frag.write(' vec3 emission_direction = emissionCol * direction_weights.y;') - frag.write(' vec2 encoded_normal = encode_oct(N) * 0.5 + 0.5;') - frag.write(' vec2 normal_direction = encoded_normal * direction_weights.y;') - frag.write(' vec3 envl_direction = envl * direction_weights.y;') - frag.write(' vec3 light_direction = direct * direction_weights.y;') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, 0)), uint(basecol_direction.r * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x)), uint(basecol_direction.g * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 2)), uint(basecol_direction.b * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 3)), uint(basecol_direction.a * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 4)), uint(emission_direction.r * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 5)), uint(emission_direction.g * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 6)), uint(emission_direction.b * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 7)), uint(normal_direction.r * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 8)), uint(normal_direction.g * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 9)), uint(envl_direction.r * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 10)), uint(envl_direction.g * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 11)), uint(envl_direction.b * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 12)), uint(light_direction.r * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 13)), uint(light_direction.g * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 14)), uint(light_direction.b * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 15)), uint(1));') - frag.write('}') - - frag.write('if (direction_weights.z > 0.0) {') - frag.write(' vec4 basecol_direction = vec4(basecol, opacity) * direction_weights.z;') - frag.write(' vec3 emission_direction = emissionCol * direction_weights.z;') - frag.write(' vec2 encoded_normal = encode_oct(N) * 0.5 + 0.5;') - frag.write(' vec2 normal_direction = encoded_normal * direction_weights.z;') - frag.write(' vec3 envl_direction = envl * direction_weights.z;') - frag.write(' vec3 light_direction = direct * direction_weights.z;') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, 0)), uint(basecol_direction.r * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x)), uint(basecol_direction.g * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 2)), uint(basecol_direction.b * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 3)), uint(basecol_direction.a * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 4)), uint(emission_direction.r * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 5)), uint(emission_direction.g * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 6)), uint(emission_direction.b * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 7)), uint(normal_direction.r * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 8)), uint(normal_direction.g * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 9)), uint(envl_direction.r * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 10)), uint(envl_direction.g * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 11)), uint(envl_direction.b * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 12)), uint(light_direction.r * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 13)), uint(light_direction.g * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 14)), uint(light_direction.b * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 15)), uint(1));') - frag.write('}') - - return con_voxel +rpass_hook = None -def make_ao(context_id): - con_voxel = mat_state.data.add_context({ 'name': context_id, 'depth_write': False, 'compare_mode': 'always', 'cull_mode': 'none', 'color_writes_red': [False], 'color_writes_green': [False], 'color_writes_blue': [False], 'color_writes_alpha': [False], 'conservative_raster': False }) +def build(material: Material, mat_users: Dict[Material, List[Object]], mat_lnxusers) -> Tuple: + mat_state.mat_users = mat_users + mat_state.mat_lnxusers = mat_lnxusers + mat_state.material = material + mat_state.nodes = material.node_tree.nodes + mat_state.data = ShaderData(material) + mat_state.output_node = cycles.node_by_type(mat_state.nodes, 'OUTPUT_MATERIAL') + if mat_state.output_node is None: + # Place empty material output to keep compiler happy.. + mat_state.output_node = mat_state.nodes.new('ShaderNodeOutputMaterial') + wrd = bpy.data.worlds['Lnx'] rpdat = lnx.utils.get_rp() + rpasses = mat_utils.get_rpasses(material) + matname = lnx.utils.safesrc(lnx.utils.asset_name(material)) + rel_path = lnx.utils.build_dir() + '/compiled/Shaders/' + full_path = lnx.utils.get_fp() + '/' + rel_path + if not os.path.exists(full_path): + os.makedirs(full_path) - vert = con_voxel.make_vert() - frag = con_voxel.make_frag() - geom = con_voxel.make_geom() - tesc = None - tese = None + make_instancing_and_skinning(material, mat_users) - geom.ins = vert.outs - frag.ins = geom.outs + bind_constants = dict() + bind_textures = dict() - frag.add_include('compiled.inc') - geom.add_include('compiled.inc') - frag.add_include('std/math.glsl') - frag.add_include('std/imageatomic.glsl') - frag.add_include('std/aabb.glsl') - frag.write_header('#extension GL_ARB_shader_image_load_store : enable') + for rp in rpasses: + car = [] + bind_constants[rp] = car + mat_state.bind_constants = car + tar = [] + bind_textures[rp] = tar + mat_state.bind_textures = tar - vert.add_include('compiled.inc') - vert.add_uniform('mat4 W', '_worldMatrix') - vert.add_uniform('mat3 N', '_normalMatrix') + con = None - geom.add_uniform('float clipmaps[voxelgiClipmapCount * 10]', '_clipmaps') - geom.add_uniform('int clipmapLevel', '_clipmapLevel') + if rpdat.rp_driver != 'Leenkx' and lnx.api.drivers[rpdat.rp_driver]['make_rpass'] is not None: + con = lnx.api.drivers[rpdat.rp_driver]['make_rpass'](rp) - frag.add_uniform('float clipmaps[voxelgiClipmapCount * 10]', '_clipmaps') - frag.add_uniform('int clipmapLevel', '_clipmapLevel') + if con is not None: + pass - """ - if lnx.utils.get_gapi() == 'direct3d11': - for e in con_voxel.data['vertex_elements']: - if e['name'] == 'nor': - con_voxel.data['vertex_elements'].remove(e) - break + elif rp == 'mesh': + con = make_mesh.make(rp, rpasses) - vert.write('uniform float4x4 W;') - vert.write('uniform float3x3 N;') - vert.write('struct SPIRV_Cross_Input {') - vert.write(' float4 pos : TEXCOORD0;') - vert.write(' float3 nor : NORMAL;') - vert.write('};') - vert.write('struct SPIRV_Cross_Output {') - vert.write(' float4 svpos : SV_POSITION;') - vert.write(' float3 svnor : NORMAL;') - vert.write('};') - vert.write('SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input) {') - vert.write(' SPIRV_Cross_Output stage_output;') - vert.write(' stage_output.svpos.xyz = mul(float4(stage_input.pos.xyz, 1.0), W).xyz;') - vert.write(' stage_output.svpos.w = 1.0;') - vert.write(' stage_output.svnor.xyz = normalize(mul(float3(nor.xy, pos.w), N).xyz);') - vert.write(' return stage_output;') - vert.write('}') + elif rp == 'shadowmap': + con = make_depth.make(rp, rpasses, shadowmap=True) - geom.write('uniform float clipmaps[voxelgiClipmapCount * 10];') - geom.write('uniform int clipmapLevel;') - geom.write('struct SPIRV_Cross_Input {') - geom.write(' float4 svpos : SV_POSITION;') - geom.write(' float3 svnor : NORMAL;') - geom.write('};') - geom.write('struct SPIRV_Cross_Output {') - geom.write(' float3 wpos : TEXCOORD0;') - geom.write(' float3 wnor : NORMAL;') - geom.write('};') - geom.write('[maxvertexcount(3)]') - geom.write('void main(triangle SPIRV_Cross_Input stage_input[3], inout TriangleStream output) {') - geom.write(' float3 p1 = stage_input[1].svpos.xyz - stage_input[0].svpos.xyz;') - geom.write(' float3 p2 = stage_input[2].svpos.xyz - stage_input[0].svpos.xyz;') - geom.write(' float3 p = abs(cross(p1, p2));') - geom.write(' for (int i = 0; i < 3; ++i) {') - geom.write(' SPIRV_Cross_Output stage_output;') - geom.write(' stage_output.wpos = (stage_input[i].svpos.xyz + float3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)])) / (float(clipmaps[clipmapLevel * 10]) * voxelgiResolution);') - geom.write(' stage_output.wnor = stage_input[i].svnor.xyz;') - geom.write(' if (p.z > p.x && p.z > p.y) {') - geom.write(' stage_output.svpos = float4(stage_input[i].svpos.x, stage_input[i].svpos.y, 0.0, 1.0);') - geom.write(' }') - geom.write(' else if (p.x > p.y && p.x > p.z) {') - geom.write(' stage_output.svpos = float4(stage_input[i].svpos.y, stage_input[i].svpos.z, 0.0, 1.0);') - geom.write(' }') - geom.write(' else {') - geom.write(' stage_output.svpos = float4(stage_input[i].svpos.x, stage_input[i].svpos.z, 0.0, 1.0);') - geom.write(' }') - geom.write(' output.Append(stage_output);') - geom.write(' }') - geom.write('}') + elif rp == 'shadowmap_transparent': + con = make_depth.make(rp, rpasses, shadowmap=True, shadowmap_transparent=True) - frag.add_uniform('layout(r8) writeonly image3D voxels') - frag.write('RWTexture3D voxels;') - frag.write('uniform float clipmaps[voxelgiClipmapCount * 10];') - frag.write('uniform int clipmapLevel;') + elif rp == 'translucent': + con = make_transluc.make(rp) - frag.write('struct SPIRV_Cross_Input {') - frag.write(' float3 wpos : TEXCOORD0;') - frag.write(' float3 wnor : NORMAL;') - frag.write('};') - frag.write('struct SPIRV_Cross_Output { float4 FragColor : SV_TARGET0; };') - frag.write('void main(SPIRV_Cross_Input stage_input) {') - frag.write(' float3 uvw = (stage_input.wpos.xyz - float3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)])) / (float(clipmaps[int(clipmapLevel * 10)]) * voxelgiResolution);') - frag.write(' uvw = uvw * 0.5 + 0.5;') - frag.write(' if(any(!saturate(uvw))) return;') - frag.write(' uvw = floor(uvw * voxelgiResolution);') - frag.write(' uint3 face_offsets = uint3(') - frag.write(' stage_input.wnor.x > 0 ? 0 : 1,') - frag.write(' stage_input.wnor.y > 0 ? 2 : 3,') - frag.write(' stage_input.wnor.z > 0 ? 4 : 5') - frag.write(' ) * voxelgiResolution;') - frag.write(' float3 direction_weights = abs(stage_input.wnor);') + elif rp == 'refraction': + con = make_refract.make(rp) - frag.write(' if (direction_weights.x > 0.0) {') - frag.write(' float opac_direction = direction_weights.x;') - frag.write(' voxels[uvw + int3(face_offsets.x, 0, 0))] = float4(opac_direction);') - frag.write(' }') + elif rp == 'overlay': + con = make_overlay.make(rp) - frag.write(' if (direction_weights.y > 0.0) {') - frag.write(' float opac_direction = direction_weights.y;') - frag.write(' voxels[uvw + int3(face_offsets.y, 0, 0))] = float4(opac_direction);') - frag.write(' }') + elif rp == 'decal': + con = make_decal.make(rp) - frag.write(' if (direction_weights.z > 0.0) {') - frag.write(' float opac_direction = direction_weights.z;') - frag.write(' voxels[uvw + int3(face_offsets.z, 0, 0))] = float4(opac_direction);') - frag.write(' }') - frag.write('}') + elif rp == 'depth': + con = make_depth.make(rp, rpasses) + + elif rp == 'voxel': + con = make_voxel.make(rp) + + elif rpass_hook is not None: + con = rpass_hook(rp) + + write_shaders(rel_path, con, rp, matname) + + shader_data_name = matname + '_data' + + if wrd.lnx_single_data_file: + if 'shader_datas' not in lnx.exporter.current_output: + lnx.exporter.current_output['shader_datas'] = [] + lnx.exporter.current_output['shader_datas'].append(mat_state.data.get()['shader_datas'][0]) else: - """ - frag.add_uniform('layout(r32ui) uimage3D voxels') + lnx.utils.write_lnx(full_path + '/' + matname + '_data.lnx', mat_state.data.get()) + shader_data_path = lnx.utils.get_fp_build() + '/compiled/Shaders/' + shader_data_name + '.lnx' + assets.add_shader_data(shader_data_path) - vert.add_out('vec3 voxpositionGeom') - vert.add_out('vec3 voxnormalGeom') + return rpasses, mat_state.data, shader_data_name, bind_constants, bind_textures - vert.write('voxpositionGeom = vec3(W * vec4(pos.xyz, 1.0));') - vert.write('voxnormalGeom = normalize(N * vec3(nor.xy, pos.w));') - geom.add_out('vec4 voxposition[3]') - geom.add_out('vec3 P') - geom.add_out('vec3 voxnormal') - geom.add_out('vec3 aabb_min') - geom.add_out('vec3 aabb_max') +def write_shaders(rel_path: str, con: ShaderContext, rpass: str, matname: str) -> None: + keep_cache = mat_state.material.lnx_cached + write_shader(rel_path, con.vert, 'vert', rpass, matname, keep_cache=keep_cache) + write_shader(rel_path, con.frag, 'frag', rpass, matname, keep_cache=keep_cache) + write_shader(rel_path, con.geom, 'geom', rpass, matname, keep_cache=keep_cache) + write_shader(rel_path, con.tesc, 'tesc', rpass, matname, keep_cache=keep_cache) + write_shader(rel_path, con.tese, 'tese', rpass, matname, keep_cache=keep_cache) - geom.add_uniform('float clipmaps[voxelgiClipmapCount * 10]', '_clipmaps') - geom.add_uniform('int clipmapLevel', '_clipmapLevel') - geom.write('aabb_min = min(voxpositionGeom[0].xyz, min(voxpositionGeom[1].xyz, voxpositionGeom[2].xyz));') - geom.write('aabb_max = max(voxpositionGeom[0].xyz, max(voxpositionGeom[1].xyz, voxpositionGeom[2].xyz));') +def write_shader(rel_path: str, shader: Shader, ext: str, rpass: str, matname: str, keep_cache=True) -> None: + if shader is None or shader.is_linked: + return - geom.write('vec3 facenormal = abs(voxnormalGeom[0] + voxnormalGeom[1] + voxnormalGeom[2]);') - geom.write('uint maxi = facenormal[1] > facenormal[0] ? 1 : 0;') - geom.write('maxi = facenormal[2] > facenormal[maxi] ? 2 : maxi;') + # TODO: blend context + if rpass == 'mesh' and mat_state.material.lnx_blending: + rpass = 'blend' - geom.write('for (uint i = 0; i < 3; ++i) {') - geom.write(' voxposition[i].xyz = (voxpositionGeom[i] - vec3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)])) / (float(clipmaps[int(clipmapLevel * 10)]));') - geom.write(' if (maxi == 0)') - geom.write(' {') - geom.write(' voxposition[i].xyz = voxposition[i].zyx;') - geom.write(' }') - geom.write(' else if (maxi == 1)') - geom.write(' {') - geom.write(' voxposition[i].xyz = voxposition[i].xzy;') - geom.write(' }') - geom.write('}') + file_ext = '.glsl' + if shader.noprocessing: + # Use hlsl directly + hlsl_dir = lnx.utils.build_dir() + '/compiled/Hlsl/' + if not os.path.exists(hlsl_dir): + os.makedirs(hlsl_dir) + file_ext = '.hlsl' + rel_path = rel_path.replace('/compiled/Shaders/', '/compiled/Hlsl/') - geom.write('vec2 side0N = normalize(voxposition[1].xy - voxposition[0].xy);') - geom.write('vec2 side1N = normalize(voxposition[2].xy - voxposition[1].xy);') - geom.write('vec2 side2N = normalize(voxposition[0].xy - voxposition[2].xy);') - geom.write('voxposition[0].xy += normalize(side2N - side0N);') - geom.write('voxposition[1].xy += normalize(side0N - side1N);') - geom.write('voxposition[2].xy += normalize(side1N - side2N);') + shader_file = matname + '_' + rpass + '.' + ext + file_ext + shader_path = lnx.utils.get_fp() + '/' + rel_path + '/' + shader_file + assets.add_shader(shader_path) + if not os.path.isfile(shader_path) or not keep_cache: + with open(shader_path, 'w') as f: + f.write(shader.get()) - geom.write('for (uint i = 0; i < 3; ++i) {') - geom.write(' voxposition[i].xy /= voxelgiResolution.xy;') - geom.write(' voxposition[i].zw = vec2(1.0);') - geom.write(' P = voxpositionGeom[i];') - geom.write(' voxnormal = voxnormalGeom[i];') - geom.write(' gl_Position = voxposition[i];') - geom.write(' EmitVertex();') - geom.write('}') - geom.write('EndPrimitive();') + if shader.noprocessing: + cwd = os.getcwd() + os.chdir(lnx.utils.get_fp() + '/' + rel_path) + hlslbin_path = lnx.utils.get_sdk_path() + '/lib/leenkx_tools/hlslbin/hlslbin.exe' + prof = 'vs_5_0' if ext == 'vert' else 'ps_5_0' if ext == 'frag' else 'gs_5_0' + # noprocessing flag - gets renamed to .d3d11 + args = [hlslbin_path.replace('/', '\\').replace('\\\\', '\\'), shader_file, shader_file[:-4] + 'glsl', prof] + if ext == 'vert': + args.append('-i') + args.append('pos') + proc = subprocess.call(args) + os.chdir(cwd) - frag.add_uniform('float clipmaps[voxelgiClipmapCount * 10]', '_clipmaps') - frag.add_uniform('int clipmapLevel', '_clipmapLevel') - frag.write('vec3 uvw = (P - vec3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)])) / (float(clipmaps[int(clipmapLevel * 10)]) * voxelgiResolution);') - frag.write('uvw = (uvw * 0.5 + 0.5);') - frag.write('if(any(notEqual(uvw, clamp(uvw, 0.0, 1.0)))) return;') - frag.write('vec3 writecoords = floor(uvw * voxelgiResolution);') - frag.write_attrib('vec3 N = normalize(voxnormal);') - frag.write('vec3 aniso_direction = N;') - frag.write('uvec3 face_offsets = uvec3(') - frag.write(' aniso_direction.x > 0 ? 0 : 1,') - frag.write(' aniso_direction.y > 0 ? 2 : 3,') - frag.write(' aniso_direction.z > 0 ? 4 : 5') - frag.write(' ) * voxelgiResolution;') - frag.write('vec3 direction_weights = abs(N);') +def make_instancing_and_skinning(mat: Material, mat_users: Dict[Material, List[Object]]) -> None: + """Build material with instancing or skinning if enabled. + If the material is a custom material, only validation checks for instancing are performed.""" + global_elems = [] + if mat_users is not None and mat in mat_users: + # Whether there are both an instanced object and a not instanced object with this material + instancing_usage = [False, False] + mat_state.uses_instancing = False - frag.write('vec3 clipmap_pixel = uvw * voxelgiResolution;') - frag.write('vec3 clipmap_uvw_center = (clipmap_pixel + 0.5) / voxelgiResolution;') - frag.write('vec3 voxel_center = clipmap_uvw_center * 2.0 - 1.0;') - frag.write('float voxel_size = float(clipmaps[int(clipmapLevel * 10)]);') - frag.write('voxel_center *= voxel_size;') - frag.write('voxel_center *= voxelgiResolution.x;') - frag.write('voxel_center += vec3(') - frag.write(' clipmaps[clipmapLevel * 10 + 4],') - frag.write(' clipmaps[clipmapLevel * 10 + 5],') - frag.write(' clipmaps[clipmapLevel * 10 + 6]);') + for bo in mat_users[mat]: + if mat.lnx_custom_material == '': + # Morph Targets + if lnx.utils.export_morph_targets(bo): + global_elems.append({'name': 'morph', 'data': 'short2norm'}) + # GPU Skinning + if lnx.utils.export_bone_data(bo): + global_elems.append({'name': 'bone', 'data': 'short4norm'}) + global_elems.append({'name': 'weight', 'data': 'short4norm'}) - frag.write('vec3 voxel_aabb[2];') - frag.write('voxel_aabb[0] = voxel_center;') - frag.write('voxel_aabb[1] = vec3(voxel_size);') - frag.write('vec3 triangle_aabb[2];') - frag.write('AABBfromMinMax(triangle_aabb, aabb_min, aabb_max);') - frag.write('if (!IntersectAABB(voxel_aabb, triangle_aabb))') - frag.write(' return;') + # Instancing + inst = bo.lnx_instanced + if inst != 'Off' or mat.lnx_particle_flag: + instancing_usage[0] = True + mat_state.uses_instancing = True - frag.write('if (direction_weights.x > 0.0) {') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, 0)), uint(direction_weights.x * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x)), uint(1));') - frag.write('}') + if mat.lnx_custom_material == '': + global_elems.append({'name': 'ipos', 'data': 'float3'}) + if 'Rot' in inst: + global_elems.append({'name': 'irot', 'data': 'float3'}) + #HACK: checking `mat.arm_particle_flag` to force appending 'iscl' to the particle's vertex shader + if 'Scale' in inst or mat.arm_particle_flag: + global_elems.append({'name': 'iscl', 'data': 'float3'}) - frag.write('if (direction_weights.y > 0.0) {') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, 0)), uint(direction_weights.y * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x)), uint(1));') - frag.write('}') + elif inst == 'Off': + # Ignore children of instanced objects, they are instanced even when set to 'Off' + instancing_usage[1] = bo.parent is None or bo.parent.lnx_instanced == 'Off' - frag.write('if (direction_weights.z > 0.0) {') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, 0)), uint(direction_weights.z * 255));') - frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x)), uint(1));') - frag.write('}') + if instancing_usage[0] and instancing_usage[1]: + # Display a warning for invalid instancing configurations + # See https://github.com/leenkx3d/leenkx/issues/2072 + log.warn(f'Material "{mat.name}" has both instanced and not instanced objects, objects might flicker!') - return con_voxel + if mat.lnx_custom_material == '': + mat_state.data.global_elems = global_elems From c9dd46c5e3d031d84b168ced75a1e0bb7820c29b Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 21 May 2025 22:56:05 +0000 Subject: [PATCH 073/136] Update leenkx/blender/lnx/material/make_shader.py --- leenkx/blender/lnx/material/make_shader.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/leenkx/blender/lnx/material/make_shader.py b/leenkx/blender/lnx/material/make_shader.py index 89f4fe9..8fd4dda 100644 --- a/leenkx/blender/lnx/material/make_shader.py +++ b/leenkx/blender/lnx/material/make_shader.py @@ -209,8 +209,7 @@ def make_instancing_and_skinning(mat: Material, mat_users: Dict[Material, List[O global_elems.append({'name': 'ipos', 'data': 'float3'}) if 'Rot' in inst: global_elems.append({'name': 'irot', 'data': 'float3'}) - #HACK: checking `mat.arm_particle_flag` to force appending 'iscl' to the particle's vertex shader - if 'Scale' in inst or mat.arm_particle_flag: + if 'Scale' in inst: global_elems.append({'name': 'iscl', 'data': 'float3'}) elif inst == 'Off': From 3be7528a6c279013a3f8d0efb83ea632d5299456 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 21 May 2025 22:58:06 +0000 Subject: [PATCH 074/136] Update leenkx/blender/lnx/material/make_voxel.py --- leenkx/blender/lnx/material/make_voxel.py | 293 ++++++++++++++++++++-- 1 file changed, 274 insertions(+), 19 deletions(-) diff --git a/leenkx/blender/lnx/material/make_voxel.py b/leenkx/blender/lnx/material/make_voxel.py index 42c88b3..f7755fc 100644 --- a/leenkx/blender/lnx/material/make_voxel.py +++ b/leenkx/blender/lnx/material/make_voxel.py @@ -68,6 +68,7 @@ def make_gi(context_id): frag.add_include('std/imageatomic.glsl') frag.add_include('std/gbuffer.glsl') frag.add_include('std/brdf.glsl') + frag.add_include('std/aabb.glsl') rpdat = lnx.utils.get_rp() frag.add_uniform('layout(r32ui) uimage3D voxels') @@ -88,7 +89,6 @@ def make_gi(context_id): else: frag.write('float opacity = 1.0;') - frag.write('float dotNV = 0.0;') cycles.parse(mat_state.nodes, con_voxel, vert, frag, geom, tesc, tese, parse_opacity=parse_opacity, parse_displacement=False, basecol_only=True) # Voxelized particles @@ -141,10 +141,11 @@ def make_gi(context_id): geom.add_out('vec3 P') geom.add_out('vec3 voxnormal') geom.add_out('vec4 lightPosition') - geom.add_out('vec4 spotPosition') geom.add_out('vec4 wvpposition') geom.add_out('vec3 eyeDir') - + geom.add_out('vec3 aabb_min') + geom.add_out('vec3 aabb_max') + if con_voxel.is_elem('col'): geom.add_out('vec3 vcolor') if con_voxel.is_elem('tex'): @@ -161,6 +162,9 @@ def make_gi(context_id): geom.write('uint maxi = facenormal[1] > facenormal[0] ? 1 : 0;') geom.write('maxi = facenormal[2] > facenormal[maxi] ? 2 : maxi;') + geom.write('aabb_min = min(voxpositionGeom[0].xyz, min(voxpositionGeom[1].xyz, voxpositionGeom[2].xyz));') + geom.write('aabb_max = max(voxpositionGeom[0].xyz, max(voxpositionGeom[1].xyz, voxpositionGeom[2].xyz));') + geom.write('for (uint i = 0; i < 3; ++i) {') geom.write(' voxposition[i].xyz = (voxpositionGeom[i] - vec3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)])) / (float(clipmaps[int(clipmapLevel * 10)]));') geom.write(' if (maxi == 0)') @@ -173,6 +177,13 @@ def make_gi(context_id): geom.write(' }') geom.write('}') + geom.write('vec2 side0N = normalize(voxposition[1].xy - voxposition[0].xy);') + geom.write('vec2 side1N = normalize(voxposition[2].xy - voxposition[1].xy);') + geom.write('vec2 side2N = normalize(voxposition[0].xy - voxposition[2].xy);') + geom.write('voxposition[0].xy += normalize(side2N - side0N);') + geom.write('voxposition[1].xy += normalize(side0N - side1N);') + geom.write('voxposition[2].xy += normalize(side1N - side2N);') + geom.write('for (uint i = 0; i < 3; ++i) {') geom.write(' voxposition[i].xy /= voxelgiResolution.xy;') geom.write(' voxposition[i].zw = vec2(1.0);') @@ -187,6 +198,10 @@ def make_gi(context_id): if export_bpos: geom.write('bposition = bpositionGeom[i];') geom.write(' eyeDir = eyeDirGeom[i];') + if '_Sun' in wrd.world_defs and not '_CSM' in wrd.world_defs and '_ShadowMap' in wrd.world_defs: + geom.write(' lightPosition = lightPositionGeom[i];') + if '_Clusters' in wrd.world_defs and '_ShadowMap' in wrd.world_defs: + geom.write(' wvpposition = wvppositionGeom[i];') geom.write(' gl_Position = voxposition[i];') geom.write(' EmitVertex();') geom.write('}') @@ -197,6 +212,7 @@ def make_gi(context_id): frag.write('vec3 uvw = (P - vec3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)])) / (float(clipmaps[int(clipmapLevel * 10)]) * voxelgiResolution);') frag.write('uvw = (uvw * 0.5 + 0.5);') + frag.write('if(any(notEqual(uvw, clamp(uvw, 0.0, 1.0)))) return;') frag.write('vec3 writecoords = floor(uvw * voxelgiResolution);') frag.write_attrib('vec3 N = normalize(voxnormal);') @@ -208,12 +224,33 @@ def make_gi(context_id): frag.write(' ) * voxelgiResolution;') frag.write('vec3 direction_weights = abs(N);') + frag.write('vec3 clipmap_pixel = uvw * voxelgiResolution;') + frag.write('vec3 clipmap_uvw_center = (clipmap_pixel + 0.5) / voxelgiResolution;') + frag.write('vec3 voxel_center = clipmap_uvw_center * 2.0 - 1.0;') + frag.write('float voxel_size = float(clipmaps[int(clipmapLevel * 10)]);') + frag.write('voxel_center *= voxel_size;') + frag.write('voxel_center *= voxelgiResolution.x;') + frag.write('voxel_center += vec3(') + frag.write(' clipmaps[clipmapLevel * 10 + 4],') + frag.write(' clipmaps[clipmapLevel * 10 + 5],') + frag.write(' clipmaps[clipmapLevel * 10 + 6]);') + + frag.write('vec3 voxel_aabb[2];') + frag.write('voxel_aabb[0] = voxel_center;') + frag.write('voxel_aabb[1] = vec3(voxel_size);') + frag.write('vec3 triangle_aabb[2];') + frag.write('AABBfromMinMax(triangle_aabb, aabb_min, aabb_max);') + frag.write('if (!IntersectAABB(voxel_aabb, triangle_aabb))') + frag.write(' return;') + frag.write('vec3 albedo = surfaceAlbedo(basecol, metallic);') frag.write('vec3 f0 = surfaceF0(basecol, metallic);') vert.add_uniform('vec3 eye', '_cameraPosition') vert.add_out('vec3 eyeDirGeom') - vert.write('eyeDirGeom = eye - pos.xyz;') + vert.write('eyeDirGeom = eye - voxpositionGeom;') + frag.write_attrib('vec3 vVec = normalize(eyeDir);') + frag.write_attrib('float dotNV = max(dot(N, vVec), 0.0);') if '_Brdf' in wrd.world_defs: frag.add_uniform('sampler2D senvmapBrdf', link='$brdf.png') @@ -222,7 +259,7 @@ def make_gi(context_id): if '_Irr' in wrd.world_defs: frag.add_include('std/shirr.glsl') frag.add_uniform('vec4 shirr[7]', link='_envmapIrradiance') - frag.write('vec3 envl = shIrradiance(voxnormal, shirr);') + frag.write('vec3 envl = shIrradiance(N, shirr);') if '_EnvTex' in wrd.world_defs: frag.write('envl /= PI;') else: @@ -231,7 +268,7 @@ def make_gi(context_id): if '_Rad' in wrd.world_defs: frag.add_uniform('sampler2D senvmapRadiance', link='_envmapRadiance') frag.add_uniform('int envmapNumMipmaps', link='_envmapNumMipmaps') - frag.write('vec3 reflectionWorld = reflect(-normalize(eyeDir), voxnormal);') + frag.write('vec3 reflectionWorld = reflect(-vVec, N);') frag.write('float lod = getMipFromRoughness(roughness, envmapNumMipmaps);') frag.write('vec3 prefilteredColor = textureLod(senvmapRadiance, envMapEquirect(reflectionWorld), lod).rgb;') @@ -253,11 +290,178 @@ def make_gi(context_id): frag.add_uniform('float envmapStrength', link='_envmapStrength') frag.write('envl *= envmapStrength * occlusion;') - frag.write('if (direction_weights.x > 0) {') - frag.write(' vec4 basecol_direction = vec4(basecol * direction_weights.x, 1.0);') + frag.add_include('std/light.glsl') + is_shadows = '_ShadowMap' in wrd.world_defs + is_shadows_atlas = '_ShadowMapAtlas' in wrd.world_defs + is_single_atlas = is_shadows_atlas and '_SingleAtlas' in wrd.world_defs + shadowmap_sun = 'shadowMap' + shadowmap_sun_tr = 'shadowMapTransparent' + if is_shadows_atlas: + shadowmap_sun = 'shadowMapAtlasSun' if not is_single_atlas else 'shadowMapAtlas' + shadowmap_sun_tr = 'shadowMapAtlasSunTransparent' if not is_single_atlas else 'shadowMapAtlasTransparent' + frag.add_uniform('vec2 smSizeUniform', '_shadowMapSize', included=True) + + frag.write('vec3 direct = vec3(0.0);') + + if '_Sun' in wrd.world_defs: + frag.add_uniform('vec3 sunCol', '_sunColor') + frag.add_uniform('vec3 sunDir', '_sunDirection') + frag.write('vec3 svisibility = vec3(1.0);') + frag.write('vec3 sh = normalize(vVec + sunDir);') + frag.write('float sdotNL = dot(N, sunDir);') + frag.write('float sdotNH = dot(N, sh);') + frag.write('float sdotVH = dot(vVec, sh);') + if is_shadows: + frag.add_uniform('bool receiveShadow') + frag.add_uniform(f'sampler2DShadow {shadowmap_sun}', top=True) + frag.add_uniform(f'sampler2D {shadowmap_sun_tr}', top=True) + frag.add_uniform('float shadowsBias', '_sunShadowsBias') + frag.write('if (receiveShadow) {') + if '_CSM' in wrd.world_defs: + frag.add_include('std/shadows.glsl') + frag.add_uniform('vec4 casData[shadowmapCascades * 4 + 4]', '_cascadeData', included=True) + frag.add_uniform('vec3 eye', '_cameraPosition') + if parse_opacity: + frag.write(f'svisibility = shadowTestCascade({shadowmap_sun},') + frag.write(f'{shadowmap_sun_tr},') + frag.write('eye, P + N * shadowsBias * 10, shadowsBias, true);') + else: + frag.write(f'svisibility = shadowTestCascade({shadowmap_sun},') + frag.write(f'{shadowmap_sun_tr},') + frag.write('eye, P + N * shadowsBias * 10, shadowsBias, false);') + else: + vert.add_out('vec4 lightPositionGeom') + vert.add_uniform('mat4 LWVP', '_biasLightWorldViewProjectionMatrixSun') + vert.write('lightPositionGeom = LWVP * vec4(pos.xyz, 1.0);') + frag.write('vec3 lPos = lightPosition.xyz / lightPosition.w;') + frag.write('const vec2 smSize = shadowmapSize;') + if parse_opacity: + frag.write(f'svisibility = PCF({shadowmap_sun},') + frag.write(f'{shadowmap_sun_tr},') + frag.write('lPos.xy, lPos.z - shadowsBias, smSize, true);') + else: + frag.write(f'svisibility = PCF({shadowmap_sun},') + frag.write(f'{shadowmap_sun_tr},') + frag.write('lPos.xy, lPos.z - shadowsBias, smSize, false);') + frag.write('}') + frag.write('direct += (lambertDiffuseBRDF(albedo, sdotNL) + specularBRDF(f0, roughness, sdotNL, sdotNH, dotNV, sdotVH) * specular) * sunCol * svisibility;') + + if '_SinglePoint' in wrd.world_defs: + frag.add_uniform('vec3 pointPos', link='_pointPosition') + frag.add_uniform('vec3 pointCol', link='_pointColor') + if '_Spot' in wrd.world_defs: + frag.add_uniform('vec3 spotDir', link='_spotDirection') + frag.add_uniform('vec3 spotRight', link='_spotRight') + frag.add_uniform('vec4 spotData', link='_spotData') + if is_shadows: + frag.add_uniform('bool receiveShadow') + frag.add_uniform('float pointBias', link='_pointShadowsBias') + if '_Spot' in wrd.world_defs: + # Skip world matrix, already in world-space + frag.add_uniform('mat4 LWVPSpot[1]', link='_biasLightViewProjectionMatrixSpotArray', included=True) + frag.add_uniform('sampler2DShadow shadowMapSpot[1]', included=True) + frag.add_uniform('sampler2D shadowMapSpotTransparent[1]', included=True) + else: + frag.add_uniform('vec2 lightProj', link='_lightPlaneProj', included=True) + frag.add_uniform('samplerCubeShadow shadowMapPoint[1]', included=True) + frag.add_uniform('samplerCube shadowMapPointTransparent[1]', included=True) + frag.write('direct += sampleLightVoxels(') + frag.write(' P, N, vVec, dotNV, pointPos, pointCol, albedo, roughness, specular, f0') + if is_shadows: + if parse_opacity: + frag.write(', 0, pointBias, receiveShadow, opacity != 1.0') + else: + frag.write(', 0, pointBias, receiveShadow, false') + if '_Spot' in wrd.world_defs: + frag.write(', true, spotData.x, spotData.y, spotDir, spotData.zw, spotRight') + frag.write(');') + + if '_Clusters' in wrd.world_defs: + frag.add_include_front('std/clusters.glsl') + frag.add_uniform('vec2 cameraProj', link='_cameraPlaneProj') + frag.add_uniform('vec2 cameraPlane', link='_cameraPlane') + frag.add_uniform('vec4 lightsArray[maxLights * 3]', link='_lightsArray') + frag.add_uniform('sampler2D clustersData', link='_clustersData') + if is_shadows: + frag.add_uniform('bool receiveShadow') + frag.add_uniform('vec2 lightProj', link='_lightPlaneProj', included=True) + if is_shadows_atlas: + if not is_single_atlas: + frag.add_uniform('sampler2DShadow shadowMapAtlasPoint', included=True) + frag.add_uniform('sampler2D shadowMapAtlasPointTransparent', included=True) + else: + frag.add_uniform('sampler2DShadow shadowMapAtlas', top=True) + frag.add_uniform('sampler2D shadowMapAtlasTransparent', top=True) + frag.add_uniform('vec4 pointLightDataArray[maxLightsCluster]', link='_pointLightsAtlasArray', included=True) + else: + frag.add_uniform('samplerCubeShadow shadowMapPoint[4]', included=True) + frag.add_uniform('samplerCube shadowMapPointTransparent[4]', included=True) + + vert.add_out('vec4 wvppositionGeom') + vert.add_uniform('mat4 VP', '_viewProjectionMatrix') + vert.write('wvppositionGeom = VP * vec4(voxpositionGeom, 1.0);') + # wvpposition.z / wvpposition.w + frag.write('float viewz = linearize((wvpposition.z / wvpposition.w) * 0.5 + 0.5, cameraProj);') + frag.write('int clusterI = getClusterI((wvpposition.xy / wvpposition.w) * 0.5 + 0.5, viewz, cameraPlane);') + frag.write('int numLights = int(texelFetch(clustersData, ivec2(clusterI, 0), 0).r * 255);') + + frag.write('#ifdef HLSL') + frag.write('viewz += texture(clustersData, vec2(0.0)).r * 1e-9;') # TODO: krafix bug, needs to generate sampler + frag.write('#endif') + + if '_Spot' in wrd.world_defs: + frag.add_uniform('vec4 lightsArraySpot[maxLights * 2]', link='_lightsArraySpot') + frag.write('int numSpots = int(texelFetch(clustersData, ivec2(clusterI, 1 + maxLightsCluster), 0).r * 255);') + frag.write('int numPoints = numLights - numSpots;') + if is_shadows: + if is_shadows_atlas: + if not is_single_atlas: + frag.add_uniform('sampler2DShadow shadowMapAtlasSpot', included=True) + frag.add_uniform('sampler2D shadowMapAtlasSpotTransparent', included=True) + else: + frag.add_uniform('sampler2DShadow shadowMapAtlas', top=True) + frag.add_uniform('sampler2D shadowMapAtlasTransparent', top=True) + else: + frag.add_uniform('sampler2DShadow shadowMapSpot[4]', included=True) + frag.add_uniform('sampler2D shadowMapSpotTransparent[4]', included=True) + frag.add_uniform('mat4 LWVPSpotArray[maxLightsCluster]', link='_biasLightWorldViewProjectionMatrixSpotArray', included=True) + + frag.write('for (int i = 0; i < min(numLights, maxLightsCluster); i++) {') + frag.write('int li = int(texelFetch(clustersData, ivec2(clusterI, i + 1), 0).r * 255);') + frag.write('direct += sampleLightVoxels(') + frag.write(' P,') + frag.write(' N,') + frag.write(' vVec,') + frag.write(' dotNV,') + frag.write(' lightsArray[li * 3].xyz,') # lp + frag.write(' lightsArray[li * 3 + 1].xyz,') # lightCol + frag.write(' albedo,') + frag.write(' roughness,') + frag.write(' specular,') + frag.write(' f0') + + if is_shadows: + if parse_opacity: + frag.write('\t, li, lightsArray[li * 3 + 2].x, lightsArray[li * 3 + 2].z != 0.0, opacity != 1.0') # bias + else: + frag.write('\t, li, lightsArray[li * 3 + 2].x, lightsArray[li * 3 + 2].z != 0.0, false') # bias + if '_Spot' in wrd.world_defs: + frag.write('\t, lightsArray[li * 3 + 2].y != 0.0') + frag.write('\t, lightsArray[li * 3 + 2].y') # spot size (cutoff) + frag.write('\t, lightsArraySpot[li * 2].w') # spot blend (exponent) + frag.write('\t, lightsArraySpot[li * 2].xyz') # spotDir + frag.write('\t, vec2(lightsArray[li * 3].w, lightsArray[li * 3 + 1].w)') # scale + frag.write('\t, lightsArraySpot[li * 2 + 1].xyz') # right + frag.write(' );') + frag.write('}') + + frag.write('if (direction_weights.x > 0.0) {') + frag.write(' vec4 basecol_direction = vec4(basecol, opacity) * direction_weights.x;') frag.write(' vec3 emission_direction = emissionCol * direction_weights.x;') - frag.write(' vec2 normal_direction = encode_oct(N * direction_weights.x) * 0.5 + 0.5;') + frag.write(' vec2 encoded_normal = encode_oct(N) * 0.5 + 0.5;') + frag.write(' vec2 normal_direction = encoded_normal * direction_weights.x;') frag.write(' vec3 envl_direction = envl * direction_weights.x;') + frag.write(' vec3 light_direction = direct * direction_weights.x;') frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, 0)), uint(basecol_direction.r * 255));') frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x)), uint(basecol_direction.g * 255));') frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 2)), uint(basecol_direction.b * 255));') @@ -270,13 +474,19 @@ def make_gi(context_id): frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 9)), uint(envl_direction.r * 255));') frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 10)), uint(envl_direction.g * 255));') frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 11)), uint(envl_direction.b * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 12)), uint(light_direction.r * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 13)), uint(light_direction.g * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 14)), uint(light_direction.b * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x * 15)), uint(1));') frag.write('}') - frag.write('if (direction_weights.y > 0) {') - frag.write(' vec4 basecol_direction = vec4(basecol * direction_weights.y, 1.0);') + frag.write('if (direction_weights.y > 0.0) {') + frag.write(' vec4 basecol_direction = vec4(basecol, opacity) * direction_weights.y;') frag.write(' vec3 emission_direction = emissionCol * direction_weights.y;') - frag.write(' vec2 normal_direction = encode_oct(N * direction_weights.y) * 0.5 + 0.5;') + frag.write(' vec2 encoded_normal = encode_oct(N) * 0.5 + 0.5;') + frag.write(' vec2 normal_direction = encoded_normal * direction_weights.y;') frag.write(' vec3 envl_direction = envl * direction_weights.y;') + frag.write(' vec3 light_direction = direct * direction_weights.y;') frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, 0)), uint(basecol_direction.r * 255));') frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x)), uint(basecol_direction.g * 255));') frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 2)), uint(basecol_direction.b * 255));') @@ -289,13 +499,19 @@ def make_gi(context_id): frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 9)), uint(envl_direction.r * 255));') frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 10)), uint(envl_direction.g * 255));') frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 11)), uint(envl_direction.b * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 12)), uint(light_direction.r * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 13)), uint(light_direction.g * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 14)), uint(light_direction.b * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x * 15)), uint(1));') frag.write('}') - frag.write('if (direction_weights.z > 0) {') - frag.write(' vec4 basecol_direction = vec4(basecol * direction_weights.z, 1.0);') + frag.write('if (direction_weights.z > 0.0) {') + frag.write(' vec4 basecol_direction = vec4(basecol, opacity) * direction_weights.z;') frag.write(' vec3 emission_direction = emissionCol * direction_weights.z;') - frag.write(' vec2 normal_direction = encode_oct(n * direction_weights.z) * 0.5 + 0.5;') + frag.write(' vec2 encoded_normal = encode_oct(N) * 0.5 + 0.5;') + frag.write(' vec2 normal_direction = encoded_normal * direction_weights.z;') frag.write(' vec3 envl_direction = envl * direction_weights.z;') + frag.write(' vec3 light_direction = direct * direction_weights.z;') frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, 0)), uint(basecol_direction.r * 255));') frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x)), uint(basecol_direction.g * 255));') frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 2)), uint(basecol_direction.b * 255));') @@ -308,6 +524,10 @@ def make_gi(context_id): frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 9)), uint(envl_direction.r * 255));') frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 10)), uint(envl_direction.g * 255));') frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 11)), uint(envl_direction.b * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 12)), uint(light_direction.r * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 13)), uint(light_direction.g * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 14)), uint(light_direction.b * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x * 15)), uint(1));') frag.write('}') return con_voxel @@ -331,6 +551,7 @@ def make_ao(context_id): geom.add_include('compiled.inc') frag.add_include('std/math.glsl') frag.add_include('std/imageatomic.glsl') + frag.add_include('std/aabb.glsl') frag.write_header('#extension GL_ARB_shader_image_load_store : enable') vert.add_include('compiled.inc') @@ -450,9 +671,15 @@ def make_ao(context_id): geom.add_out('vec4 voxposition[3]') geom.add_out('vec3 P') geom.add_out('vec3 voxnormal') + geom.add_out('vec3 aabb_min') + geom.add_out('vec3 aabb_max') + geom.add_uniform('float clipmaps[voxelgiClipmapCount * 10]', '_clipmaps') geom.add_uniform('int clipmapLevel', '_clipmapLevel') + geom.write('aabb_min = min(voxpositionGeom[0].xyz, min(voxpositionGeom[1].xyz, voxpositionGeom[2].xyz));') + geom.write('aabb_max = max(voxpositionGeom[0].xyz, max(voxpositionGeom[1].xyz, voxpositionGeom[2].xyz));') + geom.write('vec3 facenormal = abs(voxnormalGeom[0] + voxnormalGeom[1] + voxnormalGeom[2]);') geom.write('uint maxi = facenormal[1] > facenormal[0] ? 1 : 0;') geom.write('maxi = facenormal[2] > facenormal[maxi] ? 2 : maxi;') @@ -469,6 +696,13 @@ def make_ao(context_id): geom.write(' }') geom.write('}') + geom.write('vec2 side0N = normalize(voxposition[1].xy - voxposition[0].xy);') + geom.write('vec2 side1N = normalize(voxposition[2].xy - voxposition[1].xy);') + geom.write('vec2 side2N = normalize(voxposition[0].xy - voxposition[2].xy);') + geom.write('voxposition[0].xy += normalize(side2N - side0N);') + geom.write('voxposition[1].xy += normalize(side0N - side1N);') + geom.write('voxposition[2].xy += normalize(side1N - side2N);') + geom.write('for (uint i = 0; i < 3; ++i) {') geom.write(' voxposition[i].xy /= voxelgiResolution.xy;') geom.write(' voxposition[i].zw = vec2(1.0);') @@ -479,7 +713,6 @@ def make_ao(context_id): geom.write('}') geom.write('EndPrimitive();') - frag.add_uniform('float clipmaps[voxelgiClipmapCount * 10]', '_clipmaps') frag.add_uniform('int clipmapLevel', '_clipmapLevel') @@ -496,16 +729,38 @@ def make_ao(context_id): frag.write(' ) * voxelgiResolution;') frag.write('vec3 direction_weights = abs(N);') - frag.write('if (direction_weights.x > 0) {') + frag.write('vec3 clipmap_pixel = uvw * voxelgiResolution;') + frag.write('vec3 clipmap_uvw_center = (clipmap_pixel + 0.5) / voxelgiResolution;') + frag.write('vec3 voxel_center = clipmap_uvw_center * 2.0 - 1.0;') + frag.write('float voxel_size = float(clipmaps[int(clipmapLevel * 10)]);') + frag.write('voxel_center *= voxel_size;') + frag.write('voxel_center *= voxelgiResolution.x;') + frag.write('voxel_center += vec3(') + frag.write(' clipmaps[clipmapLevel * 10 + 4],') + frag.write(' clipmaps[clipmapLevel * 10 + 5],') + frag.write(' clipmaps[clipmapLevel * 10 + 6]);') + + frag.write('vec3 voxel_aabb[2];') + frag.write('voxel_aabb[0] = voxel_center;') + frag.write('voxel_aabb[1] = vec3(voxel_size);') + frag.write('vec3 triangle_aabb[2];') + frag.write('AABBfromMinMax(triangle_aabb, aabb_min, aabb_max);') + frag.write('if (!IntersectAABB(voxel_aabb, triangle_aabb))') + frag.write(' return;') + + frag.write('if (direction_weights.x > 0.0) {') frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, 0)), uint(direction_weights.x * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, voxelgiResolution.x)), uint(1));') frag.write('}') - frag.write('if (direction_weights.y > 0) {') + frag.write('if (direction_weights.y > 0.0) {') frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, 0)), uint(direction_weights.y * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, voxelgiResolution.x)), uint(1));') frag.write('}') - frag.write('if (direction_weights.z > 0) {') + frag.write('if (direction_weights.z > 0.0) {') frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, 0)), uint(direction_weights.z * 255));') + frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, voxelgiResolution.x)), uint(1));') frag.write('}') return con_voxel From eab3e3b30c0323ff55261cb3e8be27f6ac6c0077 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 21 May 2025 23:07:11 +0000 Subject: [PATCH 075/136] Update leenkx/blender/lnx/props_renderpath.py --- leenkx/blender/lnx/props_renderpath.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/leenkx/blender/lnx/props_renderpath.py b/leenkx/blender/lnx/props_renderpath.py index 6134b71..29e770e 100644 --- a/leenkx/blender/lnx/props_renderpath.py +++ b/leenkx/blender/lnx/props_renderpath.py @@ -66,7 +66,7 @@ def update_preset(self, context): rpdat.rp_stereo = False rpdat.rp_voxelgi_resolution = '32' rpdat.lnx_voxelgi_size = 0.125 - rpdat.rp_voxels = 'Voxel AO' + rpdat.rp_voxels = 'Voxel GI' rpdat.rp_render_to_texture = True rpdat.rp_supersampling = '1' rpdat.rp_antialiasing = 'SMAA' @@ -152,7 +152,7 @@ def update_preset(self, context): rpdat.rp_antialiasing = 'TAA' rpdat.rp_compositornodes = True rpdat.rp_volumetriclight = False - rpdat.rp_ssgi = 'RTAO' + rpdat.rp_ssgi = 'SSGI' rpdat.lnx_ssrs = False rpdat.lnx_micro_shadowing = True rpdat.rp_ssr = True @@ -330,6 +330,7 @@ class LnxRPListItem(bpy.types.PropertyGroup): 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_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_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 transparent shadowmaps", default=False, update=update_renderpath) rp_shadowmap_atlas_lod_subdivisions: EnumProperty( items=[('2', '2', '2'), ('3', '3', '3'), @@ -391,7 +392,8 @@ class LnxRPListItem(bpy.types.PropertyGroup): rp_ssgi: EnumProperty( items=[('Off', 'No AO', 'Off'), ('SSAO', 'SSAO', 'Screen space ambient occlusion'), - ('RTAO', 'RTAO', 'Ray-traced ambient occlusion') + ('SSGI', 'SSGI', 'Screen space global illumination') + #('RTAO', 'RTAO', 'Ray-traced ambient occlusion') # ('RTGI', 'RTGI', 'Ray-traced global illumination') ], name="SSGI", description="Screen space global illumination", default='SSAO', update=update_renderpath) @@ -507,7 +509,7 @@ class LnxRPListItem(bpy.types.PropertyGroup): ('1', '1', '1'), ('2', '2', '2')], name="Bounces", description="Trace multiple light bounces", default='1', update=update_renderpath) - lnx_voxelgi_clipmap_count: IntProperty(name="Clipmap count", description="Number of clipmaps", default=3, update=assets.invalidate_compiled_data) + lnx_voxelgi_clipmap_count: IntProperty(name="Clipmap count", description="Number of clipmaps", default=5, update=assets.invalidate_compiled_data) lnx_voxelgi_temporal: BoolProperty(name="Temporal Filter", description="Use temporal filtering to stabilize voxels", default=False, update=assets.invalidate_shader_cache) lnx_voxelgi_shadows: BoolProperty(name="Shadows", description="Use voxels to render shadows", default=False, update=update_renderpath) lnx_samples_per_pixel: EnumProperty( @@ -529,6 +531,7 @@ class LnxRPListItem(bpy.types.PropertyGroup): lnx_voxelgi_spec: FloatProperty(name="Reflection", description="", default=1.0, update=assets.invalidate_shader_cache) lnx_voxelgi_refr: FloatProperty(name="Refraction", description="", default=1.0, update=assets.invalidate_shader_cache) lnx_voxelgi_shad: FloatProperty(name="Shadows", description="Contrast for voxels shadows", default=1.0, update=assets.invalidate_shader_cache) + lnx_voxelgi_env: FloatProperty(name="Environment", description="", default=1.0, update=assets.invalidate_shader_cache) lnx_voxelgi_occ: FloatProperty(name="Occlusion", description="", default=1.0, update=assets.invalidate_shader_cache) lnx_voxelgi_size: FloatProperty(name="Size", description="Voxel size", default=0.25, update=assets.invalidate_shader_cache) lnx_voxelgi_step: FloatProperty(name="Step", description="Step size", default=1.0, update=assets.invalidate_shader_cache) @@ -544,15 +547,17 @@ class LnxRPListItem(bpy.types.PropertyGroup): lnx_water_density: FloatProperty(name="Density", default=1.0, update=assets.invalidate_shader_cache) lnx_water_refract: FloatProperty(name="Refract", default=1.0, update=assets.invalidate_shader_cache) lnx_water_reflect: FloatProperty(name="Reflect", default=1.0, update=assets.invalidate_shader_cache) - lnx_ssgi_strength: FloatProperty(name="Strength", default=1.0, update=assets.invalidate_shader_cache) + lnx_ssgi_strength: FloatProperty(name="Strength", default=8.0, update=assets.invalidate_shader_cache) lnx_ssgi_radius: FloatProperty(name="Radius", default=1.0, update=assets.invalidate_shader_cache) lnx_ssgi_step: FloatProperty(name="Step", default=2.0, update=assets.invalidate_shader_cache) - lnx_ssgi_max_steps: IntProperty(name="Max Steps", default=8, update=assets.invalidate_shader_cache) + lnx_ssgi_max_steps: IntProperty(name="Samples", default=32, update=assets.invalidate_shader_cache) + """ lnx_ssgi_rays: EnumProperty( items=[('9', '9', '9'), ('5', '5', '5'), ], name="Rays", description="Number of rays to trace for RTAO", default='5', update=assets.invalidate_shader_cache) + """ lnx_ssgi_half_res: BoolProperty(name="Half Res", description="Trace in half resolution", default=False, update=assets.invalidate_shader_cache) lnx_bloom_threshold: FloatProperty(name="Threshold", description="Brightness above which a pixel is contributing to the bloom effect", min=0, default=0.8, update=assets.invalidate_shader_cache) lnx_bloom_knee: FloatProperty(name="Knee", description="Smoothen transition around the threshold (higher values = smoother transition)", min=0, max=1, default=0.5, update=assets.invalidate_shader_cache) From 62a4bbb7144aae1534097356b2385085e73b3f79 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 21 May 2025 23:14:37 +0000 Subject: [PATCH 076/136] Update leenkx/blender/lnx/props_ui.py --- leenkx/blender/lnx/props_ui.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/leenkx/blender/lnx/props_ui.py b/leenkx/blender/lnx/props_ui.py index c266d9c..cc7d2d4 100644 --- a/leenkx/blender/lnx/props_ui.py +++ b/leenkx/blender/lnx/props_ui.py @@ -1626,6 +1626,7 @@ class LNX_PT_RenderPathShadowsPanel(bpy.types.Panel): col.prop(rpdat, 'rp_shadowmap_cube') layout.prop(rpdat, 'rp_shadowmap_cascade') layout.prop(rpdat, 'rp_shadowmap_cascades') + layout.prop(rpdat, 'rp_shadowmap_transparent') col = layout.column() col2 = col.column() col2.enabled = rpdat.rp_shadowmap_cascades != '1' @@ -1757,7 +1758,7 @@ class LNX_PT_RenderPathVoxelsPanel(bpy.types.Panel): col3.enabled = rpdat.rp_voxels == 'Voxel AO' col.prop(rpdat, 'lnx_voxelgi_shadows', text='Shadows') col2.prop(rpdat, 'lnx_voxelgi_refract', text='Refraction') - col.prop(rpdat, 'lnx_voxelgi_clipmap_count') + #col.prop(rpdat, 'lnx_voxelgi_clipmap_count') #col.prop(rpdat, 'lnx_voxelgi_cones') col.prop(rpdat, 'rp_voxelgi_resolution') col.prop(rpdat, 'lnx_voxelgi_size') @@ -1771,9 +1772,10 @@ class LNX_PT_RenderPathVoxelsPanel(bpy.types.Panel): col2.prop(rpdat, 'lnx_voxelgi_spec') col2.prop(rpdat, 'lnx_voxelgi_refr') col.prop(rpdat, 'lnx_voxelgi_shad') + #col.prop(rpdat, 'lnx_voxelgi_env') col.prop(rpdat, 'lnx_voxelgi_occ') col.label(text="Ray") - col.prop(rpdat, 'lnx_voxelgi_offset') + #col.prop(rpdat, 'lnx_voxelgi_offset') col.prop(rpdat, 'lnx_voxelgi_step') col.prop(rpdat, 'lnx_voxelgi_range') #col.prop(rpdat, 'lnx_voxelgi_aperture') @@ -1864,10 +1866,10 @@ class LNX_PT_RenderPathPostProcessPanel(bpy.types.Panel): sub = col.column() sub.enabled = rpdat.rp_ssgi != 'Off' sub.prop(rpdat, 'lnx_ssgi_half_res') - sub.prop(rpdat, 'lnx_ssgi_rays') + #sub.prop(rpdat, 'lnx_ssgi_rays') sub.prop(rpdat, 'lnx_ssgi_radius') sub.prop(rpdat, 'lnx_ssgi_strength') - sub.prop(rpdat, 'lnx_ssgi_max_steps') + sub.prop(rpdat, 'lnx_ssgi_samples') layout.separator() row = layout.row() From fa501cb09bb3043e04c398c32faabb80910976a0 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 21 May 2025 23:18:53 +0000 Subject: [PATCH 077/136] Update leenkx/blender/lnx/write_data.py --- leenkx/blender/lnx/write_data.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/leenkx/blender/lnx/write_data.py b/leenkx/blender/lnx/write_data.py index f92cea4..8c12d12 100644 --- a/leenkx/blender/lnx/write_data.py +++ b/leenkx/blender/lnx/write_data.py @@ -671,16 +671,16 @@ const float waterReflect = """ + str(round(rpdat.lnx_water_reflect * 100) / 100) f'const float ditherStrengthValue = {rpdat.lnx_dithering_strength};\n' ) - if rpdat.rp_ssgi == 'SSAO' or rpdat.rp_ssgi == 'RTAO' or rpdat.rp_volumetriclight: + if rpdat.rp_ssgi == 'SSAO' or rpdat.rp_ssgi == 'SSGI' or rpdat.rp_ssgi == 'RTAO' or rpdat.rp_volumetriclight: f.write( """const float ssaoRadius = """ + str(round(rpdat.lnx_ssgi_radius * 100) / 100) + """; const float ssaoStrength = """ + str(round(rpdat.lnx_ssgi_strength * 100) / 100) + """; const float ssaoScale = """ + ("2.0" if rpdat.lnx_ssgi_half_res else "20.0") + """; """) - if rpdat.rp_ssgi == 'RTGI' or rpdat.rp_ssgi == 'RTAO': + if rpdat.rp_ssgi == 'RTGI' or rpdat.rp_ssgi == 'RTAO' or rpdat.rp_ssgi == 'SSGI' : f.write( -"""const int ssgiMaxSteps = """ + str(rpdat.lnx_ssgi_max_steps) + """; +"""const int ssgiSamples = """ + str(rpdat.lnx_ssgi_samples) + """; const float ssgiRayStep = 0.005 * """ + str(round(rpdat.lnx_ssgi_step * 100) / 100) + """; const float ssgiStrength = """ + str(round(rpdat.lnx_ssgi_strength * 100) / 100) + """; """) @@ -824,6 +824,7 @@ const float voxelgiRange = """ + str(round(rpdat.lnx_voxelgi_range * 100) / 100) const float voxelgiOffset = """ + str(round(rpdat.lnx_voxelgi_offset * 1000) / 1000) + """; const float voxelgiAperture = """ + str(round(rpdat.lnx_voxelgi_aperture * 100) / 100) + """; const float voxelgiShad = """ + str(round(rpdat.lnx_voxelgi_shad * 100) / 100) + """; +const float voxelgiEnv = """ + str(round(rpdat.lnx_voxelgi_env * 100) / 100) + """; """) if rpdat.rp_voxels == 'Voxel GI': f.write(""" From 6d7b0078b412fccffb8e6e68708f8006e8d82e61 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 21 May 2025 23:26:42 +0000 Subject: [PATCH 078/136] Update leenkx/blender/lnx/props_renderpath.py --- leenkx/blender/lnx/props_renderpath.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/leenkx/blender/lnx/props_renderpath.py b/leenkx/blender/lnx/props_renderpath.py index 29e770e..0287f46 100644 --- a/leenkx/blender/lnx/props_renderpath.py +++ b/leenkx/blender/lnx/props_renderpath.py @@ -550,7 +550,7 @@ class LnxRPListItem(bpy.types.PropertyGroup): lnx_ssgi_strength: FloatProperty(name="Strength", default=8.0, update=assets.invalidate_shader_cache) lnx_ssgi_radius: FloatProperty(name="Radius", default=1.0, update=assets.invalidate_shader_cache) lnx_ssgi_step: FloatProperty(name="Step", default=2.0, update=assets.invalidate_shader_cache) - lnx_ssgi_max_steps: IntProperty(name="Samples", default=32, update=assets.invalidate_shader_cache) + lnx_ssgi_samples: IntProperty(name="Samples", default=32, update=assets.invalidate_shader_cache) """ lnx_ssgi_rays: EnumProperty( items=[('9', '9', '9'), From 200af347401842d543d03fa9709995f548753e30 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Thu, 22 May 2025 02:07:44 +0000 Subject: [PATCH 079/136] Update leenkx/Shaders/blur_edge_pass/blur_edge_pass.frag.glsl --- .../blur_edge_pass/blur_edge_pass.frag.glsl | 22 ++++++------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/leenkx/Shaders/blur_edge_pass/blur_edge_pass.frag.glsl b/leenkx/Shaders/blur_edge_pass/blur_edge_pass.frag.glsl index 1344157..20bea60 100644 --- a/leenkx/Shaders/blur_edge_pass/blur_edge_pass.frag.glsl +++ b/leenkx/Shaders/blur_edge_pass/blur_edge_pass.frag.glsl @@ -10,39 +10,31 @@ uniform sampler2D gbuffer0; uniform vec2 dirInv; // texStep in vec2 texCoord; -out vec3 fragColor; +out float fragColor; // const float blurWeights[5] = float[] (0.227027, 0.1945946, 0.1216216, 0.054054, 0.016216); -// const float blurWeights[10] = float[] (0.132572, 0.125472, 0.106373, 0.08078, 0.05495, 0.033482, 0.018275, 0.008934, 0.003912, 0.001535); - -const float blurWeights[16] = float[]( - 0.072572, 0.065472, 0.056373, 0.040780, - 0.024950, 0.013482, 0.008275, 0.003934, - 0.001912, 0.000535, 0.132572, 0.125472, - 0.106373, 0.080780, 0.054950, 0.033482 -); - +const float blurWeights[10] = float[] (0.132572, 0.125472, 0.106373, 0.08078, 0.05495, 0.033482, 0.018275, 0.008934, 0.003912, 0.001535); const float discardThreshold = 0.95; void main() { vec3 nor = getNor(textureLod(gbuffer0, texCoord, 0.0).rg); - fragColor = textureLod(tex, texCoord, 0.0).rgb * blurWeights[0]; + fragColor = textureLod(tex, texCoord, 0.0).r * blurWeights[0]; float weight = blurWeights[0]; - for (int i = 1; i < 16; ++i) { + for (int i = 1; i < 8; ++i) { float posadd = i;// + 0.5; vec3 nor2 = getNor(textureLod(gbuffer0, texCoord + i * dirInv, 0.0).rg); - float influenceFactor = smoothstep(0.5, discardThreshold, dot(nor2, nor)); - vec3 col = textureLod(tex, texCoord + posadd * dirInv, 0.0).rgb; + float influenceFactor = step(discardThreshold, dot(nor2, nor)); + float col = textureLod(tex, texCoord + posadd * dirInv, 0.0).r; float w = blurWeights[i] * influenceFactor; fragColor += col * w; weight += w; nor2 = getNor(textureLod(gbuffer0, texCoord - i * dirInv, 0.0).rg); influenceFactor = step(discardThreshold, dot(nor2, nor)); - col = textureLod(tex, texCoord - posadd * dirInv, 0.0).rgb; + col = textureLod(tex, texCoord - posadd * dirInv, 0.0).r; w = blurWeights[i] * influenceFactor; fragColor += col * w; weight += w; From e22b522059a0077ee8ac0d43f907ed356d8c09bf Mon Sep 17 00:00:00 2001 From: Onek8 Date: Thu, 22 May 2025 02:10:45 +0000 Subject: [PATCH 080/136] Update leenkx/Shaders/deferred_light/deferred_light.frag.glsl --- leenkx/Shaders/deferred_light/deferred_light.frag.glsl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/leenkx/Shaders/deferred_light/deferred_light.frag.glsl b/leenkx/Shaders/deferred_light/deferred_light.frag.glsl index b819d0e..a722c85 100644 --- a/leenkx/Shaders/deferred_light/deferred_light.frag.glsl +++ b/leenkx/Shaders/deferred_light/deferred_light.frag.glsl @@ -240,8 +240,9 @@ void main() { vec3 F = f0 * envBRDF.x + envBRDF.y; #endif -#ifndef _VoxelGI + #ifndef _VoxelAOvar +#ifndef _VoxelGI // Envmap #ifdef _Irr @@ -299,10 +300,11 @@ void main() { fragColor.rgb = textureLod(voxels_diffuse, texCoord, 0.0).rgb * voxelgiDiff; if(roughness < 1.0 && occspec.y > 0.0) fragColor.rgb += textureLod(voxels_specular, texCoord, 0.0).rgb * F * voxelgiRefl; -#endif +#else #ifdef _VoxelAOvar fragColor.rgb = textureLod(voxels_ao, texCoord, 0.0).rgb * voxelgiOcc; +#endif #endif // Show voxels From 3433afb1c35d7783a728963e2591bf302269336c Mon Sep 17 00:00:00 2001 From: Onek8 Date: Thu, 22 May 2025 02:14:06 +0000 Subject: [PATCH 081/136] Update leenkx/Shaders/ssrefr_pass/ssrefr_pass.frag.glsl --- .../Shaders/ssrefr_pass/ssrefr_pass.frag.glsl | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/leenkx/Shaders/ssrefr_pass/ssrefr_pass.frag.glsl b/leenkx/Shaders/ssrefr_pass/ssrefr_pass.frag.glsl index b4c3c38..52c6176 100644 --- a/leenkx/Shaders/ssrefr_pass/ssrefr_pass.frag.glsl +++ b/leenkx/Shaders/ssrefr_pass/ssrefr_pass.frag.glsl @@ -57,17 +57,14 @@ vec4 binarySearch(vec3 dir) { } vec4 rayCast(vec3 dir) { - float ddepth; - dir *= ss_refractionRayStep; - for (int i = 0; i < maxSteps; i++) { - hitCoord += dir; - ddepth = getDeltaDepth(hitCoord); - if (ddepth > 0.0) - return binarySearch(dir); - } - // No hit — fallback to projecting the ray to UV space - vec2 fallbackUV = getProjectedCoord(hitCoord); - return vec4(fallbackUV, 0.0, 0.5); // We set .w lower to indicate fallback + float ddepth; + dir *= ss_refractionRayStep; + for (int i = 0; i < maxSteps; i++) { + hitCoord += dir; + ddepth = getDeltaDepth(hitCoord); + if (ddepth > 0.0) return binarySearch(dir); + } + return vec4(getProjectedCoord(hitCoord), 0.0, 1.0); } void main() { @@ -77,7 +74,7 @@ void main() { float ior = gr.x; float opac = gr.y; float d = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0; - if (d == 0.0 || opac == 1.0 || ior == 1.0) { + if (d == 0.0 || d == 1.0 || opac == 1.0 || ior == 1.0) { fragColor.rgb = textureLod(tex1, texCoord, 0.0).rgb; return; } From 4c92c4bcc923570a0fea76177233b2d0f7e8d1ff Mon Sep 17 00:00:00 2001 From: Onek8 Date: Thu, 22 May 2025 02:16:35 +0000 Subject: [PATCH 082/136] Update leenkx/Shaders/std/conetrace.glsl --- leenkx/Shaders/std/conetrace.glsl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/leenkx/Shaders/std/conetrace.glsl b/leenkx/Shaders/std/conetrace.glsl index 4d1d1d6..776752a 100644 --- a/leenkx/Shaders/std/conetrace.glsl +++ b/leenkx/Shaders/std/conetrace.glsl @@ -92,7 +92,7 @@ vec4 traceCone(const sampler3D voxels, const sampler3D voxelsSDF, const vec3 ori float dist = voxelSize0; float step_dist = dist; vec3 samplePos; - vec3 start_pos = origin + n * voxelSize0 * voxelgiOffset; + vec3 start_pos = origin + n * voxelSize0; int clipmap_index0 = 0; vec3 aniso_direction = -dir; @@ -196,7 +196,7 @@ float traceConeAO(const sampler3D voxels, const vec3 origin, const vec3 n, const float dist = voxelSize0; float step_dist = dist; vec3 samplePos; - vec3 start_pos = origin + n * voxelSize0 * voxelgiOffset; + vec3 start_pos = origin + n * voxelSize0; int clipmap_index0 = 0; vec3 aniso_direction = -dir; @@ -267,7 +267,7 @@ float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const v float dist = voxelSize0; float step_dist = dist; vec3 samplePos; - vec3 start_pos = origin + n * voxelSize0 * voxelgiOffset; + vec3 start_pos = origin + n * voxelSize0; int clipmap_index0 = 0; vec3 aniso_direction = -dir; From 109544cea9afabf759f249b8d420036e7bbae501 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Thu, 22 May 2025 02:20:28 +0000 Subject: [PATCH 083/136] Update leenkx/Shaders/std/light.glsl --- leenkx/Shaders/std/light.glsl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/leenkx/Shaders/std/light.glsl b/leenkx/Shaders/std/light.glsl index 6232239..6b5e91f 100644 --- a/leenkx/Shaders/std/light.glsl +++ b/leenkx/Shaders/std/light.glsl @@ -22,6 +22,9 @@ #ifdef _Spot #include "std/light_common.glsl" #endif +#ifdef _VoxelShadow +#include "std/conetrace.glsl" +#endif #ifdef _ShadowMap #ifdef _SinglePoint @@ -308,7 +311,7 @@ vec3 sampleLightVoxels(const vec3 p, const vec3 n, const vec3 v, const float dot direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent); #endif #ifdef _Clusters - vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0); + vec4 lPos = LWVPSpot[index] * vec4(p + n * bias * 10, 1.0); #ifdef _ShadowMapAtlas direct *= shadowTest( #ifndef _SingleAtlas From 25f8c5f64ccec6c4bbe78c19c3ed743fce0944c5 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Thu, 22 May 2025 02:24:58 +0000 Subject: [PATCH 084/136] Update leenkx/Shaders/voxel_resolve_ao/voxel_resolve_ao.comp.glsl --- leenkx/Shaders/voxel_resolve_ao/voxel_resolve_ao.comp.glsl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/leenkx/Shaders/voxel_resolve_ao/voxel_resolve_ao.comp.glsl b/leenkx/Shaders/voxel_resolve_ao/voxel_resolve_ao.comp.glsl index d1425e9..7123f27 100644 --- a/leenkx/Shaders/voxel_resolve_ao/voxel_resolve_ao.comp.glsl +++ b/leenkx/Shaders/voxel_resolve_ao/voxel_resolve_ao.comp.glsl @@ -106,6 +106,7 @@ void main() { #ifdef _Brdf vec2 envBRDF = texelFetch(senvmapBrdf, ivec2(vec2(dotNV, 1.0 - roughness) * 256.0), 0).xy; + vec3 F = f0 * envBRDF.x + envBRDF.y; #endif // Envmap @@ -153,14 +154,14 @@ void main() { envl.rgb *= albedo; #ifdef _Brdf - envl.rgb *= 1.0 - (f0 * envBRDF.x + envBRDF.y); //LV: We should take refracted light into account + envl.rgb *= 1.0 - F; //LV: We should take refracted light into account #endif #ifdef _Rad // Indirect specular - envl.rgb += prefilteredColor * (f0 * envBRDF.x + envBRDF.y); //LV: Removed "1.5 * occspec.y". Specular should be weighted only by FV LUT + envl.rgb += prefilteredColor * F; //LV: Removed "1.5 * occspec.y". Specular should be weighted only by FV LUT #else #ifdef _EnvCol - envl.rgb += backgroundCol * (f0 * envBRDF.x + envBRDF.y); //LV: Eh, what's the point of weighting it only by F0? + envl.rgb += backgroundCol * F; //LV: Eh, what's the point of weighting it only by F0? #endif #endif From 0cc86c41b85a89e7e1aad22439c29f82b5f81918 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Thu, 22 May 2025 02:25:46 +0000 Subject: [PATCH 085/136] Update leenkx/Shaders/voxel_resolve_specular/voxel_resolve_specular.comp.glsl --- .../voxel_resolve_specular/voxel_resolve_specular.comp.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/leenkx/Shaders/voxel_resolve_specular/voxel_resolve_specular.comp.glsl b/leenkx/Shaders/voxel_resolve_specular/voxel_resolve_specular.comp.glsl index 30c07f2..8cad6a1 100644 --- a/leenkx/Shaders/voxel_resolve_specular/voxel_resolve_specular.comp.glsl +++ b/leenkx/Shaders/voxel_resolve_specular/voxel_resolve_specular.comp.glsl @@ -68,7 +68,7 @@ void main() { vec2 velocity = -textureLod(sveloc, uv, 0.0).rg; - vec3 color = traceSpecular(P, n, voxels, voxelsSDF, normalize(eye - P), g0.z * g0.z, clipmaps, pixel, velocity).rgb * voxelgiRefl; + vec3 color = traceSpecular(P, n, voxels, voxelsSDF, normalize(eye - P), g0.z * g0.z, clipmaps, pixel, velocity).rgb; imageStore(voxels_specular, ivec2(pixel), vec4(color, 1.0)); } From 58b900030529e9fb4a4a959fad4fa24e4200573e Mon Sep 17 00:00:00 2001 From: Onek8 Date: Thu, 22 May 2025 02:27:46 +0000 Subject: [PATCH 086/136] Update leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl --- leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl b/leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl index 7a89be0..7780ff7 100644 --- a/leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl +++ b/leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl @@ -35,13 +35,13 @@ uniform vec3 lightColor; uniform int lightType; uniform vec3 lightDir; uniform vec2 spotData; +uniform float envmapStrength; #ifdef _ShadowMap uniform int lightShadow; uniform vec2 lightProj; uniform float shadowsBias; uniform mat4 LVP; #endif -uniform float envmapStrength; uniform sampler3D voxelsSampler; uniform layout(r32ui) uimage3D voxels; uniform layout(r32ui) uimage3D voxelsLight; From ae72401657c20b86e305ca34f584a32bd8595850 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Thu, 22 May 2025 02:57:45 +0000 Subject: [PATCH 087/136] Update leenkx/Sources/leenkx/renderpath/Inc.hx --- leenkx/Sources/leenkx/renderpath/Inc.hx | 33 +++++++++++++++++-------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/leenkx/Sources/leenkx/renderpath/Inc.hx b/leenkx/Sources/leenkx/renderpath/Inc.hx index 3f084a4..09dd163 100644 --- a/leenkx/Sources/leenkx/renderpath/Inc.hx +++ b/leenkx/Sources/leenkx/renderpath/Inc.hx @@ -31,10 +31,10 @@ class Inc { static var m = iron.math.Mat4.identity(); static var voxel_ca1:kha.compute.ConstantLocation; static var voxel_cb1:kha.compute.ConstantLocation; - static var voxel_cc1:kha.compute.ConstantLocation; #if (rp_voxels == "Voxel GI") static var voxel_td1:kha.compute.TextureUnit; static var voxel_te1:kha.compute.TextureUnit; + static var voxel_cc1:kha.compute.ConstantLocation; #else #if lnx_voxelgi_shadows static var voxel_te1:kha.compute.TextureUnit; @@ -152,9 +152,11 @@ class Inc { for (atlas in ShadowMapAtlas.shadowMapAtlases) { path.bindTarget(atlas.target, atlas.target); } + #if rp_shadowmap_transparent for (atlas in ShadowMapAtlas.shadowMapAtlasesTransparent) { path.bindTarget(atlas.target, atlas.target); } + #end } static function getShadowMapAtlas(atlas:ShadowMapAtlas, transparent: Bool):String { @@ -195,24 +197,30 @@ class Inc { for (atlas in ShadowMapAtlas.shadowMapAtlases) { atlas.rejectedLights = []; } + #if rp_shadowmap_transparent for (atlas in ShadowMapAtlas.shadowMapAtlasesTransparent) { atlas.rejectedLights = []; } #end + #end for (light in iron.Scene.active.lights) { if (!light.lightInAtlas && !light.culledLight && light.visible && light.shadowMapScale > 0.0 && light.data.raw.strength > 0.0 && light.data.raw.cast_shadow) { ShadowMapAtlas.addLight(light, false); } + #if rp_shadowmap_transparent if (!light.lightInAtlasTransparent && !light.culledLight && light.visible && light.shadowMapScale > 0.0 && light.data.raw.strength > 0.0 && light.data.raw.cast_shadow) { ShadowMapAtlas.addLight(light, true); } + #end } // update point light data before rendering - updatePointLightAtlasData(true); updatePointLightAtlasData(false); + #if rp_shadowmap_transparent + updatePointLightAtlasData(true); + #end for (atlas in ShadowMapAtlas.shadowMapAtlases) { var tilesToRemove = []; @@ -290,6 +298,7 @@ class Inc { path.endStream(); } + #if rp_shadowmap_transparent for (atlas in ShadowMapAtlas.shadowMapAtlasesTransparent) { var tilesToRemove = []; #if lnx_shadowmap_atlas_lod @@ -384,8 +393,6 @@ class Inc { tile.freeTile(); } } - #if lnx_debug - endShadowsLogicProfile(); #end #end } @@ -490,6 +497,7 @@ class Inc { else if (l.data.raw.type == "spot" || l.data.raw.type == "area") spotIndex++; } + #if rp_shadowmap_transparent pointIndex = 0; spotIndex = 0; for (l in iron.Scene.active.lights) { @@ -511,6 +519,7 @@ class Inc { if (l.data.raw.type == "point") pointIndex++; else if (l.data.raw.type == "spot" || l.data.raw.type == "area") spotIndex++; } + #end #end // rp_shadowmap } #end @@ -597,10 +606,14 @@ class Inc { #end #if (rp_voxels != "Off") - { - path.bindTarget("voxelsOut", "voxels"); - path.bindTarget("voxelsSDF", "voxelsSDF"); - } + path.bindTarget("voxelsOut", "voxels"); + #if (rp_voxels == "Voxel GI" || lnx_voxelgi_shadows) + path.bindTarget("voxelsSDF", "voxelsSDF"); + #end + #end + + #if rp_ssrs + path.bindTarget("_main", "gbufferD"); #end path.drawMeshes("translucent"); @@ -811,6 +824,7 @@ class Inc { #if (rp_voxels == "Voxel GI") voxel_td1 = voxel_sh1.getTextureUnit("voxelsSampler"); voxel_te1 = voxel_sh1.getTextureUnit("SDF"); + voxel_cc1 = voxel_sh1.getConstantLocation("envmapStrength"); #else #if lnx_voxelgi_shadows voxel_te1 = voxel_sh1.getTextureUnit("SDF"); @@ -932,6 +946,7 @@ class Inc { #if (rp_voxels == "Voxel GI") kha.compute.Compute.setSampledTexture(voxel_td1, rts.get("voxelsOutB").image); kha.compute.Compute.setTexture(voxel_te1, rts.get("voxelsSDF").image, kha.compute.Access.Write); + kha.compute.Compute.setFloat(voxel_cc1, iron.Scene.active.world == null ? 0.0 : iron.Scene.active.world.probe.raw.strength); #else #if lnx_voxelgi_shadows kha.compute.Compute.setTexture(voxel_te1, rts.get("voxelsSDF").image, kha.compute.Access.Write); @@ -1221,8 +1236,6 @@ class Inc { kha.compute.Compute.setSampledTexture(voxel_tf4, rts.get("gbuffer2").image); #end - kha.compute.Compute.setSampledTexture(voxel_tf4, rts.get("gbuffer2").image); - var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); for (i in 0...Main.voxelgiClipmapCount) { fa[i * 10] = clipmaps[i].voxelSize; From 1ad7e0eaf422b49cf1f72006615424b36fa3b5d4 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Thu, 22 May 2025 03:03:50 +0000 Subject: [PATCH 088/136] Update leenkx/Sources/leenkx/renderpath/RenderPathDeferred.hx --- .../leenkx/renderpath/RenderPathDeferred.hx | 53 +++++++++++++------ 1 file changed, 38 insertions(+), 15 deletions(-) diff --git a/leenkx/Sources/leenkx/renderpath/RenderPathDeferred.hx b/leenkx/Sources/leenkx/renderpath/RenderPathDeferred.hx index caf8b68..9a415ef 100644 --- a/leenkx/Sources/leenkx/renderpath/RenderPathDeferred.hx +++ b/leenkx/Sources/leenkx/renderpath/RenderPathDeferred.hx @@ -271,6 +271,34 @@ class RenderPathDeferred { } #end + #if rp_volumetriclight + { + var t = new RenderTargetRaw(); + t.name = "volumetrica"; + t.width = 0; + t.height = 0; + t.displayp = Inc.getDisplayp(); + t.format = "R8"; + t.scale = Inc.getSuperSampling(); + #if rp_ssgi_half // Do we keep this ? + t.scale *= 0.5; + #end + path.createRenderTarget(t); + + var t = new RenderTargetRaw(); + t.name = "volumetricb"; + t.width = 0; + t.height = 0; + t.displayp = Inc.getDisplayp(); + t.format = "R8"; + t.scale = Inc.getSuperSampling(); + #if rp_ssgi_half + t.scale *= 0.5; + #end + path.createRenderTarget(t); + } + #end + #if ((rp_antialiasing == "SMAA") || (rp_antialiasing == "TAA")) { var t = new RenderTargetRaw(); @@ -404,7 +432,6 @@ class RenderPathDeferred { path.loadShader("shader_datas/ssrefr_pass/ssrefr_pass"); path.loadShader("shader_datas/copy_pass/copy_pass"); - path.createDepthBuffer("refraction", "DEPTH24"); // holds background depth var t = new RenderTargetRaw(); t.name = "gbufferD1"; @@ -508,7 +535,7 @@ class RenderPathDeferred { #if (rp_ssrefr || lnx_voxelgi_refract) { - path.setTarget("gbuffer_refraction"); // Only clear gbuffer0 + path.setTarget("gbuffer_refraction"); path.clearTarget(0xffffff00); } #end @@ -675,7 +702,7 @@ class RenderPathDeferred { Inc.computeVoxelsTemporal(); - #if (lnx_voxelgi_shadows || rp_voxels == "Voxel GI") + #if (rp_voxels == "Voxel GI") Inc.computeVoxelsSDF(); #end @@ -687,14 +714,9 @@ class RenderPathDeferred { #else path.clearImage("voxels_ao", 0x00000000); #end - #if lnx_voxelgi_shadows - path.bindTarget("voxelsOut", "voxels"); - path.bindTarget("voxelsSDF", "voxelsSDF"); - #end } } #end - // --- // Deferred light // --- @@ -948,13 +970,14 @@ class RenderPathDeferred { #end #if (rp_voxels != "Off") - { - path.bindTarget("voxelsOut", "voxels"); - path.bindTarget("voxelsSDF", "voxelsSDF"); - #if rp_gbuffer2 - path.bindTarget("gbuffer2", "gbuffer2"); - #end - } + path.bindTarget("voxelsOut", "voxels"); + #if (rp_voxels == "Voxel GI" || lnx_voxelgi_shadows) + path.bindTarget("voxelsSDF", "voxelsSDF"); + #end + #end + + #if rp_ssrs + path.bindTarget("_main", "gbufferD"); #end path.drawMeshes("refraction"); From 2d8bfbf1812410863bb20111f61e5105b8b66cf8 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Thu, 22 May 2025 03:07:01 +0000 Subject: [PATCH 089/136] Update leenkx/Sources/leenkx/renderpath/RenderPathForward.hx --- .../leenkx/renderpath/RenderPathForward.hx | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/leenkx/Sources/leenkx/renderpath/RenderPathForward.hx b/leenkx/Sources/leenkx/renderpath/RenderPathForward.hx index 70152f4..9bff384 100644 --- a/leenkx/Sources/leenkx/renderpath/RenderPathForward.hx +++ b/leenkx/Sources/leenkx/renderpath/RenderPathForward.hx @@ -146,12 +146,13 @@ class RenderPathForward { t.scale = Inc.getSuperSampling(); path.createRenderTarget(t); + //holds colors before refractive meshes are drawn var t = new RenderTargetRaw(); t.name = "refr"; t.width = 0; t.height = 0; t.displayp = Inc.getDisplayp(); - t.format = "RGBA64"; + t.format = Inc.getHdrFormat(); t.scale = Inc.getSuperSampling(); path.createRenderTarget(t); } @@ -200,7 +201,7 @@ class RenderPathForward { Inc.initGI("voxels"); Inc.initGI("voxelsOut"); Inc.initGI("voxelsOutB"); - #if (lnx_voxelgi_shadows || (rp_voxels == "Voxel GI")) + #if (rp_voxels == "Voxel GI" || lnx_voxelgi_shadows) Inc.initGI("voxelsSDF"); Inc.initGI("voxelsSDFtmp"); #end @@ -319,6 +320,7 @@ class RenderPathForward { path.createRenderTarget(t); } #end + #if rp_ssr { @@ -397,7 +399,6 @@ class RenderPathForward { path.setViewport(res, res); path.bindTarget("voxels", "voxels"); - path.drawMeshes("voxel"); Inc.computeVoxelsTemporal(); @@ -422,7 +423,7 @@ class RenderPathForward { #if (rp_ssrefr || lnx_voxelgi_refract) { path.setTarget("gbuffer_refraction"); // Only clear gbuffer0 - path.clearTarget(0xff000000); + path.clearTarget(0xffffff00); } #end @@ -448,10 +449,12 @@ class RenderPathForward { #if (rp_voxels != "Off") if (leenkx.data.Config.raw.rp_gi != false) { + #if (rp_voxels != "Off") path.bindTarget("voxelsOut", "voxels"); - #if (lnx_voxelgi_shadows || rp_voxels == "Voxel GI") + #if (rp_voxels == "Voxel GI" || lnx_voxelgi_shadows) path.bindTarget("voxelsSDF", "voxelsSDF"); #end + #end } #end @@ -501,12 +504,19 @@ class RenderPathForward { #if (rp_voxels != "Off") path.bindTarget("voxelsOut", "voxels"); + #if (rp_voxels == "Voxel GI" || lnx_voxelgi_shadows) path.bindTarget("voxelsSDF", "voxelsSDF"); #end + #end + + #if rp_ssrs + path.bindTarget("_main", "gbufferD"); + #end path.drawMeshes("refraction"); path.setTarget("lbuffer0"); + path.bindTarget("lbuffer0", "tex"); path.bindTarget("refr", "tex1"); path.bindTarget("_main", "gbufferD"); From 429e6d6768c4202586c80da7fd22750049dadfa2 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Thu, 22 May 2025 19:30:19 +0000 Subject: [PATCH 090/136] Update leenkx/Shaders/std/constants.glsl --- leenkx/Shaders/std/constants.glsl | 39 +++++++++++++++---------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/leenkx/Shaders/std/constants.glsl b/leenkx/Shaders/std/constants.glsl index d0309cc..72739f7 100644 --- a/leenkx/Shaders/std/constants.glsl +++ b/leenkx/Shaders/std/constants.glsl @@ -21,27 +21,26 @@ const int DIFFUSE_CONE_COUNT = 16; const float SHADOW_CONE_APERTURE = radians(15.0); -const float DIFFUSE_CONE_APERTURE = 0.872665; - -const vec3 DIFFUSE_CONE_DIRECTIONS[16] = { - vec3( 0.000000, 0.000000, 1.000000), - vec3( 0.525731, 0.000000, 0.850651), - vec3(-0.525731, 0.000000, 0.850651), - vec3( 0.000000, 0.525731, 0.850651), - vec3( 0.000000, -0.525731, 0.850651), - vec3( 0.309017, 0.809017, 0.500000), - vec3(-0.309017, 0.809017, 0.500000), - vec3( 0.309017, -0.809017, 0.500000), - vec3(-0.309017, -0.809017, 0.500000), - vec3( 0.809017, 0.309017, 0.500000), - vec3( 0.809017, -0.309017, 0.500000), - vec3(-0.809017, 0.309017, 0.500000), - vec3(-0.809017, -0.309017, 0.500000), - vec3( 0.000000, 0.000000, -1.000000), - vec3( 0.525731, 0.000000, -0.850651), - vec3(-0.525731, 0.000000, -0.850651) -}; +const float DIFFUSE_CONE_APERTURE = radians(45.0); +const vec3 DIFFUSE_CONE_DIRECTIONS[16] = vec3[]( + vec3( 0.0000, 0.0000, 1.0000), // top (zenith) + vec3( 0.5257, 0.0000, 0.8506), + vec3(-0.5257, 0.0000, 0.8506), + vec3( 0.0000, 0.5257, 0.8506), + vec3( 0.0000, -0.5257, 0.8506), + vec3( 0.3717, 0.3717, 0.8506), + vec3(-0.3717, 0.3717, 0.8506), + vec3( 0.3717, -0.3717, 0.8506), + vec3(-0.3717, -0.3717, 0.8506), + vec3( 0.6300, 0.2706, 0.7274), + vec3(-0.6300, 0.2706, 0.7274), + vec3( 0.6300, -0.2706, 0.7274), + vec3(-0.6300, -0.2706, 0.7274), + vec3( 0.2706, 0.6300, 0.7274), + vec3(-0.2706, 0.6300, 0.7274), + vec3( 0.2706, -0.6300, 0.7274) +); const float BayerMatrix8[8][8] = From 41b840212c3a9d2eafdacd0a743767fb0da08fbf Mon Sep 17 00:00:00 2001 From: Onek8 Date: Mon, 26 May 2025 23:25:50 +0000 Subject: [PATCH 091/136] Update leenkx/blender/lnx/props_ui.py --- leenkx/blender/lnx/props_ui.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/leenkx/blender/lnx/props_ui.py b/leenkx/blender/lnx/props_ui.py index cc7d2d4..9cfff8b 100644 --- a/leenkx/blender/lnx/props_ui.py +++ b/leenkx/blender/lnx/props_ui.py @@ -1772,7 +1772,7 @@ class LNX_PT_RenderPathVoxelsPanel(bpy.types.Panel): col2.prop(rpdat, 'lnx_voxelgi_spec') col2.prop(rpdat, 'lnx_voxelgi_refr') col.prop(rpdat, 'lnx_voxelgi_shad') - #col.prop(rpdat, 'lnx_voxelgi_env') + col.prop(rpdat, 'lnx_voxelgi_env') col.prop(rpdat, 'lnx_voxelgi_occ') col.label(text="Ray") #col.prop(rpdat, 'lnx_voxelgi_offset') From 2e6de515ef1817b430b04c9eef0438094a655bca Mon Sep 17 00:00:00 2001 From: Onek8 Date: Mon, 26 May 2025 23:29:54 +0000 Subject: [PATCH 092/136] Update leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl --- leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl | 1 + 1 file changed, 1 insertion(+) diff --git a/leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl b/leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl index 7780ff7..4cbc1d8 100644 --- a/leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl +++ b/leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl @@ -42,6 +42,7 @@ uniform vec2 lightProj; uniform float shadowsBias; uniform mat4 LVP; #endif +uniform float envmapStrength; uniform sampler3D voxelsSampler; uniform layout(r32ui) uimage3D voxels; uniform layout(r32ui) uimage3D voxelsLight; From 02ff259860ad7f2cc386a81c308258301c0e71d2 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Tue, 27 May 2025 17:23:03 +0000 Subject: [PATCH 093/136] Update leenkx/blender/lnx/material/make_finalize.py --- leenkx/blender/lnx/material/make_finalize.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/leenkx/blender/lnx/material/make_finalize.py b/leenkx/blender/lnx/material/make_finalize.py index 9760e3c..336980f 100644 --- a/leenkx/blender/lnx/material/make_finalize.py +++ b/leenkx/blender/lnx/material/make_finalize.py @@ -78,7 +78,7 @@ def make(con_mesh: ShaderContext): if export_wpos: vert.add_uniform('mat4 W', '_worldMatrix') vert.add_out('vec3 wposition') - vert.write('wposition = vec4(W * spos).xyz;') + vert.write_attrib('wposition = vec4(W * spos).xyz;') elif write_wpos: vert.add_uniform('mat4 W', '_worldMatrix') vert.write_attrib('vec3 wposition = vec4(W * spos).xyz;') From 2df86850f8750c0f922793f8aeaed8774200fd20 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Tue, 27 May 2025 17:51:56 +0000 Subject: [PATCH 094/136] Update leenkx/Shaders/std/constants.glsl --- leenkx/Shaders/std/constants.glsl | 34 +++++++++++++++---------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/leenkx/Shaders/std/constants.glsl b/leenkx/Shaders/std/constants.glsl index 72739f7..fc03b31 100644 --- a/leenkx/Shaders/std/constants.glsl +++ b/leenkx/Shaders/std/constants.glsl @@ -21,25 +21,25 @@ const int DIFFUSE_CONE_COUNT = 16; const float SHADOW_CONE_APERTURE = radians(15.0); -const float DIFFUSE_CONE_APERTURE = radians(45.0); +const float DIFFUSE_CONE_APERTURE = radians(50.0); const vec3 DIFFUSE_CONE_DIRECTIONS[16] = vec3[]( - vec3( 0.0000, 0.0000, 1.0000), // top (zenith) - vec3( 0.5257, 0.0000, 0.8506), - vec3(-0.5257, 0.0000, 0.8506), - vec3( 0.0000, 0.5257, 0.8506), - vec3( 0.0000, -0.5257, 0.8506), - vec3( 0.3717, 0.3717, 0.8506), - vec3(-0.3717, 0.3717, 0.8506), - vec3( 0.3717, -0.3717, 0.8506), - vec3(-0.3717, -0.3717, 0.8506), - vec3( 0.6300, 0.2706, 0.7274), - vec3(-0.6300, 0.2706, 0.7274), - vec3( 0.6300, -0.2706, 0.7274), - vec3(-0.6300, -0.2706, 0.7274), - vec3( 0.2706, 0.6300, 0.7274), - vec3(-0.2706, 0.6300, 0.7274), - vec3( 0.2706, -0.6300, 0.7274) + vec3( 0.0000, 0.0000, 1.0000), + vec3( 0.7236, 0.5257, 0.4472), + vec3(-0.2764, 0.8506, 0.4472), + vec3(-0.8944, 0.0000, 0.4472), + vec3(-0.2764, -0.8506, 0.4472), + vec3( 0.7236, -0.5257, 0.4472), + vec3( 0.7236, 0.5257, -0.4472), + vec3(-0.2764, 0.8506, -0.4472), + vec3(-0.8944, 0.0000, -0.4472), + vec3(-0.2764, -0.8506, -0.4472), + vec3( 0.7236, -0.5257, -0.4472), + vec3( 0.2764, 0.8506, 0.4472), + vec3(-0.7236, 0.5257, 0.4472), + vec3(-0.7236, -0.5257, 0.4472), + vec3( 0.2764, -0.8506, 0.4472), + vec3( 0.0000, 0.0000, -1.0000) ); From df0e24c307e44b5de023dfd8f73c5e3646a1d310 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Tue, 27 May 2025 18:42:41 +0000 Subject: [PATCH 095/136] Update leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl --- .../voxel_temporal/voxel_temporal.comp.glsl | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl b/leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl index 4cbc1d8..d077029 100644 --- a/leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl +++ b/leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl @@ -100,33 +100,33 @@ void main() { int count = int(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 15))); if (count > 0) { vec4 basecol = vec4(0.0); - basecol.r = float(imageLoad(voxels, src)) / 255; - basecol.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x))) / 255; - basecol.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 2))) / 255; - basecol.a = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 3))) / 255; + basecol.r = float(imageLoad(voxels, src)) / 1024; + basecol.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x))) / 1024; + basecol.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 2))) / 1024; + basecol.a = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 3))) / 1024; basecol /= count; vec3 emission = vec3(0.0); - emission.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 4))) / 255; - emission.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 5))) / 255; - emission.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 6))) / 255; + emission.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 4))) / 1024; + emission.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 5))) / 1024; + emission.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 6))) / 1024; emission /= count; // Retrieve encoded normal (stored in 8-bit format) vec3 N = vec3(0.0); - N.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 7))) / 255.0; - N.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 8))) / 255.0; + N.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 7))) / 1024.0; + N.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 8))) / 1024.0; N /= count; // Decode octahedral normal N = decode_oct(N.rg * 2.0 - 1.0); vec3 envl = vec3(0.0); - envl.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 9))) / 255; - envl.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 10))) / 255; - envl.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 11))) / 255; + envl.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 9))) / 1024; + envl.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 10))) / 1024; + envl.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 11))) / 1024; envl /= count; envl *= envmapStrength; vec3 light = vec3(0.0); - light.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 12))) / 255; - light.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 13))) / 255; - light.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 14))) / 255; + light.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 12))) / 1024; + light.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 13))) / 1024; + light.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 14))) / 1024; light /= count; @@ -146,7 +146,7 @@ void main() { #else int count = int(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x))); if (count > 0) { - opac = float(imageLoad(voxels, src)) / 255; + opac = float(imageLoad(voxels, src)) / 1024; opac /= count; } #endif From d102e59040fb829084399f282d849deaeba266b2 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Tue, 27 May 2025 18:53:36 +0000 Subject: [PATCH 096/136] Update leenkx/blender/lnx/material/make_voxel.py --- leenkx/blender/lnx/material/make_voxel.py | 93 ++++++++++++----------- 1 file changed, 48 insertions(+), 45 deletions(-) diff --git a/leenkx/blender/lnx/material/make_voxel.py b/leenkx/blender/lnx/material/make_voxel.py index f7755fc..f589adb 100644 --- a/leenkx/blender/lnx/material/make_voxel.py +++ b/leenkx/blender/lnx/material/make_voxel.py @@ -139,7 +139,7 @@ def make_gi(context_id): geom.add_out('vec4 voxposition[3]') geom.add_out('vec3 P') - geom.add_out('vec3 voxnormal') + geom.add_out('vec3 wnormal') geom.add_out('vec4 lightPosition') geom.add_out('vec4 wvpposition') geom.add_out('vec3 eyeDir') @@ -188,7 +188,7 @@ def make_gi(context_id): geom.write(' voxposition[i].xy /= voxelgiResolution.xy;') geom.write(' voxposition[i].zw = vec2(1.0);') geom.write(' P = voxpositionGeom[i];') - geom.write(' voxnormal = voxnormalGeom[i];') + geom.write(' wnormal = voxnormalGeom[i];') if con_voxel.is_elem('col'): geom.write('vcolor = vcolorGeom[i];') if con_voxel.is_elem('tex'): @@ -215,7 +215,7 @@ def make_gi(context_id): frag.write('if(any(notEqual(uvw, clamp(uvw, 0.0, 1.0)))) return;') frag.write('vec3 writecoords = floor(uvw * voxelgiResolution);') - frag.write_attrib('vec3 N = normalize(voxnormal);') + frag.write_attrib('vec3 N = normalize(wnormal);') frag.write('vec3 aniso_direction = N;') frag.write('uvec3 face_offsets = uvec3(') frag.write(' aniso_direction.x > 0 ? 0 : 1,') @@ -280,18 +280,20 @@ def make_gi(context_id): frag.write('envl *= albedo;') if '_Brdf' in wrd.world_defs: - frag.write('envl.rgb *= 1.0 - (f0 * envBRDF.x + envBRDF.y);') + frag.write('vec3 F = f0 + (vec3(1.0) - f0) * pow(1.0 - abs(dot(N, vVec)), 5.0);') + frag.write('envl.rgb *= 1.0 - F;') if '_Rad' in wrd.world_defs: - frag.write('envl += prefilteredColor * (f0 * envBRDF.x + envBRDF.y);') + frag.write('envl += prefilteredColor * F;') elif '_EnvCol' in wrd.world_defs: frag.add_uniform('vec3 backgroundCol', link='_backgroundCol') - frag.write('envl += backgroundCol * (f0 * envBRDF.x + envBRDF.y);') + frag.write('envl += backgroundCol * F;') frag.add_uniform('float envmapStrength', link='_envmapStrength') frag.write('envl *= envmapStrength * occlusion;') frag.add_include('std/light.glsl') is_shadows = '_ShadowMap' in wrd.world_defs + is_transparent_shadows = '_ShadowMapTransparent' in wrd.world_defs is_shadows_atlas = '_ShadowMapAtlas' in wrd.world_defs is_single_atlas = is_shadows_atlas and '_SingleAtlas' in wrd.world_defs shadowmap_sun = 'shadowMap' @@ -314,37 +316,37 @@ def make_gi(context_id): if is_shadows: frag.add_uniform('bool receiveShadow') frag.add_uniform(f'sampler2DShadow {shadowmap_sun}', top=True) - frag.add_uniform(f'sampler2D {shadowmap_sun_tr}', top=True) + if is_transparent_shadows: + frag.add_uniform(f'sampler2D {shadowmap_sun_tr}', top=True) frag.add_uniform('float shadowsBias', '_sunShadowsBias') frag.write('if (receiveShadow) {') if '_CSM' in wrd.world_defs: frag.add_include('std/shadows.glsl') frag.add_uniform('vec4 casData[shadowmapCascades * 4 + 4]', '_cascadeData', included=True) frag.add_uniform('vec3 eye', '_cameraPosition') - if parse_opacity: - frag.write(f'svisibility = shadowTestCascade({shadowmap_sun},') + frag.write(f'svisibility = shadowTestCascade({shadowmap_sun},') + if is_transparent_shadows: frag.write(f'{shadowmap_sun_tr},') - frag.write('eye, P + N * shadowsBias * 10, shadowsBias, true);') - else: - frag.write(f'svisibility = shadowTestCascade({shadowmap_sun},') - frag.write(f'{shadowmap_sun_tr},') - frag.write('eye, P + N * shadowsBias * 10, shadowsBias, false);') + frag.write('eye, P + N * shadowsBias * 10, shadowsBias') + if is_transparent_shadows: + frag.write(', false') + frag.write(');') else: vert.add_out('vec4 lightPositionGeom') vert.add_uniform('mat4 LWVP', '_biasLightWorldViewProjectionMatrixSun') vert.write('lightPositionGeom = LWVP * vec4(pos.xyz, 1.0);') frag.write('vec3 lPos = lightPosition.xyz / lightPosition.w;') frag.write('const vec2 smSize = shadowmapSize;') - if parse_opacity: - frag.write(f'svisibility = PCF({shadowmap_sun},') + frag.write(f'svisibility = PCF({shadowmap_sun},') + if is_transparent_shadows: frag.write(f'{shadowmap_sun_tr},') - frag.write('lPos.xy, lPos.z - shadowsBias, smSize, true);') - else: - frag.write(f'svisibility = PCF({shadowmap_sun},') - frag.write(f'{shadowmap_sun_tr},') - frag.write('lPos.xy, lPos.z - shadowsBias, smSize, false);') - frag.write('}') + frag.write('lPos.xy, lPos.z - shadowsBias, smSize') + if is_transparent_shadows: + frag.write(', false') + frag.write(');') + frag.write('}') # receiveShadow frag.write('direct += (lambertDiffuseBRDF(albedo, sdotNL) + specularBRDF(f0, roughness, sdotNL, sdotNH, dotNV, sdotVH) * specular) * sunCol * svisibility;') + # sun if '_SinglePoint' in wrd.world_defs: frag.add_uniform('vec3 pointPos', link='_pointPosition') @@ -360,18 +362,19 @@ def make_gi(context_id): # Skip world matrix, already in world-space frag.add_uniform('mat4 LWVPSpot[1]', link='_biasLightViewProjectionMatrixSpotArray', included=True) frag.add_uniform('sampler2DShadow shadowMapSpot[1]', included=True) - frag.add_uniform('sampler2D shadowMapSpotTransparent[1]', included=True) + if is_transparent_shadows: + frag.add_uniform('sampler2D shadowMapSpotTransparent[1]', included=True) else: frag.add_uniform('vec2 lightProj', link='_lightPlaneProj', included=True) frag.add_uniform('samplerCubeShadow shadowMapPoint[1]', included=True) - frag.add_uniform('samplerCube shadowMapPointTransparent[1]', included=True) - frag.write('direct += sampleLightVoxels(') + if is_transparent_shadows: + frag.add_uniform('samplerCube shadowMapPointTransparent[1]', included=True) + frag.write('direct += sampleLight(') frag.write(' P, N, vVec, dotNV, pointPos, pointCol, albedo, roughness, specular, f0') if is_shadows: - if parse_opacity: - frag.write(', 0, pointBias, receiveShadow, opacity != 1.0') - else: - frag.write(', 0, pointBias, receiveShadow, false') + frag.write(', 0, pointBias, receiveShadow') + if is_transparent_shadows: + frag.write(', opacity != 1.0') if '_Spot' in wrd.world_defs: frag.write(', true, spotData.x, spotData.y, spotDir, spotData.zw, spotRight') frag.write(');') @@ -388,10 +391,12 @@ def make_gi(context_id): if is_shadows_atlas: if not is_single_atlas: frag.add_uniform('sampler2DShadow shadowMapAtlasPoint', included=True) - frag.add_uniform('sampler2D shadowMapAtlasPointTransparent', included=True) + if is_transparent_shadows: + frag.add_uniform('sampler2D shadowMapAtlasPointTransparent', included=True) else: frag.add_uniform('sampler2DShadow shadowMapAtlas', top=True) - frag.add_uniform('sampler2D shadowMapAtlasTransparent', top=True) + if is_transparent_shadows: + frag.add_uniform('sampler2D shadowMapAtlasTransparent', top=True) frag.add_uniform('vec4 pointLightDataArray[maxLightsCluster]', link='_pointLightsAtlasArray', included=True) else: frag.add_uniform('samplerCubeShadow shadowMapPoint[4]', included=True) @@ -417,13 +422,16 @@ def make_gi(context_id): if is_shadows_atlas: if not is_single_atlas: frag.add_uniform('sampler2DShadow shadowMapAtlasSpot', included=True) - frag.add_uniform('sampler2D shadowMapAtlasSpotTransparent', included=True) + if is_transparent_shadows: + frag.add_uniform('sampler2D shadowMapAtlasSpotTransparent', included=True) else: frag.add_uniform('sampler2DShadow shadowMapAtlas', top=True) - frag.add_uniform('sampler2D shadowMapAtlasTransparent', top=True) + if is_transparent_shadows: + frag.add_uniform('sampler2D shadowMapAtlasTransparent', top=True) else: frag.add_uniform('sampler2DShadow shadowMapSpot[4]', included=True) - frag.add_uniform('sampler2D shadowMapSpotTransparent[4]', included=True) + if is_transparent_shadows: + frag.add_uniform('sampler2D shadowMapSpotTransparent[4]', included=True) frag.add_uniform('mat4 LWVPSpotArray[maxLightsCluster]', link='_biasLightWorldViewProjectionMatrixSpotArray', included=True) frag.write('for (int i = 0; i < min(numLights, maxLightsCluster); i++) {') @@ -439,12 +447,10 @@ def make_gi(context_id): frag.write(' roughness,') frag.write(' specular,') frag.write(' f0') - if is_shadows: - if parse_opacity: - frag.write('\t, li, lightsArray[li * 3 + 2].x, lightsArray[li * 3 + 2].z != 0.0, opacity != 1.0') # bias - else: - frag.write('\t, li, lightsArray[li * 3 + 2].x, lightsArray[li * 3 + 2].z != 0.0, false') # bias + frag.write('\t, li, lightsArray[li * 3 + 2].x, lightsArray[li * 3 + 2].z != 0.0') # bias + if is_transparent_shadows: + frag.write('\t, opacity != 1.0') if '_Spot' in wrd.world_defs: frag.write('\t, lightsArray[li * 3 + 2].y != 0.0') frag.write('\t, lightsArray[li * 3 + 2].y') # spot size (cutoff) @@ -458,8 +464,7 @@ def make_gi(context_id): frag.write('if (direction_weights.x > 0.0) {') frag.write(' vec4 basecol_direction = vec4(basecol, opacity) * direction_weights.x;') frag.write(' vec3 emission_direction = emissionCol * direction_weights.x;') - frag.write(' vec2 encoded_normal = encode_oct(N) * 0.5 + 0.5;') - frag.write(' vec2 normal_direction = encoded_normal * direction_weights.x;') + frag.write(' vec2 normal_direction = encode_oct(N * direction_weights.x) * 0.5 + 0.5;') frag.write(' vec3 envl_direction = envl * direction_weights.x;') frag.write(' vec3 light_direction = direct * direction_weights.x;') frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.x, 0, 0)), uint(basecol_direction.r * 255));') @@ -483,8 +488,7 @@ def make_gi(context_id): frag.write('if (direction_weights.y > 0.0) {') frag.write(' vec4 basecol_direction = vec4(basecol, opacity) * direction_weights.y;') frag.write(' vec3 emission_direction = emissionCol * direction_weights.y;') - frag.write(' vec2 encoded_normal = encode_oct(N) * 0.5 + 0.5;') - frag.write(' vec2 normal_direction = encoded_normal * direction_weights.y;') + frag.write(' vec2 normal_direction = encode_oct(N * direction_weights.y) * 0.5 + 0.5;') frag.write(' vec3 envl_direction = envl * direction_weights.y;') frag.write(' vec3 light_direction = direct * direction_weights.y;') frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.y, 0, 0)), uint(basecol_direction.r * 255));') @@ -508,8 +512,7 @@ def make_gi(context_id): frag.write('if (direction_weights.z > 0.0) {') frag.write(' vec4 basecol_direction = vec4(basecol, opacity) * direction_weights.z;') frag.write(' vec3 emission_direction = emissionCol * direction_weights.z;') - frag.write(' vec2 encoded_normal = encode_oct(N) * 0.5 + 0.5;') - frag.write(' vec2 normal_direction = encoded_normal * direction_weights.z;') + frag.write(' vec2 normal_direction = encode_oct(N * direction_weights.z) * 0.5 + 0.5;') frag.write(' vec3 envl_direction = envl * direction_weights.z;') frag.write(' vec3 light_direction = direct * direction_weights.z;') frag.write(' imageAtomicAdd(voxels, ivec3(writecoords + ivec3(face_offsets.z, 0, 0)), uint(basecol_direction.r * 255));') From 13ca31f480761f13b7d03012eedd409f3a9f9dbd Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 28 May 2025 01:28:14 +0000 Subject: [PATCH 097/136] Update leenkx/Sources/leenkx/renderpath/Inc.hx --- leenkx/Sources/leenkx/renderpath/Inc.hx | 3504 +++++++++++------------ 1 file changed, 1749 insertions(+), 1755 deletions(-) diff --git a/leenkx/Sources/leenkx/renderpath/Inc.hx b/leenkx/Sources/leenkx/renderpath/Inc.hx index 09dd163..dea31e7 100644 --- a/leenkx/Sources/leenkx/renderpath/Inc.hx +++ b/leenkx/Sources/leenkx/renderpath/Inc.hx @@ -7,1823 +7,1817 @@ import leenkx.math.Helper; import kha.arrays.Float32Array; class Inc { - static var path: RenderPath; - public static var superSample = 1.0; - - static var pointIndex = 0; - static var spotIndex = 0; - static var lastFrame = -1; - - #if ((rp_voxels != 'Off') && lnx_config) - static var voxelsCreated = false; - #end - - #if (rp_voxels != "Off") - static var voxel_sh0:kha.compute.Shader = null; - static var voxel_sh1:kha.compute.Shader = null; - static var voxel_ta0:kha.compute.TextureUnit; - static var voxel_tb0:kha.compute.TextureUnit; - static var voxel_ca0:kha.compute.ConstantLocation; - static var voxel_cb0:kha.compute.ConstantLocation; - static var voxel_ta1:kha.compute.TextureUnit; - static var voxel_tb1:kha.compute.TextureUnit; - static var voxel_tc1:kha.compute.TextureUnit; - static var m = iron.math.Mat4.identity(); - static var voxel_ca1:kha.compute.ConstantLocation; - static var voxel_cb1:kha.compute.ConstantLocation; - #if (rp_voxels == "Voxel GI") - static var voxel_td1:kha.compute.TextureUnit; - static var voxel_te1:kha.compute.TextureUnit; - static var voxel_cc1:kha.compute.ConstantLocation; - #else - #if lnx_voxelgi_shadows - static var voxel_te1:kha.compute.TextureUnit; - #end - #end - #if (lnx_voxelgi_shadows || rp_voxels == "Voxel GI") - static var voxel_sh2:kha.compute.Shader = null; - static var voxel_ta2:kha.compute.TextureUnit; - static var voxel_tb2:kha.compute.TextureUnit; - static var voxel_ca2:kha.compute.ConstantLocation; - static var voxel_cb2:kha.compute.ConstantLocation; - static var voxel_cc2:kha.compute.ConstantLocation; - #end - static var voxel_sh3:kha.compute.Shader = null; - static var voxel_ta3:kha.compute.TextureUnit; - static var voxel_tb3:kha.compute.TextureUnit; - static var voxel_tc3:kha.compute.TextureUnit; - static var voxel_td3:kha.compute.TextureUnit; - static var voxel_te3:kha.compute.TextureUnit; - static var voxel_tf3:kha.compute.TextureUnit; - #if lnx_brdf - static var voxel_tg3:kha.compute.TextureUnit; - #end - #if lnx_radiance - static var voxel_th3:kha.compute.TextureUnit; - #end - static var voxel_ca3:kha.compute.ConstantLocation; - static var voxel_cb3:kha.compute.ConstantLocation; - static var voxel_cc3:kha.compute.ConstantLocation; - static var voxel_cd3:kha.compute.ConstantLocation; - static var voxel_ce3:kha.compute.ConstantLocation; - #if lnx_irradiance - static var voxel_cf3:kha.compute.ConstantLocation; - #end - #if lnx_radiance - static var voxel_cg3:kha.compute.ConstantLocation; - #end - #if lnx_envcol - static var voxel_ch3:kha.compute.ConstantLocation; - #end - #if (rp_voxels == "Voxel GI") - static var voxel_sh4:kha.compute.Shader = null; - static var voxel_ta4:kha.compute.TextureUnit; - static var voxel_tb4:kha.compute.TextureUnit; - static var voxel_tc4:kha.compute.TextureUnit; - static var voxel_td4:kha.compute.TextureUnit; - static var voxel_te4:kha.compute.TextureUnit; - static var voxel_tf4:kha.compute.TextureUnit; - static var voxel_ca4:kha.compute.ConstantLocation; - static var voxel_cb4:kha.compute.ConstantLocation; - static var voxel_cc4:kha.compute.ConstantLocation; - static var voxel_cd4:kha.compute.ConstantLocation; - #end - #end //rp_voxels - - public static function init(_path: RenderPath) { - path = _path; - - #if lnx_config - var config = leenkx.data.Config.raw; - for (l in iron.Scene.active.lights) { - l.data.raw.shadowmap_size = l.data.raw.type == "sun" ? - config.rp_shadowmap_cascade : - config.rp_shadowmap_cube; - } - superSample = config.rp_supersample; - #else - - #if (rp_supersampling == 1.5) - superSample = 1.5; - #elseif (rp_supersampling == 2) - superSample = 2.0; - #elseif (rp_supersampling == 4) - superSample = 4.0; - #end - - #end - } - - #if lnx_shadowmap_atlas - public static function updatePointLightAtlasData(transparent: Bool): Void { - var atlas = transparent ? ShadowMapAtlas.shadowMapAtlasesTransparent.get(ShadowMapAtlas.shadowMapAtlasName("point", true)) : ShadowMapAtlas.shadowMapAtlases.get(ShadowMapAtlas.shadowMapAtlasName("point", false)); - if (atlas != null) { - if(LightObject.pointLightsData == null) { - LightObject.pointLightsData = new kha.arrays.Float32Array( - LightObject.maxLightsCluster * ShadowMapTile.tilesLightType("point") * 4); // max possible visible lights * 6 or 2 (faces) * 4 (xyzw) - } - - var n = iron.Scene.active.lights.length > LightObject.maxLightsCluster ? LightObject.maxLightsCluster : iron.Scene.active.lights.length; - var i = 0; - var j = 0; - for (light in iron.Scene.active.lights) { - if (i >= n) - break; - if (LightObject.discardLightCulled(light)) continue; - if (light.data.raw.type == "point") { - if (!light.data.raw.cast_shadow) { - j += 4 * 6; - continue; - } - for(k in 0...6) { - LightObject.pointLightsData[j ] = light.tileOffsetX[k]; // posx - LightObject.pointLightsData[j + 1] = light.tileOffsetY[k]; // posy - LightObject.pointLightsData[j + 2] = light.tileScale[k]; // tile scale factor relative to atlas - LightObject.pointLightsData[j + 3] = 0; // padding - j += 4; - } - } - i++; - } - } - } - - public static function bindShadowMapAtlas() { - for (atlas in ShadowMapAtlas.shadowMapAtlases) { - path.bindTarget(atlas.target, atlas.target); - } - #if rp_shadowmap_transparent - for (atlas in ShadowMapAtlas.shadowMapAtlasesTransparent) { - path.bindTarget(atlas.target, atlas.target); - } - #end - } - - static function getShadowMapAtlas(atlas:ShadowMapAtlas, transparent: Bool):String { - inline function createDepthTarget(name: String, size: Int) { - var t = new RenderTargetRaw(); - t.name = name; - t.width = t.height = size; - t.format = transparent ? "RGBA64" : "DEPTH16"; - return path.createRenderTarget(t); - } - - var rt = path.renderTargets.get(atlas.target); - // Create shadowmap atlas texture on the fly and replace existing on size change - if (rt == null) { - rt = createDepthTarget(atlas.target, atlas.sizew); - } - else if (atlas.updateRenderTarget) { - atlas.updateRenderTarget = false; - // Resize shadow map - rt.unload(); - rt = createDepthTarget(atlas.target, atlas.sizew); - } - return atlas.target; - } - - public static function drawShadowMapAtlas() { - #if rp_shadowmap - #if rp_probes - // Share shadow map with probe - if (lastFrame == RenderPath.active.frame) - return; - lastFrame = RenderPath.active.frame; - #end - - #if lnx_debug - beginShadowsLogicProfile(); - // reset data on rejected lights - for (atlas in ShadowMapAtlas.shadowMapAtlases) { - atlas.rejectedLights = []; - } - #if rp_shadowmap_transparent - for (atlas in ShadowMapAtlas.shadowMapAtlasesTransparent) { - atlas.rejectedLights = []; - } - #end - #end - - for (light in iron.Scene.active.lights) { - if (!light.lightInAtlas && !light.culledLight && light.visible && light.shadowMapScale > 0.0 - && light.data.raw.strength > 0.0 && light.data.raw.cast_shadow) { - ShadowMapAtlas.addLight(light, false); - } - #if rp_shadowmap_transparent - if (!light.lightInAtlasTransparent && !light.culledLight && light.visible && light.shadowMapScale > 0.0 - && light.data.raw.strength > 0.0 && light.data.raw.cast_shadow) { - ShadowMapAtlas.addLight(light, true); - } - #end - } - // update point light data before rendering - updatePointLightAtlasData(false); - #if rp_shadowmap_transparent - updatePointLightAtlasData(true); - #end - - for (atlas in ShadowMapAtlas.shadowMapAtlases) { - var tilesToRemove = []; - #if lnx_shadowmap_atlas_lod - var tilesToChangeSize = []; - #end - - var shadowmap = getShadowMapAtlas(atlas, false); - path.setTargetStream(shadowmap); - - path.clearTarget(null, 1.0); - - for (tile in atlas.activeTiles) { - if (tile.light == null || !tile.light.visible || tile.light.culledLight - || !tile.light.data.raw.cast_shadow || tile.light.data.raw.strength == 0) { - tile.unlockLight = true; - tilesToRemove.push(tile); - continue; - } - - #if lnx_shadowmap_atlas_lod - var newTileSize = atlas.getTileSize(tile.light.shadowMapScale); - if (newTileSize != tile.size) { - if (newTileSize == 0) { - tile.unlockLight = true; - tilesToRemove.push(tile); - continue; - } - // queue for size change - tile.newTileSize = newTileSize; - tilesToChangeSize.push(tile); - } - #end - // set the tile offset for this tile and every linked tile to this one - var j = 0; - tile.forEachTileLinked(function (lTile) { - tile.light.tileOffsetX[j] = lTile.coordsX / atlas.sizew; - tile.light.tileOffsetY[j] = lTile.coordsY / atlas.sizew; - tile.light.tileScale[j] = lTile.size / atlas.sizew; - j++; - }); - // set shadowmap size for uniform - tile.light.data.raw.shadowmap_size = atlas.sizew; - - path.light = tile.light; - - var face = 0; - var faces = ShadowMapTile.tilesLightType(tile.light.data.raw.type); - - #if lnx_debug - beginShadowsRenderProfile(); - #end - tile.forEachTileLinked(function (lTile) { - if (faces > 1) { - #if lnx_csm - switch (tile.light.data.raw.type) { - case "sun": tile.light.setCascade(iron.Scene.active.camera, face); - case "point": path.currentFace = face; - } - #else - path.currentFace = face; - #end - face++; - } - path.setCurrentViewportWithOffset(lTile.size, lTile.size, lTile.coordsX, lTile.coordsY); - - path.drawMeshesStream("shadowmap"); - }); - #if lnx_debug - endShadowsRenderProfile(); - #end - - path.currentFace = -1; - } - path.endStream(); - } - - #if rp_shadowmap_transparent - for (atlas in ShadowMapAtlas.shadowMapAtlasesTransparent) { - var tilesToRemove = []; - #if lnx_shadowmap_atlas_lod - var tilesToChangeSize = []; - #end - - var shadowmap = getShadowMapAtlas(atlas, true); - path.setTargetStream(shadowmap); - - path.clearTarget(0xffffff, 0.0); - - for (tile in atlas.activeTiles) { - if (tile.light == null || !tile.light.visible || tile.light.culledLight - || !tile.light.data.raw.cast_shadow || tile.light.data.raw.strength == 0) { - tile.unlockLight = true; - tilesToRemove.push(tile); - continue; - } - - #if lnx_shadowmap_atlas_lod - var newTileSize = atlas.getTileSize(tile.light.shadowMapScale); - if (newTileSize != tile.size) { - if (newTileSize == 0) { - tile.unlockLight = true; - tilesToRemove.push(tile); - continue; - } - // queue for size change - tile.newTileSize = newTileSize; - tilesToChangeSize.push(tile); - } - #end - // set the tile offset for this tile and every linked tile to this one - var j = 0; - tile.forEachTileLinked(function (lTile) { - tile.light.tileOffsetX[j] = lTile.coordsX / atlas.sizew; - tile.light.tileOffsetY[j] = lTile.coordsY / atlas.sizew; - tile.light.tileScale[j] = lTile.size / atlas.sizew; - j++; - }); - // set shadowmap size for uniform - tile.light.data.raw.shadowmap_size = atlas.sizew; - - path.light = tile.light; - - var face = 0; - var faces = ShadowMapTile.tilesLightType(tile.light.data.raw.type); - - #if lnx_debug - beginShadowsRenderProfile(); - #end - tile.forEachTileLinked(function (lTile) { - if (faces > 1) { - #if lnx_csm - switch (tile.light.data.raw.type) { - case "sun": tile.light.setCascade(iron.Scene.active.camera, face); - case "point": path.currentFace = face; - } - #else - path.currentFace = face; - #end - face++; - } - path.setCurrentViewportWithOffset(lTile.size, lTile.size, lTile.coordsX, lTile.coordsY); - - path.drawMeshesStream("shadowmap_transparent"); - }); - #if lnx_debug - endShadowsRenderProfile(); - #end - - path.currentFace = -1; - } - path.endStream(); - - #if lnx_shadowmap_atlas_lod - for (tile in tilesToChangeSize) { - tilesToRemove.push(tile); - - var newTile = ShadowMapTile.assignTiles(tile.light, atlas, tile); - if (newTile != null) - atlas.activeTiles.push(newTile); - } - // update point light data after changing size of tiles to avoid render issues - updatePointLightAtlasData(false); - // update point light data after changing size of tiles to avoid render issues - updatePointLightAtlasData(true); - #end - - for (tile in tilesToRemove) { - atlas.activeTiles.remove(tile); - tile.freeTile(); - } - } - #end - #end - } - #else - public static function bindShadowMap() { - for (l in iron.Scene.active.lights) { - if (!l.visible || l.data.raw.type != "sun") continue; - var n = "shadowMap"; - path.bindTarget(n, n); - var n = "shadowMapTransparent"; - path.bindTarget(n, n); - break; - } - for (i in 0...pointIndex) { - var n = "shadowMapPoint[" + i + "]"; - path.bindTarget(n, n); - var n = "shadowMapPointTransparent[" + i + "]"; - path.bindTarget(n, n); - } - for (i in 0...spotIndex) { - var n = "shadowMapSpot[" + i + "]"; - path.bindTarget(n, n); - var n = "shadowMapSpotTransparent[" + i + "]"; - path.bindTarget(n, n); - } - } - - static function shadowMapName(light: LightObject, transparent: Bool): String { - switch (light.data.raw.type) { - case "sun": - return transparent ? "shadowMapTransparent" : "shadowMap"; - case "point": - return transparent ? "shadowMapPointTransparent[" + pointIndex + "]" : "shadowMapPoint[" + pointIndex + "]"; - default: - return transparent ? "shadowMapSpotTransparent[" + spotIndex + "]" : "shadowMapSpot[" + spotIndex + "]"; - } - } - - static function getShadowMap(l: iron.object.LightObject, transparent: Bool): String { - var target = shadowMapName(l, transparent); - var rt = path.renderTargets.get(target); - // Create shadowmap on the fly - if (rt == null) { - if (path.light.data.raw.shadowmap_cube) { - // Cubemap size - var size = path.light.data.raw.shadowmap_size; - var t = new RenderTargetRaw(); - t.name = target; - t.width = size; - t.height = size; - t.format = transparent ? "RGBA64" : "DEPTH16"; - t.is_cubemap = true; - rt = path.createRenderTarget(t); - } - else { // Non-cube sm - var sizew = path.light.data.raw.shadowmap_size; - var sizeh = sizew; - #if lnx_csm // Cascades - atlas on x axis - if (l.data.raw.type == "sun") { - sizew = sizew * iron.object.LightObject.cascadeCount; - } - #end - var t = new RenderTargetRaw(); - t.name = target; - t.width = sizew; - t.height = sizeh; - t.format = transparent ? "RGBA64" : "DEPTH16"; - rt = path.createRenderTarget(t); - } - } - return target; - } - - public static function drawShadowMap() { - #if (rp_shadowmap) - - #if rp_probes - // Share shadow map with probe - if (lastFrame == RenderPath.active.frame) return; - lastFrame = RenderPath.active.frame; - #end - - pointIndex = 0; - spotIndex = 0; - for (l in iron.Scene.active.lights) { - if (!l.visible) continue; - - path.light = l; - var shadowmap = Inc.getShadowMap(l, false); - var faces = l.data.raw.shadowmap_cube ? 6 : 1; - for (i in 0...faces) { - if (faces > 1) path.currentFace = i; - path.setTarget(shadowmap); - path.clearTarget(null, 1.0); - if (l.data.raw.cast_shadow) { - path.drawMeshes("shadowmap"); - } - } - path.currentFace = -1; - - if (l.data.raw.type == "point") pointIndex++; - else if (l.data.raw.type == "spot" || l.data.raw.type == "area") spotIndex++; - } - - #if rp_shadowmap_transparent - pointIndex = 0; - spotIndex = 0; - for (l in iron.Scene.active.lights) { - if (!l.visible) continue; - - path.light = l; - var shadowmap_transparent = Inc.getShadowMap(l, true); - var faces = l.data.raw.shadowmap_cube ? 6 : 1; - for (i in 0...faces) { - if (faces > 1) path.currentFace = i; - path.setTarget(shadowmap_transparent); - path.clearTarget(0xffffff, 0.0); - if (l.data.raw.cast_shadow) { - path.drawMeshes("shadowmap_transparent"); - } - } - path.currentFace = -1; - - if (l.data.raw.type == "point") pointIndex++; - else if (l.data.raw.type == "spot" || l.data.raw.type == "area") spotIndex++; - } - #end - #end // rp_shadowmap - } - #end - - public static function applyConfig() { - #if lnx_config - var config = leenkx.data.Config.raw; - // Resize shadow map - var l = path.light; - if (l.data.raw.type == "sun" && l.data.raw.shadowmap_size != config.rp_shadowmap_cascade) { - l.data.raw.shadowmap_size = config.rp_shadowmap_cascade; - var rt = path.renderTargets.get("shadowMap"); - if (rt != null) { - rt.unload(); - path.renderTargets.remove("shadowMap"); - } - } - else if (l.data.raw.shadowmap_size != config.rp_shadowmap_cube) { - l.data.raw.shadowmap_size = config.rp_shadowmap_cube; - var rt = path.renderTargets.get("shadowMapCube"); - if (rt != null) { - rt.unload(); - path.renderTargets.remove("shadowMapCube"); - } - } - if (superSample != config.rp_supersample) { - superSample = config.rp_supersample; - for (rt in path.renderTargets) { - if (rt.raw.width == 0 && rt.raw.scale != null) { - rt.raw.scale = getSuperSampling(); - } - } - path.resize(); - } - // Init voxels - #if (rp_voxels != 'Off') - if (!voxelsCreated) initGI(); - #end - #end // lnx_config - } - - #if (rp_translucency) - public static function initTranslucency() { - path.createDepthBuffer("main", "DEPTH24"); - - var t = new RenderTargetRaw(); - t.name = "accum"; - t.width = 0; - t.height = 0; - t.displayp = getDisplayp(); - t.format = "RGBA64"; - t.scale = getSuperSampling(); - t.depth_buffer = "main"; - path.createRenderTarget(t); - - var t = new RenderTargetRaw(); - t.name = "revealage"; - t.width = 0; - t.height = 0; - t.displayp = getDisplayp(); - t.format = "R16"; - t.scale = getSuperSampling(); - t.depth_buffer = "main"; - path.createRenderTarget(t); - - path.loadShader("shader_datas/translucent_resolve/translucent_resolve"); - } - - public static function drawTranslucency(target: String) { - path.setTarget("accum"); - path.clearTarget(0xff000000); - path.setTarget("revealage"); - path.clearTarget(0xffffffff); - path.setTarget("accum", ["revealage"]); - - #if rp_shadowmap - { - #if lnx_shadowmap_atlas - bindShadowMapAtlas(); - #else - bindShadowMap(); - #end - } - #end - - #if (rp_voxels != "Off") - path.bindTarget("voxelsOut", "voxels"); - #if (rp_voxels == "Voxel GI" || lnx_voxelgi_shadows) - path.bindTarget("voxelsSDF", "voxelsSDF"); - #end - #end - - #if rp_ssrs - path.bindTarget("_main", "gbufferD"); - #end - - path.drawMeshes("translucent"); - - #if rp_render_to_texture - { - path.setTarget(target); - } - #else - { - path.setTarget(""); - } - #end - - path.bindTarget("accum", "gbuffer0"); - path.bindTarget("revealage", "gbuffer1"); - path.drawShader("shader_datas/translucent_resolve/translucent_resolve"); - } - #end - - #if rp_bloom - public static inline function drawBloom(srcRTName: String, downsampler: Downsampler, upsampler: Upsampler) { - if (leenkx.data.Config.raw.rp_bloom != false) { - // This can result in little jumps in the perceived bloom radius - // when resizing the window because numMips might change, but - // all implementations using this approach have the same problem - // (including Eevee) - final minDim = Math.min(path.currentW, path.currentH); - final logMinDim = Math.max(1.0, Helper.log2(minDim) + (Main.bloomRadius - 8.0)); - final numMips = Std.int(logMinDim); - - // Sample scale for upsampling, 0.5 to use half-texel steps, - // use fraction of logMinDim to make the visual jumps - // described above less visible - Postprocess.bloom_uniforms[3] = 0.5 + logMinDim - numMips; - - downsampler.dispatch(srcRTName, numMips); - upsampler.dispatch(srcRTName, numMips); - } - } - #end - - #if (rp_voxels != 'Off') - public static function initGI(tname = "voxels") { - var t = new RenderTargetRaw(); - t.name = tname; - - #if lnx_config - var config = leenkx.data.Config.raw; - if (config.rp_voxels != true || voxelsCreated) return; - voxelsCreated = true; - #end - - var res = iron.RenderPath.getVoxelRes(); - var resZ = iron.RenderPath.getVoxelResZ(); - - if (t.name == "voxels_diffuse" || t.name == "voxels_specular" || t.name == "voxels_ao") { - t.width = 0; - t.height = 0; - t.displayp = getDisplayp(); - t.format = "RGBA32"; - } - else { - if (t.name == "voxelsSDF" || t.name == "voxelsSDFtmp") { - t.format = "R16"; - t.width = res; - t.height = res * Main.voxelgiClipmapCount; - t.depth = res; - } - else { - #if (rp_voxels == "Voxel AO") - { - if (t.name == "voxelsOut" || t.name == "voxelsOutB") { - t.format = "R16"; - t.width = res * (6 + 16); - t.height = res * Main.voxelgiClipmapCount; - t.depth = res; - } - else { - t.format = "R32UI"; - t.width = res * 6; - t.height = res; - t.depth = res * 2; - } - } - #else - { - if (t.name == "voxelsOut" || t.name == "voxelsOutB") { - t.format = "RGBA64"; - t.width = res * (6 + 16); - t.height = res * Main.voxelgiClipmapCount; - t.depth = res; - } - else { - t.format = "R32UI"; - t.width = res * 6; - t.height = res; - t.depth = res * 16; - } - } - #end - } - } - t.is_image = true; - t.mipmaps = true; - path.createRenderTarget(t); - } - #end - - public static inline function getCubeSize(): Int { - #if (rp_shadowmap_cube == 256) - return 256; - #elseif (rp_shadowmap_cube == 512) - return 512; - #elseif (rp_shadowmap_cube == 1024) - return 1024; - #elseif (rp_shadowmap_cube == 2048) - return 2048; - #elseif (rp_shadowmap_cube == 4096) - return 4096; - #else - return 0; - #end - } - - public static inline function getCascadeSize(): Int { - #if (rp_shadowmap_cascade == 256) - return 256; - #elseif (rp_shadowmap_cascade == 512) - return 512; - #elseif (rp_shadowmap_cascade == 1024) - return 1024; - #elseif (rp_shadowmap_cascade == 2048) - return 2048; - #elseif (rp_shadowmap_cascade == 4096) - return 4096; - #elseif (rp_shadowmap_cascade == 8192) - return 8192; - #elseif (rp_shadowmap_cascade == 16384) - return 16384; - #else - return 0; - #end - } - - public static inline function getSuperSampling(): Float { - return superSample; - } - - public static inline function getHdrFormat(): String { - #if rp_hdr - return "RGBA64"; - #else - return "RGBA32"; - #end - } - - public static inline function getDisplayp(): Null { - #if rp_resolution_filter // Custom resolution set - return Main.resolutionSize; - #else - return null; - #end - } - - #if lnx_debug - public static var shadowsLogicTime = 0.0; - public static var shadowsRenderTime = 0.0; - static var startShadowsLogicTime = 0.0; - static var startShadowsRenderTime = 0.0; - static var callBackSetup = false; - static function setupEndFrameCallback() { - if (!callBackSetup) { - callBackSetup = true; - iron.App.endFrameCallbacks.push(endFrame); - } - } - static function beginShadowsLogicProfile() { setupEndFrameCallback(); startShadowsLogicTime = kha.Scheduler.realTime(); } - static function beginShadowsRenderProfile() { startShadowsRenderTime = kha.Scheduler.realTime(); } - static function endShadowsLogicProfile() { shadowsLogicTime += kha.Scheduler.realTime() - startShadowsLogicTime - shadowsRenderTime; } - static function endShadowsRenderProfile() { shadowsRenderTime += kha.Scheduler.realTime() - startShadowsRenderTime; } - public static function endFrame() { shadowsLogicTime = 0; shadowsRenderTime = 0; } - #end - - #if (rp_voxels != "Off") - public static function computeVoxelsBegin() { - if (voxel_sh0 == null) - { - voxel_sh0 = path.getComputeShader("voxel_offsetprev"); - - voxel_ta0 = voxel_sh0.getTextureUnit("voxelsB"); - voxel_tb0 = voxel_sh0.getTextureUnit("voxelsOut"); - - voxel_ca0 = voxel_sh0.getConstantLocation("clipmaps"); - voxel_cb0 = voxel_sh0.getConstantLocation("clipmapLevel"); - } - if (voxel_sh1 == null) - { - voxel_sh1 = path.getComputeShader("voxel_temporal"); - voxel_ta1 = voxel_sh1.getTextureUnit("voxels"); - voxel_tb1 = voxel_sh1.getTextureUnit("voxelsB"); - voxel_tc1 = voxel_sh1.getTextureUnit("voxelsOut"); - - voxel_ca1 = voxel_sh1.getConstantLocation("clipmaps"); - voxel_cb1 = voxel_sh1.getConstantLocation("clipmapLevel"); - voxel_cc1 = voxel_sh1.getConstantLocation("envmapStrength"); - - #if (rp_voxels == "Voxel GI") - voxel_td1 = voxel_sh1.getTextureUnit("voxelsSampler"); - voxel_te1 = voxel_sh1.getTextureUnit("SDF"); - voxel_cc1 = voxel_sh1.getConstantLocation("envmapStrength"); - #else - #if lnx_voxelgi_shadows - voxel_te1 = voxel_sh1.getTextureUnit("SDF"); - #end - #end - } - #if (lnx_voxelgi_shadows || rp_voxels == "Voxel GI") - if (voxel_sh2 == null) - { - voxel_sh2 = path.getComputeShader("voxel_sdf_jumpflood"); - voxel_ta2 = voxel_sh2.getTextureUnit("voxelsSDF"); - voxel_tb2 = voxel_sh2.getTextureUnit("voxelsSDFtmp"); - - voxel_ca2 = voxel_sh2.getConstantLocation("clipmaps"); - voxel_cb2 = voxel_sh2.getConstantLocation("clipmapLevel"); - voxel_cc2 = voxel_sh2.getConstantLocation("jump_size"); - } - #end - if (voxel_sh3 == null) - { - #if (rp_voxels == "Voxel AO") - voxel_sh3 = path.getComputeShader("voxel_resolve_ao"); - #else - voxel_sh3 = path.getComputeShader("voxel_resolve_diffuse"); - #end - voxel_ta3 = voxel_sh3.getTextureUnit("voxels"); - voxel_tb3 = voxel_sh3.getTextureUnit("gbufferD"); - voxel_tc3 = voxel_sh3.getTextureUnit("gbuffer0"); - #if (rp_voxels == "Voxel AO") - voxel_td3 = voxel_sh3.getTextureUnit("voxels_ao"); - #else - voxel_td3 = voxel_sh3.getTextureUnit("voxels_diffuse"); - #end - voxel_te3 = voxel_sh3.getTextureUnit("gbuffer1"); - voxel_tf3 = voxel_sh3.getTextureUnit("gbuffer2"); - #if lnx_brdf - voxel_tg3 = voxel_sh3.getTextureUnit("senvmapBrdf"); - #end - #if lnx_radiance - voxel_th3 = voxel_sh3.getTextureUnit("senvmapRadiance"); - #end - voxel_ca3 = voxel_sh3.getConstantLocation("clipmaps"); - voxel_cb3 = voxel_sh3.getConstantLocation("InvVP"); - voxel_cc3 = voxel_sh3.getConstantLocation("eye"); - voxel_cd3 = voxel_sh3.getConstantLocation("postprocess_resolution"); - voxel_ce3 = voxel_sh3.getConstantLocation("envmapStrength"); - #if lnx_irradiance - voxel_cf3 = voxel_sh3.getConstantLocation("shirr"); - #end - #if lnx_radiance - voxel_cg3 = voxel_sh3.getConstantLocation("envmapNumMipmaps"); - #end - #if lnx_envcol - voxel_ch3 = voxel_sh3.getConstantLocation("backgroundCol"); - #end - } - #if (rp_voxels == "Voxel GI") - if (voxel_sh4 == null) - { - voxel_sh4 = path.getComputeShader("voxel_resolve_specular"); - voxel_ta4 = voxel_sh4.getTextureUnit("voxels"); - voxel_tb4 = voxel_sh4.getTextureUnit("gbufferD"); - voxel_tc4 = voxel_sh4.getTextureUnit("gbuffer0"); - voxel_td4 = voxel_sh4.getTextureUnit("voxelsSDF"); - voxel_te4 = voxel_sh4.getTextureUnit("voxels_specular"); - voxel_tf4 = voxel_sh4.getTextureUnit("sveloc"); - voxel_ca4 = voxel_sh4.getConstantLocation("clipmaps"); - voxel_cb4 = voxel_sh4.getConstantLocation("InvVP"); - voxel_cc4 = voxel_sh4.getConstantLocation("eye"); - voxel_cd4 = voxel_sh4.getConstantLocation("postprocess_resolution"); - } - #end - } - - public static function computeVoxelsOffsetPrev() { - var rts = path.renderTargets; - var res = iron.RenderPath.getVoxelRes(); - var clipmaps = iron.RenderPath.clipmaps; - var clipmap = clipmaps[iron.RenderPath.clipmapLevel]; - - kha.compute.Compute.setShader(voxel_sh0); - - kha.compute.Compute.setTexture(voxel_ta0, rts.get("voxelsOut").image, kha.compute.Access.Read); - kha.compute.Compute.setTexture(voxel_tb0, rts.get("voxelsOutB").image, kha.compute.Access.Write); - - var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); - for (i in 0...Main.voxelgiClipmapCount) { - fa[i * 10] = clipmaps[i].voxelSize; - fa[i * 10 + 1] = clipmaps[i].extents.x; - fa[i * 10 + 2] = clipmaps[i].extents.y; - fa[i * 10 + 3] = clipmaps[i].extents.z; - fa[i * 10 + 4] = clipmaps[i].center.x; - fa[i * 10 + 5] = clipmaps[i].center.y; - fa[i * 10 + 6] = clipmaps[i].center.z; - fa[i * 10 + 7] = clipmaps[i].offset_prev.x; - fa[i * 10 + 8] = clipmaps[i].offset_prev.y; - fa[i * 10 + 9] = clipmaps[i].offset_prev.z; - } - - kha.compute.Compute.setFloats(voxel_ca0, fa); - - kha.compute.Compute.setInt(voxel_cb0, iron.RenderPath.clipmapLevel); - - kha.compute.Compute.compute(Std.int(res / 8), Std.int(res / 8), Std.int(res / 8)); - } - - public static function computeVoxelsTemporal() { - var rts = path.renderTargets; - var res = iron.RenderPath.getVoxelRes(); - var camera = iron.Scene.active.camera; - var clipmaps = iron.RenderPath.clipmaps; - var clipmap = clipmaps[iron.RenderPath.clipmapLevel]; - - kha.compute.Compute.setShader(voxel_sh1); - - kha.compute.Compute.setTexture(voxel_ta1, rts.get("voxels").image, kha.compute.Access.Read); - kha.compute.Compute.setTexture(voxel_tb1, rts.get("voxelsOutB").image, kha.compute.Access.Read); - kha.compute.Compute.setTexture(voxel_tc1, rts.get("voxelsOut").image, kha.compute.Access.Write); - #if (rp_voxels == "Voxel GI") - kha.compute.Compute.setSampledTexture(voxel_td1, rts.get("voxelsOutB").image); - kha.compute.Compute.setTexture(voxel_te1, rts.get("voxelsSDF").image, kha.compute.Access.Write); - kha.compute.Compute.setFloat(voxel_cc1, iron.Scene.active.world == null ? 0.0 : iron.Scene.active.world.probe.raw.strength); - #else - #if lnx_voxelgi_shadows - kha.compute.Compute.setTexture(voxel_te1, rts.get("voxelsSDF").image, kha.compute.Access.Write); - #end - #end - - var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); - for (i in 0...Main.voxelgiClipmapCount) { - fa[i * 10] = clipmaps[i].voxelSize; - fa[i * 10 + 1] = clipmaps[i].extents.x; - fa[i * 10 + 2] = clipmaps[i].extents.y; - fa[i * 10 + 3] = clipmaps[i].extents.z; - fa[i * 10 + 4] = clipmaps[i].center.x; - fa[i * 10 + 5] = clipmaps[i].center.y; - fa[i * 10 + 6] = clipmaps[i].center.z; - fa[i * 10 + 7] = clipmaps[i].offset_prev.x; - fa[i * 10 + 8] = clipmaps[i].offset_prev.y; - fa[i * 10 + 9] = clipmaps[i].offset_prev.z; - } - - kha.compute.Compute.setFloats(voxel_ca1, fa); - - kha.compute.Compute.setInt(voxel_cb1, iron.RenderPath.clipmapLevel); - - kha.compute.Compute.setFloat(voxel_cc1, iron.Scene.active.world == null ? 0.0 : iron.Scene.active.world.probe.raw.strength); - - kha.compute.Compute.compute(Std.int(res / 8), Std.int(res / 8), Std.int(res / 8)); - } - - #if (lnx_voxelgi_shadows || (rp_voxels == "Voxel GI")) - public static function computeVoxelsSDF() { - var rts = path.renderTargets; - var res = iron.RenderPath.getVoxelRes(); - var clipmaps = iron.RenderPath.clipmaps; - var clipmap = clipmaps[iron.RenderPath.clipmapLevel]; - - var read_sdf = "voxelsSDF"; - var write_sdf = "voxelsSDFtmp"; - - var passcount = Std.int(Math.ceil(Math.log(res) / Math.log(2.0))); - - for (i in 0...passcount) { - kha.compute.Compute.setShader(voxel_sh2); - - kha.compute.Compute.setTexture(voxel_ta2, rts.get(read_sdf).image, kha.compute.Access.Read); - kha.compute.Compute.setTexture(voxel_tb2, rts.get(write_sdf).image, kha.compute.Access.Write); - - var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); - for (i in 0...Main.voxelgiClipmapCount) { - fa[i * 10] = clipmaps[i].voxelSize; - fa[i * 10 + 1] = clipmaps[i].extents.x; - fa[i * 10 + 2] = clipmaps[i].extents.y; - fa[i * 10 + 3] = clipmaps[i].extents.z; - fa[i * 10 + 4] = clipmaps[i].center.x; - fa[i * 10 + 5] = clipmaps[i].center.y; - fa[i * 10 + 6] = clipmaps[i].center.z; - fa[i * 10 + 7] = clipmaps[i].offset_prev.x; - fa[i * 10 + 8] = clipmaps[i].offset_prev.y; - fa[i * 10 + 9] = clipmaps[i].offset_prev.z; - } - - kha.compute.Compute.setFloats(voxel_ca2, fa); - - kha.compute.Compute.setInt(voxel_cb2, iron.RenderPath.clipmapLevel); - - var jump_size = Math.pow(2.0, passcount - i - 1); - kha.compute.Compute.setFloat(voxel_cc2, jump_size); - - kha.compute.Compute.compute(Std.int(res / 8), Std.int(res / 8), Std.int(res / 8)); - - if (i < passcount - 1) - { - read_sdf = read_sdf == "voxelsSDF" ? "voxelsSDFtmp" : "voxelsSDF"; - write_sdf = write_sdf == "voxelsSDF" ? "voxelsSDFtmp" : "voxelsSDF"; - } - } - } - #end - - #if (rp_voxels == "Voxel AO") - public static function resolveAO() { - var rts = path.renderTargets; - var res = iron.RenderPath.getVoxelRes(); - var camera = iron.Scene.active.camera; - var clipmaps = iron.RenderPath.clipmaps; - var clipmap = clipmaps[iron.RenderPath.clipmapLevel]; - - kha.compute.Compute.setShader(voxel_sh3); - - kha.compute.Compute.setSampledTexture(voxel_ta3, rts.get("voxelsOut").image); - kha.compute.Compute.setSampledTexture(voxel_tb3, rts.get("half").image); - kha.compute.Compute.setSampledTexture(voxel_tc3, rts.get("gbuffer0").image); - kha.compute.Compute.setTexture(voxel_td3, rts.get("voxels_ao").image, kha.compute.Access.Write); - - kha.compute.Compute.setSampledTexture(voxel_te3, rts.get("gbuffer1").image); - #if rp_gbuffer2 - kha.compute.Compute.setSampledTexture(voxel_tf3, rts.get("gbuffer2").image); - #end - #if lnx_brdf - kha.compute.Compute.setSampledTexture(voxel_tg3, iron.Scene.active.embedded.get("brdf.png")); - #end - #if lnx_radiance - kha.compute.Compute.setSampledTexture(voxel_th3, iron.Scene.active.world.probe.radiance); - #end - - var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); - for (i in 0...Main.voxelgiClipmapCount) { - fa[i * 10] = clipmaps[i].voxelSize; - fa[i * 10 + 1] = clipmaps[i].extents.x; - fa[i * 10 + 2] = clipmaps[i].extents.y; - fa[i * 10 + 3] = clipmaps[i].extents.z; - fa[i * 10 + 4] = clipmaps[i].center.x; - fa[i * 10 + 5] = clipmaps[i].center.y; - fa[i * 10 + 6] = clipmaps[i].center.z; - fa[i * 10 + 7] = clipmaps[i].offset_prev.x; - fa[i * 10 + 8] = clipmaps[i].offset_prev.y; - fa[i * 10 + 9] = clipmaps[i].offset_prev.z; - } - - kha.compute.Compute.setFloats(voxel_ca3, fa); - - #if lnx_centerworld - m.setFrom(vmat(camera.V)); - #else - m.setFrom(camera.V); - #end - m.multmat(camera.P); - m.getInverse(m); - - kha.compute.Compute.setMatrix(voxel_cb3, m.self); - - kha.compute.Compute.setFloat3(voxel_cc3, camera.transform.worldx(), camera.transform.worldy(), camera.transform.worldz()); - - var width = iron.App.w(); - var height = iron.App.h(); - var dp = getDisplayp(); - if (dp != null) { // 1080p/.. - if (width > height) { - width = Std.int(width * (dp / height) * Inc.getSuperSampling()); - height = Std.int(dp * Inc.getSuperSampling()); - } - else { - height = Std.int(height * (dp / width) * Inc.getSuperSampling()); - width = Std.int(dp * Inc.getSuperSampling()); - } - } - kha.compute.Compute.setFloat2(voxel_cd3, width, height); - - kha.compute.Compute.setFloat(voxel_ce3, iron.Scene.active.world == null ? 0.0 : iron.Scene.active.world.probe.raw.strength); - #if lnx_irradiance - var irradiance = iron.Scene.active.world == null ? - iron.data.WorldData.getEmptyIrradiance() : - iron.Scene.active.world.probe.irradiance; - kha.compute.Compute.setFloats(voxel_cf3, irradiance); - #end - #if lnx_radiance - kha.compute.Compute.setFloat(voxel_cg3, iron.Scene.active.world != null ? iron.Scene.active.world.probe.raw.radiance_mipmaps + 1 - 2 : 1); - #end - - #if lnx_envcol - var x: kha.FastFloat = 0.0; - var y: kha.FastFloat = 0.0; - var z: kha.FastFloat = 0.0; - - if (camera.data.raw.clear_color != null) { - x = camera.data.raw.clear_color[0]; - y = camera.data.raw.clear_color[1]; - z = camera.data.raw.clear_color[2]; - } - - kha.compute.Compute.setFloat3(voxel_ch3, x, y, z); - #end - - kha.compute.Compute.compute(Std.int((width + 7) / 8), Std.int((height + 7) / 8), 1); - } - #else - public static function resolveDiffuse() { - var rts = path.renderTargets; - var res = iron.RenderPath.getVoxelRes(); - var camera = iron.Scene.active.camera; - var clipmaps = iron.RenderPath.clipmaps; - var clipmap = clipmaps[iron.RenderPath.clipmapLevel]; - - kha.compute.Compute.setShader(voxel_sh3); - - kha.compute.Compute.setSampledTexture(voxel_ta3, rts.get("voxelsOut").image); - kha.compute.Compute.setSampledTexture(voxel_tb3, rts.get("half").image); - kha.compute.Compute.setSampledTexture(voxel_tc3, rts.get("gbuffer0").image); - kha.compute.Compute.setTexture(voxel_td3, rts.get("voxels_diffuse").image, kha.compute.Access.Write); - kha.compute.Compute.setSampledTexture(voxel_te3, rts.get("gbuffer1").image); - #if rp_gbuffer2 - kha.compute.Compute.setSampledTexture(voxel_tf3, rts.get("gbuffer2").image); - #end - #if lnx_brdf - kha.compute.Compute.setSampledTexture(voxel_tg3, iron.Scene.active.embedded.get("brdf.png")); - #end - #if lnx_radiance - kha.compute.Compute.setSampledTexture(voxel_th3, iron.Scene.active.world.probe.radiance); - #end - - var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); - for (i in 0...Main.voxelgiClipmapCount) { - fa[i * 10] = clipmaps[i].voxelSize; - fa[i * 10 + 1] = clipmaps[i].extents.x; - fa[i * 10 + 2] = clipmaps[i].extents.y; - fa[i * 10 + 3] = clipmaps[i].extents.z; - fa[i * 10 + 4] = clipmaps[i].center.x; - fa[i * 10 + 5] = clipmaps[i].center.y; - fa[i * 10 + 6] = clipmaps[i].center.z; - fa[i * 10 + 7] = clipmaps[i].offset_prev.x; - fa[i * 10 + 8] = clipmaps[i].offset_prev.y; - fa[i * 10 + 9] = clipmaps[i].offset_prev.z; - } - - kha.compute.Compute.setFloats(voxel_ca3, fa); - - #if lnx_centerworld - m.setFrom(vmat(camera.V)); - #else - m.setFrom(camera.V); - #end - m.multmat(camera.P); - m.getInverse(m); - - kha.compute.Compute.setMatrix(voxel_cb3, m.self); - - kha.compute.Compute.setFloat3(voxel_cc3, camera.transform.worldx(), camera.transform.worldy(), camera.transform.worldz()); - - var width = iron.App.w(); - var height = iron.App.h(); - var dp = getDisplayp(); - if (dp != null) { // 1080p/.. - if (width > height) { - width = Std.int(width * (dp / height) * Inc.getSuperSampling()); - height = Std.int(dp * Inc.getSuperSampling()); - } - else { - height = Std.int(height * (dp / width) * Inc.getSuperSampling()); - width = Std.int(dp * Inc.getSuperSampling()); - } - } - kha.compute.Compute.setFloat2(voxel_cd3, width, height); - - kha.compute.Compute.setFloat(voxel_ce3, iron.Scene.active.world == null ? 0.0 : iron.Scene.active.world.probe.raw.strength); - #if lnx_irradiance - var irradiance = iron.Scene.active.world == null ? - iron.data.WorldData.getEmptyIrradiance() : - iron.Scene.active.world.probe.irradiance; - kha.compute.Compute.setFloats(voxel_cf3, irradiance); - #end - #if lnx_radiance - kha.compute.Compute.setFloat(voxel_cg3, iron.Scene.active.world != null ? iron.Scene.active.world.probe.raw.radiance_mipmaps + 1 - 2 : 1); - #end - - #if lnx_envcol - var x: kha.FastFloat = 0.0; - var y: kha.FastFloat = 0.0; - var z: kha.FastFloat = 0.0; - - if (camera.data.raw.clear_color != null) { - x = camera.data.raw.clear_color[0]; - y = camera.data.raw.clear_color[1]; - z = camera.data.raw.clear_color[2]; - } - - kha.compute.Compute.setFloat3(voxel_ch3, x, y, z); - #end - - kha.compute.Compute.compute(Std.int((width + 7) / 8), Std.int((height + 7) / 8), 1); - } - - public static function resolveSpecular() { - var rts = path.renderTargets; - var res = iron.RenderPath.getVoxelRes(); - var camera = iron.Scene.active.camera; - var clipmaps = iron.RenderPath.clipmaps; - var clipmap = clipmaps[iron.RenderPath.clipmapLevel]; - - kha.compute.Compute.setShader(voxel_sh4); - - kha.compute.Compute.setSampledTexture(voxel_ta4, rts.get("voxelsOut").image); - kha.compute.Compute.setSampledTexture(voxel_tb4, rts.get("half").image); - kha.compute.Compute.setSampledTexture(voxel_tc4, rts.get("gbuffer0").image); - kha.compute.Compute.setSampledTexture(voxel_td4, rts.get("voxelsSDF").image); - kha.compute.Compute.setTexture(voxel_te4, rts.get("voxels_specular").image, kha.compute.Access.Write); - #if rp_gbuffer2 - kha.compute.Compute.setSampledTexture(voxel_tf4, rts.get("gbuffer2").image); - #end - - var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); - for (i in 0...Main.voxelgiClipmapCount) { - fa[i * 10] = clipmaps[i].voxelSize; - fa[i * 10 + 1] = clipmaps[i].extents.x; - fa[i * 10 + 2] = clipmaps[i].extents.y; - fa[i * 10 + 3] = clipmaps[i].extents.z; - fa[i * 10 + 4] = clipmaps[i].center.x; - fa[i * 10 + 5] = clipmaps[i].center.y; - fa[i * 10 + 6] = clipmaps[i].center.z; - fa[i * 10 + 7] = clipmaps[i].offset_prev.x; - fa[i * 10 + 8] = clipmaps[i].offset_prev.y; - fa[i * 10 + 9] = clipmaps[i].offset_prev.z; - } - - kha.compute.Compute.setFloats(voxel_ca4, fa); - - #if lnx_centerworld - m.setFrom(vmat(camera.V)); - #else - m.setFrom(camera.V); - #end - m.multmat(camera.P); - m.getInverse(m); - - kha.compute.Compute.setMatrix(voxel_cb4, m.self); - - kha.compute.Compute.setFloat3(voxel_cc4, camera.transform.worldx(), camera.transform.worldy(), camera.transform.worldz()); - - var width = iron.App.w(); - var height = iron.App.h(); - var dp = getDisplayp(); - if (dp != null) { // 1080p/.. - if (width > height) { - width = Std.int(width * (dp / height) * Inc.getSuperSampling()); - height = Std.int(dp * Inc.getSuperSampling()); - } - else { - height = Std.int(height * (dp / width) * Inc.getSuperSampling()); - width = Std.int(dp * Inc.getSuperSampling()); - } - } - kha.compute.Compute.setFloat2(voxel_cd4, width, height); - - kha.compute.Compute.compute(Std.int((width + 7) / 8), Std.int((height + 7) / 8), 1); - } - #end // GI - #end // Voxels + static var path: RenderPath; + public static var superSample = 1.0; + + static var pointIndex = 0; + static var spotIndex = 0; + static var lastFrame = -1; + + #if ((rp_voxels != 'Off') && lnx_config) + static var voxelsCreated = false; + #end + + #if (rp_voxels != "Off") + static var voxel_sh0:kha.compute.Shader = null; + static var voxel_sh1:kha.compute.Shader = null; + static var voxel_ta0:kha.compute.TextureUnit; + static var voxel_tb0:kha.compute.TextureUnit; + static var voxel_ca0:kha.compute.ConstantLocation; + static var voxel_cb0:kha.compute.ConstantLocation; + static var voxel_ta1:kha.compute.TextureUnit; + static var voxel_tb1:kha.compute.TextureUnit; + static var voxel_tc1:kha.compute.TextureUnit; + static var m = iron.math.Mat4.identity(); + static var voxel_ca1:kha.compute.ConstantLocation; + static var voxel_cb1:kha.compute.ConstantLocation; + #if (rp_voxels == "Voxel GI") + static var voxel_td1:kha.compute.TextureUnit; + static var voxel_te1:kha.compute.TextureUnit; + #else + #if lnx_voxelgi_shadows + static var voxel_te1:kha.compute.TextureUnit; + #end + #end + #if (lnx_voxelgi_shadows || rp_voxels == "Voxel GI") + static var voxel_sh2:kha.compute.Shader = null; + static var voxel_ta2:kha.compute.TextureUnit; + static var voxel_tb2:kha.compute.TextureUnit; + static var voxel_ca2:kha.compute.ConstantLocation; + static var voxel_cb2:kha.compute.ConstantLocation; + static var voxel_cc2:kha.compute.ConstantLocation; + #end + static var voxel_sh3:kha.compute.Shader = null; + static var voxel_ta3:kha.compute.TextureUnit; + static var voxel_tb3:kha.compute.TextureUnit; + static var voxel_tc3:kha.compute.TextureUnit; + static var voxel_td3:kha.compute.TextureUnit; + static var voxel_te3:kha.compute.TextureUnit; + static var voxel_tf3:kha.compute.TextureUnit; + #if lnx_brdf + static var voxel_tg3:kha.compute.TextureUnit; + #end + #if lnx_radiance + static var voxel_th3:kha.compute.TextureUnit; + #end + static var voxel_ca3:kha.compute.ConstantLocation; + static var voxel_cb3:kha.compute.ConstantLocation; + static var voxel_cc3:kha.compute.ConstantLocation; + static var voxel_cd3:kha.compute.ConstantLocation; + static var voxel_ce3:kha.compute.ConstantLocation; + #if lnx_irradiance + static var voxel_cf3:kha.compute.ConstantLocation; + #end + #if lnx_radiance + static var voxel_cg3:kha.compute.ConstantLocation; + #end + #if lnx_envcol + static var voxel_ch3:kha.compute.ConstantLocation; + #end + #if (rp_voxels == "Voxel GI") + static var voxel_sh4:kha.compute.Shader = null; + static var voxel_ta4:kha.compute.TextureUnit; + static var voxel_tb4:kha.compute.TextureUnit; + static var voxel_tc4:kha.compute.TextureUnit; + static var voxel_td4:kha.compute.TextureUnit; + static var voxel_te4:kha.compute.TextureUnit; + static var voxel_tf4:kha.compute.TextureUnit; + static var voxel_ca4:kha.compute.ConstantLocation; + static var voxel_cb4:kha.compute.ConstantLocation; + static var voxel_cc4:kha.compute.ConstantLocation; + static var voxel_cd4:kha.compute.ConstantLocation; + #end + #end //rp_voxels + + public static function init(_path: RenderPath) { + path = _path; + + #if lnx_config + var config = leenkx.data.Config.raw; + for (l in iron.Scene.active.lights) { + l.data.raw.shadowmap_size = l.data.raw.type == "sun" ? + config.rp_shadowmap_cascade : + config.rp_shadowmap_cube; + } + superSample = config.rp_supersample; + #else + + #if (rp_supersampling == 1.5) + superSample = 1.5; + #elseif (rp_supersampling == 2) + superSample = 2.0; + #elseif (rp_supersampling == 4) + superSample = 4.0; + #end + + #end + } + + #if lnx_shadowmap_atlas + public static function updatePointLightAtlasData(transparent: Bool): Void { + var atlas = transparent ? ShadowMapAtlas.shadowMapAtlasesTransparent.get(ShadowMapAtlas.shadowMapAtlasName("point", true)) : ShadowMapAtlas.shadowMapAtlases.get(ShadowMapAtlas.shadowMapAtlasName("point", false)); + if (atlas != null) { + if(LightObject.pointLightsData == null) { + LightObject.pointLightsData = new kha.arrays.Float32Array( + LightObject.maxLightsCluster * ShadowMapTile.tilesLightType("point") * 4); // max possible visible lights * 6 or 2 (faces) * 4 (xyzw) + } + + var n = iron.Scene.active.lights.length > LightObject.maxLightsCluster ? LightObject.maxLightsCluster : iron.Scene.active.lights.length; + var i = 0; + var j = 0; + for (light in iron.Scene.active.lights) { + if (i >= n) + break; + if (LightObject.discardLightCulled(light)) continue; + if (light.data.raw.type == "point") { + if (!light.data.raw.cast_shadow) { + j += 4 * 6; + continue; + } + for(k in 0...6) { + LightObject.pointLightsData[j ] = light.tileOffsetX[k]; // posx + LightObject.pointLightsData[j + 1] = light.tileOffsetY[k]; // posy + LightObject.pointLightsData[j + 2] = light.tileScale[k]; // tile scale factor relative to atlas + LightObject.pointLightsData[j + 3] = 0; // padding + j += 4; + } + } + i++; + } + } + } + + public static function bindShadowMapAtlas() { + for (atlas in ShadowMapAtlas.shadowMapAtlases) { + path.bindTarget(atlas.target, atlas.target); + } + #if rp_shadowmap_transparent + for (atlas in ShadowMapAtlas.shadowMapAtlasesTransparent) { + path.bindTarget(atlas.target, atlas.target); + } + #end + } + + static function getShadowMapAtlas(atlas:ShadowMapAtlas, transparent: Bool):String { + inline function createDepthTarget(name: String, size: Int) { + var t = new RenderTargetRaw(); + t.name = name; + t.width = t.height = size; + t.format = transparent ? "RGBA64" : "DEPTH16"; + return path.createRenderTarget(t); + } + + var rt = path.renderTargets.get(atlas.target); + // Create shadowmap atlas texture on the fly and replace existing on size change + if (rt == null) { + rt = createDepthTarget(atlas.target, atlas.sizew); + } + else if (atlas.updateRenderTarget) { + atlas.updateRenderTarget = false; + // Resize shadow map + rt.unload(); + rt = createDepthTarget(atlas.target, atlas.sizew); + } + return atlas.target; + } + + public static function drawShadowMapAtlas() { + #if rp_shadowmap + #if rp_probes + // Share shadow map with probe + if (lastFrame == RenderPath.active.frame) + return; + lastFrame = RenderPath.active.frame; + #end + + #if lnx_debug + beginShadowsLogicProfile(); + // reset data on rejected lights + for (atlas in ShadowMapAtlas.shadowMapAtlases) { + atlas.rejectedLights = []; + } + #if rp_shadowmap_transparent + for (atlas in ShadowMapAtlas.shadowMapAtlasesTransparent) { + atlas.rejectedLights = []; + } + #end + #end + + for (light in iron.Scene.active.lights) { + if (!light.lightInAtlas && !light.culledLight && light.visible && light.shadowMapScale > 0.0 + && light.data.raw.strength > 0.0 && light.data.raw.cast_shadow) { + ShadowMapAtlas.addLight(light, false); + } + #if rp_shadowmap_transparent + if (!light.lightInAtlasTransparent && !light.culledLight && light.visible && light.shadowMapScale > 0.0 + && light.data.raw.strength > 0.0 && light.data.raw.cast_shadow) { + ShadowMapAtlas.addLight(light, true); + } + #end + } + // update point light data before rendering + updatePointLightAtlasData(false); + #if rp_shadowmap_transparent + updatePointLightAtlasData(true); + #end + + for (atlas in ShadowMapAtlas.shadowMapAtlases) { + var tilesToRemove = []; + #if lnx_shadowmap_atlas_lod + var tilesToChangeSize = []; + #end + + var shadowmap = getShadowMapAtlas(atlas, false); + path.setTargetStream(shadowmap); + + path.clearTarget(null, 1.0); + + for (tile in atlas.activeTiles) { + if (tile.light == null || !tile.light.visible || tile.light.culledLight + || !tile.light.data.raw.cast_shadow || tile.light.data.raw.strength == 0) { + tile.unlockLight = true; + tilesToRemove.push(tile); + continue; + } + + #if lnx_shadowmap_atlas_lod + var newTileSize = atlas.getTileSize(tile.light.shadowMapScale); + if (newTileSize != tile.size) { + if (newTileSize == 0) { + tile.unlockLight = true; + tilesToRemove.push(tile); + continue; + } + // queue for size change + tile.newTileSize = newTileSize; + tilesToChangeSize.push(tile); + } + #end + // set the tile offset for this tile and every linked tile to this one + var j = 0; + tile.forEachTileLinked(function (lTile) { + tile.light.tileOffsetX[j] = lTile.coordsX / atlas.sizew; + tile.light.tileOffsetY[j] = lTile.coordsY / atlas.sizew; + tile.light.tileScale[j] = lTile.size / atlas.sizew; + j++; + }); + // set shadowmap size for uniform + tile.light.data.raw.shadowmap_size = atlas.sizew; + + path.light = tile.light; + + var face = 0; + var faces = ShadowMapTile.tilesLightType(tile.light.data.raw.type); + + #if lnx_debug + beginShadowsRenderProfile(); + #end + tile.forEachTileLinked(function (lTile) { + if (faces > 1) { + #if lnx_csm + switch (tile.light.data.raw.type) { + case "sun": tile.light.setCascade(iron.Scene.active.camera, face); + case "point": path.currentFace = face; + } + #else + path.currentFace = face; + #end + face++; + } + path.setCurrentViewportWithOffset(lTile.size, lTile.size, lTile.coordsX, lTile.coordsY); + + path.drawMeshesStream("shadowmap"); + }); + #if lnx_debug + endShadowsRenderProfile(); + #end + + path.currentFace = -1; + } + path.endStream(); + } + + #if rp_shadowmap_transparent + for (atlas in ShadowMapAtlas.shadowMapAtlasesTransparent) { + var tilesToRemove = []; + #if lnx_shadowmap_atlas_lod + var tilesToChangeSize = []; + #end + + var shadowmap = getShadowMapAtlas(atlas, true); + path.setTargetStream(shadowmap); + + path.clearTarget(0xffffff, 0.0); + + for (tile in atlas.activeTiles) { + if (tile.light == null || !tile.light.visible || tile.light.culledLight + || !tile.light.data.raw.cast_shadow || tile.light.data.raw.strength == 0) { + tile.unlockLight = true; + tilesToRemove.push(tile); + continue; + } + + #if lnx_shadowmap_atlas_lod + var newTileSize = atlas.getTileSize(tile.light.shadowMapScale); + if (newTileSize != tile.size) { + if (newTileSize == 0) { + tile.unlockLight = true; + tilesToRemove.push(tile); + continue; + } + // queue for size change + tile.newTileSize = newTileSize; + tilesToChangeSize.push(tile); + } + #end + // set the tile offset for this tile and every linked tile to this one + var j = 0; + tile.forEachTileLinked(function (lTile) { + tile.light.tileOffsetX[j] = lTile.coordsX / atlas.sizew; + tile.light.tileOffsetY[j] = lTile.coordsY / atlas.sizew; + tile.light.tileScale[j] = lTile.size / atlas.sizew; + j++; + }); + // set shadowmap size for uniform + tile.light.data.raw.shadowmap_size = atlas.sizew; + + path.light = tile.light; + + var face = 0; + var faces = ShadowMapTile.tilesLightType(tile.light.data.raw.type); + + #if lnx_debug + beginShadowsRenderProfile(); + #end + tile.forEachTileLinked(function (lTile) { + if (faces > 1) { + #if lnx_csm + switch (tile.light.data.raw.type) { + case "sun": tile.light.setCascade(iron.Scene.active.camera, face); + case "point": path.currentFace = face; + } + #else + path.currentFace = face; + #end + face++; + } + path.setCurrentViewportWithOffset(lTile.size, lTile.size, lTile.coordsX, lTile.coordsY); + + path.drawMeshesStream("shadowmap_transparent"); + }); + #if lnx_debug + endShadowsRenderProfile(); + #end + + path.currentFace = -1; + } + path.endStream(); + + #if lnx_shadowmap_atlas_lod + for (tile in tilesToChangeSize) { + tilesToRemove.push(tile); + + var newTile = ShadowMapTile.assignTiles(tile.light, atlas, tile); + if (newTile != null) + atlas.activeTiles.push(newTile); + } + // update point light data after changing size of tiles to avoid render issues + updatePointLightAtlasData(false); + // update point light data after changing size of tiles to avoid render issues + updatePointLightAtlasData(true); + #end + + for (tile in tilesToRemove) { + atlas.activeTiles.remove(tile); + tile.freeTile(); + } + } + #end + #end + } + #else + public static function bindShadowMap() { + for (l in iron.Scene.active.lights) { + if (!l.visible || l.data.raw.type != "sun") continue; + var n = "shadowMap"; + path.bindTarget(n, n); + var n = "shadowMapTransparent"; + path.bindTarget(n, n); + break; + } + for (i in 0...pointIndex) { + var n = "shadowMapPoint[" + i + "]"; + path.bindTarget(n, n); + var n = "shadowMapPointTransparent[" + i + "]"; + path.bindTarget(n, n); + } + for (i in 0...spotIndex) { + var n = "shadowMapSpot[" + i + "]"; + path.bindTarget(n, n); + var n = "shadowMapSpotTransparent[" + i + "]"; + path.bindTarget(n, n); + } + } + + static function shadowMapName(light: LightObject, transparent: Bool): String { + switch (light.data.raw.type) { + case "sun": + return transparent ? "shadowMapTransparent" : "shadowMap"; + case "point": + return transparent ? "shadowMapPointTransparent[" + pointIndex + "]" : "shadowMapPoint[" + pointIndex + "]"; + default: + return transparent ? "shadowMapSpotTransparent[" + spotIndex + "]" : "shadowMapSpot[" + spotIndex + "]"; + } + } + + static function getShadowMap(l: iron.object.LightObject, transparent: Bool): String { + var target = shadowMapName(l, transparent); + var rt = path.renderTargets.get(target); + // Create shadowmap on the fly + if (rt == null) { + if (path.light.data.raw.shadowmap_cube) { + // Cubemap size + var size = path.light.data.raw.shadowmap_size; + var t = new RenderTargetRaw(); + t.name = target; + t.width = size; + t.height = size; + t.format = transparent ? "RGBA64" : "DEPTH16"; + t.is_cubemap = true; + rt = path.createRenderTarget(t); + } + else { // Non-cube sm + var sizew = path.light.data.raw.shadowmap_size; + var sizeh = sizew; + #if lnx_csm // Cascades - atlas on x axis + if (l.data.raw.type == "sun") { + sizew = sizew * iron.object.LightObject.cascadeCount; + } + #end + var t = new RenderTargetRaw(); + t.name = target; + t.width = sizew; + t.height = sizeh; + t.format = transparent ? "RGBA64" : "DEPTH16"; + rt = path.createRenderTarget(t); + } + } + return target; + } + + public static function drawShadowMap() { + #if (rp_shadowmap) + + #if rp_probes + // Share shadow map with probe + if (lastFrame == RenderPath.active.frame) return; + lastFrame = RenderPath.active.frame; + #end + + pointIndex = 0; + spotIndex = 0; + for (l in iron.Scene.active.lights) { + if (!l.visible) continue; + + path.light = l; + var shadowmap = Inc.getShadowMap(l, false); + var faces = l.data.raw.shadowmap_cube ? 6 : 1; + for (i in 0...faces) { + if (faces > 1) path.currentFace = i; + path.setTarget(shadowmap); + path.clearTarget(null, 1.0); + if (l.data.raw.cast_shadow) { + path.drawMeshes("shadowmap"); + } + } + path.currentFace = -1; + + if (l.data.raw.type == "point") pointIndex++; + else if (l.data.raw.type == "spot" || l.data.raw.type == "area") spotIndex++; + } + + #if rp_shadowmap_transparent + pointIndex = 0; + spotIndex = 0; + for (l in iron.Scene.active.lights) { + if (!l.visible) continue; + + path.light = l; + var shadowmap_transparent = Inc.getShadowMap(l, true); + var faces = l.data.raw.shadowmap_cube ? 6 : 1; + for (i in 0...faces) { + if (faces > 1) path.currentFace = i; + path.setTarget(shadowmap_transparent); + path.clearTarget(0xffffff, 0.0); + if (l.data.raw.cast_shadow) { + path.drawMeshes("shadowmap_transparent"); + } + } + path.currentFace = -1; + + if (l.data.raw.type == "point") pointIndex++; + else if (l.data.raw.type == "spot" || l.data.raw.type == "area") spotIndex++; + } + #end + #end // rp_shadowmap + } + #end + + public static function applyConfig() { + #if lnx_config + var config = leenkx.data.Config.raw; + // Resize shadow map + var l = path.light; + if (l.data.raw.type == "sun" && l.data.raw.shadowmap_size != config.rp_shadowmap_cascade) { + l.data.raw.shadowmap_size = config.rp_shadowmap_cascade; + var rt = path.renderTargets.get("shadowMap"); + if (rt != null) { + rt.unload(); + path.renderTargets.remove("shadowMap"); + } + } + else if (l.data.raw.shadowmap_size != config.rp_shadowmap_cube) { + l.data.raw.shadowmap_size = config.rp_shadowmap_cube; + var rt = path.renderTargets.get("shadowMapCube"); + if (rt != null) { + rt.unload(); + path.renderTargets.remove("shadowMapCube"); + } + } + if (superSample != config.rp_supersample) { + superSample = config.rp_supersample; + for (rt in path.renderTargets) { + if (rt.raw.width == 0 && rt.raw.scale != null) { + rt.raw.scale = getSuperSampling(); + } + } + path.resize(); + } + // Init voxels + #if (rp_voxels != 'Off') + if (!voxelsCreated) initGI(); + #end + #end // lnx_config + } + + #if (rp_translucency) + public static function initTranslucency() { + path.createDepthBuffer("main", "DEPTH24"); + + var t = new RenderTargetRaw(); + t.name = "accum"; + t.width = 0; + t.height = 0; + t.displayp = getDisplayp(); + t.format = "RGBA64"; + t.scale = getSuperSampling(); + t.depth_buffer = "main"; + path.createRenderTarget(t); + + var t = new RenderTargetRaw(); + t.name = "revealage"; + t.width = 0; + t.height = 0; + t.displayp = getDisplayp(); + t.format = "R16"; + t.scale = getSuperSampling(); + t.depth_buffer = "main"; + path.createRenderTarget(t); + + path.loadShader("shader_datas/translucent_resolve/translucent_resolve"); + } + + public static function drawTranslucency(target: String) { + path.setTarget("accum"); + path.clearTarget(0xff000000); + path.setTarget("revealage"); + path.clearTarget(0xffffffff); + path.setTarget("accum", ["revealage"]); + + #if rp_shadowmap + { + #if lnx_shadowmap_atlas + bindShadowMapAtlas(); + #else + bindShadowMap(); + #end + } + #end + + #if (rp_voxels != "Off") + path.bindTarget("voxelsOut", "voxels"); + #if (rp_voxels == "Voxel GI" || lnx_voxelgi_shadows) + path.bindTarget("voxelsSDF", "voxelsSDF"); + #end + #end + + #if rp_ssrs + path.bindTarget("_main", "gbufferD"); + #end + + path.drawMeshes("translucent"); + + #if rp_render_to_texture + { + path.setTarget(target); + } + #else + { + path.setTarget(""); + } + #end + + path.bindTarget("accum", "gbuffer0"); + path.bindTarget("revealage", "gbuffer1"); + path.drawShader("shader_datas/translucent_resolve/translucent_resolve"); + } + #end + + #if rp_bloom + public static inline function drawBloom(srcRTName: String, downsampler: Downsampler, upsampler: Upsampler) { + if (leenkx.data.Config.raw.rp_bloom != false) { + // This can result in little jumps in the perceived bloom radius + // when resizing the window because numMips might change, but + // all implementations using this approach have the same problem + // (including Eevee) + final minDim = Math.min(path.currentW, path.currentH); + final logMinDim = Math.max(1.0, Helper.log2(minDim) + (Main.bloomRadius - 8.0)); + final numMips = Std.int(logMinDim); + + // Sample scale for upsampling, 0.5 to use half-texel steps, + // use fraction of logMinDim to make the visual jumps + // described above less visible + Postprocess.bloom_uniforms[3] = 0.5 + logMinDim - numMips; + + downsampler.dispatch(srcRTName, numMips); + upsampler.dispatch(srcRTName, numMips); + } + } + #end + + #if (rp_voxels != 'Off') + public static function initGI(tname = "voxels") { + var t = new RenderTargetRaw(); + t.name = tname; + + #if lnx_config + var config = leenkx.data.Config.raw; + if (config.rp_voxels != true || voxelsCreated) return; + voxelsCreated = true; + #end + + var res = iron.RenderPath.getVoxelRes(); + var resZ = iron.RenderPath.getVoxelResZ(); + + if (t.name == "voxels_diffuse" || t.name == "voxels_specular" || t.name == "voxels_ao") { + t.width = 0; + t.height = 0; + t.displayp = getDisplayp(); + t.format = "RGBA32"; + } + else { + if (t.name == "voxelsSDF" || t.name == "voxelsSDFtmp") { + t.format = "R8"; + t.width = res; + t.height = res * Main.voxelgiClipmapCount; + t.depth = res; + } + else { + #if (rp_voxels == "Voxel AO") + { + if (t.name == "voxelsOut" || t.name == "voxelsOutB") { + t.format = "R8"; + t.width = res * (6 + 16); + t.height = res * Main.voxelgiClipmapCount; + t.depth = res; + } + else { + t.format = "R32UI"; + t.width = res * 6; + t.height = res; + t.depth = res * 2; + } + } + #else + { + if (t.name == "voxelsOut" || t.name == "voxelsOutB") { + t.format = "RGBA64"; + t.width = res * (6 + 16); + t.height = res * Main.voxelgiClipmapCount; + t.depth = res; + } + else { + t.format = "R32UI"; + t.width = res * 6; + t.height = res; + t.depth = res * 16; + } + } + #end + } + } + t.is_image = true; + t.mipmaps = true; + path.createRenderTarget(t); + } + #end + + public static inline function getCubeSize(): Int { + #if (rp_shadowmap_cube == 256) + return 256; + #elseif (rp_shadowmap_cube == 512) + return 512; + #elseif (rp_shadowmap_cube == 1024) + return 1024; + #elseif (rp_shadowmap_cube == 2048) + return 2048; + #elseif (rp_shadowmap_cube == 4096) + return 4096; + #else + return 0; + #end + } + + public static inline function getCascadeSize(): Int { + #if (rp_shadowmap_cascade == 256) + return 256; + #elseif (rp_shadowmap_cascade == 512) + return 512; + #elseif (rp_shadowmap_cascade == 1024) + return 1024; + #elseif (rp_shadowmap_cascade == 2048) + return 2048; + #elseif (rp_shadowmap_cascade == 4096) + return 4096; + #elseif (rp_shadowmap_cascade == 8192) + return 8192; + #elseif (rp_shadowmap_cascade == 16384) + return 16384; + #else + return 0; + #end + } + + public static inline function getSuperSampling(): Float { + return superSample; + } + + public static inline function getHdrFormat(): String { + #if rp_hdr + return "RGBA64"; + #else + return "RGBA32"; + #end + } + + public static inline function getDisplayp(): Null { + #if rp_resolution_filter // Custom resolution set + return Main.resolutionSize; + #else + return null; + #end + } + + #if lnx_debug + public static var shadowsLogicTime = 0.0; + public static var shadowsRenderTime = 0.0; + static var startShadowsLogicTime = 0.0; + static var startShadowsRenderTime = 0.0; + static var callBackSetup = false; + static function setupEndFrameCallback() { + if (!callBackSetup) { + callBackSetup = true; + iron.App.endFrameCallbacks.push(endFrame); + } + } + static function beginShadowsLogicProfile() { setupEndFrameCallback(); startShadowsLogicTime = kha.Scheduler.realTime(); } + static function beginShadowsRenderProfile() { startShadowsRenderTime = kha.Scheduler.realTime(); } + static function endShadowsLogicProfile() { shadowsLogicTime += kha.Scheduler.realTime() - startShadowsLogicTime - shadowsRenderTime; } + static function endShadowsRenderProfile() { shadowsRenderTime += kha.Scheduler.realTime() - startShadowsRenderTime; } + public static function endFrame() { shadowsLogicTime = 0; shadowsRenderTime = 0; } + #end + + #if (rp_voxels != "Off") + public static function computeVoxelsBegin() { + if (voxel_sh0 == null) + { + voxel_sh0 = path.getComputeShader("voxel_offsetprev"); + + voxel_ta0 = voxel_sh0.getTextureUnit("voxelsB"); + voxel_tb0 = voxel_sh0.getTextureUnit("voxelsOut"); + + voxel_ca0 = voxel_sh0.getConstantLocation("clipmaps"); + voxel_cb0 = voxel_sh0.getConstantLocation("clipmapLevel"); + } + if (voxel_sh1 == null) + { + voxel_sh1 = path.getComputeShader("voxel_temporal"); + voxel_ta1 = voxel_sh1.getTextureUnit("voxels"); + voxel_tb1 = voxel_sh1.getTextureUnit("voxelsB"); + voxel_tc1 = voxel_sh1.getTextureUnit("voxelsOut"); + + voxel_ca1 = voxel_sh1.getConstantLocation("clipmaps"); + voxel_cb1 = voxel_sh1.getConstantLocation("clipmapLevel"); + + #if (rp_voxels == "Voxel GI") + voxel_td1 = voxel_sh1.getTextureUnit("voxelsSampler"); + voxel_te1 = voxel_sh1.getTextureUnit("SDF"); + #else + #if lnx_voxelgi_shadows + voxel_te1 = voxel_sh1.getTextureUnit("SDF"); + #end + #end + } + #if (lnx_voxelgi_shadows || rp_voxels == "Voxel GI") + if (voxel_sh2 == null) + { + voxel_sh2 = path.getComputeShader("voxel_sdf_jumpflood"); + voxel_ta2 = voxel_sh2.getTextureUnit("voxelsSDF"); + voxel_tb2 = voxel_sh2.getTextureUnit("voxelsSDFtmp"); + + voxel_ca2 = voxel_sh2.getConstantLocation("clipmaps"); + voxel_cb2 = voxel_sh2.getConstantLocation("clipmapLevel"); + voxel_cc2 = voxel_sh2.getConstantLocation("jump_size"); + } + #end + if (voxel_sh3 == null) + { + #if (rp_voxels == "Voxel AO") + voxel_sh3 = path.getComputeShader("voxel_resolve_ao"); + #else + voxel_sh3 = path.getComputeShader("voxel_resolve_diffuse"); + #end + voxel_ta3 = voxel_sh3.getTextureUnit("voxels"); + voxel_tb3 = voxel_sh3.getTextureUnit("gbufferD"); + voxel_tc3 = voxel_sh3.getTextureUnit("gbuffer0"); + #if (rp_voxels == "Voxel AO") + voxel_td3 = voxel_sh3.getTextureUnit("voxels_ao"); + #else + voxel_td3 = voxel_sh3.getTextureUnit("voxels_diffuse"); + #end + voxel_te3 = voxel_sh3.getTextureUnit("gbuffer1"); + voxel_tf3 = voxel_sh3.getTextureUnit("gbuffer2"); + #if lnx_brdf + voxel_tg3 = voxel_sh3.getTextureUnit("senvmapBrdf"); + #end + #if lnx_radiance + voxel_th3 = voxel_sh3.getTextureUnit("senvmapRadiance"); + #end + voxel_ca3 = voxel_sh3.getConstantLocation("clipmaps"); + voxel_cb3 = voxel_sh3.getConstantLocation("InvVP"); + voxel_cc3 = voxel_sh3.getConstantLocation("eye"); + voxel_cd3 = voxel_sh3.getConstantLocation("postprocess_resolution"); + voxel_ce3 = voxel_sh3.getConstantLocation("envmapStrength"); + #if lnx_irradiance + voxel_cf3 = voxel_sh3.getConstantLocation("shirr"); + #end + #if lnx_radiance + voxel_cg3 = voxel_sh3.getConstantLocation("envmapNumMipmaps"); + #end + #if lnx_envcol + voxel_ch3 = voxel_sh3.getConstantLocation("backgroundCol"); + #end + } + #if (rp_voxels == "Voxel GI") + if (voxel_sh4 == null) + { + voxel_sh4 = path.getComputeShader("voxel_resolve_specular"); + voxel_ta4 = voxel_sh4.getTextureUnit("voxels"); + voxel_tb4 = voxel_sh4.getTextureUnit("gbufferD"); + voxel_tc4 = voxel_sh4.getTextureUnit("gbuffer0"); + voxel_td4 = voxel_sh4.getTextureUnit("voxelsSDF"); + voxel_te4 = voxel_sh4.getTextureUnit("voxels_specular"); + voxel_tf4 = voxel_sh4.getTextureUnit("sveloc"); + voxel_ca4 = voxel_sh4.getConstantLocation("clipmaps"); + voxel_cb4 = voxel_sh4.getConstantLocation("InvVP"); + voxel_cc4 = voxel_sh4.getConstantLocation("eye"); + voxel_cd4 = voxel_sh4.getConstantLocation("postprocess_resolution"); + } + #end + } + + public static function computeVoxelsOffsetPrev() { + var rts = path.renderTargets; + var res = iron.RenderPath.getVoxelRes(); + var clipmaps = iron.RenderPath.clipmaps; + var clipmap = clipmaps[iron.RenderPath.clipmapLevel]; + + kha.compute.Compute.setShader(voxel_sh0); + + kha.compute.Compute.setTexture(voxel_ta0, rts.get("voxelsOut").image, kha.compute.Access.Read); + kha.compute.Compute.setTexture(voxel_tb0, rts.get("voxelsOutB").image, kha.compute.Access.Write); + + var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); + for (i in 0...Main.voxelgiClipmapCount) { + fa[i * 10] = clipmaps[i].voxelSize; + fa[i * 10 + 1] = clipmaps[i].extents.x; + fa[i * 10 + 2] = clipmaps[i].extents.y; + fa[i * 10 + 3] = clipmaps[i].extents.z; + fa[i * 10 + 4] = clipmaps[i].center.x; + fa[i * 10 + 5] = clipmaps[i].center.y; + fa[i * 10 + 6] = clipmaps[i].center.z; + fa[i * 10 + 7] = clipmaps[i].offset_prev.x; + fa[i * 10 + 8] = clipmaps[i].offset_prev.y; + fa[i * 10 + 9] = clipmaps[i].offset_prev.z; + } + + kha.compute.Compute.setFloats(voxel_ca0, fa); + + kha.compute.Compute.setInt(voxel_cb0, iron.RenderPath.clipmapLevel); + + kha.compute.Compute.compute(Std.int(res / 8), Std.int(res / 8), Std.int(res / 8)); + } + + public static function computeVoxelsTemporal() { + var rts = path.renderTargets; + var res = iron.RenderPath.getVoxelRes(); + var camera = iron.Scene.active.camera; + var clipmaps = iron.RenderPath.clipmaps; + var clipmap = clipmaps[iron.RenderPath.clipmapLevel]; + + kha.compute.Compute.setShader(voxel_sh1); + + kha.compute.Compute.setTexture(voxel_ta1, rts.get("voxels").image, kha.compute.Access.Read); + kha.compute.Compute.setTexture(voxel_tb1, rts.get("voxelsOutB").image, kha.compute.Access.Read); + kha.compute.Compute.setTexture(voxel_tc1, rts.get("voxelsOut").image, kha.compute.Access.Write); + #if (rp_voxels == "Voxel GI") + kha.compute.Compute.setSampledTexture(voxel_td1, rts.get("voxelsOutB").image); + kha.compute.Compute.setTexture(voxel_te1, rts.get("voxelsSDF").image, kha.compute.Access.Write); + #else + #if lnx_voxelgi_shadows + kha.compute.Compute.setTexture(voxel_te1, rts.get("voxelsSDF").image, kha.compute.Access.Write); + #end + #end + + var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); + for (i in 0...Main.voxelgiClipmapCount) { + fa[i * 10] = clipmaps[i].voxelSize; + fa[i * 10 + 1] = clipmaps[i].extents.x; + fa[i * 10 + 2] = clipmaps[i].extents.y; + fa[i * 10 + 3] = clipmaps[i].extents.z; + fa[i * 10 + 4] = clipmaps[i].center.x; + fa[i * 10 + 5] = clipmaps[i].center.y; + fa[i * 10 + 6] = clipmaps[i].center.z; + fa[i * 10 + 7] = clipmaps[i].offset_prev.x; + fa[i * 10 + 8] = clipmaps[i].offset_prev.y; + fa[i * 10 + 9] = clipmaps[i].offset_prev.z; + } + + kha.compute.Compute.setFloats(voxel_ca1, fa); + + kha.compute.Compute.setInt(voxel_cb1, iron.RenderPath.clipmapLevel); + + kha.compute.Compute.compute(Std.int(res / 8), Std.int(res / 8), Std.int(res / 8)); + } + + #if (lnx_voxelgi_shadows || (rp_voxels == "Voxel GI")) + public static function computeVoxelsSDF() { + var rts = path.renderTargets; + var res = iron.RenderPath.getVoxelRes(); + var clipmaps = iron.RenderPath.clipmaps; + var clipmap = clipmaps[iron.RenderPath.clipmapLevel]; + + var read_sdf = "voxelsSDF"; + var write_sdf = "voxelsSDFtmp"; + + var passcount = Std.int(Math.ceil(Math.log(res) / Math.log(2.0))); + + for (i in 0...passcount) { + kha.compute.Compute.setShader(voxel_sh2); + + kha.compute.Compute.setTexture(voxel_ta2, rts.get(read_sdf).image, kha.compute.Access.Read); + kha.compute.Compute.setTexture(voxel_tb2, rts.get(write_sdf).image, kha.compute.Access.Write); + + var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); + for (i in 0...Main.voxelgiClipmapCount) { + fa[i * 10] = clipmaps[i].voxelSize; + fa[i * 10 + 1] = clipmaps[i].extents.x; + fa[i * 10 + 2] = clipmaps[i].extents.y; + fa[i * 10 + 3] = clipmaps[i].extents.z; + fa[i * 10 + 4] = clipmaps[i].center.x; + fa[i * 10 + 5] = clipmaps[i].center.y; + fa[i * 10 + 6] = clipmaps[i].center.z; + fa[i * 10 + 7] = clipmaps[i].offset_prev.x; + fa[i * 10 + 8] = clipmaps[i].offset_prev.y; + fa[i * 10 + 9] = clipmaps[i].offset_prev.z; + } + + kha.compute.Compute.setFloats(voxel_ca2, fa); + + kha.compute.Compute.setInt(voxel_cb2, iron.RenderPath.clipmapLevel); + + var jump_size = Math.pow(2.0, passcount - i - 1); + kha.compute.Compute.setFloat(voxel_cc2, jump_size); + + kha.compute.Compute.compute(Std.int(res / 8), Std.int(res / 8), Std.int(res / 8)); + + if (i < passcount - 1) + { + read_sdf = read_sdf == "voxelsSDF" ? "voxelsSDFtmp" : "voxelsSDF"; + write_sdf = write_sdf == "voxelsSDF" ? "voxelsSDFtmp" : "voxelsSDF"; + } + } + } + #end + + #if (rp_voxels == "Voxel AO") + public static function resolveAO() { + var rts = path.renderTargets; + var res = iron.RenderPath.getVoxelRes(); + var camera = iron.Scene.active.camera; + var clipmaps = iron.RenderPath.clipmaps; + var clipmap = clipmaps[iron.RenderPath.clipmapLevel]; + + kha.compute.Compute.setShader(voxel_sh3); + + kha.compute.Compute.setSampledTexture(voxel_ta3, rts.get("voxelsOut").image); + kha.compute.Compute.setSampledTexture(voxel_tb3, rts.get("half").image); + kha.compute.Compute.setSampledTexture(voxel_tc3, rts.get("gbuffer0").image); + kha.compute.Compute.setTexture(voxel_td3, rts.get("voxels_ao").image, kha.compute.Access.Write); + + kha.compute.Compute.setSampledTexture(voxel_te3, rts.get("gbuffer1").image); + #if rp_gbuffer2 + kha.compute.Compute.setSampledTexture(voxel_tf3, rts.get("gbuffer2").image); + #end + #if lnx_brdf + kha.compute.Compute.setSampledTexture(voxel_tg3, iron.Scene.active.embedded.get("brdf.png")); + #end + #if lnx_radiance + kha.compute.Compute.setSampledTexture(voxel_th3, iron.Scene.active.world.probe.radiance); + #end + + var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); + for (i in 0...Main.voxelgiClipmapCount) { + fa[i * 10] = clipmaps[i].voxelSize; + fa[i * 10 + 1] = clipmaps[i].extents.x; + fa[i * 10 + 2] = clipmaps[i].extents.y; + fa[i * 10 + 3] = clipmaps[i].extents.z; + fa[i * 10 + 4] = clipmaps[i].center.x; + fa[i * 10 + 5] = clipmaps[i].center.y; + fa[i * 10 + 6] = clipmaps[i].center.z; + fa[i * 10 + 7] = clipmaps[i].offset_prev.x; + fa[i * 10 + 8] = clipmaps[i].offset_prev.y; + fa[i * 10 + 9] = clipmaps[i].offset_prev.z; + } + + kha.compute.Compute.setFloats(voxel_ca3, fa); + + #if lnx_centerworld + m.setFrom(vmat(camera.V)); + #else + m.setFrom(camera.V); + #end + m.multmat(camera.P); + m.getInverse(m); + + kha.compute.Compute.setMatrix(voxel_cb3, m.self); + + kha.compute.Compute.setFloat3(voxel_cc3, camera.transform.worldx(), camera.transform.worldy(), camera.transform.worldz()); + + var width = iron.App.w(); + var height = iron.App.h(); + var dp = getDisplayp(); + if (dp != null) { // 1080p/.. + if (width > height) { + width = Std.int(width * (dp / height) * Inc.getSuperSampling()); + height = Std.int(dp * Inc.getSuperSampling()); + } + else { + height = Std.int(height * (dp / width) * Inc.getSuperSampling()); + width = Std.int(dp * Inc.getSuperSampling()); + } + } + kha.compute.Compute.setFloat2(voxel_cd3, width, height); + + kha.compute.Compute.setFloat(voxel_ce3, iron.Scene.active.world == null ? 0.0 : iron.Scene.active.world.probe.raw.strength); + #if lnx_irradiance + var irradiance = iron.Scene.active.world == null ? + iron.data.WorldData.getEmptyIrradiance() : + iron.Scene.active.world.probe.irradiance; + kha.compute.Compute.setFloats(voxel_cf3, irradiance); + #end + #if lnx_radiance + kha.compute.Compute.setFloat(voxel_cg3, iron.Scene.active.world != null ? iron.Scene.active.world.probe.raw.radiance_mipmaps + 1 - 2 : 1); + #end + + #if lnx_envcol + var x: kha.FastFloat = 0.0; + var y: kha.FastFloat = 0.0; + var z: kha.FastFloat = 0.0; + + if (camera.data.raw.clear_color != null) { + x = camera.data.raw.clear_color[0]; + y = camera.data.raw.clear_color[1]; + z = camera.data.raw.clear_color[2]; + } + + kha.compute.Compute.setFloat3(voxel_ch3, x, y, z); + #end + + kha.compute.Compute.compute(Std.int((width + 7) / 8), Std.int((height + 7) / 8), 1); + } + #else + public static function resolveDiffuse() { + var rts = path.renderTargets; + var res = iron.RenderPath.getVoxelRes(); + var camera = iron.Scene.active.camera; + var clipmaps = iron.RenderPath.clipmaps; + var clipmap = clipmaps[iron.RenderPath.clipmapLevel]; + + kha.compute.Compute.setShader(voxel_sh3); + + kha.compute.Compute.setSampledTexture(voxel_ta3, rts.get("voxelsOut").image); + kha.compute.Compute.setSampledTexture(voxel_tb3, rts.get("half").image); + kha.compute.Compute.setSampledTexture(voxel_tc3, rts.get("gbuffer0").image); + kha.compute.Compute.setTexture(voxel_td3, rts.get("voxels_diffuse").image, kha.compute.Access.Write); + kha.compute.Compute.setSampledTexture(voxel_te3, rts.get("gbuffer1").image); + #if rp_gbuffer2 + kha.compute.Compute.setSampledTexture(voxel_tf3, rts.get("gbuffer2").image); + #end + #if lnx_brdf + kha.compute.Compute.setSampledTexture(voxel_tg3, iron.Scene.active.embedded.get("brdf.png")); + #end + #if lnx_radiance + kha.compute.Compute.setSampledTexture(voxel_th3, iron.Scene.active.world.probe.radiance); + #end + + var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); + for (i in 0...Main.voxelgiClipmapCount) { + fa[i * 10] = clipmaps[i].voxelSize; + fa[i * 10 + 1] = clipmaps[i].extents.x; + fa[i * 10 + 2] = clipmaps[i].extents.y; + fa[i * 10 + 3] = clipmaps[i].extents.z; + fa[i * 10 + 4] = clipmaps[i].center.x; + fa[i * 10 + 5] = clipmaps[i].center.y; + fa[i * 10 + 6] = clipmaps[i].center.z; + fa[i * 10 + 7] = clipmaps[i].offset_prev.x; + fa[i * 10 + 8] = clipmaps[i].offset_prev.y; + fa[i * 10 + 9] = clipmaps[i].offset_prev.z; + } + + kha.compute.Compute.setFloats(voxel_ca3, fa); + + #if lnx_centerworld + m.setFrom(vmat(camera.V)); + #else + m.setFrom(camera.V); + #end + m.multmat(camera.P); + m.getInverse(m); + + kha.compute.Compute.setMatrix(voxel_cb3, m.self); + + kha.compute.Compute.setFloat3(voxel_cc3, camera.transform.worldx(), camera.transform.worldy(), camera.transform.worldz()); + + var width = iron.App.w(); + var height = iron.App.h(); + var dp = getDisplayp(); + if (dp != null) { // 1080p/.. + if (width > height) { + width = Std.int(width * (dp / height) * Inc.getSuperSampling()); + height = Std.int(dp * Inc.getSuperSampling()); + } + else { + height = Std.int(height * (dp / width) * Inc.getSuperSampling()); + width = Std.int(dp * Inc.getSuperSampling()); + } + } + kha.compute.Compute.setFloat2(voxel_cd3, width, height); + + kha.compute.Compute.setFloat(voxel_ce3, iron.Scene.active.world == null ? 0.0 : iron.Scene.active.world.probe.raw.strength); + #if lnx_irradiance + var irradiance = iron.Scene.active.world == null ? + iron.data.WorldData.getEmptyIrradiance() : + iron.Scene.active.world.probe.irradiance; + kha.compute.Compute.setFloats(voxel_cf3, irradiance); + #end + #if lnx_radiance + kha.compute.Compute.setFloat(voxel_cg3, iron.Scene.active.world != null ? iron.Scene.active.world.probe.raw.radiance_mipmaps + 1 - 2 : 1); + #end + + #if lnx_envcol + var x: kha.FastFloat = 0.0; + var y: kha.FastFloat = 0.0; + var z: kha.FastFloat = 0.0; + + if (camera.data.raw.clear_color != null) { + x = camera.data.raw.clear_color[0]; + y = camera.data.raw.clear_color[1]; + z = camera.data.raw.clear_color[2]; + } + + kha.compute.Compute.setFloat3(voxel_ch3, x, y, z); + #end + + kha.compute.Compute.compute(Std.int((width + 7) / 8), Std.int((height + 7) / 8), 1); + } + + public static function resolveSpecular() { + var rts = path.renderTargets; + var res = iron.RenderPath.getVoxelRes(); + var camera = iron.Scene.active.camera; + var clipmaps = iron.RenderPath.clipmaps; + var clipmap = clipmaps[iron.RenderPath.clipmapLevel]; + + kha.compute.Compute.setShader(voxel_sh4); + + kha.compute.Compute.setSampledTexture(voxel_ta4, rts.get("voxelsOut").image); + kha.compute.Compute.setSampledTexture(voxel_tb4, rts.get("half").image); + kha.compute.Compute.setSampledTexture(voxel_tc4, rts.get("gbuffer0").image); + kha.compute.Compute.setSampledTexture(voxel_td4, rts.get("voxelsSDF").image); + kha.compute.Compute.setTexture(voxel_te4, rts.get("voxels_specular").image, kha.compute.Access.Write); + #if rp_gbuffer2 + kha.compute.Compute.setSampledTexture(voxel_tf4, rts.get("gbuffer2").image); + #end + + var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); + for (i in 0...Main.voxelgiClipmapCount) { + fa[i * 10] = clipmaps[i].voxelSize; + fa[i * 10 + 1] = clipmaps[i].extents.x; + fa[i * 10 + 2] = clipmaps[i].extents.y; + fa[i * 10 + 3] = clipmaps[i].extents.z; + fa[i * 10 + 4] = clipmaps[i].center.x; + fa[i * 10 + 5] = clipmaps[i].center.y; + fa[i * 10 + 6] = clipmaps[i].center.z; + fa[i * 10 + 7] = clipmaps[i].offset_prev.x; + fa[i * 10 + 8] = clipmaps[i].offset_prev.y; + fa[i * 10 + 9] = clipmaps[i].offset_prev.z; + } + + kha.compute.Compute.setFloats(voxel_ca4, fa); + + #if lnx_centerworld + m.setFrom(vmat(camera.V)); + #else + m.setFrom(camera.V); + #end + m.multmat(camera.P); + m.getInverse(m); + + kha.compute.Compute.setMatrix(voxel_cb4, m.self); + + kha.compute.Compute.setFloat3(voxel_cc4, camera.transform.worldx(), camera.transform.worldy(), camera.transform.worldz()); + + var width = iron.App.w(); + var height = iron.App.h(); + var dp = getDisplayp(); + if (dp != null) { // 1080p/.. + if (width > height) { + width = Std.int(width * (dp / height) * Inc.getSuperSampling()); + height = Std.int(dp * Inc.getSuperSampling()); + } + else { + height = Std.int(height * (dp / width) * Inc.getSuperSampling()); + width = Std.int(dp * Inc.getSuperSampling()); + } + } + kha.compute.Compute.setFloat2(voxel_cd4, width, height); + + kha.compute.Compute.compute(Std.int((width + 7) / 8), Std.int((height + 7) / 8), 1); + } + #end // GI + #end // Voxels } #if lnx_shadowmap_atlas class ShadowMapAtlas { - public var target: String; - public var baseTileSizeConst: Int; - public var maxAtlasSizeConst: Int; + public var target: String; + public var baseTileSizeConst: Int; + public var maxAtlasSizeConst: Int; - public var sizew: Int; - public var sizeh: Int; + public var sizew: Int; + public var sizeh: Int; - public var currTileOffset = 0; - public var tiles: Array = []; - public var activeTiles: Array = []; - public var depth = 1; - #if lnx_shadowmap_atlas_lod - var tileSizes: Array = []; - var tileSizeFactor: Array = []; - #end - public var updateRenderTarget = false; - public static var shadowMapAtlases:Map = new Map(); // map a shadowmap atlas to their light type - public static var shadowMapAtlasesTransparent:Map = new Map(); // map a shadowmap atlas to their light type + public var currTileOffset = 0; + public var tiles: Array = []; + public var activeTiles: Array = []; + public var depth = 1; + #if lnx_shadowmap_atlas_lod + var tileSizes: Array = []; + var tileSizeFactor: Array = []; + #end + public var updateRenderTarget = false; + public static var shadowMapAtlases:Map = new Map(); // map a shadowmap atlas to their light type + public static var shadowMapAtlasesTransparent:Map = new Map(); // map a shadowmap atlas to their light type - #if lnx_debug - public var lightType: String; - public var rejectedLights: Array = []; - #end + #if lnx_debug + public var lightType: String; + public var rejectedLights: Array = []; + #end - function new(light: LightObject, transparent: Bool) { + function new(light: LightObject, transparent: Bool) { - var maxTileSize = shadowMapAtlasSize(light); - this.target = shadowMapAtlasName(light.data.raw.type, transparent); - this.sizew = this.sizeh = this.baseTileSizeConst = maxTileSize; - this.depth = getSubdivisions(); - this.maxAtlasSizeConst = getMaxAtlasSize(light.data.raw.type); + var maxTileSize = shadowMapAtlasSize(light); + this.target = shadowMapAtlasName(light.data.raw.type, transparent); + this.sizew = this.sizeh = this.baseTileSizeConst = maxTileSize; + this.depth = getSubdivisions(); + this.maxAtlasSizeConst = getMaxAtlasSize(light.data.raw.type); - #if lnx_shadowmap_atlas_lod - computeTileSizes(maxTileSize, depth); - #end + #if lnx_shadowmap_atlas_lod + computeTileSizes(maxTileSize, depth); + #end - #if lnx_debug - #if lnx_shadowmap_atlas_single_map - this.lightType = "any"; - #else - this.lightType = light.data.raw.type; - #end - #end + #if lnx_debug + #if lnx_shadowmap_atlas_single_map + this.lightType = "any"; + #else + this.lightType = light.data.raw.type; + #end + #end - } + } - /** - * Adds a light to an atlas. The atlas is decided based on the type of the light - * @param light of type LightObject to be added to an yatlas - * @return if the light was added succesfully - */ - public static function addLight(light: LightObject, transparent: Bool) { - var atlasName = shadowMapAtlasName(light.data.raw.type, transparent); - var atlas = transparent ? shadowMapAtlasesTransparent.get(atlasName) : shadowMapAtlases.get(atlasName); - if (atlas == null) { - // create a new atlas - atlas = new ShadowMapAtlas(light, transparent); - if (transparent) - shadowMapAtlasesTransparent.set(atlasName, atlas); - else - shadowMapAtlases.set(atlasName, atlas); - } + /** + * Adds a light to an atlas. The atlas is decided based on the type of the light + * @param light of type LightObject to be added to an yatlas + * @return if the light was added succesfully + */ + public static function addLight(light: LightObject, transparent: Bool) { + var atlasName = shadowMapAtlasName(light.data.raw.type, transparent); + var atlas = transparent ? shadowMapAtlasesTransparent.get(atlasName) : shadowMapAtlases.get(atlasName); + if (atlas == null) { + // create a new atlas + atlas = new ShadowMapAtlas(light, transparent); + if (transparent) + shadowMapAtlasesTransparent.set(atlasName, atlas); + else + shadowMapAtlases.set(atlasName, atlas); + } - // find a free tile for this light - var mainTile = ShadowMapTile.assignTiles(light, atlas, null); - if (mainTile == null) { - #if lnx_debug - if (!atlas.rejectedLights.contains(light)) - atlas.rejectedLights.push(light); - #end - return; - } + // find a free tile for this light + var mainTile = ShadowMapTile.assignTiles(light, atlas, null); + if (mainTile == null) { + #if lnx_debug + if (!atlas.rejectedLights.contains(light)) + atlas.rejectedLights.push(light); + #end + return; + } - atlas.activeTiles.push(mainTile); - // notify the tile on light remove - light.tileNotifyOnRemove = mainTile.notifyOnLightRemove; - // notify atlas when this tile is freed - mainTile.notifyOnFree = atlas.freeActiveTile; - // "lock" light to make sure it's not eligible to be added again - if (transparent) - light.lightInAtlasTransparent = true; - else - light.lightInAtlas = true; - } + atlas.activeTiles.push(mainTile); + // notify the tile on light remove + light.tileNotifyOnRemove = mainTile.notifyOnLightRemove; + // notify atlas when this tile is freed + mainTile.notifyOnFree = atlas.freeActiveTile; + // "lock" light to make sure it's not eligible to be added again + if (transparent) + light.lightInAtlasTransparent = true; + else + light.lightInAtlas = true; + } - static inline function shadowMapAtlasSize(light:LightObject):Int { - // TODO: this can break because we are changing shadowmap_size elsewhere. - return light.data.raw.shadowmap_size; - } + static inline function shadowMapAtlasSize(light:LightObject):Int { + // TODO: this can break because we are changing shadowmap_size elsewhere. + return light.data.raw.shadowmap_size; + } - public function getTileSize(shadowMapScale: Float): Int { - #if lnx_shadowmap_atlas_lod - // find the first scale factor that is smaller to the shadowmap scale, and then return the previous one. - var i = 0; - for (sizeFactor in tileSizeFactor) { - if (sizeFactor < shadowMapScale) break; - i++; - } - return tileSizes[i - 1]; - #else - return this.baseTileSizeConst; - #end - } + public function getTileSize(shadowMapScale: Float): Int { + #if lnx_shadowmap_atlas_lod + // find the first scale factor that is smaller to the shadowmap scale, and then return the previous one. + var i = 0; + for (sizeFactor in tileSizeFactor) { + if (sizeFactor < shadowMapScale) break; + i++; + } + return tileSizes[i - 1]; + #else + return this.baseTileSizeConst; + #end + } - #if lnx_shadowmap_atlas_lod - function computeTileSizes(maxTileSize: Int, depth: Int): Void { - // find the highest value based on the calculation done in the cluster code - var base = LightObject.zToShadowMapScale(0, 16); - var subdiv = base / depth; - for(i in 0...depth){ - this.tileSizes.push(Std.int(maxTileSize / Math.pow(2, i))); - this.tileSizeFactor.push(base); - base -= subdiv; - } - this.tileSizes.push(0); - this.tileSizeFactor.push(0.0); - } - #end + #if lnx_shadowmap_atlas_lod + function computeTileSizes(maxTileSize: Int, depth: Int): Void { + // find the highest value based on the calculation done in the cluster code + var base = LightObject.zToShadowMapScale(0, 16); + var subdiv = base / depth; + for(i in 0...depth){ + this.tileSizes.push(Std.int(maxTileSize / Math.pow(2, i))); + this.tileSizeFactor.push(base); + base -= subdiv; + } + this.tileSizes.push(0); + this.tileSizeFactor.push(0.0); + } + #end - public inline function atlasLimitReached() { - // asume square atlas - return (currTileOffset + 1) * baseTileSizeConst > maxAtlasSizeConst; - } + public inline function atlasLimitReached() { + // asume square atlas + return (currTileOffset + 1) * baseTileSizeConst > maxAtlasSizeConst; + } - public static inline function shadowMapAtlasName(type: String, transparent: Bool): String { - #if lnx_shadowmap_atlas_single_map - return "shadowMapAtlas"; - #else - switch (type) { - case "point": - return transparent ? "shadowMapAtlasPointTransparent" : "shadowMapAtlasPoint"; - case "sun": - return transparent ? "shadowMapAtlasSunTransparent" : "shadowMapAtlasSun"; - default: - return transparent ? "shadowMapAtlasSpotTransparent" : "shadowMapAtlasSpot"; - } - #end - } + public static inline function shadowMapAtlasName(type: String, transparent: Bool): String { + #if lnx_shadowmap_atlas_single_map + return "shadowMapAtlas"; + #else + switch (type) { + case "point": + return transparent ? "shadowMapAtlasPointTransparent" : "shadowMapAtlasPoint"; + case "sun": + return transparent ? "shadowMapAtlasSunTransparent" : "shadowMapAtlasSun"; + default: + return transparent ? "shadowMapAtlasSpotTransparent" : "shadowMapAtlasSpot"; + } + #end + } - public static inline function getSubdivisions(): Int { - #if (rp_shadowmap_atlas_lod_subdivisions == 2) - return 2; - #elseif (rp_shadowmap_atlas_lod_subdivisions == 3) - return 3; - #elseif (rp_shadowmap_atlas_lod_subdivisions == 4) - return 4; - #elseif (rp_shadowmap_atlas_lod_subdivisions == 5) - return 5; - #elseif (rp_shadowmap_atlas_lod_subdivisions == 6) - return 6; - #elseif (rp_shadowmap_atlas_lod_subdivisions == 7) - return 7; - #elseif (rp_shadowmap_atlas_lod_subdivisions == 8) - return 8; - #elseif (!lnx_shadowmap_atlas_lod) - return 1; - #end - } + public static inline function getSubdivisions(): Int { + #if (rp_shadowmap_atlas_lod_subdivisions == 2) + return 2; + #elseif (rp_shadowmap_atlas_lod_subdivisions == 3) + return 3; + #elseif (rp_shadowmap_atlas_lod_subdivisions == 4) + return 4; + #elseif (rp_shadowmap_atlas_lod_subdivisions == 5) + return 5; + #elseif (rp_shadowmap_atlas_lod_subdivisions == 6) + return 6; + #elseif (rp_shadowmap_atlas_lod_subdivisions == 7) + return 7; + #elseif (rp_shadowmap_atlas_lod_subdivisions == 8) + return 8; + #elseif (!lnx_shadowmap_atlas_lod) + return 1; + #end + } - public static inline function getMaxAtlasSize(type: String): Int { - #if lnx_shadowmap_atlas_single_map - #if (rp_shadowmap_atlas_max_size == 512) - return 512; - #elseif (rp_shadowmap_atlas_max_size == 1024) - return 1024; - #elseif (rp_shadowmap_atlas_max_size == 2048) - return 2048; - #elseif (rp_shadowmap_atlas_max_size == 4096) - return 4096; - #elseif (rp_shadowmap_atlas_max_size == 8192) - return 8192; - #elseif (rp_shadowmap_atlas_max_size == 16384) - return 16384; - #elseif (rp_shadowmap_atlas_max_size == 32768) - return 32768; - #end - #else - switch (type) { - case "point": { - #if (rp_shadowmap_atlas_max_size_point == 1024) - return 1024; - #elseif (rp_shadowmap_atlas_max_size_point == 2048) - return 2048; - #elseif (rp_shadowmap_atlas_max_size_point == 4096) - return 4096; - #elseif (rp_shadowmap_atlas_max_size_point == 8192) - return 8192; - #elseif (rp_shadowmap_atlas_max_size_point == 16384) - return 16384; - #elseif (rp_shadowmap_atlas_max_size_point == 32768) - return 32768; - #end - } - case "spot": { - #if (rp_shadowmap_atlas_max_size_spot == 512) - return 512; - #elseif (rp_shadowmap_atlas_max_size_spot == 1024) - return 1024; - #elseif (rp_shadowmap_atlas_max_size_spot == 2048) - return 2048; - #elseif (rp_shadowmap_atlas_max_size_spot == 4096) - return 4096; - #elseif (rp_shadowmap_atlas_max_size_spot == 8192) - return 8192; - #elseif (rp_shadowmap_atlas_max_size_spot == 16384) - return 16384; - #elseif (rp_shadowmap_atlas_max_size_spot == 32768) - return 32768; - #end - } - case "sun": { - #if (rp_shadowmap_atlas_max_size_sun == 512) - return 512; - #elseif (rp_shadowmap_atlas_max_size_sun == 1024) - return 1024; - #elseif (rp_shadowmap_atlas_max_size_sun == 2048) - return 2048; - #elseif (rp_shadowmap_atlas_max_size_sun == 4096) - return 4096; - #elseif (rp_shadowmap_atlas_max_size_sun == 8192) - return 8192; - #elseif (rp_shadowmap_atlas_max_size_sun == 16384) - return 16384; - #elseif (rp_shadowmap_atlas_max_size_sun == 32768) - return 32768; - #end - } - default: { - #if (rp_shadowmap_atlas_max_size == 512) - return 512; - #elseif (rp_shadowmap_atlas_max_size == 1024) - return 1024; - #elseif (rp_shadowmap_atlas_max_size == 2048) - return 2048; - #elseif (rp_shadowmap_atlas_max_size == 4096) - return 4096; - #elseif (rp_shadowmap_atlas_max_size == 8192) - return 8192; - #elseif (rp_shadowmap_atlas_max_size == 16384) - return 16384; - #elseif (rp_shadowmap_atlas_max_size == 32768) - return 32768; - #end - } - } - #end - } + public static inline function getMaxAtlasSize(type: String): Int { + #if lnx_shadowmap_atlas_single_map + #if (rp_shadowmap_atlas_max_size == 512) + return 512; + #elseif (rp_shadowmap_atlas_max_size == 1024) + return 1024; + #elseif (rp_shadowmap_atlas_max_size == 2048) + return 2048; + #elseif (rp_shadowmap_atlas_max_size == 4096) + return 4096; + #elseif (rp_shadowmap_atlas_max_size == 8192) + return 8192; + #elseif (rp_shadowmap_atlas_max_size == 16384) + return 16384; + #elseif (rp_shadowmap_atlas_max_size == 32768) + return 32768; + #end + #else + switch (type) { + case "point": { + #if (rp_shadowmap_atlas_max_size_point == 1024) + return 1024; + #elseif (rp_shadowmap_atlas_max_size_point == 2048) + return 2048; + #elseif (rp_shadowmap_atlas_max_size_point == 4096) + return 4096; + #elseif (rp_shadowmap_atlas_max_size_point == 8192) + return 8192; + #elseif (rp_shadowmap_atlas_max_size_point == 16384) + return 16384; + #elseif (rp_shadowmap_atlas_max_size_point == 32768) + return 32768; + #end + } + case "spot": { + #if (rp_shadowmap_atlas_max_size_spot == 512) + return 512; + #elseif (rp_shadowmap_atlas_max_size_spot == 1024) + return 1024; + #elseif (rp_shadowmap_atlas_max_size_spot == 2048) + return 2048; + #elseif (rp_shadowmap_atlas_max_size_spot == 4096) + return 4096; + #elseif (rp_shadowmap_atlas_max_size_spot == 8192) + return 8192; + #elseif (rp_shadowmap_atlas_max_size_spot == 16384) + return 16384; + #elseif (rp_shadowmap_atlas_max_size_spot == 32768) + return 32768; + #end + } + case "sun": { + #if (rp_shadowmap_atlas_max_size_sun == 512) + return 512; + #elseif (rp_shadowmap_atlas_max_size_sun == 1024) + return 1024; + #elseif (rp_shadowmap_atlas_max_size_sun == 2048) + return 2048; + #elseif (rp_shadowmap_atlas_max_size_sun == 4096) + return 4096; + #elseif (rp_shadowmap_atlas_max_size_sun == 8192) + return 8192; + #elseif (rp_shadowmap_atlas_max_size_sun == 16384) + return 16384; + #elseif (rp_shadowmap_atlas_max_size_sun == 32768) + return 32768; + #end + } + default: { + #if (rp_shadowmap_atlas_max_size == 512) + return 512; + #elseif (rp_shadowmap_atlas_max_size == 1024) + return 1024; + #elseif (rp_shadowmap_atlas_max_size == 2048) + return 2048; + #elseif (rp_shadowmap_atlas_max_size == 4096) + return 4096; + #elseif (rp_shadowmap_atlas_max_size == 8192) + return 8192; + #elseif (rp_shadowmap_atlas_max_size == 16384) + return 16384; + #elseif (rp_shadowmap_atlas_max_size == 32768) + return 32768; + #end + } + } + #end + } - function freeActiveTile(tile: ShadowMapTile) { - activeTiles.remove(tile); - } + function freeActiveTile(tile: ShadowMapTile) { + activeTiles.remove(tile); + } } class ShadowMapTile { - public var light:Null = null; - public var coordsX:Int; - public var coordsY:Int; - public var size:Int; - public var tiles:Array = []; - public var linkedTile:ShadowMapTile = null; + public var light:Null = null; + public var coordsX:Int; + public var coordsY:Int; + public var size:Int; + public var tiles:Array = []; + public var linkedTile:ShadowMapTile = null; - #if lnx_shadowmap_atlas_lod - public var parentTile: ShadowMapTile = null; - public var activeSubTiles: Int = 0; - public var newTileSize: Int = -1; + #if lnx_shadowmap_atlas_lod + public var parentTile: ShadowMapTile = null; + public var activeSubTiles: Int = 0; + public var newTileSize: Int = -1; - static var tilePattern = [[0, 0], [1, 0], [0, 1], [1, 1]]; - #end + static var tilePattern = [[0, 0], [1, 0], [0, 1], [1, 1]]; + #end - function new(coordsX: Int, coordsY: Int, size: Int) { - this.coordsX = coordsX; - this.coordsY = coordsY; - this.size = size; - } + function new(coordsX: Int, coordsY: Int, size: Int) { + this.coordsX = coordsX; + this.coordsY = coordsY; + this.size = size; + } - public static function assignTiles(light: LightObject, atlas: ShadowMapAtlas, oldTile: ShadowMapTile): ShadowMapTile { - var tileSize = 0; + public static function assignTiles(light: LightObject, atlas: ShadowMapAtlas, oldTile: ShadowMapTile): ShadowMapTile { + var tileSize = 0; - #if lnx_shadowmap_atlas_lod - if (oldTile != null && oldTile.newTileSize != -1) { - // reuse tilesize instead of computing it again - tileSize = oldTile.newTileSize; - oldTile.newTileSize = -1; - } - else - #end - tileSize = atlas.getTileSize(light.shadowMapScale); + #if lnx_shadowmap_atlas_lod + if (oldTile != null && oldTile.newTileSize != -1) { + // reuse tilesize instead of computing it again + tileSize = oldTile.newTileSize; + oldTile.newTileSize = -1; + } + else + #end + tileSize = atlas.getTileSize(light.shadowMapScale); - if (tileSize == 0) - return null; + if (tileSize == 0) + return null; - var tiles = []; - tiles = findCreateTiles(light, oldTile, atlas, tilesLightType(light.data.raw.type), tileSize); + var tiles = []; + tiles = findCreateTiles(light, oldTile, atlas, tilesLightType(light.data.raw.type), tileSize); - // lock new tiles with light - for (tile in tiles) - tile.lockTile(light); + // lock new tiles with light + for (tile in tiles) + tile.lockTile(light); - return linkTiles(tiles); - } + return linkTiles(tiles); + } - static inline function linkTiles(tiles: Array): ShadowMapTile { - if (tiles.length > 1) { - var linkedTile = tiles[0]; - for (i in 1...tiles.length) { - linkedTile.linkedTile = tiles[i]; - linkedTile = tiles[i]; - } - } - return tiles[0]; - } + static inline function linkTiles(tiles: Array): ShadowMapTile { + if (tiles.length > 1) { + var linkedTile = tiles[0]; + for (i in 1...tiles.length) { + linkedTile.linkedTile = tiles[i]; + linkedTile = tiles[i]; + } + } + return tiles[0]; + } - static inline function findCreateTiles(light: LightObject, oldTile: ShadowMapTile, atlas: ShadowMapAtlas, tilesPerLightType: Int, tileSize: Int): Array { - var tilesFound: Array = []; + static inline function findCreateTiles(light: LightObject, oldTile: ShadowMapTile, atlas: ShadowMapAtlas, tilesPerLightType: Int, tileSize: Int): Array { + var tilesFound: Array = []; - while (tilesFound.length < tilesPerLightType) { - findTiles(light, oldTile, atlas.tiles, tileSize, tilesPerLightType, tilesFound); + while (tilesFound.length < tilesPerLightType) { + findTiles(light, oldTile, atlas.tiles, tileSize, tilesPerLightType, tilesFound); - if (tilesFound.length < tilesPerLightType) { - tilesFound = []; // empty tilesFound - // skip creating more tiles if limit has been reached - if (atlas.atlasLimitReached()) - break; + if (tilesFound.length < tilesPerLightType) { + tilesFound = []; // empty tilesFound + // skip creating more tiles if limit has been reached + if (atlas.atlasLimitReached()) + break; - createTiles(atlas.tiles, atlas.baseTileSizeConst, atlas.depth, atlas.currTileOffset, atlas.currTileOffset); - atlas.currTileOffset++; - // update texture to accomodate new size - atlas.updateRenderTarget = true; - atlas.sizew = atlas.sizeh = atlas.currTileOffset * atlas.baseTileSizeConst; - } - } - return tilesFound; - } + createTiles(atlas.tiles, atlas.baseTileSizeConst, atlas.depth, atlas.currTileOffset, atlas.currTileOffset); + atlas.currTileOffset++; + // update texture to accomodate new size + atlas.updateRenderTarget = true; + atlas.sizew = atlas.sizeh = atlas.currTileOffset * atlas.baseTileSizeConst; + } + } + return tilesFound; + } - inline static function findTiles(light:LightObject, oldTile: ShadowMapTile, - tiles: Array, size: Int, tilesCount: Int, tilesFound: Array): Void { - #if lnx_shadowmap_atlas_lod - if (oldTile != null) { - // reuse children tiles - if (size < oldTile.size) { - oldTile.forEachTileLinked(function(lTile) { - var childTile = findFreeChildTile(lTile, size); - tilesFound.push(childTile); - }); - } - // reuse parent tiles - else { - oldTile.forEachTileLinked(function(lTile) { - // find out if parents tiles are not occupied - var parentTile = findFreeParentTile(lTile, size); - // if parent is free, add it to found tiles - if (parentTile != null) - tilesFound.push(parentTile); - }); - if (tilesFound.length < tilesCount) { - // find naively the rest of the tiles that couldn't be reused - findTilesNaive(light, tiles, size, tilesCount, tilesFound); - } - } - } - else - #end - findTilesNaive(light, tiles, size, tilesCount, tilesFound); - } + inline static function findTiles(light:LightObject, oldTile: ShadowMapTile, + tiles: Array, size: Int, tilesCount: Int, tilesFound: Array): Void { + #if lnx_shadowmap_atlas_lod + if (oldTile != null) { + // reuse children tiles + if (size < oldTile.size) { + oldTile.forEachTileLinked(function(lTile) { + var childTile = findFreeChildTile(lTile, size); + tilesFound.push(childTile); + }); + } + // reuse parent tiles + else { + oldTile.forEachTileLinked(function(lTile) { + // find out if parents tiles are not occupied + var parentTile = findFreeParentTile(lTile, size); + // if parent is free, add it to found tiles + if (parentTile != null) + tilesFound.push(parentTile); + }); + if (tilesFound.length < tilesCount) { + // find naively the rest of the tiles that couldn't be reused + findTilesNaive(light, tiles, size, tilesCount, tilesFound); + } + } + } + else + #end + findTilesNaive(light, tiles, size, tilesCount, tilesFound); + } - #if lnx_shadowmap_atlas_lod - static inline function findFreeChildTile(tile: ShadowMapTile, size: Int): ShadowMapTile { - var childrenTile = tile; - while (size < childrenTile.size) { - childrenTile = childrenTile.tiles[0]; - } - return childrenTile; - } + #if lnx_shadowmap_atlas_lod + static inline function findFreeChildTile(tile: ShadowMapTile, size: Int): ShadowMapTile { + var childrenTile = tile; + while (size < childrenTile.size) { + childrenTile = childrenTile.tiles[0]; + } + return childrenTile; + } - static inline function findFreeParentTile(tile: ShadowMapTile, size: Int): ShadowMapTile { - var parentTile = tile; - while (size > parentTile.size) { - parentTile = parentTile.parentTile; - // stop if parent tile is occupied - if (parentTile.activeSubTiles > 1) { - parentTile = null; - break; - } - } - return parentTile; - } - #end + static inline function findFreeParentTile(tile: ShadowMapTile, size: Int): ShadowMapTile { + var parentTile = tile; + while (size > parentTile.size) { + parentTile = parentTile.parentTile; + // stop if parent tile is occupied + if (parentTile.activeSubTiles > 1) { + parentTile = null; + break; + } + } + return parentTile; + } + #end - static function findTilesNaive(light:LightObject, tiles: Array, size: Int, tilesCount: Int, tilesFound: Array): Void { - for (tile in tiles) { - if (tile.size == size) { - if (tile.light == null #if lnx_shadowmap_atlas_lod && tile.activeSubTiles == 0 #end) { - tilesFound.push(tile); - // stop after finding enough tiles - if (tilesFound.length == tilesCount) - return; - } - } - else { - // skip over if end of the tree or tile is occupied - if (tile.tiles.length == 0 || tile.light != null) - continue; - findTilesNaive(light, tile.tiles, size, tilesCount, tilesFound); - // skip iterating over the rest of the tiles if found enough - if (tilesFound.length == tilesCount) - return; - } - } - } + static function findTilesNaive(light:LightObject, tiles: Array, size: Int, tilesCount: Int, tilesFound: Array): Void { + for (tile in tiles) { + if (tile.size == size) { + if (tile.light == null #if lnx_shadowmap_atlas_lod && tile.activeSubTiles == 0 #end) { + tilesFound.push(tile); + // stop after finding enough tiles + if (tilesFound.length == tilesCount) + return; + } + } + else { + // skip over if end of the tree or tile is occupied + if (tile.tiles.length == 0 || tile.light != null) + continue; + findTilesNaive(light, tile.tiles, size, tilesCount, tilesFound); + // skip iterating over the rest of the tiles if found enough + if (tilesFound.length == tilesCount) + return; + } + } + } - // create a basic tile and subdivide it if needed - public static function createTiles(tiles:Array, size:Int, depth: Int, baseX:Int, baseY:Int) { - var i = baseX; - var j = 0; - var lastTile = tiles.length; - // assume occupied tiles start from 1 line before the base x - var occupiedTiles = baseX - 1; + // create a basic tile and subdivide it if needed + public static function createTiles(tiles:Array, size:Int, depth: Int, baseX:Int, baseY:Int) { + var i = baseX; + var j = 0; + var lastTile = tiles.length; + // assume occupied tiles start from 1 line before the base x + var occupiedTiles = baseX - 1; - while (i >= 0) { - if (i <= occupiedTiles) { // avoid overriding tiles - j = baseY; - } - while (j <= baseY) { - // create base tile of max-size - tiles.push(new ShadowMapTile(size * i, size * j, size)); - #if lnx_shadowmap_atlas_lod - tiles[lastTile].tiles = subDivTile(tiles[lastTile], size, size * i, size * j, depth - 1); - #end - lastTile++; - j++; - } - i--; - } - } + while (i >= 0) { + if (i <= occupiedTiles) { // avoid overriding tiles + j = baseY; + } + while (j <= baseY) { + // create base tile of max-size + tiles.push(new ShadowMapTile(size * i, size * j, size)); + #if lnx_shadowmap_atlas_lod + tiles[lastTile].tiles = subDivTile(tiles[lastTile], size, size * i, size * j, depth - 1); + #end + lastTile++; + j++; + } + i--; + } + } - #if lnx_shadowmap_atlas_lod - static function subDivTile(parent: ShadowMapTile, size: Int, baseCoordsX: Int, baseCoordsY: Int, depth: Int): Array { - var tileSize = Std.int(size / 2); + #if lnx_shadowmap_atlas_lod + static function subDivTile(parent: ShadowMapTile, size: Int, baseCoordsX: Int, baseCoordsY: Int, depth: Int): Array { + var tileSize = Std.int(size / 2); - var tiles = []; + var tiles = []; - for (i in 0...4) { - var coordsX = baseCoordsX + tilePattern[i][0] * tileSize; - var coordsY = baseCoordsY + tilePattern[i][1] * tileSize; + for (i in 0...4) { + var coordsX = baseCoordsX + tilePattern[i][0] * tileSize; + var coordsY = baseCoordsY + tilePattern[i][1] * tileSize; - var tile = new ShadowMapTile(coordsX, coordsY, tileSize); - tile.parentTile = parent; + var tile = new ShadowMapTile(coordsX, coordsY, tileSize); + tile.parentTile = parent; - if (depth > 1) - tile.tiles = subDivTile(tile, tileSize, coordsX, coordsY, depth - 1); - tiles.push(tile); - } + if (depth > 1) + tile.tiles = subDivTile(tile, tileSize, coordsX, coordsY, depth - 1); + tiles.push(tile); + } - return tiles; - } - #end + return tiles; + } + #end - public static inline function tilesLightType(type: String): Int { - switch (type) { - case "sun": - return LightObject.cascadeCount; - case "point": - return 6; - default: - return 1; - } - } + public static inline function tilesLightType(type: String): Int { + switch (type) { + case "sun": + return LightObject.cascadeCount; + case "point": + return 6; + default: + return 1; + } + } - public function notifyOnLightRemove() { - unlockLight = true; - freeTile(); - } + public function notifyOnLightRemove() { + unlockLight = true; + freeTile(); + } - inline function lockTile(light: LightObject): Void { - if (this.light != null) - return; - this.light = light; - #if lnx_shadowmap_atlas_lod - // update the count of used tiles for parents - this.forEachParentTile(function (pTile) { - pTile.activeSubTiles++; - }); - #end - } + inline function lockTile(light: LightObject): Void { + if (this.light != null) + return; + this.light = light; + #if lnx_shadowmap_atlas_lod + // update the count of used tiles for parents + this.forEachParentTile(function (pTile) { + pTile.activeSubTiles++; + }); + #end + } - public var unlockLight: Bool = false; - public var notifyOnFree: ShadowMapTile -> Void; + public var unlockLight: Bool = false; + public var notifyOnFree: ShadowMapTile -> Void; - public function freeTile(): Void { - // prevent duplicates - if (light != null && unlockLight) { - light.lightInAtlas = false; - unlockLight = false; - } + public function freeTile(): Void { + // prevent duplicates + if (light != null && unlockLight) { + light.lightInAtlas = false; + unlockLight = false; + } - var linkedTile = this; - var tempTile = this; - while (linkedTile != null) { - linkedTile.light = null; - #if lnx_shadowmap_atlas_lod - // update the count of used tiles for parents - linkedTile.forEachParentTile(function (pTile) { - if (pTile.activeSubTiles > 0) - pTile.activeSubTiles--; - }); - #end + var linkedTile = this; + var tempTile = this; + while (linkedTile != null) { + linkedTile.light = null; + #if lnx_shadowmap_atlas_lod + // update the count of used tiles for parents + linkedTile.forEachParentTile(function (pTile) { + if (pTile.activeSubTiles > 0) + pTile.activeSubTiles--; + }); + #end - linkedTile = linkedTile.linkedTile; - // unlink linked tiles - tempTile.linkedTile = null; - tempTile = linkedTile; - } - // notify atlas that this tile has been freed - if (notifyOnFree != null) { - notifyOnFree(this); - notifyOnFree = null; - } - } + linkedTile = linkedTile.linkedTile; + // unlink linked tiles + tempTile.linkedTile = null; + tempTile = linkedTile; + } + // notify atlas that this tile has been freed + if (notifyOnFree != null) { + notifyOnFree(this); + notifyOnFree = null; + } + } - public inline function forEachTileLinked(action: ShadowMapTile->Void): Void { - var linkedTile = this; - while (linkedTile != null) { - action(linkedTile); - linkedTile = linkedTile.linkedTile; - } - } + public inline function forEachTileLinked(action: ShadowMapTile->Void): Void { + var linkedTile = this; + while (linkedTile != null) { + action(linkedTile); + linkedTile = linkedTile.linkedTile; + } + } - #if lnx_shadowmap_atlas_lod - public inline function forEachParentTile(action: ShadowMapTile->Void): Void { - var parentTile = this.parentTile; - while (parentTile != null) { - action(parentTile); - parentTile = parentTile.parentTile; - } - } - #end + #if lnx_shadowmap_atlas_lod + public inline function forEachParentTile(action: ShadowMapTile->Void): Void { + var parentTile = this.parentTile; + while (parentTile != null) { + action(parentTile); + parentTile = parentTile.parentTile; + } + } + #end } #end From 6b25d8c8ade0f746fa974a422a144ffcc2e85859 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 28 May 2025 01:36:04 +0000 Subject: [PATCH 098/136] revert 13ca31f480761f13b7d03012eedd409f3a9f9dbd revert Update leenkx/Sources/leenkx/renderpath/Inc.hx --- leenkx/Sources/leenkx/renderpath/Inc.hx | 3504 ++++++++++++----------- 1 file changed, 1755 insertions(+), 1749 deletions(-) diff --git a/leenkx/Sources/leenkx/renderpath/Inc.hx b/leenkx/Sources/leenkx/renderpath/Inc.hx index dea31e7..09dd163 100644 --- a/leenkx/Sources/leenkx/renderpath/Inc.hx +++ b/leenkx/Sources/leenkx/renderpath/Inc.hx @@ -7,1817 +7,1823 @@ import leenkx.math.Helper; import kha.arrays.Float32Array; class Inc { - static var path: RenderPath; - public static var superSample = 1.0; - - static var pointIndex = 0; - static var spotIndex = 0; - static var lastFrame = -1; - - #if ((rp_voxels != 'Off') && lnx_config) - static var voxelsCreated = false; - #end - - #if (rp_voxels != "Off") - static var voxel_sh0:kha.compute.Shader = null; - static var voxel_sh1:kha.compute.Shader = null; - static var voxel_ta0:kha.compute.TextureUnit; - static var voxel_tb0:kha.compute.TextureUnit; - static var voxel_ca0:kha.compute.ConstantLocation; - static var voxel_cb0:kha.compute.ConstantLocation; - static var voxel_ta1:kha.compute.TextureUnit; - static var voxel_tb1:kha.compute.TextureUnit; - static var voxel_tc1:kha.compute.TextureUnit; - static var m = iron.math.Mat4.identity(); - static var voxel_ca1:kha.compute.ConstantLocation; - static var voxel_cb1:kha.compute.ConstantLocation; - #if (rp_voxels == "Voxel GI") - static var voxel_td1:kha.compute.TextureUnit; - static var voxel_te1:kha.compute.TextureUnit; - #else - #if lnx_voxelgi_shadows - static var voxel_te1:kha.compute.TextureUnit; - #end - #end - #if (lnx_voxelgi_shadows || rp_voxels == "Voxel GI") - static var voxel_sh2:kha.compute.Shader = null; - static var voxel_ta2:kha.compute.TextureUnit; - static var voxel_tb2:kha.compute.TextureUnit; - static var voxel_ca2:kha.compute.ConstantLocation; - static var voxel_cb2:kha.compute.ConstantLocation; - static var voxel_cc2:kha.compute.ConstantLocation; - #end - static var voxel_sh3:kha.compute.Shader = null; - static var voxel_ta3:kha.compute.TextureUnit; - static var voxel_tb3:kha.compute.TextureUnit; - static var voxel_tc3:kha.compute.TextureUnit; - static var voxel_td3:kha.compute.TextureUnit; - static var voxel_te3:kha.compute.TextureUnit; - static var voxel_tf3:kha.compute.TextureUnit; - #if lnx_brdf - static var voxel_tg3:kha.compute.TextureUnit; - #end - #if lnx_radiance - static var voxel_th3:kha.compute.TextureUnit; - #end - static var voxel_ca3:kha.compute.ConstantLocation; - static var voxel_cb3:kha.compute.ConstantLocation; - static var voxel_cc3:kha.compute.ConstantLocation; - static var voxel_cd3:kha.compute.ConstantLocation; - static var voxel_ce3:kha.compute.ConstantLocation; - #if lnx_irradiance - static var voxel_cf3:kha.compute.ConstantLocation; - #end - #if lnx_radiance - static var voxel_cg3:kha.compute.ConstantLocation; - #end - #if lnx_envcol - static var voxel_ch3:kha.compute.ConstantLocation; - #end - #if (rp_voxels == "Voxel GI") - static var voxel_sh4:kha.compute.Shader = null; - static var voxel_ta4:kha.compute.TextureUnit; - static var voxel_tb4:kha.compute.TextureUnit; - static var voxel_tc4:kha.compute.TextureUnit; - static var voxel_td4:kha.compute.TextureUnit; - static var voxel_te4:kha.compute.TextureUnit; - static var voxel_tf4:kha.compute.TextureUnit; - static var voxel_ca4:kha.compute.ConstantLocation; - static var voxel_cb4:kha.compute.ConstantLocation; - static var voxel_cc4:kha.compute.ConstantLocation; - static var voxel_cd4:kha.compute.ConstantLocation; - #end - #end //rp_voxels - - public static function init(_path: RenderPath) { - path = _path; - - #if lnx_config - var config = leenkx.data.Config.raw; - for (l in iron.Scene.active.lights) { - l.data.raw.shadowmap_size = l.data.raw.type == "sun" ? - config.rp_shadowmap_cascade : - config.rp_shadowmap_cube; - } - superSample = config.rp_supersample; - #else - - #if (rp_supersampling == 1.5) - superSample = 1.5; - #elseif (rp_supersampling == 2) - superSample = 2.0; - #elseif (rp_supersampling == 4) - superSample = 4.0; - #end - - #end - } - - #if lnx_shadowmap_atlas - public static function updatePointLightAtlasData(transparent: Bool): Void { - var atlas = transparent ? ShadowMapAtlas.shadowMapAtlasesTransparent.get(ShadowMapAtlas.shadowMapAtlasName("point", true)) : ShadowMapAtlas.shadowMapAtlases.get(ShadowMapAtlas.shadowMapAtlasName("point", false)); - if (atlas != null) { - if(LightObject.pointLightsData == null) { - LightObject.pointLightsData = new kha.arrays.Float32Array( - LightObject.maxLightsCluster * ShadowMapTile.tilesLightType("point") * 4); // max possible visible lights * 6 or 2 (faces) * 4 (xyzw) - } - - var n = iron.Scene.active.lights.length > LightObject.maxLightsCluster ? LightObject.maxLightsCluster : iron.Scene.active.lights.length; - var i = 0; - var j = 0; - for (light in iron.Scene.active.lights) { - if (i >= n) - break; - if (LightObject.discardLightCulled(light)) continue; - if (light.data.raw.type == "point") { - if (!light.data.raw.cast_shadow) { - j += 4 * 6; - continue; - } - for(k in 0...6) { - LightObject.pointLightsData[j ] = light.tileOffsetX[k]; // posx - LightObject.pointLightsData[j + 1] = light.tileOffsetY[k]; // posy - LightObject.pointLightsData[j + 2] = light.tileScale[k]; // tile scale factor relative to atlas - LightObject.pointLightsData[j + 3] = 0; // padding - j += 4; - } - } - i++; - } - } - } - - public static function bindShadowMapAtlas() { - for (atlas in ShadowMapAtlas.shadowMapAtlases) { - path.bindTarget(atlas.target, atlas.target); - } - #if rp_shadowmap_transparent - for (atlas in ShadowMapAtlas.shadowMapAtlasesTransparent) { - path.bindTarget(atlas.target, atlas.target); - } - #end - } - - static function getShadowMapAtlas(atlas:ShadowMapAtlas, transparent: Bool):String { - inline function createDepthTarget(name: String, size: Int) { - var t = new RenderTargetRaw(); - t.name = name; - t.width = t.height = size; - t.format = transparent ? "RGBA64" : "DEPTH16"; - return path.createRenderTarget(t); - } - - var rt = path.renderTargets.get(atlas.target); - // Create shadowmap atlas texture on the fly and replace existing on size change - if (rt == null) { - rt = createDepthTarget(atlas.target, atlas.sizew); - } - else if (atlas.updateRenderTarget) { - atlas.updateRenderTarget = false; - // Resize shadow map - rt.unload(); - rt = createDepthTarget(atlas.target, atlas.sizew); - } - return atlas.target; - } - - public static function drawShadowMapAtlas() { - #if rp_shadowmap - #if rp_probes - // Share shadow map with probe - if (lastFrame == RenderPath.active.frame) - return; - lastFrame = RenderPath.active.frame; - #end - - #if lnx_debug - beginShadowsLogicProfile(); - // reset data on rejected lights - for (atlas in ShadowMapAtlas.shadowMapAtlases) { - atlas.rejectedLights = []; - } - #if rp_shadowmap_transparent - for (atlas in ShadowMapAtlas.shadowMapAtlasesTransparent) { - atlas.rejectedLights = []; - } - #end - #end - - for (light in iron.Scene.active.lights) { - if (!light.lightInAtlas && !light.culledLight && light.visible && light.shadowMapScale > 0.0 - && light.data.raw.strength > 0.0 && light.data.raw.cast_shadow) { - ShadowMapAtlas.addLight(light, false); - } - #if rp_shadowmap_transparent - if (!light.lightInAtlasTransparent && !light.culledLight && light.visible && light.shadowMapScale > 0.0 - && light.data.raw.strength > 0.0 && light.data.raw.cast_shadow) { - ShadowMapAtlas.addLight(light, true); - } - #end - } - // update point light data before rendering - updatePointLightAtlasData(false); - #if rp_shadowmap_transparent - updatePointLightAtlasData(true); - #end - - for (atlas in ShadowMapAtlas.shadowMapAtlases) { - var tilesToRemove = []; - #if lnx_shadowmap_atlas_lod - var tilesToChangeSize = []; - #end - - var shadowmap = getShadowMapAtlas(atlas, false); - path.setTargetStream(shadowmap); - - path.clearTarget(null, 1.0); - - for (tile in atlas.activeTiles) { - if (tile.light == null || !tile.light.visible || tile.light.culledLight - || !tile.light.data.raw.cast_shadow || tile.light.data.raw.strength == 0) { - tile.unlockLight = true; - tilesToRemove.push(tile); - continue; - } - - #if lnx_shadowmap_atlas_lod - var newTileSize = atlas.getTileSize(tile.light.shadowMapScale); - if (newTileSize != tile.size) { - if (newTileSize == 0) { - tile.unlockLight = true; - tilesToRemove.push(tile); - continue; - } - // queue for size change - tile.newTileSize = newTileSize; - tilesToChangeSize.push(tile); - } - #end - // set the tile offset for this tile and every linked tile to this one - var j = 0; - tile.forEachTileLinked(function (lTile) { - tile.light.tileOffsetX[j] = lTile.coordsX / atlas.sizew; - tile.light.tileOffsetY[j] = lTile.coordsY / atlas.sizew; - tile.light.tileScale[j] = lTile.size / atlas.sizew; - j++; - }); - // set shadowmap size for uniform - tile.light.data.raw.shadowmap_size = atlas.sizew; - - path.light = tile.light; - - var face = 0; - var faces = ShadowMapTile.tilesLightType(tile.light.data.raw.type); - - #if lnx_debug - beginShadowsRenderProfile(); - #end - tile.forEachTileLinked(function (lTile) { - if (faces > 1) { - #if lnx_csm - switch (tile.light.data.raw.type) { - case "sun": tile.light.setCascade(iron.Scene.active.camera, face); - case "point": path.currentFace = face; - } - #else - path.currentFace = face; - #end - face++; - } - path.setCurrentViewportWithOffset(lTile.size, lTile.size, lTile.coordsX, lTile.coordsY); - - path.drawMeshesStream("shadowmap"); - }); - #if lnx_debug - endShadowsRenderProfile(); - #end - - path.currentFace = -1; - } - path.endStream(); - } - - #if rp_shadowmap_transparent - for (atlas in ShadowMapAtlas.shadowMapAtlasesTransparent) { - var tilesToRemove = []; - #if lnx_shadowmap_atlas_lod - var tilesToChangeSize = []; - #end - - var shadowmap = getShadowMapAtlas(atlas, true); - path.setTargetStream(shadowmap); - - path.clearTarget(0xffffff, 0.0); - - for (tile in atlas.activeTiles) { - if (tile.light == null || !tile.light.visible || tile.light.culledLight - || !tile.light.data.raw.cast_shadow || tile.light.data.raw.strength == 0) { - tile.unlockLight = true; - tilesToRemove.push(tile); - continue; - } - - #if lnx_shadowmap_atlas_lod - var newTileSize = atlas.getTileSize(tile.light.shadowMapScale); - if (newTileSize != tile.size) { - if (newTileSize == 0) { - tile.unlockLight = true; - tilesToRemove.push(tile); - continue; - } - // queue for size change - tile.newTileSize = newTileSize; - tilesToChangeSize.push(tile); - } - #end - // set the tile offset for this tile and every linked tile to this one - var j = 0; - tile.forEachTileLinked(function (lTile) { - tile.light.tileOffsetX[j] = lTile.coordsX / atlas.sizew; - tile.light.tileOffsetY[j] = lTile.coordsY / atlas.sizew; - tile.light.tileScale[j] = lTile.size / atlas.sizew; - j++; - }); - // set shadowmap size for uniform - tile.light.data.raw.shadowmap_size = atlas.sizew; - - path.light = tile.light; - - var face = 0; - var faces = ShadowMapTile.tilesLightType(tile.light.data.raw.type); - - #if lnx_debug - beginShadowsRenderProfile(); - #end - tile.forEachTileLinked(function (lTile) { - if (faces > 1) { - #if lnx_csm - switch (tile.light.data.raw.type) { - case "sun": tile.light.setCascade(iron.Scene.active.camera, face); - case "point": path.currentFace = face; - } - #else - path.currentFace = face; - #end - face++; - } - path.setCurrentViewportWithOffset(lTile.size, lTile.size, lTile.coordsX, lTile.coordsY); - - path.drawMeshesStream("shadowmap_transparent"); - }); - #if lnx_debug - endShadowsRenderProfile(); - #end - - path.currentFace = -1; - } - path.endStream(); - - #if lnx_shadowmap_atlas_lod - for (tile in tilesToChangeSize) { - tilesToRemove.push(tile); - - var newTile = ShadowMapTile.assignTiles(tile.light, atlas, tile); - if (newTile != null) - atlas.activeTiles.push(newTile); - } - // update point light data after changing size of tiles to avoid render issues - updatePointLightAtlasData(false); - // update point light data after changing size of tiles to avoid render issues - updatePointLightAtlasData(true); - #end - - for (tile in tilesToRemove) { - atlas.activeTiles.remove(tile); - tile.freeTile(); - } - } - #end - #end - } - #else - public static function bindShadowMap() { - for (l in iron.Scene.active.lights) { - if (!l.visible || l.data.raw.type != "sun") continue; - var n = "shadowMap"; - path.bindTarget(n, n); - var n = "shadowMapTransparent"; - path.bindTarget(n, n); - break; - } - for (i in 0...pointIndex) { - var n = "shadowMapPoint[" + i + "]"; - path.bindTarget(n, n); - var n = "shadowMapPointTransparent[" + i + "]"; - path.bindTarget(n, n); - } - for (i in 0...spotIndex) { - var n = "shadowMapSpot[" + i + "]"; - path.bindTarget(n, n); - var n = "shadowMapSpotTransparent[" + i + "]"; - path.bindTarget(n, n); - } - } - - static function shadowMapName(light: LightObject, transparent: Bool): String { - switch (light.data.raw.type) { - case "sun": - return transparent ? "shadowMapTransparent" : "shadowMap"; - case "point": - return transparent ? "shadowMapPointTransparent[" + pointIndex + "]" : "shadowMapPoint[" + pointIndex + "]"; - default: - return transparent ? "shadowMapSpotTransparent[" + spotIndex + "]" : "shadowMapSpot[" + spotIndex + "]"; - } - } - - static function getShadowMap(l: iron.object.LightObject, transparent: Bool): String { - var target = shadowMapName(l, transparent); - var rt = path.renderTargets.get(target); - // Create shadowmap on the fly - if (rt == null) { - if (path.light.data.raw.shadowmap_cube) { - // Cubemap size - var size = path.light.data.raw.shadowmap_size; - var t = new RenderTargetRaw(); - t.name = target; - t.width = size; - t.height = size; - t.format = transparent ? "RGBA64" : "DEPTH16"; - t.is_cubemap = true; - rt = path.createRenderTarget(t); - } - else { // Non-cube sm - var sizew = path.light.data.raw.shadowmap_size; - var sizeh = sizew; - #if lnx_csm // Cascades - atlas on x axis - if (l.data.raw.type == "sun") { - sizew = sizew * iron.object.LightObject.cascadeCount; - } - #end - var t = new RenderTargetRaw(); - t.name = target; - t.width = sizew; - t.height = sizeh; - t.format = transparent ? "RGBA64" : "DEPTH16"; - rt = path.createRenderTarget(t); - } - } - return target; - } - - public static function drawShadowMap() { - #if (rp_shadowmap) - - #if rp_probes - // Share shadow map with probe - if (lastFrame == RenderPath.active.frame) return; - lastFrame = RenderPath.active.frame; - #end - - pointIndex = 0; - spotIndex = 0; - for (l in iron.Scene.active.lights) { - if (!l.visible) continue; - - path.light = l; - var shadowmap = Inc.getShadowMap(l, false); - var faces = l.data.raw.shadowmap_cube ? 6 : 1; - for (i in 0...faces) { - if (faces > 1) path.currentFace = i; - path.setTarget(shadowmap); - path.clearTarget(null, 1.0); - if (l.data.raw.cast_shadow) { - path.drawMeshes("shadowmap"); - } - } - path.currentFace = -1; - - if (l.data.raw.type == "point") pointIndex++; - else if (l.data.raw.type == "spot" || l.data.raw.type == "area") spotIndex++; - } - - #if rp_shadowmap_transparent - pointIndex = 0; - spotIndex = 0; - for (l in iron.Scene.active.lights) { - if (!l.visible) continue; - - path.light = l; - var shadowmap_transparent = Inc.getShadowMap(l, true); - var faces = l.data.raw.shadowmap_cube ? 6 : 1; - for (i in 0...faces) { - if (faces > 1) path.currentFace = i; - path.setTarget(shadowmap_transparent); - path.clearTarget(0xffffff, 0.0); - if (l.data.raw.cast_shadow) { - path.drawMeshes("shadowmap_transparent"); - } - } - path.currentFace = -1; - - if (l.data.raw.type == "point") pointIndex++; - else if (l.data.raw.type == "spot" || l.data.raw.type == "area") spotIndex++; - } - #end - #end // rp_shadowmap - } - #end - - public static function applyConfig() { - #if lnx_config - var config = leenkx.data.Config.raw; - // Resize shadow map - var l = path.light; - if (l.data.raw.type == "sun" && l.data.raw.shadowmap_size != config.rp_shadowmap_cascade) { - l.data.raw.shadowmap_size = config.rp_shadowmap_cascade; - var rt = path.renderTargets.get("shadowMap"); - if (rt != null) { - rt.unload(); - path.renderTargets.remove("shadowMap"); - } - } - else if (l.data.raw.shadowmap_size != config.rp_shadowmap_cube) { - l.data.raw.shadowmap_size = config.rp_shadowmap_cube; - var rt = path.renderTargets.get("shadowMapCube"); - if (rt != null) { - rt.unload(); - path.renderTargets.remove("shadowMapCube"); - } - } - if (superSample != config.rp_supersample) { - superSample = config.rp_supersample; - for (rt in path.renderTargets) { - if (rt.raw.width == 0 && rt.raw.scale != null) { - rt.raw.scale = getSuperSampling(); - } - } - path.resize(); - } - // Init voxels - #if (rp_voxels != 'Off') - if (!voxelsCreated) initGI(); - #end - #end // lnx_config - } - - #if (rp_translucency) - public static function initTranslucency() { - path.createDepthBuffer("main", "DEPTH24"); - - var t = new RenderTargetRaw(); - t.name = "accum"; - t.width = 0; - t.height = 0; - t.displayp = getDisplayp(); - t.format = "RGBA64"; - t.scale = getSuperSampling(); - t.depth_buffer = "main"; - path.createRenderTarget(t); - - var t = new RenderTargetRaw(); - t.name = "revealage"; - t.width = 0; - t.height = 0; - t.displayp = getDisplayp(); - t.format = "R16"; - t.scale = getSuperSampling(); - t.depth_buffer = "main"; - path.createRenderTarget(t); - - path.loadShader("shader_datas/translucent_resolve/translucent_resolve"); - } - - public static function drawTranslucency(target: String) { - path.setTarget("accum"); - path.clearTarget(0xff000000); - path.setTarget("revealage"); - path.clearTarget(0xffffffff); - path.setTarget("accum", ["revealage"]); - - #if rp_shadowmap - { - #if lnx_shadowmap_atlas - bindShadowMapAtlas(); - #else - bindShadowMap(); - #end - } - #end - - #if (rp_voxels != "Off") - path.bindTarget("voxelsOut", "voxels"); - #if (rp_voxels == "Voxel GI" || lnx_voxelgi_shadows) - path.bindTarget("voxelsSDF", "voxelsSDF"); - #end - #end - - #if rp_ssrs - path.bindTarget("_main", "gbufferD"); - #end - - path.drawMeshes("translucent"); - - #if rp_render_to_texture - { - path.setTarget(target); - } - #else - { - path.setTarget(""); - } - #end - - path.bindTarget("accum", "gbuffer0"); - path.bindTarget("revealage", "gbuffer1"); - path.drawShader("shader_datas/translucent_resolve/translucent_resolve"); - } - #end - - #if rp_bloom - public static inline function drawBloom(srcRTName: String, downsampler: Downsampler, upsampler: Upsampler) { - if (leenkx.data.Config.raw.rp_bloom != false) { - // This can result in little jumps in the perceived bloom radius - // when resizing the window because numMips might change, but - // all implementations using this approach have the same problem - // (including Eevee) - final minDim = Math.min(path.currentW, path.currentH); - final logMinDim = Math.max(1.0, Helper.log2(minDim) + (Main.bloomRadius - 8.0)); - final numMips = Std.int(logMinDim); - - // Sample scale for upsampling, 0.5 to use half-texel steps, - // use fraction of logMinDim to make the visual jumps - // described above less visible - Postprocess.bloom_uniforms[3] = 0.5 + logMinDim - numMips; - - downsampler.dispatch(srcRTName, numMips); - upsampler.dispatch(srcRTName, numMips); - } - } - #end - - #if (rp_voxels != 'Off') - public static function initGI(tname = "voxels") { - var t = new RenderTargetRaw(); - t.name = tname; - - #if lnx_config - var config = leenkx.data.Config.raw; - if (config.rp_voxels != true || voxelsCreated) return; - voxelsCreated = true; - #end - - var res = iron.RenderPath.getVoxelRes(); - var resZ = iron.RenderPath.getVoxelResZ(); - - if (t.name == "voxels_diffuse" || t.name == "voxels_specular" || t.name == "voxels_ao") { - t.width = 0; - t.height = 0; - t.displayp = getDisplayp(); - t.format = "RGBA32"; - } - else { - if (t.name == "voxelsSDF" || t.name == "voxelsSDFtmp") { - t.format = "R8"; - t.width = res; - t.height = res * Main.voxelgiClipmapCount; - t.depth = res; - } - else { - #if (rp_voxels == "Voxel AO") - { - if (t.name == "voxelsOut" || t.name == "voxelsOutB") { - t.format = "R8"; - t.width = res * (6 + 16); - t.height = res * Main.voxelgiClipmapCount; - t.depth = res; - } - else { - t.format = "R32UI"; - t.width = res * 6; - t.height = res; - t.depth = res * 2; - } - } - #else - { - if (t.name == "voxelsOut" || t.name == "voxelsOutB") { - t.format = "RGBA64"; - t.width = res * (6 + 16); - t.height = res * Main.voxelgiClipmapCount; - t.depth = res; - } - else { - t.format = "R32UI"; - t.width = res * 6; - t.height = res; - t.depth = res * 16; - } - } - #end - } - } - t.is_image = true; - t.mipmaps = true; - path.createRenderTarget(t); - } - #end - - public static inline function getCubeSize(): Int { - #if (rp_shadowmap_cube == 256) - return 256; - #elseif (rp_shadowmap_cube == 512) - return 512; - #elseif (rp_shadowmap_cube == 1024) - return 1024; - #elseif (rp_shadowmap_cube == 2048) - return 2048; - #elseif (rp_shadowmap_cube == 4096) - return 4096; - #else - return 0; - #end - } - - public static inline function getCascadeSize(): Int { - #if (rp_shadowmap_cascade == 256) - return 256; - #elseif (rp_shadowmap_cascade == 512) - return 512; - #elseif (rp_shadowmap_cascade == 1024) - return 1024; - #elseif (rp_shadowmap_cascade == 2048) - return 2048; - #elseif (rp_shadowmap_cascade == 4096) - return 4096; - #elseif (rp_shadowmap_cascade == 8192) - return 8192; - #elseif (rp_shadowmap_cascade == 16384) - return 16384; - #else - return 0; - #end - } - - public static inline function getSuperSampling(): Float { - return superSample; - } - - public static inline function getHdrFormat(): String { - #if rp_hdr - return "RGBA64"; - #else - return "RGBA32"; - #end - } - - public static inline function getDisplayp(): Null { - #if rp_resolution_filter // Custom resolution set - return Main.resolutionSize; - #else - return null; - #end - } - - #if lnx_debug - public static var shadowsLogicTime = 0.0; - public static var shadowsRenderTime = 0.0; - static var startShadowsLogicTime = 0.0; - static var startShadowsRenderTime = 0.0; - static var callBackSetup = false; - static function setupEndFrameCallback() { - if (!callBackSetup) { - callBackSetup = true; - iron.App.endFrameCallbacks.push(endFrame); - } - } - static function beginShadowsLogicProfile() { setupEndFrameCallback(); startShadowsLogicTime = kha.Scheduler.realTime(); } - static function beginShadowsRenderProfile() { startShadowsRenderTime = kha.Scheduler.realTime(); } - static function endShadowsLogicProfile() { shadowsLogicTime += kha.Scheduler.realTime() - startShadowsLogicTime - shadowsRenderTime; } - static function endShadowsRenderProfile() { shadowsRenderTime += kha.Scheduler.realTime() - startShadowsRenderTime; } - public static function endFrame() { shadowsLogicTime = 0; shadowsRenderTime = 0; } - #end - - #if (rp_voxels != "Off") - public static function computeVoxelsBegin() { - if (voxel_sh0 == null) - { - voxel_sh0 = path.getComputeShader("voxel_offsetprev"); - - voxel_ta0 = voxel_sh0.getTextureUnit("voxelsB"); - voxel_tb0 = voxel_sh0.getTextureUnit("voxelsOut"); - - voxel_ca0 = voxel_sh0.getConstantLocation("clipmaps"); - voxel_cb0 = voxel_sh0.getConstantLocation("clipmapLevel"); - } - if (voxel_sh1 == null) - { - voxel_sh1 = path.getComputeShader("voxel_temporal"); - voxel_ta1 = voxel_sh1.getTextureUnit("voxels"); - voxel_tb1 = voxel_sh1.getTextureUnit("voxelsB"); - voxel_tc1 = voxel_sh1.getTextureUnit("voxelsOut"); - - voxel_ca1 = voxel_sh1.getConstantLocation("clipmaps"); - voxel_cb1 = voxel_sh1.getConstantLocation("clipmapLevel"); - - #if (rp_voxels == "Voxel GI") - voxel_td1 = voxel_sh1.getTextureUnit("voxelsSampler"); - voxel_te1 = voxel_sh1.getTextureUnit("SDF"); - #else - #if lnx_voxelgi_shadows - voxel_te1 = voxel_sh1.getTextureUnit("SDF"); - #end - #end - } - #if (lnx_voxelgi_shadows || rp_voxels == "Voxel GI") - if (voxel_sh2 == null) - { - voxel_sh2 = path.getComputeShader("voxel_sdf_jumpflood"); - voxel_ta2 = voxel_sh2.getTextureUnit("voxelsSDF"); - voxel_tb2 = voxel_sh2.getTextureUnit("voxelsSDFtmp"); - - voxel_ca2 = voxel_sh2.getConstantLocation("clipmaps"); - voxel_cb2 = voxel_sh2.getConstantLocation("clipmapLevel"); - voxel_cc2 = voxel_sh2.getConstantLocation("jump_size"); - } - #end - if (voxel_sh3 == null) - { - #if (rp_voxels == "Voxel AO") - voxel_sh3 = path.getComputeShader("voxel_resolve_ao"); - #else - voxel_sh3 = path.getComputeShader("voxel_resolve_diffuse"); - #end - voxel_ta3 = voxel_sh3.getTextureUnit("voxels"); - voxel_tb3 = voxel_sh3.getTextureUnit("gbufferD"); - voxel_tc3 = voxel_sh3.getTextureUnit("gbuffer0"); - #if (rp_voxels == "Voxel AO") - voxel_td3 = voxel_sh3.getTextureUnit("voxels_ao"); - #else - voxel_td3 = voxel_sh3.getTextureUnit("voxels_diffuse"); - #end - voxel_te3 = voxel_sh3.getTextureUnit("gbuffer1"); - voxel_tf3 = voxel_sh3.getTextureUnit("gbuffer2"); - #if lnx_brdf - voxel_tg3 = voxel_sh3.getTextureUnit("senvmapBrdf"); - #end - #if lnx_radiance - voxel_th3 = voxel_sh3.getTextureUnit("senvmapRadiance"); - #end - voxel_ca3 = voxel_sh3.getConstantLocation("clipmaps"); - voxel_cb3 = voxel_sh3.getConstantLocation("InvVP"); - voxel_cc3 = voxel_sh3.getConstantLocation("eye"); - voxel_cd3 = voxel_sh3.getConstantLocation("postprocess_resolution"); - voxel_ce3 = voxel_sh3.getConstantLocation("envmapStrength"); - #if lnx_irradiance - voxel_cf3 = voxel_sh3.getConstantLocation("shirr"); - #end - #if lnx_radiance - voxel_cg3 = voxel_sh3.getConstantLocation("envmapNumMipmaps"); - #end - #if lnx_envcol - voxel_ch3 = voxel_sh3.getConstantLocation("backgroundCol"); - #end - } - #if (rp_voxels == "Voxel GI") - if (voxel_sh4 == null) - { - voxel_sh4 = path.getComputeShader("voxel_resolve_specular"); - voxel_ta4 = voxel_sh4.getTextureUnit("voxels"); - voxel_tb4 = voxel_sh4.getTextureUnit("gbufferD"); - voxel_tc4 = voxel_sh4.getTextureUnit("gbuffer0"); - voxel_td4 = voxel_sh4.getTextureUnit("voxelsSDF"); - voxel_te4 = voxel_sh4.getTextureUnit("voxels_specular"); - voxel_tf4 = voxel_sh4.getTextureUnit("sveloc"); - voxel_ca4 = voxel_sh4.getConstantLocation("clipmaps"); - voxel_cb4 = voxel_sh4.getConstantLocation("InvVP"); - voxel_cc4 = voxel_sh4.getConstantLocation("eye"); - voxel_cd4 = voxel_sh4.getConstantLocation("postprocess_resolution"); - } - #end - } - - public static function computeVoxelsOffsetPrev() { - var rts = path.renderTargets; - var res = iron.RenderPath.getVoxelRes(); - var clipmaps = iron.RenderPath.clipmaps; - var clipmap = clipmaps[iron.RenderPath.clipmapLevel]; - - kha.compute.Compute.setShader(voxel_sh0); - - kha.compute.Compute.setTexture(voxel_ta0, rts.get("voxelsOut").image, kha.compute.Access.Read); - kha.compute.Compute.setTexture(voxel_tb0, rts.get("voxelsOutB").image, kha.compute.Access.Write); - - var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); - for (i in 0...Main.voxelgiClipmapCount) { - fa[i * 10] = clipmaps[i].voxelSize; - fa[i * 10 + 1] = clipmaps[i].extents.x; - fa[i * 10 + 2] = clipmaps[i].extents.y; - fa[i * 10 + 3] = clipmaps[i].extents.z; - fa[i * 10 + 4] = clipmaps[i].center.x; - fa[i * 10 + 5] = clipmaps[i].center.y; - fa[i * 10 + 6] = clipmaps[i].center.z; - fa[i * 10 + 7] = clipmaps[i].offset_prev.x; - fa[i * 10 + 8] = clipmaps[i].offset_prev.y; - fa[i * 10 + 9] = clipmaps[i].offset_prev.z; - } - - kha.compute.Compute.setFloats(voxel_ca0, fa); - - kha.compute.Compute.setInt(voxel_cb0, iron.RenderPath.clipmapLevel); - - kha.compute.Compute.compute(Std.int(res / 8), Std.int(res / 8), Std.int(res / 8)); - } - - public static function computeVoxelsTemporal() { - var rts = path.renderTargets; - var res = iron.RenderPath.getVoxelRes(); - var camera = iron.Scene.active.camera; - var clipmaps = iron.RenderPath.clipmaps; - var clipmap = clipmaps[iron.RenderPath.clipmapLevel]; - - kha.compute.Compute.setShader(voxel_sh1); - - kha.compute.Compute.setTexture(voxel_ta1, rts.get("voxels").image, kha.compute.Access.Read); - kha.compute.Compute.setTexture(voxel_tb1, rts.get("voxelsOutB").image, kha.compute.Access.Read); - kha.compute.Compute.setTexture(voxel_tc1, rts.get("voxelsOut").image, kha.compute.Access.Write); - #if (rp_voxels == "Voxel GI") - kha.compute.Compute.setSampledTexture(voxel_td1, rts.get("voxelsOutB").image); - kha.compute.Compute.setTexture(voxel_te1, rts.get("voxelsSDF").image, kha.compute.Access.Write); - #else - #if lnx_voxelgi_shadows - kha.compute.Compute.setTexture(voxel_te1, rts.get("voxelsSDF").image, kha.compute.Access.Write); - #end - #end - - var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); - for (i in 0...Main.voxelgiClipmapCount) { - fa[i * 10] = clipmaps[i].voxelSize; - fa[i * 10 + 1] = clipmaps[i].extents.x; - fa[i * 10 + 2] = clipmaps[i].extents.y; - fa[i * 10 + 3] = clipmaps[i].extents.z; - fa[i * 10 + 4] = clipmaps[i].center.x; - fa[i * 10 + 5] = clipmaps[i].center.y; - fa[i * 10 + 6] = clipmaps[i].center.z; - fa[i * 10 + 7] = clipmaps[i].offset_prev.x; - fa[i * 10 + 8] = clipmaps[i].offset_prev.y; - fa[i * 10 + 9] = clipmaps[i].offset_prev.z; - } - - kha.compute.Compute.setFloats(voxel_ca1, fa); - - kha.compute.Compute.setInt(voxel_cb1, iron.RenderPath.clipmapLevel); - - kha.compute.Compute.compute(Std.int(res / 8), Std.int(res / 8), Std.int(res / 8)); - } - - #if (lnx_voxelgi_shadows || (rp_voxels == "Voxel GI")) - public static function computeVoxelsSDF() { - var rts = path.renderTargets; - var res = iron.RenderPath.getVoxelRes(); - var clipmaps = iron.RenderPath.clipmaps; - var clipmap = clipmaps[iron.RenderPath.clipmapLevel]; - - var read_sdf = "voxelsSDF"; - var write_sdf = "voxelsSDFtmp"; - - var passcount = Std.int(Math.ceil(Math.log(res) / Math.log(2.0))); - - for (i in 0...passcount) { - kha.compute.Compute.setShader(voxel_sh2); - - kha.compute.Compute.setTexture(voxel_ta2, rts.get(read_sdf).image, kha.compute.Access.Read); - kha.compute.Compute.setTexture(voxel_tb2, rts.get(write_sdf).image, kha.compute.Access.Write); - - var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); - for (i in 0...Main.voxelgiClipmapCount) { - fa[i * 10] = clipmaps[i].voxelSize; - fa[i * 10 + 1] = clipmaps[i].extents.x; - fa[i * 10 + 2] = clipmaps[i].extents.y; - fa[i * 10 + 3] = clipmaps[i].extents.z; - fa[i * 10 + 4] = clipmaps[i].center.x; - fa[i * 10 + 5] = clipmaps[i].center.y; - fa[i * 10 + 6] = clipmaps[i].center.z; - fa[i * 10 + 7] = clipmaps[i].offset_prev.x; - fa[i * 10 + 8] = clipmaps[i].offset_prev.y; - fa[i * 10 + 9] = clipmaps[i].offset_prev.z; - } - - kha.compute.Compute.setFloats(voxel_ca2, fa); - - kha.compute.Compute.setInt(voxel_cb2, iron.RenderPath.clipmapLevel); - - var jump_size = Math.pow(2.0, passcount - i - 1); - kha.compute.Compute.setFloat(voxel_cc2, jump_size); - - kha.compute.Compute.compute(Std.int(res / 8), Std.int(res / 8), Std.int(res / 8)); - - if (i < passcount - 1) - { - read_sdf = read_sdf == "voxelsSDF" ? "voxelsSDFtmp" : "voxelsSDF"; - write_sdf = write_sdf == "voxelsSDF" ? "voxelsSDFtmp" : "voxelsSDF"; - } - } - } - #end - - #if (rp_voxels == "Voxel AO") - public static function resolveAO() { - var rts = path.renderTargets; - var res = iron.RenderPath.getVoxelRes(); - var camera = iron.Scene.active.camera; - var clipmaps = iron.RenderPath.clipmaps; - var clipmap = clipmaps[iron.RenderPath.clipmapLevel]; - - kha.compute.Compute.setShader(voxel_sh3); - - kha.compute.Compute.setSampledTexture(voxel_ta3, rts.get("voxelsOut").image); - kha.compute.Compute.setSampledTexture(voxel_tb3, rts.get("half").image); - kha.compute.Compute.setSampledTexture(voxel_tc3, rts.get("gbuffer0").image); - kha.compute.Compute.setTexture(voxel_td3, rts.get("voxels_ao").image, kha.compute.Access.Write); - - kha.compute.Compute.setSampledTexture(voxel_te3, rts.get("gbuffer1").image); - #if rp_gbuffer2 - kha.compute.Compute.setSampledTexture(voxel_tf3, rts.get("gbuffer2").image); - #end - #if lnx_brdf - kha.compute.Compute.setSampledTexture(voxel_tg3, iron.Scene.active.embedded.get("brdf.png")); - #end - #if lnx_radiance - kha.compute.Compute.setSampledTexture(voxel_th3, iron.Scene.active.world.probe.radiance); - #end - - var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); - for (i in 0...Main.voxelgiClipmapCount) { - fa[i * 10] = clipmaps[i].voxelSize; - fa[i * 10 + 1] = clipmaps[i].extents.x; - fa[i * 10 + 2] = clipmaps[i].extents.y; - fa[i * 10 + 3] = clipmaps[i].extents.z; - fa[i * 10 + 4] = clipmaps[i].center.x; - fa[i * 10 + 5] = clipmaps[i].center.y; - fa[i * 10 + 6] = clipmaps[i].center.z; - fa[i * 10 + 7] = clipmaps[i].offset_prev.x; - fa[i * 10 + 8] = clipmaps[i].offset_prev.y; - fa[i * 10 + 9] = clipmaps[i].offset_prev.z; - } - - kha.compute.Compute.setFloats(voxel_ca3, fa); - - #if lnx_centerworld - m.setFrom(vmat(camera.V)); - #else - m.setFrom(camera.V); - #end - m.multmat(camera.P); - m.getInverse(m); - - kha.compute.Compute.setMatrix(voxel_cb3, m.self); - - kha.compute.Compute.setFloat3(voxel_cc3, camera.transform.worldx(), camera.transform.worldy(), camera.transform.worldz()); - - var width = iron.App.w(); - var height = iron.App.h(); - var dp = getDisplayp(); - if (dp != null) { // 1080p/.. - if (width > height) { - width = Std.int(width * (dp / height) * Inc.getSuperSampling()); - height = Std.int(dp * Inc.getSuperSampling()); - } - else { - height = Std.int(height * (dp / width) * Inc.getSuperSampling()); - width = Std.int(dp * Inc.getSuperSampling()); - } - } - kha.compute.Compute.setFloat2(voxel_cd3, width, height); - - kha.compute.Compute.setFloat(voxel_ce3, iron.Scene.active.world == null ? 0.0 : iron.Scene.active.world.probe.raw.strength); - #if lnx_irradiance - var irradiance = iron.Scene.active.world == null ? - iron.data.WorldData.getEmptyIrradiance() : - iron.Scene.active.world.probe.irradiance; - kha.compute.Compute.setFloats(voxel_cf3, irradiance); - #end - #if lnx_radiance - kha.compute.Compute.setFloat(voxel_cg3, iron.Scene.active.world != null ? iron.Scene.active.world.probe.raw.radiance_mipmaps + 1 - 2 : 1); - #end - - #if lnx_envcol - var x: kha.FastFloat = 0.0; - var y: kha.FastFloat = 0.0; - var z: kha.FastFloat = 0.0; - - if (camera.data.raw.clear_color != null) { - x = camera.data.raw.clear_color[0]; - y = camera.data.raw.clear_color[1]; - z = camera.data.raw.clear_color[2]; - } - - kha.compute.Compute.setFloat3(voxel_ch3, x, y, z); - #end - - kha.compute.Compute.compute(Std.int((width + 7) / 8), Std.int((height + 7) / 8), 1); - } - #else - public static function resolveDiffuse() { - var rts = path.renderTargets; - var res = iron.RenderPath.getVoxelRes(); - var camera = iron.Scene.active.camera; - var clipmaps = iron.RenderPath.clipmaps; - var clipmap = clipmaps[iron.RenderPath.clipmapLevel]; - - kha.compute.Compute.setShader(voxel_sh3); - - kha.compute.Compute.setSampledTexture(voxel_ta3, rts.get("voxelsOut").image); - kha.compute.Compute.setSampledTexture(voxel_tb3, rts.get("half").image); - kha.compute.Compute.setSampledTexture(voxel_tc3, rts.get("gbuffer0").image); - kha.compute.Compute.setTexture(voxel_td3, rts.get("voxels_diffuse").image, kha.compute.Access.Write); - kha.compute.Compute.setSampledTexture(voxel_te3, rts.get("gbuffer1").image); - #if rp_gbuffer2 - kha.compute.Compute.setSampledTexture(voxel_tf3, rts.get("gbuffer2").image); - #end - #if lnx_brdf - kha.compute.Compute.setSampledTexture(voxel_tg3, iron.Scene.active.embedded.get("brdf.png")); - #end - #if lnx_radiance - kha.compute.Compute.setSampledTexture(voxel_th3, iron.Scene.active.world.probe.radiance); - #end - - var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); - for (i in 0...Main.voxelgiClipmapCount) { - fa[i * 10] = clipmaps[i].voxelSize; - fa[i * 10 + 1] = clipmaps[i].extents.x; - fa[i * 10 + 2] = clipmaps[i].extents.y; - fa[i * 10 + 3] = clipmaps[i].extents.z; - fa[i * 10 + 4] = clipmaps[i].center.x; - fa[i * 10 + 5] = clipmaps[i].center.y; - fa[i * 10 + 6] = clipmaps[i].center.z; - fa[i * 10 + 7] = clipmaps[i].offset_prev.x; - fa[i * 10 + 8] = clipmaps[i].offset_prev.y; - fa[i * 10 + 9] = clipmaps[i].offset_prev.z; - } - - kha.compute.Compute.setFloats(voxel_ca3, fa); - - #if lnx_centerworld - m.setFrom(vmat(camera.V)); - #else - m.setFrom(camera.V); - #end - m.multmat(camera.P); - m.getInverse(m); - - kha.compute.Compute.setMatrix(voxel_cb3, m.self); - - kha.compute.Compute.setFloat3(voxel_cc3, camera.transform.worldx(), camera.transform.worldy(), camera.transform.worldz()); - - var width = iron.App.w(); - var height = iron.App.h(); - var dp = getDisplayp(); - if (dp != null) { // 1080p/.. - if (width > height) { - width = Std.int(width * (dp / height) * Inc.getSuperSampling()); - height = Std.int(dp * Inc.getSuperSampling()); - } - else { - height = Std.int(height * (dp / width) * Inc.getSuperSampling()); - width = Std.int(dp * Inc.getSuperSampling()); - } - } - kha.compute.Compute.setFloat2(voxel_cd3, width, height); - - kha.compute.Compute.setFloat(voxel_ce3, iron.Scene.active.world == null ? 0.0 : iron.Scene.active.world.probe.raw.strength); - #if lnx_irradiance - var irradiance = iron.Scene.active.world == null ? - iron.data.WorldData.getEmptyIrradiance() : - iron.Scene.active.world.probe.irradiance; - kha.compute.Compute.setFloats(voxel_cf3, irradiance); - #end - #if lnx_radiance - kha.compute.Compute.setFloat(voxel_cg3, iron.Scene.active.world != null ? iron.Scene.active.world.probe.raw.radiance_mipmaps + 1 - 2 : 1); - #end - - #if lnx_envcol - var x: kha.FastFloat = 0.0; - var y: kha.FastFloat = 0.0; - var z: kha.FastFloat = 0.0; - - if (camera.data.raw.clear_color != null) { - x = camera.data.raw.clear_color[0]; - y = camera.data.raw.clear_color[1]; - z = camera.data.raw.clear_color[2]; - } - - kha.compute.Compute.setFloat3(voxel_ch3, x, y, z); - #end - - kha.compute.Compute.compute(Std.int((width + 7) / 8), Std.int((height + 7) / 8), 1); - } - - public static function resolveSpecular() { - var rts = path.renderTargets; - var res = iron.RenderPath.getVoxelRes(); - var camera = iron.Scene.active.camera; - var clipmaps = iron.RenderPath.clipmaps; - var clipmap = clipmaps[iron.RenderPath.clipmapLevel]; - - kha.compute.Compute.setShader(voxel_sh4); - - kha.compute.Compute.setSampledTexture(voxel_ta4, rts.get("voxelsOut").image); - kha.compute.Compute.setSampledTexture(voxel_tb4, rts.get("half").image); - kha.compute.Compute.setSampledTexture(voxel_tc4, rts.get("gbuffer0").image); - kha.compute.Compute.setSampledTexture(voxel_td4, rts.get("voxelsSDF").image); - kha.compute.Compute.setTexture(voxel_te4, rts.get("voxels_specular").image, kha.compute.Access.Write); - #if rp_gbuffer2 - kha.compute.Compute.setSampledTexture(voxel_tf4, rts.get("gbuffer2").image); - #end - - var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); - for (i in 0...Main.voxelgiClipmapCount) { - fa[i * 10] = clipmaps[i].voxelSize; - fa[i * 10 + 1] = clipmaps[i].extents.x; - fa[i * 10 + 2] = clipmaps[i].extents.y; - fa[i * 10 + 3] = clipmaps[i].extents.z; - fa[i * 10 + 4] = clipmaps[i].center.x; - fa[i * 10 + 5] = clipmaps[i].center.y; - fa[i * 10 + 6] = clipmaps[i].center.z; - fa[i * 10 + 7] = clipmaps[i].offset_prev.x; - fa[i * 10 + 8] = clipmaps[i].offset_prev.y; - fa[i * 10 + 9] = clipmaps[i].offset_prev.z; - } - - kha.compute.Compute.setFloats(voxel_ca4, fa); - - #if lnx_centerworld - m.setFrom(vmat(camera.V)); - #else - m.setFrom(camera.V); - #end - m.multmat(camera.P); - m.getInverse(m); - - kha.compute.Compute.setMatrix(voxel_cb4, m.self); - - kha.compute.Compute.setFloat3(voxel_cc4, camera.transform.worldx(), camera.transform.worldy(), camera.transform.worldz()); - - var width = iron.App.w(); - var height = iron.App.h(); - var dp = getDisplayp(); - if (dp != null) { // 1080p/.. - if (width > height) { - width = Std.int(width * (dp / height) * Inc.getSuperSampling()); - height = Std.int(dp * Inc.getSuperSampling()); - } - else { - height = Std.int(height * (dp / width) * Inc.getSuperSampling()); - width = Std.int(dp * Inc.getSuperSampling()); - } - } - kha.compute.Compute.setFloat2(voxel_cd4, width, height); - - kha.compute.Compute.compute(Std.int((width + 7) / 8), Std.int((height + 7) / 8), 1); - } - #end // GI - #end // Voxels + static var path: RenderPath; + public static var superSample = 1.0; + + static var pointIndex = 0; + static var spotIndex = 0; + static var lastFrame = -1; + + #if ((rp_voxels != 'Off') && lnx_config) + static var voxelsCreated = false; + #end + + #if (rp_voxels != "Off") + static var voxel_sh0:kha.compute.Shader = null; + static var voxel_sh1:kha.compute.Shader = null; + static var voxel_ta0:kha.compute.TextureUnit; + static var voxel_tb0:kha.compute.TextureUnit; + static var voxel_ca0:kha.compute.ConstantLocation; + static var voxel_cb0:kha.compute.ConstantLocation; + static var voxel_ta1:kha.compute.TextureUnit; + static var voxel_tb1:kha.compute.TextureUnit; + static var voxel_tc1:kha.compute.TextureUnit; + static var m = iron.math.Mat4.identity(); + static var voxel_ca1:kha.compute.ConstantLocation; + static var voxel_cb1:kha.compute.ConstantLocation; + #if (rp_voxels == "Voxel GI") + static var voxel_td1:kha.compute.TextureUnit; + static var voxel_te1:kha.compute.TextureUnit; + static var voxel_cc1:kha.compute.ConstantLocation; + #else + #if lnx_voxelgi_shadows + static var voxel_te1:kha.compute.TextureUnit; + #end + #end + #if (lnx_voxelgi_shadows || rp_voxels == "Voxel GI") + static var voxel_sh2:kha.compute.Shader = null; + static var voxel_ta2:kha.compute.TextureUnit; + static var voxel_tb2:kha.compute.TextureUnit; + static var voxel_ca2:kha.compute.ConstantLocation; + static var voxel_cb2:kha.compute.ConstantLocation; + static var voxel_cc2:kha.compute.ConstantLocation; + #end + static var voxel_sh3:kha.compute.Shader = null; + static var voxel_ta3:kha.compute.TextureUnit; + static var voxel_tb3:kha.compute.TextureUnit; + static var voxel_tc3:kha.compute.TextureUnit; + static var voxel_td3:kha.compute.TextureUnit; + static var voxel_te3:kha.compute.TextureUnit; + static var voxel_tf3:kha.compute.TextureUnit; + #if lnx_brdf + static var voxel_tg3:kha.compute.TextureUnit; + #end + #if lnx_radiance + static var voxel_th3:kha.compute.TextureUnit; + #end + static var voxel_ca3:kha.compute.ConstantLocation; + static var voxel_cb3:kha.compute.ConstantLocation; + static var voxel_cc3:kha.compute.ConstantLocation; + static var voxel_cd3:kha.compute.ConstantLocation; + static var voxel_ce3:kha.compute.ConstantLocation; + #if lnx_irradiance + static var voxel_cf3:kha.compute.ConstantLocation; + #end + #if lnx_radiance + static var voxel_cg3:kha.compute.ConstantLocation; + #end + #if lnx_envcol + static var voxel_ch3:kha.compute.ConstantLocation; + #end + #if (rp_voxels == "Voxel GI") + static var voxel_sh4:kha.compute.Shader = null; + static var voxel_ta4:kha.compute.TextureUnit; + static var voxel_tb4:kha.compute.TextureUnit; + static var voxel_tc4:kha.compute.TextureUnit; + static var voxel_td4:kha.compute.TextureUnit; + static var voxel_te4:kha.compute.TextureUnit; + static var voxel_tf4:kha.compute.TextureUnit; + static var voxel_ca4:kha.compute.ConstantLocation; + static var voxel_cb4:kha.compute.ConstantLocation; + static var voxel_cc4:kha.compute.ConstantLocation; + static var voxel_cd4:kha.compute.ConstantLocation; + #end + #end //rp_voxels + + public static function init(_path: RenderPath) { + path = _path; + + #if lnx_config + var config = leenkx.data.Config.raw; + for (l in iron.Scene.active.lights) { + l.data.raw.shadowmap_size = l.data.raw.type == "sun" ? + config.rp_shadowmap_cascade : + config.rp_shadowmap_cube; + } + superSample = config.rp_supersample; + #else + + #if (rp_supersampling == 1.5) + superSample = 1.5; + #elseif (rp_supersampling == 2) + superSample = 2.0; + #elseif (rp_supersampling == 4) + superSample = 4.0; + #end + + #end + } + + #if lnx_shadowmap_atlas + public static function updatePointLightAtlasData(transparent: Bool): Void { + var atlas = transparent ? ShadowMapAtlas.shadowMapAtlasesTransparent.get(ShadowMapAtlas.shadowMapAtlasName("point", true)) : ShadowMapAtlas.shadowMapAtlases.get(ShadowMapAtlas.shadowMapAtlasName("point", false)); + if (atlas != null) { + if(LightObject.pointLightsData == null) { + LightObject.pointLightsData = new kha.arrays.Float32Array( + LightObject.maxLightsCluster * ShadowMapTile.tilesLightType("point") * 4); // max possible visible lights * 6 or 2 (faces) * 4 (xyzw) + } + + var n = iron.Scene.active.lights.length > LightObject.maxLightsCluster ? LightObject.maxLightsCluster : iron.Scene.active.lights.length; + var i = 0; + var j = 0; + for (light in iron.Scene.active.lights) { + if (i >= n) + break; + if (LightObject.discardLightCulled(light)) continue; + if (light.data.raw.type == "point") { + if (!light.data.raw.cast_shadow) { + j += 4 * 6; + continue; + } + for(k in 0...6) { + LightObject.pointLightsData[j ] = light.tileOffsetX[k]; // posx + LightObject.pointLightsData[j + 1] = light.tileOffsetY[k]; // posy + LightObject.pointLightsData[j + 2] = light.tileScale[k]; // tile scale factor relative to atlas + LightObject.pointLightsData[j + 3] = 0; // padding + j += 4; + } + } + i++; + } + } + } + + public static function bindShadowMapAtlas() { + for (atlas in ShadowMapAtlas.shadowMapAtlases) { + path.bindTarget(atlas.target, atlas.target); + } + #if rp_shadowmap_transparent + for (atlas in ShadowMapAtlas.shadowMapAtlasesTransparent) { + path.bindTarget(atlas.target, atlas.target); + } + #end + } + + static function getShadowMapAtlas(atlas:ShadowMapAtlas, transparent: Bool):String { + inline function createDepthTarget(name: String, size: Int) { + var t = new RenderTargetRaw(); + t.name = name; + t.width = t.height = size; + t.format = transparent ? "RGBA64" : "DEPTH16"; + return path.createRenderTarget(t); + } + + var rt = path.renderTargets.get(atlas.target); + // Create shadowmap atlas texture on the fly and replace existing on size change + if (rt == null) { + rt = createDepthTarget(atlas.target, atlas.sizew); + } + else if (atlas.updateRenderTarget) { + atlas.updateRenderTarget = false; + // Resize shadow map + rt.unload(); + rt = createDepthTarget(atlas.target, atlas.sizew); + } + return atlas.target; + } + + public static function drawShadowMapAtlas() { + #if rp_shadowmap + #if rp_probes + // Share shadow map with probe + if (lastFrame == RenderPath.active.frame) + return; + lastFrame = RenderPath.active.frame; + #end + + #if lnx_debug + beginShadowsLogicProfile(); + // reset data on rejected lights + for (atlas in ShadowMapAtlas.shadowMapAtlases) { + atlas.rejectedLights = []; + } + #if rp_shadowmap_transparent + for (atlas in ShadowMapAtlas.shadowMapAtlasesTransparent) { + atlas.rejectedLights = []; + } + #end + #end + + for (light in iron.Scene.active.lights) { + if (!light.lightInAtlas && !light.culledLight && light.visible && light.shadowMapScale > 0.0 + && light.data.raw.strength > 0.0 && light.data.raw.cast_shadow) { + ShadowMapAtlas.addLight(light, false); + } + #if rp_shadowmap_transparent + if (!light.lightInAtlasTransparent && !light.culledLight && light.visible && light.shadowMapScale > 0.0 + && light.data.raw.strength > 0.0 && light.data.raw.cast_shadow) { + ShadowMapAtlas.addLight(light, true); + } + #end + } + // update point light data before rendering + updatePointLightAtlasData(false); + #if rp_shadowmap_transparent + updatePointLightAtlasData(true); + #end + + for (atlas in ShadowMapAtlas.shadowMapAtlases) { + var tilesToRemove = []; + #if lnx_shadowmap_atlas_lod + var tilesToChangeSize = []; + #end + + var shadowmap = getShadowMapAtlas(atlas, false); + path.setTargetStream(shadowmap); + + path.clearTarget(null, 1.0); + + for (tile in atlas.activeTiles) { + if (tile.light == null || !tile.light.visible || tile.light.culledLight + || !tile.light.data.raw.cast_shadow || tile.light.data.raw.strength == 0) { + tile.unlockLight = true; + tilesToRemove.push(tile); + continue; + } + + #if lnx_shadowmap_atlas_lod + var newTileSize = atlas.getTileSize(tile.light.shadowMapScale); + if (newTileSize != tile.size) { + if (newTileSize == 0) { + tile.unlockLight = true; + tilesToRemove.push(tile); + continue; + } + // queue for size change + tile.newTileSize = newTileSize; + tilesToChangeSize.push(tile); + } + #end + // set the tile offset for this tile and every linked tile to this one + var j = 0; + tile.forEachTileLinked(function (lTile) { + tile.light.tileOffsetX[j] = lTile.coordsX / atlas.sizew; + tile.light.tileOffsetY[j] = lTile.coordsY / atlas.sizew; + tile.light.tileScale[j] = lTile.size / atlas.sizew; + j++; + }); + // set shadowmap size for uniform + tile.light.data.raw.shadowmap_size = atlas.sizew; + + path.light = tile.light; + + var face = 0; + var faces = ShadowMapTile.tilesLightType(tile.light.data.raw.type); + + #if lnx_debug + beginShadowsRenderProfile(); + #end + tile.forEachTileLinked(function (lTile) { + if (faces > 1) { + #if lnx_csm + switch (tile.light.data.raw.type) { + case "sun": tile.light.setCascade(iron.Scene.active.camera, face); + case "point": path.currentFace = face; + } + #else + path.currentFace = face; + #end + face++; + } + path.setCurrentViewportWithOffset(lTile.size, lTile.size, lTile.coordsX, lTile.coordsY); + + path.drawMeshesStream("shadowmap"); + }); + #if lnx_debug + endShadowsRenderProfile(); + #end + + path.currentFace = -1; + } + path.endStream(); + } + + #if rp_shadowmap_transparent + for (atlas in ShadowMapAtlas.shadowMapAtlasesTransparent) { + var tilesToRemove = []; + #if lnx_shadowmap_atlas_lod + var tilesToChangeSize = []; + #end + + var shadowmap = getShadowMapAtlas(atlas, true); + path.setTargetStream(shadowmap); + + path.clearTarget(0xffffff, 0.0); + + for (tile in atlas.activeTiles) { + if (tile.light == null || !tile.light.visible || tile.light.culledLight + || !tile.light.data.raw.cast_shadow || tile.light.data.raw.strength == 0) { + tile.unlockLight = true; + tilesToRemove.push(tile); + continue; + } + + #if lnx_shadowmap_atlas_lod + var newTileSize = atlas.getTileSize(tile.light.shadowMapScale); + if (newTileSize != tile.size) { + if (newTileSize == 0) { + tile.unlockLight = true; + tilesToRemove.push(tile); + continue; + } + // queue for size change + tile.newTileSize = newTileSize; + tilesToChangeSize.push(tile); + } + #end + // set the tile offset for this tile and every linked tile to this one + var j = 0; + tile.forEachTileLinked(function (lTile) { + tile.light.tileOffsetX[j] = lTile.coordsX / atlas.sizew; + tile.light.tileOffsetY[j] = lTile.coordsY / atlas.sizew; + tile.light.tileScale[j] = lTile.size / atlas.sizew; + j++; + }); + // set shadowmap size for uniform + tile.light.data.raw.shadowmap_size = atlas.sizew; + + path.light = tile.light; + + var face = 0; + var faces = ShadowMapTile.tilesLightType(tile.light.data.raw.type); + + #if lnx_debug + beginShadowsRenderProfile(); + #end + tile.forEachTileLinked(function (lTile) { + if (faces > 1) { + #if lnx_csm + switch (tile.light.data.raw.type) { + case "sun": tile.light.setCascade(iron.Scene.active.camera, face); + case "point": path.currentFace = face; + } + #else + path.currentFace = face; + #end + face++; + } + path.setCurrentViewportWithOffset(lTile.size, lTile.size, lTile.coordsX, lTile.coordsY); + + path.drawMeshesStream("shadowmap_transparent"); + }); + #if lnx_debug + endShadowsRenderProfile(); + #end + + path.currentFace = -1; + } + path.endStream(); + + #if lnx_shadowmap_atlas_lod + for (tile in tilesToChangeSize) { + tilesToRemove.push(tile); + + var newTile = ShadowMapTile.assignTiles(tile.light, atlas, tile); + if (newTile != null) + atlas.activeTiles.push(newTile); + } + // update point light data after changing size of tiles to avoid render issues + updatePointLightAtlasData(false); + // update point light data after changing size of tiles to avoid render issues + updatePointLightAtlasData(true); + #end + + for (tile in tilesToRemove) { + atlas.activeTiles.remove(tile); + tile.freeTile(); + } + } + #end + #end + } + #else + public static function bindShadowMap() { + for (l in iron.Scene.active.lights) { + if (!l.visible || l.data.raw.type != "sun") continue; + var n = "shadowMap"; + path.bindTarget(n, n); + var n = "shadowMapTransparent"; + path.bindTarget(n, n); + break; + } + for (i in 0...pointIndex) { + var n = "shadowMapPoint[" + i + "]"; + path.bindTarget(n, n); + var n = "shadowMapPointTransparent[" + i + "]"; + path.bindTarget(n, n); + } + for (i in 0...spotIndex) { + var n = "shadowMapSpot[" + i + "]"; + path.bindTarget(n, n); + var n = "shadowMapSpotTransparent[" + i + "]"; + path.bindTarget(n, n); + } + } + + static function shadowMapName(light: LightObject, transparent: Bool): String { + switch (light.data.raw.type) { + case "sun": + return transparent ? "shadowMapTransparent" : "shadowMap"; + case "point": + return transparent ? "shadowMapPointTransparent[" + pointIndex + "]" : "shadowMapPoint[" + pointIndex + "]"; + default: + return transparent ? "shadowMapSpotTransparent[" + spotIndex + "]" : "shadowMapSpot[" + spotIndex + "]"; + } + } + + static function getShadowMap(l: iron.object.LightObject, transparent: Bool): String { + var target = shadowMapName(l, transparent); + var rt = path.renderTargets.get(target); + // Create shadowmap on the fly + if (rt == null) { + if (path.light.data.raw.shadowmap_cube) { + // Cubemap size + var size = path.light.data.raw.shadowmap_size; + var t = new RenderTargetRaw(); + t.name = target; + t.width = size; + t.height = size; + t.format = transparent ? "RGBA64" : "DEPTH16"; + t.is_cubemap = true; + rt = path.createRenderTarget(t); + } + else { // Non-cube sm + var sizew = path.light.data.raw.shadowmap_size; + var sizeh = sizew; + #if lnx_csm // Cascades - atlas on x axis + if (l.data.raw.type == "sun") { + sizew = sizew * iron.object.LightObject.cascadeCount; + } + #end + var t = new RenderTargetRaw(); + t.name = target; + t.width = sizew; + t.height = sizeh; + t.format = transparent ? "RGBA64" : "DEPTH16"; + rt = path.createRenderTarget(t); + } + } + return target; + } + + public static function drawShadowMap() { + #if (rp_shadowmap) + + #if rp_probes + // Share shadow map with probe + if (lastFrame == RenderPath.active.frame) return; + lastFrame = RenderPath.active.frame; + #end + + pointIndex = 0; + spotIndex = 0; + for (l in iron.Scene.active.lights) { + if (!l.visible) continue; + + path.light = l; + var shadowmap = Inc.getShadowMap(l, false); + var faces = l.data.raw.shadowmap_cube ? 6 : 1; + for (i in 0...faces) { + if (faces > 1) path.currentFace = i; + path.setTarget(shadowmap); + path.clearTarget(null, 1.0); + if (l.data.raw.cast_shadow) { + path.drawMeshes("shadowmap"); + } + } + path.currentFace = -1; + + if (l.data.raw.type == "point") pointIndex++; + else if (l.data.raw.type == "spot" || l.data.raw.type == "area") spotIndex++; + } + + #if rp_shadowmap_transparent + pointIndex = 0; + spotIndex = 0; + for (l in iron.Scene.active.lights) { + if (!l.visible) continue; + + path.light = l; + var shadowmap_transparent = Inc.getShadowMap(l, true); + var faces = l.data.raw.shadowmap_cube ? 6 : 1; + for (i in 0...faces) { + if (faces > 1) path.currentFace = i; + path.setTarget(shadowmap_transparent); + path.clearTarget(0xffffff, 0.0); + if (l.data.raw.cast_shadow) { + path.drawMeshes("shadowmap_transparent"); + } + } + path.currentFace = -1; + + if (l.data.raw.type == "point") pointIndex++; + else if (l.data.raw.type == "spot" || l.data.raw.type == "area") spotIndex++; + } + #end + #end // rp_shadowmap + } + #end + + public static function applyConfig() { + #if lnx_config + var config = leenkx.data.Config.raw; + // Resize shadow map + var l = path.light; + if (l.data.raw.type == "sun" && l.data.raw.shadowmap_size != config.rp_shadowmap_cascade) { + l.data.raw.shadowmap_size = config.rp_shadowmap_cascade; + var rt = path.renderTargets.get("shadowMap"); + if (rt != null) { + rt.unload(); + path.renderTargets.remove("shadowMap"); + } + } + else if (l.data.raw.shadowmap_size != config.rp_shadowmap_cube) { + l.data.raw.shadowmap_size = config.rp_shadowmap_cube; + var rt = path.renderTargets.get("shadowMapCube"); + if (rt != null) { + rt.unload(); + path.renderTargets.remove("shadowMapCube"); + } + } + if (superSample != config.rp_supersample) { + superSample = config.rp_supersample; + for (rt in path.renderTargets) { + if (rt.raw.width == 0 && rt.raw.scale != null) { + rt.raw.scale = getSuperSampling(); + } + } + path.resize(); + } + // Init voxels + #if (rp_voxels != 'Off') + if (!voxelsCreated) initGI(); + #end + #end // lnx_config + } + + #if (rp_translucency) + public static function initTranslucency() { + path.createDepthBuffer("main", "DEPTH24"); + + var t = new RenderTargetRaw(); + t.name = "accum"; + t.width = 0; + t.height = 0; + t.displayp = getDisplayp(); + t.format = "RGBA64"; + t.scale = getSuperSampling(); + t.depth_buffer = "main"; + path.createRenderTarget(t); + + var t = new RenderTargetRaw(); + t.name = "revealage"; + t.width = 0; + t.height = 0; + t.displayp = getDisplayp(); + t.format = "R16"; + t.scale = getSuperSampling(); + t.depth_buffer = "main"; + path.createRenderTarget(t); + + path.loadShader("shader_datas/translucent_resolve/translucent_resolve"); + } + + public static function drawTranslucency(target: String) { + path.setTarget("accum"); + path.clearTarget(0xff000000); + path.setTarget("revealage"); + path.clearTarget(0xffffffff); + path.setTarget("accum", ["revealage"]); + + #if rp_shadowmap + { + #if lnx_shadowmap_atlas + bindShadowMapAtlas(); + #else + bindShadowMap(); + #end + } + #end + + #if (rp_voxels != "Off") + path.bindTarget("voxelsOut", "voxels"); + #if (rp_voxels == "Voxel GI" || lnx_voxelgi_shadows) + path.bindTarget("voxelsSDF", "voxelsSDF"); + #end + #end + + #if rp_ssrs + path.bindTarget("_main", "gbufferD"); + #end + + path.drawMeshes("translucent"); + + #if rp_render_to_texture + { + path.setTarget(target); + } + #else + { + path.setTarget(""); + } + #end + + path.bindTarget("accum", "gbuffer0"); + path.bindTarget("revealage", "gbuffer1"); + path.drawShader("shader_datas/translucent_resolve/translucent_resolve"); + } + #end + + #if rp_bloom + public static inline function drawBloom(srcRTName: String, downsampler: Downsampler, upsampler: Upsampler) { + if (leenkx.data.Config.raw.rp_bloom != false) { + // This can result in little jumps in the perceived bloom radius + // when resizing the window because numMips might change, but + // all implementations using this approach have the same problem + // (including Eevee) + final minDim = Math.min(path.currentW, path.currentH); + final logMinDim = Math.max(1.0, Helper.log2(minDim) + (Main.bloomRadius - 8.0)); + final numMips = Std.int(logMinDim); + + // Sample scale for upsampling, 0.5 to use half-texel steps, + // use fraction of logMinDim to make the visual jumps + // described above less visible + Postprocess.bloom_uniforms[3] = 0.5 + logMinDim - numMips; + + downsampler.dispatch(srcRTName, numMips); + upsampler.dispatch(srcRTName, numMips); + } + } + #end + + #if (rp_voxels != 'Off') + public static function initGI(tname = "voxels") { + var t = new RenderTargetRaw(); + t.name = tname; + + #if lnx_config + var config = leenkx.data.Config.raw; + if (config.rp_voxels != true || voxelsCreated) return; + voxelsCreated = true; + #end + + var res = iron.RenderPath.getVoxelRes(); + var resZ = iron.RenderPath.getVoxelResZ(); + + if (t.name == "voxels_diffuse" || t.name == "voxels_specular" || t.name == "voxels_ao") { + t.width = 0; + t.height = 0; + t.displayp = getDisplayp(); + t.format = "RGBA32"; + } + else { + if (t.name == "voxelsSDF" || t.name == "voxelsSDFtmp") { + t.format = "R16"; + t.width = res; + t.height = res * Main.voxelgiClipmapCount; + t.depth = res; + } + else { + #if (rp_voxels == "Voxel AO") + { + if (t.name == "voxelsOut" || t.name == "voxelsOutB") { + t.format = "R16"; + t.width = res * (6 + 16); + t.height = res * Main.voxelgiClipmapCount; + t.depth = res; + } + else { + t.format = "R32UI"; + t.width = res * 6; + t.height = res; + t.depth = res * 2; + } + } + #else + { + if (t.name == "voxelsOut" || t.name == "voxelsOutB") { + t.format = "RGBA64"; + t.width = res * (6 + 16); + t.height = res * Main.voxelgiClipmapCount; + t.depth = res; + } + else { + t.format = "R32UI"; + t.width = res * 6; + t.height = res; + t.depth = res * 16; + } + } + #end + } + } + t.is_image = true; + t.mipmaps = true; + path.createRenderTarget(t); + } + #end + + public static inline function getCubeSize(): Int { + #if (rp_shadowmap_cube == 256) + return 256; + #elseif (rp_shadowmap_cube == 512) + return 512; + #elseif (rp_shadowmap_cube == 1024) + return 1024; + #elseif (rp_shadowmap_cube == 2048) + return 2048; + #elseif (rp_shadowmap_cube == 4096) + return 4096; + #else + return 0; + #end + } + + public static inline function getCascadeSize(): Int { + #if (rp_shadowmap_cascade == 256) + return 256; + #elseif (rp_shadowmap_cascade == 512) + return 512; + #elseif (rp_shadowmap_cascade == 1024) + return 1024; + #elseif (rp_shadowmap_cascade == 2048) + return 2048; + #elseif (rp_shadowmap_cascade == 4096) + return 4096; + #elseif (rp_shadowmap_cascade == 8192) + return 8192; + #elseif (rp_shadowmap_cascade == 16384) + return 16384; + #else + return 0; + #end + } + + public static inline function getSuperSampling(): Float { + return superSample; + } + + public static inline function getHdrFormat(): String { + #if rp_hdr + return "RGBA64"; + #else + return "RGBA32"; + #end + } + + public static inline function getDisplayp(): Null { + #if rp_resolution_filter // Custom resolution set + return Main.resolutionSize; + #else + return null; + #end + } + + #if lnx_debug + public static var shadowsLogicTime = 0.0; + public static var shadowsRenderTime = 0.0; + static var startShadowsLogicTime = 0.0; + static var startShadowsRenderTime = 0.0; + static var callBackSetup = false; + static function setupEndFrameCallback() { + if (!callBackSetup) { + callBackSetup = true; + iron.App.endFrameCallbacks.push(endFrame); + } + } + static function beginShadowsLogicProfile() { setupEndFrameCallback(); startShadowsLogicTime = kha.Scheduler.realTime(); } + static function beginShadowsRenderProfile() { startShadowsRenderTime = kha.Scheduler.realTime(); } + static function endShadowsLogicProfile() { shadowsLogicTime += kha.Scheduler.realTime() - startShadowsLogicTime - shadowsRenderTime; } + static function endShadowsRenderProfile() { shadowsRenderTime += kha.Scheduler.realTime() - startShadowsRenderTime; } + public static function endFrame() { shadowsLogicTime = 0; shadowsRenderTime = 0; } + #end + + #if (rp_voxels != "Off") + public static function computeVoxelsBegin() { + if (voxel_sh0 == null) + { + voxel_sh0 = path.getComputeShader("voxel_offsetprev"); + + voxel_ta0 = voxel_sh0.getTextureUnit("voxelsB"); + voxel_tb0 = voxel_sh0.getTextureUnit("voxelsOut"); + + voxel_ca0 = voxel_sh0.getConstantLocation("clipmaps"); + voxel_cb0 = voxel_sh0.getConstantLocation("clipmapLevel"); + } + if (voxel_sh1 == null) + { + voxel_sh1 = path.getComputeShader("voxel_temporal"); + voxel_ta1 = voxel_sh1.getTextureUnit("voxels"); + voxel_tb1 = voxel_sh1.getTextureUnit("voxelsB"); + voxel_tc1 = voxel_sh1.getTextureUnit("voxelsOut"); + + voxel_ca1 = voxel_sh1.getConstantLocation("clipmaps"); + voxel_cb1 = voxel_sh1.getConstantLocation("clipmapLevel"); + voxel_cc1 = voxel_sh1.getConstantLocation("envmapStrength"); + + #if (rp_voxels == "Voxel GI") + voxel_td1 = voxel_sh1.getTextureUnit("voxelsSampler"); + voxel_te1 = voxel_sh1.getTextureUnit("SDF"); + voxel_cc1 = voxel_sh1.getConstantLocation("envmapStrength"); + #else + #if lnx_voxelgi_shadows + voxel_te1 = voxel_sh1.getTextureUnit("SDF"); + #end + #end + } + #if (lnx_voxelgi_shadows || rp_voxels == "Voxel GI") + if (voxel_sh2 == null) + { + voxel_sh2 = path.getComputeShader("voxel_sdf_jumpflood"); + voxel_ta2 = voxel_sh2.getTextureUnit("voxelsSDF"); + voxel_tb2 = voxel_sh2.getTextureUnit("voxelsSDFtmp"); + + voxel_ca2 = voxel_sh2.getConstantLocation("clipmaps"); + voxel_cb2 = voxel_sh2.getConstantLocation("clipmapLevel"); + voxel_cc2 = voxel_sh2.getConstantLocation("jump_size"); + } + #end + if (voxel_sh3 == null) + { + #if (rp_voxels == "Voxel AO") + voxel_sh3 = path.getComputeShader("voxel_resolve_ao"); + #else + voxel_sh3 = path.getComputeShader("voxel_resolve_diffuse"); + #end + voxel_ta3 = voxel_sh3.getTextureUnit("voxels"); + voxel_tb3 = voxel_sh3.getTextureUnit("gbufferD"); + voxel_tc3 = voxel_sh3.getTextureUnit("gbuffer0"); + #if (rp_voxels == "Voxel AO") + voxel_td3 = voxel_sh3.getTextureUnit("voxels_ao"); + #else + voxel_td3 = voxel_sh3.getTextureUnit("voxels_diffuse"); + #end + voxel_te3 = voxel_sh3.getTextureUnit("gbuffer1"); + voxel_tf3 = voxel_sh3.getTextureUnit("gbuffer2"); + #if lnx_brdf + voxel_tg3 = voxel_sh3.getTextureUnit("senvmapBrdf"); + #end + #if lnx_radiance + voxel_th3 = voxel_sh3.getTextureUnit("senvmapRadiance"); + #end + voxel_ca3 = voxel_sh3.getConstantLocation("clipmaps"); + voxel_cb3 = voxel_sh3.getConstantLocation("InvVP"); + voxel_cc3 = voxel_sh3.getConstantLocation("eye"); + voxel_cd3 = voxel_sh3.getConstantLocation("postprocess_resolution"); + voxel_ce3 = voxel_sh3.getConstantLocation("envmapStrength"); + #if lnx_irradiance + voxel_cf3 = voxel_sh3.getConstantLocation("shirr"); + #end + #if lnx_radiance + voxel_cg3 = voxel_sh3.getConstantLocation("envmapNumMipmaps"); + #end + #if lnx_envcol + voxel_ch3 = voxel_sh3.getConstantLocation("backgroundCol"); + #end + } + #if (rp_voxels == "Voxel GI") + if (voxel_sh4 == null) + { + voxel_sh4 = path.getComputeShader("voxel_resolve_specular"); + voxel_ta4 = voxel_sh4.getTextureUnit("voxels"); + voxel_tb4 = voxel_sh4.getTextureUnit("gbufferD"); + voxel_tc4 = voxel_sh4.getTextureUnit("gbuffer0"); + voxel_td4 = voxel_sh4.getTextureUnit("voxelsSDF"); + voxel_te4 = voxel_sh4.getTextureUnit("voxels_specular"); + voxel_tf4 = voxel_sh4.getTextureUnit("sveloc"); + voxel_ca4 = voxel_sh4.getConstantLocation("clipmaps"); + voxel_cb4 = voxel_sh4.getConstantLocation("InvVP"); + voxel_cc4 = voxel_sh4.getConstantLocation("eye"); + voxel_cd4 = voxel_sh4.getConstantLocation("postprocess_resolution"); + } + #end + } + + public static function computeVoxelsOffsetPrev() { + var rts = path.renderTargets; + var res = iron.RenderPath.getVoxelRes(); + var clipmaps = iron.RenderPath.clipmaps; + var clipmap = clipmaps[iron.RenderPath.clipmapLevel]; + + kha.compute.Compute.setShader(voxel_sh0); + + kha.compute.Compute.setTexture(voxel_ta0, rts.get("voxelsOut").image, kha.compute.Access.Read); + kha.compute.Compute.setTexture(voxel_tb0, rts.get("voxelsOutB").image, kha.compute.Access.Write); + + var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); + for (i in 0...Main.voxelgiClipmapCount) { + fa[i * 10] = clipmaps[i].voxelSize; + fa[i * 10 + 1] = clipmaps[i].extents.x; + fa[i * 10 + 2] = clipmaps[i].extents.y; + fa[i * 10 + 3] = clipmaps[i].extents.z; + fa[i * 10 + 4] = clipmaps[i].center.x; + fa[i * 10 + 5] = clipmaps[i].center.y; + fa[i * 10 + 6] = clipmaps[i].center.z; + fa[i * 10 + 7] = clipmaps[i].offset_prev.x; + fa[i * 10 + 8] = clipmaps[i].offset_prev.y; + fa[i * 10 + 9] = clipmaps[i].offset_prev.z; + } + + kha.compute.Compute.setFloats(voxel_ca0, fa); + + kha.compute.Compute.setInt(voxel_cb0, iron.RenderPath.clipmapLevel); + + kha.compute.Compute.compute(Std.int(res / 8), Std.int(res / 8), Std.int(res / 8)); + } + + public static function computeVoxelsTemporal() { + var rts = path.renderTargets; + var res = iron.RenderPath.getVoxelRes(); + var camera = iron.Scene.active.camera; + var clipmaps = iron.RenderPath.clipmaps; + var clipmap = clipmaps[iron.RenderPath.clipmapLevel]; + + kha.compute.Compute.setShader(voxel_sh1); + + kha.compute.Compute.setTexture(voxel_ta1, rts.get("voxels").image, kha.compute.Access.Read); + kha.compute.Compute.setTexture(voxel_tb1, rts.get("voxelsOutB").image, kha.compute.Access.Read); + kha.compute.Compute.setTexture(voxel_tc1, rts.get("voxelsOut").image, kha.compute.Access.Write); + #if (rp_voxels == "Voxel GI") + kha.compute.Compute.setSampledTexture(voxel_td1, rts.get("voxelsOutB").image); + kha.compute.Compute.setTexture(voxel_te1, rts.get("voxelsSDF").image, kha.compute.Access.Write); + kha.compute.Compute.setFloat(voxel_cc1, iron.Scene.active.world == null ? 0.0 : iron.Scene.active.world.probe.raw.strength); + #else + #if lnx_voxelgi_shadows + kha.compute.Compute.setTexture(voxel_te1, rts.get("voxelsSDF").image, kha.compute.Access.Write); + #end + #end + + var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); + for (i in 0...Main.voxelgiClipmapCount) { + fa[i * 10] = clipmaps[i].voxelSize; + fa[i * 10 + 1] = clipmaps[i].extents.x; + fa[i * 10 + 2] = clipmaps[i].extents.y; + fa[i * 10 + 3] = clipmaps[i].extents.z; + fa[i * 10 + 4] = clipmaps[i].center.x; + fa[i * 10 + 5] = clipmaps[i].center.y; + fa[i * 10 + 6] = clipmaps[i].center.z; + fa[i * 10 + 7] = clipmaps[i].offset_prev.x; + fa[i * 10 + 8] = clipmaps[i].offset_prev.y; + fa[i * 10 + 9] = clipmaps[i].offset_prev.z; + } + + kha.compute.Compute.setFloats(voxel_ca1, fa); + + kha.compute.Compute.setInt(voxel_cb1, iron.RenderPath.clipmapLevel); + + kha.compute.Compute.setFloat(voxel_cc1, iron.Scene.active.world == null ? 0.0 : iron.Scene.active.world.probe.raw.strength); + + kha.compute.Compute.compute(Std.int(res / 8), Std.int(res / 8), Std.int(res / 8)); + } + + #if (lnx_voxelgi_shadows || (rp_voxels == "Voxel GI")) + public static function computeVoxelsSDF() { + var rts = path.renderTargets; + var res = iron.RenderPath.getVoxelRes(); + var clipmaps = iron.RenderPath.clipmaps; + var clipmap = clipmaps[iron.RenderPath.clipmapLevel]; + + var read_sdf = "voxelsSDF"; + var write_sdf = "voxelsSDFtmp"; + + var passcount = Std.int(Math.ceil(Math.log(res) / Math.log(2.0))); + + for (i in 0...passcount) { + kha.compute.Compute.setShader(voxel_sh2); + + kha.compute.Compute.setTexture(voxel_ta2, rts.get(read_sdf).image, kha.compute.Access.Read); + kha.compute.Compute.setTexture(voxel_tb2, rts.get(write_sdf).image, kha.compute.Access.Write); + + var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); + for (i in 0...Main.voxelgiClipmapCount) { + fa[i * 10] = clipmaps[i].voxelSize; + fa[i * 10 + 1] = clipmaps[i].extents.x; + fa[i * 10 + 2] = clipmaps[i].extents.y; + fa[i * 10 + 3] = clipmaps[i].extents.z; + fa[i * 10 + 4] = clipmaps[i].center.x; + fa[i * 10 + 5] = clipmaps[i].center.y; + fa[i * 10 + 6] = clipmaps[i].center.z; + fa[i * 10 + 7] = clipmaps[i].offset_prev.x; + fa[i * 10 + 8] = clipmaps[i].offset_prev.y; + fa[i * 10 + 9] = clipmaps[i].offset_prev.z; + } + + kha.compute.Compute.setFloats(voxel_ca2, fa); + + kha.compute.Compute.setInt(voxel_cb2, iron.RenderPath.clipmapLevel); + + var jump_size = Math.pow(2.0, passcount - i - 1); + kha.compute.Compute.setFloat(voxel_cc2, jump_size); + + kha.compute.Compute.compute(Std.int(res / 8), Std.int(res / 8), Std.int(res / 8)); + + if (i < passcount - 1) + { + read_sdf = read_sdf == "voxelsSDF" ? "voxelsSDFtmp" : "voxelsSDF"; + write_sdf = write_sdf == "voxelsSDF" ? "voxelsSDFtmp" : "voxelsSDF"; + } + } + } + #end + + #if (rp_voxels == "Voxel AO") + public static function resolveAO() { + var rts = path.renderTargets; + var res = iron.RenderPath.getVoxelRes(); + var camera = iron.Scene.active.camera; + var clipmaps = iron.RenderPath.clipmaps; + var clipmap = clipmaps[iron.RenderPath.clipmapLevel]; + + kha.compute.Compute.setShader(voxel_sh3); + + kha.compute.Compute.setSampledTexture(voxel_ta3, rts.get("voxelsOut").image); + kha.compute.Compute.setSampledTexture(voxel_tb3, rts.get("half").image); + kha.compute.Compute.setSampledTexture(voxel_tc3, rts.get("gbuffer0").image); + kha.compute.Compute.setTexture(voxel_td3, rts.get("voxels_ao").image, kha.compute.Access.Write); + + kha.compute.Compute.setSampledTexture(voxel_te3, rts.get("gbuffer1").image); + #if rp_gbuffer2 + kha.compute.Compute.setSampledTexture(voxel_tf3, rts.get("gbuffer2").image); + #end + #if lnx_brdf + kha.compute.Compute.setSampledTexture(voxel_tg3, iron.Scene.active.embedded.get("brdf.png")); + #end + #if lnx_radiance + kha.compute.Compute.setSampledTexture(voxel_th3, iron.Scene.active.world.probe.radiance); + #end + + var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); + for (i in 0...Main.voxelgiClipmapCount) { + fa[i * 10] = clipmaps[i].voxelSize; + fa[i * 10 + 1] = clipmaps[i].extents.x; + fa[i * 10 + 2] = clipmaps[i].extents.y; + fa[i * 10 + 3] = clipmaps[i].extents.z; + fa[i * 10 + 4] = clipmaps[i].center.x; + fa[i * 10 + 5] = clipmaps[i].center.y; + fa[i * 10 + 6] = clipmaps[i].center.z; + fa[i * 10 + 7] = clipmaps[i].offset_prev.x; + fa[i * 10 + 8] = clipmaps[i].offset_prev.y; + fa[i * 10 + 9] = clipmaps[i].offset_prev.z; + } + + kha.compute.Compute.setFloats(voxel_ca3, fa); + + #if lnx_centerworld + m.setFrom(vmat(camera.V)); + #else + m.setFrom(camera.V); + #end + m.multmat(camera.P); + m.getInverse(m); + + kha.compute.Compute.setMatrix(voxel_cb3, m.self); + + kha.compute.Compute.setFloat3(voxel_cc3, camera.transform.worldx(), camera.transform.worldy(), camera.transform.worldz()); + + var width = iron.App.w(); + var height = iron.App.h(); + var dp = getDisplayp(); + if (dp != null) { // 1080p/.. + if (width > height) { + width = Std.int(width * (dp / height) * Inc.getSuperSampling()); + height = Std.int(dp * Inc.getSuperSampling()); + } + else { + height = Std.int(height * (dp / width) * Inc.getSuperSampling()); + width = Std.int(dp * Inc.getSuperSampling()); + } + } + kha.compute.Compute.setFloat2(voxel_cd3, width, height); + + kha.compute.Compute.setFloat(voxel_ce3, iron.Scene.active.world == null ? 0.0 : iron.Scene.active.world.probe.raw.strength); + #if lnx_irradiance + var irradiance = iron.Scene.active.world == null ? + iron.data.WorldData.getEmptyIrradiance() : + iron.Scene.active.world.probe.irradiance; + kha.compute.Compute.setFloats(voxel_cf3, irradiance); + #end + #if lnx_radiance + kha.compute.Compute.setFloat(voxel_cg3, iron.Scene.active.world != null ? iron.Scene.active.world.probe.raw.radiance_mipmaps + 1 - 2 : 1); + #end + + #if lnx_envcol + var x: kha.FastFloat = 0.0; + var y: kha.FastFloat = 0.0; + var z: kha.FastFloat = 0.0; + + if (camera.data.raw.clear_color != null) { + x = camera.data.raw.clear_color[0]; + y = camera.data.raw.clear_color[1]; + z = camera.data.raw.clear_color[2]; + } + + kha.compute.Compute.setFloat3(voxel_ch3, x, y, z); + #end + + kha.compute.Compute.compute(Std.int((width + 7) / 8), Std.int((height + 7) / 8), 1); + } + #else + public static function resolveDiffuse() { + var rts = path.renderTargets; + var res = iron.RenderPath.getVoxelRes(); + var camera = iron.Scene.active.camera; + var clipmaps = iron.RenderPath.clipmaps; + var clipmap = clipmaps[iron.RenderPath.clipmapLevel]; + + kha.compute.Compute.setShader(voxel_sh3); + + kha.compute.Compute.setSampledTexture(voxel_ta3, rts.get("voxelsOut").image); + kha.compute.Compute.setSampledTexture(voxel_tb3, rts.get("half").image); + kha.compute.Compute.setSampledTexture(voxel_tc3, rts.get("gbuffer0").image); + kha.compute.Compute.setTexture(voxel_td3, rts.get("voxels_diffuse").image, kha.compute.Access.Write); + kha.compute.Compute.setSampledTexture(voxel_te3, rts.get("gbuffer1").image); + #if rp_gbuffer2 + kha.compute.Compute.setSampledTexture(voxel_tf3, rts.get("gbuffer2").image); + #end + #if lnx_brdf + kha.compute.Compute.setSampledTexture(voxel_tg3, iron.Scene.active.embedded.get("brdf.png")); + #end + #if lnx_radiance + kha.compute.Compute.setSampledTexture(voxel_th3, iron.Scene.active.world.probe.radiance); + #end + + var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); + for (i in 0...Main.voxelgiClipmapCount) { + fa[i * 10] = clipmaps[i].voxelSize; + fa[i * 10 + 1] = clipmaps[i].extents.x; + fa[i * 10 + 2] = clipmaps[i].extents.y; + fa[i * 10 + 3] = clipmaps[i].extents.z; + fa[i * 10 + 4] = clipmaps[i].center.x; + fa[i * 10 + 5] = clipmaps[i].center.y; + fa[i * 10 + 6] = clipmaps[i].center.z; + fa[i * 10 + 7] = clipmaps[i].offset_prev.x; + fa[i * 10 + 8] = clipmaps[i].offset_prev.y; + fa[i * 10 + 9] = clipmaps[i].offset_prev.z; + } + + kha.compute.Compute.setFloats(voxel_ca3, fa); + + #if lnx_centerworld + m.setFrom(vmat(camera.V)); + #else + m.setFrom(camera.V); + #end + m.multmat(camera.P); + m.getInverse(m); + + kha.compute.Compute.setMatrix(voxel_cb3, m.self); + + kha.compute.Compute.setFloat3(voxel_cc3, camera.transform.worldx(), camera.transform.worldy(), camera.transform.worldz()); + + var width = iron.App.w(); + var height = iron.App.h(); + var dp = getDisplayp(); + if (dp != null) { // 1080p/.. + if (width > height) { + width = Std.int(width * (dp / height) * Inc.getSuperSampling()); + height = Std.int(dp * Inc.getSuperSampling()); + } + else { + height = Std.int(height * (dp / width) * Inc.getSuperSampling()); + width = Std.int(dp * Inc.getSuperSampling()); + } + } + kha.compute.Compute.setFloat2(voxel_cd3, width, height); + + kha.compute.Compute.setFloat(voxel_ce3, iron.Scene.active.world == null ? 0.0 : iron.Scene.active.world.probe.raw.strength); + #if lnx_irradiance + var irradiance = iron.Scene.active.world == null ? + iron.data.WorldData.getEmptyIrradiance() : + iron.Scene.active.world.probe.irradiance; + kha.compute.Compute.setFloats(voxel_cf3, irradiance); + #end + #if lnx_radiance + kha.compute.Compute.setFloat(voxel_cg3, iron.Scene.active.world != null ? iron.Scene.active.world.probe.raw.radiance_mipmaps + 1 - 2 : 1); + #end + + #if lnx_envcol + var x: kha.FastFloat = 0.0; + var y: kha.FastFloat = 0.0; + var z: kha.FastFloat = 0.0; + + if (camera.data.raw.clear_color != null) { + x = camera.data.raw.clear_color[0]; + y = camera.data.raw.clear_color[1]; + z = camera.data.raw.clear_color[2]; + } + + kha.compute.Compute.setFloat3(voxel_ch3, x, y, z); + #end + + kha.compute.Compute.compute(Std.int((width + 7) / 8), Std.int((height + 7) / 8), 1); + } + + public static function resolveSpecular() { + var rts = path.renderTargets; + var res = iron.RenderPath.getVoxelRes(); + var camera = iron.Scene.active.camera; + var clipmaps = iron.RenderPath.clipmaps; + var clipmap = clipmaps[iron.RenderPath.clipmapLevel]; + + kha.compute.Compute.setShader(voxel_sh4); + + kha.compute.Compute.setSampledTexture(voxel_ta4, rts.get("voxelsOut").image); + kha.compute.Compute.setSampledTexture(voxel_tb4, rts.get("half").image); + kha.compute.Compute.setSampledTexture(voxel_tc4, rts.get("gbuffer0").image); + kha.compute.Compute.setSampledTexture(voxel_td4, rts.get("voxelsSDF").image); + kha.compute.Compute.setTexture(voxel_te4, rts.get("voxels_specular").image, kha.compute.Access.Write); + #if rp_gbuffer2 + kha.compute.Compute.setSampledTexture(voxel_tf4, rts.get("gbuffer2").image); + #end + + var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); + for (i in 0...Main.voxelgiClipmapCount) { + fa[i * 10] = clipmaps[i].voxelSize; + fa[i * 10 + 1] = clipmaps[i].extents.x; + fa[i * 10 + 2] = clipmaps[i].extents.y; + fa[i * 10 + 3] = clipmaps[i].extents.z; + fa[i * 10 + 4] = clipmaps[i].center.x; + fa[i * 10 + 5] = clipmaps[i].center.y; + fa[i * 10 + 6] = clipmaps[i].center.z; + fa[i * 10 + 7] = clipmaps[i].offset_prev.x; + fa[i * 10 + 8] = clipmaps[i].offset_prev.y; + fa[i * 10 + 9] = clipmaps[i].offset_prev.z; + } + + kha.compute.Compute.setFloats(voxel_ca4, fa); + + #if lnx_centerworld + m.setFrom(vmat(camera.V)); + #else + m.setFrom(camera.V); + #end + m.multmat(camera.P); + m.getInverse(m); + + kha.compute.Compute.setMatrix(voxel_cb4, m.self); + + kha.compute.Compute.setFloat3(voxel_cc4, camera.transform.worldx(), camera.transform.worldy(), camera.transform.worldz()); + + var width = iron.App.w(); + var height = iron.App.h(); + var dp = getDisplayp(); + if (dp != null) { // 1080p/.. + if (width > height) { + width = Std.int(width * (dp / height) * Inc.getSuperSampling()); + height = Std.int(dp * Inc.getSuperSampling()); + } + else { + height = Std.int(height * (dp / width) * Inc.getSuperSampling()); + width = Std.int(dp * Inc.getSuperSampling()); + } + } + kha.compute.Compute.setFloat2(voxel_cd4, width, height); + + kha.compute.Compute.compute(Std.int((width + 7) / 8), Std.int((height + 7) / 8), 1); + } + #end // GI + #end // Voxels } #if lnx_shadowmap_atlas class ShadowMapAtlas { - public var target: String; - public var baseTileSizeConst: Int; - public var maxAtlasSizeConst: Int; + public var target: String; + public var baseTileSizeConst: Int; + public var maxAtlasSizeConst: Int; - public var sizew: Int; - public var sizeh: Int; + public var sizew: Int; + public var sizeh: Int; - public var currTileOffset = 0; - public var tiles: Array = []; - public var activeTiles: Array = []; - public var depth = 1; - #if lnx_shadowmap_atlas_lod - var tileSizes: Array = []; - var tileSizeFactor: Array = []; - #end - public var updateRenderTarget = false; - public static var shadowMapAtlases:Map = new Map(); // map a shadowmap atlas to their light type - public static var shadowMapAtlasesTransparent:Map = new Map(); // map a shadowmap atlas to their light type + public var currTileOffset = 0; + public var tiles: Array = []; + public var activeTiles: Array = []; + public var depth = 1; + #if lnx_shadowmap_atlas_lod + var tileSizes: Array = []; + var tileSizeFactor: Array = []; + #end + public var updateRenderTarget = false; + public static var shadowMapAtlases:Map = new Map(); // map a shadowmap atlas to their light type + public static var shadowMapAtlasesTransparent:Map = new Map(); // map a shadowmap atlas to their light type - #if lnx_debug - public var lightType: String; - public var rejectedLights: Array = []; - #end + #if lnx_debug + public var lightType: String; + public var rejectedLights: Array = []; + #end - function new(light: LightObject, transparent: Bool) { + function new(light: LightObject, transparent: Bool) { - var maxTileSize = shadowMapAtlasSize(light); - this.target = shadowMapAtlasName(light.data.raw.type, transparent); - this.sizew = this.sizeh = this.baseTileSizeConst = maxTileSize; - this.depth = getSubdivisions(); - this.maxAtlasSizeConst = getMaxAtlasSize(light.data.raw.type); + var maxTileSize = shadowMapAtlasSize(light); + this.target = shadowMapAtlasName(light.data.raw.type, transparent); + this.sizew = this.sizeh = this.baseTileSizeConst = maxTileSize; + this.depth = getSubdivisions(); + this.maxAtlasSizeConst = getMaxAtlasSize(light.data.raw.type); - #if lnx_shadowmap_atlas_lod - computeTileSizes(maxTileSize, depth); - #end + #if lnx_shadowmap_atlas_lod + computeTileSizes(maxTileSize, depth); + #end - #if lnx_debug - #if lnx_shadowmap_atlas_single_map - this.lightType = "any"; - #else - this.lightType = light.data.raw.type; - #end - #end + #if lnx_debug + #if lnx_shadowmap_atlas_single_map + this.lightType = "any"; + #else + this.lightType = light.data.raw.type; + #end + #end - } + } - /** - * Adds a light to an atlas. The atlas is decided based on the type of the light - * @param light of type LightObject to be added to an yatlas - * @return if the light was added succesfully - */ - public static function addLight(light: LightObject, transparent: Bool) { - var atlasName = shadowMapAtlasName(light.data.raw.type, transparent); - var atlas = transparent ? shadowMapAtlasesTransparent.get(atlasName) : shadowMapAtlases.get(atlasName); - if (atlas == null) { - // create a new atlas - atlas = new ShadowMapAtlas(light, transparent); - if (transparent) - shadowMapAtlasesTransparent.set(atlasName, atlas); - else - shadowMapAtlases.set(atlasName, atlas); - } + /** + * Adds a light to an atlas. The atlas is decided based on the type of the light + * @param light of type LightObject to be added to an yatlas + * @return if the light was added succesfully + */ + public static function addLight(light: LightObject, transparent: Bool) { + var atlasName = shadowMapAtlasName(light.data.raw.type, transparent); + var atlas = transparent ? shadowMapAtlasesTransparent.get(atlasName) : shadowMapAtlases.get(atlasName); + if (atlas == null) { + // create a new atlas + atlas = new ShadowMapAtlas(light, transparent); + if (transparent) + shadowMapAtlasesTransparent.set(atlasName, atlas); + else + shadowMapAtlases.set(atlasName, atlas); + } - // find a free tile for this light - var mainTile = ShadowMapTile.assignTiles(light, atlas, null); - if (mainTile == null) { - #if lnx_debug - if (!atlas.rejectedLights.contains(light)) - atlas.rejectedLights.push(light); - #end - return; - } + // find a free tile for this light + var mainTile = ShadowMapTile.assignTiles(light, atlas, null); + if (mainTile == null) { + #if lnx_debug + if (!atlas.rejectedLights.contains(light)) + atlas.rejectedLights.push(light); + #end + return; + } - atlas.activeTiles.push(mainTile); - // notify the tile on light remove - light.tileNotifyOnRemove = mainTile.notifyOnLightRemove; - // notify atlas when this tile is freed - mainTile.notifyOnFree = atlas.freeActiveTile; - // "lock" light to make sure it's not eligible to be added again - if (transparent) - light.lightInAtlasTransparent = true; - else - light.lightInAtlas = true; - } + atlas.activeTiles.push(mainTile); + // notify the tile on light remove + light.tileNotifyOnRemove = mainTile.notifyOnLightRemove; + // notify atlas when this tile is freed + mainTile.notifyOnFree = atlas.freeActiveTile; + // "lock" light to make sure it's not eligible to be added again + if (transparent) + light.lightInAtlasTransparent = true; + else + light.lightInAtlas = true; + } - static inline function shadowMapAtlasSize(light:LightObject):Int { - // TODO: this can break because we are changing shadowmap_size elsewhere. - return light.data.raw.shadowmap_size; - } + static inline function shadowMapAtlasSize(light:LightObject):Int { + // TODO: this can break because we are changing shadowmap_size elsewhere. + return light.data.raw.shadowmap_size; + } - public function getTileSize(shadowMapScale: Float): Int { - #if lnx_shadowmap_atlas_lod - // find the first scale factor that is smaller to the shadowmap scale, and then return the previous one. - var i = 0; - for (sizeFactor in tileSizeFactor) { - if (sizeFactor < shadowMapScale) break; - i++; - } - return tileSizes[i - 1]; - #else - return this.baseTileSizeConst; - #end - } + public function getTileSize(shadowMapScale: Float): Int { + #if lnx_shadowmap_atlas_lod + // find the first scale factor that is smaller to the shadowmap scale, and then return the previous one. + var i = 0; + for (sizeFactor in tileSizeFactor) { + if (sizeFactor < shadowMapScale) break; + i++; + } + return tileSizes[i - 1]; + #else + return this.baseTileSizeConst; + #end + } - #if lnx_shadowmap_atlas_lod - function computeTileSizes(maxTileSize: Int, depth: Int): Void { - // find the highest value based on the calculation done in the cluster code - var base = LightObject.zToShadowMapScale(0, 16); - var subdiv = base / depth; - for(i in 0...depth){ - this.tileSizes.push(Std.int(maxTileSize / Math.pow(2, i))); - this.tileSizeFactor.push(base); - base -= subdiv; - } - this.tileSizes.push(0); - this.tileSizeFactor.push(0.0); - } - #end + #if lnx_shadowmap_atlas_lod + function computeTileSizes(maxTileSize: Int, depth: Int): Void { + // find the highest value based on the calculation done in the cluster code + var base = LightObject.zToShadowMapScale(0, 16); + var subdiv = base / depth; + for(i in 0...depth){ + this.tileSizes.push(Std.int(maxTileSize / Math.pow(2, i))); + this.tileSizeFactor.push(base); + base -= subdiv; + } + this.tileSizes.push(0); + this.tileSizeFactor.push(0.0); + } + #end - public inline function atlasLimitReached() { - // asume square atlas - return (currTileOffset + 1) * baseTileSizeConst > maxAtlasSizeConst; - } + public inline function atlasLimitReached() { + // asume square atlas + return (currTileOffset + 1) * baseTileSizeConst > maxAtlasSizeConst; + } - public static inline function shadowMapAtlasName(type: String, transparent: Bool): String { - #if lnx_shadowmap_atlas_single_map - return "shadowMapAtlas"; - #else - switch (type) { - case "point": - return transparent ? "shadowMapAtlasPointTransparent" : "shadowMapAtlasPoint"; - case "sun": - return transparent ? "shadowMapAtlasSunTransparent" : "shadowMapAtlasSun"; - default: - return transparent ? "shadowMapAtlasSpotTransparent" : "shadowMapAtlasSpot"; - } - #end - } + public static inline function shadowMapAtlasName(type: String, transparent: Bool): String { + #if lnx_shadowmap_atlas_single_map + return "shadowMapAtlas"; + #else + switch (type) { + case "point": + return transparent ? "shadowMapAtlasPointTransparent" : "shadowMapAtlasPoint"; + case "sun": + return transparent ? "shadowMapAtlasSunTransparent" : "shadowMapAtlasSun"; + default: + return transparent ? "shadowMapAtlasSpotTransparent" : "shadowMapAtlasSpot"; + } + #end + } - public static inline function getSubdivisions(): Int { - #if (rp_shadowmap_atlas_lod_subdivisions == 2) - return 2; - #elseif (rp_shadowmap_atlas_lod_subdivisions == 3) - return 3; - #elseif (rp_shadowmap_atlas_lod_subdivisions == 4) - return 4; - #elseif (rp_shadowmap_atlas_lod_subdivisions == 5) - return 5; - #elseif (rp_shadowmap_atlas_lod_subdivisions == 6) - return 6; - #elseif (rp_shadowmap_atlas_lod_subdivisions == 7) - return 7; - #elseif (rp_shadowmap_atlas_lod_subdivisions == 8) - return 8; - #elseif (!lnx_shadowmap_atlas_lod) - return 1; - #end - } + public static inline function getSubdivisions(): Int { + #if (rp_shadowmap_atlas_lod_subdivisions == 2) + return 2; + #elseif (rp_shadowmap_atlas_lod_subdivisions == 3) + return 3; + #elseif (rp_shadowmap_atlas_lod_subdivisions == 4) + return 4; + #elseif (rp_shadowmap_atlas_lod_subdivisions == 5) + return 5; + #elseif (rp_shadowmap_atlas_lod_subdivisions == 6) + return 6; + #elseif (rp_shadowmap_atlas_lod_subdivisions == 7) + return 7; + #elseif (rp_shadowmap_atlas_lod_subdivisions == 8) + return 8; + #elseif (!lnx_shadowmap_atlas_lod) + return 1; + #end + } - public static inline function getMaxAtlasSize(type: String): Int { - #if lnx_shadowmap_atlas_single_map - #if (rp_shadowmap_atlas_max_size == 512) - return 512; - #elseif (rp_shadowmap_atlas_max_size == 1024) - return 1024; - #elseif (rp_shadowmap_atlas_max_size == 2048) - return 2048; - #elseif (rp_shadowmap_atlas_max_size == 4096) - return 4096; - #elseif (rp_shadowmap_atlas_max_size == 8192) - return 8192; - #elseif (rp_shadowmap_atlas_max_size == 16384) - return 16384; - #elseif (rp_shadowmap_atlas_max_size == 32768) - return 32768; - #end - #else - switch (type) { - case "point": { - #if (rp_shadowmap_atlas_max_size_point == 1024) - return 1024; - #elseif (rp_shadowmap_atlas_max_size_point == 2048) - return 2048; - #elseif (rp_shadowmap_atlas_max_size_point == 4096) - return 4096; - #elseif (rp_shadowmap_atlas_max_size_point == 8192) - return 8192; - #elseif (rp_shadowmap_atlas_max_size_point == 16384) - return 16384; - #elseif (rp_shadowmap_atlas_max_size_point == 32768) - return 32768; - #end - } - case "spot": { - #if (rp_shadowmap_atlas_max_size_spot == 512) - return 512; - #elseif (rp_shadowmap_atlas_max_size_spot == 1024) - return 1024; - #elseif (rp_shadowmap_atlas_max_size_spot == 2048) - return 2048; - #elseif (rp_shadowmap_atlas_max_size_spot == 4096) - return 4096; - #elseif (rp_shadowmap_atlas_max_size_spot == 8192) - return 8192; - #elseif (rp_shadowmap_atlas_max_size_spot == 16384) - return 16384; - #elseif (rp_shadowmap_atlas_max_size_spot == 32768) - return 32768; - #end - } - case "sun": { - #if (rp_shadowmap_atlas_max_size_sun == 512) - return 512; - #elseif (rp_shadowmap_atlas_max_size_sun == 1024) - return 1024; - #elseif (rp_shadowmap_atlas_max_size_sun == 2048) - return 2048; - #elseif (rp_shadowmap_atlas_max_size_sun == 4096) - return 4096; - #elseif (rp_shadowmap_atlas_max_size_sun == 8192) - return 8192; - #elseif (rp_shadowmap_atlas_max_size_sun == 16384) - return 16384; - #elseif (rp_shadowmap_atlas_max_size_sun == 32768) - return 32768; - #end - } - default: { - #if (rp_shadowmap_atlas_max_size == 512) - return 512; - #elseif (rp_shadowmap_atlas_max_size == 1024) - return 1024; - #elseif (rp_shadowmap_atlas_max_size == 2048) - return 2048; - #elseif (rp_shadowmap_atlas_max_size == 4096) - return 4096; - #elseif (rp_shadowmap_atlas_max_size == 8192) - return 8192; - #elseif (rp_shadowmap_atlas_max_size == 16384) - return 16384; - #elseif (rp_shadowmap_atlas_max_size == 32768) - return 32768; - #end - } - } - #end - } + public static inline function getMaxAtlasSize(type: String): Int { + #if lnx_shadowmap_atlas_single_map + #if (rp_shadowmap_atlas_max_size == 512) + return 512; + #elseif (rp_shadowmap_atlas_max_size == 1024) + return 1024; + #elseif (rp_shadowmap_atlas_max_size == 2048) + return 2048; + #elseif (rp_shadowmap_atlas_max_size == 4096) + return 4096; + #elseif (rp_shadowmap_atlas_max_size == 8192) + return 8192; + #elseif (rp_shadowmap_atlas_max_size == 16384) + return 16384; + #elseif (rp_shadowmap_atlas_max_size == 32768) + return 32768; + #end + #else + switch (type) { + case "point": { + #if (rp_shadowmap_atlas_max_size_point == 1024) + return 1024; + #elseif (rp_shadowmap_atlas_max_size_point == 2048) + return 2048; + #elseif (rp_shadowmap_atlas_max_size_point == 4096) + return 4096; + #elseif (rp_shadowmap_atlas_max_size_point == 8192) + return 8192; + #elseif (rp_shadowmap_atlas_max_size_point == 16384) + return 16384; + #elseif (rp_shadowmap_atlas_max_size_point == 32768) + return 32768; + #end + } + case "spot": { + #if (rp_shadowmap_atlas_max_size_spot == 512) + return 512; + #elseif (rp_shadowmap_atlas_max_size_spot == 1024) + return 1024; + #elseif (rp_shadowmap_atlas_max_size_spot == 2048) + return 2048; + #elseif (rp_shadowmap_atlas_max_size_spot == 4096) + return 4096; + #elseif (rp_shadowmap_atlas_max_size_spot == 8192) + return 8192; + #elseif (rp_shadowmap_atlas_max_size_spot == 16384) + return 16384; + #elseif (rp_shadowmap_atlas_max_size_spot == 32768) + return 32768; + #end + } + case "sun": { + #if (rp_shadowmap_atlas_max_size_sun == 512) + return 512; + #elseif (rp_shadowmap_atlas_max_size_sun == 1024) + return 1024; + #elseif (rp_shadowmap_atlas_max_size_sun == 2048) + return 2048; + #elseif (rp_shadowmap_atlas_max_size_sun == 4096) + return 4096; + #elseif (rp_shadowmap_atlas_max_size_sun == 8192) + return 8192; + #elseif (rp_shadowmap_atlas_max_size_sun == 16384) + return 16384; + #elseif (rp_shadowmap_atlas_max_size_sun == 32768) + return 32768; + #end + } + default: { + #if (rp_shadowmap_atlas_max_size == 512) + return 512; + #elseif (rp_shadowmap_atlas_max_size == 1024) + return 1024; + #elseif (rp_shadowmap_atlas_max_size == 2048) + return 2048; + #elseif (rp_shadowmap_atlas_max_size == 4096) + return 4096; + #elseif (rp_shadowmap_atlas_max_size == 8192) + return 8192; + #elseif (rp_shadowmap_atlas_max_size == 16384) + return 16384; + #elseif (rp_shadowmap_atlas_max_size == 32768) + return 32768; + #end + } + } + #end + } - function freeActiveTile(tile: ShadowMapTile) { - activeTiles.remove(tile); - } + function freeActiveTile(tile: ShadowMapTile) { + activeTiles.remove(tile); + } } class ShadowMapTile { - public var light:Null = null; - public var coordsX:Int; - public var coordsY:Int; - public var size:Int; - public var tiles:Array = []; - public var linkedTile:ShadowMapTile = null; + public var light:Null = null; + public var coordsX:Int; + public var coordsY:Int; + public var size:Int; + public var tiles:Array = []; + public var linkedTile:ShadowMapTile = null; - #if lnx_shadowmap_atlas_lod - public var parentTile: ShadowMapTile = null; - public var activeSubTiles: Int = 0; - public var newTileSize: Int = -1; + #if lnx_shadowmap_atlas_lod + public var parentTile: ShadowMapTile = null; + public var activeSubTiles: Int = 0; + public var newTileSize: Int = -1; - static var tilePattern = [[0, 0], [1, 0], [0, 1], [1, 1]]; - #end + static var tilePattern = [[0, 0], [1, 0], [0, 1], [1, 1]]; + #end - function new(coordsX: Int, coordsY: Int, size: Int) { - this.coordsX = coordsX; - this.coordsY = coordsY; - this.size = size; - } + function new(coordsX: Int, coordsY: Int, size: Int) { + this.coordsX = coordsX; + this.coordsY = coordsY; + this.size = size; + } - public static function assignTiles(light: LightObject, atlas: ShadowMapAtlas, oldTile: ShadowMapTile): ShadowMapTile { - var tileSize = 0; + public static function assignTiles(light: LightObject, atlas: ShadowMapAtlas, oldTile: ShadowMapTile): ShadowMapTile { + var tileSize = 0; - #if lnx_shadowmap_atlas_lod - if (oldTile != null && oldTile.newTileSize != -1) { - // reuse tilesize instead of computing it again - tileSize = oldTile.newTileSize; - oldTile.newTileSize = -1; - } - else - #end - tileSize = atlas.getTileSize(light.shadowMapScale); + #if lnx_shadowmap_atlas_lod + if (oldTile != null && oldTile.newTileSize != -1) { + // reuse tilesize instead of computing it again + tileSize = oldTile.newTileSize; + oldTile.newTileSize = -1; + } + else + #end + tileSize = atlas.getTileSize(light.shadowMapScale); - if (tileSize == 0) - return null; + if (tileSize == 0) + return null; - var tiles = []; - tiles = findCreateTiles(light, oldTile, atlas, tilesLightType(light.data.raw.type), tileSize); + var tiles = []; + tiles = findCreateTiles(light, oldTile, atlas, tilesLightType(light.data.raw.type), tileSize); - // lock new tiles with light - for (tile in tiles) - tile.lockTile(light); + // lock new tiles with light + for (tile in tiles) + tile.lockTile(light); - return linkTiles(tiles); - } + return linkTiles(tiles); + } - static inline function linkTiles(tiles: Array): ShadowMapTile { - if (tiles.length > 1) { - var linkedTile = tiles[0]; - for (i in 1...tiles.length) { - linkedTile.linkedTile = tiles[i]; - linkedTile = tiles[i]; - } - } - return tiles[0]; - } + static inline function linkTiles(tiles: Array): ShadowMapTile { + if (tiles.length > 1) { + var linkedTile = tiles[0]; + for (i in 1...tiles.length) { + linkedTile.linkedTile = tiles[i]; + linkedTile = tiles[i]; + } + } + return tiles[0]; + } - static inline function findCreateTiles(light: LightObject, oldTile: ShadowMapTile, atlas: ShadowMapAtlas, tilesPerLightType: Int, tileSize: Int): Array { - var tilesFound: Array = []; + static inline function findCreateTiles(light: LightObject, oldTile: ShadowMapTile, atlas: ShadowMapAtlas, tilesPerLightType: Int, tileSize: Int): Array { + var tilesFound: Array = []; - while (tilesFound.length < tilesPerLightType) { - findTiles(light, oldTile, atlas.tiles, tileSize, tilesPerLightType, tilesFound); + while (tilesFound.length < tilesPerLightType) { + findTiles(light, oldTile, atlas.tiles, tileSize, tilesPerLightType, tilesFound); - if (tilesFound.length < tilesPerLightType) { - tilesFound = []; // empty tilesFound - // skip creating more tiles if limit has been reached - if (atlas.atlasLimitReached()) - break; + if (tilesFound.length < tilesPerLightType) { + tilesFound = []; // empty tilesFound + // skip creating more tiles if limit has been reached + if (atlas.atlasLimitReached()) + break; - createTiles(atlas.tiles, atlas.baseTileSizeConst, atlas.depth, atlas.currTileOffset, atlas.currTileOffset); - atlas.currTileOffset++; - // update texture to accomodate new size - atlas.updateRenderTarget = true; - atlas.sizew = atlas.sizeh = atlas.currTileOffset * atlas.baseTileSizeConst; - } - } - return tilesFound; - } + createTiles(atlas.tiles, atlas.baseTileSizeConst, atlas.depth, atlas.currTileOffset, atlas.currTileOffset); + atlas.currTileOffset++; + // update texture to accomodate new size + atlas.updateRenderTarget = true; + atlas.sizew = atlas.sizeh = atlas.currTileOffset * atlas.baseTileSizeConst; + } + } + return tilesFound; + } - inline static function findTiles(light:LightObject, oldTile: ShadowMapTile, - tiles: Array, size: Int, tilesCount: Int, tilesFound: Array): Void { - #if lnx_shadowmap_atlas_lod - if (oldTile != null) { - // reuse children tiles - if (size < oldTile.size) { - oldTile.forEachTileLinked(function(lTile) { - var childTile = findFreeChildTile(lTile, size); - tilesFound.push(childTile); - }); - } - // reuse parent tiles - else { - oldTile.forEachTileLinked(function(lTile) { - // find out if parents tiles are not occupied - var parentTile = findFreeParentTile(lTile, size); - // if parent is free, add it to found tiles - if (parentTile != null) - tilesFound.push(parentTile); - }); - if (tilesFound.length < tilesCount) { - // find naively the rest of the tiles that couldn't be reused - findTilesNaive(light, tiles, size, tilesCount, tilesFound); - } - } - } - else - #end - findTilesNaive(light, tiles, size, tilesCount, tilesFound); - } + inline static function findTiles(light:LightObject, oldTile: ShadowMapTile, + tiles: Array, size: Int, tilesCount: Int, tilesFound: Array): Void { + #if lnx_shadowmap_atlas_lod + if (oldTile != null) { + // reuse children tiles + if (size < oldTile.size) { + oldTile.forEachTileLinked(function(lTile) { + var childTile = findFreeChildTile(lTile, size); + tilesFound.push(childTile); + }); + } + // reuse parent tiles + else { + oldTile.forEachTileLinked(function(lTile) { + // find out if parents tiles are not occupied + var parentTile = findFreeParentTile(lTile, size); + // if parent is free, add it to found tiles + if (parentTile != null) + tilesFound.push(parentTile); + }); + if (tilesFound.length < tilesCount) { + // find naively the rest of the tiles that couldn't be reused + findTilesNaive(light, tiles, size, tilesCount, tilesFound); + } + } + } + else + #end + findTilesNaive(light, tiles, size, tilesCount, tilesFound); + } - #if lnx_shadowmap_atlas_lod - static inline function findFreeChildTile(tile: ShadowMapTile, size: Int): ShadowMapTile { - var childrenTile = tile; - while (size < childrenTile.size) { - childrenTile = childrenTile.tiles[0]; - } - return childrenTile; - } + #if lnx_shadowmap_atlas_lod + static inline function findFreeChildTile(tile: ShadowMapTile, size: Int): ShadowMapTile { + var childrenTile = tile; + while (size < childrenTile.size) { + childrenTile = childrenTile.tiles[0]; + } + return childrenTile; + } - static inline function findFreeParentTile(tile: ShadowMapTile, size: Int): ShadowMapTile { - var parentTile = tile; - while (size > parentTile.size) { - parentTile = parentTile.parentTile; - // stop if parent tile is occupied - if (parentTile.activeSubTiles > 1) { - parentTile = null; - break; - } - } - return parentTile; - } - #end + static inline function findFreeParentTile(tile: ShadowMapTile, size: Int): ShadowMapTile { + var parentTile = tile; + while (size > parentTile.size) { + parentTile = parentTile.parentTile; + // stop if parent tile is occupied + if (parentTile.activeSubTiles > 1) { + parentTile = null; + break; + } + } + return parentTile; + } + #end - static function findTilesNaive(light:LightObject, tiles: Array, size: Int, tilesCount: Int, tilesFound: Array): Void { - for (tile in tiles) { - if (tile.size == size) { - if (tile.light == null #if lnx_shadowmap_atlas_lod && tile.activeSubTiles == 0 #end) { - tilesFound.push(tile); - // stop after finding enough tiles - if (tilesFound.length == tilesCount) - return; - } - } - else { - // skip over if end of the tree or tile is occupied - if (tile.tiles.length == 0 || tile.light != null) - continue; - findTilesNaive(light, tile.tiles, size, tilesCount, tilesFound); - // skip iterating over the rest of the tiles if found enough - if (tilesFound.length == tilesCount) - return; - } - } - } + static function findTilesNaive(light:LightObject, tiles: Array, size: Int, tilesCount: Int, tilesFound: Array): Void { + for (tile in tiles) { + if (tile.size == size) { + if (tile.light == null #if lnx_shadowmap_atlas_lod && tile.activeSubTiles == 0 #end) { + tilesFound.push(tile); + // stop after finding enough tiles + if (tilesFound.length == tilesCount) + return; + } + } + else { + // skip over if end of the tree or tile is occupied + if (tile.tiles.length == 0 || tile.light != null) + continue; + findTilesNaive(light, tile.tiles, size, tilesCount, tilesFound); + // skip iterating over the rest of the tiles if found enough + if (tilesFound.length == tilesCount) + return; + } + } + } - // create a basic tile and subdivide it if needed - public static function createTiles(tiles:Array, size:Int, depth: Int, baseX:Int, baseY:Int) { - var i = baseX; - var j = 0; - var lastTile = tiles.length; - // assume occupied tiles start from 1 line before the base x - var occupiedTiles = baseX - 1; + // create a basic tile and subdivide it if needed + public static function createTiles(tiles:Array, size:Int, depth: Int, baseX:Int, baseY:Int) { + var i = baseX; + var j = 0; + var lastTile = tiles.length; + // assume occupied tiles start from 1 line before the base x + var occupiedTiles = baseX - 1; - while (i >= 0) { - if (i <= occupiedTiles) { // avoid overriding tiles - j = baseY; - } - while (j <= baseY) { - // create base tile of max-size - tiles.push(new ShadowMapTile(size * i, size * j, size)); - #if lnx_shadowmap_atlas_lod - tiles[lastTile].tiles = subDivTile(tiles[lastTile], size, size * i, size * j, depth - 1); - #end - lastTile++; - j++; - } - i--; - } - } + while (i >= 0) { + if (i <= occupiedTiles) { // avoid overriding tiles + j = baseY; + } + while (j <= baseY) { + // create base tile of max-size + tiles.push(new ShadowMapTile(size * i, size * j, size)); + #if lnx_shadowmap_atlas_lod + tiles[lastTile].tiles = subDivTile(tiles[lastTile], size, size * i, size * j, depth - 1); + #end + lastTile++; + j++; + } + i--; + } + } - #if lnx_shadowmap_atlas_lod - static function subDivTile(parent: ShadowMapTile, size: Int, baseCoordsX: Int, baseCoordsY: Int, depth: Int): Array { - var tileSize = Std.int(size / 2); + #if lnx_shadowmap_atlas_lod + static function subDivTile(parent: ShadowMapTile, size: Int, baseCoordsX: Int, baseCoordsY: Int, depth: Int): Array { + var tileSize = Std.int(size / 2); - var tiles = []; + var tiles = []; - for (i in 0...4) { - var coordsX = baseCoordsX + tilePattern[i][0] * tileSize; - var coordsY = baseCoordsY + tilePattern[i][1] * tileSize; + for (i in 0...4) { + var coordsX = baseCoordsX + tilePattern[i][0] * tileSize; + var coordsY = baseCoordsY + tilePattern[i][1] * tileSize; - var tile = new ShadowMapTile(coordsX, coordsY, tileSize); - tile.parentTile = parent; + var tile = new ShadowMapTile(coordsX, coordsY, tileSize); + tile.parentTile = parent; - if (depth > 1) - tile.tiles = subDivTile(tile, tileSize, coordsX, coordsY, depth - 1); - tiles.push(tile); - } + if (depth > 1) + tile.tiles = subDivTile(tile, tileSize, coordsX, coordsY, depth - 1); + tiles.push(tile); + } - return tiles; - } - #end + return tiles; + } + #end - public static inline function tilesLightType(type: String): Int { - switch (type) { - case "sun": - return LightObject.cascadeCount; - case "point": - return 6; - default: - return 1; - } - } + public static inline function tilesLightType(type: String): Int { + switch (type) { + case "sun": + return LightObject.cascadeCount; + case "point": + return 6; + default: + return 1; + } + } - public function notifyOnLightRemove() { - unlockLight = true; - freeTile(); - } + public function notifyOnLightRemove() { + unlockLight = true; + freeTile(); + } - inline function lockTile(light: LightObject): Void { - if (this.light != null) - return; - this.light = light; - #if lnx_shadowmap_atlas_lod - // update the count of used tiles for parents - this.forEachParentTile(function (pTile) { - pTile.activeSubTiles++; - }); - #end - } + inline function lockTile(light: LightObject): Void { + if (this.light != null) + return; + this.light = light; + #if lnx_shadowmap_atlas_lod + // update the count of used tiles for parents + this.forEachParentTile(function (pTile) { + pTile.activeSubTiles++; + }); + #end + } - public var unlockLight: Bool = false; - public var notifyOnFree: ShadowMapTile -> Void; + public var unlockLight: Bool = false; + public var notifyOnFree: ShadowMapTile -> Void; - public function freeTile(): Void { - // prevent duplicates - if (light != null && unlockLight) { - light.lightInAtlas = false; - unlockLight = false; - } + public function freeTile(): Void { + // prevent duplicates + if (light != null && unlockLight) { + light.lightInAtlas = false; + unlockLight = false; + } - var linkedTile = this; - var tempTile = this; - while (linkedTile != null) { - linkedTile.light = null; - #if lnx_shadowmap_atlas_lod - // update the count of used tiles for parents - linkedTile.forEachParentTile(function (pTile) { - if (pTile.activeSubTiles > 0) - pTile.activeSubTiles--; - }); - #end + var linkedTile = this; + var tempTile = this; + while (linkedTile != null) { + linkedTile.light = null; + #if lnx_shadowmap_atlas_lod + // update the count of used tiles for parents + linkedTile.forEachParentTile(function (pTile) { + if (pTile.activeSubTiles > 0) + pTile.activeSubTiles--; + }); + #end - linkedTile = linkedTile.linkedTile; - // unlink linked tiles - tempTile.linkedTile = null; - tempTile = linkedTile; - } - // notify atlas that this tile has been freed - if (notifyOnFree != null) { - notifyOnFree(this); - notifyOnFree = null; - } - } + linkedTile = linkedTile.linkedTile; + // unlink linked tiles + tempTile.linkedTile = null; + tempTile = linkedTile; + } + // notify atlas that this tile has been freed + if (notifyOnFree != null) { + notifyOnFree(this); + notifyOnFree = null; + } + } - public inline function forEachTileLinked(action: ShadowMapTile->Void): Void { - var linkedTile = this; - while (linkedTile != null) { - action(linkedTile); - linkedTile = linkedTile.linkedTile; - } - } + public inline function forEachTileLinked(action: ShadowMapTile->Void): Void { + var linkedTile = this; + while (linkedTile != null) { + action(linkedTile); + linkedTile = linkedTile.linkedTile; + } + } - #if lnx_shadowmap_atlas_lod - public inline function forEachParentTile(action: ShadowMapTile->Void): Void { - var parentTile = this.parentTile; - while (parentTile != null) { - action(parentTile); - parentTile = parentTile.parentTile; - } - } - #end + #if lnx_shadowmap_atlas_lod + public inline function forEachParentTile(action: ShadowMapTile->Void): Void { + var parentTile = this.parentTile; + while (parentTile != null) { + action(parentTile); + parentTile = parentTile.parentTile; + } + } + #end } #end From 9cb523218717076c7bfc9d8dc1c293d80d03d6a9 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Thu, 29 May 2025 16:53:10 +0000 Subject: [PATCH 099/136] Update leenkx/Shaders/deferred_light/deferred_light.frag.glsl --- .../deferred_light/deferred_light.frag.glsl | 132 ++++++++++++------ 1 file changed, 93 insertions(+), 39 deletions(-) diff --git a/leenkx/Shaders/deferred_light/deferred_light.frag.glsl b/leenkx/Shaders/deferred_light/deferred_light.frag.glsl index a722c85..73788ff 100644 --- a/leenkx/Shaders/deferred_light/deferred_light.frag.glsl +++ b/leenkx/Shaders/deferred_light/deferred_light.frag.glsl @@ -20,7 +20,7 @@ uniform sampler2D gbuffer0; uniform sampler2D gbuffer1; #ifdef _gbuffer2 - //!uniform sampler2D gbuffer2; + uniform sampler2D gbuffer2; #endif #ifdef _EmissionShaded uniform sampler2D gbufferEmission; @@ -29,10 +29,11 @@ uniform sampler2D gbuffer1; #ifdef _VoxelGI uniform sampler2D voxels_diffuse; uniform sampler2D voxels_specular; -#endif +#else #ifdef _VoxelAOvar uniform sampler2D voxels_ao; #endif +#endif #ifdef _VoxelShadow uniform sampler3D voxels; uniform sampler3D voxelsSDF; @@ -117,11 +118,15 @@ uniform vec2 cameraPlane; #ifdef _SinglePoint #ifdef _Spot //!uniform sampler2DShadow shadowMapSpot[1]; + #ifdef _ShadowMapTransparent //!uniform sampler2D shadowMapSpotTransparent[1]; + #endif //!uniform mat4 LWVPSpot[1]; #else //!uniform samplerCubeShadow shadowMapPoint[1]; + #ifdef _ShadowMapTransparent //!uniform samplerCube shadowMapPointTransparent[1]; + #endif //!uniform vec2 lightProj; #endif #endif @@ -129,30 +134,40 @@ 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]; + #ifdef _ShadowMapTransparent //!uniform sampler2D shadowMapSpotTransparent[4]; #endif + #endif //!uniform mat4 LWVPSpotArray[maxLightsCluster]; #endif #endif @@ -165,12 +180,16 @@ uniform vec3 sunCol; #ifdef _ShadowMapAtlas #ifndef _SingleAtlas uniform sampler2DShadow shadowMapAtlasSun; + #ifdef _ShadowMapTransparent uniform sampler2D shadowMapAtlasSunTransparent; #endif + #endif #else uniform sampler2DShadow shadowMap; + #ifdef _ShadowMapTransparent uniform sampler2D shadowMapTransparent; #endif + #endif uniform float shadowsBias; #ifdef _CSM //!uniform vec4 casData[shadowmapCascades * 4 + 4]; @@ -231,21 +250,22 @@ void main() { vec4 g2 = textureLod(gbuffer2, texCoord, 0.0); #endif + #ifdef _MicroShadowing occspec.x = mix(1.0, occspec.x, dotNV); // AO Fresnel #endif #ifdef _Brdf vec2 envBRDF = texelFetch(senvmapBrdf, ivec2(vec2(dotNV, 1.0 - roughness) * 256.0), 0).xy; - vec3 F = f0 * envBRDF.x + envBRDF.y; + vec3 F = f0 * envBRDF.x + envBRDF.y; +#else + vec3 F = f0; #endif - #ifndef _VoxelAOvar #ifndef _VoxelGI -// Envmap + // Envmap #ifdef _Irr - vec3 envl = shIrradiance(n, shirr); #ifdef _gbuffer2 @@ -279,14 +299,14 @@ void main() { envl.rgb *= albedo; #ifdef _Brdf - envl.rgb *= 1.0 - F; + envl.rgb *= 1.0 - F; //LV: We should take refracted light into account #endif #ifdef _Rad // Indirect specular - envl.rgb += prefilteredColor * F; + envl.rgb += prefilteredColor * F; //LV: Removed "1.5 * occspec.y". Specular should be weighted only by FV LUT #else #ifdef _EnvCol - envl.rgb += backgroundCol * F; + envl.rgb += backgroundCol * F; //LV: Eh, what's the point of weighting it only by F0? #endif #endif @@ -301,7 +321,6 @@ void main() { if(roughness < 1.0 && occspec.y > 0.0) fragColor.rgb += textureLod(voxels_specular, texCoord, 0.0).rgb * F * voxelgiRefl; #else - #ifdef _VoxelAOvar fragColor.rgb = textureLod(voxels_ao, texCoord, 0.0).rgb * voxelgiOcc; #endif @@ -356,46 +375,76 @@ void main() { float sdotVH = max(0.0, dot(v, sh)); float sdotNL = max(0.0, dot(n, sunDir)); vec3 svisibility = vec3(1.0); - vec3 sdirect = lambertDiffuseBRDF(albedo, sdotNL) + + vec3 sdirect = lambertDiffuseBRDF(albedo, sdotNL) + specularBRDF(f0, roughness, sdotNL, sdotNH, dotNV, sdotVH) * occspec.y; #ifdef _ShadowMap #ifdef _CSM svisibility = shadowTestCascade( - #ifdef _ShadowMapAtlas - #ifndef _SingleAtlas - shadowMapAtlasSun, shadowMapAtlasSunTransparent - #else - shadowMapAtlas, shadowMapAtlasTransparent - #endif - #else - shadowMap, shadowMapTransparent - #endif - , eye, p + n * shadowsBias * 10, shadowsBias, false - ); + #ifdef _ShadowMapAtlas + #ifdef _ShadowMapTransparent + #ifndef _SingleAtlas + shadowMapAtlasSun, shadowMapAtlasSunTransparent + #else + shadowMapAtlas, shadowMapAtlasTransparent + #endif + #else + #ifndef _SingleAtlas + shadowMapAtlasSun + #else + shadowMapAtlas + #endif + #endif + #else + #ifdef _ShadowMapTransparent + shadowMap, shadowMapTransparent + #else + shadowMap + #endif + #endif + , eye, p + n * shadowsBias * 10, shadowsBias + #ifdef _ShadowMapTransparent + , false + #endif + ); #else vec4 lPos = LWVP * vec4(p + n * shadowsBias * 100, 1.0); if (lPos.w > 0.0) { svisibility = shadowTest( - #ifdef _ShadowMapAtlas - #ifndef _SingleAtlas - shadowMapAtlasSun, shadowMapAtlasSunTransparent - #else - shadowMapAtlas, shadowMapAtlasTransparent - #endif - #else - shadowMap, shadowMapTransparent - #endif - , lPos.xyz / lPos.w, shadowsBias, false - ); + #ifdef _ShadowMapAtlas + #ifdef _ShadowMapTransparent + #ifndef _SingleAtlas + shadowMapAtlasSun, shadowMapAtlasSunTransparent + #else + shadowMapAtlas, shadowMapAtlasTransparent + #endif + #else + #ifndef _SingleAtlas + shadowMapAtlasSun + #else + shadowMapAtlas + #endif + #endif + #else + #ifdef _ShadowMapTransparent + shadowMap, shadowMapTransparent + #else + shadowMap + #endif + #endif + , lPos.xyz / lPos.w, shadowsBias + #ifdef _ShadowMapTransparent + , false + #endif + ); } #endif #endif #ifdef _VoxelShadow - svisibility *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, sunDir, clipmaps, gl_FragCoord.xy, g2.rg).r) * voxelgiShad; + svisibility *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, sunDir, clipmaps, gl_FragCoord.xy, -g2.rg).r) * voxelgiShad; #endif - + #ifdef _SSRS // vec2 coords = getProjectedCoord(hitCoord); // vec2 deltaCoords = abs(vec2(0.5, 0.5) - coords.xy); @@ -452,7 +501,10 @@ void main() { fragColor.rgb += sampleLight( p, n, v, dotNV, pointPos, pointCol, albedo, roughness, occspec.y, f0 #ifdef _ShadowMap - , 0, pointBias, true, false + , 0, pointBias, true + #ifdef _ShadowMapTransparent + , false + #endif #endif #ifdef _Spot , true, spotData.x, spotData.y, spotDir, spotData.zw, spotRight @@ -505,7 +557,10 @@ void main() { f0 #ifdef _ShadowMap // light index, shadow bias, cast_shadows - , li, lightsArray[li * 3 + 2].x, lightsArray[li * 3 + 2].z != 0.0, false + , 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 @@ -527,6 +582,5 @@ void main() { ); } #endif // _Clusters - fragColor.a = 1.0; // Mark as opaque } From 1591ccdae5e46289ba865d8d053366685754a551 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Thu, 29 May 2025 16:56:38 +0000 Subject: [PATCH 100/136] Update leenkx/Shaders/deferred_light/deferred_light.json --- leenkx/Shaders/deferred_light/deferred_light.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/leenkx/Shaders/deferred_light/deferred_light.json b/leenkx/Shaders/deferred_light/deferred_light.json index 7018e73..bcbdf1d 100644 --- a/leenkx/Shaders/deferred_light/deferred_light.json +++ b/leenkx/Shaders/deferred_light/deferred_light.json @@ -11,6 +11,11 @@ "name": "eye", "link": "_cameraPosition" }, + { + "name": "voxelBlend", + "link": "_voxelBlend", + "ifdef": ["_VoxelTemporal"] + }, { "name": "eyeLook", "link": "_cameraLook" From 5639234eb99b7c8fb169c8624572ff0b1c2e540f Mon Sep 17 00:00:00 2001 From: Onek8 Date: Thu, 29 May 2025 21:22:25 +0000 Subject: [PATCH 101/136] Update leenkx/Shaders/std/light.glsl --- leenkx/Shaders/std/light.glsl | 448 ++++++++++++++++++++++++++++------ 1 file changed, 378 insertions(+), 70 deletions(-) diff --git a/leenkx/Shaders/std/light.glsl b/leenkx/Shaders/std/light.glsl index 6b5e91f..b3267fe 100644 --- a/leenkx/Shaders/std/light.glsl +++ b/leenkx/Shaders/std/light.glsl @@ -31,40 +31,54 @@ #ifdef _Spot #ifndef _LTC uniform sampler2DShadow shadowMapSpot[1]; + #ifdef _ShadowMapTransparent uniform sampler2D shadowMapSpotTransparent[1]; - uniform mat4 LWVPSpot[1]; + #endif + uniform mat4 LWVPSpotArray[1]; #endif #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 uniform vec2 lightProj; #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[4]; + #ifdef _ShadowMapTransparent uniform sampler2D shadowMapSpotTransparent[4]; #endif + #endif uniform mat4 LWVPSpotArray[maxLightsCluster]; #endif #endif @@ -81,12 +95,16 @@ uniform sampler2D sltcMag; #ifndef _Spot #ifdef _SinglePoint uniform sampler2DShadow shadowMapSpot[1]; + #ifdef _ShadowMapTransparent uniform sampler2D shadowMapSpotTransparent[1]; - uniform mat4 LWVPSpot[1]; + #endif + uniform mat4 LWVPSpotArray[1]; #endif #ifdef _Clusters uniform sampler2DShadow shadowMapSpot[maxLightsCluster]; + #ifdef _ShadowMapTransparent uniform sampler2D shadowMapSpotTransparent[maxLightsCluster]; + #endif uniform mat4 LWVPSpotArray[maxLightsCluster]; #endif #endif @@ -96,7 +114,10 @@ uniform sampler2D sltcMag; vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, const vec3 lp, const vec3 lightCol, const vec3 albedo, const float rough, const float spec, const vec3 f0 #ifdef _ShadowMap - , int index, float bias, bool receiveShadow, bool transparent + , int index, float bias, bool receiveShadow + #ifdef _ShadowMapTransparent + , bool transparent + #endif #endif #ifdef _Spot , const bool isSpot, const float spotSize, float spotBlend, vec3 spotDir, vec2 scale, vec3 right @@ -150,7 +171,7 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co #ifdef _VoxelShadow vec3 lightDir = l; #ifdef _Spot - if(isSpot) + if (isSpot) lightDir = spotDir; #endif direct *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, lightDir, clipmaps, gl_FragCoord.xy, velocity).r) * voxelgiShad; @@ -160,15 +181,55 @@ 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], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent); + vec4 lPos = LWVPSpot[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); - if (index == 0) direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent); - else if (index == 1) direct *= shadowTest(shadowMapSpot[1], shadowMapSpotTransparent[1], lPos.xyz / lPos.w, bias, transparent); - else if (index == 2) direct *= shadowTest(shadowMapSpot[2], shadowMapSpotTransparent[2], lPos.xyz / lPos.w, bias, transparent); - else if (index == 3) direct *= shadowTest(shadowMapSpot[3], shadowMapSpotTransparent[3], lPos.xyz / lPos.w, bias, transparent); + vec4 lPos = LWVPSpot[index] * vec4(p + n * bias * 10, 1.0); + if (index == 0) direct *= shadowTest(shadowMapSpot[0], + #ifdef _ShadowMapTransparent + shadowMapSpotTransparent[0], + #endif + 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 @@ -182,25 +243,76 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co #ifdef _ShadowMap if (receiveShadow) { #ifdef _SinglePoint - vec4 lPos = LWVPSpot[0] * vec4(p + n * bias * 10, 1.0); - direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent); + 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 direct *= shadowTest( - #ifndef _SingleAtlas - shadowMapAtlasSpot, shadowMapAtlasSpotTransparent - #else - shadowMapAtlas, shadowMapAtlasTransparent - #endif - , lPos.xyz / lPos.w, bias, transparent - ); + #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], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent); - else if (index == 1) direct *= shadowTest(shadowMapSpot[1], shadowMapSpotTransparent[1], lPos.xyz / lPos.w, bias, transparent); - else if (index == 2) direct *= shadowTest(shadowMapSpot[2], shadowMapSpotTransparent[2], lPos.xyz / lPos.w, bias, transparent); - else if (index == 3) direct *= shadowTest(shadowMapSpot[3], shadowMapSpotTransparent[3], lPos.xyz / lPos.w, bias, transparent); + if (index == 0) direct *= shadowTest(shadowMapSpot[0], + #ifdef _ShadowMapTransparent + shadowMapSpotTransparent[0], + #endif + 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 } @@ -217,24 +329,75 @@ 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], shadowMapPointTransparent[0], ld, -l, bias, lightProj, n, transparent); + 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, shadowMapAtlasPointTransparent - #else - shadowMapAtlas, shadowMapAtlasTransparent - #endif - , ld, -l, bias, lightProj, n, index, transparent - ); + #ifdef _ShadowMapTransparent + #ifndef _SingleAtlas + shadowMapAtlasPoint, shadowMapAtlasPointTransparent + #else + 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], shadowMapPointTransparent[0], ld, -l, bias, lightProj, n, transparent); - else if (index == 1) direct *= PCFCube(shadowMapPoint[1], shadowMapPointTransparent[1], ld, -l, bias, lightProj, n, transparent); - else if (index == 2) direct *= PCFCube(shadowMapPoint[2], shadowMapPointTransparent[2], ld, -l, bias, lightProj, n, transparent); - else if (index == 3) direct *= PCFCube(shadowMapPoint[3], shadowMapPointTransparent[3], ld, -l, bias, lightProj, n, transparent); + 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 } @@ -247,7 +410,10 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co vec3 sampleLightVoxels(const vec3 p, const vec3 n, const vec3 v, const float dotNV, const vec3 lp, const vec3 lightCol, const vec3 albedo, const float rough, const float spec, const vec3 f0 #ifdef _ShadowMap - , int index, float bias, bool receiveShadow, bool transparent + , int index, float bias, bool receiveShadow + #ifdef _ShadowMapTransparent + , bool transparent + #endif #endif #ifdef _Spot , const bool isSpot, const float spotSize, float spotBlend, vec3 spotDir, vec2 scale, vec3 right @@ -285,15 +451,55 @@ vec3 sampleLightVoxels(const vec3 p, const vec3 n, const vec3 v, const float dot #ifdef _ShadowMap if (receiveShadow) { #ifdef _SinglePoint - vec4 lPos = LWVPSpotArray[0] * vec4(p + n * bias * 10, 1.0); - direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent); + vec4 lPos = LWVPSpot[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); - if (index == 0) direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent); - else if (index == 1) direct *= shadowTest(shadowMapSpot[1], shadowMapSpotTransparent[1], lPos.xyz / lPos.w, bias, transparent); - else if (index == 2) direct *= shadowTest(shadowMapSpot[2], shadowMapSpotTransparent[2], lPos.xyz / lPos.w, bias, transparent); - else if (index == 3) direct *= shadowTest(shadowMapSpot[3], shadowMapSpotTransparent[3], lPos.xyz / lPos.w, bias, transparent); + vec4 lPos = LWVPSpot[index] * vec4(p + n * bias * 10, 1.0); + if (index == 0) direct *= shadowTest(shadowMapSpot[0], + #ifdef _ShadowMapTransparent + shadowMapSpotTransparent[0], + #endif + 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 @@ -307,25 +513,76 @@ vec3 sampleLightVoxels(const vec3 p, const vec3 n, const vec3 v, const float dot #ifdef _ShadowMap if (receiveShadow) { #ifdef _SinglePoint - vec4 lPos = LWVPSpot[0] * vec4(p + n * bias * 10, 1.0); - direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent); + 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 = LWVPSpot[index] * vec4(p + n * bias * 10, 1.0); + vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0); #ifdef _ShadowMapAtlas direct *= shadowTest( - #ifndef _SingleAtlas - shadowMapAtlasSpot, shadowMapAtlasSpotTransparent - #else - shadowMapAtlas, shadowMapAtlasTransparent - #endif - , lPos.xyz / lPos.w, bias, transparent - ); + #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], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent); - else if (index == 1) direct *= shadowTest(shadowMapSpot[1], shadowMapSpotTransparent[1], lPos.xyz / lPos.w, bias, transparent); - else if (index == 2) direct *= shadowTest(shadowMapSpot[2], shadowMapSpotTransparent[2], lPos.xyz / lPos.w, bias, transparent); - else if (index == 3) direct *= shadowTest(shadowMapSpot[3], shadowMapSpotTransparent[3], lPos.xyz / lPos.w, bias, transparent); + if (index == 0) direct *= shadowTest(shadowMapSpot[0], + #ifdef _ShadowMapTransparent + shadowMapSpotTransparent[0], + #endif + 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 } @@ -342,24 +599,75 @@ vec3 sampleLightVoxels(const vec3 p, const vec3 n, const vec3 v, const float dot if (receiveShadow) { #ifdef _SinglePoint #ifndef _Spot - direct *= PCFCube(shadowMapPoint[0], shadowMapPointTransparent[0], ld, -l, bias, lightProj, n, transparent); + 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, shadowMapAtlasPointTransparent - #else - shadowMapAtlas, shadowMapAtlasTransparent - #endif - , ld, -l, bias, lightProj, n, index, transparent - ); + #ifdef _ShadowMapTransparent + #ifndef _SingleAtlas + shadowMapAtlasPoint, shadowMapAtlasPointTransparent + #else + 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], shadowMapPointTransparent[0], ld, -l, bias, lightProj, n, transparent); - else if (index == 1) direct *= PCFCube(shadowMapPoint[1], shadowMapPointTransparent[1], ld, -l, bias, lightProj, n, transparent); - else if (index == 2) direct *= PCFCube(shadowMapPoint[2], shadowMapPointTransparent[2], ld, -l, bias, lightProj, n, transparent); - else if (index == 3) direct *= PCFCube(shadowMapPoint[3], shadowMapPointTransparent[3], ld, -l, bias, lightProj, n, transparent); + 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 } From 1e4510ba5642ef02d51fa58521f7a98057d05ce9 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Fri, 30 May 2025 19:16:59 +0000 Subject: [PATCH 102/136] Update leenkx/Shaders/std/conetrace.glsl --- leenkx/Shaders/std/conetrace.glsl | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/leenkx/Shaders/std/conetrace.glsl b/leenkx/Shaders/std/conetrace.glsl index 776752a..5eb745e 100644 --- a/leenkx/Shaders/std/conetrace.glsl +++ b/leenkx/Shaders/std/conetrace.glsl @@ -125,7 +125,7 @@ vec4 traceCone(const sampler3D voxels, const sampler3D voxelsSDF, const vec3 ori if(clipmap_blend > 0.0 && clipmap_index < voxelgiClipmapCount - 1) { vec4 mipSampleNext = sampleVoxel(voxels, p0, clipmaps, clipmap_index + 1.0, step_dist, precomputed_direction, face_offset, direction_weight); - mipSample = mix(mipSample, mipSampleNext, smoothstep(0.0, 1.0, clipmap_blend)); + mipSample = mix(mipSample, mipSampleNext, clipmap_blend); } sampleCol += (1.0 - sampleCol.a) * mipSample; @@ -148,8 +148,9 @@ vec4 traceCone(const sampler3D voxels, const sampler3D voxelsSDF, const vec3 ori vec4 traceDiffuse(const vec3 origin, const vec3 normal, const sampler3D voxels, const float clipmaps[voxelgiClipmapCount * 10]) { float sum = 0.0; vec4 amount = vec4(0.0); + mat3 TBN = makeTangentBasis(normal); for (int i = 0; i < DIFFUSE_CONE_COUNT; ++i) { - vec3 coneDir = DIFFUSE_CONE_DIRECTIONS[i]; + vec3 coneDir = TBN * DIFFUSE_CONE_DIRECTIONS[i]; const float cosTheta = dot(normal, coneDir); if (cosTheta <= 0) continue; @@ -166,7 +167,7 @@ vec4 traceDiffuse(const vec3 origin, const vec3 normal, const sampler3D voxels, } vec4 traceSpecular(const vec3 origin, const vec3 normal, const sampler3D voxels, const sampler3D voxelsSDF, const vec3 viewDir, const float roughness, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel, const vec2 velocity) { - vec3 specularDir = reflect(-viewDir, normal); + vec3 specularDir = reflect(normalize(-viewDir), normal); vec3 P = origin + specularDir * ((BayerMatrix8[int(pixel.x + velocity.x) % 8][int(pixel.y + velocity.y) % 8] - 0.5)) * voxelgiStep; vec4 amount = traceCone(voxels, voxelsSDF, P, normal, specularDir, 0, true, roughness, voxelgiStep, clipmaps); @@ -177,8 +178,8 @@ vec4 traceSpecular(const vec3 origin, const vec3 normal, const sampler3D voxels, } vec4 traceRefraction(const vec3 origin, const vec3 normal, sampler3D voxels, sampler3D voxelsSDF, const vec3 viewDir, const float ior, const float roughness, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel, const vec2 velocity, const float opacity) { - const float transmittance = 1.0; - vec3 refractionDir = refract(-viewDir, normal, 1.0 / ior); + const float transmittance = 1.0 - opacity; + vec3 refractionDir = refract(normalize(-viewDir), normal, 1.0 / ior); vec3 P = origin + refractionDir * (BayerMatrix8[int(pixel.x + velocity.x) % 8][int(pixel.y + velocity.y) % 8] - 0.5) * voxelgiStep; vec4 amount = transmittance * traceCone(voxels, voxelsSDF, P, normal, refractionDir, 0, true, roughness, voxelgiStep, clipmaps); @@ -259,7 +260,6 @@ float traceAO(const vec3 origin, const vec3 normal, const sampler3D voxels, cons } #endif - #ifdef _VoxelShadow float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const vec3 origin, const vec3 n, const vec3 dir, const float aperture, const float step_size, const float clipmaps[voxelgiClipmapCount * 10]) { float sampleCol = 0.0; @@ -287,7 +287,7 @@ float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const v float clipmap_blend = fract(lod); vec3 p0 = start_pos + dir * dist; - samplePos = (p0 - vec3(clipmaps[int(clipmap_index * 10 + 4)], clipmaps[int(clipmap_index * 10 + 5)], clipmaps[int(clipmap_index * 10 + 6)])) / (float(clipmaps[int(clipmap_index * 10)]) * voxelgiResolution.x); + samplePos = (p0 - vec3(clipmaps[int(clipmap_index * 10 + 4)], clipmaps[int(clipmap_index * 10 + 5)], clipmaps[int(clipmap_index * 10 + 6)])) / (float(clipmaps[int(clipmap_index * 10)]) * voxelgiResolution); samplePos = samplePos * 0.5 + 0.5; if ((any(notEqual(samplePos, clamp(samplePos, 0.0, 1.0))))) { From 6ad615a961d63199bfa4df86ae36dd9f2a0295a1 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Fri, 30 May 2025 19:18:06 +0000 Subject: [PATCH 103/136] Update leenkx/Shaders/std/constants.glsl --- leenkx/Shaders/std/constants.glsl | 48 +++++++++++++++++++------------ 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/leenkx/Shaders/std/constants.glsl b/leenkx/Shaders/std/constants.glsl index fc03b31..7aa5d15 100644 --- a/leenkx/Shaders/std/constants.glsl +++ b/leenkx/Shaders/std/constants.glsl @@ -1,13 +1,16 @@ /* Copyright (c) 2024 Turánszki János + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -23,25 +26,34 @@ const float SHADOW_CONE_APERTURE = radians(15.0); const float DIFFUSE_CONE_APERTURE = radians(50.0); -const vec3 DIFFUSE_CONE_DIRECTIONS[16] = vec3[]( - vec3( 0.0000, 0.0000, 1.0000), - vec3( 0.7236, 0.5257, 0.4472), - vec3(-0.2764, 0.8506, 0.4472), - vec3(-0.8944, 0.0000, 0.4472), - vec3(-0.2764, -0.8506, 0.4472), - vec3( 0.7236, -0.5257, 0.4472), - vec3( 0.7236, 0.5257, -0.4472), - vec3(-0.2764, 0.8506, -0.4472), - vec3(-0.8944, 0.0000, -0.4472), - vec3(-0.2764, -0.8506, -0.4472), - vec3( 0.7236, -0.5257, -0.4472), - vec3( 0.2764, 0.8506, 0.4472), - vec3(-0.7236, 0.5257, 0.4472), - vec3(-0.7236, -0.5257, 0.4472), - vec3( 0.2764, -0.8506, 0.4472), - vec3( 0.0000, 0.0000, -1.0000) +const vec3 DIFFUSE_CONE_DIRECTIONS[DIFFUSE_CONE_COUNT] = vec3[]( + vec3(0.0, 0.0, 1.0), // center + + vec3(0.0, 0.5, 0.866), + vec3(0.5, 0.0, 0.866), + vec3(0.0, -0.5, 0.866), + vec3(-0.5, 0.0, 0.866), + + vec3(0.353, 0.353, 0.866), + vec3(0.353, -0.353, 0.866), + vec3(-0.353, -0.353, 0.866), + vec3(-0.353, 0.353, 0.866), + + vec3(0.707, 0.0, 0.707), + vec3(0.0, 0.707, 0.707), + vec3(-0.707, 0.0, 0.707), + vec3(0.0, -0.707, 0.707), + + vec3(0.5, 0.5, 0.707), + vec3(-0.5, 0.5, 0.707), + vec3(-0.5, -0.5, 0.707) ); +mat3 makeTangentBasis(vec3 normal) { + vec3 tangent = normalize(abs(normal.y) < 0.999 ? cross(normal, vec3(0, 1, 0)) : cross(normal, vec3(1, 0, 0))); + vec3 bitangent = cross(normal, tangent); + return mat3(tangent, bitangent, normal); +} const float BayerMatrix8[8][8] = { @@ -53,4 +65,4 @@ const float BayerMatrix8[8][8] = { 35.0 / 65.0, 19.0 / 65.0, 47.0 / 65.0, 31.0 / 65.0, 34.0 / 65.0, 18.0 / 65.0, 46.0 / 65.0, 30.0 / 65.0 }, { 11.0 / 65.0, 59.0 / 65.0, 7.0 / 65.0, 55.0 / 65.0, 10.0 / 65.0, 58.0 / 65.0, 6.0 / 65.0, 54.0 / 65.0 }, { 43.0 / 65.0, 27.0 / 65.0, 39.0 / 65.0, 23.0 / 65.0, 42.0 / 65.0, 26.0 / 65.0, 38.0 / 65.0, 22.0 / 65.0 } -}; \ No newline at end of file +}; From c4378be891c0d546930ace209e916a2e2a427971 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Fri, 30 May 2025 19:19:33 +0000 Subject: [PATCH 104/136] Update leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl --- .../voxel_temporal/voxel_temporal.comp.glsl | 74 ++++++++++--------- 1 file changed, 39 insertions(+), 35 deletions(-) diff --git a/leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl b/leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl index d077029..679e0f3 100644 --- a/leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl +++ b/leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl @@ -35,28 +35,26 @@ uniform vec3 lightColor; uniform int lightType; uniform vec3 lightDir; uniform vec2 spotData; -uniform float envmapStrength; #ifdef _ShadowMap uniform int lightShadow; uniform vec2 lightProj; uniform float shadowsBias; uniform mat4 LVP; #endif -uniform float envmapStrength; uniform sampler3D voxelsSampler; uniform layout(r32ui) uimage3D voxels; uniform layout(r32ui) uimage3D voxelsLight; uniform layout(rgba16f) image3D voxelsB; uniform layout(rgba16f) image3D voxelsOut; -uniform layout(r16f) image3D SDF; +uniform layout(r8) image3D SDF; #else #ifdef _VoxelAOvar #ifdef _VoxelShadow -uniform layout(r16f) image3D SDF; +uniform layout(r8) image3D SDF; #endif uniform layout(r32ui) uimage3D voxels; -uniform layout(r16f) image3D voxelsB; -uniform layout(r16f) image3D voxelsOut; +uniform layout(r8) image3D voxelsB; +uniform layout(r8) image3D voxelsOut; #endif #endif @@ -76,6 +74,9 @@ void main() { #endif #endif + mat3 TBN = mat3(1.0); + vec3 avgNormal = vec3(0.0); + for (int i = 0; i < 6 + DIFFUSE_CONE_COUNT; i++) { #ifdef _VoxelGI @@ -100,45 +101,46 @@ void main() { int count = int(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 15))); if (count > 0) { vec4 basecol = vec4(0.0); - basecol.r = float(imageLoad(voxels, src)) / 1024; - basecol.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x))) / 1024; - basecol.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 2))) / 1024; - basecol.a = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 3))) / 1024; + basecol.r = float(imageLoad(voxels, src)) / 255; + basecol.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x))) / 255; + basecol.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 2))) / 255; + basecol.a = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 3))) / 255; basecol /= count; vec3 emission = vec3(0.0); - emission.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 4))) / 1024; - emission.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 5))) / 1024; - emission.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 6))) / 1024; + emission.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 4))) / 255; + emission.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 5))) / 255; + emission.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 6))) / 255; emission /= count; - // Retrieve encoded normal (stored in 8-bit format) vec3 N = vec3(0.0); - N.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 7))) / 1024.0; - N.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 8))) / 1024.0; + N.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 7))) / 255; + N.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 8))) / 255; N /= count; - // Decode octahedral normal N = decode_oct(N.rg * 2.0 - 1.0); + avgNormal += N; + + if (i == 5) + TBN = makeTangentBasis(normalize(avgNormal)); + vec3 envl = vec3(0.0); - envl.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 9))) / 1024; - envl.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 10))) / 1024; - envl.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 11))) / 1024; + envl.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 9))) / 255; + envl.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 10))) / 255; + envl.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 11))) / 255; envl /= count; - envl *= envmapStrength; vec3 light = vec3(0.0); - light.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 12))) / 1024; - light.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 13))) / 1024; - light.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 14))) / 1024; + light.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 12))) / 255; + light.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 13))) / 255; + light.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 14))) / 255; light /= count; - //clipmap to world - vec3 P = (gl_GlobalInvocationID.xyz + 0.5) / voxelgiResolution.x; - P = P * 2.0 - 1.0; - P *= float(clipmaps[int(clipmapLevel * 10)]); - P *= voxelgiResolution.x; - P += vec3(clipmaps[clipmapLevel * 10 + 4], clipmaps[clipmapLevel * 10 + 5], clipmaps[clipmapLevel * 10 + 6]); + vec3 wposition = (gl_GlobalInvocationID.xyz + 0.5) / voxelgiResolution.x; + wposition = wposition * 2.0 - 1.0; + wposition *= float(clipmaps[int(clipmapLevel * 10)]); + wposition *= voxelgiResolution.x; + wposition += vec3(clipmaps[clipmapLevel * 10 + 4], clipmaps[clipmapLevel * 10 + 5], clipmaps[clipmapLevel * 10 + 6]); radiance = basecol; - vec4 trace = traceDiffuse(P, N, voxelsSampler, clipmaps); + vec4 trace = traceDiffuse(wposition, N, voxelsSampler, clipmaps); vec3 indirect = trace.rgb + envl.rgb * (1.0 - trace.a); radiance.rgb *= light + indirect; radiance.rgb += emission.rgb; @@ -146,7 +148,7 @@ void main() { #else int count = int(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x))); if (count > 0) { - opac = float(imageLoad(voxels, src)) / 1024; + opac = float(imageLoad(voxels, src)) / 255; opac /= count; } #endif @@ -202,7 +204,7 @@ void main() { } else { // precompute cone sampling: - vec3 coneDirection = DIFFUSE_CONE_DIRECTIONS[i - 6]; + vec3 coneDirection = TBN * DIFFUSE_CONE_DIRECTIONS[i - 6]; vec3 aniso_direction = -coneDirection; uvec3 face_offsets = uvec3( aniso_direction.x > 0 ? 0 : 1, @@ -214,13 +216,15 @@ void main() { vec4 sam = aniso_colors[face_offsets.x] * direction_weights.x + aniso_colors[face_offsets.y] * direction_weights.y + - aniso_colors[face_offsets.z] * direction_weights.z; + aniso_colors[face_offsets.z] * direction_weights.z + ; radiance = sam; #else float sam = aniso_colors[face_offsets.x] * direction_weights.x + aniso_colors[face_offsets.y] * direction_weights.y + - aniso_colors[face_offsets.z] * direction_weights.z; + aniso_colors[face_offsets.z] * direction_weights.z + ; opac = sam; #endif } From 45a48acf8adb2d3aa4ddd396d05bff7bbd8ec76d Mon Sep 17 00:00:00 2001 From: Onek8 Date: Sun, 1 Jun 2025 03:39:35 +0000 Subject: [PATCH 105/136] Update leenkx/Sources/leenkx/renderpath/Inc.hx --- leenkx/Sources/leenkx/renderpath/Inc.hx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/leenkx/Sources/leenkx/renderpath/Inc.hx b/leenkx/Sources/leenkx/renderpath/Inc.hx index 09dd163..1d23303 100644 --- a/leenkx/Sources/leenkx/renderpath/Inc.hx +++ b/leenkx/Sources/leenkx/renderpath/Inc.hx @@ -678,7 +678,7 @@ class Inc { } else { if (t.name == "voxelsSDF" || t.name == "voxelsSDFtmp") { - t.format = "R16"; + t.format = "R8"; t.width = res; t.height = res * Main.voxelgiClipmapCount; t.depth = res; @@ -687,7 +687,7 @@ class Inc { #if (rp_voxels == "Voxel AO") { if (t.name == "voxelsOut" || t.name == "voxelsOutB") { - t.format = "R16"; + t.format = "R8"; t.width = res * (6 + 16); t.height = res * Main.voxelgiClipmapCount; t.depth = res; @@ -702,7 +702,7 @@ class Inc { #else { if (t.name == "voxelsOut" || t.name == "voxelsOutB") { - t.format = "RGBA64"; + t.format = "RGBA32"; t.width = res * (6 + 16); t.height = res * Main.voxelgiClipmapCount; t.depth = res; From cbbd6fe4952beec09aedfb2810c01535b5905279 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Sun, 1 Jun 2025 03:40:37 +0000 Subject: [PATCH 106/136] Update leenkx/Shaders/voxel_offsetprev/voxel_offsetprev.comp.glsl --- .../Shaders/voxel_offsetprev/voxel_offsetprev.comp.glsl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/leenkx/Shaders/voxel_offsetprev/voxel_offsetprev.comp.glsl b/leenkx/Shaders/voxel_offsetprev/voxel_offsetprev.comp.glsl index 098284f..3b5fe1c 100644 --- a/leenkx/Shaders/voxel_offsetprev/voxel_offsetprev.comp.glsl +++ b/leenkx/Shaders/voxel_offsetprev/voxel_offsetprev.comp.glsl @@ -30,11 +30,11 @@ layout (local_size_x = 8, local_size_y = 8, local_size_z = 8) in; #include "std/constants.glsl" #ifdef _VoxelGI -uniform layout(rgba16f) image3D voxelsB; -uniform layout(rgba16f) image3D voxelsOut; +uniform layout(rgba8) image3D voxelsB; +uniform layout(rgba8) image3D voxelsOut; #else -uniform layout(r16f) image3D voxelsB; -uniform layout(r16f) image3D voxelsOut; +uniform layout(r8) image3D voxelsB; +uniform layout(r8) image3D voxelsOut; #endif uniform int clipmapLevel; From 74bbb6ca875b24a5af6bc4213daec69912bd9db5 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Sun, 1 Jun 2025 03:41:14 +0000 Subject: [PATCH 107/136] Update leenkx/Shaders/voxel_sdf_jumpflood/voxel_sdf_jumpflood.comp.glsl --- .../Shaders/voxel_sdf_jumpflood/voxel_sdf_jumpflood.comp.glsl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/leenkx/Shaders/voxel_sdf_jumpflood/voxel_sdf_jumpflood.comp.glsl b/leenkx/Shaders/voxel_sdf_jumpflood/voxel_sdf_jumpflood.comp.glsl index 9bd624d..5e6a0ea 100644 --- a/leenkx/Shaders/voxel_sdf_jumpflood/voxel_sdf_jumpflood.comp.glsl +++ b/leenkx/Shaders/voxel_sdf_jumpflood/voxel_sdf_jumpflood.comp.glsl @@ -23,8 +23,8 @@ THE SOFTWARE. #include "compiled.inc" -uniform layout(r16f) image3D input_sdf; -uniform layout(r16f) image3D output_sdf; +uniform layout(r8) image3D input_sdf; +uniform layout(r8) image3D output_sdf; uniform float jump_size; uniform int clipmapLevel; From 872433cafb13bca1ea362b6f2168cf7cfebf1dd7 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Sun, 1 Jun 2025 03:42:22 +0000 Subject: [PATCH 108/136] Update leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl --- leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl b/leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl index 679e0f3..a5b6350 100644 --- a/leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl +++ b/leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl @@ -44,8 +44,8 @@ uniform mat4 LVP; uniform sampler3D voxelsSampler; uniform layout(r32ui) uimage3D voxels; uniform layout(r32ui) uimage3D voxelsLight; -uniform layout(rgba16f) image3D voxelsB; -uniform layout(rgba16f) image3D voxelsOut; +uniform layout(rgba8) image3D voxelsB; +uniform layout(rgba8) image3D voxelsOut; uniform layout(r8) image3D SDF; #else #ifdef _VoxelAOvar From 908efdd5543b2e9aa880a6a1f27f4558c9726f4b Mon Sep 17 00:00:00 2001 From: Onek8 Date: Mon, 2 Jun 2025 20:33:49 +0000 Subject: [PATCH 109/136] Update leenkx/blender/lnx/material/make_mesh.py --- leenkx/blender/lnx/material/make_mesh.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/leenkx/blender/lnx/material/make_mesh.py b/leenkx/blender/lnx/material/make_mesh.py index db6d899..20ad682 100644 --- a/leenkx/blender/lnx/material/make_mesh.py +++ b/leenkx/blender/lnx/material/make_mesh.py @@ -789,10 +789,11 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): frag.write('direct += sampleLight(') frag.write(' wposition, n, vVec, dotNV, pointPos, pointCol, albedo, roughness, specular, f0') if is_shadows: - if parse_opacity: - frag.write(', 0, pointBias, receiveShadow, opacity != 1.0') + frag.write(', 0, pointBias, receiveShadow') + if '_ShadowMapTransparent' in wrd.world_defs and parse_opacity: + frag.write(', opacity != 1.0') else: - frag.write(', 0, pointBias, receiveShadow, false') + frag.write(', false') if '_Spot' in wrd.world_defs: frag.write(', true, spotData.x, spotData.y, spotDir, spotData.zw, spotRight') if '_VoxelShadow' in wrd.world_defs: From 38eb66a0b53e69dac5aacd9969eda3ef6294cb14 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Mon, 2 Jun 2025 20:35:28 +0000 Subject: [PATCH 110/136] Update leenkx/blender/lnx/material/make_cluster.py --- leenkx/blender/lnx/material/make_cluster.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/leenkx/blender/lnx/material/make_cluster.py b/leenkx/blender/lnx/material/make_cluster.py index b3fdd25..8e40606 100644 --- a/leenkx/blender/lnx/material/make_cluster.py +++ b/leenkx/blender/lnx/material/make_cluster.py @@ -84,12 +84,12 @@ def write(vert: shader.Shader, frag: shader.Shader): frag.write(' roughness,') frag.write(' specular,') frag.write(' f0') - if is_shadows: - if parse_opacity: - frag.write('\t, li, lightsArray[li * 3 + 2].x, lightsArray[li * 3 + 2].z != 0.0, opacity != 1.0') # bias + frag.write('\t, li, lightsArray[li * 3 + 2].x, lightsArray[li * 3 + 2].z != 0.0') + if '_ShadowMapTransparent' in wrd.world_defs and parse_opacity: + frag.write(', opacity != 1.0') else: - frag.write('\t, li, lightsArray[li * 3 + 2].x, lightsArray[li * 3 + 2].z != 0.0, false') # bias + frag.write(', false') if '_Spot' in wrd.world_defs: frag.write('\t, lightsArray[li * 3 + 2].y != 0.0') frag.write('\t, lightsArray[li * 3 + 2].y') # spot size (cutoff) From 63565052e3e1d23017879894b5f64bc302d3c186 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Mon, 2 Jun 2025 20:37:45 +0000 Subject: [PATCH 111/136] Disable BayerMatrix momentaraily --- leenkx/Shaders/std/constants.glsl | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/leenkx/Shaders/std/constants.glsl b/leenkx/Shaders/std/constants.glsl index 7aa5d15..b9ccfdc 100644 --- a/leenkx/Shaders/std/constants.glsl +++ b/leenkx/Shaders/std/constants.glsl @@ -55,7 +55,8 @@ mat3 makeTangentBasis(vec3 normal) { return mat3(tangent, bitangent, normal); } -const float BayerMatrix8[8][8] = +// TO DO - Disabled momentarily instead of changing formulas +const float off_BayerMatrix8[8][8] = { { 1.0 / 65.0, 49.0 / 65.0, 13.0 / 65.0, 61.0 / 65.0, 4.0 / 65.0, 52.0 / 65.0, 16.0 / 65.0, 64.0 / 65.0 }, { 33.0 / 65.0, 17.0 / 65.0, 45.0 / 65.0, 29.0 / 65.0, 36.0 / 65.0, 20.0 / 65.0, 48.0 / 65.0, 32.0 / 65.0 }, @@ -66,3 +67,15 @@ const float BayerMatrix8[8][8] = { 11.0 / 65.0, 59.0 / 65.0, 7.0 / 65.0, 55.0 / 65.0, 10.0 / 65.0, 58.0 / 65.0, 6.0 / 65.0, 54.0 / 65.0 }, { 43.0 / 65.0, 27.0 / 65.0, 39.0 / 65.0, 23.0 / 65.0, 42.0 / 65.0, 26.0 / 65.0, 38.0 / 65.0, 22.0 / 65.0 } }; +const float BayerMatrix8[8][8] = +{ + { 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0 }, + { 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0 }, + { 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0 }, + { 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0 }, + { 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0 }, + { 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0 }, + { 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0 }, + { 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0 } +}; + From b5af208766baa9a9cbe25b045063a59ce25f033b Mon Sep 17 00:00:00 2001 From: Onek8 Date: Tue, 3 Jun 2025 03:09:32 +0000 Subject: [PATCH 112/136] Update leenkx/Shaders/std/shadows.glsl --- leenkx/Shaders/std/shadows.glsl | 192 +++++++++++++++++--------------- 1 file changed, 103 insertions(+), 89 deletions(-) diff --git a/leenkx/Shaders/std/shadows.glsl b/leenkx/Shaders/std/shadows.glsl index 3ee7b23..7f74a78 100644 --- a/leenkx/Shaders/std/shadows.glsl +++ b/leenkx/Shaders/std/shadows.glsl @@ -58,7 +58,15 @@ vec2 sampleCube(vec3 dir, out int faceIndex) { } #endif -vec3 PCF(sampler2DShadow shadowMap, sampler2D shadowMapTransparent, const vec2 uv, const float compare, const vec2 smSize, const bool transparent) { +vec3 PCF(sampler2DShadow shadowMap, + #ifdef _ShadowMapTransparent + sampler2D shadowMapTransparent, + #endif + const vec2 uv, const float compare, const vec2 smSize + #ifdef _ShadowMapTransparent + , const bool transparent + #endif + ) { vec3 result = vec3(0.0); result.x = texture(shadowMap, vec3(uv + (vec2(-1.0, -1.0) / smSize), compare)); result.x += texture(shadowMap, vec3(uv + (vec2(-1.0, 0.0) / smSize), compare)); @@ -71,11 +79,13 @@ vec3 PCF(sampler2DShadow shadowMap, sampler2D shadowMapTransparent, const vec2 u result.x += texture(shadowMap, vec3(uv + (vec2(1.0, 1.0) / smSize), compare)); result = result.xxx / 9.0; + #ifdef _ShadowMapTransparent if (transparent == false) { vec4 shadowmap_transparent = texture(shadowMapTransparent, uv); if (shadowmap_transparent.a < compare) result *= shadowmap_transparent.rgb; } + #endif return result; } @@ -87,7 +97,15 @@ float lpToDepth(vec3 lp, const vec2 lightProj) { return zcomp * 0.5 + 0.5; } -vec3 PCFCube(samplerCubeShadow shadowMapCube, samplerCube shadowMapCubeTransparent, const vec3 lp, vec3 ml, const float bias, const vec2 lightProj, const vec3 n, const bool transparent) { +vec3 PCFCube(samplerCubeShadow shadowMapCube, + #ifdef _ShadowMapTransparent + samplerCube shadowMapCubeTransparent, + #endif + const vec3 lp, vec3 ml, const float bias, const vec2 lightProj, const vec3 n + #ifdef _ShadowMapTransparent + , const bool transparent + #endif + ) { const float s = shadowmapCubePcfSize; // TODO: incorrect... float compare = lpToDepth(lp, lightProj) - bias * 1.5; ml = ml + n * bias * 20; @@ -106,11 +124,13 @@ vec3 PCFCube(samplerCubeShadow shadowMapCube, samplerCube shadowMapCubeTranspare result.x += texture(shadowMapCube, vec4(ml + vec3(-s, -s, -s), compare)); result = result.xxx / 9.0; + #ifdef _ShadowMapTransparent if (transparent == false) { vec4 shadowmap_transparent = texture(shadowMapCubeTransparent, ml); if (shadowmap_transparent.a < compare) result *= shadowmap_transparent.rgb; } + #endif return result; } @@ -209,32 +229,57 @@ vec2 transformOffsetedUV(const int faceIndex, out int newFaceIndex, vec2 uv) { return uv; } -vec3 PCFFakeCube(sampler2DShadow shadowMap, sampler2D shadowMapTransparent, const vec3 lp, vec3 ml, const float bias, const vec2 lightProj, const vec3 n, const int index, const bool transparent) { +vec3 PCFFakeCube(sampler2DShadow shadowMap, + #ifdef _ShadowMapTransparent + sampler2D shadowMapTransparent, + #endif + const vec3 lp, vec3 ml, const float bias, const vec2 lightProj, const vec3 n, const int index + #ifdef _ShadowMapTransparent + , const bool transparent + #endif + ) { const vec2 smSize = smSizeUniform; // TODO: incorrect... const float compare = lpToDepth(lp, lightProj) - bias * 1.5; ml = ml + n * bias * 20; - int faceIndex = 0; const int lightIndex = index * 6; const vec2 uv = sampleCube(ml, faceIndex); - vec4 pointLightTile = pointLightDataArray[lightIndex + faceIndex]; // x: tile X offset, y: tile Y offset, z: tile size relative to atlas vec2 uvtiled = pointLightTile.z * uv + pointLightTile.xy; #ifdef _FlipY uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system #endif + if (any(lessThan(uvtiled, vec2(0.0))) || any(greaterThan(uvtiled, vec2(1.0)))) { + return vec3(1.0); // Or handle edge cases differently + } + vec3 result = vec3(0.0); - result.x += texture(shadowMap, vec3(uvtiled, compare)); - // soft shadowing - int newFaceIndex = 0; - uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(-1.0, 0.0) / smSize))); - pointLightTile = pointLightDataArray[lightIndex + newFaceIndex]; - uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy; + // In PCFFakeCube(), modify the sampling pattern to be more robust: + const vec2 offsets[9] = vec2[]( + vec2(0, 0), + vec2(1, 0), vec2(-1, 0), vec2(0, 1), vec2(0, -1), + vec2(1, 1), vec2(-1, 1), vec2(1, -1), vec2(-1, -1) + ); + + for (int i = 0; i < 9; i++) { + vec2 sampleUV = uv + offsets[i] / smSize; + int newFaceIndex; + vec2 transformedUV = transformOffsetedUV(faceIndex, newFaceIndex, sampleUV); + pointLightTile = pointLightDataArray[lightIndex + newFaceIndex]; + uvtiled = pointLightTile.z * transformedUV + pointLightTile.xy; + #ifdef _FlipY + uvtiled.y = 1.0 - uvtiled.y; + #endif + result.x += texture(shadowMap, vec3(uvtiled, compare)); + } + result = result.xxx / 9.0; + + pointLightTile = pointLightDataArray[lightIndex + faceIndex]; // x: tile X offset, y: tile Y offset, z: tile size relative to atlas + uvtiled = pointLightTile.z * uv + pointLightTile.xy; #ifdef _FlipY uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system #endif - result.x += texture(shadowMap, vec3(uvtiled, compare)); #ifdef _ShadowMapTransparent if (transparent == false) { @@ -244,88 +289,39 @@ vec3 PCFFakeCube(sampler2DShadow shadowMap, sampler2D shadowMapTransparent, cons } #endif - result.x += texture(shadowMap, vec3(uvtiled, compare)); - - uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(0.0, -1.0) / smSize))); - pointLightTile = pointLightDataArray[lightIndex + newFaceIndex]; - uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy; - #ifdef _FlipY - uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system - #endif - result.x += texture(shadowMap, vec3(uvtiled, compare)); - - uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(-1.0, -1.0) / smSize))); - pointLightTile = pointLightDataArray[lightIndex + newFaceIndex]; - uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy; - #ifdef _FlipY - uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system - #endif - result.x += texture(shadowMap, vec3(uvtiled, compare)); - - uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(0.0, 1.0) / smSize))); - pointLightTile = pointLightDataArray[lightIndex + newFaceIndex]; - uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy; - #ifdef _FlipY - uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system - #endif - result.x += texture(shadowMap, vec3(uvtiled, compare)); - - uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(1.0, -1.0) / smSize))); - pointLightTile = pointLightDataArray[lightIndex + newFaceIndex]; - uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy; - #ifdef _FlipY - uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system - #endif - result.x += texture(shadowMap, vec3(uvtiled, compare)); - - uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(1.0, 0.0) / smSize))); - pointLightTile = pointLightDataArray[lightIndex + newFaceIndex]; - uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy; - #ifdef _FlipY - uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system - #endif - result.x += texture(shadowMap, vec3(uvtiled, compare)); - - uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(1.0, 1.0) / smSize))); - pointLightTile = pointLightDataArray[lightIndex + newFaceIndex]; - uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy; - #ifdef _FlipY - uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system - #endif - result.x += texture(shadowMap, vec3(uvtiled, compare)); - - result = result.xxx / 9.0; - - pointLightTile = pointLightDataArray[lightIndex + faceIndex]; // x: tile X offset, y: tile Y offset, z: tile size relative to atlas - uvtiled = pointLightTile.z * uv + pointLightTile.xy; - #ifdef _FlipY - uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system - #endif - - if (transparent == false) { - vec4 shadowmap_transparent = texture(shadowMapTransparent, uvtiled); - if (shadowmap_transparent.a < compare) - result *= shadowmap_transparent.rgb; - } - return result; } #endif -vec3 shadowTest(sampler2DShadow shadowMap, sampler2D shadowMapTransparent, const vec3 lPos, const float shadowsBias, const bool transparent) { +vec3 shadowTest(sampler2DShadow shadowMap, + #ifdef _ShadowMapTransparent + sampler2D shadowMapTransparent, + #endif + const vec3 lPos, const float shadowsBias + #ifdef _ShadowMapTransparent + , const bool transparent + #endif + ) { #ifdef _SMSizeUniform vec2 smSize = smSizeUniform; #else const vec2 smSize = shadowmapSize; #endif if (lPos.x < 0.0 || lPos.y < 0.0 || lPos.x > 1.0 || lPos.y > 1.0) return vec3(1.0); - return PCF(shadowMap, shadowMapTransparent, lPos.xy, lPos.z - shadowsBias, smSize, transparent); + return PCF(shadowMap, + #ifdef _ShadowMapTransparent + shadowMapTransparent, + #endif + lPos.xy, lPos.z - shadowsBias, smSize + #ifdef _ShadowMapTransparent + , transparent + #endif + ); } #ifdef _CSM mat4 getCascadeMat(const float d, out int casi, out int casIndex) { const int c = shadowmapCascades; - // Get cascade index // TODO: use bounding box slice selection instead of sphere const vec4 ci = vec4(float(c > 0), float(c > 1), float(c > 2), float(c > 3)); @@ -341,21 +337,26 @@ mat4 getCascadeMat(const float d, out int casi, out int casIndex) { float(d > casData[c * 4].z), float(d > casData[c * 4].w)); casi = int(min(dot(ci, comp), c)); - // Get cascade mat casIndex = casi * 4; - return mat4( casData[casIndex ], casData[casIndex + 1], casData[casIndex + 2], casData[casIndex + 3]); - // if (casIndex == 0) return mat4(casData[0], casData[1], casData[2], casData[3]); // .. } -vec3 shadowTestCascade(sampler2DShadow shadowMap, sampler2D shadowMapTransparent, const vec3 eye, const vec3 p, const float shadowsBias, const bool transparent) { +vec3 shadowTestCascade(sampler2DShadow shadowMap, + #ifdef _ShadowMapTransparent + sampler2D shadowMapTransparent, + #endif + const vec3 eye, const vec3 p, const float shadowsBias + #ifdef _ShadowMapTransparent + , const bool transparent + #endif + ) { #ifdef _SMSizeUniform vec2 smSize = smSizeUniform; #else @@ -363,16 +364,22 @@ vec3 shadowTestCascade(sampler2DShadow shadowMap, sampler2D shadowMapTransparent #endif const int c = shadowmapCascades; float d = distance(eye, p); - int casi; int casIndex; mat4 LWVP = getCascadeMat(d, casi, casIndex); - vec4 lPos = LWVP * vec4(p, 1.0); lPos.xyz /= lPos.w; vec3 visibility = vec3(1.0); - if (lPos.w > 0.0) visibility = PCF(shadowMap, shadowMapTransparent, lPos.xy, lPos.z - shadowsBias, smSize, transparent); + if (lPos.w > 0.0) visibility = PCF(shadowMap, + #ifdef _ShadowMapTransparent + shadowMapTransparent, + #endif + lPos.xy, lPos.z - shadowsBias, smSize + #ifdef _ShadowMapTransparent + , transparent + #endif + ); // Blend cascade // https://github.com/TheRealMJP/Shadows @@ -391,13 +398,20 @@ vec3 shadowTestCascade(sampler2DShadow shadowMap, sampler2D shadowMapTransparent vec4 lPos2 = LWVP2 * vec4(p, 1.0); lPos2.xyz /= lPos2.w; vec3 visibility2 = vec3(1.0); - if (lPos2.w > 0.0) visibility2 = PCF(shadowMap, shadowMapTransparent, lPos2.xy, lPos2.z - shadowsBias, smSize, transparent); + if (lPos2.w > 0.0) visibility2 = PCF(shadowMap, + #ifdef _ShadowMapTransparent + shadowMapTransparent, + #endif + lPos.xy, lPos.z - shadowsBias, smSize + #ifdef _ShadowMapTransparent + , transparent + #endif + ); float lerpAmt = smoothstep(0.0, blendThres, splitDist); return mix(visibility2, visibility, lerpAmt); } return visibility; - // Visualize cascades // if (ci == 0) albedo.rgb = vec3(1.0, 0.0, 0.0); // if (ci == 4) albedo.rgb = vec3(0.0, 1.0, 0.0); @@ -405,4 +419,4 @@ vec3 shadowTestCascade(sampler2DShadow shadowMap, sampler2D shadowMapTransparent // if (ci == 12) albedo.rgb = vec3(1.0, 1.0, 0.0); } #endif -#endif +#endif \ No newline at end of file From 846c3b2c11ba3b2ed9a8adfcb00478d4985aaba6 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Tue, 3 Jun 2025 16:18:05 +0000 Subject: [PATCH 113/136] Update leenkx/blender/lnx/material/make_mesh.py --- leenkx/blender/lnx/material/make_mesh.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/leenkx/blender/lnx/material/make_mesh.py b/leenkx/blender/lnx/material/make_mesh.py index 20ad682..6fba67d 100644 --- a/leenkx/blender/lnx/material/make_mesh.py +++ b/leenkx/blender/lnx/material/make_mesh.py @@ -797,7 +797,9 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): if '_Spot' in wrd.world_defs: frag.write(', true, spotData.x, spotData.y, spotDir, spotData.zw, spotRight') if '_VoxelShadow' in wrd.world_defs: - frag.write(', voxels, voxelsSDF, clipmaps, velocity') + frag.write(', voxels, voxelsSDF, clipmaps') + if '_Veloc' in wrd.world_defs or '_VoxelShadow' in wrd.world_defs: + frag.write(', velocity') if '_MicroShadowing' in wrd.world_defs: frag.write(', occlusion') if '_SSRS' in wrd.world_defs: From 1ef805eb0beeaf1a7ac3a5bc81a766ff7acadd16 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Fri, 6 Jun 2025 20:01:29 +0000 Subject: [PATCH 114/136] Update leenkx/blender/lnx/material/make_mesh.py --- leenkx/blender/lnx/material/make_mesh.py | 40 +++++++++++++++--------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/leenkx/blender/lnx/material/make_mesh.py b/leenkx/blender/lnx/material/make_mesh.py index 6fba67d..f935826 100644 --- a/leenkx/blender/lnx/material/make_mesh.py +++ b/leenkx/blender/lnx/material/make_mesh.py @@ -646,6 +646,7 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): frag.add_include('std/light.glsl') is_shadows = '_ShadowMap' in wrd.world_defs + is_transparent_shadows = '_ShadowMapTransparent' in wrd.world_defs is_shadows_atlas = '_ShadowMapAtlas' in wrd.world_defs is_single_atlas = is_shadows_atlas and '_SingleAtlas' in wrd.world_defs shadowmap_sun = 'shadowMap' @@ -662,7 +663,9 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): frag.add_uniform('sampler2D senvmapBrdf', link='$brdf.png') frag.write('vec2 envBRDF = texelFetch(senvmapBrdf, ivec2(vec2(dotNV, 1.0 - roughness) * 256.0), 0).xy;') frag.write('vec3 F = f0 * envBRDF.x + envBRDF.y;') - + else: + frag.write('vec3 F = f0;') + if '_Irr' in wrd.world_defs: frag.add_include('std/shirr.glsl') frag.add_uniform('vec4 shirr[7]', link='_envmapIrradiance') @@ -730,17 +733,21 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): if is_shadows: frag.add_uniform('bool receiveShadow') frag.add_uniform(f'sampler2DShadow {shadowmap_sun}', top=True) - frag.add_uniform(f'sampler2D {shadowmap_sun_tr}', top=True) + if is_transparent_shadows: + frag.add_uniform(f'sampler2D {shadowmap_sun_tr}', top=True) frag.add_uniform('float shadowsBias', '_sunShadowsBias') frag.write('if (receiveShadow) {') if '_CSM' in wrd.world_defs: frag.add_include('std/shadows.glsl') frag.add_uniform('vec4 casData[shadowmapCascades * 4 + 4]', '_cascadeData', included=True) frag.add_uniform('vec3 eye', '_cameraPosition') - if parse_opacity: - frag.write(f'svisibility = shadowTestCascade({shadowmap_sun}, {shadowmap_sun_tr}, eye, wposition + n * shadowsBias * 10, shadowsBias, true);') - else: - frag.write(f'svisibility = shadowTestCascade({shadowmap_sun}, {shadowmap_sun_tr}, eye, wposition + n * shadowsBias * 10, shadowsBias, false);') + frag.write(f'svisibility = shadowTestCascade({shadowmap_sun},') + if is_transparent_shadows: + frag.write(f'{shadowmap_sun_tr},') + frag.write('eye, wposition + n * shadowsBias * 10, shadowsBias') + if is_transparent_shadows: + frag.write(', false') + frag.write(');') else: if tese is not None: tese.add_out('vec4 lightPosition') @@ -757,10 +764,13 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): vert.write('lightPosition = LWVP * pos;') frag.write('vec3 lPos = lightPosition.xyz / lightPosition.w;') frag.write('const vec2 smSize = shadowmapSize;') - if parse_opacity: - frag.write(f'svisibility = PCF({shadowmap_sun}, {shadowmap_sun_tr}, lPos.xy, lPos.z - shadowsBias, smSize, true);') - else: - frag.write(f'svisibility = PCF({shadowmap_sun}, {shadowmap_sun_tr}, lPos.xy, lPos.z - shadowsBias, smSize, false);') + frag.write(f'svisibility = PCF({shadowmap_sun},') + if is_transparent_shadows: + frag.write(f'{shadowmap_sun_tr},') + frag.write('lPos.xy, lPos.z - shadowsBias, smSize') + if is_transparent_shadows: + frag.write(', false') + frag.write(');') if '_VoxelShadow' in wrd.world_defs: frag.write('svisibility *= (1.0 - traceShadow(wposition, n, voxels, voxelsSDF, sunDir, clipmaps, gl_FragCoord.xy, velocity).r) * voxelgiShad;') frag.write('}') # receiveShadow @@ -781,7 +791,8 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): # Skip world matrix, already in world-space frag.add_uniform('mat4 LWVPSpot[1]', link='_biasLightViewProjectionMatrixSpotArray', included=True) frag.add_uniform('sampler2DShadow shadowMapSpot[1]', included=True) - frag.add_uniform('sampler2D shadowMapSpotTransparent[1]', included=True) + if is_transparent_shadows: + frag.add_uniform('sampler2D shadowMapSpotTransparent[1]', included=True) else: frag.add_uniform('vec2 lightProj', link='_lightPlaneProj', included=True) frag.add_uniform('samplerCubeShadow shadowMapPoint[1]', included=True) @@ -790,10 +801,8 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): frag.write(' wposition, n, vVec, dotNV, pointPos, pointCol, albedo, roughness, specular, f0') if is_shadows: frag.write(', 0, pointBias, receiveShadow') - if '_ShadowMapTransparent' in wrd.world_defs and parse_opacity: + if is_transparent_shadows: frag.write(', opacity != 1.0') - else: - frag.write(', false') if '_Spot' in wrd.world_defs: frag.write(', true, spotData.x, spotData.y, spotDir, spotData.zw, spotRight') if '_VoxelShadow' in wrd.world_defs: @@ -803,9 +812,10 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): if '_MicroShadowing' in wrd.world_defs: frag.write(', occlusion') if '_SSRS' in wrd.world_defs: + frag.add_uniform('sampler2D gbufferD') frag.add_uniform('mat4 invVP', '_inverseViewProjectionMatrix') frag.add_uniform('vec3 eye', '_cameraPosition') - frag.write(', wposition.z, invVP, eye') + frag.write(', gbufferD, invVP, eye') frag.write(');') if '_Clusters' in wrd.world_defs: From 7b17633c283efedfd2093d93aa92e8a266dc211c Mon Sep 17 00:00:00 2001 From: Onek8 Date: Sat, 7 Jun 2025 19:47:12 +0000 Subject: [PATCH 115/136] Update leenkx/blender/lnx/material/make_cluster.py --- leenkx/blender/lnx/material/make_cluster.py | 30 ++++++++++++--------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/leenkx/blender/lnx/material/make_cluster.py b/leenkx/blender/lnx/material/make_cluster.py index 8e40606..abe68f1 100644 --- a/leenkx/blender/lnx/material/make_cluster.py +++ b/leenkx/blender/lnx/material/make_cluster.py @@ -19,6 +19,7 @@ def write(vert: shader.Shader, frag: shader.Shader): parse_opacity = blend or mat_utils.is_transluc(mat_state.material) is_mobile = rpdat.lnx_material_model == 'Mobile' is_shadows = '_ShadowMap' in wrd.world_defs + is_transparent_shadows = '_ShadowMapTransparent' in wrd.world_defs is_shadows_atlas = '_ShadowMapAtlas' in wrd.world_defs is_single_atlas = '_SingleAtlas' in wrd.world_defs @@ -33,14 +34,17 @@ def write(vert: shader.Shader, frag: shader.Shader): if is_shadows_atlas: if not is_single_atlas: frag.add_uniform('sampler2DShadow shadowMapAtlasPoint', included=True) - frag.add_uniform('sampler2D shadowMapAtlasPointTransparent', included=True) + if is_transparent_shadows: + frag.add_uniform('sampler2D shadowMapAtlasPointTransparent', included=True) else: frag.add_uniform('sampler2DShadow shadowMapAtlas', top=True) - frag.add_uniform('sampler2D shadowMapAtlasTransparent', top=True) + if is_transparent_shadows: + frag.add_uniform('sampler2D shadowMapAtlasTransparent', top=True) frag.add_uniform('vec4 pointLightDataArray[maxLightsCluster]', link='_pointLightsAtlasArray', included=True) else: frag.add_uniform('samplerCubeShadow shadowMapPoint[4]', included=True) - frag.add_uniform('samplerCube shadowMapPointTransparent[4]', included=True) + 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') @@ -62,13 +66,16 @@ def write(vert: shader.Shader, frag: shader.Shader): if is_shadows_atlas: if not is_single_atlas: frag.add_uniform('sampler2DShadow shadowMapAtlasSpot', included=True) - frag.add_uniform('sampler2D shadowMapAtlasSpotTransparent', included=True) + if is_transparent_shadows: + frag.add_uniform('sampler2D shadowMapAtlasSpotTransparent', included=True) else: frag.add_uniform('sampler2DShadow shadowMapAtlas', top=True) - frag.add_uniform('sampler2D shadowMapAtlasTransparent', top=True) + if is_transparent_shadows: + frag.add_uniform('sampler2D shadowMapAtlasTransparent', top=True) else: frag.add_uniform('sampler2DShadow shadowMapSpot[4]', included=True) - frag.add_uniform('sampler2D shadowMapSpotTransparent[4]', included=True) + if is_transparent_shadows: + frag.add_uniform('sampler2D shadowMapSpotTransparent[4]', included=True) frag.add_uniform('mat4 LWVPSpotArray[maxLightsCluster]', link='_biasLightWorldViewProjectionMatrixSpotArray', included=True) frag.write('for (int i = 0; i < min(numLights, maxLightsCluster); i++) {') @@ -85,11 +92,9 @@ def write(vert: shader.Shader, frag: shader.Shader): frag.write(' specular,') frag.write(' f0') if is_shadows: - frag.write('\t, li, lightsArray[li * 3 + 2].x, lightsArray[li * 3 + 2].z != 0.0') - if '_ShadowMapTransparent' in wrd.world_defs and parse_opacity: - frag.write(', opacity != 1.0') - else: - frag.write(', false') + frag.write('\t, li, lightsArray[li * 3 + 2].x, lightsArray[li * 3 + 2].z != 0.0') # bias + if is_transparent_shadows: + frag.write('\t, opacity != 1.0') if '_Spot' in wrd.world_defs: frag.write('\t, lightsArray[li * 3 + 2].y != 0.0') frag.write('\t, lightsArray[li * 3 + 2].y') # spot size (cutoff) @@ -102,9 +107,10 @@ def write(vert: shader.Shader, frag: shader.Shader): if '_MicroShadowing' in wrd.world_defs and not is_mobile: frag.write('\t, occlusion') if '_SSRS' in wrd.world_defs: + frag.add_uniform('sampler2D gbufferD') frag.add_uniform('mat4 invVP', '_inverseViewProjectionMatrix') frag.add_uniform('vec3 eye', '_cameraPosition') - frag.write(', wposition.z, invVP, eye') + frag.write(', gbufferD, invVP, eye') frag.write(');') frag.write('}') # for numLights From b89ebfd9c6ddc9e3d7d9d8cea9b8a0f2f0319331 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Thu, 3 Jul 2025 04:34:04 +0000 Subject: [PATCH 116/136] Update leenkx/blender/lnx/material/make_refract.py --- leenkx/blender/lnx/material/make_refract.py | 1 + 1 file changed, 1 insertion(+) diff --git a/leenkx/blender/lnx/material/make_refract.py b/leenkx/blender/lnx/material/make_refract.py index a4c07ea..b30f6b2 100644 --- a/leenkx/blender/lnx/material/make_refract.py +++ b/leenkx/blender/lnx/material/make_refract.py @@ -58,6 +58,7 @@ def make(context_id): frag.write('fragColor[1] = vec4(n.xy, roughness, metallic);') frag.write('fragColor[2] = vec4(ior, opacity, 0.0, 1.0);') + # frag.write('fragColor[2] = vec4(ior, opacity, packFloat2(basecol.r, basecol.g), basecol.b);') make_finalize.make(con_refract) From 0439dde4a81d3fd1ac2fed91907c14ecba33c8e5 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 9 Jul 2025 23:15:54 +0000 Subject: [PATCH 117/136] Update leenkx/Shaders/deferred_light/deferred_light.frag.glsl --- .../deferred_light/deferred_light.frag.glsl | 989 ++++++++---------- 1 file changed, 433 insertions(+), 556 deletions(-) diff --git a/leenkx/Shaders/deferred_light/deferred_light.frag.glsl b/leenkx/Shaders/deferred_light/deferred_light.frag.glsl index 73788ff..a1c01f4 100644 --- a/leenkx/Shaders/deferred_light/deferred_light.frag.glsl +++ b/leenkx/Shaders/deferred_light/deferred_light.frag.glsl @@ -1,586 +1,463 @@ -#version 450 +//Transparent shadow implemented by Yvain Douard with reference: +//https://wickedengine.net/2018/01/easy-transparent-shadow-maps/comment-page-1/ + +#ifndef _SHADOWS_GLSL_ +#define _SHADOWS_GLSL_ #include "compiled.inc" -#include "std/gbuffer.glsl" -#ifdef _Clusters -#include "std/clusters.glsl" -#endif -#ifdef _Irr -#include "std/shirr.glsl" -#endif -#ifdef _SSS -#include "std/sss.glsl" -#endif -#ifdef _SSRS -#include "std/ssrs.glsl" -#endif -uniform sampler2D gbufferD; -uniform sampler2D gbuffer0; -uniform sampler2D gbuffer1; - -#ifdef _gbuffer2 - uniform sampler2D gbuffer2; -#endif -#ifdef _EmissionShaded - uniform sampler2D gbufferEmission; -#endif - -#ifdef _VoxelGI -uniform sampler2D voxels_diffuse; -uniform sampler2D voxels_specular; -#else -#ifdef _VoxelAOvar -uniform sampler2D voxels_ao; -#endif -#endif -#ifdef _VoxelShadow -uniform sampler3D voxels; -uniform sampler3D voxelsSDF; -uniform float clipmaps[10 * voxelgiClipmapCount]; -#endif - -uniform float envmapStrength; -#ifdef _Irr -uniform vec4 shirr[7]; -#endif -#ifdef _Brdf -uniform sampler2D senvmapBrdf; -#endif -#ifdef _Rad -uniform sampler2D senvmapRadiance; -uniform int envmapNumMipmaps; -#endif -#ifdef _EnvCol -uniform vec3 backgroundCol; -#endif - -#ifdef _SSAO -uniform sampler2D ssaotex; -#else -#ifdef _SSGI -uniform sampler2D ssaotex; -#endif -#endif - -#ifdef _SSS -uniform vec2 lightPlane; -#endif - -#ifdef _SSRS -//!uniform mat4 VP; -uniform mat4 invVP; -#endif - -#ifdef _LightIES -//!uniform sampler2D texIES; +#ifdef _CSM +uniform vec4 casData[shadowmapCascades * 4 + 4]; #endif #ifdef _SMSizeUniform -//!uniform vec2 smSizeUniform; +uniform vec2 smSizeUniform; #endif -#ifdef _LTC -//!uniform vec3 lightArea0; -//!uniform vec3 lightArea1; -//!uniform vec3 lightArea2; -//!uniform vec3 lightArea3; -//!uniform sampler2D sltcMat; -//!uniform sampler2D sltcMag; #ifdef _ShadowMap - #ifdef _SinglePoint - //!uniform sampler2DShadow shadowMapSpot[1]; - //!uniform sampler2D shadowMapSpotTransparent[1]; - //!uniform mat4 LWVPSpot[1]; - #endif #ifdef _Clusters - //!uniform sampler2DShadow shadowMapSpot[4]; - //!uniform sampler2D shadowMapSpotTransparent[4]; - //!uniform mat4 LWVPSpotArray[4]; - #endif -#endif -#endif - -uniform vec2 cameraProj; -uniform vec3 eye; -uniform vec3 eyeLook; - -#ifdef _Clusters -uniform vec4 lightsArray[maxLights * 3]; - #ifdef _Spot - uniform vec4 lightsArraySpot[maxLights * 2]; - #endif -uniform sampler2D clustersData; -uniform vec2 cameraPlane; -#endif - -#ifdef _ShadowMap -#ifdef _SinglePoint - #ifdef _Spot - //!uniform sampler2DShadow shadowMapSpot[1]; - #ifdef _ShadowMapTransparent - //!uniform sampler2D shadowMapSpotTransparent[1]; - #endif - //!uniform mat4 LWVPSpot[1]; - #else - //!uniform samplerCubeShadow shadowMapPoint[1]; - #ifdef _ShadowMapTransparent - //!uniform samplerCube shadowMapPointTransparent[1]; - #endif - //!uniform vec2 lightProj; - #endif -#endif -#ifdef _Clusters - #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 - #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; + uniform vec4 pointLightDataArray[maxLightsCluster * 6]; #endif - #endif - #else - //!uniform sampler2DShadow shadowMapSpot[4]; - #ifdef _ShadowMapTransparent - //!uniform sampler2D shadowMapSpotTransparent[4]; - #endif - #endif - //!uniform mat4 LWVPSpotArray[maxLightsCluster]; - #endif -#endif -#endif - -#ifdef _Sun -uniform vec3 sunDir; -uniform vec3 sunCol; - #ifdef _ShadowMap - #ifdef _ShadowMapAtlas - #ifndef _SingleAtlas - uniform sampler2DShadow shadowMapAtlasSun; - #ifdef _ShadowMapTransparent - uniform sampler2D shadowMapAtlasSunTransparent; - #endif - #endif - #else - uniform sampler2DShadow shadowMap; - #ifdef _ShadowMapTransparent - uniform sampler2D shadowMapTransparent; - #endif - #endif - uniform float shadowsBias; - #ifdef _CSM - //!uniform vec4 casData[shadowmapCascades * 4 + 4]; - #else - uniform mat4 LWVP; - #endif - #endif // _ShadowMap -#endif - -#ifdef _SinglePoint // Fast path for single light -uniform vec3 pointPos; -uniform vec3 pointCol; - #ifdef _ShadowMap - uniform float pointBias; - #endif - #ifdef _Spot - uniform vec3 spotDir; - uniform vec3 spotRight; - uniform vec4 spotData; #endif #endif -#ifdef _LightClouds -uniform sampler2D texClouds; -uniform float time; -#endif - -#include "std/light.glsl" - -in vec2 texCoord; -in vec3 viewRay; -out vec4 fragColor; - -void main() { - vec4 g0 = textureLod(gbuffer0, texCoord, 0.0); // Normal.xy, roughness, metallic/matid - - vec3 n; - n.z = 1.0 - abs(g0.x) - abs(g0.y); - n.xy = n.z >= 0.0 ? g0.xy : octahedronWrap(g0.xy); - n = normalize(n); - - float roughness = g0.b; - float metallic; - uint matid; - unpackFloatInt16(g0.a, metallic, matid); - - 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); - - float depth = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0; - vec3 p = getPos(eye, eyeLook, normalize(viewRay), depth, cameraProj); - vec3 v = normalize(eye - p); - float dotNV = max(dot(n, v), 0.0); - -#ifdef _gbuffer2 - vec4 g2 = textureLod(gbuffer2, texCoord, 0.0); -#endif - - -#ifdef _MicroShadowing - occspec.x = mix(1.0, occspec.x, dotNV); // AO Fresnel -#endif - -#ifdef _Brdf - vec2 envBRDF = texelFetch(senvmapBrdf, ivec2(vec2(dotNV, 1.0 - roughness) * 256.0), 0).xy; - vec3 F = f0 * envBRDF.x + envBRDF.y; -#else - vec3 F = f0; -#endif - -#ifndef _VoxelAOvar -#ifndef _VoxelGI - // Envmap -#ifdef _Irr - vec3 envl = shIrradiance(n, shirr); - - #ifdef _gbuffer2 - if (g2.b < 0.5) { - envl = envl; - } else { - envl = vec3(0.0); - } - #endif - - #ifdef _EnvTex - envl /= PI; - #endif -#else - vec3 envl = vec3(0.0); -#endif - -#ifdef _Rad - vec3 reflectionWorld = reflect(-v, n); - float lod = getMipFromRoughness(roughness, envmapNumMipmaps); - vec3 prefilteredColor = textureLod(senvmapRadiance, envMapEquirect(reflectionWorld), lod).rgb; -#endif - -#ifdef _EnvLDR - envl.rgb = pow(envl.rgb, vec3(2.2)); - #ifdef _Rad - prefilteredColor = pow(prefilteredColor, vec3(2.2)); - #endif -#endif - - envl.rgb *= albedo; - -#ifdef _Brdf - envl.rgb *= 1.0 - F; //LV: We should take refracted light into account -#endif - -#ifdef _Rad // Indirect specular - envl.rgb += prefilteredColor * F; //LV: Removed "1.5 * occspec.y". Specular should be weighted only by FV LUT -#else - #ifdef _EnvCol - envl.rgb += backgroundCol * F; //LV: Eh, what's the point of weighting it only by F0? - #endif -#endif - - envl.rgb *= envmapStrength * occspec.x; - - fragColor.rgb = envl; -#endif -#endif - -#ifdef _VoxelGI - fragColor.rgb = textureLod(voxels_diffuse, texCoord, 0.0).rgb * voxelgiDiff; - if(roughness < 1.0 && occspec.y > 0.0) - fragColor.rgb += textureLod(voxels_specular, texCoord, 0.0).rgb * F * voxelgiRefl; -#else -#ifdef _VoxelAOvar - fragColor.rgb = textureLod(voxels_ao, texCoord, 0.0).rgb * voxelgiOcc; -#endif -#endif - - // Show voxels - // vec3 origin = vec3(texCoord * 2.0 - 1.0, 0.99); - // vec3 direction = vec3(0.0, 0.0, -1.0); - // vec4 color = vec4(0.0f); - // for(uint step = 0; step < 400 && color.a < 0.99f; ++step) { - // vec3 point = origin + 0.005 * step * direction; - // color += (1.0f - color.a) * textureLod(voxels, point * 0.5 + 0.5, 0); - // } - // fragColor.rgb += color.rgb; - - // Show SSAO - // fragColor.rgb = texture(ssaotex, texCoord).rrr; - -#ifdef _SSAO - // #ifdef _RTGI - // fragColor.rgb *= textureLod(ssaotex, texCoord, 0.0).rgb; - // #else - fragColor.rgb *= textureLod(ssaotex, texCoord, 0.0).r; - // #endif -#else -#ifdef _SSGI - fragColor.rgb += textureLod(ssaotex, texCoord, 0.0).rgb; -#endif -#endif - -#ifdef _EmissionShadeless - if (matid == 1) { // pure emissive material, color stored in basecol - fragColor.rgb += g1.rgb; - fragColor.a = 1.0; // Mark as opaque - return; +#ifdef _ShadowMapAtlas +// https://www.khronos.org/registry/OpenGL/specs/gl/glspec20.pdf // p:168 +// https://www.gamedev.net/forums/topic/687535-implementing-a-cube-map-lookup-function/5337472/ +vec2 sampleCube(vec3 dir, out int faceIndex) { + vec3 dirAbs = abs(dir); + float ma; + vec2 uv; + if(dirAbs.z >= dirAbs.x && dirAbs.z >= dirAbs.y) { + faceIndex = dir.z < 0.0 ? 5 : 4; + ma = 0.5 / dirAbs.z; + uv = vec2(dir.z < 0.0 ? -dir.x : dir.x, -dir.y); + } + else if(dirAbs.y >= dirAbs.x) { + faceIndex = dir.y < 0.0 ? 3 : 2; + ma = 0.5 / dirAbs.y; + uv = vec2(dir.x, dir.y < 0.0 ? -dir.z : dir.z); } -#endif -#ifdef _EmissionShaded - #ifdef _EmissionShadeless else { - #endif - vec3 emission = textureLod(gbufferEmission, texCoord, 0.0).rgb; - fragColor.rgb += emission; - #ifdef _EmissionShadeless + faceIndex = dir.x < 0.0 ? 1 : 0; + ma = 0.5 / dirAbs.x; + uv = vec2(dir.x < 0.0 ? dir.z : -dir.z, -dir.y); } + // downscale uv a little to hide seams + // transform coordinates from clip space to texture space + #ifndef _FlipY + return uv * 0.9976 * ma + 0.5; + #else + #ifdef HLSL + return uv * 0.9976 * ma + 0.5; + #else + return vec2(uv.x * ma, uv.y * -ma) * 0.9976 + 0.5; + #endif #endif +} #endif -#ifdef _Sun - vec3 sh = normalize(v + sunDir); - float sdotNH = max(0.0, dot(n, sh)); - float sdotVH = max(0.0, dot(v, sh)); - float sdotNL = max(0.0, dot(n, sunDir)); - vec3 svisibility = vec3(1.0); - vec3 sdirect = lambertDiffuseBRDF(albedo, sdotNL) + - specularBRDF(f0, roughness, sdotNL, sdotNH, dotNV, sdotVH) * occspec.y; +vec3 PCF(sampler2DShadow shadowMap, + #ifdef _ShadowMapTransparent + sampler2D shadowMapTransparent, + #endif + const vec2 uv, const float compare, const vec2 smSize + #ifdef _ShadowMapTransparent + , const bool transparent + #endif + ) { + vec3 result = vec3(0.0); + result.x = texture(shadowMap, vec3(uv + (vec2(-1.0, -1.0) / smSize), compare)); + result.x += texture(shadowMap, vec3(uv + (vec2(-1.0, 0.0) / smSize), compare)); + result.x += texture(shadowMap, vec3(uv + (vec2(-1.0, 1.0) / smSize), compare)); + result.x += texture(shadowMap, vec3(uv + (vec2(0.0, -1.0) / smSize), compare)); + result.x += texture(shadowMap, vec3(uv, compare)); + result.x += texture(shadowMap, vec3(uv + (vec2(0.0, 1.0) / smSize), compare)); + result.x += texture(shadowMap, vec3(uv + (vec2(1.0, -1.0) / smSize), compare)); + result.x += texture(shadowMap, vec3(uv + (vec2(1.0, 0.0) / smSize), compare)); + result.x += texture(shadowMap, vec3(uv + (vec2(1.0, 1.0) / smSize), compare)); + result = result.xxx / 9.0; - #ifdef _ShadowMap - #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 + #ifdef _ShadowMapTransparent + if (transparent == false) { + vec4 shadowmap_transparent = texture(shadowMapTransparent, uv); + if (shadowmap_transparent.a < compare) + result *= shadowmap_transparent.rgb; + } + #endif + + return result; +} + +float lpToDepth(vec3 lp, const vec2 lightProj) { + lp = abs(lp); + float zcomp = max(lp.x, max(lp.y, lp.z)); + zcomp = lightProj.x - lightProj.y / zcomp; + return zcomp * 0.5 + 0.5; +} + +vec3 PCFCube(samplerCubeShadow shadowMapCube, + #ifdef _ShadowMapTransparent + samplerCube shadowMapCubeTransparent, + #endif + const vec3 lp, vec3 ml, const float bias, const vec2 lightProj, const vec3 n + #ifdef _ShadowMapTransparent + , const bool transparent + #endif + ) { + const float s = shadowmapCubePcfSize; // TODO: incorrect... + float compare = lpToDepth(lp, lightProj) - bias * 1.5; + ml = ml + n * bias * 20; + #ifdef _InvY + ml.y = -ml.y; + #endif + vec3 result = vec3(0.0); + result.x = texture(shadowMapCube, vec4(ml, compare)); + result.x += texture(shadowMapCube, vec4(ml + vec3(s, s, s), compare)); + result.x += texture(shadowMapCube, vec4(ml + vec3(-s, s, s), compare)); + result.x += texture(shadowMapCube, vec4(ml + vec3(s, -s, s), compare)); + result.x += texture(shadowMapCube, vec4(ml + vec3(s, s, -s), compare)); + result.x += texture(shadowMapCube, vec4(ml + vec3(-s, -s, s), compare)); + result.x += texture(shadowMapCube, vec4(ml + vec3(s, -s, -s), compare)); + result.x += texture(shadowMapCube, vec4(ml + vec3(-s, s, -s), compare)); + result.x += texture(shadowMapCube, vec4(ml + vec3(-s, -s, -s), compare)); + result = result.xxx / 9.0; + + #ifdef _ShadowMapTransparent + if (transparent == false) { + vec4 shadowmap_transparent = texture(shadowMapCubeTransparent, ml); + if (shadowmap_transparent.a < compare) + result *= shadowmap_transparent.rgb; + } + #endif + + return result; +} + +#ifdef _ShadowMapAtlas +// transform "out-of-bounds" coordinates to the correct face/coordinate system +// https://www.khronos.org/opengl/wiki/File:CubeMapAxes.png +vec2 transformOffsetedUV(const int faceIndex, out int newFaceIndex, vec2 uv) { + if (uv.x < 0.0) { + if (faceIndex == 0) { // X+ + newFaceIndex = 4; // Z+ + } + else if (faceIndex == 1) { // X- + newFaceIndex = 5; // Z- + } + else if (faceIndex == 2) { // Y+ + newFaceIndex = 1; // X- + } + else if (faceIndex == 3) { // Y- + newFaceIndex = 1; // X- + } + else if (faceIndex == 4) { // Z+ + newFaceIndex = 1; // X- + } + else { // Z- + newFaceIndex = 0; // X+ + } + uv = vec2(1.0 + uv.x, uv.y); + } + else if (uv.x > 1.0) { + if (faceIndex == 0) { // X+ + newFaceIndex = 5; // Z- + } + else if (faceIndex == 1) { // X- + newFaceIndex = 4; // Z+ + } + else if (faceIndex == 2) { // Y+ + newFaceIndex = 0; // X+ + } + else if (faceIndex == 3) { // Y- + newFaceIndex = 0; // X+ + } + else if (faceIndex == 4) { // Z+ + newFaceIndex = 0; // X+ + } + else { // Z- + newFaceIndex = 1; // X- + } + uv = vec2(1.0 - uv.x, uv.y); + } + else if (uv.y < 0.0) { + if (faceIndex == 0) { // X+ + newFaceIndex = 2; // Y+ + } + else if (faceIndex == 1) { // X- + newFaceIndex = 2; // Y+ + } + else if (faceIndex == 2) { // Y+ + newFaceIndex = 5; // Z- + } + else if (faceIndex == 3) { // Y- + newFaceIndex = 4; // Z+ + } + else if (faceIndex == 4) { // Z+ + newFaceIndex = 2; // Y+ + } + else { // Z- + newFaceIndex = 2; // Y+ + } + uv = vec2(uv.x, 1.0 + uv.y); + } + else if (uv.y > 1.0) { + if (faceIndex == 0) { // X+ + newFaceIndex = 3; // Y- + } + else if (faceIndex == 1) { // X- + newFaceIndex = 3; // Y- + } + else if (faceIndex == 2) { // Y+ + newFaceIndex = 4; // Z+ + } + else if (faceIndex == 3) { // Y- + newFaceIndex = 5; // Z- + } + else if (faceIndex == 4) { // Z+ + newFaceIndex = 3; // Y- + } + else { // Z- + newFaceIndex = 3; // Y- + } + uv = vec2(uv.x, 1.0 - uv.y); + } else { + newFaceIndex = faceIndex; + } + // cover corner cases too + return uv; +} + +vec3 PCFFakeCube(sampler2DShadow shadowMap, + #ifdef _ShadowMapTransparent + sampler2D shadowMapTransparent, + #endif + const vec3 lp, vec3 ml, const float bias, const vec2 lightProj, const vec3 n, const int index + #ifdef _ShadowMapTransparent + , const bool transparent + #endif + ) { + const vec2 smSize = smSizeUniform; // TODO: incorrect... + const float compare = lpToDepth(lp, lightProj) - bias * 1.5; + ml = ml + n * bias * 20; + int faceIndex = 0; + const int lightIndex = index * 6; + const vec2 uv = sampleCube(ml, faceIndex); + vec4 pointLightTile = pointLightDataArray[lightIndex + faceIndex]; // x: tile X offset, y: tile Y offset, z: tile size relative to atlas + vec2 uvtiled = pointLightTile.z * uv + pointLightTile.xy; + #ifdef _FlipY + uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system + #endif + + if (any(lessThan(uvtiled, vec2(0.0))) || any(greaterThan(uvtiled, vec2(1.0)))) { + return vec3(1.0); // Handle edge cases by returning full light + } + + vec3 result = vec3(0.0); + result.x += texture(shadowMap, vec3(uvtiled, compare)); + // soft shadowing + int newFaceIndex = 0; + uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(-1.0, 0.0) / smSize))); + pointLightTile = pointLightDataArray[lightIndex + newFaceIndex]; + uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy; + #ifdef _FlipY + uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system + #endif + result.x += texture(shadowMap, vec3(uvtiled, compare)); + + uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(0.0, -1.0) / smSize))); + pointLightTile = pointLightDataArray[lightIndex + newFaceIndex]; + uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy; + #ifdef _FlipY + uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system + #endif + result.x += texture(shadowMap, vec3(uvtiled, compare)); + + uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(-1.0, -1.0) / smSize))); + pointLightTile = pointLightDataArray[lightIndex + newFaceIndex]; + uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy; + #ifdef _FlipY + uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system + #endif + result.x += texture(shadowMap, vec3(uvtiled, compare)); + + uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(0.0, 1.0) / smSize))); + pointLightTile = pointLightDataArray[lightIndex + newFaceIndex]; + uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy; + #ifdef _FlipY + uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system + #endif + result.x += texture(shadowMap, vec3(uvtiled, compare)); + + uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(1.0, -1.0) / smSize))); + pointLightTile = pointLightDataArray[lightIndex + newFaceIndex]; + uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy; + #ifdef _FlipY + uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system + #endif + result.x += texture(shadowMap, vec3(uvtiled, compare)); + + uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(1.0, 0.0) / smSize))); + pointLightTile = pointLightDataArray[lightIndex + newFaceIndex]; + uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy; + #ifdef _FlipY + uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system + #endif + result.x += texture(shadowMap, vec3(uvtiled, compare)); + + uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(1.0, 1.0) / smSize))); + pointLightTile = pointLightDataArray[lightIndex + newFaceIndex]; + uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy; + #ifdef _FlipY + uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system + #endif + result.x += texture(shadowMap, vec3(uvtiled, compare)); + + result = result.xxx / 9.0; + + pointLightTile = pointLightDataArray[lightIndex + faceIndex]; // x: tile X offset, y: tile Y offset, z: tile size relative to atlas + uvtiled = pointLightTile.z * uv + pointLightTile.xy; + #ifdef _FlipY + uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system + #endif + + #ifdef _ShadowMapTransparent + if (transparent == false) { + vec4 shadowmap_transparent = texture(shadowMapTransparent, uvtiled); + if (shadowmap_transparent.a < compare) + result *= shadowmap_transparent.rgb; + } + #endif + + return result; +} +#endif + +vec3 shadowTest(sampler2DShadow shadowMap, + #ifdef _ShadowMapTransparent + sampler2D shadowMapTransparent, + #endif + const vec3 lPos, const float shadowsBias + #ifdef _ShadowMapTransparent + , const bool transparent + #endif + ) { + #ifdef _SMSizeUniform + vec2 smSize = smSizeUniform; + #else + const vec2 smSize = shadowmapSize; + #endif + if (lPos.x < 0.0 || lPos.y < 0.0 || lPos.x > 1.0 || lPos.y > 1.0) return vec3(1.0); + return PCF(shadowMap, + #ifdef _ShadowMapTransparent + shadowMapTransparent, + #endif + lPos.xy, lPos.z - shadowsBias, smSize + #ifdef _ShadowMapTransparent + , transparent + #endif + ); +} + +#ifdef _CSM +mat4 getCascadeMat(const float d, out int casi, out int casIndex) { + const int c = shadowmapCascades; + // Get cascade index + // TODO: use bounding box slice selection instead of sphere + const vec4 ci = vec4(float(c > 0), float(c > 1), float(c > 2), float(c > 3)); + // int ci; + // if (d < casData[c * 4].x) ci = 0; + // else if (d < casData[c * 4].y) ci = 1 * 4; + // else if (d < casData[c * 4].z) ci = 2 * 4; + // else ci = 3 * 4; + // Splits + vec4 comp = vec4( + float(d > casData[c * 4].x), + float(d > casData[c * 4].y), + float(d > casData[c * 4].z), + float(d > casData[c * 4].w)); + casi = int(min(dot(ci, comp), c)); + // Get cascade mat + casIndex = casi * 4; + return mat4( + casData[casIndex ], + casData[casIndex + 1], + casData[casIndex + 2], + casData[casIndex + 3]); + // if (casIndex == 0) return mat4(casData[0], casData[1], casData[2], casData[3]); + // .. +} + +vec3 shadowTestCascade(sampler2DShadow shadowMap, + #ifdef _ShadowMapTransparent + sampler2D shadowMapTransparent, + #endif + const vec3 eye, const vec3 p, const float shadowsBias + #ifdef _ShadowMapTransparent + , const bool transparent + #endif + ) { + #ifdef _SMSizeUniform + vec2 smSize = smSizeUniform; + #else + const vec2 smSize = shadowmapSize * vec2(shadowmapCascades, 1.0); + #endif + const int c = shadowmapCascades; + float d = distance(eye, p); + int casi; + int casIndex; + mat4 LWVP = getCascadeMat(d, casi, casIndex); + vec4 lPos = LWVP * vec4(p, 1.0); + lPos.xyz /= lPos.w; + + vec3 visibility = vec3(1.0); + if (lPos.w > 0.0) visibility = PCF(shadowMap, + #ifdef _ShadowMapTransparent + shadowMapTransparent, + #endif + lPos.xy, lPos.z - shadowsBias, smSize + #ifdef _ShadowMapTransparent + , transparent + #endif + ); + + // Blend cascade + // https://github.com/TheRealMJP/Shadows + const float blendThres = 0.15; + float nextSplit = casData[c * 4][casi]; + float splitSize = casi == 0 ? nextSplit : nextSplit - casData[c * 4][casi - 1]; + float splitDist = (nextSplit - d) / splitSize; + if (splitDist <= blendThres && casi != c - 1) { + int casIndex2 = casIndex + 4; + mat4 LWVP2 = mat4( + casData[casIndex2 ], + casData[casIndex2 + 1], + casData[casIndex2 + 2], + casData[casIndex2 + 3]); + + vec4 lPos2 = LWVP2 * vec4(p, 1.0); + lPos2.xyz /= lPos2.w; + vec3 visibility2 = vec3(1.0); + if (lPos2.w > 0.0) visibility2 = PCF(shadowMap, #ifdef _ShadowMapTransparent - shadowMap, shadowMapTransparent - #else - shadowMap + shadowMapTransparent, #endif - #endif - , eye, p + n * shadowsBias * 10, shadowsBias + lPos.xy, lPos.z - shadowsBias, smSize #ifdef _ShadowMapTransparent - , false + , transparent #endif ); - #else - vec4 lPos = LWVP * vec4(p + n * shadowsBias * 100, 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 - #ifdef _ShadowMapTransparent - shadowMap, shadowMapTransparent - #else - shadowMap - #endif - #endif - , lPos.xyz / lPos.w, shadowsBias - #ifdef _ShadowMapTransparent - , false - #endif - ); - } - #endif - #endif - #ifdef _VoxelShadow - svisibility *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, sunDir, clipmaps, gl_FragCoord.xy, -g2.rg).r) * voxelgiShad; - #endif - - #ifdef _SSRS - // vec2 coords = getProjectedCoord(hitCoord); - // vec2 deltaCoords = abs(vec2(0.5, 0.5) - coords.xy); - // float screenEdgeFactor = clamp(1.0 - (deltaCoords.x + deltaCoords.y), 0.0, 1.0); - svisibility *= traceShadowSS(sunDir, p, gbufferD, invVP, eye); - #endif - - #ifdef _LightClouds - svisibility *= textureLod(texClouds, vec2(p.xy / 100.0 + time / 80.0), 0.0).r * dot(n, vec3(0,0,1)); - #endif - - #ifdef _MicroShadowing - // See https://advances.realtimerendering.com/other/2016/naughty_dog/NaughtyDog_TechArt_Final.pdf - svisibility *= clamp(sdotNL + 2.0 * occspec.x * occspec.x - 1.0, 0.0, 1.0); - #endif - - fragColor.rgb += sdirect * sunCol * svisibility; - -// #ifdef _Hair // Aniso -// if (matid == 2) { -// const float shinyParallel = roughness; -// const float shinyPerpendicular = 0.1; -// const vec3 v = vec3(0.99146, 0.11664, 0.05832); -// vec3 T = abs(dot(n, v)) > 0.99999 ? cross(n, vec3(0.0, 1.0, 0.0)) : cross(n, v); -// fragColor.rgb = orenNayarDiffuseBRDF(albedo, roughness, dotNV, dotNL, dotVH) + wardSpecular(n, h, dotNL, dotNV, dotNH, T, shinyParallel, shinyPerpendicular) * spec; -// } -// #endif - - #ifdef _SSS - if (matid == 2) { - #ifdef _CSM - int casi, casindex; - mat4 LWVP = getCascadeMat(distance(eye, p), casi, casindex); - #endif - fragColor.rgb += fragColor.rgb * SSSSTransmittance( - LWVP, p, n, sunDir, lightPlane.y, - #ifdef _ShadowMapAtlas - #ifndef _SingleAtlas - shadowMapAtlasSun - #else - shadowMapAtlas - #endif - #else - shadowMap - #endif - );//TODO implement transparent shadowmaps into the SSSSTransmittance() + float lerpAmt = smoothstep(0.0, blendThres, splitDist); + return mix(visibility2, visibility, lerpAmt); } - #endif - -#endif // _Sun - -#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 - #endif - #ifdef _VoxelShadow - , voxels, voxelsSDF, clipmaps, -g2.rg - #endif - #ifdef _MicroShadowing - , occspec.x - #endif - #ifdef _SSRS - , gbufferD, invVP, eye - #endif - ); - - #ifdef _Spot - #ifdef _SSS - if (matid == 2) fragColor.rgb += fragColor.rgb * SSSSTransmittance(LWVPSpot[0], p, n, normalize(pointPos - p), lightPlane.y, shadowMapSpot[0]);//TODO implement transparent shadowmaps into the SSSSTransmittance() - #endif - #endif - -#endif - -#ifdef _Clusters - float viewz = linearize(depth * 0.5 + 0.5, cameraProj); - int clusterI = getClusterI(texCoord, viewz, cameraPlane); - int numLights = int(texelFetch(clustersData, ivec2(clusterI, 0), 0).r * 255); - - #ifdef HLSL - viewz += textureLod(clustersData, vec2(0.0), 0.0).r * 1e-9; // TODO: krafix bug, needs to generate sampler - #endif - - #ifdef _Spot - int numSpots = int(texelFetch(clustersData, ivec2(clusterI, 1 + maxLightsCluster), 0).r * 255); - int numPoints = numLights - numSpots; - #endif - - for (int i = 0; i < min(numLights, maxLightsCluster); i++) { - int li = int(texelFetch(clustersData, ivec2(clusterI, i + 1), 0).r * 255); - fragColor.rgb += sampleLight( - p, - n, - v, - dotNV, - lightsArray[li * 3].xyz, // lp - lightsArray[li * 3 + 1].xyz, // lightCol - albedo, - roughness, - occspec.y, - f0 - #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 * 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 - #ifdef _VoxelShadow - , voxels, voxelsSDF, clipmaps, -g2.rg - #endif - #ifdef _MicroShadowing - , occspec.x - #endif - #ifdef _SSRS - , gbufferD, invVP, eye - #endif - ); - } -#endif // _Clusters - fragColor.a = 1.0; // Mark as opaque + return visibility; + // Visualize cascades + // if (ci == 0) albedo.rgb = vec3(1.0, 0.0, 0.0); + // if (ci == 4) albedo.rgb = vec3(0.0, 1.0, 0.0); + // if (ci == 8) albedo.rgb = vec3(0.0, 0.0, 1.0); + // if (ci == 12) albedo.rgb = vec3(1.0, 1.0, 0.0); } +#endif +#endif \ No newline at end of file From 9e2b6014457840048aeeae2c8cafb6b05d1d29c6 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 9 Jul 2025 23:16:54 +0000 Subject: [PATCH 118/136] revert 0439dde4a81d3fd1ac2fed91907c14ecba33c8e5 revert Update leenkx/Shaders/deferred_light/deferred_light.frag.glsl --- .../deferred_light/deferred_light.frag.glsl | 973 ++++++++++-------- 1 file changed, 548 insertions(+), 425 deletions(-) diff --git a/leenkx/Shaders/deferred_light/deferred_light.frag.glsl b/leenkx/Shaders/deferred_light/deferred_light.frag.glsl index a1c01f4..73788ff 100644 --- a/leenkx/Shaders/deferred_light/deferred_light.frag.glsl +++ b/leenkx/Shaders/deferred_light/deferred_light.frag.glsl @@ -1,463 +1,586 @@ -//Transparent shadow implemented by Yvain Douard with reference: -//https://wickedengine.net/2018/01/easy-transparent-shadow-maps/comment-page-1/ - -#ifndef _SHADOWS_GLSL_ -#define _SHADOWS_GLSL_ +#version 450 #include "compiled.inc" +#include "std/gbuffer.glsl" +#ifdef _Clusters +#include "std/clusters.glsl" +#endif +#ifdef _Irr +#include "std/shirr.glsl" +#endif +#ifdef _SSS +#include "std/sss.glsl" +#endif +#ifdef _SSRS +#include "std/ssrs.glsl" +#endif -#ifdef _CSM -uniform vec4 casData[shadowmapCascades * 4 + 4]; +uniform sampler2D gbufferD; +uniform sampler2D gbuffer0; +uniform sampler2D gbuffer1; + +#ifdef _gbuffer2 + uniform sampler2D gbuffer2; +#endif +#ifdef _EmissionShaded + uniform sampler2D gbufferEmission; +#endif + +#ifdef _VoxelGI +uniform sampler2D voxels_diffuse; +uniform sampler2D voxels_specular; +#else +#ifdef _VoxelAOvar +uniform sampler2D voxels_ao; +#endif +#endif +#ifdef _VoxelShadow +uniform sampler3D voxels; +uniform sampler3D voxelsSDF; +uniform float clipmaps[10 * voxelgiClipmapCount]; +#endif + +uniform float envmapStrength; +#ifdef _Irr +uniform vec4 shirr[7]; +#endif +#ifdef _Brdf +uniform sampler2D senvmapBrdf; +#endif +#ifdef _Rad +uniform sampler2D senvmapRadiance; +uniform int envmapNumMipmaps; +#endif +#ifdef _EnvCol +uniform vec3 backgroundCol; +#endif + +#ifdef _SSAO +uniform sampler2D ssaotex; +#else +#ifdef _SSGI +uniform sampler2D ssaotex; +#endif +#endif + +#ifdef _SSS +uniform vec2 lightPlane; +#endif + +#ifdef _SSRS +//!uniform mat4 VP; +uniform mat4 invVP; +#endif + +#ifdef _LightIES +//!uniform sampler2D texIES; #endif #ifdef _SMSizeUniform -uniform vec2 smSizeUniform; +//!uniform vec2 smSizeUniform; +#endif + +#ifdef _LTC +//!uniform vec3 lightArea0; +//!uniform vec3 lightArea1; +//!uniform vec3 lightArea2; +//!uniform vec3 lightArea3; +//!uniform sampler2D sltcMat; +//!uniform sampler2D sltcMag; +#ifdef _ShadowMap + #ifdef _SinglePoint + //!uniform sampler2DShadow shadowMapSpot[1]; + //!uniform sampler2D shadowMapSpotTransparent[1]; + //!uniform mat4 LWVPSpot[1]; + #endif + #ifdef _Clusters + //!uniform sampler2DShadow shadowMapSpot[4]; + //!uniform sampler2D shadowMapSpotTransparent[4]; + //!uniform mat4 LWVPSpotArray[4]; + #endif +#endif +#endif + +uniform vec2 cameraProj; +uniform vec3 eye; +uniform vec3 eyeLook; + +#ifdef _Clusters +uniform vec4 lightsArray[maxLights * 3]; + #ifdef _Spot + uniform vec4 lightsArraySpot[maxLights * 2]; + #endif +uniform sampler2D clustersData; +uniform vec2 cameraPlane; #endif #ifdef _ShadowMap - #ifdef _Clusters +#ifdef _SinglePoint + #ifdef _Spot + //!uniform sampler2DShadow shadowMapSpot[1]; + #ifdef _ShadowMapTransparent + //!uniform sampler2D shadowMapSpotTransparent[1]; + #endif + //!uniform mat4 LWVPSpot[1]; + #else + //!uniform samplerCubeShadow shadowMapPoint[1]; + #ifdef _ShadowMapTransparent + //!uniform samplerCube shadowMapPointTransparent[1]; + #endif + //!uniform vec2 lightProj; + #endif +#endif +#ifdef _Clusters + #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 + #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 - uniform vec4 pointLightDataArray[maxLightsCluster * 6]; + #ifndef _SingleAtlas + //!uniform sampler2DShadow shadowMapAtlasSpot; + #ifdef _ShadowMapTransparent + //!uniform sampler2D shadowMapAtlasSpotTransparent; + #endif #endif - #endif -#endif - -#ifdef _ShadowMapAtlas -// https://www.khronos.org/registry/OpenGL/specs/gl/glspec20.pdf // p:168 -// https://www.gamedev.net/forums/topic/687535-implementing-a-cube-map-lookup-function/5337472/ -vec2 sampleCube(vec3 dir, out int faceIndex) { - vec3 dirAbs = abs(dir); - float ma; - vec2 uv; - if(dirAbs.z >= dirAbs.x && dirAbs.z >= dirAbs.y) { - faceIndex = dir.z < 0.0 ? 5 : 4; - ma = 0.5 / dirAbs.z; - uv = vec2(dir.z < 0.0 ? -dir.x : dir.x, -dir.y); - } - else if(dirAbs.y >= dirAbs.x) { - faceIndex = dir.y < 0.0 ? 3 : 2; - ma = 0.5 / dirAbs.y; - uv = vec2(dir.x, dir.y < 0.0 ? -dir.z : dir.z); - } - else { - faceIndex = dir.x < 0.0 ? 1 : 0; - ma = 0.5 / dirAbs.x; - uv = vec2(dir.x < 0.0 ? dir.z : -dir.z, -dir.y); - } - // downscale uv a little to hide seams - // transform coordinates from clip space to texture space - #ifndef _FlipY - return uv * 0.9976 * ma + 0.5; - #else - #ifdef HLSL - return uv * 0.9976 * ma + 0.5; #else - return vec2(uv.x * ma, uv.y * -ma) * 0.9976 + 0.5; + //!uniform sampler2DShadow shadowMapSpot[4]; + #ifdef _ShadowMapTransparent + //!uniform sampler2D shadowMapSpotTransparent[4]; #endif + #endif + //!uniform mat4 LWVPSpotArray[maxLightsCluster]; #endif -} +#endif #endif -vec3 PCF(sampler2DShadow shadowMap, - #ifdef _ShadowMapTransparent - sampler2D shadowMapTransparent, - #endif - const vec2 uv, const float compare, const vec2 smSize - #ifdef _ShadowMapTransparent - , const bool transparent - #endif - ) { - vec3 result = vec3(0.0); - result.x = texture(shadowMap, vec3(uv + (vec2(-1.0, -1.0) / smSize), compare)); - result.x += texture(shadowMap, vec3(uv + (vec2(-1.0, 0.0) / smSize), compare)); - result.x += texture(shadowMap, vec3(uv + (vec2(-1.0, 1.0) / smSize), compare)); - result.x += texture(shadowMap, vec3(uv + (vec2(0.0, -1.0) / smSize), compare)); - result.x += texture(shadowMap, vec3(uv, compare)); - result.x += texture(shadowMap, vec3(uv + (vec2(0.0, 1.0) / smSize), compare)); - result.x += texture(shadowMap, vec3(uv + (vec2(1.0, -1.0) / smSize), compare)); - result.x += texture(shadowMap, vec3(uv + (vec2(1.0, 0.0) / smSize), compare)); - result.x += texture(shadowMap, vec3(uv + (vec2(1.0, 1.0) / smSize), compare)); - result = result.xxx / 9.0; - +#ifdef _Sun +uniform vec3 sunDir; +uniform vec3 sunCol; + #ifdef _ShadowMap + #ifdef _ShadowMapAtlas + #ifndef _SingleAtlas + uniform sampler2DShadow shadowMapAtlasSun; #ifdef _ShadowMapTransparent - if (transparent == false) { - vec4 shadowmap_transparent = texture(shadowMapTransparent, uv); - if (shadowmap_transparent.a < compare) - result *= shadowmap_transparent.rgb; - } + uniform sampler2D shadowMapAtlasSunTransparent; #endif - - return result; -} - -float lpToDepth(vec3 lp, const vec2 lightProj) { - lp = abs(lp); - float zcomp = max(lp.x, max(lp.y, lp.z)); - zcomp = lightProj.x - lightProj.y / zcomp; - return zcomp * 0.5 + 0.5; -} - -vec3 PCFCube(samplerCubeShadow shadowMapCube, - #ifdef _ShadowMapTransparent - samplerCube shadowMapCubeTransparent, - #endif - const vec3 lp, vec3 ml, const float bias, const vec2 lightProj, const vec3 n - #ifdef _ShadowMapTransparent - , const bool transparent - #endif - ) { - const float s = shadowmapCubePcfSize; // TODO: incorrect... - float compare = lpToDepth(lp, lightProj) - bias * 1.5; - ml = ml + n * bias * 20; - #ifdef _InvY - ml.y = -ml.y; #endif - vec3 result = vec3(0.0); - result.x = texture(shadowMapCube, vec4(ml, compare)); - result.x += texture(shadowMapCube, vec4(ml + vec3(s, s, s), compare)); - result.x += texture(shadowMapCube, vec4(ml + vec3(-s, s, s), compare)); - result.x += texture(shadowMapCube, vec4(ml + vec3(s, -s, s), compare)); - result.x += texture(shadowMapCube, vec4(ml + vec3(s, s, -s), compare)); - result.x += texture(shadowMapCube, vec4(ml + vec3(-s, -s, s), compare)); - result.x += texture(shadowMapCube, vec4(ml + vec3(s, -s, -s), compare)); - result.x += texture(shadowMapCube, vec4(ml + vec3(-s, s, -s), compare)); - result.x += texture(shadowMapCube, vec4(ml + vec3(-s, -s, -s), compare)); - result = result.xxx / 9.0; - + #else + uniform sampler2DShadow shadowMap; #ifdef _ShadowMapTransparent - if (transparent == false) { - vec4 shadowmap_transparent = texture(shadowMapCubeTransparent, ml); - if (shadowmap_transparent.a < compare) - result *= shadowmap_transparent.rgb; - } + uniform sampler2D shadowMapTransparent; #endif - - return result; -} - -#ifdef _ShadowMapAtlas -// transform "out-of-bounds" coordinates to the correct face/coordinate system -// https://www.khronos.org/opengl/wiki/File:CubeMapAxes.png -vec2 transformOffsetedUV(const int faceIndex, out int newFaceIndex, vec2 uv) { - if (uv.x < 0.0) { - if (faceIndex == 0) { // X+ - newFaceIndex = 4; // Z+ - } - else if (faceIndex == 1) { // X- - newFaceIndex = 5; // Z- - } - else if (faceIndex == 2) { // Y+ - newFaceIndex = 1; // X- - } - else if (faceIndex == 3) { // Y- - newFaceIndex = 1; // X- - } - else if (faceIndex == 4) { // Z+ - newFaceIndex = 1; // X- - } - else { // Z- - newFaceIndex = 0; // X+ - } - uv = vec2(1.0 + uv.x, uv.y); - } - else if (uv.x > 1.0) { - if (faceIndex == 0) { // X+ - newFaceIndex = 5; // Z- - } - else if (faceIndex == 1) { // X- - newFaceIndex = 4; // Z+ - } - else if (faceIndex == 2) { // Y+ - newFaceIndex = 0; // X+ - } - else if (faceIndex == 3) { // Y- - newFaceIndex = 0; // X+ - } - else if (faceIndex == 4) { // Z+ - newFaceIndex = 0; // X+ - } - else { // Z- - newFaceIndex = 1; // X- - } - uv = vec2(1.0 - uv.x, uv.y); - } - else if (uv.y < 0.0) { - if (faceIndex == 0) { // X+ - newFaceIndex = 2; // Y+ - } - else if (faceIndex == 1) { // X- - newFaceIndex = 2; // Y+ - } - else if (faceIndex == 2) { // Y+ - newFaceIndex = 5; // Z- - } - else if (faceIndex == 3) { // Y- - newFaceIndex = 4; // Z+ - } - else if (faceIndex == 4) { // Z+ - newFaceIndex = 2; // Y+ - } - else { // Z- - newFaceIndex = 2; // Y+ - } - uv = vec2(uv.x, 1.0 + uv.y); - } - else if (uv.y > 1.0) { - if (faceIndex == 0) { // X+ - newFaceIndex = 3; // Y- - } - else if (faceIndex == 1) { // X- - newFaceIndex = 3; // Y- - } - else if (faceIndex == 2) { // Y+ - newFaceIndex = 4; // Z+ - } - else if (faceIndex == 3) { // Y- - newFaceIndex = 5; // Z- - } - else if (faceIndex == 4) { // Z+ - newFaceIndex = 3; // Y- - } - else { // Z- - newFaceIndex = 3; // Y- - } - uv = vec2(uv.x, 1.0 - uv.y); - } else { - newFaceIndex = faceIndex; - } - // cover corner cases too - return uv; -} - -vec3 PCFFakeCube(sampler2DShadow shadowMap, - #ifdef _ShadowMapTransparent - sampler2D shadowMapTransparent, - #endif - const vec3 lp, vec3 ml, const float bias, const vec2 lightProj, const vec3 n, const int index - #ifdef _ShadowMapTransparent - , const bool transparent - #endif - ) { - const vec2 smSize = smSizeUniform; // TODO: incorrect... - const float compare = lpToDepth(lp, lightProj) - bias * 1.5; - ml = ml + n * bias * 20; - int faceIndex = 0; - const int lightIndex = index * 6; - const vec2 uv = sampleCube(ml, faceIndex); - vec4 pointLightTile = pointLightDataArray[lightIndex + faceIndex]; // x: tile X offset, y: tile Y offset, z: tile size relative to atlas - vec2 uvtiled = pointLightTile.z * uv + pointLightTile.xy; - #ifdef _FlipY - uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system #endif - - if (any(lessThan(uvtiled, vec2(0.0))) || any(greaterThan(uvtiled, vec2(1.0)))) { - return vec3(1.0); // Handle edge cases by returning full light - } - - vec3 result = vec3(0.0); - result.x += texture(shadowMap, vec3(uvtiled, compare)); - // soft shadowing - int newFaceIndex = 0; - uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(-1.0, 0.0) / smSize))); - pointLightTile = pointLightDataArray[lightIndex + newFaceIndex]; - uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy; - #ifdef _FlipY - uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system + uniform float shadowsBias; + #ifdef _CSM + //!uniform vec4 casData[shadowmapCascades * 4 + 4]; + #else + uniform mat4 LWVP; #endif - result.x += texture(shadowMap, vec3(uvtiled, compare)); - - uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(0.0, -1.0) / smSize))); - pointLightTile = pointLightDataArray[lightIndex + newFaceIndex]; - uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy; - #ifdef _FlipY - uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system - #endif - result.x += texture(shadowMap, vec3(uvtiled, compare)); - - uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(-1.0, -1.0) / smSize))); - pointLightTile = pointLightDataArray[lightIndex + newFaceIndex]; - uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy; - #ifdef _FlipY - uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system - #endif - result.x += texture(shadowMap, vec3(uvtiled, compare)); - - uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(0.0, 1.0) / smSize))); - pointLightTile = pointLightDataArray[lightIndex + newFaceIndex]; - uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy; - #ifdef _FlipY - uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system - #endif - result.x += texture(shadowMap, vec3(uvtiled, compare)); - - uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(1.0, -1.0) / smSize))); - pointLightTile = pointLightDataArray[lightIndex + newFaceIndex]; - uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy; - #ifdef _FlipY - uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system - #endif - result.x += texture(shadowMap, vec3(uvtiled, compare)); - - uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(1.0, 0.0) / smSize))); - pointLightTile = pointLightDataArray[lightIndex + newFaceIndex]; - uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy; - #ifdef _FlipY - uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system - #endif - result.x += texture(shadowMap, vec3(uvtiled, compare)); - - uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(1.0, 1.0) / smSize))); - pointLightTile = pointLightDataArray[lightIndex + newFaceIndex]; - uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy; - #ifdef _FlipY - uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system - #endif - result.x += texture(shadowMap, vec3(uvtiled, compare)); - - result = result.xxx / 9.0; - - pointLightTile = pointLightDataArray[lightIndex + faceIndex]; // x: tile X offset, y: tile Y offset, z: tile size relative to atlas - uvtiled = pointLightTile.z * uv + pointLightTile.xy; - #ifdef _FlipY - uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system - #endif - - #ifdef _ShadowMapTransparent - if (transparent == false) { - vec4 shadowmap_transparent = texture(shadowMapTransparent, uvtiled); - if (shadowmap_transparent.a < compare) - result *= shadowmap_transparent.rgb; - } - #endif - - return result; -} + #endif // _ShadowMap #endif -vec3 shadowTest(sampler2DShadow shadowMap, - #ifdef _ShadowMapTransparent - sampler2D shadowMapTransparent, - #endif - const vec3 lPos, const float shadowsBias - #ifdef _ShadowMapTransparent - , const bool transparent - #endif - ) { - #ifdef _SMSizeUniform - vec2 smSize = smSizeUniform; - #else - const vec2 smSize = shadowmapSize; +#ifdef _SinglePoint // Fast path for single light +uniform vec3 pointPos; +uniform vec3 pointCol; + #ifdef _ShadowMap + uniform float pointBias; #endif - if (lPos.x < 0.0 || lPos.y < 0.0 || lPos.x > 1.0 || lPos.y > 1.0) return vec3(1.0); - return PCF(shadowMap, - #ifdef _ShadowMapTransparent - shadowMapTransparent, - #endif - lPos.xy, lPos.z - shadowsBias, smSize - #ifdef _ShadowMapTransparent - , transparent - #endif - ); -} - -#ifdef _CSM -mat4 getCascadeMat(const float d, out int casi, out int casIndex) { - const int c = shadowmapCascades; - // Get cascade index - // TODO: use bounding box slice selection instead of sphere - const vec4 ci = vec4(float(c > 0), float(c > 1), float(c > 2), float(c > 3)); - // int ci; - // if (d < casData[c * 4].x) ci = 0; - // else if (d < casData[c * 4].y) ci = 1 * 4; - // else if (d < casData[c * 4].z) ci = 2 * 4; - // else ci = 3 * 4; - // Splits - vec4 comp = vec4( - float(d > casData[c * 4].x), - float(d > casData[c * 4].y), - float(d > casData[c * 4].z), - float(d > casData[c * 4].w)); - casi = int(min(dot(ci, comp), c)); - // Get cascade mat - casIndex = casi * 4; - return mat4( - casData[casIndex ], - casData[casIndex + 1], - casData[casIndex + 2], - casData[casIndex + 3]); - // if (casIndex == 0) return mat4(casData[0], casData[1], casData[2], casData[3]); - // .. -} - -vec3 shadowTestCascade(sampler2DShadow shadowMap, - #ifdef _ShadowMapTransparent - sampler2D shadowMapTransparent, - #endif - const vec3 eye, const vec3 p, const float shadowsBias - #ifdef _ShadowMapTransparent - , const bool transparent - #endif - ) { - #ifdef _SMSizeUniform - vec2 smSize = smSizeUniform; - #else - const vec2 smSize = shadowmapSize * vec2(shadowmapCascades, 1.0); + #ifdef _Spot + uniform vec3 spotDir; + uniform vec3 spotRight; + uniform vec4 spotData; #endif - const int c = shadowmapCascades; - float d = distance(eye, p); - int casi; - int casIndex; - mat4 LWVP = getCascadeMat(d, casi, casIndex); - vec4 lPos = LWVP * vec4(p, 1.0); - lPos.xyz /= lPos.w; +#endif - vec3 visibility = vec3(1.0); - if (lPos.w > 0.0) visibility = PCF(shadowMap, - #ifdef _ShadowMapTransparent - shadowMapTransparent, - #endif - lPos.xy, lPos.z - shadowsBias, smSize - #ifdef _ShadowMapTransparent - , transparent - #endif - ); +#ifdef _LightClouds +uniform sampler2D texClouds; +uniform float time; +#endif - // Blend cascade - // https://github.com/TheRealMJP/Shadows - const float blendThres = 0.15; - float nextSplit = casData[c * 4][casi]; - float splitSize = casi == 0 ? nextSplit : nextSplit - casData[c * 4][casi - 1]; - float splitDist = (nextSplit - d) / splitSize; - if (splitDist <= blendThres && casi != c - 1) { - int casIndex2 = casIndex + 4; - mat4 LWVP2 = mat4( - casData[casIndex2 ], - casData[casIndex2 + 1], - casData[casIndex2 + 2], - casData[casIndex2 + 3]); +#include "std/light.glsl" - vec4 lPos2 = LWVP2 * vec4(p, 1.0); - lPos2.xyz /= lPos2.w; - vec3 visibility2 = vec3(1.0); - if (lPos2.w > 0.0) visibility2 = PCF(shadowMap, +in vec2 texCoord; +in vec3 viewRay; +out vec4 fragColor; + +void main() { + vec4 g0 = textureLod(gbuffer0, texCoord, 0.0); // Normal.xy, roughness, metallic/matid + + vec3 n; + n.z = 1.0 - abs(g0.x) - abs(g0.y); + n.xy = n.z >= 0.0 ? g0.xy : octahedronWrap(g0.xy); + n = normalize(n); + + float roughness = g0.b; + float metallic; + uint matid; + unpackFloatInt16(g0.a, metallic, matid); + + 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); + + float depth = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0; + vec3 p = getPos(eye, eyeLook, normalize(viewRay), depth, cameraProj); + vec3 v = normalize(eye - p); + float dotNV = max(dot(n, v), 0.0); + +#ifdef _gbuffer2 + vec4 g2 = textureLod(gbuffer2, texCoord, 0.0); +#endif + + +#ifdef _MicroShadowing + occspec.x = mix(1.0, occspec.x, dotNV); // AO Fresnel +#endif + +#ifdef _Brdf + vec2 envBRDF = texelFetch(senvmapBrdf, ivec2(vec2(dotNV, 1.0 - roughness) * 256.0), 0).xy; + vec3 F = f0 * envBRDF.x + envBRDF.y; +#else + vec3 F = f0; +#endif + +#ifndef _VoxelAOvar +#ifndef _VoxelGI + // Envmap +#ifdef _Irr + vec3 envl = shIrradiance(n, shirr); + + #ifdef _gbuffer2 + if (g2.b < 0.5) { + envl = envl; + } else { + envl = vec3(0.0); + } + #endif + + #ifdef _EnvTex + envl /= PI; + #endif +#else + vec3 envl = vec3(0.0); +#endif + +#ifdef _Rad + vec3 reflectionWorld = reflect(-v, n); + float lod = getMipFromRoughness(roughness, envmapNumMipmaps); + vec3 prefilteredColor = textureLod(senvmapRadiance, envMapEquirect(reflectionWorld), lod).rgb; +#endif + +#ifdef _EnvLDR + envl.rgb = pow(envl.rgb, vec3(2.2)); + #ifdef _Rad + prefilteredColor = pow(prefilteredColor, vec3(2.2)); + #endif +#endif + + envl.rgb *= albedo; + +#ifdef _Brdf + envl.rgb *= 1.0 - F; //LV: We should take refracted light into account +#endif + +#ifdef _Rad // Indirect specular + envl.rgb += prefilteredColor * F; //LV: Removed "1.5 * occspec.y". Specular should be weighted only by FV LUT +#else + #ifdef _EnvCol + envl.rgb += backgroundCol * F; //LV: Eh, what's the point of weighting it only by F0? + #endif +#endif + + envl.rgb *= envmapStrength * occspec.x; + + fragColor.rgb = envl; +#endif +#endif + +#ifdef _VoxelGI + fragColor.rgb = textureLod(voxels_diffuse, texCoord, 0.0).rgb * voxelgiDiff; + if(roughness < 1.0 && occspec.y > 0.0) + fragColor.rgb += textureLod(voxels_specular, texCoord, 0.0).rgb * F * voxelgiRefl; +#else +#ifdef _VoxelAOvar + fragColor.rgb = textureLod(voxels_ao, texCoord, 0.0).rgb * voxelgiOcc; +#endif +#endif + + // Show voxels + // vec3 origin = vec3(texCoord * 2.0 - 1.0, 0.99); + // vec3 direction = vec3(0.0, 0.0, -1.0); + // vec4 color = vec4(0.0f); + // for(uint step = 0; step < 400 && color.a < 0.99f; ++step) { + // vec3 point = origin + 0.005 * step * direction; + // color += (1.0f - color.a) * textureLod(voxels, point * 0.5 + 0.5, 0); + // } + // fragColor.rgb += color.rgb; + + // Show SSAO + // fragColor.rgb = texture(ssaotex, texCoord).rrr; + +#ifdef _SSAO + // #ifdef _RTGI + // fragColor.rgb *= textureLod(ssaotex, texCoord, 0.0).rgb; + // #else + fragColor.rgb *= textureLod(ssaotex, texCoord, 0.0).r; + // #endif +#else +#ifdef _SSGI + fragColor.rgb += textureLod(ssaotex, texCoord, 0.0).rgb; +#endif +#endif + +#ifdef _EmissionShadeless + if (matid == 1) { // pure emissive material, color stored in basecol + fragColor.rgb += g1.rgb; + fragColor.a = 1.0; // Mark as opaque + return; + } +#endif +#ifdef _EmissionShaded + #ifdef _EmissionShadeless + else { + #endif + vec3 emission = textureLod(gbufferEmission, texCoord, 0.0).rgb; + fragColor.rgb += emission; + #ifdef _EmissionShadeless + } + #endif +#endif + +#ifdef _Sun + vec3 sh = normalize(v + sunDir); + float sdotNH = max(0.0, dot(n, sh)); + float sdotVH = max(0.0, dot(v, sh)); + float sdotNL = max(0.0, dot(n, sunDir)); + vec3 svisibility = vec3(1.0); + vec3 sdirect = lambertDiffuseBRDF(albedo, sdotNL) + + specularBRDF(f0, roughness, sdotNL, sdotNH, dotNV, sdotVH) * occspec.y; + + #ifdef _ShadowMap + #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 #ifdef _ShadowMapTransparent - shadowMapTransparent, + shadowMap, shadowMapTransparent + #else + shadowMap #endif - lPos.xy, lPos.z - shadowsBias, smSize + #endif + , eye, p + n * shadowsBias * 10, shadowsBias #ifdef _ShadowMapTransparent - , transparent + , false #endif ); + #else + vec4 lPos = LWVP * vec4(p + n * shadowsBias * 100, 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 + #ifdef _ShadowMapTransparent + shadowMap, shadowMapTransparent + #else + shadowMap + #endif + #endif + , lPos.xyz / lPos.w, shadowsBias + #ifdef _ShadowMapTransparent + , false + #endif + ); + } + #endif + #endif - float lerpAmt = smoothstep(0.0, blendThres, splitDist); - return mix(visibility2, visibility, lerpAmt); + #ifdef _VoxelShadow + svisibility *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, sunDir, clipmaps, gl_FragCoord.xy, -g2.rg).r) * voxelgiShad; + #endif + + #ifdef _SSRS + // vec2 coords = getProjectedCoord(hitCoord); + // vec2 deltaCoords = abs(vec2(0.5, 0.5) - coords.xy); + // float screenEdgeFactor = clamp(1.0 - (deltaCoords.x + deltaCoords.y), 0.0, 1.0); + svisibility *= traceShadowSS(sunDir, p, gbufferD, invVP, eye); + #endif + + #ifdef _LightClouds + svisibility *= textureLod(texClouds, vec2(p.xy / 100.0 + time / 80.0), 0.0).r * dot(n, vec3(0,0,1)); + #endif + + #ifdef _MicroShadowing + // See https://advances.realtimerendering.com/other/2016/naughty_dog/NaughtyDog_TechArt_Final.pdf + svisibility *= clamp(sdotNL + 2.0 * occspec.x * occspec.x - 1.0, 0.0, 1.0); + #endif + + fragColor.rgb += sdirect * sunCol * svisibility; + +// #ifdef _Hair // Aniso +// if (matid == 2) { +// const float shinyParallel = roughness; +// const float shinyPerpendicular = 0.1; +// const vec3 v = vec3(0.99146, 0.11664, 0.05832); +// vec3 T = abs(dot(n, v)) > 0.99999 ? cross(n, vec3(0.0, 1.0, 0.0)) : cross(n, v); +// fragColor.rgb = orenNayarDiffuseBRDF(albedo, roughness, dotNV, dotNL, dotVH) + wardSpecular(n, h, dotNL, dotNV, dotNH, T, shinyParallel, shinyPerpendicular) * spec; +// } +// #endif + + #ifdef _SSS + if (matid == 2) { + #ifdef _CSM + int casi, casindex; + mat4 LWVP = getCascadeMat(distance(eye, p), casi, casindex); + #endif + fragColor.rgb += fragColor.rgb * SSSSTransmittance( + LWVP, p, n, sunDir, lightPlane.y, + #ifdef _ShadowMapAtlas + #ifndef _SingleAtlas + shadowMapAtlasSun + #else + shadowMapAtlas + #endif + #else + shadowMap + #endif + );//TODO implement transparent shadowmaps into the SSSSTransmittance() } - return visibility; - // Visualize cascades - // if (ci == 0) albedo.rgb = vec3(1.0, 0.0, 0.0); - // if (ci == 4) albedo.rgb = vec3(0.0, 1.0, 0.0); - // if (ci == 8) albedo.rgb = vec3(0.0, 0.0, 1.0); - // if (ci == 12) albedo.rgb = vec3(1.0, 1.0, 0.0); -} + #endif + +#endif // _Sun + +#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 + #endif + #ifdef _VoxelShadow + , voxels, voxelsSDF, clipmaps, -g2.rg + #endif + #ifdef _MicroShadowing + , occspec.x + #endif + #ifdef _SSRS + , gbufferD, invVP, eye + #endif + ); + + #ifdef _Spot + #ifdef _SSS + if (matid == 2) fragColor.rgb += fragColor.rgb * SSSSTransmittance(LWVPSpot[0], p, n, normalize(pointPos - p), lightPlane.y, shadowMapSpot[0]);//TODO implement transparent shadowmaps into the SSSSTransmittance() + #endif + #endif + #endif -#endif \ No newline at end of file + +#ifdef _Clusters + float viewz = linearize(depth * 0.5 + 0.5, cameraProj); + int clusterI = getClusterI(texCoord, viewz, cameraPlane); + int numLights = int(texelFetch(clustersData, ivec2(clusterI, 0), 0).r * 255); + + #ifdef HLSL + viewz += textureLod(clustersData, vec2(0.0), 0.0).r * 1e-9; // TODO: krafix bug, needs to generate sampler + #endif + + #ifdef _Spot + int numSpots = int(texelFetch(clustersData, ivec2(clusterI, 1 + maxLightsCluster), 0).r * 255); + int numPoints = numLights - numSpots; + #endif + + for (int i = 0; i < min(numLights, maxLightsCluster); i++) { + int li = int(texelFetch(clustersData, ivec2(clusterI, i + 1), 0).r * 255); + fragColor.rgb += sampleLight( + p, + n, + v, + dotNV, + lightsArray[li * 3].xyz, // lp + lightsArray[li * 3 + 1].xyz, // lightCol + albedo, + roughness, + occspec.y, + f0 + #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 * 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 + #ifdef _VoxelShadow + , voxels, voxelsSDF, clipmaps, -g2.rg + #endif + #ifdef _MicroShadowing + , occspec.x + #endif + #ifdef _SSRS + , gbufferD, invVP, eye + #endif + ); + } +#endif // _Clusters + fragColor.a = 1.0; // Mark as opaque +} From 58140ad583a802994c58cd57a86d778ffdfb240c Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 9 Jul 2025 23:18:52 +0000 Subject: [PATCH 119/136] Update leenkx/Shaders/std/shadows.glsl --- leenkx/Shaders/std/shadows.glsl | 77 +++++++++++++++++++++++++-------- 1 file changed, 59 insertions(+), 18 deletions(-) diff --git a/leenkx/Shaders/std/shadows.glsl b/leenkx/Shaders/std/shadows.glsl index 7f74a78..a1c01f4 100644 --- a/leenkx/Shaders/std/shadows.glsl +++ b/leenkx/Shaders/std/shadows.glsl @@ -251,28 +251,69 @@ vec3 PCFFakeCube(sampler2DShadow shadowMap, #endif if (any(lessThan(uvtiled, vec2(0.0))) || any(greaterThan(uvtiled, vec2(1.0)))) { - return vec3(1.0); // Or handle edge cases differently + return vec3(1.0); // Handle edge cases by returning full light } vec3 result = vec3(0.0); - // In PCFFakeCube(), modify the sampling pattern to be more robust: - const vec2 offsets[9] = vec2[]( - vec2(0, 0), - vec2(1, 0), vec2(-1, 0), vec2(0, 1), vec2(0, -1), - vec2(1, 1), vec2(-1, 1), vec2(1, -1), vec2(-1, -1) - ); + result.x += texture(shadowMap, vec3(uvtiled, compare)); + // soft shadowing + int newFaceIndex = 0; + uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(-1.0, 0.0) / smSize))); + pointLightTile = pointLightDataArray[lightIndex + newFaceIndex]; + uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy; + #ifdef _FlipY + uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system + #endif + result.x += texture(shadowMap, vec3(uvtiled, compare)); + + uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(0.0, -1.0) / smSize))); + pointLightTile = pointLightDataArray[lightIndex + newFaceIndex]; + uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy; + #ifdef _FlipY + uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system + #endif + result.x += texture(shadowMap, vec3(uvtiled, compare)); + + uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(-1.0, -1.0) / smSize))); + pointLightTile = pointLightDataArray[lightIndex + newFaceIndex]; + uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy; + #ifdef _FlipY + uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system + #endif + result.x += texture(shadowMap, vec3(uvtiled, compare)); + + uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(0.0, 1.0) / smSize))); + pointLightTile = pointLightDataArray[lightIndex + newFaceIndex]; + uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy; + #ifdef _FlipY + uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system + #endif + result.x += texture(shadowMap, vec3(uvtiled, compare)); + + uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(1.0, -1.0) / smSize))); + pointLightTile = pointLightDataArray[lightIndex + newFaceIndex]; + uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy; + #ifdef _FlipY + uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system + #endif + result.x += texture(shadowMap, vec3(uvtiled, compare)); + + uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(1.0, 0.0) / smSize))); + pointLightTile = pointLightDataArray[lightIndex + newFaceIndex]; + uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy; + #ifdef _FlipY + uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system + #endif + result.x += texture(shadowMap, vec3(uvtiled, compare)); + + uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(1.0, 1.0) / smSize))); + pointLightTile = pointLightDataArray[lightIndex + newFaceIndex]; + uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy; + #ifdef _FlipY + uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system + #endif + result.x += texture(shadowMap, vec3(uvtiled, compare)); - for (int i = 0; i < 9; i++) { - vec2 sampleUV = uv + offsets[i] / smSize; - int newFaceIndex; - vec2 transformedUV = transformOffsetedUV(faceIndex, newFaceIndex, sampleUV); - pointLightTile = pointLightDataArray[lightIndex + newFaceIndex]; - uvtiled = pointLightTile.z * transformedUV + pointLightTile.xy; - #ifdef _FlipY - uvtiled.y = 1.0 - uvtiled.y; - #endif - result.x += texture(shadowMap, vec3(uvtiled, compare)); - } result = result.xxx / 9.0; pointLightTile = pointLightDataArray[lightIndex + faceIndex]; // x: tile X offset, y: tile Y offset, z: tile size relative to atlas From 8077f00ada1887fa28adc17d31c03eb7dd4d07c2 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Wed, 9 Jul 2025 23:53:56 +0000 Subject: [PATCH 120/136] Update leenkx/blender/lnx/props_renderpath.py --- leenkx/blender/lnx/props_renderpath.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/leenkx/blender/lnx/props_renderpath.py b/leenkx/blender/lnx/props_renderpath.py index c85a642..d813c34 100644 --- a/leenkx/blender/lnx/props_renderpath.py +++ b/leenkx/blender/lnx/props_renderpath.py @@ -330,7 +330,7 @@ class LnxRPListItem(bpy.types.PropertyGroup): 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_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_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 transparent shadowmaps", default=False, update=update_renderpath) + rp_shadowmap_transparent: BoolProperty(name="Transparency", description="Enable shadows for transparent objects", default=False, update=update_renderpath) rp_shadowmap_atlas_lod_subdivisions: EnumProperty( items=[('2', '2', '2'), ('3', '3', '3'), From 15ac833f2c9b2a57f30c6ed1a2904571c3c63856 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Thu, 10 Jul 2025 00:09:21 +0000 Subject: [PATCH 121/136] Update leenkx/Shaders/std/constants.glsl --- leenkx/Shaders/std/constants.glsl | 57 +++++++++++++++++-------------- 1 file changed, 32 insertions(+), 25 deletions(-) diff --git a/leenkx/Shaders/std/constants.glsl b/leenkx/Shaders/std/constants.glsl index b9ccfdc..caf04dc 100644 --- a/leenkx/Shaders/std/constants.glsl +++ b/leenkx/Shaders/std/constants.glsl @@ -24,37 +24,44 @@ const int DIFFUSE_CONE_COUNT = 16; const float SHADOW_CONE_APERTURE = radians(15.0); -const float DIFFUSE_CONE_APERTURE = radians(50.0); +const float DIFFUSE_CONE_APERTURE = 0.872665; // 50 degrees in radians -const vec3 DIFFUSE_CONE_DIRECTIONS[DIFFUSE_CONE_COUNT] = vec3[]( - vec3(0.0, 0.0, 1.0), // center +mat3 makeTangentBasis(const vec3 normal) { + // Create a tangent basis from normal vector + vec3 tangent; + vec3 bitangent; - vec3(0.0, 0.5, 0.866), - vec3(0.5, 0.0, 0.866), - vec3(0.0, -0.5, 0.866), - vec3(-0.5, 0.0, 0.866), + // Compute tangent (Frisvad's method) + if (abs(normal.z) < 0.999) { + tangent = normalize(cross(vec3(0, 1, 0), normal)); + } else { + tangent = normalize(cross(normal, vec3(1, 0, 0))); + } + bitangent = cross(normal, tangent); - vec3(0.353, 0.353, 0.866), - vec3(0.353, -0.353, 0.866), - vec3(-0.353, -0.353, 0.866), - vec3(-0.353, 0.353, 0.866), - - vec3(0.707, 0.0, 0.707), - vec3(0.0, 0.707, 0.707), - vec3(-0.707, 0.0, 0.707), - vec3(0.0, -0.707, 0.707), - - vec3(0.5, 0.5, 0.707), - vec3(-0.5, 0.5, 0.707), - vec3(-0.5, -0.5, 0.707) -); - -mat3 makeTangentBasis(vec3 normal) { - vec3 tangent = normalize(abs(normal.y) < 0.999 ? cross(normal, vec3(0, 1, 0)) : cross(normal, vec3(1, 0, 0))); - vec3 bitangent = cross(normal, tangent); return mat3(tangent, bitangent, normal); } +// 16 optimized cone directions for hemisphere sampling (Z-up, normalized) +const vec3 DIFFUSE_CONE_DIRECTIONS[16] = vec3[]( + vec3(0.707107, 0.000000, 0.707107), // Front + vec3(-0.707107, 0.000000, 0.707107), // Back + vec3(0.000000, 0.707107, 0.707107), // Right + vec3(0.000000, -0.707107, 0.707107), // Left + vec3(0.500000, 0.500000, 0.707107), // Front-right + vec3(-0.500000, 0.500000, 0.707107), // Back-right + vec3(0.500000, -0.500000, 0.707107), // Front-left + vec3(-0.500000, -0.500000, 0.707107),// Back-left + vec3(0.353553, 0.000000, 0.935414), // Narrow front + vec3(-0.353553, 0.000000, 0.935414), // Narrow back + vec3(0.000000, 0.353553, 0.935414), // Narrow right + vec3(0.000000, -0.353553, 0.935414), // Narrow left + vec3(0.270598, 0.270598, 0.923880), // Narrow front-right + vec3(-0.270598, 0.270598, 0.923880), // Narrow back-right + vec3(0.270598, -0.270598, 0.923880), // Narrow front-left + vec3(-0.270598, -0.270598, 0.923880) // Narrow back-left +); + // TO DO - Disabled momentarily instead of changing formulas const float off_BayerMatrix8[8][8] = { From c35c59e6a9383ae89fb5e70b22406615acc2c5ad Mon Sep 17 00:00:00 2001 From: Onek8 Date: Thu, 10 Jul 2025 00:10:46 +0000 Subject: [PATCH 122/136] Update leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl --- .../voxel_temporal/voxel_temporal.comp.glsl | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl b/leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl index a5b6350..919e01a 100644 --- a/leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl +++ b/leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl @@ -74,8 +74,9 @@ void main() { #endif #endif - mat3 TBN = mat3(1.0); + int nor_count = 0; vec3 avgNormal = vec3(0.0); + mat3 TBN = mat3(0.0); for (int i = 0; i < 6 + DIFFUSE_CONE_COUNT; i++) { @@ -116,10 +117,18 @@ void main() { N.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 8))) / 255; N /= count; N = decode_oct(N.rg * 2.0 - 1.0); - avgNormal += N; + if (abs(N.x) > 0) + avgNormal.x += N.x; + if (abs(N.y) > 0) + avgNormal.y += N.y; + if (abs(N.z) > 0) + avgNormal.z += N.z; if (i == 5) - TBN = makeTangentBasis(normalize(avgNormal)); + { + avgNormal = normalize(avgNormal); + TBN = makeTangentBasis(avgNormal); + } vec3 envl = vec3(0.0); envl.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 9))) / 255; @@ -245,4 +254,4 @@ void main() { imageStore(SDF, dst_sdf, vec4(sdf)); #endif #endif -} +} \ No newline at end of file From 2998a5585e0b8005a7f7217bef96147aeeae1407 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Thu, 10 Jul 2025 00:57:07 +0000 Subject: [PATCH 123/136] Update leenkx/Shaders/ssao_pass/ssao_pass.frag.glsl --- leenkx/Shaders/ssao_pass/ssao_pass.frag.glsl | 73 ++++++++++++++++++-- 1 file changed, 69 insertions(+), 4 deletions(-) diff --git a/leenkx/Shaders/ssao_pass/ssao_pass.frag.glsl b/leenkx/Shaders/ssao_pass/ssao_pass.frag.glsl index 34a63c1..9ab0f35 100644 --- a/leenkx/Shaders/ssao_pass/ssao_pass.frag.glsl +++ b/leenkx/Shaders/ssao_pass/ssao_pass.frag.glsl @@ -45,12 +45,77 @@ void main() { fragColor = 0; const int samples = 8; - const float samplesInv = PI2 * (1.0 / samples); - for (int i = 0; i < samples; ++i) { - float theta = samplesInv * (i + 0.5) + phi; + const float samplesInv = PI2 * (1.0 / 8.0); + + // Manually unrolled sampling loop for better performance on older hardware + // Sample 0 + { + float theta = samplesInv * (0 + 0.5) + phi; + vec2 k = vec2(cos(theta), sin(theta)) / currentDistanceA; + depth = textureLod(gbufferD, texCoord + k, 0.0).r * 2.0 - 1.0; + vec3 pos = getPos2NoEye(eye, invVP, depth, texCoord + k) - currentPos; + fragColor += max(0, dot(pos, n) - currentDistanceB) / (dot(pos, pos) + 0.015); + } + + // Sample 1 + { + float theta = samplesInv * (1 + 0.5) + phi; + vec2 k = vec2(cos(theta), sin(theta)) / currentDistanceA; + depth = textureLod(gbufferD, texCoord + k, 0.0).r * 2.0 - 1.0; + vec3 pos = getPos2NoEye(eye, invVP, depth, texCoord + k) - currentPos; + fragColor += max(0, dot(pos, n) - currentDistanceB) / (dot(pos, pos) + 0.015); + } + + // Sample 2 + { + float theta = samplesInv * (2 + 0.5) + phi; + vec2 k = vec2(cos(theta), sin(theta)) / currentDistanceA; + depth = textureLod(gbufferD, texCoord + k, 0.0).r * 2.0 - 1.0; + vec3 pos = getPos2NoEye(eye, invVP, depth, texCoord + k) - currentPos; + fragColor += max(0, dot(pos, n) - currentDistanceB) / (dot(pos, pos) + 0.015); + } + + // Sample 3 + { + float theta = samplesInv * (3 + 0.5) + phi; + vec2 k = vec2(cos(theta), sin(theta)) / currentDistanceA; + depth = textureLod(gbufferD, texCoord + k, 0.0).r * 2.0 - 1.0; + vec3 pos = getPos2NoEye(eye, invVP, depth, texCoord + k) - currentPos; + fragColor += max(0, dot(pos, n) - currentDistanceB) / (dot(pos, pos) + 0.015); + } + + // Sample 4 + { + float theta = samplesInv * (4 + 0.5) + phi; + vec2 k = vec2(cos(theta), sin(theta)) / currentDistanceA; + depth = textureLod(gbufferD, texCoord + k, 0.0).r * 2.0 - 1.0; + vec3 pos = getPos2NoEye(eye, invVP, depth, texCoord + k) - currentPos; + fragColor += max(0, dot(pos, n) - currentDistanceB) / (dot(pos, pos) + 0.015); + } + + // Sample 5 + { + float theta = samplesInv * (5 + 0.5) + phi; + vec2 k = vec2(cos(theta), sin(theta)) / currentDistanceA; + depth = textureLod(gbufferD, texCoord + k, 0.0).r * 2.0 - 1.0; + vec3 pos = getPos2NoEye(eye, invVP, depth, texCoord + k) - currentPos; + fragColor += max(0, dot(pos, n) - currentDistanceB) / (dot(pos, pos) + 0.015); + } + + // Sample 6 + { + float theta = samplesInv * (6 + 0.5) + phi; + vec2 k = vec2(cos(theta), sin(theta)) / currentDistanceA; + depth = textureLod(gbufferD, texCoord + k, 0.0).r * 2.0 - 1.0; + vec3 pos = getPos2NoEye(eye, invVP, depth, texCoord + k) - currentPos; + fragColor += max(0, dot(pos, n) - currentDistanceB) / (dot(pos, pos) + 0.015); + } + + // Sample 7 + { + float theta = samplesInv * (7 + 0.5) + phi; vec2 k = vec2(cos(theta), sin(theta)) / currentDistanceA; depth = textureLod(gbufferD, texCoord + k, 0.0).r * 2.0 - 1.0; - // vec3 pos = getPosNoEye(eyeLook, vray, depth, cameraProj) - currentPos; vec3 pos = getPos2NoEye(eye, invVP, depth, texCoord + k) - currentPos; fragColor += max(0, dot(pos, n) - currentDistanceB) / (dot(pos, pos) + 0.015); } From 858537d54c5b66eed49c8dfbdd5e98bc5878097b Mon Sep 17 00:00:00 2001 From: Onek8 Date: Thu, 10 Jul 2025 00:58:53 +0000 Subject: [PATCH 124/136] revert 2998a5585e0b8005a7f7217bef96147aeeae1407 revert Update leenkx/Shaders/ssao_pass/ssao_pass.frag.glsl --- leenkx/Shaders/ssao_pass/ssao_pass.frag.glsl | 73 ++------------------ 1 file changed, 4 insertions(+), 69 deletions(-) diff --git a/leenkx/Shaders/ssao_pass/ssao_pass.frag.glsl b/leenkx/Shaders/ssao_pass/ssao_pass.frag.glsl index 9ab0f35..34a63c1 100644 --- a/leenkx/Shaders/ssao_pass/ssao_pass.frag.glsl +++ b/leenkx/Shaders/ssao_pass/ssao_pass.frag.glsl @@ -45,77 +45,12 @@ void main() { fragColor = 0; const int samples = 8; - const float samplesInv = PI2 * (1.0 / 8.0); - - // Manually unrolled sampling loop for better performance on older hardware - // Sample 0 - { - float theta = samplesInv * (0 + 0.5) + phi; - vec2 k = vec2(cos(theta), sin(theta)) / currentDistanceA; - depth = textureLod(gbufferD, texCoord + k, 0.0).r * 2.0 - 1.0; - vec3 pos = getPos2NoEye(eye, invVP, depth, texCoord + k) - currentPos; - fragColor += max(0, dot(pos, n) - currentDistanceB) / (dot(pos, pos) + 0.015); - } - - // Sample 1 - { - float theta = samplesInv * (1 + 0.5) + phi; - vec2 k = vec2(cos(theta), sin(theta)) / currentDistanceA; - depth = textureLod(gbufferD, texCoord + k, 0.0).r * 2.0 - 1.0; - vec3 pos = getPos2NoEye(eye, invVP, depth, texCoord + k) - currentPos; - fragColor += max(0, dot(pos, n) - currentDistanceB) / (dot(pos, pos) + 0.015); - } - - // Sample 2 - { - float theta = samplesInv * (2 + 0.5) + phi; - vec2 k = vec2(cos(theta), sin(theta)) / currentDistanceA; - depth = textureLod(gbufferD, texCoord + k, 0.0).r * 2.0 - 1.0; - vec3 pos = getPos2NoEye(eye, invVP, depth, texCoord + k) - currentPos; - fragColor += max(0, dot(pos, n) - currentDistanceB) / (dot(pos, pos) + 0.015); - } - - // Sample 3 - { - float theta = samplesInv * (3 + 0.5) + phi; - vec2 k = vec2(cos(theta), sin(theta)) / currentDistanceA; - depth = textureLod(gbufferD, texCoord + k, 0.0).r * 2.0 - 1.0; - vec3 pos = getPos2NoEye(eye, invVP, depth, texCoord + k) - currentPos; - fragColor += max(0, dot(pos, n) - currentDistanceB) / (dot(pos, pos) + 0.015); - } - - // Sample 4 - { - float theta = samplesInv * (4 + 0.5) + phi; - vec2 k = vec2(cos(theta), sin(theta)) / currentDistanceA; - depth = textureLod(gbufferD, texCoord + k, 0.0).r * 2.0 - 1.0; - vec3 pos = getPos2NoEye(eye, invVP, depth, texCoord + k) - currentPos; - fragColor += max(0, dot(pos, n) - currentDistanceB) / (dot(pos, pos) + 0.015); - } - - // Sample 5 - { - float theta = samplesInv * (5 + 0.5) + phi; - vec2 k = vec2(cos(theta), sin(theta)) / currentDistanceA; - depth = textureLod(gbufferD, texCoord + k, 0.0).r * 2.0 - 1.0; - vec3 pos = getPos2NoEye(eye, invVP, depth, texCoord + k) - currentPos; - fragColor += max(0, dot(pos, n) - currentDistanceB) / (dot(pos, pos) + 0.015); - } - - // Sample 6 - { - float theta = samplesInv * (6 + 0.5) + phi; - vec2 k = vec2(cos(theta), sin(theta)) / currentDistanceA; - depth = textureLod(gbufferD, texCoord + k, 0.0).r * 2.0 - 1.0; - vec3 pos = getPos2NoEye(eye, invVP, depth, texCoord + k) - currentPos; - fragColor += max(0, dot(pos, n) - currentDistanceB) / (dot(pos, pos) + 0.015); - } - - // Sample 7 - { - float theta = samplesInv * (7 + 0.5) + phi; + const float samplesInv = PI2 * (1.0 / samples); + for (int i = 0; i < samples; ++i) { + float theta = samplesInv * (i + 0.5) + phi; vec2 k = vec2(cos(theta), sin(theta)) / currentDistanceA; depth = textureLod(gbufferD, texCoord + k, 0.0).r * 2.0 - 1.0; + // vec3 pos = getPosNoEye(eyeLook, vray, depth, cameraProj) - currentPos; vec3 pos = getPos2NoEye(eye, invVP, depth, texCoord + k) - currentPos; fragColor += max(0, dot(pos, n) - currentDistanceB) / (dot(pos, pos) + 0.015); } From 70695b3b31b2f9c49d30e2d1c4a42a3e58fbf1cf Mon Sep 17 00:00:00 2001 From: Onek8 Date: Thu, 10 Jul 2025 01:14:03 +0000 Subject: [PATCH 125/136] Update leenkx/Shaders/deferred_light/deferred_light.frag.glsl --- leenkx/Shaders/deferred_light/deferred_light.frag.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/leenkx/Shaders/deferred_light/deferred_light.frag.glsl b/leenkx/Shaders/deferred_light/deferred_light.frag.glsl index 73788ff..7af6c9b 100644 --- a/leenkx/Shaders/deferred_light/deferred_light.frag.glsl +++ b/leenkx/Shaders/deferred_light/deferred_light.frag.glsl @@ -319,7 +319,7 @@ void main() { #ifdef _VoxelGI fragColor.rgb = textureLod(voxels_diffuse, texCoord, 0.0).rgb * voxelgiDiff; if(roughness < 1.0 && occspec.y > 0.0) - fragColor.rgb += textureLod(voxels_specular, texCoord, 0.0).rgb * F * voxelgiRefl; + fragColor.rgb += textureLod(voxels_specular, texCoord, 0.0).rgb * occspec.y * voxelgiRefl; #else #ifdef _VoxelAOvar fragColor.rgb = textureLod(voxels_ao, texCoord, 0.0).rgb * voxelgiOcc; From da25d8c313bbc986b7c27aaf340c4e25f27e594a Mon Sep 17 00:00:00 2001 From: Onek8 Date: Thu, 10 Jul 2025 01:16:02 +0000 Subject: [PATCH 126/136] Update leenkx/Shaders/voxel_resolve_diffuse/voxel_resolve_diffuse.comp.glsl --- .../voxel_resolve_diffuse/voxel_resolve_diffuse.comp.glsl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/leenkx/Shaders/voxel_resolve_diffuse/voxel_resolve_diffuse.comp.glsl b/leenkx/Shaders/voxel_resolve_diffuse/voxel_resolve_diffuse.comp.glsl index 75d5c3d..a605d79 100644 --- a/leenkx/Shaders/voxel_resolve_diffuse/voxel_resolve_diffuse.comp.glsl +++ b/leenkx/Shaders/voxel_resolve_diffuse/voxel_resolve_diffuse.comp.glsl @@ -106,8 +106,11 @@ void main() { #ifdef _Brdf vec2 envBRDF = texelFetch(senvmapBrdf, ivec2(vec2(dotNV, 1.0 - roughness) * 256.0), 0).xy; vec3 F = f0 * envBRDF.x + envBRDF.y; +#else + vec3 F = f0; #endif + // Envmap #ifdef _Irr vec4 shPacked[7]; From 1e583a795d1a702a2cecf0901cc49050962a08b4 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Thu, 10 Jul 2025 05:10:54 +0000 Subject: [PATCH 127/136] Update leenkx/blender/lnx/props_renderpath.py --- leenkx/blender/lnx/props_renderpath.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/leenkx/blender/lnx/props_renderpath.py b/leenkx/blender/lnx/props_renderpath.py index d813c34..1e19a5d 100644 --- a/leenkx/blender/lnx/props_renderpath.py +++ b/leenkx/blender/lnx/props_renderpath.py @@ -548,8 +548,8 @@ class LnxRPListItem(bpy.types.PropertyGroup): lnx_water_density: FloatProperty(name="Density", default=1.0, update=assets.invalidate_shader_cache) lnx_water_refract: FloatProperty(name="Refract", default=1.0, update=assets.invalidate_shader_cache) lnx_water_reflect: FloatProperty(name="Reflect", default=1.0, update=assets.invalidate_shader_cache) - lnx_ssgi_strength: FloatProperty(name="Strength", default=8.0, update=assets.invalidate_shader_cache) - lnx_ssgi_radius: FloatProperty(name="Radius", default=1.0, update=assets.invalidate_shader_cache) + lnx_ssgi_strength: FloatProperty(name="Strength", default=1.250, update=assets.invalidate_shader_cache) + lnx_ssgi_radius: FloatProperty(name="Radius", default=0.750, update=assets.invalidate_shader_cache) lnx_ssgi_step: FloatProperty(name="Step", default=2.0, update=assets.invalidate_shader_cache) lnx_ssgi_samples: IntProperty(name="Samples", default=32, update=assets.invalidate_shader_cache) """ From 76472316963c2f91a4704a655dbfcafff66c1669 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Thu, 10 Jul 2025 08:59:53 +0000 Subject: [PATCH 128/136] Update leenkx/Shaders/ssrefr_pass/ssrefr_pass.frag.glsl --- .../Shaders/ssrefr_pass/ssrefr_pass.frag.glsl | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/leenkx/Shaders/ssrefr_pass/ssrefr_pass.frag.glsl b/leenkx/Shaders/ssrefr_pass/ssrefr_pass.frag.glsl index 52c6176..3af7411 100644 --- a/leenkx/Shaders/ssrefr_pass/ssrefr_pass.frag.glsl +++ b/leenkx/Shaders/ssrefr_pass/ssrefr_pass.frag.glsl @@ -1,5 +1,5 @@ //https://lettier.github.io/3d-game-shaders-for-beginners/screen-space-refraction.html -//Implemented by Yvain Douard. +//Implemented by Yvain Douard an 1k8. #version 450 @@ -64,7 +64,7 @@ vec4 rayCast(vec3 dir) { ddepth = getDeltaDepth(hitCoord); if (ddepth > 0.0) return binarySearch(dir); } - return vec4(getProjectedCoord(hitCoord), 0.0, 1.0); + return vec4(texCoord, 0.0, 1.0); } void main() { @@ -72,10 +72,11 @@ void main() { float roughness = g0.z; vec4 gr = textureLod(gbuffer_refraction, texCoord, 0.0); float ior = gr.x; - float opac = gr.y; + float opac = 1.0 - gr.y; float d = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0; if (d == 0.0 || d == 1.0 || opac == 1.0 || ior == 1.0) { fragColor.rgb = textureLod(tex1, texCoord, 0.0).rgb; + fragColor.a = opac; return; } vec2 enc = g0.rg; @@ -86,7 +87,7 @@ void main() { vec3 viewNormal = V3 * n; vec3 viewPos = getPosView(viewRay, d, cameraProj); - vec3 refracted = refract(viewPos, viewNormal, 1.0 / ior); + vec3 refracted = refract(normalize(viewPos), viewNormal, 1.0 / ior); hitCoord = viewPos; vec3 dir = refracted * (1.0 - rand(texCoord) * ss_refractionJitter * roughness) * 2.0; @@ -98,9 +99,12 @@ void main() { clamp(-refracted.z, 0.0, 1.0) * clamp((length(viewPos - hitCoord)), 0.0, 1.0) * coords.w; intensity = clamp(intensity, 0.0, 1.0); - vec3 refractionCol = textureLod(tex1, coords.xy, 0.0).rgb; - refractionCol *= intensity; - vec3 color = textureLod(tex, texCoord.xy, 0.0).rgb; + vec4 refractionCol = textureLod(tex1, coords.xy, 0.0).rgba; + refractionCol.a = opac; + //refractionCol *= intensity; + vec4 color = textureLod(tex, texCoord.xy, 0.0).rgba; + color.a = opac; - fragColor.rgb = mix(refractionCol, color, opac); + fragColor.rgba = mix(refractionCol, color, opac); + fragColor.a = opac; } From 53c5000975b96279296c43e794721c45f7afe094 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Thu, 10 Jul 2025 09:00:12 +0000 Subject: [PATCH 129/136] Update leenkx/Shaders/ssrefr_pass/ssrefr_pass.frag.glsl --- leenkx/Shaders/ssrefr_pass/ssrefr_pass.frag.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/leenkx/Shaders/ssrefr_pass/ssrefr_pass.frag.glsl b/leenkx/Shaders/ssrefr_pass/ssrefr_pass.frag.glsl index 3af7411..562d651 100644 --- a/leenkx/Shaders/ssrefr_pass/ssrefr_pass.frag.glsl +++ b/leenkx/Shaders/ssrefr_pass/ssrefr_pass.frag.glsl @@ -1,5 +1,5 @@ //https://lettier.github.io/3d-game-shaders-for-beginners/screen-space-refraction.html -//Implemented by Yvain Douard an 1k8. +//Implemented by Yvain Douard and 1k8. #version 450 From 0265ef5b6418763cff8bba1632a98535349caf29 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Thu, 10 Jul 2025 09:01:28 +0000 Subject: [PATCH 130/136] Update leenkx/Shaders/ssrefr_pass/ssrefr_pass.frag.glsl --- leenkx/Shaders/ssrefr_pass/ssrefr_pass.frag.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/leenkx/Shaders/ssrefr_pass/ssrefr_pass.frag.glsl b/leenkx/Shaders/ssrefr_pass/ssrefr_pass.frag.glsl index 562d651..44a2647 100644 --- a/leenkx/Shaders/ssrefr_pass/ssrefr_pass.frag.glsl +++ b/leenkx/Shaders/ssrefr_pass/ssrefr_pass.frag.glsl @@ -1,5 +1,5 @@ //https://lettier.github.io/3d-game-shaders-for-beginners/screen-space-refraction.html -//Implemented by Yvain Douard and 1k8. +//Implemented by Yvain Douard. #version 450 From 6ff7804ec129d7b496257d2ef5f09b2309f1b628 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Thu, 10 Jul 2025 09:01:58 +0000 Subject: [PATCH 131/136] Update leenkx/Shaders/ssrefr_pass/ssrefr_pass.json --- leenkx/Shaders/ssrefr_pass/ssrefr_pass.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/leenkx/Shaders/ssrefr_pass/ssrefr_pass.json b/leenkx/Shaders/ssrefr_pass/ssrefr_pass.json index 716f218..77a4f40 100644 --- a/leenkx/Shaders/ssrefr_pass/ssrefr_pass.json +++ b/leenkx/Shaders/ssrefr_pass/ssrefr_pass.json @@ -5,6 +5,12 @@ "depth_write": false, "compare_mode": "always", "cull_mode": "none", + "blend_source": "source_alpha", + "blend_destination": "inverse_source_alpha", + "blend_operation": "add", + "alpha_blend_source": "blend_one", + "alpha_blend_destination": "blend_one", + "alpha_blend_operation": "add", "links": [ { "name": "P", From da666e6d231d3b3e54cbc0f26b6c39c6e6e71514 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Thu, 10 Jul 2025 09:03:26 +0000 Subject: [PATCH 132/136] Update leenkx/blender/lnx/material/cycles_nodes/nodes_shader.py --- leenkx/blender/lnx/material/cycles_nodes/nodes_shader.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/leenkx/blender/lnx/material/cycles_nodes/nodes_shader.py b/leenkx/blender/lnx/material/cycles_nodes/nodes_shader.py index 4885430..b6084c1 100644 --- a/leenkx/blender/lnx/material/cycles_nodes/nodes_shader.py +++ b/leenkx/blender/lnx/material/cycles_nodes/nodes_shader.py @@ -250,7 +250,7 @@ def parse_bsdfglass(node: bpy.types.ShaderNodeBsdfGlass, out_socket: NodeSocket, c.write_normal(node.inputs[3]) state.out_roughness = c.parse_value_input(node.inputs[1]) if state.parse_opacity: - state.out_opacity = '0.1' + state.out_opacity = '1.0' state.out_ior = c.parse_value_input(node.inputs[2]) @@ -270,7 +270,7 @@ def parse_bsdfrefraction(node: bpy.types.ShaderNodeBsdfRefraction, out_socket: N c.write_normal(node.inputs[3]) state.out_roughness = c.parse_value_input(node.inputs[1]) if state.parse_opacity: - state.out_opacity = '0.0' + state.out_opacity = '1.0' state.out_ior = c.parse_value_input(node.inputs[2]) def parse_subsurfacescattering(node: bpy.types.ShaderNodeSubsurfaceScattering, out_socket: NodeSocket, state: ParserState) -> None: From 9622f35b73e56409396376f256ba60f85aa270d6 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Thu, 10 Jul 2025 09:10:43 +0000 Subject: [PATCH 133/136] Update leenkx/Shaders/std/brdf.glsl --- leenkx/Shaders/std/brdf.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/leenkx/Shaders/std/brdf.glsl b/leenkx/Shaders/std/brdf.glsl index cce227e..ab4d49a 100644 --- a/leenkx/Shaders/std/brdf.glsl +++ b/leenkx/Shaders/std/brdf.glsl @@ -86,7 +86,7 @@ vec3 surfaceAlbedo(const vec3 baseColor, const float metalness) { } vec3 surfaceF0(const vec3 baseColor, const float metalness) { - return mix(vec3(0.04), baseColor, metalness); + return mix(vec3(0.04), baseColor * (2.0 + metalness * 1.2), metalness); } float getMipFromRoughness(const float roughness, const float numMipmaps) { From a318e08072a865ba11c27b96aab3f8283e66dc77 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Tue, 22 Jul 2025 23:20:35 +0000 Subject: [PATCH 134/136] Update leenkx/Shaders/sss_pass/sss_pass.frag.glsl --- leenkx/Shaders/sss_pass/sss_pass.frag.glsl | 119 +++++++++++++-------- 1 file changed, 77 insertions(+), 42 deletions(-) diff --git a/leenkx/Shaders/sss_pass/sss_pass.frag.glsl b/leenkx/Shaders/sss_pass/sss_pass.frag.glsl index 872676f..0b5296f 100644 --- a/leenkx/Shaders/sss_pass/sss_pass.frag.glsl +++ b/leenkx/Shaders/sss_pass/sss_pass.frag.glsl @@ -1,6 +1,7 @@ // // Copyright (C) 2012 Jorge Jimenez (jorge@iryoku.com) // Copyright (C) 2012 Diego Gutierrez (diegog@unizar.es) +// Copyright (C) 2025 Onek8 (info@leenkx.com) // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -33,6 +34,14 @@ // policies, either expressed or implied, of the copyright holders. // +// TODO: +// Add real sss radius +// Add real sss scale +// Move temp hash, reorganize shader utility functions +// Add compiler flag for quality presets or with samples parameter +// Clean up + Document comment + + #version 450 #include "compiled.inc" @@ -49,67 +58,93 @@ out vec4 fragColor; const float SSSS_FOVY = 108.0; -// Separable SSS Reflectance -// const float sssWidth = 0.005; +// Temp hash func - +float hash13(vec3 p3) { + p3 = fract(p3 * vec3(0.1031, 0.1030, 0.0973)); + p3 += dot(p3, p3.yzx + 33.33); + return fract((p3.x + p3.y) * p3.z); +} + vec4 SSSSBlur() { - // Quality = 0 - const int SSSS_N_SAMPLES = 11; - vec4 kernel[SSSS_N_SAMPLES]; - kernel[0] = vec4(0.560479, 0.669086, 0.784728, 0); - kernel[1] = vec4(0.00471691, 0.000184771, 5.07566e-005, -2); - kernel[2] = vec4(0.0192831, 0.00282018, 0.00084214, -1.28); - kernel[3] = vec4(0.03639, 0.0130999, 0.00643685, -0.72); - kernel[4] = vec4(0.0821904, 0.0358608, 0.0209261, -0.32); - kernel[5] = vec4(0.0771802, 0.113491, 0.0793803, -0.08); - kernel[6] = vec4(0.0771802, 0.113491, 0.0793803, 0.08); - kernel[7] = vec4(0.0821904, 0.0358608, 0.0209261, 0.32); - kernel[8] = vec4(0.03639, 0.0130999, 0.00643685, 0.72); - kernel[9] = vec4(0.0192831, 0.00282018, 0.00084214, 1.28); - kernel[10] = vec4(0.00471691, 0.000184771, 5.07565e-005, 2); + const int SSSS_N_SAMPLES = 15; + vec4 kernel[SSSS_N_SAMPLES]; + + // color neutral kernel weights to prevent color shifting + kernel[0] = vec4(0.2, 0.2, 0.2, 0.0); + kernel[1] = vec4(0.12, 0.12, 0.12, 0.2); + kernel[2] = vec4(0.09, 0.09, 0.09, 0.4); + kernel[3] = vec4(0.06, 0.06, 0.06, 0.8); + kernel[4] = vec4(0.04, 0.04, 0.04, 1.2); + kernel[5] = vec4(0.025, 0.025, 0.025, 1.6); + kernel[6] = vec4(0.015, 0.015, 0.015, 2.0); + kernel[7] = vec4(0.005, 0.005, 0.005, 2.5); + kernel[8] = vec4(0.12, 0.12, 0.12, -0.2); + kernel[9] = vec4(0.09, 0.09, 0.09, -0.4); + kernel[10] = vec4(0.06, 0.06, 0.06, -0.8); + kernel[11] = vec4(0.04, 0.04, 0.04, -1.2); + kernel[12] = vec4(0.025, 0.025, 0.025, -1.6); + kernel[13] = vec4(0.015, 0.015, 0.015, -2.0); + kernel[14] = vec4(0.005, 0.005, 0.005, -2.5); vec4 colorM = textureLod(tex, texCoord, 0.0); - // Fetch linear depth of current pixel float depth = textureLod(gbufferD, texCoord, 0.0).r; float depthM = cameraProj.y / (depth - cameraProj.x); - // Calculate the sssWidth scale (1.0 for a unit plane sitting on the projection window) float distanceToProjectionWindow = 1.0 / tan(0.5 * radians(SSSS_FOVY)); float scale = distanceToProjectionWindow / depthM; - // Calculate the final step to fetch the surrounding pixels vec2 finalStep = sssWidth * scale * dir; - finalStep *= 1.0;//SSSS_STREGTH_SOURCE; // Modulate it using the alpha channel. - finalStep *= 1.0 / 3.0; // Divide by 3 as the kernels range from -3 to 3. - finalStep *= 0.05; // + - // Accumulate the center sample: - vec4 colorBlurred = colorM; - colorBlurred.rgb *= kernel[0].rgb; - - // Accumulate the other samples + vec3 jitterSeed = vec3(texCoord.xy * 1000.0, fract(cameraProj.x * 0.0001)); + float jitterOffset = (hash13(jitterSeed) * 2.0 - 1.0) * 0.15; // 15% jitteR + + finalStep *= (1.0 + jitterOffset); + finalStep *= 0.05; + vec3 colorBlurred = vec3(0.0); + vec3 weightSum = vec3(0.0); + colorBlurred += colorM.rgb * kernel[0].rgb; + weightSum += kernel[0].rgb; + + // Accumulate the other samples with per-pixel jittering to reduce banding for (int i = 1; i < SSSS_N_SAMPLES; i++) { - // Fetch color and depth for current sample - vec2 offset = texCoord + kernel[i].a * finalStep; + float sampleJitter = hash13(vec3(texCoord.xy * 720.0, float(i) * 37.45)) * 0.1 - 0.05; + + vec2 offset = texCoord + (kernel[i].a + sampleJitter) * finalStep; vec4 color = textureLod(tex, offset, 0.0); - //#if SSSS_FOLLOW_SURFACE == 1 - // If the difference in depth is huge, we lerp color back to "colorM": - //float depth = textureLod(tex, offset, 0.0).r; - //float s = clamp(300.0f * distanceToProjectionWindow * sssWidth * abs(depthM - depth),0.0,1.0); - //color.rgb = mix(color.rgb, colorM.rgb, s); - //#endif - // Accumulate - colorBlurred.rgb += kernel[i].rgb * color.rgb; + + // ADJUST FOR SURFACE FOLLOWING + // 0.0 = disabled (maximum SSS but with bleeding), 1.0 = fully enabled (prevents bleeding but might reduce SSS effect) + const float SURFACE_FOLLOWING_STRENGTH = 0.15; // Reduced to preserve more SSS effect + + if (SURFACE_FOLLOWING_STRENGTH > 0.0) { + float sampleDepth = textureLod(gbufferD, offset, 0.0).r; + float depthScale = 5.0; + float depthDiff = abs(depth - sampleDepth) * depthScale; + if (depthDiff > 0.3) { + float blendFactor = clamp(depthDiff - 0.3, 0.0, 1.0) * SURFACE_FOLLOWING_STRENGTH; + color.rgb = mix(color.rgb, colorM.rgb, blendFactor); + } + } + + colorBlurred += color.rgb * kernel[i].rgb; + weightSum += kernel[i].rgb; } - - return colorBlurred; + vec3 normalizedColor = colorBlurred / max(weightSum, vec3(0.00001)); + float dither = hash13(vec3(texCoord * 1333.0, 0.0)) * 0.003 - 0.0015; + return vec4(normalizedColor + vec3(dither), colorM.a); } void main() { + if (textureLod(gbuffer0, texCoord, 0.0).a == 8192.0) { - fragColor = clamp(SSSSBlur(), 0.0, 1.0); - } - else { + vec4 originalColor = textureLod(tex, texCoord, 0.0); + vec4 blurredColor = SSSSBlur(); + vec4 finalColor = mix(blurredColor, originalColor, 0.15); + + fragColor = clamp(finalColor, 0.0, 1.0); + } else { fragColor = textureLod(tex, texCoord, 0.0); } } From fbf63e4f174fcb96e30d61526b70eddf6f99aa72 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Tue, 22 Jul 2025 23:33:21 +0000 Subject: [PATCH 135/136] Update leenkx/Shaders/std/brdf.glsl --- leenkx/Shaders/std/brdf.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/leenkx/Shaders/std/brdf.glsl b/leenkx/Shaders/std/brdf.glsl index ab4d49a..cce227e 100644 --- a/leenkx/Shaders/std/brdf.glsl +++ b/leenkx/Shaders/std/brdf.glsl @@ -86,7 +86,7 @@ vec3 surfaceAlbedo(const vec3 baseColor, const float metalness) { } vec3 surfaceF0(const vec3 baseColor, const float metalness) { - return mix(vec3(0.04), baseColor * (2.0 + metalness * 1.2), metalness); + return mix(vec3(0.04), baseColor, metalness); } float getMipFromRoughness(const float roughness, const float numMipmaps) { From 662981fa0308e48d4a4c965d69e8d43ecbc254f0 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Thu, 14 Aug 2025 22:46:53 +0000 Subject: [PATCH 136/136] Update leenkx/blender/lnx/material/make_mesh.py --- leenkx/blender/lnx/material/make_mesh.py | 1 + 1 file changed, 1 insertion(+) diff --git a/leenkx/blender/lnx/material/make_mesh.py b/leenkx/blender/lnx/material/make_mesh.py index 082b6f7..6054fbd 100644 --- a/leenkx/blender/lnx/material/make_mesh.py +++ b/leenkx/blender/lnx/material/make_mesh.py @@ -715,6 +715,7 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False): frag.write('vec3 indirect = envl;') if '_VoxelGI' in wrd.world_defs: + frag.write('vec2 velocity = gl_FragCoord.xy;') frag.write('vec4 diffuse_indirect = traceDiffuse(wposition, n, voxels, clipmaps);') frag.write('indirect = (diffuse_indirect.rgb * albedo * (1.0 - F) + envl * (1.0 - diffuse_indirect.a)) * voxelgiDiff;') frag.write('if (roughness < 1.0 && specular > 0.0) {')