From 728b6c0039868426341705bee4e4b140ece51dac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Mon, 30 Dec 2024 15:32:19 -0300 Subject: [PATCH] add portals/midtextures to ray-traced dynamic lights --- .../rendering/hwrenderer/data/hw_cvars.cpp | 2 +- .../descriptorsets/vk_descriptorset.cpp | 16 +++- .../rendering/vulkan/shaders/vk_shader.cpp | 1 + .../rendering/vulkan/shaders/vk_shader.h | 3 +- .../rendering/vulkan/vk_renderstate.cpp | 6 +- src/playsim/a_dynlight.h | 2 +- wadsrc/static/menudef.txt | 1 + .../shaders/lightmap/binding_lightmapper.glsl | 54 +------------- .../shaders/lightmap/binding_raytrace.glsl | 21 +----- .../lightmap/binding_struct_definitions.glsl | 73 +++++++++++++++++++ .../shaders/lightmap/binding_viewer.glsl | 56 +------------- .../shaders/lightmap/polyfill_rayquery.glsl | 5 -- .../shaders/lightmap/trace_levelmesh.glsl | 15 ++++ .../static/shaders/scene/binding_fixed.glsl | 33 +++------ wadsrc/static/shaders/scene/light_shadow.glsl | 58 +++++++++++---- 15 files changed, 168 insertions(+), 178 deletions(-) create mode 100644 wadsrc/static/shaders/lightmap/binding_struct_definitions.glsl diff --git a/src/common/rendering/hwrenderer/data/hw_cvars.cpp b/src/common/rendering/hwrenderer/data/hw_cvars.cpp index 7d8c4aa3b..cdf7cdd63 100644 --- a/src/common/rendering/hwrenderer/data/hw_cvars.cpp +++ b/src/common/rendering/hwrenderer/data/hw_cvars.cpp @@ -130,7 +130,7 @@ CVAR(Bool, gl_precache, true, CVAR_ARCHIVE) CUSTOM_CVAR(Int, gl_light_shadows, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) { - if (self < 0 || self > 3) + if (self < 0 || self > 4) self = 1; } diff --git a/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.cpp b/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.cpp index 4343612b9..2c4229c4d 100644 --- a/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.cpp +++ b/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.cpp @@ -154,9 +154,14 @@ void VkDescriptorSetManager::UpdateFixedSet() else { update.AddBuffer(Fixed.Set.get(), 5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetNodeBuffer()); - update.AddBuffer(Fixed.Set.get(), 6, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetVertexBuffer()); - update.AddBuffer(Fixed.Set.get(), 7, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetIndexBuffer()); } + + update.AddBuffer(Fixed.Set.get(), 6, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetVertexBuffer()); + update.AddBuffer(Fixed.Set.get(), 7, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetIndexBuffer()); + update.AddBuffer(Fixed.Set.get(), 8, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetSurfaceIndexBuffer()); + update.AddBuffer(Fixed.Set.get(), 9, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetSurfaceBuffer()); + update.AddBuffer(Fixed.Set.get(), 10, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetPortalBuffer()); + update.Execute(fb->GetDevice()); } @@ -280,9 +285,12 @@ void VkDescriptorSetManager::CreateFixedLayout() else { builder.AddBinding(5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT); - builder.AddBinding(6, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT); - builder.AddBinding(7, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT); } + builder.AddBinding(6, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT); + builder.AddBinding(7, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT); + builder.AddBinding(8, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT); + builder.AddBinding(9, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT); + builder.AddBinding(10, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT); builder.DebugName("VkDescriptorSetManager.Fixed.SetLayout"); Fixed.Layout = builder.Create(fb->GetDevice()); } diff --git a/src/common/rendering/vulkan/shaders/vk_shader.cpp b/src/common/rendering/vulkan/shaders/vk_shader.cpp index 622041974..66293a7c3 100644 --- a/src/common/rendering/vulkan/shaders/vk_shader.cpp +++ b/src/common/rendering/vulkan/shaders/vk_shader.cpp @@ -255,6 +255,7 @@ std::unique_ptr VkShaderManager::LoadFragShader(FString shadername if (key.Glowmap) definesBlock << "#define TEXF_Glowmap\n"; if (key.UseRaytrace) definesBlock << "#define USE_RAYTRACE\n"; + if (key.UseRaytracePrecise) definesBlock << "#define USE_RAYTRACE_PRECISE\n"; if (key.UseShadowmap) definesBlock << "#define USE_SHADOWMAP\n"; if (key.UseLevelMesh) definesBlock << "#define USE_LEVELMESH\n"; diff --git a/src/common/rendering/vulkan/shaders/vk_shader.h b/src/common/rendering/vulkan/shaders/vk_shader.h index 61dee3e72..507f968d5 100644 --- a/src/common/rendering/vulkan/shaders/vk_shader.h +++ b/src/common/rendering/vulkan/shaders/vk_shader.h @@ -100,7 +100,8 @@ public: uint64_t AlphaTestOnly : 1; // ALPHATEST_ONLY uint64_t LightBlendMode : 2; // LIGHT_BLEND_CLAMPED , LIGHT_BLEND_COLORED_CLAMP , LIGHT_BLEND_UNCLAMPED uint64_t LightAttenuationMode : 1; // LIGHT_ATTENUATION_LINEAR , LIGHT_ATTENUATION_INVERSE_SQUARE - uint64_t Unused : 37; + uint64_t UseRaytracePrecise : 1; // USE_RAYTRACE_PRECISE + uint64_t Unused : 36; }; uint64_t AsQWORD = 0; }; diff --git a/src/common/rendering/vulkan/vk_renderstate.cpp b/src/common/rendering/vulkan/vk_renderstate.cpp index 5e7d9caf8..9ff7d69f7 100644 --- a/src/common/rendering/vulkan/vk_renderstate.cpp +++ b/src/common/rendering/vulkan/vk_renderstate.cpp @@ -303,7 +303,8 @@ void VkRenderState::ApplyRenderPass(int dt) } pipelineKey.ShaderKey.UseShadowmap = gl_light_shadows == 1; - pipelineKey.ShaderKey.UseRaytrace = gl_light_shadows == 2; + pipelineKey.ShaderKey.UseRaytrace = gl_light_shadows >= 2; + pipelineKey.ShaderKey.UseRaytracePrecise = gl_light_shadows >= 3; pipelineKey.ShaderKey.GBufferPass = mRenderTarget.DrawBuffers > 1; @@ -1066,7 +1067,8 @@ void VkRenderState::ApplyLevelMeshPipeline(VulkanCommandBuffer* cmdbuffer, VkPip // Global state that don't require rebuilding the mesh pipelineKey.ShaderKey.NoFragmentShader = noFragmentShader; pipelineKey.ShaderKey.UseShadowmap = gl_light_shadows == 1; - pipelineKey.ShaderKey.UseRaytrace = gl_light_shadows == 2; + pipelineKey.ShaderKey.UseRaytrace = gl_light_shadows >= 2; + pipelineKey.ShaderKey.UseRaytracePrecise = gl_light_shadows >= 3; pipelineKey.ShaderKey.GBufferPass = mRenderTarget.DrawBuffers > 1; // State overridden by the renderstate drawing the mesh diff --git a/src/playsim/a_dynlight.h b/src/playsim/a_dynlight.h index 1860e0def..7aa834952 100644 --- a/src/playsim/a_dynlight.h +++ b/src/playsim/a_dynlight.h @@ -239,7 +239,7 @@ struct FDynamicLight bool IsSpot() const { return !!((*pLightFlags) & LF_SPOT); } bool IsAttenuated() const { return !!((*pLightFlags) & LF_ATTENUATE); } bool Trace() const { return !!((*pLightFlags) & (LF_TRACE)); } - bool TraceActors() const { return Trace() || gl_light_shadows == 2; } + bool TraceActors() const { return Trace() || gl_light_shadows >= 2; } bool DontShadowmap() const { return !!((*pLightFlags) & LF_NOSHADOWMAP); } bool DontLightSelf() const { return !!((*pLightFlags) & (LF_DONTLIGHTSELF|LF_DONTLIGHTACTORS)); } // dontlightactors implies dontlightself. bool DontLightActors() const { return !!((*pLightFlags) & LF_DONTLIGHTACTORS); } diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index fd67d171f..91df1b6a4 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -2715,6 +2715,7 @@ OptionValue ShadowMode 0, "$OPTVAL_NONE" 1, "$OPTVAL_SHADOWMAP" 2, "$OPTVAL_RAYTRACE" + 3, "$OPTVAL_RAYTRACE_PRECISE" } OptionValue ShadowFilter diff --git a/wadsrc/static/shaders/lightmap/binding_lightmapper.glsl b/wadsrc/static/shaders/lightmap/binding_lightmapper.glsl index 393a01b50..a12377cab 100644 --- a/wadsrc/static/shaders/lightmap/binding_lightmapper.glsl +++ b/wadsrc/static/shaders/lightmap/binding_lightmapper.glsl @@ -1,3 +1,4 @@ +#include layout(set = 0, binding = 0) uniform readonly Uniforms { @@ -7,63 +8,10 @@ layout(set = 0, binding = 0) uniform readonly Uniforms float SunIntensity; }; -struct SurfaceInfo -{ - vec3 Normal; - float Sky; - uint PortalIndex; - int TextureIndex; - float Alpha; - float Padding0; - uint LightStart; - uint LightEnd; - uint Padding1; - uint Padding2; -}; - -struct PortalInfo -{ - mat4 Transformation; -}; - -struct LightInfo -{ - vec3 Origin; - float Padding0; - vec3 RelativeOrigin; - float Padding1; - float Radius; - float Intensity; - float InnerAngleCos; - float OuterAngleCos; - vec3 SpotDir; - float SoftShadowRadius; - vec3 Color; - float Padding3; -}; - layout(set = 0, binding = 1) buffer readonly SurfaceIndexBuffer { uint surfaceIndices[]; }; layout(set = 0, binding = 2) buffer readonly SurfaceBuffer { SurfaceInfo surfaces[]; }; layout(set = 0, binding = 3) buffer readonly LightBuffer { LightInfo lights[]; }; layout(set = 0, binding = 4) buffer readonly LightIndexBuffer { int lightIndexes[]; }; layout(set = 0, binding = 5) buffer readonly PortalBuffer { PortalInfo portals[]; }; -struct LightmapRaytracePC -{ - int SurfaceIndex; - int Padding0; - int Padding1; - int Padding2; - vec3 WorldToLocal; - float TextureSize; - vec3 ProjLocalToU; - float Padding3; - vec3 ProjLocalToV; - float Padding4; - float TileX; - float TileY; - float TileWidth; - float TileHeight; -}; - layout(std430, set = 0, binding = 6) buffer readonly ConstantsBuffer { LightmapRaytracePC constants[]; }; diff --git a/wadsrc/static/shaders/lightmap/binding_raytrace.glsl b/wadsrc/static/shaders/lightmap/binding_raytrace.glsl index 3083d3623..0f2fa9a9d 100644 --- a/wadsrc/static/shaders/lightmap/binding_raytrace.glsl +++ b/wadsrc/static/shaders/lightmap/binding_raytrace.glsl @@ -1,3 +1,4 @@ +#include #if defined(USE_RAYQUERY) @@ -5,18 +6,6 @@ layout(set = 1, binding = 0) uniform accelerationStructureEXT acc; #else -struct CollisionNode -{ - vec3 center; - float padding1; - vec3 extents; - float padding2; - int left; - int right; - int element_index; - int padding3; -}; - layout(std430, set = 1, binding = 0) buffer readonly NodeBuffer { int nodesRoot; @@ -28,13 +17,5 @@ layout(std430, set = 1, binding = 0) buffer readonly NodeBuffer #endif -struct SurfaceVertex // Note: this must always match the FFlatVertex struct -{ - vec3 pos; - float lindex; - vec2 uv; - vec2 luv; -}; - layout(std430, set = 1, binding = 1) buffer readonly VertexBuffer { SurfaceVertex vertices[]; }; layout(std430, set = 1, binding = 2) buffer readonly ElementBuffer { int elements[]; }; diff --git a/wadsrc/static/shaders/lightmap/binding_struct_definitions.glsl b/wadsrc/static/shaders/lightmap/binding_struct_definitions.glsl new file mode 100644 index 000000000..50147ed4d --- /dev/null +++ b/wadsrc/static/shaders/lightmap/binding_struct_definitions.glsl @@ -0,0 +1,73 @@ + +struct SurfaceInfo +{ + vec3 Normal; + float Sky; + uint PortalIndex; + int TextureIndex; + float Alpha; + float Padding0; + uint LightStart; + uint LightEnd; + uint Padding1; + uint Padding2; +}; + +struct PortalInfo +{ + mat4 Transformation; +}; + +struct LightInfo +{ + vec3 Origin; + float Padding0; + vec3 RelativeOrigin; + float Padding1; + float Radius; + float Intensity; + float InnerAngleCos; + float OuterAngleCos; + vec3 SpotDir; + float SoftShadowRadius; + vec3 Color; + float Padding3; +}; + +struct CollisionNode +{ + vec3 center; + float padding1; + vec3 extents; + float padding2; + int left; + int right; + int element_index; + int padding3; +}; + +struct SurfaceVertex // Note: this must always match the FFlatVertex struct +{ + vec3 pos; + float lindex; + vec2 uv; + vec2 luv; +}; + +struct LightmapRaytracePC +{ + int SurfaceIndex; + int Padding0; + int Padding1; + int Padding2; + vec3 WorldToLocal; + float TextureSize; + vec3 ProjLocalToU; + float Padding3; + vec3 ProjLocalToV; + float Padding4; + float TileX; + float TileY; + float TileWidth; + float TileHeight; +}; \ No newline at end of file diff --git a/wadsrc/static/shaders/lightmap/binding_viewer.glsl b/wadsrc/static/shaders/lightmap/binding_viewer.glsl index 5a5dbc1b7..4b1fca5c5 100644 --- a/wadsrc/static/shaders/lightmap/binding_viewer.glsl +++ b/wadsrc/static/shaders/lightmap/binding_viewer.glsl @@ -1,38 +1,4 @@ - -struct SurfaceInfo -{ - vec3 Normal; - float Sky; - uint PortalIndex; - int TextureIndex; - float Alpha; - float Padding0; - uint LightStart; - uint LightEnd; - uint Padding1; - uint Padding2; -}; - -struct PortalInfo -{ - mat4 Transformation; -}; - -struct LightInfo -{ - vec3 Origin; - float Padding0; - vec3 RelativeOrigin; - float Padding1; - float Radius; - float Intensity; - float InnerAngleCos; - float OuterAngleCos; - vec3 SpotDir; - float SoftShadowRadius; - vec3 Color; - float Padding3; -}; +#include layout(set = 0, binding = 0, std430) buffer readonly SurfaceIndexBuffer { uint surfaceIndices[]; }; layout(set = 0, binding = 1, std430) buffer readonly SurfaceBuffer { SurfaceInfo surfaces[]; }; @@ -46,18 +12,6 @@ layout(set = 0, binding = 5) uniform accelerationStructureEXT acc; #else -struct CollisionNode -{ - vec3 center; - float padding1; - vec3 extents; - float padding2; - int left; - int right; - int element_index; - int padding3; -}; - layout(set = 0, binding = 5, std430) buffer readonly NodeBuffer { int nodesRoot; @@ -69,14 +23,6 @@ layout(set = 0, binding = 5, std430) buffer readonly NodeBuffer #endif -struct SurfaceVertex // Note: this must always match the FFlatVertex struct -{ - vec3 pos; - float lindex; - vec2 uv; - vec2 luv; -}; - layout(set = 0, binding = 6, std430) buffer readonly VertexBuffer { SurfaceVertex vertices[]; }; layout(set = 0, binding = 7, std430) buffer readonly ElementBuffer { int elements[]; }; diff --git a/wadsrc/static/shaders/lightmap/polyfill_rayquery.glsl b/wadsrc/static/shaders/lightmap/polyfill_rayquery.glsl index 4e4519a37..27faf72a6 100644 --- a/wadsrc/static/shaders/lightmap/polyfill_rayquery.glsl +++ b/wadsrc/static/shaders/lightmap/polyfill_rayquery.glsl @@ -277,8 +277,3 @@ TraceResult TraceFirstHit(vec3 origin, float tmin, vec3 dir, float tmax) } #endif - -bool traceHit(vec3 origin, vec3 direction, float dist) -{ - return TraceAnyHit(origin, 0.01f, direction, dist); -} \ No newline at end of file diff --git a/wadsrc/static/shaders/lightmap/trace_levelmesh.glsl b/wadsrc/static/shaders/lightmap/trace_levelmesh.glsl index b5f616e07..a87200a0e 100644 --- a/wadsrc/static/shaders/lightmap/trace_levelmesh.glsl +++ b/wadsrc/static/shaders/lightmap/trace_levelmesh.glsl @@ -37,6 +37,21 @@ vec3 PassRayThroughSurface(SurfaceInfo surface, vec2 uv, vec3 rayColor) } } +float PassRayThroughSurfaceDynLight(SurfaceInfo surface, vec2 uv, float rayAlpha) +{ + if (surface.TextureIndex == 0) + { + return rayAlpha; + } + else + { + vec4 color = texture(textures[surface.TextureIndex], uv); + + // Assume the renderstyle is basic alpha blend for now. + return rayAlpha * (1.0 - color.a * surface.Alpha); + } +} + void TransformRay(uint portalIndex, inout vec3 origin, inout vec3 dir) { mat4 transformationMatrix = portals[portalIndex].Transformation; diff --git a/wadsrc/static/shaders/scene/binding_fixed.glsl b/wadsrc/static/shaders/scene/binding_fixed.glsl index 9fd142ed5..0741e7dfc 100644 --- a/wadsrc/static/shaders/scene/binding_fixed.glsl +++ b/wadsrc/static/shaders/scene/binding_fixed.glsl @@ -1,3 +1,4 @@ +#include layout(set = 0, binding = 0) uniform sampler2D ShadowMap; layout(set = 0, binding = 1) uniform sampler2DArray LightMap; @@ -7,20 +8,12 @@ layout(set = 0, binding = 4) uniform samplerCubeArray PrefilterMap; #if defined(USE_RAYTRACE) #if defined(SUPPORTS_RAYQUERY) + layout(set = 0, binding = 5) uniform accelerationStructureEXT acc; + #else -struct CollisionNode -{ - vec3 center; - float padding1; - vec3 extents; - float padding2; - int left; - int right; - int element_index; - int padding3; -}; -layout(std430, set = 0, binding = 5) buffer readonly NodeBuffer + +layout(set = 0, binding = 5, std430) buffer readonly NodeBuffer { int nodesRoot; int nodebufferPadding1; @@ -28,14 +21,12 @@ layout(std430, set = 0, binding = 5) buffer readonly NodeBuffer int nodebufferPadding3; CollisionNode nodes[]; }; -struct SurfaceVertex // Note: this must always match the FFlatVertex struct -{ - vec3 pos; - float lindex; - vec2 uv; - vec2 luv; -}; -layout(std430, set = 0, binding = 6) buffer readonly VertexBuffer { SurfaceVertex vertices[]; }; -layout(std430, set = 0, binding = 7) buffer readonly ElementBuffer { int elements[]; }; + #endif + +layout(set = 0, binding = 6, std430) buffer readonly VertexBuffer { SurfaceVertex vertices[]; }; +layout(set = 0, binding = 7, std430) buffer readonly ElementBuffer { int elements[]; }; +layout(set = 0, binding = 8, std430) buffer readonly SurfaceIndexBuffer { uint surfaceIndices[]; }; +layout(set = 0, binding = 9, std430) buffer readonly SurfaceBuffer { SurfaceInfo surfaces[]; }; +layout(set = 0, binding = 10, std430) buffer readonly PortalBuffer { PortalInfo portals[]; }; #endif diff --git a/wadsrc/static/shaders/scene/light_shadow.glsl b/wadsrc/static/shaders/scene/light_shadow.glsl index 9e480e034..c9db2fc05 100644 --- a/wadsrc/static/shaders/scene/light_shadow.glsl +++ b/wadsrc/static/shaders/scene/light_shadow.glsl @@ -4,20 +4,48 @@ #if defined(USE_RAYTRACE) #include +#include +#include -vec2 getVogelDiskSample(int sampleIndex, int sampleCount, float phi) +float TraceDynLightRay(vec3 origin, float tmin, vec3 direction, float dist) { - const float goldenAngle = radians(180.0) * (3.0 - sqrt(5.0)); - float sampleIndexF = float(sampleIndex); - float sampleCountF = float(sampleCount); - - float r = sqrt((sampleIndexF + 0.5) / sampleCountF); // Assuming index and count are positive - float theta = sampleIndexF * goldenAngle + phi; - - float sine = sin(theta); - float cosine = cos(theta); - - return vec2(cosine, sine) * r; + float alpha = 1.0; + + for (int i = 0; i < 3; i++) + { + TraceResult result = TraceFirstHit(origin, tmin, direction, dist); + + // Stop if we hit nothing - the point light is visible. + if (result.primitiveIndex == -1) + return alpha; + + SurfaceInfo surface = GetSurface(result.primitiveIndex); + + // Pass through surface texture + alpha = PassRayThroughSurfaceDynLight(surface, GetSurfaceUV(result.primitiveIndex, result.primitiveWeights), alpha); + + // Stop if there is no light left + if (alpha <= 0.0) + return 0.0; + + // Move to surface hit point + origin += direction * result.t; + dist -= result.t; + + // Move through the portal, if any + TransformRay(surface.PortalIndex, origin, direction); + } + + return 0.0; +} + +float traceHit(vec3 origin, vec3 direction, float dist) +{ + #if defined(USE_RAYTRACE_PRECISE) + return TraceDynLightRay(origin, 0.01f, direction, dist); + #else + return TraceAnyHit(origin, 0.01f, direction, dist) ? 0.0 : 1.0; + #endif } float traceShadow(vec4 lightpos, int quality, float softShadowRadius) @@ -30,7 +58,7 @@ float traceShadow(vec4 lightpos, int quality, float softShadowRadius) if (quality == 0 || softShadowRadius == 0) { - return traceHit(origin, direction, dist) ? 0.0 : 1.0; + return traceHit(origin, direction, dist); } else { @@ -44,9 +72,9 @@ float traceShadow(vec4 lightpos, int quality, float softShadowRadius) { vec2 gridoffset = getVogelDiskSample(i, step_count, gl_FragCoord.x + gl_FragCoord.y * 13.37) * softShadowRadius; vec3 pos = target + xdir * gridoffset.x + ydir * gridoffset.y; - sum += traceHit(origin, normalize(pos - origin), dist) ? 0.0 : 1.0; + sum += traceHit(origin, normalize(pos - origin), dist); } - return sum / step_count; + return (sum / step_count); } }