diff --git a/Krom/kinc.dmp b/Krom/kinc.dmp new file mode 100644 index 0000000..9599794 Binary files /dev/null and b/Krom/kinc.dmp differ diff --git a/leenkx/Shaders/volumetric_light/volumetric_light.frag.glsl b/leenkx/Shaders/volumetric_light/volumetric_light.frag.glsl index bb342fc..2a3fb23 100644 --- a/leenkx/Shaders/volumetric_light/volumetric_light.frag.glsl +++ b/leenkx/Shaders/volumetric_light/volumetric_light.frag.glsl @@ -137,7 +137,7 @@ void rayStep(inout vec3 curPos, inout float curOpticalDepth, inout float scatter visibility *= spotlightMask(normalize(pointPos - curPos), spotDir, spotRight, spotData.zw, spotData.x, spotData.y); #else vec3 ld = pointPos - curPos; - visibility = PCFCube(shadowMapPoint[0], ld, -normalize(ld), pointBias, lightProj, vec3(0.0)); + visibility = PCFCube(shadowMapPoint[0], ld, -normalize(ld), pointBias, lightProj, vec3(0.0)).x; #endif #endif diff --git a/leenkx/Shaders/voxel_light/voxel_light.comp.glsl b/leenkx/Shaders/voxel_light/voxel_light.comp.glsl index 3fbdd82..759fc78 100644 --- a/leenkx/Shaders/voxel_light/voxel_light.comp.glsl +++ b/leenkx/Shaders/voxel_light/voxel_light.comp.glsl @@ -96,7 +96,7 @@ void main() { wposition += vec3(clipmaps[clipmapLevel * 10 + 4], clipmaps[clipmapLevel * 10 + 5], clipmaps[clipmapLevel * 10 + 6]); float visibility; - vec3 lp = lightPos -wposition; + vec3 lp = lightPos - wposition; vec3 l; if (lightType == 0) { l = lightDir; visibility = 1.0; } else { l = normalize(lp); visibility = attenuate(distance(wposition, lightPos)); } @@ -105,7 +105,7 @@ void main() { 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; + visibility *= texture(shadowMap, vec3(lPos.xy, lPos.z - shadowsBias)).r; } else if (lightShadow == 2) { vec4 lightPosition = LVP * vec4(wposition, 1.0); @@ -129,7 +129,8 @@ void main() { } #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)); + vec3 light = visibility * lightColor; + imageAtomicAdd(voxelsLight, dst, 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)); } diff --git a/leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl b/leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl index 919e01a..75f35c5 100644 --- a/leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl +++ b/leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl @@ -74,9 +74,13 @@ void main() { #endif #endif - int nor_count = 0; - vec3 avgNormal = vec3(0.0); - mat3 TBN = mat3(0.0); + #ifdef _VoxelGI + vec3 light = vec3(0.0); + light.r = float(imageLoad(voxelsLight, ivec3(gl_GlobalInvocationID.xyz)).r) / 255; + light.g = float(imageLoad(voxelsLight, ivec3(gl_GlobalInvocationID.xyz) + ivec3(0, 0, voxelgiResolution.x)).r) / 255; + light.b = float(imageLoad(voxelsLight, ivec3(gl_GlobalInvocationID.xyz) + ivec3(0, 0, voxelgiResolution.x * 2)).r) / 255; + light /= 3; + #endif for (int i = 0; i < 6 + DIFFUSE_CONE_COUNT; i++) { @@ -99,67 +103,46 @@ void main() { if (i < 6) { #ifdef _VoxelGI - 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; - 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 /= count; - N = decode_oct(N.rg * 2.0 - 1.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 /= 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; + #ifdef _HOSEK + envl *= 100; + #endif - 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) - { - avgNormal = normalize(avgNormal); - TBN = makeTangentBasis(avgNormal); - } + //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]); - 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; - 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; + radiance = basecol; + vec4 trace = traceDiffuse(wposition, wnormal, voxelsSampler, clipmaps); + vec3 indirect = trace.rgb + envl.rgb * (1.0 - trace.a); + radiance.rgb *= light.rgb + indirect.rgb; + radiance.rgb += emission.rgb; - //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, N, voxelsSampler, clipmaps); - vec3 indirect = trace.rgb + envl.rgb * (1.0 - trace.a); - radiance.rgb *= light + indirect; - radiance.rgb += emission.rgb; - } #else - int count = int(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x))); - if (count > 0) { - opac = float(imageLoad(voxels, src)) / 255; - opac /= count; - } + opac = float(imageLoad(voxels, src)) / 255; #endif #ifdef _VoxelGI @@ -213,7 +196,7 @@ void main() { } else { // precompute cone sampling: - vec3 coneDirection = TBN * DIFFUSE_CONE_DIRECTIONS[i - 6]; + vec3 coneDirection = DIFFUSE_CONE_DIRECTIONS[i - 6]; vec3 aniso_direction = -coneDirection; uvec3 face_offsets = uvec3( aniso_direction.x > 0 ? 0 : 1, diff --git a/leenkx/Sources/leenkx/renderpath/Inc.hx b/leenkx/Sources/leenkx/renderpath/Inc.hx index 7198b98..5e90488 100644 --- a/leenkx/Sources/leenkx/renderpath/Inc.hx +++ b/leenkx/Sources/leenkx/renderpath/Inc.hx @@ -19,10 +19,6 @@ class Inc { #end #end - #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; @@ -636,7 +632,7 @@ class Inc { } // Init voxels #if (rp_voxels != 'Off') - if (!voxelsCreated) initGI(); + initGI(); #if (rp_voxels == "Voxel GI") initGI("voxelsLight"); #end @@ -744,12 +740,6 @@ class Inc { 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(); @@ -761,48 +751,38 @@ class Inc { } 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; } else if (t.name == "voxelsLight") { - t.format = "RGBA32"; + t.format = "R32UI"; t.width = res; t.height = res * Main.voxelgiClipmapCount; + t.depth = res * 3; // Store R, G, B in separate z-slices + } + else if (t.name == "voxelsOut" || t.name == "voxelsOutB") { + #if (rp_voxels == "Voxel AO") + t.format = "R8"; + #else + t.format = "RGBA32"; + #end + t.width = res * (6 + 16); + 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; - } - } + t.format = "R32UI"; + t.width = res * 6; + t.height = res; + t.depth = res * 2; #else - { - if (t.name == "voxelsOut" || t.name == "voxelsOutB") { - t.format = "RGBA32"; - 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; - } - } + t.format = "R32UI"; + t.width = res * 6; + t.height = res; + t.depth = res * 16; #end } } @@ -1063,6 +1043,20 @@ class Inc { var clipmaps = iron.RenderPath.clipmaps; var clipmap = clipmaps[iron.RenderPath.clipmapLevel]; + // Ensure all required render targets exist + if (rts.get("voxels") == null) initGI("voxels"); + if (rts.get("voxelsOut") == null) initGI("voxelsOut"); + if (rts.get("voxelsOutB") == null) initGI("voxelsOutB"); + #if (rp_voxels == "Voxel GI") + if (rts.get("voxelsLight") == null) initGI("voxelsLight"); + if (rts.get("voxelsSDF") == null) initGI("voxelsSDF"); + #elseif lnx_voxelgi_shadows + if (rts.get("voxelsSDF") == null) initGI("voxelsSDF"); + #end + + // Check again after init + if (rts.get("voxels") == null || rts.get("voxelsOutB") == null || rts.get("voxelsOut") == null) return; + kha.compute.Compute.setShader(voxel_sh1); kha.compute.Compute.setTexture(voxel_ta1, rts.get("voxels").image, kha.compute.Access.Read); diff --git a/leenkx/blender/lnx/material/make_voxel.py b/leenkx/blender/lnx/material/make_voxel.py index 7851b95..dd38f1a 100644 --- a/leenkx/blender/lnx/material/make_voxel.py +++ b/leenkx/blender/lnx/material/make_voxel.py @@ -369,7 +369,7 @@ def make_gi(context_id): frag.add_uniform('samplerCubeShadow shadowMapPoint[1]', included=True) if is_transparent_shadows: frag.add_uniform('samplerCube shadowMapPointTransparent[1]', included=True) - frag.write('direct += sampleLight(') + frag.write('direct += sampleLightVoxels(') frag.write(' P, N, vVec, dotNV, pointPos, pointCol, albedo, roughness, specular, f0') if is_shadows: frag.write(', 0, pointBias, receiveShadow')