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 depth to world position #9718

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
11 changes: 11 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -1663,6 +1663,17 @@ description = "A shader and a material that uses it"
category = "Shaders"
wasm = true

[[example]]
name = "shader_depth_position"
path = "examples/shader/shader_depth_position.rs"
doc-scrape-examples = true

[package.metadata.example.shader_depth_position]
name = "shader_depth_position"
description = ""
category = "Shaders"
wasm = false

[[example]]
name = "shader_prepass"
path = "examples/shader/shader_prepass.rs"
Expand Down
8 changes: 8 additions & 0 deletions crates/bevy_pbr/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ pub const PBR_FUNCTIONS_HANDLE: Handle<Shader> = Handle::weak_from_u128(16550102
pub const PBR_AMBIENT_HANDLE: Handle<Shader> = Handle::weak_from_u128(2441520459096337034);
pub const PARALLAX_MAPPING_SHADER_HANDLE: Handle<Shader> =
Handle::weak_from_u128(17035894873630133905);
pub const DEPTH_FUNCTIONS_SHADER_HANDLE: Handle<Shader> =
Handle::weak_from_u128(1246561570914304165);

/// Sets up the entire PBR infrastructure of bevy.
pub struct PbrPlugin {
Expand Down Expand Up @@ -149,6 +151,12 @@ impl Plugin for PbrPlugin {
"render/parallax_mapping.wgsl",
Shader::from_wgsl
);
load_internal_asset!(
app,
DEPTH_FUNCTIONS_SHADER_HANDLE,
"render/depth_functions.wgsl",
Shader::from_wgsl
);

app.register_asset_reflect::<StandardMaterial>()
.register_type::<AlphaMode>()
Expand Down
31 changes: 31 additions & 0 deletions crates/bevy_pbr/src/render/depth_functions.wgsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#define_import_path bevy_pbr::depth_functions

// NDC depth using our projections is 1 at the near plane and 0 at the far plane.
// If UV is 0,0 top left and 1,1 bottom right, then say xy = uv * vec2(2.0, -2.0) + vec2(-1.0, 1.0) I think.
// and then you make p_ndc = vec4(xy, depth_ndc, 1.0); p_view_homogeneous = view.inverse_projection * p_ndc; p_view = p_view_homogeneous.xyz / p_view_homogeneous.w; p_world = view.view * vec4(p_view, 1.0);

fn depth_to_world_position(uv: vec2<f32>, depth: f32, inverse_projection: mat4x4<f32>, view: mat4x4<f32>) -> vec3<f32>{
let clip_xy = uv_to_clip(uv);
let p_ndc = vec4(clip_xy, depth, 1.0);
let p_view_homogeneous = inverse_projection * p_ndc;
let p_view = p_view_homogeneous.xyz / p_view_homogeneous.w;
let p_world = view * vec4(p_view, 1.0);
return p_world.xyz;
}

fn depth_to_world_position_two(uv: vec2<f32>, depth: f32, inverse_projection: mat4x4<f32>, view_world_pos: vec3<f32>) -> vec3<f32>{
let view_pos = depth_to_view_space_position(uv, depth, inverse_projection);
let world_pos = view_pos - view_world_pos;
return world_pos;
}

fn depth_to_view_space_position(uv: vec2<f32>, depth: f32, inverse_projection: mat4x4<f32>) -> vec3<f32> {
let clip_xy = uv_to_clip(uv);
let t = inverse_projection * vec4(clip_xy, depth, 1.0);
let view_xyz = t.xyz / t.w;
return view_xyz;
}

fn uv_to_clip(uv: vec2<f32>) -> vec2<f32>{
return uv * vec2(2.0, -2.0) + vec2(-1.0, 1.0);
}
12 changes: 3 additions & 9 deletions crates/bevy_pbr/src/ssao/gtao.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#import bevy_pbr::utils PI, HALF_PI
#import bevy_render::view View
#import bevy_render::globals Globals
#import bevy_pbr::depth_functions depth_to_view_space_position

@group(0) @binding(0) var preprocessed_depth: texture_2d<f32>;
@group(0) @binding(1) var normals: texture_2d<f32>;
Expand Down Expand Up @@ -78,16 +79,9 @@ fn load_normal_view_space(uv: vec2<f32>) -> vec3<f32> {
return inverse_view * world_normal;
}

fn reconstruct_view_space_position(depth: f32, uv: vec2<f32>) -> vec3<f32> {
let clip_xy = vec2<f32>(uv.x * 2.0 - 1.0, 1.0 - 2.0 * uv.y);
let t = view.inverse_projection * vec4<f32>(clip_xy, depth, 1.0);
let view_xyz = t.xyz / t.w;
return view_xyz;
}

fn load_and_reconstruct_view_space_position(uv: vec2<f32>, sample_mip_level: f32) -> vec3<f32> {
let depth = textureSampleLevel(preprocessed_depth, point_clamp_sampler, uv, sample_mip_level).r;
return reconstruct_view_space_position(depth, uv);
return depth_to_view_space_position(uv, depth, view.inverse_projection);
}

@compute
Expand All @@ -107,7 +101,7 @@ fn gtao(@builtin(global_invocation_id) global_id: vec3<u32>) {
var pixel_depth = calculate_neighboring_depth_differences(pixel_coordinates);
pixel_depth += 0.00001; // Avoid depth precision issues

let pixel_position = reconstruct_view_space_position(pixel_depth, uv);
let pixel_position = depth_to_view_space_position(uv, pixel_depth, view.inverse_projection);
let pixel_normal = load_normal_view_space(uv);
let view_vec = normalize(-pixel_position);

Expand Down
85 changes: 85 additions & 0 deletions examples/shader/shader_depth_position.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
//! A shader and a material that uses it.

use bevy::{
prelude::*,
reflect::TypePath,
render::render_resource::{AsBindGroup, ShaderRef},
};
use bevy_internal::core_pipeline::prepass::DepthPrepass;

pub const SHADER_HANDLE: Handle<Shader> = Handle::weak_from_u128(8695250969165824);

fn main() {
App::new()
.add_plugins((DefaultPlugins, MaterialPlugin::<CustomMaterial>::default()))
.add_systems(Startup, setup)
.run();
}

const SHADER_CODE: &str = r"
#import bevy_pbr::mesh_vertex_output MeshVertexOutput
#import bevy_pbr::mesh_view_bindings view
#import bevy_pbr::depth_functions depth_to_view_space_position, depth_to_world_position, depth_to_world_position_two
#import bevy_pbr::prepass_utils
@fragment
fn fragment(
mesh: MeshVertexOutput,
) -> @location(0) vec4<f32> {
let depth = bevy_pbr::prepass_utils::prepass_depth(mesh.position, 0u);
let frag_coord = mesh.position;
let uv = frag_coord.xy;
let world_position = depth_to_world_position_two(uv, depth, view.inverse_projection, view.world_position);
// let view_pos = depth_to_view_space_position(depth, uv);
return vec4(world_position / 10.0, 1.0);
// return material.color * textureSample(base_color_texture, base_color_sampler, mesh.uv);
}
";

/// set up a simple 3D scene
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<CustomMaterial>>,
asset_server: Res<AssetServer>,
mut shaders: ResMut<Assets<Shader>>,
) {
shaders.insert(SHADER_HANDLE, Shader::from_wgsl(SHADER_CODE, file!()));

// cube
commands.spawn(MaterialMeshBundle {
mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
transform: Transform::from_xyz(0.0, 0.5, 0.0),
material: materials.add(CustomMaterial {}),
..default()
});

// plane
commands.spawn(MaterialMeshBundle {
mesh: meshes.add(shape::Plane::from_size(5.0).into()),
material: materials.add(CustomMaterial {}),
..default()
});

// camera
commands.spawn((
Camera3dBundle {
transform: Transform::from_xyz(-2.0, 2.5, 5.0).looking_at(Vec3::ZERO, Vec3::Y),
..default()
},
DepthPrepass,
));
}

/// The Material trait is very configurable, but comes with sensible defaults for all methods.
/// You only need to implement functions for features that need non-default behavior. See the Material api docs for details!
impl Material for CustomMaterial {
fn fragment_shader() -> ShaderRef {
SHADER_HANDLE.into()
}
}

// This is the struct that will be passed to your shader
#[derive(Asset, TypePath, AsBindGroup, Debug, Clone)]
pub struct CustomMaterial {}
Loading