From 95098711f772756abf3b8d7e7201409b650661d4 Mon Sep 17 00:00:00 2001 From: TheRedShip Date: Tue, 14 Jan 2025 10:27:06 +0100 Subject: [PATCH] + | New file for volumetric --- shaders/compute.glsl | 89 ++++------------------------------------- shaders/light.glsl | 53 ++++++++++++++++++++++++ shaders/random.glsl | 19 --------- shaders/volumetric.glsl | 60 +++++++++++++++++++++++++++ 4 files changed, 120 insertions(+), 101 deletions(-) create mode 100644 shaders/light.glsl create mode 100644 shaders/volumetric.glsl diff --git a/shaders/compute.glsl b/shaders/compute.glsl index 91284a4..8430e8b 100644 --- a/shaders/compute.glsl +++ b/shaders/compute.glsl @@ -80,6 +80,8 @@ struct hitInfo #include "shaders/random.glsl" #include "shaders/intersect.glsl" #include "shaders/scatter.glsl" +#include "shaders/light.glsl" +#include "shaders/volumetric.glsl" Ray portalRay(Ray ray, hitInfo hit) { @@ -139,68 +141,6 @@ hitInfo traceRay(Ray ray) return (hit); } -float sampleHG(float g, inout uint rng_state) -{ - if (abs(g) < 0.001) - return 2.0 * randomValue(rng_state) - 1.0; - - float sqr_term = (1.0 - g * g) / (1.0 + g - 2.0 * g * randomValue(rng_state)); - return (1.0 + g * g - sqr_term * sqr_term) / (2.0 * g); -} - -vec3 sampleDirection(vec3 forward, float cos_theta, inout uint rng_state) -{ - float phi = 2.0 * M_PI * randomValue(rng_state); - float sin_theta = sqrt(max(0.0, 1.0 - cos_theta * cos_theta)); - - vec3 dir; - dir.x = sin_theta * cos(phi); - dir.y = sin_theta * sin(phi); - dir.z = cos_theta; - - vec3 up = abs(forward.z) < 0.999 ? vec3(0, 0, 1) : vec3(1, 0, 0); - vec3 right = normalize(cross(up, forward)); - up = cross(forward, right); - - return normalize( - dir.x * right + - dir.y * up + - dir.z * forward - ); -} - -vec3 sampleLights(vec3 position) -{ - vec3 light = vec3(0.0); - - for (int i = 0; i < u_objectsNum; i++) - { - GPUObject obj = objects[i]; - GPUMaterial mat = materials[obj.mat_index]; - - if (obj.type == 0 && mat.emission > 0.0) - { - vec3 light_dir = normalize(obj.position - position); - float light_dist = length(obj.position - position); - - Ray shadow_ray = Ray(position + light_dir * 0.01, light_dir); - hitInfo shadow_hit = traceRay(shadow_ray); - - if (shadow_hit.obj_index == i) - light += mat.emission * mat.color / (light_dist); - } - } - - return (light); -} - -struct VolumeProperties { - vec3 sigma_a; // absorption coefficient - vec3 sigma_s; // scattering coefficient - vec3 sigma_t; // extinction coefficient - float g; // phase function parameter -}; - vec3 pathtrace(Ray ray, inout uint rng_state) { vec3 color = vec3(1.0); @@ -218,23 +158,10 @@ vec3 pathtrace(Ray ray, inout uint rng_state) { hitInfo hit = traceRay(ray); - float t_scatter = -log(randomValue(rng_state)) / volume.sigma_t.x; - float t_surface = hit.t; - - if (t_scatter < t_surface && volume.sigma_t.x > 0.0) + float t_scatter = 0.0; + if (atmosScatter(volume, hit, t_scatter, rng_state)) { - vec3 scatter_pos = ray.origin + ray.direction * t_scatter; - - transmittance *= exp(-volume.sigma_t * t_scatter); - color *= volume.sigma_s / volume.sigma_t; - - light += transmittance * color * sampleLights(scatter_pos); - - float cos_theta = sampleHG(volume.g, rng_state); - vec3 new_dir = sampleDirection(ray.direction, cos_theta, rng_state); - - ray.origin = scatter_pos; - ray.direction = new_dir; + calculateVolumetricLight(t_scatter, volume, ray, color, light, transmittance, rng_state); continue; } @@ -245,7 +172,7 @@ vec3 pathtrace(Ray ray, inout uint rng_state) break; } - transmittance *= exp(-volume.sigma_t * t_surface); + transmittance *= exp(-volume.sigma_t * hit.t); GPUObject obj = objects[hit.obj_index]; GPUMaterial mat = materials[obj.mat_index]; @@ -257,9 +184,7 @@ vec3 pathtrace(Ray ray, inout uint rng_state) color /= p; // - color *= mat.color; - light += mat.emission * mat.color; - // light += sampleLights(hit.position); + calculateLightColor(color, light, mat, hit); if (mat.emission > 0.0) break; diff --git a/shaders/light.glsl b/shaders/light.glsl new file mode 100644 index 0000000..49e5bc8 --- /dev/null +++ b/shaders/light.glsl @@ -0,0 +1,53 @@ + +vec3 GetEnvironmentLight(Ray ray) +{ + vec3 sun_pos = vec3(-1., 1.0, 0.); + float SunFocus = 1.5; + float SunIntensity = 0.5; + + vec3 GroundColour = vec3(0.5, 0.5, 0.5); + vec3 SkyColourHorizon = vec3(135 / 255.0f, 206 / 255.0f, 235 / 255.0f); + vec3 SkyColourZenith = SkyColourHorizon / 2.0; + + float skyGradientT = pow(smoothstep(0.0, 0.4, ray.direction.y), 0.35); + float groundToSkyT = smoothstep(-0.01, 0.0, ray.direction.y); + vec3 skyGradient = mix(SkyColourHorizon, SkyColourZenith, skyGradientT); + float sun = pow(max(0, dot(ray.direction, sun_pos.xyz)), SunFocus) * SunIntensity; + // Combine ground, sky, and sun + vec3 composite = mix(GroundColour, skyGradient, groundToSkyT) + sun * int(groundToSkyT >= 1); + return composite; +} + +hitInfo traceRay(Ray ray); + +vec3 sampleLights(vec3 position) +{ + vec3 light = vec3(0.0); + + for (int i = 0; i < u_objectsNum; i++) + { + GPUObject obj = objects[i]; + GPUMaterial mat = materials[obj.mat_index]; + + if (obj.type == 0 && mat.emission > 0.0) + { + vec3 light_dir = normalize(obj.position - position); + float light_dist = length(obj.position - position); + + Ray shadow_ray = Ray(position + light_dir * 0.01, light_dir); + hitInfo shadow_hit = traceRay(shadow_ray); + + if (shadow_hit.obj_index == i) + light += mat.emission * mat.color / (light_dist); + } + } + + return (light); +} + +void calculateLightColor(inout vec3 color, inout vec3 light, GPUMaterial mat, hitInfo hit) +{ + color *= mat.color; + light += mat.emission * mat.color; + // light += sampleLights(hit.position); +} \ No newline at end of file diff --git a/shaders/random.glsl b/shaders/random.glsl index a6b689b..76b4757 100644 --- a/shaders/random.glsl +++ b/shaders/random.glsl @@ -35,22 +35,3 @@ vec3 randomHemisphereDirection(vec3 normal, inout uint rng_state) vec3 direction = randomDirection(rng_state); return (direction * sign(dot(normal, direction))); } - -vec3 GetEnvironmentLight(Ray ray) -{ - vec3 sun_pos = vec3(-1., 1.0, 0.); - float SunFocus = 1.5; - float SunIntensity = 0.5; - - vec3 GroundColour = vec3(0.5, 0.5, 0.5); - vec3 SkyColourHorizon = vec3(135 / 255.0f, 206 / 255.0f, 235 / 255.0f); - vec3 SkyColourZenith = SkyColourHorizon / 2.0; - - float skyGradientT = pow(smoothstep(0.0, 0.4, ray.direction.y), 0.35); - float groundToSkyT = smoothstep(-0.01, 0.0, ray.direction.y); - vec3 skyGradient = mix(SkyColourHorizon, SkyColourZenith, skyGradientT); - float sun = pow(max(0, dot(ray.direction, sun_pos.xyz)), SunFocus) * SunIntensity; - // Combine ground, sky, and sun - vec3 composite = mix(GroundColour, skyGradient, groundToSkyT) + sun * int(groundToSkyT >= 1); - return composite; -} diff --git a/shaders/volumetric.glsl b/shaders/volumetric.glsl new file mode 100644 index 0000000..239517d --- /dev/null +++ b/shaders/volumetric.glsl @@ -0,0 +1,60 @@ + +struct VolumeProperties { + vec3 sigma_a; // absorption coefficient + vec3 sigma_s; // scattering coefficient + vec3 sigma_t; // extinction coefficient + float g; // phase function parameter +}; + +float sampleHG(float g, inout uint rng_state) +{ + if (abs(g) < 0.001) + return 2.0 * randomValue(rng_state) - 1.0; + + float sqr_term = (1.0 - g * g) / (1.0 + g - 2.0 * g * randomValue(rng_state)); + return (1.0 + g * g - sqr_term * sqr_term) / (2.0 * g); +} + +vec3 sampleDirection(vec3 forward, float cos_theta, inout uint rng_state) +{ + float phi = 2.0 * M_PI * randomValue(rng_state); + float sin_theta = sqrt(max(0.0, 1.0 - cos_theta * cos_theta)); + + vec3 dir; + dir.x = sin_theta * cos(phi); + dir.y = sin_theta * sin(phi); + dir.z = cos_theta; + + vec3 up = abs(forward.z) < 0.999 ? vec3(0, 0, 1) : vec3(1, 0, 0); + vec3 right = normalize(cross(up, forward)); + up = cross(forward, right); + + return normalize( + dir.x * right + + dir.y * up + + dir.z * forward + ); +} + +bool atmosScatter(VolumeProperties volume, hitInfo hit, inout float t_scatter, inout uint rng_state) +{ + t_scatter = -log(randomValue(rng_state)) / volume.sigma_t.x; + + return (t_scatter < hit.t && volume.sigma_t.x > 0.0); +} + +void calculateVolumetricLight(float t_scatter, VolumeProperties volume, inout Ray ray, inout vec3 color, inout vec3 light, inout vec3 transmittance, inout uint rng_state) +{ + vec3 scatter_pos = ray.origin + ray.direction * t_scatter; + + transmittance *= exp(-volume.sigma_t * t_scatter); + color *= volume.sigma_s / volume.sigma_t; + + light += transmittance * color * sampleLights(scatter_pos); + + float cos_theta = sampleHG(volume.g, rng_state); + vec3 new_dir = sampleDirection(ray.direction, cos_theta, rng_state); + + ray.origin = scatter_pos; + ray.direction = new_dir; +}