Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Unity 2022.2 is now available as the latest Tech release.
    Dismiss Notice
  3. We are making some changes to the DOTS forums.
    Dismiss Notice
  4. Have a look at our Games Focus blog post series which will show what Unity is doing for all game developers – now, next year, and in the future.
    Dismiss Notice

[RELEASED] GPU Instancer

Discussion in 'Assets and Asset Store' started by LouskRad, May 3, 2018.

  1. Gabe851

    Gabe851

    Joined:
    May 13, 2017
    Posts:
    22
    Hello, I'm having build issues on the latest unity 2022/ecs experimental build that seem to be related to GPUI.

    Using Entities 1.0.0-exp.12, entities graphics 1.0.0-exp.14, Unity 2022.2.0b13, Jobs 0.70 exp, etc...

    Building to windows I get the following errors (it plays fine in editor):




    should i delete and reimport GPUI? I tried fixing it by using the render pipeline converter update, but that didn't work either. Is there a build setting i'm missing?
     
  2. GurhanH

    GurhanH

    Joined:
    Apr 24, 2017
    Posts:
    389
    Hi there,
    The "Assertion failed" messages was resolved in the latest version (v1.7.5).
    However we did not encounter the shader errors previously. It is most probably a Unity bug in the beta version. We do not test alpha or beta versions of Unity, since there are a lot of bugs in Unity itself which get resolved in stable versions. We will look into it if the issue continues in tech stream release.
     
  3. Gabe851

    Gabe851

    Joined:
    May 13, 2017
    Posts:
    22
    thank you for the reply! Yes, I just reverted back to Unity 2021 and can build now.

    I have another question for you though. I saw on some earlier pages you mentioned doing a demo scene or example with ECS. Is there an ECS/DOTS example with GPUInstancer yet? GPUI lets me render and animate many tens of thousands of units, but with the limitations of gameobjects when moving them around I max out performance wise closer to 10k when trying to do much with the instanced, animated characters. I tried using a compute shader to move them, which worked, but I couldn't get them looking as good in their movement as I can with nav agents/A* pathfinding, and also it just maxed out at around 10k anyway because it put the GPU at 99%.
     
  4. GurhanH

    GurhanH

    Joined:
    Apr 24, 2017
    Posts:
    389
    Latest Crowd Animations version has a demo scene called NoGameObjectsWithJobsDemo. It has example code showing how you can control animations within Jobs using internal NativeArrays instead of using the CrowdAnimator.
     
    Gabe851 likes this.
  5. Mamoru_Suzuki

    Mamoru_Suzuki

    Joined:
    Nov 8, 2022
    Posts:
    2
    Hello, I have a question about detail manager.
    (1) When I update the contents of a prefab inProject, it seems that the changes are not reflected in the prefab that is already registered in prototype. Is there any way to reflect this update?
    (2) Currently, when I update the prefab, I select "Generate Prototypes" again to update the prototype.
    At this time, I would like to [Generate Prototypes] only for the updated prefab. Is there a way to do this?
    (3) When I [Generate Prototypes], the MultipleSelection setting is reset.
    Is there a way to [Generate Prototypes] without resetting?

    If there is a way to update the prefab in (1), then questions (2) and (3) are as good as resolved.

    Thank you in advance.

    Translated with DeepL
     
    Last edited: Nov 8, 2022
  6. GurhanH

    GurhanH

    Joined:
    Apr 24, 2017
    Posts:
    389
    Hi there,
    To update the renderers with the changes in edit mode, you can use one of these methods:

    Stop and Start Simulation:
    upload_2022-11-9_10-49-56.png

    Disable and then Enable the Detail Manager:
    upload_2022-11-9_10-51-16.png

    Call InitializeGPUInstancer API method from a script:
    Code (CSharp):
    1. GPUInstancerAPI.InitializeGPUInstancer(myDetailManager);
     
  7. Mamoru_Suzuki

    Mamoru_Suzuki

    Joined:
    Nov 8, 2022
    Posts:
    2
    ThankYou GurhanH!!!


     
  8. ForemanDesigns

    ForemanDesigns

    Joined:
    Feb 4, 2018
    Posts:
    34
    Hey there @GurhanH! I'm wondering if you could add support for WebGL (2.0)? While DrawMeshInstancedIndirect isn't supported for WebGL, WebGL does fully support DrawMeshInstanced using a procedural texture to store the data rather than a structured buffer, so it should be entirely possible to add support for this platform!

    Our team would absolutely love to add an instancing tool like this to our workflow to optimize WebGL content. Instancing is particularly useful to reduce the file size of WebGL builds. Other draw call optimization methods like static batching or baking meshes to a large static mesh drastically inflates the build file size, which is a no-go for WebGL apps that need to download quickly. So, we're seeking out solutions based on instancing.
     
  9. Gabe851

    Gabe851

    Joined:
    May 13, 2017
    Posts:
    22
    awesome! thanks
     
  10. unity_CTqEIUhs36mSiQ

    unity_CTqEIUhs36mSiQ

    Joined:
    Nov 12, 2022
    Posts:
    1
    Why grass like this in build ?
     

    Attached Files:

  11. GurhanH

    GurhanH

    Joined:
    Apr 24, 2017
    Posts:
    389
    Hi there,
    Unfortunately we are not planning to add WebGL support since we can not implement most of the current features because of technical limitations (mainly Compute Shaders and Buffers).
    We are working on a new solution where we are considering adding support for platforms with no Compute Shader support. But it is currently under development and I can not say for sure if no Compute Shader option will make it to the final product.

    Hi there,
    I am not sure why this issue is happening. It might be related to target device or player settings. Please email us a bug report following this guide with a sample project, so we can investigate.
     
  12. ForemanDesigns

    ForemanDesigns

    Joined:
    Feb 4, 2018
    Posts:
    34
    Thanks for the reply!

    That's too bad - WebGL could really benefit from instancing tools since instancing keeps the build file size low (vs static static batching or static baking, both of which severely inflates build file size). This is far more important for web-based apps... Even with a limited feature set this plugin would be so helpful. I hope WebGL is supported at some point!
     
  13. Rail9

    Rail9

    Joined:
    Feb 21, 2020
    Posts:
    23
    Hello! Thank you for your previous help.

    I previously asked about dynamic object generation and solved the problem of objects not being deleted correctly, but now I am experiencing a phenomenon where objects are not deleted when the spawning device is activated after a certain period of time.

    For example, after 20 seconds, the spawning device becomes active and spawns where the ray hit, but unlike when it is active from the beginning, the object cannot be destroyed (deleted).

    Due to the procedural nature of the gameplay where terrain is generated, we want the spawn to spawn after a certain time, but the above issue prevents trees, rocks, etc. from being destroyed.

    The script in question is almost unchanged.
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. namespace GPUInstancer
    6. {
    7.     public class SpawnerObjectTree : MonoBehaviour
    8.     {
    9.         public GameObject inst;
    10.  
    11.         public GPUInstancerPrefabManager GPUInstancerPrefabManager;
    12.         public List<GPUInstancerPrefab> listObjs = new List<GPUInstancerPrefab>();
    13.  
    14.         public List<GPUInstancerPrefab> listObjComp = new List<GPUInstancerPrefab>();
    15.         public GPUInstancerPrefab allocated;
    16.  
    17.         public float xMinRange;
    18.         public float xMaxRange;
    19.         public float yMinRange;
    20.         public float yMaxRange;
    21.         public float zMinRange;
    22.         public float zMaxRange;
    23.         public float range;
    24.  
    25.         public int instNumver;
    26.  
    27.         RaycastHit hit;
    28.  
    29.         private void Awake()
    30.         {
    31.             inst = GameObject.FindGameObjectWithTag("InstanceTree");
    32.             GPUInstancerPrefabManager = inst.GetComponent<GPUInstancerPrefabManager>();
    33.  
    34.             Shoot();
    35.         }
    36.  
    37.         void Shoot()
    38.         {
    39.             for (int i = 0; i < instNumver; i++)
    40.             {
    41.                 if (Physics.Raycast(transform.position, transform.forward + new Vector3(Random.Range(xMinRange, xMaxRange), Random.Range(yMinRange, yMaxRange), Random.Range(zMinRange, zMaxRange)), out hit, range))
    42.                 {
    43.                     if (hit.collider.gameObject.layer == LayerMask.NameToLayer("Ground"))
    44.                     {
    45.                         allocated = Instantiate(listObjs[Random.Range(0, listObjs.Count)], hit.point, Quaternion.Euler(0, Random.Range(0, 360), 0));
    46.  
    47.                         listObjComp.Add(instancerPrefab());
    48.                     }
    49.                 }
    50.             }
    51.         }
    52.  
    53.         private GPUInstancerPrefab instancerPrefab()
    54.         {
    55.             return allocated;
    56.         }
    57.  
    58.         private void Start()
    59.         {
    60.             InitializePrefab();
    61.         }
    62.  
    63.         public void InitializePrefab()
    64.         {
    65.             GPUInstancerAPI.RegisterPrefabInstanceList(GPUInstancerPrefabManager, listObjComp);
    66.             GPUInstancerAPI.InitializeGPUInstancer(GPUInstancerPrefabManager);
    67.         }
    68.  
    69.         public void RemovePrefabInstance(GameObject go)
    70.         {
    71.             if (go.TryGetComponent(out GPUInstancerPrefab gpuiPrefab))
    72.                 GPUInstancerAPI.RemovePrefabInstance(GPUInstancerPrefabManager, gpuiPrefab, false);
    73.         }
    74.     }
    75. }
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using Polyperfect.Crafting.Demo;
    5.  
    6. namespace GPUInstancer
    7. {
    8.     public class TreeHitDamage : MonoBehaviour
    9.     {
    10.         public int treeHealth;
    11.         public int treeDamage;
    12.         public float time;
    13.         public float activeFalsetime;
    14.         public int randomAxis;
    15.  
    16.         public bool rigidOn;
    17.  
    18.         public SpawnerObjectTree spawnerObject;
    19.  
    20.         private void Awake()
    21.         {
    22.             spawnerObject = GameObject.Find("Instantiater_Tree").GetComponent<SpawnerObjectTree>();
    23.         }
    24.  
    25.         private void Update()
    26.         {
    27.             if (treeHealth <= 0)
    28.             {
    29.                 GetComponent<CapsuleCollider>().enabled = false;
    30.                 GetComponent<BoxCollider>().enabled = true;
    31.  
    32.                 if (!rigidOn)
    33.                 {
    34.                     rigidOn = true;
    35.                     randomAxis = Random.Range(0, 4);
    36.  
    37.                     GetComponent<Rigidbody>().constraints = RigidbodyConstraints.None;
    38.  
    39.                     if (randomAxis == 0)
    40.                     {
    41.                         transform.rotation = Quaternion.Euler(5, 0, 0);
    42.                     }
    43.  
    44.                     if (randomAxis == 1)
    45.                     {
    46.                         transform.rotation = Quaternion.Euler(-5, 0, 0);
    47.                     }
    48.  
    49.                     if (randomAxis == 2)
    50.                     {
    51.                         transform.rotation = Quaternion.Euler(0, 0, 5);
    52.                     }
    53.  
    54.                     if (randomAxis == 3)
    55.                     {
    56.                         transform.rotation = Quaternion.Euler(0, 0, -5);
    57.                     }
    58.                 }
    59.  
    60.                 time += Time.unscaledDeltaTime;
    61.  
    62.                 if (time > activeFalsetime)
    63.                 {
    64.                     spawnerObject.RemovePrefabInstance(gameObject);
    65.                     Destroy(gameObject);
    66.                 }
    67.             }
    68.         }
    69.  
    70.         public void TreeHits()
    71.         {
    72.             treeHealth -= treeDamage;
    73.         }
    74.     }
    75. }
     
  14. Rail9

    Rail9

    Joined:
    Feb 21, 2020
    Posts:
    23
    It seems to be a bug only for the sales project, but I don't know the cause.

    Seems I was a little premature in asking the question.
     
  15. kevinsyang17

    kevinsyang17

    Joined:
    Apr 3, 2018
    Posts:
    5
    Any idea how to optimize GPU? I'm getting heavy fps drop from QuadTreeNode.renderer. I have attached my game view, scene view, and GPUISettings and profiler. I have enabled all culling and optimized with LOD and billboard, and in the scene view, you can see not many Trees are rendered and shouldn't lower the fps so much. For reference, the trees are GameObjects using The Vegetation Engine optimized shaders, but there are tens of thousands of them (can see in GPUIPrefabManager screenshot attached). I'm using Unity 2020.3.32f1 and the latest GPUInstancer.

    UPDATE:
    I turned off UseOriginalShadowCaster off and it improved drastically. The problem is that now Tree shadows are static and look a bit weird or of lesser quality (tree is moving in wind but shadows not). Is there a way to optimize with use original shadow caster? Such as enable that for the closest trees and further trees/objects use the static shadow i assume from GPUI, or maybe up the quality of GPUI shadows?
     

    Attached Files:

    Last edited: Nov 20, 2022
  16. Rail9

    Rail9

    Joined:
    Feb 21, 2020
    Posts:
    23
    After all, even in the test project, I could generate a tree by Ray from an object that was instantiated later, but I could not delete it after the build.

    I can delete the tree if I don't Instantiate the spawner object, but I want to instantiate it later from a processing standpoint.
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using GPUInstancer;
    5.  
    6. public class PlayerDistance : MonoBehaviour
    7. {
    8.     public GameObject terrain;
    9.  
    10.     public GameObject inst;
    11.  
    12.     public GPUInstancerPrefabManager GPUInstancerPrefabManager;
    13.     public List<GPUInstancerPrefab> listObjs = new List<GPUInstancerPrefab>();
    14.  
    15.     public List<GPUInstancerPrefab> listObjComp = new List<GPUInstancerPrefab>();
    16.     private GPUInstancerPrefab allocated;
    17.  
    18.     public GameObject player;
    19.  
    20.     public float enableDistance;
    21.     public float targetDistance;
    22.  
    23.     private void Update()
    24.     {
    25.         Vector3 posA = player.transform.position;
    26.         Vector3 posB = transform.position;
    27.         targetDistance = Vector3.Distance(posA, posB);
    28.  
    29.         if (targetDistance < enableDistance)
    30.         {
    31.             terrain.gameObject.SetActive(true);
    32.         }
    33.  
    34.         if (targetDistance > enableDistance)
    35.         {
    36.             terrain.gameObject.SetActive(false);
    37.         }
    38.     }
    39.  
    40.     private void Awake()
    41.     {
    42.         inst = GameObject.Find("GPUI Prefab ManagerTerrain");
    43.         GPUInstancerPrefabManager = inst.GetComponent<GPUInstancerPrefabManager>();
    44.  
    45.         Shoot();
    46.     }
    47.  
    48.     void Shoot()
    49.     {
    50.         listObjComp.Add(instancerPrefab());
    51.     }
    52.  
    53.     private GPUInstancerPrefab instancerPrefab()
    54.     {
    55.         allocated = Instantiate(listObjs[Random.Range(0, listObjs.Count)], transform.position, Quaternion.identity);
    56.         allocated.transform.parent = terrain.transform;
    57.         allocated.transform.localPosition = new Vector3(0, 100, 0);
    58.         allocated.transform.localEulerAngles = new Vector3(90, 0, 0);
    59.         return allocated;
    60.     }
    61.  
    62.     private void Start()
    63.     {
    64.         player = GameObject.FindGameObjectWithTag("Player");
    65.  
    66.         InitializePrefab();
    67.     }
    68.  
    69.     public void InitializePrefab()
    70.     {
    71.         GPUInstancerAPI.RegisterPrefabInstanceList(GPUInstancerPrefabManager, listObjComp);
    72.         GPUInstancerAPI.InitializeGPUInstancer(GPUInstancerPrefabManager);
    73.     }
    74.  
    75.     public void RemovePrefabInstance(GameObject go)
    76.     {
    77.         if (go.TryGetComponent(out GPUInstancerPrefab gpuiPrefab))
    78.             GPUInstancerAPI.RemovePrefabInstance(GPUInstancerPrefabManager, gpuiPrefab, false);
    79.     }
    80. }
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using GPUInstancer;
    5.  
    6. public class EnableDistance : MonoBehaviour
    7. {
    8.     public GPUInstancerPrefabManager GPUInstancerPrefabManager;
    9.     public List<GPUInstancerPrefab> listObjs = new List<GPUInstancerPrefab>();
    10.  
    11.     public List<GPUInstancerPrefab> listObjComp = new List<GPUInstancerPrefab>();
    12.     private GPUInstancerPrefab allocated;
    13.  
    14.     public float high;
    15.     public float width;
    16.     public int vertical;
    17.     public int horizontal;
    18.  
    19.     Vector3 pos;
    20.  
    21.     private void Awake()
    22.     {
    23.         Shoot();
    24.     }
    25.  
    26.     void Shoot()
    27.     {
    28.         pos = transform.position;
    29.  
    30.         for (int vi = 0; vi < vertical; vi++)
    31.         {
    32.             for (int hi = 0; hi < horizontal; hi++)
    33.             {
    34.                 allocated =
    35.                 Instantiate(listObjs[Random.Range(0, listObjs.Count)], new Vector3(pos.x + horizontal * width / 2 - hi * width - width / 2, high, pos.z + vertical * width / 2 - vi * width - width / 2), Quaternion.identity);
    36.  
    37.                 listObjComp.Add(instancerPrefab());
    38.             }
    39.         }
    40.     }
    41.  
    42.     private GPUInstancerPrefab instancerPrefab()
    43.     {
    44.         return allocated;
    45.     }
    46.  
    47.     private void Start()
    48.     {
    49.         InitializePrefab();
    50.     }
    51.  
    52.     public void InitializePrefab()
    53.     {
    54.         GPUInstancerAPI.RegisterPrefabInstanceList(GPUInstancerPrefabManager, listObjComp);
    55.         GPUInstancerAPI.InitializeGPUInstancer(GPUInstancerPrefabManager);
    56.     }
    57.  
    58.     public void RemovePrefabInstance(GameObject go)
    59.     {
    60.         if (go.TryGetComponent(out GPUInstancerPrefab gpuiPrefab))
    61.             GPUInstancerAPI.RemovePrefabInstance(GPUInstancerPrefabManager, gpuiPrefab, false);
    62.     }
    63. }
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. namespace GPUInstancer
    6. {
    7.     public class SpawnerObject : MonoBehaviour
    8.     {
    9.         public GameObject inst;
    10.  
    11.         public GPUInstancerPrefabManager GPUInstancerPrefabManager;
    12.         public List<GPUInstancerPrefab> listObjs = new List<GPUInstancerPrefab>();
    13.  
    14.         public List<GPUInstancerPrefab> listObjComp = new List<GPUInstancerPrefab>();
    15.         public GPUInstancerPrefab allocated;
    16.  
    17.         public float xMinRange;
    18.         public float xMaxRange;
    19.         public float yMinRange;
    20.         public float yMaxRange;
    21.         public float zMinRange;
    22.         public float zMaxRange;
    23.         public float range;
    24.  
    25.         public int instNumver;
    26.  
    27.         RaycastHit hit;
    28.  
    29.         private void Awake()
    30.         {
    31.             inst = GameObject.FindGameObjectWithTag("Instance");
    32.             GPUInstancerPrefabManager = inst.GetComponent<GPUInstancerPrefabManager>();
    33.  
    34.             Shoot();
    35.         }
    36.  
    37.         void Shoot()
    38.         {
    39.             for (int i = 0; i < instNumver; i++)
    40.             {
    41.                 int randomNumver = Random.Range(0, 3);
    42.  
    43.                 if (Physics.Raycast(transform.position, transform.forward + new Vector3(Random.Range(xMinRange, xMaxRange), Random.Range(yMinRange, yMaxRange), Random.Range(zMinRange, zMaxRange)), out hit, range))
    44.                 {
    45.                     if (hit.collider.gameObject.layer == LayerMask.NameToLayer("Ground"))
    46.                     {
    47.                         listObjComp.Add(instancerPrefab());
    48.                     }
    49.                 }
    50.             }
    51.         }
    52.  
    53.         private GPUInstancerPrefab instancerPrefab()
    54.         {
    55.             allocated = Instantiate(listObjs[Random.Range(0, listObjs.Count)], hit.point, Quaternion.Euler(0, Random.Range(0, 360), 0));
    56.  
    57.             allocated.GetComponent<TreeHitDamage>().spawnerObject = GetComponent<SpawnerObject>();
    58.             return allocated;
    59.         }
    60.  
    61.         private void Start()
    62.         {
    63.             InitializePrefab();
    64.         }
    65.  
    66.         public void InitializePrefab()
    67.         {
    68.             GPUInstancerAPI.RegisterPrefabInstanceList(GPUInstancerPrefabManager, listObjComp);
    69.             GPUInstancerAPI.InitializeGPUInstancer(GPUInstancerPrefabManager);
    70.         }
    71.  
    72.         public void RemovePrefabInstance(GameObject go)
    73.         {
    74.             if (go.TryGetComponent(out GPUInstancerPrefab gpuiPrefab))
    75.                 GPUInstancerAPI.RemovePrefabInstance(GPUInstancerPrefabManager, gpuiPrefab, false);
    76.         }
    77.     }
    78. }
     
  17. GurhanH

    GurhanH

    Joined:
    Apr 24, 2017
    Posts:
    389
    Hi there,
    Probably you application is GPU bound because of vertex processing. So you need to use a simpler/faster shader and/or reduce the amount of vertices.
    A common mistake is to have many instances of a tree with 100s of thousands of vertices, which is then too much to process for the GPU in a timely manner every a frame. Some examples of how to reduce the amount of vertices:
    Use LODs for distant objects.
    Simplify meshes where you do not need the detail.
    Use billboards for far away objects.
    Use LOD levels with less vertices for shadows.

    Hi there,
    You can use the AddPrefabInstance API method to add prefab instances at runtime. Avoid using InitializeGPUInstancer all the time. This method is, as the name suggests, for initialization. You normally only need to call it when you use GPUI API methods before the manager ran it's Awake and OnEnable methods. Also RegisterPrefabInstanceList method is for adding a list of prefabs to the manager before initialization. It is not a good practice to use it to add instances at runtime.

    So, use InitializeGPUInstancer API only once at the beginning before you add/remove instances. Also set the "forceNew" parameter to false to not make unnecessary operations, as such:

    Code (CSharp):
    1. private void Awake()
    2. {
    3.     inst = GameObject.FindGameObjectWithTag("Instance");
    4.     GPUInstancerPrefabManager = inst.GetComponent<GPUInstancerPrefabManager>();
    5.  
    6.     GPUInstancerAPI.InitializeGPUInstancer(GPUInstancerPrefabManager, false);
    7.  
    8.     Shoot();
    9. }
    And to add instances at runtime:
    Code (CSharp):
    1. public void InitializePrefab()
    2. {
    3.     foreach(var prafabInstance in listObjComp)
    4.     {
    5.         GPUInstancerAPI.AddPrefabInstance(GPUInstancerPrefabManager, prafabInstance, true);
    6.     }
    7. }
     
  18. sirleto

    sirleto

    Joined:
    Sep 9, 2019
    Posts:
    83
    Hello Gürhan and Burak,
    thanks for this great product!


    1.

    i have a simple test terrrain with 1 tree prefab, placed 101.000 times. i am using a prefab with LOD0,1,2 and then custom Billboard Distance at 95%. strangely randomly but half of the billboards are looking good the others seem very dark or black.

    upload_2022-11-21_22-19-54.png

    does this happen because of this warning?
    upload_2022-11-21_22-20-14.png

    or what setting did i misuse or do i need to correct?

    EDIT: i can see that it seems to be because of the normals being totally funky:
    upload_2022-11-22_23-34-51.png

    while the albedo does look correct:
    upload_2022-11-22_23-35-29.png


    2.
    also i dont see the Lod Fading at all, i guess my shader dosnt support it?


    3.
    in your DetailInstancing demo, with terrain and lots of foliage. it seems that the shader to render the foliage is forward, even though the camera is deferred. this means neither normals, nor any other g-buffer layer gets written to by the foliage.

    how can i change this shader? do you have one in your samples that is deferred which i can just swap to?


    thanks and greetings from switzerland
     
    Last edited: Nov 22, 2022
  19. kevinsyang17

    kevinsyang17

    Joined:
    Apr 3, 2018
    Posts:
    5

    Hi I'm already doing that. I used 4 LOD levels, the highest vertex count for a tree is 1200. I have the furtherest cull level being replaced by GPUI billboard.
     
  20. sirleto

    sirleto

    Joined:
    Sep 9, 2019
    Posts:
    83
    Try this to double check: if GPU bound, throw more (expensive) shaders on each pixel, should reduce your FPS. if instead CPU bound, which 99% of unity games are, change the GPU instancer billboards to appear much earlier, try allready with 40%.

    On windows, don't trust what unity shows you. The GPU ms shown in game view is only the render thread, check task manager -> details -> unity.exe -> GPU % (you need to add this column to the view first).

    A good way to see being GPU bound is the GPU instancer demo scene with detail grass (with lawnmower).
     
    GurhanH likes this.
  21. GurhanH

    GurhanH

    Joined:
    Apr 24, 2017
    Posts:
    389
    Hi there,
    and thank you for your kind words.
    It might be an issue with the billboard shader or the baked normal texture. Can you please email us an example project so we can investigate?
     
    sirleto likes this.
  22. sirleto

    sirleto

    Joined:
    Sep 9, 2019
    Posts:
    83
    send you the issue as example project, okay, i will do send it via email in the next day(s).


    4.
    and another problem i have in a less "plain" test scene with microverse is this:

    ArgumentNullException: Value cannot be null.
    Parameter name: shader
    UnityEngine.Material..ctor (UnityEngine.Shader shader) (at <86acb61e0d2b4b36bc20af11093be9a5>:0)

    GPUInstancer.GPUInstancerUtility.GetBillboardMaterial (GPUInstancer.GPUInstancerPrototype prototype) (at Assets/tools/GPUInstancer/Scripts/Core/Static/GPUInstancerUtility.cs:2278)
    GPUInstancer.GPUInstancerUtility.GenerateInstancedShadersForGameObject (GPUInstancer.GPUInstancerPrototype prototype) (at Assets/tools/GPUInstancer/Scripts/Core/Static/GPUInstancerUtility.cs:2656)
    GPUInstancer.GPUInstancerManager.CheckPrototypeChanges () (at Assets/tools/GPUInstancer/Scripts/Core/Contract/GPUInstancerManager.cs:367)
    GPUInstancer.GPUInstancerTerrainManager.CheckPrototypeChanges () (at Assets/tools/GPUInstancer/Scripts/Core/Contract/GPUInstancerTerrainManager.cs:140)
    GPUInstancer.GPUInstancerTreeManager.CheckPrototypeChanges () (at Assets/tools/GPUInstancer/Scripts/GPUInstancerTreeManager.cs:71)
    GPUInstancer.GPUInstancerManager.LateUpdate () (at Assets/tools/GPUInstancer/Scripts/Core/Contract/GPUInstancerManager.cs:261)

    any idea whats going on here? i mean, can you generally describe what these lines of code do, and what could be rough outlines?

    thanks
     
  23. sirleto

    sirleto

    Joined:
    Sep 9, 2019
    Posts:
    83
    on my above point 1: i was testing with just 1 prototype (tree), and now that i added another prototype (rock), it seems that this strange normal bug happens only on first prototype, my trees look correct now, the rocks not. if i move my game view camera somewhere, then go to scene view to inspect billboards of rocks far away from the game view camera, i can clearly tell that this strange normals still happen and it causes rocks to go black. but i would say it is not all, just some / most. maybe you have some drying-out detail-alike noise texture that causes some to be dark, and the problem is perhaps i dont supply any custom texture (yet?) and that causes it to be black (?)

    i still want to send you a repro project, but right now i first wanted to see if the hassle is worth the effort, and yes, indeed it is. the performance of GPU instancer is U N B E L I E V A B L E incredible :-D

    i have had trouble to have more than 30mio verts from my details, with range of 60m on my unity terrains. it causes my test scene to be below 1st frame (16ms) on RTX 2070 (i7 9700k).

    now with my details being run by gpu instancer, i can have range of 500m (billboards after aprox 100m), more density so i guess we are talking easily 100-500m tris, and it runs on 10ms.

    A M A Z I N G :)

    PS: i have found some other bugs, that i want to report you in a structured manner

    5.
    when i multi select detail managers (created for multiple terrains), i can click an action but its not triggered on all managers, only the last one selected. i think there is somewhere a for() loop missing in your code, to make it compatible to unity multi selection? it would be a quite important feature to me, as i have 20-40 terrains in my large scene and quite often need changes (e.g. adding new prototypes, etc)

    6.
    using GPU instancer on top of microverse is really a good workflow that might be adapted by more and more users in the future. but microverse is modifying prototypes directly on unity terrains, so we need to click "regenerate prototypes" in GPU instancer. would be cool if you guys can come up with a better (automated) way in the future.

    7.
    now i have added a third tree prototype, and something causes now that only the billboards for this tree are renderer (not my previous working tree + rock prototypes).

    i get this error
    IndexOutOfRangeException: Index was outside the bounds of the array.

    GPUInstancer.GPUInstancerUtility.AddBillboardToRuntimeData (GPUInstancer.GPUInstancerRuntimeData runtimeData) (at Assets/tools/GPUInstancer/Scripts/Core/Static/GPUInstancerUtility.cs:2172)
    GPUInstancer.GPUInstancerUtility.AddTreeInstanceRuntimeDataToList (System.Collections.Generic.List`1[T] runtimeDataList, System.Collections.Generic.List`1[T] treePrototypes, GPUInstancer.GPUInstancerTerrainSettings terrainSettings) (at Assets/tools/GPUInstancer/Scripts/Core/Static/GPUInstancerUtility.cs:1499)
    GPUInstancer.GPUInstancerTreeManager.InitializeRuntimeDataAndBuffers (System.Boolean forceNew) (at Assets/tools/GPUInstancer/Scripts/GPUInstancerTreeManager.cs:102)
    GPUInstancer.GPUInstancerManager.OnEnable () (at Assets/tools/GPUInstancer/Scripts/Core/Contract/GPUInstancerManager.cs:226)

    it is this line:
    int index = (runtimeData.instanceLODs.Count - 1) * 4;
    if (lodSize > runtimeData.lodSizes[index])

    and what happens, is that the count -1 * 4 equals to 16, but there are only 16 (so 0 to 15).
    the reason seems to be, that my rock has 5 lods, the two tree prefabs only 4 lod levels. so as soon as i removed 1 lod level from the rock, it works. would be great if you can fix that bug, as real world objects tend to have a mix of 1-4 lod levels, maybe cutting all down to 3 is possible, but not all can have more than 2 or even just the 1 main level.
     
    Last edited: Nov 25, 2022
  24. auroxi

    auroxi

    Joined:
    Dec 31, 2012
    Posts:
    85
    Hi great asset but I have one question; Is there a way that I can use random height and width to grass? Everything is the same, even though Unity terrain allows me to specify a min/max width/height values for variation.

    How can I get random width 0.25f to 1f and random height 0.5f to 1.5f for example? Is it possible?

    Thanks :)
     
  25. Rail9

    Rail9

    Joined:
    Feb 21, 2020
    Posts:
    23
    The object can now be destroyed, but the frame rate keeps dropping each time a tree is generated.

    Also, when the spawner object is instantiated after registering it with GPUInstancer, the frame rate drops to 0 when the number of randomly generated maps is increased, making it impossible to play the game.

    The number of trees itself is about 20,000, but at that point the frame rate is already below 10.
    How can we continue to generate objects without lowering the frame rate?
     
  26. GurhanH

    GurhanH

    Joined:
    Apr 24, 2017
    Posts:
    389
    Hi there,

    4.
    Looks like one of the billboard shaders can not be found: GPUInstancer/Shaders/Billboard/Billboard2DRendererStandard_GPUI
    If it is deleted, you can extract it form this package:
    GPUInstancer/Extras/GPUI_Shaders_Standard

    5-6.
    Thank you for the feedback, we will look into it.
    For now you can use the GeneratePrototypes method as such:
    Code (CSharp):
    1. myDetailManager.GeneratePrototypes(true);
    7.
    Thank you for reporting the bug, we will fix it with the next update.
    You can add these two lines to the code to solve the issue:
    Code (CSharp):
    1. int index = (runtimeData.instanceLODs.Count - 1) * 4;
    2. if (runtimeData.instanceLODs.Count > 4)
    3.     index = (runtimeData.instanceLODs.Count - 5) * 4 + 1;
    4. if (lodSize > runtimeData.lodSizes[index])
    Hi there,
    Detail Manager has the Detail Scale setting which allows you to edit the min-max width and height values. Then the resulting height and width is determined by Healthy/Dry Noise Texture and Noise Spread values (e.g. white is healthy/max scale, black is dry/min scale).

    Hi there,
    Please use the Profiler to see what is causing the slow down.
     
    sirleto likes this.
  27. Rail9

    Rail9

    Joined:
    Feb 21, 2020
    Posts:
    23
    I checked the profiler and it seems that rigidbody and collider are one of the reasons for the heavy weight, but I have set them as shown in this video to no avail.



    Also, when I checked with the collider turned off, the frame rate gradually decreased and I could not determine the cause.

    Furthermore, the cause of the problem of not being able to play when the number of maps lined up in an array increases is also unknown. If the sponer object is made active as a child object without registering it in GPUinstancer, there is no problem even when 50 x 50 maps are lined up.
     
  28. fax58

    fax58

    Joined:
    Dec 27, 2021
    Posts:
    13
    Hi,
    I would like to buy GPUI and would like to know if the billboard system can be used with buildings.
    I read in the documentation that "GPUI's billboard generator is mainly designed for use with trees", but can it be use also for bigger objects? Or your advice is to use a specific tool like impostors?
    Thanks in advance
     
  29. GurhanH

    GurhanH

    Joined:
    Apr 24, 2017
    Posts:
    389
    Hi there,
    GPUI will let you create billboards for buildings, but we do not recommend it. GPUI's billboard system has snapshots only from y-axis and does not have shadow casting. In most cases, for objects like buildings, it is better to use a more complex billboard system which has snapshots from multiple axes and has shaders with more features.
     
    sirleto likes this.
  30. fax58

    fax58

    Joined:
    Dec 27, 2021
    Posts:
    13
    Ok perfect, thank you for your reply!
     
  31. Sisay

    Sisay

    Joined:
    Dec 6, 2012
    Posts:
    48
    urp shader gpui
    redefinition of 'LightData'
    Compiling Subshader: 0, Pass: Universal Forward, Vertex program with <no keywords>
    Platform defines: SHADER_API_DESKTOP UNITY_ENABLE_DETAIL_NORMALMAP UNITY_ENABLE_REFLECTION_BUFFERS UNITY_LIGHTMAP_FULL_HDR UNITY_LIGHT_PROBE_PROXY_VOLUME UNITY_PBS_USE_BRDF1 UNITY_SPECCUBE_BLENDING UNITY_SPECCUBE_BOX_PROJECTION UNITY_USE_DITHER_MASK_FOR_ALPHABLENDED_SHADOWS
    Disabled keywords: DIRLIGHTMAP_COMBINED DOTS_INSTANCING_ON DYNAMICLIGHTMAP_ON FOG_EXP FOG_EXP2 FOG_LINEAR INSTANCING_ON LIGHTMAP_ON LIGHTMAP_SHADOW_MIXING PROCEDURAL_INSTANCING_ON SHADER_API_GLES30 SHADOWS_SHADOWMASK UNITY_ASTC_NORMALMAP_ENCODING UNITY_COLORSPACE_GAMMA UNITY_ENABLE_NATIVE_SHADOW_LOOKUPS UNITY_FRAMEBUFFER_FETCH_AVAILABLE UNITY_HALF_PRECISION_FRAGMENT_SHADER_REGISTERS UNITY_HARDWARE_TIER1 UNITY_HARDWARE_TIER2 UNITY_HARDWARE_TIER3 UNITY_LIGHTMAP_DLDR_ENCODING UNITY_LIGHTMAP_RGBM_ENCODING UNITY_METAL_SHADOWS_USE_POINT_FILTERING UNITY_NO_DXT5nm UNITY_NO_FULL_STANDARD_SHADER UNITY_NO_SCREENSPACE_SHADOWS UNITY_PBS_USE_BRDF2 UNITY_PBS_USE_BRDF3 UNITY_PRETRANSFORM_TO_DISPLAY_ORIENTATION UNITY_UNIFIED_SHADER_PRECISION_MODEL UNITY_VIRTUAL_TEXTURING _ADDITIONAL_LIGHTS _ADDITIONAL_LIGHTS_VERTEX _CLUSTERED_RENDERING _DISTANCEBLEND_ON _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE _MAIN_LIGHT_SHADOWS_SCREEN _WINDCOLORMIX_ON
     
    Last edited: Nov 30, 2022
  32. UrbanNuke

    UrbanNuke

    Joined:
    Jun 11, 2019
    Posts:
    13
    Hello!
    Am I right that material variations (described on that article) won't work if in prefab mesh renderer is turned off?
     
  33. kevinsyang17

    kevinsyang17

    Joined:
    Apr 3, 2018
    Posts:
    5
    Hi, I'm using the Serialize Registered Instances option to optimize my mass terrain of 250k trees (prefab). It works well but the trees no longer have collider and their scripts attached. Is there a way to enable collider and to get the Transform data of these serialized objects so I can assign collider at runtime?

    In addition, my game tracks which trees player have chopped off (removed from map). Is there a way to modify the serialized data such as inserting a new object, or removing one. Thanks!
     
  34. GurhanH

    GurhanH

    Joined:
    Apr 24, 2017
    Posts:
    389
    Hi there,
    Please make a bug report following this guide so we can investigate.

    Hi there,
    I did not understand the question. Can you please elaborate? GPUI renders the prefab instances so it disables the Mesh Renderer components already. Do you have another system that modifies the Mesh Renderers?

    Hi there,
    Serialize Registered Instances option will only render the instances. If you need to use scripts/colliders, you can use the API methods for No-GameObject Workflow and implement your own logic.
     
  35. PutridEx

    PutridEx

    Joined:
    Feb 3, 2021
    Posts:
    973
    Hi,
    does GPU instancer support motion vectors for indirect instancing? Unity recently added an API (2021.2) to add motion vectors to indirect instancing, already utilized by an asset that handles terrain detail rendering. Unity's terrain detail & trees does not support motion vectors currently.
     
  36. UrbanNuke

    UrbanNuke

    Joined:
    Jun 11, 2019
    Posts:
    13
    Could you please give instructions in what order should initialize prefabs in runtime?

    I create gameobject, add gpuInstancerPrefabManagerComponent in runtime.
    After registered prototypes
    AddPrototypeToManager -> InitializePrototype

    In for loop define variationBuffers
    DefinePrototypeVariationBuffer and AddVariation
    for each instance

    And finally call

    GPUInstancerAPI.RegisterPrefabInstanceList();
    GPUInstancerAPI.InitializeGPUInstancer();

    After that call UpdateVariation but nothing changed

    But if I recreate prototypes object
    ( 1. Delete gpu prefab instancer component from prefabs
    2. Create gpu instancer manager on scene
    3. Drag and drop prefabs to instancer, to create prototype
    4. Delete gpu instancer from scene)

    In that case UpdateVariation will work
    It looks like prototypes were cached
     
    Last edited: Dec 1, 2022
  37. kevinsyang17

    kevinsyang17

    Joined:
    Apr 3, 2018
    Posts:
    5
    Yes, so I'm asking is there a way to deserialize the serialized instance data so I can read position values from it.

    I read through the code that performs the editor serialization

    public void SerializeTransforms(GPUInstancerPrefabPrototype prefabPrototype)
    {
    if (_prefabManager == null || _prefabManager.registeredPrefabs == null)
    return;
    RegisteredPrefabsData registeredPrefabsData = _prefabManager.registeredPrefabs.Find(rpd => rpd.prefabPrototype == prefabPrototype);
    if (registeredPrefabsData == null || registeredPrefabsData.registeredPrefabs == null || registeredPrefabsData.registeredPrefabs.Count == 0)
    return;
    string transformString = "";
    foreach (GPUInstancerPrefab prefabInstance in registeredPrefabsData.registeredPrefabs)
    {
    transformString += GPUInstancerUtility.Matrix4x4ToString(prefabInstance.transform.localToWorldMatrix) + "\n";
    }
    transformString = transformString.Substring(0, transformString.Length - 2);
    TextAsset textAsset = new TextAsset(transformString);
    string assetPath = GPUInstancerConstants.GetDefaultPath() + GPUInstancerConstants.PROTOTYPES_SERIALIZED_PATH + prefabPrototype.name + ".asset";
    if (!System.IO.Directory.Exists(GPUInstancerConstants.GetDefaultPath() + GPUInstancerConstants.PROTOTYPES_SERIALIZED_PATH))
    {
    System.IO.Directory.CreateDirectory(GPUInstancerConstants.GetDefaultPath() + GPUInstancerConstants.PROTOTYPES_SERIALIZED_PATH);
    }
    AssetDatabase.CreateAsset(textAsset, assetPath);
    AssetDatabase.SaveAssets();
    prefabPrototype.isTransformsSerialized = true;
    prefabPrototype.serializedTransformData = textAsset;
    prefabPrototype.serializedTransformDataCount = registeredPrefabsData.registeredPrefabs.Count;
    foreach (GPUInstancerPrefab prefabInstance in registeredPrefabsData.registeredPrefabs)
    {
    DestroyImmediate(prefabInstance.gameObject);
    }
    registeredPrefabsData.registeredPrefabs.Clear();
    }


    I now know how to serialize my data to the matrix4x4 but how would I load in all the data the way GPUI does it, very fast and has no lag spike. Is there a tutorial or could you please suggest a sample code to load in the serialized data and have GPUI instancing rener it the same way the serialize transform option does.
     
    Last edited: Dec 3, 2022 at 8:19 AM
  38. Rail9

    Rail9

    Joined:
    Feb 21, 2020
    Posts:
    23
    Sorry, I may not have explained it well enough.

    The load on GPUInstancerPrefabManager.Update()[Invoke] keeps going up and the frames keep dropping a little bit even with tens of thousands of objects.

    Of course, this is the result without RigidBody and collider, and the load would be much higher if the two were attached.

    The load on the script we have prepared is stable, hovering around 30% of the total, so we are sure it is not a bolt-neck.

    When using RigidBody I referred to the video above, but I get the following error. Does it mean that object deletion is not supported?

    MissingReferenceException: The object of type 'GPUInstancerPrefab' has been destroyed but you are still trying to access it.
    Your script should either check if it is null or you should not destroy the object.
    GetComponent[T] () (at <24d45e813e524a99bfb7a145158a7980>:0)
    GPUInstancer.GPUInstancerModificationCollider.IsInsideCollider (GPUInstancer.GPUInstancerPrefab prefabInstance) (at Assets/GPUInstancer/Scripts/GPUInstancerModificationCollider.cs:77)
    GPUInstancer.GPUInstancerModificationCollider.Update () (at Assets/GPUInstancer/Scripts/GPUInstancerModificationCollider.cs:35)
     
  39. eggdog14

    eggdog14

    Joined:
    Feb 5, 2013
    Posts:
    1
  40. GurhanH

    GurhanH

    Joined:
    Apr 24, 2017
    Posts:
    389
    Hi there,
    No, it is currently not supported. But we will look into it.

    Most probably the issue is caused by the InitializeGPUInstancer call. When you call InitializeGPUInstancer, everything resets, so you loose the variations If you want to add instances at runtime, use the AddPrefabInstance API method instead of the RegisterPrefabInstanceList and InitializeGPUInstancer methods.

    Please look at the GPUInstancerPrefabManager.cs line 260-280 to see how GPUI reads this text asset.

    Hi there,
    I was able to recreate the error, and it will be fixed in the next update. Please see below how to solve the issue:

    Add the following code to GPUInstancerModificationCollider.cs after line 34
    Code (CSharp):
    1. if (prefabInstance == null)
    2. {
    3.     _enteredInstances.RemoveAt(i);
    4.     i--;
    5.     continue;
    6. }
    It should look like this:
    upload_2022-12-5_9-2-15.png

    Hi there,
    Please read this article which explains this subject in detail.
     
    eggdog14 and sirleto like this.
  41. sirleto

    sirleto

    Joined:
    Sep 9, 2019
    Posts:
    83
    Adding to the nice article about terrain details: GPU instancer is a bit slower than the second best terrain detail option: Advanced Terrain Grass asset. BUT only with comparisons of distances at less than 400m + it doesn't have shadows.

    If you want to do open world with 1000m view distances, then currently GPU instancer with billboarding is the fastest solution.

    If you feel it's slower in your setup/scene, then maybe you are doing defensively few terrain details. Try putting more and more prototypes, density, view distance and you will see that a great realistic look and feel makes unity terrain render in 15ms+ what GPU instancer can do in less than 5ms.

    Obviously, some devices and frame budgets don't allow for more than 2ms of terrain details, then you will only benefit from GPU instancer being super performant on trees (with billboarding easily 10.000m draw distances are less than 1ms).
     
  42. zetingq

    zetingq

    Joined:
    Dec 8, 2016
    Posts:
    23
    Hello, I have encountered some problems with the GPU Instancer plugin recently. Now the project uses the GPU Instancer plugin of unity2018.3.13 and 1.2.2. Due to project reasons, we cannot upgrade the version right now.

    There was no problem using the plug-in before. Recently, I made a new scene and used the GPU instancer. I found that the GPU Instancer plug-in does not work, and the frame rate is relatively low.

    We package the art scene into unity format and use it in the import project program. In the unity project of the imported project, the frame rate of the scene is very good.

    However, after the project engineering exe program imports the scene package, the frame rate is relatively low. Now I don't understand why this is happening.

    Do you have any suggestions for improving this question?