Search Unity

Compositing Depth of Field || Mobile

Discussion in 'Shaders' started by Lanre, Jun 23, 2015.

  1. Lanre

    Lanre

    Joined:
    Dec 26, 2013
    Posts:
    3,973
    Hello guys. I have been working on shaders for the past couple of days and have made some progress. But I have a problem.

    BACKGROUND
    I'm trying to make depth-based, variable-magnitude fullscreen gaussian blur (pseudo-DOF). It's basically depth of field without the magic (CoCs, complex calculations, bokehs and all that DX-11 spec shiny stuff). It has to be able to maintain 60FPS on an iPhone 4S (as a minimum benchmark) and eat less than 6ms GPU time for its operation (as I have to maintain 60FPS and as I might even motion blur). It is a lot to ask for but it's not impossible.

    METHOD
    I am building off Unity's Fast Blur solution as it works very well with mobiles. It's a highly optimized solution and it gives cool looking blurs.
    -I needed depth info, so I got a shader that renders scene depth to a texture. Unfortunately, this:
    Code (CSharp):
    1. return pow(Linear01Depth(UNITY_SAMPLE_DEPTH(tex2D(_CameraDepthTexture, o.uv))), _DepthLevel);
    eats up a staggering 2.6ms. I don't know whether this is because setting the camera to render depth is too much to do, or Unity's functions Linear01Depth and UNITY_SAMPLE_DEPTH are too heavy. Changing the rendering path to deferred (as it implies that a depth texture is always rendered) doesn't mitigate the cost. It's quite saddening.
    -Then I thought I'd use the depth as alphas and overlay the base (view without blur) and the blurred view. Unfortunately, this produces playstation 2-spec DOF - like so. https://drive.google.com/file/d/0B9Ro3SbNiUH-akFYdFFIUzFZc2c/view?usp=sharing
    As you can see, there's a falloff on the outline of the sphere, almost like a bloom effect. This is what I need: https://drive.google.com/file/d/0B9Ro3SbNiUH-UDJ4MHVFSzY4THM/view?usp=sharing .

    I'd like to know how I can composite 3 layers: Depth, Base, and Blur, to yield Depth of Field.

    Thank you
     
  2. Lanre

    Lanre

    Joined:
    Dec 26, 2013
    Posts:
    3,973
    Oh and for anyone who would like to know, the full effect (which produces the unwanted bloomy outline) altogether takes ~9.5ms GPU time. That's 9.5ms for drawing (a very simple scene as you can see) + depth + fullscreen blur + compositing. Not too bad.
     
  3. brianasu

    brianasu

    Joined:
    Mar 9, 2010
    Posts:
    369
    Not sure if you have tried this but you can calculate depth in material shader and store it in the alpha channel. This will allow you to skip rendering an extra depth buffer. The down side is you only get 8 bits of depth info and every material has to have a custom shader which writes depth to the alpha channel. This is how all the fast mobile DOF effects work.
     
  4. Lanre

    Lanre

    Joined:
    Dec 26, 2013
    Posts:
    3,973
    Thanks for the tip Brianasu. I'll implement that. I have implemented a way to fake tilt shift based off the blur shader. I want to make my own blur shader, as building DOF off Unity's is too cumbersome. This is what my eyes are set on http://blog.ivank.net/fastest-gaussian-blur.html .
     
  5. Lanre

    Lanre

    Joined:
    Dec 26, 2013
    Posts:
    3,973
    I did manage to make DOF with Unity's fast blur (SGX Gauss as it had 6 texture reads versus standard gauss' 7). It looks pretty nice. I also made tilt shift effect when its in blur mode. It runs fine but now I can't downsample, and it takes too much time on mobile which is my intended platform. I'm still making optimizations, and am yet to implement a new depth texture implementation. When I'm done, I'll upload the unitypackage. Screen Shot 2015-06-29 at 7.58.27 PM.png
     
  6. brianasu

    brianasu

    Joined:
    Mar 9, 2010
    Posts:
    369
    That looks pretty nice. Did you encode depth in the alpha channel of the shaders?
     
  7. Lanre

    Lanre

    Joined:
    Dec 26, 2013
    Posts:
    3,973
    Hey Brianasu! No, I am about to do so. Here's a zip. Note that DOF is extremely heavy on mobile hardware right now. But it can be optimized a lot. I want to implement Iris radial defocus and vignetting in the shader. It uses OnRenderImage (so that I could stack up image effects) but it shouldn't be a hit as I first change the target texture of the camera to a render texture, so Unity doesn't have to recreate the source render texture - it would already have it. Knock yourself out.
     

    Attached Files: