better vector handling
This commit is contained in:
93
src/main.rs
93
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, phit + sphere_center, dir, nhit);
|
||||
|
||||
let lighting = get_point_light(light, add(phit, sphere_center), dir, nhit);
|
||||
let hit_color = clamp(
|
||||
sphere_color + (lighting.diffuse * light.diffuse_color + lighting.specular * light.specular_color),
|
||||
0.0, 255.0);
|
||||
|
||||
let mut hit_color = add(lighting.diffuse, lighting.specular);
|
||||
|
||||
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]);
|
||||
}
|
||||
};
|
||||
|
||||
253
src/util.rs
Normal file
253
src/util.rs
Normal file
@@ -0,0 +1,253 @@
|
||||
use std::ops::{Add, Div, Mul, Neg, Sub};
|
||||
|
||||
pub trait Dot<Rhs = Self> {
|
||||
/// 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<f32> 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<i32> 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<f32> 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 }
|
||||
|
||||
@@ -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<float>(ray.z * sin(1.57) + ray.x * cos(1.57)),
|
||||
static_cast<float>(ray.y),
|
||||
static_cast<float>(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;
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user