1
Fork 0

Reformat code

This commit is contained in:
Joshua Goins 2022-08-16 07:41:12 -04:00
parent f0713452fc
commit 81d5045037
13 changed files with 370 additions and 319 deletions

33
.clang-format Normal file
View file

@ -0,0 +1,33 @@
---
AllowShortIfStatementsOnASingleLine: Never
CompactNamespaces: 'false'
DisableFormat: 'false'
IndentCaseLabels: 'true'
IndentPPDirectives: BeforeHash
IndentWidth: '4'
Language: Cpp
NamespaceIndentation: All
PointerAlignment: Left
ReflowComments: 'true'
SortIncludes: 'true'
SortUsingDeclarations: 'true'
SpacesInCStyleCastParentheses: 'false'
Standard: Cpp11
TabWidth: '0'
UseTab: Never
AllowShortEnumsOnASingleLine: false
BraceWrapping:
AfterEnum: true
AccessModifierOffset: -4
SpaceAfterTemplateKeyword: 'false'
AllowAllParametersOfDeclarationOnNextLine: false
AlignAfterOpenBracket: AlwaysBreak
BinPackArguments: false
BinPackParameters: false
ColumnLimit: 120
AllowShortBlocksOnASingleLine: 'false'
AllowShortCaseLabelsOnASingleLine: 'false'
AllowShortFunctionsOnASingleLine: 'Empty'
AllowShortLambdasOnASingleLine: 'Empty'
AllowShortLoopsOnASingleLine: 'false'
SeparateDefinitionBlocks : 'Always'

8
.editorconfig Normal file
View file

@ -0,0 +1,8 @@
root = true
[*]
insert_final_newline = true
indent_style = space
indent_size = 4
tab_width = 4
max_line_length = 120

View file

@ -1,6 +1,8 @@
# Raytracer # Raytracer
A multi-threaded raytracer using glm, tinyobjloader and C++17. The UI is written in imgui and image display is A multi-threaded raytracer using glm, tinyobjloader and C++17. The UI is written in imgui and image display is
rendered using OpenGL. I tried to write this to not be insanely fast or compact like other raytracers, but to be readable and understandable. rendered using OpenGL. I tried to write this to not be insanely fast or compact like other raytracers, but to be
readable and understandable.
![example result](misc/output.png) ![example result](misc/output.png)

View file

