]> code.bitgloo.com Git - clyne/raytracer.git/commitdiff
many changes, more controls
authorClyne Sullivan <clyne@bitgloo.com>
Tue, 14 May 2024 23:58:40 +0000 (19:58 -0400)
committerClyne Sullivan <clyne@bitgloo.com>
Tue, 14 May 2024 23:58:40 +0000 (19:58 -0400)
.gitignore
Makefile
main.cpp
vec3.h
view.h

index aedd486b441cca0e797eeffcaef7bff00aae1b74..2b90f68f7f8b406a95822887905ad590a13f0275 100644 (file)
@@ -1,4 +1,5 @@
 *.o
+*.png
 *.sw*
 main
 imgui.ini
index 838da7eb6758c2016de8b011a103c7628e806d4e..9c5a43a96c74f3e3156681d55ddb691eb92f2b54 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,9 +1,10 @@
 CXXFLAGS := -std=c++23 -O3 -ggdb -g3 -march=native -mtune=native `sdl2-config --cflags` -Iimgui -Iimgui/backends
-LDFLAGS := `sdl2-config --libs`
+LDFLAGS := `sdl2-config --libs` -lSDL2_image
 
 all: main
 
-main: imgui/imgui.o imgui/imgui_draw.o imgui/imgui_widgets.o imgui/imgui_tables.o imgui/backends/imgui_impl_sdl2.o imgui/backends/imgui_impl_sdlrenderer2.o
+main: main.cpp imgui/imgui.o imgui/imgui_draw.o imgui/imgui_widgets.o imgui/imgui_tables.o imgui/backends/imgui_impl_sdl2.o imgui/backends/imgui_impl_sdlrenderer2.o
+       g++ $(CXXFLAGS) $^ $(LDFLAGS) -o main
 
 image.ppm: main
        time ./main > image.ppm
index 034aefa2ec85a655fc450fb208b0f4116659ffd9..bd749abd6bd5b61189a613779ec55ae336e3348c 100644 (file)
--- a/main.cpp
+++ b/main.cpp
@@ -1,7 +1,7 @@
 constexpr unsigned Width = 1000;
 constexpr double   Aspect = 16.0 / 9.0;
 constexpr unsigned Height = Width / Aspect;
-constexpr unsigned Threads = 8;
+constexpr unsigned Threads = 3;
 
 #include "color.h"
 #include "ray.h"
@@ -15,6 +15,7 @@ constexpr unsigned Threads = 8;
 #include "imgui_impl_sdl2.h"
 #include "imgui_impl_sdlrenderer2.h"
 #include <SDL2/SDL.h>
+#include <SDL2/SDL_image.h>
 
 #include <algorithm>
 #include <chrono>
@@ -23,10 +24,10 @@ constexpr unsigned Threads = 8;
 #include <ranges>
 #include <thread>
 
-static World world;
-
 static View Camera;
+static World world;
 static int SamplesPerPixel = 20;
+static float Daylight = 0.5f;
 static std::unique_ptr<Renderer<Threads>> renderer;
 static std::chrono::time_point<std::chrono::high_resolution_clock> renderStart;
 static std::chrono::duration<double> renderTime;
@@ -37,6 +38,7 @@ static void initiateRender(SDL_Surface *canvas);
 int main()
 {
     SDL_Init(SDL_INIT_VIDEO);
+    IMG_Init(IMG_INIT_PNG);
     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*/);
@@ -52,6 +54,7 @@ int main()
 
     std::cout << "Spawning threads..." << std::endl;
     initiateRender(canvas);
+    auto tex = SDL_CreateTextureFromSurface(painter, canvas);
 
     std::cout << "Entering render..." << std::endl;
     bool run = true;
@@ -74,55 +77,85 @@ int main()
         ImGui::SameLine(); ImGui::SetNextItemWidth(100); ImGui::InputDouble("Y", &Camera.camera.y(), 0.1, 0.05, "%.2lf");
         ImGui::SameLine(); ImGui::SetNextItemWidth(100); ImGui::InputDouble("Z", &Camera.camera.z(), 0.1, 0.05, "%.2lf");
         ImGui::SliderInt("samples", &SamplesPerPixel, 1, 200);
+        ImGui::SliderFloat("shade", &Daylight, 0.f, 1.f);
         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;
+        }
+        ImGui::SameLine();
         if (ImGui::Button("exit")) {
             renderer->stop();
             run = false;
         }
         if (*renderer) {
+            SDL_DestroyTexture(tex);
+            tex = SDL_CreateTextureFromSurface(painter, canvas);
+
             ImGui::SameLine();
             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;
         } else {
             ImGui::Text("%0.6lfs", renderTime.count());
         }
         ImGui::End();
 
