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_subdirectory(extern)
|
||||||
|
|
||||||
add_executable(raytracer
|
add_executable(raytracer)
|
||||||
include/camera.h
|
target_sources(raytracer PRIVATE
|
||||||
include/intersections.h
|
|
||||||
include/lighting.h
|
|
||||||
include/ray.h
|
|
||||||
include/image.h
|
|
||||||
include/scene.h
|
|
||||||
include/aabb.h
|
|
||||||
include/octree.h
|
|
||||||
src/main.cpp
|
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)
|
src/scene.cpp)
|
||||||
target_include_directories(raytracer PUBLIC include PRIVATE ${GLM_INCLUDE_DIR})
|
target_include_directories(raytracer PUBLIC include PRIVATE ${GLM_INCLUDE_DIR})
|
||||||
target_link_libraries(raytracer PUBLIC stb SDL2::Main imgui glad tinyobjloader)
|
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 23
|
||||||
CXX_STANDARD_REQUIRED YES
|
CXX_STANDARD_REQUIRED YES
|
||||||
CXX_EXTENSIONS NO
|
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)
|
add_library(tinyobjloader STATIC)
|
||||||
target_include_directories(tinyobjloader INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
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;
|
glm::vec3 min, max;
|
||||||
|
|
||||||
[[nodiscard]] glm::vec3 center() const {
|
[[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:
|
public:
|
||||||
Camera() : position(glm::vec3(0)), direction(glm::vec3(0)) {}
|
Camera() : position(glm::vec3(0)), direction(glm::vec3(0)) {}
|
||||||
|
|
||||||
|
@ -20,7 +25,7 @@ public:
|
||||||
const float h2 = height / 2.0f;
|
const float h2 = height / 2.0f;
|
||||||
const float w2 = width / 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;
|
static_cast<float>(x - w2) * right;
|
||||||
return Ray(position, ray_dir);
|
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 <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:
|
public:
|
||||||
void reset() {
|
void reset() {
|
||||||
array = {};
|
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) {
|
inline bool ray_sphere(const Ray ray, const glm::vec4 sphere) {
|
||||||
const glm::vec3 diff = ray.origin - glm::vec3(sphere);
|
const glm::vec3 diff = ray.origin - glm::vec3(sphere);
|
||||||
const float b = glm::dot(ray.direction, diff);
|
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) {
|
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 glm::vec3 dir = glm::normalize(light - pos);
|
||||||
const float n_dot_l = glm::max(glm::dot(normal, dir), 0.0f);
|
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 <SDL.h>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <future>
|
#include <future>
|
||||||
#include <glm/glm.hpp>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||||
#include <stb_image_write.h>
|
#include <stb_image_write.h>
|
||||||
|
|
||||||
#include "camera.h"
|
|
||||||
#include "glad/glad.h"
|
#include "glad/glad.h"
|
||||||
#include "image.h"
|
|
||||||
#include "imgui.h"
|
#include "imgui.h"
|
||||||
#include "imgui_impl_opengl3.h"
|
#include "imgui_impl_opengl3.h"
|
||||||
#include "imgui_impl_sdl.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
|
// scene information
|
||||||
constexpr int32_t width = 256, height = 256;
|
constexpr int32_t width = 256, height = 256;
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
#pragma once
|
module;
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "aabb.h"
|
export module octree;
|
||||||
|
|
||||||
|
import aabb;
|
||||||
|
import glm;
|
||||||
|
|
||||||
constexpr int max_contained_types = 16;
|
constexpr int max_contained_types = 16;
|
||||||
constexpr int max_octree_depth = 2;
|
constexpr int max_octree_depth = 2;
|
||||||
|
@ -18,7 +22,7 @@ constexpr std::array child_pattern = {
|
||||||
glm::vec3(-1, +1, +1),
|
glm::vec3(-1, +1, +1),
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename UnderlyingType> struct Node {
|
export template<typename UnderlyingType> struct Node {
|
||||||
using NodeType = Node<UnderlyingType>;
|
using NodeType = Node<UnderlyingType>;
|
||||||
|
|
||||||
AABB extent;
|
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>;
|
using NodeType = Node<UnderlyingType>;
|
||||||
|
|
||||||
NodeType root;
|
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) {}
|
Ray(const glm::vec3 origin, const glm::vec3 direction) : origin(origin), direction(direction) {}
|
||||||
|
|
||||||
glm::vec3 origin, direction;
|
glm::vec3 origin, direction;
|
117
src/scene.cpp
117
src/scene.cpp
|
@ -1,7 +1,122 @@
|
||||||
#include "scene.h"
|
module;
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <numbers>
|
#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) {
|
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];
|
const tinyobj::index_t idx = mesh.indices[(index * 3) + vertex];
|
||||||
|
|
Loading…
Add table
Reference in a new issue