Search Unity

Many rendering precision issues after Unity 5 "upgrade"

Discussion in 'General Graphics' started by Tallek, Jun 18, 2015.

  1. Tallek

    Tallek

    Joined:
    Apr 21, 2014
    Posts:
    34
    I've been working on porting a flight sim game developed in Unity 4 to Unity 5 / 5.1. I've been encountering numerous rendering issues, starting to feel like I'm going crazy here. Feels like Unity just decided to cut the precision of floats in half... Everything worked fantastic in Unity 4, no problems.

    Seeing lots of z-fighting between parts of the planes. Seeing a lot of shadow flickering on the surface of various objects. Appears to be surfaces casting shadows upon themselves, then z-fighting with themselves. This starts to show itself around 1000 - 3000 units from the origin, getting progressively worse. The z-fighting and shadow flickering seems to be mostly mitigated by implementing a floating origin (which was not required before), however I'm still seeing serious shadow flickering on a few (but not all) Android devices. Can't seem to fix that issue on Android no matter what, short of disabling shadows.

    A large water plane (60,000 x 60,000) is getting cut off by the near clip plane of a camera (set at 0.7) on a Galaxy Tab, but works fine on most devices. Dropping the size of the plane fixes the issue but visually makes it useless as a water plane.

    Also seeing an issue where the seam between our near and far cameras leaves a noticeable gap in the geometry, seeming to get much worse the further away you get from the origin. The near camera's far clip plane is set to the same value as the near clip plane for the far camera. If the clip planes overlap, I think it resolves the issue, yet it worked fine as is in Unity 4. I can't remember the exact numbers but i believe the overlap had to be non-trivial, a 0.1 overlap didn't always fix it if I remember correctly.

    It has been costing me a lot of work finding, and trying to fix these issues. Am I crazy here or is anybody else seeing similar things? Did I do something wrong somewhere along the lines? Are these bugs, or just the new way of life in Unity 5? I've tried toggling every Unity setting I can find, but no luck. I submitted a bug report about the z-fighting/shadows as distance from the origin increases and got a response back.. "This is a known issue and for now it is not going to be fixed." That's not cool... They suggested a floating origin. Part of me wonders if I just got a canned response back because obviously a floating origin is required if you move too far away - not sure if they realize how little distance it takes now versus Unity 4. Also submitted a bug on the Android shadow issues but have yet to hear back.

    Should I just keep on going and trying to come up with work-arounds for these issues, or would it be too much to hope for some patch fixes in the not too distant future?

    Thanks.


    EDIT: Here are some screenshots/videos of some of the issues

    Shadow flickering


    Shadow flickering / z-fighting


    Camera seam issue


    Android shadow issue

     
    Last edited: Jun 18, 2015
  2. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    Screenshots would help here... Just saying. :D
     
  3. Tallek

    Tallek

    Joined:
    Apr 21, 2014
    Posts:
    34
    Yeah, sorry... My bad. I've updated the original post with some screenshots / videos of some of the issues.
     
  4. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    You need to report this as a bug using the bug reporter tool. It does look like a bug that will not be resolved on the forum.
     
  5. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    I agree with hippocoder here. On top of this, I haven't seen such unusual ways of rendering the scene before... :D
     
  6. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    Actually, on second thought, is graphics emulation on? that might be stuffing things... :D
     
  7. Tallek

    Tallek

    Joined:
    Apr 21, 2014
    Posts:
    34
    No graphics emulation. The first couple plane videos were taken on a windows build and the two android screenshots were taken on the actual android devices.

    I've submitted another bug, this one related to the clipping of large scale planes on some android devices.

    Been working more on my floating origin, which seems to help the z-fighting and shadow-flickering on the plane itself, but it just shifts the problem around. Now I see the same sort of z-fighting issues with the runways & water on the terrain. :-(
     
  8. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    This truly is weird. If you kept a backup, I recommend falling back to 5.0.2 for the time being, since 5.1 is REALLY buggy atm... :(
     
  9. Noisecrime

    Noisecrime

    Joined:
    Apr 7, 2010
    Posts:
    2,054
    Are you aware that shadows from lights now have two offset parameters, the old 'bias' value and a new 'Normal Bias'? In my experience the new 'Normal Bias' was actually quite annoying since it created gaps between shadows, but I believe it was added to address self-shadowing issues, which looks like it could be part of the problem in some of your screenshots? So maybe something did change in 5.x ad that all you need is to increase 'Normal Bias' a bit?
     
  10. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    Could be his issue, I found the issue was only visible though if you have the bias at 4 or something. ;) The default setting would be fine otherwise. Unless, of course, his world objects are VERY small... WAIT A MINUTE!

    @Tallek: What is your world scale?! I completely forgot to ask that; if it's too small, that could be stuffing things!!! :D
     
    Noisecrime likes this.
  11. Tallek

    Tallek

    Joined:
    Apr 21, 2014
    Posts:
    34
    I was not aware, thanks for the heads up. I did some tweaking with this and still can't get things looking right. Even with values maxed out, while helping quite a bit, some of the same issues still occur. Raising the normal bias is resulting in some ugly shadow gaps though, and raising the regular bias setting results in a loss of shadows in most cases. A bit of a no-win scenario...

    The world is rather large, which I'm sure isn't helping things, yet everything worked great in Unity 4.6. I believe our terrain is 15,000 x 15,000 units.
     
  12. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    That is MASSIVE! So we can probably rule out subtle errors caused by small flating point numbers...

    ...But a massive drawing distance, (higher than about 4000) can cause issues, especially on mobile. I think you already tried this, but try lowering the draw distance on your cameras and see what happens. (I am aware of your dual-camera setup, BTW. ;))
     
  13. Noisecrime

    Noisecrime

    Joined:
    Apr 7, 2010
    Posts:
    2,054
    Coincidentally yesterday I downloaded the new 'Blacksmith - Unique Character Shadows' asset provided by Unity ( its aimed at improving shadows on very near objects/characters, whilst having a large render/shadow distance - 3000 units) in order to check out their code. The first thing I noticed in the test scene on the distant models were the same shadowing flashing and graphical artifacts that you seem to be suffering from. I'd seen both of these issues before, but generally the bias settings could be used to fix them when shadow distance was kept to reasonable values ( e.g. < 200 units ).

    Now in my opinion the majority of the issues I see are solely due to self-shadowing and the issue of precision at greater distances this causes. So I surmised that the obvious solution is that bias values should be mapped/scaled by distance from the camera. That way the bias starts small in the foreground and grow larger towards the background. In fact I'm really surprised this wasn't done as default for either the old or new bias techniques, since as you've discovered, increasing the bias can help resolve problems at far distance, but then cause there own problems ( offsets and gaps ) in the near distance. So by making the bias scale with distance would seem to be a no-brainer to addressing this tricky issue.

    Anyway long story short I messed around with Unity's ShadowCaster Bias shader code ( found in UnityCG.cginc) so it would sort of scale by distance and for my test scene this has greatly improved things. There is still some graphical artifacts, but they are consistent ( i.e. don't flash) and more importantly mostly remove the self-shadowing issues.

    Of course it should be mentioned that at large distances I've probably totally removed self-shadowing due to the increase in bias, or maybe with more detailed models ( using cubes as test currently) you might find artifacts again, but overall I'd guess this is preferable to either having no shadows at distance or the current artifacts we have.

    Alas i'm unsure if these experiments would really help in your case. I think you're world size is rather large and can't really ever see shadows working at such distances. I'm kind of surprised it apparently worked fine back in Unity 4.x. I would be very interested in double checking this, as I wonder if you happened upon some combination of settings that worked, which have either been reset or no longer apply in Unity 5.x. Indeed I think it would be useful to have a small testbed of your specific issues to look at. Perhaps this testbed should be built in 4.x and then a copy upgraded to 5.x just to be sure everything is consistent. For example a project that includes the multi-camera set up and an environment that is representative of the size of the models/objects you are rendering, but no gameplay, no fancy effects or materials, small overall project/file size etc.

    Anyway i'm going to try and do so more testing over the weekend of scaling the bias by distance and if it pans out I'll see if anyone at UT is interested in taking a look.

    I've attached an image showing various screenshots and settings to illustrate the 'benefit' of scaling bias by depth/distance. However I must stress that this has only been tested on the most basic of scenes, so I cannot be sure that it doesn't cause more problems elsewhere or that it works effectively in all cases.
     

    Attached Files:

    Last edited: Jun 27, 2015
  14. Tallek

    Tallek

    Joined:
    Apr 21, 2014
    Posts:
    34
    Scaling bias by distance sounds like a great idea, however I am not sure it will help in my scenario. Our shadow distance is actually quite small... 70 I believe. Don't have to zoom out too far to make shadows disappear entirely. The one major shadowing issue I'm still fighting with that only occurs on some Android devices, shows up at a fairly close distance to the plane so the more I adjust the bias to make the shadow artifacts disappear, the more messed up the actual shadows look at that same distance.

    As far as test projects go, I threw this together for a Unity bug report: https://drive.google.com/file/d/0B1er80zRDOXTdFZxN3oxZUxGZkk/view?usp=sharing. In that zip file are two scenes that should be set up the same, one in Unity 4 and one in Unity 5. Nothing much more than a rotating cube, camera, and directional light. The camera has a script on it to adjust the distance from the origin. Crank it up to 10,000 on Unity 4, everything looks great. By 3,000 in Unity 5, the issue is noticeable. By 5,000, it is downright terrible.

    The response from that particular bug report was as follows:
    "This is a known issue and for now it is not going to be fixed. This problem appears mainly because of float precision. As a workaround you can try changing all scene objects position relative to world origin so it would be closer to it."

    I've finally got a floating origin implemented, which did seem to mostly solve those issues, but it was a non-trivial amount of work and did create some new problems to deal with. Still fighting with that Android shadow issue shown in the last couple screenshots of the original post. Our current workaround is providing a shadow quality setting that does not allow the plane to receive shadows (and turning of shadow casting on the runway, which should never have been enabled in the first place). The shadow of the plane on the runway still looks bad though.

    I did get a response from Unity on that Android shadow bug...
    "We did some more investigation regarding this issue and it appears that the problem that you see different results in a device is this: the Mali GPU (that's inside Galaxy S6) can use 16-bit floating point precision whenever possible for a performance boost, whereas on desktop everything is 32-bit floating point precision all the time. The issue is not fixable on our end, but the very simple workaround is to increase shadow bias in the light inspector, once that is done, the problem disappears."

    Doesn't really explain why it worked fine on Unity 4 though...

    For my Camera seam issue, I just overlapped the clip planes by a non-trivial amount. Seemed to fix the issue, though it bothers me that it was unnecessary in U4. I think the other remaining issue I have yet to solve is the clip plane with the water plane. Yes it is very large, but it did work fine in Unity 4. The plane is getting clipped long before the camera's near clip plane. Decreasing the size of the plane does seem to help, but it cannot be completely fixed until the water plane is far far to small to actually work as a water plane for us. Have yet to hear back on my bug report on that one, don't have a lot of hope though...

    Just seems like I've encountered quite a few issues with U5 related to float precision that never seemed to cause a problem in U4...
     
  15. Noisecrime

    Noisecrime

    Joined:
    Apr 7, 2010
    Posts:
    2,054
    Thanks for taking the time to outline the various issues. I see you posted much of it before but its useful to have it in one post and to re-assert the nature of the issue. That being the problem is not necessarily overall distance, but relative distance from the world origin due to precision errors. The supplied example project is a perfect example of the failure that has occurred between U4 and U5.

    Whilst i'm sure most people understand there are going to be issues with float precision,I wish Unity had responded better here to explain why precision has become such a problem with the move to U5. You example project clearly illustrates that in U4 there are no issues with shadows or self-shadowing even when displaced up to 10k units away. Yet very troubling I can see shadow issues as close as 2k units in U5 and at 10k units its unusable! Whats worse is its not just an issue with self-shadowing, shadows cast onto other objects become increasingly jittery at larger displacements from the origin too, again making it unusable.

    I'm somewhat surprised as to how other developers have not seen this. I don't consider 2k-10k to be excessively large world dimensions, but I guess many simple games simply never get that large. Combined with the fact that the self-shadow flicker progressively gets worse beyond around 2k units from the world origin ( though it may even happen earlier) does make it a bit hard to notice. I wonder if more developers are going to run into this over time?

    What really annoys me is how Unity have decided this will not be fixed, yet give no reason as to why or what has changed to cause this. The fact that U4 has no such problems suggests to me that either something has gone horribly wrong somewhere or that there changes to the shadow maps in U5 are simply no longer able to deliver expected results when displaced from the world origin. In which case I would have thought that is a strong recommendation for them to have ensure developers could fall back to the old shadow mapping method.

    Having to implement a floating origin for environments/maps that are > 2k would seem to me to be immensely stupid and limiting. If the shadow mapping technique now used is that bad, then I would expect UT to implement a floating origin feature to fix this.

    I wonder if its possible to re-create the shadow mapping seen in U4 in U5. We have ( I think ) all the shader code, but I don't think its possible to patch into the shadow feature code of the engine, meaning it would have to be accomplished via say command buffers or some other means. Might be an interesting side project some time.

    One point. I noticed that you had rather small near place values for your camera at 0.1 units. Although technically thats not really small, especially if using 1 unit = 1 meter, it is problematic since much of the depth precision will be biased to the near place, almost regardless of how close your far plane is. Anyway, setting the near plane to 0.3 address most of the shadowing issues up to 4-6k units displaced from origin and greatly reduces the problem. See LearningToLoveYourZbuffer for more information .

    So obviously there is an issue of precision with the camera, but that is only half the story since the shadow map itself is storing depth so there must be precision issues there too. Wouldn't be surprised to learn its so combination of the two that leads to the worse shadowing artifacts.


    Are you saying the project built for Android using U4 does not suffer the same precision issue on this device when compared to U5? If so that would suggest that its not purely a device issue, but a combination of that and whatever changes were made to Unity shadows.


    I guess overall there isn't much to say. I've not looked into the split camera issue you have, but glad you were able to get a workaround, but these shadowing issues seem bad enough that Unity really should be more pro-active in addressing or at least offer an alternative U4 method. You might not get as nice shadows in U4 but at least thery were functional at reasonable distances from the world origin.
     
    Last edited: Jun 29, 2015
  16. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    Well, I must have solved both on my mobile game by simply using my own system, because I haven't even tried mobile shadows yet on 5.x! (Well, I tell a lie; once I had 5.x running, I migrated my shadow system to a custom built one so tegra chips could use it)

    EDIT:
    @Noisecrime: That dynamic shadow bias sounds interesting. :) Could you give it to us? :D
     
  17. Noisecrime

    Noisecrime

    Joined:
    Apr 7, 2010
    Posts:
    2,054
    Interesting, could you provide some broad strokes as to how you created and integrated your own system? I do feel that perhaps the easiest solution here is to somehow restore the old U4 shadow mapping method, even if its at the expense of losing the much nicer shadowing U5 provides.

    Um, OK. Its rather simple actually, but also rather embarrassing on many levels as i've never really played with shadows or clipspace much before. This means I have some general awareness of issues and differences between opengl/DirectX, but not exact specifics or experience. Most of my decisions were simply made on getting something up and running with the idea to improve and increase robustness later.

    I've included the hardcoded change to cginc file below, but also attached the test project i'm using, which implements a globalVector to pass in the values. All very much WIP.

    Notes & Issues
    • ClipSpace - Pretty sure the z component here is different between opengl (-1 to 1) vs DirectX (0 to 1), but not looked into it.
    • Addition NOT Scaling - Though I talked about scaling the Bias, in the end I went with a method that simply adds to the bias value. Not entirely sure why I did this now or whether its better.
    • Scaling curve - I used smoothstep as I was lazy and since it bounds lower/upper to 0 and 1. Was thinking I needed a curve here since the depthBuffer is non-linear, but now I'm not so sure. Maybe linear would work just as well, maybe at this point z component is still linear. More research needed.
    • Shaders - Since its changing UnityCG.cginc, you have to be careful with other shaders. In my experience it never seems to work with built-in shaders or is at least temperamental, so I tend to import then rename any built-in shaders I need to use, to ensure they reflect the changes to cginc files.
    • Normal Bias - I've only applied the scaling to the new Normal Bias calculation. It may be that the same thing should be done to Bias or even only to Bias ( see UnityApplyLinearShadowBias in UnityCG.cginc).
    • HardCoded - Currently the values are hardcoded in smoothstep. These can easily be moved into a GlobalVector and through a script update them in real-time. The values currently are 0.3 lower bound, i.e. normalized z values below this threshold become zero. 1.0 is upper bound, and 32 is an arbitary scaling value.

    Remember I changed this to add not scale/multiply the original 'Normal Bias' value. So if the scaling value is 0, then the shadowCaster method will produce the same results as those if you hadn't changed the code.

    Again I want to point out that i've only performed minimal testing on this and only on Windows. Therefore I have no idea if this is simply 'moving' the issues somewhere else, or whether the results in more complex scenes are still usable. Overall though I feel scaling the biases should work to a decent degree.

    Overall I'm sure there are much better ways of implementing this feature. While multiplying the bias value might be better, I thinking that maybe a mapping function providing lower and upper limits to the bias value and using some form of user controlled curve might be more appropriate, but that depends on whether the precision issues are linear or non-linear.

    Code from UnityCG.cginc
    Code (CSharp):
    1. float4 UnityClipSpaceShadowCasterPos(float3 vertex, float3 normal)
    2. {
    3.     float4 clipPos;
    4.  
    5.     // Important to match MVP transform precision exactly while rendering
    6.     // into the depth texture, so branch on normal bias being zero.
    7.     if (unity_LightShadowBias.z != 0.0)
    8.     {    
    9.         float finalShadowBias = unity_LightShadowBias.z;
    10.  
    11.         // NC - Clip Space
    12.         float4 posMVP         = mul(UNITY_MATRIX_MVP, float4(vertex,1));
    13.         float distBias             = smoothstep(0.3, 1, (posMVP.z/posMVP.w) ) * 32;
    14.         finalShadowBias     += distBias;
    15.         // END    
    16.    
    17.         float3 wPos = mul(_Object2World, float4(vertex,1)).xyz;
    18.         float3 wNormal = UnityObjectToWorldNormal(normal);
    19.         float3 wLight = normalize(UnityWorldSpaceLightDir(wPos));
    20.  
    21.         // apply normal offset bias (inset position along the normal)
    22.         // bias needs to be scaled by sine between normal and light direction
    23.         // (http://the-witness.net/news/2013/09/shadow-mapping-summary-part-1/)
    24.         //
    25.         // unity_LightShadowBias.z contains user-specified normal offset amount
    26.         // scaled by world space texel size.
    27.  
    28.         float shadowCos = dot(wNormal, wLight);
    29.         float shadowSine = sqrt(1-shadowCos*shadowCos);
    30.         // float normalBias = unity_LightShadowBias.z * shadowSine; // Original code
    31.         float normalBias = finalShadowBias * shadowSine;
    32.  
    33.         wPos -= wNormal * normalBias;
    34.  
    35.         clipPos = mul(UNITY_MATRIX_VP, float4(wPos,1));
    36.     }
    37.     else
    38.     {
    39.         clipPos = mul(UNITY_MATRIX_MVP, float4(vertex,1));
    40.     }
    41.     return clipPos;
    42. }
     

    Attached Files:

    Last edited: Jun 29, 2015
  18. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    Well, the integration was made easier by the fact that these days, I ALWAYS hard-code my shaders rather than using surface shaders! I have full control of the code optimization this way, and it does pay off on mobile. :)

    I also looked at some of the code in this thread for some ideas. ;) (This link here:http://forum.unity3d.com/threads/unity-tegra-shadows.167686/) What I basically do is use a separate camera for the shadows, and have that camera set it's position and rotation every frame so that it's the same pos as the camera, but the rotation of the light. It means that in the shader, I can add my own distance fade to the shadow, and I can also crank the resolution up fairly high! (I can also apply 2-tap shadow filtering on the shadows!)

    Only caveat atm is that the depth test went haywire at some point, because sometimes, the shadows flicker then vanish at certain angles... :D Probably an issue to do with where the depths being projected.

    And restoring unity 4's shadows? That's actually hard-coded into the engine itself, and probably not an easy option, since the shader bits are just interfaces to unity's internal shadow rendering engine. :cool:
     
    Noisecrime likes this.
  19. Noisecrime

    Noisecrime

    Joined:
    Apr 7, 2010
    Posts:
    2,054
    Thanks for the link, i'll check it out.

    That is a little disheartening to hear. Are you relying on any part of Unity's own shadow pipeline, could it be some change in U5 has resulted in this issue?

    Restore was probably the wrong word, recreate would be better. Essentially the aim being to recapture the robustness of the old U4 shadowing method.
     
  20. DivergenceOnline

    DivergenceOnline

    Joined:
    Apr 19, 2015
    Posts:
    244
    Speaking from experience as a Unity 4 Pro user, this problem was just as prevalent as close as 20,000m from the origin of the scene, which i found unacceptable. That basically makes it impossible to have anything resembling a "large" game in unity such as a [true] mmo or a flight simulator. So what I did to fix it was actually to use the cginc posted above that was intended for unity 5 and simultaneously boosted the minimum clipping plane from 0.2 to 1. This completely fixed the issue for me, so I'm posting it here incase anyone else has the same issue.