diff --git a/.gitpod.yml b/.gitpod.yml new file mode 100644 index 0000000..2be156f --- /dev/null +++ b/.gitpod.yml @@ -0,0 +1,12 @@ +image: + file: Dockerfile +tasks: +- command: > + mkdir --parents build && + cd build && + cmake .. && + make && + ./tinyraycaster && + pnmtopng out.ppm > out.png && + open out.png && + cd .. diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..aa1f8a5 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,6 @@ +FROM gitpod/workspace-full + +USER root +# add your tools here +RUN apt-get update && apt-get install -y \ + netpbm diff --git a/doc/depthmap.jpg b/doc/depthmap.jpg new file mode 100644 index 0000000..eb9b770 Binary files /dev/null and b/doc/depthmap.jpg differ diff --git a/geometry.h b/geometry.h index 86aeecd..3b2f3f1 100644 --- a/geometry.h +++ b/geometry.h @@ -3,83 +3,41 @@ #include #include #include -#include -template struct vec { - vec() { for (size_t i=DIM; i--; data_[i] = T()); } - T& operator[](const size_t i) { assert(i Vec2f; -typedef vec<3, float> Vec3f; -typedef vec<3, int > Vec3i; -typedef vec<4, float> Vec4f; - -template struct vec<2,T> { - vec() : x(T()), y(T()) {} - vec(T X, T Y) : x(X), y(Y) {} - template vec<2,T>(const vec<2,U> &v); - T& operator[](const size_t i) { assert(i<2); return i<=0 ? x : y; } - const T& operator[](const size_t i) const { assert(i<2); return i<=0 ? x : y; } - T x,y; -}; - -template struct vec<3,T> { - vec() : x(T()), y(T()), z(T()) {} - vec(T X, T Y, T Z) : x(X), y(Y), z(Z) {} +template struct vec3 { T& operator[](const size_t i) { assert(i<3); return i<=0 ? x : (1==i ? y : z); } const T& operator[](const size_t i) const { assert(i<3); return i<=0 ? x : (1==i ? y : z); } - float norm() { return std::sqrt(x*x+y*y+z*z); } - vec<3,T> & normalize(T l=1) { *this = (*this)*(l/norm()); return *this; } + vec3 & normalize(T l=1) { *this = (*this)*(l/std::sqrt((*this)*(*this))); return *this; } T x,y,z; }; -template struct vec<4,T> { - vec() : x(T()), y(T()), z(T()), w(T()) {} - vec(T X, T Y, T Z, T W) : x(X), y(Y), z(Z), w(W) {} - T& operator[](const size_t i) { assert(i<4); return i<=0 ? x : (1==i ? y : (2==i ? z : w)); } - const T& operator[](const size_t i) const { assert(i<4); return i<=0 ? x : (1==i ? y : (2==i ? z : w)); } - T x,y,z,w; -}; - -template T operator*(const vec& lhs, const vec& rhs) { +template T operator*(const vec3& lhs, const vec3& rhs) { T ret = T(); - for (size_t i=DIM; i--; ret+=lhs[i]*rhs[i]); + for (size_t i=3; i--; ret+=lhs[i]*rhs[i]); return ret; } -templatevec operator+(vec lhs, const vec& rhs) { - for (size_t i=DIM; i--; lhs[i]+=rhs[i]); +template vec3 operator+(vec3 lhs, const vec3& rhs) { + for (size_t i=3; i--; lhs[i]+=rhs[i]); return lhs; } -templatevec operator-(vec lhs, const vec& rhs) { - for (size_t i=DIM; i--; lhs[i]-=rhs[i]); +template vec3 operator-(vec3 lhs, const vec3& rhs) { + for (size_t i=3; i--; lhs[i]-=rhs[i]); return lhs; } -template vec operator*(const vec &lhs, const U& rhs) { - vec ret; - for (size_t i=DIM; i--; ret[i]=lhs[i]*rhs); +template vec3 operator*(const vec3 &lhs, const U& rhs) { + vec3 ret; + for (size_t i=3; i--; ret[i]=lhs[i]*rhs); return ret; } -template vec operator-(const vec &lhs) { +template vec3 operator-(const vec3 &lhs) { return lhs*T(-1); } -template vec<3,T> cross(vec<3,T> v1, vec<3,T> v2) { - return vec<3,T>(v1.y*v2.z - v1.z*v2.y, v1.z*v2.x - v1.x*v2.z, v1.x*v2.y - v1.y*v2.x); -} +typedef vec3 Vec3f; -template std::ostream& operator<<(std::ostream& out, const vec& v) { - for(unsigned int i=0; i +#define _USE_MATH_DEFINES #include +#include #include #include #include +#include #include "geometry.h" -struct Material { - Material(const Vec3f &color) : diffuse_color(color) {} - Material() : diffuse_color() {} - Vec3f diffuse_color; -}; - struct Sphere { Vec3f center; float radius; - Material material; - - Sphere(const Vec3f &c, const float &r, const Material &m) : center(c), radius(r), material(m) {} - - bool ray_intersect(const Vec3f &orig, const Vec3f &dir, float &t0) const { - Vec3f L = center - orig; - float tca = L*dir; - float d2 = L*L - tca*tca; - if (d2 > radius*radius) return false; - float thc = sqrtf(radius*radius - d2); - t0 = tca - thc; - float t1 = tca + thc; - if (t0 < 0) t0 = t1; - if (t0 < 0) return false; - return true; - } }; -bool scene_intersect(const Vec3f &orig, const Vec3f &dir, const std::vector &spheres, Vec3f &hit, Vec3f &N, Material &material) { +bool sphere_ray_intersect(const Sphere &sphere, const Vec3f &orig, const Vec3f &dir, float &t0) { + Vec3f L = sphere.center - orig; + float tca = L*dir; + float d2 = L*L - tca*tca; + if (d2 > pow(sphere.radius, 2)) return false; + float thc = sqrtf(pow(sphere.radius, 2) - d2); + t0 = tca - thc; + float t1 = tca + thc; + if (t0 < 0) t0 = t1; + if (t0 < 0) return false; + return true; +} + +float scene_intersect(const Vec3f &orig, const Vec3f &dir, const std::vector &spheres) { float spheres_dist = std::numeric_limits::max(); - for (size_t i=0; i < spheres.size(); i++) { + for (size_t i=0; i::max(); + if (fabs(dir.y)>1e-3) { + float d = -(orig.y+4)/dir.y; // the checkerboard plane has equation y = -4 + Vec3f pt = orig + dir*d; + if (d>0 && fabs(pt.x)<10 && pt.z<-10 && pt.z>-30) { + checkerboard_dist = d; + } + } + + return std::min(spheres_dist, checkerboard_dist); } -Vec3f cast_ray(const Vec3f &orig, const Vec3f &dir, const std::vector &spheres) { - Vec3f point, N; - Material material; - - if (!scene_intersect(orig, dir, spheres, point, N, material)) { - return Vec3f(0.2, 0.7, 0.8); // background color - } - - return material.diffuse_color; -} - -void render(const std::vector &spheres) { - const int width = 1024; - const int height = 768; - const int fov = M_PI/2.; - std::vector framebuffer(width*height); - - #pragma omp parallel for - for (size_t j = 0; j &spheres, std::vector &zbuffer) { +#pragma omp parallel for + for (size_t j=0; j::max(); // clamp the zbuffer by the far plane and normalize it between 0 and 1 + float maxval = -std::numeric_limits::max(); + for (size_t i=0; i spheres = { {{-3,0,-16}, 2}, {{-1,-1.5,-12}, 2}, {{1.5,-.5,-18}, 3}, {{7,5,-18}, 4} }; + const size_t width = 1024; + const size_t height = 768; + const float fov = M_PI/3.; + std::vector zbuffer(width*height); + compute_depthmap(width, height, fov, 23.f, spheres, zbuffer); - std::vector spheres; - spheres.push_back(Sphere(Vec3f(-3, 0, -16), 2, ivory)); - spheres.push_back(Sphere(Vec3f(-1.0, -1.5, -12), 2, red_rubber)); - spheres.push_back(Sphere(Vec3f( 1.5, -0.5, -18), 3, red_rubber)); - spheres.push_back(Sphere(Vec3f( 7, 5, -18), 4, ivory)); + std::vector framebuffer(width*height*3); + for (size_t j=0; j(framebuffer.data()), 3*height*width); + ofs.close(); return 0; }