mayingzhen / nvidia-texture-tools

Automatically exported from code.google.com/p/nvidia-texture-tools
Other
0 stars 0 forks source link

PolyphaseFilter is non-symmetric #167

Closed GoogleCodeExporter closed 8 years ago

GoogleCodeExporter commented 8 years ago
The current code for constructing filter weights is incorrect, resulting in 
non-symmetric filters. By default, it evaluates the filter function at 32 
samples and averages them. However, those 32 sample positions are positioned at 
floor(x) + [0,32) / 32. The net effect is that the entire resulting filter 
shifts the image by 1/32 of a texel per mip level. It's easy to see this in the 
debugger by examining the contents of xFilter and yFilter after they're 
constructed.

Original issue reported on code.google.com by osman.br...@gmail.com on 5 Jul 2011 at 6:19

GoogleCodeExporter commented 8 years ago
Good point. I think you are totally right. It seems it should be a simple fix, 
but I'm a bit busy to take a closer look at this right now. Would you be 
willing to provide a patch? Thanks!

Original comment by cast...@gmail.com on 6 Jul 2011 at 4:58

GoogleCodeExporter commented 8 years ago
Sure. I haven't actually fixed it locally (I just switched to 1 sample), and
I'm going on vacation for a week, but I can try to patch it when I get back.

Original comment by osman.br...@gmail.com on 6 Jul 2011 at 9:15

GoogleCodeExporter commented 8 years ago
OK, this is an interesting one. It has given me some trouble to track this down.

It's true that there's some slight asymmetry when sampling complex filters with 
large number of taps, but when looking at the tap locations and the sampled 
values I was getting perfectly symmetric results.

For example, in a 2x downsampling filter the 2-element kernel is constructed 
sampling the filter at:

w0: -0.43750000, -0.31250000, -0.18750000, -0.062500000
w1: 0.062500000, 0.18750000, 0.31250000, 0.43750000

Increasing the number of taps or the size of the filter did not change 
anything, the results were still correct.

The next suspect was the actual filter shape itself, but looking the values 
produce they also seemed to be perfectly symmetric, these are for example the 
first and last taps of a Kaiser-windowed sinc filter:

2.562500: 0.02599737 (3CD4F86F)
2.687500: 0.01708135 (3C8BEE31)
2.812500: 0.00860267 (3C0CF23A)
2.937500: 0.00219194 (3B0FA6B5)

-2.937500: 0.00219194 (3B0FA6B5)
-2.812500: 0.00860267 (3C0CF23A)
-2.687500: 0.01708135 (3C8BEE31)
-2.562500: 0.02599737 (3CD4F86F)

Turns out the problem is due to the way the samples are accumulated. When you 
add these samples in this specific order, in the first case you get:

There are several solutions. you could use a symmetric reduction to add the 
values, a Kahan sum, or use doubles to accumulate the result of the sum.

Using doubles seems the most simple solution and the results seem to be fully 
symmetric now.

Anyway, I should probably have a special case for single-phase symmetric 
filters, there's not much point in using a polyphase filter in those cases. 
That would be faster and avoid these problems entirely.

Original comment by cast...@gmail.com on 14 Sep 2011 at 5:46

GoogleCodeExporter commented 8 years ago
Darn, I forgot to paste the sums:

0.013468 (3C5CAA49)
0.013468 (3C5CAA4A)

Notice the slight difference in the lowest bits of the floating point values.

Original comment by cast...@gmail.com on 14 Sep 2011 at 5:48

GoogleCodeExporter commented 8 years ago
This issue was closed by revision r1271.

Original comment by cast...@gmail.com on 14 Sep 2011 at 5:51