mirror of
https://github.com/bevyengine/bevy
synced 2024-11-25 14:10:19 +00:00
Exposure settings (adopted) (#11347)
Rebased and finished version of https://github.com/bevyengine/bevy/pull/8407. Huge thanks to @GitGhillie for adjusting all the examples, and the many other people who helped write this PR (@superdump , @coreh , among others) :) Fixes https://github.com/bevyengine/bevy/issues/8369 --- ## Changelog - Added a `brightness` control to `Skybox`. - Added an `intensity` control to `EnvironmentMapLight`. - Added `ExposureSettings` and `PhysicalCameraParameters` for controlling exposure of 3D cameras. - Removed the baked-in `DirectionalLight` exposure Bevy previously hardcoded internally. ## Migration Guide - If using a `Skybox` or `EnvironmentMapLight`, use the new `brightness` and `intensity` controls to adjust their strength. - All 3D scene will now have different apparent brightnesses due to Bevy implementing proper exposure controls. You will have to adjust the intensity of your lights and/or your camera exposure via the new `ExposureSettings` component to compensate. --------- Co-authored-by: Robert Swain <robert.swain@gmail.com> Co-authored-by: GitGhillie <jillisnoordhoek@gmail.com> Co-authored-by: Marco Buono <thecoreh@gmail.com> Co-authored-by: vero <email@atlasdostal.com> Co-authored-by: atlas dostal <rodol@rivalrebels.com>
This commit is contained in:
parent
184f233a67
commit
fcd7c0fc3d
70 changed files with 436 additions and 131 deletions
|
@ -76,13 +76,17 @@ impl ViewNode for MainOpaquePass3dNode {
|
|||
}
|
||||
|
||||
// Draw the skybox using a fullscreen triangle
|
||||
if let (Some(skybox_pipeline), Some(skybox_bind_group)) =
|
||||
if let (Some(skybox_pipeline), Some(SkyboxBindGroup(skybox_bind_group))) =
|
||||
(skybox_pipeline, skybox_bind_group)
|
||||
{
|
||||
let pipeline_cache = world.resource::<PipelineCache>();
|
||||
if let Some(pipeline) = pipeline_cache.get_render_pipeline(skybox_pipeline.0) {
|
||||
render_pass.set_render_pipeline(pipeline);
|
||||
render_pass.set_bind_group(0, &skybox_bind_group.0, &[view_uniform_offset.offset]);
|
||||
render_pass.set_bind_group(
|
||||
0,
|
||||
&skybox_bind_group.0,
|
||||
&[view_uniform_offset.offset, skybox_bind_group.1],
|
||||
);
|
||||
render_pass.draw(0..3, 0..1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,21 +2,20 @@ use bevy_app::{App, Plugin};
|
|||
use bevy_asset::{load_internal_asset, Handle};
|
||||
use bevy_ecs::{
|
||||
prelude::{Component, Entity},
|
||||
query::With,
|
||||
query::{QueryItem, With},
|
||||
schedule::IntoSystemConfigs,
|
||||
system::{Commands, Query, Res, ResMut, Resource},
|
||||
};
|
||||
use bevy_render::{
|
||||
extract_component::{ExtractComponent, ExtractComponentPlugin},
|
||||
camera::ExposureSettings,
|
||||
extract_component::{
|
||||
ComponentUniforms, DynamicUniformIndex, ExtractComponent, ExtractComponentPlugin,
|
||||
UniformComponentPlugin,
|
||||
},
|
||||
render_asset::RenderAssets,
|
||||
render_resource::{
|
||||
binding_types::{sampler, texture_cube, uniform_buffer},
|
||||
BindGroup, BindGroupEntries, BindGroupLayout, BindGroupLayoutEntries,
|
||||
CachedRenderPipelineId, ColorTargetState, ColorWrites, CompareFunction, DepthBiasState,
|
||||
DepthStencilState, FragmentState, MultisampleState, PipelineCache, PrimitiveState,
|
||||
RenderPipelineDescriptor, SamplerBindingType, Shader, ShaderStages,
|
||||
SpecializedRenderPipeline, SpecializedRenderPipelines, StencilFaceState, StencilState,
|
||||
TextureFormat, TextureSampleType, VertexState,
|
||||
*,
|
||||
},
|
||||
renderer::RenderDevice,
|
||||
texture::{BevyDefault, Image},
|
||||
|
@ -34,7 +33,10 @@ impl Plugin for SkyboxPlugin {
|
|||
fn build(&self, app: &mut App) {
|
||||
load_internal_asset!(app, SKYBOX_SHADER_HANDLE, "skybox.wgsl", Shader::from_wgsl);
|
||||
|
||||
app.add_plugins(ExtractComponentPlugin::<Skybox>::default());
|
||||
app.add_plugins((
|
||||
ExtractComponentPlugin::<Skybox>::default(),
|
||||
UniformComponentPlugin::<SkyboxUniforms>::default(),
|
||||
));
|
||||
|
||||
let Ok(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
|
@ -68,8 +70,41 @@ impl Plugin for SkyboxPlugin {
|
|||
/// To do so, use `EnvironmentMapLight` alongside this component.
|
||||
///
|
||||
/// See also <https://en.wikipedia.org/wiki/Skybox_(video_games)>.
|
||||
#[derive(Component, ExtractComponent, Clone)]
|
||||
pub struct Skybox(pub Handle<Image>);
|
||||
#[derive(Component, Clone)]
|
||||
pub struct Skybox {
|
||||
pub image: Handle<Image>,
|
||||
/// Scale factor applied to the skybox image.
|
||||
/// After applying this multiplier to the image samples, the resulting values should
|
||||
/// be in units of [cd/m^2](https://en.wikipedia.org/wiki/Candela_per_square_metre).
|
||||
pub brightness: f32,
|
||||
}
|
||||
|
||||
impl ExtractComponent for Skybox {
|
||||
type Data = (&'static Self, Option<&'static ExposureSettings>);
|
||||
type Filter = ();
|
||||
type Out = (Self, SkyboxUniforms);
|
||||
|
||||
fn extract_component(
|
||||
(skybox, exposure_settings): QueryItem<'_, Self::Data>,
|
||||
) -> Option<Self::Out> {
|
||||
let exposure = exposure_settings
|
||||
.map(|e| e.exposure())
|
||||
.unwrap_or_else(|| ExposureSettings::default().exposure());
|
||||
|
||||
Some((
|
||||
skybox.clone(),
|
||||
SkyboxUniforms {
|
||||
brightness: skybox.brightness * exposure,
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Replace with a push constant once WebGPU gets support for that
|
||||
#[derive(Component, ShaderType, Clone)]
|
||||
pub struct SkyboxUniforms {
|
||||
brightness: f32,
|
||||
}
|
||||
|
||||
#[derive(Resource)]
|
||||
struct SkyboxPipeline {
|
||||
|
@ -88,6 +123,7 @@ impl SkyboxPipeline {
|
|||
sampler(SamplerBindingType::Filtering),
|
||||
uniform_buffer::<ViewUniform>(true)
|
||||
.visibility(ShaderStages::VERTEX_FRAGMENT),
|
||||
uniform_buffer::<SkyboxUniforms>(true),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -186,20 +222,23 @@ fn prepare_skybox_pipelines(
|
|||
}
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct SkyboxBindGroup(pub BindGroup);
|
||||
pub struct SkyboxBindGroup(pub (BindGroup, u32));
|
||||
|
||||
fn prepare_skybox_bind_groups(
|
||||
mut commands: Commands,
|
||||
pipeline: Res<SkyboxPipeline>,
|
||||
view_uniforms: Res<ViewUniforms>,
|
||||
skybox_uniforms: Res<ComponentUniforms<SkyboxUniforms>>,
|
||||
images: Res<RenderAssets<Image>>,
|
||||
render_device: Res<RenderDevice>,
|
||||
views: Query<(Entity, &Skybox)>,
|
||||
views: Query<(Entity, &Skybox, &DynamicUniformIndex<SkyboxUniforms>)>,
|
||||
) {
|
||||
for (entity, skybox) in &views {
|
||||
if let (Some(skybox), Some(view_uniforms)) =
|
||||
(images.get(&skybox.0), view_uniforms.uniforms.binding())
|
||||
{
|
||||
for (entity, skybox, skybox_uniform_index) in &views {
|
||||
if let (Some(skybox), Some(view_uniforms), Some(skybox_uniforms)) = (
|
||||
images.get(&skybox.image),
|
||||
view_uniforms.uniforms.binding(),
|
||||
skybox_uniforms.binding(),
|
||||
) {
|
||||
let bind_group = render_device.create_bind_group(
|
||||
"skybox_bind_group",
|
||||
&pipeline.bind_group_layout,
|
||||
|
@ -207,10 +246,13 @@ fn prepare_skybox_bind_groups(
|
|||
&skybox.texture_view,
|
||||
&skybox.sampler,
|
||||
view_uniforms,
|
||||
skybox_uniforms,
|
||||
)),
|
||||
);
|
||||
|
||||
commands.entity(entity).insert(SkyboxBindGroup(bind_group));
|
||||
commands
|
||||
.entity(entity)
|
||||
.insert(SkyboxBindGroup((bind_group, skybox_uniform_index.index())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
@group(0) @binding(0) var skybox: texture_cube<f32>;
|
||||
@group(0) @binding(1) var skybox_sampler: sampler;
|
||||
@group(0) @binding(2) var<uniform> view: View;
|
||||
@group(0) @binding(3) var<uniform> brightness: f32;
|
||||
|
||||
fn coords_to_ray_direction(position: vec2<f32>, viewport: vec4<f32>) -> vec3<f32> {
|
||||
// Using world positions of the fragment and camera to calculate a ray direction
|
||||
|
@ -62,5 +63,5 @@ fn skybox_fragment(in: VertexOutput) -> @location(0) vec4<f32> {
|
|||
let ray_direction = coords_to_ray_direction(in.position.xy, view.viewport);
|
||||
|
||||
// Cube maps are left-handed so we negate the z coordinate.
|
||||
return textureSample(skybox, skybox_sampler, ray_direction * vec3(1.0, 1.0, -1.0));
|
||||
return textureSample(skybox, skybox_sampler, ray_direction * vec3(1.0, 1.0, -1.0)) * brightness;
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ fn environment_map_light(
|
|||
let kD = diffuse_color * Edss;
|
||||
|
||||
var out: EnvironmentMapLight;
|
||||
out.diffuse = (FmsEms + kD) * irradiance;
|
||||
out.specular = FssEss * radiance;
|
||||
out.diffuse = (FmsEms + kD) * irradiance * bindings::lights.environment_map_intensity;
|
||||
out.specular = FssEss * radiance * bindings::lights.environment_map_intensity;
|
||||
return out;
|
||||
}
|
||||
|
|
|
@ -51,6 +51,13 @@ impl Plugin for EnvironmentMapPlugin {
|
|||
pub struct EnvironmentMapLight {
|
||||
pub diffuse_map: Handle<Image>,
|
||||
pub specular_map: Handle<Image>,
|
||||
/// Scale factor applied to the diffuse and specular light generated by this component.
|
||||
///
|
||||
/// After applying this multiplier, the resulting values should
|
||||
/// be in units of [cd/m^2](https://en.wikipedia.org/wiki/Candela_per_square_metre).
|
||||
///
|
||||
/// See also <https://google.github.io/filament/Filament.html#lighting/imagebasedlights/iblunit>.
|
||||
pub intensity: f32,
|
||||
}
|
||||
|
||||
impl EnvironmentMapLight {
|
||||
|
|
|
@ -557,7 +557,7 @@ fn calculate_cascade(
|
|||
/// # use bevy_ecs::system::ResMut;
|
||||
/// # use bevy_pbr::AmbientLight;
|
||||
/// fn setup_ambient_light(mut ambient_light: ResMut<AmbientLight>) {
|
||||
/// ambient_light.brightness = 0.3;
|
||||
/// ambient_light.brightness = 20.0;
|
||||
/// }
|
||||
/// ```
|
||||
#[derive(Resource, Clone, Debug, ExtractResource, Reflect)]
|
||||
|
@ -572,7 +572,7 @@ impl Default for AmbientLight {
|
|||
fn default() -> Self {
|
||||
Self {
|
||||
color: Color::rgb(1.0, 1.0, 1.0),
|
||||
brightness: 0.05,
|
||||
brightness: 8.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -197,6 +197,7 @@ pub struct GpuLights {
|
|||
// offset from spot light's light index to spot light's shadow map index
|
||||
spot_light_shadowmap_offset: i32,
|
||||
environment_map_smallest_specular_mip_level: u32,
|
||||
environment_map_intensity: f32,
|
||||
}
|
||||
|
||||
// NOTE: this must be kept in sync with the same constants in pbr.frag
|
||||
|
@ -857,18 +858,6 @@ pub fn prepare_lights(
|
|||
flags |= DirectionalLightFlags::SHADOWS_ENABLED;
|
||||
}
|
||||
|
||||
// convert from illuminance (lux) to candelas
|
||||
//
|
||||
// exposure is hard coded at the moment but should be replaced
|
||||
// by values coming from the camera
|
||||
// see: https://google.github.io/filament/Filament.html#imagingpipeline/physicallybasedcamera/exposuresettings
|
||||
const APERTURE: f32 = 4.0;
|
||||
const SHUTTER_SPEED: f32 = 1.0 / 250.0;
|
||||
const SENSITIVITY: f32 = 100.0;
|
||||
let ev100 = f32::log2(APERTURE * APERTURE / SHUTTER_SPEED) - f32::log2(SENSITIVITY / 100.0);
|
||||
let exposure = 1.0 / (f32::powf(2.0, ev100) * 1.2);
|
||||
let intensity = light.illuminance * exposure;
|
||||
|
||||
let num_cascades = light
|
||||
.cascade_shadow_config
|
||||
.bounds
|
||||
|
@ -877,9 +866,9 @@ pub fn prepare_lights(
|
|||
gpu_directional_lights[index] = GpuDirectionalLight {
|
||||
// Filled in later.
|
||||
cascades: [GpuDirectionalCascade::default(); MAX_CASCADES_PER_LIGHT],
|
||||
// premultiply color by intensity
|
||||
// premultiply color by illuminance
|
||||
// we don't use the alpha at all, so no reason to multiply only [0..3]
|
||||
color: Vec4::from_slice(&light.color.as_linear_rgba_f32()) * intensity,
|
||||
color: Vec4::from_slice(&light.color.as_linear_rgba_f32()) * light.illuminance,
|
||||
// direction is negated to be ready for N.L
|
||||
dir_to_light: light.transform.back(),
|
||||
flags: flags.bits(),
|
||||
|
@ -972,6 +961,9 @@ pub fn prepare_lights(
|
|||
.and_then(|env_map| images.get(&env_map.specular_map))
|
||||
.map(|specular_map| specular_map.mip_level_count - 1)
|
||||
.unwrap_or(0),
|
||||
environment_map_intensity: environment_map
|
||||
.map(|env_map| env_map.intensity)
|
||||
.unwrap_or(1.0),
|
||||
};
|
||||
|
||||
// TODO: this should select lights based on relevance to the view instead of the first ones that show up in a query
|
||||
|
|
|
@ -58,6 +58,7 @@ struct Lights {
|
|||
n_directional_lights: u32,
|
||||
spot_light_shadowmap_offset: i32,
|
||||
environment_map_smallest_specular_mip_level: u32,
|
||||
environment_map_intensity: f32,
|
||||
};
|
||||
|
||||
struct Fog {
|
||||
|
|
|
@ -386,7 +386,7 @@ fn apply_pbr_lighting(
|
|||
|
||||
// Total light
|
||||
output_color = vec4<f32>(
|
||||
transmitted_light + direct_light + indirect_light + emissive_light,
|
||||
view_bindings::view.exposure * (transmitted_light + direct_light + indirect_light + emissive_light),
|
||||
output_color.a
|
||||
);
|
||||
|
||||
|
@ -423,7 +423,7 @@ fn apply_fog(fog_params: mesh_view_types::Fog, input_color: vec4<f32>, fragment_
|
|||
0.0
|
||||
),
|
||||
fog_params.directional_light_exponent
|
||||
) * light.color.rgb;
|
||||
) * light.color.rgb * view_bindings::view.exposure;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,9 @@ fn specular_transmissive_light(world_position: vec4<f32>, frag_coord: vec3<f32>,
|
|||
background_color = fetch_transmissive_background(offset_position, frag_coord, view_z, perceptual_roughness);
|
||||
}
|
||||
|
||||
// Compensate for exposure, since the background color is coming from an already exposure-adjusted texture
|
||||
background_color = vec4(background_color.rgb / view_bindings::view.exposure, background_color.a);
|
||||
|
||||
// Dot product of the refracted direction with the exit normal (Note: We assume the exit normal is the entry normal but inverted)
|
||||
let MinusNdotT = dot(-N, T);
|
||||
|
||||
|
|
|
@ -84,6 +84,73 @@ pub struct ComputedCameraValues {
|
|||
old_viewport_size: Option<UVec2>,
|
||||
}
|
||||
|
||||
/// How much energy a `Camera3d` absorbs from incoming light.
|
||||
///
|
||||
/// <https://en.wikipedia.org/wiki/Exposure_(photography)>
|
||||
#[derive(Component)]
|
||||
pub struct ExposureSettings {
|
||||
/// <https://en.wikipedia.org/wiki/Exposure_value#Tabulated_exposure_values>
|
||||
pub ev100: f32,
|
||||
}
|
||||
|
||||
impl ExposureSettings {
|
||||
pub const EV100_SUNLIGHT: f32 = 15.0;
|
||||
pub const EV100_OVERCAST: f32 = 12.0;
|
||||
pub const EV100_INDOOR: f32 = 7.0;
|
||||
|
||||
pub fn from_physical_camera(physical_camera_parameters: PhysicalCameraParameters) -> Self {
|
||||
Self {
|
||||
ev100: physical_camera_parameters.ev100(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts EV100 values to exposure values.
|
||||
/// <https://google.github.io/filament/Filament.md.html#imagingpipeline/physicallybasedcamera/exposure>
|
||||
#[inline]
|
||||
pub fn exposure(&self) -> f32 {
|
||||
(-self.ev100).exp2() / 1.2
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for ExposureSettings {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
ev100: Self::EV100_INDOOR,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Parameters based on physical camera characteristics for calculating
|
||||
/// EV100 values for use with [`ExposureSettings`].
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct PhysicalCameraParameters {
|
||||
/// <https://en.wikipedia.org/wiki/F-number>
|
||||
pub aperture_f_stops: f32,
|
||||
/// <https://en.wikipedia.org/wiki/Shutter_speed>
|
||||
pub shutter_speed_s: f32,
|
||||
/// <https://en.wikipedia.org/wiki/Film_speed>
|
||||
pub sensitivity_iso: f32,
|
||||
}
|
||||
|
||||
impl PhysicalCameraParameters {
|
||||
/// Calculate the [EV100](https://en.wikipedia.org/wiki/Exposure_value).
|
||||
pub fn ev100(&self) -> f32 {
|
||||
(self.aperture_f_stops * self.aperture_f_stops * 100.0
|
||||
/ (self.shutter_speed_s * self.sensitivity_iso))
|
||||
.log2()
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for PhysicalCameraParameters {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
aperture_f_stops: 1.0,
|
||||
shutter_speed_s: 1.0 / 125.0,
|
||||
sensitivity_iso: 100.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The defining [`Component`] for camera entities,
|
||||
/// storing information about how and what to render through this camera.
|
||||
///
|
||||
|
@ -695,6 +762,7 @@ pub struct ExtractedCamera {
|
|||
pub msaa_writeback: bool,
|
||||
pub clear_color: ClearColorConfig,
|
||||
pub sorted_camera_index_for_target: usize,
|
||||
pub exposure: f32,
|
||||
}
|
||||
|
||||
pub fn extract_cameras(
|
||||
|
@ -708,6 +776,7 @@ pub fn extract_cameras(
|
|||
&VisibleEntities,
|
||||
&Frustum,
|
||||
Option<&ColorGrading>,
|
||||
Option<&ExposureSettings>,
|
||||
Option<&TemporalJitter>,
|
||||
Option<&RenderLayers>,
|
||||
Option<&Projection>,
|
||||
|
@ -724,6 +793,7 @@ pub fn extract_cameras(
|
|||
visible_entities,
|
||||
frustum,
|
||||
color_grading,
|
||||
exposure_settings,
|
||||
temporal_jitter,
|
||||
render_layers,
|
||||
projection,
|
||||
|
@ -766,6 +836,9 @@ pub fn extract_cameras(
|
|||
clear_color: camera.clear_color.clone(),
|
||||
// this will be set in sort_cameras
|
||||
sorted_camera_index_for_target: 0,
|
||||
exposure: exposure_settings
|
||||
.map(|e| e.exposure())
|
||||
.unwrap_or_else(|| ExposureSettings::default().exposure()),
|
||||
},
|
||||
ExtractedView {
|
||||
projection: camera.projection_matrix(),
|
||||
|
|
|
@ -7,7 +7,8 @@ pub use window::*;
|
|||
|
||||
use crate::{
|
||||
camera::{
|
||||
ClearColor, ClearColorConfig, ExtractedCamera, ManualTextureViews, MipBias, TemporalJitter,
|
||||
ClearColor, ClearColorConfig, ExposureSettings, ExtractedCamera, ManualTextureViews,
|
||||
MipBias, TemporalJitter,
|
||||
},
|
||||
extract_resource::{ExtractResource, ExtractResourcePlugin},
|
||||
prelude::{Image, Shader},
|
||||
|
@ -170,6 +171,7 @@ pub struct ViewUniform {
|
|||
projection: Mat4,
|
||||
inverse_projection: Mat4,
|
||||
world_position: Vec3,
|
||||
exposure: f32,
|
||||
// viewport(x_origin, y_origin, width, height)
|
||||
viewport: Vec4,
|
||||
frustum: [Vec4; 6],
|
||||
|
@ -368,6 +370,7 @@ pub fn prepare_view_uniforms(
|
|||
mut view_uniforms: ResMut<ViewUniforms>,
|
||||
views: Query<(
|
||||
Entity,
|
||||
Option<&ExtractedCamera>,
|
||||
&ExtractedView,
|
||||
Option<&Frustum>,
|
||||
Option<&TemporalJitter>,
|
||||
|
@ -384,9 +387,18 @@ pub fn prepare_view_uniforms(
|
|||
else {
|
||||
return;
|
||||
};
|
||||
for (entity, camera, frustum, temporal_jitter, mip_bias, maybe_layers) in &views {
|
||||
let viewport = camera.viewport.as_vec4();
|
||||
let unjittered_projection = camera.projection;
|
||||
for (
|
||||
entity,
|
||||
extracted_camera,
|
||||
extracted_view,
|
||||
frustum,
|
||||
temporal_jitter,
|
||||
mip_bias,
|
||||
maybe_layers,
|
||||
) in &views
|
||||
{
|
||||
let viewport = extracted_view.viewport.as_vec4();
|
||||
let unjittered_projection = extracted_view.projection;
|
||||
let mut projection = unjittered_projection;
|
||||
|
||||
if let Some(temporal_jitter) = temporal_jitter {
|
||||
|
@ -394,13 +406,13 @@ pub fn prepare_view_uniforms(
|
|||
}
|
||||
|
||||
let inverse_projection = projection.inverse();
|
||||
let view = camera.transform.compute_matrix();
|
||||
let view = extracted_view.transform.compute_matrix();
|
||||
let inverse_view = view.inverse();
|
||||
|
||||
let view_proj = if temporal_jitter.is_some() {
|
||||
projection * inverse_view
|
||||
} else {
|
||||
camera
|
||||
extracted_view
|
||||
.view_projection
|
||||
.unwrap_or_else(|| projection * inverse_view)
|
||||
};
|
||||
|
@ -419,10 +431,13 @@ pub fn prepare_view_uniforms(
|
|||
inverse_view,
|
||||
projection,
|
||||
inverse_projection,
|
||||
world_position: camera.transform.translation(),
|
||||
world_position: extracted_view.transform.translation(),
|
||||
exposure: extracted_camera
|
||||
.map(|c| c.exposure)
|
||||
.unwrap_or_else(|| ExposureSettings::default().exposure()),
|
||||
viewport,
|
||||
frustum,
|
||||
color_grading: camera.color_grading,
|
||||
color_grading: extracted_view.color_grading,
|
||||
mip_bias: mip_bias.unwrap_or(&MipBias(0.0)).0,
|
||||
render_layers: maybe_layers.copied().unwrap_or_default().bits(),
|
||||
}),
|
||||
|
|
|
@ -16,6 +16,7 @@ struct View {
|
|||
projection: mat4x4<f32>,
|
||||
inverse_projection: mat4x4<f32>,
|
||||
world_position: vec3<f32>,
|
||||
exposure: f32,
|
||||
// viewport(x_origin, y_origin, width, height)
|
||||
viewport: vec4<f32>,
|
||||
frustum: array<vec4<f32>, 6>,
|
||||
|
|
|
@ -37,7 +37,7 @@ fn setup(
|
|||
// light
|
||||
commands.spawn(PointLightBundle {
|
||||
point_light: PointLight {
|
||||
intensity: 1500.0,
|
||||
intensity: 250000.0,
|
||||
shadows_enabled: true,
|
||||
..default()
|
||||
},
|
||||
|
|
|
@ -32,7 +32,7 @@ fn setup(
|
|||
// light
|
||||
commands.spawn(PointLightBundle {
|
||||
point_light: PointLight {
|
||||
intensity: 1500.0,
|
||||
intensity: 250_000.0,
|
||||
shadows_enabled: true,
|
||||
..default()
|
||||
},
|
||||
|
|
|
@ -67,7 +67,7 @@ fn setup(
|
|||
|
||||
commands.spawn(PointLightBundle {
|
||||
point_light: PointLight {
|
||||
intensity: 9000.0,
|
||||
intensity: 1500000.0,
|
||||
range: 100.,
|
||||
shadows_enabled: true,
|
||||
..default()
|
||||
|
|
|
@ -61,6 +61,10 @@ fn setup(
|
|||
// light
|
||||
commands.spawn(DirectionalLightBundle {
|
||||
transform: Transform::from_translation(Vec3::ONE).looking_at(Vec3::ZERO, Vec3::Y),
|
||||
directional_light: DirectionalLight {
|
||||
illuminance: 2000.0,
|
||||
..default()
|
||||
},
|
||||
..default()
|
||||
});
|
||||
|
||||
|
|
|
@ -289,6 +289,7 @@ fn setup(
|
|||
// Light
|
||||
commands.spawn(DirectionalLightBundle {
|
||||
directional_light: DirectionalLight {
|
||||
illuminance: 3000.0,
|
||||
shadows_enabled: true,
|
||||
..default()
|
||||
},
|
||||
|
@ -325,6 +326,7 @@ fn setup(
|
|||
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: 150.0,
|
||||
},
|
||||
FogSettings {
|
||||
color: Color::rgba_u8(43, 44, 47, 255),
|
||||
|
|
|
@ -61,6 +61,7 @@ fn setup_terrain_scene(
|
|||
commands.spawn(DirectionalLightBundle {
|
||||
directional_light: DirectionalLight {
|
||||
color: Color::rgb(0.98, 0.95, 0.82),
|
||||
illuminance: 3000.0,
|
||||
shadows_enabled: true,
|
||||
..default()
|
||||
},
|
||||
|
|
|
@ -174,6 +174,10 @@ fn setup(
|
|||
|
||||
// Light
|
||||
commands.spawn(PointLightBundle {
|
||||
point_light: PointLight {
|
||||
intensity: 150_000.0,
|
||||
..default()
|
||||
},
|
||||
transform: Transform::from_xyz(4.0, 8.0, 4.0),
|
||||
..default()
|
||||
});
|
||||
|
|
|
@ -39,15 +39,15 @@ fn setup_scene(
|
|||
));
|
||||
|
||||
let material_emissive1 = materials.add(StandardMaterial {
|
||||
emissive: Color::rgb_linear(13.99, 5.32, 2.0), // 4. Put something bright in a dark environment to see the effect
|
||||
emissive: Color::rgb_linear(2300.0, 900.0, 300.0), // 4. Put something bright in a dark environment to see the effect
|
||||
..default()
|
||||
});
|
||||
let material_emissive2 = materials.add(StandardMaterial {
|
||||
emissive: Color::rgb_linear(2.0, 13.99, 5.32),
|
||||
emissive: Color::rgb_linear(300.0, 2300.0, 900.0),
|
||||
..default()
|
||||
});
|
||||
let material_emissive3 = materials.add(StandardMaterial {
|
||||
emissive: Color::rgb_linear(5.32, 2.0, 13.99),
|
||||
emissive: Color::rgb_linear(900.0, 300.0, 2300.0),
|
||||
..default()
|
||||
});
|
||||
let material_non_emissive = materials.add(StandardMaterial {
|
||||
|
|
|
@ -62,6 +62,7 @@ fn setup(
|
|||
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: 150.0,
|
||||
},
|
||||
DepthPrepass,
|
||||
MotionVectorPrepass,
|
||||
|
@ -71,6 +72,7 @@ fn setup(
|
|||
|
||||
commands.spawn(DirectionalLightBundle {
|
||||
directional_light: DirectionalLight {
|
||||
illuminance: 4000.0,
|
||||
shadows_enabled: true,
|
||||
..default()
|
||||
},
|
||||
|
@ -145,7 +147,7 @@ fn setup(
|
|||
// Light
|
||||
commands.spawn(PointLightBundle {
|
||||
point_light: PointLight {
|
||||
intensity: 1.0,
|
||||
intensity: 150.0,
|
||||
radius: 0.125,
|
||||
shadows_enabled: true,
|
||||
color: sphere_color,
|
||||
|
|
|
@ -128,7 +128,7 @@ fn setup_pyramid_scene(
|
|||
commands.spawn(PointLightBundle {
|
||||
transform: Transform::from_xyz(0.0, 1.0, 0.0),
|
||||
point_light: PointLight {
|
||||
intensity: 1500.,
|
||||
intensity: 300_000.,
|
||||
range: 100.,
|
||||
shadows_enabled: true,
|
||||
..default()
|
||||
|
|
|
@ -58,7 +58,7 @@ fn setup(
|
|||
// Light up the scene.
|
||||
commands.spawn(PointLightBundle {
|
||||
point_light: PointLight {
|
||||
intensity: 1000.0,
|
||||
intensity: 100_000.0,
|
||||
range: 100.0,
|
||||
..default()
|
||||
},
|
||||
|
|
|
@ -3,21 +3,34 @@
|
|||
|
||||
use std::f32::consts::PI;
|
||||
|
||||
use bevy::{pbr::CascadeShadowConfigBuilder, prelude::*};
|
||||
use bevy::{
|
||||
pbr::CascadeShadowConfigBuilder,
|
||||
prelude::*,
|
||||
render::camera::{ExposureSettings, PhysicalCameraParameters},
|
||||
};
|
||||
|
||||
fn main() {
|
||||
App::new()
|
||||
.add_plugins(DefaultPlugins)
|
||||
.insert_resource(Parameters(PhysicalCameraParameters {
|
||||
aperture_f_stops: 1.0,
|
||||
shutter_speed_s: 1.0 / 15.0,
|
||||
sensitivity_iso: 400.0,
|
||||
}))
|
||||
.add_systems(Startup, setup)
|
||||
.add_systems(Update, (movement, animate_light_direction))
|
||||
.add_systems(Update, (update_exposure, movement, animate_light_direction))
|
||||
.run();
|
||||
}
|
||||
|
||||
#[derive(Resource, Default, Deref, DerefMut)]
|
||||
struct Parameters(PhysicalCameraParameters);
|
||||
|
||||
#[derive(Component)]
|
||||
struct Movable;
|
||||
|
||||
/// set up a simple 3D scene
|
||||
fn setup(
|
||||
parameters: Res<Parameters>,
|
||||
mut commands: Commands,
|
||||
mut meshes: ResMut<Assets<Mesh>>,
|
||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||
|
@ -122,7 +135,7 @@ fn setup(
|
|||
// transform: Transform::from_xyz(5.0, 8.0, 2.0),
|
||||
transform: Transform::from_xyz(1.0, 2.0, 0.0),
|
||||
point_light: PointLight {
|
||||
intensity: 1600.0, // lumens - roughly a 100W non-halogen incandescent bulb
|
||||
intensity: 4000.0, // lumens - roughly a 300W non-halogen incandescent bulb
|
||||
color: Color::RED,
|
||||
shadows_enabled: true,
|
||||
..default()
|
||||
|
@ -150,7 +163,7 @@ fn setup(
|
|||
transform: Transform::from_xyz(-1.0, 2.0, 0.0)
|
||||
.looking_at(Vec3::new(-1.0, 0.0, 0.0), Vec3::Z),
|
||||
spot_light: SpotLight {
|
||||
intensity: 1600.0, // lumens - roughly a 100W non-halogen incandescent bulb
|
||||
intensity: 4000.0, // lumens - roughly a 300W non-halogen incandescent bulb
|
||||
color: Color::GREEN,
|
||||
shadows_enabled: true,
|
||||
inner_angle: 0.6,
|
||||
|
@ -182,7 +195,7 @@ fn setup(
|
|||
// transform: Transform::from_xyz(5.0, 8.0, 2.0),
|
||||
transform: Transform::from_xyz(0.0, 4.0, 0.0),
|
||||
point_light: PointLight {
|
||||
intensity: 1600.0, // lumens - roughly a 100W non-halogen incandescent bulb
|
||||
intensity: 4000.0, // lumens - roughly a 300W non-halogen incandescent bulb
|
||||
color: Color::BLUE,
|
||||
shadows_enabled: true,
|
||||
..default()
|
||||
|
@ -207,6 +220,7 @@ fn setup(
|
|||
// directional 'sun' light
|
||||
commands.spawn(DirectionalLightBundle {
|
||||
directional_light: DirectionalLight {
|
||||
illuminance: 100.0,
|
||||
shadows_enabled: true,
|
||||
..default()
|
||||
},
|
||||
|
@ -227,21 +241,37 @@ fn setup(
|
|||
..default()
|
||||
});
|
||||
|
||||
// camera
|
||||
commands.spawn(Camera3dBundle {
|
||||
transform: Transform::from_xyz(-2.0, 2.5, 5.0).looking_at(Vec3::ZERO, Vec3::Y),
|
||||
..default()
|
||||
});
|
||||
|
||||
// example instructions
|
||||
let style = TextStyle {
|
||||
font_size: 20.0,
|
||||
..default()
|
||||
};
|
||||
commands.spawn(
|
||||
TextBundle::from_section(
|
||||
"Use arrow keys to move objects",
|
||||
TextStyle {
|
||||
font_size: 20.0,
|
||||
..default()
|
||||
},
|
||||
)
|
||||
TextBundle::from_sections(vec![
|
||||
TextSection::new(
|
||||
format!("Aperture: f/{:.0}\n", parameters.aperture_f_stops),
|
||||
style.clone(),
|
||||
),
|
||||
TextSection::new(
|
||||
format!(
|
||||
"Shutter speed: 1/{:.0}s\n",
|
||||
1.0 / parameters.shutter_speed_s
|
||||
),
|
||||
style.clone(),
|
||||
),
|
||||
TextSection::new(
|
||||
format!("Sensitivity: ISO {:.0}\n", parameters.sensitivity_iso),
|
||||
style.clone(),
|
||||
),
|
||||
TextSection::new("\n\n", style.clone()),
|
||||
TextSection::new("Controls\n", style.clone()),
|
||||
TextSection::new("---------------\n", style.clone()),
|
||||
TextSection::new("Arrow keys - Move objects\n", style.clone()),
|
||||
TextSection::new("1/2 - Decrease/Increase aperture\n", style.clone()),
|
||||
TextSection::new("3/4 - Decrease/Increase shutter speed\n", style.clone()),
|
||||
TextSection::new("5/6 - Decrease/Increase sensitivity\n", style.clone()),
|
||||
TextSection::new("R - Reset exposure", style),
|
||||
])
|
||||
.with_style(Style {
|
||||
position_type: PositionType::Absolute,
|
||||
top: Val::Px(12.0),
|
||||
|
@ -249,6 +279,52 @@ fn setup(
|
|||
..default()
|
||||
}),
|
||||
);
|
||||
|
||||
// camera
|
||||
commands.spawn((
|
||||
Camera3dBundle {
|
||||
transform: Transform::from_xyz(-2.0, 2.5, 5.0).looking_at(Vec3::ZERO, Vec3::Y),
|
||||
..default()
|
||||
},
|
||||
ExposureSettings::from_physical_camera(**parameters),
|
||||
));
|
||||
}
|
||||
|
||||
fn update_exposure(
|
||||
key_input: Res<ButtonInput<KeyCode>>,
|
||||
mut parameters: ResMut<Parameters>,
|
||||
mut query: Query<&mut ExposureSettings>,
|
||||
mut text: Query<&mut Text>,
|
||||
) {
|
||||
// TODO: Clamp values to a reasonable range
|
||||
let mut text = text.single_mut();
|
||||
if key_input.just_pressed(KeyCode::Digit2) {
|
||||
parameters.aperture_f_stops *= 2.0;
|
||||
} else if key_input.just_pressed(KeyCode::Digit1) {
|
||||
parameters.aperture_f_stops *= 0.5;
|
||||
}
|
||||
if key_input.just_pressed(KeyCode::Digit4) {
|
||||
parameters.shutter_speed_s *= 2.0;
|
||||
} else if key_input.just_pressed(KeyCode::Digit3) {
|
||||
parameters.shutter_speed_s *= 0.5;
|
||||
}
|
||||
if key_input.just_pressed(KeyCode::Digit6) {
|
||||
parameters.sensitivity_iso += 100.0;
|
||||
} else if key_input.just_pressed(KeyCode::Digit5) {
|
||||
parameters.sensitivity_iso -= 100.0;
|
||||
}
|
||||
if key_input.just_pressed(KeyCode::KeyR) {
|
||||
*parameters = Parameters::default();
|
||||
}
|
||||
|
||||
text.sections[0].value = format!("Aperture: f/{:.0}\n", parameters.aperture_f_stops);
|
||||
text.sections[1].value = format!(
|
||||
"Shutter speed: 1/{:.0}s\n",
|
||||
1.0 / parameters.shutter_speed_s
|
||||
);
|
||||
text.sections[2].value = format!("Sensitivity: ISO {:.0}\n", parameters.sensitivity_iso);
|
||||
|
||||
*query.single_mut() = ExposureSettings::from_physical_camera(**parameters);
|
||||
}
|
||||
|
||||
fn animate_light_direction(
|
||||
|
|
|
@ -8,7 +8,7 @@ fn main() {
|
|||
.add_plugins(DefaultPlugins)
|
||||
.insert_resource(AmbientLight {
|
||||
color: Color::WHITE,
|
||||
brightness: 0.2,
|
||||
brightness: 0.0,
|
||||
})
|
||||
.add_systems(Startup, setup)
|
||||
.add_systems(Update, add_lightmaps_to_meshes)
|
||||
|
@ -30,10 +30,21 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
fn add_lightmaps_to_meshes(
|
||||
mut commands: Commands,
|
||||
asset_server: Res<AssetServer>,
|
||||
meshes: Query<(Entity, &Name), (With<Handle<Mesh>>, Without<Lightmap>)>,
|
||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||
meshes: Query<
|
||||
(Entity, &Name, &Handle<StandardMaterial>),
|
||||
(With<Handle<Mesh>>, Without<Lightmap>),
|
||||
>,
|
||||
) {
|
||||
for (entity, name) in meshes.iter() {
|
||||
let exposure = 250.0;
|
||||
for (entity, name, material) in meshes.iter() {
|
||||
if &**name == "Light" {
|
||||
materials.get_mut(material).unwrap().emissive = Color::WHITE * exposure;
|
||||
continue;
|
||||
}
|
||||
|
||||
if &**name == "large_box" {
|
||||
materials.get_mut(material).unwrap().lightmap_exposure = exposure;
|
||||
commands.entity(entity).insert(Lightmap {
|
||||
image: asset_server.load("lightmaps/CornellBox-Large.zstd.ktx2"),
|
||||
..default()
|
||||
|
@ -42,6 +53,7 @@ fn add_lightmaps_to_meshes(
|
|||
}
|
||||
|
||||
if &**name == "small_box" {
|
||||
materials.get_mut(material).unwrap().lightmap_exposure = exposure;
|
||||
commands.entity(entity).insert(Lightmap {
|
||||
image: asset_server.load("lightmaps/CornellBox-Small.zstd.ktx2"),
|
||||
..default()
|
||||
|
@ -50,6 +62,7 @@ fn add_lightmaps_to_meshes(
|
|||
}
|
||||
|
||||
if name.starts_with("cornell_box") {
|
||||
materials.get_mut(material).unwrap().lightmap_exposure = exposure;
|
||||
commands.entity(entity).insert(Lightmap {
|
||||
image: asset_server.load("lightmaps/CornellBox-Box.zstd.ktx2"),
|
||||
..default()
|
||||
|
|
|
@ -25,11 +25,13 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
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: 150.0,
|
||||
},
|
||||
));
|
||||
|
||||
commands.spawn(DirectionalLightBundle {
|
||||
directional_light: DirectionalLight {
|
||||
illuminance: 2000.0,
|
||||
shadows_enabled: true,
|
||||
..default()
|
||||
},
|
||||
|
|
|
@ -61,6 +61,10 @@ fn setup(
|
|||
// light
|
||||
commands.spawn(PointLightBundle {
|
||||
transform: Transform::from_xyz(3.0, 8.0, 5.0),
|
||||
point_light: PointLight {
|
||||
intensity: 150_000.0,
|
||||
..default()
|
||||
},
|
||||
..default()
|
||||
});
|
||||
}
|
||||
|
|
|
@ -224,7 +224,7 @@ fn setup(
|
|||
.spawn(PointLightBundle {
|
||||
transform: Transform::from_xyz(1.8, 0.7, -1.1),
|
||||
point_light: PointLight {
|
||||
intensity: 226.0,
|
||||
intensity: 50_000.0,
|
||||
shadows_enabled: true,
|
||||
..default()
|
||||
},
|
||||
|
|
|
@ -57,6 +57,10 @@ fn setup(
|
|||
// light
|
||||
commands.spawn(PointLightBundle {
|
||||
transform: Transform::from_xyz(4.0, 5.0, -4.0),
|
||||
point_light: PointLight {
|
||||
intensity: 150_000.0,
|
||||
..default()
|
||||
},
|
||||
..default()
|
||||
});
|
||||
// camera
|
||||
|
|
|
@ -61,7 +61,7 @@ fn setup(
|
|||
commands.spawn(PointLightBundle {
|
||||
transform: Transform::from_xyz(50.0, 50.0, 50.0),
|
||||
point_light: PointLight {
|
||||
intensity: 600000.,
|
||||
intensity: 100_000_000.,
|
||||
range: 100.,
|
||||
..default()
|
||||
},
|
||||
|
@ -138,6 +138,7 @@ fn setup(
|
|||
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: 150.0,
|
||||
},
|
||||
));
|
||||
}
|
||||
|
|
|
@ -92,6 +92,10 @@ fn setup(
|
|||
commands.spawn((
|
||||
PointLightBundle {
|
||||
transform: Transform::from_translation(Vec3::new(0.0, 0.0, 10.0)),
|
||||
point_light: PointLight {
|
||||
intensity: 150_000.0,
|
||||
..default()
|
||||
},
|
||||
..default()
|
||||
},
|
||||
RenderLayers::all(),
|
||||
|
|
|
@ -74,7 +74,7 @@ fn setup(
|
|||
});
|
||||
builder.spawn(DirectionalLightBundle {
|
||||
directional_light: DirectionalLight {
|
||||
illuminance: 100000.0,
|
||||
illuminance: 1500.0,
|
||||
shadow_depth_bias: 0.0,
|
||||
shadow_normal_bias: 0.0,
|
||||
shadows_enabled: true,
|
||||
|
|
|
@ -98,7 +98,7 @@ fn setup(
|
|||
|
||||
commands.spawn(DirectionalLightBundle {
|
||||
directional_light: DirectionalLight {
|
||||
illuminance: 100000.0,
|
||||
illuminance: 1500.0,
|
||||
shadows_enabled: true,
|
||||
..default()
|
||||
},
|
||||
|
@ -134,7 +134,7 @@ fn toggle_light(
|
|||
for mut light in &mut point_lights {
|
||||
light.intensity = if light.intensity == 0.0 {
|
||||
println!("Using PointLight");
|
||||
100000000.0
|
||||
500_000.0
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
|
@ -142,7 +142,7 @@ fn toggle_light(
|
|||
for mut light in &mut directional_lights {
|
||||
light.illuminance = if light.illuminance == 0.0 {
|
||||
println!("Using DirectionalLight");
|
||||
100000.0
|
||||
1500.0
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
|
|
|
@ -78,7 +78,10 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
..default()
|
||||
},
|
||||
CameraController::default(),
|
||||
Skybox(skybox_handle.clone()),
|
||||
Skybox {
|
||||
image: skybox_handle.clone(),
|
||||
brightness: 150.0,
|
||||
},
|
||||
));
|
||||
|
||||
// ambient light
|
||||
|
@ -157,7 +160,7 @@ fn asset_loaded(
|
|||
}
|
||||
|
||||
for mut skybox in &mut skyboxes {
|
||||
skybox.0 = cubemap.image_handle.clone();
|
||||
skybox.image = cubemap.image_handle.clone();
|
||||
}
|
||||
|
||||
cubemap.is_loaded = true;
|
||||
|
|
|
@ -16,7 +16,7 @@ fn setup(
|
|||
) {
|
||||
// camera
|
||||
commands.spawn(Camera3dBundle {
|
||||
transform: Transform::from_xyz(1.0, 2.5, 5.0).looking_at(Vec3::ZERO, Vec3::Y),
|
||||
transform: Transform::from_xyz(0.2, 1.5, 2.5).looking_at(Vec3::ZERO, Vec3::Y),
|
||||
..default()
|
||||
});
|
||||
|
||||
|
@ -32,8 +32,8 @@ fn setup(
|
|||
});
|
||||
|
||||
const COUNT: usize = 6;
|
||||
let position_range = -4.0..4.0;
|
||||
let radius_range = 0.0..0.8;
|
||||
let position_range = -2.0..2.0;
|
||||
let radius_range = 0.0..0.4;
|
||||
let pos_len = position_range.end - position_range.start;
|
||||
let radius_len = radius_range.end - radius_range.start;
|
||||
let mesh = meshes.add(shape::UVSphere {
|
||||
|
@ -55,14 +55,14 @@ fn setup(
|
|||
unlit: true,
|
||||
..default()
|
||||
}),
|
||||
transform: Transform::from_xyz(position_range.start + percent * pos_len, 0.6, 0.0)
|
||||
transform: Transform::from_xyz(position_range.start + percent * pos_len, 0.3, 0.0)
|
||||
.with_scale(Vec3::splat(radius)),
|
||||
..default()
|
||||
})
|
||||
.with_children(|children| {
|
||||
children.spawn(PointLightBundle {
|
||||
point_light: PointLight {
|
||||
intensity: 1500.0,
|
||||
intensity: 100_000.0,
|
||||
radius,
|
||||
color: Color::rgb(0.2, 0.2, 1.0),
|
||||
..default()
|
||||
|
|
|
@ -37,6 +37,7 @@ fn setup(
|
|||
commands.spawn(DirectionalLightBundle {
|
||||
transform: Transform::from_rotation(Quat::from_euler(EulerRot::ZYX, 0.0, 1.0, -PI / 4.)),
|
||||
directional_light: DirectionalLight {
|
||||
illuminance: 1500.0,
|
||||
shadows_enabled: true,
|
||||
..default()
|
||||
},
|
||||
|
|
|
@ -10,7 +10,7 @@ use rand::{rngs::StdRng, Rng, SeedableRng};
|
|||
fn main() {
|
||||
App::new()
|
||||
.insert_resource(AmbientLight {
|
||||
brightness: 0.02,
|
||||
brightness: 4.0,
|
||||
..default()
|
||||
})
|
||||
.add_plugins((
|
||||
|
@ -69,12 +69,12 @@ fn setup(
|
|||
});
|
||||
let red_emissive = materials.add(StandardMaterial {
|
||||
base_color: Color::RED,
|
||||
emissive: Color::rgba_linear(1.0, 0.0, 0.0, 0.0),
|
||||
emissive: Color::rgba_linear(100.0, 0.0, 0.0, 0.0),
|
||||
..default()
|
||||
});
|
||||
let maroon_emissive = materials.add(StandardMaterial {
|
||||
base_color: Color::MAROON,
|
||||
emissive: Color::rgba_linear(0.369, 0.0, 0.0, 0.0),
|
||||
emissive: Color::rgba_linear(50.0, 0.0, 0.0, 0.0),
|
||||
..default()
|
||||
});
|
||||
for x in 0..4 {
|
||||
|
@ -87,7 +87,7 @@ fn setup(
|
|||
transform: Transform::from_xyz(1.0 + x, 2.0, z)
|
||||
.looking_at(Vec3::new(1.0 + x, 0.0, z), Vec3::X),
|
||||
spot_light: SpotLight {
|
||||
intensity: 200.0, // lumens
|
||||
intensity: 100_000.0, // lumens
|
||||
color: Color::WHITE,
|
||||
shadows_enabled: true,
|
||||
inner_angle: PI / 4.0 * 0.85,
|
||||
|
|
|
@ -14,7 +14,7 @@ use std::f32::consts::PI;
|
|||
fn main() {
|
||||
App::new()
|
||||
.insert_resource(AmbientLight {
|
||||
brightness: 5.0,
|
||||
brightness: 750.0,
|
||||
..default()
|
||||
})
|
||||
.add_plugins((DefaultPlugins, TemporalAntiAliasPlugin))
|
||||
|
@ -85,6 +85,7 @@ fn setup(
|
|||
|
||||
commands.spawn(DirectionalLightBundle {
|
||||
directional_light: DirectionalLight {
|
||||
illuminance: 3000.0,
|
||||
shadows_enabled: true,
|
||||
..default()
|
||||
},
|
||||
|
|
|
@ -76,6 +76,7 @@ fn setup(
|
|||
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: 150.0,
|
||||
},
|
||||
));
|
||||
|
||||
|
@ -194,7 +195,7 @@ fn setup_basic_scene(
|
|||
DirectionalLightBundle {
|
||||
directional_light: DirectionalLight {
|
||||
shadows_enabled: true,
|
||||
illuminance: 50000.0,
|
||||
illuminance: 3000.0,
|
||||
..default()
|
||||
},
|
||||
transform: Transform::from_rotation(Quat::from_euler(
|
||||
|
|
|
@ -153,7 +153,7 @@ fn setup(
|
|||
PbrBundle {
|
||||
mesh: icosphere_mesh.clone(),
|
||||
material: materials.add(StandardMaterial {
|
||||
emissive: Color::ANTIQUE_WHITE * 20.0 + Color::ORANGE_RED * 4.0,
|
||||
emissive: Color::ANTIQUE_WHITE * 80.0 + Color::ORANGE_RED * 16.0,
|
||||
diffuse_transmission: 1.0,
|
||||
..default()
|
||||
}),
|
||||
|
@ -325,7 +325,7 @@ fn setup(
|
|||
transform: Transform::from_xyz(-1.0, 1.7, 0.0),
|
||||
point_light: PointLight {
|
||||
color: Color::ANTIQUE_WHITE * 0.8 + Color::ORANGE_RED * 0.2,
|
||||
intensity: 1600.0,
|
||||
intensity: 60_000.0,
|
||||
radius: 0.2,
|
||||
range: 5.0,
|
||||
shadows_enabled: true,
|
||||
|
@ -345,7 +345,6 @@ fn setup(
|
|||
},
|
||||
transform: Transform::from_xyz(1.0, 1.8, 7.0).looking_at(Vec3::ZERO, Vec3::Y),
|
||||
color_grading: ColorGrading {
|
||||
exposure: -2.0,
|
||||
post_saturation: 1.2,
|
||||
..default()
|
||||
},
|
||||
|
@ -355,6 +354,7 @@ fn setup(
|
|||
#[cfg(not(all(feature = "webgl2", target_arch = "wasm32")))]
|
||||
TemporalAntiAliasBundle::default(),
|
||||
EnvironmentMapLight {
|
||||
intensity: 25.0,
|
||||
diffuse_map: asset_server.load("environment_maps/pisa_diffuse_rgb9e5_zstd.ktx2"),
|
||||
specular_map: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
|
||||
},
|
||||
|
@ -648,7 +648,7 @@ fn flicker_system(
|
|||
let c = (s * 7.0).cos() * 0.0125 + (s * 2.0).cos() * 0.025;
|
||||
let (mut light, mut light_transform) = light.single_mut();
|
||||
let mut flame_transform = flame.single_mut();
|
||||
light.intensity = 1600.0 + 3000.0 * (a + b + c);
|
||||
light.intensity = 60_000.0 + 3000.0 * (a + b + c);
|
||||
flame_transform.translation = Vec3::new(-1.0, 1.23, 0.0);
|
||||
flame_transform.look_at(Vec3::new(-1.0 - c, 1.7 - b, 0.0 - a), Vec3::X);
|
||||
flame_transform.rotate(Quat::from_euler(EulerRot::XYZ, 0.0, 0.0, PI / 2.0));
|
||||
|
|
|
@ -91,7 +91,7 @@ fn setup(
|
|||
// light
|
||||
commands.spawn(PointLightBundle {
|
||||
point_light: PointLight {
|
||||
intensity: 1500.0,
|
||||
intensity: 1_000_000.0,
|
||||
shadows_enabled: true,
|
||||
..default()
|
||||
},
|
||||
|
|
|
@ -31,7 +31,7 @@ fn setup(
|
|||
// light
|
||||
commands.spawn(PointLightBundle {
|
||||
point_light: PointLight {
|
||||
intensity: 1500.0,
|
||||
intensity: 500_000.0,
|
||||
shadows_enabled: true,
|
||||
..default()
|
||||
},
|
||||
|
|
|
@ -19,6 +19,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
commands.spawn(DirectionalLightBundle {
|
||||
transform: Transform::from_xyz(4.0, 25.0, 8.0).looking_at(Vec3::ZERO, Vec3::Y),
|
||||
directional_light: DirectionalLight {
|
||||
illuminance: 2000.0,
|
||||
shadows_enabled: true,
|
||||
..default()
|
||||
},
|
||||
|
@ -33,6 +34,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
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: 150.0,
|
||||
},
|
||||
));
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ fn setup(
|
|||
// light
|
||||
commands.spawn(PointLightBundle {
|
||||
point_light: PointLight {
|
||||
intensity: 1500.0,
|
||||
intensity: 500_000.0,
|
||||
shadows_enabled: true,
|
||||
..default()
|
||||
},
|
||||
|
|
|
@ -95,6 +95,10 @@ fn setup(
|
|||
// light
|
||||
commands.spawn(PointLightBundle {
|
||||
transform: Transform::from_xyz(4.0, 8.0, 4.0),
|
||||
point_light: PointLight {
|
||||
intensity: 150_000.0,
|
||||
..default()
|
||||
},
|
||||
..default()
|
||||
});
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ fn main() {
|
|||
.add_plugins(DefaultPlugins)
|
||||
.insert_resource(AmbientLight {
|
||||
color: Color::WHITE,
|
||||
brightness: 1.0,
|
||||
brightness: 150.0,
|
||||
})
|
||||
.add_systems(Startup, setup)
|
||||
.add_systems(
|
||||
|
@ -54,6 +54,7 @@ fn setup(
|
|||
commands.spawn(DirectionalLightBundle {
|
||||
transform: Transform::from_rotation(Quat::from_euler(EulerRot::ZYX, 0.0, 1.0, -PI / 4.)),
|
||||
directional_light: DirectionalLight {
|
||||
illuminance: 2000.0,
|
||||
shadows_enabled: true,
|
||||
..default()
|
||||
},
|
||||
|
|
|
@ -9,7 +9,7 @@ fn main() {
|
|||
.add_plugins(DefaultPlugins)
|
||||
.insert_resource(AmbientLight {
|
||||
color: Color::WHITE,
|
||||
brightness: 1.0,
|
||||
brightness: 150.0,
|
||||
})
|
||||
.add_systems(Startup, setup)
|
||||
.run();
|
||||
|
|
|
@ -49,7 +49,7 @@ fn setup(
|
|||
// Some light to see something
|
||||
commands.spawn(PointLightBundle {
|
||||
point_light: PointLight {
|
||||
intensity: 9000.,
|
||||
intensity: 1_500_000.,
|
||||
range: 100.,
|
||||
shadows_enabled: true,
|
||||
..default()
|
||||
|
|
|
@ -20,7 +20,7 @@ fn main() {
|
|||
App::new()
|
||||
.add_plugins(DefaultPlugins)
|
||||
.insert_resource(AmbientLight {
|
||||
brightness: 1.0,
|
||||
brightness: 150.0,
|
||||
..default()
|
||||
})
|
||||
.add_systems(Startup, setup)
|
||||
|
|
|
@ -9,7 +9,7 @@ fn main() {
|
|||
App::new()
|
||||
.add_plugins(DefaultPlugins)
|
||||
.insert_resource(AmbientLight {
|
||||
brightness: 1.0,
|
||||
brightness: 150.0,
|
||||
..default()
|
||||
})
|
||||
.add_systems(Startup, setup)
|
||||
|
|
|
@ -20,7 +20,7 @@ fn main() {
|
|||
..default()
|
||||
}))
|
||||
.insert_resource(AmbientLight {
|
||||
brightness: 1.0,
|
||||
brightness: 150.0,
|
||||
..default()
|
||||
})
|
||||
.add_systems(Startup, setup)
|
||||
|
@ -46,7 +46,7 @@ fn setup(asset_server: Res<AssetServer>, mut commands: Commands) {
|
|||
commands.spawn(DirectionalLightBundle {
|
||||
directional_light: DirectionalLight {
|
||||
color: Color::WHITE,
|
||||
illuminance: 19350.0,
|
||||
illuminance: 1000.0,
|
||||
..default()
|
||||
},
|
||||
transform: Transform::from_rotation(Quat::from_rotation_z(PI / 2.0)),
|
||||
|
|
|
@ -61,7 +61,7 @@ fn setup(
|
|||
// light
|
||||
commands.spawn(PointLightBundle {
|
||||
point_light: PointLight {
|
||||
intensity: 1500.0,
|
||||
intensity: 1_000_000.0,
|
||||
shadows_enabled: true,
|
||||
..default()
|
||||
},
|
||||
|
|
|
@ -112,7 +112,7 @@ fn generate_bodies(
|
|||
),
|
||||
material: materials.add(StandardMaterial {
|
||||
base_color: Color::ORANGE_RED,
|
||||
emissive: Color::ORANGE_RED * 2.,
|
||||
emissive: (Color::ORANGE_RED * 18.),
|
||||
..default()
|
||||
}),
|
||||
..default()
|
||||
|
@ -126,7 +126,7 @@ fn generate_bodies(
|
|||
p.spawn(PointLightBundle {
|
||||
point_light: PointLight {
|
||||
color: Color::WHITE,
|
||||
intensity: 400.0,
|
||||
intensity: 100_000.0,
|
||||
range: 100.0,
|
||||
radius: star_radius,
|
||||
..default()
|
||||
|
|
|
@ -115,7 +115,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>, mut game: ResMu
|
|||
commands.spawn(PointLightBundle {
|
||||
transform: Transform::from_xyz(4.0, 10.0, 4.0),
|
||||
point_light: PointLight {
|
||||
intensity: 3000.0,
|
||||
intensity: 500_000.0,
|
||||
shadows_enabled: true,
|
||||
range: 30.0,
|
||||
..default()
|
||||
|
@ -344,7 +344,7 @@ fn spawn_bonus(
|
|||
children.spawn(PointLightBundle {
|
||||
point_light: PointLight {
|
||||
color: Color::rgb(1.0, 1.0, 0.0),
|
||||
intensity: 1000.0,
|
||||
intensity: 100_000.0,
|
||||
range: 10.0,
|
||||
..default()
|
||||
},
|
||||
|
|
|
@ -90,7 +90,7 @@ fn setup_scene(
|
|||
commands.spawn(PointLightBundle {
|
||||
transform: Transform::from_xyz(4.0, 8.0, 4.0),
|
||||
point_light: PointLight {
|
||||
intensity: 5000.0,
|
||||
intensity: 1_000_000.0,
|
||||
// Shadows makes some Android devices segfault, this is under investigation
|
||||
// https://github.com/bevyengine/bevy/issues/8214
|
||||
#[cfg(not(target_os = "android"))]
|
||||
|
|
|
@ -34,7 +34,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
// light
|
||||
commands.spawn(PointLightBundle {
|
||||
point_light: PointLight {
|
||||
intensity: 3000.0,
|
||||
intensity: 150_000.0,
|
||||
..Default::default()
|
||||
},
|
||||
transform: Transform::from_xyz(-3.0, 2.0, -1.0),
|
||||
|
@ -42,7 +42,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
});
|
||||
commands.spawn(PointLightBundle {
|
||||
point_light: PointLight {
|
||||
intensity: 3000.0,
|
||||
intensity: 150_000.0,
|
||||
..Default::default()
|
||||
},
|
||||
transform: Transform::from_xyz(3.0, 2.0, 1.0),
|
||||
|
|
|
@ -50,7 +50,16 @@ fn setup(
|
|||
});
|
||||
|
||||
// light
|
||||
commands.spawn((PointLightBundle::default(), Rotate));
|
||||
commands.spawn((
|
||||
PointLightBundle {
|
||||
point_light: PointLight {
|
||||
intensity: 150_000.0,
|
||||
..default()
|
||||
},
|
||||
..default()
|
||||
},
|
||||
Rotate,
|
||||
));
|
||||
|
||||
// camera
|
||||
commands.spawn(Camera3dBundle {
|
||||
|
|
|
@ -331,6 +331,10 @@ fn setup(
|
|||
));
|
||||
// light
|
||||
commands.spawn(PointLightBundle {
|
||||
point_light: PointLight {
|
||||
intensity: 150_000.0,
|
||||
..default()
|
||||
},
|
||||
transform: Transform::from_translation(Vec3::new(0.0, 0.0, 10.0)),
|
||||
..default()
|
||||
});
|
||||
|
|
|
@ -30,6 +30,10 @@ fn setup(
|
|||
..default()
|
||||
});
|
||||
commands.spawn(PointLightBundle {
|
||||
point_light: PointLight {
|
||||
intensity: 150_000.0,
|
||||
..default()
|
||||
},
|
||||
transform: Transform::from_xyz(4.0, 8.0, 4.0),
|
||||
..default()
|
||||
});
|
||||
|
|
|
@ -125,7 +125,7 @@ fn setup(
|
|||
// light
|
||||
commands.spawn(PointLightBundle {
|
||||
point_light: PointLight {
|
||||
intensity: 1500.0,
|
||||
intensity: 300_000.0,
|
||||
shadows_enabled: true,
|
||||
..default()
|
||||
},
|
||||
|
|
|
@ -15,7 +15,7 @@ use bevy::{
|
|||
#[derive(FromArgs, Resource)]
|
||||
/// `many_foxes` stress test
|
||||
struct Args {
|
||||
/// wether all foxes run in sync.
|
||||
/// whether all foxes run in sync.
|
||||
#[argh(switch)]
|
||||
sync: bool,
|
||||
|
||||
|
@ -58,7 +58,7 @@ fn main() {
|
|||
})
|
||||
.insert_resource(AmbientLight {
|
||||
color: Color::WHITE,
|
||||
brightness: 1.0,
|
||||
brightness: 100.0,
|
||||
})
|
||||
.add_systems(Startup, setup)
|
||||
.add_systems(
|
||||
|
@ -194,6 +194,7 @@ fn setup(
|
|||
commands.spawn(DirectionalLightBundle {
|
||||
transform: Transform::from_rotation(Quat::from_euler(EulerRot::ZYX, 0.0, 1.0, -PI / 4.)),
|
||||
directional_light: DirectionalLight {
|
||||
illuminance: 3000.0,
|
||||
shadows_enabled: true,
|
||||
..default()
|
||||
},
|
||||
|
|
|
@ -28,11 +28,7 @@ use scene_viewer_plugin::{SceneHandle, SceneViewerPlugin};
|
|||
|
||||
fn main() {
|
||||
let mut app = App::new();
|
||||
app.insert_resource(AmbientLight {
|
||||
color: Color::WHITE,
|
||||
brightness: 1.0 / 5.0f32,
|
||||
})
|
||||
.add_plugins((
|
||||
app.add_plugins((
|
||||
DefaultPlugins
|
||||
.set(WindowPlugin {
|
||||
primary_window: Some(Window {
|
||||
|
@ -144,6 +140,7 @@ fn setup_scene_after_load(
|
|||
.load("assets/environment_maps/pisa_diffuse_rgb9e5_zstd.ktx2"),
|
||||
specular_map: asset_server
|
||||
.load("assets/environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
|
||||
intensity: 150.0,
|
||||
},
|
||||
camera_controller,
|
||||
));
|
||||
|
@ -153,6 +150,7 @@ fn setup_scene_after_load(
|
|||
info!("Spawning a directional light");
|
||||
commands.spawn(DirectionalLightBundle {
|
||||
directional_light: DirectionalLight {
|
||||
illuminance: 3000.0,
|
||||
shadows_enabled: false,
|
||||
..default()
|
||||
},
|
||||
|
|
|
@ -42,6 +42,10 @@ fn setup(
|
|||
|
||||
// Add a light source so we can see clearly.
|
||||
commands.spawn(PointLightBundle {
|
||||
point_light: PointLight {
|
||||
intensity: 150_000.0,
|
||||
..default()
|
||||
},
|
||||
transform: Transform::from_translation(Vec3::ONE * 3.0),
|
||||
..default()
|
||||
});
|
||||
|
|
|
@ -58,6 +58,10 @@ fn setup(
|
|||
|
||||
// Add a light source for better 3d visibility.
|
||||
commands.spawn(PointLightBundle {
|
||||
point_light: PointLight {
|
||||
intensity: 150_000.0,
|
||||
..default()
|
||||
},
|
||||
transform: Transform::from_translation(Vec3::ONE * 3.0),
|
||||
..default()
|
||||
});
|
||||
|
|
|
@ -93,6 +93,10 @@ fn setup(
|
|||
|
||||
// Add a light source for better 3d visibility.
|
||||
commands.spawn(PointLightBundle {
|
||||
point_light: PointLight {
|
||||
intensity: 150_000.0,
|
||||
..default()
|
||||
},
|
||||
transform: Transform::from_translation(Vec3::ONE * 3.0),
|
||||
..default()
|
||||
});
|
||||
|
|
|
@ -56,6 +56,10 @@ fn setup(
|
|||
|
||||
// Add a light source for better 3d visibility.
|
||||
commands.spawn(PointLightBundle {
|
||||
point_light: PointLight {
|
||||
intensity: 150_000.0,
|
||||
..default()
|
||||
},
|
||||
transform: Transform::from_translation(Vec3::ONE * 3.0),
|
||||
..default()
|
||||
});
|
||||
|
|
|
@ -158,7 +158,7 @@ pub(crate) mod test_setup {
|
|||
));
|
||||
commands.spawn(PointLightBundle {
|
||||
point_light: PointLight {
|
||||
intensity: 1500.0,
|
||||
intensity: 1_000_000.0,
|
||||
shadows_enabled: true,
|
||||
..default()
|
||||
},
|
||||
|
|
|
@ -19,6 +19,10 @@ fn setup_scene(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
});
|
||||
// light
|
||||
commands.spawn(PointLightBundle {
|
||||
point_light: PointLight {
|
||||
intensity: 150_000.0,
|
||||
..default()
|
||||
},
|
||||
transform: Transform::from_xyz(4.0, 5.0, 4.0),
|
||||
..default()
|
||||
});
|
||||
|
|
|
@ -49,7 +49,7 @@ fn setup(
|
|||
// light
|
||||
commands.spawn(PointLightBundle {
|
||||
point_light: PointLight {
|
||||
intensity: 1500.0,
|
||||
intensity: 500_000.0,
|
||||
shadows_enabled: true,
|
||||
..default()
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue