2023-10-17 21:28:08 +00:00
|
|
|
#define_import_path bevy_pbr::pbr_fragment
|
|
|
|
|
2023-10-21 11:51:58 +00:00
|
|
|
#import bevy_pbr::{
|
|
|
|
pbr_functions,
|
|
|
|
pbr_bindings,
|
|
|
|
pbr_types,
|
|
|
|
prepass_utils,
|
|
|
|
mesh_bindings::mesh,
|
|
|
|
mesh_view_bindings::view,
|
|
|
|
parallax_mapping::parallaxed_uv,
|
Implement lightmaps. (#10231)
![Screenshot](https://i.imgur.com/A4KzWFq.png)
# Objective
Lightmaps, textures that store baked global illumination, have been a
mainstay of real-time graphics for decades. Bevy currently has no
support for them, so this pull request implements them.
## Solution
The new `Lightmap` component can be attached to any entity that contains
a `Handle<Mesh>` and a `StandardMaterial`. When present, it will be
applied in the PBR shader. Because multiple lightmaps are frequently
packed into atlases, each lightmap may have its own UV boundaries within
its texture. An `exposure` field is also provided, to control the
brightness of the lightmap.
Note that this PR doesn't provide any way to bake the lightmaps. That
can be done with [The Lightmapper] or another solution, such as Unity's
Bakery.
---
## Changelog
### Added
* A new component, `Lightmap`, is available, for baked global
illumination. If your mesh has a second UV channel (UV1), and you attach
this component to the entity with that mesh, Bevy will apply the texture
referenced in the lightmap.
[The Lightmapper]: https://github.com/Naxela/The_Lightmapper
---------
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2024-01-02 20:38:47 +00:00
|
|
|
lightmap::lightmap,
|
2023-10-21 11:51:58 +00:00
|
|
|
}
|
2023-10-17 21:28:08 +00:00
|
|
|
|
|
|
|
#ifdef SCREEN_SPACE_AMBIENT_OCCLUSION
|
2023-10-21 11:51:58 +00:00
|
|
|
#import bevy_pbr::mesh_view_bindings::screen_space_ambient_occlusion_texture
|
|
|
|
#import bevy_pbr::gtao_utils::gtao_multibounce
|
2023-10-17 21:28:08 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef PREPASS_PIPELINE
|
2023-10-21 11:51:58 +00:00
|
|
|
#import bevy_pbr::prepass_io::VertexOutput
|
2023-10-17 21:28:08 +00:00
|
|
|
#else
|
2023-10-21 11:51:58 +00:00
|
|
|
#import bevy_pbr::forward_io::VertexOutput
|
2023-10-17 21:28:08 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
// prepare a basic PbrInput from the vertex stage output, mesh binding and view binding
|
|
|
|
fn pbr_input_from_vertex_output(
|
|
|
|
in: VertexOutput,
|
|
|
|
is_front: bool,
|
|
|
|
double_sided: bool,
|
|
|
|
) -> pbr_types::PbrInput {
|
|
|
|
var pbr_input: pbr_types::PbrInput = pbr_types::pbr_input_new();
|
|
|
|
|
|
|
|
pbr_input.flags = mesh[in.instance_index].flags;
|
|
|
|
pbr_input.is_orthographic = view.projection[3].w == 1.0;
|
|
|
|
pbr_input.V = pbr_functions::calculate_view(in.world_position, pbr_input.is_orthographic);
|
|
|
|
pbr_input.frag_coord = in.position;
|
|
|
|
pbr_input.world_position = in.world_position;
|
|
|
|
|
|
|
|
#ifdef VERTEX_COLORS
|
|
|
|
pbr_input.material.base_color = in.color;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
pbr_input.world_normal = pbr_functions::prepare_world_normal(
|
|
|
|
in.world_normal,
|
|
|
|
double_sided,
|
|
|
|
is_front,
|
|
|
|
);
|
|
|
|
|
|
|
|
#ifdef LOAD_PREPASS_NORMALS
|
2023-10-21 11:51:58 +00:00
|
|
|
pbr_input.N = prepass_utils::prepass_normal(in.position, 0u);
|
2023-10-17 21:28:08 +00:00
|
|
|
#else
|
|
|
|
pbr_input.N = normalize(pbr_input.world_normal);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return pbr_input;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Prepare a full PbrInput by sampling all textures to resolve
|
|
|
|
// the material members
|
|
|
|
fn pbr_input_from_standard_material(
|
|
|
|
in: VertexOutput,
|
|
|
|
is_front: bool,
|
|
|
|
) -> pbr_types::PbrInput {
|
|
|
|
let double_sided = (pbr_bindings::material.flags & pbr_types::STANDARD_MATERIAL_FLAGS_DOUBLE_SIDED_BIT) != 0u;
|
|
|
|
|
|
|
|
var pbr_input: pbr_types::PbrInput = pbr_input_from_vertex_output(in, is_front, double_sided);
|
|
|
|
pbr_input.material.flags = pbr_bindings::material.flags;
|
|
|
|
pbr_input.material.base_color *= pbr_bindings::material.base_color;
|
|
|
|
pbr_input.material.deferred_lighting_pass_id = pbr_bindings::material.deferred_lighting_pass_id;
|
|
|
|
|
|
|
|
#ifdef VERTEX_UVS
|
|
|
|
var uv = in.uv;
|
|
|
|
|
|
|
|
#ifdef VERTEX_TANGENTS
|
|
|
|
if ((pbr_bindings::material.flags & pbr_types::STANDARD_MATERIAL_FLAGS_DEPTH_MAP_BIT) != 0u) {
|
|
|
|
let V = pbr_input.V;
|
|
|
|
let N = in.world_normal;
|
|
|
|
let T = in.world_tangent.xyz;
|
|
|
|
let B = in.world_tangent.w * cross(N, T);
|
|
|
|
// Transform V from fragment to camera in world space to tangent space.
|
|
|
|
let Vt = vec3(dot(V, T), dot(V, B), dot(V, N));
|
|
|
|
uv = parallaxed_uv(
|
|
|
|
pbr_bindings::material.parallax_depth_scale,
|
|
|
|
pbr_bindings::material.max_parallax_layer_count,
|
|
|
|
pbr_bindings::material.max_relief_mapping_search_steps,
|
|
|
|
uv,
|
|
|
|
// Flip the direction of Vt to go toward the surface to make the
|
|
|
|
// parallax mapping algorithm easier to understand and reason
|
|
|
|
// about.
|
|
|
|
-Vt,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
#endif // VERTEX_TANGENTS
|
|
|
|
|
|
|
|
if ((pbr_bindings::material.flags & pbr_types::STANDARD_MATERIAL_FLAGS_BASE_COLOR_TEXTURE_BIT) != 0u) {
|
|
|
|
pbr_input.material.base_color *= textureSampleBias(pbr_bindings::base_color_texture, pbr_bindings::base_color_sampler, uv, view.mip_bias);
|
|
|
|
}
|
|
|
|
#endif // VERTEX_UVS
|
|
|
|
|
|
|
|
pbr_input.material.flags = pbr_bindings::material.flags;
|
|
|
|
|
|
|
|
// NOTE: Unlit bit not set means == 0 is true, so the true case is if lit
|
|
|
|
if ((pbr_bindings::material.flags & pbr_types::STANDARD_MATERIAL_FLAGS_UNLIT_BIT) == 0u) {
|
|
|
|
pbr_input.material.reflectance = pbr_bindings::material.reflectance;
|
`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
|
|
|
pbr_input.material.ior = pbr_bindings::material.ior;
|
|
|
|
pbr_input.material.attenuation_color = pbr_bindings::material.attenuation_color;
|
|
|
|
pbr_input.material.attenuation_distance = pbr_bindings::material.attenuation_distance;
|
2023-10-17 21:28:08 +00:00
|
|
|
pbr_input.material.alpha_cutoff = pbr_bindings::material.alpha_cutoff;
|
|
|
|
|
`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
|
|
|
// emissive
|
2023-10-17 21:28:08 +00:00
|
|
|
// TODO use .a for exposure compensation in HDR
|
|
|
|
var emissive: vec4<f32> = pbr_bindings::material.emissive;
|
|
|
|
#ifdef VERTEX_UVS
|
|
|
|
if ((pbr_bindings::material.flags & pbr_types::STANDARD_MATERIAL_FLAGS_EMISSIVE_TEXTURE_BIT) != 0u) {
|
|
|
|
emissive = vec4<f32>(emissive.rgb * textureSampleBias(pbr_bindings::emissive_texture, pbr_bindings::emissive_sampler, uv, view.mip_bias).rgb, 1.0);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
pbr_input.material.emissive = emissive;
|
|
|
|
|
|
|
|
// metallic and perceptual roughness
|
|
|
|
var metallic: f32 = pbr_bindings::material.metallic;
|
|
|
|
var perceptual_roughness: f32 = pbr_bindings::material.perceptual_roughness;
|
|
|
|
#ifdef VERTEX_UVS
|
|
|
|
if ((pbr_bindings::material.flags & pbr_types::STANDARD_MATERIAL_FLAGS_METALLIC_ROUGHNESS_TEXTURE_BIT) != 0u) {
|
|
|
|
let metallic_roughness = textureSampleBias(pbr_bindings::metallic_roughness_texture, pbr_bindings::metallic_roughness_sampler, uv, view.mip_bias);
|
|
|
|
// Sampling from GLTF standard channels for now
|
|
|
|
metallic *= metallic_roughness.b;
|
|
|
|
perceptual_roughness *= metallic_roughness.g;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
pbr_input.material.metallic = metallic;
|
|
|
|
pbr_input.material.perceptual_roughness = perceptual_roughness;
|
|
|
|
|
`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
|
|
|
var specular_transmission: f32 = pbr_bindings::material.specular_transmission;
|
|
|
|
#ifdef PBR_TRANSMISSION_TEXTURES_SUPPORTED
|
|
|
|
if ((pbr_bindings::material.flags & pbr_types::STANDARD_MATERIAL_FLAGS_SPECULAR_TRANSMISSION_TEXTURE_BIT) != 0u) {
|
|
|
|
specular_transmission *= textureSample(pbr_bindings::specular_transmission_texture, pbr_bindings::specular_transmission_sampler, uv).r;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
pbr_input.material.specular_transmission = specular_transmission;
|
|
|
|
|
|
|
|
var thickness: f32 = pbr_bindings::material.thickness;
|
|
|
|
#ifdef PBR_TRANSMISSION_TEXTURES_SUPPORTED
|
|
|
|
if ((pbr_bindings::material.flags & pbr_types::STANDARD_MATERIAL_FLAGS_THICKNESS_TEXTURE_BIT) != 0u) {
|
|
|
|
thickness *= textureSample(pbr_bindings::thickness_texture, pbr_bindings::thickness_sampler, uv).g;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
// scale thickness, accounting for non-uniform scaling (e.g. a “squished” mesh)
|
|
|
|
thickness *= length(
|
|
|
|
(transpose(mesh[in.instance_index].model) * vec4(pbr_input.N, 0.0)).xyz
|
|
|
|
);
|
|
|
|
pbr_input.material.thickness = thickness;
|
|
|
|
|
|
|
|
var diffuse_transmission = pbr_bindings::material.diffuse_transmission;
|
|
|
|
#ifdef PBR_TRANSMISSION_TEXTURES_SUPPORTED
|
|
|
|
if ((pbr_bindings::material.flags & pbr_types::STANDARD_MATERIAL_FLAGS_DIFFUSE_TRANSMISSION_TEXTURE_BIT) != 0u) {
|
|
|
|
diffuse_transmission *= textureSample(pbr_bindings::diffuse_transmission_texture, pbr_bindings::diffuse_transmission_sampler, uv).a;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
pbr_input.material.diffuse_transmission = diffuse_transmission;
|
|
|
|
|
2023-10-17 21:28:08 +00:00
|
|
|
// occlusion
|
|
|
|
// TODO: Split into diffuse/specular occlusion?
|
|
|
|
var occlusion: vec3<f32> = vec3(1.0);
|
|
|
|
#ifdef VERTEX_UVS
|
|
|
|
if ((pbr_bindings::material.flags & pbr_types::STANDARD_MATERIAL_FLAGS_OCCLUSION_TEXTURE_BIT) != 0u) {
|
|
|
|
occlusion = vec3(textureSampleBias(pbr_bindings::occlusion_texture, pbr_bindings::occlusion_sampler, uv, view.mip_bias).r);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef SCREEN_SPACE_AMBIENT_OCCLUSION
|
|
|
|
let ssao = textureLoad(screen_space_ambient_occlusion_texture, vec2<i32>(in.position.xy), 0i).r;
|
|
|
|
let ssao_multibounce = gtao_multibounce(ssao, pbr_input.material.base_color.rgb);
|
|
|
|
occlusion = min(occlusion, ssao_multibounce);
|
|
|
|
#endif
|
|
|
|
pbr_input.occlusion = occlusion;
|
|
|
|
|
|
|
|
// N (normal vector)
|
|
|
|
#ifndef LOAD_PREPASS_NORMALS
|
|
|
|
pbr_input.N = pbr_functions::apply_normal_mapping(
|
|
|
|
pbr_bindings::material.flags,
|
|
|
|
pbr_input.world_normal,
|
2023-10-31 09:44:40 +00:00
|
|
|
double_sided,
|
|
|
|
is_front,
|
2023-10-17 21:28:08 +00:00
|
|
|
#ifdef VERTEX_TANGENTS
|
|
|
|
#ifdef STANDARDMATERIAL_NORMAL_MAP
|
|
|
|
in.world_tangent,
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
#ifdef VERTEX_UVS
|
|
|
|
uv,
|
|
|
|
#endif
|
|
|
|
view.mip_bias,
|
|
|
|
);
|
|
|
|
#endif
|
Implement lightmaps. (#10231)
![Screenshot](https://i.imgur.com/A4KzWFq.png)
# Objective
Lightmaps, textures that store baked global illumination, have been a
mainstay of real-time graphics for decades. Bevy currently has no
support for them, so this pull request implements them.
## Solution
The new `Lightmap` component can be attached to any entity that contains
a `Handle<Mesh>` and a `StandardMaterial`. When present, it will be
applied in the PBR shader. Because multiple lightmaps are frequently
packed into atlases, each lightmap may have its own UV boundaries within
its texture. An `exposure` field is also provided, to control the
brightness of the lightmap.
Note that this PR doesn't provide any way to bake the lightmaps. That
can be done with [The Lightmapper] or another solution, such as Unity's
Bakery.
---
## Changelog
### Added
* A new component, `Lightmap`, is available, for baked global
illumination. If your mesh has a second UV channel (UV1), and you attach
this component to the entity with that mesh, Bevy will apply the texture
referenced in the lightmap.
[The Lightmapper]: https://github.com/Naxela/The_Lightmapper
---------
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2024-01-02 20:38:47 +00:00
|
|
|
|
|
|
|
#ifdef LIGHTMAP
|
|
|
|
pbr_input.lightmap_light = lightmap(
|
|
|
|
in.uv_b,
|
|
|
|
pbr_bindings::material.lightmap_exposure,
|
|
|
|
in.instance_index);
|
|
|
|
#endif
|
2023-10-17 21:28:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return pbr_input;
|
|
|
|
}
|