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;
|
extern crate rand;
|
||||||
|
|
||||||
use std::cmp::max;
|
use std::cmp::max;
|
||||||
@@ -11,6 +14,10 @@ use image::ImageFormat;
|
|||||||
use image::io::Reader as ImageReader;
|
use image::io::Reader as ImageReader;
|
||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
|
|
||||||
|
mod util;
|
||||||
|
|
||||||
|
use crate::util::*;
|
||||||
|
|
||||||
struct Circle {
|
struct Circle {
|
||||||
x: i32,
|
x: i32,
|
||||||
y: 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 {
|
fn saturate(v: f32) -> f32 {
|
||||||
f32::min(f32::max(v, 0.0), 1.0)
|
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
|
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 {
|
fn mult(vec: Vector3f, scalar: f32) -> Vector3f {
|
||||||
Vector3f {
|
Vector3f {
|
||||||
x: vec.x * scalar,
|
x: vec.x * scalar,
|
||||||
@@ -92,7 +93,10 @@ fn pow(vec: Vector3f, scalar: f32) -> Vector3f {
|
|||||||
|
|
||||||
fn mix(a: Vector3f, b: Vector3f, mixValue: 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 {
|
fn len(vec: Vector3f) -> f32 {
|
||||||
@@ -171,41 +175,41 @@ struct Lighting
|
|||||||
struct PointLight
|
struct PointLight
|
||||||
{
|
{
|
||||||
position : Vector3f,
|
position : Vector3f,
|
||||||
diffuseColor : Vector3f,
|
diffuse_color: Vector3f,
|
||||||
diffusePower : f32,
|
diffuse_power: f32,
|
||||||
specularColor : Vector3f,
|
specular_color: Vector3f,
|
||||||
specularPower : f32,
|
specular_power: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns the diffuse and specular
|
// 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();
|
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
|
let light_dir = sub(light.position, pos3d); //3D position in space of the surface
|
||||||
out.distance = len(lightDir);
|
out.distance = len(light_dir);
|
||||||
let lightDir = div(lightDir, out.distance); // = normalize(lightDir);
|
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
|
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.
|
//Intensity of the diffuse light. Saturate to keep within the 0-1 range.
|
||||||
let NdotL = dot(normal, lightDir);
|
let ndot_l = dot(normal, light_dir);
|
||||||
let intensity = saturate(NdotL);
|
let intensity = saturate(ndot_l);
|
||||||
|
|
||||||
// Calculate the diffuse light factoring in light color, power and the attenuation
|
// 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.
|
//Calculate the half vector between the light vector and the view vector.
|
||||||
// This is typically slower than calculating the actual reflection vector
|
// This is typically slower than calculating the actual reflection vector
|
||||||
// due to the normalize function's reciprocal square root
|
// 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
|
//Intensity of the specular light
|
||||||
let NdotH = dot(normal, H);
|
let ndot_h = dot(normal, H);
|
||||||
let intensity = f32::powf(saturate(NdotH), 1.0);
|
let intensity = f32::powf(saturate(ndot_h), 1.0);
|
||||||
|
|
||||||
//Sum up the specular light factoring
|
//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
|
out
|
||||||
}
|
}
|
||||||
@@ -295,24 +299,25 @@ fn main() {
|
|||||||
z: -dir.z,
|
z: -dir.z,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let x = ndir * 1.0;
|
||||||
|
|
||||||
let light = PointLight {
|
let light = PointLight {
|
||||||
position : Vector3f{x:0.0,y:0.0,z:0.0},
|
position : Vector3f{x:-13.0,y:0.0,z:0.0},
|
||||||
diffuseColor : Vector3f{x:255.0,y:255.0,z:255.0},
|
diffuse_color: Vector3f{x:255.0,y:255.0,z:255.0},
|
||||||
diffusePower : 100.0,
|
diffuse_power: 10.0,
|
||||||
specularColor : Vector3f{x:255.0,y:255.0,z:255.0},
|
specular_color: Vector3f{x:255.0,y:255.0,z:255.0},
|
||||||
specularPower : 70.0,
|
specular_power: 100.0,
|
||||||
};
|
};
|
||||||
|
|
||||||
let red = Vector3f {x:255.0, y:0.0, z:0.0};
|
let lighting = get_point_light(light, phit + sphere_center, dir, nhit);
|
||||||
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 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 : {:?}", hit_color);
|
||||||
|
//println!("{:?}", add(nhit, sphere_center));
|
||||||
println!("{:?}", hit_color);
|
// println!("lighting : {:?}", lighting);
|
||||||
println!("{:?}", add(nhit, sphere_center));
|
|
||||||
// println!("{:?}", lighting);
|
|
||||||
*pixel = image::Rgb([hit_color.x as u8, hit_color.y as u8, hit_color.z as u8]);
|
*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