Search Unity

Sprites Diffuse Shader Has Transparency overlap issues with lighting?

Discussion in '2D' started by Jesse_Pixelsmith, Dec 20, 2013.

  1. Jesse_Pixelsmith

    Jesse_Pixelsmith

    Joined:
    Nov 22, 2009
    Posts:
    296
    $Sprite Lighting Transparency Overlap.PNG

    So I'm using the Sprites/Diffuse shader to light some of my sprites, but they seem to have an issue with transparency when they overlap.

    I can see why this might be the case because they are on the same Z value, and the same "Order In Layer" - without lighting these overlap normally without Z-fighting (I assume Unity does something behind the scenes for this to work).

    If I change the "Order In Layer" of one of these, the problem goes away.

    So that would be possible ( but annoying) to set up different Orders for every overlapping static object in my scene, but I'm trying to solve for a situation where 2 characters might run past eachother and overlap, how is that best handled?
     
    shottogan likes this.
  2. fuedR

    fuedR

    Joined:
    Aug 30, 2013
    Posts:
    11
    I usually just use multiple Order In Layer, layers.

    how is unity supposed to know which one will go on top, and which will be underneath otherwise?

    even without diffuse shader, i get visual bugs when they are both set to the same layer(and have no sorting layer attached or z position difference)
     
  3. Kilrath81

    Kilrath81

    Joined:
    Nov 19, 2013
    Posts:
    153
    ive just changed the z position to solve most of that.
     
  4. Jesse_Pixelsmith

    Jesse_Pixelsmith

    Joined:
    Nov 22, 2009
    Posts:
    296
    what do you guys do for dynamic moving objects (ie NPCs) who might wander over each other, but otherwise are separate. Would you assign all NPCs to their own unique Order In Layer?
     
  5. mcroswell

    mcroswell

    Joined:
    Jan 6, 2010
    Posts:
    79
    Hey Jesse, did you ever find an answer to this? I'm about to write a modified version of one of the Sprite shaders (Sprites-Diffuse or -Default) that respects z-depth. That is, it will ideally use layers as defined when the z-depth is approximately equal but paint by more-distant-z first when not equal. I think this is what we're both looking for. I would guess Unity would supply some kind of Respect_Z option in the future instead of just Layer Groups. Or perhaps -1 would mean ignore Layer Groups and respect Z - that kind of thing. I certainly hope. SmoothMoves is still out there. ;-)

    -Mike (from Fort Collins!)
     
    Last edited: Jan 29, 2014
  6. zombiegorilla

    zombiegorilla

    Moderator

    Joined:
    May 8, 2012
    Posts:
    9,052
    Yup, that is pretty much the purpose of have it setup that way.. For more trivial elements, I use z-depth. Sprites render in order: Layer, Order then Z.
     
  7. zombiegorilla

    zombiegorilla

    Moderator

    Joined:
    May 8, 2012
    Posts:
    9,052
    It's pretty unlikely they would. The whole point of having layer groups and order is provide better control than was available before. You don't need to have an "ignore" feature, just don't use use them. Ignore is the default state. ;)
     
  8. mcroswell

    mcroswell

    Joined:
    Jan 6, 2010
    Posts:
    79
    You are right in general, but I'm pretty sure you either didn't understand us or you don't understand the subtleties of the issue, OR you've created your own shader.

    Yes, z-depth works with quads, or sprites using something like the Transparent Cutout shader. The sprite shaders (defaults) only respect layer order, though, as I think you implied, do respect z when used with the other shaders. However, if you have say, two NPC's and they interweave in terms of z, the sprite shaders (as they stand) do not work. They _do_ need an "Respect Z with Other Sprites" option. Yes, it should be off by default. However, Unity could (and in my opinion, should) add this option.

    The current Unity system does not allow sprites to render both in layer-order and still respect Z using the sprite shader(s). In other words, what we (Jesse and I) are trying to do is is have sprites respect layer when the parts are all together in the same z (like when you make a sprite using the new system) and respect Z when those very same sprites are placed in a world where z-placement is constantly changing for NPC's. I'm guessing that when you say "ignore" you're saying to use some other shader (and not the built-in sprite shaders. If this is the case then you will lose the nice inner-character layering, if you follow.

    Note, when I have time, I can post a visual of the problem, if either of you'd like , as well as the solution I found by modifying one of the built-in sprite shaders. Would you like to see the issue visually? If so, maybe we could move this discussion to the Answers area?

     
  9. ADoby

    ADoby

    Joined:
    Dec 10, 2012
    Posts:
    21
    Hey, got a fix for you guys.
    Everytime you spawn something (you normally use GameObjectPools for performance reasons) you just change the z axis a bit (just a very little bit).
    Easy to do if you have something like an EntitySpawnManager or something which counts your entities.

    GameObjectPool.Spawn(Prefab, Position + Vector3.forward * 0.0001f * CurrentSpawnedEntityCount);

    This will stop them from getting rendered transparent.
    CurrentSpawnedEntityCount HAS to be changed every time something spawns or despawns, otherwise it won't work.
     
  10. s-m-k

    s-m-k

    Joined:
    Oct 26, 2013
    Posts:
    16
    I don't really like the idea of modifying "z" or "sorting order" in the current framework. They sound dirty as hell, especially when you're dealing with skeleton animations with several bones.

    The best solution for that kind of situations would be just taking into account the order of which the objects appear in the scene. So, all characters could have the same "sorting order" and they would look good, because they would be drawn in the correct order anyway. You would be able to just spawn/delete them freely without even thinking about that "sorting order" or changing "z", which can affect character's lighting if the difference is too big.
     
    shottogan likes this.
  11. mcroswell

    mcroswell

    Joined:
    Jan 6, 2010
    Posts:
    79
    @zombiegorilla : This thread just got a hit and it reminded me that I should have come back and modified this thread. I was wrong. Anyway, some background: I used to do sprites (and still often do) the old Transparent/Cutout/[Whatever] shaders. Back when we discussed this it was the only way to fix the problem and so, that is why I though Unity should add a check box to make this available automatically.

    @ADoby Shifting by a little is a good option, but back when we first wrote this it wouldn't work with the regular transparent shader. Back then, for getting z-defined shading (where you arrange your sprites in z-depth) you simply had to use a material that uses the built-in Transparent/Cutout/[Whatever].

    So, I was just about to post a picture and found out that the new default sprite shader always (edit: sometimes) respects z now. So, Unity fixed this issue by simply adding z-respecting all (edi: some of) the time. The trick is if you don't want that, simply put everything at the same z. So, here are two sprite (sets). With the same z you see the intertwine. The second ant (highest order) is supposed to be on the other flower and I'd like it to be hidden.
    upload_2014-12-8_16-48-35.png
    So, the fix is either use change the Sorting Layer (select all three parts and change) and that would result in this:
    upload_2014-12-8_16-52-29.png
    Or, because Unity fixed it, just change the depth (this next screen shot changes the z fairly dramatically - a .22 z diff):
    upload_2014-12-8_16-54-36.png
    So, for sprites that have the same orders this works well.

    Now if the sprites are different and have different orders (say the first was composed of orders 50,60, 70 and the back was a different set of orders 0,1,2) then no matter how close the back one is it would stay in the background!!! Another Unity bug? Here the bigger one, _should_ be in the back (in my opinion size the z is so close to us). FYI, you'd normally not do this since the closer one has the orders 0,1,2 for the stem, flower and ant respectively:
    upload_2014-12-8_17-8-23.png

    Again, the fix, like it was back then, is to use the Transparent/Cutout to get this:
    upload_2014-12-8_17-6-32.png

    Just wanted folks to know that this is not a simple problem, but there are tons of solutions. I guess, I will continue to use Transparent/Cutout, when z matters. :)
     
  12. mcroswell

    mcroswell

    Joined:
    Jan 6, 2010
    Posts:
    79
    EDIT: Since this may change over time, I would like to say this is from version 4.6.0f3
     
  13. zombiegorilla

    zombiegorilla

    Moderator

    Joined:
    May 8, 2012
    Posts:
    9,052
    Your problem is that you are mixing, and over complicating the process a bit. The sprite shaders work perfectly and as expected... when using them in context with sprite shaders. Mixing them in with quads and other shaders or materials (not specifically designed to work with the layering system) will yield unexpected results. You can manually set the render layer/order via code on other renderers like this:
    Code (CSharp):
    1. gameObject.renderer.sortingLayerName =  <string>;
    2. gameObject.renderer.sortingOrder = <int>;
    3.  
    But that doesn't always work like you would expect if you are not using sprite renderers (or include the layering aspect in the shader).
    Not a bug, that is exactly how it is supposed to work. Order takes precedence over camera distance (z). Lower orders will always be behind higher orders, on the same layer. Lower layers will always behind higher ones, irrespective of order and camera distance.
    Lower layers and their contents are rendered first. Inside each layer, lower orders and their contents are rendered first. Sprites inside an order are rendered in order of their distance from the camera.
    Again this is assuming you are using the Sprite shaders. If you use other shaders, there are going to be a variety of things that affect the render order, depending on the shader. For example the transparent/cutout shader doesn't appear to take layer/order into account.

    That is why for this express purpose, you want to use the Sprite shader. By introducing the cutout shader, you are circumventing the whole layer system, and unless you are very knowledgable about shaders and write it correctly, or fully understand the render queue, you are going to unplanned results. If you switch materials (and shader), it doesn't really respect the order/layer (unless the shader supports it), and will default to camera depth despite what you set in the layer/order.

    Why are switching the shader? The simple solution is just use the Sprite shader for this type of thing. Everything will work as expected and be very efficient have other benefits beyond layering.
     
  14. mcroswell

    mcroswell

    Joined:
    Jan 6, 2010
    Posts:
    79
    You are correct. That is how it should be. But it is not the case - when z is involved. In the first example, I've shown above the lower orders are rendered first. This is why the pieces are intertwined and give the results that you would expect for stuff at the same z and same layer. Even though it's not what the artist/designer intended.

    However, (and this is why I and the other member here introduced z depth) sometimes you don't want that behavior and want z to take precedence over order. Think Jesse's original issue where he wanted one character on same layer and same order (same "infrastructure" ).

    Actually, this is the point I'm making (and what you yourself put me on the correct path almost a year ago): The transparent/cutout shader does take order into account, but when using it, it trumps order.

    Yes, I would normally recommend using layer/order and the default shader as you recommend.

    Only for the case where you have characters coming wandering in terms of z depth. If you have such a game, like we did for Hero-U (an orthonormal action/adventure) and the character is wandering in and about 2.5D props - it is required (or more painfully, you can set the layer in code based on depth). Agreed though, if one is doing a normal side scroller, you certainly want to avoid the complexity.
     
  15. zombiegorilla

    zombiegorilla

    Moderator

    Joined:
    May 8, 2012
    Posts:
    9,052
    Again, it is working 100% correctly. In the first example you said:
    Order supersedes distance from camera. If you set it to the highest order it will always be in front of everything else in that layer. Again the render order (for Sprites) is Layer, Order, z-depth. The only time z is considered is if objects have the same Layer and Order.
    Actually his issue was just z-fighting with the diffuse shader, with a simple fix.
    Don't use layers for things like that.
    The whole purpose of layers (and order) is to permanently set the rendering order. You can programmatically switch layers and order, but that kind of defeats the purpose of using them in the first place. If you are using a orthogonal camera, there is no scale based on distance, so you can go nuts with the z. The benefit value of layers/order is isolate and set certain things. For example, I recently did a iso/exploration style game using the 2d functionality of Unity. Layers were Background, Stage, FX, GameUI, MenuUI. All the game play took place on the stage and I just bound the z to the y. Objects lower on the stage was in front of stuff higher (interleaving of grouped objects was handled by rounding the z). All the same order. You only need to use layers/order when it actually makes sense (like UI or fixed backgrounds). As you said changing layers is tedious and needlessly complex. Keep it simple.
     
  16. Chrispins

    Chrispins

    Joined:
    Dec 9, 2014
    Posts:
    15
    I am also struggling with this problem right now. I want my 2D game to have normal maps, but when I apply the material to my enemy sprites (which get spawned and overlap very frequently), the normal maps appear to merge and it gives the effect of the enemies appearing transparent.

    I don't want to mess with sorting layers because then I would have a million different sorting layers just for enemies alone, and I don't want to mess with the Z values because then it affects the distance from the point light source over time causing inconsistency.

    Unless there is some solution that anyone found, I think we need a checkbox for "Don't merge shaders with objects on same Z".

    EDIT: I did a little bit of testing and found out a few things. I just want to point out that this normal map artifact only appears when using lights other than directional lights, so this is not an intended "feature" what-so-ever
     
    Last edited: Jan 9, 2016
  17. Razziel

    Razziel

    Joined:
    Nov 1, 2016
    Posts:
    7
    Hi guys Unity 5.6.2 here. And i couldn't find a solution as well. The only that helped me to solve this was going into Graphics Settings / Camera Settings - Transparency sort mode. I set it to perspective, and it's kind of working.. I'm making a 2d game with normal maps.
     
    Gsbzin and Maletsky like this.
  18. Gsbzin

    Gsbzin

    Joined:
    Aug 19, 2017
    Posts:
    1
    I changed the render mode in the light to not important and solved the problem. :)
     
    vampur likes this.