bevy/examples/3d
Marco Buono 44928e0df4
StandardMaterial Light Transmission (#8015)
# Objective

<img width="1920" alt="Screenshot 2023-04-26 at 01 07 34"
src="https://user-images.githubusercontent.com/418473/234467578-0f34187b-5863-4ea1-88e9-7a6bb8ce8da3.png">

This PR adds both diffuse and specular light transmission capabilities
to the `StandardMaterial`, with support for screen space refractions.
This enables realistically representing a wide range of real-world
materials, such as:

  - Glass; (Including frosted glass)
  - Transparent and translucent plastics;
  - Various liquids and gels;
  - Gemstones;
  - Marble;
  - Wax;
  - Paper;
  - Leaves;
  - Porcelain.

Unlike existing support for transparency, light transmission does not
rely on fixed function alpha blending, and therefore works with both
`AlphaMode::Opaque` and `AlphaMode::Mask` materials.

## Solution

- Introduces a number of transmission related fields in the
`StandardMaterial`;
- For specular transmission:
- Adds logic to take a view main texture snapshot after the opaque
phase; (in order to perform screen space refractions)
- Introduces a new `Transmissive3d` phase to the renderer, to which all
meshes with `transmission > 0.0` materials are sent.
- Calculates a light exit point (of the approximate mesh volume) using
`ior` and `thickness` properties
- Samples the snapshot texture with an adaptive number of taps across a
`roughness`-controlled radius enabling “blurry” refractions
- For diffuse transmission:
- Approximates transmitted diffuse light by using a second, flipped +
displaced, diffuse-only Lambertian lobe for each light source.

## To Do

- [x] Figure out where `fresnel_mix()` is taking place, if at all, and
where `dielectric_specular` is being calculated, if at all, and update
them to use the `ior` value (Not a blocker, just a nice-to-have for more
correct BSDF)
- To the _best of my knowledge, this is now taking place, after
964340cdd. The fresnel mix is actually "split" into two parts in our
implementation, one `(1 - fresnel(...))` in the transmission, and
`fresnel()` in the light implementations. A surface with more
reflectance now will produce slightly dimmer transmission towards the
grazing angle, as more of the light gets reflected.
- [x] Add `transmission_texture`
- [x] Add `diffuse_transmission_texture`
- [x] Add `thickness_texture`
- [x] Add `attenuation_distance` and `attenuation_color`
- [x] Connect values to glTF loader
  - [x] `transmission` and `transmission_texture`
  - [x] `thickness` and `thickness_texture`
  - [x] `ior`
- [ ] `diffuse_transmission` and `diffuse_transmission_texture` (needs
upstream support in `gltf` crate, not a blocker)
- [x] Add support for multiple screen space refraction “steps”
- [x] Conditionally create no transmission snapshot texture at all if
`steps == 0`
- [x] Conditionally enable/disable screen space refraction transmission
snapshots
- [x] Read from depth pre-pass to prevent refracting pixels in front of
the light exit point
- [x] Use `interleaved_gradient_noise()` function for sampling blur in a
way that benefits from TAA
- [x] Drill down a TAA `#define`, tweak some aspects of the effect
conditionally based on it
- [x] Remove const array that's crashing under HLSL (unless a new `naga`
release with https://github.com/gfx-rs/naga/pull/2496 comes out before
we merge this)
- [ ] Look into alternatives to the `switch` hack for dynamically
indexing the const array (might not be needed, compilers seem to be
decent at expanding it)
- [ ] Add pipeline keys for gating transmission (do we really want/need
this?)
- [x] Tweak some material field/function names?

## A Note on Texture Packing

_This was originally added as a comment to the
`specular_transmission_texture`, `thickness_texture` and
`diffuse_transmission_texture` documentation, I removed it since it was
more confusing than helpful, and will likely be made redundant/will need
to be updated once we have a better infrastructure for preprocessing
assets_

Due to how channels are mapped, you can more efficiently use a single
shared texture image
for configuring the following:

- R - `specular_transmission_texture`
- G - `thickness_texture`
- B - _unused_
- A - `diffuse_transmission_texture`

The `KHR_materials_diffuse_transmission` glTF extension also defines a
`diffuseTransmissionColorTexture`,
that _we don't currently support_. One might choose to pack the
intensity and color textures together,
using RGB for the color and A for the intensity, in which case this
packing advice doesn't really apply.

---

## Changelog

- Added a new `Transmissive3d` render phase for rendering specular
transmissive materials with screen space refractions
- Added rendering support for transmitted environment map light on the
`StandardMaterial` as a fallback for screen space refractions
- Added `diffuse_transmission`, `specular_transmission`, `thickness`,
`ior`, `attenuation_distance` and `attenuation_color` to the
`StandardMaterial`
- Added `diffuse_transmission_texture`, `specular_transmission_texture`,
`thickness_texture` to the `StandardMaterial`, gated behind a new
`pbr_transmission_textures` cargo feature (off by default, for maximum
hardware compatibility)
- Added `Camera3d::screen_space_specular_transmission_steps` for
controlling the number of “layers of transparency” rendered for
transmissive objects
- Added a `TransmittedShadowReceiver` component for enabling shadows in
(diffusely) transmitted light. (disabled by default, as it requires
carefully setting up the `thickness` to avoid self-shadow artifacts)
- Added support for the `KHR_materials_transmission`,
`KHR_materials_ior` and `KHR_materials_volume` glTF extensions
- Renamed items related to temporal jitter for greater consistency