-        ImGui::Begin("balls", nullptr, ImGuiWindowFlags_AlwaysAutoResize); {
+        ImGui::Begin("balls", nullptr, ImGuiWindowFlags_NoResize); {
             char radius[] = "radius 0";
             char mat[] = "mat 0";
             char xpos[] = "x 0";
             char ypos[] = "y 0";
             char zpos[] = "z 0";
+
             for (auto& o : std::views::drop(world.objects, 1)) {
-                ImGui::Combo(mat, reinterpret_cast<int *>(&o.M), "Lambertian\0Metal\0Dielectric\0");
-                ImGui::SameLine(); ImGui::SetNextItemWidth(100); ImGui::InputDouble(radius, &o.radius, 0.1, 0.05, "%.2lf");
-                ImGui::SetNextItemWidth(100); ImGui::InputDouble(xpos, &o.center.x(), 0.05, 0.05, "%.2lf");
-                ImGui::SameLine(); ImGui::SetNextItemWidth(100); ImGui::InputDouble(ypos, &o.center.y(), 0.1, 0.05, "%.2lf");
-                ImGui::SameLine(); ImGui::SetNextItemWidth(100); ImGui::InputDouble(zpos, &o.center.z(), 0.1, 0.05, "%.2lf");
+                ImGui::SetNextItemWidth(200);
+                ImGui::Combo(mat, reinterpret_cast<int *>(&o.M),
+                    "Lambertian\0Metal\0Dielectric\0");
+                ImGui::SameLine(); ImGui::SetNextItemWidth(100);
+                ImGui::InputDouble(radius, &o.radius, 0.1, 0.05, "%.2lf");
+                ImGui::SetNextItemWidth(100);
+                ImGui::InputDouble(xpos, &o.center.x(), 0.05, 0.05, "%.2lf");
+                ImGui::SameLine(); ImGui::SetNextItemWidth(100);
+                ImGui::InputDouble(ypos, &o.center.y(), 0.1, 0.05, "%.2lf");
+                ImGui::SameLine(); ImGui::SetNextItemWidth(100);
+                ImGui::InputDouble(zpos, &o.center.z(), 0.1, 0.05, "%.2lf");
+
                 radius[7]++;
                 mat[4]++;
                 xpos[2]++;
                 ypos[2]++;
                 zpos[2]++;
             }
+            if (ImGui::Button("add")) {
+                const point3 pos = vec3::random() * vec3(4, 1.5, 4) - vec3(2, 0, 4);
+                const color col = vec3::random();
+                world.add(pos, randomN() * 0.5 + 0.1, Material::Lambertian, col);
+                initiateRender(canvas);
+            }
+            if (ImGui::Button("del")) {
+                world.objects.pop_back();
+                initiateRender(canvas);
+            }
         } ImGui::End();
 
-        auto tex = SDL_CreateTextureFromSurface(painter, canvas);
-
         ImGui::Render();
         SDL_RenderClear(painter);
         SDL_RenderCopy(painter, tex, nullptr, nullptr);
         ImGui_ImplSDLRenderer2_RenderDrawData(ImGui::GetDrawData());
         SDL_RenderPresent(painter);
-        SDL_DestroyTexture(tex);
 
         std::this_thread::sleep_for(std::chrono::milliseconds(30));
     }
@@ -148,7 +181,7 @@ color ray_color(const ray& r, int depth)
         return atten * ray_color(scat, depth - 1);
     } else {
         const auto unitDir = r.direction().normalize();
-        const auto a = 0.5 * (unitDir.y() + 1.0);
+        const auto a = Daylight * (unitDir.y() + 1.0);
         return (1.0 - a) * color(1.0, 1.0, 1.0) + a * color(0.5, 0.7, 1.0);
     }
 }
diff --git a/vec3.h b/vec3.h
index 46367d21a51c8baa357ce9e6b4e2ca967453c67f..b648ce3a2d3ff4e8d4f1b70320e6c49926f15a56 100644 (file)
--- a/vec3.h
+++ b/vec3.h
@@ -94,6 +94,10 @@ struct vec3 {
         auto rpara = v * -std::sqrt(std::fabs(1.0 - rperp.length_squared()));
         return rperp + rpara;
     }
+
+    static vec3 random() {
+        return vec3(randomN(), randomN(), randomN());
+    }
 };
 
 // point3 is just an alias for vec3, but useful for geometric clarity in the code.
@@ -125,7 +129,7 @@ inline constexpr vec3 unit_vector(const vec3& v) {
 
 inline vec3 randomUnitSphere() {
     for (;;) {
-        if (auto p = vec3(randomN(), randomN(), randomN()) * 2 - vec3(1, 1, 1); p.length_squared() < 1)
+        if (auto p = vec3::random() * 2 - vec3(1, 1, 1); p.length_squared() < 1)
             return p;
     }
 }
diff --git a/view.h b/view.h
index e27176e27ecc0846096ee98c23574e93ec553bb1..0f973580cb422790091d6fd142da293849991fe3 100644 (file)
--- a/view.h
+++ b/view.h
@@ -12,11 +12,11 @@ struct View
     static constexpr auto vup    = vec3(0, 1, 0);    // Camera-relative "up" direction
 
     float fieldOfView = 90.f;
+    point3 camera {0, 0.5, 0.5};
+
     float focalLength;
     float viewportHeight;
     float viewportWidth;
-
-    point3 camera;
     vec3 viewportX;
     vec3 viewportY;
     vec3 pixelDX;