mirror of
https://github.com/bevyengine/bevy
synced 2024-11-26 22:50:19 +00:00
Add ability to independently suppress shadows in diffuse transmission lobe
This commit is contained in:
parent
e2b816bc7c
commit
927cfa24fc
5 changed files with 50 additions and 20 deletions
|
@ -606,6 +606,18 @@ pub struct NotShadowCaster;
|
|||
#[reflect(Component, Default)]
|
||||
pub struct NotShadowReceiver;
|
||||
|
||||
/// Add this component to make a [`Mesh`](bevy_render::mesh::Mesh) not receive shadows
|
||||
/// on its diffuse transmission lobe.
|
||||
///
|
||||
/// Useful, for example, when a thick translucent mesh using [`StandardMaterial::diffuse_transmission`]
|
||||
/// has a complicated shape that's hard to model via [`StandardMaterial::thickness`], and you'd like
|
||||
/// to avoid self-shadows from affecting the transmitted light.
|
||||
///
|
||||
/// **Note:** Setting [`NotShadowReceiver`] disables both regular and transmitted shadows.
|
||||
#[derive(Component, Reflect, Default)]
|
||||
#[reflect(Component, Default)]
|
||||
pub struct NotTransmittedShadowReceiver;
|
||||
|
||||
#[derive(Debug, Hash, PartialEq, Eq, Clone, SystemSet)]
|
||||
pub enum SimulationLightSystems {
|
||||
AddClusters,
|
||||
|
|
|
@ -153,7 +153,8 @@ pub struct StandardMaterial {
|
|||
/// values higher than 0.5 will cause more diffuse light to be transmitted than reflected, resulting in a “darker” appearance
|
||||
/// for the front Lambertian lobe when an object is illuminated primarily from a single direction.
|
||||
///
|
||||
/// **Note:** Typically used in conjunction with [`StandardMaterial::thickness`].
|
||||
/// **Note:** Typically used in conjunction with [`StandardMaterial::thickness`]. To avoid self-shadows on complicated
|
||||
/// mesh shapes without having to fine tune the thickness, consider using the [`NotTransmittedShadowReceiver`] component.
|
||||
pub diffuse_transmission: f32,
|
||||
|
||||
/// The amount of light transmitted _specularly_ through the material (i.e. via refraction)
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
use crate::{
|
||||
environment_map, prepass, EnvironmentMapLight, FogMeta, GlobalLightMeta, GpuFog, GpuLights,
|
||||
GpuPointLights, LightMeta, NotShadowCaster, NotShadowReceiver, PreviousGlobalTransform,
|
||||
ShadowSamplers, ViewClusterBindings, ViewFogUniformOffset, ViewLightsUniformOffset,
|
||||
ViewShadowBindings, CLUSTERED_FORWARD_STORAGE_BUFFER_COUNT, MAX_CASCADES_PER_LIGHT,
|
||||
MAX_DIRECTIONAL_LIGHTS,
|
||||
GpuPointLights, LightMeta, NotShadowCaster, NotShadowReceiver, NotTransmittedShadowReceiver,
|
||||
PreviousGlobalTransform, ShadowSamplers, ViewClusterBindings, ViewFogUniformOffset,
|
||||
ViewLightsUniformOffset, ViewShadowBindings, CLUSTERED_FORWARD_STORAGE_BUFFER_COUNT,
|
||||
MAX_CASCADES_PER_LIGHT, MAX_DIRECTIONAL_LIGHTS,
|
||||
};
|
||||
use bevy_app::Plugin;
|
||||
use bevy_asset::{load_internal_asset, Assets, Handle, HandleUntyped};
|
||||
|
@ -134,12 +134,13 @@ pub struct MeshUniform {
|
|||
bitflags::bitflags! {
|
||||
#[repr(transparent)]
|
||||
struct MeshFlags: u32 {
|
||||
const SHADOW_RECEIVER = (1 << 0);
|
||||
const SHADOW_RECEIVER = (1 << 0);
|
||||
const TRANSMITTED_SHADOW_RECEIVER = (1 << 1);
|
||||
// Indicates the sign of the determinant of the 3x3 model matrix. If the sign is positive,
|
||||
// then the flag should be set, else it should not be set.
|
||||
const SIGN_DETERMINANT_MODEL_3X3 = (1 << 31);
|
||||
const NONE = 0;
|
||||
const UNINITIALIZED = 0xFFFF;
|
||||
const SIGN_DETERMINANT_MODEL_3X3 = (1 << 31);
|
||||
const NONE = 0;
|
||||
const UNINITIALIZED = 0xFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -155,6 +156,7 @@ pub fn extract_meshes(
|
|||
Option<&PreviousGlobalTransform>,
|
||||
&Handle<Mesh>,
|
||||
Option<With<NotShadowReceiver>>,
|
||||
Option<With<NotTransmittedShadowReceiver>>,
|
||||
Option<With<NotShadowCaster>>,
|
||||
)>,
|
||||
>,
|
||||
|
@ -163,8 +165,16 @@ pub fn extract_meshes(
|
|||
let mut not_caster_commands = Vec::with_capacity(*prev_not_caster_commands_len);
|
||||
let visible_meshes = meshes_query.iter().filter(|(_, vis, ..)| vis.is_visible());
|
||||
|
||||
for (entity, _, transform, previous_transform, handle, not_receiver, not_caster) in
|
||||
visible_meshes
|
||||
for (
|
||||
entity,
|
||||
_,
|
||||
transform,
|
||||
previous_transform,
|
||||
handle,
|
||||
not_receiver,
|
||||
not_transmitted_receiver,
|
||||
not_caster,
|
||||
) in visible_meshes
|
||||
{
|
||||
let transform = transform.compute_matrix();
|
||||
let previous_transform = previous_transform.map(|t| t.0).unwrap_or(transform);
|
||||
|
@ -173,6 +183,9 @@ pub fn extract_meshes(
|
|||
} else {
|
||||
MeshFlags::SHADOW_RECEIVER
|
||||
};
|
||||
if not_transmitted_receiver.is_none() {
|
||||
flags |= MeshFlags::TRANSMITTED_SHADOW_RECEIVER;
|
||||
}
|
||||
if Mat3A::from_mat4(transform).determinant().is_sign_positive() {
|
||||
flags |= MeshFlags::SIGN_DETERMINANT_MODEL_3X3;
|
||||
}
|
||||
|
|
|
@ -15,5 +15,6 @@ struct SkinnedMesh {
|
|||
#endif
|
||||
|
||||
const MESH_FLAGS_SHADOW_RECEIVER_BIT: u32 = 1u;
|
||||
const MESH_FLAGS_TRANSMITTED_SHADOW_RECEIVER_BIT: u32 = 2u;
|
||||
// 2^31 - if the flag is set, the sign is positive, else it is negative
|
||||
const MESH_FLAGS_SIGN_DETERMINANT_MODEL_3X3_BIT: u32 = 2147483648u;
|
||||
|
|
|
@ -235,12 +235,13 @@ fn pbr(
|
|||
// R = vec3<f32>(0.0) // doesn't really matter
|
||||
// f_ab = vec2<f32>(0.1)
|
||||
// F0 = vec3<f32>(0.0)
|
||||
if ((in.flags & MESH_FLAGS_SHADOW_RECEIVER_BIT) != 0u
|
||||
var transmitted_shadow: f32 = 1.0;
|
||||
if ((in.flags & (MESH_FLAGS_SHADOW_RECEIVER_BIT | MESH_FLAGS_TRANSMITTED_SHADOW_RECEIVER_BIT)) == (MESH_FLAGS_SHADOW_RECEIVER_BIT | MESH_FLAGS_TRANSMITTED_SHADOW_RECEIVER_BIT)
|
||||
&& (point_lights.data[light_id].flags & POINT_LIGHT_FLAGS_SHADOWS_ENABLED_BIT) != 0u) {
|
||||
shadow = fetch_point_shadow(light_id, diffuse_transmissive_lobe_world_position, -in.world_normal);
|
||||
transmitted_shadow = fetch_point_shadow(light_id, diffuse_transmissive_lobe_world_position, -in.world_normal);
|
||||
}
|
||||
let light_contrib = point_light(diffuse_transmissive_lobe_world_position.xyz, light_id, 1.0, 1.0, -in.N, -in.V, vec3<f32>(0.0), vec3<f32>(0.0), vec2<f32>(0.1), diffuse_transmissive_color);
|
||||
transmitted_light += light_contrib * shadow;
|
||||
transmitted_light += light_contrib * transmitted_shadow;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -265,12 +266,13 @@ fn pbr(
|
|||
// R = vec3<f32>(0.0) // doesn't really matter
|
||||
// f_ab = vec2<f32>(0.1)
|
||||
// F0 = vec3<f32>(0.0)
|
||||
if ((in.flags & MESH_FLAGS_SHADOW_RECEIVER_BIT) != 0u
|
||||
var transmitted_shadow: f32 = 1.0;
|
||||
if ((in.flags & (MESH_FLAGS_SHADOW_RECEIVER_BIT | MESH_FLAGS_TRANSMITTED_SHADOW_RECEIVER_BIT)) == (MESH_FLAGS_SHADOW_RECEIVER_BIT | MESH_FLAGS_TRANSMITTED_SHADOW_RECEIVER_BIT)
|
||||
&& (point_lights.data[light_id].flags & POINT_LIGHT_FLAGS_SHADOWS_ENABLED_BIT) != 0u) {
|
||||
shadow = fetch_spot_shadow(light_id, diffuse_transmissive_lobe_world_position, -in.world_normal);
|
||||
transmitted_shadow = fetch_spot_shadow(light_id, diffuse_transmissive_lobe_world_position, -in.world_normal);
|
||||
}
|
||||
let light_contrib = spot_light(diffuse_transmissive_lobe_world_position.xyz, light_id, 1.0, 1.0, -in.N, -in.V, vec3<f32>(0.0), vec3<f32>(0.0), vec2<f32>(0.1), diffuse_transmissive_color);
|
||||
transmitted_light += light_contrib * shadow;
|
||||
transmitted_light += light_contrib * transmitted_shadow;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -298,12 +300,13 @@ fn pbr(
|
|||
// R = vec3<f32>(0.0) // doesn't really matter
|
||||
// f_ab = vec2<f32>(0.1)
|
||||
// F0 = vec3<f32>(0.0)
|
||||
if ((in.flags & MESH_FLAGS_SHADOW_RECEIVER_BIT) != 0u
|
||||
var transmitted_shadow: f32 = 1.0;
|
||||
if ((in.flags & (MESH_FLAGS_SHADOW_RECEIVER_BIT | MESH_FLAGS_TRANSMITTED_SHADOW_RECEIVER_BIT)) == (MESH_FLAGS_SHADOW_RECEIVER_BIT | MESH_FLAGS_TRANSMITTED_SHADOW_RECEIVER_BIT)
|
||||
&& (lights.directional_lights[i].flags & DIRECTIONAL_LIGHT_FLAGS_SHADOWS_ENABLED_BIT) != 0u) {
|
||||
shadow = fetch_directional_shadow(i, diffuse_transmissive_lobe_world_position, -in.world_normal, view_z);
|
||||
transmitted_shadow = fetch_directional_shadow(i, diffuse_transmissive_lobe_world_position, -in.world_normal, view_z);
|
||||
}
|
||||
let light_contrib = directional_light(i, 1.0, 1.0, -in.N, -in.V, vec3<f32>(0.0), vec3<f32>(0.0), vec2<f32>(0.1), diffuse_transmissive_color);
|
||||
transmitted_light += light_contrib * shadow;
|
||||
transmitted_light += light_contrib * transmitted_shadow;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue