Add march from fog to light for occlusion

This commit is contained in:
Lauri Räsänen 2023-11-11 16:43:07 +02:00
parent f4a7253922
commit 5497e8d6ce
2 changed files with 38 additions and 15 deletions

View file

@ -7,6 +7,9 @@ const SHADOW_SAMPLES = 2;
const INV_SHADOW_SAMPLES = 1.0 / 25.0;
const FOG_MAX_STEPS = 30;
const FOG_STEP_SIZE = 5.0;
const FOG_LIGHT_MAX_STEPS = 10;
const FOG_LIGHT_STEP_SIZE = 10.0;
const FOG_DENSITY = 2.0;
const FOG_LIGHT_DENSITY = 3.0;
const FOG_ALPHA = 1.0;
const FOG_BLEND_STEPS = 4;

View file

@ -61,27 +61,45 @@ fn fog_noise(pos: vec3<f32>) -> f32 {
return 0.8 * noise1 + 0.2 * noise2;
}
fn ray_march(origin: vec3<f32>, direction: vec3<f32>, scene_depth: f32) -> vec2<f32> {
fn ray_march(origin: vec3<f32>, direction: vec3<f32>, max_depth: f32, max_steps: i32, step_size: f32, fog_density: f32) -> vec2<f32> {
var density = 0.0;
var depth = 0.0;
for (var i = 0; i < FOG_MAX_STEPS; i++)
for (var i = 0; i < max_steps; i++)
{
depth += step_size;
if (depth >= max_depth)
{
break;
}
let noise = fog_noise(origin + direction * depth);
depth += FOG_STEP_SIZE;
let blend = min(f32(i + 1) / f32(FOG_BLEND_STEPS), 1.0);
let contribution = FOG_DENSITY / f32(FOG_MAX_STEPS);
let contribution = fog_density / f32(max_steps);
density += blend * noise * contribution;
if (density >= 1.0)
{
density = 1.0;
break;
}
if (depth >= scene_depth)
{
break;
}
return vec2(density, depth);
}
return vec2<f32>(density, depth);
fn ray_march_fog(origin: vec3<f32>, direction: vec3<f32>, scene_depth: f32) -> vec3<f32> {
// march into the fog volume
let fog_march = ray_march(origin, direction, scene_depth, FOG_MAX_STEPS, FOG_STEP_SIZE, FOG_DENSITY);
let fog_density = fog_march.x;
let fog_depth = fog_march.y;
let fog_end_position = origin + direction * fog_depth;
// march from fog volume to the light
let fog_to_light = light.position - fog_end_position;
let max_light_dist = length(fog_to_light);
let light_direction = fog_to_light / max_light_dist;
let light_march = ray_march(fog_end_position, light_direction, max_light_dist, FOG_LIGHT_MAX_STEPS, FOG_LIGHT_STEP_SIZE, FOG_LIGHT_DENSITY);
let occlusion = light_march.x;
return vec3<f32>(fog_density, fog_depth, occlusion);
}
fn depth_to_linear(depth: f32) -> f32 {
@ -93,7 +111,8 @@ fn depth_to_linear(depth: f32) -> f32 {
@fragment
fn fs_main(vert: FogVertexOutput) -> @location(0) vec4<f32> {
let direction = normalize(vert.world_position.xyz - camera.position.xyz);
let origin = vert.world_position.xyz;
let direction = normalize(origin - camera.position.xyz);
let volume_depth = depth_to_linear(vert.clip_position.z);
let uv = vert.clip_position.xy / camera.planes.zw;
let geometry_depth = depth_to_linear(textureSample(t_geometry_depth, s_geometry_depth, uv));
@ -103,12 +122,13 @@ fn fs_main(vert: FogVertexOutput) -> @location(0) vec4<f32> {
return vec4<f32>(0.0);
}
let dd = ray_march(vert.world_position.xyz, direction, max_fog_depth);
let fog_density = dd.x;
let fog_depth = dd.y;
let march_result = ray_march_fog(origin, direction, max_fog_depth);
let fog_density = march_result.x;
let fog_depth = march_result.y;
let occlusion = march_result.z;
var base_color = vec3<f32>(mix(0.5, 0.1, fog_density));
let ambient_strength = 0.04;
let ambient_strength = 0.05;
let ambient_color = base_color * ambient_strength;
var radiance = vec3<f32>(0.0);
@ -121,7 +141,7 @@ fn fs_main(vert: FogVertexOutput) -> @location(0) vec4<f32> {
let coef_b = 1.0;
let light_attenuation = 1.0 / (1.0 + coef_a * light_dist + coef_b * light_dist * light_dist);
radiance = light.color.rgb * light.color.a * light_attenuation * in_light;
radiance = light.color.rgb * light.color.a * light_attenuation * in_light * (1.0 - occlusion);
}
var result = ambient_color + radiance;