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

Add Order Independent Transparency #14876

Merged
merged 38 commits into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
782e85e
Add Order Independent Transparency
IceSentry Aug 19, 2024
8b41310
modulo
IceSentry Aug 19, 2024
f475891
add more docs
IceSentry Aug 19, 2024
dd6f009
pass layer_count to shader
IceSentry Aug 21, 2024
db04fa1
docs
IceSentry Aug 22, 2024
234d42c
fix ordering
IceSentry Aug 22, 2024
f7f41e0
Merge branch 'main' into oit-upstreaming
IceSentry Aug 22, 2024
dc52923
typo
IceSentry Aug 22, 2024
9ec68da
fix example readme
IceSentry Aug 22, 2024
c2057c2
Merge branch 'main' into oit-upstreaming
IceSentry Sep 29, 2024
a83e2a6
fix review comments
IceSentry Sep 29, 2024
7e158f1
Clean up OIT
IceSentry Sep 29, 2024
4ae944d
ci
IceSentry Sep 29, 2024
6e60a47
don't panic
IceSentry Sep 29, 2024
aaf4b8a
add new edge
IceSentry Sep 29, 2024
0bbea5b
use smallvec
IceSentry Sep 29, 2024
d3e69ad
move use
IceSentry Sep 30, 2024
ba7fec0
Apply suggestions from code review
IceSentry Sep 30, 2024
4a52dd6
don't use discard
IceSentry Sep 30, 2024
ec959b4
fix backticks
IceSentry Sep 30, 2024
005066f
Improve docs
kristoff3r Oct 1, 2024
dc0fd36
Merge branch 'main' into oit-upstreaming
kristoff3r Oct 1, 2024
626b249
Fix warning
kristoff3r Oct 1, 2024
d77c1bc
Merge pull request #7 from kristoff3r/oit-upstreaming
IceSentry Oct 2, 2024
00d0e41
Merge branch 'main' into oit-upstreaming
IceSentry Oct 2, 2024
6f0255e
fix ci
IceSentry Oct 2, 2024
0ef56e6
migrate example to required components
IceSentry Oct 2, 2024
af88f21
use discard
IceSentry Oct 2, 2024
fab1579
add back transform to light in example
IceSentry Oct 2, 2024
10e90bc
color/alpha/depth packing
IceSentry Oct 3, 2024
b4777a1
Merge branch 'main' into oit-upstreaming
IceSentry Oct 3, 2024
6c4541e
fix despawning in example
IceSentry Oct 3, 2024
1533e05
Merge branch 'main' into oit-upstreaming
IceSentry Oct 3, 2024
6850c83
remove comment about packing
IceSentry Oct 3, 2024
c89cf12
Merge branch 'main' into oit-upstreaming
IceSentry Oct 3, 2024
8fd3861
Fixes from upstream.
tychedelia Oct 6, 2024
1e65381
Disable OIT on webgl.
tychedelia Oct 6, 2024
a23da13
Ignore oit layout if webgl.
tychedelia Oct 7, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions crates/bevy_core_pipeline/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ bevy_render = { path = "../bevy_render", version = "0.15.0-dev" }
bevy_transform = { path = "../bevy_transform", version = "0.15.0-dev" }
bevy_math = { path = "../bevy_math", version = "0.15.0-dev" }
bevy_utils = { path = "../bevy_utils", version = "0.15.0-dev" }
bevy_window = { path = "../bevy_window", version = "0.15.0-dev" }

serde = { version = "1", features = ["derive"] }
bitflags = "2.3"
Expand Down
58 changes: 44 additions & 14 deletions crates/bevy_core_pipeline/src/oit/mod.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,32 @@
//! # Order Independent Transparency (OIT)
//!
//! This implementation uses 2 passes.
//!
//! The first pass writes the depth and color of all the fragments to a big buffer.
//! The buffer contains N layers for each pixel.
IceSentry marked this conversation as resolved.
Show resolved Hide resolved
//! This pass is essentially a forward pass.
//!
//! The second pass is a single fullscreen triangle pass that sorts all the fragments then blends them together
//! and outputs the result to the screen.
//!
//! If you want to use OIT for your custom material you need to call `oit_draw(position, color)` in your fragment shader.
//! You also need to make sure that your fragment shader doesn't output any colors.

