Search Unity

Mist in front of the camera

Discussion in 'Scripting' started by Manny Calavera, Oct 6, 2014.

  1. Manny Calavera

    Manny Calavera

    Joined:
    Oct 19, 2011
    Posts:
    205
    Hi,

    I have the following setup:
    - 2D scene composed of sprite renderers
    - Ortho camera
    - Shuriken particle system between the camera and sprites, max particles 50, large particles that cover almost the entire screen.
    - Standalone build.

    The desired effect is a mist passing through in front of the camera. This works fine on high end hardware.

    However, in most laptops it causes a serious hit on refresh rate.

    Any alternatives for achieving a mist effect? Or any optimization I could apply to the particle system?
     
  2. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,527
    How about some large textures with transparency effects to look like mist/fog, that are set to parallax scroll in front of the scene.

    Similar to a parallax scrolling background, just as a foreground. You could put multiple layered textures to give a depth effect to it.

    You could maybe even animate said mist/fog layers as well so that it also gets a moving look even when standing still.
     
    Manny Calavera likes this.
  3. ThermalFusion

    ThermalFusion

    Joined:
    May 1, 2011
    Posts:
    906
    What lordofduct suggest, but I would limit the amount of layers you use, since this is what's causing your issues originally.
    You could look into scene fog, but doubt it would give the result you want.
    You could make a shader that has a fixed alpha, with a scrolling rgb texture, just to reduce the amount of overdraw.
     
    Manny Calavera likes this.
  4. besttof

    besttof

    Joined:
    Jul 17, 2012
    Posts:
    29
    Having 50 almost screen filling particles could very well test the limits of the fill rates on the laptops you're testing on. Basically each pixel gets drawn too many times (overdraw) for the poor graphics card to handle. To see this, set the 2nd dropdown (defaults to RGB) in the top bar of your scene view to "overdraw" then brighter areas show where overdraw is happening.

    Using large textures with a texture on it may help in your case, but know that fully transparent pixels contribute to overdraw too (they are "drawn" too)
     
    Manny Calavera likes this.
  5. Manny Calavera

    Manny Calavera

    Joined:
    Oct 19, 2011
    Posts:
    205
    Thanks everyone for the replies!

    That's what the particle system is doing, no?

    I'm looking this up and trying to see if I can understand this suggestion.

    Yes, I can see it now. Somehow I had the misconception that overdrawing was only a problem on mobile devices.
     
  6. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,527
    Yes and no.

    It's animating the particles in that it's moving particles around.

    But it's not the same thing.

    The particle system has tons of particles on screen moving in 3 space, rotating, growing, moving about. Creating a lot of overlap and updates.

    What I meant is you can animate the sprite (think like sprite sheets). You have far fewer textures on screen (you could have 2 layers with say 8 frames of sprite animation, and still have 1/3rd the amount of things on screen). These textures will be much larger (full screen) which makes them take up memory, but they still are fewer objects. And their movement is more predictable.

    For example, for 3d water we have 2 planes with textures on them. And we animate those textures (not the planes... the textures) to simulate slow stagnant swamp water. It's not very expensive at all and looks great. You'd basically be doing the same thing, but flipping those planes vertically so it was like fog between the camera and the player.
     
  7. SteveJ

    SteveJ

    Joined:
    Mar 26, 2010
    Posts:
    3,085
    I did something like this at one point - similar to what lordofduct is suggesting. Basically used a tile-able, transparent texture plane sitting in front of the camera and then "animated" it to scroll with something along the lines of:

    Code (csharp):
    1.  
    2. using UnityEngine;
    3.  
    4. public class AnimateMist : MonoBehaviour
    5. {
    6.     public float MistSpeed = 0.025f;
    7.  
    8.     private Renderer _myRenderer;
    9.  
    10.     private void Awake()
    11.     {
    12.         _myRenderer = renderer;
    13.     }
    14.  
    15.     private void Update()
    16.     {
    17.         float offset = Time.time * MistSpeed;
    18.         _myRenderer.material.SetTextureOffset("_MainTex", new Vector2(offset, 0.0f));
    19.     }
    20. }
    21.  

    EDIT: Made a couple of changes to script.
     
    Last edited: Oct 8, 2014
  8. Manny Calavera

    Manny Calavera

    Joined:
    Oct 19, 2011
    Posts:
    205
    I've managed to achieve the same dynamic mist animation at a lower cost (on an old laptop it went from 15FPS to 40FPS).

    Here is how I did it:
    - Created a second camera, Culling Mask = Mist
    - Moved the particle system in front of the second camera. Set it to Mist layer.
    - Shader to render transparency.
    - Render to texture.
    - Created Quad in front of the main camera and applied the RenderTexture to it.

    Worked like a charm.

    Now what I can't possibly understand is why is this faster? Isn't the second camera essentially rendering the same amount of pixels? If anything I expected this to be slower than the original, single camera approach.
     
  9. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,527
    Weird...

    Maybe it has to do with the transparency of the mist. When you have it in front of the scene, it's calculating everything behind it (your scene). Where as when off to the side, there's nothing behind it. So it's calculation is cheaper.

    So then when you render to texture. The texture is only one calculation with the scene behind it, instead of for each individual particle.
     
  10. ThermalFusion

    ThermalFusion

    Joined:
    May 1, 2011
    Posts:
    906
    Perhaps you were using a much lower resolution on the render texture, fewer overdrawn pixels to render?
     
  11. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,527
    I'll say, if you're going to go this route and render the effect to a texture anyways. Why not just record the particle effect, baking it into a texture animation, and play that on the quad instead. It could bring your frame rate up more since the particle effect doesn't even exist, but will look like the particle effect.

    Of course having the particle effect there means you can change it on the fly.

    Just saying, if you're looking to save frames.