hannobraun / fornjot

Early-stage b-rep CAD kernel, written in the Rust programming language.
https://www.fornjot.app/
Other
2.01k stars 113 forks source link

Improve shading to properly display blind holes #2161

Open hannobraun opened 8 months ago

hannobraun commented 8 months ago

Problem

This is how blind holes currently look: Screenshot from 2024-01-16 11-28-41

You can reproduce this picture, by running cargo run -p holes from the repository root, then rotating (drag while left mouse button is pressed) and moving (drag while right mouse button is pressed) the model until you see the blind hole.

As you can see in this screenshot, the surface of the part and the bottom of the blind hole look exactly the same. This is because they are parallel, and the shading only depends on the angle between a surface and the viewing direction.

Solution

I'm not an expert on graphics, and I'm sure there are many ways to improve this. If you know of one, feel free to implement it!

The solution that comes to my mind, is to make shading also depend on the distance to the camera. This would have to be carefully tuned, to make cases as the one shown in the screenshot look decent, without making far-away parts completely black. It might make sense to clamp the result in such a way, that the effect of distance can never make a part too dark.

Implementation

Rendering is implemented in the fj-viewer crate, specifically within shader.wgsl. It's possible that this issue can be completely addressed with only changes to the linked shader function. It's also possible (especially, if a more advanced solution is chosen), that this requires changes to the larger graphics system.

In any case, implementing this will only require knowledge shader languages (I'm guessing that WGSL is pretty easy to understand for anyone familiar with other shader languages), and possibly Rust and wgpu. It won't require knowledge of other Fornjot internals. For this reason, I'm tagging this as a https://github.com/hannobraun/fornjot/labels/good%20first%20issue.

felix91gr commented 1 month ago

It's been a long while since I've done shader programming, but as far as I'm aware the canonical way that these kinds of shadows are computed and drawn is Shadow Mapping.

https://github.com/gfx-rs/wgpu/tree/trunk/examples/src/shadow I'm going to see if I can extract the design from the wgpu-rs examples, and will ping you back if I do :)

felix91gr commented 1 month ago

Okay I think I'm right regarding the shadow map, but currently I'm not able to work on this.

hannobraun commented 1 month ago

Thank you for the feedback, @felix91gr, but we're talking about different things!

I'm talking about shading, not shadows. See the side walls of the hole in the screenshot above. Those are shaded (in this case made darker), based on the viewing angle of the triangles. If shading did not only depend on viewing angle, but also on distance, then the bottom of the whole would have a color that's distinct from the top surface of the part.

I don't know if shadows would be a benefit for rendering CAD models. But either way, I don't think I would want to merge them, if there was a pull request. This is just a simple renderer to augment the kernel, for testing and demonstration purposes. I'd like to leave anything that's complicated to third-party renderers.