Refactor path tracing and material rendering system
Added a new enum `path_state` and a struct `path_output` in `Common.h` to manage path tracing states and outputs. Added a new `simple_lit_render_loop` function in `SimpleLit.c` to handle rendering for simple lit materials, integrating light contributions and BSDF evaluations. Changed the function signatures in `Light.h` to use `path_output` instead of `vec3s` for BSDF evaluations. Changed the `evaluate_bsdf_directional` function in `LightEvaluation.h` to return `path_output` instead of `vec3s`. Changed the `evaluate_bsdf_sky` function in `LightEvaluation.h` to return `path_output` and updated its implementation accordingly. Changed the function signature of `evaluate_bsdf_const_sky` in `SkyLight.h` to return `path_output` and modified its implementation to match. Removed several old BSDF-related functions in `Material.c` that are no longer needed due to the new structure. Updated the `material_create` function in `Material.c` to accept the new render loop function pointer. Updated the `path_trace` function in `PathTracing.c` to utilize the new `path_output` structure for managing light contributions and state transitions during path tracing. Updated the `evaluate_bsdf_directional` function in `LightEvaluation.c` to return `path_output` and adjusted its internal logic to populate the output structure. Updated the `evaluate_bsdf_const_sky` function in `SkyLight.c` to return `path_output` and modified its logic to handle light contributions correctly. Updated the intensity of the sky light to `0.0f` during scene setup in `main.c`, effectively disabling it.
This commit is contained in:
@@ -3,7 +3,6 @@
|
||||
#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)
|
||||
{
|
||||
@@ -21,91 +20,75 @@ vec4s path_trace(const scene_t* scene, ray_t ray, uint32_t sample_index, uint16_
|
||||
|
||||
if (!closest_hit.hit)
|
||||
{
|
||||
vec3s sky_light = evaluate_bsdf_sky(scene, NULL, throughput, sample_index);
|
||||
vec3s sky_light = evaluate_bsdf_sky(&scene->lights, NULL, throughput, sample_index).direct_lighting;
|
||||
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
|
||||
const material_t* hit_material = &scene->materials.buffer[scene->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 =
|
||||
{
|
||||
.hit_point = closest_hit.point,
|
||||
.normal = closest_hit.normal,
|
||||
.tangent = closest_hit.tangent,
|
||||
.uv = closest_hit.uv,
|
||||
.wo = active_ray.direction,
|
||||
|
||||
.bounce_depth = depth,
|
||||
|
||||
.bvh_tree = &scene->bvh_tree,
|
||||
.material = hit_material,
|
||||
.textures = &scene->textures,
|
||||
};
|
||||
|
||||
// Running the light loop.
|
||||
// TODO: Implementing other light types.
|
||||
for (uint32_t i = 0; i < scene->lights.directional_light_count; i++)
|
||||
{
|
||||
vec3s l = evaluate_bsdf_directional(scene->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
|
||||
shading_context_t shading_context =
|
||||
{
|
||||
.position = closest_hit.point,
|
||||
.normal = closest_hit.normal,
|
||||
.tangent = closest_hit.tangent,
|
||||
.uv = closest_hit.uv,
|
||||
.wo = glms_vec3_negate(active_ray.direction),
|
||||
.wo = active_ray.direction,
|
||||
.throughput = throughput,
|
||||
|
||||
.sample_index = sample_index,
|
||||
.bounce_depth = depth,
|
||||
|
||||
.bvh_tree = &scene->bvh_tree,
|
||||
.triangles = &scene->triangles,
|
||||
.lights = &scene->lights,
|
||||
.textures = &scene->textures,
|
||||
};
|
||||
|
||||
vec3s wi = sample_material_bsdf(hit_material, &shading_context, sample_index, depth, &pdf_bsdf);
|
||||
shading_context.wi = wi;
|
||||
if (pdf_bsdf <= 0.0f)
|
||||
path_output material_output = render_material(hit_material, &shading_context);
|
||||
accumulated_color = glms_vec4_add(accumulated_color, glms_vec4(material_output.direct_lighting, 0.0f));
|
||||
|
||||
float cos_theta = fmaxf(0.0f, glms_vec3_dot(material_output.wi, closest_hit.normal));
|
||||
throughput = glms_vec3_mul(throughput, material_output.bsdf);
|
||||
|
||||
switch (material_output.state)
|
||||
{
|
||||
break;
|
||||
case TERMINATE:
|
||||
goto end_path_trace;
|
||||
case PATH_THROUGH:
|
||||
active_ray = ray_create(BIAS_RAY_ORIGION(closest_hit.point, glms_vec3_negate(closest_hit.normal)), active_ray.direction);
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
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));
|
||||
if (rr_sample > q)
|
||||
float rr = sobol_sample(sample_index, sobol_get_dimension(depth, PRNG_TERMINATE));
|
||||
if (rr > q)
|
||||
{
|
||||
break; // Terminate the path
|
||||
goto end_path_trace;
|
||||
}
|
||||
// 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);
|
||||
active_ray = ray_create(BIAS_RAY_ORIGION(closest_hit.point, closest_hit.normal), material_output.wi);
|
||||
prev_normal = closest_hit.normal;
|
||||
pdf_bsdf = material_output.pdf;
|
||||
|
||||
depth++;
|
||||
}
|
||||
|
||||
end_path_trace:
|
||||
return accumulated_color;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user