GPU Instancer:FAQ

From GurBu Wiki
Revision as of 22:00, 21 April 2019 by GurBu Admin (talk | contribs) (How Can I Use ShaderGraph shaders with GPUI?)
Jump to: navigation, search

About | Features | Getting Started | Terminology | Best Practices | F.A.Q.

General Questions


What are the Minimum Requirements?


To provide the fastest possible performance, GPU Instancer utilizes indirect GPU instancing using Unity's DrawMeshInstancedIndirect API and Compute Shaders. Following are the minimum requirements for GPU instancing and Compute Shader support:


  • DirectX 11 or DirectX 12 and Shader Model 5.0 GPU (Windows, Windows Store)
  • Metal (macOS, iOS)
  • OpenGL Core 4.3 (Windows, Linux)
  • Vulkan (Android, Windows, Linux)
  • OpenGL ES 3.1 (Android 8.0 Oreo or later)
  • Modern Consoles (PS4, Xbox One)


Please also note that even though some integrated graphics cards may satisfy these requirements, they may not provide the boost you can get from GPU Instancing. Therefore, hardware with a dedicated GPU is recommended.


How does GPU Instancer work?



The aim of GPUI is to provide an easy to use interface to use indirect instancing without having to go through the learning curves of (or extensive development times of) GPU programming and Compute Shaders. To provide this, GPUI analyzes a prefab (or Unity terrain) and uses indirect instancing to render its instances (or detail/tree prototypes). Upon sending the mesh and material data to the GPU once, GPUI creates various GPU buffers and dispatches Compute Shaders on every frame to manipulate the instance data in these buffers. This approach takes the load completely off the CPU and uses the GPU for all rendering processes - so that the CPU threads work more efficiently for game scripts. GPUI also uses different optimization techniques to effectively work on different platforms; so that whether the target platform is a high-end PC, VR, or a modern mobile device, GPUI provides the best indirect instancing strategy.


If you're not familiar with these concepts, you can take a look at the Terminology Page for more information. In any case, here is a basic primer on GPU instancing:


(Indirect) GPU instancing works by sending mesh/material data to the GPU in a single draw call. This reduces the amount of batching to one even if there are hundreds or even thousands of the same mesh/material combination. This removes the bottleneck that occurs when sending mesh and material data from CPU to the GPU, and results in higher fps if there are many of the same mesh-material combinations. That is, GPU instancing helps in scenarios where you have many instances of the same game object.


How is GPUI Different from the Unity Material GPU Instancing Option?



Untiy provides instancing support by using the "Enable GPU instancing" option in Unity Standard and Surface shaders. When you use this option, Unity will handle frustum culling and culling by baked occlusion maps automatically. However, when using this option, Unity will group together instances and issue a draw call for every 500 instances in Direct3D and 125 instances in OpenGL ES 3, OpenGL Core, and Metal. The reason for this limitation is that Unity is aiming to support as many devices as possible, and older devices have a smaller GPU buffer size.


Other options in Unity are the DrawMeshInstanced and the DrawMeshInstancedIndirect scripting APIs. The former allows for 1023 instances per batch, and the latter does not have a limit. However, when using both of these options, you need to manage frustum, occlusion and distance culling for your instances manually.


GPU Instancer uses the indirect instancing method in the background and manages all culling operations in the GPU by making use of Compute Shaders. Furthermore, GPUI gives you a user friendly interface to add indirect instancing support for your Prefabs (with LOD groups, child hierarchies etc.) and your Unity Terrains in a few clicks - without writing any code. Since GPUI automatically generates a copy of the original shader of the material that it configures to work with itself, you are also not limited to using the Standard and Surface shaders and can use most custom shaders out of the box with it.


GPUI also builds additional features on its core by allowing you to use shadows, select shadow LODs, add/remove/update instances automatically, generate billboards and a lot more. Advanced features also include support for a no-game object workflow through an easy to use scripting API.


How can I convert shaders manually to support GPU Instancer?



GPUI has a system that automatically generates a converted version of most shaders to work with itself. This system keeps track of shader changes and handles re-conversions automatically as well. This includes most of the shaders created by shader creation editors like Amplify Shader Editor. But in some special cases, it might be needed to change the shader manually to support GPU Instancer. GPUI detects if a shader is compatible with it and will not generate a separate shader if that is the case. Here is the information you need to manually edit your shaders to support GPUI.