@ -16,12 +16,9 @@ struct AABB {
} }
bool inside(const AABB extent) const { bool inside(const AABB extent) const {
return(max.x > extent.min.x && return (
min.x < extent.max.x && max.x > extent.min.x && min.x < extent.max.x && max.y > extent.min.y && min.y < extent.max.y &&
max.y > extent.min.y && max.z > extent.min.z && min.z < extent.max.z);
min.y < extent.max.y &&
max.z > extent.min.z &&
min.z < extent.max.z);
} }
bool contains(const Ray& ray) const { bool contains(const Ray& ray) const {

View file

@ -5,6 +5,7 @@
class Camera { class Camera {
public: public:
Camera() : position(glm::vec3(0)), direction(glm::vec3(0)) {} Camera() : position(glm::vec3(0)), direction(glm::vec3(0)) {}
Camera(glm::vec3 position, glm::vec3 direction) : position(position), direction(direction) {} Camera(glm::vec3 position, glm::vec3 direction) : position(position), direction(direction) {}
void look_at(glm::vec3 eye, glm::vec3 target) { void look_at(glm::vec3 eye, glm::vec3 target) {
@ -19,7 +20,8 @@ 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 + static_cast<float>(x - w2) * right; const glm::vec3 ray_dir = position + (h2 / tan(glm::radians(fov) / 2)) * direction + (y - h2) * up +
static_cast<float>(x - w2) * right;
return Ray(position, ray_dir); return Ray(position, ray_dir);
} }

View file

@ -1,10 +1,9 @@
#pragma once #pragma once
#include <glm/glm.hpp>
#include <array> #include <array>
#include <glm/glm.hpp>
template<class T, int Width, int Height> template<class T, int Width, int Height> class Image {
class Image {
public: public:
void reset() { void reset() {
array = {}; array = {};

View file

@ -22,7 +22,8 @@ namespace intersections {
return false; return false;
} }
inline float ray_triangle(const Ray ray, inline float ray_triangle(
const Ray ray,
const glm::vec3 v0, const glm::vec3 v0,
const glm::vec3 v1, const glm::vec3 v1,
const glm::vec3 v2, const glm::vec3 v2,
@ -37,7 +38,8 @@ namespace intersections {
// if determinant is zero then ray is // if determinant is zero then ray is
// parallel with the triangle plane // parallel with the triangle plane
if (det > -epsilon && det < epsilon) return false; if (det > -epsilon && det < epsilon)
return false;
float invdet = 1.0 / det; float invdet = 1.0 / det;
// calculate distance from m[0] to origin // calculate distance from m[0] to origin
@ -48,17 +50,19 @@ namespace intersections {
u = glm::dot(tvec, pvec) * invdet; u = glm::dot(tvec, pvec) * invdet;
// check against one edge and opposite point // check against one edge and opposite point
if (u < 0.0 || u > 1.0) return false; if (u < 0.0 || u > 1.0)
return false;
glm::vec3 qvec = glm::cross(tvec, e1); glm::vec3 qvec = glm::cross(tvec, e1);
v = glm::dot(ray.direction, qvec) * invdet; v = glm::dot(ray.direction, qvec) * invdet;
// check against other edges // check against other edges
if (v < 0.0 || u + v > 1.0) return false; if (v < 0.0 || u + v > 1.0)
return false;
// distance along the ray, i.e. intersect at o + t * d // distance along the ray, i.e. intersect at o + t * d
t = glm::dot(e2, qvec) * invdet; t = glm::dot(e2, qvec) * invdet;
return true; return true;
} }
}; }; // namespace intersections

View file

@ -9,4 +9,4 @@ namespace lighting {
return n_dot_l; return n_dot_l;
} }
}; }; // namespace lighting

View file

@ -18,8 +18,7 @@ constexpr auto child_pattern = {
glm::vec3(-1, +1, +1), glm::vec3(-1, +1, +1),
}; };
template<typename UnderlyingType> template<typename UnderlyingType> struct Node {
struct Node {
using NodeType = Node<UnderlyingType>; using NodeType = Node<UnderlyingType>;
AABB extent; AABB extent;
@ -73,8 +72,7 @@ struct Node {
} }
}; };
template<typename UnderlyingType> template<typename UnderlyingType> struct Octree {
struct Octree {
using NodeType = Node<UnderlyingType>; using NodeType = Node<UnderlyingType>;
NodeType root; NodeType root;

View file

@ -1,17 +1,17 @@
#pragma once #pragma once
#include <optional>
#include <glm/glm.hpp>
#include <array> #include <array>
#include <glm/glm.hpp>
#include <iostream> #include <iostream>
#include <optional>
#include <random> #include <random>
#include <tiny_obj_loader.h> #include <tiny_obj_loader.h>
#include "ray.h"
#include "intersections.h" #include "intersections.h"
#include "lighting.h" #include "lighting.h"
#include "octree.h" #include "octree.h"
#include "ray.h"
constexpr glm::vec3 light_position = glm::vec3(5); constexpr glm::vec3 light_position = glm::vec3(5);
constexpr float light_bias = 0.01f; constexpr float light_bias = 0.01f;
@ -111,4 +111,3 @@ struct SceneResult {
}; };
std::optional<SceneResult> cast_scene(const Ray ray, Scene& scene, const bool use_bvh, const int depth = 0); std::optional<SceneResult> cast_scene(const Ray ray, Scene& scene, const bool use_bvh, const int depth = 0);

View file

@ -1,23 +1,23 @@
#include <iostream>
#include <limits>
#include <future>
#include <vector>
#include <glm/glm.hpp>
#include <SDL.h> #include <SDL.h>
#include <array> #include <array>
#include <future>
#include <glm/glm.hpp>
#include <iostream>
#include <limits>
#include <vector>
#define STB_IMAGE_WRITE_IMPLEMENTATION #define STB_IMAGE_WRITE_IMPLEMENTATION
#include <stb_image_write.h> #include <stb_image_write.h>
#include "intersections.h"
#include "camera.h" #include "camera.h"
#include "glad/glad.h"
#include "image.h" #include "image.h"
#include "imgui.h"
#include "imgui_impl_opengl3.h"
#include "imgui_impl_sdl.h"
#include "intersections.h"
#include "lighting.h" #include "lighting.h"
#include "scene.h" #include "scene.h"
#include "glad/glad.h"
#include "imgui.h"
#include "imgui_impl_sdl.h"
#include "imgui_impl_opengl3.h"
#define TINYOBJLOADER_IMPLEMENTATION #define TINYOBJLOADER_IMPLEMENTATION
#include <tiny_obj_loader.h> #include <tiny_obj_loader.h>
@ -50,12 +50,7 @@ enum class DisplayMode {
Reflect Reflect
}; };
const std::array diplay_mode_strings = { const std::array diplay_mode_strings = {"Combined", "Direct", "Indirect", "Reflect"};
"Combined",
"Direct",
"Indirect",
"Reflect"
};
inline DisplayMode display_mode; inline DisplayMode display_mode;
@ -98,16 +93,12 @@ GLuint pixels_texture = 0;
void setup_gfx() { void setup_gfx() {
// create quad for pixel rendering // create quad for pixel rendering
constexpr std::array vertices = { constexpr std::array vertices = {
-0.5f, 0.5f, 0.0f, 0.0f, 0.0f, -0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.5f,
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, -0.5f, 0.0f, 1.0f, -1.0f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f // we render it upside down (to opengl) so we flip our
0.5f, -0.5f, 0.0f, 1.0f, -1.0f, // tex coord
-0.5f, -0.5f, 0.0f, 0.0f, -1.0f // we render it upside down (to opengl) so we flip our tex coord
}; };
constexpr std::array elements = { constexpr std::array elements = {0, 1, 2, 2, 3, 0};
0, 1, 2,
2, 3, 0
};
glGenVertexArrays(1, &quad_vao); glGenVertexArrays(1, &quad_vao);
glBindVertexArray(quad_vao); glBindVertexArray(quad_vao);
@ -128,8 +119,7 @@ void setup_gfx() {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, elements.size() * sizeof(uint32_t), elements.data(), GL_STATIC_DRAW); glBufferData(GL_ELEMENT_ARRAY_BUFFER, elements.size() * sizeof(uint32_t), elements.data(), GL_STATIC_DRAW);
constexpr std::string_view vertex_glsl = constexpr std::string_view vertex_glsl = "#version 330 core\n"
"#version 330 core\n"
"layout (location = 0) in vec3 in_position;\n" "layout (location = 0) in vec3 in_position;\n"
"layout (location = 1) in vec2 in_uv;\n" "layout (location = 1) in vec2 in_uv;\n"
"out vec2 uv;\n" "out vec2 uv;\n"
@ -140,8 +130,7 @@ void setup_gfx() {
"}\n"; "}\n";
const char* vertex_src = vertex_glsl.data(); const char* vertex_src = vertex_glsl.data();
constexpr std::string_view fragment_glsl = constexpr std::string_view fragment_glsl = "#version 330 core\n"
"#version 330 core\n"
"in vec2 uv;\n" "in vec2 uv;\n"
"out vec4 out_color;\n" "out vec4 out_color;\n"
"uniform sampler2D pixel_texture;\n" "uniform sampler2D pixel_texture;\n"
@ -212,9 +201,16 @@ void dump_to_file() {
stbi_write_png("output.png", width, height, 3, pixels, width * 3); stbi_write_png("output.png", width, height, 3, pixels, width * 3);
} }
template<typename UnderlyingType> template<typename UnderlyingType> void walk_node(Node<UnderlyingType>& node) {
void walk_node(Node<UnderlyingType>& node) { if (ImGui::TreeNode(
if(ImGui::TreeNode(&node, "min: (%f %f %f)\n max: (%f %f %f)", node.extent.min.x, node.extent.min.y, node.extent.min.z, node.extent.max.x, node.extent.max.y, node.extent.max.z)) { &node,
"min: (%f %f %f)\n max: (%f %f %f)",
node.extent.min.x,
node.extent.min.y,
node.extent.min.z,
node.extent.max.x,
node.extent.max.y,
node.extent.max.z)) {
ImGui::Text("Is split: %i", node.is_split); ImGui::Text("Is split: %i", node.is_split);
ImGui::Text("Contained triangles: %lu", node.contained_objects.size()); ImGui::Text("Contained triangles: %lu", node.contained_objects.size());
@ -239,7 +235,8 @@ int main(int, char*[]) {
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_Window* window = SDL_CreateWindow("raytracer", SDL_Window* window = SDL_CreateWindow(
"raytracer",
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
800, 800,

View file

@ -1,7 +1,7 @@
#include "scene.h" #include "scene.h"
#include <glm/gtx/perpendicular.hpp>
#include <functional> #include <functional>
#include <glm/gtx/perpendicular.hpp>
constexpr double pi = 3.14159265358979323846l; constexpr double pi = 3.14159265358979323846l;
@ -25,7 +25,14 @@ glm::vec3 fetch_normal(const Object& object, const tinyobj::mesh_t& mesh, const
return glm::vec3(nx, ny, nz); return glm::vec3(nx, ny, nz);
} }
bool test_triangle(const Ray ray, const Object& object, const tinyobj::mesh_t& mesh, const size_t i, float& tClosest, bool& intersection, HitResult& result) { bool test_triangle(
const Ray ray,
const Object& object,
const tinyobj::mesh_t& mesh,
const size_t i,
float& tClosest,
bool& intersection,
HitResult& result) {
const glm::vec3 v0 = fetch_position(object, mesh, i, 0) + object.position; const glm::vec3 v0 = fetch_position(object, mesh, i, 0) + object.position;
const glm::vec3 v1 = fetch_position(object, mesh, i, 1) + object.position; const glm::vec3 v1 = fetch_position(object, mesh, i, 1) + object.position;
const glm::vec3 v2 = fetch_position(object, mesh, i, 2) + object.position; const glm::vec3 v2 = fetch_position(object, mesh, i, 2) + object.position;
@ -103,8 +110,7 @@ std::optional<HitResult> test_scene(const Ray ray, const Scene& scene) {
return {}; return {};
} }
template<typename T> template<typename T> Node<T>* find_hit_ray_search(Node<T>& node, const Ray ray, std::vector<Node<T>*>* out) {
Node<T>* find_hit_ray_search(Node<T>& node, const Ray ray, std::vector<Node<T>*>* out) {
if (node.extent.contains(ray)) { if (node.extent.contains(ray)) {
if (node.is_split) { if (node.is_split) {
for (auto& child : node.children) for (auto& child : node.children)
@ -117,8 +123,7 @@ Node<T>* find_hit_ray_search(Node<T>& node, const Ray ray, std::vector<Node<T>*>
return nullptr; return nullptr;
} }
template<typename T> template<typename T> std::vector<Node<T>*> find_hit_ray(Node<T>& node, const Ray ray) {
std::vector<Node<T>*> find_hit_ray(Node<T>& node, const Ray ray) {
std::vector<Node<T>*> vec; std::vector<Node<T>*> vec;
find_hit_ray_search(node, ray, &vec); find_hit_ray_search(node, ray, &vec);
@ -134,7 +139,14 @@ std::optional<HitResult> test_scene_octree(const Ray ray, const Scene& scene) {
for (auto& object : scene.objects) { for (auto& object : scene.objects) {
for (auto& node : find_hit_ray(object->octree->root, ray)) { for (auto& node : find_hit_ray(object->octree->root, ray)) {
for (auto& triangle_object : node->contained_objects) { for (auto& triangle_object : node->contained_objects) {
if(test_triangle(ray, *object, *triangle_object.mesh, triangle_object.vertice_index, tClosest, intersection, result)) if (test_triangle(
ray,
*object,
*triangle_object.mesh,
triangle_object.vertice_index,
tClosest,
intersection,
result))
result.object = object.get(); result.object = object.get();
} }
} }
@ -195,7 +207,8 @@ std::optional<SceneResult> cast_scene(const Ray ray, Scene& scene, const bool us
result.direct = hit->object->color * diffuse * shadow; result.direct = hit->object->color * diffuse * shadow;
} }
if(auto reflect_result = cast_scene(Ray(hit->position, glm::reflect(ray.direction, hit->normal)), scene, use_bvh, depth + 1)) if (auto reflect_result =
cast_scene(Ray(hit->position, glm::reflect(ray.direction, hit->normal)), scene, use_bvh, depth + 1))
result.reflect = reflect_result->combined; result.reflect = reflect_result->combined;
// indirect lighting calculation // indirect lighting calculation
@ -213,8 +226,7 @@ std::optional<SceneResult> cast_scene(const Ray ray, Scene& scene, const bool us
const glm::vec3 rotated_dir = { const glm::vec3 rotated_dir = {
glm::dot({rotX.x, rotY.x, hit->normal.x}, sampled_dir), glm::dot({rotX.x, rotY.x, hit->normal.x}, sampled_dir),
glm::dot({rotX.y, rotY.y, hit->normal.y}, sampled_dir), glm::dot({rotX.y, rotY.y, hit->normal.y}, sampled_dir),
glm::dot({rotX.z, rotY.z, hit->normal.z}, sampled_dir) glm::dot({rotX.z, rotY.z, hit->normal.z}, sampled_dir)};
};
if (const auto indirect_result = cast_scene(Ray(ray.origin, rotated_dir), scene, use_bvh, depth + 1)) if (const auto indirect_result = cast_scene(Ray(ray.origin, rotated_dir), scene, use_bvh, depth + 1))
result.indirect += indirect_result->combined * cos_theta; result.indirect += indirect_result->combined * cos_theta;