211 lines
8.2 KiB
Rust
211 lines
8.2 KiB
Rust
extern crate mat4;
|
|
extern crate vec3;
|
|
extern crate vec4;
|
|
|
|
use crate::object::Object;
|
|
use crate::ray::Ray;
|
|
use crate::sphere::Sphere;
|
|
use sdl2::pixels::Color;
|
|
|
|
fn put_pixel(data: &mut [u8], x: usize, y: usize, color: Color) {
|
|
data[y * 3 * 800 + x * 3] = color.r;
|
|
data[y * 3 * 800 + x * 3 + 1] = color.g;
|
|
data[y * 3 * 800 + x * 3 + 2] = color.b;
|
|
}
|
|
|
|
pub fn render(data: &mut [u8], i: i32) {
|
|
let sphere = Sphere {};
|
|
let forward = *vec3::transform_mat4(
|
|
&mut vec3::new_zero(),
|
|
&vec3::new(0. as f64, 0. as f64, -1. as f64),
|
|
mat4::rotate(
|
|
&mut mat4::new_zero(),
|
|
&mat4::new_identity(),
|
|
&0.,
|
|
&(3.141592 / 4.),
|
|
&0.,
|
|
),
|
|
);
|
|
let view_matrix = *mat4::inv(
|
|
&mut mat4::new_zero(),
|
|
mat4::look_at(
|
|
&mut mat4::new_zero(),
|
|
&[100., 0., 100.],
|
|
&[100. + forward[0], 0. + forward[1], 100. + forward[2]],
|
|
&[0., 1., 0.],
|
|
),
|
|
);
|
|
// let view_matrix = *mat4::look_at(
|
|
// &mut mat4::new_zero(),
|
|
// &[0., 0., 10.],
|
|
// &[0., 0., 9.],
|
|
// &[0., 1., 0.],
|
|
// );
|
|
let scale = *mat4::scale(
|
|
&mut mat4::new_zero(),
|
|
&mat4::new_identity(),
|
|
&vec3::new(1. / 3., 1. / 3., 1. / 3.),
|
|
);
|
|
let translate = *mat4::translate(
|
|
&mut mat4::new_zero(),
|
|
&mat4::new_identity(),
|
|
&vec3::new(-i as f64, -i as f64, 0.),
|
|
);
|
|
let rotate = *mat4::transpose(
|
|
&mut mat4::new_zero(),
|
|
mat4::rotate(&mut mat4::new_zero(), &mat4::new_identity(), &0., &0., &0.),
|
|
);
|
|
let model_matrix_tmp = *mat4::mul(&mut mat4::new_zero(), &scale, &rotate);
|
|
let model_matrix1 = *mat4::mul(&mut mat4::new_zero(), &model_matrix_tmp, &translate);
|
|
let mut origin = [0., 0., 0.];
|
|
let test = origin;
|
|
vec3::transform_mat4(&mut origin, &test, &view_matrix);
|
|
let test = origin;
|
|
vec3::transform_mat4(&mut origin, &test, &model_matrix1);
|
|
let mut prelight = [-10., 10., 0.];
|
|
let test = prelight;
|
|
vec3::transform_mat4(&mut prelight, &test, &model_matrix1);
|
|
for x in 0..800 {
|
|
for y in 0..800 {
|
|
let pi_4: f64 = 3.141592 / 8.;
|
|
let dirx = (2. * ((x as f64 + 0.5) / 800.) - 1.) * pi_4.tan();
|
|
let diry = (1. - 2. * ((y as f64 + 0.5) / 800.)) * pi_4.tan();
|
|
let scalar = (dirx.powi(2) + diry.powi(2) + 1.).sqrt();
|
|
let mut ray = Ray {
|
|
origin: origin,
|
|
direction: [dirx / scalar, diry / scalar, -1. / scalar],
|
|
};
|
|
let test = ray.direction;
|
|
vec3::transform_mat4(&mut ray.direction, &test, &view_matrix);
|
|
let test = ray.direction;
|
|
vec3::transform_mat4(&mut ray.direction, &test, &model_matrix1);
|
|
ray.direction[0] = ray.direction[0] - ray.origin[0];
|
|
ray.direction[1] = ray.direction[1] - ray.origin[1];
|
|
ray.direction[2] = ray.direction[2] - ray.origin[2];
|
|
let scalar =
|
|
(ray.direction[0].powi(2) + ray.direction[1].powi(2) + ray.direction[2].powi(2))
|
|
.sqrt();
|
|
ray.direction = [
|
|
ray.direction[0] / scalar,
|
|
ray.direction[1] / scalar,
|
|
ray.direction[2] / scalar,
|
|
];
|
|
|
|
if x == 0 && y == 0 {
|
|
println!("{:?}", ray);
|
|
}
|
|
let ray2 = ray;
|
|
let mut distances = Vec::new();
|
|
distances.push(sphere.get_intersection(ray));
|
|
distances.push(None);
|
|
let a = (distances[0], distances[1]);
|
|
match a {
|
|
(Some(dist), None) => {
|
|
let n = [
|
|
ray.origin[0] + ray.direction[0] * dist,
|
|
ray.origin[1] + ray.direction[1] * dist,
|
|
ray.origin[2] + ray.direction[2] * dist,
|
|
];
|
|
let normal = sphere.get_normal(n);
|
|
let light = [prelight[0] - n[0], prelight[1] - n[1], prelight[2] - n[2]];
|
|
let scalar = (light[0].powi(2) + light[1].powi(2) + light[2].powi(2)).sqrt();
|
|
let light_d = [light[0] / scalar, light[1] / scalar, light[2] / scalar];
|
|
let mut diffuse =
|
|
normal[0] * light_d[0] + normal[1] * light_d[1] + normal[2] * light_d[2];
|
|
if diffuse < 0. {
|
|
diffuse = 0.;
|
|
}
|
|
put_pixel(
|
|
&mut *data,
|
|
x,
|
|
y,
|
|
Color {
|
|
r: (diffuse * 128. * 0.9 + 0.1 * 255.) as u8,
|
|
g: 0,
|
|
b: (diffuse * 255. * 0.9 + 0.1 * 255.) as u8,
|
|
a: 0,
|
|
},
|
|
);
|
|
}
|
|
|
|
(None, Some(dist)) => {
|
|
let n = [
|
|
ray2.origin[0] + ray2.direction[0] * dist,
|
|
ray2.origin[1] + ray2.direction[1] * dist,
|
|
ray2.origin[2] + ray2.direction[2] * dist,
|
|
];
|
|
let normal = sphere.get_normal(n);
|
|
let light = [n[0] - 10., n[1] - 10., n[2] + 10.];
|
|
let scalar = (light[0].powi(2) + light[1].powi(2) + light[2].powi(2)).sqrt();
|
|
let light_d = [light[0] / scalar, light[1] / scalar, light[2] / scalar];
|
|
let mut diffuse =
|
|
normal[0] * light_d[0] + normal[1] * light_d[1] + normal[2] * light_d[2];
|
|
if diffuse < 0. {
|
|
diffuse = 0.;
|
|
}
|
|
put_pixel(
|
|
&mut *data,
|
|
x,
|
|
y,
|
|
Color {
|
|
r: 0,
|
|
g: (diffuse * 255. * 0.9 + 0.1 * 255.) as u8,
|
|
b: (diffuse * 255. * 0.9 + 0.1 * 255.) as u8,
|
|
a: 0,
|
|
},
|
|
);
|
|
}
|
|
(Some(dist1), Some(dist2)) => {
|
|
let n;
|
|
if dist1 < dist2 {
|
|
n = [
|
|
ray.origin[0] + ray.direction[0] * dist1,
|
|
ray.origin[1] + ray.direction[1] * dist1,
|
|
ray.origin[2] + ray.direction[2] * dist1,
|
|
];
|
|
} else {
|
|
n = [
|
|
ray2.origin[0] + ray2.direction[0] * dist2,
|
|
ray2.origin[1] + ray2.direction[1] * dist2,
|
|
ray2.origin[2] + ray2.direction[2] * dist2,
|
|
];
|
|
}
|
|
let normal = sphere.get_normal(n);
|
|
let light = [n[0] - 10., n[1] - 10., n[2] + 10.];
|
|
let scalar = (light[0].powi(2) + light[1].powi(2) + light[2].powi(2)).sqrt();
|
|
let light_d = [light[0] / scalar, light[1] / scalar, light[2] / scalar];
|
|
let mut diffuse =
|
|
normal[0] * light_d[0] + normal[1] * light_d[1] + normal[2] * light_d[2];
|
|
if diffuse < 0. {
|
|
diffuse = 0.;
|
|
}
|
|
put_pixel(
|
|
&mut *data,
|
|
x,
|
|
y,
|
|
Color {
|
|
r: 0,
|
|
g: (diffuse * 255. * 0.9 + 0.1 * 255.) as u8,
|
|
b: (diffuse * 255. * 0.9 + 0.1 * 255.) as u8,
|
|
a: 0,
|
|
},
|
|
);
|
|
}
|
|
(None, None) => {
|
|
put_pixel(
|
|
&mut *data,
|
|
x,
|
|
y,
|
|
Color {
|
|
r: 0,
|
|
g: 0,
|
|
b: 0,
|
|
a: 0,
|
|
},
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|