diff options
Diffstat (limited to 'main.cpp')
-rw-r--r-- | main.cpp | 128 |
1 files changed, 72 insertions, 56 deletions
@@ -30,15 +30,17 @@ static int threads = 4; static int SamplesPerPixel = 20; static int SamplesPerPixelTmp = 20; static float Daylight = 0.5f; -static std::unique_ptr<Renderer> renderer; +static Renderer renderer; static std::chrono::time_point<std::chrono::high_resolution_clock> renderStart; static std::chrono::duration<double> renderTime; static color ray_color(const ray& r, int depth = 50); static void initiateRender(SDL_Surface *canvas); static void showObjectControls(int index, std::unique_ptr<Object>& o); +static void showCameraControls(SDL_Surface *canvas); static void addRandomObject(); static void preview(SDL_Surface *canvas); +static void exportScreenshot(SDL_Surface *canvas); int main() { @@ -47,6 +49,8 @@ int main() auto window = SDL_CreateWindow("raytrace", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, Width, Height, SDL_WINDOW_RESIZABLE); auto canvas = SDL_CreateRGBSurfaceWithFormat(0, Width, Height, 32, SDL_PIXELFORMAT_RGBA8888); auto painter = SDL_CreateRenderer(window, -1, SDL_RENDERER_PRESENTVSYNC /*| SDL_RENDERER_ACCELERATED*/); + auto tex = SDL_CreateTextureFromSurface(painter, canvas); + bool run = true; ImGui::CreateContext(); ImGui_ImplSDL2_InitForSDLRenderer(window, painter); @@ -57,17 +61,12 @@ int main() for (auto i : std::views::iota(0, 10)) addRandomObject(); - std::cout << "Spawning threads..." << std::endl; initiateRender(canvas); - auto tex = SDL_CreateTextureFromSurface(painter, canvas); - - std::cout << "Entering render..." << std::endl; - bool run = true; for (SDL_Event event; run;) { while (SDL_PollEvent(&event)) { ImGui_ImplSDL2_ProcessEvent(&event); if (event.type == SDL_QUIT) { - renderer->stop(); + renderer.stop(); run = false; } } @@ -80,51 +79,36 @@ int main() if (ImGui::SliderFloat("fov", &Camera.fieldOfView, 10, 160)) preview(canvas); ImGui::SameLine(); ImGui::SetNextItemWidth(80); - ImGui::InputInt("T", &threads); - ImGui::SetNextItemWidth(100); - if (ImGui::InputDouble("X", &Camera.camera.x(), 0.1, 0.05, "%.2lf")) - preview(canvas); - ImGui::SameLine(); ImGui::SetNextItemWidth(100); - if (ImGui::InputDouble("Y", &Camera.camera.y(), 0.1, 0.05, "%.2lf")) - preview(canvas); - ImGui::SameLine(); ImGui::SetNextItemWidth(100); - if (ImGui::InputDouble("Z", &Camera.camera.z(), 0.1, 0.05, "%.2lf")) - preview(canvas); + if (ImGui::InputInt("T", &threads)) + threads = std::max(threads, 1); + showCameraControls(canvas); if (ImGui::SliderInt("samples", &SamplesPerPixel, 1, 200)) { SamplesPerPixelTmp = SamplesPerPixel; } ImGui::SliderFloat("shade", &Daylight, 0.25f, 1.f); - if (ImGui::Button("recalculate")) { + if (ImGui::Button("recalculate")) initiateRender(canvas); - } ImGui::SameLine(); - if (ImGui::Button("export")) { - std::string filename ("screenshot_"); - filename += std::to_string(int(randomN() * 1000000)); - filename += ".png"; - IMG_SavePNG(canvas, filename.c_str()); - std::cout << "saved " << filename << std::endl; - } + if (ImGui::Button("export")) + exportScreenshot(canvas); ImGui::SameLine(); if (ImGui::Button("exit")) { - renderer->stop(); + renderer.stop(); run = false; } - if (*renderer) { + if (renderer) { SDL_DestroyTexture(tex); tex = SDL_CreateTextureFromSurface(painter, canvas); ImGui::SameLine(); - if (ImGui::Button("stop")) { - renderer->stop(); - } - ImGui::Text("wait... %u%%", renderer->progress()); + if (ImGui::Button("stop")) + renderer.stop(); + ImGui::Text("wait... %u%%", renderer.progress()); } else if (renderTime == std::chrono::duration<double>::zero()) { SDL_DestroyTexture(tex); tex = SDL_CreateTextureFromSurface(painter, canvas); - renderTime = std::chrono::high_resolution_clock::now() - renderStart; SamplesPerPixel = SamplesPerPixelTmp; } else { @@ -132,21 +116,20 @@ int main() } ImGui::End(); - ImGui::Begin("balls", nullptr, ImGuiWindowFlags_NoResize); { - std::ranges::for_each( - std::views::zip(std::views::iota(0), - std::views::drop(world.objects, 1)), - [](auto io) { std::apply(showObjectControls, io); }); + ImGui::Begin("balls", nullptr, ImGuiWindowFlags_NoResize); + std::ranges::for_each( + std::views::zip(std::views::iota(0), std::views::drop(world.objects, 1)), + [](auto io) { std::apply(showObjectControls, io); }); - if (ImGui::Button("add")) { - addRandomObject(); - initiateRender(canvas); - } - if (ImGui::Button("del")) { - world.objects.pop_back(); - initiateRender(canvas); - } - } ImGui::End(); + if (ImGui::Button("add")) { + addRandomObject(); + initiateRender(canvas); + } + if (ImGui::Button("del")) { + world.objects.pop_back(); + initiateRender(canvas); + } + ImGui::End(); ImGui::Render(); SDL_RenderClear(painter); @@ -185,21 +168,23 @@ color ray_color(const ray& r, int depth) void initiateRender(SDL_Surface *canvas) { - renderStart = std::chrono::high_resolution_clock::now(); + if (renderer) + renderer.stop(); + renderTime = std::chrono::duration<double>::zero(); - auto func = [format = canvas->format](auto x, auto y, auto pbuf) { + auto func = [format = canvas->format](auto x, auto y) { auto col = std::ranges::fold_left(std::views::iota(0, SamplesPerPixel), color(), [y, x](color c, int i) { return c + ray_color(Camera.getRay(x, y, true)); }); col = col / SamplesPerPixel * 255; - pbuf[y * Width + x] = SDL_MapRGBA(format, col.x(), col.y(), col.z(), 255); + return SDL_MapRGB(format, col.x(), col.y(), col.z()); }; Camera.recalculate(); - threads = std::clamp(threads, 1, Renderer::MaxThreads); - renderer.reset(new Renderer(threads, func, Width, Height, - (uint32_t *)canvas->pixels)); + renderer.setBuffer((uint32_t *)canvas->pixels, Width, Height); + renderStart = std::chrono::high_resolution_clock::now(); + renderer.start(func, threads); } void showObjectControls(int index, std::unique_ptr<Object>& o) @@ -209,9 +194,9 @@ void showObjectControls(int index, std::unique_ptr<Object>& o) ImGui::SetNextItemWidth(200); ImGui::Combo((std::string("mat") + idx).c_str(), reinterpret_cast<int *>(&o->M), "Lambertian\0Metal\0Dielectric\0"); - //ImGui::SameLine(); ImGui::SetNextItemWidth(100); - //ImGui::InputDouble((std::string("radius") + idx).c_str(), - // &o->radius, 0.1, 0.05, "%.2lf"); + ImGui::SameLine(); ImGui::SetNextItemWidth(100); + ImGui::InputDouble((std::string("radius") + idx).c_str(), + &dynamic_cast<Sphere *>(o.get())->radius, 0.1, 0.05, "%.2lf"); ImGui::SetNextItemWidth(100); ImGui::InputDouble((std::string("x") + idx).c_str(), &o->center.x(), 0.05, 0.05, "%.2lf"); @@ -223,6 +208,28 @@ void showObjectControls(int index, std::unique_ptr<Object>& o) &o->center.z(), 0.1, 0.05, "%.2lf"); } +void showCameraControls(SDL_Surface *canvas) +{ + ImGui::SetNextItemWidth(100); + if (ImGui::InputDouble("X", &Camera.camera.x(), 0.1, 0.05, "%.2lf")) + preview(canvas); + ImGui::SameLine(); ImGui::SetNextItemWidth(100); + if (ImGui::InputDouble("Y", &Camera.camera.y(), 0.1, 0.05, "%.2lf")) + preview(canvas); + ImGui::SameLine(); ImGui::SetNextItemWidth(100); + if (ImGui::InputDouble("Z", &Camera.camera.z(), 0.1, 0.05, "%.2lf")) + preview(canvas); + ImGui::SetNextItemWidth(100); + if (ImGui::InputDouble("I", &Camera.lookat.x(), 0.1, 0.05, "%.2lf")) + preview(canvas); + ImGui::SameLine(); ImGui::SetNextItemWidth(100); + if (ImGui::InputDouble("J", &Camera.lookat.y(), 0.1, 0.05, "%.2lf")) + preview(canvas); + ImGui::SameLine(); ImGui::SetNextItemWidth(100); + if (ImGui::InputDouble("K", &Camera.lookat.z(), 0.1, 0.05, "%.2lf")) + preview(canvas); +} + void addRandomObject() { const point3 pos = vec3::random() * vec3(6, 0.8, 3) - vec3(3, 0, 3.8); @@ -238,3 +245,12 @@ void preview(SDL_Surface *canvas) initiateRender(canvas); } +void exportScreenshot(SDL_Surface *canvas) +{ + std::string filename ("screenshot_"); + filename += std::to_string(int(randomN() * 1000000)); + filename += ".png"; + IMG_SavePNG(canvas, filename.c_str()); + std::cout << "saved " << filename << std::endl; +} + |