Enhance graphics library functionality and structure
Added new function signatures in `assimp-vc143-mt.lib` for improved logging, parsing, and vector operations. Added new metadata and configuration information in `assimp-vc143-mt.dll` for versioning and licensing compliance. Added Sobol sequence generation in `Sobol.c` for quasi-random sampling. Added window message handling in `Window.c` for rendering graphics. Added ray-triangle intersection tests in `RayIntersection.c` for collision detection. Added functions for loading mesh data in `Mesh.c` to support 3D model import. Added functions for managing triangle collections in `Triangle.c` to enhance geometric data handling. Added light evaluation functions in `LightEvaluation.c` and `SkyLight.c` for realistic rendering. Added sampling and evaluation functions for simple lit materials in `SimpleLit.c`. Changed various header files to include copyright and licensing information. Changed existing functions in multiple files to improve performance and clarity. Removed unused code in several files to streamline the library.
This commit is contained in:
@@ -1,104 +1,73 @@
|
||||
#include "Algorithm/PathTracing.h"
|
||||
#include "Common.h"
|
||||
#include "Material.h"
|
||||
#include "Algorithm/RayIntersection.h"
|
||||
#include "Algorithm/BSDF.h"
|
||||
#include "Algorithm/Sobol.h"
|
||||
#include "Lighting/LightEvaluation.h"
|
||||
|
||||
static hit_result_t ray_intersect(const triangle_t triangle, const ray_t ray)
|
||||
// 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
|
||||
vec3s path_trace(const scene_t* scene, const ray_t ray, const uint32_t sample_index, const int max_depth)
|
||||
{
|
||||
hit_result_t result = {0};
|
||||
const triangle_collection_t* triangles = &scene->triangles;
|
||||
const material_collection_t* materials = &scene->materials;
|
||||
const light_collection_t* lights = &scene->lights;
|
||||
|
||||
vec3s normal = triangle.normal;
|
||||
float n_dot_r = glms_vec3_dot(normal, ray.direction);
|
||||
if (n_dot_r > 0.0f)
|
||||
{
|
||||
normal = glms_vec3_scale(normal, -1.0f);
|
||||
}
|
||||
|
||||
// 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, triangle.point1) - glms_vec3_dot(normal, ray.origin)) / glms_vec3_dot(normal, ray.direction);
|
||||
|
||||
if (distance < FLT_EPSILON)
|
||||
{
|
||||
result.hit = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
vec3s intersection_point = glms_vec3_add(ray.origin, glms_vec3_scale(ray.direction, distance));
|
||||
|
||||
// Check if the intersection point is inside the triangle using barycentric coordinates
|
||||
vec3s edge1 = glms_vec3_sub(triangle.point2, triangle.point1);
|
||||
vec3s edge2 = glms_vec3_sub(triangle.point3, triangle.point2);
|
||||
vec3s edge3 = glms_vec3_sub(triangle.point1, triangle.point3);
|
||||
vec3s vp = glms_vec3_sub(intersection_point, triangle.point1);
|
||||
vec3s vp2 = glms_vec3_sub(intersection_point, triangle.point2);
|
||||
vec3s vp3 = glms_vec3_sub(intersection_point, triangle.point3);
|
||||
|
||||
vec3s c1 = glms_vec3_cross(edge1, vp);
|
||||
vec3s c2 = glms_vec3_cross(edge2, vp2);
|
||||
vec3s c3 = glms_vec3_cross(edge3, vp3);
|
||||
|
||||
if (glms_vec3_dot(triangle.normal, c1) < 0.0f
|
||||
|| glms_vec3_dot(triangle.normal, c2) < 0.0f
|
||||
|| glms_vec3_dot(triangle.normal, c3) < 0.0f)
|
||||
{
|
||||
result.hit = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
result.hit = true;
|
||||
result.point = intersection_point;
|
||||
result.normal = normal;
|
||||
result.distance = distance;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// TODO: Implement faster methods like BVH, KD-Tree or uniform grid acceleration
|
||||
vec3s path_trace(const triangle_collection_t* triangles, const material_collection_t* materials, ray_t ray, int max_depth)
|
||||
{
|
||||
vec3s accumulated_color = glms_vec3_zero();
|
||||
vec3s throughput = glms_vec3_one();
|
||||
|
||||
ray_t active_ray = ray;
|
||||
vec3s prev_normal = glms_vec3_zero();
|
||||
float pdf_bsdf = 1.0f; // Even though pdf_bsdf should be avaliable after the first bounce. For seafty, we set it to 1.0f for the first iteration.
|
||||
sobol_state_t sobol_state = {sample_index, 0};
|
||||
|
||||
int depth = 0;
|
||||
while (depth < max_depth)
|
||||
{
|
||||
uint8_t material_id = 255;
|
||||
hit_result_t closest_hit = {0};
|
||||
closest_hit.distance = 1145141919.810f;
|
||||
|
||||
for (uint64_t i = 0; i < triangles->count; i++)
|
||||
{
|
||||
hit_result_t hit_result = ray_intersect(triangles->buffer[i], ray);
|
||||
if (hit_result.hit && hit_result.distance < closest_hit.distance)
|
||||
{
|
||||
closest_hit = hit_result;
|
||||
material_id = triangles->buffer[i].material_id;
|
||||
}
|
||||
}
|
||||
hit_result_t closest_hit = ray_intersect_closest(triangles, active_ray);
|
||||
|
||||
if (!closest_hit.hit)
|
||||
{
|
||||
// accumulated_color = glms_vec3_add(accumulated_color, throughput); // TODO: Skybox
|
||||
vec3s sky_light = evaluate_bsdf_sky(scene, NULL, &sobol_state);
|
||||
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_vec3_add(accumulated_color, sky_light); // TODO: Skybox
|
||||
break;
|
||||
}
|
||||
|
||||
material_t* hit_material = &materials->buffer[material_id];
|
||||
// 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_vec3_add(accumulated_color, glms_vec3_mul(throughput, emission));
|
||||
|
||||
float pdf;
|
||||
vec3s wo = glms_vec3_negate(ray.direction); // We need to negate the direction of the incoming ray
|
||||
vec3s wi = sample_material_bsdf(hit_material, closest_hit.normal, wo, &pdf);
|
||||
//vec3s wi = random_cosine_direction(closest_hit.normal);
|
||||
//float cos_theta_s = fmaxf(0.0f, glms_vec3_dot(wi, closest_hit.normal));
|
||||
//float pdf = cos_theta_s / (float)M_PI;
|
||||
if (pdf < 0.0f)
|
||||
light_shading_context_t light_context = {
|
||||
.normal = closest_hit.normal,
|
||||
.hit_point = closest_hit.point,
|
||||
.wo = active_ray.direction,
|
||||
.throughput = throughput,
|
||||
.triangles = triangles,
|
||||
.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, &sobol_state);
|
||||
accumulated_color = glms_vec3_add(accumulated_color, l);
|
||||
}
|
||||
|
||||
vec3s sky_light = evaluate_bsdf_sky(scene, &light_context, &sobol_state);
|
||||
accumulated_color = glms_vec3_add(accumulated_color, sky_light);
|
||||
|
||||
// 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, &sobol_state, &pdf_bsdf);
|
||||
if (pdf_bsdf <= 0.0f)
|
||||
{
|
||||
break;
|
||||
}
|
||||
@@ -110,20 +79,24 @@ vec3s path_trace(const triangle_collection_t* triangles, const material_collecti
|
||||
};
|
||||
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));
|
||||
|
||||
// We do Russian roulette to decide whether to continue tracing or terminate the path
|
||||
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)
|
||||
{
|
||||
float q = fminf(glms_vec3_max(throughput), 0.95f);
|
||||
if (random_float() > q)
|
||||
{
|
||||
break; // Terminate the path
|
||||
break; // Terminate the path
|
||||
}
|
||||
// Keep the energy of the path by scaling the throughput
|
||||
throughput = glms_vec3_scale(throughput, 1.0f / q);
|
||||
}
|
||||
|
||||
ray.origin = glms_vec3_add(closest_hit.point, glms_vec3_scale(closest_hit.normal, FLT_EPSILON));
|
||||
ray.direction = wi;
|
||||
active_ray.origin = glms_vec3_add(closest_hit.point, glms_vec3_scale(closest_hit.normal, FLT_EPSILON));
|
||||
active_ray.direction = wi;
|
||||
prev_normal = closest_hit.normal;
|
||||
|
||||
depth++;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user