From 4e8e3aa54688366a65ba4bc7eaf733eb0423e2c5 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Thu, 28 Sep 2023 22:32:53 +0200 Subject: [PATCH] Add soft shadows the lightmapper --- .../shaders/lightmap/frag_raytrace.glsl | 2 + .../shaders/lightmap/trace_levelmesh.glsl | 1 + .../static/shaders/lightmap/trace_light.glsl | 39 +++++++++++++++++++ .../shaders/lightmap/trace_sunlight.glsl | 32 +++++++++++++++ 4 files changed, 74 insertions(+) diff --git a/wadsrc/static/shaders/lightmap/frag_raytrace.glsl b/wadsrc/static/shaders/lightmap/frag_raytrace.glsl index 26c58502d..b499cf59e 100644 --- a/wadsrc/static/shaders/lightmap/frag_raytrace.glsl +++ b/wadsrc/static/shaders/lightmap/frag_raytrace.glsl @@ -1,4 +1,6 @@ +#define USE_SOFTSHADOWS + #include #include #include diff --git a/wadsrc/static/shaders/lightmap/trace_levelmesh.glsl b/wadsrc/static/shaders/lightmap/trace_levelmesh.glsl index 5487c2207..f5f08832c 100644 --- a/wadsrc/static/shaders/lightmap/trace_levelmesh.glsl +++ b/wadsrc/static/shaders/lightmap/trace_levelmesh.glsl @@ -149,3 +149,4 @@ vec4 blend(vec4 a, vec4 b) { return BeerLambertSimple(vec4(1.0 - a.rgb, a.w), b); } + diff --git a/wadsrc/static/shaders/lightmap/trace_light.glsl b/wadsrc/static/shaders/lightmap/trace_light.glsl index 3b801e634..bb7189df1 100644 --- a/wadsrc/static/shaders/lightmap/trace_light.glsl +++ b/wadsrc/static/shaders/lightmap/trace_light.glsl @@ -1,4 +1,6 @@ +vec2 getVogelDiskSample(int sampleIndex, int sampleCount, float phi); + vec3 TraceLight(vec3 origin, vec3 normal, LightInfo light, int surfaceIndex) { const float minDistance = 0.01; @@ -25,13 +27,50 @@ vec3 TraceLight(vec3 origin, vec3 normal, LightInfo light, int surfaceIndex) float attenuation = distAttenuation * angleAttenuation * spotAttenuation; if (attenuation > 0.0) { +#if defined(USE_SOFTSHADOWS) + + vec3 v = (abs(dir.x) > abs(dir.y)) ? vec3(0.0, 1.0, 0.0) : vec3(1.0, 0.0, 0.0); + vec3 xdir = normalize(cross(dir, v)); + vec3 ydir = cross(dir, xdir); + + float lightsize = 10; + int step_count = 16; + for (int i = 0; i < step_count; i++) + { + vec2 gridoffset = getVogelDiskSample(i, step_count, gl_FragCoord.x + gl_FragCoord.y * 13.37) * lightsize; + vec3 pos = light.Origin + xdir * gridoffset.x + ydir * gridoffset.y; + + rayColor = vec4(light.Color.rgb, 1.0); + if (TracePoint(origin, pos, minDistance, normalize(pos - origin), distance(origin, pos))) + { + incoming.rgb += (rayColor.rgb * rayColor.w) * (attenuation * light.Intensity) / float(step_count); + } + } + +#else rayColor = vec4(light.Color.rgb, 1.0); if(TracePoint(origin, light.Origin, minDistance, dir, dist)) { incoming.rgb += (rayColor.rgb * rayColor.w) * (attenuation * light.Intensity); } +#endif } } return incoming; } + +vec2 getVogelDiskSample(int sampleIndex, int sampleCount, float phi) +{ + 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; +} diff --git a/wadsrc/static/shaders/lightmap/trace_sunlight.glsl b/wadsrc/static/shaders/lightmap/trace_sunlight.glsl index 375583266..1908c55bb 100644 --- a/wadsrc/static/shaders/lightmap/trace_sunlight.glsl +++ b/wadsrc/static/shaders/lightmap/trace_sunlight.glsl @@ -1,10 +1,39 @@ +vec2 getVogelDiskSample(int sampleIndex, int sampleCount, float phi); + vec3 TraceSunLight(vec3 origin) { const float minDistance = 0.01; vec3 incoming = vec3(0.0); const float dist = 32768.0; +#if defined(USE_SOFTSHADOWS) + + vec3 target = origin + SunDir * dist; + vec3 dir = SunDir; + vec3 v = (abs(dir.x) > abs(dir.y)) ? vec3(0.0, 1.0, 0.0) : vec3(1.0, 0.0, 0.0); + vec3 xdir = normalize(cross(dir, v)); + vec3 ydir = cross(dir, xdir); + + float lightsize = 100; + int step_count = 16; + for (int i = 0; i < step_count; i++) + { + vec2 gridoffset = getVogelDiskSample(i, step_count, gl_FragCoord.x + gl_FragCoord.y * 13.37) * lightsize; + vec3 pos = target + xdir * gridoffset.x + ydir * gridoffset.y; + + rayColor = vec4(SunColor.rgb * SunIntensity, 1.0); + + int primitiveID = TraceFirstHitTriangle(origin, minDistance, normalize(pos - origin), dist); + if (primitiveID != -1) + { + SurfaceInfo surface = surfaces[surfaceIndices[primitiveID]]; + incoming.rgb += rayColor.rgb * rayColor.w * surface.Sky / float(step_count); + } + } + +#else + rayColor = vec4(SunColor.rgb * SunIntensity, 1.0); int primitiveID = TraceFirstHitTriangle(origin, minDistance, SunDir, dist); @@ -13,5 +42,8 @@ vec3 TraceSunLight(vec3 origin) SurfaceInfo surface = surfaces[surfaceIndices[primitiveID]]; incoming.rgb = rayColor.rgb * rayColor.w * surface.Sky; } + +#endif + return incoming; }