Create correct primary rays
This commit is contained in:
parent
8f74621937
commit
5db23fca50
5 changed files with 168 additions and 5 deletions
3
.vscode/settings.json
vendored
Normal file
3
.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"rust-analyzer.enableCargoWatchOnStartup": true
|
||||
}
|
BIN
raytrace.png
BIN
raytrace.png
Binary file not shown.
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 5.1 KiB |
63
src/camera.rs
Normal file
63
src/camera.rs
Normal file
|
@ -0,0 +1,63 @@
|
|||
use cgmath::{InnerSpace, Vector3};
|
||||
|
||||
use super::ray::Ray;
|
||||
|
||||
pub struct Camera {
|
||||
position: Vector3<f32>,
|
||||
direction: Vector3<f32>,
|
||||
up: Vector3<f32>,
|
||||
right: Vector3<f32>,
|
||||
|
||||
_fov: f32,
|
||||
tan: f32,
|
||||
aspect_ratio: f32,
|
||||
}
|
||||
|
||||
impl Camera {
|
||||
pub fn new(
|
||||
eye: Vector3<f32>,
|
||||
center: Vector3<f32>,
|
||||
up: Vector3<f32>,
|
||||
fov: f32,
|
||||
aspect_ratio: f32,
|
||||
) -> Camera {
|
||||
let mut up = up.normalize();
|
||||
|
||||
let view = (center - eye).normalize();
|
||||
|
||||
let right = view.cross(up).normalize();
|
||||
|
||||
up = right.cross(view);
|
||||
|
||||
let fovy = fov.to_radians() / 2.0;
|
||||
|
||||
Camera {
|
||||
position: eye,
|
||||
direction: view,
|
||||
up,
|
||||
right,
|
||||
|
||||
_fov: fovy,
|
||||
tan: fovy.tan(),
|
||||
aspect_ratio,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn primary_ray(&self, x: u32, y: u32, dim_x: u32, dim_y: u32) -> Ray {
|
||||
let x_scaled = Self::scale(x, dim_x);
|
||||
let y_scaled = Self::scale(y, dim_y);
|
||||
|
||||
let mut dir = self.direction;
|
||||
|
||||
dir += self.right * self.tan * self.aspect_ratio * x_scaled;
|
||||
dir += self.up * self.tan * y_scaled;
|
||||
|
||||
dir = dir.normalize();
|
||||
|
||||
Ray::new(self.position, dir)
|
||||
}
|
||||
|
||||
fn scale(v: u32, s: u32) -> f32 {
|
||||
((v as f32 + 0.5) / s as f32) * 2.0 - 1.0
|
||||
}
|
||||
}
|
34
src/main.rs
34
src/main.rs
|
@ -17,6 +17,9 @@ use ray::Ray;
|
|||
mod view;
|
||||
use view::View;
|
||||
|
||||
mod camera;
|
||||
use camera::Camera;
|
||||
|
||||
fn main() {
|
||||
let input_data = [
|
||||
Triangle::new(
|
||||
|
@ -48,9 +51,18 @@ fn main() {
|
|||
fov: 45.0,
|
||||
};
|
||||
|
||||
let debug_ray = Ray::primary_ray(640.0, 360.0, 1280.0, 720.0, &view);
|
||||
let camera = Camera::new(
|
||||
vec3(0.0, -4.0, 4.0),
|
||||
vec3(0.0, 0.0, 0.0),
|
||||
vec3(0.0, 0.0, 1.0),
|
||||
45.0,
|
||||
1280.0 / 720.0,
|
||||
);
|
||||
|
||||
debug_raytracer(1280, 720, &view, &input_data);
|
||||
let _debug_ray = camera.primary_ray(640, 360, 1280, 720);
|
||||
|
||||
//debug_raytracer_view(1280, 720, &view, &input_data);
|
||||
debug_raytracer_camera(1280, 720, &camera, &input_data);
|
||||
}
|
||||
|
||||
fn f_to_u(color: f32) -> u8 {
|
||||
|
@ -111,7 +123,23 @@ fn look_at_test(eye: Vector3<f32>, center: Vector3<f32>, up: Vector3<f32>) -> Ma
|
|||
}
|
||||
*/
|
||||
|
||||
fn debug_raytracer(dim_x: u32, dim_y: u32, view: &View, data: &[Triangle]) {
|
||||
fn debug_raytracer_camera(dim_x: u32, dim_y: u32, camera: &Camera, data: &[Triangle]) {
|
||||
let mut imgbuf = ImageBuffer::new(dim_x, dim_y);
|
||||
|
||||
let acceleration_data = create_acceleration_data(data);
|
||||
|
||||
for (x, y, pixel) in imgbuf.enumerate_pixels_mut() {
|
||||
let ray = camera.primary_ray(x, y, dim_x, dim_y);
|
||||
|
||||
let color = pixel_color(&ray, data, &acceleration_data);
|
||||
|
||||
*pixel = image::Rgb([f_to_u(color.x), f_to_u(color.y), f_to_u(color.z)]);
|
||||
}
|
||||
|
||||
imgbuf.save("raytrace.png").unwrap();
|
||||
}
|
||||
|
||||
fn debug_raytracer_view(dim_x: u32, dim_y: u32, view: &View, data: &[Triangle]) {
|
||||
let mut imgbuf = ImageBuffer::new(dim_x, dim_y);
|
||||
|
||||
let acceleration_data = create_acceleration_data(data);
|
||||
|
|
73
src/ray.rs
73
src/ray.rs
|
@ -1,7 +1,11 @@
|
|||
use cgmath::{vec2, vec3, InnerSpace, Vector3};
|
||||
use cgmath::{
|
||||
vec2, vec3, vec4, EuclideanSpace, InnerSpace, Matrix4, Point3, SquareMatrix, Vector2, Vector3,
|
||||
};
|
||||
|
||||
use super::view::View;
|
||||
|
||||
use std::f32::consts::PI as M_PI;
|
||||
|
||||
pub struct Ray {
|
||||
pub origin: Vector3<f32>,
|
||||
pub direction: Vector3<f32>,
|
||||
|
@ -26,6 +30,7 @@ impl Ray {
|
|||
}
|
||||
|
||||
pub fn primary_ray(x: f32, y: f32, dim_x: f32, dim_y: f32, view: &View) -> Ray {
|
||||
/*
|
||||
let aspect_ratio = dim_x / dim_y;
|
||||
|
||||
let uv = vec2((x + 0.5) / dim_x, (y + 0.5) / dim_y);
|
||||
|
@ -41,7 +46,71 @@ impl Ray {
|
|||
raw_dir.z * aspect_ratio,
|
||||
)
|
||||
.normalize();
|
||||
*/
|
||||
|
||||
return Self::new(view.position, dir);
|
||||
let aspect_ratio = dim_x / dim_y;
|
||||
let fov = view.fov / M_PI * 2.0 / 180.0;
|
||||
|
||||
let p_x = (1.0 - 2.0 * ((x as f32 + 0.5) / dim_x as f32)) * fov * aspect_ratio;
|
||||
let p_y = (2.0 * (((y) as f32 + 0.5) / dim_y as f32) - 1.0) * fov;
|
||||
|
||||
return Self::cast_ray(vec2(p_x, p_y), view);
|
||||
}
|
||||
|
||||
pub fn cast_ray(uv: Vector2<f32>, view: &View) -> Ray {
|
||||
let look_at = Matrix4::look_at(
|
||||
Point3::from_vec(view.position),
|
||||
Point3::from_vec(view.look_at),
|
||||
vec3(0.0, 0.0, 1.0),
|
||||
);
|
||||
|
||||
let camera_to_world = look_at.invert().unwrap();
|
||||
|
||||
let origin = camera_to_world * vec4(0.0, 0.0, 0.0, 1.0);
|
||||
let direction = camera_to_world * vec4(uv.x, uv.y, -1.0, 1.0);
|
||||
|
||||
Ray::new(origin.truncate(), -direction.truncate().normalize())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn perspective(fov_y: f32, aspect: f32, z_near: f32, z_far: f32) -> cgmath::Matrix4<f32> {
|
||||
let zero = 0.0;
|
||||
let one = 1.0;
|
||||
let two = 2.0;
|
||||
let q = one / (fov_y / two).tan();
|
||||
let a = q / aspect;
|
||||
let b = (z_near + z_far) / (z_near - z_far);
|
||||
let c = (two * z_near * z_far) / (z_near - z_far);
|
||||
|
||||
cgmath::Matrix4::new(
|
||||
a,
|
||||
zero,
|
||||
zero,
|
||||
zero,
|
||||
zero,
|
||||
-q,
|
||||
zero,
|
||||
zero,
|
||||
zero,
|
||||
zero,
|
||||
b,
|
||||
zero - one,
|
||||
zero,
|
||||
zero,
|
||||
c,
|
||||
zero,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn text_ray_casting() {
|
||||
let center = vec3(0.0, 0.0, 0.0);
|
||||
|
||||
let view = View {
|
||||
position: vec3(0.0, -4.0, 4.0),
|
||||
look_at: center,
|
||||
up: vec3(0.0, 0.0, 1.0),
|
||||
fov: 45.0,
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue