Search Unity

[RELEASED] Super Fast Soft Shadows

Discussion in 'Works In Progress' started by Andy-Korth, Jun 5, 2015.

  1. slembcke2

    slembcke2

    Joined:
    Jun 26, 2013
    Posts:
    263
    Ah, right. So the vertexes on the projected end of the shadows are not shared, each segment is drawn individually. Normally you have two soft edges that line up and cancel each other out. Not exactly, due to precision errors, but very very close. When you use a radius of 0, the error isn't an slight variation in a shade of grey, but either completely on or off. Any precision error has a good chance to make the pixel completely the wrong color.

    The simplified shader removes all the penumbra calculations so that two segments that share a point will have *exactly* the same output.
     
  2. castor76

    castor76

    Joined:
    Dec 5, 2011
    Posts:
    1,416
    I will double check it but, are you sure the shader code above actually works? It doesnt block any lights at all.. I might be using slightly older shader from the package than the latest one. Because I had to.. it's a long story. Anyway I would post the other shaders here if I am allowed, to make sure the shader above works with the version of sf-shaders I am using.
     
  3. slembcke2

    slembcke2

    Joined:
    Jun 26, 2013
    Posts:
    263
    I'm not sure how compatible it is with earlier versions of SFSS. The shadow mask shader has evolved slightly to work around Unity limitations and bugs. I'd strongly prefer if you didn't post the shadow masking shader, since that is the biggest part of what makes SFSS unique.

    Regardless of what version you have, you should be able to easily modify it by hardcoding the radius value to 0 at the top of the vertex shader, and output (0, 0, 0, 1) from the fragment shader. To avoid divide by zero in the penumbra calculations in the fragment shader, the radius was never quite allowed to be 0. Multiplying by zero should definitely be handled correctly by any GPU, and removing the penumbra calculations from the fragment shader avoids divide by zeros. I ripped out the rest of the shader while figuring out what to change, but it doesn't hurt anything to leave it in.

    On a side note, I found another way to avoid the divide by zero issue, so true zero radius lights without speckled shadows will be possible in the next update.
     
  4. Epsiloncool

    Epsiloncool

    Joined:
    Mar 30, 2016
    Posts:
    16
    Hello,

    I have some speed issues with multiple lights and colliders. The issue is only visible at mobile devices. I have a labyrinth made from lots of square blocks (64x64) and some blocks which are actually "wall" have their own polygon collider. SSFS is using these colliders as shadow-casters and it looks fine on PC. However it makes huge speed-drop on mobiles. I have something like 3-10 frames per seconds!

    When I remove colliders completely (but leave lights there) I have very good FPS again (almost the same FPS as I had without SSFS at all). So I guess issue not in shader (because shader works always, independently from shadows, am I correct?).

    Simplifying colliders (when I made them completely simple - like 4 lines per block) slightly make all this runs a bit faster. But speed is not enough fast yet.

    I read your PerformanceTips.pdf and found this line:
    "Turning off PixelSnapping can occasionally make a big difference."
    What you exactly meant here? What should I do to increase speed?

    Why even very simple colliders slows down the app so much? What can I change?

    E20160604-014208[1].png
    There are 3 lights at the scene. Visible area is a rectangle at the middle top, so I see only one light source.

    Thanks.
     
    Last edited: Jun 4, 2016
  5. slembcke2

    slembcke2

    Joined:
    Jun 26, 2013
    Posts:
    263
    Do you really have an SFPolygon for every green collider there? That's a *lot*! Guessing from your light size in the screenshot, there must be hundreds for every light. There is a cost on the CPU for every polygon and vertex, and on the GPU for each segment and each shadowed pixel for each segment.

    Remember that you only need the outline of the surface, you don't need to fill the volume. Every segment you add that isn't on the surface lowers your performance, and a fraction of your segments are on the surface. Of the polygons at the surface, each one has maybe 2-3 segments each. That will cause a lot of cache misses and might be ruining the CPU performance. Join them together into larger chunks maybe 1/4 the size of the screen if possible for the best batching/culling performance. Just dropping the inner segments should improve performance by several times though.

    Another thing to note is that it looks like your shadow map scale is set very low. This increases the number of pixels the GPU must draw. Double the scale number, and you'll quarter the number of pixels that it has to draw, but also halve the resolution. For a mobile game, 4 is a good number for the shadow map resolution. The lightmap resolution can be even bigger, like 16 or so since it will have few details.

    Given your art style, it doesn't look like you are using it to begin with? It should be pretty minor, I'm not quite sure why we even bothered to mention in the docs other than to be thorough.
     
  6. Epsiloncool

    Epsiloncool

    Joined:
    Mar 30, 2016
    Posts:
    16
    Thank you, slembcke2!

    I think I really need to redo my shadow colliders structure. But as soon as I am using maps created in external program, I will need to create good algorithm to smart polygon merging.

    Increasing shadow map scaling really increases performance. However, it also adds worse "waves" on the shadow boundaries. Even value=2 is visible at PC, but ok I will try now at mobile also.

    Another question: which operation is executed when you need to analyze all colliders in the scene? I guess you are creating a special polygon in SSFS's buffer to be processed by pixel shader or so. This polygon contains initial lighting cookie with substraction for "shadowed" pieces, right? This was my idea today - I can create special "cookie" using my initial cookie and remove some areas from it to get correctly lighted screen zones and then just remove SSFS shadow colliders at all to improve speed - since most of my lights and walls are static, it could increase speed a lot.
    But later I guess this type of "caching" could be done inside of SSFS itself.

    Do you have thoughts about it?

    Thanks.
     
  7. Epsiloncool

    Epsiloncool

    Joined:
    Mar 30, 2016
    Posts:
    16
    Well, I've just tested shadow map scale =4 at the mobile. Looks not good, I see "waves". However I think =2 will be pretty good.
    By the way, I did not see much improvement in speed when I increase the value to 4. Obviously, this option is only useful on a mobile devices with a very weak GPU. Well, fine. I can put this parameter to 2 by default and let users increase quality of gfx (or increase gfx performance) by justifying parameter in "Game Settings".
     
  8. Epsiloncool

    Epsiloncool

    Joined:
    Mar 30, 2016
    Posts:
    16
    Sorry, one more question:

    do you analyze ALL shadow colliders in the scene or only currently visible ones at the screen?

    Thanks.
     
  9. slembcke2

    slembcke2

    Joined:
    Jun 26, 2013
    Posts:
    263
    Unfortunately yes, higher quality does mean more GPU time. Mobile GPUs don't have a lot of resources for pixel shaders, yet they have *huge* screens. You have to compromise somewhere. Unity's 3D shadows on mobile are also not great for the same reasons. You get hard shadows with aliasing, and the shadow resolution can really slow things down.

    There isn't a specific method for it, though watch the "polys" variable in SFRenderer.RenderLightMap(). It's not optimal, but it's quite simple and effective.

    Static lightmaps? I haven't given them a lot of thought. They would be possible, but use a lot of memory. Static lightmaps for 3D scenes are usually very, very low resolution. Not sure if many people would find that good enough in 2D.
     
  10. slembcke2

    slembcke2

    Joined:
    Jun 26, 2013
    Posts:
    263
    It has to check the whole list to see which could possibly cast shadows onto the screen based on the current lights. Then that list is filtered again for each light. Nearly optimal assuming all lights and polygons are dynamic. Less optimal of some of them are static.

    I'm going to send you a PM with the latest development version. It should give you some additional mobile performance. It seemed to help @castor76 a lot.
     
  11. Epsiloncool

    Epsiloncool

    Joined:
    Mar 30, 2016
    Posts:
    16
    Thanks a lot!

    Again, your product is a great and best solution for 2d lights and shadows! :)
     
  12. castor76

    castor76

    Joined:
    Dec 5, 2011
    Posts:
    1,416
    Well, I did try your suggestion but it is still the same. No shadow casting at all. However, I was managed to come up with shader that did the trick by conserving the part of calculation for the clipPosition. After that, it all seems to work as good hard shadow without leaking, even on Xboxone. So it's good.

    I still feel it could be optimized further for my case.. perhaps even during the shadow polygon collider construction part on SFLight.. but I could not go that far because I still don't understand fully how the collider's values are constructed..

    Soft shadow is good, but the most important thing for me was non leaking light at all times, so I guess I will have to stick with hard shadow.

    Thanks for the ideas. If you ever can come up with softshadow with non leaking method, it would be super cool.. I think leaking isn't very good for any light + shadow casting solution even if they are not that notice-able by having some kind of compromising configurations. I mean they should never leak, unless used in wrong way. Still very cool plugin thou.
     
  13. slembcke2

    slembcke2

    Joined:
    Jun 26, 2013
    Posts:
    263
    Version 3.1 has been submitted to the asset store, and is waiting for review. Changes include:
    • Memory usage improvements.
      • No dynamic memory allocation. (Very GC friendly)
      • Reducing memory usage by sharing meshes and vertex arrays.
    • Correctly render lights and SFPolygons with flipped transforms.
    • Copy from collider now respects the "offset" property.
    • Fix "cracks" that would appear in shadows for a 0 radius light.
    • Always show light intensity. (It would disappear with certain colorspace settings.)
    • Editor mode shadow culling fixes.
     
  14. slembcke2

    slembcke2

    Joined:
    Jun 26, 2013
    Posts:
    263
  15. Cybertiger

    Cybertiger

    Joined:
    Dec 19, 2013
    Posts:
    27
    Hi there,
    I just purchased your product and tried your demo scenes in Unity 5.4.B017.
    Unfortunately none of them are casting shadows.
    Could it be because i have an extra layer in my project settings?

    Thanks
     
  16. slembcke2

    slembcke2

    Joined:
    Jun 26, 2013
    Posts:
    263
    Upgrade to b21 or greater. The earlier 5.4 betas had bugs that broke SFSS. Fortunately Unity fixed them though. \o/
     
  17. Cybertiger

    Cybertiger

    Joined:
    Dec 19, 2013
    Posts:
    27
    Thanks for your fast response. I tried that but still the same issue with Unity 5.4B22.
     
  18. slembcke2

    slembcke2

    Joined:
    Jun 26, 2013
    Posts:
    263
    Do the example scenes work? If so, some configuration in your scene is probably missing. If that's not the issue, then what OS are you using, and what renderer are you using in your platform build settings (GLCore, DX11, etc).
     
  19. Cybertiger

    Cybertiger

    Joined:
    Dec 19, 2013
    Posts:
    27
    I tried to make a completely empty new project with your example scenes and with Standard settings. I am on a MacbookPro here.
    I noticed that "Shadow Layers" is empty in the "SFLight" script?
    Didn't change that but wondering if something is messed up with layers?
    Tried to select a layer for the light as well as for the geometry but also no luck. Any further help much appreciated.
     
  20. slembcke2

    slembcke2

    Joined:
    Jun 26, 2013
    Posts:
    263
    That might have something to do with it? The default layers value in both the light and polygon scripts is everything. If a light has no layers, it won't cast shadows on anything. If a polygon has no layers, it won't cast shadows from any light. Try setting them to everything or a specific layer you want.
     
  21. Cybertiger

    Cybertiger

    Joined:
    Dec 19, 2013
    Posts:
    27
    Like i mentioned in my previous post. I tried that already but unfortunately also no luck. Tried to make a new custom layer and set the light and geometry to it. And also tried "Everything" layer but no luck either. ;(
     
  22. Togimaro

    Togimaro

    Joined:
    Jan 30, 2013
    Posts:
    1
    Hi,
    I saw before in the thread that the perspective camera didn't work.
    Is this still true?

    Thanks
     
  23. Cybertiger

    Cybertiger

    Joined:
    Dec 19, 2013
    Posts:
    27
    I am testing with your provided example scenes and they are set to Orthographic.
     
  24. slembcke2

    slembcke2

    Joined:
    Jun 26, 2013
    Posts:
    263
    @Cybertiger So to be clear, the example scenes don't work either? You said you are on a MacBook Pro (OS X is our primary testing target), but are you using the Metal or one of the GL renderers in your build settings?

    @MrTogimaro SFSS does not work with perspective cameras at this time.
     
  25. Cybertiger

    Cybertiger

    Joined:
    Dec 19, 2013
    Posts:
    27
    Okay. For anyone else who is having issues on his mac.
    In unity 5.4 in your Player Settings / Other Settings.
    Turn off "Auto Graphics API for Mac"
    And reorder the Graphics API to the following:
    OpenGL2
    OpenGLCore
    Metal(Experimental)

    It only works when "openGL2" is on top. For some reason for me "OpenGLCore" was automatically on top.
    Thanks for your help @slembcke2
     
  26. slembcke2

    slembcke2

    Joined:
    Jun 26, 2013
    Posts:
    263
    OpenGLCore should be working. Metal too, but that one has been really unstable (experimental after all?). The OpenGL2 renderer is very obsolete. We might have to upgrade to the latest beta and file another round of bugs. Supporting a rendering asset is fun. :-\
     
  27. Andy-Korth

    Andy-Korth

    Joined:
    Jun 7, 2013
    Posts:
    140
    I've confirmed that SFSS works in 5.4.0b21 but doesn't work in 5.4.0b22. We will file a bug for this one.
     
  28. slembcke2

    slembcke2

    Joined:
    Jun 26, 2013
    Posts:
    263
    Unity 5.2 -> 5.3 broke a lot of stuff that needed some nasty workarounds. This time we are being more proactive about filing bugs in the betas to get them fixed, but it's definitely not less work. :-\
     
  29. Cybertiger

    Cybertiger

    Joined:
    Dec 19, 2013
    Posts:
    27
    I can imagine that it is super though to support a render asset. ALL the time something changes.
    But if it works it looks superB and your support is fantastic. Thanks for your help so far. Hope it works soon again on openGLCore.
     
  30. Andy-Korth

    Andy-Korth

    Joined:
    Jun 7, 2013
    Posts:
    140
    Case 807990: "We have been able to reproduce this bug and have sent it for resolution with our developers."

    Unity has been great lately with their bug fixes. Especially since this is a regression, I expect it to be fixed very quickly! For now, use 5.4.0b21 if you need to use a beta version of Unity. But thanks for reporting this, we don't download every single beta for testing, so it's a big help!
     
  31. Cypras

    Cypras

    Joined:
    Oct 25, 2013
    Posts:
    52
    Fantastic asset, I am having a weird issues where shadows do not appear on some android devices. The lights work, but no shadows show up, im using the latest version of Unity and version 3.0.0 of your asset. I've tried everything I can think of to fix this, but no luck.
     
  32. slembcke2

    slembcke2

    Joined:
    Jun 26, 2013
    Posts:
    263
  33. Cypras

    Cypras

    Joined:
    Oct 25, 2013
    Posts:
    52
  34. Cypras

    Cypras

    Joined:
    Oct 25, 2013
    Posts:
    52
    After testing the DirectionalLightExample in a completely new Unity Project, it fails to show the shadows.

    The test device is HTC One m8 with a 6.0 Android. This also happens on Galaxy s5 with Android 6.0.1.

    These are the only 2 devices with known issues.
     
  35. slembcke2

    slembcke2

    Joined:
    Jun 26, 2013
    Posts:
    263
    To be clear, the lights are working, but the shadows are not?

    In SFRenderer.cs, look for this line:

    RenderTextureFormat format = (camera.hdr ? RenderTextureFormat.DefaultHDR : RenderTextureFormat.Default);

    and try replacing it with this:

    RenderTextureFormat format = RenderTextureFormat.ARGB32;

    Can you check the device's log. Does it mention anything about shaders failing to load? Both of those phones have an Adreno 330 GPU. Qualcom used to have notoriously buggy drivers.
     
  36. Cypras

    Cypras

    Joined:
    Oct 25, 2013
    Posts:
    52
    Thanks for the reply. I'm going on holiday for a few days, and ill test it when I get back.

    I do know that not all galaxy s5 phones have this problem. Just some.
     
  37. Shinzironine

    Shinzironine

    Joined:
    Nov 30, 2013
    Posts:
    32
    Hey guys, just bought the asset - great stuff! I'm wondering if there is a way to use sorting layer names and order with super fast shadows? Thanks.
    P.S. What I mean is set the sorting order to the light and shadow itself, so that it will be obscured by sprites that are in front of it.
     
  38. slembcke2

    slembcke2

    Joined:
    Jun 26, 2013
    Posts:
    263
    Unfortunately no. I think what you are describing would require re-rendering all of the lights in separate passes after each sprite is drawn which would be incredibly expensive. The alternative would be to use a 3D shadow technique that would gain all of the quality downsides of 3D shadow algorithms and lose all of the benefits of SFSS since it's solving a much simpler problem. SFSS does have it's own limitations since it's all strictly working in 2D though.

    Maybe there is another way to get the effect you want. Could you describe what you are trying to do more, or make a quick picture maybe?
     
  39. Shinzironine

    Shinzironine

    Joined:
    Nov 30, 2013
    Posts:
    32
    I totally get the limitation thing, the asset works for me incredibly regardless.

    What I was thinking was the light in the virtual 3d plane. The guy in the scene stands on the ground, so the light would not leak under the ground normally and the foreground (I have separate sprites for foreground) would also hide the light.

    Hmm now that I think about it, maybe I just should draw a polygon around my ground object to stop the light.

    Upd: ops, the cookie still leaks
     
    Last edited: Jul 25, 2016
  40. slembcke2

    slembcke2

    Joined:
    Jun 26, 2013
    Posts:
    263
    Ooh. Took me a while to figure out what I was looking at in that gif. (It's really dark!)

    Things that might be causing that:
    • On your ground's material, check the "Unshadowed/Shadow" and "Lit/Ambient" sliders. These let you mix the strength of shadows and ambient light.
    • Make sure your ground polygon isn't set to be semi-transparent. (SFPolygon opacity)
    • Try turning on "Linear light blending" in the SFRenderer settings. Turning it off is a cheap hack to try and make HDR-ish lighting on mobile without the cost. It has some artifacts with tinted shadows though. Maybe the issue?
     
    Shinzironine likes this.
  41. Shinzironine

    Shinzironine

    Joined:
    Nov 30, 2013
    Posts:
    32
    Thank you! Figured out the settings that work perfectly for my game.
     
  42. Shinzironine

    Shinzironine

    Joined:
    Nov 30, 2013
    Posts:
    32
    Another question: is there a way to find out wether or not the object is lit by the light cookie?
     
  43. slembcke2

    slembcke2

    Joined:
    Jun 26, 2013
    Posts:
    263
    Unfortunately not very easily since almost none of the lighting runs on the CPU or exists in system RAM. If the object is onscreen, you could read back the lightmap texture (usually sorta slow) and check pixels. Otherwise you need to do raycasts against the SFPolygons, but the hard way since there might not be colliders for them. Ideally you also want to do cone tracing to emulate penumbras, and that's even harder.

    Realistically, you'll have to settle on a distance/angle check or regular Unity raycasts to check that.
     
  44. Shinzironine

    Shinzironine

    Joined:
    Nov 30, 2013
    Posts:
    32
    Got it, thank you!
     
  45. ittinop

    ittinop

    Joined:
    Nov 9, 2015
    Posts:
    15
    Hello Andy,

    I am sure your asset must be really great, but the only problem is that I snatched it up too quickly without noticing that it is only for 2D game.
    Would you remind refunding this asset for account name "ittinop" ?
    Sorry for the inconvenience.

    Thanks a lot in advance,
    Ittinop (Pun)
     
  46. Andy-Korth

    Andy-Korth

    Joined:
    Jun 7, 2013
    Posts:
    140
    Hi ittinop, please send your invoice email from the asset store to our support email, admin at howlingmoonsoftware.com. We need the invoice number and we can send it to unity support via email. Then they can review it.

    Officially, the asset store does not offer refunds, but if we jump through enough hoops, we can usually get one for you.

    See: https://unity3d.com/asset-store/help
     
  47. Oribow

    Oribow

    Joined:
    Nov 9, 2012
    Posts:
    38
    Hello,
    just bought your Asset and it looks amazing! But I have problems with the shadowlayers. They don't seem to work. The only thing that works is, when I set the light shadowlayer to nothing. It correctly stops drawing shadows for that light. But no other configuration does something. It renders always all shadows. A code search yielded the result, that the shadowlayer field of the SFPolygone is no where used. Please help.

    My specs:
    Unity 5.4.0f3
    Win 10
    SFVersion: not sure, but this is the first part of the changelog file
    Changes since 3.0:
    * Memory usage improvements.
    * No dynamic memory allocation. (Very GC friendly)
    * Reducing memory usage by sharing meshes and vertex arrays.
    * Correctly render lights and SFPolygons with flipped transforms.
    * Copy from collider now respects the "offset" property.
    * Fix "cracks" that would appear in shadows for a 0 radius light.
    * Always show light intensity. (It would disappear with certain colorspace settings.)
    * Editor mode shadow fixes.
     
  48. Andy-Korth

    Andy-Korth

    Joined:
    Jun 7, 2013
    Posts:
    140
    Hi Oribow,
    Oops, it looks like we lost something there. I will get back to you in more detail after the holiday, but for now go to SFLight.cs and add this if statement and continue starting at Line 122:

    Code (CSharp):
    1.         var j = 0;
    2.         for(int c = 0; c < polys.Count; c++){
    3.             var poly = polys[c];
    4.             if( (poly.shadowLayers & this.shadowLayers) == 0){
    5.                 continue;
    6.             }
    Then only matching lights will be drawn. We will include an example in the next update.

     
  49. Oribow

    Oribow

    Joined:
    Nov 9, 2012
    Posts:
    38
    Thanks for the reply. Now that I now the code place, I can fix it my self. Another question, why do you allow copyColliders only from polygoneColliders? Wouldn't it be easy to add support for other types of 2d colliders?
     
  50. Oribow

    Oribow

    Joined:
    Nov 9, 2012
    Posts:
    38
    Hi Andy,
    The solution you post is incomplete.The if statement must also be added here:
    Code (CSharp):
    1. for(int i = 0; i < polys.Count; i++){
    2.             var poly = polys[i];
    3.             if (_shadowLayers != (_shadowLayers | 1 << poly.shadowLayers))
    4.                 continue;
    If you dont do that strange shadow artifacts will occure. Took me serval hours to find, although it seems obvious by now. I'm a bit disappointed.

    For others who read this and want layer checking, that doesnt just compare the two layermasks. Do the following: Change both occurences of this line :
    Code (CSharp):
    1. if( (poly.shadowLayers & this.shadowLayers) == 0){
    2.                 continue;
    3.             }
    To this:
    Code (CSharp):
    1. if (_shadowLayers != (_shadowLayers | 1 << poly.shadowLayers))
    2.                 continue;
    In the SFPolygon file change the type of "shadowLayers" and "_shadowLayers" from LayerMask to int.
    Finally change the following line in the SFPolygonEditor class (included in the SFEditor file)
    Code (CSharp):
    1. PropertyField("_shadowLayers");
    to this:
    Code (CSharp):
    1. serializedObject.FindProperty("_shadowLayers").intValue = EditorGUILayout.LayerField("shadowLayers", serializedObject.FindProperty("_shadowLayers").intValue);
    Now you can select one layer shadowlayer for each SFPolygon and exclude or include shadow drawing for them with the SFLight shadowmask.