Added mip selection using ray differentials
This commit is contained in:
@@ -98,7 +98,11 @@ static void render_pixel(const rendering_config_t* config, scene_t* scene, vec3s
|
||||
image_plane_point = glms_vec3_add(image_plane_point, glms_vec3_scale(camera_right, sensor_offset_x));
|
||||
image_plane_point = glms_vec3_add(image_plane_point, glms_vec3_scale(camera_up, sensor_offset_y));
|
||||
|
||||
ray_t ray = ray_create(scene->camera.position, glms_vec3_normalize(glms_vec3_sub(image_plane_point, scene->camera.position)));
|
||||
// Calculate initial spread angle for ray differentials
|
||||
float pixel_height = scene->camera.size_y / (float)config->height;
|
||||
float spread_angle = atanf(pixel_height / scene->camera.focal_length);
|
||||
|
||||
ray_t ray = ray_create(scene->camera.position, glms_vec3_normalize(glms_vec3_sub(image_plane_point, scene->camera.position)), 0.0f, spread_angle);
|
||||
|
||||
aov_output_t aov_output = {0};
|
||||
if (has_flag(aov_flags, AOV_BEAUTY))
|
||||
@@ -147,7 +151,7 @@ void renderer_start(render_job_t* job)
|
||||
|
||||
vec3s coord = glms_vec3_add(job->scene->camera.position, glms_vec3_scale(quat_get_forward(job->scene->camera.rotation), job->scene->camera.focal_length));
|
||||
|
||||
uint32_t x, y, tile_index; // OpenMP requires these to be declared outside the parallel region.
|
||||
int64_t x, y, tile_index; // OpenMP requires these to be declared outside the parallel region.
|
||||
#pragma omp parallel for schedule(dynamic, 1) default(none) \
|
||||
shared(tile_count_x, tile_count_y, tile_count, coord, job) \
|
||||
private(x, y, tile_index)
|
||||
|
||||
@@ -393,13 +393,33 @@ vec4s texture_get_pixel(const texture_t* texture, vec2s uv, uint8_t lod)
|
||||
return get_pixel_data_from_buffer(mipmap->data, x, y, mipmap->width, texture->channel_count, texture->stride);
|
||||
}
|
||||
|
||||
float texture_get_sample_lod(vec3s view_direction, vec3s normal, float distance)
|
||||
// Calculate LOD based on Ray Cones
|
||||
float texture_get_sample_lod(const texture_t* texture, const texture_sample_context_t* sample_context)
|
||||
{
|
||||
// TODO: Implement a more accurate LOD calculation.
|
||||
const float factor = 1.0f;
|
||||
// 1. Calculate the ray footprint on the surface
|
||||
// If we hit the surface at an angle, the footprint elongates.
|
||||
float cos_theta = fabsf(glms_vec3_dot(sample_context->normal, sample_context->view_direction));
|
||||
float surface_width = sample_context->ray_width / fmaxf(cos_theta, 0.001f); // Project width onto surface
|
||||
|
||||
float n_dot_v = glms_vec3_dot(normal, view_direction);
|
||||
return fmaxf(log2f(distance * factor) - fabsf(n_dot_v), 0.0f);
|
||||
// 2. Estimate UV density (How much UV changes per meter of surface)
|
||||
// This is an approximation. A more accurate way uses Triangle derivatives (Ray Differentials).
|
||||
// For a triangle, we can approximate the scale:
|
||||
float edge1_len = glms_vec3_norm(sample_context->edge1);
|
||||
float edge2_len = glms_vec3_norm(sample_context->edge2);
|
||||
float uv_area = fabsf((sample_context->uv1.x * sample_context->uv2.y) - (sample_context->uv1.y * sample_context->uv2.x)); // Approximation of UV area
|
||||
float geo_area = glms_vec3_norm(glms_vec3_cross(sample_context->edge1, sample_context->edge2));
|
||||
|
||||
// Ratio of Texture Area to Geometric Area
|
||||
float uv_density = sqrtf(uv_area / geo_area);
|
||||
|
||||
// 3. Calculate texture footprint
|
||||
// How many texels does our ray cover?
|
||||
float texels_covered = surface_width * uv_density * fmaxf(texture->width, texture->height);
|
||||
|
||||
// 4. Convert to LOD
|
||||
// LOD 0 = 1 texel. LOD 1 = 2 texels. LOD 2 = 4 texels.
|
||||
// log2(texels_covered) gives the mip level.
|
||||
return log2f(texels_covered);
|
||||
}
|
||||
|
||||
static vec4s nearest_filter(const texture_t* texture, vec2s uv, uint8_t lod)
|
||||
@@ -460,10 +480,11 @@ static inline vec4s filter_texture(const texture_t* texture, vec2s uv, float lod
|
||||
}
|
||||
}
|
||||
|
||||
vec4s texture_sample(const texture_t* texture, vec2s uv, vec3s view_direction, vec3s normal, float distance)
|
||||
vec4s texture_sample(const texture_t* texture, const texture_sample_context_t* sample_context, vec2s uv)
|
||||
{
|
||||
warp_uv(texture->wrap_mode, &uv);
|
||||
return filter_texture(texture, uv, texture_get_sample_lod(view_direction, normal, distance));
|
||||
float lod = texture_get_sample_lod(texture, sample_context);
|
||||
return filter_texture(texture, uv, lod);
|
||||
}
|
||||
|
||||
vec4s texture_sample_lod(const texture_t* texture, vec2s uv, float lod)
|
||||
|
||||
Reference in New Issue
Block a user