camera lens + random scene

This commit is contained in:
K Tyl 2020-06-07 04:13:39 +01:00
parent ac6cc84bf5
commit c41297b074
3 changed files with 110 additions and 41 deletions

View File

@ -5,22 +5,40 @@
class camera
{
public:
const double ASPECT_RATIO = 16.0 / 9.0;
const double VIEWPORT_HEIGHT = 2.0;
const double VIEWPORT_WIDTH = ASPECT_RATIO * VIEWPORT_HEIGHT;
const double FOCAL_LENGTH = 1.0;
camera() :
origin_ (point3(0,0,0)),
horizontal_ (vec3(VIEWPORT_WIDTH,0.0,0.0)),
vertical_ (vec3(0.0, VIEWPORT_HEIGHT, 0.0))
camera(
point3 lookfrom,
point3 lookat,
vec3 vup,
double vfov, // vertical field of view in degrees
double aspect_ratio,
double aperture,
double focus_dist)
{
lower_left_corner_ = origin_ - horizontal_/2 - vertical_/2 - vec3(0,0,FOCAL_LENGTH);
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 u, double v) const
ray get_ray(double s, double t) const
{
return ray(origin_, lower_left_corner_ + u*horizontal_ + v*vertical_ - origin_);
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:
@ -28,4 +46,6 @@ class camera
point3 lower_left_corner_;
vec3 horizontal_;
vec3 vertical_;
vec3 u_, v_, w_;
double lens_radius_;
};

View File

@ -8,11 +8,11 @@
#include <iostream>
const double ASPECT_RATIO = 16.0 / 9.0;
const int WIDTH = 384;
const double ASPECT_RATIO = 32.0 / 9.0;
const int WIDTH = 800;
const int HEIGHT = static_cast<int>(WIDTH / ASPECT_RATIO);
const int SAMPLES_PER_PIXEL = 100;
const int MAX_DEPTH = 50;
const int SAMPLES_PER_PIXEL = 32;
const int MAX_DEPTH = 16;
colour ray_colour(const ray& r, const hittable& world, int depth)
{
@ -38,41 +38,80 @@ colour ray_colour(const ray& r, const hittable& world, int depth)
vec3 unit_direction = unit_vector(r.direction());
auto t = 0.5 * (unit_direction.y() + 1.0);
auto a = colour(0.5, 0.6, 0.7);
auto b = colour(0.5, 0.5, 0.5);
auto a = colour(0.8, 0.7, 1.0);
auto b = colour(1.0, 1.0, 1.0);
return lerp(a, b, t);
}
hittable_list random_scene()
{
hittable_list world;
auto ground_material = make_shared<lambertian>(colour(0.5, 0.5, 0.5));
world.add(make_shared<sphere>(point3(0,-1000,0), 1000, ground_material));
for (int a = -11; a < 11; a++)
{
for (int b = -11; b < 11; b++)
{
auto choose_mat = random_double();
point3 centre(a + 0.9*random_double(), 0.2, b + 0.9*random_double());
if ((centre - point3(4, 0.2, 0)).length() > 0.9)
{
shared_ptr<material> sphere_material;
if (choose_mat < 0.8)
{
// diffuse
auto albedo = colour::random() * colour::random();
sphere_material = make_shared<lambertian>(albedo);
world.add(make_shared<sphere>(centre, 0.2, sphere_material));
}
else if (choose_mat < 0.95)
{
// metal
auto albedo = colour::random(0.5, 1);
auto fuzz = random_double(0, 0.5);
sphere_material = make_shared<metal>(albedo, fuzz);
world.add(make_shared<sphere>(centre, 0.2, sphere_material));
}
else
{
// glass
sphere_material = make_shared<dielectric>(1.5);
world.add(make_shared<sphere>(centre,0.2, sphere_material));
}
}
}
}
auto material1 = make_shared<dielectric>(1.5);
world.add(make_shared<sphere>(point3(0, 1, 0), 1.0, material1));
auto material2 = make_shared<lambertian>(colour(0.4, 0.2, 0.1));
world.add(make_shared<sphere>(point3(-4, 1, 0), 1.0, material2));
auto material3 = make_shared<metal>(colour(0.7, 0.6, 0.5), 0.0);
world.add(make_shared<sphere>(point3(4, 1, 0), 1.0, material3));
return world;
}
int main()
{
std::cout << "P3\n" << WIDTH << ' ' << HEIGHT << "\n255\n";
hittable_list world;
hittable_list world = random_scene();
world.add(make_shared<sphere>(
point3(0,0,-1),
0.5,
make_shared<lambertian>(colour(0.1,0.2,0.5))));
world.add(make_shared<sphere>(
point3(0,-100.5,-1),
100,
make_shared<lambertian>(colour(0.8,0.8,0.0))));
point3 lookfrom(13,2,3);
point3 lookat(0,0,0);
vec3 vup(0,1,0);
auto dist_to_focus = 10.0;
auto aperture = 0.1;
world.add(make_shared<sphere>(
point3(1,0,-1),
0.5,
make_shared<metal>(colour(0.8,0.6,0.2), 0.0)));
world.add(make_shared<sphere>(
point3(-1,0,-1),
0.5,
make_shared<dielectric>(1.5)));
world.add(make_shared<sphere>(
point3(-1,0,-1),
-0.45,
make_shared<dielectric>(1.5)));
camera cam;
camera cam(lookfrom, lookat, vup, 20, ASPECT_RATIO, aperture, dist_to_focus);
for (int j = HEIGHT - 1; j >= 0; --j)
{

View File

@ -160,6 +160,16 @@ vec3 random_in_hemisphere(const vec3& normal)
}
}
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;