~turminal/raytracing

cc772aa6f9d3dd849a254c6743167cd7e6a3cdf5 — Bor Grošelj Simić 2 years ago 779a6c9
dielectric materials
2 files changed, 54 insertions(+), 3 deletions(-)

M main.ha
M material.ha
M main.ha => main.ha +2 -2
@@ 5,8 5,8 @@ use time;

fn init_scene() *hittable = {
	let ground = alloc(make_lambertian(&C(0.8, 0.8, 0.0)));
	let center = alloc(make_lambertian(&C(0.7, 0.3, 0.3)));
	let left = alloc(make_metal(&C(0.8, 0.8, 0.8), 0.3));
	let center = alloc(make_dielectric(1.5));
	let left = alloc(make_dielectric(1.2));
	let right = alloc(make_metal(&C(0.8, 0.6, 0.2), 1.0));
	let a = alloc(multi([]));
	append(a.arr, [

M material.ha => material.ha +52 -1
@@ 1,4 1,4 @@
use math::{absf64};
use math::{absf64, powf64, sqrtf64};

export type scatterfunc = *fn(
	mat: *const material,


@@ 73,3 73,54 @@ fn metal_scatter(
	*att = m.albedo;
	return dot(r_out.direction, rec.normal) > 0.0;
};

fn refract(v: *const vector, n: *const vector, r: f64) vector = {
	let k = dot(neg(*v), *n);
	let k = if (k < 1.0) k else 1.0;
	let c1 = scale(sum(*v, scale(*n, k)), r);
	let c2 = scale(*n, -sqrtf64(absf64(1.0 - dot(c1, c1))));
	return sum(c1, c2);
};

fn schlick_reflectance(cos: f64, r_ind: f64) f64 = {
	let r0 = (1.0 - r_ind) / (1.0 + r_ind);
	r0 = r0 * r0;
	return r0 + (1.0 - r0) * powf64(1.0 - cos, 5.0);
};

type dielectric = struct {
	material,
	r_ind: f64,
};

fn make_dielectric(r: f64) dielectric = dielectric {
	scatter = &dielectric_scatter,
	r_ind = r,
};

fn dielectric_scatter(
	m: *const material,
	r_in: *const ray,
	rec: *const hit_record,
	att: *color,
	r_out: *ray
) bool = {
	let d = m: *const dielectric;
	*att = C(1.0, 1.0, 1.0);

	let r_ind = if (rec.front_face) 1.0 / d.r_ind else d.r_ind;
	let unit_dir = unit(r_in.direction);
	let cos = dot(neg(unit_dir), rec.normal);
	let cos = if (cos < 1.0) cos else 1.0;
	let sin = sqrtf64(1.0 - cos * cos);
	*r_out = ray {
		origin = rec.point,
		direction =
			if (r_ind * sin <= 1.0
			|| schlick_reflectance(cos, r_ind) > random(0.0, 1.0))
				refract(&unit_dir, &rec.normal, r_ind)
			else
				reflect(&unit_dir, &rec.normal),
	};
	return true;
};