mirror of
https://github.com/bevyengine/bevy.git
synced 2026-05-06 06:06:42 -04:00
Gate LTC LUTs behind a feature and merge them to a texture array (#24065)
# Objective Alternative to #24004. https://github.com/bevyengine/bevy/pull/23288 adds ltc luts for rect light support which implicitly requires `bevy_image/ktx2` and `bevy_image/zstd` otherwise loading ltc luts will panic. We either accept to always enable area light supoort (#24004), or add a feature to opt out it (this PR). ## Solution Gate ltc luts behind a feature and merge them to a texture array. ## Testing `rect_light` example works. --------- Co-authored-by: Kevin Chen <chen.kevin.f@gmail.com>
This commit is contained in:
committed by
Carter Anderson
parent
827358a922
commit
c757497b27
@@ -52,7 +52,7 @@ jobs:
|
||||
example_name=`basename $example .ron`
|
||||
echo -n $example_name > last_example_run
|
||||
echo "running $example_name - "`date`
|
||||
time TRACE_CHROME=trace-$example_name.json CI_TESTING_CONFIG=$example cargo run --example $example_name --features "bevy_ci_testing,trace,trace_chrome,bevy_ui_debug"
|
||||
time TRACE_CHROME=trace-$example_name.json CI_TESTING_CONFIG=$example cargo run --example $example_name --features "bevy_ci_testing,trace,trace_chrome,bevy_ui_debug,area_light_luts"
|
||||
sleep 10
|
||||
if [ `find ./ -maxdepth 1 -name 'screenshot-*.png' -print -quit` ]; then
|
||||
mkdir screenshots-$example_name
|
||||
@@ -132,7 +132,7 @@ jobs:
|
||||
example_name=`basename $example .ron`
|
||||
echo -n $example_name > last_example_run
|
||||
echo "running $example_name - "`date`
|
||||
time TRACE_CHROME=trace-$example_name.json CI_TESTING_CONFIG=$example xvfb-run cargo run --example $example_name --features "bevy_ci_testing,trace,trace_chrome,bevy_ui_debug"
|
||||
time TRACE_CHROME=trace-$example_name.json CI_TESTING_CONFIG=$example xvfb-run cargo run --example $example_name --features "bevy_ci_testing,trace,trace_chrome,bevy_ui_debug,area_light_luts"
|
||||
sleep 10
|
||||
if [ `find ./ -maxdepth 1 -name 'screenshot-*.png' -print -quit` ]; then
|
||||
mkdir screenshots-$example_name
|
||||
@@ -202,7 +202,7 @@ jobs:
|
||||
example_name=`basename $example .ron`
|
||||
echo -n $example_name > last_example_run
|
||||
echo "running $example_name - "`date`
|
||||
time WGPU_BACKEND=dx12 TRACE_CHROME=trace-$example_name.json CI_TESTING_CONFIG=$example cargo run --example $example_name --features "statically-linked-dxc,bevy_ci_testing,trace,trace_chrome,bevy_ui_debug"
|
||||
time WGPU_BACKEND=dx12 TRACE_CHROME=trace-$example_name.json CI_TESTING_CONFIG=$example cargo run --example $example_name --features "statically-linked-dxc,bevy_ci_testing,trace,trace_chrome,bevy_ui_debug,area_light_luts"
|
||||
sleep 10
|
||||
if [ `find ./ -maxdepth 1 -name 'screenshot-*.png' -print -quit` ]; then
|
||||
mkdir screenshots-$example_name
|
||||
|
||||
+5
-1
@@ -574,6 +574,9 @@ bluenoise_texture = ["bevy_internal/bluenoise_texture"]
|
||||
# Include a preintegrated BRDF Look Up Table for more accurate specular shading.
|
||||
dfg_lut = ["bevy_internal/dfg_lut"]
|
||||
|
||||
# Include Look Up Tables that are required for area lights.
|
||||
area_light_luts = ["bevy_internal/area_light_luts"]
|
||||
|
||||
# NVIDIA Deep Learning Super Sampling
|
||||
dlss = ["bevy_internal/dlss"]
|
||||
|
||||
@@ -1190,7 +1193,7 @@ wasm = true
|
||||
name = "rect_light"
|
||||
path = "examples/3d/rect_light.rs"
|
||||
doc-scrape-examples = true
|
||||
required-features = ["free_camera"]
|
||||
required-features = ["free_camera", "area_light_luts"]
|
||||
|
||||
[package.metadata.example.rect_light]
|
||||
name = "Rectangular Area Light"
|
||||
@@ -5192,6 +5195,7 @@ hidden = true
|
||||
name = "testbed_3d"
|
||||
path = "examples/testbed/3d.rs"
|
||||
doc-scrape-examples = true
|
||||
required-features = ["area_light_luts"]
|
||||
|
||||
[package.metadata.example.testbed_3d]
|
||||
hidden = true
|
||||
|
||||
@@ -12,4 +12,6 @@ The implementation uses [Linearly Transformed Cosines](https://eheitzresearch.wo
|
||||
|
||||
Rectangular lights currently don't cast shadows or have support for anisotropic materials.
|
||||
|
||||
You need to enable the `area_light_luts` cargo feature to use it.
|
||||
|
||||
Check out [the new example](https://github.com/bevyengine/bevy/tree/latest/examples/3d/rect_light.rs) to see them in action.
|
||||
|
||||
@@ -85,6 +85,9 @@ bluenoise_texture = ["bevy_pbr?/bluenoise_texture", "ktx2", "bevy_image/zstd"]
|
||||
# Include a preintegrated BRDF Look Up Table for more accurate specular shading.
|
||||
dfg_lut = ["bevy_pbr?/dfg_lut", "ktx2", "bevy_image/zstd"]
|
||||
|
||||
# Include Look Up Tables that are required for area lights.
|
||||
area_light_luts = ["bevy_pbr?/area_light_luts", "ktx2", "bevy_image/zstd"]
|
||||
|
||||
# NVIDIA Deep Learning Super Sampling
|
||||
dlss = ["bevy_anti_alias/dlss", "bevy_solari?/dlss"]
|
||||
|
||||
|
||||
@@ -13,6 +13,8 @@ use crate::light_consts;
|
||||
///
|
||||
/// Shadow maps are currently unsupported, objects illuminated by a
|
||||
/// ``RectLight`` will not cast shadows.
|
||||
///
|
||||
/// Note: Requires the `area_light_luts` cargo feature.
|
||||
#[derive(Component, Debug, Clone, Copy, Reflect)]
|
||||
#[reflect(Component, Default, Debug, Clone)]
|
||||
#[require(Transform, Visibility, VisibilityClass)]
|
||||
|
||||
@@ -22,6 +22,7 @@ pbr_clustered_decals = []
|
||||
pbr_light_textures = []
|
||||
bluenoise_texture = ["bevy_image/ktx2", "bevy_image/zstd"]
|
||||
dfg_lut = ["bevy_image/ktx2", "bevy_image/zstd"]
|
||||
area_light_luts = ["bevy_image/ktx2", "bevy_image/zstd"]
|
||||
shader_format_glsl = ["bevy_shader/shader_format_glsl"]
|
||||
trace = ["bevy_render/trace"]
|
||||
# Enables the meshlet renderer for dense high-poly scenes (experimental)
|
||||
|
||||
+64
-40
@@ -107,14 +107,14 @@ use bevy_asset::{AssetApp, AssetPath, Assets, Handle, RenderAssetUsages};
|
||||
use bevy_core_pipeline::mip_generation::experimental::depth::early_downsample_depth;
|
||||
use bevy_core_pipeline::schedule::{Core3d, Core3dSystems};
|
||||
use bevy_ecs::prelude::*;
|
||||
use bevy_image::{CompressedImageFormats, Image, ImageSampler, ImageType};
|
||||
use bevy_image::{Image, ImageSampler};
|
||||
use bevy_material::AlphaMode;
|
||||
use bevy_render::{
|
||||
camera::sort_cameras,
|
||||
extract_resource::ExtractResourcePlugin,
|
||||
render_resource::{
|
||||
Extent3d, TextureDataOrder, TextureDescriptor, TextureDimension, TextureFormat,
|
||||
TextureUsages,
|
||||
TextureUsages, TextureViewDescriptor, TextureViewDimension,
|
||||
},
|
||||
sync_component::SyncComponentPlugin,
|
||||
ExtractSchedule, GpuResourceAppExt, Render, RenderApp, RenderDebugFlags, RenderStartup,
|
||||
@@ -169,14 +169,14 @@ pub struct Bluenoise {
|
||||
|
||||
/// LTC (Linearly Transformed Cosines) LUT textures for area light shading.
|
||||
///
|
||||
/// `ltc_1` encodes the 4 non-trivial elements of the inverse GGX LTC matrix.
|
||||
/// `ltc_2` encodes amplitude and Fresnel-related weights.
|
||||
/// It is a texture array containing 2 LUT textures:
|
||||
/// The first entry encodes the 4 non-trivial elements of the inverse GGX LTC matrix.
|
||||
/// The second entry encodes amplitude and Fresnel-related weights.
|
||||
///
|
||||
/// [LUT source and fitting code](https://github.com/selfshadow/ltc_code/blob/master/fit/results)
|
||||
#[derive(Resource, Clone)]
|
||||
pub struct LtcLuts {
|
||||
pub ltc_1: Handle<Image>,
|
||||
pub ltc_2: Handle<Image>,
|
||||
pub struct AreaLightLuts {
|
||||
pub image: Handle<Image>,
|
||||
}
|
||||
|
||||
// See https://github.com/bevyengine/bevy/pull/23737 for information on how the LUT was generated.
|
||||
@@ -282,15 +282,16 @@ impl Plugin for PbrPlugin {
|
||||
let mut images = app.world_mut().resource_mut::<Assets<Image>>();
|
||||
#[cfg(feature = "bluenoise_texture")]
|
||||
let handle = {
|
||||
let image = Image::from_buffer(
|
||||
let mut image = Image::from_buffer(
|
||||
include_bytes!("bluenoise/stbn.ktx2"),
|
||||
ImageType::Extension("ktx2"),
|
||||
CompressedImageFormats::NONE,
|
||||
bevy_image::ImageType::Extension("ktx2"),
|
||||
bevy_image::CompressedImageFormats::NONE,
|
||||
false,
|
||||
ImageSampler::Default,
|
||||
RenderAssetUsages::RENDER_WORLD,
|
||||
)
|
||||
.expect("Failed to decode embedded blue-noise texture");
|
||||
image.texture_descriptor.label = Some("bluenoise");
|
||||
images.add(image)
|
||||
};
|
||||
|
||||
@@ -304,39 +305,32 @@ impl Plugin for PbrPlugin {
|
||||
}
|
||||
}
|
||||
|
||||
let has_ltc_luts = app
|
||||
let has_area_light_luts = app
|
||||
.get_sub_app(RenderApp)
|
||||
.is_some_and(|render_app| render_app.world().is_resource_added::<LtcLuts>());
|
||||
.is_some_and(|render_app| render_app.world().is_resource_added::<AreaLightLuts>());
|
||||
|
||||
if !has_ltc_luts {
|
||||
if !has_area_light_luts {
|
||||
let mut images = app.world_mut().resource_mut::<Assets<Image>>();
|
||||
let ltc_luts = LtcLuts {
|
||||
ltc_1: images.add(
|
||||
Image::from_buffer(
|
||||
include_bytes!("ltc/ltc1.ktx2"),
|
||||
ImageType::Extension("ktx2"),
|
||||
CompressedImageFormats::NONE,
|
||||
false,
|
||||
ImageSampler::linear(),
|
||||
RenderAssetUsages::RENDER_WORLD,
|
||||
)
|
||||
.expect("Failed to decode embedded LTC LUT 1"),
|
||||
),
|
||||
ltc_2: images.add(
|
||||
Image::from_buffer(
|
||||
include_bytes!("ltc/ltc2.ktx2"),
|
||||
ImageType::Extension("ktx2"),
|
||||
CompressedImageFormats::NONE,
|
||||
false,
|
||||
ImageSampler::linear(),
|
||||
RenderAssetUsages::RENDER_WORLD,
|
||||
)
|
||||
.expect("Failed to decode embedded LTC LUT 2"),
|
||||
),
|
||||
#[cfg(feature = "area_light_luts")]
|
||||
let handle = {
|
||||
let mut image = Image::from_buffer(
|
||||
include_bytes!("ltc/ltc.ktx2"),
|
||||
bevy_image::ImageType::Extension("ktx2"),
|
||||
bevy_image::CompressedImageFormats::NONE,
|
||||
false,
|
||||
ImageSampler::linear(),
|
||||
RenderAssetUsages::RENDER_WORLD,
|
||||
)
|
||||
.expect("Failed to decode embedded LTC LUTs");
|
||||
image.texture_descriptor.label = Some("area_light_luts");
|
||||
images.add(image)
|
||||
};
|
||||
#[cfg(not(feature = "area_light_luts"))]
|
||||
let handle = images.add(area_light_luts_placeholder());
|
||||
|
||||
let area_light_luts = AreaLightLuts { image: handle };
|
||||
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||
render_app.world_mut().insert_resource(ltc_luts);
|
||||
render_app.world_mut().insert_resource(area_light_luts);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -349,8 +343,8 @@ impl Plugin for PbrPlugin {
|
||||
let texture = app.world_mut().resource_mut::<Assets<Image>>().add(
|
||||
Image::from_buffer(
|
||||
include_bytes!("environment_map/dfg.ktx2"),
|
||||
ImageType::Extension("ktx2"),
|
||||
CompressedImageFormats::NONE,
|
||||
bevy_image::ImageType::Extension("ktx2"),
|
||||
bevy_image::CompressedImageFormats::NONE,
|
||||
false,
|
||||
ImageSampler::linear(),
|
||||
RenderAssetUsages::RENDER_WORLD,
|
||||
@@ -468,7 +462,7 @@ pub fn stbn_placeholder() -> Image {
|
||||
size: Extent3d::default(),
|
||||
format,
|
||||
dimension: TextureDimension::D2,
|
||||
label: None,
|
||||
label: Some("bluenoise_placeholder"),
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
usage: TextureUsages::TEXTURE_BINDING,
|
||||
@@ -481,6 +475,36 @@ pub fn stbn_placeholder() -> Image {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn area_light_luts_placeholder() -> Image {
|
||||
let format = TextureFormat::Rgba16Float;
|
||||
let data = vec![0; 16];
|
||||
Image {
|
||||
data: Some(data),
|
||||
data_order: TextureDataOrder::default(),
|
||||
texture_descriptor: TextureDescriptor {
|
||||
size: Extent3d {
|
||||
width: 1,
|
||||
height: 1,
|
||||
depth_or_array_layers: 2,
|
||||
},
|
||||
format,
|
||||
dimension: TextureDimension::D2,
|
||||
label: Some("area_light_luts_placeholder"),
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
usage: TextureUsages::TEXTURE_BINDING,
|
||||
view_formats: &[],
|
||||
},
|
||||
sampler: ImageSampler::Default,
|
||||
texture_view_descriptor: Some(TextureViewDescriptor {
|
||||
dimension: Some(TextureViewDimension::D2Array),
|
||||
..Default::default()
|
||||
}),
|
||||
asset_usage: RenderAssetUsages::RENDER_WORLD,
|
||||
copy_on_resize: false,
|
||||
}
|
||||
}
|
||||
|
||||
impl SyncComponent<PbrPlugin> for DirectionalLight {
|
||||
type Target = (
|
||||
Self,
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -420,6 +420,7 @@ pub fn extract_lights(
|
||||
&mut RenderExtractedShadowMapVisibleEntities,
|
||||
&mut RenderShadowMapVisibleEntities,
|
||||
)>,
|
||||
mut rect_light_missing_luts_warning_emitted: Local<bool>,
|
||||
) {
|
||||
let mapper = &visibility_extraction_system_param.mapper;
|
||||
|
||||
@@ -824,6 +825,12 @@ pub fn extract_lights(
|
||||
}
|
||||
|
||||
for (main_entity, render_entity, rect_light, transform, view_visibility) in &rect_lights {
|
||||
if !cfg!(feature = "area_light_luts") && !*rect_light_missing_luts_warning_emitted {
|
||||
warn!(
|
||||
"RectLight will not work properly because the `area_light_luts` cargo feature is not enabled."
|
||||
);
|
||||
*rect_light_missing_luts_warning_emitted = true;
|
||||
}
|
||||
if !view_visibility.get() {
|
||||
if let Ok(mut entity_commands) = commands.get_entity(render_entity) {
|
||||
entity_commands.remove::<ExtractedRectLight>();
|
||||
|
||||
@@ -3344,6 +3344,9 @@ impl SpecializedMeshPipeline for MeshPipeline {
|
||||
if cfg!(feature = "dfg_lut") {
|
||||
shader_defs.push("DFG_LUT".into());
|
||||
}
|
||||
if cfg!(feature = "area_light_luts") {
|
||||
shader_defs.push("AREA_LIGHT_LUTS".into());
|
||||
}
|
||||
|
||||
let bind_group_layout = self.get_view_layout(key.into());
|
||||
let mut bind_group_layout = vec![
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::{
|
||||
DfgLut, LtcLuts, ScreenSpaceTransmission, ViewEnvironmentMapUniformOffset,
|
||||
AreaLightLuts, DfgLut, ScreenSpaceTransmission, ViewEnvironmentMapUniformOffset,
|
||||
ViewFogUniformOffset, ViewLightProbesUniformOffset, ViewLightsUniformOffset,
|
||||
ViewScreenSpaceReflectionsUniformOffset,
|
||||
};
|
||||
@@ -97,6 +97,7 @@ bitflags::bitflags! {
|
||||
const SCREEN_SPACE_TRANSMISSION = 1 << 13;
|
||||
const CONTACT_SHADOWS = 1 << 14;
|
||||
const DISTANCE_FOG = 1 << 15;
|
||||
const AREA_LIGHT_LUTS = 1 << 16;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,6 +151,10 @@ impl From<MeshPipelineKey> for MeshPipelineViewLayoutKey {
|
||||
result |= MeshPipelineViewLayoutKey::STBN;
|
||||
}
|
||||
|
||||
if cfg!(feature = "area_light_luts") {
|
||||
result |= MeshPipelineViewLayoutKey::AREA_LIGHT_LUTS;
|
||||
}
|
||||
|
||||
if value.contains(MeshPipelineKey::TONEMAP_IN_SHADER) {
|
||||
result |= MeshPipelineViewLayoutKey::TONEMAP_IN_SHADER;
|
||||
}
|
||||
@@ -462,25 +467,23 @@ fn layout_entries(
|
||||
),));
|
||||
}
|
||||
// LTC LUTs for area lights
|
||||
entries = entries.extend_with_indices((
|
||||
(
|
||||
36,
|
||||
texture_2d(TextureSampleType::Float { filterable: true }),
|
||||
),
|
||||
(
|
||||
37,
|
||||
texture_2d(TextureSampleType::Float { filterable: true }),
|
||||
),
|
||||
(38, sampler(SamplerBindingType::Filtering)),
|
||||
));
|
||||
if cfg!(feature = "area_light_luts") {
|
||||
entries = entries.extend_with_indices((
|
||||
(
|
||||
36,
|
||||
texture_2d_array(TextureSampleType::Float { filterable: true }),
|
||||
),
|
||||
(37, sampler(SamplerBindingType::Filtering)),
|
||||
));
|
||||
}
|
||||
// DFG LUT
|
||||
if cfg!(feature = "dfg_lut") {
|
||||
entries = entries.extend_with_indices((
|
||||
(
|
||||
39,
|
||||
38,
|
||||
texture_2d(TextureSampleType::Float { filterable: true }),
|
||||
),
|
||||
(40, sampler(SamplerBindingType::Filtering)),
|
||||
(39, sampler(SamplerBindingType::Filtering)),
|
||||
));
|
||||
}
|
||||
|
||||
@@ -678,7 +681,7 @@ pub fn prepare_mesh_view_bind_groups(
|
||||
atmosphere_buffer,
|
||||
atmosphere_sampler,
|
||||
blue_noise,
|
||||
ltc_luts,
|
||||
area_light_luts,
|
||||
dfg_lut,
|
||||
): (
|
||||
Res<DecalsBuffer>,
|
||||
@@ -686,7 +689,7 @@ pub fn prepare_mesh_view_bind_groups(
|
||||
Option<Res<AtmosphereBuffer>>,
|
||||
Option<Res<AtmosphereSampler>>,
|
||||
Res<Bluenoise>,
|
||||
Res<LtcLuts>,
|
||||
Res<AreaLightLuts>,
|
||||
Res<DfgLut>,
|
||||
),
|
||||
// TODO: Figure out how to reuse the memory. `BindGroupEntry` is non-send on wasm with atomics.
|
||||
@@ -896,16 +899,16 @@ pub fn prepare_mesh_view_bind_groups(
|
||||
};
|
||||
|
||||
// LTC LUTs for area lights
|
||||
let (ltc1_view, ltc_sampler) = images
|
||||
.get(<c_luts.ltc_1)
|
||||
.map(|img| (&img.texture_view, &img.sampler))
|
||||
.unwrap_or((&fallback_image.d2.texture_view, &fallback_image.d2.sampler));
|
||||
let ltc2_view = images
|
||||
.get(<c_luts.ltc_2)
|
||||
.map(|img| &img.texture_view)
|
||||
.unwrap_or(&fallback_image.d2.texture_view);
|
||||
entries =
|
||||
entries.extend_with_indices(((36, ltc1_view), (37, ltc2_view), (38, ltc_sampler)));
|
||||
if cfg!(feature = "area_light_luts") {
|
||||
let (ltc_view, ltc_sampler) = images
|
||||
.get(&area_light_luts.image)
|
||||
.map(|img| (&img.texture_view, &img.sampler))
|
||||
.unwrap_or((
|
||||
&fallback_image.d2_array.texture_view,
|
||||
&fallback_image.d2_array.sampler,
|
||||
));
|
||||
entries = entries.extend_with_indices(((36, ltc_view), (37, ltc_sampler)));
|
||||
}
|
||||
|
||||
// DFG LUT
|
||||
if cfg!(feature = "dfg_lut") {
|
||||
@@ -913,7 +916,7 @@ pub fn prepare_mesh_view_bind_groups(
|
||||
.get(&dfg_lut.texture)
|
||||
.map(|img| (&img.texture_view, &img.sampler))
|
||||
.unwrap_or((&fallback_image.d2.texture_view, &fallback_image.d2.sampler));
|
||||
entries = entries.extend_with_indices(((39, dfg_view), (40, dfg_sampler)));
|
||||
entries = entries.extend_with_indices(((38, dfg_view), (39, dfg_sampler)));
|
||||
}
|
||||
|
||||
let environment_map_bind_group_entries =
|
||||
|
||||
@@ -121,16 +121,19 @@ const VISIBILITY_RANGE_UNIFORM_BUFFER_SIZE: u32 = 64u;
|
||||
@group(0) @binding(33) var atmosphere_transmittance_sampler: sampler;
|
||||
@group(0) @binding(34) var<storage> atmosphere: atmosphere_types::Atmosphere;
|
||||
#endif // ATMOSPHERE
|
||||
|
||||
#ifdef BLUE_NOISE_TEXTURE
|
||||
@group(0) @binding(35) var blue_noise_texture: texture_2d_array<f32>;
|
||||
#endif // BLUE_NOISE_TEXTURE
|
||||
|
||||
@group(0) @binding(36) var ltc_lut1: texture_2d<f32>;
|
||||
@group(0) @binding(37) var ltc_lut2: texture_2d<f32>;
|
||||
@group(0) @binding(38) var ltc_lut_sampler: sampler;
|
||||
#ifdef AREA_LIGHT_LUTS
|
||||
@group(0) @binding(36) var area_light_luts: texture_2d_array<f32>;
|
||||
@group(0) @binding(37) var area_light_luts_sampler: sampler;
|
||||
#endif
|
||||
|
||||
#ifdef DFG_LUT
|
||||
@group(0) @binding(39) var dfg_lut: texture_2d<f32>;
|
||||
@group(0) @binding(40) var dfg_lut_sampler: sampler;
|
||||
@group(0) @binding(38) var dfg_lut: texture_2d<f32>;
|
||||
@group(0) @binding(39) var dfg_lut_sampler: sampler;
|
||||
#endif // DFG_LUT
|
||||
|
||||
#ifdef ENVIRONMENT_MAP
|
||||
|
||||
@@ -657,6 +657,7 @@ fn apply_pbr_lighting(
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef AREA_LIGHT_LUTS
|
||||
// Rect lights
|
||||
let n_rect_lights = view_bindings::lights.n_rect_lights;
|
||||
for (var i: u32 = 0u; i < n_rect_lights; i = i + 1u) {
|
||||
@@ -670,6 +671,7 @@ fn apply_pbr_lighting(
|
||||
transmitted_light += transmitted_light_contrib;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef STANDARD_MATERIAL_DIFFUSE_TRANSMISSION
|
||||
// NOTE: We use the diffuse transmissive color, the second Lambertian lobe's calculated
|
||||
|
||||
@@ -84,7 +84,7 @@ struct LightingInput {
|
||||
// Specular reflectance at the normal incidence angle.
|
||||
F0_dielectric: vec3<f32>,
|
||||
F0_metallic: vec3<f32>,
|
||||
|
||||
|
||||
// Constants for the BRDF approximation.
|
||||
//
|
||||
// See `EnvBRDFApprox` in
|
||||
@@ -930,7 +930,7 @@ color *= (*light).color.rgb * texture_sample;
|
||||
// Sample atmosphere
|
||||
let transmittance = sample_transmittance_lut(r, mu_light);
|
||||
let sun_visibility = calculate_visible_sun_ratio(atmosphere, r, mu_light, (*light).sun_disk_angular_size);
|
||||
|
||||
|
||||
// Apply atmospheric effects
|
||||
color *= transmittance * sun_visibility;
|
||||
#endif
|
||||
@@ -983,12 +983,12 @@ fn ltc_integrate_quad(
|
||||
let a = L[i];
|
||||
let b = L[(i + 1) % 4];
|
||||
if (a.z >= 0.0) {
|
||||
clipped[n_clipped] = a;
|
||||
clipped[n_clipped] = a;
|
||||
n_clipped++;
|
||||
}
|
||||
if ((a.z >= 0.0) != (b.z >= 0.0)) {
|
||||
let t = a.z / (a.z - b.z);
|
||||
clipped[n_clipped] = mix(a, b, t);
|
||||
clipped[n_clipped] = mix(a, b, t);
|
||||
n_clipped++;
|
||||
}
|
||||
}
|
||||
@@ -1010,6 +1010,7 @@ fn ltc_integrate_quad(
|
||||
return sum;
|
||||
}
|
||||
|
||||
#ifdef AREA_LIGHT_LUTS
|
||||
fn rect_light(
|
||||
light_id: u32,
|
||||
input: ptr<function, LightingInput>,
|
||||
@@ -1046,8 +1047,8 @@ fn rect_light(
|
||||
let LUT_SCALE = 63.0 / 64.0;
|
||||
let LUT_BIAS = 0.5 / 64.0;
|
||||
let uv = vec2<f32>(perceptual_roughness, sqrt(1.0 - NdotV)) * LUT_SCALE + LUT_BIAS;
|
||||
let t1 = textureSampleLevel(view_bindings::ltc_lut1, view_bindings::ltc_lut_sampler, uv, 0.0);
|
||||
let t2 = textureSampleLevel(view_bindings::ltc_lut2, view_bindings::ltc_lut_sampler, uv, 0.0);
|
||||
let t1 = textureSampleLevel(view_bindings::area_light_luts, view_bindings::area_light_luts_sampler, uv, 0, 0.0);
|
||||
let t2 = textureSampleLevel(view_bindings::area_light_luts, view_bindings::area_light_luts_sampler, uv, 1, 0.0);
|
||||
|
||||
// Reconstruct the GGX inverse-LTC matrix
|
||||
let Minv = mat3x3<f32>(
|
||||
@@ -1077,8 +1078,8 @@ fn rect_light(
|
||||
|
||||
// Sample LUTs for clearcoat layer
|
||||
let cc_uv = vec2<f32>(clearcoat_perceptual_roughness, sqrt(1.0 - clearcoat_NdotV)) * LUT_SCALE + LUT_BIAS;
|
||||
let tc1 = textureSampleLevel(view_bindings::ltc_lut1, view_bindings::ltc_lut_sampler, cc_uv, 0.0);
|
||||
let tc2 = textureSampleLevel(view_bindings::ltc_lut2, view_bindings::ltc_lut_sampler, cc_uv, 0.0);
|
||||
let tc1 = textureSampleLevel(view_bindings::area_light_luts, view_bindings::area_light_luts_sampler, cc_uv, 0, 0.0);
|
||||
let tc2 = textureSampleLevel(view_bindings::area_light_luts, view_bindings::area_light_luts_sampler, cc_uv, 1, 0.0);
|
||||
let Minv_cc = mat3x3<f32>(
|
||||
vec3<f32>(tc1.x, 0.0, tc1.y),
|
||||
vec3<f32>(0.0, 1.0, 0.0),
|
||||
@@ -1097,13 +1098,14 @@ fn rect_light(
|
||||
return (spec_weight * spec + diffuse_color * diff) * (*light).color.rgb * range_falloff;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef ATMOSPHERE
|
||||
fn sample_transmittance_lut(r: f32, mu: f32) -> vec3<f32> {
|
||||
let uv = transmittance_lut_r_mu_to_uv(view_bindings::atmosphere, r, mu);
|
||||
return textureSampleLevel(
|
||||
view_bindings::atmosphere_transmittance_texture,
|
||||
view_bindings::atmosphere_transmittance_texture,
|
||||
view_bindings::atmosphere_transmittance_sampler, uv, 0.0).rgb;
|
||||
}
|
||||
#endif // ATMOSPHERE
|
||||
|
||||
@@ -514,6 +514,9 @@ impl SpecializedRenderPipeline for ScreenSpaceReflectionsPipeline {
|
||||
if cfg!(feature = "dfg_lut") {
|
||||
shader_defs.push("DFG_LUT".into());
|
||||
}
|
||||
if cfg!(feature = "area_light_luts") {
|
||||
shader_defs.push("AREA_LIGHT_LUTS".into());
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
shader_defs.push("USE_DEPTH_SAMPLERS".into());
|
||||
|
||||
@@ -62,6 +62,7 @@ This is the complete `bevy` cargo feature list, without "profiles" or "collectio
|
||||
|accesskit_unix|Enable AccessKit on Unix backends (currently only works with experimental screen readers and forks.)|
|
||||
|android-game-activity|Android GameActivity support. Default, choose between this and `android-native-activity`.|
|
||||
|android-native-activity|Android NativeActivity support. Legacy, should be avoided for most new Android games.|
|
||||
|area_light_luts|Include Look Up Tables that are required for area lights.|
|
||||
|asset_processor|Enables the built-in asset processor for processed assets.|
|
||||
|async-io|Use async-io's implementation of block_on instead of futures-lite's implementation. This is preferred if your application uses async-io.|
|
||||
|async_executor|Uses `async-executor` as a task execution backend.|
|
||||
|
||||
Reference in New Issue
Block a user