Fix: Compositor results are fuzzy with bilinear filtering

The realtime compositor sometimes produces fuzzy results when the
interpolation is set to bilinear. This was due to the domain realization
shader, which incorrectly sampled the input image.

This patch fixes such fuzziness by introducing a 0.5 offset to evaluate
the sampler at the center of pixels. Additionally, it makes sure the
centring offset is an integer offset by taking its floor, retaining the
previous 0.5 offset even with the difference in size is odd.
This commit is contained in:
Omar Emara 2022-08-23 08:55:31 +02:00
parent 35cc755366
commit 78061e6c3e
1 changed files with 9 additions and 5 deletions

View File

@ -4,18 +4,22 @@ void main()
{
ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
/* First, transform the input image by transforming the domain coordinates with the inverse of
* input image's transformation. The inverse transformation is an affine matrix and thus the
/* Add 0.5 to evaluate the input sampler at the center of the pixel. */
vec2 coordinates = vec2(texel) + vec2(0.5);
/* Transform the input image by transforming the domain coordinates with the inverse of input
* image's transformation. The inverse transformation is an affine matrix and thus the
* coordinates should be in homogeneous coordinates. */
vec2 coordinates = (mat3(inverse_transformation) * vec3(texel, 1.0)).xy;
coordinates = (mat3(inverse_transformation) * vec3(coordinates, 1.0)).xy;
/* Since an input image with an identity transformation is supposed to be centered in the domain,
* we subtract the offset between the lower left corners of the input image and the domain, which
* is half the difference between their sizes, because the difference in size is on both sides of
* the centered image. */
* the centered image. Additionally, we floor the offset to retain the 0.5 offset added above in
* case the difference in sizes was odd. */
ivec2 domain_size = imageSize(domain_img);
ivec2 input_size = texture_size(input_tx);
vec2 offset = (domain_size - input_size) / 2.0;
vec2 offset = floor((domain_size - input_size) / 2.0);
/* Subtract the offset and divide by the input image size to get the relevant coordinates into
* the sampler's expected [0, 1] range. */