## Migration Guide

- `SsaoPipelineKey::temporal_noise` has been renamed to
`SsaoPipelineKey::temporal_jitter`
- The `TAA` shader def (controlled by the presence of the
`TemporalAntiAliasSettings` component in the camera) has been replaced
with the `TEMPORAL_JITTER` shader def (controlled by the presence of the
`TemporalJitter` component in the camera)
- `MeshPipelineKey::TAA` has been replaced by
`MeshPipelineKey::TEMPORAL_JITTER`
- The `TEMPORAL_NOISE` shader def has been consolidated with
`TEMPORAL_JITTER`
2023-10-31 20:59:02 +00:00
..
3d_gizmos.rs Instanced line rendering for gizmos based on bevy_polyline (#8427) 2023-06-13 06:49:47 +00:00
3d_scene.rs Schedule-First: the new and improved add_systems (#8079) 2023-03-18 01:45:34 +00:00
3d_shapes.rs Schedule-First: the new and improved add_systems (#8079) 2023-03-18 01:45:34 +00:00
3d_viewport_to_world.rs Add example for Camera::viewport_to_world (#7179) 2023-09-11 18:52:11 +00:00
anti_aliasing.rs Image Sampler Improvements (#10254) 2023-10-26 23:30:09 +00:00
atmospheric_fog.rs Fix fog color being inaccurate (#10226) 2023-10-23 12:45:18 +00:00
blend_modes.rs Added Val::ZERO Constant (#9566) 2023-08-26 14:00:53 +00:00
bloom_3d.rs Fix CI for Rust 1.72 (#9562) 2023-08-25 12:34:24 +00:00
deferred_rendering.rs make deferred_rendering simpler to render for CI (#10150) 2023-10-28 20:39:45 +00:00
fog.rs Fix fog color being inaccurate (#10226) 2023-10-23 12:45:18 +00:00
generate_custom_mesh.rs Add consuming builder methods for more ergonomic Mesh creation (#10056) 2023-10-09 19:47:41 +00:00
lighting.rs standardize instructions in examples (#8478) 2023-04-26 19:52:31 +00:00
lines.rs Add consuming builder methods for more ergonomic Mesh creation (#10056) 2023-10-09 19:47:41 +00:00
load_gltf.rs Bevy Asset V2 (#8624) 2023-09-07 02:07:27 +00:00
orthographic.rs Schedule-First: the new and improved add_systems (#8079) 2023-03-18 01:45:34 +00:00
parallax_mapping.rs Add consuming builder methods for more ergonomic Mesh creation (#10056) 2023-10-09 19:47:41 +00:00
parenting.rs Schedule-First: the new and improved add_systems (#8079) 2023-03-18 01:45:34 +00:00
pbr.rs Bevy Asset V2 (#8624) 2023-09-07 02:07:27 +00:00
render_to_texture.rs Schedule-First: the new and improved add_systems (#8079) 2023-03-18 01:45:34 +00:00
shadow_biases.rs shadow_biases: Support moving the light position and resetting biases (#10185) 2023-10-19 14:41:39 +00:00
shadow_caster_receiver.rs Allow clippy::type_complexity in more places. (#9796) 2023-10-02 21:55:16 +00:00
skybox.rs Replace all usages of texture_descritor.size.* with the helper methods (#10227) 2023-10-23 20:49:02 +00:00
spherical_area_lights.rs Schedule-First: the new and improved add_systems (#8079) 2023-03-18 01:45:34 +00:00
split_screen.rs Refactor EventReader::iter to read (#9631) 2023-08-30 14:20:03 +00:00
spotlight.rs Improve execution of examples in CI (#9331) 2023-08-03 12:45:28 +00:00
ssao.rs Allow clippy::type_complexity in more places. (#9796) 2023-10-02 21:55:16 +00:00
texture.rs Schedule-First: the new and improved add_systems (#8079) 2023-03-18 01:45:34 +00:00
tonemapping.rs Image Sampler Improvements (#10254) 2023-10-26 23:30:09 +00:00
transmission.rs StandardMaterial Light Transmission (#8015) 2023-10-31 20:59:02 +00:00
transparency_3d.rs Fixed several missing links in docs. (#8117) 2023-04-23 17:28:36 +00:00
two_passes.rs Schedule-First: the new and improved add_systems (#8079) 2023-03-18 01:45:34 +00:00
update_gltf_scene.rs Schedule-First: the new and improved add_systems (#8079) 2023-03-18 01:45:34 +00:00
vertex_colors.rs Schedule-First: the new and improved add_systems (#8079) 2023-03-18 01:45:34 +00:00
wireframe.rs Configurable colors for wireframe (#5303) 2023-10-13 00:06:24 +00:00