diff --git a/rtiww/CMakeLists.txt b/rtiww/CMakeLists.txt index d5ee58d..42527f8 100644 --- a/rtiww/CMakeLists.txt +++ b/rtiww/CMakeLists.txt @@ -3,4 +3,4 @@ project(rtiww) set(CMAKE_CXX_STANDARD 17) -add_executable(rtiww src/main.cpp) +add_executable(rtiww src/main.cpp src/vec3.h src/color.h src/ray.h) diff --git a/rtiww/src/color.h b/rtiww/src/color.h new file mode 100644 index 0000000..0949b24 --- /dev/null +++ b/rtiww/src/color.h @@ -0,0 +1,14 @@ +#ifndef RTIWW_COLOR_H +#define RTIWW_COLOR_H + +#include "vec3.h" + +#include + +void write_color(std::ostream &out, color pixel_color) { + out << static_cast(255.999 * pixel_color.x()) << ' ' + << static_cast(255.999 * pixel_color.y()) << ' ' + << static_cast(255.999 * pixel_color.z()) << '\n'; +} + +#endif //RTIWW_COLOR_H diff --git a/rtiww/src/main.cpp b/rtiww/src/main.cpp index bc8f460..2f9f2ce 100644 --- a/rtiww/src/main.cpp +++ b/rtiww/src/main.cpp @@ -1,6 +1,48 @@ +#include "color.h" +#include "vec3.h" +#include "ray.h" + #include +color ray_color(const ray& r) { + vec3 unit_direction = unit_vector(r.direction()); + auto t = 0.5 * (unit_direction.y() + 1.0); + return (1.0-t)*color(1.0, 1.0, 1.0) + t*color(0.5, 0.7, 1.0); +} + int main() { - std::cout << "Hello, World!" << std::endl; + + // Image + const auto aspect_ratio = 16.0/9.0; + const int image_width = 400; + const int image_height = static_cast(image_width / aspect_ratio); + + // Camera + auto viewport_height = 2.0; + auto viewport_width = aspect_ratio*viewport_height; + auto focal_length = 1.0; + + auto origin = point3(0, 0, 0); + auto horizontal = vec3(viewport_width, 0, 0); + auto vertical = vec3(0, viewport_height, 0); + auto lower_left_corner = origin - horizontal/2 - vertical/2 - vec3(0, 0, focal_length); + + // Render + std::cout << "P3\n" << image_width << ' ' << image_height << "\n255\n"; + + for (int j = image_height - 1; j >= 0; --j) { + std::cerr << "\rScanlines remaining: " << j << ' ' << std::flush; + for (int i = 0; i < image_width; ++i) { + auto u = double(i)/(image_width-1); + auto v = double(j) / (image_height-1); + + ray r(origin, lower_left_corner + u*horizontal + v*vertical - origin); + color pixel_color = ray_color(r); + write_color(std::cout, pixel_color); + } + } + + std::cerr << "\nDone.\n"; + return 0; } diff --git a/rtiww/src/ray.h b/rtiww/src/ray.h new file mode 100644 index 0000000..d1d7cf6 --- /dev/null +++ b/rtiww/src/ray.h @@ -0,0 +1,24 @@ +#ifndef RTIWW_RAY_H +#define RTIWW_RAY_H + +#include "vec3.h" + +class ray { +public: + ray() {} + + ray(const point3 &origin, const vec3 &direction) : orig(origin), dir(direction) {} + + point3 origin() const { return orig; } + vec3 direction() const { return dir; } + + point3 at(double t) const { + return orig + t*dir; + } + +public: + point3 orig; + vec3 dir; +}; + +#endif //RTIWW_RAY_H diff --git a/rtiww/src/vec3.h b/rtiww/src/vec3.h new file mode 100644 index 0000000..fc29264 --- /dev/null +++ b/rtiww/src/vec3.h @@ -0,0 +1,101 @@ +#ifndef RTIWW_VEC3_H +#define RTIWW_VEC3_H + +#include +#include + +class vec3 { +public: + vec3() : e{0, 0, 0} {} + + vec3(double e0, double e1, double e2) : e{e0, e1, e2} {} + + double x() const { return e[0]; } + + double y() const { return e[1]; } + + double z() const { return e[2]; } + + vec3 operator-() const {return vec3(-e[0], -e[1], -e[2]);} + double operator[](int i) const { return e[i]; } + double& operator[](int i) {return e[i];} + + vec3& operator+=(const vec3 &v) { + e[0] += v.e[0]; + e[1] += v.e[1]; + e[2] += v.e[2]; + return *this; + } + + vec3& operator*=(const double t) { + e[0] *= t; + e[1] *= t; + e[2] *= t; + return *this; + } + + vec3& operator/=(const double t) { + return *this *= 1/t; + } + + double length() const { + return sqrt(length_squared()); + } + + double length_squared() const { + return e[0]*e[0] + e[1]*e[1] + e[2]*e[2]; + } + + +public: + double e[3]; +}; + +using point3 = vec3; +using color = vec3; + +inline std::ostream& operator<<(std::ostream &out, const vec3 &v) { + return out << v.e[0] << ' ' << v.e[1] << ' ' << v.e[2]; +} + +inline vec3 operator+(const vec3 &u, const vec3 &v) { + return vec3(u.e[0] + v.e[0], u.e[1] + v.e[1], u.e[2] + v.e[2]); +} + +inline vec3 operator-(const vec3 &u, const vec3 &v) { + return vec3(u.e[0] - v.e[0], u.e[1] - v.e[1], u.e[2] + v.e[2]); +} + +inline vec3 operator*(const vec3 &u, const vec3 &v) { + return vec3(u.e[0] * v.e[0], u.e[1] * v.e[1], u.e[2] * v.e[2]); +} + +inline vec3 operator*(double t, const vec3 &v) { + return vec3(t*v.e[0], t*v.e[1], t*v.e[2]); +} + +inline vec3 operator*(const vec3 &v, double t) { + return t*v; +} + +inline vec3 operator/(vec3 v, double t) { + return (1/t) * v; +} + +inline double dot(const vec3 &u, const vec3 &v) { + return u.e[0] * v.e[0] + + u.e[1] * v.e[1] + + u.e[2] * v.e[2]; +} + +inline vec3 cross(const vec3 &u, const vec3 &v) { + return vec3(u.e[1] * v.e[2] - u.e[2] * v.e[1], + u.e[2] * v.e[0] - u.e[0] * v.e[2], + u.e[0] * v.e[1] - u.e[1] * v.e[0]); +} + +inline vec3 unit_vector(vec3 v) { + return v / v.length(); +} + +#endif //RTIWW_VEC3_H