mirror of
https://github.com/bevyengine/bevy
synced 2024-11-21 20:23:28 +00:00
adjust cluster index for viewport origin (#5947)
# Objective fixes #5946 ## Solution adjust cluster index calculation for viewport origin. from reading point 2 of the rasterization algorithm description in https://gpuweb.github.io/gpuweb/#rasterization, it looks like framebuffer space (and so @bulitin(position)) is not meant to be adjusted for viewport origin, so we need to subtract that to get the right cluster index. - add viewport origin to rust `ExtractedView` and wgsl `View` structs - subtract from frag coord for cluster index calculation
This commit is contained in:
parent
deeab3fc90
commit
503c2a9677
12 changed files with 65 additions and 34 deletions
|
@ -1,4 +1,5 @@
|
|||
#import bevy_pbr::mesh_view_bindings
|
||||
#import bevy_pbr::utils
|
||||
|
||||
@group(1) @binding(0)
|
||||
var texture: texture_2d<f32>;
|
||||
|
@ -12,7 +13,7 @@ fn fragment(
|
|||
#import bevy_sprite::mesh2d_vertex_output
|
||||
) -> @location(0) vec4<f32> {
|
||||
// Get screen position with coordinates from 0 to 1
|
||||
let uv = position.xy / vec2<f32>(view.width, view.height);
|
||||
let uv = coords_to_viewport_uv(position.xy, view.viewport);
|
||||
let offset_strength = 0.02;
|
||||
|
||||
// Sample each color channel with an arbitrary shift
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#import bevy_pbr::mesh_view_bindings
|
||||
#import bevy_pbr::utils
|
||||
|
||||
@group(1) @binding(0)
|
||||
var texture: texture_2d<f32>;
|
||||
|
@ -10,7 +11,7 @@ fn fragment(
|
|||
@builtin(position) position: vec4<f32>,
|
||||
#import bevy_pbr::mesh_vertex_output
|
||||
) -> @location(0) vec4<f32> {
|
||||
let uv = position.xy / vec2<f32>(view.width, view.height);
|
||||
let uv = coords_to_viewport_uv(position.xy, view.viewport);
|
||||
let color = textureSample(texture, texture_sampler, uv);
|
||||
return color;
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ fn view_z_to_z_slice(view_z: f32, is_orthographic: bool) -> u32 {
|
|||
}
|
||||
|
||||
fn fragment_cluster_index(frag_coord: vec2<f32>, view_z: f32, is_orthographic: bool) -> u32 {
|
||||
let xy = vec2<u32>(floor(frag_coord * lights.cluster_factors.xy));
|
||||
let xy = vec2<u32>(floor((frag_coord - view.viewport.xy) * lights.cluster_factors.xy));
|
||||
let z_slice = view_z_to_z_slice(view_z, is_orthographic);
|
||||
// NOTE: Restricting cluster index to avoid undefined behavior when accessing uniform buffer
|
||||
// arrays based on the cluster index.
|
||||
|
|
|
@ -967,8 +967,8 @@ pub fn prepare_lights(
|
|||
ambient_color: Vec4::from_slice(&ambient_light.color.as_linear_rgba_f32())
|
||||
* ambient_light.brightness,
|
||||
cluster_factors: Vec4::new(
|
||||
clusters.dimensions.x as f32 / extracted_view.width as f32,
|
||||
clusters.dimensions.y as f32 / extracted_view.height as f32,
|
||||
clusters.dimensions.x as f32 / extracted_view.viewport.z as f32,
|
||||
clusters.dimensions.y as f32 / extracted_view.viewport.w as f32,
|
||||
cluster_factors_zw.x,
|
||||
cluster_factors_zw.y,
|
||||
),
|
||||
|
@ -1024,8 +1024,12 @@ pub fn prepare_lights(
|
|||
),
|
||||
},
|
||||
ExtractedView {
|
||||
width: point_light_shadow_map.size as u32,
|
||||
height: point_light_shadow_map.size as u32,
|
||||
viewport: UVec4::new(
|
||||
0,
|
||||
0,
|
||||
point_light_shadow_map.size as u32,
|
||||
point_light_shadow_map.size as u32,
|
||||
),
|
||||
transform: view_translation * *view_rotation,
|
||||
projection: cube_face_projection,
|
||||
},
|
||||
|
@ -1076,8 +1080,12 @@ pub fn prepare_lights(
|
|||
pass_name: format!("shadow pass spot light {}", light_index,),
|
||||
},
|
||||
ExtractedView {
|
||||
width: directional_light_shadow_map.size as u32,
|
||||
height: directional_light_shadow_map.size as u32,
|
||||
viewport: UVec4::new(
|
||||
0,
|
||||
0,
|
||||
directional_light_shadow_map.size as u32,
|
||||
directional_light_shadow_map.size as u32,
|
||||
),
|
||||
transform: spot_view_transform,
|
||||
projection: spot_projection,
|
||||
},
|
||||
|
@ -1156,8 +1164,12 @@ pub fn prepare_lights(
|
|||
pass_name: format!("shadow pass directional light {}", i),
|
||||
},
|
||||
ExtractedView {
|
||||
width: directional_light_shadow_map.size as u32,
|
||||
height: directional_light_shadow_map.size as u32,
|
||||
viewport: UVec4::new(
|
||||
0,
|
||||
0,
|
||||
directional_light_shadow_map.size as u32,
|
||||
directional_light_shadow_map.size as u32,
|
||||
),
|
||||
transform: GlobalTransform::from(view.inverse()),
|
||||
projection,
|
||||
},
|
||||
|
|
|
@ -8,8 +8,8 @@ struct View {
|
|||
projection: mat4x4<f32>,
|
||||
inverse_projection: mat4x4<f32>,
|
||||
world_position: vec3<f32>,
|
||||
width: f32,
|
||||
height: f32,
|
||||
// viewport(x_origin, y_origin, width, height)
|
||||
viewport: vec4<f32>,
|
||||
};
|
||||
|
||||
struct PointLight {
|
||||
|
|
|
@ -21,3 +21,11 @@ fn hsv2rgb(hue: f32, saturation: f32, value: f32) -> vec3<f32> {
|
|||
fn random1D(s: f32) -> f32 {
|
||||
return fract(sin(s * 12.9898) * 43758.5453123);
|
||||
}
|
||||
|
||||
// returns the (0-1, 0-1) position within the given viewport for the current buffer coords .
|
||||
// buffer coords can be obtained from `@builtin(position).xy`.
|
||||
// the view uniform struct contains the current camera viewport in `view.viewport`.
|
||||
// topleft = 0,0
|
||||
fn coords_to_viewport_uv(position: vec2<f32>, viewport: vec4<f32>) -> vec2<f32> {
|
||||
return (position - viewport.xy) / viewport.zw;
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ use bevy_ecs::{
|
|||
reflect::ReflectComponent,
|
||||
system::{Commands, ParamSet, Query, Res},
|
||||
};
|
||||
use bevy_math::{Mat4, UVec2, Vec2, Vec3};
|
||||
use bevy_math::{Mat4, UVec2, UVec4, Vec2, Vec3};
|
||||
use bevy_reflect::prelude::*;
|
||||
use bevy_reflect::FromReflect;
|
||||
use bevy_transform::components::GlobalTransform;
|
||||
|
@ -418,7 +418,8 @@ pub fn extract_cameras(
|
|||
if !camera.is_active {
|
||||
continue;
|
||||
}
|
||||
if let (Some(viewport_size), Some(target_size)) = (
|
||||
if let (Some((viewport_origin, _)), Some(viewport_size), Some(target_size)) = (
|
||||
camera.physical_viewport_rect(),
|
||||
camera.physical_viewport_size(),
|
||||
camera.physical_target_size(),
|
||||
) {
|
||||
|
@ -437,8 +438,12 @@ pub fn extract_cameras(
|
|||
ExtractedView {
|
||||
projection: camera.projection_matrix(),
|
||||
transform: *transform,
|
||||
width: viewport_size.x,
|
||||
height: viewport_size.y,
|
||||
viewport: UVec4::new(
|
||||
viewport_origin.x,
|
||||
viewport_origin.y,
|
||||
viewport_size.x,
|
||||
viewport_size.y,
|
||||
),
|
||||
},
|
||||
visible_entities.clone(),
|
||||
));
|
||||
|
|
|
@ -21,7 +21,7 @@ use crate::{
|
|||
};
|
||||
use bevy_app::{App, Plugin};
|
||||
use bevy_ecs::prelude::*;
|
||||
use bevy_math::{Mat4, Vec3};
|
||||
use bevy_math::{Mat4, UVec4, Vec3, Vec4};
|
||||
use bevy_reflect::Reflect;
|
||||
use bevy_transform::components::GlobalTransform;
|
||||
use bevy_utils::HashMap;
|
||||
|
@ -81,8 +81,8 @@ impl Default for Msaa {
|
|||
pub struct ExtractedView {
|
||||
pub projection: Mat4,
|
||||
pub transform: GlobalTransform,
|
||||
pub width: u32,
|
||||
pub height: u32,
|
||||
// uvec4(origin.x, origin.y, width, height)
|
||||
pub viewport: UVec4,
|
||||
}
|
||||
|
||||
impl ExtractedView {
|
||||
|
@ -101,8 +101,8 @@ pub struct ViewUniform {
|
|||
projection: Mat4,
|
||||
inverse_projection: Mat4,
|
||||
world_position: Vec3,
|
||||
width: f32,
|
||||
height: f32,
|
||||
// viewport(x_origin, y_origin, width, height)
|
||||
viewport: Vec4,
|
||||
}
|
||||
|
||||
#[derive(Resource, Default)]
|
||||
|
@ -163,8 +163,7 @@ fn prepare_view_uniforms(
|
|||
projection,
|
||||
inverse_projection,
|
||||
world_position: camera.transform.translation(),
|
||||
width: camera.width as f32,
|
||||
height: camera.height as f32,
|
||||
viewport: camera.viewport.as_vec4(),
|
||||
}),
|
||||
};
|
||||
|
||||
|
|
|
@ -8,6 +8,6 @@ struct View {
|
|||
projection: mat4x4<f32>,
|
||||
inverse_projection: mat4x4<f32>,
|
||||
world_position: vec3<f32>,
|
||||
width: f32,
|
||||
height: f32,
|
||||
// viewport(x_origin, y_origin, width, height)
|
||||
viewport: vec4<f32>,
|
||||
};
|
||||
|
|
|
@ -6,8 +6,8 @@ struct View {
|
|||
projection: mat4x4<f32>,
|
||||
inverse_projection: mat4x4<f32>,
|
||||
world_position: vec3<f32>,
|
||||
width: f32,
|
||||
height: f32,
|
||||
// viewport(x_origin, y_origin, width, height)
|
||||
viewport: vec4<f32>,
|
||||
};
|
||||
@group(0) @binding(0)
|
||||
var<uniform> view: View;
|
||||
|
|
|
@ -9,7 +9,7 @@ use crate::{prelude::UiCameraConfig, CalculatedClip, Node, UiColor, UiImage};
|
|||
use bevy_app::prelude::*;
|
||||
use bevy_asset::{load_internal_asset, AssetEvent, Assets, Handle, HandleUntyped};
|
||||
use bevy_ecs::prelude::*;
|
||||
use bevy_math::{Mat4, Rect, Vec2, Vec3, Vec4Swizzles};
|
||||
use bevy_math::{Mat4, Rect, UVec4, Vec2, Vec3, Vec4Swizzles};
|
||||
use bevy_reflect::TypeUuid;
|
||||
use bevy_render::{
|
||||
camera::{Camera, CameraProjection, OrthographicProjection, WindowOrigin},
|
||||
|
@ -238,8 +238,9 @@ pub fn extract_default_ui_camera_view<T: Component>(
|
|||
if matches!(camera_ui, Some(&UiCameraConfig { show_ui: false, .. })) {
|
||||
continue;
|
||||
}
|
||||
if let (Some(logical_size), Some(physical_size)) = (
|
||||
if let (Some(logical_size), Some((physical_origin, _)), Some(physical_size)) = (
|
||||
camera.logical_viewport_size(),
|
||||
camera.physical_viewport_rect(),
|
||||
camera.physical_viewport_size(),
|
||||
) {
|
||||
let mut projection = OrthographicProjection {
|
||||
|
@ -257,8 +258,12 @@ pub fn extract_default_ui_camera_view<T: Component>(
|
|||
0.0,
|
||||
UI_CAMERA_FAR + UI_CAMERA_TRANSFORM_OFFSET,
|
||||
),
|
||||
width: physical_size.x,
|
||||
height: physical_size.y,
|
||||
viewport: UVec4::new(
|
||||
physical_origin.x,
|
||||
physical_origin.y,
|
||||
physical_size.x,
|
||||
physical_size.y,
|
||||
),
|
||||
})
|
||||
.id();
|
||||
commands.get_or_spawn(entity).insert_bundle((
|
||||
|
|
|
@ -6,8 +6,8 @@ struct View {
|
|||
projection: mat4x4<f32>,
|
||||
inverse_projection: mat4x4<f32>,
|
||||
world_position: vec3<f32>,
|
||||
width: f32,
|
||||
height: f32,
|
||||
// viewport(x_origin, y_origin, width, height)
|
||||
viewport: vec4<f32>,
|
||||
};
|
||||
@group(0) @binding(0)
|
||||
var<uniform> view: View;
|
||||
|
|
Loading…
Reference in a new issue