Enhance build system and project documentation
Added LICENSE file with MIT License and copyright notice. Added preview.png binary file for project assets. Changed CMakeLists.txt to include asset copying command. Changed mesh loading in Mesh.c to support smooth normals. Changed ray origin biasing in PathTracing.c and shadow rays. Changed ray-triangle intersection logic in RayIntersection.c. Changed ray_intersect_bvh_count function in Debug.c to static. Changed rendering functions in Scene.c with TODO for optimization. Updated README.md with project description and build instructions. Updated window dimensions in main.c for testing purposes.
This commit is contained in:
@@ -84,7 +84,7 @@ vec4s path_trace(const scene_t* scene, ray_t ray, uint32_t sample_index, uint16_
|
||||
throughput = glms_vec3_mul(throughput, glms_vec3_scale(bsdf, cos_theta / pdf_bsdf));
|
||||
|
||||
// We do Russian roulette to decide whether to continue tracing or terminate the path
|
||||
if (depth > 2)
|
||||
if (depth > 1)
|
||||
{
|
||||
float q = fminf(glms_vec3_max(throughput), 0.95f);
|
||||
float rr_sample = sobol_sample(sample_index, sobol_get_dimension(depth, PRNG_TERMINATE));
|
||||
@@ -97,7 +97,7 @@ vec4s path_trace(const scene_t* scene, ray_t ray, uint32_t sample_index, uint16_
|
||||
throughput = glms_vec3_scale(throughput, 1.0f / q);
|
||||
}
|
||||
|
||||
active_ray.origin = glms_vec3_add(closest_hit.point, glms_vec3_scale(closest_hit.normal, 1.192092896e-04F));
|
||||
active_ray.origin = BIAS_RAY_ORIGION(closest_hit.point, closest_hit.normal);
|
||||
active_ray.direction = wi;
|
||||
prev_normal = closest_hit.normal;
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "algorithm/RayIntersection.h"
|
||||
#include "Geometry/Triangle.h"
|
||||
#include "cglm/struct/vec3.h"
|
||||
|
||||
hit_result_t ray_intersect_triangle(ray_t ray, triangle_t triangle)
|
||||
{
|
||||
@@ -15,16 +16,14 @@ hit_result_t ray_intersect_triangle(ray_t ray, triangle_t triangle)
|
||||
// triangle is parallel to the ray
|
||||
if (fabsf(n_dot_r) < FLT_EPSILON)
|
||||
{
|
||||
result.hit = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Get distance from ray origin to triangle plane
|
||||
float distance = (glms_vec3_dot(normal_face, triangle.point_1) - glms_vec3_dot(normal_face, ray.origin)) / glms_vec3_dot(normal_face, ray.direction);
|
||||
|
||||
if (distance < FLT_EPSILON)
|
||||
if (distance < RAY_EPSILON)
|
||||
{
|
||||
result.hit = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -43,99 +42,25 @@ hit_result_t ray_intersect_triangle(ray_t ray, triangle_t triangle)
|
||||
vec3s c3 = glms_vec3_cross(edge3, vp3);
|
||||
|
||||
if (glms_vec3_dot(triangle.normal_face, c1) < 0.0f
|
||||
|| glms_vec3_dot(triangle.normal_face, c2) < 0.0f
|
||||
|| glms_vec3_dot(triangle.normal_face, c2) < 0.0f
|
||||
|| glms_vec3_dot(triangle.normal_face, c3) < 0.0f)
|
||||
{
|
||||
result.hit = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Normal interpolation
|
||||
float d00 = glms_vec3_dot(edge1, edge1);
|
||||
float d01 = glms_vec3_dot(edge1, edge2);
|
||||
float d11 = glms_vec3_dot(edge2, edge2);
|
||||
float d20 = glms_vec3_dot(vp, edge1);
|
||||
float d21 = glms_vec3_dot(vp, edge2);
|
||||
|
||||
float denom = d00 * d11 - d01 * d01;
|
||||
|
||||
float v = (d11 * d20 - d01 * d21) / denom;
|
||||
float w = (d00 * d21 - d01 * d20) / denom;
|
||||
float u = 1.0f - v - w;
|
||||
|
||||
vec3s normal_interp = glms_vec3_addadd(
|
||||
glms_vec3_scale(triangle.normal_1, u),
|
||||
glms_vec3_scale(triangle.normal_2, v),
|
||||
glms_vec3_scale(triangle.normal_3, w));
|
||||
normal_interp = glms_vec3_normalize(normal_interp);
|
||||
if (n_dot_r > 0.0f)
|
||||
{
|
||||
normal_interp = glms_vec3_negate(normal_interp);
|
||||
}
|
||||
// TODO: Normal interpolation
|
||||
|
||||
result.hit = true;
|
||||
result.point = intersection_point;
|
||||
result.normal = normal_interp;
|
||||
result.normal = normal_face;
|
||||
result.distance = distance;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static hit_result_t intersect_triangle(ray_t ray, triangle_t tri)
|
||||
{
|
||||
hit_result_t result = {0};
|
||||
|
||||
vec3s edge1 = glms_vec3_sub(tri.point_2, tri.point_1);
|
||||
vec3s edge2 = glms_vec3_sub(tri.point_3, tri.point_1);
|
||||
vec3s h = glms_vec3_cross(ray.direction, edge2);
|
||||
float a = glms_vec3_dot(edge1, h);
|
||||
|
||||
if (a > -FLT_EPSILON && a < FLT_EPSILON)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
float f = 1.0f / a;
|
||||
vec3s s = glms_vec3_sub(ray.origin, tri.point_1);
|
||||
float u = f * glms_vec3_dot(s, h);
|
||||
|
||||
if (u < 0.0f || u > 1.0f)
|
||||
{
|
||||
return result; // Hit outside the triangle's u range.
|
||||
}
|
||||
|
||||
vec3s q = glms_vec3_cross(s, edge1);
|
||||
float v = f * glms_vec3_dot(ray.direction, q);
|
||||
|
||||
if (v < 0.0f || u + v > 1.0f)
|
||||
{
|
||||
return result; // Hit outside the triangle's v range.
|
||||
}
|
||||
|
||||
// At this stage we can compute t to find out where the intersection point is on the line.
|
||||
float t = f * glms_vec3_dot(edge2, q);
|
||||
float esp = fmaxf(glms_vec3_max(glms_vec3_abs(edge1)), glms_vec3_max(glms_vec3_abs(edge2))) * 1.192092896e-04F;
|
||||
if (t > 1.192092896e-04F)
|
||||
{
|
||||
result.hit = true;
|
||||
result.distance = t;
|
||||
result.point = glms_vec3_add(ray.origin, glms_vec3_scale(ray.direction, t));
|
||||
result.normal = glms_vec3_cross(edge1, edge2);
|
||||
if (glms_vec3_dot(result.normal, ray.direction) > 0)
|
||||
{
|
||||
result.normal = glms_vec3_scale(result.normal, -1.0f);
|
||||
}
|
||||
result.normal = glms_vec3_normalize(result.normal);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool ray_intersect_aabb(ray_t ray, aabb_t aabb, float* enter_out, float* exit_out)
|
||||
{
|
||||
//vec3s inv_dir = glms_vec3_div(glms_vec3_one(), ray.direction);
|
||||
// vec3s inv_dir = glms_vec3_div(glms_vec3_one(), ray.direction);
|
||||
vec3s inv_dir;
|
||||
inv_dir.x = ray.direction.x != 0.0f ? 1.0f / ray.direction.x : FLT_MAX;
|
||||
inv_dir.y = ray.direction.y != 0.0f ? 1.0f / ray.direction.y : FLT_MAX;
|
||||
@@ -150,7 +75,7 @@ bool ray_intersect_aabb(ray_t ray, aabb_t aabb, float* enter_out, float* exit_ou
|
||||
float tmin = fminf(t1, t2);
|
||||
float tmax = fmaxf(t1, t2);
|
||||
t_near = fmaxf(t_near, tmin);
|
||||
t_far = fminf(t_far, tmax);
|
||||
t_far = fminf(t_far, tmax);
|
||||
}
|
||||
// Y axis
|
||||
{
|
||||
@@ -159,7 +84,7 @@ bool ray_intersect_aabb(ray_t ray, aabb_t aabb, float* enter_out, float* exit_ou
|
||||
float tmin = fminf(t1, t2);
|
||||
float tmax = fmaxf(t1, t2);
|
||||
t_near = fmaxf(t_near, tmin);
|
||||
t_far = fminf(t_far, tmax);
|
||||
t_far = fminf(t_far, tmax);
|
||||
}
|
||||
// Z axis
|
||||
{
|
||||
@@ -168,7 +93,7 @@ bool ray_intersect_aabb(ray_t ray, aabb_t aabb, float* enter_out, float* exit_ou
|
||||
float tmin = fminf(t1, t2);
|
||||
float tmax = fmaxf(t1, t2);
|
||||
t_near = fmaxf(t_near, tmin);
|
||||
t_far = fminf(t_far, tmax);
|
||||
t_far = fminf(t_far, tmax);
|
||||
}
|
||||
|
||||
if (t_near > t_far || t_far < 0.0f)
|
||||
@@ -176,8 +101,10 @@ bool ray_intersect_aabb(ray_t ray, aabb_t aabb, float* enter_out, float* exit_ou
|
||||
return false;
|
||||
}
|
||||
|
||||
if (enter_out) *enter_out = t_near;
|
||||
if (exit_out) *exit_out = t_far;
|
||||
if (enter_out)
|
||||
*enter_out = t_near;
|
||||
if (exit_out)
|
||||
*exit_out = t_far;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -191,18 +118,19 @@ static inline float distance_to_aabb(vec3s point, aabb_t aabb)
|
||||
}
|
||||
|
||||
// TODO: Use a stack to avoid recursion.
|
||||
void ray_intersect_bvh(const ray_t ray, const bvh_node_t* bvh_nodes,
|
||||
const uint64_t* primitive_indices, const triangle_collection_t* all_triangles, uint64_t node_index,
|
||||
float* closest_out, hit_result_t* best_hit_out)
|
||||
void ray_intersect_bvh(const ray_t ray, const bvh_node_t* bvh_nodes, const uint64_t* primitive_indices, const triangle_collection_t* all_triangles, uint64_t node_index, float* closest_out,
|
||||
hit_result_t* best_hit_out)
|
||||
{
|
||||
const bvh_node_t* node = &bvh_nodes[node_index];
|
||||
|
||||
float enter, exit;
|
||||
if (!ray_intersect_aabb(ray, node->bounds, &enter, &exit)) {
|
||||
if (!ray_intersect_aabb(ray, node->bounds, &enter, &exit))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (enter > *closest_out) {
|
||||
if (enter > *closest_out)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -212,8 +140,8 @@ void ray_intersect_bvh(const ray_t ray, const bvh_node_t* bvh_nodes,
|
||||
for (uint32_t i = 0; i < node->primitive_count; i++)
|
||||
{
|
||||
uint64_t triangle_index = primitive_indices[node->start_index + i];
|
||||
hit_result_t hit_result = intersect_triangle(ray, all_triangles->buffer[triangle_index]);
|
||||
if (hit_result.hit && hit_result.distance < *closest_out )
|
||||
hit_result_t hit_result = ray_intersect_triangle(ray, all_triangles->buffer[triangle_index]);
|
||||
if (hit_result.hit && hit_result.distance < *closest_out)
|
||||
{
|
||||
hit_result.triangle_id = triangle_index;
|
||||
*best_hit_out = hit_result;
|
||||
@@ -233,7 +161,6 @@ void ray_intersect_bvh(const ray_t ray, const bvh_node_t* bvh_nodes,
|
||||
bool hit_left_aabb = ray_intersect_aabb(ray, left_child->bounds, &left_enter, &left_exit);
|
||||
bool hit_right_aabb = ray_intersect_aabb(ray, right_child->bounds, &right_enter, &right_exit);
|
||||
|
||||
|
||||
// Traverse children based on closest AABB and current best hit distance (*closest_t)
|
||||
if (hit_left_aabb && hit_right_aabb)
|
||||
{
|
||||
@@ -270,8 +197,7 @@ hit_result_t ray_intersect_scene(ray_t ray, const scene_t* scene)
|
||||
hit_result_t result = {0};
|
||||
float closest = FLT_MAX;
|
||||
|
||||
if (scene == NULL || scene->bvh_tree.nodes == NULL
|
||||
|| scene->triangles.count == 0 || scene->bvh_tree.node_count == 0 || scene->bvh_tree.primitive_count == 0)
|
||||
if (scene == NULL || scene->bvh_tree.nodes == NULL || scene->triangles.count == 0 || scene->bvh_tree.node_count == 0 || scene->bvh_tree.primitive_count == 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user