diff --git a/crates/bevy_pbr/src/render/view_transformations.wgsl b/crates/bevy_pbr/src/render/view_transformations.wgsl index 80c26d7b69b2e..d21a1d534c3c3 100644 --- a/crates/bevy_pbr/src/render/view_transformations.wgsl +++ b/crates/bevy_pbr/src/render/view_transformations.wgsl @@ -2,6 +2,7 @@ #import bevy_pbr::mesh_view_bindings as view_bindings #import bevy_pbr::prepass_bindings +#import bevy_render::view /// World space: /// +y is up @@ -31,33 +32,33 @@ // ----------------- /// Convert a view space position to world space +/// DEPRECATED: use bevy_render::view::position_view_to_world instead fn position_view_to_world(view_pos: vec3) -> vec3 { - let world_pos = view_bindings::view.world_from_view * vec4(view_pos, 1.0); - return world_pos.xyz; + return view::position_view_to_world(view_pos, view_bindings::view.world_from_view); } /// Convert a clip space position to world space +/// DEPRECATED: use bevy_render::view::position_clip_to_world instead fn position_clip_to_world(clip_pos: vec4) -> vec3 { - let world_pos = view_bindings::view.world_from_clip * clip_pos; - return world_pos.xyz; + return view::position_clip_to_world(clip_pos, view_bindings::view.world_from_clip); } /// Convert a ndc space position to world space +/// DEPRECATED: use bevy_render::view::position_ndc_to_world instead fn position_ndc_to_world(ndc_pos: vec3) -> vec3 { - let world_pos = view_bindings::view.world_from_clip * vec4(ndc_pos, 1.0); - return world_pos.xyz / world_pos.w; + return view::position_ndc_to_world(ndc_pos, view_bindings::view.world_from_clip); } /// Convert a view space direction to world space +/// DEPRECATED: use bevy_render::view::direction_view_to_world instead fn direction_view_to_world(view_dir: vec3) -> vec3 { - let world_dir = view_bindings::view.world_from_view * vec4(view_dir, 0.0); - return world_dir.xyz; + return view::direction_view_to_world(view_dir, view_bindings::view.world_from_view); } /// Convert a clip space direction to world space +/// DEPRECATED: use bevy_render::view::direction_clip_to_world instead fn direction_clip_to_world(clip_dir: vec4) -> vec3 { - let world_dir = view_bindings::view.world_from_clip * clip_dir; - return world_dir.xyz; + return view::direction_clip_to_world(clip_dir, view_bindings::view.world_from_clip); } // ----------------- @@ -65,49 +66,47 @@ fn direction_clip_to_world(clip_dir: vec4) -> vec3 { // ----------------- /// Convert a world space position to view space +/// DEPRECATED: use bevy_render::view::position_world_to_view instead fn position_world_to_view(world_pos: vec3) -> vec3 { - let view_pos = view_bindings::view.view_from_world * vec4(world_pos, 1.0); - return view_pos.xyz; + return view::position_world_to_view(world_pos, view_bindings::view.view_from_world); } /// Convert a clip space position to view space +/// DEPRECATED: use bevy_render::view::position_clip_to_view instead fn position_clip_to_view(clip_pos: vec4) -> vec3 { - let view_pos = view_bindings::view.view_from_clip * clip_pos; - return view_pos.xyz; + return view::position_clip_to_view(clip_pos, view_bindings::view.view_from_clip); } /// Convert a ndc space position to view space +/// DEPRECATED: use bevy_render::view::position_ndc_to_view instead fn position_ndc_to_view(ndc_pos: vec3) -> vec3 { - let view_pos = view_bindings::view.view_from_clip * vec4(ndc_pos, 1.0); - return view_pos.xyz / view_pos.w; + return view::position_ndc_to_view(ndc_pos, view_bindings::view.view_from_clip); } /// Convert a world space direction to view space +/// DEPRECATED: use bevy_render::view::direction_world_to_view instead fn direction_world_to_view(world_dir: vec3) -> vec3 { - let view_dir = view_bindings::view.view_from_world * vec4(world_dir, 0.0); - return view_dir.xyz; + return view::direction_world_to_view(world_dir, view_bindings::view.view_from_world); } /// Convert a clip space direction to view space +/// DEPRECATED: use bevy_render::view::direction_clip_to_view instead fn direction_clip_to_view(clip_dir: vec4) -> vec3 { - let view_dir = view_bindings::view.view_from_clip * clip_dir; - return view_dir.xyz; + return view::direction_clip_to_view(clip_dir, view_bindings::view.view_from_clip); } // ----------------- // TO PREV. VIEW --- // ----------------- +/// DEPRECATED: use bevy_render::view::position_world_to_view instead fn position_world_to_prev_view(world_pos: vec3) -> vec3 { - let view_pos = prepass_bindings::previous_view_uniforms.view_from_world * - vec4(world_pos, 1.0); - return view_pos.xyz; + return view::position_world_to_view(world_pos, prepass_bindings::previous_view_uniforms.view_from_world); } +/// DEPRECATED: use bevy_render::view::position_world_to_ndc instead fn position_world_to_prev_ndc(world_pos: vec3) -> vec3 { - let ndc_pos = prepass_bindings::previous_view_uniforms.clip_from_world * - vec4(world_pos, 1.0); - return ndc_pos.xyz / ndc_pos.w; + return view::position_world_to_ndc(world_pos, prepass_bindings::previous_view_uniforms.clip_from_world); } // ----------------- @@ -115,27 +114,27 @@ fn position_world_to_prev_ndc(world_pos: vec3) -> vec3 { // ----------------- /// Convert a world space position to clip space +/// DEPRECATED: use bevy_render::view::position_world_to_clip instead fn position_world_to_clip(world_pos: vec3) -> vec4 { - let clip_pos = view_bindings::view.clip_from_world * vec4(world_pos, 1.0); - return clip_pos; + return view::position_world_to_clip(world_pos, view_bindings::view.clip_from_world); } /// Convert a view space position to clip space +/// DEPRECATED: use bevy_render::view::position_view_to_clip instead fn position_view_to_clip(view_pos: vec3) -> vec4 { - let clip_pos = view_bindings::view.clip_from_view * vec4(view_pos, 1.0); - return clip_pos; + return view::position_view_to_clip(view_pos, view_bindings::view.clip_from_view); } /// Convert a world space direction to clip space +/// DEPRECATED: use bevy_render::view::direction_world_to_clip instead fn direction_world_to_clip(world_dir: vec3) -> vec4 { - let clip_dir = view_bindings::view.clip_from_world * vec4(world_dir, 0.0); - return clip_dir; + return view::direction_world_to_clip(world_dir, view_bindings::view.clip_from_world); } /// Convert a view space direction to clip space +/// DEPRECATED: use bevy_render::view::direction_view_to_clip instead fn direction_view_to_clip(view_dir: vec3) -> vec4 { - let clip_dir = view_bindings::view.clip_from_view * vec4(view_dir, 0.0); - return clip_dir; + return view::direction_view_to_clip(view_dir, view_bindings::view.clip_from_view); } // ----------------- @@ -143,15 +142,15 @@ fn direction_view_to_clip(view_dir: vec3) -> vec4 { // ----------------- /// Convert a world space position to ndc space +/// DEPRECATED: use bevy_render::view::position_world_to_ndc instead fn position_world_to_ndc(world_pos: vec3) -> vec3 { - let ndc_pos = view_bindings::view.clip_from_world * vec4(world_pos, 1.0); - return ndc_pos.xyz / ndc_pos.w; + return view::position_world_to_ndc(world_pos, view_bindings::view.clip_from_world); } /// Convert a view space position to ndc space +/// DEPRECATED: use bevy_render::view::position_view_to_ndc instead fn position_view_to_ndc(view_pos: vec3) -> vec3 { - let ndc_pos = view_bindings::view.clip_from_view * vec4(view_pos, 1.0); - return ndc_pos.xyz / ndc_pos.w; + return view::position_view_to_ndc(view_pos, view_bindings::view.clip_from_view); } // ----------------- @@ -159,47 +158,28 @@ fn position_view_to_ndc(view_pos: vec3) -> vec3 { // ----------------- /// Retrieve the perspective camera near clipping plane +/// DEPRECATED: use bevy_render::view::perspective_camera_near instead fn perspective_camera_near() -> f32 { - return view_bindings::view.clip_from_view[3][2]; + return view::perspective_camera_near(view_bindings::view.clip_from_view); } /// Convert ndc depth to linear view z. /// Note: Depth values in front of the camera will be negative as -z is forward +/// DEPRECATED: use bevy_render::view::depth_ndc_to_view_z instead fn depth_ndc_to_view_z(ndc_depth: f32) -> f32 { -#ifdef VIEW_PROJECTION_PERSPECTIVE - return -perspective_camera_near() / ndc_depth; -#else ifdef VIEW_PROJECTION_ORTHOGRAPHIC - return -(view_bindings::view.clip_from_view[3][2] - ndc_depth) / view_bindings::view.clip_from_view[2][2]; -#else - let view_pos = view_bindings::view.view_from_clip * vec4(0.0, 0.0, ndc_depth, 1.0); - return view_pos.z / view_pos.w; -#endif + return view::depth_ndc_to_view_z(ndc_depth, view_bindings::view.clip_from_view, view_bindings::view.view_from_clip); } /// Convert linear view z to ndc depth. /// Note: View z input should be negative for values in front of the camera as -z is forward +/// DEPRECATED: use bevy_render::view::view_z_to_depth_ndc instead fn view_z_to_depth_ndc(view_z: f32) -> f32 { -#ifdef VIEW_PROJECTION_PERSPECTIVE - return -perspective_camera_near() / view_z; -#else ifdef VIEW_PROJECTION_ORTHOGRAPHIC - return view_bindings::view.clip_from_view[3][2] + view_z * view_bindings::view.clip_from_view[2][2]; -#else - let ndc_pos = view_bindings::view.clip_from_view * vec4(0.0, 0.0, view_z, 1.0); - return ndc_pos.z / ndc_pos.w; -#endif + return view::view_z_to_depth_ndc(view_z, view_bindings::view.clip_from_view); } +/// DEPRECATED: use bevy_render::view::prev_view_z_to_depth_ndc instead fn prev_view_z_to_depth_ndc(view_z: f32) -> f32 { -#ifdef VIEW_PROJECTION_PERSPECTIVE - return -perspective_camera_near() / view_z; -#else ifdef VIEW_PROJECTION_ORTHOGRAPHIC - return prepass_bindings::previous_view_uniforms.clip_from_view[3][2] + - view_z * prepass_bindings::previous_view_uniforms.clip_from_view[2][2]; -#else - let ndc_pos = prepass_bindings::previous_view_uniforms.clip_from_view * - vec4(0.0, 0.0, view_z, 1.0); - return ndc_pos.z / ndc_pos.w; -#endif + return view::view_z_to_depth_ndc(view_z, prepass_bindings::previous_view_uniforms.clip_from_view); } // ----------------- @@ -207,28 +187,33 @@ fn prev_view_z_to_depth_ndc(view_z: f32) -> f32 { // ----------------- /// Convert ndc space xy coordinate [-1.0 .. 1.0] to uv [0.0 .. 1.0] +/// DEPRECATED: use bevy_render::view::ndc_to_uv instead fn ndc_to_uv(ndc: vec2) -> vec2 { - return ndc * vec2(0.5, -0.5) + vec2(0.5); + return view::ndc_to_uv(ndc); } /// Convert uv [0.0 .. 1.0] coordinate to ndc space xy [-1.0 .. 1.0] +/// DEPRECATED: use bevy_render::view::uv_to_ndc instead fn uv_to_ndc(uv: vec2) -> vec2 { - return uv * vec2(2.0, -2.0) + vec2(-1.0, 1.0); + return view::uv_to_ndc(uv); } /// returns the (0.0, 0.0) .. (1.0, 1.0) position within the viewport for the current render target /// [0 .. render target viewport size] eg. [(0.0, 0.0) .. (1280.0, 720.0)] to [(0.0, 0.0) .. (1.0, 1.0)] +/// DEPRECATED: use bevy_render::view::frag_coord_to_uv instead fn frag_coord_to_uv(frag_coord: vec2) -> vec2 { - return (frag_coord - view_bindings::view.viewport.xy) / view_bindings::view.viewport.zw; + return view::frag_coord_to_uv(frag_coord, view_bindings::view.viewport); } /// Convert frag coord to ndc +/// DEPRECATED: use bevy_render::view::frag_coord_to_ndc instead fn frag_coord_to_ndc(frag_coord: vec4) -> vec3 { - return vec3(uv_to_ndc(frag_coord_to_uv(frag_coord.xy)), frag_coord.z); + return view::frag_coord_to_ndc(frag_coord, view_bindings::view.viewport); } /// Convert ndc space xy coordinate [-1.0 .. 1.0] to [0 .. render target /// viewport size] +/// DEPRECATED: use bevy_render::view::ndc_to_frag_coord instead fn ndc_to_frag_coord(ndc: vec2) -> vec2 { - return ndc_to_uv(ndc) * view_bindings::view.viewport.zw; + return view::ndc_to_frag_coord(ndc, view_bindings::view.viewport); } diff --git a/crates/bevy_render/src/view/view.wgsl b/crates/bevy_render/src/view/view.wgsl index 7b14bab9e1ca7..375b9349f5036 100644 --- a/crates/bevy_render/src/view/view.wgsl +++ b/crates/bevy_render/src/view/view.wgsl @@ -64,3 +64,204 @@ struct View { mip_bias: f32, frame_count: u32, }; + +/// World space: +/// +y is up + +/// View space: +/// -z is forward, +x is right, +y is up +/// Forward is from the camera position into the scene. +/// (0.0, 0.0, -1.0) is linear distance of 1.0 in front of the camera's view relative to the camera's rotation +/// (0.0, 1.0, 0.0) is linear distance of 1.0 above the camera's view relative to the camera's rotation + +/// NDC (normalized device coordinate): +/// https://www.w3.org/TR/webgpu/#coordinate-systems +/// (-1.0, -1.0) in NDC is located at the bottom-left corner of NDC +/// (1.0, 1.0) in NDC is located at the top-right corner of NDC +/// Z is depth where: +/// 1.0 is near clipping plane +/// Perspective projection: 0.0 is inf far away +/// Orthographic projection: 0.0 is far clipping plane + +/// UV space: +/// 0.0, 0.0 is the top left +/// 1.0, 1.0 is the bottom right + + +// ----------------- +// TO WORLD -------- +// ----------------- + +/// Convert a view space position to world space +fn position_view_to_world(view_pos: vec3, world_from_view: mat4x4) -> vec3 { + let world_pos = world_from_view * vec4(view_pos, 1.0); + return world_pos.xyz; +} + +/// Convert a clip space position to world space +fn position_clip_to_world(clip_pos: vec4, world_from_clip: mat4x4) -> vec3 { + let world_pos = world_from_clip * clip_pos; + return world_pos.xyz; +} + +/// Convert a ndc space position to world space +fn position_ndc_to_world(ndc_pos: vec3, world_from_clip: mat4x4) -> vec3 { + let world_pos = world_from_clip * vec4(ndc_pos, 1.0); + return world_pos.xyz / world_pos.w; +} + +/// Convert a view space direction to world space +fn direction_view_to_world(view_dir: vec3, world_from_view: mat4x4) -> vec3 { + let world_dir = world_from_view * vec4(view_dir, 0.0); + return world_dir.xyz; +} + +/// Convert a clip space direction to world space +fn direction_clip_to_world(clip_dir: vec4, world_from_clip: mat4x4) -> vec3 { + let world_dir = world_from_clip * clip_dir; + return world_dir.xyz; +} + +// ----------------- +// TO VIEW --------- +// ----------------- + +/// Convert a world space position to view space +fn position_world_to_view(world_pos: vec3, view_from_world: mat4x4) -> vec3 { + let view_pos = view_from_world * vec4(world_pos, 1.0); + return view_pos.xyz; +} + +/// Convert a clip space position to view space +fn position_clip_to_view(clip_pos: vec4, view_from_clip: mat4x4) -> vec3 { + let view_pos = view_from_clip * clip_pos; + return view_pos.xyz; +} + +/// Convert a ndc space position to view space +fn position_ndc_to_view(ndc_pos: vec3, view_from_clip: mat4x4) -> vec3 { + let view_pos = view_from_clip * vec4(ndc_pos, 1.0); + return view_pos.xyz / view_pos.w; +} + +/// Convert a world space direction to view space +fn direction_world_to_view(world_dir: vec3, view_from_world: mat4x4) -> vec3 { + let view_dir = view_from_world * vec4(world_dir, 0.0); + return view_dir.xyz; +} + +/// Convert a clip space direction to view space +fn direction_clip_to_view(clip_dir: vec4, view_from_clip: mat4x4) -> vec3 { + let view_dir = view_from_clip * clip_dir; + return view_dir.xyz; +} + +// ----------------- +// TO CLIP --------- +// ----------------- + +/// Convert a world space position to clip space +fn position_world_to_clip(world_pos: vec3, clip_from_world: mat4x4) -> vec4 { + let clip_pos = clip_from_world * vec4(world_pos, 1.0); + return clip_pos; +} + +/// Convert a view space position to clip space +fn position_view_to_clip(view_pos: vec3, clip_from_view: mat4x4) -> vec4 { + let clip_pos = clip_from_view * vec4(view_pos, 1.0); + return clip_pos; +} + +/// Convert a world space direction to clip space +fn direction_world_to_clip(world_dir: vec3, clip_from_world: mat4x4) -> vec4 { + let clip_dir = clip_from_world * vec4(world_dir, 0.0); + return clip_dir; +} + +/// Convert a view space direction to clip space +fn direction_view_to_clip(view_dir: vec3, clip_from_view: mat4x4) -> vec4 { + let clip_dir = clip_from_view * vec4(view_dir, 0.0); + return clip_dir; +} + +// ----------------- +// TO NDC ---------- +// ----------------- + +/// Convert a world space position to ndc space +fn position_world_to_ndc(world_pos: vec3, clip_from_world: mat4x4) -> vec3 { + let ndc_pos = clip_from_world * vec4(world_pos, 1.0); + return ndc_pos.xyz / ndc_pos.w; +} + +/// Convert a view space position to ndc space +fn position_view_to_ndc(view_pos: vec3, clip_from_view: mat4x4) -> vec3 { + let ndc_pos = clip_from_view * vec4(view_pos, 1.0); + return ndc_pos.xyz / ndc_pos.w; +} + +// ----------------- +// DEPTH ----------- +// ----------------- + +/// Retrieve the perspective camera near clipping plane +fn perspective_camera_near(clip_from_view: mat4x4) -> f32 { + return clip_from_view[3][2]; +} + +/// Convert ndc depth to linear view z. +/// Note: Depth values in front of the camera will be negative as -z is forward +fn depth_ndc_to_view_z(ndc_depth: f32, clip_from_view: mat4x4, view_from_clip: mat4x4) -> f32 { +#ifdef VIEW_PROJECTION_PERSPECTIVE + return -perspective_camera_near(clip_from_view) / ndc_depth; +#else ifdef VIEW_PROJECTION_ORTHOGRAPHIC + return -(clip_from_view[3][2] - ndc_depth) / clip_from_view[2][2]; +#else + let view_pos = view_from_clip * vec4(0.0, 0.0, ndc_depth, 1.0); + return view_pos.z / view_pos.w; +#endif +} + +/// Convert linear view z to ndc depth. +/// Note: View z input should be negative for values in front of the camera as -z is forward +fn view_z_to_depth_ndc(view_z: f32, clip_from_view: mat4x4) -> f32 { +#ifdef VIEW_PROJECTION_PERSPECTIVE + return -perspective_camera_near(clip_from_view) / view_z; +#else ifdef VIEW_PROJECTION_ORTHOGRAPHIC + return clip_from_view[3][2] + view_z * clip_from_view[2][2]; +#else + let ndc_pos = clip_from_view * vec4(0.0, 0.0, view_z, 1.0); + return ndc_pos.z / ndc_pos.w; +#endif +} + +// ----------------- +// UV -------------- +// ----------------- + +/// Convert ndc space xy coordinate [-1.0 .. 1.0] to uv [0.0 .. 1.0] +fn ndc_to_uv(ndc: vec2) -> vec2 { + return ndc * vec2(0.5, -0.5) + vec2(0.5); +} + +/// Convert uv [0.0 .. 1.0] coordinate to ndc space xy [-1.0 .. 1.0] +fn uv_to_ndc(uv: vec2) -> vec2 { + return uv * vec2(2.0, -2.0) + vec2(-1.0, 1.0); +} + +/// returns the (0.0, 0.0) .. (1.0, 1.0) position within the viewport for the current render target +/// [0 .. render target viewport size] eg. [(0.0, 0.0) .. (1280.0, 720.0)] to [(0.0, 0.0) .. (1.0, 1.0)] +fn frag_coord_to_uv(frag_coord: vec2, viewport: vec4) -> vec2 { + return (frag_coord - viewport.xy) / viewport.zw; +} + +/// Convert frag coord to ndc +fn frag_coord_to_ndc(frag_coord: vec4, viewport: vec4) -> vec3 { + return vec3(uv_to_ndc(frag_coord_to_uv(frag_coord.xy, viewport)), frag_coord.z); +} + +/// Convert ndc space xy coordinate [-1.0 .. 1.0] to [0 .. render target +/// viewport size] +fn ndc_to_frag_coord(ndc: vec2, viewport: vec4) -> vec2 { + return ndc_to_uv(ndc) * viewport.zw; +}