camera projection wip
This commit is contained in:
@@ -5,7 +5,6 @@
|
||||
|
||||
@group(0) @binding(2) var<uniform> config: TracerUniforms;
|
||||
|
||||
@group(0) @binding(3) var<uniform> view: ViewUniform;
|
||||
|
||||
struct View {
|
||||
view_proj: mat4x4<f32>,
|
||||
@@ -16,25 +15,10 @@ struct View {
|
||||
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 {
|
||||
sky_color: vec4<f32>,
|
||||
world_from_clip: mat4x4<f32>,
|
||||
world_position: vec3<f32>,
|
||||
}
|
||||
|
||||
@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 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);
|
||||
result += ray.energy * shade(&ray, hit);
|
||||
// var hit = trace(ray);
|
||||
// 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));
|
||||
|
||||
textureStore(output, location, color);
|
||||
}
|
||||
|
||||
@@ -113,19 +113,34 @@ fn createRay(origin: vec3<f32>, direction: vec3<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 direction = (view.inv_view * vec4<f32>(direction_view, 0.0)).xyz;
|
||||
|
||||
let origin = view.world_position;
|
||||
let target_point = view.world_from_clip * vec4<f32>(ndc, 0.0f, 1.0f);
|
||||
let origin = config.world_position;
|
||||
let target_point = config.world_from_clip * vec4<f32>(ndc, 0.0f, 1.0f);
|
||||
let direction_point = target_point.xyz / target_point.w;
|
||||
let direction = normalize(direction_point - origin);
|
||||
|
||||
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
|
||||
{
|
||||
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)
|
||||
{
|
||||
//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 p1 = -dot(ray.direction, d);
|
||||
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
|
||||
{
|
||||
(*ray).energy = vec3(0.0f);
|
||||
return vec3<f32>(0.1f);
|
||||
return config.sky_color.xyz;
|
||||
// var theta = acos(ray.direction.y) / -PI;
|
||||
// var phi = atan2(ray.direction.x, -ray.direction.z) / -PI * .5f;
|
||||
// return _SkyboxTexture.SampleLevel(sampler_SkyboxTexture, float2(phi, theta), 0).xyz;
|
||||
|
||||
23
src/app.rs
23
src/app.rs
@@ -1,12 +1,19 @@
|
||||
use bevy::{
|
||||
asset::RenderAssetUsages,
|
||||
math::VectorSpace,
|
||||
prelude::*,
|
||||
render::render_resource::{Extent3d, TextureDimension, TextureFormat, TextureUsages},
|
||||
render::{
|
||||
render_resource::{Extent3d, TextureDimension, TextureFormat, TextureUsages},
|
||||
view::RenderLayers,
|
||||
},
|
||||
window::PrimaryWindow,
|
||||
};
|
||||
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;
|
||||
|
||||
@@ -18,6 +25,7 @@ impl Plugin for Blackhole {
|
||||
app.add_plugins(TracerPipelinePlugin);
|
||||
app.insert_resource(TracerUniforms {
|
||||
sky_color: LinearRgba::BLUE,
|
||||
..default()
|
||||
});
|
||||
|
||||
//Perf UI
|
||||
@@ -74,5 +82,16 @@ fn setup(mut commands: Commands, mut images: ResMut<Assets<Image>>, window: Sing
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
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};
|
||||
|
||||
mod app;
|
||||
pub mod components;
|
||||
mod render;
|
||||
|
||||
pub const SHADER_ASSET_PATH: &str = "trace.wgsl";
|
||||
|
||||
@@ -4,6 +4,7 @@ use bevy::{
|
||||
prelude::*,
|
||||
render::{
|
||||
Render, RenderApp, RenderSet,
|
||||
camera::CameraProjection,
|
||||
extract_resource::{ExtractResource, ExtractResourcePlugin},
|
||||
render_asset::RenderAssets,
|
||||
render_graph::{RenderGraph, RenderLabel},
|
||||
@@ -15,11 +16,10 @@ use bevy::{
|
||||
},
|
||||
renderer::{RenderDevice, RenderQueue},
|
||||
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)]
|
||||
pub struct TracerLabel;
|
||||
@@ -31,6 +31,8 @@ pub struct TracerRenderTextures(pub Handle<Image>, pub Handle<Image>);
|
||||
#[derive(Resource, Clone, ExtractResource, ShaderType, Default)]
|
||||
pub struct TracerUniforms {
|
||||
pub sky_color: LinearRgba,
|
||||
pub world_from_clip: Mat4,
|
||||
pub world_position: Vec3,
|
||||
}
|
||||
|
||||
pub struct TracerPipelinePlugin;
|
||||
@@ -43,6 +45,8 @@ impl Plugin for TracerPipelinePlugin {
|
||||
));
|
||||
app.init_resource::<TracerUniforms>()
|
||||
.add_systems(Update, switch_textures);
|
||||
|
||||
app.add_systems(First, update_tracer_uniforms);
|
||||
let render_app = app.sub_app_mut(RenderApp);
|
||||
|
||||
// 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::WriteOnly),
|
||||
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::WriteOnly),
|
||||
uniform_buffer::<TracerUniforms>(false),
|
||||
uniform_buffer::<ViewUniform>(false),
|
||||
),
|
||||
),
|
||||
);
|
||||
@@ -170,6 +172,24 @@ fn init_pipeline(
|
||||
#[derive(Resource)]
|
||||
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(
|
||||
mut commands: Commands,
|
||||
pipeline: Res<TracerPipeline>,
|
||||
@@ -178,13 +198,10 @@ fn prepare_bind_groups(
|
||||
tracer_uniforms: Res<TracerUniforms>,
|
||||
render_device: Res<RenderDevice>,
|
||||
queue: Res<RenderQueue>,
|
||||
view_uniforms: Res<ViewUniforms>,
|
||||
) {
|
||||
let view_a = gpu_images.get(&tracer_images.0).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
|
||||
// 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());
|
||||
|
||||
Reference in New Issue
Block a user