Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion crates/bevy_pbr/src/volumetric_fog/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -818,7 +818,7 @@ fn get_far_planes(view_from_local: &Affine3A) -> [Vec4; 3] {
continue;
}

let view_position = view_from_local.transform_point3a(-local_normal * 0.5);
let view_position = view_from_local.transform_point3a(local_normal * 0.5);
let plane_coords = view_normal.extend(-view_normal.dot(view_position));

far_planes[next_index] = plane_coords;
Expand Down Expand Up @@ -890,3 +890,24 @@ fn calculate_fog_volume_clip_from_local_transforms(
vec4(0.0, 0.0, z_near, z_near),
)
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn get_far_planes_identity_has_correct_z_plane_position() {
let far_planes = get_far_planes(&Affine3A::IDENTITY);

let z_plane = far_planes[0];
assert_eq!(z_plane.truncate(), Vec3::Z);
assert!((z_plane.w + 0.5).abs() < 1e-6);

let z_face_point = Vec3::new(0.0, 0.0, 0.5);
let plane_eval = z_plane.truncate().dot(z_face_point) + z_plane.w;
assert!(plane_eval.abs() < 1e-6);

assert_eq!(far_planes[1], Vec4::ZERO);
assert_eq!(far_planes[2], Vec4::ZERO);
}
}
26 changes: 17 additions & 9 deletions crates/bevy_pbr/src/volumetric_fog/volumetric_fog.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,10 @@ fn fragment(@builtin(position) position: vec4<f32>) -> @location(0) vec4<f32> {
// faces of the AABB, this is the current fragment's depth.
let view_start_pos = position_ndc_to_view(frag_coord_to_ndc(frag_coord));

// Calculate the ray direction in view space (needed for AABB intersection)
let Rd_ndc = vec3(frag_coord_to_ndc(position).xy, 1.0);
let Rd_view = normalize(position_ndc_to_view(Rd_ndc));

// Calculate the end position of the ray. This requires us to raytrace the
// three back faces of the AABB to find the one that our ray intersects.
var end_depth_view = 0.0;
Expand All @@ -150,13 +154,20 @@ fn fragment(@builtin(position) position: vec4<f32>) -> @location(0) vec4<f32> {
let other_plane_a = volumetric_fog.far_planes[(plane_index + 1) % 3];
let other_plane_b = volumetric_fog.far_planes[(plane_index + 2) % 3];

// Calculate the intersection of the ray and the plane. The ray must
// intersect in front of us (t > 0).
let t = -plane.w / dot(plane.xyz, view_start_pos.xyz);
// Calculate the intersection of the ray and the plane using proper ray-plane intersection.
// Ray: P = view_start_pos + Rd_view * t
// Plane: dot(plane.xyz, P) + plane.w = 0
let denom = dot(plane.xyz, Rd_view);
if (abs(denom) < 0.0001) {
// Ray is parallel to plane
continue;
}
let t = -(dot(plane.xyz, view_start_pos.xyz) + plane.w) / denom;
if (t < 0.0) {
// Intersection is behind the ray start
continue;
}
let hit_pos = view_start_pos.xyz * t;
let hit_pos = view_start_pos.xyz + Rd_view * t;

// The intersection point must be in front of the other backfaces.
let other_sides = vec2(
Expand All @@ -183,16 +194,13 @@ fn fragment(@builtin(position) position: vec4<f32>) -> @location(0) vec4<f32> {

let directional_light_count = lights.n_directional_lights;

// Calculate the ray origin (`Ro`) and the ray direction (`Rd`) in NDC,
// view, and world coordinates.
let Rd_ndc = vec3(frag_coord_to_ndc(position).xy, 1.0);
let Rd_view = normalize(position_ndc_to_view(Rd_ndc));
// Calculate the ray origin (`Ro`) and the ray direction (`Rd`) in world coordinates.
var Ro_world = position_view_to_world(view_start_pos.xyz);
let Rd_world = normalize(position_ndc_to_world(Rd_ndc) - view.world_position);

// Offset by jitter.
let jitter = interleaved_gradient_noise(position.xy, globals.frame_count) * jitter_strength;
Ro_world += Rd_world * jitter;
Ro_world += Rd_world * jitter * step_size_world;

// Use Beer's law [1] [2] to calculate the maximum amount of light that each
// directional light could contribute, and modulate that value by the light
Expand Down
Loading