diff --git a/src/main.rs b/src/main.rs index f8df5a0..d8968c9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,6 @@ +#![feature(lang_items)] +#![feature(doc_alias)] + extern crate rand; use std::cmp::max; @@ -11,6 +14,10 @@ use image::ImageFormat; use image::io::Reader as ImageReader; use rand::prelude::*; +mod util; + +use crate::util::*; + struct Circle { x: i32, y: i32, @@ -27,20 +34,6 @@ fn createCircle() -> Circle { } } -#[derive(Clone, Copy, Debug, Default)] -struct Vector2f { x: f32, y: f32 } - -#[derive(Clone, Copy, Debug, Default)] -struct Vector2i { x: i32, y: i32 } - -#[derive(Clone, Copy, Debug, Default)] -struct Vector3f { x: f32, y: f32, z: f32 } - -#[derive(Clone, Copy, Debug, Default)] -struct Vector4f { x: f32, y: f32, z: f32, w: f32 } - - - fn saturate(v: f32) -> f32 { f32::min(f32::max(v, 0.0), 1.0) } @@ -50,6 +43,14 @@ fn dot(vec_a: Vector3f, vec_b: Vector3f) -> f32 { vec_a.x * vec_b.x + vec_a.y * vec_b.y + vec_a.z * vec_b.z } +fn clamp(vec: Vector3f, lower: f32, upper: f32) -> Vector3f { + Vector3f { + x: f32::min(f32::max(vec.x, lower), upper), + y: f32::min(f32::max(vec.y, lower), upper), + z: f32::min(f32::max(vec.z, lower), upper), + } +} + fn mult(vec: Vector3f, scalar: f32) -> Vector3f { Vector3f { x: vec.x * scalar, @@ -92,7 +93,10 @@ fn pow(vec: Vector3f, scalar: f32) -> Vector3f { fn mix(a: Vector3f, b: Vector3f, mixValue: f32) -> Vector3f { - add(mult(a, (1.0 - mixValue)), mult(b, mixValue)) + add( + mult(a, (1.0 - mixValue)), + mult(b, mixValue) + ) } fn len(vec: Vector3f) -> f32 { @@ -171,41 +175,41 @@ struct Lighting struct PointLight { position : Vector3f, - diffuseColor : Vector3f, - diffusePower : f32, - specularColor : Vector3f, - specularPower : f32, + diffuse_color: Vector3f, + diffuse_power: f32, + specular_color: Vector3f, + specular_power: f32, } // returns the diffuse and specular -fn get_point_light(light: PointLight, pos3D: Vector3f, viewDir: Vector3f, normal: Vector3f) -> Lighting +fn get_point_light(light: PointLight, pos3d: Vector3f, view_dir: Vector3f, normal: Vector3f) -> Lighting { let mut out = Lighting::default(); - if (light.diffusePower > 0.0) + if (light.diffuse_power > 0.0) { - let lightDir = sub(light.position, pos3D); //3D position in space of the surface - out.distance = len(lightDir); - let lightDir = div(lightDir, out.distance); // = normalize(lightDir); + let light_dir = sub(light.position, pos3d); //3D position in space of the surface + out.distance = len(light_dir); + let light_dir = div(light_dir, out.distance); // = normalize(light_dir); let distance = out.distance * out.distance; //This line may be optimised using Inverse square root //Intensity of the diffuse light. Saturate to keep within the 0-1 range. - let NdotL = dot(normal, lightDir); - let intensity = saturate(NdotL); + let ndot_l = dot(normal, light_dir); + let intensity = saturate(ndot_l); // Calculate the diffuse light factoring in light color, power and the attenuation - out.diffuse = div(mult(mult(light.diffuseColor, intensity), light.diffusePower), distance); + out.diffuse = div(mult(mult(light.diffuse_color, intensity), light.diffuse_power), distance); //Calculate the half vector between the light vector and the view vector. // This is typically slower than calculating the actual reflection vector // due to the normalize function's reciprocal square root - let H = normalize(add(lightDir, viewDir)); + let H = normalize(add(light_dir, view_dir)); //Intensity of the specular light - let NdotH = dot(normal, H); - let intensity = f32::powf(saturate(NdotH), 1.0); + let ndot_h = dot(normal, H); + let intensity = f32::powf(saturate(ndot_h), 1.0); //Sum up the specular light factoring - out.specular = div(mult(mult(light.specularColor, intensity), light.specularPower), distance); + out.specular = div(mult(mult(light.specular_color, intensity), light.specular_power), distance); } out } @@ -295,24 +299,25 @@ fn main() { z: -dir.z, }; + let x = ndir * 1.0; + let light = PointLight { - position : Vector3f{x:0.0,y:0.0,z:0.0}, - diffuseColor : Vector3f{x:255.0,y:255.0,z:255.0}, - diffusePower : 100.0, - specularColor : Vector3f{x:255.0,y:255.0,z:255.0}, - specularPower : 70.0, + position : Vector3f{x:-13.0,y:0.0,z:0.0}, + diffuse_color: Vector3f{x:255.0,y:255.0,z:255.0}, + diffuse_power: 10.0, + specular_color: Vector3f{x:255.0,y:255.0,z:255.0}, + specular_power: 100.0, }; - let red = Vector3f {x:255.0, y:0.0, z:0.0}; - let color2 = Vector3f {x:200.0, y:90.0, z:120.0}; - - let lighting = get_point_light(light, add(phit, sphere_center), dir, nhit); + let lighting = get_point_light(light, phit + sphere_center, dir, nhit); - let mut hit_color = add(lighting.diffuse, lighting.specular); + let hit_color = clamp( + sphere_color + (lighting.diffuse * light.diffuse_color + lighting.specular * light.specular_color), + 0.0, 255.0); - println!("{:?}", hit_color); - println!("{:?}", add(nhit, sphere_center)); -// println!("{:?}", lighting); + // println!("hit_color : {:?}", hit_color); + //println!("{:?}", add(nhit, sphere_center)); + // println!("lighting : {:?}", lighting); *pixel = image::Rgb([hit_color.x as u8, hit_color.y as u8, hit_color.z as u8]); } }; diff --git a/src/util.rs b/src/util.rs new file mode 100644 index 0000000..ff5082c --- /dev/null +++ b/src/util.rs @@ -0,0 +1,253 @@ +use std::ops::{Add, Div, Mul, Neg, Sub}; + +pub trait Dot { + /// The resulting type after applying the `*` operator. + type Output; + + /// Performs the `*` operation. + #[must_use] + fn dot(self, rhs: Rhs) -> Self::Output; +} + +#[derive(Clone, Copy, Debug, Default, PartialEq)] +pub struct Vector2f { pub x: f32, pub y: f32 } + +impl Add for Vector2f { + type Output = Self; + + fn add(self, other: Self) -> Self { + Self { + x: self.x + other.x, + y: self.y + other.y, + } + } +} + +impl Mul for Vector2f { + type Output = Self; + + fn mul(self, other: Self) -> Self { + Self { + x: self.x * other.x, + y: self.y * other.y, + } + } +} + +impl Mul for Vector2f { + type Output = Self; + + fn mul(self, rhs: f32) -> Self::Output { + Vector2f { + x: self.x * rhs, + y: self.y * rhs, + } + } +} + +impl Dot for Vector2f { + type Output = f32; + + fn dot(self, other: Self) -> f32 { + self.x * other.x + self.y * other.y + } +} + +impl Sub for Vector2f { + type Output = Self; + + fn sub(self, other: Self) -> Self { + Self { + x: self.x - other.x, + y: self.y - other.y, + } + } +} + +impl Div for Vector2f { + type Output = Self; + + fn div(self, other: Self) -> Self { + Self { + x: self.x / other.x, + y: self.y / other.y, + } + } +} + +impl Neg for Vector2f { + type Output = Self; + + fn neg(self) -> Self { + Self { + x: -self.x, + y: -self.y, + } + } +} + +#[derive(Clone, Copy, Debug, Default, PartialEq)] +pub struct Vector2i { pub x: i32, pub y: i32 } + +impl Add for Vector2i { + type Output = Self; + + fn add(self, other: Self) -> Self { + Self { + x: self.x + other.x, + y: self.y + other.y, + } + } +} + +impl Mul for Vector2i { + type Output = Self; + + fn mul(self, other: Self) -> Self { + Self { + x: self.x * other.x, + y: self.y * other.y, + } + } +} + +impl Mul for Vector2i { + type Output = Self; + + fn mul(self, rhs: i32) -> Self::Output { + Vector2i { + x: self.x * rhs, + y: self.y * rhs, + } + } +} + +impl Dot for Vector2i { + type Output = i32; + + fn dot(self, other: Self) -> i32 { + self.x * other.x + self.y * other.y + } +} + +impl Sub for Vector2i { + type Output = Self; + + fn sub(self, other: Self) -> Self { + Self { + x: self.x - other.x, + y: self.y - other.y, + } + } +} + +impl Div for Vector2i { + type Output = Self; + + fn div(self, other: Self) -> Self { + Self { + x: self.x / other.x, + y: self.y / other.y, + } + } +} + +impl Neg for Vector2i { + type Output = Self; + + fn neg(self) -> Self { + Self { + x: -self.x, + y: -self.y, + } + } +} + + +#[derive(Clone, Copy, Debug, Default, PartialEq)] +pub struct Vector3f { pub x: f32, pub y: f32, pub z: f32 } + +impl Add for Vector3f { + type Output = Self; + + fn add(self, other: Self) -> Self { + Self { + x: self.x + other.x, + y: self.y + other.y, + z: self.z + other.z, + } + } +} + +impl Mul for Vector3f { + type Output = Self; + + fn mul(self, other: Self) -> Self { + Self { + x: self.x * other.x, + y: self.y * other.y, + z: self.z * other.z, + } + } +} + +impl Mul for Vector3f { + type Output = Self; + + fn mul(self, other: f32) -> Self { + Self { + x: self.x * other, + y: self.y * other, + z: self.z * other, + } + } +} + +impl Dot for Vector3f { + type Output = f32; + + fn dot(self, other: Self) -> f32 { + self.x * other.x + self.y * other.y + self.z * other.z + } +} + +impl Sub for Vector3f { + type Output = Self; + + fn sub(self, other: Self) -> Self { + Self { + x: self.x - other.x, + y: self.y - other.y, + z: self.z - other.z, + } + } +} + +impl Div for Vector3f { + type Output = Self; + + fn div(self, other: Self) -> Self { + Self { + x: self.x / other.x, + y: self.y / other.y, + z: self.z / other.z, + } + } +} + +impl Neg for Vector3f { + type Output = Self; + + fn neg(self) -> Self { + Self { + x: -self.x, + y: -self.y, + z: -self.z, + } + } +} + + +#[derive(Clone, Copy, Debug, Default, PartialEq)] +pub struct Vector4f { pub x: f32, pub y: f32, pub z: f32, pub w: f32 } + diff --git a/src/voxel-stuff b/src/voxel-stuff index f363737..e69de29 100644 --- a/src/voxel-stuff +++ b/src/voxel-stuff @@ -1,71 +0,0 @@ -bool CLCaster::create_viewport(int width, int height, float v_fov, float h_fov) { - - - - sf::Vector2i view_res(width, height); - - This creates a buffer to give the kernal a [x,y] coord set - if (!create_buffer("viewport_resolution", sizeof(int) * 2, &view_res)) - return false; - - - // And an array of vectors describing the way the "lens" of our - // camera works - viewport_matrix = new sf::Vector4f[width * height * 4]; - - for (int y = -view_res.y / 2; y < view_res.y / 2; y++) { - - for (int x = -view_res.x / 2; x < view_res.x / 2; x++) { - - // The base ray direction to slew from - sf::Vector3f ray(-800, x, y); - - // correct for the base ray pointing to (1, 0, 0) as (0, 0). Should equal (1.57, 0) - ray = sf::Vector3f( - static_cast(ray.z * sin(1.57) + ray.x * cos(1.57)), - static_cast(ray.y), - static_cast(ray.z * cos(1.57) - ray.x * sin(1.57)) - ); - -// ray.y += (rand() % 1000) / 100000.0; -// ray.x += (rand() % 1000) / 100000.0; -// ray.z += (rand() % 1000) / 100000.0; - - ray = Normalize(ray); - int index = (x + view_res.x / 2) + view_res.x * (y + view_res.y / 2); - - viewport_matrix[index] = sf::Vector4f( - ray.x, - ray.y, - ray.z, - 0 - ); - } - } - - if (!create_buffer("viewport_matrix", sizeof(float) * 4 * view_res.x * view_res.y, viewport_matrix)) - return false; - - // Create the image that opencl's rays write to - viewport_image = new sf::Uint8[width * height * 4]; - - for (int i = 0; i < width * height * 4; i += 4) { - - viewport_image[i] = 255; // R - viewport_image[i + 1] = 255; // G - viewport_image[i + 2] = 255; // B - viewport_image[i + 3] = 100; // A - } - - // Interop lets us keep a reference to it as a texture - viewport_texture.create(width, height); - viewport_texture.update(viewport_image); - viewport_sprite.setTexture(viewport_texture); - - // Pass the buffer to opencl - if (!create_image_buffer("image", sizeof(sf::Uint8) * width * height * 4, &viewport_texture, CL_MEM_WRITE_ONLY)) - return false; - - return true; - -}