瀏覽代碼

ray type, sphere collision

master
red 4 年之前
父節點
當前提交
6c87d28cff
共有 4 個檔案被更改,包括 99 行新增18 行删除
  1. 二進制
      hello.png
  2. +54
    -9
      src/main.rs
  3. +20
    -0
      src/ray.rs
  4. +25
    -9
      src/vec3.rs

二進制
hello.png 查看文件

Before After
Width: 320  |  Height: 240  |  Size: 16KB Width: 600  |  Height: 450  |  Size: 60KB

+ 54
- 9
src/main.rs 查看文件

@@ -1,18 +1,63 @@
extern crate image;

mod vec3;
use vec3::Vec3;
use image;
use vec3::{Vec3, Ray};

/// Given a filename, pixel data, and bounds, render a PNG image.

fn encode_png(filename: &str, pixels: &[Vec3], bounds: (usize, usize)) {
let mut imgbuf =
image::ImageBuffer::new(bounds.0 as u32, bounds.1 as u32);
for (x, y, pixel) in imgbuf.enumerate_pixels_mut() {
let (x, y) = (x as usize, y as usize);
*pixel = pixels[y*bounds.0 + x].to_rgb().unwrap();
}
let imgbuf = image::imageops::flip_vertical(&imgbuf);
imgbuf.save(filename).unwrap();
}

fn main() {
let imgx = 320;
let imgy = 240;
let imgx = 600;
let imgy = 450;

let mut imgbuf = image::ImageBuffer::new(imgx, imgy);
let mut pixels = vec![Vec3(0.0, 0.0, 0.0); imgx*imgy];

for (x, y, pixel) in imgbuf.enumerate_pixels_mut() {
let v = Vec3::new(x as f32 / imgx as f32, y as f32 / imgy as f32, 0.4);
*pixel = v.to_rgb().unwrap();
let lower_left = Vec3(-2.0, -1.5, -1.0);
let horizontal = Vec3(4.0, 0.0, 0.0);
let vertical = Vec3(0.0, 3.0, 0.0);
let origin = Vec3(0.0, 0.0, 0.0);
for i in 0..imgx*imgy {
let u = (i % imgx) as f32 / imgx as f32;
let v = (i / imgx) as f32 / imgy as f32;
let r = Ray{origin, direction: lower_left + u*horizontal + v*vertical};
pixels[i] = colour(r);
}
encode_png("hello.png", &pixels, (imgx, imgy));
}

imgbuf.save("hello.png").unwrap();
fn colour(r: Ray) -> Vec3 {
let t = hit_sphere(Vec3(0.0,0.0,-1.0), 0.5, r);
if t > 0.0 {
let normal = (r.point_at(t) - Vec3(0.0, 0.0, -1.0)).unit();
0.5*Vec3(normal.0+1.0, normal.1+1.0,normal.2+1.0)
} else {
let u_direction = r.direction.unit();
let t = 0.5 * (u_direction.1 + 1.0);
(1.0 - t) * Vec3(1.0, 1.0, 1.0) + t * Vec3(0.5, 0.7, 1.0)
}
}

fn hit_sphere(center: Vec3, radius: f32, r: Ray) -> f32 {
let oc = r.origin - center;
let a = r.direction.squared_length();
let b = 2.0 * oc.dot(r.direction);
let c = oc.squared_length() - radius*radius;
let disc = b*b - 4.0*a*c;
if disc < 0.0 {
-1.0
} else {
(-b - disc.sqrt()) / (2.0 * a)
}

}

+ 20
- 0
src/ray.rs 查看文件

@@ -0,0 +1,20 @@
use vec3::Vec3;

pub struct Ray {
origin: Vec3,
direction: Vec3,
}

impl Ray {
pub fn origin(&self) -> Vec3 {
self.origin
}

pub fn direction(&self) -> Vec3 {
self.direction
}

pub fn point_at(&self, t: f32) -> Vec3 {
self.origin + t*self.direction
}
}

+ 25
- 9
src/vec3.rs 查看文件

@@ -3,7 +3,7 @@ use std::f32;
use image::Rgb;

#[derive(Clone, Copy, Debug)]
pub struct Vec3(f32, f32, f32);
pub struct Vec3(pub f32, pub f32, pub f32);

impl Vec3 {
pub fn new(x: f32, y: f32, z: f32) -> Vec3 {
@@ -30,13 +30,13 @@ impl Vec3 {
)
}

pub fn unit(&self) -> Vec3 {
*self / self.length()
pub fn unit(self) -> Vec3 {
self / self.length()
}

pub fn to_rgb(&self) -> Result<Rgb<u8>, &str> {
pub fn to_rgb(&self) -> Result<Rgb<u8>, String> {
if self.0 < 0.0 || self.0 > 1.0 || self.1 < 0.0 || self.1 > 1.0 || self.2 < 0.0 || self.2 > 1.0 {
return Err("input out of bounds");
return Err(format!("input out of bounds: {0} {1} {2}", self.0, self.1, self.2));
}
let r = (self.0 * 255.99) as u8;
let g = (self.1 * 255.99) as u8;
@@ -72,16 +72,16 @@ impl Neg for Vec3 {
impl Mul<f32> for Vec3 {
type Output = Vec3;

fn mul(self, k: f32) -> Vec3 {
Vec3(self.0 * k, self.1 * k, self.2 * k)
fn mul(self, t: f32) -> Vec3 {
Vec3(self.0 * t, self.1 * t, self.2 * t)
}
}

impl Div<f32> for Vec3 {
type Output = Vec3;

fn div(self, k: f32) -> Vec3 {
Vec3(self.0 / k, self.1 / k, self.2 / k)
fn div(self, t: f32) -> Vec3 {
Vec3(self.0 / t, self.1 / t, self.2 / t)
}
}

@@ -91,4 +91,20 @@ impl Mul<Vec3> for f32 {
fn mul(self, v: Vec3) -> Vec3 {
v*self
}
}

#[derive(Clone, Copy, Debug)]
pub struct Ray {
pub origin: Vec3,
pub direction: Vec3,
}

impl Ray {
pub fn new(origin : Vec3, direction : Vec3) -> Ray {
Ray{origin, direction}
}

pub fn point_at(&self, t: f32) -> Vec3 {
self.origin + t*self.direction
}
}

Loading…
取消
儲存