Port to C++ modules
Still incomplete, but now builds in modules.
This commit is contained in:
parent
f25d0e4c17
commit
6098f0dcca
14 changed files with 2883 additions and 158 deletions
|
@ -8,16 +8,18 @@ find_package(SDL2 REQUIRED)
|
|||
|
||||
add_subdirectory(extern)
|
||||
|
||||
add_executable(raytracer
|
||||
include/camera.h
|
||||
include/intersections.h
|
||||
include/lighting.h
|
||||
include/ray.h
|
||||
include/image.h
|
||||
include/scene.h
|
||||
include/aabb.h
|
||||
include/octree.h
|
||||
add_executable(raytracer)
|
||||
target_sources(raytracer PRIVATE
|
||||
src/main.cpp
|
||||
PRIVATE FILE_SET CXX_MODULES FILES
|
||||
src/aabb.cpp
|
||||
src/camera.cpp
|
||||
src/glm.cpp
|
||||
src/image.cpp
|
||||
src/intersections.cpp
|
||||
src/lighting.cpp
|
||||
src/octree.cpp
|
||||
src/ray.cpp
|
||||
src/scene.cpp)
|
||||
target_include_directories(raytracer PUBLIC include PRIVATE ${GLM_INCLUDE_DIR})
|
||||
target_link_libraries(raytracer PUBLIC stb SDL2::Main imgui glad tinyobjloader)
|
||||
|
@ -25,4 +27,5 @@ set_target_properties(raytracer PROPERTIES
|
|||
CXX_STANDARD 23
|
||||
CXX_STANDARD_REQUIRED YES
|
||||
CXX_EXTENSIONS NO
|
||||
CXX_SCAN_FOR_MODULES ON # For main.cpp, which is not in the module set technically
|
||||
)
|
||||
|
|
12
extern/tinyobjloader/CMakeLists.txt
vendored
12
extern/tinyobjloader/CMakeLists.txt
vendored
|
@ -1,2 +1,10 @@
|
|||
add_library(tinyobjloader INTERFACE)
|
||||
target_include_directories(tinyobjloader INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
add_library(tinyobjloader STATIC)
|
||||
target_sources(tinyobjloader PUBLIC
|
||||
FILE_SET CXX_MODULES FILES
|
||||
src/tiny_obj_loader.cpp)
|
||||
target_include_directories(tinyobjloader PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
set_target_properties(tinyobjloader PROPERTIES
|
||||
CXX_STANDARD 23
|
||||
CXX_STANDARD_REQUIRED YES
|
||||
CXX_EXTENSIONS NO
|
||||
)
|
||||
|
|
15
extern/tinyobjloader/src/tiny_obj_loader.cpp
vendored
Normal file
15
extern/tinyobjloader/src/tiny_obj_loader.cpp
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
module;
|
||||
|
||||
#define TINYOBJLOADER_IMPLEMENTATION
|
||||
#include <tiny_obj_loader.h>
|
||||
|
||||
export module tiny_obj_loader;
|
||||
|
||||
export namespace tinyobj {
|
||||
using ::tinyobj::mesh_t;
|
||||
using ::tinyobj::attrib_t;
|
||||
using ::tinyobj::shape_t;
|
||||
using ::tinyobj::material_t;
|
||||
using ::tinyobj::index_t;
|
||||
using ::tinyobj::LoadObj;
|
||||
}
|
113
include/scene.h
113
include/scene.h
|
@ -1,113 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <glm/glm.hpp>
|
||||
#include <optional>
|
||||
#include <random>
|
||||
#include <print>
|
||||
|
||||
#include <tiny_obj_loader.h>
|
||||
|
||||
#include "intersections.h"
|
||||
#include "lighting.h"
|
||||
#include "octree.h"
|
||||
#include "ray.h"
|
||||
|
||||
constexpr glm::vec3 light_position = glm::vec3(5);
|
||||
constexpr float light_bias = 0.01f;
|
||||
constexpr int max_depth = 2;
|
||||
inline int num_indirect_samples = 4;
|
||||
|
||||
struct TriangleBox {
|
||||
uint64_t vertice_index = 0;
|
||||
tinyobj::mesh_t* mesh;
|
||||
AABB extent;
|
||||
};
|
||||
|
||||
struct Object;
|
||||
|
||||
glm::vec3 fetch_position(const Object& object, const tinyobj::mesh_t& mesh, int32_t index, int32_t vertex);
|
||||
glm::vec3 fetch_normal(const Object& object, const tinyobj::mesh_t& mesh, int32_t index, int32_t vertex);
|
||||
|
||||
struct Object {
|
||||
glm::vec3 position = glm::vec3(0);
|
||||
glm::vec3 color = glm::vec3(1);
|
||||
|
||||
tinyobj::attrib_t attrib;
|
||||
std::vector<tinyobj::shape_t> shapes;
|
||||
std::vector<tinyobj::material_t> materials;
|
||||
|
||||
std::unique_ptr<Octree<TriangleBox>> octree;
|
||||
|
||||
void create_octree() {
|
||||
octree = std::make_unique<Octree<TriangleBox>>(glm::vec3(-2), glm::vec3(2));
|
||||
|
||||
for (auto& shape : shapes) {
|
||||
for (size_t i = 0; i < shape.mesh.num_face_vertices.size(); i++) {
|
||||
const glm::vec3 v0 = fetch_position(*this, shape.mesh, i, 0);
|
||||
const glm::vec3 v1 = fetch_position(*this, shape.mesh, i, 1);
|
||||
const glm::vec3 v2 = fetch_position(*this, shape.mesh, i, 2);
|
||||
|
||||
AABB extent{};
|
||||
extent.min = glm::min(v0, v1);
|
||||
extent.min = glm::min(extent.min, v2);
|
||||
|
||||
extent.max = glm::max(v0, v1);
|
||||
extent.max = glm::max(extent.max, v2);
|
||||
|
||||
TriangleBox box = {};
|
||||
box.vertice_index = i;
|
||||
box.extent = extent;
|
||||
box.mesh = &shape.mesh;
|
||||
|
||||
octree->add(box, box.extent);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct Scene {
|
||||
std::vector<std::unique_ptr<Object>> objects;
|
||||
|
||||
std::random_device rd;
|
||||
std::mt19937 gen;
|
||||
std::uniform_real_distribution<> dis;
|
||||
|
||||
Scene() : gen(rd()), dis(0.0, 1.0) {}
|
||||
|
||||
double distribution() {
|
||||
return dis(gen);
|
||||
}
|
||||
|
||||
Object& load_from_file(const std::string_view path) {
|
||||
auto o = std::make_unique<Object>();
|
||||
|
||||
std::string err;
|
||||
if (!tinyobj::LoadObj(&o->attrib, &o->shapes, &o->materials, &err, path.data())) [[unlikely]]
|
||||
std::println("Could not load obj: {}", err);
|
||||
|
||||
return *objects.emplace_back(std::move(o));
|
||||
}
|
||||
|
||||
void generate_acceleration() {
|
||||
for (auto& object : objects) {
|
||||
object->create_octree();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct HitResult {
|
||||
glm::vec3 position, normal;
|
||||
const Object* object = nullptr;
|
||||
};
|
||||
|
||||
std::optional<HitResult> test_mesh(Ray ray, const Object& object, const tinyobj::mesh_t& mesh, float& tClosest);
|
||||
std::optional<HitResult> test_scene(Ray ray, const Scene& scene);
|
||||
std::optional<HitResult> test_scene_octree(Ray ray, const Scene& scene);
|
||||
|
||||
struct SceneResult {
|
||||
HitResult hit;
|
||||
glm::vec3 direct, indirect, reflect, combined;
|
||||
};
|
||||
|
||||
std::optional<SceneResult> cast_scene(Ray ray, Scene& scene, bool use_bvh, int depth = 0);
|
|
@ -1,6 +1,13 @@
|
|||
#pragma once
|
||||
module;
|
||||
|
||||
struct AABB {
|
||||
#include <cmath>
|
||||
|
||||
export module aabb;
|
||||
|
||||
import ray;
|
||||
import glm;
|
||||
|
||||
export struct AABB {
|
||||
glm::vec3 min, max;
|
||||
|
||||
[[nodiscard]] glm::vec3 center() const {
|
|
@ -1,8 +1,13 @@
|
|||
#pragma once
|
||||
module;
|
||||
|
||||
#include "ray.h"
|
||||
#include <cstdint>
|
||||
|
||||
class Camera {
|
||||
export module camera;
|
||||
|
||||
import ray;
|
||||
import glm;
|
||||
|
||||
export class Camera {
|
||||
public:
|
||||
Camera() : position(glm::vec3(0)), direction(glm::vec3(0)) {}
|
||||
|
||||
|
@ -20,7 +25,7 @@ public:
|
|||
const float h2 = height / 2.0f;
|
||||
const float w2 = width / 2.0f;
|
||||
|
||||
const glm::vec3 ray_dir = position + (h2 / tan(glm::radians(fov) / 2)) * direction + (y - h2) * up +
|
||||
const glm::vec3 ray_dir = position + static_cast<float>(h2 / glm::tan(glm::radians(fov) / 2)) * direction + (y - h2) * up +
|
||||
static_cast<float>(x - w2) * right;
|
||||
return Ray(position, ray_dir);
|
||||
}
|
2676
src/glm.cpp
Normal file
2676
src/glm.cpp
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,9 +1,11 @@
|
|||
#pragma once
|
||||
module;
|
||||
|
||||
#include <cstdint>
|
||||
#include <array>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
template<class T, int Width, int Height> class Image {
|
||||
export module image;
|
||||
|
||||
export template<class T, int Width, int Height> class Image {
|
||||
public:
|
||||
void reset() {
|
||||
array = {};
|
|
@ -1,12 +1,15 @@
|
|||
#pragma once
|
||||
module;
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <limits>
|
||||
|
||||
#include "ray.h"
|
||||
export module intersections;
|
||||
|
||||
constexpr float epsilon = std::numeric_limits<float>::epsilon();
|
||||
import ray;
|
||||
import glm;
|
||||
|
||||
namespace intersections {
|
||||
export constexpr float epsilon = std::numeric_limits<float>::epsilon();
|
||||
|
||||
export namespace intersections {
|
||||
inline bool ray_sphere(const Ray ray, const glm::vec4 sphere) {
|
||||
const glm::vec3 diff = ray.origin - glm::vec3(sphere);
|
||||
const float b = glm::dot(ray.direction, diff);
|
|
@ -1,8 +1,10 @@
|
|||
#pragma once
|
||||
module;
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
import glm;
|
||||
|
||||
namespace lighting {
|
||||
export module lighting;
|
||||
|
||||
export namespace lighting {
|
||||
inline float point_light(const glm::vec3 pos, const glm::vec3 light, const glm::vec3 normal) {
|
||||
const glm::vec3 dir = glm::normalize(light - pos);
|
||||
const float n_dot_l = glm::max(glm::dot(normal, dir), 0.0f);
|
16
src/main.cpp
16
src/main.cpp
|
@ -1,24 +1,22 @@
|
|||
import camera;
|
||||
import glm;
|
||||
import scene;
|
||||
import image;
|
||||
import ray;
|
||||
import octree;
|
||||
|
||||
#include <SDL.h>
|
||||
#include <array>
|
||||
#include <future>
|
||||
#include <glm/glm.hpp>
|
||||
#include <vector>
|
||||
|
||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
#include <stb_image_write.h>
|
||||
|
||||
#include "camera.h"
|
||||
#include "glad/glad.h"
|
||||
#include "image.h"
|
||||
#include "imgui.h"
|
||||
#include "imgui_impl_opengl3.h"
|
||||
#include "imgui_impl_sdl.h"
|
||||
#include "intersections.h"
|
||||
#include "lighting.h"
|
||||
#include "scene.h"
|
||||
|
||||
#define TINYOBJLOADER_IMPLEMENTATION
|
||||
#include <tiny_obj_loader.h>
|
||||
|
||||
// scene information
|
||||
constexpr int32_t width = 256, height = 256;
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
#pragma once
|
||||
module;
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "aabb.h"
|
||||
export module octree;
|
||||
|
||||
import aabb;
|
||||
import glm;
|
||||
|
||||
constexpr int max_contained_types = 16;
|
||||
constexpr int max_octree_depth = 2;
|
||||
|
@ -18,7 +22,7 @@ constexpr std::array child_pattern = {
|
|||
glm::vec3(-1, +1, +1),
|
||||
};
|
||||
|
||||
template<typename UnderlyingType> struct Node {
|
||||
export template<typename UnderlyingType> struct Node {
|
||||
using NodeType = Node<UnderlyingType>;
|
||||
|
||||
AABB extent;
|
||||
|
@ -72,7 +76,7 @@ template<typename UnderlyingType> struct Node {
|
|||
}
|
||||
};
|
||||
|
||||
template<typename UnderlyingType> struct Octree {
|
||||
export template<typename UnderlyingType> struct Octree {
|
||||
using NodeType = Node<UnderlyingType>;
|
||||
|
||||
NodeType root;
|
|
@ -1,8 +1,8 @@
|
|||
#pragma once
|
||||
export module ray;
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
import glm;
|
||||
|
||||
struct Ray {
|
||||
export struct Ray {
|
||||
Ray(const glm::vec3 origin, const glm::vec3 direction) : origin(origin), direction(direction) {}
|
||||
|
||||
glm::vec3 origin, direction;
|
117
src/scene.cpp
117
src/scene.cpp
|
@ -1,7 +1,122 @@
|
|||
#include "scene.h"
|
||||
module;
|
||||
|
||||
#include <functional>
|
||||
#include <numbers>
|
||||
#include <memory>
|
||||
|
||||
#include <array>
|
||||
#include <optional>
|
||||
#include <random>
|
||||
#include <print>
|
||||
|
||||
export module scene;
|
||||
|
||||
import aabb;
|
||||
import octree;
|
||||
import ray;
|
||||
import intersections;
|
||||
import lighting;
|
||||
import tiny_obj_loader;
|
||||
import glm;
|
||||
|
||||
constexpr glm::vec3 light_position = glm::vec3(5);
|
||||
constexpr float light_bias = 0.01f;
|
||||
constexpr int max_depth = 2;
|
||||
export inline int num_indirect_samples = 4;
|
||||
|
||||
struct TriangleBox {
|
||||
uint64_t vertice_index = 0;
|
||||
tinyobj::mesh_t* mesh;
|
||||
AABB extent;
|
||||
};
|
||||
|
||||
export struct Object;
|
||||
|
||||
glm::vec3 fetch_position(const Object& object, const tinyobj::mesh_t& mesh, int32_t index, int32_t vertex);
|
||||
glm::vec3 fetch_normal(const Object& object, const tinyobj::mesh_t& mesh, int32_t index, int32_t vertex);
|
||||
|
||||
struct Object {
|
||||
glm::vec3 position = glm::vec3(0);
|
||||
glm::vec3 color = glm::vec3(1);
|
||||
|
||||
tinyobj::attrib_t attrib;
|
||||
std::vector<tinyobj::shape_t> shapes;
|
||||
std::vector<tinyobj::material_t> materials;
|
||||
|
||||
std::unique_ptr<Octree<TriangleBox>> octree;
|
||||
|
||||
void create_octree() {
|
||||
octree = std::make_unique<Octree<TriangleBox>>(glm::vec3(-2), glm::vec3(2));
|
||||
|
||||
for (auto& shape : shapes) {
|
||||
for (size_t i = 0; i < shape.mesh.num_face_vertices.size(); i++) {
|
||||
const glm::vec3 v0 = fetch_position(*this, shape.mesh, i, 0);
|
||||
const glm::vec3 v1 = fetch_position(*this, shape.mesh, i, 1);
|
||||
const glm::vec3 v2 = fetch_position(*this, shape.mesh, i, 2);
|
||||
|
||||
AABB extent{};
|
||||
extent.min = glm::min(v0, v1);
|
||||
extent.min = glm::min(extent.min, v2);
|
||||
|
||||
extent.max = glm::max(v0, v1);
|
||||
extent.max = glm::max(extent.max, v2);
|
||||
|
||||
TriangleBox box = {};
|
||||
box.vertice_index = i;
|
||||
box.extent = extent;
|
||||
box.mesh = &shape.mesh;
|
||||
|
||||
octree->add(box, box.extent);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export struct Scene {
|
||||
std::vector<std::unique_ptr<Object>> objects;
|
||||
|
||||
std::random_device rd;
|
||||
std::mt19937 gen;
|
||||
std::uniform_real_distribution<> dis;
|
||||
|
||||
Scene() : gen(rd()), dis(0.0, 1.0) {}
|
||||
|
||||
double distribution() {
|
||||
return dis(gen);
|
||||
}
|
||||
|
||||
Object& load_from_file(const std::string_view path) {
|
||||
auto o = std::make_unique<Object>();
|
||||
|
||||
std::string err;
|
||||
if (!tinyobj::LoadObj(&o->attrib, &o->shapes, &o->materials, &err, path.data())) [[unlikely]]
|
||||
std::println("Could not load obj: {}", err);
|
||||
|
||||
return *objects.emplace_back(std::move(o));
|
||||
}
|
||||
|
||||
void generate_acceleration() {
|
||||
for (auto& object : objects) {
|
||||
object->create_octree();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct HitResult {
|
||||
glm::vec3 position, normal;
|
||||
const Object* object = nullptr;
|
||||
};
|
||||
|
||||
std::optional<HitResult> test_mesh(Ray ray, const Object& object, const tinyobj::mesh_t& mesh, float& tClosest);
|
||||
std::optional<HitResult> test_scene(Ray ray, const Scene& scene);
|
||||
std::optional<HitResult> test_scene_octree(Ray ray, const Scene& scene);
|
||||
|
||||
struct SceneResult {
|
||||
HitResult hit;
|
||||
glm::vec3 direct, indirect, reflect, combined;
|
||||
};
|
||||
|
||||
export std::optional<SceneResult> cast_scene(Ray ray, Scene& scene, bool use_bvh, int depth = 0);
|
||||
|
||||
glm::vec3 fetch_position(const Object& object, const tinyobj::mesh_t& mesh, const int32_t index, const int32_t vertex) {
|
||||
const tinyobj::index_t idx = mesh.indices[(index * 3) + vertex];
|
||||
|
|
Loading…
Add table
Reference in a new issue