Added mip selection using ray differentials

This commit is contained in:
2025-12-29 23:36:21 +09:00
parent adee5acd10
commit 400137ee99
12 changed files with 125 additions and 28 deletions

View File

@@ -128,21 +128,37 @@ static float oren_nayar_eval(vec3s l, vec3s v, vec3s n, float roughness, float n
static void get_surface_data(const shading_context_t* context, const standard_lit_properties_t* properties, standard_lit_surface_data_t* data_out)
{
float camera_distance = glms_vec3_distance(context->camera_position, context->position);
vec3s view = (context->camera_direction);
// Use the ray cone width (footprint) instead of simple distance for mip selection
float footprint = context->cone_width;
float distance = glms_vec3_distance(context->camera_position, context->position);
vec3s view = context->camera_direction;
// Fetch geometry data for LOD calculation
const triangle_t* triangle = &context->triangles->buffer[context->triangle_id];
texture_sample_context_t sample_context =
{
.view_direction = view,
.normal = context->normal,
.edge1 = glms_vec3_sub(triangle->vertices[1].position, triangle->vertices[0].position),
.edge2 = glms_vec3_sub(triangle->vertices[2].position, triangle->vertices[0].position),
.uv1 = glms_vec2_sub(triangle->vertices[1].uv, triangle->vertices[0].uv),
.uv2 = glms_vec2_sub(triangle->vertices[2].uv, triangle->vertices[0].uv),
.ray_width = footprint,
.distance = distance
};
data_out->albedo = properties->albedo;
const texture_t* albedo_texture = get_texture(context->textures, properties->albedo_texture);
if (albedo_texture != NULL && albedo_texture->data != NULL)
{
data_out->albedo = glms_vec3_mul(data_out->albedo, glms_vec3(texture_sample(albedo_texture, context->uv, view, context->normal, camera_distance)));
data_out->albedo = glms_vec3_mul(data_out->albedo, glms_vec3(texture_sample(albedo_texture, &sample_context, context->uv)));
}
data_out->normal = context->normal;
const texture_t* normal_texture = get_texture(context->textures, properties->normal_texture);
if (normal_texture != NULL && normal_texture->data != NULL)
{
vec3s normal_sample = glms_vec3(texture_sample(normal_texture, context->uv, view, context->normal, camera_distance));
vec3s normal_sample = glms_vec3(texture_sample(normal_texture, &sample_context, context->uv));
normal_sample = normal_unpack(normal_sample);
data_out->normal = normal_ts_to_ws(normal_sample, context->normal, context->tangent);
}
@@ -153,14 +169,14 @@ static void get_surface_data(const shading_context_t* context, const standard_li
const texture_t* roughness_texture = get_texture(context->textures, properties->roughness_texture);
if (roughness_texture != NULL && roughness_texture->data != NULL)
{
data_out->roughness = data_out->roughness * texture_sample(roughness_texture, context->uv, view, context->normal, camera_distance).x;
data_out->roughness = data_out->roughness * texture_sample(roughness_texture, &sample_context, context->uv).x;
}
data_out->metallic = properties->metallic;
const texture_t* metallic_texture = get_texture(context->textures, properties->metallic_texture);
if (metallic_texture != NULL && metallic_texture->data != NULL)
{
data_out->metallic = data_out->metallic * texture_sample(metallic_texture, context->uv, view, context->normal, camera_distance).x;
data_out->metallic = data_out->metallic * texture_sample(metallic_texture, &sample_context, context->uv).x;
}
}
@@ -391,6 +407,10 @@ path_output standard_lit_render_loop(const standard_lit_properties_t* properties
// Throughput multiplier must be: (f * NoL) / pdf_total
output.bsdf = glms_vec3_scale(spec_f, n_dot_l / pdf_gen);
// Propagate spread angle for ray cones
// Heuristic: spread increases with roughness
output.spread_angle = context->spread_angle + surface_data.roughness * 0.2f;
}
else
{
@@ -420,6 +440,9 @@ path_output standard_lit_render_loop(const standard_lit_properties_t* properties
vec3s kD = glms_vec3_scale(glms_vec3_sub(glms_vec3_one(), F_est), 1.0f - surface_data.metallic);
float on = oren_nayar_eval(output.wi, V, surface_data.normal, surface_data.diffuse_roughness, n_dot_l, n_dot_v);
// Diffuse bounce significantly increases spread (effectively resets or becomes very wide)
output.spread_angle = context->spread_angle + 0.5f;
vec3s diff_f = glms_vec3_scale(glms_vec3_mul(surface_data.albedo, kD), on);
// Throughput multiplier: (f * NoL) / pdf_total