Update AOV support, ray intersection logic, and README

Added:
- AOV support for normals, albedo, and depth marked as completed.
- New function `normal_unpack` in `BSDF.h`.
- New field `esp` in `ray_t` structure in `RayIntersection.h`.

Changed:
- Updated `normal_ts_to_ws` to accept an additional parameter.
- Refactored `weight_nee_light` for clarity.
- Modified `RAY_EPSILON` for improved precision.
- Updated `path_output` structure to include a `normal` field.
- Normalized unpacked normal vector in `normal_unpack` function.
- Updated `path_trace` to use closest hit ray intersection.
- Updated `render_aov` to utilize closest hit logic.
- Modified `ray_create` to initialize `esp` based on ray origin.
- Improved accuracy in `offset_ray_origin` calculations.
- Updated ray intersection logic in `ray_intersect_triangle` and `ray_intersect_aabb` to include epsilon checks.
- Updated `evaluate_bsdf_directional` and `evaluate_bsdf_const_sky` for shadow rays.
- Adjusted `sample_bsdf_simple_lit` for incoming light direction calculations.
- Enhanced `render_pixel` to manage AOV flags effectively.
- Changed camera rotation and light intensity in `scene_setup`.
- Simplified texture loading by removing unnecessary sRGB conversion.

Modified:
- Several binary image files have been updated.
This commit is contained in:
2025-05-05 01:59:13 +09:00
parent 4b29de15cd
commit f940569ca3
21 changed files with 190 additions and 85 deletions

View File

@@ -19,13 +19,15 @@ static void get_surface_data(const shading_context_t* context, const void* prope
data_out->albedo = glms_vec3_mul(data_out->albedo, glms_vec3(texture_sample(albedo_texture, context->uv.x, context->uv.y)));
}
// NOTE: Currently normal map will produce lots of fireflies, need to be fixed.
// Not sure is it because of the quality of the normal map or the algorithm itself.
data_out->normal = context->normal;
const texture_t* normal_texture = get_texture(context->textures, prop->normal_texture);
if (normal_texture != NULL && normal_texture->data != NULL)
{
vec3s normal_sample = glms_vec3(texture_sample(normal_texture, context->uv.x, context->uv.y));
normal_sample = normal_unpack(normal_sample);
data_out->normal = glms_vec3_add(data_out->normal, normal_ts_to_ws(normal_sample, context->tangent));
data_out->normal = normal_ts_to_ws(normal_sample, context->normal, context->tangent);
}
data_out->roughness = prop->roughness;
@@ -54,6 +56,7 @@ static vec3s sample_bsdf_simple_lit(const shading_context_t* context, const surf
vec3s f = fresnel_schlick_vec3(f0, cos_theta_0);
float lum_f = (f.x + f.y + f.z) / 3.0f;
//float prob_specular = 0.0f;
float prob_specular = glm_lerp(lum_f, 1.0f, surface_data->metallic);
float prob_diffuse = (1.0f - surface_data->metallic) * (1.0f - lum_f); // Diffuse only for non-metals, reduced by reflection
float total_prob = prob_diffuse + prob_specular;
@@ -110,8 +113,8 @@ static vec3s sample_bsdf_simple_lit(const shading_context_t* context, const surf
h_ws = glms_vec3_add(h_ws, scaled_n);
h_ws = glms_vec3_normalize(h_ws);
// wi is simple now, just reflect wo around normal
wi = glms_vec3_reflect(glms_vec3_negate(L), h_ws);
// wi is simple now, just reflect L around normal
wi = glms_vec3_reflect(L, h_ws);
}
// Final check to ensure wi is in the correct hemisphere
@@ -139,7 +142,7 @@ static float sample_bsdf_pdf_simple_lit(const shading_context_t* context, const
vec3s L = glms_vec3_negate(context->wo);
vec3s f0 = glms_vec3_lerp(DIELECTRIC_REFLECTIVE, surface_data->albedo, surface_data->metallic);
float cos_theta_o = fmaxf(glms_vec3_dot(context->normal, L), 0.0f); // Use 'o' for outgoing (wo)
float cos_theta_o = fmaxf(glms_vec3_dot(surface_data->normal, L), 0.0f); // Use 'o' for outgoing (wo)
float F = glms_vec3_max(fresnel_schlick_vec3(f0, cos_theta_o));
float prob_specular = glm_lerp(F, 1.0f, surface_data->metallic);
@@ -153,11 +156,10 @@ static float sample_bsdf_pdf_simple_lit(const shading_context_t* context, const
prob_diffuse /= total_prob;
prob_specular /= total_prob;
float pdf_diff = pdf_cosine_weighted_hemisphere(context->normal, wi);
float pdf_diff = pdf_cosine_weighted_hemisphere(surface_data->normal, wi);
float diffuse_pdf_component = prob_diffuse * pdf_diff;
// When computing specular PDF, L is the wi and wi is the view direction
float pdf_spec = pdf_blinn_phong_lobe(context->normal, L, wi, surface_data->roughness);
float pdf_spec = pdf_blinn_phong_lobe(surface_data->normal, wi, L, surface_data->roughness);
float specular_pdf_component = prob_specular * pdf_spec;
return diffuse_pdf_component + specular_pdf_component;
@@ -231,7 +233,8 @@ path_output simple_lit_render_loop(const shading_context_t* properties, const sh
if (light_output.state == PS_NORMAL)
{
vec3s bsdf_dir_light = evaluate_bsdf_simple_lit(context, &surface_data, light_output.wi);
vec3s light_contribute = glms_vec3_mul(light_output.direct_lighting, bsdf_dir_light);
float pdf_bsdf = sample_bsdf_pdf_simple_lit(context, &surface_data, light_output.wi);
vec3s light_contribute = weight_nee_light(bsdf_dir_light, light_output.direct_lighting, pdf_bsdf, light_output.pdf);
output.direct_lighting = glms_vec3_add(output.direct_lighting, light_contribute);
}
}
@@ -254,8 +257,9 @@ path_output simple_lit_render_loop(const shading_context_t* properties, const sh
}
vec3s bsdf = evaluate_bsdf_simple_lit(context, &surface_data, output.wi);
float cos_theta = fmaxf(0.0f, glms_vec3_dot(output.wi, context->normal));
float cos_theta = fmaxf(0.0f, glms_vec3_dot(output.wi, surface_data.normal));
output.normal = surface_data.normal;
output.bsdf = glms_vec3_scale(bsdf, cos_theta / output.pdf);
output.state = PS_NORMAL;
return output;