agent: implement a commandline interface for render parameters except model loading
This commit is contained in:
+45
-9
@@ -2,32 +2,63 @@
|
||||
#include "cpu/CPURenderer.h"
|
||||
#include "metal/MetalRenderer.h"
|
||||
#include "util/ModelLoader.h"
|
||||
#include "util/CLI.h"
|
||||
#include <imgui.h>
|
||||
|
||||
int main()
|
||||
int main(int argc, const char* argv[])
|
||||
{
|
||||
// Parse command-line arguments
|
||||
CLIArgs cliArgs = parseCLIArgs(argc, argv);
|
||||
|
||||
// Show help if requested
|
||||
if (cliArgs.help)
|
||||
{
|
||||
printUsage(argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Create renderer
|
||||
std::unique_ptr<Renderer> renderer = std::make_unique<MetalRenderer>();
|
||||
renderer->addDirectionalLight(DirectionalLight{
|
||||
.direction = glm::normalize(glm::vec3(-0.4f, -0.3f, -0.2f)),
|
||||
.color = glm::vec3(1, 1, 1),
|
||||
});
|
||||
renderer->addPointLight(PointLight{});
|
||||
|
||||
// Add lights from CLI arguments, or use defaults if none specified
|
||||
if (cliArgs.pointLights.empty() && cliArgs.directionalLights.empty())
|
||||
{
|
||||
// Use default lights when no CLI lights are specified
|
||||
renderer->addDirectionalLight(DirectionalLight{
|
||||
.direction = glm::normalize(glm::vec3(-0.4f, -0.3f, -0.2f)),
|
||||
.color = glm::vec3(1, 1, 1),
|
||||
});
|
||||
renderer->addPointLight(PointLight{});
|
||||
}
|
||||
else
|
||||
{
|
||||
// Apply lights from CLI arguments
|
||||
applyCLIToScene(*renderer, cliArgs);
|
||||
}
|
||||
|
||||
renderer->addModels(ModelLoader::loadModel("../res/models/stanford-bunny.obj"),
|
||||
glm::mat4(glm::vec4(1.0f, 0.0f, 0.0f, 0.0f), glm::vec4(0.0f, 1.0f, 0.0f, 0.0f), glm::vec4(0.0f, 0.0f, 1.0f, 0.0f),
|
||||
glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)));
|
||||
renderer->generate();
|
||||
|
||||
// Initialize camera and render parameters with defaults
|
||||
Camera camera = Camera{
|
||||
.position = glm::vec3(2, 1, 2),
|
||||
.target = glm::vec3(0, 0, 0),
|
||||
.f = 0,
|
||||
.A = 0,
|
||||
.S_O = 6,
|
||||
.f = 0.7f,
|
||||
.A = 0.35f,
|
||||
.S_O = 20.0f,
|
||||
};
|
||||
RenderParameter render = RenderParameter{
|
||||
.width = 1920,
|
||||
.height = 1080,
|
||||
.numSamples = 10000,
|
||||
};
|
||||
|
||||
// Apply CLI arguments (overrides defaults for specified values)
|
||||
applyCLIToCamera(camera, cliArgs);
|
||||
applyCLIToRenderParams(render, cliArgs);
|
||||
|
||||
renderer->startRender(camera, render);
|
||||
|
||||
while (true)
|
||||
@@ -39,6 +70,11 @@ int main()
|
||||
ImGui::InputFloat("Focal Length", &camera.f);
|
||||
ImGui::InputFloat("Aperture", &camera.A);
|
||||
ImGui::InputFloat("S_O", &camera.S_O);
|
||||
ImGui::InputFloat2("Sensor Size", &camera.sensorSize.x);
|
||||
ImGui::Text("Material Parameters");
|
||||
ImGui::InputFloat3("Fog Emissive", &camera.fogEmm.x);
|
||||
ImGui::InputFloat("Specular Coeff", &camera.ks);
|
||||
ImGui::InputFloat("Ambient Coeff", &camera.ka);
|
||||
ImGui::Text("Render Parameters");
|
||||
ImGui::InputInt2("Dimensions", (int*)&render.width);
|
||||
ImGui::InputInt("Samples", (int*)&render.numSamples);
|
||||
|
||||
@@ -195,10 +195,10 @@ void MetalRenderer::render(Camera camera, RenderParameter parameter)
|
||||
.f = camera.f,
|
||||
.cameraForward = camera.target - camera.position,
|
||||
.S_O = camera.S_O,
|
||||
.fogEmm = glm::vec3(0, 0, 0),
|
||||
.ks = 0,
|
||||
.fogEmm = camera.fogEmm,
|
||||
.ks = camera.ks,
|
||||
.A = camera.A,
|
||||
.ka = 0,
|
||||
.ka = camera.ka,
|
||||
.sensorSize = camera.sensorSize,
|
||||
.width = parameter.width,
|
||||
.height = parameter.height,
|
||||
|
||||
@@ -0,0 +1,403 @@
|
||||
#include "CLI.h"
|
||||
#include "scene/Renderer.h"
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <cstdlib>
|
||||
|
||||
void printUsage(const char* programName)
|
||||
{
|
||||
std::cout << "Usage: " << programName << " [options]\n"
|
||||
<< "\n"
|
||||
<< "Camera Parameters:\n"
|
||||
<< " --pos <x> <y> <z> Camera position (default: 2 1 2)\n"
|
||||
<< " --target <x> <y> <z> Camera target (default: 0 0 0)\n"
|
||||
<< " --focal <f> Focal length in meters (default: 0.7)\n"
|
||||
<< " --aperture <A> Aperture radius in meters (default: 0.35)\n"
|
||||
<< " --subject-dist <d> Subject distance S_O in meters (default: 20)\n"
|
||||
<< " --sensor <w> <h> Sensor size in meters (default: 0.036 0.024)\n"
|
||||
<< "\n"
|
||||
<< "Material Parameters:\n"
|
||||
<< " --fog <r> <g> <b> Fog emissive color (default: 0 0 0)\n"
|
||||
<< " --specular <s> Specular coefficient (default: 0)\n"
|
||||
<< " --ambient <a> Ambient coefficient (default: 0)\n"
|
||||
<< "\n"
|
||||
<< "Light Parameters:\n"
|
||||
<< " --point-light <x> <y> <z> <r> <g> <b> [attenuation]\n"
|
||||
<< " Add a point light (default attenuation: 1.0)\n"
|
||||
<< " --dir-light <x> <y> <z> <r> <g> <b>\n"
|
||||
<< " Add a directional light\n"
|
||||
<< "\n"
|
||||
<< "Render Parameters:\n"
|
||||
<< " --width <w> Image width in pixels (default: 1920)\n"
|
||||
<< " --height <h> Image height in pixels (default: 1080)\n"
|
||||
<< " --samples <n> Number of samples per pixel (default: 10000)\n"
|
||||
<< "\n"
|
||||
<< "Other:\n"
|
||||
<< " -h, --help Show this help message\n"
|
||||
<< "\n"
|
||||
<< "Examples:\n"
|
||||
<< " " << programName << " --width 1280 --height 720 --samples 1000\n"
|
||||
<< " " << programName << " --pos 3 2 3 --focal 0.5\n"
|
||||
<< " " << programName << " --fog 0.1 0.1 0.2 --specular 0.5 --ambient 0.1\n"
|
||||
<< " " << programName << " --point-light 0 5 0 1 1 1 --dir-light -1 -1 -1 1 0.8 0.6\n"
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
static bool parseFloat(const char* str, float& out)
|
||||
{
|
||||
try
|
||||
{
|
||||
out = std::stof(str);
|
||||
return true;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool parseUint(const char* str, uint32_t& out)
|
||||
{
|
||||
try
|
||||
{
|
||||
out = static_cast<uint32_t>(std::stoul(str));
|
||||
return true;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool parseVec3(const char* xStr, const char* yStr, const char* zStr, glm::vec3& out)
|
||||
{
|
||||
float x, y, z;
|
||||
if (!parseFloat(xStr, x) || !parseFloat(yStr, y) || !parseFloat(zStr, z))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
out = glm::vec3(x, y, z);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool parseVec2(const char* xStr, const char* yStr, glm::vec2& out)
|
||||
{
|
||||
float x, y;
|
||||
if (!parseFloat(xStr, x) || !parseFloat(yStr, y))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
out = glm::vec2(x, y);
|
||||
return true;
|
||||
}
|
||||
|
||||
CLIArgs parseCLIArgs(int argc, const char* argv[])
|
||||
{
|
||||
CLIArgs args;
|
||||
|
||||
for (int i = 1; i < argc; ++i)
|
||||
{
|
||||
std::string arg = argv[i];
|
||||
|
||||
if (arg == "-h" || arg == "--help")
|
||||
{
|
||||
args.help = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (arg == "--pos" && i + 3 < argc)
|
||||
{
|
||||
glm::vec3 pos;
|
||||
if (parseVec3(argv[i + 1], argv[i + 2], argv[i + 3], pos))
|
||||
{
|
||||
args.cameraPosition = pos;
|
||||
i += 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Error: Invalid camera position values\n";
|
||||
std::exit(1);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (arg == "--target" && i + 3 < argc)
|
||||
{
|
||||
glm::vec3 target;
|
||||
if (parseVec3(argv[i + 1], argv[i + 2], argv[i + 3], target))
|
||||
{
|
||||
args.cameraTarget = target;
|
||||
i += 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Error: Invalid camera target values\n";
|
||||
std::exit(1);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (arg == "--focal" && i + 1 < argc)
|
||||
{
|
||||
float f;
|
||||
if (parseFloat(argv[i + 1], f))
|
||||
{
|
||||
args.focalLength = f;
|
||||
++i;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Error: Invalid focal length value\n";
|
||||
std::exit(1);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (arg == "--aperture" && i + 1 < argc)
|
||||
{
|
||||
float A;
|
||||
if (parseFloat(argv[i + 1], A))
|
||||
{
|
||||
args.aperture = A;
|
||||
++i;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Error: Invalid aperture value\n";
|
||||
std::exit(1);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (arg == "--subject-dist" && i + 1 < argc)
|
||||
{
|
||||
float d;
|
||||
if (parseFloat(argv[i + 1], d))
|
||||
{
|
||||
args.subjectDistance = d;
|
||||
++i;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Error: Invalid subject distance value\n";
|
||||
std::exit(1);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (arg == "--sensor" && i + 2 < argc)
|
||||
{
|
||||
glm::vec2 sensor;
|
||||
if (parseVec2(argv[i + 1], argv[i + 2], sensor))
|
||||
{
|
||||
args.sensorSize = sensor;
|
||||
i += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Error: Invalid sensor size values\n";
|
||||
std::exit(1);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (arg == "--fog" && i + 3 < argc)
|
||||
{
|
||||
glm::vec3 fog;
|
||||
if (parseVec3(argv[i + 1], argv[i + 2], argv[i + 3], fog))
|
||||
{
|
||||
args.fogEmissive = fog;
|
||||
i += 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Error: Invalid fog emissive values\n";
|
||||
std::exit(1);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (arg == "--specular" && i + 1 < argc)
|
||||
{
|
||||
float s;
|
||||
if (parseFloat(argv[i + 1], s))
|
||||
{
|
||||
args.specularCoeff = s;
|
||||
++i;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Error: Invalid specular coefficient value\n";
|
||||
std::exit(1);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (arg == "--ambient" && i + 1 < argc)
|
||||
{
|
||||
float a;
|
||||
if (parseFloat(argv[i + 1], a))
|
||||
{
|
||||
args.ambientCoeff = a;
|
||||
++i;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Error: Invalid ambient coefficient value\n";
|
||||
std::exit(1);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (arg == "--point-light" && i + 5 < argc)
|
||||
{
|
||||
glm::vec3 position, color;
|
||||
if (parseVec3(argv[i + 1], argv[i + 2], argv[i + 3], position) &&
|
||||
parseVec3(argv[i + 4], argv[i + 5], argv[i + 6], color))
|
||||
{
|
||||
PointLight light;
|
||||
light.position = position;
|
||||
light.color = color;
|
||||
light.attenuation = 1.0f;
|
||||
if (i + 7 < argc)
|
||||
{
|
||||
if (!parseFloat(argv[i + 7], light.attenuation))
|
||||
{
|
||||
std::cerr << "Error: Invalid point light attenuation value\n";
|
||||
std::exit(1);
|
||||
}
|
||||
i += 7;
|
||||
}
|
||||
else
|
||||
{
|
||||
i += 6;
|
||||
}
|
||||
args.pointLights.push_back(light);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Error: Invalid point light values (expected: <x> <y> <z> <r> <g> <b> [attenuation])\n";
|
||||
std::exit(1);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (arg == "--dir-light" && i + 5 < argc)
|
||||
{
|
||||
glm::vec3 direction, color;
|
||||
if (parseVec3(argv[i + 1], argv[i + 2], argv[i + 3], direction) &&
|
||||
parseVec3(argv[i + 4], argv[i + 5], argv[i + 6], color))
|
||||
{
|
||||
DirectionalLight light;
|
||||
light.direction = direction;
|
||||
light.color = color;
|
||||
i += 6;
|
||||
args.directionalLights.push_back(light);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Error: Invalid directional light values (expected: <x> <y> <z> <r> <g> <b>)\n";
|
||||
std::exit(1);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (arg == "--width" && i + 1 < argc)
|
||||
{
|
||||
uint32_t w;
|
||||
if (parseUint(argv[i + 1], w))
|
||||
{
|
||||
args.width = w;
|
||||
++i;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Error: Invalid width value\n";
|
||||
std::exit(1);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (arg == "--height" && i + 1 < argc)
|
||||
{
|
||||
uint32_t h;
|
||||
if (parseUint(argv[i + 1], h))
|
||||
{
|
||||
args.height = h;
|
||||
++i;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Error: Invalid height value\n";
|
||||
std::exit(1);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (arg == "--samples" && i + 1 < argc)
|
||||
{
|
||||
uint32_t n;
|
||||
if (parseUint(argv[i + 1], n))
|
||||
{
|
||||
args.numSamples = n;
|
||||
++i;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Error: Invalid samples value\n";
|
||||
std::exit(1);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
std::cerr << "Error: Unknown argument '" << arg << "'\n";
|
||||
std::cerr << "Use --help for usage information\n";
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
void applyCLIToCamera(Camera& camera, const CLIArgs& args)
|
||||
{
|
||||
if (args.cameraPosition)
|
||||
camera.position = *args.cameraPosition;
|
||||
if (args.cameraTarget)
|
||||
camera.target = *args.cameraTarget;
|
||||
if (args.focalLength)
|
||||
camera.f = *args.focalLength;
|
||||
if (args.aperture)
|
||||
camera.A = *args.aperture;
|
||||
if (args.subjectDistance)
|
||||
camera.S_O = *args.subjectDistance;
|
||||
if (args.sensorSize)
|
||||
camera.sensorSize = *args.sensorSize;
|
||||
if (args.fogEmissive)
|
||||
camera.fogEmm = *args.fogEmissive;
|
||||
if (args.specularCoeff)
|
||||
camera.ks = *args.specularCoeff;
|
||||
if (args.ambientCoeff)
|
||||
camera.ka = *args.ambientCoeff;
|
||||
}
|
||||
|
||||
void applyCLIToRenderParams(RenderParameter& params, const CLIArgs& args)
|
||||
{
|
||||
if (args.width)
|
||||
params.width = *args.width;
|
||||
if (args.height)
|
||||
params.height = *args.height;
|
||||
if (args.numSamples)
|
||||
params.numSamples = *args.numSamples;
|
||||
}
|
||||
|
||||
void applyCLIToScene(Scene& scene, const CLIArgs& args)
|
||||
{
|
||||
for (const auto& light : args.pointLights)
|
||||
{
|
||||
scene.addPointLight(light);
|
||||
}
|
||||
for (const auto& light : args.directionalLights)
|
||||
{
|
||||
scene.addDirectionalLight(light);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
#pragma once
|
||||
#include "Camera.h"
|
||||
#include "Scene.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <optional>
|
||||
#include <cstdint>
|
||||
|
||||
// Forward declaration - defined in scene/Renderer.h
|
||||
struct RenderParameter;
|
||||
|
||||
/// Parsed command-line arguments for render parameters
|
||||
struct CLIArgs
|
||||
{
|
||||
// Camera parameters
|
||||
std::optional<glm::vec3> cameraPosition;
|
||||
std::optional<glm::vec3> cameraTarget;
|
||||
std::optional<float> focalLength;
|
||||
std::optional<float> aperture;
|
||||
std::optional<float> subjectDistance;
|
||||
std::optional<glm::vec2> sensorSize;
|
||||
std::optional<glm::vec3> fogEmissive;
|
||||
std::optional<float> specularCoeff;
|
||||
std::optional<float> ambientCoeff;
|
||||
|
||||
// Light parameters
|
||||
std::vector<PointLight> pointLights;
|
||||
std::vector<DirectionalLight> directionalLights;
|
||||
|
||||
// Render parameters
|
||||
std::optional<uint32_t> width;
|
||||
std::optional<uint32_t> height;
|
||||
std::optional<uint32_t> numSamples;
|
||||
|
||||
// Flags
|
||||
bool help = false;
|
||||
};
|
||||
|
||||
/// Parse command-line arguments
|
||||
/// @param argc Argument count
|
||||
/// @param argv Argument values
|
||||
/// @return Parsed CLIArgs structure
|
||||
CLIArgs parseCLIArgs(int argc, const char* argv[]);
|
||||
|
||||
/// Apply CLI arguments to camera, using defaults for unspecified values
|
||||
/// @param camera Camera to modify
|
||||
/// @param args Parsed CLI arguments
|
||||
void applyCLIToCamera(Camera& camera, const CLIArgs& args);
|
||||
|
||||
/// Apply CLI arguments to render parameters, using defaults for unspecified values
|
||||
/// @param params RenderParameter to modify
|
||||
/// @param args Parsed CLI arguments
|
||||
void applyCLIToRenderParams(RenderParameter& params, const CLIArgs& args);
|
||||
|
||||
/// Apply CLI light arguments to scene
|
||||
/// @param scene Scene to add lights to
|
||||
/// @param args Parsed CLI arguments
|
||||
void applyCLIToScene(Scene& scene, const CLIArgs& args);
|
||||
|
||||
/// Print usage/help information
|
||||
void printUsage(const char* programName);
|
||||
@@ -3,6 +3,8 @@ target_sources(RayTracer
|
||||
BRDF.h
|
||||
BRDF.cpp
|
||||
Camera.h
|
||||
CLI.h
|
||||
CLI.cpp
|
||||
Material.h
|
||||
Material.cpp
|
||||
Model.h
|
||||
@@ -14,4 +16,4 @@ target_sources(RayTracer
|
||||
Texture.cpp
|
||||
TextureLoader.h
|
||||
TextureLoader.cpp
|
||||
)
|
||||
)
|
||||
|
||||
+4
-1
@@ -9,4 +9,7 @@ struct Camera
|
||||
float S_O = 20;
|
||||
float f = 0.7;
|
||||
float A = 0.35;
|
||||
};
|
||||
glm::vec3 fogEmm = glm::vec3(0, 0, 0);
|
||||
float ks = 0;
|
||||
float ka = 0;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user