Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Merged by Bors] - Use the infinite reverse right-handed perspective projection #2543

4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,10 @@ path = "examples/3d/msaa.rs"
name = "orthographic"
path = "examples/3d/orthographic.rs"

[[example]]
name = "orthographic_pipelined"
path = "examples/3d/orthographic_pipelined.rs"

[[example]]
name = "parenting"
path = "examples/3d/parenting.rs"
Expand Down
23 changes: 14 additions & 9 deletions examples/3d/3d_scene_pipelined.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,7 @@ fn setup(
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
commands.insert_resource(AmbientLight {
color: Color::ORANGE_RED,
brightness: 0.02,
});
// plane
// ground plane
commands.spawn_bundle(PbrBundle {
mesh: meshes.add(Mesh::from(shape::Plane { size: 10.0 })),
material: materials.add(StandardMaterial {
Expand All @@ -51,6 +47,7 @@ fn setup(
..Default::default()
});

// left wall
let mut transform = Transform::from_xyz(2.5, 2.5, 0.0);
transform.rotate(Quat::from_rotation_z(std::f32::consts::FRAC_PI_2));
commands.spawn_bundle(PbrBundle {
Expand All @@ -63,7 +60,7 @@ fn setup(
}),
..Default::default()
});

// back (right) wall
let mut transform = Transform::from_xyz(0.0, 2.5, -2.5);
transform.rotate(Quat::from_rotation_x(std::f32::consts::FRAC_PI_2));
commands.spawn_bundle(PbrBundle {
Expand All @@ -76,6 +73,7 @@ fn setup(
}),
..Default::default()
});

// cube
commands
.spawn_bundle(PbrBundle {
Expand Down Expand Up @@ -104,7 +102,13 @@ fn setup(
})
.insert(Movable);

// light
// ambient light
commands.insert_resource(AmbientLight {
color: Color::ORANGE_RED,
brightness: 0.02,
});

// red point light
commands
.spawn_bundle(PointLightBundle {
// transform: Transform::from_xyz(5.0, 8.0, 2.0),
Expand All @@ -131,7 +135,7 @@ fn setup(
});
});

// light
// green point light
commands
.spawn_bundle(PointLightBundle {
// transform: Transform::from_xyz(5.0, 8.0, 2.0),
Expand All @@ -158,7 +162,7 @@ fn setup(
});
});

// light
// blue point light
commands
.spawn_bundle(PointLightBundle {
// transform: Transform::from_xyz(5.0, 8.0, 2.0),
Expand All @@ -185,6 +189,7 @@ fn setup(
});
});

