Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Transparency and tree billboards

Discussion in 'Shaders' started by Kragh, Dec 7, 2009.

  1. Kragh

    Kragh

    Joined:
    Jan 22, 2008
    Posts:
    657
    I have a problem with sorting of transparent objects on terrains. I have no idea how to get objects to sort correctly with the billboards. They will either be behind the collection of trees, or en front (depending on how I make the shader). Only the cutout shaders can avoid this, but those arent really good for my pupose. How do I force the render queue to be correct?
     
  2. shawn

    shawn

    Unity Technologies

    Joined:
    Aug 4, 2007
    Posts:
    552
    Last edited by a moderator: Dec 3, 2015
    twobob likes this.
  3. Kragh

    Kragh

    Joined:
    Jan 22, 2008
    Posts:
    657
    Thx for the info, but it doesn't really solve my problem :wink:. As I stated, my object will go either in front or behind, depending on what I write in my shader, which isn't good enough.
    I need my object to sort correctly, not to be eiother in front or behind. Right now I can't make an object be in a forest, as it can't sort correctly. But you say transparent-100. Is that for all trees? If that's so, then I don't see any possibility of getting a transparent (non alpha tested) object in between trees. Is that correct?
     
  4. multivac

    multivac

    Joined:
    Oct 27, 2009
    Posts:
    133
    there's a shader under Nature called Vegetation-TwopassUnlit,it seems like it might have been made for this kind of thing or provide a starting point for you.
     
  5. Kragh

    Kragh

    Joined:
    Jan 22, 2008
    Posts:
    657
    No, it doesn't do it correctly. The only thing that will sort correctly are the first pass, which is treated as a solid object. The second pass which does the gradient alpha will sort in front of the tree billboards. But thanks anyways :)
     
  6. shawn

    shawn

    Unity Technologies

    Joined:
    Aug 4, 2007
    Posts:
    552
    You're running into the typical "alpha blended materials don't sort properly problem". This is just the nature of alpha blended objects. The graphics card is unable to know how to sort alpha blended pixels.

    In the abstract, you have to manually tell the renderer when to render each alpha-blended object. There's two ways of doing this in Unity.

    One solution is set the render queue inside the shader. This is the easier solution, but isn't dynamic.

    The second solution is to manually render the tris in the order you want them to be rendered. This requires combining all of the alpha-blended objects into a single mesh and then sorting the tris to render from back to front. This is a pain the ass and really only works if you can cheat for sorting the tris, otherwise it takes to long to rebuild the mesh every frame. Plus there's no easy way to really get at the billboards from the terrain and render them yourself.

    Unfortunately, there's no good way to do what you want to do. This is common problem that all game engines/developers have to deal with and work around. If you look closely at other games in the world you'll see that there are many clever solutions to this problem, but they are almost always unique to the specific game and can almost never be generalized. Your best bet is to think of some clever way to get the effect you want without using alpha-blended materials.
     
    twobob likes this.
  7. Kragh

    Kragh

    Joined:
    Jan 22, 2008
    Posts:
    657
    Hey Shawn :) Thanks for all your info, I like that you take my problem seriously enough to post such a reply!
    But... I know all about the issue. And I have worked out tons of individual solutions through my many years in the business. Only now have I begun to make my own shaders as well.
    The problem here is not so much the very nature of sorting alpha blended objects. It's how I can't seem to stick an object in between the trees manually. If I knew that the trees rendered with queues from Transparency-x and forward (x + the number of trees), I would have a mean to find a clever way of putting the object into the right place in this queue. But as all trees have the render queue of transparency-100, I can't do anything.

    Other than what I did... :D I ended up using the ideas "multivac" guided me to, using a two pass system. As my trasparent areas of the object are entirely defined by the distance to the obejct (meaning I don't use a transparency map, but calculate transp. on the fly), I can live with the transparent pass creating sorting issues. So now I Render all opaque areas without alpha blending, solving the sorting issue, and then I only have it on the transparent areas, which will always be near me, and therefore always should be rendered after the trees. So... it works perfectly. Just have to live with an extra pass.

    Thanks for the info anyways :!:
     
  8. shawn

    shawn

    Unity Technologies

    Joined:
    Aug 4, 2007
    Posts:
    552
    Awesome! :)

    Always hard to gauge people's background knowledge on the forums, so I tend to just keep things rather abstract and simple.

    Anyways, I'm guessing that all the billboarded trees are on the same rendering queue because they do some run time mesh combining stuff? Not every billboard is a draw call, so it's possible to be in a situation where you want to place an object between two billboarded trees that are actually drawn with the same mesh, so there's no real way to change their rendering queue with relation to your object.
     
  9. ChrisBolton

    ChrisBolton

    Joined:
    Nov 19, 2008
    Posts:
    41
    Could you use a z-depth pass to sort the tri's? Im not a coder so it may never work, but if you could some how link the greyscale pixels to the tris, i.e. white is infront, 128 grey is middle, black is behind, that may help you fit an object inbetween, as it wil work the same way, also any dynamic objects should work that way too solong as you update your zdepth every frame is thats possible?
     
  10. fuzail.india

    fuzail.india

    Joined:
    Jul 9, 2012
    Posts:
    2
    I think this might help out.
    Calculate the distance of object from camera and use the distance to render the object. I think this might solve your problem.
    i am attaching the code to calculate the distance from camera.
    var object2 : GameObject;
    var m_camera : Camera;
    function Update () {
    var distance = Vector3.Distance(m_camera.transform.position, object2.transform.position);
    }
     
  11. fuzail.india

    fuzail.india

    Joined:
    Jul 9, 2012
    Posts:
    2
    #pragma strict
    var object : GameObject[];
    var m_camera : Camera;


    function Update () {
    var d :float[];
    d= new float[7];
    var i :int;
    var j :int;
    var p :int = 3000;
    var t : int = 0;

    d[0] = Vector3.Distance(m_camera.transform.position, object[0].transform.position);
    object[0].renderer.material.renderQueue=p;
    for(i=1;i<7;i++)
    {
    d = Vector3.Distance(m_camera.transform.position, object.transform.position);
    p=p+1000;
    object.renderer.material.renderQueue=p;
    }
    for(i=1;i<6;i++)
    { //p=p+1000;
    //object.renderer.sharedMaterial.renderQueue=p;
    //d = Vector3.Distance(m_camera.transform.position, object.transform.position);
    //object.renderer.sharedMaterial.renderQueue=p;
    for(j=i+1;j<7;j++)
    {
    if(d<d[j])
    {
    t=object.renderer.material.renderQueue;

    object.renderer.material.renderQueue=object[j].renderer.material.renderQueue;
    object[j].renderer.material.renderQueue=t;
    }
    }
    Debug.Log(object[5].renderer.material.renderQueue);

    }


    //Debug.Log(d[j]);


    /*var t : int = 0;

    for( i=0;i<6;i++)
    {
    for( j=0;j<7;j++)
    {
    if(d<d[j])
    {
    Debug.Log(object.transform.name);

    t = object.renderer.sharedMaterial.renderQueue;
    object.renderer.sharedMaterial.renderQueue = object[j].renderer.sharedMaterial.renderQueue;
    object[j].renderer.sharedMaterial.renderQueue = t;
    }
    else
    {Debug.Log(object[j].transform.name);
    object[j].renderer.sharedMaterial.renderQueue = p;
    Debug.Log(d[j]);

    for( i=0;i<6;i++)
    {
    Debug.Log(object.renderer.sharedMaterial.renderQueue);
    }
    }
    }

    }*/
    //object[4].renderer.material.renderQueue=15000;
    }
     
  12. Kragh

    Kragh

    Joined:
    Jan 22, 2008
    Posts:
    657
    Thank you very much for your effort, fuzail.india!
    This is a very old thread, though (almost three years old), and I'm not working on this anymore. I'm sure, though, the problem persist in newer versions of Unity (I don't think the terrain system is being updated anymore), and it seems your script is just a manual way of sorting objects in relation the their distance to the camera. But this is done by Unity automatically, before the objects are being sent to the graphics card, so you aren't really doing something ekstra.

    The problem mentioned in this thread was a completely different type, where a whole group of trees in the terrain system, will be passed to the graphics card's renderQueue in one single batch, and because of that, transparent objects can't be stuck in between the trees. They will either go in front, or behind the whole collection. If you want objects in between, they either have to be solid (and render to the z-.buffer), or they have to have a cut out pass/alpha test pass (which again will render in the z-buffer, based on the transparency level)
    I did the last, and it worked fine for my use.

    But again, even if your solution won't work here, I thank you very much for taking the time!
     
  13. graphicDNA

    graphicDNA

    Joined:
    Jun 26, 2017
    Posts:
    47