camera projection wip
This commit is contained in:
@@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
@group(0) @binding(2) var<uniform> config: TracerUniforms;
|
@group(0) @binding(2) var<uniform> config: TracerUniforms;
|
||||||
|
|
||||||
@group(0) @binding(3) var<uniform> view: ViewUniform;
|
|
||||||
|
|
||||||
struct View {
|
struct View {
|
||||||
view_proj: mat4x4<f32>,
|
view_proj: mat4x4<f32>,
|
||||||
@@ -16,25 +15,10 @@ struct View {
|
|||||||
inv_projection: mat4x4<f32>, // equic to Unity's _CameraInverseProjection
|
inv_projection: mat4x4<f32>, // equic to Unity's _CameraInverseProjection
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ViewUniform {
|
|
||||||
clip_from_world: mat4x4<f32>,
|
|
||||||
unjittered_clip_from_world: mat4x4<f32>,
|
|
||||||
world_from_clip: mat4x4<f32>,
|
|
||||||
world_from_view: mat4x4<f32>,
|
|
||||||
view_from_world: mat4x4<f32>,
|
|
||||||
clip_from_view: mat4x4<f32>,
|
|
||||||
view_from_clip: mat4x4<f32>,
|
|
||||||
world_position: vec3<f32>,
|
|
||||||
exposure: f32,
|
|
||||||
viewport: vec4<f32>,
|
|
||||||
frustum: array<vec4<f32>, 6>,
|
|
||||||
color_grading: vec4<f32>, // simplified for example
|
|
||||||
mip_bias: f32,
|
|
||||||
frame_count: u32,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TracerUniforms {
|
struct TracerUniforms {
|
||||||
sky_color: vec4<f32>,
|
sky_color: vec4<f32>,
|
||||||
|
world_from_clip: mat4x4<f32>,
|
||||||
|
world_position: vec3<f32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@compute @workgroup_size(8, 8, 1)
|
@compute @workgroup_size(8, 8, 1)
|
||||||
@@ -53,17 +37,33 @@ fn update(@builtin(global_invocation_id) invocation_id: vec3<u32>) {
|
|||||||
let size = textureDimensions(output);
|
let size = textureDimensions(output);
|
||||||
|
|
||||||
let loc = vec2<f32>(f32(invocation_id.x), f32(invocation_id.y)) / vec2<f32>(size.xy);
|
let loc = vec2<f32>(f32(invocation_id.x), f32(invocation_id.y)) / vec2<f32>(size.xy);
|
||||||
let ndc = loc * 2.0f - 1.0f;
|
// let ndc = loc * 2.0f - 1.0f;
|
||||||
|
|
||||||
var ray = createCameraRay(ndc);
|
// var ray = createCameraRay(ndc);
|
||||||
|
|
||||||
var result = vec3<f32>(0.0f);
|
// var result = vec3<f32>(0.0f);
|
||||||
|
|
||||||
var hit = trace(ray);
|
// var hit = trace(ray);
|
||||||
result += ray.energy * shade(&ray, hit);
|
// result += ray.energy * shade(&ray, hit);
|
||||||
|
|
||||||
|
// var rayTest = createCameraRay2(ndc);
|
||||||
|
// let dirColor = (rayTest.direction * 0.5) + vec3<f32>(0.5, 0.5, 0.5);
|
||||||
|
// let color = vec4(dirColor, 1.0);
|
||||||
|
|
||||||
|
let ndc = vec2<f32>(
|
||||||
|
(f32(invocation_id.x) / f32(size.x)) * 2.0 - 1.0,
|
||||||
|
(f32(invocation_id.y) / f32(size.y)) * 2.0 - 1.0
|
||||||
|
);
|
||||||
|
|
||||||
|
let clip = vec4<f32>(ndc, 0.0, 1.0);
|
||||||
|
let world = config.world_from_clip * clip;
|
||||||
|
let world_pos = world.xyz / world.w;
|
||||||
|
|
||||||
|
// map directly to color
|
||||||
|
let color = vec4<f32>((world_pos * 0.1) + vec3<f32>(0.5), 1.0);
|
||||||
|
|
||||||
let color = vec4(result , 1.0);
|
|
||||||
let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));
|
let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));
|
||||||
|
|
||||||
textureStore(output, location, color);
|
textureStore(output, location, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,19 +113,34 @@ fn createRay(origin: vec3<f32>, direction: vec3<f32>) -> Ray
|
|||||||
|
|
||||||
|
|
||||||
fn createCameraRay(ndc: vec2<f32>) -> Ray {
|
fn createCameraRay(ndc: vec2<f32>) -> Ray {
|
||||||
// let origin = (view.inv_view * vec4<f32>(0.0, 0.0, 0.0, 1.0)).xyz;
|
|
||||||
|
|
||||||
// let direction_view = (view.inv_projection * vec4<f32>(uv, 0.0, 1.0)).xyz;
|
let origin = config.world_position;
|
||||||
// let direction = (view.inv_view * vec4<f32>(direction_view, 0.0)).xyz;
|
let target_point = config.world_from_clip * vec4<f32>(ndc, 0.0f, 1.0f);
|
||||||
|
|
||||||
let origin = view.world_position;
|
|
||||||
let target_point = view.world_from_clip * vec4<f32>(ndc, 0.0f, 1.0f);
|
|
||||||
let direction_point = target_point.xyz / target_point.w;
|
let direction_point = target_point.xyz / target_point.w;
|
||||||
let direction = normalize(direction_point - origin);
|
let direction = normalize(direction_point - origin);
|
||||||
|
|
||||||
return createRay(origin, direction);
|
return createRay(origin, direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn createCameraRay2(ndc: vec2<f32>) -> Ray {
|
||||||
|
// clip points at near and far
|
||||||
|
let near_clip = vec4<f32>(ndc, 0.0, 1.0);
|
||||||
|
let far_clip = vec4<f32>(ndc, 1.0, 1.0);
|
||||||
|
|
||||||
|
// project into world space
|
||||||
|
let near_world4 = config.world_from_clip * near_clip;
|
||||||
|
let far_world4 = config.world_from_clip * far_clip;
|
||||||
|
|
||||||
|
let near_world = near_world4.xyz / near_world4.w;
|
||||||
|
let far_world = far_world4.xyz / far_world4.w;
|
||||||
|
|
||||||
|
// ray starts at near plane, points toward far plane
|
||||||
|
let origin = near_world;
|
||||||
|
let direction = normalize(far_world - near_world);
|
||||||
|
|
||||||
|
return createRay(origin, direction);
|
||||||
|
}
|
||||||
|
|
||||||
fn createSphere(position: vec3<f32>, radius: f32) -> Sphere
|
fn createSphere(position: vec3<f32>, radius: f32) -> Sphere
|
||||||
{
|
{
|
||||||
var s: Sphere;
|
var s: Sphere;
|
||||||
@@ -139,7 +154,9 @@ fn createSphere(position: vec3<f32>, radius: f32) -> Sphere
|
|||||||
fn intersectSphere(ray: Ray, bestHit: ptr<function, RayHit>, sphereIndex: u32)
|
fn intersectSphere(ray: Ray, bestHit: ptr<function, RayHit>, sphereIndex: u32)
|
||||||
{
|
{
|
||||||
//Sphere sphere = _Spheres[sphereIndex];
|
//Sphere sphere = _Spheres[sphereIndex];
|
||||||
var sphere = createSphere(vec3<f32>(0.0), 1.0f);
|
var sphere = createSphere(vec3<f32>(0.0f, 0.0f, -10.0f), 1.0f);
|
||||||
|
|
||||||
|
|
||||||
var d = ray.origin - sphere.position;
|
var d = ray.origin - sphere.position;
|
||||||
var p1 = -dot(ray.direction, d);
|
var p1 = -dot(ray.direction, d);
|
||||||
var p2sqr = p1 * p1 - dot(d, d) + sphere.radius * sphere.radius;
|
var p2sqr = p1 * p1 - dot(d, d) + sphere.radius * sphere.radius;
|
||||||
@@ -209,7 +226,7 @@ fn shade(ray: ptr<function, Ray>, hit: RayHit) -> vec3<f32>
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
(*ray).energy = vec3(0.0f);
|
(*ray).energy = vec3(0.0f);
|
||||||
return vec3<f32>(0.1f);
|
return config.sky_color.xyz;
|
||||||
// var theta = acos(ray.direction.y) / -PI;
|
// var theta = acos(ray.direction.y) / -PI;
|
||||||
// var phi = atan2(ray.direction.x, -ray.direction.z) / -PI * .5f;
|
// var phi = atan2(ray.direction.x, -ray.direction.z) / -PI * .5f;
|
||||||
// return _SkyboxTexture.SampleLevel(sampler_SkyboxTexture, float2(phi, theta), 0).xyz;
|
// return _SkyboxTexture.SampleLevel(sampler_SkyboxTexture, float2(phi, theta), 0).xyz;
|
||||||
|
|||||||
23
src/app.rs
23
src/app.rs
@@ -1,12 +1,19 @@
|
|||||||
use bevy::{
|
use bevy::{
|
||||||
asset::RenderAssetUsages,
|
asset::RenderAssetUsages,
|
||||||
|
math::VectorSpace,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
render::render_resource::{Extent3d, TextureDimension, TextureFormat, TextureUsages},
|
render::{
|
||||||
|
render_resource::{Extent3d, TextureDimension, TextureFormat, TextureUsages},
|
||||||
|
view::RenderLayers,
|
||||||
|
},
|
||||||
window::PrimaryWindow,
|
window::PrimaryWindow,
|
||||||
};
|
};
|
||||||
use iyes_perf_ui::prelude::*;
|
use iyes_perf_ui::prelude::*;
|
||||||
|
|
||||||
use crate::render::pipeline::{TracerPipelinePlugin, TracerRenderTextures, TracerUniforms};
|
use crate::{
|
||||||
|
components::rt::RTCamera,
|
||||||
|
render::pipeline::{TracerPipelinePlugin, TracerRenderTextures, TracerUniforms},
|
||||||
|
};
|
||||||
|
|
||||||
pub struct Blackhole;
|
pub struct Blackhole;
|
||||||
|
|
||||||
@@ -18,6 +25,7 @@ impl Plugin for Blackhole {
|
|||||||
app.add_plugins(TracerPipelinePlugin);
|
app.add_plugins(TracerPipelinePlugin);
|
||||||
app.insert_resource(TracerUniforms {
|
app.insert_resource(TracerUniforms {
|
||||||
sky_color: LinearRgba::BLUE,
|
sky_color: LinearRgba::BLUE,
|
||||||
|
..default()
|
||||||
});
|
});
|
||||||
|
|
||||||
//Perf UI
|
//Perf UI
|
||||||
@@ -74,5 +82,16 @@ fn setup(mut commands: Commands, mut images: ResMut<Assets<Image>>, window: Sing
|
|||||||
|
|
||||||
commands.spawn(Camera2d);
|
commands.spawn(Camera2d);
|
||||||
|
|
||||||
|
commands.spawn((
|
||||||
|
// Camera3d::default(),
|
||||||
|
Projection::Perspective(PerspectiveProjection {
|
||||||
|
aspect_ratio: size.x as f32 / size.y as f32,
|
||||||
|
..default()
|
||||||
|
}),
|
||||||
|
RTCamera,
|
||||||
|
Transform::from_xyz(0.0, 0.0, 5.0).looking_at(Vec3::ZERO, Vec3::Y),
|
||||||
|
Name::new("RT Camera"),
|
||||||
|
));
|
||||||
|
|
||||||
commands.insert_resource(TracerRenderTextures(img0, img1));
|
commands.insert_resource(TracerRenderTextures(img0, img1));
|
||||||
}
|
}
|
||||||
|
|||||||
1
src/components/mod.rs
Normal file
1
src/components/mod.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
pub mod rt;
|
||||||
4
src/components/rt.rs
Normal file
4
src/components/rt.rs
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
use bevy::{prelude::*, render::render_resource::encase::private::ShaderType};
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
pub struct RTCamera;
|
||||||
@@ -4,6 +4,7 @@ use bevy::window::PresentMode;
|
|||||||
use bevy_inspector_egui::{bevy_egui::EguiPlugin, quick::WorldInspectorPlugin};
|
use bevy_inspector_egui::{bevy_egui::EguiPlugin, quick::WorldInspectorPlugin};
|
||||||
|
|
||||||
mod app;
|
mod app;
|
||||||
|
pub mod components;
|
||||||
mod render;
|
mod render;
|
||||||
|
|
||||||
pub const SHADER_ASSET_PATH: &str = "trace.wgsl";
|
pub const SHADER_ASSET_PATH: &str = "trace.wgsl";
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ use bevy::{
|
|||||||
prelude::*,
|
prelude::*,
|
||||||
render::{
|
render::{
|
||||||
Render, RenderApp, RenderSet,
|
Render, RenderApp, RenderSet,
|
||||||
|
camera::CameraProjection,
|
||||||
extract_resource::{ExtractResource, ExtractResourcePlugin},
|
extract_resource::{ExtractResource, ExtractResourcePlugin},
|
||||||
render_asset::RenderAssets,
|
render_asset::RenderAssets,
|
||||||
render_graph::{RenderGraph, RenderLabel},
|
render_graph::{RenderGraph, RenderLabel},
|
||||||
@@ -15,11 +16,10 @@ use bevy::{
|
|||||||
},
|
},
|
||||||
renderer::{RenderDevice, RenderQueue},
|
renderer::{RenderDevice, RenderQueue},
|
||||||
texture::GpuImage,
|
texture::GpuImage,
|
||||||
view::{ViewUniform, ViewUniforms},
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{SHADER_ASSET_PATH, render::node::TracerNode};
|
use crate::{SHADER_ASSET_PATH, components::rt::RTCamera, render::node::TracerNode};
|
||||||
|
|
||||||
#[derive(Debug, Hash, PartialEq, Eq, Clone, RenderLabel)]
|
#[derive(Debug, Hash, PartialEq, Eq, Clone, RenderLabel)]
|
||||||
pub struct TracerLabel;
|
pub struct TracerLabel;
|
||||||
@@ -31,6 +31,8 @@ pub struct TracerRenderTextures(pub Handle<Image>, pub Handle<Image>);
|
|||||||
#[derive(Resource, Clone, ExtractResource, ShaderType, Default)]
|
#[derive(Resource, Clone, ExtractResource, ShaderType, Default)]
|
||||||
pub struct TracerUniforms {
|
pub struct TracerUniforms {
|
||||||
pub sky_color: LinearRgba,
|
pub sky_color: LinearRgba,
|
||||||
|
pub world_from_clip: Mat4,
|
||||||
|
pub world_position: Vec3,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TracerPipelinePlugin;
|
pub struct TracerPipelinePlugin;
|
||||||
@@ -43,6 +45,8 @@ impl Plugin for TracerPipelinePlugin {
|
|||||||
));
|
));
|
||||||
app.init_resource::<TracerUniforms>()
|
app.init_resource::<TracerUniforms>()
|
||||||
.add_systems(Update, switch_textures);
|
.add_systems(Update, switch_textures);
|
||||||
|
|
||||||
|
app.add_systems(First, update_tracer_uniforms);
|
||||||
let render_app = app.sub_app_mut(RenderApp);
|
let render_app = app.sub_app_mut(RenderApp);
|
||||||
|
|
||||||
// render_app.add_systems(Startup, init_pipeline);
|
// render_app.add_systems(Startup, init_pipeline);
|
||||||
@@ -86,7 +90,6 @@ impl FromWorld for TracerPipeline {
|
|||||||
texture_storage_2d(TextureFormat::Rgba32Float, StorageTextureAccess::ReadOnly),
|
texture_storage_2d(TextureFormat::Rgba32Float, StorageTextureAccess::ReadOnly),
|
||||||
texture_storage_2d(TextureFormat::Rgba32Float, StorageTextureAccess::WriteOnly),
|
texture_storage_2d(TextureFormat::Rgba32Float, StorageTextureAccess::WriteOnly),
|
||||||
uniform_buffer::<TracerUniforms>(false),
|
uniform_buffer::<TracerUniforms>(false),
|
||||||
uniform_buffer::<ViewUniform>(false),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -135,7 +138,6 @@ fn init_pipeline(
|
|||||||
texture_storage_2d(TextureFormat::Rgba32Float, StorageTextureAccess::ReadOnly),
|
texture_storage_2d(TextureFormat::Rgba32Float, StorageTextureAccess::ReadOnly),
|
||||||
texture_storage_2d(TextureFormat::Rgba32Float, StorageTextureAccess::WriteOnly),
|
texture_storage_2d(TextureFormat::Rgba32Float, StorageTextureAccess::WriteOnly),
|
||||||
uniform_buffer::<TracerUniforms>(false),
|
uniform_buffer::<TracerUniforms>(false),
|
||||||
uniform_buffer::<ViewUniform>(false),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -170,6 +172,24 @@ fn init_pipeline(
|
|||||||
#[derive(Resource)]
|
#[derive(Resource)]
|
||||||
pub struct TracerImageBindGroups(pub [BindGroup; 2]);
|
pub struct TracerImageBindGroups(pub [BindGroup; 2]);
|
||||||
|
|
||||||
|
fn update_tracer_uniforms(
|
||||||
|
mut tracer_uniforms: ResMut<TracerUniforms>,
|
||||||
|
rt_camera: Single<(&GlobalTransform, &Projection), With<RTCamera>>,
|
||||||
|
) {
|
||||||
|
let (transform, projection) = rt_camera.into_inner();
|
||||||
|
let view = transform.compute_matrix().inverse();
|
||||||
|
let clip_from_view = match projection {
|
||||||
|
Projection::Perspective(perspective_projection) => perspective_projection.get_clip_from_view(),
|
||||||
|
_ => unreachable!("This should never happen: Invalid projection type on RT Camera"),
|
||||||
|
};
|
||||||
|
let clip_from_world = clip_from_view * view;
|
||||||
|
let world_from_clip = clip_from_world.inverse();
|
||||||
|
info_once!("world_from_clip = {:?}", world_from_clip);
|
||||||
|
|
||||||
|
tracer_uniforms.world_from_clip = world_from_clip;
|
||||||
|
tracer_uniforms.world_position = transform.translation();
|
||||||
|
}
|
||||||
|
|
||||||
fn prepare_bind_groups(
|
fn prepare_bind_groups(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
pipeline: Res<TracerPipeline>,
|
pipeline: Res<TracerPipeline>,
|
||||||
@@ -178,13 +198,10 @@ fn prepare_bind_groups(
|
|||||||
tracer_uniforms: Res<TracerUniforms>,
|
tracer_uniforms: Res<TracerUniforms>,
|
||||||
render_device: Res<RenderDevice>,
|
render_device: Res<RenderDevice>,
|
||||||
queue: Res<RenderQueue>,
|
queue: Res<RenderQueue>,
|
||||||
view_uniforms: Res<ViewUniforms>,
|
|
||||||
) {
|
) {
|
||||||
let view_a = gpu_images.get(&tracer_images.0).unwrap();
|
let view_a = gpu_images.get(&tracer_images.0).unwrap();
|
||||||
let view_b = gpu_images.get(&tracer_images.1).unwrap();
|
let view_b = gpu_images.get(&tracer_images.1).unwrap();
|
||||||
|
|
||||||
//Todo: Insert View Uniforms
|
|
||||||
|
|
||||||
// Uniform buffer is used here to demonstrate how to set up a uniform in a compute shader
|
// Uniform buffer is used here to demonstrate how to set up a uniform in a compute shader
|
||||||
// Alternatives such as storage buffers or push constants may be more suitable for your use case
|
// Alternatives such as storage buffers or push constants may be more suitable for your use case
|
||||||
let mut uniform_buffer = UniformBuffer::from(tracer_uniforms.into_inner());
|
let mut uniform_buffer = UniformBuffer::from(tracer_uniforms.into_inner());
|
||||||
|
|||||||
Reference in New Issue
Block a user