Skip to content

Commit

Permalink
Fix trilinear filtering
Browse files Browse the repository at this point in the history
A texture footprint with 'width' characteristic size corresponds to texture
sampling rate with 1 sample per screen pixel. In order to satisfy the Nyquist
limit we need a filter of size '2*width' - and that's what we have in the original
code. This computation does not take into account though, that after computing
lod and selecting mip levels, we apply bilinear filtering to sample each mip.
This effectively increases filter size to '4*width' which results in too blurry images.

There could be at least two solutions here: the first one is to use '2*width' filter size
and then use point sampling when working with separate mip levels. Another solution
proposed here is to select the mip levels based on the 'width' filter size and then rely
on bilinear filtering to get correct result.

I didn't check this but the second method could provide better results because the last step
when we apply bilinear filtering takes into account specific use case and in the case of
point sampling the final result is baked into the mip level, so we don't have an opportunity
to select proper position between texels as we do with bilinear filtering.

The proposed solution also matched HW filtering results, for example, in this
project https://github.com/kennyalive/vulkan-raytracing, the RTX raytracing code
computes texture lod using just 'width' and then applies bilinear filter. The result
closely matches rasterization version. Color encoding of lod levels used in that demo
allows to visualize differences in lod selection. By modifying the code to use '2*width' it
can be shown that is produces wrong result.
  • Loading branch information
kennyalive authored and mmp committed Jun 26, 2020
1 parent 9629f11 commit aaa552a
Showing 1 changed file with 1 addition and 1 deletion.
2 changes: 1 addition & 1 deletion src/core/mipmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ T MIPMap<T>::Lookup(const Point2f &st, Vector2f dst0, Vector2f dst1) const {
if (doTrilinear) {
Float width = std::max(std::max(std::abs(dst0[0]), std::abs(dst0[1])),
std::max(std::abs(dst1[0]), std::abs(dst1[1])));
return Lookup(st, 2 * width);
return Lookup(st, width);
}
++nEWALookups;
ProfilePhase p(Prof::TexFiltEWA);
Expand Down

0 comments on commit aaa552a

Please sign in to comment.