203 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			Rust
		
	
	
	
			
		
		
	
	
			203 lines
		
	
	
		
			7.8 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 view_matrix = *mat4::inv(
 | |
|         &mut mat4::new_zero(),
 | |
|         mat4::look_at(
 | |
|             &mut mat4::new_zero(),
 | |
|             &[0., 0., 20.],
 | |
|             &[0., 0., 19.],
 | |
|             &[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. / 1., 1. / 3., 1. / 1.),
 | |
|     );
 | |
|     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(),
 | |
|             &(3.141592 / 4.),
 | |
|             &0.,
 | |
|             &(3.141592 / 4.),
 | |
|         ),
 | |
|     );
 | |
|     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);
 | |
|     for x in 0..800 {
 | |
|         for y in 0..800 {
 | |
|             let pi_4: f64 = 3.141592 / 3.;
 | |
|             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: [0., 0., 0.],
 | |
|                 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);
 | |
|             let test = ray.origin;
 | |
|             vec3::transform_mat4(&mut ray.origin, &test, &view_matrix);
 | |
|             let test = ray.origin;
 | |
|             vec3::transform_mat4(&mut ray.origin, &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 = [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: (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,
 | |
|                         },
 | |
|                     );
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 |