Changed CMakeLists.txt to set the C standard to C11. Added multiple binary image files for new visual assets. Added several new image files to enhance rendering capabilities. Changed stb_image.h to improve support for various image formats. Changed ray tracing engine to enhance ray creation and intersection. Changed triangle structure to use a vertex array for better attribute handling. Changed scene initialization to accommodate new texture management.
111 lines
4.4 KiB
C
111 lines
4.4 KiB
C
#include "Algorithm/PathTracing.h"
|
|
#include "Algorithm/RayIntersection.h"
|
|
#include "Algorithm/BSDF.h"
|
|
#include "Lighting/LightEvaluation.h"
|
|
|
|
// TODO: Implement a faster methods like BVH, KD-Tree or uniform grid acceleration
|
|
// TODO: Split the diffuse and specular into different Monte Carlo, so we can decide the sample count for each one
|
|
vec4s path_trace(const scene_t* scene, ray_t ray, uint32_t sample_index, uint16_t max_depth)
|
|
{
|
|
const triangle_collection_t* triangles = &scene->triangles;
|
|
const bvh_tree_t* bvh_tree = &scene->bvh_tree;
|
|
const material_collection_t* materials = &scene->materials;
|
|
const light_collection_t* lights = &scene->lights;
|
|
|
|
vec4s accumulated_color = (vec4s){0.0f, 0.0f, 0.0f, 1.0f};
|
|
vec3s throughput = glms_vec3_one();
|
|
|
|
ray_t active_ray = ray;
|
|
vec3s prev_normal = glms_vec3_zero();
|
|
float pdf_bsdf = 1.0f;
|
|
|
|
uint16_t depth = 0;
|
|
while (depth < max_depth)
|
|
{
|
|
hit_result_t closest_hit = ray_intersect_scene(&active_ray, scene);
|
|
|
|
if (!closest_hit.hit)
|
|
{
|
|
vec3s sky_light = evaluate_bsdf_sky(scene, NULL, throughput, sample_index);
|
|
if (depth > 0)
|
|
{
|
|
// Have to multiply the weight since we evaluate the sky at each bounce
|
|
float pdf_nee = pdf_cosine_weighted_hemisphere(prev_normal, active_ray.direction);
|
|
float weight = power_heuristic(pdf_bsdf, pdf_nee);
|
|
sky_light = glms_vec3_scale(sky_light, weight);
|
|
}
|
|
accumulated_color = glms_vec4_add(accumulated_color, glms_vec4(sky_light, 0.0f));
|
|
break;
|
|
}
|
|
|
|
// Add the emission of the hit material to the accumulated color
|
|
material_t* hit_material = &materials->buffer[triangles->buffer[closest_hit.triangle_id].material_id];
|
|
vec3s emission = hit_material->emission;
|
|
accumulated_color = glms_vec4_add(accumulated_color, glms_vec4(glms_vec3_mul(throughput, emission), 0.0f));
|
|
|
|
light_shading_context_t light_context = {
|
|
.normal = closest_hit.normal,
|
|
.hit_point = closest_hit.point,
|
|
.wo = active_ray.direction,
|
|
.uv = closest_hit.uv,
|
|
|
|
.bounce_depth = depth,
|
|
|
|
.bvh_tree = bvh_tree,
|
|
.material = hit_material
|
|
};
|
|
|
|
// Running the light loop.
|
|
// TODO: Implementing other light types.
|
|
for (uint32_t i = 0; i < lights->directional_light_count; i++)
|
|
{
|
|
vec3s l = evaluate_bsdf_directional(lights->directional_lights[i], &light_context, throughput, sample_index);
|
|
accumulated_color = glms_vec4_add(accumulated_color, glms_vec4(l, 0.0f));
|
|
}
|
|
|
|
vec3s sky_light = evaluate_bsdf_sky(scene, &light_context, throughput, sample_index);
|
|
accumulated_color = glms_vec4_add(accumulated_color, glms_vec4(sky_light, 0.0f));
|
|
|
|
// Bounce and prepare for the next iteration
|
|
vec3s wo = glms_vec3_negate(active_ray.direction); // We need to negate the direction of the incoming ray
|
|
vec3s wi = sample_material_bsdf(hit_material, closest_hit.normal, wo, closest_hit.uv, sample_index, depth, &pdf_bsdf);
|
|
if (pdf_bsdf <= 0.0f)
|
|
{
|
|
break;
|
|
}
|
|
|
|
shading_context_t shading_context = {
|
|
.normal = closest_hit.normal,
|
|
.position = closest_hit.point,
|
|
.wi = wi,
|
|
.wo = wo,
|
|
.uv = closest_hit.uv,
|
|
};
|
|
vec3s bsdf = evaluate_material_bsdf(hit_material, &shading_context);
|
|
float cos_theta = fmaxf(0.0f, glms_vec3_dot(wi, closest_hit.normal));
|
|
|
|
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 > 1)
|
|
{
|
|
float q = fminf(glms_vec3_max(throughput), 0.95f);
|
|
float rr_sample = sobol_sample(sample_index, sobol_get_dimension(depth, PRNG_TERMINATE));
|
|
// float rr_sample = random_float();
|
|
if (rr_sample > q)
|
|
{
|
|
break; // Terminate the path
|
|
}
|
|
// Keep the energy of the path by scaling the throughput
|
|
throughput = glms_vec3_scale(throughput, 1.0f / q);
|
|
}
|
|
|
|
active_ray = ray_create(BIAS_RAY_ORIGION(closest_hit.point, closest_hit.normal), wi);
|
|
prev_normal = closest_hit.normal;
|
|
|
|
depth++;
|
|
}
|
|
|
|
return accumulated_color;
|
|
}
|