Search Unity

Snow Deformation Optimizations

Discussion in 'Shaders' started by Mr_Admirals, Jan 30, 2019.

  1. Mr_Admirals

    Mr_Admirals

    Joined:
    May 13, 2017
    Posts:
    86
    Hello!

    I've got my snow shader in a basically complete state, with proper shading and shadows. However, despite my best efforts to keep everything running smoothly, I've noticed a huge jump in batches. I'm looking to reduce the number of batches, but based on my research my options are pretty limited to none.

    upload_2019-1-30_12-14-35.png

    Here's how it works:

    1. Recursively divide mesh into quadrants
    2. Assign a Snow Deformation Module to each quadrant
    ---Unique Snow.shader material
    ---Unique set of depth Render Textures
    ---Pair of cameras
    ---Snow Render Texture Pipeline Script
    3. Enable and disable cameras and Snow Render Texture Pipeline script as objects enter and leave the camera view box

    I'm not too sure what code to post, since I'm not sure where I can improve performance, if it's at all possible.

    Based on how I've done this, I'm fairly certain GPU instancing and batching is off the table.
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    "86" is not a huge number of batches. If that number was multiple hundreds or thousands, then you might have a problem. On PC hardware that's nothing. Hell, on modern mobile that's nothing.

    Focus your efforts elsewhere, like tracking down what's taking 12ms on the CPU. (Hint: it's not the batches.)
     
  3. Mr_Admirals

    Mr_Admirals

    Joined:
    May 13, 2017
    Posts:
    86
    Really? Dang, really happy to hear that! I was just spooked when I implemented lighting and shadows and saw my batch count double.

    I'm fairly certain the 12ms CPU time is just my slow computer. It's a bit outdated. But I'll definitely do some investigating to see if there's something taking up a brutal amount of time.
     
  4. McDev02

    McDev02

    Joined:
    Nov 22, 2010
    Posts:
    664
    That is completely normal and has nothing to do with your snow shader in particular. Shadows require to render the objects casting shadow twice. When using Cascade Shadows this can even be more as each cascade causes another draw call for an object if it is within the range of it.

    I like your shader and would like to know more about how it works. I already thought about implementing something similar for my game but I am afraid of using too much performance for such eye candy only feature.
     
  5. Mr_Admirals

    Mr_Admirals

    Joined:
    May 13, 2017
    Posts:
    86
    To be honest, I may have gone overboard, haha. This is basically my first custom shader so it's been very challenging, but one hell of a learning experience.

    Okay, so how it works:

    Snow Mesh Divide

    upload_2019-2-1_11-9-59.png

    This script is where it all starts. One thing I quickly learned when building my initial prototype is that large meshes require large textures. This can be quite demanding, so my solution was to divide suitable meshes (Meshes with 4 right angle corners, and only variation in the Y direction) into recursive quadrants. These quadrants are then given a Snow Deformation Module and the tag of "Tile".


    Snow Deformation Manager

    upload_2019-2-1_11-6-13.png


    This is the command center. It's a script that takes in primarily texture and deformation settings. These settings are used to initialize Snow Deformation Modules that are made child to any game object tagged with "Tile".


    Snow Deformation Module

    upload_2019-2-1_11-22-54.png

    These modules consist of a parent game object with a a trigger box collider, and a script called "SDMControl". The two child objects consist of cameras. The Object Cam is located below the tile and points up to capture the depth of any objects pressing down on the "snow". It also has a script called the Snow Render Texture Pipeline attached to it. The Ground cam is just a camera and is located above the tile, pointing down to capture the depth of the tile's mesh. When objects on the correct layer enter and exit the box collider, the Snow Deformation Module is turned on and off correspondingly.


    The Deformation Pipeline

    This is where the magic happens. It consists of a C# script (Snow Render Texture Pipeline) that uses three shaders to manipulate depth render textures to produce an output that tessellates geometry and moves the geometry accordingly.

    1. Normalize the Object Camera and Ground Camera depth textures

    Technically, you only need one camera to actually displace geometry, but the downside is that it only works on flat pieces of geometry. Which, unless you're dealing with snow in an urban area (Batman Arkham Origins), isn't exactly ideal. The issue with using a single cam to deform snow on an arbitrary planar surface is that the camera's viewing box is just a box. There's no way to get it's shape to conform to the shape of the ground (unless it's flat of course). To get around that, I used a second camera to capture the depth of the terrain. Using the depth of the terrain, I was able to normalize object depth map by converting a given depth value's proportion to fit that of the terrain. (If you're confused, it's hard for me to explain so I can try explaining in more detail)

    2. Blur the depth texture

    With the now normalized (or proportionally correct) depth texture, I send it to my blur shader. The blur shader is just a Gaussian Blur that I modified to blur depth maps. The reason why you want to blur the depth maps is because on the boundary between captured depth and no captured depth, it's like a cliff face. So the geometry ends up getting displaced really sharply. By blurring it, you soften the edges, giving it a more snow (or even sand-like) appearance. The texture is sent through the blur shader for as many times as specified. I find one level of blurring to be enough though.

    3. Use the depth texture to tessellate and displace

    At this point the depth texture is handed off to the snow shader which operates autonomously. First it uses the depth map to tessellate the geometry only where displacement will occur, and then it shades and actually displaces the vertices.

    If you've got any questions or need any clarifications just let me know!

    At some point I think I'll also be putting this on the asset store.
     
  6. Jhaire

    Jhaire

    Joined:
    Nov 30, 2012
    Posts:
    7
    Hey - did you ever release this on the asset store? I've just started looking into making a snow deformation solution for my game but this looks incredible!