use bevy_app::prelude::*;
use bevy_asset::{load_internal_asset, Handle};
use bevy_ecs::prelude::*;
use bevy_math::UVec2;
use bevy_render::{
camera::ExtractedCamera,
camera::{Camera, ExtractedCamera},
extract_component::{ExtractComponent, ExtractComponentPlugin},
render_graph::{RenderGraphApp, ViewNodeRunner},
render_resource::{BufferUsages, BufferVec, DynamicUniformBuffer, Shader, TextureUsages},
renderer::{RenderDevice, RenderQueue},
view::Msaa,
Render, RenderApp, RenderSet,
};
use bevy_utils::{tracing::trace, warn_once, Instant};
use bevy_utils::{tracing::trace, HashSet, Instant};
use bevy_window::PrimaryWindow;
use resolve::{
node::{OitResolveNode, OitResolvePass},
OitResolvePlugin,
Expand All @@ -29,7 +44,7 @@ pub mod resolve;
pub const OIT_DRAW_SHADER_HANDLE: Handle<Shader> = Handle::weak_from_u128(4042527984320512);

/// Used to identify which camera will use OIT to render transparent meshes
/// Alos used to configure OIT
/// and to configure OIT
IceSentry marked this conversation as resolved.
Show resolved Hide resolved
// TODO consider supporting multiple OIT techniques like WBOIT, Moment Based OIT,
// depth peeling, stochastic transparency, ray tracing etc.
// This should probably be done by adding an enum to this component
Expand Down Expand Up @@ -90,17 +105,32 @@ impl Plugin for OrderIndependentTransparencyPlugin {

// WARN This should only happen for cameras with the [`OrderIndependentTransparencySettings`]
IceSentry marked this conversation as resolved.
Show resolved Hide resolved
// but when multiple cameras are present on the same window
// bevy reuses the same depth texture so we need to set this on all cameras.
// bevy reuses the same depth texture so we need to set this on all cameras with the same render target.
fn configure_depth_texture_usages(
mut new_cameras: Query<
&mut Camera3d,
(Added<Camera3d>, With<OrderIndependentTransparencySettings>),
>,
p: Query<Entity, With<PrimaryWindow>>,
cameras: Query<(&Camera, Has<OrderIndependentTransparencySettings>)>,
mut new_cameras: Query<(&mut Camera3d, &Camera), Added<Camera3d>>,
) {
for mut camera in &mut new_cameras {
let mut usages = TextureUsages::from(camera.depth_texture_usages);
usages |= TextureUsages::RENDER_ATTACHMENT | TextureUsages::TEXTURE_BINDING;
camera.depth_texture_usages = usages.into();
if new_cameras.is_empty() {
return;
}

// Find all the render target that potentially uses OIT
let primary_window = p.get_single().expect("No primary window found");
IceSentry marked this conversation as resolved.
Show resolved Hide resolved
let mut render_target_has_oit = HashSet::new();
for (camera, has_oit) in &cameras {
if has_oit {
render_target_has_oit.insert(camera.target.normalize(Some(primary_window)));
}
}

// Update the depth texture usage for cameras with a render target that has OIT
for (mut camera_3d, camera) in &mut new_cameras {
if render_target_has_oit.contains(&camera.target.normalize(Some(primary_window))) {
let mut usages = TextureUsages::from(camera_3d.depth_texture_usages);
usages |= TextureUsages::RENDER_ATTACHMENT | TextureUsages::TEXTURE_BINDING;
camera_3d.depth_texture_usages = usages.into();
}
}
}

Expand Down Expand Up @@ -203,7 +233,7 @@ pub fn prepare_oit_buffers(
trace!(
"OIT layers buffer updated in {:.01}ms with total size {} MiB",
start.elapsed().as_millis(),
buffers.layers.capacity() * std::mem::size_of::<UVec2>() / 1024 / 1024,
buffers.layers.capacity() * size_of::<UVec2>() / 1024 / 1024,
);
}

Expand All @@ -223,7 +253,7 @@ pub fn prepare_oit_buffers(
trace!(
"OIT layer ids buffer updated in {:.01}ms with total size {} MiB",
start.elapsed().as_millis(),
buffers.layer_ids.capacity() * std::mem::size_of::<UVec2>() / 1024 / 1024,
buffers.layer_ids.capacity() * size_of::<UVec2>() / 1024 / 1024,
);
}

Expand Down
1 change: 0 additions & 1 deletion crates/bevy_core_pipeline/src/oit/resolve/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ use bevy_render::{
view::{ExtractedView, ViewTarget, ViewUniform, ViewUniforms},
Render, RenderApp, RenderSet,
};
use bevy_utils::HashMap;

use crate::{
fullscreen_vertex_shader::fullscreen_shader_vertex_state,
Expand Down
12 changes: 6 additions & 6 deletions crates/bevy_pbr/src/render/mesh_view_bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -361,11 +361,11 @@ fn layout_entries(
if layout_key.contains(MeshPipelineViewLayoutKey::OIT_ENABLED) {
entries = entries.extend_with_indices((
// oit_layers
(29, storage_buffer_sized(false, None)),
(31, storage_buffer_sized(false, None)),
// oit_layer_ids,
(30, storage_buffer_sized(false, None)),
(32, storage_buffer_sized(false, None)),
// oit_layer_count
(31, uniform_buffer::<i32>(true)),
(33, uniform_buffer::<i32>(true)),
));
}

Expand Down Expand Up @@ -682,9 +682,9 @@ pub fn prepare_mesh_view_bind_groups(
oit_buffers.layers_count_uniforms.binding(),
) {
entries = entries.extend_with_indices((
(29, oit_layers_binding.clone()),
(30, oit_layer_ids_binding.clone()),
(31, oit_layers_count_uniforms_binding.clone()),
(31, oit_layers_binding.clone()),
(32, oit_layer_ids_binding.clone()),
(33, oit_layers_count_uniforms_binding.clone()),
));
}
}
Expand Down
6 changes: 3 additions & 3 deletions crates/bevy_pbr/src/render/mesh_view_bindings.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ const VISIBILITY_RANGE_UNIFORM_BUFFER_SIZE: u32 = 64u;
@group(0) @binding(30) var view_transmission_sampler: sampler;

#ifdef OIT_ENABLED
@group(0) @binding(29) var<storage, read_write> oit_layers: array<vec2<u32>>;
@group(0) @binding(30) var<storage, read_write> oit_layer_ids: array<atomic<i32>>;
@group(0) @binding(31) var<uniform> oit_layers_count: i32;
@group(0) @binding(31) var<storage, read_write> oit_layers: array<vec2<u32>>;
@group(0) @binding(32) var<storage, read_write> oit_layer_ids: array<atomic<i32>>;
@group(0) @binding(33) var<uniform> oit_layers_count: i32;
#endif OIT_ENABLED
9 changes: 6 additions & 3 deletions examples/3d/order_independent_transparency.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
//! A simple 3D scene with light shining over a cube sitting on a plane.
//! A simple 3D scene showing how alpha blending can break and how OIT can fix it.
//!
IceSentry marked this conversation as resolved.
Show resolved Hide resolved
//! If you want to use OIT for your custom material you need to call `oit_draw(position, color)` in your fragment shader.
//! You also need to make sure that your fragment shader doesn't output any colors.

use bevy::{
color::palettes::css::{BLUE, GREEN, RED},
Expand Down Expand Up @@ -29,12 +32,12 @@ fn setup(
transform: Transform::from_xyz(0.0, 0.0, 10.0).looking_at(Vec3::ZERO, Vec3::Y),
..default()
},
// Add this component so this camera to render transparent meshes using OIT
// Add this component to this camera to render transparent meshes using OIT
OrderIndependentTransparencySettings::default(),
RenderLayers::layer(1),
))
.insert(
// Msaa currently doesn't work well with OIT
// Msaa currently doesn't work with OIT
Msaa::Off,
);

Expand Down
Loading