Surface Shaders


...
SubShader {
    ...
    CGPROGRAM
    #include "UnityCG.cginc"
    #include "GPUInstancer/Shaders/Include/GPUInstancerInclude.cginc"
    #pragma instancing_options procedural:setupGPUI
    ...
    ENDCG
}
...


Since the #pragma multi_compile_instancing directive is automatically added to the generated code from surface shaders, you do not need to include it. However, if you have a additional passes (such as a shadowcaster pass), you need to add support to these passes as well (see Vertex/fragment Shaders below)


Vertex/fragment Shaders

For all passes:


...
Pass {
    ...
    CGPROGRAM
    #include "UnityCG.cginc"
    #include "GPUInstancer/Shaders/Include/GPUInstancerInclude.cginc"
    #pragma multi_compile_instancing
    #pragma instancing_options procedural:setupGPUI
    ...
    ENDCG
}
...


You also need to add instancing setup to your input structs and vertex functions if you don't already have it:


struct appdata_custom
{
    ...
    UNITY_VERTEX_INPUT_INSTANCE_ID
}


v2f vert( appdata_custom v )
{
    v2f o;
    UNITY_SETUP_INSTANCE_ID(v);
    ...
    return o;
}


SRP Shaders

You need to reference the SRP includes you need and add GPUI support afterwards. Here is an example which uses LWRP:

HLSLPROGRAM
...
#include "LWRP/ShaderLibrary/InputSurfacePBR.hlsl"
#include "LWRP/ShaderLibrary/LightweightPassLit.hlsl"
#include "GPUInstancer/Shaders/Include/GPUInstancerInclude.cginc"
#pragma instancing_options procedural:setupGPUI
ENDHLSL


Amplify Shader Editor directives

It is important to add support from the ASE window rather than the code since ASE would overwrite your changes if you save the shader again. You can use the following additional directives:


Amplify Shader Editor Directives for GPUI


What are the Build Settings for Android platforms?



Build Settings for Android


GPUI relies heavily on Compute Shaders for its operations in the GPU. In mobile platforms, Compute Shaders are usually supported by the higher-end devices. The requirement for Compute Shaders in the Android systems is at least Open GL ES 3.1 or the Vulkan API.


GPUI does not need any additional settings when targeting Vulkan; however, you need to enable Open GL ES 3.1 support when targeting the Open GL ES API.


To do this, you can simply enable the Require ES3.1 checkbox under:

Edit->Project Settings->Player->Other Settings.


Otherwise Unity will disable the Compute Shaders and your build will run without GPUI enabled.


Please also note that older versions of Unity have some bugs for some of the GPU models on Android devices. If you're working on an Android game, it is recommended to use the latest Unity version.


How can I Increase Billboard Visibility Distances Beyond Manager Limits?



The max billboard distance is tied to the Max Tree Distance property of the manager if you are using the Tree Manager - or if you are using the Prefab Manager, it is tied to the Max Distance property of the prototype. The Tree Manager limits you to 2500 where the Prefab Manager limits to 10000.

If you need more visibility distance, you can edit the limitations of the corresponding managers from the GPUI settings window: Edit -> Preferences -> GPU Instancer


How can I Setup my Instances to have Material Variations on them?



Material Variations on Instances of a Single Prototype


GPU Instancing works by drawing a single mesh and material combination multiple times on the screen. This is why GPUI creates its prototypes from Prefab definitions where it uses the mesh and material information for each renderer the Prefab has and issues drawcalls for them seperately. Thus, out of the box, there would not be any variations for the materials of the prefab instances. However, GPUI offers a solution for having material variations through the GPU Instancer API. The included demo scene ColorVariationsDemo is intended as an example usage of this, so you can take a look at it to get started. Please note, however, that this is an advanced feature and will require you to do some scripting and shader editing.


To setup instance based variations, you basically need to define a buffer, register this buffer to the GPUI prototype instances (and the Prefab Manager) and modify your shader to accept this buffer. The contents of the buffer (variations) can then be set and updated during runtime. Therefore, the setup has a C# scripting part and a shader scripting part:


1. On the MonoBehaviour Script:


Here you can define the buffer and register it to the GPUI instances and a Prefab Manager. You can then update the instances through the GPU Instancer API to make GPUI use this buffer for variations of the instance material. The following example generates a number of GPUI prototype instances, defines a color variations buffer and registers it to the GPUI instances in the Start method. It then updates the buffer with random colors in the Update method, making the generated instances change to a random color every update without breaking instancing. The required references are to the GPUI Prototype (the Prefab itself can be assigned for this since the GPUI prototype component lives on the Prefab) and the active Prefab Manager in the scene.


  1.  
  2.     public class ColorVariations : MonoBehaviour
  3.     {
  4.         // The reference to the Prototype (the prefab itself can be assigned here since the GPUI Prototype component lives on the Prefab).
  5.         public GPUInstancerPrefab prefab;
  6.         // The reference to the active Prefab Manager in the scene.
  7.         public GPUInstancerPrefabManager prefabManager;
  8.         // The count of instances that will be generated.
  9.         public int instances = 1000;
  10.         // The name of the buffer. Must be the same with the StructuredBuffer in the shader that the Mateiral will use. See: "ColorVariationShader_GPUI.shader".
  11.         private string bufferName = "colorBuffer";
  12.         // The List to hold the instances that will be generated.
  13.         private List<GPUInstancerPrefab> goList;
  14.         void Start()
  15.         {
  16.             goList = new List<GPUInstancerPrefab>();
  17.             // Define the buffer to the Prefab Manager.
  18.             if (prefabManager != null && prefabManager.isActiveAndEnabled)
  19.             {
  20.                 GPUInstancerAPI.DefinePrototypeVariationBuffer<Vector4>(prefabManager, prefab.prefabPrototype, bufferName);
  21.             }
  22.             // Generate instances inside a radius.
  23.             for (int i = 0; i < instances; i++)
  24.             {
  25.                 GPUInstancerPrefab prefabInstance = Instantiate(prefab);
  26.                 prefabInstance.transform.localPosition = Random.insideUnitSphere * 20;
  27.                 prefabInstance.transform.SetParent(transform);
  28.                 goList.Add(prefabInstance);
  29.                 // Register the variation buffer for this instance.
  30.                 prefabInstance.AddVariation(bufferName, (Vector4)Random.ColorHSV());
  31.             }
  32.             // Register the generated instances to the manager and initialize the manager.
  33.             if (prefabManager != null && prefabManager.isActiveAndEnabled)
  34.             {
  35.                 GPUInstancerAPI.RegisterPrefabInstanceList(prefabManager, goList);
  36.                 GPUInstancerAPI.InitializeGPUInstancer(prefabManager);
  37.             }
  38.         }
  39.         void Update()
  40.         {
  41.             // Update the variation buffer with a random set of colors every frame, thus changing instance colors per instance every frame.
  42.             GPUInstancerAPI.UpdateVariation(prefabManager, goList[Random.Range(0, goList.Count)], bufferName, (Vector4)Random.ColorHSV());
  43.         }
  44.     }
  45.  


The important parts are as follows:


Defining the name of the varitation buffer (it is important to notice that the name of this buffer must match the StructuredBuffer on the shader exactly):

        private string bufferName = "colorBuffer";


Defining the variation buffer to the Prefab Manager. Please note that you define which type of variation you will use while defining the prototype variation buffer to the manager. In this example, we use a [CODE]Vector4[/CODE] since we are using color variation. This is a generic method and you can read more on it from its API documentation.

        GPUInstancerAPI.DefinePrototypeVariationBuffer<Vector4>(prefabManager, prefab.prefabPrototype, bufferName);


Registering the variation buffer per instance:

        prefabInstance.AddVariation(bufferName, (Vector4)Random.ColorHSV());


And updating the variation buffer later on if you wish:

        GPUInstancerAPI.UpdateVariation(prefabManager, goList[Random.Range(0, goList.Count)], bufferName, (Vector4)Random.ColorHSV());


2. On the Material's Shader:


For this setup to work, you also need the shader that the material will use to recognize the buffer you have defined above. This can be achieved by defining a [CODE]StructuredBuffer[/CODE] property in the shader with exactly the same name as you defined the buffer in the MonoBehaviour script.


You can define the structured buffer among the shader properties as such:

  1.  
  2.         #if SHADER_API_D3D11
  3.         #ifdef UNITY_PROCEDURAL_INSTANCING_ENABLED       
  4.             StructuredBuffer<float4> colorBuffer;
  5.         #endif
  6.         #endif
  7.  


