Skip to content

Conversation

@Breakdown-Dog
Copy link
Contributor

Objective

  • In the depth_of_field example, setting focal_distance to a small value (<= 0.02) causes the DoF effect to disappear unexpectedly.
before
  • I believe that a small focal_distance makes (focus - f) zero or negative. This leads to a non-positive candidate_coc, which is then clamped to 0.0, effectively disabling the DoF effect.

  • Although the formula is physically accurate, we cannot assume users have a deep understanding of the depth of field effect. This will make them confused.

Solution

  • Use max(focus - f, EPSILON) to ensure the denominator is always positive.

  • Now, the effect looks correct.

later

Testing

  • CI

@Breakdown-Dog Breakdown-Dog changed the title Use max(focus - f, EPSILON) to ensure the denominator is always Prevent DoF effect disappearing at small focus_distances Nov 12, 2025
@JMS55 JMS55 added C-Bug An unexpected or incorrect behavior A-Rendering Drawing game state to the screen S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Nov 12, 2025
@Breakdown-Dog
Copy link
Contributor Author

Seems the CI failed because the  heapless  crate update caused Bevy to use a deprecated method. May need another PR to fix this issue.

@group(1) @binding(1) var color_texture_sampler: sampler;

// used to ensure `depth * (focus - f)` is always a positive number,
const EPSILON: f32 = 1.19209290e-07;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use f32::EPSILON, no need to define a custom constant.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried using  f32::EPSILON  in WGSL, but it seems this constant isn't provided by the language. So I just copied the value from Rust's standard library and defined a custom constant in my WGSL code.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I completely forgot this was wgsl and not rust. Ignore that 😅

//
// [1]: https://en.wikipedia.org/wiki/Circle_of_confusion#Determining_a_circle_of_confusion_diameter_from_the_object_field
let candidate_coc = scale * abs(depth - focus) / (depth * (focus - f));
let candidate_coc = scale * abs(depth - focus) / (depth * max(focus - f, EPSILON));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let candidate_coc = scale * abs(depth - focus) / (depth * max(focus - f, EPSILON));
let candidate_coc = scale * abs(depth - focus) / (depth * max(focus - f, f32::EPSILON));

@mockersf mockersf added this pull request to the merge queue Nov 12, 2025
Merged via the queue into bevyengine:main with commit 2930d9f Nov 12, 2025
42 of 43 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-Rendering Drawing game state to the screen C-Bug An unexpected or incorrect behavior S-Needs-Review Needs reviewer attention (from anyone!) to move forward

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants