feat(rendering): Vendor Bevy rendering crates (Phase 1 complete)
Closes #6, #7, #8, #9, #10 Refs #2, #122 Vendored bevy_render, bevy_core_pipeline, and bevy_pbr from Bevy v0.17.2 (commit 566358363126dd69f6e457e47f306c68f8041d2a) into libmarathon. - ~51K LOC vendored to crates/libmarathon/src/render/ - Merged bevy_render_macros into crates/macros/ - Fixed 773→0 compilation errors - Updated dependencies (encase 0.10→0.11, added 4 new deps) - Removed bevy_render/pbr/core_pipeline from app Cargo features All builds passing, macOS smoke test successful. Signed-off-by: Sienna Meridian Satterwhite <sienna@r3t.io>
This commit is contained in:
117
crates/libmarathon/src/render/oit/resolve/oit_resolve.wgsl
Normal file
117
crates/libmarathon/src/render/oit/resolve/oit_resolve.wgsl
Normal file
@@ -0,0 +1,117 @@
|
||||
#import bevy_render::view::View
|
||||
|
||||
@group(0) @binding(0) var<uniform> view: View;
|
||||
@group(0) @binding(1) var<storage, read_write> layers: array<vec2<u32>>;
|
||||
@group(0) @binding(2) var<storage, read_write> layer_ids: array<atomic<i32>>;
|
||||
|
||||
@group(1) @binding(0) var depth: texture_depth_2d;
|
||||
|
||||
struct OitFragment {
|
||||
color: vec3<f32>,
|
||||
alpha: f32,
|
||||
depth: f32,
|
||||
}
|
||||
// Contains all the colors and depth for this specific fragment
|
||||
var<private> fragment_list: array<OitFragment, #{LAYER_COUNT}>;
|
||||
|
||||
struct FullscreenVertexOutput {
|
||||
@builtin(position) position: vec4<f32>,
|
||||
@location(0) uv: vec2<f32>,
|
||||
};
|
||||
|
||||
@fragment
|
||||
fn fragment(in: FullscreenVertexOutput) -> @location(0) vec4<f32> {
|
||||
let buffer_size = i32(view.viewport.z * view.viewport.w);
|
||||
let screen_index = i32(floor(in.position.x) + floor(in.position.y) * view.viewport.z);
|
||||
|
||||
let counter = atomicLoad(&layer_ids[screen_index]);
|
||||
if counter == 0 {
|
||||
reset_indices(screen_index);
|
||||
|
||||
// https://github.com/gfx-rs/wgpu/issues/4416
|
||||
if true {
|
||||
discard;
|
||||
}
|
||||
return vec4(0.0);
|
||||
} else {
|
||||
// Load depth for manual depth testing.
|
||||
// This is necessary because early z doesn't seem to trigger in the transparent pass.
|
||||
// This should be done during the draw pass so those fragments simply don't exist in the list,
|
||||
// but this requires a bigger refactor
|
||||
let d = textureLoad(depth, vec2<i32>(in.position.xy), 0);
|
||||
let result = sort(screen_index, buffer_size, d);
|
||||
reset_indices(screen_index);
|
||||
|
||||
return result.color;
|
||||
}
|
||||
}
|
||||
|
||||
// Resets all indices to 0.
|
||||
// This means we don't have to clear the entire layers buffer
|
||||
fn reset_indices(screen_index: i32) {
|
||||
atomicStore(&layer_ids[screen_index], 0);
|
||||
layers[screen_index] = vec2(0u);
|
||||
}
|
||||
|
||||
struct SortResult {
|
||||
color: vec4f,
|
||||
depth: f32,
|
||||
}
|
||||
|
||||
fn sort(screen_index: i32, buffer_size: i32, opaque_depth: f32) -> SortResult {
|
||||
var counter = atomicLoad(&layer_ids[screen_index]);
|
||||
|
||||
// fill list
|
||||
for (var i = 0; i < counter; i += 1) {
|
||||
let fragment = layers[screen_index + buffer_size * i];
|
||||
// unpack color/alpha/depth
|
||||
let color = bevy_pbr::rgb9e5::rgb9e5_to_vec3_(fragment.x);
|
||||
let depth_alpha = bevy_core_pipeline::oit::unpack_24bit_depth_8bit_alpha(fragment.y);
|
||||
fragment_list[i].color = color;
|
||||
fragment_list[i].alpha = depth_alpha.y;
|
||||
fragment_list[i].depth = depth_alpha.x;
|
||||
}
|
||||
|
||||
// bubble sort the list based on the depth
|
||||
for (var i = counter; i >= 0; i -= 1) {
|
||||
for (var j = 0; j < i; j += 1) {
|
||||
if fragment_list[j].depth < fragment_list[j + 1].depth {
|
||||
// swap
|
||||
let temp = fragment_list[j + 1];
|
||||
fragment_list[j + 1] = fragment_list[j];
|
||||
fragment_list[j] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// resolve blend
|
||||
var final_color = vec4(0.0);
|
||||
for (var i = 0; i <= counter; i += 1) {
|
||||
// depth testing
|
||||
// This needs to happen here because we can only stop iterating if the fragment is
|
||||
// occluded by something opaque and the fragments need to be sorted first
|
||||
if fragment_list[i].depth < opaque_depth {
|
||||
break;
|
||||
}
|
||||
let color = fragment_list[i].color;
|
||||
let alpha = fragment_list[i].alpha;
|
||||
var base_color = vec4(color.rgb * alpha, alpha);
|
||||
final_color = blend(final_color, base_color);
|
||||
if final_color.a == 1.0 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
var result: SortResult;
|
||||
result.color = final_color;
|
||||
result.depth = fragment_list[0].depth;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// OVER operator using premultiplied alpha
|
||||
// see: https://en.wikipedia.org/wiki/Alpha_compositing
|
||||
fn blend(color_a: vec4<f32>, color_b: vec4<f32>) -> vec4<f32> {
|
||||
let final_color = color_a.rgb + (1.0 - color_a.a) * color_b.rgb;
|
||||
let alpha = color_a.a + (1.0 - color_a.a) * color_b.a;
|
||||
return vec4(final_color.rgb, alpha);
|
||||
}
|
||||
Reference in New Issue
Block a user