un-fix threads; more refactoring

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

@ -1,7 +1,6 @@
constexpr unsigned Width = 1000;
constexpr double Aspect = 16.0 / 9.0;
constexpr unsigned Height = Width / Aspect;
constexpr unsigned Threads = 3;
#include "color.h"
#include "ray.h"
@ -26,14 +25,17 @@ constexpr unsigned Threads = 3;
static View Camera;
static World world;
static int threads = 4;
static int SamplesPerPixel = 20;
static float Daylight = 0.5f;
static std::unique_ptr<Renderer<Threads>> renderer;
static std::unique_ptr<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, Sphere& o);
static void addRandomObject();
int main()
{
@ -47,10 +49,10 @@ int main()
ImGui_ImplSDL2_InitForSDLRenderer(window, painter);
ImGui_ImplSDLRenderer2_Init(painter);
world.add(point3( 0.00, -100.50, -1.0), 100.0, Material::Lambertian, color(0.5, 1.0, 0.5));
world.add(point3(-0.50, 0.00, -1.2), 0.5, Material::Dielectric, color(1.0, 0.8, 0.8));
world.add(point3( 0.50, 0.00, -1.0), 0.5, Material::Metal, color(0.5, 0.5, 0.5));
world.add(point3(-0.05, -0.35, -0.7), 0.1, Material::Metal, color(0.8, 0.6, 0.0));
world.add(point3(0.00, -100.50, -1.0), 100.0,
Material::Lambertian, color(0.5, 1.0, 0.5));
for (auto i : std::views::iota(0, 10))
addRandomObject();
std::cout << "Spawning threads..." << std::endl;
initiateRender(canvas);
@ -73,11 +75,17 @@ int main()
ImGui::Begin("settings", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
ImGui::SliderFloat("fov", &Camera.fieldOfView, 10, 160);
ImGui::SetNextItemWidth(100); ImGui::InputDouble("X", &Camera.camera.x(), 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(60);
ImGui::InputInt("T", &threads);
ImGui::SetNextItemWidth(100);
ImGui::InputDouble("X", &Camera.camera.x(), 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::SliderInt("samples", &SamplesPerPixel, 1, 200);
ImGui::SliderFloat("shade", &Daylight, 0.f, 1.f);
if (ImGui::Button("recalculate")) {
initiateRender(canvas);
}
@ -94,6 +102,7 @@ int main()
renderer->stop();
run = false;
}
if (*renderer) {
SDL_DestroyTexture(tex);
tex = SDL_CreateTextureFromSurface(painter, canvas);
@ -114,35 +123,13 @@ int main()
ImGui::End();
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::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]++;
}
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")) {
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);
addRandomObject();
initiateRender(canvas);
}
if (ImGui::Button("del")) {
@ -200,5 +187,37 @@ void initiateRender(SDL_Surface *canvas)
};
Camera.recalculate();
renderer.reset(new Renderer<Threads>(func, Width, Height, (uint32_t *)canvas->pixels));
threads = std::clamp(threads, 1, Renderer::MaxThreads);
renderer.reset(new Renderer(threads, func, Width, Height,
(uint32_t *)canvas->pixels));
}
void showObjectControls(int index, Sphere& o)
{
const auto idx = std::to_string(index);
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::SetNextItemWidth(100);
ImGui::InputDouble((std::string("x") + idx).c_str(),
&o.center.x(), 0.05, 0.05, "%.2lf");
ImGui::SameLine(); ImGui::SetNextItemWidth(100);
ImGui::InputDouble((std::string("y") + idx).c_str(),
&o.center.y(), 0.1, 0.05, "%.2lf");
ImGui::SameLine(); ImGui::SetNextItemWidth(100);
ImGui::InputDouble((std::string("z") + idx).c_str(),
&o.center.z(), 0.1, 0.05, "%.2lf");
}
void addRandomObject()
{
const point3 pos = vec3::random() * vec3(6, 0.8, 3) - vec3(3, 0, 3.8);
const color col = vec3::random();
const auto mat = (int)(randomN() * ((int)Material::Undefined - 1));
world.add(pos, randomN() * 0.3 + 0.05, (Material)mat, col);
}

@ -6,7 +6,7 @@
inline double randomN()
{
static std::uniform_real_distribution<double> distribution (0.0, 1.0);
static std::mt19937 generator;
static std::mt19937 generator (std::random_device{}());
return distribution(generator);
}

@ -1,3 +1,6 @@
#ifndef RENDERER_H
#define RENDERER_H
#include <algorithm>
#include <atomic>
#include <memory>
@ -5,28 +8,32 @@
#include <semaphore>
#include <thread>
template<int Threads>
class Renderer
{
std::counting_semaphore<Threads> Workers;
public:
static constexpr int MaxThreads = 64;
private:
int N;
std::counting_semaphore<MaxThreads> Workers;
std::atomic_uint processed;
unsigned total;
std::atomic_bool Stop;
std::unique_ptr<std::thread> primary;
public:
Renderer(auto func, unsigned Width, unsigned Height, auto pbuf):
Workers(Threads), processed(0), total(Threads * 8)
Renderer(int n, auto func, unsigned width, unsigned height, auto pbuf):
N(n), Workers(N), processed(0), total(N * 8)
{
Stop.store(false);
auto threads = std::views::transform(
std::views::chunk(
std::views::cartesian_product(
std::views::iota(0u, Width),
std::views::iota(0u, Height),
std::views::iota(0u, width),
std::views::iota(0u, height),
std::views::single(pbuf)),
Width * Height / total),
width * height / total),
[=, this](auto chunk) { return std::thread([=, this] { worker(func, chunk); }); });
primary.reset(new std::thread([=, this] {
@ -34,10 +41,8 @@ public:
Workers.acquire();
th.detach();
}
for (auto i : std::views::iota(0, Threads))
for (int i : std::views::iota(0, N))
Workers.acquire();
for (auto i : std::views::iota(0, Threads))
Workers.release();
Stop.store(true);
}));
}
@ -73,4 +78,5 @@ private:
}
};
#endif // RENDERER_H

@ -10,9 +10,10 @@
#include <tuple>
enum class Material : int {
Lambertian,
Lambertian = 0,
Metal,
Dielectric
Dielectric,
Undefined
};
struct Sphere

Loading…
Cancel
Save