Search Unity

gpu instancing for older standard shaders?

Discussion in 'Shaders' started by creat327, Apr 6, 2017.

  1. creat327

    creat327

    Joined:
    Mar 19, 2009
    Posts:
    1,756
    Hi
    Has unity updated the old shaders? if not, any idea how can I get the Hidden/Nature/Tree Creator Leaves Fast Optimized and Hidden/Nature/Tree Creator Bark Optimized
    to work with gpu instancing? I tried myself with no luck and it would save tons of drawcalls on my mobile device

    I checked the source of the shaders and it seems to include instancing but exchanging them with the old ones and with the new ones brings no difference on performance so something is off
     
    Last edited: Apr 6, 2017
    Stardog likes this.
  2. Stardog

    Stardog

    Joined:
    Jun 28, 2010
    Posts:
    1,913
    I'm making a WebGL game, so I had the same problem.

    If I placed the trees manually by hand, it seems to use GPU instancing, even with the default materials (Optimised Bark/Leaf without Enable Instancing). Whereas the terrain placement trees had 9 draw calls for each tree, due to shadows and multiple materials, etc. So, it seems like the optimised materials can instance, but not if they're placed by the terrain system.

    I replaced the terrain-placed trees with my tree creator prefab using the script below, but the tree looked too bright at certain angles, so I switched the Optimised Leaf material with an instancing-enabled Nature/Tree Creator Leaves material, by replacing it in the Mesh Renderer.

    Now I can draw a whole forest with 22 added draw calls, and 7k tris, and don't even have to bother will billboarding because they're so low-poly. I can also use the terrain tree painter and just set tree distance to 0 when I want to hide them.

    Use this script to replace the terrain-placed trees with your prefab asset. It still needs options, such as replacing different detail meshes with different prefabs. That requires using TreeInstance.prototypeIndex (what number detail mesh it is).

    http://answers.unity3d.com/question...jects.html?childToView=1419858#answer-1419858
    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEditor;
    5.  
    6. // Replaces Unity terrain trees with prefab GameObject.
    7. // http://answers.unity3d.com/questions/723266/converting-all-terrain-trees-to-gameobjects.html
    8. [ExecuteInEditMode]
    9. public class TreeReplacerS : EditorWindow {
    10.  
    11.    [Header("Settings")]
    12.    public GameObject _tree;
    13.  
    14.    [Header("References")]
    15.    public Terrain _terrain;
    16.  
    17.    //============================================
    18.  
    19.    [MenuItem("Window/My/TreeReplacer")]
    20.    static void Init()
    21.    {
    22.        TreeReplacerS window = (TreeReplacerS)GetWindow(typeof(TreeReplacerS));
    23.    }
    24.  
    25.    void OnGUI()
    26.    {
    27.        _terrain = (Terrain)EditorGUILayout.ObjectField(_terrain, typeof(Terrain), true);
    28.  
    29.        _tree = (GameObject)EditorGUILayout.ObjectField(_tree, typeof(GameObject), true);
    30.  
    31.        if (GUILayout.Button("Convert to objects"))
    32.        {
    33.            Convert();
    34.        }
    35.  
    36.        if (GUILayout.Button("Clear generated trees"))
    37.        {
    38.            Clear();
    39.        }
    40.    }
    41.  
    42.    //============================================
    43.  
    44.    public void Convert()
    45.    {
    46.        TerrainData data = _terrain.terrainData;
    47.  
    48.        // Create parent
    49.        GameObject parent = GameObject.Find("TREES_GENERATED");
    50.  
    51.        if (parent == null)
    52.        {
    53.            parent = new GameObject("TREES_GENERATED");
    54.        }
    55.  
    56.        // Create trees
    57.        foreach (TreeInstance tree in data.treeInstances)
    58.        {
    59.            Vector3 position = new Vector3(tree.position.x * data.detailWidth - (data.size.x / 2), tree.position.y * data.size.y - (data.size.y / 2), tree.position.z * data.detailHeight - (data.size.z / 2));
    60.  
    61.            // Instantiate as Prefab if is one, if not, instantiate as normal
    62.            GameObject go = PrefabUtility.InstantiatePrefab(_tree) as GameObject;
    63.  
    64.            if (go != null)
    65.            {
    66.                go.transform.position = position;
    67.                go.transform.parent = parent.transform;
    68.            }
    69.            else
    70.            {
    71.                Instantiate(_tree, position, Quaternion.identity, parent.transform);
    72.            }
    73.        }
    74.    }
    75.  
    76.    public void Clear()
    77.    {
    78.        DestroyImmediate(GameObject.Find("TREES_GENERATED"));
    79.    }
    80.  
    81. }
     
    Last edited: Oct 13, 2017
  3. creat327

    creat327

    Joined:
    Mar 19, 2009
    Posts:
    1,756
    Just to clarify, the steps are:
    1) Use Nature/Tree Creator Leaves material instead of Optimised Bark/Leaf
    2) Instead of terrain trees, replace them with prefabs by hand with the script and then hide the terrain trees.

    Correct?
     
  4. Stardog

    Stardog

    Joined:
    Jun 28, 2010
    Posts:
    1,913
    Yes. Remember to check Enable Instancing on the new material, and replace it in the mesh renderer, not the tree creator script.
     
  5. creat327

    creat327

    Joined:
    Mar 19, 2009
    Posts:
    1,756
    Thanks. I wonder why it doesn't work if using the default Terrain system. That hasn't been updated or fixed since I was born :/
     
  6. romi-fauzi

    romi-fauzi

    Joined:
    Aug 16, 2013
    Posts:
    161
    I just tested it, and it actually works with terrain, but if you enabled instancing after adding trees to the terrain, you'll need to choose the tree under the terrain tree menu, edit trees, and just press apply to update the tree prefabs, and you'll see the gpu instancing are actually batching on the profiler.
     
  7. creat327

    creat327

    Joined:
    Mar 19, 2009
    Posts:
    1,756
    well, i don't see that behavior. I use the default tree editor (no speedtrees since those are slower than a turtle). I select the tree, drag it into the terrain, hit apply... same thing than before
     
  8. romi-fauzi

    romi-fauzi

    Joined:
    Aug 16, 2013
    Posts:
    161
    @creat327 : Apparently you're right, I tested with a pre-modeled 3d trees, and it works, but when I try it using the tree editor, it doesn't, so maybe we need to convert the tree from the editor to a 3d model first, dunno if that is possible though.
     
  9. creat327

    creat327

    Joined:
    Mar 19, 2009
    Posts:
    1,756
    well, that's actually what @Stardog said right before your post.
     
  10. romi-fauzi

    romi-fauzi

    Joined:
    Aug 16, 2013
    Posts:
    161
    Sorry if my post wasn't clear, but its not solely terrain issues, since if you use a pre-modelled 3d tree on a terrain, the instancing works, only when you use the tree from tree creator, than it won't. Reading back Stardog post, I assume it's not possible at all to do instancing using terrain, so I gave it a try.

    With tree creator, you can always convert it to a mesh (I believe there is a script to do this), and use the converted mesh as the tree prefabs to be painted on the terrain.
     
  11. MadeFromPolygons

    MadeFromPolygons

    Joined:
    Oct 5, 2013
    Posts:
    3,980
    Your problem is your using the terrain engine. Just make your terrain as a model. And then use microsplat shader for free from store.

    Currently, the terrain system is not really fit for purpose, its basicaly 2010 tech with some bugfixes. I always find if I stop using it, things go better.

    EDIT: linking in @jbooth , the creator of microsplat and one of the shader wizards around, as he can probably explain why this is better than anyone (other than maybe @bgolus , the other shader wizard of the community - both of who I follow meticulously)
     
    romi-fauzi likes this.