2 registered members (AndrewAMD, juanex),
1,247
guests, and 6
spiders. |
Key:
Admin,
Global Mod,
Mod
|
|
|
gaussian kernel for bilinear filtering
#373019
06/06/11 20:12
06/06/11 20:12
|
Joined: Jan 2003
Posts: 4,615 Cambridge
Joey
OP
Expert
|
OP
Expert
Joined: Jan 2003
Posts: 4,615
Cambridge
|
hey, since blurring is quite important in many shaders I thought I could give you a little speedup. Cards can filter samples in a bilinear way, thus saving you half the samples when calculating something like a gaussian blur. so here
samples[width_] := Module[{t, p, l, w},
w = Max[Round[width], 1];
t = Table[
N[PDF[NormalDistribution[0, w/2.2], x]], {x, -w - .5, w + .5}];
p = Partition[t, 2];
{#[[1]] + #[[2]], 1 - #[[1]]/(#1[[1]] + #1[[2]])} & /@ p
]
is the generating code for anyone who wants to use it and here are some sample kernels: 4
{{0.0653515, 0.833874}, {0.433296, 0.631295}, {0.433296,
0.368705}, {0.0653515, 0.166126}}
6
{{0.0341105, 0.724721}, {0.149481, 0.641251}, {0.312518,
0.548249}, {0.312518, 0.451751}, {0.149481, 0.358749}, {0.0341105,
0.275279}}
10
{{0.0178401, 0.631295}, {0.0457636, 0.60307}, {0.0927521,
0.574141}, {0.148539, 0.544695}, {0.187973, 0.514934}, {0.187973,
0.485066}, {0.148539, 0.455305}, {0.0927521, 0.425859}, {0.0457636,
0.39693}, {0.0178401, 0.368705}}
16
{{0.0105133, 0.579974}, {0.0191392, 0.569459}, {0.0319842,
0.558881}, {0.0490657, 0.548249}, {0.0690956, 0.537573}, {0.0893212,
0.526863}, {0.105996, 0.516128}, {0.115467, 0.505378}, {0.115467,
0.494622}, {0.105996, 0.483872}, {0.0893212, 0.473137}, {0.0690956,
0.462427}, {0.0490657, 0.451751}, {0.0319842, 0.441119}, {0.0191392,
0.430541}, {0.0105133, 0.420026}}
If you need any specific sizes you can ask me. Usage is as follows:
static const float2 kernel[NUM]=...; // here goes the sample output I posted above
for(int i = 0; i < NUM; i++)
{
pixel = tex2D(mytex,texcoord0 + float2(kernel[i].y-NUM+2*i,0)/resolution_x)*kernel[i].x;
color += pixel;
}
same goes for the y direction, so you need to do two passes. Could be that the kernel is off one pixel, I'm not sure atm, but the shader gurus (for whom this is intended) should be able to tell. Joey btw. you could replace the NormalDistribution by anything you like.
Last edited by Joey; 06/06/11 21:46. Reason: divide offset by resolution
|
|
|
Re: gaussian kernel for bilinear filtering
[Re: Joey]
#373021
06/06/11 20:47
06/06/11 20:47
|
Joined: Jul 2001
Posts: 6,904
HeelX
Senior Expert
|
Senior Expert
Joined: Jul 2001
Posts: 6,904
|
First, it is not "bilinear", but "seperated". Bilinear sampling refers to texture filtering whereas seperability refers to the fact that a square-kernel could be seperate into a vector and a transposed vector, which, multiplied, generate the original kernel again. That way, a convolution K * I can be replaced by the convolution v * ( v^T * I), which requires less arithmetics.
The problem you have is that your kernel is always even. That way, you never sample the pixel on which the kernel is applied to. You could shift the kernel pivot, so that you sample the original pixel, but then you have an odd weighting scheme for the surrounding pixels and you are weighting more the next right (or left pixel), so an odd NUM value is beneficial.
Second, I don't get why you sample in an intended fashion bilinear texture samples (this time this is the correct term) by adding a fraction on the tex-coord:
... texcoord0 + float2(kernel[i].y ...
Why don't you simply use vecViewport to get the pixel size and sample "real" neighbour pixels.
Third, you are sampling in a tapped fashion. Since your NUM value is storing the number of samples, you are going a length of NUM to the left (or up) and the double of the i-counter to the right (or down). You should divide both values by 2 to get a non-tapped sampling.
Fourth, since the gaussian bell is symmetric, it is totally sufficient to store only the weights of the half of the bell. Though, I don't know if the arithmetic overhead then generates more instructions, but I would only store half the kernel weights.
Best regards, -Christian
Last edited by HeelX; 06/06/11 20:49.
|
|
|
Re: gaussian kernel for bilinear filtering
[Re: Slin]
#373027
06/06/11 21:30
06/06/11 21:30
|
Joined: Jul 2001
Posts: 6,904
HeelX
Senior Expert
|
Senior Expert
Joined: Jul 2001
Posts: 6,904
|
Ah. I thought this was an ordinary filter stupid me! So can anyone tell me a reason why I get the same result with less samples when using the interpolated values?
Last edited by HeelX; 06/06/11 21:33.
|
|
|
Re: gaussian kernel for bilinear filtering
[Re: HeelX]
#373030
06/06/11 21:54
06/06/11 21:54
|
Joined: Jan 2003
Posts: 4,615 Cambridge
Joey
OP
Expert
|
OP
Expert
Joined: Jan 2003
Posts: 4,615
Cambridge
|
well, imagine i want to sample pixel a and pixel b and weight them both by 50% (average them). i can do that by two tex2D's or by one, sampling halfway between them (assuming they're neighbours). now imagine i want to weight them differently, say 90% a and 10% b. i can still do that with only one tex2D, now 10% away from a in direction of b. that's what i'm calculating. instead of just the weights for each pixel i store a sampling position and a combined weight. also, the kernel is not symmetric (the weights are, but then, it's only some bytes). you could calculate everything in a shader, only storing one side of the gaussian convolution and reconstructing the rest, of course. but that will definitely be slower, way slower. i think i see how you misunderstood my idea, so i'm sorry for not being more precise ^^.
edit: by the way, odd numbers work fine as well.
Last edited by Joey; 06/06/11 22:00.
|
|
|
Re: gaussian kernel for bilinear filtering
[Re: HeelX]
#373043
06/07/11 01:03
06/07/11 01:03
|
Joined: Mar 2006
Posts: 3,538 WA, Australia
JibbSmart
Expert
|
Expert
Joined: Mar 2006
Posts: 3,538
WA, Australia
|
I've been using something like this for my anti-aliasing (so pp effects can be used with it, the effect isn't just on the edges of objects, and it can be toggled on/off instantly) -- I render the scene to a bmap with twice the dimensions of the screen, and then render the result to the screen using one sample per pixel -- each sample being in the corner between four pixels on the larger bmap. It works like a charm. I also use it for my bloom, whether I'm using anti-aliasing or not.
Jibb
Formerly known as JulzMighty. I made KarBOOM!
|
|
|
|