start splitting out header and source files

This commit is contained in:
ktyl 2023-02-19 19:55:42 +00:00
parent ed4243cf89
commit 577867ca35
22 changed files with 258 additions and 172 deletions

View File

@ -2,10 +2,8 @@ cmake_minimum_required(VERSION 3.10)
project(snoopy) project(snoopy)
file(GLOB snoopy_src include_directories("include")
"src/*.h" file(GLOB SOURCES "src/*.cpp")
"src/*.cpp"
)
add_executable(snoopy ${snoopy_src}) add_executable(snoopy ${SOURCES})

52
include/camera.h Normal file
View File

@ -0,0 +1,52 @@
#pragma once
#include "rtweekend.h"
#include "image.h"
class camera
{
public:
camera(
point3 lookfrom,
point3 lookat,
vec3 vup,
double vfov, // vertical field of view in degrees
double aspect_ratio,
double aperture,
double focus_dist)
{
auto theta = degrees_to_radians(vfov);
auto h = tan(theta/2);
auto viewport_height = 2.0 * h;
auto viewport_width = aspect_ratio * viewport_height;
w_ = unit_vector(lookfrom - lookat);
u_ = unit_vector(cross(vup, w_));
v_ = cross(w_, u_);
origin_ = lookfrom;
horizontal_ = focus_dist * viewport_width * u_;
vertical_ = focus_dist * viewport_height * v_;
lower_left_corner_ = origin_ - horizontal_/2 - vertical_/2 - focus_dist * w_;
lens_radius_ = aperture / 2;
}
ray get_ray(double s, double t) const
{
vec3 rd = lens_radius_ * random_in_unit_disk();
vec3 offset = (u_ * rd.x()) + (v_ * rd.y());
return ray(
origin_ + offset,
lower_left_corner_ + s*horizontal_ + t*vertical_ - origin_ - offset);
}
private:
point3 origin_;
point3 lower_left_corner_;
vec3 horizontal_;
vec3 vertical_;
vec3 u_, v_, w_;
double lens_radius_;
};

View File

@ -26,6 +26,11 @@ void correct_gamma(colour& pixel_colour, int samples)
pixel_colour = colour(r, g, b); pixel_colour = colour(r, g, b);
} }
int format_component(double component)
{
return int(256 * math::clamp(component, 0.0, 0.999));
}
void write_colour_to_stream(std::ostream &out, colour pixel_colour, int samples_per_pixel) void write_colour_to_stream(std::ostream &out, colour pixel_colour, int samples_per_pixel)
{ {
correct_gamma(pixel_colour, samples_per_pixel); correct_gamma(pixel_colour, samples_per_pixel);
@ -35,14 +40,9 @@ void write_colour_to_stream(std::ostream &out, colour pixel_colour, int samples_
auto b = pixel_colour.z(); auto b = pixel_colour.z();
// write the translated [0,255] value of each colour component. // write the translated [0,255] value of each colour component.
out << static_cast<int>(256 * clamp(r, 0.0, 0.999)) << ' ' out << format_component(r) << ' '
<< static_cast<int>(256 * clamp(g, 0.0, 0.999)) << ' ' << format_component(g) << ' '
<< static_cast<int>(256 * clamp(b, 0.0, 0.999)) << '\n'; << format_component(b) << '\n';
}
int format_component(double component)
{
return int(256 * clamp(component, 0.0, 0.999));
} }
void write_colour_to_socket(int sockfd, colour pixel_colour, int samples_per_pixel) void write_colour_to_socket(int sockfd, colour pixel_colour, int samples_per_pixel)

1
include/foo.h Normal file
View File

@ -0,0 +1 @@
#include <iostream>

View File

@ -31,7 +31,7 @@ class lambertian : public material
colour& attenuation, colour& attenuation,
ray& scattered) const ray& scattered) const
{ {
vec3 scatter_direction = rec.normal + random_unit_vector(); vec3 scatter_direction = rec.normal + vec3::random_unit_vector();
scattered = ray(rec.p, scatter_direction); scattered = ray(rec.p, scatter_direction);
attenuation = albedo_; attenuation = albedo_;
return true; return true;
@ -54,8 +54,8 @@ class metal : public material
colour& attenuation, colour& attenuation,
ray& scattered) const ray& scattered) const
{ {
vec3 reflected = reflect(unit_vector(r_in.direction()), rec.normal); vec3 reflected = vec3::reflect(unit_vector(r_in.direction()), rec.normal);
scattered = ray(rec.p, reflected + fuzz_*random_in_unit_sphere()); scattered = ray(rec.p, reflected + fuzz_ * vec3::random_in_unit_sphere());
attenuation = albedo_; attenuation = albedo_;
return dot(scattered.direction(), rec.normal) > 0; return dot(scattered.direction(), rec.normal) > 0;
} }
@ -85,20 +85,20 @@ class dielectric : public material
double sin_theta = sqrt(1.0 - cos_theta*cos_theta); double sin_theta = sqrt(1.0 - cos_theta*cos_theta);
if (etai_over_etat * sin_theta > 1.0) if (etai_over_etat * sin_theta > 1.0)
{ {
vec3 reflected = reflect(unit_direction, rec.normal); vec3 reflected = vec3::reflect(unit_direction, rec.normal);
scattered = ray(rec.p, reflected); scattered = ray(rec.p, reflected);
return true; return true;
} }
double reflect_prob = schlick(cos_theta, etai_over_etat); double reflect_prob = schlick(cos_theta, etai_over_etat);
if (random_double() < reflect_prob) if (math::random_double() < reflect_prob)
{ {
vec3 reflected = reflect(unit_direction, rec.normal); vec3 reflected = vec3::reflect(unit_direction, rec.normal);
scattered = ray(rec.p, reflected); scattered = ray(rec.p, reflected);
return true; return true;
} }
vec3 refracted = refract(unit_direction, rec.normal, etai_over_etat); vec3 refracted = vec3::refract(unit_direction, rec.normal, etai_over_etat);
scattered = ray(rec.p, refracted); scattered = ray(rec.p, refracted);
return true; return true;

