many changes, more controls

main
Clyne 6 months ago
parent af1740bde3
commit 7d174816fe
Signed by: clyne
GPG Key ID: 1B74EE6C49C96795

1
.gitignore vendored

@ -1,4 +1,5 @@
*.o *.o
*.png
*.sw* *.sw*
main main
imgui.ini imgui.ini

@ -1,9 +1,10 @@
CXXFLAGS := -std=c++23 -O3 -ggdb -g3 -march=native -mtune=native `sdl2-config --cflags` -Iimgui -Iimgui/backends 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 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 image.ppm: main
time ./main > image.ppm time ./main > image.ppm

@ -1,7 +1,7 @@
constexpr unsigned Width = 1000; constexpr unsigned Width = 1000;
constexpr double Aspect = 16.0 / 9.0; constexpr double Aspect = 16.0 / 9.0;
constexpr unsigned Height = Width / Aspect; constexpr unsigned Height = Width / Aspect;
constexpr unsigned Threads = 8; constexpr unsigned Threads = 3;
#include "color.h" #include "color.h"
#include "ray.h" #include "ray.h"
@ -15,6 +15,7 @@ constexpr unsigned Threads = 8;
#include "imgui_impl_sdl2.h" #include "imgui_impl_sdl2.h"
#include "imgui_impl_sdlrenderer2.h" #include "imgui_impl_sdlrenderer2.h"
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <algorithm> #include <algorithm>
#include <chrono> #include <chrono>
@ -23,10 +24,10 @@ constexpr unsigned Threads = 8;
#include <ranges> #include <ranges>
#include <thread> #include <thread>
static World world;
static View Camera; static View Camera;
static World world;
static int SamplesPerPixel = 20; static int SamplesPerPixel = 20;
static float Daylight = 0.5f;
static std::unique_ptr<Renderer<Threads>> renderer; static std::unique_ptr<Renderer<Threads>> renderer;
static std::chrono::time_point<std::chrono::high_resolution_clock> renderStart; static std::chrono::time_point<std::chrono::high_resolution_clock> renderStart;
static std::chrono::duration<double> renderTime; static std::chrono::duration<double> renderTime;
@ -37,6 +38,7 @@ static void initiateRender(SDL_Surface *canvas);
int main() int main()
{ {
SDL_Init(SDL_INIT_VIDEO); 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 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 canvas = SDL_CreateRGBSurfaceWithFormat(0, Width, Height, 32, SDL_PIXELFORMAT_RGBA8888);
auto painter = SDL_CreateRenderer(window, -1, SDL_RENDERER_PRESENTVSYNC /*| SDL_RENDERER_ACCELERATED*/); auto painter = SDL_CreateRenderer(window, -1, SDL_RENDERER_PRESENTVSYNC /*| SDL_RENDERER_ACCELERATED*/);
@ -52,6 +54,7 @@ int main()
std::cout << "Spawning threads..." << std::endl; std::cout << "Spawning threads..." << std::endl;
initiateRender(canvas); initiateRender(canvas);
auto tex = SDL_CreateTextureFromSurface(painter, canvas);
std::cout << "Entering render..." << std::endl; std::cout << "Entering render..." << std::endl;
bool run = true; 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("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::SameLine(); ImGui::SetNextItemWidth(100); ImGui::InputDouble("Z", &Camera.camera.z(), 0.1, 0.05, "%.2lf");
ImGui::SliderInt("samples", &SamplesPerPixel, 1, 200); ImGui::SliderInt("samples", &SamplesPerPixel, 1, 200);
ImGui::SliderFloat("shade", &Daylight, 0.f, 1.f);
if (ImGui::Button("recalculate")) { if (ImGui::Button("recalculate")) {
initiateRender(canvas); initiateRender(canvas);
} }
ImGui::SameLine(); 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")) { if (ImGui::Button("exit")) {
renderer->stop(); renderer->stop();
run = false; run = false;
} }
if (*renderer) { if (*renderer) {
SDL_DestroyTexture(tex);
tex = SDL_CreateTextureFromSurface(painter, canvas);
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::Button("stop")) { if (ImGui::Button("stop")) {
renderer->stop(); renderer->stop();
} }
ImGui::Text("wait... %u%%", renderer->progress()); ImGui::Text("wait... %u%%", renderer->progress());
} else if (renderTime == std::chrono::duration<double>::zero()) { } else if (renderTime == std::chrono::duration<double>::zero()) {
SDL_DestroyTexture(tex);
tex = SDL_CreateTextureFromSurface(painter, canvas);
renderTime = std::chrono::high_resolution_clock::now() - renderStart; renderTime = std::chrono::high_resolution_clock::now() - renderStart;
} else { } else {
ImGui::Text("%0.6lfs", renderTime.count()); ImGui::Text("%0.6lfs", renderTime.count());
} }
ImGui::End(); ImGui::End();
ImGui::Begin("balls", nullptr, ImGuiWindowFlags_AlwaysAutoResize); { ImGui::Begin("balls", nullptr, ImGuiWindowFlags_NoResize); {
char radius[] = "radius 0"; char radius[] = "radius 0";
char mat[] = "mat 0"; char mat[] = "mat 0";
char xpos[] = "x 0"; char xpos[] = "x 0";
char ypos[] = "y 0"; char ypos[] = "y 0";
char zpos[] = "z 0"; char zpos[] = "z 0";
for (auto& o : std::views::drop(world.objects, 1)) { for (auto& o : std::views::drop(world.objects, 1)) {
ImGui::Combo(mat, reinterpret_cast<int *>(&o.M), "Lambertian\0Metal\0Dielectric\0"); ImGui::SetNextItemWidth(200);
ImGui::SameLine(); ImGui::SetNextItemWidth(100); ImGui::InputDouble(radius, &o.radius, 0.1, 0.05, "%.2lf"); ImGui::Combo(mat, reinterpret_cast<int *>(&o.M),
ImGui::SetNextItemWidth(100); ImGui::InputDouble(xpos, &o.center.x(), 0.05, 0.05, "%.2lf"); "Lambertian\0Metal\0Dielectric\0");
ImGui::SameLine(); ImGui::SetNextItemWidth(100); ImGui::InputDouble(ypos, &o.center.y(), 0.1, 0.05, "%.2lf"); ImGui::SameLine(); ImGui::SetNextItemWidth(100);
ImGui::SameLine(); ImGui::SetNextItemWidth(100); ImGui::InputDouble(zpos, &o.center.z(), 0.1, 0.05, "%.2lf"); 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]++; radius[7]++;
mat[4]++; mat[4]++;
xpos[2]++; xpos[2]++;
ypos[2]++; ypos[2]++;
zpos[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(); } ImGui::End();
auto tex = SDL_CreateTextureFromSurface(painter, canvas);
ImGui::Render(); ImGui::Render();
SDL_RenderClear(painter); SDL_RenderClear(painter);
SDL_RenderCopy(painter, tex, nullptr, nullptr); SDL_RenderCopy(painter, tex, nullptr, nullptr);
ImGui_ImplSDLRenderer2_RenderDrawData(ImGui::GetDrawData()); ImGui_ImplSDLRenderer2_RenderDrawData(ImGui::GetDrawData());
SDL_RenderPresent(painter); SDL_RenderPresent(painter);
SDL_DestroyTexture(tex);
std::this_thread::sleep_for(std::chrono::milliseconds(30)); 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); return atten * ray_color(scat, depth - 1);
} else { } else {
const auto unitDir = r.direction().normalize(); 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); return (1.0 - a) * color(1.0, 1.0, 1.0) + a * color(0.5, 0.7, 1.0);
} }
} }

@ -94,6 +94,10 @@ struct vec3 {
auto rpara = v * -std::sqrt(std::fabs(1.0 - rperp.length_squared())); auto rpara = v * -std::sqrt(std::fabs(1.0 - rperp.length_squared()));
return rperp + rpara; 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. // 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() { inline vec3 randomUnitSphere() {
for (;;) { 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; return p;
} }
} }

@ -12,11 +12,11 @@ struct View
static constexpr auto vup = vec3(0, 1, 0); // Camera-relative "up" direction static constexpr auto vup = vec3(0, 1, 0); // Camera-relative "up" direction
float fieldOfView = 90.f; float fieldOfView = 90.f;
point3 camera {0, 0.5, 0.5};
float focalLength; float focalLength;
float viewportHeight; float viewportHeight;
float viewportWidth; float viewportWidth;
point3 camera;
vec3 viewportX; vec3 viewportX;
vec3 viewportY; vec3 viewportY;
vec3 pixelDX; vec3 pixelDX;

Loading…
Cancel
Save