init: create git repo
This commit is contained in:
23
include/buffer.hpp
Normal file
23
include/buffer.hpp
Normal file
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include "./vec.hpp"
|
||||
#include "./raytrace.hpp"
|
||||
|
||||
struct Frame {
|
||||
v3* data;
|
||||
};
|
||||
|
||||
void bg_fg(v3* cols, v3& bg, v3& fg, const char*& c);
|
||||
|
||||
inline int colcvt(choice_t x) {
|
||||
if (x < 0.0) return 0;
|
||||
if (x > 1.0) return 255;
|
||||
return int(x * 255.0);
|
||||
}
|
||||
|
||||
void display_frame(const Screen& screen, const Frame& frame);
|
||||
|
||||
void render_frame(const Screen& screen, Camera& camera, Frame& frame,
|
||||
const std::vector<Renderable*>& scene,
|
||||
const std::vector<Renderable*>& objects,
|
||||
const std::vector<Renderable*>& lights);
|
38
include/objects.hpp
Normal file
38
include/objects.hpp
Normal file
@@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
#include "./vec.hpp"
|
||||
#include "./raytrace.hpp"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
struct Plane : Renderable {
|
||||
v3 n;
|
||||
choice_t offset;
|
||||
|
||||
int surface_type;
|
||||
|
||||
Plane(const v3& n, choice_t offset, const Material& specs, int surface_type);
|
||||
Plane(const v3& n, choice_t offset, const Material& specs);
|
||||
|
||||
inline v3 normal(const v3& _) { return n; }
|
||||
int intersect(const v3& eye, const v3& dir, choice_t& hit_dist, v3& hit_loc, v3& hit_normal) override;
|
||||
};
|
||||
|
||||
struct Sphere : Renderable {
|
||||
v3 o;
|
||||
choice_t r;
|
||||
|
||||
int surface_type;
|
||||
|
||||
Sphere(const v3& origin, choice_t r, const Material& specs, int surface_type);
|
||||
Sphere(const v3& origin, choice_t r);
|
||||
|
||||
inline v3 normal(const v3& xyz) const { return (xyz - o).norm(); }
|
||||
int intersect(const v3& eye, const v3& dir, choice_t& hit_dist, v3& hit_loc, v3& hit_normal) override;
|
||||
int transmit(const v3& eye, const v3& dir, choice_t& hit_dist, v3& hit_loc, v3& hit_normal) override;
|
||||
};
|
||||
|
||||
struct Light : Sphere {
|
||||
Light(const v3& origin, choice_t r, const v3& colour);
|
||||
Light(const v3& origin, choice_t r, const Material& specs);
|
||||
};
|
82
include/raytrace.hpp
Normal file
82
include/raytrace.hpp
Normal file
@@ -0,0 +1,82 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "./vec.hpp"
|
||||
|
||||
struct Screen {
|
||||
const int W, H;
|
||||
const choice_t ASPECT_RATIO;
|
||||
constexpr Screen(int W, int H, choice_t ASPECT_RATIO)
|
||||
: W(W), H(H), ASPECT_RATIO(ASPECT_RATIO) {}
|
||||
};
|
||||
|
||||
struct Camera {
|
||||
v3 pos; v3 rotation; v3 translation{0,0,0};
|
||||
choice_t zoom = 0.5;
|
||||
choice_t exposure = -0.6;
|
||||
choice_t dynamic_range = 1;
|
||||
};
|
||||
|
||||
struct Material {
|
||||
choice_t specular = 0.1;
|
||||
choice_t roughness = 0.5;
|
||||
choice_t ior = 1.2;
|
||||
choice_t transparency = 0.8;
|
||||
v3 colour;
|
||||
};
|
||||
|
||||
struct Renderable {
|
||||
Material specs;
|
||||
|
||||
Renderable(const Material& specs);
|
||||
|
||||
virtual int intersect(const v3& eye, const v3& dir, choice_t& hit_dist, v3& hit_loc, v3& hit_normal)=0;
|
||||
|
||||
/**
|
||||
Like #intersect, but for transmission rays inside the object. #eye must
|
||||
be on the surface of the object.
|
||||
*/
|
||||
virtual int transmit(const v3& eye, const v3& dir, choice_t& hit_dist, v3& hit_loc, v3& hit_normal) { return -1; }
|
||||
};
|
||||
|
||||
/**
|
||||
Shoots a ray from #eye in direction #dir, (possibly) hitting the closest object from #objs.
|
||||
Expects #dir to be normalised.
|
||||
|
||||
The hit object's distance, location, normal and type will be written in the
|
||||
references so-aptly named. If nothing was hit, the contents of those variables is UB.
|
||||
|
||||
Returns the pointer to the object it hit, or `nullptr' otherwise.
|
||||
|
||||
Respects the initial value of #hit_dist, et al.
|
||||
|
||||
Optional parameter #self is a pointer to an object considered 'self' that
|
||||
will be skipped during collision checks. The objects are compared by pointer
|
||||
address.
|
||||
*/
|
||||
Renderable* shoot_ray_into_objects(const v3& eye, const v3& dir, const std::vector<Renderable*>& objs,
|
||||
choice_t& hit_dist, v3& hit_loc, v3& hit_normal, int& hit_type,
|
||||
Renderable* self = nullptr);
|
||||
|
||||
/**
|
||||
Shoots a ray from #eye in (unit) direction #dir into a #scene and returns the
|
||||
colour of that ray.
|
||||
|
||||
#scene must be #objects u #lights.
|
||||
|
||||
#depth is how much the ray tracer is allowed to recurse.
|
||||
*/
|
||||
v3 ray_trace(const v3& eye, const v3& dir,
|
||||
const std::vector<Renderable*>& scene,
|
||||
const std::vector<Renderable*>& objects,
|
||||
const std::vector<Renderable*>& lights, int depth,
|
||||
Renderable* skip = nullptr,
|
||||
choice_t* dist_to_hit = nullptr);
|
||||
|
||||
choice_t ggx_ndf(const v3& dir, const v3& h, const v3& normal, choice_t roughness);
|
||||
choice_t blinn_phong_ndf(const v3& dir, const v3& h, const v3& normal, choice_t roughness);
|
||||
choice_t cook_torrance_gaf(const v3& dir, const v3& h, const v3& normal, const v3& light);
|
||||
choice_t cook_torrance_fresnel(const v3& dir, const v3& h, choice_t ior);
|
||||
|
||||
v3 cook_torrance(const v3& dir, const v3& normal, const v3& light, choice_t specular, choice_t roughness,
|
||||
choice_t ior, const v3& light_colour, const v3& surface_colour);
|
105
include/vec.hpp
Normal file
105
include/vec.hpp
Normal file
@@ -0,0 +1,105 @@
|
||||
#pragma once
|
||||
|
||||
#include <math.h>
|
||||
|
||||
typedef float choice_t;
|
||||
|
||||
#define do_op(o, r, i) \
|
||||
inline void operator o##= (const r & rhs) { for(unsigned n=0; n<(i); n++) c[n] o##= rhs.c[n]; } \
|
||||
inline void operator o##= (choice_t d) { for(unsigned n=0; n<(i); n++) c[n] o##= d; } \
|
||||
inline r operator o (const r & rhs) const { r tmp(*this); tmp o##= rhs; return tmp; } \
|
||||
inline r operator o (choice_t d) const { r tmp(*this); tmp o##= d; return tmp; }
|
||||
|
||||
#define do_ops(c, i) \
|
||||
do_op(*, c, i); \
|
||||
do_op(/, c, i); \
|
||||
do_op(+, c, i); \
|
||||
do_op(-, c, i);
|
||||
|
||||
|
||||
struct v3 {
|
||||
union {
|
||||
choice_t c[4];
|
||||
struct {
|
||||
choice_t x, y, z, w;
|
||||
};
|
||||
};
|
||||
|
||||
v3(choice_t x, choice_t y, choice_t z) : c{x,y,z} {}
|
||||
v3(choice_t f) : v3(f,f,f) {}
|
||||
v3() : v3(0,0,0) {}
|
||||
|
||||
do_ops(v3, 3);
|
||||
|
||||
inline v3 operator-(void) const { return {-x, -y, -z}; }
|
||||
|
||||
inline choice_t operator^(const v3& rhs) const
|
||||
{ return x * rhs.x + y * rhs.y + z * rhs.z; }
|
||||
|
||||
/* Return normalised (unit) vector. */
|
||||
inline v3 norm() const
|
||||
{ return *this / len(); }
|
||||
|
||||
inline choice_t len() const
|
||||
{ return sqrtf(x*x + y*y + z*z); }
|
||||
|
||||
inline choice_t lensquared() const
|
||||
{ return x*x + y*y + z*z; }
|
||||
|
||||
/* Return vector reflected around `n'. Expects `this' and `n' to be unit. */
|
||||
inline v3 ref(const v3& n) const
|
||||
{ return n * ((*this ^ n) * 2) - *this;}
|
||||
|
||||
/* Cross product. */
|
||||
inline v3 cross(const v3& b) const
|
||||
{ return { y*b.z - z*b.y,
|
||||
x*b.z - z*b.x,
|
||||
x*b.y - y*b.x }; }
|
||||
|
||||
inline v3 refract(const v3& n, choice_t ior_ratio) const
|
||||
{
|
||||
return n * sqrtf(1 - powf(ior_ratio, 2) * (1 - powf(*this ^ n, 2))) + (*this - n * (*this ^ n)) * ior_ratio;
|
||||
}
|
||||
|
||||
inline v3 refract(const v3& n, choice_t ior_incident, choice_t ior_refract) const
|
||||
{ return refract(n, ior_incident / ior_refract); }
|
||||
|
||||
inline v3 clamp(const v3& from, const v3& to) const
|
||||
{ return { fmin(fmax(x, from.x), to.x),
|
||||
fmin(fmax(y, from.y), to.y),
|
||||
fmin(fmax(z, from.z), to.z) }; }
|
||||
|
||||
inline v3 exp() const
|
||||
{ return { ::exp(x), ::exp(y), ::exp(z) }; }
|
||||
|
||||
inline v3 htan(choice_t exposure = 0) const
|
||||
{
|
||||
return { powf((tanh(x + exposure) + 1) / 2, 2.2), powf((tanh(y + exposure) + 1) / 2, 2.2), powf((tanh(z + exposure) + 1) / 2, 2.2) };
|
||||
return { tanh(x + exposure), tanh(y + exposure), tanh(z + exposure) };
|
||||
}
|
||||
};
|
||||
|
||||
#undef do_ops
|
||||
#undef do_op
|
||||
|
||||
#define V3_FMT "v3(%.2f, %.2f, %.2f)"
|
||||
#define V3_ARG(v) (v).x, (v).y, (v).z
|
||||
|
||||
struct Matrix
|
||||
{
|
||||
v3 m[4];
|
||||
void init_rotate(const v3& angle)
|
||||
{
|
||||
choice_t Cx = cos(angle.c[0]), Cy = cos(angle.c[1]), Cz = cos(angle.c[2]);
|
||||
choice_t Sx = sin(angle.c[0]), Sy = sin(angle.c[1]), Sz = sin(angle.c[2]);
|
||||
choice_t sxsz = Sx*Sz, cxsz = Cx*Sz;
|
||||
choice_t cxcz = Cx*Cz, sxcz = Sx*Cz;
|
||||
Matrix result = {{ { Cy*Cz, Cy*Sz, -Sy },
|
||||
{ sxcz*Sy - cxsz, sxsz*Sy + cxcz, Sx*Cy },
|
||||
{ cxcz*Sy + sxsz, cxsz*Sy - sxcz, Cx*Cy } }};
|
||||
*this = result;
|
||||
}
|
||||
|
||||
v3 transform(const v3& vec) const
|
||||
{ return { m[0] ^ vec, m[1] ^ vec, m[2] ^ vec }; }
|
||||
};
|
Reference in New Issue
Block a user