mirror of
https://github.com/bevyengine/bevy
synced 2024-11-13 00:17:27 +00:00
Add support for environment map transformation (#14290)
# Objective - Fixes: https://github.com/bevyengine/bevy/issues/14036 ## Solution - Add a world space transformation for the environment sample direction. ## Testing - I have tested the newly added `transform` field using the newly added `rotate_environment_map` example. https://github.com/user-attachments/assets/2de77c65-14bc-48ee-b76a-fb4e9782dbdb ## Migration Guide - Since we have added a new filed to the `EnvironmentMapLight` struct, users will need to include `..default()` or some rotation value in their initialization code.
This commit is contained in:
parent
d8d49fdd13
commit
9da18cce2a
35 changed files with 373 additions and 63 deletions
12
Cargo.toml
12
Cargo.toml
|
@ -3315,6 +3315,18 @@ description = "Demonstrates the built-in postprocessing features"
|
||||||
category = "3D Rendering"
|
category = "3D Rendering"
|
||||||
wasm = true
|
wasm = true
|
||||||
|
|
||||||
|
[[example]]
|
||||||
|
name = "rotate_environment_map"
|
||||||
|
path = "examples/3d/rotate_environment_map.rs"
|
||||||
|
doc-scrape-examples = true
|
||||||
|
required-features = ["pbr_multi_layer_material_textures"]
|
||||||
|
|
||||||
|
[package.metadata.example.rotate_environment_map]
|
||||||
|
name = "Rotate Environment Map"
|
||||||
|
description = "Demonstrates how to rotate the skybox and the environment map simultaneously"
|
||||||
|
category = "3D Rendering"
|
||||||
|
wasm = false
|
||||||
|
|
||||||
[profile.wasm-release]
|
[profile.wasm-release]
|
||||||
inherits = "release"
|
inherits = "release"
|
||||||
opt-level = "z"
|
opt-level = "z"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
graph::NodePbr, irradiance_volume::IrradianceVolume, prelude::EnvironmentMapLight,
|
graph::NodePbr, irradiance_volume::IrradianceVolume, prelude::EnvironmentMapLight,
|
||||||
MeshPipeline, MeshViewBindGroup, RenderViewLightProbes, ScreenSpaceAmbientOcclusionSettings,
|
MeshPipeline, MeshViewBindGroup, RenderViewLightProbes, ScreenSpaceAmbientOcclusionSettings,
|
||||||
ScreenSpaceReflectionsUniform, ViewLightProbesUniformOffset,
|
ScreenSpaceReflectionsUniform, ViewEnvironmentMapUniformOffset, ViewLightProbesUniformOffset,
|
||||||
ViewScreenSpaceReflectionsUniformOffset,
|
ViewScreenSpaceReflectionsUniformOffset,
|
||||||
};
|
};
|
||||||
use bevy_app::prelude::*;
|
use bevy_app::prelude::*;
|
||||||
|
@ -149,6 +149,7 @@ impl ViewNode for DeferredOpaquePass3dPbrLightingNode {
|
||||||
&'static ViewFogUniformOffset,
|
&'static ViewFogUniformOffset,
|
||||||
&'static ViewLightProbesUniformOffset,
|
&'static ViewLightProbesUniformOffset,
|
||||||
&'static ViewScreenSpaceReflectionsUniformOffset,
|
&'static ViewScreenSpaceReflectionsUniformOffset,
|
||||||
|
&'static ViewEnvironmentMapUniformOffset,
|
||||||
&'static MeshViewBindGroup,
|
&'static MeshViewBindGroup,
|
||||||
&'static ViewTarget,
|
&'static ViewTarget,
|
||||||
&'static DeferredLightingIdDepthTexture,
|
&'static DeferredLightingIdDepthTexture,
|
||||||
|
@ -165,6 +166,7 @@ impl ViewNode for DeferredOpaquePass3dPbrLightingNode {
|
||||||
view_fog_offset,
|
view_fog_offset,
|
||||||
view_light_probes_offset,
|
view_light_probes_offset,
|
||||||
view_ssr_offset,
|
view_ssr_offset,
|
||||||
|
view_environment_map_offset,
|
||||||
mesh_view_bind_group,
|
mesh_view_bind_group,
|
||||||
target,
|
target,
|
||||||
deferred_lighting_id_depth_texture,
|
deferred_lighting_id_depth_texture,
|
||||||
|
@ -220,6 +222,7 @@ impl ViewNode for DeferredOpaquePass3dPbrLightingNode {
|
||||||
view_fog_offset.offset,
|
view_fog_offset.offset,
|
||||||
**view_light_probes_offset,
|
**view_light_probes_offset,
|
||||||
**view_ssr_offset,
|
**view_ssr_offset,
|
||||||
|
**view_environment_map_offset,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
render_pass.set_bind_group(1, &bind_group_1, &[]);
|
render_pass.set_bind_group(1, &bind_group_1, &[]);
|
||||||
|
@ -256,11 +259,11 @@ impl SpecializedRenderPipeline for DeferredLightingLayout {
|
||||||
shader_defs.push("TONEMAP_IN_SHADER".into());
|
shader_defs.push("TONEMAP_IN_SHADER".into());
|
||||||
shader_defs.push(ShaderDefVal::UInt(
|
shader_defs.push(ShaderDefVal::UInt(
|
||||||
"TONEMAPPING_LUT_TEXTURE_BINDING_INDEX".into(),
|
"TONEMAPPING_LUT_TEXTURE_BINDING_INDEX".into(),
|
||||||
20,
|
21,
|
||||||
));
|
));
|
||||||
shader_defs.push(ShaderDefVal::UInt(
|
shader_defs.push(ShaderDefVal::UInt(
|
||||||
"TONEMAPPING_LUT_SAMPLER_BINDING_INDEX".into(),
|
"TONEMAPPING_LUT_SAMPLER_BINDING_INDEX".into(),
|
||||||
21,
|
22,
|
||||||
));
|
));
|
||||||
|
|
||||||
let method = key.intersection(MeshPipelineKey::TONEMAP_METHOD_RESERVED_BITS);
|
let method = key.intersection(MeshPipelineKey::TONEMAP_METHOD_RESERVED_BITS);
|
||||||
|
|
|
@ -50,13 +50,15 @@ use bevy_asset::{AssetId, Handle};
|
||||||
use bevy_ecs::{
|
use bevy_ecs::{
|
||||||
bundle::Bundle, component::Component, query::QueryItem, system::lifetimeless::Read,
|
bundle::Bundle, component::Component, query::QueryItem, system::lifetimeless::Read,
|
||||||
};
|
};
|
||||||
|
use bevy_math::Quat;
|
||||||
use bevy_reflect::Reflect;
|
use bevy_reflect::Reflect;
|
||||||
use bevy_render::{
|
use bevy_render::{
|
||||||
extract_instances::ExtractInstance,
|
extract_instances::ExtractInstance,
|
||||||
prelude::SpatialBundle,
|
prelude::SpatialBundle,
|
||||||
render_asset::RenderAssets,
|
render_asset::RenderAssets,
|
||||||
render_resource::{
|
render_resource::{
|
||||||
binding_types, BindGroupLayoutEntryBuilder, Sampler, SamplerBindingType, Shader,
|
binding_types::{self, uniform_buffer},
|
||||||
|
BindGroupLayoutEntryBuilder, Sampler, SamplerBindingType, Shader, ShaderStages,
|
||||||
TextureSampleType, TextureView,
|
TextureSampleType, TextureView,
|
||||||
},
|
},
|
||||||
renderer::RenderDevice,
|
renderer::RenderDevice,
|
||||||
|
@ -67,7 +69,8 @@ use std::num::NonZeroU32;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
add_cubemap_texture_view, binding_arrays_are_usable, LightProbe, MAX_VIEW_LIGHT_PROBES,
|
add_cubemap_texture_view, binding_arrays_are_usable, EnvironmentMapUniform, LightProbe,
|
||||||
|
MAX_VIEW_LIGHT_PROBES,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{LightProbeComponent, RenderViewLightProbes};
|
use super::{LightProbeComponent, RenderViewLightProbes};
|
||||||
|
@ -96,6 +99,22 @@ pub struct EnvironmentMapLight {
|
||||||
///
|
///
|
||||||
/// See also <https://google.github.io/filament/Filament.html#lighting/imagebasedlights/iblunit>.
|
/// See also <https://google.github.io/filament/Filament.html#lighting/imagebasedlights/iblunit>.
|
||||||
pub intensity: f32,
|
pub intensity: f32,
|
||||||
|
|
||||||
|
/// World space rotation applied to the environment light cubemaps.
|
||||||
|
/// This is useful for users who require a different axis, such as the Z-axis, to serve
|
||||||
|
/// as the vertical axis.
|
||||||
|
pub rotation: Quat,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for EnvironmentMapLight {
|
||||||
|
fn default() -> Self {
|
||||||
|
EnvironmentMapLight {
|
||||||
|
diffuse_map: Handle::default(),
|
||||||
|
specular_map: Handle::default(),
|
||||||
|
intensity: 0.0,
|
||||||
|
rotation: Quat::IDENTITY,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Like [`EnvironmentMapLight`], but contains asset IDs instead of handles.
|
/// Like [`EnvironmentMapLight`], but contains asset IDs instead of handles.
|
||||||
|
@ -193,7 +212,7 @@ impl ExtractInstance for EnvironmentMapIds {
|
||||||
/// specular binding arrays respectively, in addition to the sampler.
|
/// specular binding arrays respectively, in addition to the sampler.
|
||||||
pub(crate) fn get_bind_group_layout_entries(
|
pub(crate) fn get_bind_group_layout_entries(
|
||||||
render_device: &RenderDevice,
|
render_device: &RenderDevice,
|
||||||
) -> [BindGroupLayoutEntryBuilder; 3] {
|
) -> [BindGroupLayoutEntryBuilder; 4] {
|
||||||
let mut texture_cube_binding =
|
let mut texture_cube_binding =
|
||||||
binding_types::texture_cube(TextureSampleType::Float { filterable: true });
|
binding_types::texture_cube(TextureSampleType::Float { filterable: true });
|
||||||
if binding_arrays_are_usable(render_device) {
|
if binding_arrays_are_usable(render_device) {
|
||||||
|
@ -205,6 +224,7 @@ pub(crate) fn get_bind_group_layout_entries(
|
||||||
texture_cube_binding,
|
texture_cube_binding,
|
||||||
texture_cube_binding,
|
texture_cube_binding,
|
||||||
binding_types::sampler(SamplerBindingType::Filtering),
|
binding_types::sampler(SamplerBindingType::Filtering),
|
||||||
|
uniform_buffer::<EnvironmentMapUniform>(true).visibility(ShaderStages::FRAGMENT),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,6 +332,7 @@ impl LightProbeComponent for EnvironmentMapLight {
|
||||||
diffuse_map: diffuse_map_handle,
|
diffuse_map: diffuse_map_handle,
|
||||||
specular_map: specular_map_handle,
|
specular_map: specular_map_handle,
|
||||||
intensity,
|
intensity,
|
||||||
|
..
|
||||||
}) = view_component
|
}) = view_component
|
||||||
{
|
{
|
||||||
if let (Some(_), Some(specular_map)) = (
|
if let (Some(_), Some(specular_map)) = (
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#import bevy_pbr::light_probe::query_light_probe
|
#import bevy_pbr::light_probe::query_light_probe
|
||||||
#import bevy_pbr::mesh_view_bindings as bindings
|
#import bevy_pbr::mesh_view_bindings as bindings
|
||||||
#import bevy_pbr::mesh_view_bindings::light_probes
|
#import bevy_pbr::mesh_view_bindings::light_probes
|
||||||
|
#import bevy_pbr::mesh_view_bindings::environment_map_uniform
|
||||||
#import bevy_pbr::lighting::{
|
#import bevy_pbr::lighting::{
|
||||||
F_Schlick_vec, LayerLightingInput, LightingInput, LAYER_BASE, LAYER_CLEARCOAT
|
F_Schlick_vec, LayerLightingInput, LightingInput, LAYER_BASE, LAYER_CLEARCOAT
|
||||||
}
|
}
|
||||||
|
@ -57,17 +58,29 @@ fn compute_radiances(
|
||||||
bindings::specular_environment_maps[query_result.texture_index]) - 1u);
|
bindings::specular_environment_maps[query_result.texture_index]) - 1u);
|
||||||
|
|
||||||
if (!found_diffuse_indirect) {
|
if (!found_diffuse_indirect) {
|
||||||
|
var irradiance_sample_dir = N;
|
||||||
|
// Rotating the world space ray direction by the environment light map transform matrix, it is
|
||||||
|
// equivalent to rotating the diffuse environment cubemap itself.
|
||||||
|
irradiance_sample_dir = (environment_map_uniform.transform * vec4(irradiance_sample_dir, 1.0)).xyz;
|
||||||
|
// Cube maps are left-handed so we negate the z coordinate.
|
||||||
|
irradiance_sample_dir.z = -irradiance_sample_dir.z;
|
||||||
radiances.irradiance = textureSampleLevel(
|
radiances.irradiance = textureSampleLevel(
|
||||||
bindings::diffuse_environment_maps[query_result.texture_index],
|
bindings::diffuse_environment_maps[query_result.texture_index],
|
||||||
bindings::environment_map_sampler,
|
bindings::environment_map_sampler,
|
||||||
vec3(N.xy, -N.z),
|
irradiance_sample_dir,
|
||||||
0.0).rgb * query_result.intensity;
|
0.0).rgb * query_result.intensity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var radiance_sample_dir = R;
|
||||||
|
// Rotating the world space ray direction by the environment light map transform matrix, it is
|
||||||
|
// equivalent to rotating the specular environment cubemap itself.
|
||||||
|
radiance_sample_dir = (environment_map_uniform.transform * vec4(radiance_sample_dir, 1.0)).xyz;
|
||||||
|
// Cube maps are left-handed so we negate the z coordinate.
|
||||||
|
radiance_sample_dir.z = -radiance_sample_dir.z;
|
||||||
radiances.radiance = textureSampleLevel(
|
radiances.radiance = textureSampleLevel(
|
||||||
bindings::specular_environment_maps[query_result.texture_index],
|
bindings::specular_environment_maps[query_result.texture_index],
|
||||||
bindings::environment_map_sampler,
|
bindings::environment_map_sampler,
|
||||||
vec3(R.xy, -R.z),
|
radiance_sample_dir,
|
||||||
radiance_level).rgb * query_result.intensity;
|
radiance_level).rgb * query_result.intensity;
|
||||||
|
|
||||||
return radiances;
|
return radiances;
|
||||||
|
@ -102,17 +115,29 @@ fn compute_radiances(
|
||||||
let intensity = light_probes.intensity_for_view;
|
let intensity = light_probes.intensity_for_view;
|
||||||
|
|
||||||
if (!found_diffuse_indirect) {
|
if (!found_diffuse_indirect) {
|
||||||
|
var irradiance_sample_dir = N;
|
||||||
|
// Rotating the world space ray direction by the environment light map transform matrix, it is
|
||||||
|
// equivalent to rotating the diffuse environment cubemap itself.
|
||||||
|
irradiance_sample_dir = (environment_map_uniform.transform * vec4(irradiance_sample_dir, 1.0)).xyz;
|
||||||
|
// Cube maps are left-handed so we negate the z coordinate.
|
||||||
|
irradiance_sample_dir.z = -irradiance_sample_dir.z;
|
||||||
radiances.irradiance = textureSampleLevel(
|
radiances.irradiance = textureSampleLevel(
|
||||||
bindings::diffuse_environment_map,
|
bindings::diffuse_environment_map,
|
||||||
bindings::environment_map_sampler,
|
bindings::environment_map_sampler,
|
||||||
vec3(N.xy, -N.z),
|
irradiance_sample_dir,
|
||||||
0.0).rgb * intensity;
|
0.0).rgb * intensity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var radiance_sample_dir = R;
|
||||||
|
// Rotating the world space ray direction by the environment light map transform matrix, it is
|
||||||
|
// equivalent to rotating the specular environment cubemap itself.
|
||||||
|
radiance_sample_dir = (environment_map_uniform.transform * vec4(radiance_sample_dir, 1.0)).xyz;
|
||||||
|
// Cube maps are left-handed so we negate the z coordinate.
|
||||||
|
radiance_sample_dir.z = -radiance_sample_dir.z;
|
||||||
radiances.radiance = textureSampleLevel(
|
radiances.radiance = textureSampleLevel(
|
||||||
bindings::specular_environment_map,
|
bindings::specular_environment_map,
|
||||||
bindings::environment_map_sampler,
|
bindings::environment_map_sampler,
|
||||||
vec3(R.xy, -R.z),
|
radiance_sample_dir,
|
||||||
radiance_level).rgb * intensity;
|
radiance_level).rgb * intensity;
|
||||||
|
|
||||||
return radiances;
|
return radiances;
|
||||||
|
|
|
@ -25,7 +25,7 @@ use bevy_render::{
|
||||||
view::ExtractedView,
|
view::ExtractedView,
|
||||||
Extract, ExtractSchedule, Render, RenderApp, RenderSet,
|
Extract, ExtractSchedule, Render, RenderApp, RenderSet,
|
||||||
};
|
};
|
||||||
use bevy_transform::prelude::GlobalTransform;
|
use bevy_transform::{components::Transform, prelude::GlobalTransform};
|
||||||
use bevy_utils::{tracing::error, HashMap};
|
use bevy_utils::{tracing::error, HashMap};
|
||||||
|
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
|
@ -296,6 +296,31 @@ impl LightProbe {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The uniform struct extracted from [`EnvironmentMapLight`].
|
||||||
|
/// Will be available for use in the Environment Map shader.
|
||||||
|
#[derive(Component, ShaderType, Clone)]
|
||||||
|
pub struct EnvironmentMapUniform {
|
||||||
|
/// The world space transformation matrix of the sample ray for environment cubemaps.
|
||||||
|
transform: Mat4,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for EnvironmentMapUniform {
|
||||||
|
fn default() -> Self {
|
||||||
|
EnvironmentMapUniform {
|
||||||
|
transform: Mat4::IDENTITY,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A GPU buffer that stores the environment map settings for each view.
|
||||||
|
#[derive(Resource, Default, Deref, DerefMut)]
|
||||||
|
pub struct EnvironmentMapUniformBuffer(pub DynamicUniformBuffer<EnvironmentMapUniform>);
|
||||||
|
|
||||||
|
/// A component that stores the offset within the
|
||||||
|
/// [`EnvironmentMapUniformBuffer`] for each view.
|
||||||
|
#[derive(Component, Default, Deref, DerefMut)]
|
||||||
|
pub struct ViewEnvironmentMapUniformOffset(u32);
|
||||||
|
|
||||||
impl Plugin for LightProbePlugin {
|
impl Plugin for LightProbePlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
load_internal_asset!(
|
load_internal_asset!(
|
||||||
|
@ -330,15 +355,41 @@ impl Plugin for LightProbePlugin {
|
||||||
render_app
|
render_app
|
||||||
.add_plugins(ExtractInstancesPlugin::<EnvironmentMapIds>::new())
|
.add_plugins(ExtractInstancesPlugin::<EnvironmentMapIds>::new())
|
||||||
.init_resource::<LightProbesBuffer>()
|
.init_resource::<LightProbesBuffer>()
|
||||||
|
.init_resource::<EnvironmentMapUniformBuffer>()
|
||||||
|
.add_systems(ExtractSchedule, gather_environment_map_uniform)
|
||||||
.add_systems(ExtractSchedule, gather_light_probes::<EnvironmentMapLight>)
|
.add_systems(ExtractSchedule, gather_light_probes::<EnvironmentMapLight>)
|
||||||
.add_systems(ExtractSchedule, gather_light_probes::<IrradianceVolume>)
|
.add_systems(ExtractSchedule, gather_light_probes::<IrradianceVolume>)
|
||||||
.add_systems(
|
.add_systems(
|
||||||
Render,
|
Render,
|
||||||
upload_light_probes.in_set(RenderSet::PrepareResources),
|
(upload_light_probes, prepare_environment_uniform_buffer)
|
||||||
|
.in_set(RenderSet::PrepareResources),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Extracts [`EnvironmentMapLight`] from views and creates [`EnvironmentMapUniform`] for them.
|
||||||
|
/// Compared to the `ExtractComponentPlugin`, this implementation will create a default instance
|
||||||
|
/// if one does not already exist.
|
||||||
|
fn gather_environment_map_uniform(
|
||||||
|
view_query: Extract<Query<(Entity, Option<&EnvironmentMapLight>), With<Camera3d>>>,
|
||||||
|
mut commands: Commands,
|
||||||
|
) {
|
||||||
|
for (view_entity, environment_map_light) in view_query.iter() {
|
||||||
|
let environment_map_uniform = if let Some(environment_map_light) = environment_map_light {
|
||||||
|
EnvironmentMapUniform {
|
||||||
|
transform: Transform::from_rotation(environment_map_light.rotation)
|
||||||
|
.compute_matrix()
|
||||||
|
.inverse(),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
EnvironmentMapUniform::default()
|
||||||
|
};
|
||||||
|
commands
|
||||||
|
.get_or_spawn(view_entity)
|
||||||
|
.insert(environment_map_uniform);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Gathers up all light probes of a single type in the scene and assigns them
|
/// Gathers up all light probes of a single type in the scene and assigns them
|
||||||
/// to views, performing frustum culling and distance sorting in the process.
|
/// to views, performing frustum culling and distance sorting in the process.
|
||||||
fn gather_light_probes<C>(
|
fn gather_light_probes<C>(
|
||||||
|
@ -395,6 +446,32 @@ fn gather_light_probes<C>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gathers up environment map settings for each applicable view and
|
||||||
|
/// writes them into a GPU buffer.
|
||||||
|
pub fn prepare_environment_uniform_buffer(
|
||||||
|
mut commands: Commands,
|
||||||
|
views: Query<(Entity, Option<&EnvironmentMapUniform>), With<ExtractedView>>,
|
||||||
|
mut environment_uniform_buffer: ResMut<EnvironmentMapUniformBuffer>,
|
||||||
|
render_device: Res<RenderDevice>,
|
||||||
|
render_queue: Res<RenderQueue>,
|
||||||
|
) {
|
||||||
|
let Some(mut writer) =
|
||||||
|
environment_uniform_buffer.get_writer(views.iter().len(), &render_device, &render_queue)
|
||||||
|
else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
for (view, environment_uniform) in views.iter() {
|
||||||
|
let uniform_offset = match environment_uniform {
|
||||||
|
None => 0,
|
||||||
|
Some(environment_uniform) => writer.write(environment_uniform),
|
||||||
|
};
|
||||||
|
commands
|
||||||
|
.entity(view)
|
||||||
|
.insert(ViewEnvironmentMapUniformOffset(uniform_offset));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// A system that runs after [`gather_light_probes`] and populates the GPU
|
// A system that runs after [`gather_light_probes`] and populates the GPU
|
||||||
// uniforms with the results.
|
// uniforms with the results.
|
||||||
//
|
//
|
||||||
|
|
|
@ -7,8 +7,8 @@ use super::{
|
||||||
MeshletGpuScene,
|
MeshletGpuScene,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
MeshViewBindGroup, PrepassViewBindGroup, ViewFogUniformOffset, ViewLightProbesUniformOffset,
|
MeshViewBindGroup, PrepassViewBindGroup, ViewEnvironmentMapUniformOffset, ViewFogUniformOffset,
|
||||||
ViewLightsUniformOffset, ViewScreenSpaceReflectionsUniformOffset,
|
ViewLightProbesUniformOffset, ViewLightsUniformOffset, ViewScreenSpaceReflectionsUniformOffset,
|
||||||
};
|
};
|
||||||
use bevy_core_pipeline::prepass::{
|
use bevy_core_pipeline::prepass::{
|
||||||
MotionVectorPrepass, PreviousViewUniformOffset, ViewPrepassTextures,
|
MotionVectorPrepass, PreviousViewUniformOffset, ViewPrepassTextures,
|
||||||
|
@ -41,6 +41,7 @@ impl ViewNode for MeshletMainOpaquePass3dNode {
|
||||||
&'static ViewFogUniformOffset,
|
&'static ViewFogUniformOffset,
|
||||||
&'static ViewLightProbesUniformOffset,
|
&'static ViewLightProbesUniformOffset,
|
||||||
&'static ViewScreenSpaceReflectionsUniformOffset,
|
&'static ViewScreenSpaceReflectionsUniformOffset,
|
||||||
|
&'static ViewEnvironmentMapUniformOffset,
|
||||||
&'static MeshletViewMaterialsMainOpaquePass,
|
&'static MeshletViewMaterialsMainOpaquePass,
|
||||||
&'static MeshletViewBindGroups,
|
&'static MeshletViewBindGroups,
|
||||||
&'static MeshletViewResources,
|
&'static MeshletViewResources,
|
||||||
|
@ -59,6 +60,7 @@ impl ViewNode for MeshletMainOpaquePass3dNode {
|
||||||
view_fog_offset,
|
view_fog_offset,
|
||||||
view_light_probes_offset,
|
view_light_probes_offset,
|
||||||
view_ssr_offset,
|
view_ssr_offset,
|
||||||
|
view_environment_map_offset,
|
||||||
meshlet_view_materials,
|
meshlet_view_materials,
|
||||||
meshlet_view_bind_groups,
|
meshlet_view_bind_groups,
|
||||||
meshlet_view_resources,
|
meshlet_view_resources,
|
||||||
|
@ -111,6 +113,7 @@ impl ViewNode for MeshletMainOpaquePass3dNode {
|
||||||
view_fog_offset.offset,
|
view_fog_offset.offset,
|
||||||
**view_light_probes_offset,
|
**view_light_probes_offset,
|
||||||
**view_ssr_offset,
|
**view_ssr_offset,
|
||||||
|
**view_environment_map_offset,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
render_pass.set_bind_group(1, meshlet_material_draw_bind_group, &[]);
|
render_pass.set_bind_group(1, meshlet_material_draw_bind_group, &[]);
|
||||||
|
|
|
@ -1774,11 +1774,11 @@ impl SpecializedMeshPipeline for MeshPipeline {
|
||||||
shader_defs.push("TONEMAP_IN_SHADER".into());
|
shader_defs.push("TONEMAP_IN_SHADER".into());
|
||||||
shader_defs.push(ShaderDefVal::UInt(
|
shader_defs.push(ShaderDefVal::UInt(
|
||||||
"TONEMAPPING_LUT_TEXTURE_BINDING_INDEX".into(),
|
"TONEMAPPING_LUT_TEXTURE_BINDING_INDEX".into(),
|
||||||
20,
|
21,
|
||||||
));
|
));
|
||||||
shader_defs.push(ShaderDefVal::UInt(
|
shader_defs.push(ShaderDefVal::UInt(
|
||||||
"TONEMAPPING_LUT_SAMPLER_BINDING_INDEX".into(),
|
"TONEMAPPING_LUT_SAMPLER_BINDING_INDEX".into(),
|
||||||
21,
|
22,
|
||||||
));
|
));
|
||||||
|
|
||||||
let method = key.intersection(MeshPipelineKey::TONEMAP_METHOD_RESERVED_BITS);
|
let method = key.intersection(MeshPipelineKey::TONEMAP_METHOD_RESERVED_BITS);
|
||||||
|
@ -2105,6 +2105,7 @@ impl<P: PhaseItem, const I: usize> RenderCommand<P> for SetMeshViewBindGroup<I>
|
||||||
Read<ViewFogUniformOffset>,
|
Read<ViewFogUniformOffset>,
|
||||||
Read<ViewLightProbesUniformOffset>,
|
Read<ViewLightProbesUniformOffset>,
|
||||||
Read<ViewScreenSpaceReflectionsUniformOffset>,
|
Read<ViewScreenSpaceReflectionsUniformOffset>,
|
||||||
|
Read<ViewEnvironmentMapUniformOffset>,
|
||||||
Read<MeshViewBindGroup>,
|
Read<MeshViewBindGroup>,
|
||||||
);
|
);
|
||||||
type ItemQuery = ();
|
type ItemQuery = ();
|
||||||
|
@ -2112,10 +2113,15 @@ impl<P: PhaseItem, const I: usize> RenderCommand<P> for SetMeshViewBindGroup<I>
|
||||||
#[inline]
|
#[inline]
|
||||||
fn render<'w>(
|
fn render<'w>(
|
||||||
_item: &P,
|
_item: &P,
|
||||||
(view_uniform, view_lights, view_fog, view_light_probes, view_ssr, mesh_view_bind_group): ROQueryItem<
|
(
|
||||||
'w,
|
view_uniform,
|
||||||
Self::ViewQuery,
|
view_lights,
|
||||||
>,
|
view_fog,
|
||||||
|
view_light_probes,
|
||||||
|
view_ssr,
|
||||||
|
view_environment_map,
|
||||||
|
mesh_view_bind_group,
|
||||||
|
): ROQueryItem<'w, Self::ViewQuery>,
|
||||||
_entity: Option<()>,
|
_entity: Option<()>,
|
||||||
_: SystemParamItem<'w, '_, Self::Param>,
|
_: SystemParamItem<'w, '_, Self::Param>,
|
||||||
pass: &mut TrackedRenderPass<'w>,
|
pass: &mut TrackedRenderPass<'w>,
|
||||||
|
@ -2129,6 +2135,7 @@ impl<P: PhaseItem, const I: usize> RenderCommand<P> for SetMeshViewBindGroup<I>
|
||||||
view_fog.offset,
|
view_fog.offset,
|
||||||
**view_light_probes,
|
**view_light_probes,
|
||||||
**view_ssr,
|
**view_ssr,
|
||||||
|
**view_environment_map,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -41,11 +41,11 @@ use crate::{
|
||||||
self, IrradianceVolume, RenderViewIrradianceVolumeBindGroupEntries,
|
self, IrradianceVolume, RenderViewIrradianceVolumeBindGroupEntries,
|
||||||
IRRADIANCE_VOLUMES_ARE_USABLE,
|
IRRADIANCE_VOLUMES_ARE_USABLE,
|
||||||
},
|
},
|
||||||
prepass, FogMeta, GlobalClusterableObjectMeta, GpuClusterableObjects, GpuFog, GpuLights,
|
prepass, EnvironmentMapUniformBuffer, FogMeta, GlobalClusterableObjectMeta,
|
||||||
LightMeta, LightProbesBuffer, LightProbesUniform, MeshPipeline, MeshPipelineKey,
|
GpuClusterableObjects, GpuFog, GpuLights, LightMeta, LightProbesBuffer, LightProbesUniform,
|
||||||
RenderViewLightProbes, ScreenSpaceAmbientOcclusionTextures, ScreenSpaceReflectionsBuffer,
|
MeshPipeline, MeshPipelineKey, RenderViewLightProbes, ScreenSpaceAmbientOcclusionTextures,
|
||||||
ScreenSpaceReflectionsUniform, ShadowSamplers, ViewClusterBindings, ViewShadowBindings,
|
ScreenSpaceReflectionsBuffer, ScreenSpaceReflectionsUniform, ShadowSamplers,
|
||||||
CLUSTERED_FORWARD_STORAGE_BUFFER_COUNT,
|
ViewClusterBindings, ViewShadowBindings, CLUSTERED_FORWARD_STORAGE_BUFFER_COUNT,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -299,6 +299,7 @@ fn layout_entries(
|
||||||
(15, environment_map_entries[0]),
|
(15, environment_map_entries[0]),
|
||||||
(16, environment_map_entries[1]),
|
(16, environment_map_entries[1]),
|
||||||
(17, environment_map_entries[2]),
|
(17, environment_map_entries[2]),
|
||||||
|
(18, environment_map_entries[3]),
|
||||||
));
|
));
|
||||||
|
|
||||||
// Irradiance volumes
|
// Irradiance volumes
|
||||||
|
@ -306,16 +307,16 @@ fn layout_entries(
|
||||||
let irradiance_volume_entries =
|
let irradiance_volume_entries =
|
||||||
irradiance_volume::get_bind_group_layout_entries(render_device);
|
irradiance_volume::get_bind_group_layout_entries(render_device);
|
||||||
entries = entries.extend_with_indices((
|
entries = entries.extend_with_indices((
|
||||||
(18, irradiance_volume_entries[0]),
|
(19, irradiance_volume_entries[0]),
|
||||||
(19, irradiance_volume_entries[1]),
|
(20, irradiance_volume_entries[1]),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tonemapping
|
// Tonemapping
|
||||||
let tonemapping_lut_entries = get_lut_bind_group_layout_entries();
|
let tonemapping_lut_entries = get_lut_bind_group_layout_entries();
|
||||||
entries = entries.extend_with_indices((
|
entries = entries.extend_with_indices((
|
||||||
(20, tonemapping_lut_entries[0]),
|
(21, tonemapping_lut_entries[0]),
|
||||||
(21, tonemapping_lut_entries[1]),
|
(22, tonemapping_lut_entries[1]),
|
||||||
));
|
));
|
||||||
|
|
||||||
// Prepass
|
// Prepass
|
||||||
|
@ -325,7 +326,7 @@ fn layout_entries(
|
||||||
{
|
{
|
||||||
for (entry, binding) in prepass::get_bind_group_layout_entries(layout_key)
|
for (entry, binding) in prepass::get_bind_group_layout_entries(layout_key)
|
||||||
.iter()
|
.iter()
|
||||||
.zip([22, 23, 24, 25])
|
.zip([23, 24, 25, 26])
|
||||||
{
|
{
|
||||||
if let Some(entry) = entry {
|
if let Some(entry) = entry {
|
||||||
entries = entries.extend_with_indices(((binding as u32, *entry),));
|
entries = entries.extend_with_indices(((binding as u32, *entry),));
|
||||||
|
@ -336,10 +337,10 @@ fn layout_entries(
|
||||||
// View Transmission Texture
|
// View Transmission Texture
|
||||||
entries = entries.extend_with_indices((
|
entries = entries.extend_with_indices((
|
||||||
(
|
(
|
||||||
26,
|
27,
|
||||||
texture_2d(TextureSampleType::Float { filterable: true }),
|
texture_2d(TextureSampleType::Float { filterable: true }),
|
||||||
),
|
),
|
||||||
(27, sampler(SamplerBindingType::Filtering)),
|
(28, sampler(SamplerBindingType::Filtering)),
|
||||||
));
|
));
|
||||||
|
|
||||||
entries.to_vec()
|
entries.to_vec()
|
||||||
|
@ -450,7 +451,7 @@ pub fn prepare_mesh_view_bind_groups(
|
||||||
light_meta: Res<LightMeta>,
|
light_meta: Res<LightMeta>,
|
||||||
global_light_meta: Res<GlobalClusterableObjectMeta>,
|
global_light_meta: Res<GlobalClusterableObjectMeta>,
|
||||||
fog_meta: Res<FogMeta>,
|
fog_meta: Res<FogMeta>,
|
||||||
view_uniforms: Res<ViewUniforms>,
|
(view_uniforms, environment_map_uniform): (Res<ViewUniforms>, Res<EnvironmentMapUniformBuffer>),
|
||||||
views: Query<(
|
views: Query<(
|
||||||
Entity,
|
Entity,
|
||||||
&ViewShadowBindings,
|
&ViewShadowBindings,
|
||||||
|
@ -484,6 +485,7 @@ pub fn prepare_mesh_view_bind_groups(
|
||||||
Some(light_probes_binding),
|
Some(light_probes_binding),
|
||||||
Some(visibility_ranges_buffer),
|
Some(visibility_ranges_buffer),
|
||||||
Some(ssr_binding),
|
Some(ssr_binding),
|
||||||
|
Some(environment_map_binding),
|
||||||
) = (
|
) = (
|
||||||
view_uniforms.uniforms.binding(),
|
view_uniforms.uniforms.binding(),
|
||||||
light_meta.view_gpu_lights.binding(),
|
light_meta.view_gpu_lights.binding(),
|
||||||
|
@ -493,6 +495,7 @@ pub fn prepare_mesh_view_bind_groups(
|
||||||
light_probes_buffer.binding(),
|
light_probes_buffer.binding(),
|
||||||
visibility_ranges.buffer().buffer(),
|
visibility_ranges.buffer().buffer(),
|
||||||
ssr_buffer.binding(),
|
ssr_buffer.binding(),
|
||||||
|
environment_map_uniform.binding(),
|
||||||
) {
|
) {
|
||||||
for (
|
for (
|
||||||
entity,
|
entity,
|
||||||
|
@ -559,6 +562,7 @@ pub fn prepare_mesh_view_bind_groups(
|
||||||
(15, diffuse_texture_view),
|
(15, diffuse_texture_view),
|
||||||
(16, specular_texture_view),
|
(16, specular_texture_view),
|
||||||
(17, sampler),
|
(17, sampler),
|
||||||
|
(18, environment_map_binding.clone()),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
RenderViewEnvironmentMapBindGroupEntries::Multiple {
|
RenderViewEnvironmentMapBindGroupEntries::Multiple {
|
||||||
|
@ -570,6 +574,7 @@ pub fn prepare_mesh_view_bind_groups(
|
||||||
(15, diffuse_texture_views.as_slice()),
|
(15, diffuse_texture_views.as_slice()),
|
||||||
(16, specular_texture_views.as_slice()),
|
(16, specular_texture_views.as_slice()),
|
||||||
(17, sampler),
|
(17, sampler),
|
||||||
|
(18, environment_map_binding.clone()),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -590,21 +595,21 @@ pub fn prepare_mesh_view_bind_groups(
|
||||||
texture_view,
|
texture_view,
|
||||||
sampler,
|
sampler,
|
||||||
}) => {
|
}) => {
|
||||||
entries = entries.extend_with_indices(((18, texture_view), (19, sampler)));
|
entries = entries.extend_with_indices(((19, texture_view), (20, sampler)));
|
||||||
}
|
}
|
||||||
Some(RenderViewIrradianceVolumeBindGroupEntries::Multiple {
|
Some(RenderViewIrradianceVolumeBindGroupEntries::Multiple {
|
||||||
ref texture_views,
|
ref texture_views,
|
||||||
sampler,
|
sampler,
|
||||||
}) => {
|
}) => {
|
||||||
entries = entries
|
entries = entries
|
||||||
.extend_with_indices(((18, texture_views.as_slice()), (19, sampler)));
|
.extend_with_indices(((19, texture_views.as_slice()), (20, sampler)));
|
||||||
}
|
}
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
let lut_bindings =
|
let lut_bindings =
|
||||||
get_lut_bindings(&images, &tonemapping_luts, tonemapping, &fallback_image);
|
get_lut_bindings(&images, &tonemapping_luts, tonemapping, &fallback_image);
|
||||||
entries = entries.extend_with_indices(((20, lut_bindings.0), (21, lut_bindings.1)));
|
entries = entries.extend_with_indices(((21, lut_bindings.0), (22, lut_bindings.1)));
|
||||||
|
|
||||||
// When using WebGL, we can't have a depth texture with multisampling
|
// When using WebGL, we can't have a depth texture with multisampling
|
||||||
let prepass_bindings;
|
let prepass_bindings;
|
||||||
|
@ -614,7 +619,7 @@ pub fn prepare_mesh_view_bind_groups(
|
||||||
for (binding, index) in prepass_bindings
|
for (binding, index) in prepass_bindings
|
||||||
.iter()
|
.iter()
|
||||||
.map(Option::as_ref)
|
.map(Option::as_ref)
|
||||||
.zip([22, 23, 24, 25])
|
.zip([23, 24, 25, 26])
|
||||||
.flat_map(|(b, i)| b.map(|b| (b, i)))
|
.flat_map(|(b, i)| b.map(|b| (b, i)))
|
||||||
{
|
{
|
||||||
entries = entries.extend_with_indices(((index, binding),));
|
entries = entries.extend_with_indices(((index, binding),));
|
||||||
|
@ -630,7 +635,7 @@ pub fn prepare_mesh_view_bind_groups(
|
||||||
.unwrap_or(&fallback_image_zero.sampler);
|
.unwrap_or(&fallback_image_zero.sampler);
|
||||||
|
|
||||||
entries =
|
entries =
|
||||||
entries.extend_with_indices(((26, transmission_view), (27, transmission_sampler)));
|
entries.extend_with_indices(((27, transmission_view), (28, transmission_sampler)));
|
||||||
|
|
||||||
commands.entity(entity).insert(MeshViewBindGroup {
|
commands.entity(entity).insert(MeshViewBindGroup {
|
||||||
value: render_device.create_bind_group("mesh_view_bind_group", layout, &entries),
|
value: render_device.create_bind_group("mesh_view_bind_group", layout, &entries),
|
||||||
|
|
|
@ -53,47 +53,48 @@ const VISIBILITY_RANGE_UNIFORM_BUFFER_SIZE: u32 = 64u;
|
||||||
@group(0) @binding(16) var specular_environment_map: texture_cube<f32>;
|
@group(0) @binding(16) var specular_environment_map: texture_cube<f32>;
|
||||||
#endif
|
#endif
|
||||||
@group(0) @binding(17) var environment_map_sampler: sampler;
|
@group(0) @binding(17) var environment_map_sampler: sampler;
|
||||||
|
@group(0) @binding(18) var<uniform> environment_map_uniform: types::EnvironmentMapUniform;
|
||||||
|
|
||||||
#ifdef IRRADIANCE_VOLUMES_ARE_USABLE
|
#ifdef IRRADIANCE_VOLUMES_ARE_USABLE
|
||||||
#ifdef MULTIPLE_LIGHT_PROBES_IN_ARRAY
|
#ifdef MULTIPLE_LIGHT_PROBES_IN_ARRAY
|
||||||
@group(0) @binding(18) var irradiance_volumes: binding_array<texture_3d<f32>, 8u>;
|
@group(0) @binding(19) var irradiance_volumes: binding_array<texture_3d<f32>, 8u>;
|
||||||
#else
|
#else
|
||||||
@group(0) @binding(18) var irradiance_volume: texture_3d<f32>;
|
@group(0) @binding(19) var irradiance_volume: texture_3d<f32>;
|
||||||
#endif
|
#endif
|
||||||
@group(0) @binding(19) var irradiance_volume_sampler: sampler;
|
@group(0) @binding(20) var irradiance_volume_sampler: sampler;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@group(0) @binding(20) var dt_lut_texture: texture_3d<f32>;
|
@group(0) @binding(21) var dt_lut_texture: texture_3d<f32>;
|
||||||
@group(0) @binding(21) var dt_lut_sampler: sampler;
|
@group(0) @binding(22) var dt_lut_sampler: sampler;
|
||||||
|
|
||||||
#ifdef MULTISAMPLED
|
#ifdef MULTISAMPLED
|
||||||
#ifdef DEPTH_PREPASS
|
#ifdef DEPTH_PREPASS
|
||||||
@group(0) @binding(22) var depth_prepass_texture: texture_depth_multisampled_2d;
|
@group(0) @binding(23) var depth_prepass_texture: texture_depth_multisampled_2d;
|
||||||
#endif // DEPTH_PREPASS
|
#endif // DEPTH_PREPASS
|
||||||
#ifdef NORMAL_PREPASS
|
#ifdef NORMAL_PREPASS
|
||||||
@group(0) @binding(23) var normal_prepass_texture: texture_multisampled_2d<f32>;
|
@group(0) @binding(24) var normal_prepass_texture: texture_multisampled_2d<f32>;
|
||||||
#endif // NORMAL_PREPASS
|
#endif // NORMAL_PREPASS
|
||||||
#ifdef MOTION_VECTOR_PREPASS
|
#ifdef MOTION_VECTOR_PREPASS
|
||||||
@group(0) @binding(24) var motion_vector_prepass_texture: texture_multisampled_2d<f32>;
|
@group(0) @binding(25) var motion_vector_prepass_texture: texture_multisampled_2d<f32>;
|
||||||
#endif // MOTION_VECTOR_PREPASS
|
#endif // MOTION_VECTOR_PREPASS
|
||||||
|
|
||||||
#else // MULTISAMPLED
|
#else // MULTISAMPLED
|
||||||
|
|
||||||
#ifdef DEPTH_PREPASS
|
#ifdef DEPTH_PREPASS
|
||||||
@group(0) @binding(22) var depth_prepass_texture: texture_depth_2d;
|
@group(0) @binding(23) var depth_prepass_texture: texture_depth_2d;
|
||||||
#endif // DEPTH_PREPASS
|
#endif // DEPTH_PREPASS
|
||||||
#ifdef NORMAL_PREPASS
|
#ifdef NORMAL_PREPASS
|
||||||
@group(0) @binding(23) var normal_prepass_texture: texture_2d<f32>;
|
@group(0) @binding(24) var normal_prepass_texture: texture_2d<f32>;
|
||||||
#endif // NORMAL_PREPASS
|
#endif // NORMAL_PREPASS
|
||||||
#ifdef MOTION_VECTOR_PREPASS
|
#ifdef MOTION_VECTOR_PREPASS
|
||||||
@group(0) @binding(24) var motion_vector_prepass_texture: texture_2d<f32>;
|
@group(0) @binding(25) var motion_vector_prepass_texture: texture_2d<f32>;
|
||||||
#endif // MOTION_VECTOR_PREPASS
|
#endif // MOTION_VECTOR_PREPASS
|
||||||
|
|
||||||
#endif // MULTISAMPLED
|
#endif // MULTISAMPLED
|
||||||
|
|
||||||
#ifdef DEFERRED_PREPASS
|
#ifdef DEFERRED_PREPASS
|
||||||
@group(0) @binding(25) var deferred_prepass_texture: texture_2d<u32>;
|
@group(0) @binding(26) var deferred_prepass_texture: texture_2d<u32>;
|
||||||
#endif // DEFERRED_PREPASS
|
#endif // DEFERRED_PREPASS
|
||||||
|
|
||||||
@group(0) @binding(26) var view_transmission_texture: texture_2d<f32>;
|
@group(0) @binding(27) var view_transmission_texture: texture_2d<f32>;
|
||||||
@group(0) @binding(27) var view_transmission_sampler: sampler;
|
@group(0) @binding(28) var view_transmission_sampler: sampler;
|
||||||
|
|
|
@ -148,3 +148,8 @@ struct ScreenSpaceReflectionsSettings {
|
||||||
bisection_steps: u32,
|
bisection_steps: u32,
|
||||||
use_secant: u32,
|
use_secant: u32,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct EnvironmentMapUniform {
|
||||||
|
// Transformation matrix for the environment cubemaps in world space.
|
||||||
|
transform: mat4x4<f32>,
|
||||||
|
};
|
|
@ -43,7 +43,8 @@ use bevy_utils::{info_once, prelude::default};
|
||||||
use crate::{
|
use crate::{
|
||||||
binding_arrays_are_usable, graph::NodePbr, prelude::EnvironmentMapLight,
|
binding_arrays_are_usable, graph::NodePbr, prelude::EnvironmentMapLight,
|
||||||
MeshPipelineViewLayoutKey, MeshPipelineViewLayouts, MeshViewBindGroup, RenderViewLightProbes,
|
MeshPipelineViewLayoutKey, MeshPipelineViewLayouts, MeshViewBindGroup, RenderViewLightProbes,
|
||||||
ViewFogUniformOffset, ViewLightProbesUniformOffset, ViewLightsUniformOffset,
|
ViewEnvironmentMapUniformOffset, ViewFogUniformOffset, ViewLightProbesUniformOffset,
|
||||||
|
ViewLightsUniformOffset,
|
||||||
};
|
};
|
||||||
|
|
||||||
const SSR_SHADER_HANDLE: Handle<Shader> = Handle::weak_from_u128(10438925299917978850);
|
const SSR_SHADER_HANDLE: Handle<Shader> = Handle::weak_from_u128(10438925299917978850);
|
||||||
|
@ -258,6 +259,7 @@ impl ViewNode for ScreenSpaceReflectionsNode {
|
||||||
Read<ViewFogUniformOffset>,
|
Read<ViewFogUniformOffset>,
|
||||||
Read<ViewLightProbesUniformOffset>,
|
Read<ViewLightProbesUniformOffset>,
|
||||||
Read<ViewScreenSpaceReflectionsUniformOffset>,
|
Read<ViewScreenSpaceReflectionsUniformOffset>,
|
||||||
|
Read<ViewEnvironmentMapUniformOffset>,
|
||||||
Read<MeshViewBindGroup>,
|
Read<MeshViewBindGroup>,
|
||||||
Read<ScreenSpaceReflectionsPipelineId>,
|
Read<ScreenSpaceReflectionsPipelineId>,
|
||||||
);
|
);
|
||||||
|
@ -273,6 +275,7 @@ impl ViewNode for ScreenSpaceReflectionsNode {
|
||||||
view_fog_offset,
|
view_fog_offset,
|
||||||
view_light_probes_offset,
|
view_light_probes_offset,
|
||||||
view_ssr_offset,
|
view_ssr_offset,
|
||||||
|
view_environment_map_offset,
|
||||||
view_bind_group,
|
view_bind_group,
|
||||||
ssr_pipeline_id,
|
ssr_pipeline_id,
|
||||||
): QueryItem<'w, Self::ViewQuery>,
|
): QueryItem<'w, Self::ViewQuery>,
|
||||||
|
@ -324,6 +327,7 @@ impl ViewNode for ScreenSpaceReflectionsNode {
|
||||||
view_fog_offset.offset,
|
view_fog_offset.offset,
|
||||||
**view_light_probes_offset,
|
**view_light_probes_offset,
|
||||||
**view_ssr_offset,
|
**view_ssr_offset,
|
||||||
|
**view_environment_map_offset,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -46,8 +46,9 @@ use bitflags::bitflags;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
FogVolume, MeshPipelineViewLayoutKey, MeshPipelineViewLayouts, MeshViewBindGroup,
|
FogVolume, MeshPipelineViewLayoutKey, MeshPipelineViewLayouts, MeshViewBindGroup,
|
||||||
ViewFogUniformOffset, ViewLightProbesUniformOffset, ViewLightsUniformOffset,
|
ViewEnvironmentMapUniformOffset, ViewFogUniformOffset, ViewLightProbesUniformOffset,
|
||||||
ViewScreenSpaceReflectionsUniformOffset, VolumetricFogSettings, VolumetricLight,
|
ViewLightsUniformOffset, ViewScreenSpaceReflectionsUniformOffset, VolumetricFogSettings,
|
||||||
|
VolumetricLight,
|
||||||
};
|
};
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
|
@ -306,6 +307,7 @@ impl ViewNode for VolumetricFogNode {
|
||||||
Read<ViewVolumetricFog>,
|
Read<ViewVolumetricFog>,
|
||||||
Read<MeshViewBindGroup>,
|
Read<MeshViewBindGroup>,
|
||||||
Read<ViewScreenSpaceReflectionsUniformOffset>,
|
Read<ViewScreenSpaceReflectionsUniformOffset>,
|
||||||
|
Read<ViewEnvironmentMapUniformOffset>,
|
||||||
);
|
);
|
||||||
|
|
||||||
fn run<'w>(
|
fn run<'w>(
|
||||||
|
@ -323,6 +325,7 @@ impl ViewNode for VolumetricFogNode {
|
||||||
view_fog_volumes,
|
view_fog_volumes,
|
||||||
view_bind_group,
|
view_bind_group,
|
||||||
view_ssr_offset,
|
view_ssr_offset,
|
||||||
|
view_environment_map_offset,
|
||||||
): QueryItem<'w, Self::ViewQuery>,
|
): QueryItem<'w, Self::ViewQuery>,
|
||||||
world: &'w World,
|
world: &'w World,
|
||||||
) -> Result<(), NodeRunError> {
|
) -> Result<(), NodeRunError> {
|
||||||
|
@ -445,6 +448,7 @@ impl ViewNode for VolumetricFogNode {
|
||||||
view_fog_offset.offset,
|
view_fog_offset.offset,
|
||||||
**view_light_probes_offset,
|
**view_light_probes_offset,
|
||||||
**view_ssr_offset,
|
**view_ssr_offset,
|
||||||
|
**view_environment_map_offset,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
render_pass.set_bind_group(
|
render_pass.set_bind_group(
|
||||||
|
|
|
@ -26,6 +26,7 @@ fn setup(
|
||||||
diffuse_map: asset_server.load("environment_maps/pisa_diffuse_rgb9e5_zstd.ktx2"),
|
diffuse_map: asset_server.load("environment_maps/pisa_diffuse_rgb9e5_zstd.ktx2"),
|
||||||
specular_map: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
|
specular_map: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
|
||||||
intensity: 2_000.0,
|
intensity: 2_000.0,
|
||||||
|
..default()
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|
|
@ -240,12 +240,13 @@ fn add_skybox_and_environment_map(
|
||||||
.insert(Skybox {
|
.insert(Skybox {
|
||||||
brightness: 5000.0,
|
brightness: 5000.0,
|
||||||
image: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
|
image: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
|
||||||
..Default::default()
|
..default()
|
||||||
})
|
})
|
||||||
.insert(EnvironmentMapLight {
|
.insert(EnvironmentMapLight {
|
||||||
diffuse_map: asset_server.load("environment_maps/pisa_diffuse_rgb9e5_zstd.ktx2"),
|
diffuse_map: asset_server.load("environment_maps/pisa_diffuse_rgb9e5_zstd.ktx2"),
|
||||||
specular_map: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
|
specular_map: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
|
||||||
intensity: 2500.0,
|
intensity: 2500.0,
|
||||||
|
..default()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -324,6 +324,7 @@ fn setup(
|
||||||
diffuse_map: asset_server.load("environment_maps/pisa_diffuse_rgb9e5_zstd.ktx2"),
|
diffuse_map: asset_server.load("environment_maps/pisa_diffuse_rgb9e5_zstd.ktx2"),
|
||||||
specular_map: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
|
specular_map: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
|
||||||
intensity: 150.0,
|
intensity: 150.0,
|
||||||
|
..default()
|
||||||
},
|
},
|
||||||
FogSettings {
|
FogSettings {
|
||||||
color: Color::srgba_u8(43, 44, 47, 255),
|
color: Color::srgba_u8(43, 44, 47, 255),
|
||||||
|
|
|
@ -54,7 +54,7 @@ fn setup(
|
||||||
Skybox {
|
Skybox {
|
||||||
image: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
|
image: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
|
||||||
brightness: bevy::pbr::light_consts::lux::DIRECT_SUNLIGHT,
|
brightness: bevy::pbr::light_consts::lux::DIRECT_SUNLIGHT,
|
||||||
..Default::default()
|
..default()
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|
|
@ -224,12 +224,13 @@ fn spawn_camera(commands: &mut Commands, asset_server: &AssetServer) {
|
||||||
.insert(Skybox {
|
.insert(Skybox {
|
||||||
brightness: 5000.0,
|
brightness: 5000.0,
|
||||||
image: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
|
image: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
|
||||||
..Default::default()
|
..default()
|
||||||
})
|
})
|
||||||
.insert(EnvironmentMapLight {
|
.insert(EnvironmentMapLight {
|
||||||
diffuse_map: asset_server.load("environment_maps/pisa_diffuse_rgb9e5_zstd.ktx2"),
|
diffuse_map: asset_server.load("environment_maps/pisa_diffuse_rgb9e5_zstd.ktx2"),
|
||||||
specular_map: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
|
specular_map: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
|
||||||
intensity: 2000.0,
|
intensity: 2000.0,
|
||||||
|
..default()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -374,6 +374,7 @@ fn add_camera(commands: &mut Commands, asset_server: &AssetServer, color_grading
|
||||||
diffuse_map: asset_server.load("environment_maps/pisa_diffuse_rgb9e5_zstd.ktx2"),
|
diffuse_map: asset_server.load("environment_maps/pisa_diffuse_rgb9e5_zstd.ktx2"),
|
||||||
specular_map: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
|
specular_map: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
|
||||||
intensity: 2000.0,
|
intensity: 2000.0,
|
||||||
|
..default()
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,6 +56,7 @@ fn setup(
|
||||||
diffuse_map: asset_server.load("environment_maps/pisa_diffuse_rgb9e5_zstd.ktx2"),
|
diffuse_map: asset_server.load("environment_maps/pisa_diffuse_rgb9e5_zstd.ktx2"),
|
||||||
specular_map: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
|
specular_map: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
|
||||||
intensity: 2000.0,
|
intensity: 2000.0,
|
||||||
|
..default()
|
||||||
},
|
},
|
||||||
DepthPrepass,
|
DepthPrepass,
|
||||||
MotionVectorPrepass,
|
MotionVectorPrepass,
|
||||||
|
|
|
@ -239,7 +239,7 @@ fn spawn_camera(commands: &mut Commands, assets: &ExampleAssets) {
|
||||||
.insert(Skybox {
|
.insert(Skybox {
|
||||||
image: assets.skybox.clone(),
|
image: assets.skybox.clone(),
|
||||||
brightness: 150.0,
|
brightness: 150.0,
|
||||||
..Default::default()
|
..default()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||||
diffuse_map: asset_server.load("environment_maps/pisa_diffuse_rgb9e5_zstd.ktx2"),
|
diffuse_map: asset_server.load("environment_maps/pisa_diffuse_rgb9e5_zstd.ktx2"),
|
||||||
specular_map: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
|
specular_map: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
|
||||||
intensity: 250.0,
|
intensity: 250.0,
|
||||||
|
..default()
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|
|
@ -56,6 +56,7 @@ fn setup(
|
||||||
diffuse_map: asset_server.load("environment_maps/pisa_diffuse_rgb9e5_zstd.ktx2"),
|
diffuse_map: asset_server.load("environment_maps/pisa_diffuse_rgb9e5_zstd.ktx2"),
|
||||||
specular_map: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
|
specular_map: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
|
||||||
intensity: 150.0,
|
intensity: 150.0,
|
||||||
|
..default()
|
||||||
},
|
},
|
||||||
CameraController::default(),
|
CameraController::default(),
|
||||||
));
|
));
|
||||||
|
|
|
@ -130,6 +130,7 @@ fn setup(
|
||||||
diffuse_map: asset_server.load("environment_maps/pisa_diffuse_rgb9e5_zstd.ktx2"),
|
diffuse_map: asset_server.load("environment_maps/pisa_diffuse_rgb9e5_zstd.ktx2"),
|
||||||
specular_map: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
|
specular_map: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
|
||||||
intensity: 900.0,
|
intensity: 900.0,
|
||||||
|
..default()
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,6 +80,7 @@ fn spawn_camera(commands: &mut Commands, asset_server: &AssetServer) {
|
||||||
diffuse_map: asset_server.load("environment_maps/pisa_diffuse_rgb9e5_zstd.ktx2"),
|
diffuse_map: asset_server.load("environment_maps/pisa_diffuse_rgb9e5_zstd.ktx2"),
|
||||||
specular_map: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
|
specular_map: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
|
||||||
intensity: 2000.0,
|
intensity: 2000.0,
|
||||||
|
..default()
|
||||||
},
|
},
|
||||||
// Include the `ChromaticAberration` component.
|
// Include the `ChromaticAberration` component.
|
||||||
ChromaticAberration::default(),
|
ChromaticAberration::default(),
|
||||||
|
|
|
@ -151,6 +151,7 @@ fn spawn_reflection_probe(commands: &mut Commands, cubemaps: &Cubemaps) {
|
||||||
diffuse_map: cubemaps.diffuse.clone(),
|
diffuse_map: cubemaps.diffuse.clone(),
|
||||||
specular_map: cubemaps.specular_reflection_probe.clone(),
|
specular_map: cubemaps.specular_reflection_probe.clone(),
|
||||||
intensity: 5000.0,
|
intensity: 5000.0,
|
||||||
|
..default()
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -187,7 +188,7 @@ fn add_environment_map_to_camera(
|
||||||
.insert(Skybox {
|
.insert(Skybox {
|
||||||
image: cubemaps.skybox.clone(),
|
image: cubemaps.skybox.clone(),
|
||||||
brightness: 5000.0,
|
brightness: 5000.0,
|
||||||
..Default::default()
|
..default()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -299,6 +300,7 @@ fn create_camera_environment_map_light(cubemaps: &Cubemaps) -> EnvironmentMapLig
|
||||||
diffuse_map: cubemaps.diffuse.clone(),
|
diffuse_map: cubemaps.diffuse.clone(),
|
||||||
specular_map: cubemaps.specular_environment_map.clone(),
|
specular_map: cubemaps.specular_environment_map.clone(),
|
||||||
intensity: 5000.0,
|
intensity: 5000.0,
|
||||||
|
..default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
124
examples/3d/rotate_environment_map.rs
Normal file
124
examples/3d/rotate_environment_map.rs
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
//! Demonstrates how to rotate the skybox and the environment map simultaneously.
|
||||||
|
|
||||||
|
use std::f32::consts::PI;
|
||||||
|
|
||||||
|
use bevy::{
|
||||||
|
color::palettes::css::{GOLD, WHITE},
|
||||||
|
core_pipeline::{tonemapping::Tonemapping::AcesFitted, Skybox},
|
||||||
|
prelude::*,
|
||||||
|
render::texture::ImageLoaderSettings,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Entry point.
|
||||||
|
pub fn main() {
|
||||||
|
App::new()
|
||||||
|
.add_plugins(DefaultPlugins)
|
||||||
|
.add_systems(Startup, setup)
|
||||||
|
.add_systems(Update, rotate_skybox_and_environment_map)
|
||||||
|
.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Initializes the scene.
|
||||||
|
fn setup(
|
||||||
|
mut commands: Commands,
|
||||||
|
mut meshes: ResMut<Assets<Mesh>>,
|
||||||
|
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||||
|
asset_server: Res<AssetServer>,
|
||||||
|
) {
|
||||||
|
let sphere_mesh = create_sphere_mesh(&mut meshes);
|
||||||
|
spawn_sphere(&mut commands, &mut materials, &asset_server, &sphere_mesh);
|
||||||
|
spawn_light(&mut commands);
|
||||||
|
spawn_camera(&mut commands, &asset_server);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Rotate the skybox and the environment map per frame.
|
||||||
|
fn rotate_skybox_and_environment_map(
|
||||||
|
mut environments: Query<(&mut Skybox, &mut EnvironmentMapLight)>,
|
||||||
|
time: Res<Time>,
|
||||||
|
) {
|
||||||
|
let now = time.elapsed_seconds();
|
||||||
|
let rotation = Quat::from_rotation_y(0.2 * now);
|
||||||
|
for (mut skybox, mut environment_map) in environments.iter_mut() {
|
||||||
|
skybox.rotation = rotation;
|
||||||
|
environment_map.rotation = rotation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generates a sphere.
|
||||||
|
fn create_sphere_mesh(meshes: &mut Assets<Mesh>) -> Handle<Mesh> {
|
||||||
|
// We're going to use normal maps, so make sure we've generated tangents, or
|
||||||
|
// else the normal maps won't show up.
|
||||||
|
|
||||||
|
let mut sphere_mesh = Sphere::new(1.0).mesh().build();
|
||||||
|
sphere_mesh
|
||||||
|
.generate_tangents()
|
||||||
|
.expect("Failed to generate tangents");
|
||||||
|
meshes.add(sphere_mesh)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Spawn a regular object with a clearcoat layer. This looks like car paint.
|
||||||
|
fn spawn_sphere(
|
||||||
|
commands: &mut Commands,
|
||||||
|
materials: &mut Assets<StandardMaterial>,
|
||||||
|
asset_server: &AssetServer,
|
||||||
|
sphere_mesh: &Handle<Mesh>,
|
||||||
|
) {
|
||||||
|
commands.spawn(PbrBundle {
|
||||||
|
mesh: sphere_mesh.clone(),
|
||||||
|
material: materials.add(StandardMaterial {
|
||||||
|
clearcoat: 1.0,
|
||||||
|
clearcoat_perceptual_roughness: 0.3,
|
||||||
|
clearcoat_normal_texture: Some(asset_server.load_with_settings(
|
||||||
|
"textures/ScratchedGold-Normal.png",
|
||||||
|
|settings: &mut ImageLoaderSettings| settings.is_srgb = false,
|
||||||
|
)),
|
||||||
|
metallic: 0.9,
|
||||||
|
perceptual_roughness: 0.1,
|
||||||
|
base_color: GOLD.into(),
|
||||||
|
..default()
|
||||||
|
}),
|
||||||
|
transform: Transform::from_xyz(0.0, 0.0, 0.0).with_scale(Vec3::splat(1.25)),
|
||||||
|
..default()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Spawns a light.
|
||||||
|
fn spawn_light(commands: &mut Commands) {
|
||||||
|
commands.spawn(PointLightBundle {
|
||||||
|
point_light: PointLight {
|
||||||
|
color: WHITE.into(),
|
||||||
|
intensity: 100000.0,
|
||||||
|
..default()
|
||||||
|
},
|
||||||
|
..default()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Spawns a camera with associated skybox and environment map.
|
||||||
|
fn spawn_camera(commands: &mut Commands, asset_server: &AssetServer) {
|
||||||
|
commands
|
||||||
|
.spawn(Camera3dBundle {
|
||||||
|
camera: Camera {
|
||||||
|
hdr: true,
|
||||||
|
..default()
|
||||||
|
},
|
||||||
|
projection: Projection::Perspective(PerspectiveProjection {
|
||||||
|
fov: 27.0 / 180.0 * PI,
|
||||||
|
..default()
|
||||||
|
}),
|
||||||
|
transform: Transform::from_xyz(0.0, 0.0, 10.0),
|
||||||
|
tonemapping: AcesFitted,
|
||||||
|
..default()
|
||||||
|
})
|
||||||
|
.insert(Skybox {
|
||||||
|
brightness: 5000.0,
|
||||||
|
image: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
|
||||||
|
..default()
|
||||||
|
})
|
||||||
|
.insert(EnvironmentMapLight {
|
||||||
|
diffuse_map: asset_server.load("environment_maps/pisa_diffuse_rgb9e5_zstd.ktx2"),
|
||||||
|
specular_map: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
|
||||||
|
intensity: 2000.0,
|
||||||
|
..default()
|
||||||
|
});
|
||||||
|
}
|
|
@ -81,7 +81,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||||
Skybox {
|
Skybox {
|
||||||
image: skybox_handle.clone(),
|
image: skybox_handle.clone(),
|
||||||
brightness: 1000.0,
|
brightness: 1000.0,
|
||||||
..Default::default()
|
..default()
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|
|
@ -242,11 +242,12 @@ fn spawn_camera(commands: &mut Commands, asset_server: &AssetServer) {
|
||||||
diffuse_map: asset_server.load("environment_maps/pisa_diffuse_rgb9e5_zstd.ktx2"),
|
diffuse_map: asset_server.load("environment_maps/pisa_diffuse_rgb9e5_zstd.ktx2"),
|
||||||
specular_map: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
|
specular_map: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
|
||||||
intensity: 5000.0,
|
intensity: 5000.0,
|
||||||
|
..default()
|
||||||
})
|
})
|
||||||
.insert(Skybox {
|
.insert(Skybox {
|
||||||
image: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
|
image: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
|
||||||
brightness: 5000.0,
|
brightness: 5000.0,
|
||||||
..Default::default()
|
..default()
|
||||||
})
|
})
|
||||||
.insert(ScreenSpaceReflectionsBundle::default())
|
.insert(ScreenSpaceReflectionsBundle::default())
|
||||||
.insert(Fxaa::default());
|
.insert(Fxaa::default());
|
||||||
|
|
|
@ -78,6 +78,7 @@ fn setup(
|
||||||
diffuse_map: asset_server.load("environment_maps/pisa_diffuse_rgb9e5_zstd.ktx2"),
|
diffuse_map: asset_server.load("environment_maps/pisa_diffuse_rgb9e5_zstd.ktx2"),
|
||||||
specular_map: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
|
specular_map: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
|
||||||
intensity: 2000.0,
|
intensity: 2000.0,
|
||||||
|
..default()
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|
|
@ -360,6 +360,7 @@ fn setup(
|
||||||
intensity: 25.0,
|
intensity: 25.0,
|
||||||
diffuse_map: asset_server.load("environment_maps/pisa_diffuse_rgb9e5_zstd.ktx2"),
|
diffuse_map: asset_server.load("environment_maps/pisa_diffuse_rgb9e5_zstd.ktx2"),
|
||||||
specular_map: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
|
specular_map: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
|
||||||
|
..default()
|
||||||
},
|
},
|
||||||
BloomSettings::default(),
|
BloomSettings::default(),
|
||||||
));
|
));
|
||||||
|
|
|
@ -34,6 +34,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||||
diffuse_map: asset_server.load("environment_maps/pisa_diffuse_rgb9e5_zstd.ktx2"),
|
diffuse_map: asset_server.load("environment_maps/pisa_diffuse_rgb9e5_zstd.ktx2"),
|
||||||
specular_map: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
|
specular_map: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
|
||||||
intensity: 150.0,
|
intensity: 150.0,
|
||||||
|
..default()
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|
|
@ -152,6 +152,7 @@ fn setup(
|
||||||
diffuse_map: asset_server.load("environment_maps/pisa_diffuse_rgb9e5_zstd.ktx2"),
|
diffuse_map: asset_server.load("environment_maps/pisa_diffuse_rgb9e5_zstd.ktx2"),
|
||||||
specular_map: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
|
specular_map: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
|
||||||
intensity: 150.0,
|
intensity: 150.0,
|
||||||
|
..default()
|
||||||
});
|
});
|
||||||
|
|
||||||
// Create the text.
|
// Create the text.
|
||||||
|
|
|
@ -52,7 +52,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||||
.insert(Skybox {
|
.insert(Skybox {
|
||||||
image: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
|
image: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
|
||||||
brightness: 1000.0,
|
brightness: 1000.0,
|
||||||
..Default::default()
|
..default()
|
||||||
})
|
})
|
||||||
.insert(VolumetricFogSettings {
|
.insert(VolumetricFogSettings {
|
||||||
// This value is explicitly set to 0 since we have no environment map light
|
// This value is explicitly set to 0 since we have no environment map light
|
||||||
|
|
|
@ -157,6 +157,7 @@ Example | Description
|
||||||
[Physically Based Rendering](../examples/3d/pbr.rs) | Demonstrates use of Physically Based Rendering (PBR) properties
|
[Physically Based Rendering](../examples/3d/pbr.rs) | Demonstrates use of Physically Based Rendering (PBR) properties
|
||||||
[Reflection Probes](../examples/3d/reflection_probes.rs) | Demonstrates reflection probes
|
[Reflection Probes](../examples/3d/reflection_probes.rs) | Demonstrates reflection probes
|
||||||
[Render to Texture](../examples/3d/render_to_texture.rs) | Shows how to render to a texture, useful for mirrors, UI, or exporting images
|
[Render to Texture](../examples/3d/render_to_texture.rs) | Shows how to render to a texture, useful for mirrors, UI, or exporting images
|
||||||
|
[Rotate Environment Map](../examples/3d/rotate_environment_map.rs) | Demonstrates how to rotate the skybox and the environment map simultaneously
|
||||||
[Screen Space Ambient Occlusion](../examples/3d/ssao.rs) | A scene showcasing screen space ambient occlusion
|
[Screen Space Ambient Occlusion](../examples/3d/ssao.rs) | A scene showcasing screen space ambient occlusion
|
||||||
[Screen Space Reflections](../examples/3d/ssr.rs) | Demonstrates screen space reflections with water ripples
|
[Screen Space Reflections](../examples/3d/ssr.rs) | Demonstrates screen space reflections with water ripples
|
||||||
[Shadow Biases](../examples/3d/shadow_biases.rs) | Demonstrates how shadow biases affect shadows in a 3d scene
|
[Shadow Biases](../examples/3d/shadow_biases.rs) | Demonstrates how shadow biases affect shadows in a 3d scene
|
||||||
|
|
|
@ -145,6 +145,7 @@ fn setup_scene_after_load(
|
||||||
specular_map: asset_server
|
specular_map: asset_server
|
||||||
.load("assets/environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
|
.load("assets/environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
|
||||||
intensity: 150.0,
|
intensity: 150.0,
|
||||||
|
..default()
|
||||||
},
|
},
|
||||||
camera_controller,
|
camera_controller,
|
||||||
));
|
));
|
||||||
|
|
Loading…
Reference in a new issue