// directional 'sun' light
const HALF_SIZE: f32 = 10.0;
commands.spawn_bundle(DirectionalLightBundle {
directional_light: DirectionalLight {
Expand Down
71 changes: 71 additions & 0 deletions examples/3d/orthographic_pipelined.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
use bevy::{
ecs::prelude::*,
math::Vec3,
pbr2::{PbrBundle, PointLightBundle, StandardMaterial},
prelude::{App, Assets, Transform},
render2::{
camera::OrthographicCameraBundle,
color::Color,
mesh::{shape, Mesh},
},
PipelinedDefaultPlugins,
};

fn main() {
App::new()
.add_plugins(PipelinedDefaultPlugins)
.add_startup_system(setup.system())
.run();
}

/// set up a simple 3D scene
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
// set up the camera
let mut camera = OrthographicCameraBundle::new_3d();
camera.orthographic_projection.scale = 3.0;
camera.transform = Transform::from_xyz(5.0, 5.0, 5.0).looking_at(Vec3::ZERO, Vec3::Y);

// camera
commands.spawn_bundle(camera);

// plane
commands.spawn_bundle(PbrBundle {
mesh: meshes.add(Mesh::from(shape::Plane { size: 5.0 })),
material: materials.add(Color::rgb(0.3, 0.5, 0.3).into()),
..Default::default()
});
// cubes
commands.spawn_bundle(PbrBundle {
mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
material: materials.add(Color::rgb(0.8, 0.7, 0.6).into()),
transform: Transform::from_xyz(1.5, 0.5, 1.5),
..Default::default()
});
commands.spawn_bundle(PbrBundle {
mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
material: materials.add(Color::rgb(0.8, 0.7, 0.6).into()),
transform: Transform::from_xyz(1.5, 0.5, -1.5),
..Default::default()
});
commands.spawn_bundle(PbrBundle {
mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
material: materials.add(Color::rgb(0.8, 0.7, 0.6).into()),
transform: Transform::from_xyz(-1.5, 0.5, 1.5),
..Default::default()
});
commands.spawn_bundle(PbrBundle {
mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
material: materials.add(Color::rgb(0.8, 0.7, 0.6).into()),
transform: Transform::from_xyz(-1.5, 0.5, -1.5),
..Default::default()
});
// light
commands.spawn_bundle(PointLightBundle {
transform: Transform::from_xyz(3.0, 8.0, 5.0),
..Default::default()
});
}
1 change: 1 addition & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ Example | File | Description
`load_gltf_pipelined` | [`3d/load_gltf_pipelined.rs`](./3d/load_gltf_pipelined.rs) | Loads and renders a gltf file as a scene
`msaa` | [`3d/msaa.rs`](./3d/msaa.rs) | Configures MSAA (Multi-Sample Anti-Aliasing) for smoother edges
`orthographic` | [`3d/orthographic.rs`](./3d/orthographic.rs) | Shows how to create a 3D orthographic view (for isometric-look games or CAD applications)
`orthographic_pipelined` | [`3d/orthographic_pipelined.rs`](./3d/orthographic_pipelined.rs) | Shows how to create a 3D orthographic view (for isometric-look games or CAD applications)
`parenting` | [`3d/parenting.rs`](./3d/parenting.rs) | Demonstrates parent->child relationships and relative transformations
`pbr` | [`3d/pbr.rs`](./3d/pbr.rs) | Demonstrates use of Physically Based Rendering (PBR) properties
`pbr_pipelined` | [`3d/pbr_pipelined.rs`](./3d/pbr_pipelined.rs) | Demonstrates use of Physically Based Rendering (PBR) properties
Expand Down
2 changes: 1 addition & 1 deletion pipelined/bevy_core_pipeline/src/main_pass_3d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ impl Node for MainPass3dNode {
depth_stencil_attachment: Some(RenderPassDepthStencilAttachment {
view: depth_texture,
depth_ops: Some(Operations {
load: LoadOp::Clear(1.0),
load: LoadOp::Clear(0.0),
store: true,
}),
stencil_ops: None,
Expand Down
2 changes: 1 addition & 1 deletion pipelined/bevy_pbr2/src/light.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ impl Default for PointLight {

impl PointLight {
pub const DEFAULT_SHADOW_DEPTH_BIAS: f32 = 0.02;
pub const DEFAULT_SHADOW_NORMAL_BIAS: f32 = 0.5;
pub const DEFAULT_SHADOW_NORMAL_BIAS: f32 = 0.6;
}

#[derive(Clone, Debug)]
Expand Down
6 changes: 4 additions & 2 deletions pipelined/bevy_pbr2/src/render/depth.wgsl
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// NOTE: Keep in sync with pbr.wgsl
[[block]]
struct View {
view_proj: mat4x4<f32>;
projection: mat4x4<f32>;
world_position: vec3<f32>;
};
[[group(0), binding(0)]]
Expand All @@ -9,7 +11,7 @@ var view: View;

[[block]]
struct Mesh {
transform: mat4x4<f32>;
model: mat4x4<f32>;
};
[[group(1), binding(0)]]
var mesh: Mesh;
Expand All @@ -25,6 +27,6 @@ struct VertexOutput {
[[stage(vertex)]]
fn vertex(vertex: Vertex) -> VertexOutput {
var out: VertexOutput;
out.clip_position = view.view_proj * mesh.transform * vec4<f32>(vertex.position, 1.0);
out.clip_position = view.view_proj * mesh.model * vec4<f32>(vertex.position, 1.0);
return out;
}
16 changes: 8 additions & 8 deletions pipelined/bevy_pbr2/src/render/light.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ pub type ExtractedDirectionalLightShadowMap = DirectionalLightShadowMap;
#[repr(C)]
#[derive(Copy, Clone, AsStd140, Default, Debug)]
pub struct GpuPointLight {
projection: Mat4,
color: Vec4,
// proj: Mat4,
position: Vec3,
inverse_square_range: f32,
radius: f32,
Expand Down Expand Up @@ -120,7 +120,7 @@ impl FromWorld for ShadowShaders {
has_dynamic_offset: true,
// TODO: change this to ViewUniform::std140_size_static once crevice fixes this!
// Context: https://github.com/LPGhatguy/crevice/issues/29
min_binding_size: BufferSize::new(80),
min_binding_size: BufferSize::new(144),
},
count: None,
},
Expand Down Expand Up @@ -168,7 +168,7 @@ impl FromWorld for ShadowShaders {
depth_stencil: Some(DepthStencilState {
format: SHADOW_FORMAT,
depth_write_enabled: true,
depth_compare: CompareFunction::LessEqual,
depth_compare: CompareFunction::GreaterEqual,
stencil: StencilState {
front: StencilFaceState::IGNORE,
back: StencilFaceState::IGNORE,
Expand Down Expand Up @@ -205,7 +205,7 @@ impl FromWorld for ShadowShaders {
mag_filter: FilterMode::Linear,
min_filter: FilterMode::Linear,
mipmap_filter: FilterMode::Nearest,
compare: Some(CompareFunction::LessEqual),
compare: Some(CompareFunction::GreaterEqual),
..Default::default()
}),
directional_light_sampler: render_device.create_sampler(&SamplerDescriptor {
Expand All @@ -215,7 +215,7 @@ impl FromWorld for ShadowShaders {
mag_filter: FilterMode::Linear,
min_filter: FilterMode::Linear,
mipmap_filter: FilterMode::Nearest,
compare: Some(CompareFunction::LessEqual),
compare: Some(CompareFunction::GreaterEqual),
..Default::default()
}),
}
Expand Down Expand Up @@ -435,7 +435,7 @@ pub fn prepare_lights(
// TODO: this should select lights based on relevance to the view instead of the first ones that show up in a query
for (light_index, light) in point_lights.iter().enumerate().take(MAX_POINT_LIGHTS) {
let projection =
Mat4::perspective_rh(std::f32::consts::FRAC_PI_2, 1.0, 0.1, light.range);
Mat4::perspective_infinite_reverse_rh(std::f32::consts::FRAC_PI_2, 1.0, 0.1);

// ignore scale because we don't want to effectively scale light radius and range
// by applying those as a view transform to shadow map rendering of objects
Expand Down Expand Up @@ -484,6 +484,7 @@ pub fn prepare_lights(
}

gpu_lights.point_lights[light_index] = GpuPointLight {
projection,
// premultiply color by intensity
// we don't use the alpha at all, so no reason to multiply only [0..3]
color: (light.color.as_rgba_linear() * light.intensity).into(),
Expand All @@ -492,7 +493,6 @@ pub fn prepare_lights(
inverse_square_range: 1.0 / (light.range * light.range),
near: 0.1,
far: light.range,
// proj: projection,
shadow_depth_bias: light.shadow_depth_bias,
shadow_normal_bias: light.shadow_normal_bias,
};
Expand Down Expand Up @@ -656,7 +656,7 @@ impl Node for ShadowPassNode {
depth_stencil_attachment: Some(RenderPassDepthStencilAttachment {
view: &view_light.depth_texture_view,
depth_ops: Some(Operations {
load: LoadOp::Clear(1.0),
load: LoadOp::Clear(0.0),
store: true,
}),
stencil_ops: None,
Expand Down
16 changes: 11 additions & 5 deletions pipelined/bevy_pbr2/src/render/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ impl FromWorld for PbrShaders {
has_dynamic_offset: true,
// TODO: change this to ViewUniform::std140_size_static once crevice fixes this!
// Context: https://github.com/LPGhatguy/crevice/issues/29
min_binding_size: BufferSize::new(80),
min_binding_size: BufferSize::new(144),
},
count: None,
},
Expand All @@ -66,7 +66,7 @@ impl FromWorld for PbrShaders {
has_dynamic_offset: true,
// TODO: change this to GpuLights::std140_size_static once crevice fixes this!
// Context: https://github.com/LPGhatguy/crevice/issues/29
min_binding_size: BufferSize::new(1024),
min_binding_size: BufferSize::new(1424),
},
count: None,
},
Expand Down Expand Up @@ -225,7 +225,9 @@ impl FromWorld for PbrShaders {
ty: BindingType::Buffer {
ty: BufferBindingType::Uniform,
has_dynamic_offset: true,
min_binding_size: BufferSize::new(80),
// TODO: change this to MeshUniform::std140_size_static once crevice fixes this!
// Context: https://github.com/LPGhatguy/crevice/issues/29
min_binding_size: BufferSize::new(144),
},
count: None,
}],
Expand Down Expand Up @@ -291,7 +293,7 @@ impl FromWorld for PbrShaders {
depth_stencil: Some(DepthStencilState {
format: TextureFormat::Depth32Float,
depth_write_enabled: true,
depth_compare: CompareFunction::Less,
depth_compare: CompareFunction::Greater,
stencil: StencilState {
front: StencilFaceState::IGNORE,
back: StencilFaceState::IGNORE,
Expand Down Expand Up @@ -455,6 +457,7 @@ struct MeshDrawInfo {
#[derive(Debug, AsStd140)]
pub struct MeshUniform {
model: Mat4,
inverse_transpose_model: Mat4,
flags: u32,
}

Expand Down Expand Up @@ -486,13 +489,16 @@ pub fn prepare_meshes(
.transform_uniforms
.reserve_and_clear(extracted_meshes.meshes.len(), &render_device);
for extracted_mesh in extracted_meshes.meshes.iter_mut() {
let model = extracted_mesh.transform;
let inverse_transpose_model = model.inverse().transpose();
let flags = if extracted_mesh.receives_shadows {
MeshFlags::SHADOW_RECEIVER
} else {
MeshFlags::NONE
};
extracted_mesh.transform_binding_offset = mesh_meta.transform_uniforms.push(MeshUniform {
model: extracted_mesh.transform,
model,
inverse_transpose_model,
flags: flags.bits,
});
}
Expand Down
Loading