From 0d0ce0a318c6c26128f24574cbc63005dcd4a757 Mon Sep 17 00:00:00 2001 From: ladevieq Date: Wed, 6 Jan 2021 00:34:02 +0100 Subject: Customisalbe camera with focus plan --- include/camera.hpp | 2 +- include/rt.hpp | 12 ++--- include/vk-renderer.hpp | 52 +++++++++++++--------- shaders/compute.comp | 41 ++++++++++------- src/camera.cpp | 6 +-- src/main.cpp | 114 ++++++++++++++++++++---------------------------- 6 files changed, 116 insertions(+), 111 deletions(-) diff --git a/include/camera.hpp b/include/camera.hpp index f1b199a..858833b 100644 --- a/include/camera.hpp +++ b/include/camera.hpp @@ -17,7 +17,7 @@ class camera { ray get_ray(double u, double v) const; point3 position; - double lens_radius; + float lens_radius; float viewport_width; float viewport_height; diff --git a/include/rt.hpp b/include/rt.hpp index 1961d35..09cf1b0 100644 --- a/include/rt.hpp +++ b/include/rt.hpp @@ -29,12 +29,12 @@ inline float clamp(float x, float min, float max) { #include "vec3.hpp" #include "ray.hpp" #include "color.hpp" -#include "sphere.hpp" +// #include "sphere.hpp" #include "camera.hpp" -#include "material.hpp" -#include "lambertian.hpp" -#include "metal.hpp" -#include "dielectric.hpp" -#include "hittable_list.hpp" +// #include "material.hpp" +// #include "lambertian.hpp" +// #include "metal.hpp" +// #include "dielectric.hpp" +// #include "hittable_list.hpp" #endif // !__RT_HPP_ diff --git a/include/vk-renderer.hpp b/include/vk-renderer.hpp index 2e996c8..311b3e5 100644 --- a/include/vk-renderer.hpp +++ b/include/vk-renderer.hpp @@ -12,34 +12,46 @@ enum MATERIAL_TYPE: uint32_t { DIELECTRIC, }; +struct material { + color albedo; + float fuzz; + float ior; + uint32_t type; + uint32_t padding; +}; + +struct sphere { + vec3 position; + material mat; + float radius; + float padding[3]; +}; + struct input_data { color sky_color; color ground_color; - vec3 camera_pos; - - uint32_t samples_per_pixel; - float viewport_width; - float viewport_height; - float proj_plane_distance; - float random_numbers[200]; + struct camera { + vec3 position; + vec3 up; + vec3 right; + vec3 forward; + float viewport_width; + float viewport_height; + float lens_radius; + float focus_distance; + } cam; + + float random_offset[200]; + float random_disk[200]; vec3 random_in_sphere[1000]; - struct sphere { - vec3 position; - struct material { - color albedo; - float fuzz; - float ior; - uint32_t type; - uint32_t padding; - } material; - float radius; - float padding[3]; - } spheres[5]; + sphere spheres[512]; uint32_t max_bounce; - float padding[3]; + uint32_t samples_per_pixel; + + float padding[2]; }; struct path_tracer_data { diff --git a/shaders/compute.comp b/shaders/compute.comp index 92fae9d..83302b9 100644 --- a/shaders/compute.comp +++ b/shaders/compute.comp @@ -30,24 +30,31 @@ struct sphere { float[3] padding; }; -layout(set = 0, binding = 0) buffer Inputs { - vec4 sky_color; - vec4 ground_color; - vec4 camera_pos; - - uint samples_per_pixel; +struct camera { + vec4 position; + vec4 up; + vec4 right; + vec4 forward; float viewport_width; float viewport_height; - float proj_plane_distance; + float lens_radius; + float focus_distance; +}; - float[200] random_numbers; +layout(set = 0, binding = 0) buffer Inputs { + vec4 sky_color; + vec4 ground_color; + camera cam; + vec2[100] random_offset; + vec2[100] random_disk; vec4[1000] random_in_sphere; - sphere[5] spheres; + sphere[512] spheres; uint max_bounce; - float [3] padding; + uint samples_per_pixel; + float [2] padding; vec4[] image; }; @@ -105,7 +112,7 @@ bool hit_spheres(ray r, float min_t, float max_t, out hit_info info) { float closest_t = max_t; hit_info temp_info; bool hit = false; - for (uint sphere_index = 0; sphere_index < 5; sphere_index++) { + for (uint sphere_index = 0; sphere_index < 512; sphere_index++) { if (hit_sphere(spheres[sphere_index], r, min_t, closest_t, temp_info)) { info = temp_info; closest_t = temp_info.t; @@ -199,15 +206,19 @@ void main() { uint height = gl_NumWorkGroups.y; vec2 uv = vec2(float(x) / (width - 1), 1.0 - (float(y) / (height - 1))); - vec3 first = camera_pos.xyz - vec3(viewport_width / 2.0, viewport_height / 2.0, proj_plane_distance); + vec3 horizontal = cam.focus_distance * cam.right.xyz * cam.viewport_width; + vec3 vertical = cam.focus_distance * cam.up.xyz * cam.viewport_height; + vec3 first = cam.position.xyz - horizontal / 2.0 - vertical / 2.0 + cam.focus_distance * cam.forward.xyz; image[y * width + x] = vec4(0.0); for (uint sample_index = 0; sample_index < samples_per_pixel; sample_index++) { - vec2 jittered_uvs = uv + vec2(random_numbers[sample_index * 2] / (width - 1), random_numbers[sample_index * 2 + 1] / (height - 1)); - vec3 proj_plane_pos = first + vec3(jittered_uvs.x * viewport_width, jittered_uvs.y * viewport_height, 0.0); + vec2 jittered_uvs = uv + vec2(random_disk[sample_index].x / (width - 1), random_disk[sample_index].y / (height - 1)); + vec2 lens_disk = random_disk[sample_index] * cam.lens_radius; + vec3 offset = lens_disk.x * cam.right.xyz + lens_disk.y * cam.up.xyz; + vec3 proj_plane_pos = first + jittered_uvs.x * horizontal + jittered_uvs.y * vertical; - image[y * width + x] += ray_color(ray(camera_pos.xyz, proj_plane_pos - camera_pos.xyz), sample_index); + image[y * width + x] += ray_color(ray(cam.position.xyz + offset, proj_plane_pos - cam.position.xyz - offset), sample_index); } float spp_scale = (1.0 / samples_per_pixel); diff --git a/src/camera.cpp b/src/camera.cpp index 592f3d5..c7e2e35 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -11,9 +11,9 @@ camera::camera( double focus_dist ) : position(position), lens_radius(aperture / 2.0) { - forward = (position - target).unit(); - right = vec3{ 0.0, 1.0, 0.0 }.cross(forward).unit(); - up = forward.cross(right).unit(); + forward = (target - position).unit(); + right = forward.cross(vec3{ 0.0, 1.0, 0.0 }).unit(); + up = right.cross(forward).unit(); auto h = tan(deg_to_rad(v_fov) / 2.0); viewport_height = 2.0 * h; diff --git a/src/main.cpp b/src/main.cpp index 66b1f6a..af8334f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -10,11 +10,12 @@ color ground_color { 1.0, 1.0, 1.0 }; color sky_color { 0.5, 0.7, 1.0 }; -hittable_list random_scene() { - hittable_list world; +void random_scene(sphere *world) { + material ground_material = { { 0.5, 0.5, 0.5 } }; + ground_material.type = MATERIAL_TYPE::LAMBERTIAN; + world[0] = sphere{ { 0,-1000,0 }, ground_material, 1000 }; - auto ground_material = std::make_shared(color{ 0.5, 0.5, 0.5 }); - world.add(std::make_shared(point3{ 0,-1000,0 }, 1000, ground_material)); + uint32_t world_sphere_index = 1; for (int a = -11; a < 11; a++) { for (int b = -11; b < 11; b++) { @@ -22,59 +23,44 @@ hittable_list random_scene() { point3 center(a + 0.9 * randd(), 0.2, b + 0.9 * randd()); if ((center - point3{ 4, 0.2, 0 }).length() > 0.9) { - std::shared_ptr sphere_material; + material sphere_material = {}; if (choose_mat < 0.8) { // diffuse - auto albedo = color::random() * color::random(); - sphere_material = std::make_shared(albedo); - world.add(std::make_shared(center, 0.2, sphere_material)); + sphere_material.albedo = color::random() * color::random(); + sphere_material.type = MATERIAL_TYPE::LAMBERTIAN; } else if (choose_mat < 0.95) { // metal - auto albedo = color::random(0.5, 1); - auto fuzz = randd(0, 0.5); - sphere_material = std::make_shared(albedo, fuzz); - world.add(std::make_shared(center, 0.2, sphere_material)); + sphere_material.albedo = color::random(0.5, 1); + sphere_material.fuzz = randd(0, 0.5); + sphere_material.type = MATERIAL_TYPE::METAL; } else { // glass - sphere_material = std::make_shared(1.5); - world.add(std::make_shared(center, 0.2, sphere_material)); + sphere_material.ior = 1.5; + sphere_material.type = MATERIAL_TYPE::DIELECTRIC; } - } - } - } - - auto material1 = std::make_shared(1.5); - world.add(std::make_shared(point3{ 0, 1, 0 }, 1.0, material1)); - - auto material2 = std::make_shared(color{ 0.4, 0.2, 0.1 }); - world.add(std::make_shared(point3{ -4, 1, 0 }, 1.0, material2)); - - auto material3 = std::make_shared(color{ 0.7, 0.6, 0.5 }, 0.0); - world.add(std::make_shared(point3{ 4, 1, 0 }, 1.0, material3)); - - return world; -} -color ray_color(ray& r, const hittable& world, uint32_t depth) { - if (depth <= 0) { - return color{}; - } - - struct hit_info info; - if (world.hit(r, 0.001, infinity, info)) { - color attenuation; - ray scattered {}; - - if (info.mat_ptr->scatter(r, info, attenuation, scattered)) { - return attenuation * ray_color(scattered, world, depth - 1); + world[world_sphere_index] = { center, sphere_material, 0.2 }; + world_sphere_index++; + } } - return color{}; } - auto unit_dir = r.direction.unit(); - auto t = (unit_dir.y + 1.0) * 0.5; - return lerp(ground_color, sky_color, t); + material material1 = {}; + material1.ior = 1.5; + material1.type = MATERIAL_TYPE::DIELECTRIC; + world[world_sphere_index] = { { 0, 1, 0 }, material1, 1.0 }; + + material material2 = {}; + material2.albedo = color{ 0.4, 0.2, 0.1 }; + material2.type = MATERIAL_TYPE::LAMBERTIAN; + world[world_sphere_index + 1] = { { -4, 1, 0 }, material2, 1.0 }; + + material material3 = {}; + material3.albedo = color{ 0.7, 0.6, 0.5 }; + material3.fuzz = 0.0; + material3.type = MATERIAL_TYPE::METAL; + world[world_sphere_index + 2] = { { 4, 1, 0 }, material3, 1.0 }; } int main() { @@ -82,38 +68,34 @@ int main() { // Image dimensions const float aspect_ratio = 16.0 / 9.0; - // const float aspect_ratio = 1.0; const size_t width = 1920; const size_t height = width / aspect_ratio; const uint32_t samples_per_pixel = 100; const uint32_t max_depth = 100; - // const vec3 camera_position{ 13.0, 2.0, 3.0 }; - const vec3 camera_position{ 0.0, 0.0, 0.0 }; - const vec3 camera_target{ 0.0, 0.0, 1.0 }; - const double aperture = 0.1; - const double distance_to_focus = 10; + const vec3 camera_position{ 13.0, 2.0, 3.0 }; + const vec3 camera_target{ 0.0, 0.0, 0.0 }; + const float aperture = 0.1; + const float distance_to_focus = 10; camera camera { camera_position, camera_target, 20.0, aspect_ratio, aperture, distance_to_focus }; struct input_data inputs = { .sky_color = sky_color, .ground_color = ground_color, - .camera_pos = camera_position, - .samples_per_pixel = samples_per_pixel, - .viewport_width = 2.f * aspect_ratio, - .viewport_height = 2.f, - .proj_plane_distance = 1.f, - .spheres = { - { { -1.f, 0.f, -1.f }, { { 0.8f, 0.8f, 0.8f }, 0.3, 1.5, MATERIAL_TYPE::DIELECTRIC }, 0.5f }, - { { -1.f, 0.f, -1.f }, { { 0.8f, 0.8f, 0.8f }, 0.3, 1.5, MATERIAL_TYPE::DIELECTRIC }, -0.4f }, - { { 0.f, 0.f, -1.f }, { { 0.7f, 0.3f, 0.3f }, 0.0, 1.5, MATERIAL_TYPE::DIELECTRIC }, 0.5f }, - { { 1.f, 0.f, -1.f }, { { 0.8f, 0.6f, 0.2f }, 1.0, 0.0, MATERIAL_TYPE::METAL }, 0.5f }, - { { 0.f, -100.5f, -1.f }, { { 0.8f, 0.8f, 0.f }, 0.0, 0.0, MATERIAL_TYPE::LAMBERTIAN }, 100.f } - }, + .cam = { camera_position, camera.up, camera.right, camera.forward, camera.viewport_width, camera.viewport_height, camera.lens_radius, distance_to_focus }, + .spheres = {}, .max_bounce = max_depth, + .samples_per_pixel = samples_per_pixel, }; - for (size_t rand_number_index = 0; rand_number_index < samples_per_pixel * 2; rand_number_index++) { - inputs.random_numbers[rand_number_index] = randd(); + for (size_t rand_number_index = 0; rand_number_index < samples_per_pixel * 2; rand_number_index += 2) { + inputs.random_offset[rand_number_index] = randd(); + inputs.random_offset[rand_number_index + 1] = randd(); + } + + for (size_t rand_number_index = 0; rand_number_index < samples_per_pixel * 2; rand_number_index += 2) { + vec3 random_unit_disk = random_in_unit_disk(); + inputs.random_disk[rand_number_index] = random_unit_disk.x; + inputs.random_disk[rand_number_index + 1] = random_unit_disk.y; } for (size_t rand_number_index = 0; rand_number_index < max_depth * 10; rand_number_index++) { @@ -121,7 +103,7 @@ int main() { } // World hittable objects - hittable_list world = random_scene(); + random_scene(inputs.spheres); // PPM format header std::cout << "P3\n" << width << '\n' << height << "\n255" << std::endl; -- cgit v1.3