Add HDR files and improve light handling

Added three binary files: `golden_gate_hills_1k.hdr`, `rogland_sunset_1k.hdr`, and `studio_small_03_1k.hdr`.
Added a new inline function `weight_nee_light` in `BSDF.h` to compute the weighted contribution of light based on the next event estimation (NEE).
Added a new function pointer type `sky_free_f` in `Light.h` for freeing sky light data.
Added a new structure `hdr_sky_data_t` in `SkyLight.h` to hold HDR sky data, including texture and intensity.
Changed the `RAY_EPSILON` definition in `Common.h` to a new value.
Changed the `light_collection_free` function in `Light.h` to include freeing sky light data if it exists.
Changed the `sky_create_hdr_sky` function in `SkyLight.h` to initialize HDR sky data and compute marginal and conditional distributions.
Changed the `texture_load` function in `Texture.h` to accept a `stride` parameter for different texture formats.
Changed the `evaluate_bsdf_directional` function in `LightEvaluation.c` to handle light intensity checks.
Changed the `evaluate_bsdf_const_sky` function in `SkyLight.c` to use a pointer for sky data and added checks for intensity.
Removed TODO comments related to handling triangle and material removal in `Triangle.h` and `Light.h`.
Removed the old `weight_sky_light` function in `SkyLight.h` and replaced it with the new `weight_nee_light` function.
Updated the `scene_setup` function in `main.c` to change camera position and light direction, and to load HDR textures.
Increased the sample count in the rendering configuration in `main.c` for better quality rendering.
This commit is contained in:
2025-05-02 01:25:56 +09:00
parent 0061609267
commit 9a1069db90
18 changed files with 378 additions and 82 deletions

View File

@@ -1,17 +1,24 @@
#include "Lighting/SkyLight.h"
#include "Algorithm/RayIntersection.h"
#include "Common.h"
path_output evaluate_bsdf_const_sky(const void* data, const light_shading_context_t* context, vec3s throughput, uint32_t sample_index)
{
constant_sky_data_t sky_data = *(const constant_sky_data_t*)data;
vec3s sky_color = glms_vec3_scale(sky_data.color, sky_data.intensity);
const constant_sky_data_t* sky_data = (const constant_sky_data_t*)data;
path_output output = {0.0f};
output.state = TERMINATE;
if (context == NULL)
if (sky_data->intensity <= 0.0f)
{
output.direct_lighting = glms_vec3_mul(sky_color, throughput);
return output;
}
vec3s sky_light = glms_vec3_scale(sky_data->color, sky_data->intensity);
if (context->bvh_tree == NULL)
{
output.direct_lighting = glms_vec3_mul(sky_light, throughput);
return output;
}
@@ -19,7 +26,6 @@ path_output evaluate_bsdf_const_sky(const void* data, const light_shading_contex
uint16_t d2 = sobol_get_dimension(context->bounce_depth, PRNG_LIGHT_V);
vec3s wi = random_uniform_cdf_direction(context->normal, sample_index, d1, d2);
float pdf = 1.0f / (4.0f * (float)M_PI);
ray_t shadow_ray = ray_create(BIAS_RAY_ORIGION(context->hit_point, context->normal), wi);
@@ -32,7 +38,8 @@ path_output evaluate_bsdf_const_sky(const void* data, const light_shading_contex
}
float cos_theta = fmaxf(glms_vec3_dot(wi, context->normal), 0.0f);
output.direct_lighting = glms_vec3_scale(throughput, cos_theta / pdf);
float pdf = 1.0f / (4.0f * (float)M_PI);
output.direct_lighting = glms_vec3_scale(glms_vec3_mul(sky_light, throughput), cos_theta / pdf);
output.wi = wi;
output.pdf = pdf;
@@ -40,3 +47,94 @@ path_output evaluate_bsdf_const_sky(const void* data, const light_shading_contex
return output;
}
path_output evaluate_bsdf_hdr_sky(const void* data, const light_shading_context_t* context, vec3s throughput, uint32_t sample_index)
{
const hdr_sky_data_t* sky_data = (const hdr_sky_data_t*)data;
path_output output = {0.0f};
output.state = TERMINATE;
if (sky_data->intensity <= 0.0f)
{
return output;
}
if (context->bvh_tree == NULL)
// if (true)
{
vec2s uv = direction_to_equirectangular(context->wo);
vec4s sky_light = texture_sample(get_texture(context->textures, sky_data->texture), uv.x, uv.y);
output.direct_lighting = glms_vec3_scale(glms_vec3_mul(glms_vec3(sky_light), throughput), sky_data->intensity);
output.pdf = 0.0f;
return output;
}
float u0 = random_float();
uint32_t i = 0;
while (i < sky_data->height && u0 > sky_data->marginal[i])
{
i++;
}
float u1 = random_float();
uint32_t j = 0;
while (j < sky_data->width && u1 > sky_data->conditional[i * sky_data->width + j])
{
j++;
}
float theta = (i - 0.5f) / sky_data->height * (float)M_PI;
float phi = (j - 0.5f) / sky_data->width * (2.0f * (float)M_PI);
float sin_theta = sinf(theta);
float cos_theta = cosf(theta);
float sin_phi = sinf(phi);
float cos_phi = cosf(phi);
float domega = (2.0f * (float)M_PI / sky_data->width) * ((float)M_PI / sky_data->height) * sin_theta;
float w_ij = (sky_data->marginal[i] - (i > 0 ? sky_data->marginal[i - 1] : 0.0f)) *
(sky_data->conditional[i * sky_data->width + j] - (j > 0 ? sky_data->conditional[i * sky_data->width + j - 1] : 0.0f));
float pdf = w_ij / domega;
vec3s wi = (vec3s)
{
cos_theta * cos_phi,
sin_theta,
cos_theta * sin_phi,
};
ray_t shadow_ray = ray_create(BIAS_RAY_ORIGION(context->hit_point, context->normal), wi);
float closest = FLT_MAX;
hit_result_t shadow_hit = {1};
ray_intersect_bvh(&shadow_ray, context->bvh_tree->nodes, context->bvh_tree->primitive_indices, context->bvh_tree->triangles, 0, &closest, &shadow_hit);
if (shadow_hit.hit)
{
return output;
}
vec2s uv = direction_to_equirectangular(wi);
const texture_t* hdri = get_texture(context->textures, sky_data->texture);
vec4s pixel = texture_sample(hdri, uv.x, uv.y);
vec3s sky_light = glms_vec3_scale(glms_vec3(pixel), sky_data->intensity);
float angle = fmaxf(glms_vec3_dot(wi, context->normal), 0.0f);
output.direct_lighting = glms_vec3_scale(glms_vec3_mul(sky_light, throughput), angle / pdf);
output.direct_lighting = glms_vec3_clamp(output.direct_lighting, 0.0f, 1000.0f);
output.wi = wi;
output.pdf = pdf;
output.state = NORMAL;
return output;
}
void hdr_sky_free(hdr_sky_data_t* data)
{
free(data->marginal);
free(data->conditional);
data->marginal = NULL;
data->conditional = NULL;
}