Unity Community


Page 1 of 2 12 LastLast
Results 1 to 20 of 30

  1. Location
    Paris
    Posts
    3,730

    AlphaTesting unadvised in 1.1, removed in 2.0

    Hello,

    I've been recently in performance optimization problem that could concern everyone here : the alpha blending.

    Basically, it's just about rendering overlapping semi-transparent textured objects properly, with the right depth sorting.

    Actually, if we don't want pixels with alpha zero to hide what's behind them, we have to use AlphaTesting in one pass, and Blending in a second pass.

    But .... unfortunately, I just found that AlphaTest was a huge hit in performance. In fact, this 2 passes trick practically cut the global FPS by a half.

    I started a thread in the ShaderLab forums about it, feel free to join.

    Cheers


    edit : changed the title to fit the overall problem


  2. Location
    Paris
    Posts
    3,730
    Update : I found a way to make things as fast as with no Alpha Test, in a single pass.

    Just split all the translucent faces into separate objects in your 3D Tool.

    This way, Unity will be able to apply batching, and you will be able to use a single pass shader using only Blending, without Zwriting. Just because you are already doing Z sorting, manually.

    Advantage is it releases some processing power in your shader for other textures combines or other passes (or nothing if you want absolute speed).

    The only thing you have to take care of will be your overall batching cost, if too many splitted faces. You can manage it with the Profiler.

    One thing you could do to optimize it is grouping faces by depth level (unless your mesh has to be viewable from any side).

    Actually, this works great for me, pushed my frametime from 34 (alphatest 2-pass) to 24, without losing any visual feature.


  3. Location
    Paris
    Posts
    3,730
    A pretty useful sum-up of every possible sorting possibility.

    As we can see, it's an endless pain ...


  4. Location
    Paris
    Posts
    3,730
    Correction : you can use Zwrite with this method. Don't understand why it doesn't produce background killing on alpha zero pixels, but it doesn't.

    Well, packing all those experiences I made, I can conclude it would be possible for Unity to create an optional polygon sorting parameter, splitting all the translucent triangles in virtual gameobjects, and then batch them back.

    What I proceeded here and the results it gives is a clear proof that it would be at least 1.5 times faster than AlphaTest.

    Would save a lot of time for intensive alpha users, as we won't be forced to manually split our translucent objects in the 3D tool anymore.

    Alpha quads is the best way to create nice visual FX without having to use tons of polygons. For example, in a level I made, I used quads to display 2D textures of different islands in the background. Would have been much slower with real 3D models.



    Speed is the nerve of war for iphone, so alpha tricks are not an option for many of us.

    Would be awesome if iPhone Unity managed to have better support of alpha blending optimization, especially when the iPhone rendering pipeline is not designed for AlphaTesting, but Blending (see Apple articles I put in Shaderlab thread).

    I read some blurry things about BSP (Binary Space Partitioning Trees), and their efficiency in fast Z sorting.

    Here is an interesting topic about different sorting algorythms.


  5. Location
    Paris
    Posts
    3,730
    I'm surprised nobody feels somehow affected by this alpha translucency performance problem ...

  6. Unity tech writer

    Location
    Blackpool, United Kingdom
    Posts
    8,696
    This is good work, n0mad, but you've actually got a link in your first post that redirects people to the ShaderLab thread and you are getting some response there.
    I'm wired to the world... that's how I... know... everything...


  7. Location
    Paris
    Posts
    3,730
    Hello andee, and thank you for your attention ^^

    Yes, the Shaderlab has one participation (Thanks to the Shaderlab's ultra helpful Daniel Brauer).

    Over the 2 discussions here and at Shaderlab, the only problem sorted is the answer to why we can't have proper Z sorting with Alpha Blending (or translucency, in another word).

    But actually, the main, unresolved, undiscussed, and more deeply attached problem, is that with how Unity sorts Depth stuff, the overall Alpha management philosophy is pushing us toward the use of AlphaTest instead of Alpha Blending. It's a fact, and it's written in the Unity docs.

    But AlphaTesting is clearly unadvised on iPhone, as Apple stated (sorry for the underline, I'm not feeling quite understood on this problem). So I'm finding this more of a Unity-side issue than coder-side.
    What I'm presenting here is a dirty solution to not use AlphaTesting, but it's still dirty ...

    It would be cool to know Unity's position with that, as Alpha is a very critical feature for performance and polygon saving.
    Aras is stating not to use a lot of translucent objects in several threads, like other gamestudios don't. But sometimes, we can't !

    If we want to achieve high framerates with nice visuals and the fewest possible triangles, we are forced to abuse of translucency. And I don't even talk about 2D games, and how Alpha Blending is vital for them

    The only quite ignorant solution I found would be sorting depth by polygon, not objects, as manual polygon collapsing does work. But I'm not an expert in this, so I don't even know what I'm talking about

    Just to make it clear at the end, to display proper translucency and proper Depth with Unity, we have actually 2 solutions :
    - use AlphaTesting and see global FPS cut by an half.
    - split every translucent polygons into separate objects under the 3D tool, and let the Unity Zwrite & auto-batching do the rest. But what a mess when your scene have dozens and dozens of translucent objects !

    Both of those solutions aren't viable, long term.

    Would be really good to have a solid recognition of that problem from Unity staff, and how could it be managed by Unity in the future.


    Thank you again for your attention, it helps


  8. Location
    Paris
    Posts
    3,730
    The splitting faces method I mentionned above finally seems to be completely random with results ... Some huge levels manage translucent objects' depth properly, and some other don't, while they share the same shader ...

    So let me ask the ultimate question, because I'm actually in a serious need of answer.

    Fact : Apple don't recommand to use AlphaTest.

    ---> How can we correctly display overlapping translucent objects ?

    Do you guys have tips, or tricks ? Or does nobody ever use translucency on several depth levels ?


  9. Location
    Paris
    Posts
    3,730
    One week already since I posted the problem, and still no answer from Unity guys ... Maybe I should delete and recreate this thread in Unity Support forum for more visibility ?


    Seriously, I feel like nobody cares at all. Not about my case, but the whole alpha depth mess.
    Sorry for the forum spamming, but even if I sent a bug report 3 days ago that would probably resolve my problem, I don't think I would be the only one concerned by this. Performance and translucent Sprites are not an option on iPhone. So just need some clarification.

    Just a "yes" or "no" to a simple question : "Is it possible to display proper translucent overlapping objects without alphaTest ? If yes, how ?"

    A reminder about Apple recommandation concerning ES 1.1 :

    Quote Originally Posted by Apple
    Avoid Alpha Test and Discard

    If your application uses an alpha test in OpenGL ES 1.1 or the discard instruction in an OpenGL ES 2.0 fragment shader, some hardware depth-buffer optimizations must be disabled. In particular, this may require a fragment’s color to be calculated completely before being discarded.

    An alternative to using alpha test or discard to kill pixels is to use alpha blending with alpha forced to zero. This can be implemented by looking up an alpha value in a texture. This effectively eliminates any contribution to the framebuffer color while retaining the Z-buffer optimizations. This does change the value stored in the depth buffer.

    If you need to use alpha testing or a discard instruction, you should draw these objects separately in the scene after processing any geometry that does not require it. Place the discard instruction early in the fragment shader to avoid performing calculations whose results are unused.
    Now just look at Khronos statement about AlphaTest in ES 2.0 :

    Quote Originally Posted by Khronos
    One of the first (and toughest) decisions we made for OpenGL ES 2.0 was to break backward compatibility with ES 1.0 and 1.1. We decided to interpret the “avoid redundancy” rule to mean that anything that can be done in a shader should be removed from the fixed-functionality pipeline. That means that transformation, lighting, texturing, and fog calculation have been removed from the API. We even removed alpha test, since you can perform it in a fragment shader using discard.
    So first, Apple says we shouldn't use AlphaTest in OpenGL ES 1.1, and now Khronos is just removing it !

    We need an alternative, seriously. A clean one I mean, not something that "sometimes works, sometimes doesn't". Actually using Blending is precisely that versatile.
    And Discard fragment shading should not be the answer, as CG is not possible for OpenGL ES 1.1 !

    Please, check a box :

    [ ] You should pay more attention to forums, as we already explained how to solve that problem.
    [ ] Yes, we are aware of this problem, and working on an accessible solution.
    [ ] We are too busy for the next decade and won't be able to fulfill this request.
    [ ] Go on your own.




  10. Location
    Southampton UK
    Posts
    369
    Nomad,

    just saw this thread and I know very little about shaders. Our currently released game has a huge amount of sprites (we use SpriteManager heavily) and this shader:

    Code:  
    1. Shader "SpriteMan"
    2. {
    3.     Properties
    4.     {
    5.         _Color ("Color Tint", Color) = (1,1,1,1)
    6.         _MainTex ("Color (RGB) Alpha (A)", 2D) = "white"
    7.     }
    8.  
    9.     Category
    10.     {
    11.         ZWrite Off
    12.         Cull Back
    13.         Fog { Mode Off }
    14.         Blend SrcAlpha OneMinusSrcAlpha
    15.         Tags { "Queue" = "Transparent"}
    16.  
    17.         SubShader
    18.         {
    19.             Pass
    20.             {
    21.                 SetTexture [_MainTex]
    22.                 {
    23.                     ConstantColor [_Color]
    24.                     Combine Texture * Constant
    25.                 }
    26.             }
    27.         }
    28.     }
    29. }

    The performance we get is great but the one area we have not looked at is the shader but I am sure it can be optimised. One of the main problems we had was Z Fighting and to overcome this we just extended the distance between the sprites (its an overhead ortho camera). This fixed things but now reading your thread I am wondering if our shader also has two passes and if so how we can put this down to 1 pass and elimate the Z fighting.

    Maybe this is quite different that what you are discussing here I am not sure
    Steve


  11. Location
    Paris
    Posts
    3,730
    Hello imparare, thank you for your participation

    The shader you put here has 1 pass, yes.

    But actually, Z-fighting won't be resolved because you disabled Zwriting. And it's an endless hole, as if you enable it, you wil have artifacts with some sprites masking others, even if they are transparent.

    Actualy, for 2D games, it's not really a problem, because there are too few artifacts with ortho cams.
    But it's not safe either, as there could still be artifacts ...

    These artifacts are dramatically exposed with 3D cams. For example, in one of my scene, I got a 2D sprite composed with 6 moving quads. It's just a waitress coming from left to right in front of the camera, perfectly aligned on its Z axis.

    But depending on which portion it belongs in the cam viewport (left or right), her right arm will sometimes be put in front of the body, sometimes behind ...

    Overall it's completely random.

    For performance precise numbers, I had a frametime of 33 with AlphaTest, 2 pass, and 24 with Blending one pass.


  12. Location
    Southampton UK
    Posts
    369
    Even with ZWrite On my understanding was that if you have a big enough distance between the objects then that would resolve the issue ?

    thanks for the reply
    Steve


  13. Location
    Paris
    Posts
    3,730
    Yes, maybe, I didn't really dig this approach as it is not really "acceptable" : Some 3D objects are made of several translucent polygons, and therefore aren't able to match that distance.

    But in 2D, it could do the trick, yes.


  14. Posts
    1,361
    I read n0mad. I care, too.
    Jamie T. Bentley
    Technical Director
    The Binary Mill
    Facebook - Twitter


  15. Location
    Paris
    Posts
    3,730

  16. ReJ ReJ is offline

    Location
    Unity Technologies
    Posts
    355
    Quote Originally Posted by n0mad
    Just a "yes" or "no" to a simple question : "Is it possible to display proper translucent overlapping objects without alphaTest ? If yes, how ?"
    NO. It is an inherit problem of deph-buffer based rasterizers. There is no generic solution to that. Period.

    Quote Originally Posted by n0mad
    Additional cost of AlphaTest is PowerVR architecture specific. It has no additional cost on other platforms.
    Alpha Test is NOT deprecated in ES1.1 by any means. AlphaTest was removed from ES2.0 as redundant because discard in shader provides exactly the same functionality and virtually the same performance.

    Quote Originally Posted by n0mad
    We need an alternative, seriously. A clean one I mean, not something that "sometimes works, sometimes doesn't".
    As I said there is no generic solution only rules of thumb:
    • * in 3D - split your transparent objects into convex shapes - allow engine to sort them or use renderQueue if you know better
      * in 3D/2D (when you know exactly from what side your object will be always visible) - sort triangles manually in the Editor or just after the loading
      * in 2D - you must sort your sprites yourself (usually you just arrange them in layers to minimize sorting) or use particle system forcing engine to sort them for you.



    Automatic per-polygon sorting is NOT an option for an engine due to excessive CPU cost, if implemented in a generic way.


  17. Location
    Southampton UK
    Posts
    369
    ReJ said:

    in 2D - you must sort your sprites yourself (usually you just arrange them in layers to minimize sorting) or use particle system forcing engine to sort them for you.
    What is a particle system forcing engine ? (did a search but nothing found)

    thanks
    Steve


  18. Location
    Paris
    Posts
    3,730
    Good morning ReJ,

    thank you for your reply, I really appreciate.
    I changed the "deprecated" word in the title to ensure nobody reads bad info.
    But by deprecated I saw "we don't want you to use it, and it will be deleted in the next build".

    Quote Originally Posted by ReJ
    NO. It is an inherit problem of deph-buffer based rasterizers. There is no generic solution to that. Period.
    This is really bad news ...
    I may sound cocky, but I'm really shocked that in 2010 there is still no stable implementation of such a critical feature as Alpha translucency in any 3D engine.

    I mean basically ... Alpha is just "take the pixel under the one I'm rendering, and mix it with my alpha". And if the real problem is that primitives are culling each other, well ... I can't understand how there couldn't be an easy solution, like "take into account pixels that are already rendered when I render a new one".

    In pure 2D engines, like Flash, there is no problem at all, even with hundreds of overlapping translucent clips. They sort nicely. I don't see where putting a perspective parameter in this would mess the whole stuff.

    Quote Originally Posted by ReJ
    Additional cost of AlphaTest is PowerVR architecture specific. It has no additional cost on other platforms.
    Which could explain why Khronos doesn't care about that precise problem.

    But still, iPhone devs who use Alpha like me are really stuck in the mud with this.

    Quote Originally Posted by ReJ
    As I said there is no generic solution only rules of thumb:
    [list]
    * in 3D - split your transparent objects into convex shapes - allow engine to sort them or use renderQueue if you know better
    Ok, but isn't RenderQueue Shader wise ?
    Which means we can't use it properly, as we would be forced to put a different shader for each translucent triangle

    On the other hand, I tried to split objects into convex shapes, but there are still depth artifacts (submitted a bug report for that). So it is not safe.

    Quote Originally Posted by ReJ
    * in 3D/2D (when you know exactly from what side your object will be always visible) - sort triangles manually in the Editor or just after the loading
    Sorry, what type of Editor sorting do you mean ?
    (this 3D/2D would be my case, yes)

    `


    Quote Originally Posted by ReJ
    Automatic per-polygon sorting is NOT an option for an engine due to excessive CPU cost, if implemented in a generic way.
    I understand. Would there be a way to do this automation manually (no pun intended) ? By script ?


    Also, an important discovery :
    I made huge researches over the net about that problem. And I found numerous devs advising to use the function glTexEnv() in order to mask portions of primitives. This function uses a Blend mode too, so I believe it would be way much faster than AlphaTest. Principle is to blend the primitive with an alpha, turning it into a masked one, and then put the final texture on it.


    I didn't find this function in GL class. How could it be achieved ?


    And one last question : How could it be possible to write manually to the Z buffer, instead of letting Unity do the job ? This could resolve many problems, I think.



    Thank you ReJ for taking time to answer.


  19. Location
    Paris
    Posts
    3,730
    Up


    Sidenote : I found a way to maximize optimization with AlphaTest, by separating Alpha Objects and Opaque Objects into 2 distinct batched meshes, in my 3D Tool.
    Then giving them 2 materials, one for Alpha with Alpha Testing + Render=Transparent, and one other with no AlphaTest nor Blend + Render=Geometry (this RenderQueue is the most optimized, according to the docs).

    I'm pretty satisfied with the final FPS, as long as there aren't to many translucent triangles in my scene.

    But still, I don't believe this is the most optimized method.

    Questions in the previous post are still up to date, then


  20. Location
    The Netherlands
    Posts
    1,023
    Quote Originally Posted by n0mad
    I mean basically ... Alpha is just "take the pixel under the one I'm rendering, and mix it with my alpha". And if the real problem is that primitives are culling each other, well ... I can't understand how there couldn't be an easy solution, like "take into account pixels that are already rendered when I render a new one".
    It's not this simple.

    Imagine two windows: a red one (1,0,0,.4) and a darker green one (0,1,0,.9) on a black background. If we use the most common blending mode "SRC_ALPHA, ONE_MINUS_SRC_ALPHA" the result will be:
    (0,0,0) blend (1,0,0,.4) = .4*(1,0,0) + .6 * (0,0,0) = (.4,0,0)
    (.4,0,0) blend (0,1,0,.9) = .9*(0,1,0) + .1 * (.4,0,0) = (.04,0.9,0) (bright green)

    However, if the green window happens to be provided to the graphics card first:

    (0,0,0) blend (0,1,0,.9) = .9*(0,1,0) + .1*(0,0,0) = (0,.9,0)
    (0,.9,0) blend (1,0,0,.4) = .4*(1,0,0) + .6*(0,.9,0) = (.4,0.54,0) (dark yellow/brown-ish)

    These two colors differ significantly and just because
    we rendered the two windows in different orders. This has nothing to do with the z-buffer: it is the rendering order which determines the final color-value of a pixel. In order to get a correct final blending color, you need to make sure that every single translucent triangle is rendered back-to-front (and that every pair of intersecting translucent triangles is split up in non-intersecting triangles).

    This limitation is rooted in the graphics hardware, which is why you will not find a feasible, generic solution to this problem anywhere.

    This wiki entry explains more thoroughly:
    http://www.opengl.org/wiki/Transparency_Sorting

Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •