Added mip selection using ray differentials
This commit is contained in:
@@ -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