Search Unity

Swift Shadows [RELEASED]

Discussion in 'Assets and Asset Store' started by ZimM, Feb 3, 2014.

  1. ZimM

    ZimM

    Joined:
    Dec 24, 2012
    Posts:
    963
    Swift Shadows is a lightweight substitute for Blob Shadow Projector, heavily optimized for mobile devices. It works by casting a ray to the surface and drawing a transparent quad that hovers above it. Literally hundreds of shadows can be drawn on a mobile device with a single draw call.

    Demos:
    Highlights:
    • Blazing fast. And I really mean it.
    • Works on any platform, does not requires Pro license to work. Heavily optimized for mobile.
    • Supports shadow texture atlases. All shadows in the scene can be drawn in a single draw call, even when they have different shapes.
    • Tons of customization options.
    • Shadows match object rotations.
    • “Static” shadows that are calculated only once and produce no overhead in run-time. It is possible to have hundreds of static shadows without a performance hit even on mobile devices.
    • Shadow generator tool for creating nice looking shadows automatically.
    • Sprite packer tool for easily packing multiple shadow textures into one to reduce the amount of drawcalls.
    • Ease of use, absolutely no scripting required.
    • Full source code and useful examples.
    Certain limitations exist:
    • Shadow textures are static. Shape of a single shadow is not updated in real-time. In some cases it is possible to work around this by using animated shadow cookie or by using multiple shadows.
    • Each individual shadows only projects on one surface at a time. This leads to a discontinuity as shadow moves from one object to another.
    • Shadow can extend the edges of object it is being projected on. It can also clip inside complex-shaped objects.
    These peculiarities are rarely noticeable for moving objects with blurry edges.
    Plugin is tested in Unity 4.6.x - 2017.x. Pro license is not required. All platforms are supported.

    Support:
    For any questions regarding this plugin, feel free to contact me at contact at lostpolygon.com or post in this thread.​

    Documentation:
    If you like the asset, please review/rate it on the Asset Store, I'll greatly appreciate that :)
     
    Last edited: Nov 27, 2017
  2. prometheusgr

    prometheusgr

    Joined:
    Aug 10, 2013
    Posts:
    2
    Do these shadows work on Tegra 3 devices? Looking for a cheaper solution than Sunshine that can get the job done for mobiles - and Ouya.
     
  3. ZimM

    ZimM

    Joined:
    Dec 24, 2012
    Posts:
    963
    Yes, it'll should run on Tegra 3 without any problems.
     
  4. Zaddo67

    Zaddo67

    Joined:
    Aug 14, 2012
    Posts:
    489
    Great Asset. I searched the asset store for a fast shadow tool that works with Unity Indie. I picked yours because you have the shadow material generator.

    Everything works great. I had shadows applied to my character in less than 10 minutes.

    Only one slight glitch. When my character is on the ground, it is not projecting a shadow? Any suggestions on what might be causing this glitch?

    Shadow Working


    $ShadowWorking.JPG


    Shadow Gone

    $ShadowGone.JPG
     
  5. ZimM

    ZimM

    Joined:
    Dec 24, 2012
    Posts:
    963
    Hi,

    this happens because the shadow is projected from the position of the GameObject, which in case of characters is often the lowest point in the model. Because of that, the raycast goes under the ground, not hitting anything. The fix is simple:
    1) Create an empty GameObject
    2) Attach it as a child of your character
    3) Position it to the (0, 0, 0), then move it up roughly to the middle of your character
    4) Add SwiftShadows script to that empty GameObject (removing the SwiftShadows script from the character object itself).

    $2014-02-10_15-17-33.png
    Hope this helps.
     
    RagingJacob likes this.
  6. Zaddo67

    Zaddo67

    Joined:
    Aug 14, 2012
    Posts:
    489
    Thanks for the quick reply. That worked perfectly. :)
     
    RagingJacob likes this.
  7. theHost

    theHost

    Joined:
    Nov 30, 2009
    Posts:
    37
    I have a situation where an object needs to cast a shadow but is created during runtime, and never moves after (but can be destroyed). Is it possible to mark them as static and therefore they don't need further shadow calculation? So basically, does your plugin support static shadows that are created at runtime?
     
  8. ZimM

    ZimM

    Joined:
    Dec 24, 2012
    Posts:
    963
    Yes, that'll work without any problems.

    Code (csharp):
    1. void Start() {
    2.   SwiftShadow ss = gameObject.AddComponent<SwiftShadow>();
    3.   ss.IsStatic = true;
    4. }
     
  9. theHost

    theHost

    Joined:
    Nov 30, 2009
    Posts:
    37
    Thanks for quick reply.
     
  10. Zaddo67

    Zaddo67

    Joined:
    Aug 14, 2012
    Posts:
    489
    I love this asset!!!

    I just want to share some code for automatically changing the light source to the closest light. This is usefull if you aren't using a directional light and have lots of lights in your scene.

    You will need to tag all your lights to find them. I am using the tag "LightsTag"

    I have SwiftShadow on a child object, "AnchorPos". You will need to adjust this line for your setup.

    I also have a mask on the raycast. You can remove this, or setup for your environment.

    Then just attach this script to your character.

    We don't need to check for a change in light source every update call. Note the variable, updateLightShadowFrames. The higher the value, the less often the script will check for a change in light source. This makes it less costly.



    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4. using System.Collections.Generic;
    5.  
    6. public class ShadowFollow : MonoBehaviour
    7. {
    8.     // Class Variables
    9.     public int updateLightShadowFrames = 50;
    10.     private List<Transform> Lights = new List<Transform>();
    11.     private string LightsTag = "Lights Tag";
    12.     private int updateLightShadowFramesCount = 0;
    13.     private SwiftShadow _shadow1;
    14.  
    15.     void Start()
    16.     {
    17.         // Get all lights
    18.         GameObject[] go = GameObject.FindGameObjectsWithTag(LightsTag);
    19.         foreach(GameObject g in go)
    20.         {
    21.                 Lights.Add(g.transform);
    22.         }
    23.  
    24.         // Get shadow script
    25.         _shadow1 = GameObject.Find("AnchorPos").GetComponent<SwiftShadow>();
    26.  
    27.     }
    28.  
    29.     void Update()
    30.     {
    31.         UpdateShadowLight();
    32.     }
    33.  
    34.     private void UpdateShadowLight()
    35.     {
    36.  
    37.         if (updateLightShadowFramesCount++ > updateLightShadowFrames)
    38.         {
    39.             // Reset counter
    40.             updateLightShadowFramesCount = 0;
    41.  
    42.             float closestDistance = float.MaxValue;
    43.             int lightId = -1;
    44.  
    45.             // Loop through all lights to find the closest
    46.             for (int i = 0; i < Lights.Count; i++)
    47.             {
    48.                 float distance = (transform.position - Lights[i].transform.position).sqrMagnitude;
    49.                 if (distance < closestDistance)
    50.                 {
    51.  
    52.                     // Cast a ray to find out if light can reach player
    53.                     Vector3 direction = transform.position - Lights[i].transform.position;
    54.                     RaycastHit hitInfo = new RaycastHit();
    55.                     Physics.Raycast(Lights[i].transform.position, direction, out hitInfo, 1000f, PlayerController.Instance.Laser.MaskTargets);
    56.                     if (hitInfo.transform)
    57.                     {
    58.                         // if we hit player then this light is closer
    59.                         if (transform == hitInfo.transform)
    60.                         {
    61.                             lightId = i;
    62.                             closestDistance = distance;
    63.                         }
    64.                     }
    65.                 }
    66.  
    67.             }
    68.  
    69.             // If we found a light, then update shadow
    70.             if (lightId > -1)
    71.             {
    72.                 if (_shadow1.LightSourceObject != Lights[lightId].transform)
    73.                 {
    74.                     _shadow1.LightSourceObject = Lights[lightId].transform;
    75.                 }
    76.             }
    77.         }
    78.     }
    79. }
    80.  
     
    Last edited: Feb 18, 2014
  11. ZimM

    ZimM

    Joined:
    Dec 24, 2012
    Posts:
    963
    That's a really useful script! I was actually going to implement something like that for an update :)
     
  12. briveira

    briveira

    Joined:
    Mar 31, 2014
    Posts:
    3
    I have just bought it and tried it but the default (without texture) shows up as a black square instead of a round, fuzzy shadow. Any ideas?
     
  13. briveira

    briveira

    Joined:
    Mar 31, 2014
    Posts:
    3
    well, also happens to my android project with textures (btw the texture generator seems to be fantastically simple and useful)
     
  14. briveira

    briveira

    Joined:
    Mar 31, 2014
    Posts:
    3
    solved, my textured shadows just needed a swift shadow shader in the material :) and somehow, after reapplying the quality settings, also the default blob works ok; I suppose I have just messed too much with the settings

    for what I have seen, your product is nice, perfectly encapsulated and easy to use!
     
  15. ZimM

    ZimM

    Joined:
    Dec 24, 2012
    Posts:
    963
    Hey everyone, Swift Shadows is a 24 Hour Deal right now with 50% discount! Go grab it while you still can :)
     
    Last edited: Jun 22, 2014
  16. imtrobin

    imtrobin

    Joined:
    Nov 30, 2009
    Posts:
    1,548
    The profiler reports garbage generated every frame. Also, there is a dll, no source?
     
  17. ZimM

    ZimM

    Joined:
    Dec 24, 2012
    Posts:
    963
    How many garbage are you getting? There are two "sources" of garbage in Swift Shadows:
    2014-06-22_20-29-17.png
    The first one is just 28 bytes per frame, it's nothing to worry about even on a ancient device like iPhone 3GS. The second one is bigger, but it does not happens in the build, it exists only in the Editor, so it is not a problem too. So actually, only 28B of garbage per frame will be generated in the actual build, and even that isn't worth worrying about.

    Only the shadow generator tool is put inside a dll, everything else is in the source form.
     
    Last edited: Jun 22, 2014
  18. Meceka

    Meceka

    Joined:
    Dec 23, 2013
    Posts:
    423
    In your demo, there is a "use two cameras" option. Can you explain this? It isn't in your documentation.

    I am working on a vehicle driving game. And while on road sometimes shadow gets clipped if road isn't planar, on terrain it's worse. I need to use that option, but would it affect performance?, if it would, how bad would it be?

    Also, how can i make a texture atlas? Does swift shadows auto generate asset? Or should I make it manually?

    Thanks.
     
  19. Meceka

    Meceka

    Joined:
    Dec 23, 2013
    Posts:
    423
    Well, I after checking the demo, i have made a secondary camera, made it show only ignore raycast, set shadow to ignore raycast layer. And removed ignore raycast layer from main camera. And then I've set the depth.

    But right now shadow is "on" the car, it's in front. How did you workaround that in that demo? Thanks.
     
  20. ZimM

    ZimM

    Joined:
    Dec 24, 2012
    Posts:
    963
    "Use two cameras" isn't really an option in Swift Shadow, it is just a way cameras are set up, as you have discovered. You got it almost right, except this: your car must be in the same layer as the shadow. In the demo, character has "Ignore Raycast" layer, and the shadow is just attached to it as a component, with "Shadow Layer" set to "Same as GameObject". This technique indeed has some performance hit, because the secondary camera has to clear the depth. However, that is a really cheap operation. I've just did a quick benchmark and found zero difference in actual performance on my device.

    Texture atlases are not generated automatically, so yes, you have to do that manually at the moment. The atlas in the demo is simply 2x2 square cells, so it isn't really hard to do it manually. And of course, you can generate atlas with some external tool.
     
  21. Meceka

    Meceka

    Joined:
    Dec 23, 2013
    Posts:
    423
    I am having this error each time I am accessing shadow layer;

    Layer index out of bounds
    UnityEditorInternal.InternalEditorUtility:GetLayerName(Int32)
    UnityEditor.EditorGUI:LayerField(Rect, GUIContent, Int32)
    LostPolygon.Internal.SwiftShadows.SS_ShadowEditor:<OnInspectorGUI>m__184(Rect, GUIContent, SerializedProperty) (at Assets/SwiftShadows/Internal/Editor/SS_ShadowEditor.cs:370)
    LostPolygon.Internal.SwiftShadows.EditorExtensions.PropertyEditor`1:DoFieldProperty(SerializedProperty, GUIContent, String, Func`4) (at Assets/SwiftShadows/Internal/Editor/SS_EditorExtensions.cs:326)
    LostPolygon.Internal.SwiftShadows.SS_ShadowEditor:OnInspectorGUI() (at Assets/SwiftShadows/Internal/Editor/SS_ShadowEditor.cs:363)
    UnityEditor.DockArea:OnGUI()
     
  22. ZimM

    ZimM

    Joined:
    Dec 24, 2012
    Posts:
    963
    This should not happen. What version of Unity are you using? Could you try creating an empty project, importing Swift Shadows there and see if it works there?
     
  23. Meceka

    Meceka

    Joined:
    Dec 23, 2013
    Posts:
    423
    I did camera layers as you said, and now shadow is below the vehicle, but there is a problem.

    Because of camera depths, now when going by a tree, if a tree enters between camera and vehicle, vehicle is drawn in front of tree where it shouldn't. I have been thinking about it and how I can modify layers so it wouldn't happen, but I am stuck. What can i do? Thanks in response.
     
  24. ZimM

    ZimM

    Joined:
    Dec 24, 2012
    Posts:
    963
    Well, in case your camera never goes below the road/terrain level, you can try moving your trees to the same layer as vehicle.
     
  25. imtrobin

    imtrobin

    Joined:
    Nov 30, 2009
    Posts:
    1,548
    28 bytes per frame adds up quickly. I try to avoid any garbage. I think it is foreach loop. I have Fast Shadow, it does not have garbage.
     
  26. ZimM

    ZimM

    Joined:
    Dec 24, 2012
    Posts:
    963
    Could you please explain why are you trying to avoid any garbage? This isn't a resonable thing to do when we are talking about 28 bytes. They don't really add up to anything noticeable, and they get collected immediately. In no circumstances can that amount of garbage cause any hiccups.
    Swift Shadows already work much faster than Fast Shadows, and 28 bytes of garbage are not an issue. Just the bare fact of generating zero garbage doesn't means anything.
    Just to elaborate - I can indeed rewrite the code in a way that will produce absolutely no garbage, but I'd like to hear why would anyone need that, because this change will make the code uglier and actually decrease the perfomance a bit, without any actual upsides.
     
    Last edited: Jun 23, 2014
    red2blue likes this.
  27. bobcat53

    bobcat53

    Joined:
    Jul 12, 2010
    Posts:
    26
    Hi ZimM,

    Great looking asset you have here! I was just wondering if the single surface limitation as seen in your moving cubes demo can be overcome in future updates?
     
  28. ZimM

    ZimM

    Joined:
    Dec 24, 2012
    Posts:
    963
    It is impossible with the current quad-based approach. It is doable in general, but then it'd also require Unity Pro, require much more processing power and pretty much mean writing a new plugin from scratch. So I wouldn't count on this limitation to be lifted in soon or at all, unfortunately.
     
  29. morepixels

    morepixels

    Joined:
    May 21, 2014
    Posts:
    18
    First of all, thanks for the great asset! This is the most robust shadow solution for mobile I've seen on Asset Store.

    That being said, I do have a problem setting up the shadows to work properly. The shadow of a vehicle flicker most of the time.
    To reproduce this issue you can:
    1. Create a project with Sample Assets (Beta) and Swift Shadows.
    2. Open "Car" scene
    3. Add SwiftShadow component to the Car GameObject
    4. Remove "Vehicles" from Raycast layer mask of the component
    5. Hit play and drive

    Once the car gains some speed, the shadow disappears. Do you know what it can be or how to fix this?
    Thank you
     
  30. Meceka

    Meceka

    Joined:
    Dec 23, 2013
    Posts:
    423
    Everything was working perfectly, and without any changes in shadow settings, swift shadows have begun to cause lag spikes about every half second. Something like garbage colleciton but "I don't have profiler". I know swift shadows causes it, because when I disable gameobject with swiftshadow component that lag spike disappears.

    It wasn't happening before, and what I did was populating the scene further, I didn't do anything else with swiftshadows but after populating scene that lag spikes have begun. That lag spike can begin anytime, in beginning of level or after some time, but lag spike never ends after appearing once, until a scene load.

    I am building for windows phone, and testing on lumia 520.

    Thanks.
     
  31. ZimM

    ZimM

    Joined:
    Dec 24, 2012
    Posts:
    963
    I've reproduced the problem, and that's exactly the same problem Zaddo67 encountered earlier in this thread. The solution is here:
    http://forum.unity3d.com/threads/swift-shadows-released.226227/#post-1514885
    Basically, create a child GameObject, move it up a little, and attach SwiftShadow component to it instead of the root. I've did that and the problem was gone.
     
    Last edited: Aug 4, 2014
    morepixels likes this.
  32. ZimM

    ZimM

    Joined:
    Dec 24, 2012
    Posts:
    963
    Sorry to hear that. How many shadow objects do you have? Have you tried disabling just the SwiftShadows component and not the whole GameObject? It's pretty much impossible to tell what exactly is causing the problem without any actual data. Could you please make a small project that reproduces the bug and send it to me? That way I'll be able to look into the problem much faster without making random guesses.
    Does the problem happens only on Windows Phone, or are you seeing the same behaviour on other platforms too (or in editor)?
     
  33. morepixels

    morepixels

    Joined:
    May 21, 2014
    Posts:
    18
    Thanks ZimM, this fixed the problem!
     
  34. Meceka

    Meceka

    Joined:
    Dec 23, 2013
    Posts:
    423
    Lag spikes start to occur when memory usage is close to limit (about 170mb i guess)

    Probably something about garbage collection. It must be getting called more often when memory usage is close to limit.

    I need some suggestion or workaround, my game becomes really unplayable when it happens.

    Disabling swiftshadow gameobject when in that situation always fixes these lag spikes.

    I am building for windows phone, and I've tested on a lumia 520, it has 180mb commited limit.
     
  35. ZimM

    ZimM

    Joined:
    Dec 24, 2012
    Posts:
    963
    Can you answer these questions, please?
    I really doubt it has something to garbage collection - Swift Shadows generates practically no garbage so it must be something else.
    To suggest a workaround I at least have to reproduce the bug. It's really hard to say something because I've never encountered such an issue and it was never reported before. So again, the most important question is
    In any case, a reproduction project would be the best way for me to actually try to investigate the problem.
     
  36. Meceka

    Meceka

    Joined:
    Dec 23, 2013
    Posts:
    423
    Usually one, sometimes two objects. If there is second shadow object, it usually gets disabled after some time when player gets far from that. As I remember it also occurs on scene where there is a single shadow object.

    You need to test on a phone, and somehow leak memory and it will begin when it's close to memory limit OS gives to application.
     
  37. Arkade

    Arkade

    Joined:
    Oct 11, 2012
    Posts:
    655
    Hi
    Great asset. Bought a while back as yet another attempt to get perfomant shadows in my mobile game (Ouya TEGRA-3 shadows, sigh). Seems promising so far :) However, I've just encountered a little bug that seems impossibly simple...

    I have a sphere model (a snowball) that I drag as a prefab into the Shadow Texture Generator. Everything is fine until I hit "Save shadow image" when it throws a "Trying to read pixel out of bounds" error. It goes on to save the file but it's a blurred square (not the obvious circle). Several other shapes have worked fine (including other spheres with same shader!?)

    Any thoughts welcome!
    Thanks, Rupert.
     
  38. ZimM

    ZimM

    Joined:
    Dec 24, 2012
    Posts:
    963
    Hi there,
    that's really weird. Could you send me the problematic model so I can investigate the issue?
     
  39. Arkade

    Arkade

    Joined:
    Oct 11, 2012
    Posts:
    655
    A little investigating says I don't need to -- it's using the Unity-integral "Sphere"!
    • Menu: GameObject | Create other | Sphere
    • Drag that into Shadow Texture Generator
    • Save.
    • Check errors and saved texture to see whether match mine.
     
  40. Arkade

    Arkade

    Joined:
    Oct 11, 2012
    Posts:
    655
    Also, is there any advantage to creating multiple circular shadows? (e.g. a shadow for a big sphere and one for a small sphere.) I could imagine there might be some [small?] performance benefit to not having to scale? (Question obviously assumes no other differences were desired (e.g. greater blur)).
    Thanks!
     
  41. Arkade

    Arkade

    Joined:
    Oct 11, 2012
    Posts:
    655
    P.s. I'm also getting it with a football model I made (suggesting it's not merely a Unity-integral-mesh thing). I can send that if needed.
     
  42. ZimM

    ZimM

    Joined:
    Dec 24, 2012
    Posts:
    963
    Well, that's a workaround, but not really a solution for the problem, so it'd still be nice if you'll send the model so I can examine it.
    No, there are zero performance advantages in doing that. In fact, it has a negative effect, as more textures have to be loaded in the memory.
    Yes, I'd be grateful if you do. Please PM me about that. Thanks!
     
  43. Arkade

    Arkade

    Joined:
    Oct 11, 2012
    Posts:
    655
    Hmm... So the Unity-integral-sphere mesh works OK for you? (your still asking for a model implies so.)
    That said, the wording of you reply makes me wonder whether I mis-communicated -- this isn't a workaround -- the Unity-integral-mesh causes the problem. I haven't worked-around. However...

    ... after this response, I'm anticipating creating a range of circular shadows at various blur levels to choose between.

    Sure, I'll PM you with the football mesh just in case.

    Thanks for the speedy responses btw!
     
  44. ZimM

    ZimM

    Joined:
    Dec 24, 2012
    Posts:
    963
    I've indeed have misunderstood you. But yes, the standard Unity sphere works fine for me...
    That's perfectly fine, I only wanted to say that it is pointless to have the same texture in multiple sizes because the scaling is basically free. If you want to be extra sure, you can put multiple shadows into an atlas texture to save some resources and improve batching (remember that only shadows with the same texture get batched).
     
  45. Arkade

    Arkade

    Joined:
    Oct 11, 2012
    Posts:
    655
    So I built myself a range of circular blobs using Inkscape to accompany my SS-generated model shadows and looked for an atlas generator. I have 2D Toolkit which includes this facility so started investigating how to get texture coordinates out of that. Not quite solved yet but queried their private support forum (here for any future curious). If I get a useful answer/script I'll hope to post back here.

    Obviously, self-atlassing is a bit of a pain. May I add a vote for integrated atlas generation? It would be super handy!

    I guess you could also do some sort of integration with some other atlas generators. Options?
    • Unity 4.5? integral atlas generation? (I'm not yet a Pro licensee to know)
    • TexturePacker -- not that I have it but it seems one of the most widely used.
    • Could this work with Pro Draw Call Optimizer? I'd guess not but... ?
    Obviously including my externally-generated blobs would break it but I assume all users have to address this if they're going to get the best from this asset, right?

    Thanks for listening!
     
  46. ZimM

    ZimM

    Joined:
    Dec 24, 2012
    Posts:
    963
    @Arkade
    Including some built-in atlasing support would be really neat, I agree. I haven't done it for the initial release, but I think I'd be able to make Unity 4.3+ sprites system work for this task (even without requiring Pro license). TexturePacker and Pro Draw Call Optimizer - well, maybe it's technically possible to somehow integrate them into Swift Shadows, but I definitely won't be doing anything specific about it for simplicity sake. But I like the idea of using 4.3+ sprite system, so that'd definitely be on my list.
     
  47. Arkade

    Arkade

    Joined:
    Oct 11, 2012
    Posts:
    655
    Got my 2D Toolkit wizard mostly working! (a few curios remain but will have to wait a while since I have other work this week).
    Will test it for a bit then hope to submit for your amusement!
     
  48. Arkade

    Arkade

    Joined:
    Oct 11, 2012
    Posts:
    655
    Cool. I'm sure it'll be good. (having spent most of today working with your asset and occasionally peeking at the code, I've gotta say it's good stuff!)

    I'm a little confused by "Unity 4.3+ sprites system ... without requiring Pro license". You mean something other than its integrated Sprite Packer facility? (I believe that's Pro only, right?)

    Thanks, R.
     
  49. ZimM

    ZimM

    Joined:
    Dec 24, 2012
    Posts:
    963
    The Sprite Packer is there only for convenience and ease of use, nothing can stop a programmer without a Pro license from implementing texture packing in some other way. And actually, yes, there are texture packing facilities that have been in Unity for a years, and I'm pretty sure they are available in Free. And even if they don't - meh, I'll just write my own packer :)
     
  50. ZimM

    ZimM

    Joined:
    Dec 24, 2012
    Posts:
    963
    Just wanted to ask - does anyone uses Swift Shadows with Flash exporter? I am considering removing Flash support as it makes code quite messy and puts an additional support burden while having a near-zero userbase.