fluid rendering, how to calculate varying filter radius for bilateral blur

Started by
3 comments, last by trs79 12 years, 9 months ago
Hey all,

I'm working on implementing screen space fluid rendering as described in the presentation here. I've implemented the bilateral blur from the paper in HLSL, however there are two issues with the blur:

  1. Performance, the author states the code is "not optimized". It looks to be similar to SSAO blur algorithms but my math knowledge is limited in this area. Anyone know of similar bilateral blurs that would be faster, i.e. recursive ones?
  2. Currently, I have a hard-coded fiter radius, which I've set to be half the width of the final rendered pixels of the sprite in question (there are multiple particle sprites being shaded in a full-screen quad post-processing pass). The problem is as the camera moves closer or further from the sprites, the filter width has to be changed to accommodate. I have access to the depth values (non-linear z/w) in the post-processing pass, but I'm not sure the best way to figure out the filter radius based on that. Code below:


    float depth = tex2D(depthSampler, texcoord).x;
    float sum = 0;
    float wsum = 0;

    for(float x=-filterRadius; x<=filterRadius; x+=1.0) {
    float sample = tex2D(depthSampler, texcoord + x*blurDir).x;
    // spatial domain
    float r = x * blurScale;
    float w = exp(-r*r);

    // range domain
    float r2 = (sample -depth) * blurDepthFalloff;
    float g = exp(-r2*r2);
    sum += sample * w * g;
    wsum += w * g;
    }

    if (wsum > 0.0) {
    sum /= wsum;
    }

    return sum;

The author says the filter width should be constant in world space but variable in screen-space. In my world space each sprite is one unit wide and tall. Thanks for any help!
Advertisement
to clarify my main concern is if I have a z/w depth, and I know the width of my quad sprite in world space, is there a way to calculate how many pixels wide it would be on screen?
you project the sprites to the screen, it's simply done by sprite_width/sprite_z in screenspace.

to be really accurate, you'd need to transform it by your view projection matrix and scale it from the viewport size (-1 to 1) to texture size (0 to 1).

but a simple solution would be to just hardcode a scaling value that looks good for you.




if you assume that your depth is from 0 to 1.f, your scaling of N is for the far clip plane, if you'd want to have 0.5 pixel blur for a sprite that far, your scaling would be

Scale=0.5f/ScreenWidth;




for all other distances your kernel would be simply

LocalScale=Scale/z;




I didn't test it, it'sjust out of my head ;)
Thanks so much for the response. Just to make sure I understand, when you say I divide sprite_width/sprite_z in screenspace, is that sprite_width in world space (in my case 1 unit) divided by screenspace z? Also does that only work if I had linear z, or would it work with post-projection z/w? It looks like it would only hold true for linear z after I tried some different z values. I guess I'm not sure how to compute the scale for the LocalScale=Scale/z; formula, thanks!
Here are some test results if that's helpful:

Camera Distance from sprite in world Z | square sprite pixels wide on screen (measured by taking screen capture and loading in photoshop)

6 | 122 pixels wide
12 | 61 pixels wide (so far linear reduction)
18 | 41 pixels wide (not linear anymore)

I can't seem to find a simple formula to get screen width from depth, even if I setup a linear z target it still isn't coming out linear, thanks for the help

This topic is closed to new replies.

Advertisement