15
include/math.h Normal file
View File

@ -0,0 +1,15 @@
#pragma once
#include <cmath>
class math
{
public:
static constexpr double infinity = std::numeric_limits<double>::infinity();
static constexpr double pi = 3.1415926535897932385;
static double degrees_to_radians(double degrees);
static double random_double();
static double random_double(double min, double max);
static double clamp(double x, double min, double max);
};

18
include/rtweekend.h Normal file
View File

@ -0,0 +1,18 @@
#pragma once
#include <cmath>
#include <cstdlib>
#include <limits>
#include <memory>
// usings
using std::shared_ptr;
using std::make_shared;
using std::sqrt;
// common headers
#include "error.h"
#include "ray.h"
#include "vec3.h"

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include "math.h"
#include "sphere.h" #include "sphere.h"
#include "colour.h" #include "colour.h"
#include "material.h" #include "material.h"
@ -14,7 +15,7 @@ colour ray_colour(const ray& r, const hittable& world, int depth)
return grey; return grey;
} }
if (world.hit(r, 0.001, infinity, rec)) if (world.hit(r, 0.001, math::infinity, rec))
{ {
ray scattered; ray scattered;
colour attenuation; colour attenuation;

View File

@ -1,23 +1,28 @@
#pragma once #pragma once
#include <cmath>
#include <iostream> #include <iostream>
#include "rtweekend.h" #include "math.h"
class vec3 class vec3
{ {
public: public:
inline static vec3 random() inline static vec3 random()
{ {
return vec3(random_double(),random_double(),random_double()); return vec3(math::random_double(),math::random_double(),math::random_double());
} }
inline static vec3 random(double min, double max) inline static vec3 random(double min, double max)
{ {
return vec3(random_double(min,max),random_double(min,max),random_double(min,max)); return vec3(math::random_double(min,max),math::random_double(min,max),math::random_double(min,max));
} }
static vec3 random_in_unit_disk();
static vec3 random_unit_vector();
static vec3 random_in_unit_sphere();
static vec3 reflect(const vec3& v, const vec3& n);
static vec3 refract(const vec3& uv, const vec3& n, double etai_over_etat);
vec3() : e{0,0,0} {} vec3() : e{0,0,0} {}
vec3(double e0, double e1, double e2) : e{e0, e1, e2} {} vec3(double e0, double e1, double e2) : e{e0, e1, e2} {}
@ -129,57 +134,3 @@ inline vec3 unit_vector(vec3 v)
return v / v.length(); return v / v.length();
} }
vec3 random_in_unit_sphere()
{
while (true)
{
auto p = vec3::random(-1,1);
if (p.length_squared() >= 1) continue;
return p;
}
}
vec3 random_unit_vector()
{
auto a = random_double(0, 2*pi);
auto z = random_double(-1,1);
auto r = sqrt(1 - z*z);
return vec3(r*cos(a), r*sin(a), z);
}
vec3 random_in_hemisphere(const vec3& normal)
{
vec3 in_unit_sphere = random_in_unit_sphere();
if (dot(in_unit_sphere, normal) > 0.0)
{
return in_unit_sphere;
}
else
{
return -in_unit_sphere;
}
}
vec3 random_in_unit_disk()
{
while(true)
{
auto p = vec3(random_double(-1,1), random_double(-1,1), 0);
if (p.length_squared() >= 1) continue;
return p;
}
}
vec3 reflect(const vec3& v, const vec3& n)
{
return v - 2*dot(v,n)*n;
}
vec3 refract(const vec3& uv, const vec3& n, double etai_over_etat)
{
auto cos_theta = dot(-uv, n);
vec3 r_out_parallel = etai_over_etat * (uv + cos_theta*n);
vec3 r_out_perp = -sqrt(1.0 - r_out_parallel.length_squared()) * n;
return r_out_parallel + r_out_perp;
}

38
src/camera.cpp Normal file
View File

@ -0,0 +1,38 @@
#include "math.h"
#include "camera.h"
camera::camera(
point3 lookfrom,
point3 lookat,
vec3 vup,
double vfov, // vertical field of view in degrees
double aspect_ratio,
double aperture,
double focus_dist)
{
auto theta = math::degrees_to_radians(vfov);
auto h = tan(theta/2);
auto viewport_height = 2.0 * h;
auto viewport_width = aspect_ratio * viewport_height;
w_ = unit_vector(lookfrom - lookat);
u_ = unit_vector(cross(vup, w_));
v_ = cross(w_, u_);
origin_ = lookfrom;
horizontal_ = focus_dist * viewport_width * u_;
vertical_ = focus_dist * viewport_height * v_;
lower_left_corner_ = origin_ - horizontal_/2 - vertical_/2 - focus_dist * w_;
lens_radius_ = aperture / 2;
}
ray camera::get_ray(double s, double t) const
{
vec3 rd = lens_radius_ * vec3::random_in_unit_disk();
vec3 offset = (u_ * rd.x()) + (v_ * rd.y());
return ray(
origin_ + offset,
lower_left_corner_ + s*horizontal_ + t*vertical_ - origin_ - offset);
}

View File

@ -1,11 +1,13 @@
#pragma once #pragma once
#include "rtweekend.h" #include "math.h"
#include "vec3.h"
#include "ray.h"
#include "image.h" #include "image.h"
class camera class camera
{ {
public: public:
camera( camera(
point3 lookfrom, point3 lookfrom,
point3 lookat, point3 lookat,
@ -13,36 +15,11 @@ class camera
double vfov, // vertical field of view in degrees double vfov, // vertical field of view in degrees
double aspect_ratio, double aspect_ratio,
double aperture, double aperture,
double focus_dist) double focus_dist);
{
auto theta = degrees_to_radians(vfov);
auto h = tan(theta/2);
auto viewport_height = 2.0 * h;
auto viewport_width = aspect_ratio * viewport_height;
w_ = unit_vector(lookfrom - lookat); ray get_ray(double s, double t) const;
u_ = unit_vector(cross(vup, w_));
v_ = cross(w_, u_);
origin_ = lookfrom; private:
horizontal_ = focus_dist * viewport_width * u_;
vertical_ = focus_dist * viewport_height * v_;
lower_left_corner_ = origin_ - horizontal_/2 - vertical_/2 - focus_dist * w_;
lens_radius_ = aperture / 2;
}
ray get_ray(double s, double t) const
{
vec3 rd = lens_radius_ * random_in_unit_disk();
vec3 offset = (u_ * rd.x()) + (v_ * rd.y());
return ray(
origin_ + offset,
lower_left_corner_ + s*horizontal_ + t*vertical_ - origin_ - offset);
}
private:
point3 origin_; point3 origin_;
point3 lower_left_corner_; point3 lower_left_corner_;
vec3 horizontal_; vec3 horizontal_;

1
src/foo.cpp Normal file
View File

@ -0,0 +1 @@
#include "foo.h"

View File

@ -117,8 +117,8 @@ void render(camera& cam, hittable_list& world, int client_sock)
for (int s = 0; s < SAMPLES_PER_PIXEL; ++s) for (int s = 0; s < SAMPLES_PER_PIXEL; ++s)
{ {
auto u = (i + random_double()) / (WIDTH-1); auto u = (i + math::random_double()) / (WIDTH-1);
auto v = (j + random_double()) / (HEIGHT-1); auto v = (j + math::random_double()) / (HEIGHT-1);
ray r = cam.get_ray(u, v); ray r = cam.get_ray(u, v);
pixel_colour += ray_colour(r, world, MAX_DEPTH); pixel_colour += ray_colour(r, world, MAX_DEPTH);
} }

25
src/math.cpp Normal file
View File

@ -0,0 +1,25 @@
#include "math.h"
double math::random_double()
{
// returns a random real in [0,1)
return rand() / (RAND_MAX + 1.0);
}
double math::random_double(double min, double max)
{
// returns a random real in [min,max)
return min + (max-min)*math::random_double();
}
double math::degrees_to_radians(double degrees)
{
return degrees * math::pi / 180;
}
double math::clamp(double x, double min, double max)
{
if (x < min) return min;
if (x > max) return max;
return x;
}

View File

@ -1,48 +0,0 @@
#pragma once
#include <cmath>
#include <cstdlib>
#include <limits>
#include <memory>
// usings
using std::shared_ptr;
using std::make_shared;
using std::sqrt;
// constants
const double infinity = std::numeric_limits<double>::infinity();
const double pi = 3.1415926535897932385;
// utility functions
inline double degrees_to_radians(double degrees)
{
return degrees * pi / 180;
}
inline double random_double()
{
// returns a random real in [0,1)
return rand() / (RAND_MAX + 1.0);
}
inline double random_double(double min, double max)
{
// returns a random real in [min,max)
return min + (max-min)*random_double();
}
inline double clamp(double x, double min, double max)
{
if (x < min) return min;
if (x > max) return max;
return x;
}
// common headers
#include "error.h"
#include "ray.h"
#include "vec3.h"

57
src/vec3.cpp Normal file
View File

@ -0,0 +1,57 @@
#include "vec3.h"
vec3 vec3::random_unit_vector()
{
auto a = math::random_double(0, 2 * math::pi);
auto z = math::random_double(-1,1);
auto r = sqrt(1 - z*z);
return vec3(r*cos(a), r*sin(a), z);
}
vec3 vec3::reflect(const vec3& v, const vec3& n)
{
return v - 2*dot(v,n)*n;
}
vec3 vec3::refract(const vec3& uv, const vec3& n, double etai_over_etat)
{
auto cos_theta = dot(-uv, n);
vec3 r_out_parallel = etai_over_etat * (uv + cos_theta*n);
vec3 r_out_perp = -sqrt(1.0 - r_out_parallel.length_squared()) * n;
return r_out_parallel + r_out_perp;
}
vec3 vec3::random_in_unit_disk()
{
while(true)
{
auto p = vec3(math::random_double(-1,1), math::random_double(-1,1), 0);
if (p.length_squared() >= 1) continue;
return p;
}
}
vec3 vec3::random_in_unit_sphere()
{
while (true)
{
auto p = vec3::random(-1,1);
if (p.length_squared() >= 1) continue;
return p;
}
}
vec3 random_in_hemisphere(const vec3& normal)
{
vec3 in_unit_sphere = vec3::random_in_unit_sphere();
if (dot(in_unit_sphere, normal) > 0.0)
{
return in_unit_sphere;
}
else
{
return -in_unit_sphere;
}
}