Reformat code
This commit is contained in:
parent
f0713452fc
commit
81d5045037
13 changed files with 370 additions and 319 deletions
33
.clang-format
Normal file
33
.clang-format
Normal 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
8
.editorconfig
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
insert_final_newline = true
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
tab_width = 4
|
||||||
|
max_line_length = 120
|
|
@ -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.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 = {};
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -9,4 +9,4 @@ namespace lighting {
|
||||||
|
|
||||||
return n_dot_l;
|
return n_dot_l;
|
||||||
}
|
}
|
||||||
};
|
}; // namespace lighting
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
61
src/main.cpp
61
src/main.cpp
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Add table
Reference in a new issue