Search Unity

[Released] Off Screen Particles, render particles at 1/2, 1/4, or 1/8 screen resolution

Discussion in 'Assets and Asset Store' started by jbooth, Oct 1, 2015.

  1. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,461
    Off Screen Particles
    Asset Store Link

    As part of my Unite2015 talk, we released our off screen particle rendering system for free.

    Do you have lots of large particle effects bogging down your scene? Do you like to put large alpha textures over your scene? If so, rendering them offscreen to a smaller buffer may help.



    This package allows you to add an image effect to your camera that will render a layer to a buffer which is 1/2, 1/4, or 1/8th of your screen size, and then blend it back into your scene with minimal artifacts. This can make the rendering of complex overdraw cases up to 50 times faster! More importantly, it allows you to use techniques you couldn't use otherwise, filling your scene with fog planes or other low-frequency alpha objects that would be too inefficient render at full screen resolutions.


    Features:
    - Image effect to perform off screen rendering and upsampling
    - Two example shaders and a test scene showing off the effect

    Notes:
    This effect requires the depth buffer to be generated for your scene, and requires custom shaders for any surface rendered at low resolution. The changes to your shaders are relatively minor, and well documented examples are included in the package.

    The speedup gained from using an offscreen rendering system is highly scene dependent. The effect requires rendering another camera and a post processing effect to resolve the output back to the screen buffer, if these effects take longer to render than rendering your particles would normally take it will actually slow your scene down. As such, it is most useful in scenes which want a high degree of overdraw that wouldn't be possible without such a system. More information can be found in my Unity 2015 talk:



    This package has been tested on Windows, OSX, iOS, Android and webGL.
     
    Last edited: Oct 21, 2015
    PolyMad, IgorAherne, Zenchuck and 5 others like this.
  2. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,461
    The 1.02 version has been submitted, which offers some speedups to the post processing part of the effect.
     
  3. larsbertram1

    larsbertram1

    Joined:
    Oct 7, 2008
    Posts:
    6,900
    broken on opengl?
     
  4. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,461
    Tested on android, osx, pc, ios, and webgl and working fine. What issue are you having?
     
  5. larsbertram1

    larsbertram1

    Joined:
    Oct 7, 2008
    Posts:
    6,900
    no z-testing for particles.
     
  6. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,461
    Are you using the included shaders or your own? If your using your own shaders, you need to do the z-test in the pixel shader as shown in the included shaders.

    I did see a bug today in the editor in which the depth buffer stopped being generated, but on the next run everything was fine (I'm currently using 5.2.1.p2); perhaps it was the same issue?
     
  7. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,461
    I just submitted an update to fix an issue with DX9/MSAA in which the depth buffer would be upside down.
     
  8. raja-bala

    raja-bala

    Joined:
    Jul 11, 2012
    Posts:
    29
    I should take a look at your package before I ask this, but I'm on Unity 5.0.x at the moment.
    I'm curious about your implementation. I tried this early last year, but hit a few roadblocks.

    1) Do you use two cameras, the second one solely for the particles layer?
    2) Is the depth test for the particles done in hardware or in the pixel shader? If h/w, I'd think you are using the particle shaders that ship with Unity, which brings me to
    3) How do you "transfer" the downsampled depth buffer to the second camera's depth buffer? When I tried this last, I remember the second camera doing a Z clear and wiping away what I wrote prior to rendering the particles.

    Look forward to your reply. Thanks!
     
  9. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,461
    1) Yes
    2) Done in the pixel shader of the particle effect
    3) Yeah, you can't do that in Unity - It would be nice if you could, because it would allow you to use hardware z-test instead of doing it in the pixel shader.

    The package should be fine in 5.0; I just built it with the version I'm on. It'll likely work in 4.6 as well, but I've never tried it..
     
  10. raja-bala

    raja-bala

    Joined:
    Jul 11, 2012
    Posts:
    29
    Thanks for the quick reply!
    Reg 2, aren't there several particle effect shaders? Your package seems to have only one particle shader.
    Reg 3, did you face the "Unity clears by Z buffer when I say Camera.RenderWithShader" issue, or even writing to it via SV_DEPTH (or DEPTH semantic in unity)?

    Weirdly, the package can't be downloaded from the asset store when I'm using 5.0.
     
  11. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,461
    I include two example shaders in the package, it's easy enough to write your own for any additional effects you might want. You just have to add the ztest from my shaders into yours.

    I don't use Camera.RenderWithShader at all in my technique, since the particle shaders are customized to render correctly against the low res depth buffer.
     
    J_Moller likes this.
  12. larsbertram1

    larsbertram1

    Joined:
    Oct 7, 2008
    Posts:
    6,900
    i just found the reason of my problem.
    enabling ral time shadows breaks z-testing – at least on open gl.
    any idea how to fix this?
     
  13. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,461
    Hmm.. We don't use real time shadows in our project - if I had to guess, I would guess that the real time shadows are clearing the zbuffer when they render from the view of the light, and that this is happening either before the particles are drawn or before the image effect is run. My bet would be the latter, otherwise all ztesting would break with multiple cameras.

    If it is the zbuffer being cleared by the shadow camera, we'd need to capture the zbuffer into a full screen buffer before this happens and use it for the depth comparison in the post processing function. However, this would incur a significant memory cost, so that would be nice to avoid. I'm also not sure when you could do this capture and be sure it happens before the shadow camera.

    One thing you could try, though it will have a side effect: Put [ImageEffectOpaque] above the declaration of the post processing effect - this will cause it to be drawn earlier in the process, hopefully before shadows are drawn. The side effect is the off screen particles will be drawn before alpha in your scene, which may or may not matter. If this works, you could also write an image effect which captures the depth buffer using [ImageEffectOpaque] and sets a global for the captured depth buffer that the offscreen particles can use.

    We're in the middle of shipping a product this week, but I'll try to carve out some time to turn on real time shadows in the demo scene and see what I can find out.
     
  14. larsbertram1

    larsbertram1

    Joined:
    Oct 7, 2008
    Posts:
    6,900
    thanks a lot for your answer!
    it seems that real time shadows force an "update depth texture" call which clears the _CameraDepthTexture (see image attached)

    i managed to avoid this by disabling shadows on all lights in the "void OnRenderImage".

    btw: [ImageEffectOpaque] is no option for me as i need particles to be rendered on top of other image effects.


    Bildschirmfoto 2015-10-25 um 14.03.07.png
     
  15. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,461
    Interesting - I wonder if there's a systematic way this can be done without going through all the lights in the scene? It would be nice if the component would 'just work' without these kinds of project specific hacks..
     
  16. larsbertram1

    larsbertram1

    Joined:
    Oct 7, 2008
    Posts:
    6,900
    well, to make it more general first of all you should set the particle camera to forward (my main camera uses deferred).
     
  17. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,461
    Yes, someone else contact me about that as well. I'll submit an update soon with the change so everything works with deferred cameras correctly - but it would be nice to find a way around the realtime shadow issues that 'just works' as well.
     
  18. larsbertram1

    larsbertram1

    Joined:
    Oct 7, 2008
    Posts:
    6,900
    hi jason,
    just some more feedback on the particle renderer.

    using your original: "Blend SrcAlpha OneMinusSrcAlpha" in the final composite shader gives me some "dark" borders around the particles:

    Bildschirmfoto 2015-10-30 um 23.34.39.png

    using: "Blend One OneMinusSrcAlpha" instead removes those borders:

    Bildschirmfoto 2015-10-30 um 23.39.53.png
     
  19. larsbertram1

    larsbertram1

    Joined:
    Oct 7, 2008
    Posts:
    6,900
    and i have to admit: i am not into image effects at all.
    but i have found a "Gaphics.Blit" which i do not know what it is good for (see code below).
    commenting it out did not make any changes as fas as i can say.

    void OnRenderImage(RenderTexture src, RenderTexture dest)
    {
    // make sure everything is assigned correctly
    if (!enabled || compositeShader == null || downsampleDepthFastShader == null)
    {
    if (compositeShader == null)
    {
    Debug.Log("OffScreenParticle: composite shader not assigned");
    }
    if (downsampleDepthFastShader == null)
    {
    Debug.Log("OffScreenParticle: downsample shader not assigned");
    }
    // what is that for?
    // Graphics.Blit(src, dest);
    return;
    }
     
  20. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,461
    Are you sure the code took that path? Because if you don't copy the src buffer to the output buffer you'll end up with a blank screen. This blit only happens if the shaders are not assigned and the effect cannot be run.
     
  21. aki-kanerva

    aki-kanerva

    Joined:
    Jan 3, 2012
    Posts:
    1,398
    @jbooth, This looks like a perfect solution for getting particles to ignore a Depth of Field effect (or any other image effect that doesn't play nice with transparent objects). And it works!

    Except... it doesn't work when I also have my main camera rendering into RenderTexture. I'm doing this to render the entire scene at a slightly lower resolution for performance optimization purposes (unrelated to particle performance).

    I tried poking around the code a bit, but couldn't figure out why it doesn't work when the main camera uses a RenderTexture. Any help would be appreciated! :)
     
  22. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,461
    If you just want to render the scene at lower res for performance, use Screen.SetResolution to lower the rendering resolution. You can change this on the fly on some platforms (android will flicker when you change it) to dynamically adjust fill rate costs based on current frame rates.
     
  23. aki-kanerva

    aki-kanerva

    Joined:
    Jan 3, 2012
    Posts:
    1,398
    Thanks for the quick reply, @jbooth!

    I'm afraid just changing the resolution is not an option as I'm working on a console platform. :) Plus I also use other tricks like rendering the HUD at full resolution while letting the game resolution change dynamically based on the current scene.
     
  24. Zenchuck

    Zenchuck

    Joined:
    Jun 2, 2010
    Posts:
    297
    Hi there, I am trying to get this working on a nexus 7 with tegra 3 gpu. I believe there is a problem with sampling the depth texture? Should I try reconstructing the depth buffer with replace shaders? I'm over my head here.

    ***edit

    I'm happy to forget about Tegra3 support for now.

    Thanks for providing an awesome solution to the fill rate challenged.

    I'm onto my next GPU - the Mali-400 and finding a strange banding effect. When I lower the ground plane the effect goes away.


    Here is an interesting thread:
    https://community.arm.com/thread/4080

    Here is an article on linearized Z-Depth
    http://www.mvps.org/directx/articles/linear_z/linearz.htm

    Here is a good article on "flimmering" and low precision z-buffer
    https://www.sjbaker.org/steve/omniv/love_your_z_buffer.html
     
    Last edited: Aug 30, 2016
  25. PolyMad

    PolyMad

    Joined:
    Mar 19, 2009
    Posts:
    2,350
    This piece of software can't be found anywhere now, why?
     
    AlejMC likes this.
  26. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,461
    It’s on my github...
     
  27. PolyMad

    PolyMad

    Joined:
    Mar 19, 2009
    Posts:
    2,350
    Ummm cool, but I can't find the URL of your Github page :(

    Btw, a curiosity: why it has been pulled away from the Asset Store?
     
  28. jbooth

    jbooth

    Joined:
    Jan 6, 2014
    Posts:
    5,461
    Not sure, but you can find my github in my signature.
     
  29. PolyMad

    PolyMad

    Joined:
    Mar 19, 2009
    Posts:
    2,350
    Mhhh ok, I found it and found that it's expensive in terms of production (must rewrite all the shaders).

    I can't understand this, why rewrite all the shaders?
    Couldn't the billboards just be drawn all together without regards to the environment, and then make them interact with the Z buffer of the rendered scene and clean up those parts that are behind the objects?
     
  30. alan-lawrance

    alan-lawrance

    Joined:
    Feb 1, 2013
    Posts:
    360
    I was glad to find this sample, as I have a need to do exactly this. Thanks Jason!

    Using the unmodified sample from Jason's github, the particle system doesn't z-sort correctly in game view for me (but does is scene view, oddly enough).

    Using frame debugger in 2022 I don't see any issues with the data, so it feels like I must be overlooking something obvious. Using the provided debug views the src image doesn't look right, but I don't think that is related. The (red) volume cloud is working as expected. Comparing the shaders, they have the same ztest logic in the shaders.

    Attached image is from Unity 5.5 (get same results as in 2022).
     

    Attached Files:

  31. alan-lawrance

    alan-lawrance

    Joined:
    Feb 1, 2013
    Posts:
    360
    Just a follow-up with more info -- looking at debug views when using Unity 2022, the src image output looks correct now, but it does look like the downsampled depth is flipped in Y? Again, probably not related, as red cloud is sorting correctly.

    upload_2024-2-7_4-48-56.png