And then use it as you wish by referencing the instance by its unity_InstanceID from the gpuiTransformationMatrix StructuredBuffer. This is where the instance matrices are stored by GPUI in the GPU. The following example, in line with the color variations example, modifies the Albedo of the surface shader in the surf function with the variations buffer:


  1.  
  2.         void surf (Input IN, inout SurfaceOutputStandard o) {
  3.             float4 col = _Color;
  4.             #if SHADER_API_D3D11
  5.             #ifdef UNITY_PROCEDURAL_INSTANCING_ENABLED
  6.                     uint index = gpuiTransformationMatrix[unity_InstanceID];
  7.                     col = colorBuffer[index];
  8.             #endif
  9.             #endif
  10.             // Albedo comes from a texture tinted by color
  11.             fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * saturate(col);
  12.             o.Albedo = c.rgb;
  13.             // Metallic and smoothness come from slider variables
  14.             o.Metallic = _Metallic;
  15.             o.Smoothness = _Glossiness;
  16.             o.Alpha = c.a;
  17.         }
  18.  


The important part here is getting the variation buffer index of the instance by accessing the GPUI prototype instance matrices with the unity_InstanceID:

        uint index = gpuiTransformationMatrix[unity_InstanceID];


And using that index to access the variation in the buffer:

        col = colorBuffer[index];


How Can I (Automatically) Add/Remove Prototype Instances



GPU Instancer allows you to add and remove instances during runtime. This can be done automatically without writing any additional code, in which case GPUI will keep track of new instantiations (or destroying) of the prefab instances and will handle the prototype GPU buffers accordingly. For more control, you can also use the API to handle this yourself - or completely register and initialize the managers with exactly the instances you want. You can see below how to use each option:


The Auto. Add/Remove Instances Option


1. The easiest way to add/remove instances at runtime is to enable Auto. Add/Remove Instances option under the Runtime Settings.


When this is enabled, the Prefab Manager will add a component called GPUInstancerPrefabRuntimeHandler on the prefab object and will handle all runtime changes automatically when new instances are instantiated or existing ones are destroyed.


The Add/Remove Instances at Runtime Option


2. Optionally, you can add prefab instances through the GPU Instancer API methods AddPrefabInstance and RemovePrefabInstance.


Please keep in mind that the Add/Remove Instances At Runtime option should be enabled in the prototype definition for this API methods to work. Also, Extra Buffer Size should have a high enough number to add all the prefab instances generated at runtime.


3. Alternatively, you can use the GPU Instancer API to register the prefab instances and reinitialize the Prefab Manager for complete control. This can be done by first calling the RegisterPrefabInstanceList method and then calling the InitializeGPUInstancer method.


The following code demonstrates how this can be done:


using UnityEngine;
 
namespace GPUInstancer.Extras
{
    public class GPUIRegisterPrefabInstances : MonoBehaviour
    {
        // Keeping a static reference to the manager so it can be shared between scenes.
        public static GPUInstancerPrefabManager prefabManager;
        // The list of prefab instances in scene
        public List<GPUInstancerPrefab> prefabInstanceList;
 
 
        // In this example we fill the list in the Reset method which works when adding the component for the first time (or using the reset command in the inspector).
        // You can fill the list in any way you want.
        public void Reset()
        {
            // Add prefabs in the scene to the list
            prefabInstanceList = new List<GPUInstancerPrefab>(FindObjectsOfType<GPUInstancerPrefab>());
        }
 
        void Start()
        {
            // Find the prefab manager and set it to the static property
            if(prefabManager == null && GPUInstancerAPI.GetActiveManagers() != null)
            {
                GPUInstancerManager manager = GPUInstancerAPI.GetActiveManagers().Find(m => m is GPUInstancerPrefabManager);
                prefabManager = (GPUInstancerPrefabManager)manager;
            }
 
            // Register the prefab instance list to the manager
            if (prefabManager != null && prefabManager.isActiveAndEnabled)
            {
                GPUInstancerAPI.RegisterPrefabInstanceList(prefabManager, prefabInstanceList);
                GPUInstancerAPI.InitializeGPUInstancer(prefabManager);
            }
        }
    }
}


How Can I Use a no-GameObject Workflow?



GPU Instancer allows you to work with a no-GameObject workflow to maximize your scene performance. By using this workflow, you can render prefab instances without instantiating GameObjects and therefore not using any CPU time for them. Please not that this is an advanced feature and requires a good understanding of Transformation Matrices and GPU Instancing.


The basic idea behind this workflow is supplying an array of Matrix4x4s to the GPU Instancer API to initialize the instances. The included demo scene PrefabsWithoutGameObjects is designed to demonstrate an example usage of this workflow, so it can be a good starting point.


The below script is also is an example that demonstrates a basic usage. What this script does is to first initialize the GPU Instancer Prefab Manager with matrix data that represents transforms at ranfom positions inside a radius of 15 units in the Awake method. Then, if a key is pressed, it updates the matrices with new random positions:



using GPUInstancer;
 
public class NoGameObject : MonoBehaviour
{
    // reference to Prefab Manager
    public GPUInstancerPrefabManager prefabManager;
    // reference to prefab
    public GPUInstancerPrefab prefab;
    // size of array and buffers
    public int bufferSize;
 
    // transform data array
    private Matrix4x4[] _matrix4x4Array;
 
    // Use this for initialization
    void Awake ()
    {
        // initialize the array with the max size
        _matrix4x4Array = new Matrix4x4[bufferSize];
        // set the data of the array
        for (int i = 0; i < _matrix4x4Array.Length; i++)
            _matrix4x4Array[i] = Matrix4x4.TRS(Random.insideUnitSphere * 15, Quaternion.identity, Vector3.one);
        // initialize the buffers with array
        GPUInstancerAPI.InitializeWithMatrix4x4Array(prefabManager, prefab.prefabPrototype, _matrix4x4Array);
    }
 
    private void Update()
    {
        if (Input.anyKeyDown)
        {
            // change the data of the array
            for (int i = 0; i < _matrix4x4Array.Length; i++)
                _matrix4x4Array[i] = Matrix4x4.TRS(Random.insideUnitSphere * 15, Quaternion.identity, Vector3.one);
            // update buffers
            GPUInstancerAPI.UpdateVisibilityBufferWithMatrix4x4Array(prefabManager, prefab.prefabPrototype, _matrix4x4Array);
        }
    }
}
 


How Can I Change the Camera at Runtime?


GPUI keeps a reference to the scene camera, and auto-detects the cameras with the "Main Camera" tag. You can also specify a specific camera for use with a given manager. However, if you wish to switch cameras at runtime, you need to call the SetCamera API method from your script right after you enable/instantiate your new camera.


Alternatively, you can add the included GPUInstancerCameraHandler component on your cameras to have GPUI automatically handle this for you.


Troubleshooting


Instances don't Show / Show at Incorrect Locations when Using a Custom Shader



If you are using a custom vertex/fragment shader, the shader needs to be setup for instancing. GPUI sets shaders up for working with itself, but cannot automate general instancing setup since there is no good way to generalize this.


If you are using a custom shader on your instances, or if you are using an asset from the Asset Store, this will most likely be the reason why your instances do not show correctly. To setup your shaders with GPUI in this case, you can take a look at setting vertex/fragment shaders up manually to work with GPU Instancer.


Shadows on the Prefab Instances Look Blocky/Wrong



Using the Shadow Pass of the Original Shader


By default, GPUI uses a custom, lightweight "shadows only" shader to render the shadows of the prototypes that are defined on a Prefab Manager. Using this shader helps increase the shadow performance slightly more; especially if the original shader is using a shadow pass generated by a surface shader (using the addshadow directive). In most cases this shader is enough to render the prototype flawlessly; however, if the original shader uses vertex animation and/or alpha cutoff, then the shadows might not look right. Typical cases of this are when adding tree prefabs. In these cases you can enable the Shadow with Original Shader option under the Shadow settings for the prototype (in the Prefab Manager). This will use the shadow pass of the original shaders of the prefab and the shadows should then look right.



Batch Counts are Higher than without GPUI



Increased batch counts usually means that there are prototypes with very few instance counts that are registered to the Prefab Manager.


GPUI works best with prefabs that have high instance counts. The reason for this is related to the nature of GPU instancing. Since prefabs with low instance counts will not gain a noticeable performance boost from GPU Instancing, it is usually better to let Unity handle their rendering. Unity uses draw call batching techniques on the background (such as dynamic batching). These techniques depend on the CPU to run and tax their operations on the CPU memory. When there are many instances of the same prefabs, these operations turn out to be too costly and the reduction in batch counts dwarf in comparison to GPU Instancing. But where the instance counts are noticeably low, the cost on the CPU when using these techniques becomes trivial - yet they will still reduce batch and draw call counts. While using GPU instancing, on the other hand, since meshes are not combined, every mesh/material combination will always be one draw call.


In short, the lowest batch counts (and the best performance gain) can be achieved by using GPUI with high instance counts. Therefore, rendering everything with GPUI where some prefabs have very few instance counts is not recommended.


The rule of thumb to keep in mind is to have only the prefabs that have high instance counts rendering with GPUI, while minimizing the amount of prototypes as much as possible. For more information on instance counts, you can check the page for best practices.


GPUI not working while targeting Android platforms



Disabling OpenGL ES 3.0 Emulation in Android Projects

GPU Instancer requires OpenGL ES 3.1 or Vulkan API for Android platforms. Unity Editor currently can not emulate GLES 3.1. It emulates GLES 3.0 which does not support Compute Shaders. So currently it is not possible to test GPU Instancer with GLES 3.1 at Unity Editor.


If you leave the Emulation mode on, and if you try running your scene with a GPUI manager in it, Unity will throw the following error in the console and GPUI will be deactivated:


Target Graphics API does not support Compute Shaders. Please refer to Minimum Requirements on GPUInstancer/ReadMe.txt for detailed information.


In order to solve this, you can use Unity Editor in No Emulation mode as shown in the picture to the right and make your mobile tests with a build. The editor will then run in the original mode of your operating system (e.g. Direct3D 11 on Windows).


Please also note that Unity switches back to the emulation mode regularly, so you might need to switch back often.


For information on how to use build settings for Android devices you can look at this section.



With Projectors in my Scene, I see Artifacts/Performance Hit


Unity Projectors can cause a performance hit and/or artifacts on the screen when using GPU Instancer. The reason for this is related to how Unity handles projectors internally. There is, however, a very easy solution to workaround this by using Layers. The steps are as follows:


Creating a Layer for GPUI

1) You can start by creating a new Layer (e.g. GPUIRenderingLayer)

Defining the Rendering Layer for Prefabs

2) Setting this Layer to the prefabs are enough for prefab instancing with Prefab Manager, Tree Manager and for the prefab type prototypes in the Detail Manager.

Defining the Rendering Layer in the Manager

3) For the Detail Textures, you can set this new Layer to the Detail Texture Layer of the Detail Manager.

Ignoring the GPUI Rendering Layer in the Projector

4) You can then set the projector to ignore the GPUI Rendering Layer as shown in the picture to the left.


Transperent Materials Look Inside-Out/Back-to-Front when Used on Prototypes


Materials with transparency can result in unexpected behavior when used with GPU Instancer. Since GPU instancing works by treating all instances as the same, the GPU draws one mesh multiple times without any regard to draw ordering. This will result in wrong draw orders while using transparency, and the typical result would be inside-out or back-to-front looking prototype instances. This can be solved by implementing a form of OIT approximation. Please note, however, that GPUI currently does not include such an implementation so if you are willing to use transparent objects with GPUI, you should manually implement an OIT solution.


Screen Space Post Processing Effects (e.g. Ambient Occlusion) Look Wrong



Graphics Settings Custom Depth Shader Setup

If you are having issues with some post processing effects (like Ambient Occlusion) in Forward Rendering mode, you can use the included custom depth-normals shader instead of the built in one to solve these issues. You can find this shader in:


GPUInstancer/Shaders/Internal-DepthNormalsTexture_GPUI.shader


Please note that this is only necessary in Forward Rendering mode. This shader is almost the the same with the built in version of the Unity depth-normals shader, and only includes the GPUI setup additionally. You can thus safely use this shader without effecting anything else.


Compatibility with Other Assets

GPU Instancer has out of the box compatibility with some other Unity Asset Store assets, and also integration with some others. With some assets, however, it will simply not work together because of the nature of the two assets. Assets that rely on Mesh Combining or those that come with their own GPU Instancing solutions fall into this later category.


As Gurbu Technologies, we are always up to integration with other assets. If you are an Asset Store developer, please contact us and we can investigate possible integrations.


In this section, you can find a list of assets that are already known to work or not with GPUI.


Amplify Shader Editor

GPUI works out of the box with ASE shaders. GPUI creates a copy of your ASE shader and configures it to work with itself. Any updates will also be reflected on the created shader. At runtime, GPUI use this converted shader for its prototypes where the material has the original shader. However, if you don't want your shader to be duplicated, you can also check the above description to see how you can manually use the directives necessary for GPUI in your ASE shaders.


Please note, however, that Unity does not support tessellation and GPU instancing at the same time, so tessellated ASE shaders won't work with GPUI as well.


Amplify Impostors

Using a Custom Billboard (Amplify Impostors)


GPUI works out of the box with Amplify Impostors. You can define any Impostor Prefab as a GPUI prototype. GPUI will also use the impostor if it is an a LOD level of the prefab.


Alternatively, you can use the Use Custom Billboard option under the Billboard Settings in all managers and assign the mesh and material that you can generate with Amplify Impostors. This will allow you to keep using GPUI's billboard settings for the selected prototype but render the billboard with Amplify Impostors.


Amplify Occlusion

GPUI works out of the box with Amplify Occlusion in Deferred rendering mode. In Forward rendering, you can use the included custom depth-normals shader instead of the Unity built-in one. This setup is described here.


MapMagic World Generator

GPUI - MapMagic Integration

GPU Instancer has a built-in integration with MapMagic World Generator. To use GPUI in your MapMagic Terrains, , you can use the following menu item:


Tools -> GPU Instancer -> Integration -> Add MapMagic Integration


Please note that GPUI checks the scripting define symbols in the player settings to determine whether you have MapMagic installed. If you don't have MapMagic, you will not see this menu item. If you have MapMagic, however, and if you don't see the integration menu item, the scripting define symbol might not be added to your player settings for some reason. In that case, you can manually add it by opening your Unity Player Settings (Edit -> Project Settings -> Player) and entering ;MAPMAGIC at the end of your scripting define symbols line.


When you add the integration from the menu, GPUI will add a GameObject to your scene with the options showing you what you want to import to GPUI from the MapMagic generation ruleset in the scene. You can then check the options you wish and click Import. This will turn the integration object into what looks like a combined version of all the GPUI Managers, and you can use the settings as you normally would in those managers.


This is all you need to do to render your MapMagic terrains with GPUI. If at any time you change or edit the MapMagic ruleset, you can click Import again and the changes will reflect on the integration as well.


Gaia

GPUI - Gaia Integration

GPU Instancer has a built-in integration with Gaia. If you wish to use Gaia generated terrains with GPUI, you can use the GX tab under the Gaia Manager to add all desired GPUI managers to your scene.


When you add the The Detail and the Tree Managers this way, it is exactly like adding them from the GPU Instancer Menu. They are there only for convenience.


When you use Add the Prefab Manager from the GX menu, however, GPUI shows you a window that is similar to GPUI's Scene Prefab Importer tool. Using this window, however, instead of the prefab instances in your scene, you are presented with prefab instances that come from the Gaia ruleset that that is defined in the scene.


We recommended you to check the Best Practices Page before using Gaia with GPUI - especially the section on Detail instancing - to get the most out of GPUI.


AQUAS

AQUAS works out of the box with GPU Instancer. However, the AQUAS water planes use two Projectors for water caustics - and these projectors cause a performance hit when using GPU Instancer. There is a very easy solution to overcome this; the steps are as follows:


Creating a Layer for GPUI

1) GPUI includes a feature where you can define a layer that you wish to use for the texture details in the Detail Manager. So you can create a new Layer first (e.g. GPUIRenderingLayer)

Defining the Rendering Layer in the Manager

2) Then set this new Layer to the Detail Texture Layer of the Detail Manager. For all prefabs, GPUI uses the layer of the prefab for this purpose.

Aquas Caustics Projectors

3) Finally, you can set this as the Ignore Layer for the AQUAS caustic projectors. There are two of them under the Aquas Water Plane object.

Ignoring the GPUI Rendering Layer in the Projector

4) You can set ignore the GPUI Rendering Layer as shown in the picture to the left.


Vegetation Studio / Vegetation Studio (Pro)

Since Vegetation Studio uses its own rendering system, it is not possible for GPUI and VS to work on the same objects. However, if you wish to use VS and GPUI together, you can still use GPUI for prefabs that you do not define in VS.