Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Baffling graphics performance issue for custom clouds

Discussion in 'Editor & General Support' started by OhNoDinos, May 24, 2014.

  1. OhNoDinos

    OhNoDinos

    Joined:
    Feb 16, 2014
    Posts:
    6
    I've been working on a complex system for creating a huge cloud-scape, and everything has been going great until one inexplicable problem came up.

    Essentially, the system works by creating a bunch of billboards along vertex points of a procedurally generated mesh. Rather than render the mesh, the billboards are created by placeing the four verts of a quad at the correct positions, and then the billboarding all takes place in the shader. As a result, the system is blazingly fast - it can handle probably millions of the individual sprites.

    $cloud1.PNG

    There's just one thing that behaves weirdly. The shader handles a multiplier for the size of the sprites, and whenever the size goes up, the framerate plummets. But as you can see in the picture below, the draw calls, tri/vert count, and every other stat are exactly the same, other than the main thread and FPS.

    $cloud2.PNG

    I've tried adjusting everything I could think would solve the problem. It's not an issue of too many billboards, since increasing/decreasing the number of billboards doesn't effect the frame rate, but no matter how many there are the size drastically affects the FPS. I even tried setting the texture size to the very minimum, and to 1/4 resolution in the quality settings, but that had no effect.

    Weirder still is that the frame-rate improves simply by moving the camera away from the billboards, as seen here, which also doesn't change any of the stats.

    $cloud3.PNG

    I know I should use the compiler for this, but unfortunately I'm not using pro. I'm just wondering if i'm missing something about textures or screen-space that could be the cause of this.

    Could it have something to do with the individual billboards overlapping more when larger?

    Any help is hugely appreciated!
     
  2. billykater

    billykater

    Joined:
    Mar 12, 2011
    Posts:
    327
    What you are seeing in this scenario is the prime example of a fillrate issue. You are drawing so much per pixel that the GPU slows down because of it.

    I suspect each of the quads in this example is a alpha blended sprite, so the gpu has to render a lot of things on top of each other, as this is alpha blended the GPU can't skip any of the work and has to draw something at each pixels location several times while always reading the last value back to do alpha blending. As a result as you increase your sprite scale, or decrease the amount of pixel drawn by moving the camera away the performance of this scene changes drastically.

    The easiest method to confirm this is to just use a non transparent material for the billboards, the speed should go up quite a bit on modern gpus.

    Ways to fix this:
    Reduce the amount of drawing the GPU has to do per pixel. My first attempt would be to simplify the shader, but I don't suspect you are doing anything fancy for this example. Only other way would be to reduce the amount of overlapping elements. Here my first attempt would be to disable elements which aren't directly influencing the final image: Disable all elemens after the e.g. third layer, they won't contribute much to the final image but still require a lot of drawing.
     
  3. OhNoDinos

    OhNoDinos

    Joined:
    Feb 16, 2014
    Posts:
    6
    Aha! You were absolutely right! I imagined it had something to do with overlapping, since that seemed to be the only thing that actually increased as the size went up. As it turns out, the major thing was that I had zwrite turned off in the shader, which explains why it was trying to combine so many layers for each pixel. Thanks a ton, you really taught me something!

    Just out of curiosity, do you know of a way to limit the overlapping, as you describe, within the shader? I'm sure this is a highly complicated question, but is it possible to, say, have the pixel calculation stop after the first 3 layers it combines? I'm trying to keep all the handling of the billboards within the shader, since putting any sort of calculation on the CPU for thousands of billboards would definitely be a problem. enable zwrite does solve this problem, but it isn't compatible with alpha whatsoever.

    Thanks again though!
     
  4. AlkisFortuneFish

    AlkisFortuneFish

    Joined:
    Apr 26, 2013
    Posts:
    958
    If you are on Pro, you could use the stencil buffer, incrementing on every draw and doing an LEqual stencil test with some arbitrary overdraw limit value but I can't really say how much that would actually help without testing it.