Commit f247b18f authored by 's avatar
Browse files

Initial commit

parents
build
.vs
assets/meshes/*
!assets/meshes/Spheres.dae
assets/textures/*
!assets/textures/ryfjallet
*.bmf
*.bsmf
build_VS
*.hdr
cmake_minimum_required(VERSION 3.1)
include(config.cmake)
include(${CMAKE_MODULE_PATH}/setup/system_check.cmake)
include(${CMAKE_MODULE_PATH}/setup/directory_macros.cmake)
include(${CMAKE_MODULE_PATH}/setup/external_libraries.cmake)
include(${CMAKE_MODULE_PATH}/setup/macros.cmake)
set(CMAKE_CXX_STANDARD 14)
if(SYS_WINDOWS)
add_definitions("-DLOG_PLATFORM_WINDOWS")
endif()
collect_subdirectories(PROJECT_EXECUTABLES ${CMAKE_SOURCE_DIR}/src/executables)
collect_subdirectories(PROJECT_LIBRARIES ${CMAKE_SOURCE_DIR}/src/libraries)
FOREACH(subdir ${PROJECT_LIBRARIES})
make_library(${subdir} ${CMAKE_SOURCE_DIR}/src/libraries/${subdir} LIBRARIES)
ENDFOREACH()
include_directories(${CMAKE_SOURCE_DIR}/include)
include_directories(${CMAKE_SOURCE_DIR}/src/libraries)
FOREACH(subdir ${PROJECT_EXECUTABLES})
make_executable(${subdir} ${CMAKE_SOURCE_DIR}/src/executables/${subdir})
target_link_libraries(${subdir} ${LIBRARIES})
ENDFOREACH()
\ No newline at end of file
# GLARE - An Open**GL** **a**nd **R**aytracing **E**ngine #
![Glare_exp.png](https://bitbucket.org/repo/75kRBX/images/866943033-Glare_exp.png)
## Uses a custom OpenGL C++ Wrapper that is mostly typesafe ##
All used GLenums are represented by fitting enum classes.
### OpenGL Features ###
* Tidy library folder.
* Loading Collada Scenes (*.dae)
* Loading images as Textures
* Saving image data as images, convertable from textures
* Easy rendering to framebuffers
* Intuitive shader construction
* Cube map skybox
* Environment mapped simple reflections with roughness
* Deferred rendering with a G-Buffer
* Phong shading
* Normal mapping
* Parallax mapping
* Custom control scheme loading
* Console logging system
* Component based scenegraph
* Saving and loading preferences
* Asset/Resource management
* OpenGL GLenum and GLbitfield type-safety with enum class wrapping
### Raytracing Features ###
* Pathtracer with 8 different BSDF's and semi-automatic BSDF choosing system
* Stackless Bounding volume hierarchy datastructure
* Different Methods for generating primary rays
* Generate and trace with a BVH
* Draw with a GBuffer (generally about 80% faster, but not as smooth)
* N-Tree (hierarchical voxelization)
* Uniform Grid (flat voxelization)
* Line Space mask generation in one command
* Line Space traversal? Not yet.
\ No newline at end of file
@echo off
setlocal enabledelayedexpansion
set /p path="Enter a path: "
set /p className="Enter a class name: "
set /p subNamespace="What namespace should it be in? "
set fileNameCPP=%className%.cpp
set fileNameH=%className%.h
set fileNameUpperH=%className%.h
for %%b in (A B C D E F G H I J K L M N O P Q R S T U V W X Y Z) do (
set "fileNameUpperH=!fileNameUpperH:%%b=%%b!"
)
set fileNameUpperH=__%fileNameUpperH:.=_%
if not exist src/%path%/%fileNameH% (
echo #ifndef %fileNameUpperH%>> src/%path%/%fileNameH%
echo #define %fileNameUpperH%>> src/%path%/%fileNameH%
echo.>> src/%path%/%fileNameH%
echo namespace glare>> src/%path%/%fileNameH%
echo {>> src/%path%/%fileNameH%
echo namespace %subNamespace%>> src/%path%/%fileNameH%
echo {>> src/%path%/%fileNameH%
echo class %className%>> src/%path%/%fileNameH%
echo {>> src/%path%/%fileNameH%
echo public:>> src/%path%/%fileNameH%
echo };>> src/%path%/%fileNameH%
echo }>> src/%path%/%fileNameH%
echo }>> src/%path%/%fileNameH%
echo.>> src/%path%/%fileNameH%
echo #endif //%fileNameUpperH%>> src/%path%/%fileNameH%
echo #include "%fileNameH%">> src/%path%/%fileNameCPP%
echo namespace glare>> src/%path%/%fileNameCPP%
echo {>> src/%path%/%fileNameCPP%
echo namespace %subNamespace%>> src/%path%/%fileNameCPP%
echo {>> src/%path%/%fileNameCPP%
echo.>> src/%path%/%fileNameCPP%
echo }>> src/%path%/%fileNameCPP%
echo }>> src/%path%/%fileNameCPP%
) else (
echo File %path%/%fileNameH% already exists!
)
call build
\ No newline at end of file
# Screenshots
This folder will contain your rendered Pathtracer images when you save them. They will be in HDR-32bit format (*.hdr* File) as they are being rendered as such.
\ No newline at end of file
#ifndef __BSDF_DIFFUSE_GLH
#define __BDSF_DIFFUSE_GLH
#include <raytracer/basic_structs.glh>
#include <raytracer/random.glh>
#include <raytracer/utilities.glh>
#include <bsdf/ray_transform.glh>
#include <bsdf/fresnel.glh>
vec3 bsdf__sampleDiffuse(const in Material material, const in vec2 random, const in Vertex vertex, const in Ray ray_in, inout Ray ray_out, out vec3 light_influence, out float pdf)
{
bool entering = dot(-ray_in.direction.xyz, vertex.normal.xyz) > 0.f;
vec3 hemi = randCosineHemisphere(random.x, random.y);
ray_out.direction.xyz = normalize(localToWorldNormal(entering ? hemi : -hemi, vertex.normal.xyz));
pdf = abs(dot(ray_out.direction, vertex.normal)) * ONE_OVER_PI;
if (pdf == 0.f)
{
return vec3(0.f);
}
ray_out.origin = vertex.position + 1e-5 * -ray_in.direction;
vec3 diffuse = material__getDiffuse(material, vertex.texcoord).xyz;
light_influence = diffuse * ONE_OVER_PI;
return diffuse * ONE_OVER_PI;
}
vec3 bsdf__sampleTranslucent(const in Material material, const in vec2 random, const in Vertex vertex, const in Ray ray_in, inout Ray ray_out, out vec3 light_influence, out float pdf)
{
bool entering = dot(-ray_in.direction, vertex.normal) > 0.f;
vec3 hemi = randCosineHemisphere(random.x, random.y);
/*if (entering) {
light_influence = vec3(1, 0, 0);
}*/
ray_out.direction.xyz =localToWorldNormal(hemi, (entering ? -1 : 1) * vertex.normal.xyz);
pdf = abs(dot(ray_out.direction, vertex.normal)) * ONE_OVER_PI;
ray_out.origin = vertex.position + 1e-5f * ray_in.direction;
if (pdf == 0.f)
{
return vec3(0.f);
}
vec3 diffuse = material__getDiffuse(material, vertex.texcoord).xyz;
light_influence = diffuse * ONE_OVER_PI;
return diffuse * ONE_OVER_PI;
}
vec3 bsdf__sampleGlass(const in Material material, const in vec2 random, const in Vertex vertex, const in Ray ray_in, inout Ray ray_out, out vec3 light_influence, out float pdf)
{
//Needed parameters for refraction and reflection
bool entering = dot(-ray_in.direction, vertex.normal) > 0.f;
float eta_i = entering ? 1.f : material.ior;
float eta_t = entering ? material.ior : 1.f;
float fresnel = dialectricFresnel(abs(dot(-ray_in.direction, vertex.normal)), eta_i, eta_t);
//refract ray.
ray_out.direction = refract(ray_in.direction, faceforward(vertex.normal, ray_in.direction, vertex.normal), eta_i / eta_t);
light_influence = vec3(0);
// Choose whether to sample refractive or reflective BSDF
if ((ray_out.direction.xyz != vec3(0)) && (random.x > fresnel) && (!isnan(ray_out.direction.x)))
{
ray_out.origin = vertex.position + 1e-5 * ray_out.direction;
pdf = 1.0f - fresnel;
vec3 ft = material__getTransparent(material, vertex.texcoord).xyz * (1.0f - fresnel);
return ft / abs(dot(ray_out.direction, vertex.normal));
}
ray_out.direction = reflect(ray_in.direction, faceforward(vertex.normal, ray_in.direction, vertex.normal));
ray_out.origin = vertex.position + 1e-5 * ray_out.direction;
pdf = fresnel;
return fresnel * material__getSpecular(material, vertex.texcoord).xyz / abs(dot(ray_out.direction, vertex.normal));
}
vec3 bsdf__sampleRoughGlass(const in Material material, const in vec2 random, const in Vertex vertex, const in Ray ray_in, inout Ray ray_out, out vec3 light_influence, out float pdf)
{
//Needed parameters for refraction and reflection
bool entering = dot(-ray_in.direction, vertex.normal) > 0.f;
float eta_i = entering ? 1.f : material.ior;
float eta_t = entering ? material.ior : 1.f;
float fresnel = dialectricFresnel(abs(dot(-ray_in.direction, vertex.normal)), eta_i, eta_t);
float roughness = clamp(1.f - (sqrt(material.specular_exponent) / 10.f), 0, 1);
vec3 diffuse = material__getDiffuse(material, vertex.texcoord).xyz;
light_influence = mix(vec3(0), diffuse * ONE_OVER_PI, roughness);
//refract ray.
vec3 refracted = refract(ray_in.direction, faceforward(vertex.normal, ray_in.direction, vertex.normal), eta_i / eta_t).xyz;
// Choose whether to sample refractive or reflective BSDF
if ((refracted != vec3(0)) && (random.x > fresnel) && (!isnan(refracted.x)))
{
float rad = radians(180.0f - (1.0f - roughness) * 180.0f);
vec3 sampledPoint = randAngle(random.x, random.y, rad);
ray_out.direction.xyz = localToWorldNormal(sampledPoint, refracted);
if (dot(ray_out.direction, faceforward(vertex.normal, ray_in.direction, vertex.normal)) > 0.0f)
{
ray_out.direction.xyz = localToWorldNormal(sampledPoint * vec3(-1, -1, 1), refracted);
}
pdf = mix(1.0f - fresnel, abs(dot(ray_out.direction, vertex.normal)) * ONE_OVER_PI, roughness);
vec3 ft = material__getTransparent(material, vertex.texcoord).xyz * (1.0f - fresnel);
ray_out.origin = vertex.position + 1e-5 * ray_out.direction;
return mix(ft / abs(dot(ray_out.direction, vertex.normal)), diffuse * ONE_OVER_PI, roughness);
}
float rad = radians(180.0f - (1.0f - roughness) * 180.0f);
vec3 reflected = reflect(ray_in.direction, faceforward(vertex.normal, ray_in.direction, vertex.normal)).xyz;
vec3 sampledPoint = randAngle(random.x, random.y, rad);
ray_out.direction.xyz = localToWorldNormal(sampledPoint, reflected);
if (dot(ray_out.direction, faceforward(vertex.normal, ray_in.direction, vertex.normal)) < 0.0f)
{
ray_out.direction.xyz = localToWorldNormal(sampledPoint * vec3(-1, -1, 1), reflected);
}
pdf = mix(fresnel, abs(dot(ray_out.direction, vertex.normal)) * ONE_OVER_PI, roughness);
ray_out.origin = vertex.position + 1e-5 * ray_out.direction;
return mix(fresnel * material__getSpecular(material, vertex.texcoord).xyz / abs(dot(ray_out.direction, vertex.normal)), diffuse * ONE_OVER_PI, roughness);
}
vec3 bsdf__sampleTransparent(const in Material material, const in vec2 random, const in Vertex vertex, const in Ray ray_in, inout Ray ray_out, out vec3 light_influence, out float pdf)
{
//refract ray.
ray_out.direction = ray_in.direction;
ray_out.origin = vertex.position + 1e-5 * ray_out.direction;
pdf = 1;
light_influence = vec3(0);
return material__getTransparent(material, vertex.texcoord).xyz / abs(dot(ray_out.direction, vertex.normal));
}
vec3 bsdf__sampleMirror(const in Material material, const in vec2 random, const in Vertex vertex, const in Ray ray_in, inout Ray ray_out, out vec3 light_influence, out float pdf)
{
pdf = 1.f;
ray_out.direction = reflect(ray_in.direction, faceforward(vertex.normal, ray_in.direction, vertex.normal));
light_influence = vec3(0);
ray_out.origin = vertex.position + 1e-5 * ray_out.direction;
return material__getSpecular(material, vertex.texcoord).xyz / abs(dot(ray_out.direction, vertex.normal));
}
vec3 bsdf__sampleGlossy(const in Material material, const in vec2 random, const in Vertex vertex, const in Ray ray_in, inout Ray ray_out, out vec3 light_influence, out float pdf)
{
float roughness = clamp(1.f - (sqrt(material.specular_exponent) / 10.f), 0, 1);
float rad = radians(180.0f - (1.0f - roughness) * 180.0f);
vec3 reflected = normalize(reflect(ray_in.direction, faceforward(vertex.normal, ray_in.direction, vertex.normal)).xyz);
vec3 sampledPoint = normalize(randAngle(random.x, random.y, rad));
vec3 diffuse = material__getDiffuse(material, vertex.texcoord).xyz;
light_influence = roughness * diffuse * ONE_OVER_PI;
ray_out.direction.xyz = normalize(localToWorldNormal(sampledPoint, reflected));
if (dot(ray_out.direction, faceforward(vertex.normal, ray_in.direction, vertex.normal)) < 0.0f)
{
ray_out.direction.xyz = normalize(localToWorldNormal(sampledPoint * vec3(-1, -1, 1), reflected));
}
ray_out.origin = vertex.position + 1e-5 * ray_out.direction;
pdf = 1.f - roughness * abs(dot(ray_out.direction, vertex.normal)) * ONE_OVER_PI;
return mix(material__getSpecular(material, vertex.texcoord).xyz / abs(dot(ray_out.direction, vertex.normal)), diffuse * ONE_OVER_PI, roughness);
}
vec3 bsdf__sampleEmissive(const in Material material, const in vec2 random, const in Vertex vertex, const in Ray ray_in, inout Ray ray_out, out vec3 light_influence, out float pdf)
{
pdf = 1.f;
ray_out.direction = vec4(0);
light_influence = material__getEmissive(material, vertex.texcoord).xyz;
ray_out.origin = vertex.position + 1e-5 * ray_out.direction;
return vec3(0);
}
const uint eGlossy = 1 << 0;
const uint eMirror = 1 << 1;
const uint eDiffuse = 1 << 2;
const uint eTransparentGlossy = 1 << 8;
const uint eTransparentMirror = 1 << 9;
const uint eTransparentDiffuse = 1 << 10;
const uint eTransparent = 1 << 11;
const uint eEmissive = 1 << 16;
vec3 bsdf__sample(const in Material material, const in vec2 random, const in Vertex vertex, const in Ray ray_in, inout Ray ray_out, out vec3 light_influence, out float pdf)
{
//Kind of crude but also kind of well functional bsdf selector.
ray_out.pixel = ray_in.pixel;
bool rough = material.specular_exponent < 100;
uint bitset = 1; //Glossy by default.
bitset = 1 << (1 * uint(!rough)); //mirror
bitset = 1 << (2 * uint(material.specular_exponent <= 1)); //glossy;
bitset = bitset << (8 * uint(length(material__getTransparent(material, vertex.texcoord).xyz) >= 0.1));
uint mask = uint((bitset & (0x700)) > 0) * uint(material.ior==1);
bitset = mask*(1 << 11) + ((1-mask)*bitset);
uint emissive = uint(length(material__getEmissive(material, vertex.texcoord).xyz) >= 0.01);
bitset = emissive*(1 << 16) + ((1 - emissive)*bitset);
switch (bitset)
{
default:
case eGlossy:
return bsdf__sampleGlossy(material, random, vertex, ray_in, ray_out, light_influence, pdf);
case eMirror:
return bsdf__sampleMirror(material, random, vertex, ray_in, ray_out, light_influence, pdf);
case eDiffuse:
return bsdf__sampleDiffuse(material, random, vertex, ray_in, ray_out, light_influence, pdf);
case eTransparentGlossy:
return bsdf__sampleRoughGlass(material, random, vertex, ray_in, ray_out, light_influence, pdf);
case eTransparentMirror:
return bsdf__sampleGlass(material, random, vertex, ray_in, ray_out, light_influence, pdf);
case eTransparentDiffuse:
return bsdf__sampleTranslucent(material, random, vertex, ray_in, ray_out, light_influence, pdf);
case eTransparent:
return bsdf__sampleTransparent(material, random, vertex, ray_in, ray_out, light_influence, pdf);
case eEmissive:
return bsdf__sampleEmissive(material, random, vertex, ray_in, ray_out, light_influence, pdf);
}
}
#endif //!__BDSF_DIFFUSE_GLH
\ No newline at end of file
#ifndef __FRESNEL_GLH
#define __FRESNEL_GLH
float dialectricFresnel(const in float cos_theta, in float eta_i, in float eta_t) {
float cos_theta_i = clamp(cos_theta, -1.f, 1.f);
// If we are not entering, we have to swap the indices of refraction:
if (cos_theta_i <= 0) {
float tmp = eta_i;
eta_i = eta_t;
eta_t = tmp;
cos_theta_i = abs(cos_theta_i);
}
// Snell's law
float sin_theta_i = sqrt(max(0.f, 1 - cos_theta_i * cos_theta_i));
float sin_theta_t = eta_i / eta_t * sin_theta_i;
if (sin_theta_t >= 1) {
return 1;
}
float cos_theta_t = sqrt(max(0.f, 1 - sin_theta_t * sin_theta_t));
float rparl = ((eta_t * cos_theta_i) - (eta_i * cos_theta_t)) /
((eta_t * cos_theta_i) + (eta_i * cos_theta_t));
float rperp = ((eta_i * cos_theta_i) - (eta_t * cos_theta_t)) /
((eta_i * cos_theta_i) + (eta_t * cos_theta_t));
// Valid only for unpolarised light, which is what we assume here.
return (rparl * rparl + rperp * rperp) / 2;
}
#endif
\ No newline at end of file
#ifndef __RAY_TRANSFORM_GLH
#define __RAY_TRANSFORM_GLH
vec3 worldToLocal(const in vec3 v, const in vec3 ss, const in vec3 ts, const in vec3 ns)
{
return vec3(dot(v, ss), dot(v, ts), dot(v, ns));
}
vec3 localToWorld(const in vec3 v, const in vec3 ss, const in vec3 ts, const in vec3 ns)
{
return v.x * ss + v.y * ts + v.z * ns;
}
vec3 localToWorldNormal(const in vec3 v, const in vec3 normal) {
vec3 perpendicular = normalize(
max(
max(
cross(normal, vec3(0.0, 1.0, 0.0)),
cross(normal, vec3(0.0, 0.0, 1.0))
),
cross(normal, vec3(1.0, 0.0, 0.0))
)
);
vec3 secondary_perpendicular = cross(normal, perpendicular);
perpendicular = cross(normal, secondary_perpendicular);
return localToWorld(v, perpendicular, secondary_perpendicular, normal); // bring vectors to local shading space
}
#endif // !__RAY_TRANSFORM_GLH
\ No newline at end of file
#version 430
in vec3 out_texcoord;
uniform samplerCube u_cube_map;
layout(location=0) out vec4 out_color;
layout(location = 1) out vec4 out_final_normal;
void main()
{
out_color = vec4(texture(u_cube_map, out_texcoord).rgb, 1);
out_final_normal = vec4(0,0,0,1);
}
\ No newline at end of file
#version 430
layout(location=0) in vec4 in_position;
layout(location=1) in vec4 in_normal;
layout(location=2) in vec2 in_texcoord;
uniform mat4 u_view_projection;
uniform mat4 u_model;
out vec3 out_texcoord;
void main()
{
gl_Position = (u_view_projection * u_model * in_position).xyzw;
out_texcoord = in_position.xyz;
}
\ No newline at end of file
#version 430
in vec3 out_texcoord;
uniform samplerCube u_cube_map;
layout(location = 0) out vec4 out_color;
layout(location = 1) out vec4 out_final_normal;
void main()
{
out_color = vec4(texture(u_cube_map, out_texcoord).rgb, 1);
out_final_normal = vec4(0, 0, 0, 1);
}
\ No newline at end of file
#version 430
layout(location = 0) in vec4 in_position;
layout(location = 1) in vec4 in_normal;
layout(location = 2) in vec2 in_texcoord;
uniform mat4 u_inv_view_projection;
uniform vec3 cam_position;
out vec3 out_texcoord;
void main()
{
gl_Position = in_position;
vec4 sky_vec = vec4(in_position.x, in_position.y, 1, 1);
sky_vec = u_inv_view_projection * sky_vec;
sky_vec /= sky_vec.w;
vec3 direction = sky_vec.xyz - cam_position;
out_texcoord = direction;
}
\ No newline at end of file
#ifndef __LINESPACE_GLH
#define __LINESPACE_GLH
#extension GL_ARB_shading_language_include : require
#extension GL_ARB_compute_variable_group_size : require
#extension GL_NV_gpu_shader5 : require
#extension GL_NV_shader_buffer_load : require
layout(local_size_variable) in;
#include <raytracer/basic_structs.glh>
#include <raytracer/utilities.glh>
#define FACE_BIAS 0.003
#define T_MIN_BIAS 0.0001
struct Voxel
{
Bounds bounds;
UIntRange children;
uint containment_flags;
uint depth;
};
uniform struct
{
uint node_count;
uint max_depth;
Triangle* triangles;
Int32Range* candidates;
Voxel* voxels;
} u_ntree;
uniform struct
{
uint resolution;
uint resolution_pow2;
uint resolution_6xpow2;
uint entries_per_node;
//equals lines buffer item count (which is approx. line count/32)
uint entry_count;
//Buffer
uint32_t* lines;
} u_linespace;
const int c_correllating_faces[3][2] = {
{1, 2}, {0, 2}, {0, 1}
};
bool getLineSpaceEntry(int nodeIndex, int start_face, int start_dim_a, int start_dim_b, int end_face, int end_dim_a, int end_dim_b) // faces in [0..5]
{
int lineIndex = (start_face * int(u_linespace.resolution_pow2) + start_dim_b * int(u_linespace.resolution) + start_dim_a) * int(u_linespace.resolution_6xpow2) +
(end_face * int(u_linespace.resolution_pow2) + end_dim_b * int(u_linespace.resolution) + end_dim_a);
return (u_linespace.lines[nodeIndex * int(u_linespace.entries_per_node) + ((lineIndex) >> 5)] & (1 << (lineIndex & 31))) != 0;
}
bool faceIsPlausible(const in float axis_value)
{
return abs(axis_value) < FACE_BIAS;
}
struct StackElement
{
vec3 delta;
float t_min;
vec3 t_next;
float t_max;
ivec3 current_index;
int node_index;
int start_face_index;
int end_face_index;
};
bool lspace_intersectsAny(const in Ray ray, const in float max_t, inout uint voxel_index, inout vec4 debug_color)
{
//TODO: FIX!
//Why? Somewhere in here there is a HUGE buffer overflow. At least I think so. It may also be some kind of indetermined loop or something of that I can't think right now.
return false;
Voxel root = u_ntree.voxels[0];
StackElement stack[5];
//Initialize delta
vec3 step = sign(ray.direction.xyz);
stack[0].delta = step / ray.direction.xyz * bounds__size(root.bounds).xyz;
//Initialize t_min and t_max
vec3 t_max = (root.bounds.max.xyz - ray.origin.xyz) / ray.direction.xyz;
vec3 t_min = (root.bounds.min.xyz - ray.origin.xyz) / ray.direction.xyz;
stack[0].t_min = compMax(min(t_min, t_max));
stack[0].t_max = min(compMin(max(t_min, t_max)), max_t);
if (stack[0].t_max < stack[0].t_min || stack[0].t_max < 0) return false;
stack[0].t_min = max(stack[0].t_min, 0);
const ivec3 max_index = ivec3(u_linespace.resolution - 1);
vec3 start_position = ((ray.origin.xyz + stack[0].t_min*ray.direction.xyz) - root.bounds.min.xyz) / (bounds__size(root.bounds).xyz / u_linespace.resolution);
stack[0].current_index = max(min(ivec3(start_position), max_index), 0);
stack[0].delta /= vec3(u_linespace.resolution);
vec3 next_factor = start_position - vec3(stack[0].current_index);
next_factor.x = mix(next_factor.x, 1.0f - next_factor.x, floor((sign(step.x) + 1) / 2));
next_factor.y = mix(next_factor.y, 1.0f - next_factor.y, floor((sign(step.y) + 1) / 2));
next_factor.z = mix(next_factor.z, 1.0f - next_factor.z, floor((sign(step.z) + 1) / 2));
stack[0].t_next = next_factor * stack[0].delta + stack[0].t_min;
stack[0].node_index = 0;
stack[0].start_face_index = -1;
for (int i = 0; i < 3; ++i)
{
//Replaces the following if-statement
//if (faceIsPlausible(start_position[i]) || faceIsPlausible(start_position[i] - u_linespace.resolution)) stack[0].sFaceIndex = i;
stack[0].start_face_index = max(stack[0].start_face_index + 1, (i + 1) * int(faceIsPlausible(start_position[i]) || faceIsPlausible(start_position[i] - u_linespace.resolution))) - 1;
}
//Now, the start face index is -1, if the ray begins inside the voxel, otherwise it is between 0 and 2
//Temporary variables used when traversing.
//Start