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

Using Tree gameobjects vs Unity's built in system

Discussion in 'Scripting' started by jc_lvngstn, May 22, 2013.

  1. jc_lvngstn

    jc_lvngstn

    Joined:
    Jul 19, 2006
    Posts:
    1,508
    I accidentally started a thread on this, but in the support forum. I meant for it to be here.

    In tests where I am mostly displaying full meshes (not billboards), the Unity tree system appears to be slower than just using tree gameobjects. This is very interesting to me personally, as my project makes heavy use of trees.

    I'm going to create a demo project, that allows comparison between the built in tree system vs just using gameobjects, so there can be hard numbers. I may end up providing an asset that packages helpful features, like billboard creation and such. Your assistance would be helpful :)

    Using trees from prefabs:

    Pros:
    You get rotation.
    You get individual tree colliders, instead of the tree colliders being combined with the terrain. You know exactly which tree you are interacting with.
    You can use the LOD system, to have more control over tree detail. High detail trees, then lower ones.
    Unity created trees can be used also.
    Much easier to work with if your project modifies trees or terrain. Modifying trees has doesn't require unity to recreate the terrain and its collider.
    Supports batching for very low detail trees.

    Cons:
    Have to have some way to create a billboard of the tree (if you want them).
    You see each individual tree instance in the hierarchy...you'd want to parent them to a "Tree" parent so they don't clutter everything.
    Creating them all doesn't seem as fast as Unity's (need to verify)
    Non-unity trees can have shadows and bumps. But if you want wind ALSO, you will need special shaders.

    Using Unity's system:

    Pros:
    You don't have to manage LODs or anything...it automatically creates the billboard, at the correct angle of view.
    Built in placement/painting tools.
    You don't actually see all of the individual tree instances.
    Appears to create the trees very quickly.

    Cons:
    No rotation. If you want a large number of trees, this looks bad or it requires you to create multiple models.
    The billboards get badly tilted when the camera tilts up and down, looks pretty bad if the billboards are somewhat close.
    Only two levels of detail...full mesh and billboard.
    Trees and their colliders are merged with the terrain. So you need hackish code if you want to interact with the trees, and it's not always possible to know exactly which tree you are interacting with.
    If your project modifies terrain or trees, unity has to update the whole batch. This causes hitches in gameplay for somewhat complex terrains.

    Other thoughts:

    I'm not sure if the Unity tree system batches low detail trees, need to see if I can verify this.
    I need to see if I can get a shader that allows bumping, shadows, AND wind. This works for Unity created trees, but I'm not having luck getting this on "homemade" trees.
    I have a very simple script to create individual trees from the trees painted on a terrain. So you use Unity's built in tools to place them, then run the script and there are your individual ones.
    If it is slower to create the trees from prefabs than Unity's system, I'm curious to see how much.

    I need a script that can automatically create a billboard from a tree. We might even get fancy and get one that can do a tree from different angles, but that's going to be a little more complicated. Storing different tree billboards in an atlas, which means a tradeoff for billboard quality. It might not really be worth it when billboards are pretty far off.

    I don't see how to set LOD distances in the Unity scripting guide. I would have thought you could set the distance for each LOD stage, but I've done some quick searching and it looks somewhat complicated and confusing to setup via scripts. If anyone could shed some light on this...

    Anyway...any thoughts or suggestions, corrections are welcome.
     
    Baldinoboy likes this.
  2. virror

    virror

    Joined:
    Feb 3, 2012
    Posts:
    2,963
    You dont set LOD distance for the lod group, you set a relative screen hight instead, just look at the reference guide on how its done.

    LOD constructor: static function LOD (screenRelativeTransitionHeight : float, renderers : Renderer[]) : LOD
    And in the example you can see how they use it: lods = new LOD(1.0F / (i + 1), renderers);
    They set the relative screen hight using the formula "1.0F / (i + 1)" were i is the current LOD, so a low LOD gets a higher number and will switch closer to the screen than a higher LOD.

    Maybe this was not what you asked for, but anyways : D

    Edit: Btw, if there was some external software that can make LODs and/or billboards that would also help.
     
  3. jc_lvngstn

    jc_lvngstn

    Joined:
    Jul 19, 2006
    Posts:
    1,508
    Thanks, Virror. That seems very confusing to me. It's easier for me to think of it in terms of distance...50 meters for LOD 2, 150 meters for LOD3, etc. I'm not sure how to "translate" that into their system.

    As far as the billboards...I wonder if a script could do this, with by just rendering the tree to a texture with a transparent background and saving it as a prefab.
     
  4. virror

    virror

    Joined:
    Feb 3, 2012
    Posts:
    2,963
    Well, i think its better to use screen size as you can use pretty much the same values even if the models are of different sizes since smaller objects usually can be closer before they switch, but i agree its a bit confusing to think about it that way, hope it help you a bit at least : p I think its easier to scrap thinking about distances and just trying to imagine the object on the screen and think about how big it should be before it should switch. Also trial and error will probably help a lot : D

    Also, i found this model to billboard script that seems to be just what we need for this: http://forum.unity3d.com/threads/68644-LOD-change-to-billboard-at-a-distance-billboard-generation
    Should be easy enough to run that from the editor once for each model or something, if it works that is, have not tested it.

    Edit: Working on a C# conversion now so i can test it out : )
     
    Last edited: May 22, 2013
  5. virror

    virror

    Joined:
    Feb 3, 2012
    Posts:
    2,963
    Enjoy!

    Edit: Cant get the c# one to work, but the js script works kind of. Just place the mesh in the scene, set the reference and add a light. Problem is that only trunk shows in image for some reason. Have to go home now, will look more on this when i get home : )

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class TreeToBillboard : MonoBehaviour
    6. {
    7.     /*
    8.     Make a billboard out of an object in the scene
    9.     The camera will auto-place to get the best view of the object so no need for camera adjustment
    10.    
    11.     To use - place an object in an empty scene with just camera and any lighting you want.
    12.     Add this script to your scene camera and link to the object you want to render.
    13.     Press play and you will get a snapshot of the object (looking down the +Z-axis at it) saved out to billboard.png in your project folder
    14.     Any pixels colored the same as the camera background color will be transparent
    15.     */
    16.  
    17.     public GameObject objectToRender;
    18.     public int imageWidth = 128;
    19.     public int imageHeight = 128;
    20.    
    21.     void Start()
    22.     {
    23.         if(objectToRender)
    24.             ConvertToImage();
    25.     }
    26.    
    27.     IEnumerator ConvertToImage()
    28.     {
    29.         //grab the main camera and mess with it for rendering the object - make sure orthographic
    30.         Camera cam = Camera.main;
    31.         cam.orthographic = true;
    32.        
    33.         //render to screen rect area equal to out image size
    34.         float rw  = imageWidth;
    35.         rw /= Screen.width;
    36.         float rh = imageHeight;
    37.         rh /= Screen.height;
    38.         cam.rect = new Rect(0,0,rw,rh);
    39.        
    40.         //grab size of object to render - place/size camera to fit
    41.         Bounds bb = objectToRender.GetComponent<Renderer>().bounds;
    42.        
    43.         //place camera looking at centre of object - and backwards down the z-axis from it
    44.         cam.transform.position = bb.center;
    45.         cam.transform.position.Set(cam.transform.position.x, cam.transform.position.y, -1.0f + (bb.min.z * 2.0f));
    46.         //make clip planes fairly optimal and enclose whole mesh
    47.         cam.nearClipPlane = 0.5f;
    48.         cam.farClipPlane = -cam.transform.position.z + 10.0f + bb.max.z;
    49.         //set camera size to just cover entire mesh
    50.         cam.orthographicSize = 1.01f * Mathf.Max( (bb.max.y - bb.min.y)/2.0f, (bb.max.x - bb.min.x)/2.0f);
    51.         cam.transform.position.Set(cam.transform.position.x, cam.orthographicSize * 0.05f, cam.transform.position.y);
    52.    
    53.         //render
    54.         yield return new WaitForEndOfFrame();
    55.        
    56.         var tex = new Texture2D( imageWidth, imageHeight, TextureFormat.ARGB32, false );
    57.         // Read screen contents into the texture
    58.         tex.ReadPixels(new Rect(0, 0, imageWidth, imageHeight), 0, 0 );
    59.         tex.Apply();
    60.    
    61.         //turn all pixels == background-color to transparent
    62.         Color bCol = cam.backgroundColor;
    63.         Color alpha = bCol;
    64.         alpha.a = 0.0f;
    65.         for(int y = 0; y < imageHeight; y++)
    66.         {
    67.             for(int x = 0; x < imageWidth; x++)
    68.             {
    69.                 Color c = tex.GetPixel(x,y);
    70.                 if (c.r == bCol.r)
    71.                     tex.SetPixel(x,y,alpha);
    72.             }
    73.         }
    74.         tex.Apply();
    75.    
    76.         // Encode texture into PNG
    77.         byte[] bytes = tex.EncodeToPNG();
    78.         Destroy( tex );
    79.         System.IO.File.WriteAllBytes(Application.dataPath + "/../billboard.png", bytes);
    80.     }
    81. }
    82.  
    83.  
     
    Last edited: May 22, 2013
    jason-fisher likes this.
  6. PolyMad

    PolyMad

    Joined:
    Mar 19, 2009
    Posts:
    2,350
    I was thinking to this since ever. First of all because the tree system in Unity is odd to use.

    Just tried recently again and guess what, even a simple thing like the texture for some leaves is messed up. Can't set up UV properly and I'm not the last noob working with meshes, I'm a modeler trying to use the built in system. It's simply that there seems to be no documentation about the features or oddities.
    Asked for info in the forums, nobody seems to know anything about this. And it's fun, because I just set up a bunch of leaves in the center of a texture and they look offset by .5 or something for some reason. Tried to move them into half texture, no way.

    Then there are more problems with the shaders. Like the translucency that remains active even when there are no lights in the scene. This was posted by a guy in the forum, I didn't test it, but I noticed that the shader is also very difficult to use or plain bugged, always giving too light or too dark trees.

    Then there are the billboards: they distort the mesh if they are near, because of course they have to adapt to perspective from being flat, so you can't use billboards from near, and in fact they were never conceived for this type of use.
    On the other side, when the trees in Unity are far, they SHRINK the damn leaves if you use billboards or some types of leaves.
    BUT the billboard is calculated on the FULL foliage! So when the billboard comes it totally POPS out in the full glory of the tree, wasting half of the reason to be in existence: smooth transition from full detail to low detail.
    So you cannot even use some type of foliages.

    Another reason: you CAN'T close the bottom of the trees.
    So you put collider in trees, but if you make them fall you will see the culled inner of the mesh, which destroys the reality immersion.
    A stupid feature that is missing for some stupid reason.

    LOD. You can very easily create LODs of the trees you generate inside Unity, BUT you can't use them in the trees system! That's so dumb too.



    You have also put up a good list of pro and vs.

    Maybe it's missing that, I've read somewhere, Unity terrain and trees are optimized in a way that terrain HIDES trees behind hills, which is pretty useful in some cases.

    And one thing I don't know is if Unity batches all the trees of one type before and send them in a single drawcall, that would also save a huge number of drawcalls. But it would eat some CPU on the other side.



    Now, the thing is, I didn't tested this stuff properly BUT:

    - if I can't use the billboard leaves
    - if I can't use LODs
    - if I can't use billboard impostors
    - if I can't use colliders

    Then what the heck would I use Unity trees for?
    Only for the terrain culling system?
    No, because with something like InstantOC I can help myself by placing some occluders under the hills as well.
    A bit more work, that's sure, but I can overcome that within one day.

    So now a little examination about my game.
    I need the leaves to NOT shrink in distance because the players can hide in bushes and they CAN'T change their coverage.
    I need to see the bottom of trunks of fallen trees because in my game they will easily fall down.
    And after all I don't need thousands of trees, I am more on the order of 100-200 trees on the whole map.



    Now, I really think I'm going to test Unity trees vs mesh trees very soon because I need to decide what to use finally.

    What I was looking for, was also a well done impostor script.
    The impostor in Unity looks like it's projected on a grey background 128,128,128 and has some 1 px line of grey all around, another reason that makes the Unity system impostors practically unusable if you want a clean professional visual.

    If you can get that impostor script to work, that would be really great :)
     
    Jaqal likes this.
  7. virror

    virror

    Joined:
    Feb 3, 2012
    Posts:
    2,963
    Working on it! : p
    Some really strange issues with the alpha it seems, even when just grabbing the texture from the screen without doing the for loop that sets alpha i get strange stuff going on. Any help would be great : )
     
  8. Vanamerax

    Vanamerax

    Joined:
    Jan 12, 2012
    Posts:
    938
    Strange things mentioned here I didnt know of,

    Also, don't forget that the lighting of the billboard won't be updated if your lighting setup changes (day/night cycle), or has that been fixed lately? That was enough reason for me to switch over to gameObject trees (well, maybe also the hassle of determining which tree to interact with in the Unity terrain), not to mention all the other problems and "features" which fail in doing their thing properly.. Personally, I wouldn't even bother doing these tests, since meshes will be way better if you can get the draw call amount to an acceptable level and have a decent LOD system
     
  9. virror

    virror

    Joined:
    Feb 3, 2012
    Posts:
    2,963
    Lightning issue is simple to solve, just use the billboard shader from the free ats package on the asset store : )
    We need to do a bunch of tests, if not just because its very interesting : p
     
  10. PolyMad

    PolyMad

    Joined:
    Mar 19, 2009
    Posts:
    2,350
    So, 2000 trees visible, 3.3 Mil triangles, for a total of 4000 drawcalls get batched to 6 drawcalls, and I am on 75 fps, and this is cool.
    I didn't even put in any LOD, and I used a single shader for the tree.

    The problems come when you get IN the forest, fps get down to 25 because of the huge overdraw, but with some LODs and the impostors that should also get a hit.

    And anyway, at least for me this is not a problem, since I don't need to build dense forests.

    BTW I am on a laptop. And even if, yes, this is not a low level laptop, because it's a i7, the graphic board is still not comparable to the ones of desktop PCs.
     
  11. virror

    virror

    Joined:
    Feb 3, 2012
    Posts:
    2,963
    First: Sorry jc for stealing your thread : p
    Second: Thanx jc for all the inspiration, still interested in a cooperation : )

    megmaltese: Nice! Not that surprising though really, unitys terrain system is no magic, its mostly for making it easy to set up.
    I have a nice system in mind, this is what i can thought of now:

    -Automatic billboard creation.
    -Automatic LOD group creation. Click a button and your LOD groups will be created for you with dynamic amount of stages by searching for tree names with fixed endings. Also make billboard here.
    -Easy placing. Place your trees as usual with unitys tree creator and press a button and it will be converted to mesh trees based on tree names

    Something like that, sounds nice?
     
    Jaqal likes this.
  12. jc_lvngstn

    jc_lvngstn

    Joined:
    Jul 19, 2006
    Posts:
    1,508
    I share your frustration, megmaltese. I haven't experienced all of the issues you have, but a lot of them. Bad billboarding perspective. Open bottom of trees.

    As far as terrain occlusion is concerned...seems like you could cast two rays, one at the top left "corner" of the tree and one at the top right corner. If both of this hit terrain...the tree is probably behind the landscape.

    So...initial feature set would be something like:

    An inspector UI, that allows you to convert built in terrain trees to gameobjects, placing them under children of a "TreeParent" gameobject.
    With the option to apply random rotation on the Y axis.

    A UI option to create a billboard from a tree prefab.

    Nice to have's:
    Be able to have a list of prefabs to create from the list of trees assigned to the terrain. Currently, if you try to use a LOD group to paint on the terrain, you won't see anything painted. This way, you could use say a pine tree, but in the matching list would be the prefab for correct LOD group prefab.

    A script to close the bottom of trees created from Unity trees. You could supply a texture for the bottom, and it would just add a submesh to close the vertices and use that texture. Not ideal, but better than a gaping hole.
     
  13. jc_lvngstn

    jc_lvngstn

    Joined:
    Jul 19, 2006
    Posts:
    1,508
  14. PolyMad

    PolyMad

    Joined:
    Mar 19, 2009
    Posts:
    2,350
    Uh I don't know, for my personal point of view I'll go with Unity LOD, which should be quite efficient, and it already has built in name based system.
    The addition could be that the last LOD level is the billboard and make it work seamlessly with in the Unity LOD system.

    Transforming Unity terrain trees to mesh trees is maybe a good idea but may reveal somewhat cumbersome, but still better than placing all trees one by one by hand.

    The most important thing anyway is an impostor script that does a GOOD rendering, without that grey silhouette line.
    I know it's probably not trivial to realize, but that's what's most needed.
     
  15. virror

    virror

    Joined:
    Feb 3, 2012
    Posts:
    2,963
    Im talking about the built in unity LOD groups here, just the thing that you dont have to do the dragging, just follow a naming conversion and it will be taken care of.

    The terrain trees to mesh tress thing should be trivial, most ppl are used to that and making the conversion is easy, user just have to press a button or something similar.

    Imposters should also be pretty easy if i just could figure out whats wrong with the alpha...
    jc, maybe you could take a look at that script as well? : p
     
    Last edited: May 22, 2013
  16. PolyMad

    PolyMad

    Joined:
    Mar 19, 2009
    Posts:
    2,350
  17. virror

    virror

    Joined:
    Feb 3, 2012
    Posts:
    2,963
    Solid 50, with some drops to 40 seldom : )
     
  18. virror

    virror

    Joined:
    Feb 3, 2012
    Posts:
    2,963
    Working on a simple Benchmark scene, will make 4 different:
    Terrain trees, all full mesh
    Terrain trees, half mesh, half billboard
    Mesh trees, all full mesh
    Mesh trees, half full mesh, half billboard
     
  19. virror

    virror

    Joined:
    Feb 3, 2012
    Posts:
    2,963
    Why wont i get any batching at all when using the built in Unity trees?
    4096 trees gives me 30000 drawcalls O.O
     
  20. jc_lvngstn

    jc_lvngstn

    Joined:
    Jul 19, 2006
    Posts:
    1,508
    The script looks interesting, I'll have to do testing when I get home. I'm not able to do anything with it for a few hours.

    The script to swap out terrain trees with the original prefabs is pretty simple, I can post it tonight. From memory (pseudocode):

    Code (csharp):
    1. function CreateTrees(Terrain terrain)
    2. {
    3.  
    4. foreach (TreeInstance tree in terrain.TerrainData.TreeInstances)
    5.  
    6.   {
    7.  
    8.     Vector3 treeWorldPosition = tree.Position * terrain.TerrainData.Size + terrain.transform.Position;
    9.      Instantiate(tree.Prototype.Prefab, treeWorldPosition, Quaternion.Identity);
    10.  
    11.   }
    12.  
    13.  
    14. }
    15.  
    Or something pretty similar. I can put something more accurate on tonight!
     
  21. PolyMad

    PolyMad

    Joined:
    Mar 19, 2009
    Posts:
    2,350
    Have you enabled batching in the build settings?
     
  22. jc_lvngstn

    jc_lvngstn

    Joined:
    Jul 19, 2006
    Posts:
    1,508
    Also...(and this kind of vague I know)...at times I saw batching happen, and at times I didn't. I was monkeying around, so I don't know if it is because I had shadows on, or was using the wrong render path. At times dynamic batching actually seemed to offer worse performance.
     
  23. virror

    virror

    Joined:
    Feb 3, 2012
    Posts:
    2,963
    jc: yes, thats simple, i have a bunch of scripts that handle terrain trees.
    megmaltese: yes, both static and dynamic and i get no batching from either terrain or mesh trees.

    RESULTS ARE IN!
    Very interesting results as well!
    First an image of the scene:
    $loadOfTrees.png
    (if you don't see it, try to clear the cache)

    4096 trees placed by script in a grid pattern, exactly the same and exact same camera location for both cases.
    Case1, Terrain trees
    FPS: 19,5 (51,5ms), 12283 drawcalls

    Case2, Mesh trees
    FPS: 45,6 (21,9ms), 12283 drawcalls

    Memory usage was the same in both cases.

    Wow, just wow, that's a huge difference!
    Need to tripple check if i did it right, also need to figure out why no batching since that can impact the results.
     
    Last edited: May 22, 2013
  24. Gobla

    Gobla

    Joined:
    May 28, 2012
    Posts:
    354
    Did you do this in one session in one scene or did you clone the scenes and used one with the terrain trees and the others with the mesh trees?

    EDIT: Also are they with or without colliders?
     
  25. virror

    virror

    Joined:
    Feb 3, 2012
    Posts:
    2,963
    Same scene.
    -First added the terrain trees
    -Did benchmark
    -Removed all trees
    -Enabled mesh tree script instead
    -Did benchmark
    -Repeated this 3 times in same scene by starting over directly with adding terrain trees again. Exactly the same result every time.

    Edit: Note: I used Deferred rendering so thats why its 3x drawcalls vs trees, forward cutts this to 2x but still gives same ratio between the mesh and terrain trees.
     
  26. Gobla

    Gobla

    Joined:
    May 28, 2012
    Posts:
    354
    And if you do that process in reverse order? Not that I doubt your method, but I also have that performance issue in one of the games I am working on, and I really want (someone) to get to the bottom of this.

    Also, what is the memory usage in both scenario's?
     
  27. virror

    virror

    Joined:
    Feb 3, 2012
    Posts:
    2,963
    Well, since i repeated the process it was also done in reverse order when going back from mesh trees to terrain trees again : )

    Next on list is to test billboarding:
    Terrain billboards vs mesh billboards vs particle billboards

    Then test if there is any difference when part of terrain is occluded by itself since someone said that unity terrain had some tricks there.
     
  28. Gobla

    Gobla

    Joined:
    May 28, 2012
    Posts:
    354
    I will also do these tests then on the OMPH project once I work on it.
     
  29. virror

    virror

    Joined:
    Feb 3, 2012
    Posts:
    2,963
    Some temporary results regarding the billboards:
    Unity is drawing their billboards with an incredible speed, 4096 billboards at a blazing 1400fps, 36 drawcalls.
    Mesh billboards without any script at all is only drawn at 144fps, 2 drawcalls.

    Any idea on how they manage with that???
     
  30. Gobla

    Gobla

    Joined:
    May 28, 2012
    Posts:
    354
    Yes, they most likely use the particle system. Much Much faster!
     
  31. virror

    virror

    Joined:
    Feb 3, 2012
    Posts:
    2,963
    Ok, my tests with the particle system is slower : p
    You know how to set it up properly for showing a static billboard only?

    Also, forgot to say before but memory usage was exactly the same between mesh and terrain trees, important factor as well.
     
  32. Gobla

    Gobla

    Joined:
    May 28, 2012
    Posts:
    354
    Well I only know how to do that with the particle system. You have to use one system per type of tree.
    Do note that this is with the old particlesystem.

    Pseudocode:
    Code (csharp):
    1.  
    2. particles = particleEmitter.particles;
    3.  
    4.             for (int i=0; i < particles.Length; i++)
    5.             {
    6.                 particles[i].position = treelist[i].position;
    7.             }
    8.  
    Also good that the memory usage is the same.
     
  33. jc_lvngstn

    jc_lvngstn

    Joined:
    Jul 19, 2006
    Posts:
    1,508
    Interesting numbers, somewhat of a relief to know that I'm not just bonkers.

    I wonder if Unity has optimized regular prefab drawing a lot, and the internal tree stuff hasn't kept up. I just haven't seen a reason to use the tree system anymore unless you have really close billboards, and using those with big trees up close is a no-no because of how they tilt badly and the low resolution.

    Regardless...this is very exciting. I envision a complete tree replacement system, that uses prefabs and/or lods, and allows you to paint them on terrains or anything else if you want. It would allow rotation, scaling, align to normals, coloring (of leaves), closing the trunk, colliders for the trunk only, and have shaders that support wind/bending, shadows and bump mapping.

    I think this is a good community cause. Maybe some shader experts could chime in on advanced shading?
     
  34. jc_lvngstn

    jc_lvngstn

    Joined:
    Jul 19, 2006
    Posts:
    1,508
    When you say mesh billboards...do you mean you created a two-tri mesh plane for each tree, and had it face the camera?
     
  35. brilliantgames

    brilliantgames

    Joined:
    Jan 7, 2012
    Posts:
    1,937

    Hey. Does this script turn any object into a sprite?
     
  36. virror

    virror

    Joined:
    Feb 3, 2012
    Posts:
    2,963
    Yes! If you look at it you can see its just taking a screenshot of the screen really, so it should work on anything thats a GameObject and has a correct bounding box. Feel free to tell me whats wrong with my c# version as it wont work : p

    jc: Yes, two plane mesh but no script attached at all, got a tip that i should do billboards with a shader instead because thats a lot faster than any other approach and probably how Unity are doing it to get such a high framerate.

    One thing i thought about as well is batching, what are the requirements for batching? Will allowing for random scaling, rotation and stuff break batching? That would be a potential drawback if thats the case since trees placed all same can be batched.
     
  37. virror

    virror

    Joined:
    Feb 3, 2012
    Posts:
    2,963
    Just want to add some more interesting results:
    Here at work (yeah, i know : p) i have built in intel crappy graphics and then i get the exact same results from both scenes.

    Would be nice if more ppl could run this benchmark and post their results here.
    https://dl.dropboxusercontent.com/u/1688685/TreeBenchmark.unitypackage
    Just run the two different scenes without changing anything.
     
  38. virror

    virror

    Joined:
    Feb 3, 2012
    Posts:
    2,963
    Will continue my monologue here by posting the finished Object -> Billboard script, instructions in file. Added small improvements like autoplacing of Object and light, just remove that part if you don't need it.

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class TreeToBillboard : MonoBehaviour
    6. {
    7.     /*
    8.     Make a billboard out of an object in the scene
    9.     The camera will auto-place to get the best view of the object so no need for camera adjustment
    10.     Lighting and Object is automaticly added to the scene.
    11.    
    12.     To use:
    13.     Add this script to any object and link to the object you want to render.
    14.     Press play and you will get a snapshot of the object (looking down the +Z-axis at it) saved out to nameOfObject.png in your project folder
    15.     Any pixels colored the same as the camera background color will be transparent
    16.     */
    17.  
    18.     public GameObject objectToRender;
    19.     public int imageWidth = 512;
    20.     public int imageHeight = 512;
    21.    
    22.     void Start()
    23.     {
    24.         if(!objectToRender)
    25.             return;
    26.        
    27.         GameObject lightGameObject = new GameObject("The Light");  
    28.         Light light = lightGameObject.AddComponent<Light>();
    29.         light.type = LightType.Directional;
    30.         lightGameObject.transform.position = new Vector3(0, 100, 0);
    31.         lightGameObject.transform.localEulerAngles = new Vector3(90, 0, 0);
    32.    
    33.         GameObject.Instantiate(objectToRender, Vector3.zero, Quaternion.Euler(0,0,0));
    34.        
    35.         StartCoroutine("ConvertToImage");
    36.     }
    37.    
    38.     IEnumerator ConvertToImage()
    39.     {
    40.         //grab the main camera and mess with it for rendering the object - make sure orthographic
    41.         Camera cam = Camera.main;
    42.         cam.orthographic = true;
    43.         //render to screen rect area equal to out image size
    44.         float rw  = imageWidth;
    45.         rw /= Screen.width;
    46.         float rh = imageHeight;
    47.         rh /= Screen.height;
    48.         cam.rect = new Rect(0,0,rw,rh);
    49.        
    50.         //grab size of object to render - place/size camera to fit
    51.         Bounds bb = objectToRender.GetComponent<Renderer>().bounds;
    52.  
    53.         //place camera looking at centre of object - and backwards down the z-axis from it
    54.         cam.transform.position = new Vector3(bb.center.x, bb.center.y, -1.0f + (bb.min.z * 2.0f));
    55.         //make clip planes fairly optimal and enclose whole mesh
    56.         cam.nearClipPlane = 0.5f;
    57.         cam.farClipPlane = -cam.transform.position.z + 10.0f + bb.max.z;
    58.         //set camera size to just cover entire mesh
    59.         cam.orthographicSize = 1.01f * Mathf.Max((bb.max.y - bb.min.y) / 2.0f, (bb.max.x - bb.min.x) / 2.0f);
    60.         cam.transform.position = new Vector3(cam.transform.position.x, cam.transform.position.y + cam.orthographicSize * 0.05f, cam.transform.position.z);
    61.         //render
    62.         yield return new WaitForEndOfFrame();
    63.        
    64.         var tex = new Texture2D( imageWidth, imageHeight, TextureFormat.ARGB32, false );
    65.         // Read screen contents into the texture
    66.         tex.ReadPixels(new Rect(0, 0, imageWidth, imageHeight), 0, 0 );
    67.         tex.Apply();
    68.        
    69.         int x;
    70.         int y;
    71.        
    72.         for(y = 0; y < imageHeight; y++)
    73.         {
    74.             for(x = 0; x < imageWidth; x++)
    75.             {
    76.                 Color c = tex.GetPixel(x, y);
    77.                 c.a = 1.0f;
    78.                 tex.SetPixel(x, y, c);
    79.             }
    80.         }
    81.         tex.Apply();
    82.        
    83.         //turn all pixels == background-color to transparent
    84.         Color bCol = cam.backgroundColor;
    85.         Color alpha = bCol;
    86.         alpha.a = 0.0f;
    87.         for(y = 0; y < imageHeight; y++)
    88.         {
    89.             for(x = 0; x < imageWidth; x++)
    90.             {
    91.                 Color c2 = tex.GetPixel(x, y);
    92.                 if (c2.r == bCol.r  c2.g == bCol.g  c2.b == bCol.b)
    93.                     tex.SetPixel(x, y, alpha);
    94.             }
    95.         }
    96.         tex.Apply();
    97.    
    98.         // Encode texture into PNG
    99.         byte[] bytes = tex.EncodeToPNG();
    100.         Destroy( tex );
    101.         //System.IO.File.WriteAllBytes(Application.dataPath + "/../billboard.png", bytes);
    102.         System.IO.File.WriteAllBytes("Assets/Tree project/" + objectToRender.name + ".png", bytes);
    103.     }
    104. }
    105.  
    106.  
     
    Last edited: May 23, 2013
    Arkade likes this.
  39. Gobla

    Gobla

    Joined:
    May 28, 2012
    Posts:
    354
    From my mobile:
    You can enable static batching from script. However you will need pro.
     
  40. virror

    virror

    Joined:
    Feb 3, 2012
    Posts:
    2,963
    static batching did not make any difference for me with fps, only drawcalls, but memory consumption was really huge which was as expected. Static batching is not recommended by Unity for huge forests and similar because of that.

    Currently working on trying to get some efficient billboards but i have no clue on how to write a shader that does that + alpha cutout : p
    Any help in that area + benchmarking is greatly appreciated : )

    As soon as the billboards are done the work can start on creating the the LOD objects and other stuff.
     
  41. jc_lvngstn

    jc_lvngstn

    Joined:
    Jul 19, 2006
    Posts:
    1,508
    I didn't get a chance to look at this last night. But the whole question of batching seems somewhat up in the air.

    This thread:
    http://forum.unity3d.com/threads/163284-Unity-4-static-dynamic-batching-deferred-lighting

    Frankly, it was a frustrating read, and I wanted to vent. There doesn't seem to be a consistent clear answer to when things batch and when they don't. I feel at times that UT is not very involved at times, and the documentation is fuzzy.

    ok rant off. Anyway...the billboard creation script. Would rendertotexture have better transparency? I haven't messed with it or your script yet, just curious.

    If there was a way to have a material with all of the tree bitmaps in an atlased texture, and for each particle you pass an index value to the shader that sets the uvs at the correct tree, we could use shuriken with only 1 emitter. Is that possible, or would it require the particles to have different materials?

    The texture animation over time module sorta does this, but I get the impression it affects all particles instead of just specific ones.

    By the way...virror, thanks for being so active on this. I don't have near as much spare time as I would like :(
     
    Last edited: May 23, 2013
  42. virror

    virror

    Joined:
    Feb 3, 2012
    Posts:
    2,963
    I don't think i will bother with the batching thing since it should be the same anyway if using terrain trees or mesh trees batched or not batched.
    Also its a tricky subject, but if anyone loves batching feel free to share results/information ; )

    What do you mean "better transparency"? Transparency is working very well at the moment with the textures i have generated. Probably misunderstanding you here somehow.

    Texture atlas, i guess this is to reduce textures and also enable batching for all billboards regardless of tree type? Possible i guess but would require some more work, also it would reduce the quality of the billboards maybe cause need to use smaller images if we want to put many in the same atlas?

    I don't want to use the particle system for this since its slow, might be a bit faster than a mesh but using a shader should be a lot faster, thats my current approach but i really suck bigtime at shaders, cant even make the simplest one, so its a big uphill battle : /
     
  43. jc_lvngstn

    jc_lvngstn

    Joined:
    Jul 19, 2006
    Posts:
    1,508
    I thought that when you used the earlier technique for billboards, it didn't render it on a transparent background...my goof :)

    I see what you mean about billboard quality...that was one of my peeves about Unity's, the billboard textures can be pretty pixellated for large trees. Do you think it's unacceptably slow to use the LOD approach with a prefab, that is a simple plane, one tree billboard texture, that faces the camera via script?
     
  44. virror

    virror

    Joined:
    Feb 3, 2012
    Posts:
    2,963
    Well, its loads faster than using mesh trees anyway : p
    Might work as a start : )
     
  45. virror

    virror

    Joined:
    Feb 3, 2012
    Posts:
    2,963
    Updated the script on the previous page, there was a bug that could cause artifacts from the original script i copied, this should be fixed now : )
     
  46. jc_lvngstn

    jc_lvngstn

    Joined:
    Jul 19, 2006
    Posts:
    1,508
    My results:

    Unity's trees: About 24 fps.
    Mesh: 72 fps (after I turned off VSync)
    Turning batching on/off didn't seem to make any difference.
     
  47. Gobla

    Gobla

    Joined:
    May 28, 2012
    Posts:
    354
    On the mediocre test laptop:

    Mesh: 49 fps @ 8193 draw calls.
    All mesh batched in one set: 12 fps @ 4283 draw calls.
    All mesh batched per row 12 fps @ 4288 draw calls.
    All mesh batched in sets of 4 trees: 12 fps @ 5123 draw calls.
    TerrainTrees: 23 fps @ 8193 draw calls.

    After changing camheight from 320 to 100.
    Mesh: 64 fps @ 1795 draw calls.
    All mesh batched in one set: 65 fps @ 777 drawcalls.
    All mesh batched per row 65 fps @ 799 draw calls.
    All mesh batched in sets of 4 trees: 72 fps @ 1159 draw calls.
    TerrainTrees: 64 fps @ 1795 draw calls.
     
  48. jc_lvngstn

    jc_lvngstn

    Joined:
    Jul 19, 2006
    Posts:
    1,508
    That's interesting...in your second test, you got the same fps as terrain trees? I wonder why...

     
  49. jc_lvngstn

    jc_lvngstn

    Joined:
    Jul 19, 2006
    Posts:
    1,508
    In my test scene, I added a LOD group with a billboard using the script you posted, Virror. I used this script from the wiki to make it face the camera.

    Code (csharp):
    1.  
    2. public class CameraFacingBillboard : MonoBehaviour
    3. {
    4.     private Camera m_Camera;
    5.     // Use this for initialization
    6.     private void Start()
    7.  
    8.     {
    9.         m_Camera = Camera.main;
    10.     }
    11.  
    12.     // Update is called once per frame
    13.     private void Update()
    14.     {
    15.         transform.LookAt(transform.position + m_Camera.transform.rotation * Vector3.back,
    16.                          m_Camera.transform.rotation * Vector3.up);
    17.     }
    18. }
    19.  
    The pine tree I was using had 980 polys, 666 verts
    With full meshes, I was getting 103 fps.
    Lod1 at 23%: 99%
    Lod1 at 80%: 103fps

    So...it's possible my tree was such low poly to begin, there wasn't much of a difference. And, possibly the script and LOD grouping itself requires overhead. But basically...at least in my test, the LOD grouping wasn't worth it at all for simple objects. Not for billboarding, with a script doing the lookat.
    Also...the transform.lookat has that wretched tilting effect if the billboards are close. I think it should only rotate on the Y axis, and lock the X axis maybe.

    Tomorrow, I think I'll test just having 2 intersecting planes with the billboard on them as a very low detail tree. That will be almost as fast as drawing the billboard, and it will get rid of the camera facing script AND the goofy tilting effect :)
     
  50. PolyMad

    PolyMad

    Joined:
    Mar 19, 2009
    Posts:
    2,350
    Yes your tree was in fact too small to make much difference. So low poly objects are good only to test number of drawcalls and, in case you extend the polygons a lot, overdraw (pixel fill performance).

    Anyway, if those are the trees you need, that's the test you need to do :D



    On my side I think I'm goin with a "hybrid" solution for some of the trees and especially bushes: mesh for trunk + billboard particles for leaves.
    Billboards have the problem that they are always facing the camera and so from near they can look odd when rotating the pov.
    But they also have one advantage when we talk about trees: they mantain their vertical alignment.
    So if your game is only developed on an horizontal main plane, billboards can help a lot when you want those trees to fall down.
    A willow would look very odd in example if the leaves kept aligned like in its vertical position.
    Of course for some trees the way to go is all mesh, but for some others I'll go with this solution.
     
    Last edited: May 24, 2013