Repository navigation
Expand file tree
/
Copy pathmain.cpp
More file actions
118 lines (93 loc) · 4.13 KB
/
Copy pathmain.cpp
File metadata and controls
118 lines (93 loc) · 4.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#include <iostream>
#include <fstream>
#include <memory>
#include <string>
#include <vector>
#include <chrono>
#include "vec3.h"
#include "ray.h"
#include "hittable_list.h"
#include "sphere.h"
#include "material.h"
#include "triangle.h"
#include "mesh.h"
Vec3 ray_color(const Ray& r, const Hittable& world, int depth) {
HitRecord rec;
if (depth <= 0) return Vec3(0, 0, 0);
if (world.hit(r, 0.001f, 1000.0f, rec)) {
Ray scattered;
Vec3 attenuation;
if (rec.mat_ptr->scatter(r, rec, attenuation, scattered)) {
Vec3 color_from_scatter = ray_color(scattered, world, depth - 1);
return Vec3(attenuation.x * color_from_scatter.x / 255.0f,
attenuation.y * color_from_scatter.y / 255.0f,
attenuation.z * color_from_scatter.z / 255.0f);
}
return Vec3(0, 0, 0);
}
Vec3 unit_direction = r.direction().normalize();
float sky_t = 0.5f * (unit_direction.y + 1.0f);
return Vec3(255.0, 255.0, 255.0) * (1.0f - sky_t) + Vec3(127.0, 178.0, 255.0) * sky_t;
}
int main(int argc, char* argv[]) {
if (argc < 2) {
std::cerr << "Error: No 3D model provided.\n";
std::cerr << "Usage: .\\raytracer <filename.obj>\n";
return 1;
}
std::string model_filename = argv[1];
const int image_width = 256;
const int image_height = 256;
int samples_per_pixel = 50;
int max_depth = 50;
HittableList world;
auto material_ground = std::make_shared<Lambertian>(Vec3(204, 204, 0));
auto material_right = std::make_shared<Metal>(Vec3(204, 153, 51));
world.add(std::make_shared<Sphere>(Vec3( 0.0, -100.5, -1.0), 100.0, material_ground));
// 1. Dropped Y to -0.3 so the models sit perfectly on the ground.
// 2. Brought Z forward to -1.5 so it's closer to the camera.
// 3. Cranked the universal scale up to 2.5f so it fills the screen!
world.add(std::make_shared<Mesh>(model_filename, material_right, Vec3(0.0, -0.3, -1.5), 2.5f));
Vec3 origin(0.0, 0.0, 0.0);
Vec3 lower_left_corner(-1.0, -1.0, -1.0);
Vec3 horizontal(2.0, 0.0, 0.0);
Vec3 vertical(0.0, 2.0, 0.0);
// Framebuffer setup
std::vector<Vec3> framebuffer(image_width * image_height);
std::cout << "Rendering on multiple threads... please wait.\n";
auto start_time = std::chrono::high_resolution_clock::now();
#pragma omp parallel for schedule(dynamic)
for (int j = image_height - 1; j >= 0; --j) {
for (int i = 0; i < image_width; ++i) {
Vec3 pixel_color(0, 0, 0);
for (int s = 0; s < samples_per_pixel; ++s) {
float u = (float(i) + random_float()) / (image_width - 1);
float v = (float(j) + random_float()) / (image_height - 1);
Ray r(origin, lower_left_corner + (horizontal * u) + (vertical * v) - origin);
pixel_color = pixel_color + ray_color(r, world, max_depth);
}
float scale = 1.0f / samples_per_pixel;
float r_color = std::sqrt((pixel_color.x * scale) / 255.0f) * 255.0f;
float g_color = std::sqrt((pixel_color.y * scale) / 255.0f) * 255.0f;
float b_color = std::sqrt((pixel_color.z * scale) / 255.0f) * 255.0f;
framebuffer[j * image_width + i] = Vec3(r_color, g_color, b_color);
}
}
auto end_time = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> render_time = end_time - start_time;
std::cout << "Engine finished in " << render_time.count() << " seconds!\n";
std::cout << "Writing to image.ppm...\n";
std::ofstream out_file("image.ppm");
out_file << "P3\n" << image_width << ' ' << image_height << "\n255\n";
for (int j = image_height - 1; j >= 0; --j) {
for (int i = 0; i < image_width; ++i) {
Vec3 color = framebuffer[j * image_width + i];
out_file << static_cast<int>(color.x) << ' '
<< static_cast<int>(color.y) << ' '
<< static_cast<int>(color.z) << '\n';
}
}
out_file.close();
std::cout << "Done!\n";
return 0;
}