From fba6ab469570de132c68ab89a1617929c50cfd4d Mon Sep 17 00:00:00 2001 From: Keuin Date: Thu, 21 Apr 2022 21:01:53 +0800 Subject: Add final render scene. --- main_final_render.cpp | 151 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 main_final_render.cpp (limited to 'main_final_render.cpp') diff --git a/main_final_render.cpp b/main_final_render.cpp new file mode 100644 index 0000000..1b93a81 --- /dev/null +++ b/main_final_render.cpp @@ -0,0 +1,151 @@ +// +// Created by Keuin on 2022/4/21. +// + +#include "viewport.h" +#include "hitlist.h" +#include "aa.h" +#include "bitmap.h" + +#include "material_diffusive.h" +#include "material_reflective.h" +#include "material_dielectric.h" + +#include "sphere.h" + +#include "timer.h" + +#include +#include +#include +#include + +template +class final_scene { + hitlist world; + std::vector materials; +public: + explicit final_scene(uint64_t seed); + + ~final_scene() { + for (material *item: materials) { + delete item; + } + } + + bitmap render(uint32_t image_width, uint32_t image_height, uint32_t spp) { + aa_viewport camera{ + {13, 2, 3}, + {6.5, 1, 1.5}, //{0, 0, 0}, + static_cast(image_width), + static_cast(image_height), + 24.0 * (M_PI / 180.0), + 0.1, + 2.432043413435534, + world, + spp + }; + return camera.render(); + } +}; + +template +final_scene::final_scene(uint64_t seed) : world{} { + std::mt19937_64 rand{seed}; + std::uniform_real_distribution uni{0, 1}; + material *m_ball; + + // earth + m_ball = new material_diffuse_lambertian{{0.5, 0.5, 0.5}}; + world.add_object(std::make_shared(vec3d{0, -1000, 0}, 1000.0, *m_ball)); + materials.push_back(m_ball); + + // add random small balls + for (int i = -11; i < 11; ++i) { + for (int j = -11; j < 11; ++j) { + double rv = uni(rand); + vec3d center{i + 0.9 * uni(rand), 0.2, j + 0.9 * uni(rand)}; + + if ((center - vec3d{4, 0.2, 0}).norm() > 0.9) { + + if (rv < 0.8) { + // diffuse + const auto albedo = vec3d{ + uni(rand) * uni(rand), + uni(rand) * uni(rand), + uni(rand) * uni(rand) + }; + m_ball = new material_diffuse_lambertian{albedo}; + world.add_object(std::make_shared(center, 0.2, *m_ball)); + } else if (rv < 0.95) { + // metal + auto albedo = vec3d{ + 0.5 * uni(rand) + 0.5, + 0.5 * uni(rand) + 0.5, + 0.5 * uni(rand) + 0.5 + }; + auto fuzz = 0.5 * uni(rand); + m_ball = new material_fuzzy_reflective{albedo, fuzz}; + world.add_object(std::make_shared(center, 0.2, *m_ball)); + } else { + // glass + m_ball = new material_dielectric{1.5}; + world.add_object(std::make_shared(center, 0.2, *m_ball)); + } + materials.push_back(m_ball); + } + } + } + + // add three big balls + material *mat; + mat = new material_dielectric{1.5}; + world.add_object(std::make_shared( + vec3d{0, 1, 0}, + 1.0, + *mat + )); + materials.push_back(mat); + + mat = new material_diffuse_lambertian{{0.4, 0.2, 0.1}}; + world.add_object(std::make_shared( + vec3d{-4, 1, 0}, + 1.0, + *mat + )); + materials.push_back(mat); + + mat = new material_reflective{{0.7, 0.6, 0.5}}; // not fuzzy + world.add_object(std::make_shared( + vec3d{4, 1, 0}, + 1.0, + *mat + )); + materials.push_back(mat); +} + + +int main(int argc, char *argv[]) { + if (argc != 4) { + printf("%s \n", argv[0]); + return 0; + } + std::string s_image_width{argv[1]}, s_image_height{argv[2]}, s_spp{argv[3]}; + uint32_t image_width = std::stoul(s_image_width); + uint32_t image_height = std::stoul(s_image_height); + uint32_t spp = std::stoul(s_spp); + std::cerr << "image size: " << image_width << "*" << image_height << std::endl + << "spp: " << spp << std::endl; + + final_scene scene{0x793def6344ef29d4}; + timer tm; + std::cerr << "Start rendering..." << std::endl; + tm.start_measure(); + const auto image = scene.render(image_width, image_height, spp); + tm.stop_measure(); + std::cerr << "Apply gamma2 correction..." << std::endl; + tm.start_measure(); + const auto image2 = image.gamma2(); + tm.stop_measure(); + image2.write_plain_ppm(std::cout); +} \ No newline at end of file -- cgit v1.2.3