add camera
This commit is contained in:
parent
dec83055a4
commit
07d4587584
|
@ -0,0 +1,73 @@
|
|||
#ifndef CAMERA_H
|
||||
#define CAMERA_H
|
||||
|
||||
#include "common.h"
|
||||
#include "hittable.h"
|
||||
|
||||
class Camera {
|
||||
public:
|
||||
double aspect_ratio = 1.0; // Ratio of image width over height
|
||||
int image_width = 100; // Rendered image width in pixel count
|
||||
|
||||
void render(const hittable &world, Canvas &canvas) {
|
||||
initialize();
|
||||
|
||||
for (int j = 0; j < canvas.height; j++) {
|
||||
for (int i = 0; i < canvas.width; i++) {
|
||||
auto pixel_center =
|
||||
pixel00_loc + (i * pixel_delta_u) + (j * pixel_delta_v);
|
||||
auto ray_direction = pixel_center - center;
|
||||
Ray r(center, ray_direction);
|
||||
|
||||
canvas.set_pixel(i, j, ray_color(r, world));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void move_to(Point3 loc) { center = loc; }
|
||||
|
||||
private:
|
||||
int image_height; // Rendered image height
|
||||
Point3 center = Point3(0, 0, 0);
|
||||
Point3 pixel00_loc; // Location of pixel 0, 0
|
||||
Vec3 pixel_delta_u; // Offset to pixel to the right
|
||||
Vec3 pixel_delta_v; // Offset to pixel below
|
||||
|
||||
void initialize() {
|
||||
image_height = int(image_width / aspect_ratio);
|
||||
image_height = (image_height < 1) ? 1 : image_height;
|
||||
|
||||
// Determine viewport dimensions.
|
||||
auto focal_length = 1.0;
|
||||
auto viewport_height = 2.0;
|
||||
auto viewport_width =
|
||||
viewport_height * (double(image_width) / image_height);
|
||||
|
||||
// Calculate the vectors across the horizontal and down the vertical
|
||||
// viewport edges.
|
||||
auto viewport_u = Vec3(viewport_width, 0, 0);
|
||||
auto viewport_v = Vec3(0, -viewport_height, 0);
|
||||
|
||||
// Calculate the horizontal and vertical delta vectors from pixel to pixel.
|
||||
pixel_delta_u = viewport_u / image_width;
|
||||
pixel_delta_v = viewport_v / image_height;
|
||||
|
||||
// Calculate the location of the upper left pixel.
|
||||
auto viewport_upper_left =
|
||||
center - Vec3(0, 0, focal_length) - viewport_u / 2 - viewport_v / 2;
|
||||
pixel00_loc = viewport_upper_left + 0.5 * (pixel_delta_u + pixel_delta_v);
|
||||
}
|
||||
|
||||
Color ray_color(const Ray &r, const hittable &world) {
|
||||
hit_record rec;
|
||||
if (world.hit(r, 0, infinity, rec)) {
|
||||
return 0.5 * (rec.normal + Color(1, 1, 1));
|
||||
}
|
||||
|
||||
Vec3 unit_direction = unit_vector(r.direction());
|
||||
auto a = 0.5 * (unit_direction.y() + 1.0);
|
||||
return (1.0 - a) * Color(1.0, 1.0, 1.0) + a * Color(0.5, 0.7, 1.0);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,6 +1,6 @@
|
|||
#include "simulation.h"
|
||||
#include "camera.h"
|
||||
#include "common.h"
|
||||
#include "hittable.h"
|
||||
#include "hittable_list.h"
|
||||
#include "sphere.h"
|
||||
|
||||
|
@ -124,73 +124,32 @@ void simulation_thread(RingBuffer<SimulationState> &buffer) {
|
|||
}
|
||||
}
|
||||
|
||||
Color ray_color(const Ray &r, const hittable &world) {
|
||||
hit_record rec;
|
||||
if (world.hit(r, 0, infinity, rec)) {
|
||||
return 0.5 * (rec.normal + Color(1, 1, 1));
|
||||
}
|
||||
|
||||
Vec3 unit_direction = unit_vector(r.direction());
|
||||
auto a = 0.5 * (unit_direction.y() + 1.0);
|
||||
return (1.0 - a) * Color(1.0, 1.0, 1.0) + a * Color(0.5, 0.7, 1.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render raytracing.
|
||||
*/
|
||||
void render(SimulationState state, Canvas &canvas) {
|
||||
hittable_list world;
|
||||
|
||||
const double SCALE = 1e9;
|
||||
|
||||
for (auto b : state.bodies) {
|
||||
// we need to swap y and z because the raytracter uses opengl style coordinates
|
||||
auto bb = b.position / SCALE;
|
||||
world.add(make_shared<sphere>(Vec3(bb.x(), bb.z(), bb.y()), b.radius));
|
||||
}
|
||||
|
||||
// Camera
|
||||
auto focal_length = 1.0;
|
||||
auto viewport_height = 2.0;
|
||||
auto viewport_width = viewport_height * (float(canvas.width) / canvas.height);
|
||||
auto camera_center = Point3(0, 0, 100);
|
||||
|
||||
// Calculate the vectors across the horizontal and down the vertical viewport
|
||||
// edges.
|
||||
auto viewport_u = Vec3(viewport_width, 0, 0);
|
||||
auto viewport_v = Vec3(0, -viewport_height, 0);
|
||||
|
||||
// Calculate the horizontal and vertical delta vectors from pixel to pixel.
|
||||
auto pixel_delta_u = viewport_u / canvas.width;
|
||||
auto pixel_delta_v = viewport_v / canvas.height;
|
||||
|
||||
// Calculate the location of the upper left pixel.
|
||||
auto viewport_upper_left = camera_center - Vec3(0, 0, focal_length) -
|
||||
viewport_u / 2 - viewport_v / 2;
|
||||
auto pixel00_loc =
|
||||
viewport_upper_left + 0.5 * (pixel_delta_u + pixel_delta_v);
|
||||
|
||||
for (int j = 0; j < canvas.height; j++) {
|
||||
for (int i = 0; i < canvas.width; i++) {
|
||||
auto pixel_center =
|
||||
pixel00_loc + (i * pixel_delta_u) + (j * pixel_delta_v);
|
||||
auto ray_direction = pixel_center - camera_center;
|
||||
Ray r(camera_center, ray_direction);
|
||||
|
||||
canvas.set_pixel(i, j, ray_color(r, world));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Render thread.
|
||||
*/
|
||||
void render_thread(RingBuffer<SimulationState> &buffer, Canvas &canvas) {
|
||||
Camera cam;
|
||||
cam.aspect_ratio = 16.0 / 9.0;
|
||||
cam.image_width = 400;
|
||||
cam.move_to(Point3(0, 0, 100));
|
||||
|
||||
while (running) {
|
||||
auto maybe_state = buffer.pop();
|
||||
if (maybe_state.has_value()) {
|
||||
const SimulationState &state = maybe_state.value();
|
||||
render(state, canvas); // Pure function: write pixel colors into canvas
|
||||
|
||||
hittable_list world;
|
||||
|
||||
const double SCALE = 1e9;
|
||||
|
||||
for (auto b : state.bodies) {
|
||||
// we need to swap y and z because the raytracter uses opengl style
|
||||
// coordinates
|
||||
auto bb = b.position / SCALE;
|
||||
world.add(make_shared<sphere>(Vec3(bb.x(), bb.z(), bb.y()), b.radius));
|
||||
}
|
||||
|
||||
cam.render(world, canvas);
|
||||
} else {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue