├── .gitignore ├── Demos-DrawMeshInstancedIndirect ├── Assets │ ├── FlyCamera.cs │ ├── FlyCamera.cs.meta │ ├── InstancedIndirectAppend.meta │ ├── InstancedIndirectAppend │ │ ├── InstancedIndirectComputeAppend.cs │ │ ├── InstancedIndirectComputeAppend.cs.meta │ │ ├── InstancedIndirectComputeAppend.mat │ │ ├── InstancedIndirectComputeAppend.mat.meta │ │ ├── InstancedIndirectComputeAppend.shader │ │ ├── InstancedIndirectComputeAppend.shader.meta │ │ ├── InstancedIndirectComputeAppend.unity │ │ ├── InstancedIndirectComputeAppend.unity.meta │ │ ├── InstancedIndirectComputeAppendKernel.compute │ │ └── InstancedIndirectComputeAppendKernel.compute.meta │ ├── InstancedIndirectCompute.meta │ ├── InstancedIndirectCompute │ │ ├── ComputeKernel.compute │ │ ├── ComputeKernel.compute.meta │ │ ├── InstancedIndirectComputeExample.cs │ │ ├── InstancedIndirectComputeExample.cs.meta │ │ ├── InstancedIndirectComputeExample.unity │ │ ├── InstancedIndirectComputeExample.unity.meta │ │ ├── InstancedIndirectComputeSurfaceShader.shader │ │ ├── InstancedIndirectComputeSurfaceShader.shader.meta │ │ ├── InstancedIndirectComputeTest.mat │ │ └── InstancedIndirectComputeTest.mat.meta │ ├── InstancedIndirectExample.meta │ ├── InstancedIndirectExample │ │ ├── Floor.mat │ │ ├── Floor.mat.meta │ │ ├── InstancedIndirectExample.cs │ │ ├── InstancedIndirectExample.cs.meta │ │ ├── InstancedIndirectExample.unity │ │ ├── InstancedIndirectExample.unity.meta │ │ ├── InstancedIndirectSurfaceShader.shader │ │ ├── InstancedIndirectSurfaceShader.shader.meta │ │ ├── InstancedIndirectTest.mat │ │ └── InstancedIndirectTest.mat.meta │ ├── InstancedIndirectNoBuffer.meta │ ├── InstancedIndirectNoBuffer │ │ ├── InstancedIndirectNoBuffer.cs │ │ ├── InstancedIndirectNoBuffer.cs.meta │ │ ├── InstancedIndirectNoBuffer.unity │ │ ├── InstancedIndirectNoBuffer.unity.meta │ │ ├── InstancedIndirectNoBufferSurfaceShader.shader │ │ ├── InstancedIndirectNoBufferSurfaceShader.shader.meta │ │ ├── InstancedIndirectNoBufferTest.mat │ │ └── InstancedIndirectNoBufferTest.mat.meta │ ├── InstancedIndirectShadowsIssue.meta │ └── InstancedIndirectShadowsIssue │ │ ├── InstancedIndirectShadowsIssue.cs │ │ ├── InstancedIndirectShadowsIssue.cs.meta │ │ ├── InstancedIndirectShadowsIssue.mat │ │ ├── InstancedIndirectShadowsIssue.mat.meta │ │ ├── InstancedIndirectShadowsIssue.unity │ │ ├── InstancedIndirectShadowsIssue.unity.meta │ │ ├── InstancedIndirectShadowsIssueSurfaceShader.shader │ │ └── InstancedIndirectShadowsIssueSurfaceShader.shader.meta └── ProjectSettings │ ├── AudioManager.asset │ ├── ClusterInputManager.asset │ ├── DynamicsManager.asset │ ├── EditorBuildSettings.asset │ ├── EditorSettings.asset │ ├── GraphicsSettings.asset │ ├── InputManager.asset │ ├── NavMeshAreas.asset │ ├── NetworkManager.asset │ ├── Physics2DSettings.asset │ ├── ProjectSettings.asset │ ├── ProjectVersion.txt │ ├── QualitySettings.asset │ ├── TagManager.asset │ ├── TimeManager.asset │ └── UnityConnectSettings.asset ├── LICENSE ├── README.md └── Untitled.png /.gitignore: -------------------------------------------------------------------------------- 1 | # =============== # 2 | # Unity generated # 3 | # =============== # 4 | Temp/ 5 | Library/ 6 | Build/ 7 | prints/ 8 | #StreamingAssets/ 9 | #StreamingAssets.meta 10 | 11 | # ===================================== # 12 | # Visual Studio / MonoDevelop generated # 13 | # ===================================== # 14 | ExportedObj/ 15 | StreamingAssets/ 16 | obj/ 17 | *.svd 18 | *.userprefs 19 | *.csproj 20 | *.pidb 21 | *.suo 22 | *.sln 23 | *.user 24 | *.unityproj 25 | *.booproj 26 | 27 | # ============ # 28 | # OS generated # 29 | # ============ # 30 | .DS_Store 31 | .DS_Store? 32 | ._* 33 | .Spotlight-V100 34 | .Trashes 35 | ehthumbs.db 36 | Thumbs.db -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/FlyCamera.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using UnityEngine.EventSystems; 4 | 5 | public class FlyCamera : MonoBehaviour 6 | { 7 | public Terrain terrain; 8 | public EventSystem eventSystem; 9 | 10 | /** 11 | * Writen by Windexglow 11-13-10. Use it, edit it, steal it I don't care. 12 | * Converted to C# 27-02-13 - no credit wanted. 13 | * Added resetRotation, RF control, improved initial mouse position, 2015-03-11 - Roi Danton. 14 | * Simple flycam I made, since I couldn't find any others made public. 15 | * Made simple to use (drag and drop, done) for regular keyboard layout 16 | * wasdrf : basic movement 17 | * shift : Makes camera accelerate 18 | * space : Moves camera on X and Z axis only. So camera doesn't gain any height 19 | */ 20 | 21 | public float minSpeed = 0.5f; 22 | public float mainSpeed = 10f; // Regular speed. 23 | public float shiftMultiplier = 2f; // Multiplied by how long shift is held. Basically running. 24 | public float maxShift = 100000f; // Maximum speed when holding shift. 25 | public float camSens = .35f; // Camera sensitivity by mouse input. 26 | private Vector3 lastMouse = new Vector3(Screen.width / 2, Screen.height / 2, 0); // Kind of in the middle of the screen, rather than at the top (play). 27 | private float totalRun = 1.0f; 28 | 29 | public bool clickToMove = true; 30 | public bool keepItAboveTerrain = true; 31 | public float unitsAboveTerrain = 4f; 32 | 33 | void Start() 34 | { 35 | // Get terrain reference 36 | terrain = Terrain.activeTerrain; 37 | eventSystem = EventSystem.current; 38 | } 39 | 40 | 41 | void Update() 42 | { 43 | // This should prevent the mouse input from getting through the UI. 44 | //if (eventSystem.IsPointerOverGameObject() && !dragging) 45 | // return; 46 | 47 | mainSpeed += Input.GetAxis("Mouse ScrollWheel") * mainSpeed; 48 | if (mainSpeed < minSpeed) 49 | mainSpeed = minSpeed; 50 | 51 | if (clickToMove) 52 | { 53 | if (!Input.GetMouseButton(0)) 54 | { 55 | return; 56 | } 57 | 58 | if (Input.GetMouseButtonDown(0)) 59 | { 60 | lastMouse = Input.mousePosition; 61 | return; 62 | } 63 | } 64 | 65 | // Mouse input. 66 | lastMouse = Input.mousePosition - lastMouse; 67 | lastMouse = new Vector3(-lastMouse.y * camSens, lastMouse.x * camSens, 0); 68 | lastMouse = new Vector3(transform.eulerAngles.x + lastMouse.x, transform.eulerAngles.y + lastMouse.y, 0); 69 | transform.eulerAngles = lastMouse; 70 | lastMouse = Input.mousePosition; 71 | 72 | 73 | // Keyboard commands. 74 | Vector3 p = getDirection(); 75 | if (Input.GetKey(KeyCode.LeftShift)) 76 | { 77 | //totalRun += Time.deltaTime; 78 | totalRun += Time.unscaledDeltaTime; 79 | p = p * totalRun * shiftMultiplier; 80 | p.x = Mathf.Clamp(p.x, -maxShift, maxShift); 81 | p.y = Mathf.Clamp(p.y, -maxShift, maxShift); 82 | p.z = Mathf.Clamp(p.z, -maxShift, maxShift); 83 | } 84 | else 85 | { 86 | totalRun = Mathf.Clamp(totalRun * 0.5f, 1f, 1000f); 87 | p = p * mainSpeed; 88 | } 89 | 90 | //p = p * Time.deltaTime; 91 | p = p * Time.unscaledDeltaTime; 92 | Vector3 newPosition = transform.position; 93 | if (Input.GetKey(KeyCode.V)) 94 | { //If player wants to move on X and Z axis only 95 | transform.Translate(p); 96 | newPosition.x = transform.position.x; 97 | newPosition.z = transform.position.z; 98 | transform.position = newPosition; 99 | } 100 | else 101 | { 102 | transform.Translate(p); 103 | } 104 | 105 | if (keepItAboveTerrain) 106 | { 107 | // Keep it above terrain 108 | newPosition = transform.position; 109 | newPosition.y = terrain.SampleHeight(newPosition) + terrain.transform.position.y + unitsAboveTerrain; 110 | if (transform.position.y <= newPosition.y) 111 | transform.position = newPosition; 112 | } 113 | 114 | 115 | } 116 | 117 | private Vector3 getDirection() 118 | { 119 | Vector3 p_Velocity = new Vector3(); 120 | if (Input.GetKey(KeyCode.W)) 121 | { 122 | p_Velocity += new Vector3(0, 0, 1); 123 | } 124 | if (Input.GetKey(KeyCode.S)) 125 | { 126 | p_Velocity += new Vector3(0, 0, -1); 127 | } 128 | if (Input.GetKey(KeyCode.A)) 129 | { 130 | p_Velocity += new Vector3(-1, 0, 0); 131 | } 132 | if (Input.GetKey(KeyCode.D)) 133 | { 134 | p_Velocity += new Vector3(1, 0, 0); 135 | } 136 | if (Input.GetKey(KeyCode.R)) 137 | { 138 | p_Velocity += new Vector3(0, 1, 0); 139 | } 140 | if (Input.GetKey(KeyCode.F)) 141 | { 142 | p_Velocity += new Vector3(0, -1, 0); 143 | } 144 | return p_Velocity; 145 | } 146 | 147 | public void resetRotation(Vector3 lookAt) 148 | { 149 | transform.LookAt(lookAt); 150 | } 151 | } -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/FlyCamera.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fe47489b52b15664eb0af627736ac604 3 | timeCreated: 1488639142 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectAppend.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 636c2f9965fab2b4691166dd9f10f782 3 | folderAsset: yes 4 | timeCreated: 1488639118 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectAppend/InstancedIndirectComputeAppend.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEngine.Rendering; 3 | 4 | /// 5 | /// This demo shows the use of Compute Shaders to update the object's positions. 6 | /// The buffer is stored and updated directly in GPU. 7 | /// The append buffer can be used when there is an unknown output buffer size. 8 | /// 9 | public class InstancedIndirectComputeAppend : MonoBehaviour 10 | { 11 | public int instanceCount = 100000; 12 | public Mesh instanceMesh; 13 | public Material instanceMaterial; 14 | 15 | public ShadowCastingMode castShadows = ShadowCastingMode.Off; 16 | public bool receiveShadows = false; 17 | 18 | public ComputeShader positionComputeShader; 19 | private int positionComputeKernelId; 20 | 21 | private ComputeBuffer positionAppendBuffer; 22 | private ComputeBuffer argsBuffer; 23 | 24 | void Start() 25 | { 26 | /// it's 5 args: index count per instance, instance count, start index location, base vertex location, start instance location. 27 | argsBuffer = new ComputeBuffer(5, sizeof(uint), ComputeBufferType.IndirectArguments); 28 | CreateBuffers(); 29 | } 30 | 31 | void Update() 32 | { 33 | // Update position buffer 34 | UpdateBuffers(); 35 | 36 | // Render - same old, only now we'll have argsBuffer with the count set from the append result. 37 | Graphics.DrawMeshInstancedIndirect(instanceMesh, 0, instanceMaterial, instanceMesh.bounds, argsBuffer, 0, null, castShadows, receiveShadows); 38 | } 39 | 40 | void UpdateBuffers() 41 | { 42 | /// reset the append buffer counter, 43 | /// this is important! otherwise we'll keep appending to a buffer indefinitely! 44 | positionAppendBuffer.SetCounterValue(0); 45 | 46 | /// TODO this only works with POT, integral sqrt vals 47 | int bs = instanceCount / 64; 48 | positionComputeShader.Dispatch(positionComputeKernelId, bs, 1, 1); 49 | positionComputeShader.SetBuffer(positionComputeKernelId, "positionBuffer", positionAppendBuffer); 50 | positionComputeShader.SetFloat("_Dim", Mathf.Sqrt(instanceCount)); 51 | 52 | /// as we don't know exactly how many positions were output, we use this function 53 | /// to copy the count from positionAppendBuffer to argsBuffer, which will be used for rendering. 54 | /// The offset 4 is because the instance count is placed in args[1] for the DrawMeshInstancedIndirect 55 | /// + info https://docs.unity3d.com/ScriptReference/ComputeBuffer.CopyCount.html 56 | ComputeBuffer.CopyCount(positionAppendBuffer, argsBuffer, 4); 57 | } 58 | 59 | void CreateBuffers() 60 | { 61 | if (instanceCount < 1) 62 | instanceCount = 1; 63 | 64 | instanceCount = Mathf.ClosestPowerOfTwo(instanceCount); 65 | 66 | positionComputeKernelId = positionComputeShader.FindKernel("CSPositionKernel"); 67 | instanceMesh.bounds = new Bounds(Vector3.zero, Vector3.one * 10000f); 68 | 69 | if (positionAppendBuffer != null) 70 | positionAppendBuffer.Release(); 71 | 72 | /// note the compute buffer append type! 73 | positionAppendBuffer = new ComputeBuffer(instanceCount, 16, ComputeBufferType.Append); 74 | positionAppendBuffer.SetCounterValue(0); 75 | instanceMaterial.SetBuffer("positionBuffer", positionAppendBuffer); 76 | 77 | // indirect args 78 | uint numIndices = (instanceMesh != null) ? (uint)instanceMesh.GetIndexCount(0) : 0; 79 | argsBuffer.SetData(new uint[5] { numIndices, (uint)instanceCount, 0, 0, 0 }); 80 | } 81 | 82 | void OnDisable() 83 | { 84 | if (positionAppendBuffer != null) 85 | positionAppendBuffer.Release(); 86 | positionAppendBuffer = null; 87 | 88 | if (argsBuffer != null) 89 | argsBuffer.Release(); 90 | argsBuffer = null; 91 | } 92 | 93 | void OnGUI() 94 | { 95 | GUI.Label(new Rect(265, 12, 200, 30), "Instance Count: " + instanceCount.ToString("N0")); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectAppend/InstancedIndirectComputeAppend.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 52cf2243e9b0a364294cf131471bfbcf 3 | timeCreated: 1481682952 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectAppend/InstancedIndirectComputeAppend.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttvertex/Unity-InstancedIndirectExamples/960604d705bd3f4db09773c07c4b36ac5e8dc295/Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectAppend/InstancedIndirectComputeAppend.mat -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectAppend/InstancedIndirectComputeAppend.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9b63139e12467e443a7a64ff79a90db2 3 | timeCreated: 1481683451 4 | licenseType: Pro 5 | NativeFormatImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectAppend/InstancedIndirectComputeAppend.shader: -------------------------------------------------------------------------------- 1 | Shader "Instanced/InstancedIndirectComputeAppend" 2 | { 3 | Properties{ 4 | _MainTex("Albedo (RGB)", 2D) = "white" {} 5 | _Glossiness("Smoothness", Range(0,1)) = 0.5 6 | _Metallic("Metallic", Range(0,1)) = 0.0 7 | } 8 | SubShader{ 9 | Tags{ "RenderType" = "Opaque" } 10 | LOD 200 11 | 12 | CGPROGRAM 13 | // Physically based Standard lighting model 14 | #pragma surface surf Standard addshadow 15 | #pragma multi_compile_instancing 16 | #pragma instancing_options procedural:setup 17 | 18 | sampler2D _MainTex; 19 | 20 | struct Input { 21 | float2 uv_MainTex; 22 | }; 23 | 24 | #ifdef UNITY_PROCEDURAL_INSTANCING_ENABLED 25 | StructuredBuffer positionBuffer; 26 | #endif 27 | 28 | void setup() 29 | { 30 | #ifdef UNITY_PROCEDURAL_INSTANCING_ENABLED 31 | /// Positions are calculated in the compute shader. 32 | /// here we just use them. 33 | float4 position = positionBuffer[unity_InstanceID]; 34 | float scale = position.w; 35 | 36 | unity_ObjectToWorld._11_21_31_41 = float4(scale, 0, 0, 0); 37 | unity_ObjectToWorld._12_22_32_42 = float4(0, scale, 0, 0); 38 | unity_ObjectToWorld._13_23_33_43 = float4(0, 0, scale, 0); 39 | unity_ObjectToWorld._14_24_34_44 = float4(position.xyz, 1); 40 | unity_WorldToObject = unity_ObjectToWorld; 41 | unity_WorldToObject._14_24_34 *= -1; 42 | unity_WorldToObject._11_22_33 = 1.0f / unity_WorldToObject._11_22_33; 43 | #endif 44 | } 45 | 46 | half _Glossiness; 47 | half _Metallic; 48 | 49 | float rand(in float2 uv) 50 | { 51 | float2 noise = (frac(sin(dot(uv, float2(12.9898, 78.233) * 2.0)) * 43758.5453)); 52 | return abs(noise.x + noise.y) * 0.5; 53 | } 54 | 55 | void surf(Input IN, inout SurfaceOutputStandard o) 56 | { 57 | float4 col = 1.0f; 58 | #ifdef UNITY_PROCEDURAL_INSTANCING_ENABLED 59 | col = float4(unity_ObjectToWorld._11, rand(unity_ObjectToWorld._14_34), 1, 1); 60 | #endif 61 | 62 | fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * col; 63 | o.Albedo = c.rgb; 64 | o.Metallic = _Metallic; 65 | o.Smoothness = _Glossiness; 66 | o.Alpha = c.a; 67 | } 68 | ENDCG 69 | } 70 | FallBack "Diffuse" 71 | } 72 | -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectAppend/InstancedIndirectComputeAppend.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 191cd539e00de8e42b0fae7aa25149e3 3 | timeCreated: 1481683330 4 | licenseType: Pro 5 | ShaderImporter: 6 | defaultTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectAppend/InstancedIndirectComputeAppend.unity: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttvertex/Unity-InstancedIndirectExamples/960604d705bd3f4db09773c07c4b36ac5e8dc295/Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectAppend/InstancedIndirectComputeAppend.unity -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectAppend/InstancedIndirectComputeAppend.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7382f704d6d6e61478142b52efe0938f 3 | timeCreated: 1481683507 4 | licenseType: Pro 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectAppend/InstancedIndirectComputeAppendKernel.compute: -------------------------------------------------------------------------------- 1 | #pragma kernel CSPositionKernel 2 | 3 | #define thread_group_size_x 64 4 | #define thread_group_size_y 1 5 | 6 | AppendStructuredBuffer positionBuffer; 7 | 8 | float _Dim; 9 | 10 | float rand(in float2 uv) 11 | { 12 | float2 noise = (frac(sin(dot(uv ,float2(12.9898,78.233)*2.0)) * 43758.5453)); 13 | return abs(noise.x + noise.y) * 0.5; 14 | } 15 | 16 | [numthreads(thread_group_size_x, thread_group_size_y, 1)] 17 | void CSPositionKernel (uint3 id : SV_DispatchThreadID) 18 | { 19 | // this uv assumes the # of instances is _Dim * _Dim. 20 | // so we calculate the uv inside a grid of _Dim x _Dim elements. 21 | float2 uv = float2( floor(id.x / _Dim) / _Dim, (id.x % (int)_Dim) / _Dim); 22 | 23 | // in this case, _Dim can be replaced by the grid size in the world 24 | float4 pos = float4((uv.x - 0.5) * _Dim * 2, 0, (uv.y - 0.5) * _Dim * 2, rand(uv)); 25 | 26 | /// in this example, not all threads will output a position. 27 | /// note: the output order is not deterministic! 28 | if (rand(uv) > 0.5) 29 | positionBuffer.Append(pos); 30 | } -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectAppend/InstancedIndirectComputeAppendKernel.compute.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3febdf7cfed45cd4b9684d48d46ecdb7 3 | timeCreated: 1488637146 4 | licenseType: Free 5 | ComputeShaderImporter: 6 | currentAPIMask: 4 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectCompute.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: eeb63abdc338ebb4aaf4ffed4ee4e471 3 | folderAsset: yes 4 | timeCreated: 1488639118 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectCompute/ComputeKernel.compute: -------------------------------------------------------------------------------- 1 | #pragma kernel CSPositionKernel 2 | 3 | #define thread_group_size_x 64 4 | #define thread_group_size_y 1 5 | 6 | RWStructuredBuffer positionBuffer; 7 | 8 | float _Dim; 9 | float _Time; 10 | 11 | float rand(in float2 uv) 12 | { 13 | float2 noise = (frac(sin(dot(uv ,float2(12.9898,78.233)*2.0)) * 43758.5453)); 14 | return abs(noise.x + noise.y) * 0.5; 15 | } 16 | 17 | void rotate2D(inout float2 v, float r) 18 | { 19 | float s, c; 20 | sincos(r, s, c); 21 | v = float2(v.x * c - v.y * s, v.x * s + v.y * c); 22 | } 23 | 24 | [numthreads(thread_group_size_x, thread_group_size_y, 1)] 25 | void CSPositionKernel (uint3 id : SV_DispatchThreadID) 26 | { 27 | // this uv assumes the # of instances is _Dim * _Dim. 28 | // so we calculate the uv inside a grid of _Dim x _Dim elements. 29 | float2 uv = float2( floor(id.x / _Dim) / _Dim, (id.x % (int)_Dim) / _Dim); 30 | 31 | // in this case, _Dim can be replaced by the grid size in the world 32 | float4 pos = float4((uv.x - 0.5) * _Dim, 0, (uv.y - 0.5) * _Dim, rand(uv)); 33 | 34 | float rotation = pos.w * pos.w * _Time * 0.5f; 35 | rotate2D(pos.xz, rotation); 36 | 37 | positionBuffer[id.x] = pos; 38 | } -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectCompute/ComputeKernel.compute.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 64221cf7b19dbb84c8efa10de9ceb22f 3 | timeCreated: 1488637146 4 | licenseType: Free 5 | ComputeShaderImporter: 6 | currentAPIMask: 4 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectCompute/InstancedIndirectComputeExample.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEngine.Rendering; 3 | 4 | /// 5 | /// This demo shows the use of Compute Shaders to update the object's 6 | /// positions. The buffer is stored and updated directly in GPU. 7 | /// 8 | public class InstancedIndirectComputeExample : MonoBehaviour 9 | { 10 | public int instanceCount = 100000; 11 | public Mesh instanceMesh; 12 | public Material instanceMaterial; 13 | 14 | public ShadowCastingMode castShadows = ShadowCastingMode.Off; 15 | public bool receiveShadows = false; 16 | 17 | public ComputeShader positionComputeShader; 18 | private int positionComputeKernelId; 19 | 20 | private ComputeBuffer positionBuffer; 21 | private ComputeBuffer argsBuffer; 22 | private ComputeBuffer colorBuffer; 23 | 24 | private uint[] args = new uint[5] { 0, 0, 0, 0, 0 }; 25 | 26 | void Start() 27 | { 28 | argsBuffer = new ComputeBuffer(5, sizeof(uint), ComputeBufferType.IndirectArguments); 29 | CreateBuffers(); 30 | } 31 | 32 | void Update() 33 | { 34 | // Update position buffer 35 | UpdateBuffers(); 36 | 37 | // Render 38 | Graphics.DrawMeshInstancedIndirect(instanceMesh, 0, instanceMaterial, instanceMesh.bounds, argsBuffer, 0, null, castShadows, receiveShadows); 39 | } 40 | 41 | void UpdateBuffers() 42 | { 43 | positionComputeShader.SetFloat("_Time", Time.time); 44 | 45 | /// TODO this only works with POT, integral sqrt vals 46 | int bs = instanceCount / 64; 47 | positionComputeShader.Dispatch(positionComputeKernelId, bs, 1, 1); 48 | } 49 | 50 | void CreateBuffers() 51 | { 52 | if ( instanceCount < 1 ) instanceCount = 1; 53 | 54 | instanceCount = Mathf.ClosestPowerOfTwo(instanceCount); 55 | 56 | positionComputeKernelId = positionComputeShader.FindKernel("CSPositionKernel"); 57 | instanceMesh.bounds = new Bounds(Vector3.zero, Vector3.one * 10000f); 58 | 59 | // Positions & Colors 60 | if (positionBuffer != null) positionBuffer.Release(); 61 | if (colorBuffer != null) colorBuffer.Release(); 62 | 63 | positionBuffer = new ComputeBuffer(instanceCount, 16); 64 | colorBuffer = new ComputeBuffer(instanceCount, 16); 65 | 66 | Vector4[] colors = new Vector4[instanceCount]; 67 | for (int i = 0; i < instanceCount; i++) 68 | colors[i] = Random.ColorHSV(); 69 | 70 | colorBuffer.SetData(colors); 71 | 72 | instanceMaterial.SetBuffer("positionBuffer", positionBuffer); 73 | instanceMaterial.SetBuffer("colorBuffer", colorBuffer); 74 | 75 | // indirect args 76 | uint numIndices = (instanceMesh != null) ? (uint)instanceMesh.GetIndexCount(0) : 0; 77 | args[0] = numIndices; 78 | args[1] = (uint)instanceCount; 79 | argsBuffer.SetData(args); 80 | 81 | positionComputeShader.SetBuffer(positionComputeKernelId, "positionBuffer", positionBuffer); 82 | positionComputeShader.SetFloat("_Dim", Mathf.Sqrt(instanceCount)); 83 | } 84 | 85 | void OnDisable() 86 | { 87 | if (positionBuffer != null) positionBuffer.Release(); 88 | positionBuffer = null; 89 | 90 | if (colorBuffer != null) colorBuffer.Release(); 91 | colorBuffer = null; 92 | 93 | if (argsBuffer != null) argsBuffer.Release(); 94 | argsBuffer = null; 95 | } 96 | 97 | void OnGUI() 98 | { 99 | GUI.Label(new Rect(265, 12, 200, 30), "Instance Count: " + instanceCount.ToString("N0")); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectCompute/InstancedIndirectComputeExample.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 51ad6be56c44c0c4ba3af455446d6a86 3 | timeCreated: 1481682952 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectCompute/InstancedIndirectComputeExample.unity: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttvertex/Unity-InstancedIndirectExamples/960604d705bd3f4db09773c07c4b36ac5e8dc295/Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectCompute/InstancedIndirectComputeExample.unity -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectCompute/InstancedIndirectComputeExample.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1ef00fd5ea063284889beac71679c1d6 3 | timeCreated: 1481683507 4 | licenseType: Pro 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectCompute/InstancedIndirectComputeSurfaceShader.shader: -------------------------------------------------------------------------------- 1 | Shader "Instanced/InstancedIndirectCompute" 2 | { 3 | Properties{ 4 | _MainTex("Albedo (RGB)", 2D) = "white" {} 5 | _Glossiness("Smoothness", Range(0,1)) = 0.5 6 | _Metallic("Metallic", Range(0,1)) = 0.0 7 | } 8 | SubShader{ 9 | Tags{ "RenderType" = "Opaque" } 10 | LOD 200 11 | 12 | CGPROGRAM 13 | // Physically based Standard lighting model 14 | #pragma surface surf Standard addshadow 15 | #pragma multi_compile_instancing 16 | #pragma instancing_options procedural:setup 17 | 18 | sampler2D _MainTex; 19 | 20 | struct Input { 21 | float2 uv_MainTex; 22 | }; 23 | 24 | #ifdef UNITY_PROCEDURAL_INSTANCING_ENABLED 25 | StructuredBuffer positionBuffer; 26 | StructuredBuffer colorBuffer; 27 | #endif 28 | 29 | void setup() 30 | { 31 | #ifdef UNITY_PROCEDURAL_INSTANCING_ENABLED 32 | /// Positions are calculated in the compute shader. 33 | /// here we just use them. 34 | float4 position = positionBuffer[unity_InstanceID]; 35 | float scale = position.w; 36 | 37 | unity_ObjectToWorld._11_21_31_41 = float4(scale, 0, 0, 0); 38 | unity_ObjectToWorld._12_22_32_42 = float4(0, scale, 0, 0); 39 | unity_ObjectToWorld._13_23_33_43 = float4(0, 0, scale, 0); 40 | unity_ObjectToWorld._14_24_34_44 = float4(position.xyz, 1); 41 | unity_WorldToObject = unity_ObjectToWorld; 42 | unity_WorldToObject._14_24_34 *= -1; 43 | unity_WorldToObject._11_22_33 = 1.0f / unity_WorldToObject._11_22_33; 44 | #endif 45 | } 46 | 47 | half _Glossiness; 48 | half _Metallic; 49 | 50 | void surf(Input IN, inout SurfaceOutputStandard o) 51 | { 52 | float4 col = 1.0f; 53 | 54 | #ifdef UNITY_PROCEDURAL_INSTANCING_ENABLED 55 | col = colorBuffer[unity_InstanceID]; 56 | #else 57 | col = float4(0, 0, 1, 1); 58 | #endif 59 | fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * col; 60 | o.Albedo = c.rgb; 61 | o.Metallic = _Metallic; 62 | o.Smoothness = _Glossiness; 63 | o.Alpha = c.a; 64 | } 65 | ENDCG 66 | } 67 | FallBack "Diffuse" 68 | } 69 | -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectCompute/InstancedIndirectComputeSurfaceShader.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 311a9917696a65246b07034b0f71d336 3 | timeCreated: 1481683330 4 | licenseType: Pro 5 | ShaderImporter: 6 | defaultTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectCompute/InstancedIndirectComputeTest.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttvertex/Unity-InstancedIndirectExamples/960604d705bd3f4db09773c07c4b36ac5e8dc295/Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectCompute/InstancedIndirectComputeTest.mat -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectCompute/InstancedIndirectComputeTest.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 782c69a42fb2ab743ac6fa696c8a2e26 3 | timeCreated: 1481683451 4 | licenseType: Pro 5 | NativeFormatImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectExample.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9abacd4c603193f48aacbb65cec9a28b 3 | folderAsset: yes 4 | timeCreated: 1481682941 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectExample/Floor.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttvertex/Unity-InstancedIndirectExamples/960604d705bd3f4db09773c07c4b36ac5e8dc295/Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectExample/Floor.mat -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectExample/Floor.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0a72a31b07277f7449c3b1ab27e785fa 3 | timeCreated: 1481766471 4 | licenseType: Pro 5 | NativeFormatImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectExample/InstancedIndirectExample.cs: -------------------------------------------------------------------------------- 1 | // https://docs.unity3d.com/560/Documentation/ScriptReference/Graphics.DrawMeshInstancedIndirect.html 2 | 3 | using UnityEngine; 4 | 5 | public class InstancedIndirectExample : MonoBehaviour 6 | { 7 | public int instanceCount = 100000; 8 | public Mesh instanceMesh; 9 | public Material instanceMaterial; 10 | 11 | private int cachedInstanceCount = -1; 12 | private ComputeBuffer positionBuffer; 13 | private ComputeBuffer argsBuffer; 14 | private ComputeBuffer colorBuffer; 15 | 16 | private uint[] args = new uint[5] { 0, 0, 0, 0, 0 }; 17 | 18 | void Start() 19 | { 20 | argsBuffer = new ComputeBuffer(5, sizeof(uint), ComputeBufferType.IndirectArguments); 21 | UpdateBuffers(); 22 | } 23 | 24 | void Update() 25 | { 26 | // Update starting position buffer 27 | if (cachedInstanceCount != instanceCount) UpdateBuffers(); 28 | 29 | // Pad input 30 | if (Input.GetAxisRaw("Horizontal") != 0.0f) instanceCount = (int)Mathf.Clamp(instanceCount + Input.GetAxis("Horizontal") * 40000, 1.0f, 5000000.0f); 31 | 32 | // Render 33 | // instanceMaterial.SetBuffer("positionBuffer", positionBuffer); 34 | Graphics.DrawMeshInstancedIndirect(instanceMesh, 0, instanceMaterial, new Bounds(Vector3.zero, new Vector3(100.0f, 100.0f, 100.0f)), argsBuffer); 35 | } 36 | 37 | void OnGUI() 38 | { 39 | GUI.Label(new Rect(265, 12, 200, 30), "Instance Count: " + instanceCount.ToString("N0")); 40 | instanceCount = (int)GUI.HorizontalSlider(new Rect(25, 20, 200, 30), (float)instanceCount, 1.0f, 5000000.0f); 41 | } 42 | 43 | void UpdateBuffers() 44 | { 45 | if ( instanceCount < 1 ) instanceCount = 1; 46 | 47 | // Positions & Colors 48 | if (positionBuffer != null) positionBuffer.Release(); 49 | if (colorBuffer != null) colorBuffer.Release(); 50 | 51 | positionBuffer = new ComputeBuffer(instanceCount, 16); 52 | colorBuffer = new ComputeBuffer(instanceCount, 4*4); 53 | 54 | Vector4[] positions = new Vector4[instanceCount]; 55 | Vector4[] colors = new Vector4[instanceCount]; 56 | 57 | for (int i=0; i < instanceCount; i++) 58 | { 59 | float angle = Random.Range(0.0f, Mathf.PI * 2.0f); 60 | float distance = Random.Range(20.0f, 100.0f); 61 | float height = Random.Range(-2.0f, 2.0f); 62 | float size = Random.Range(0.05f, 0.25f); 63 | positions[i] = new Vector4(Mathf.Sin(angle) * distance, height, Mathf.Cos(angle) * distance, size); 64 | colors[i] = new Vector4( Random.value, Random.value, Random.value, 1f ); 65 | } 66 | 67 | positionBuffer.SetData(positions); 68 | colorBuffer.SetData(colors); 69 | 70 | instanceMaterial.SetBuffer("positionBuffer", positionBuffer); 71 | instanceMaterial.SetBuffer("colorBuffer", colorBuffer); 72 | 73 | // indirect args 74 | uint numIndices = (instanceMesh != null) ? (uint)instanceMesh.GetIndexCount(0) : 0; 75 | args[0] = numIndices; 76 | args[1] = (uint)instanceCount; 77 | argsBuffer.SetData(args); 78 | 79 | cachedInstanceCount = instanceCount; 80 | } 81 | 82 | void OnDisable() 83 | { 84 | if (positionBuffer != null) positionBuffer.Release(); 85 | positionBuffer = null; 86 | 87 | if (colorBuffer != null) colorBuffer.Release(); 88 | colorBuffer = null; 89 | 90 | if (argsBuffer != null) argsBuffer.Release(); 91 | argsBuffer = null; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectExample/InstancedIndirectExample.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 93f8ec55e72f462458e09232944f33c1 3 | timeCreated: 1481682952 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectExample/InstancedIndirectExample.unity: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttvertex/Unity-InstancedIndirectExamples/960604d705bd3f4db09773c07c4b36ac5e8dc295/Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectExample/InstancedIndirectExample.unity -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectExample/InstancedIndirectExample.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d94c05110437ffe408a2ee32769362b7 3 | timeCreated: 1481683507 4 | licenseType: Pro 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectExample/InstancedIndirectSurfaceShader.shader: -------------------------------------------------------------------------------- 1 | Shader "Instanced/InstancedIndirect" 2 | { 3 | Properties{ 4 | _MainTex("Albedo (RGB)", 2D) = "white" {} 5 | _Glossiness("Smoothness", Range(0,1)) = 0.5 6 | _Metallic("Metallic", Range(0,1)) = 0.0 7 | } 8 | SubShader{ 9 | Tags{ "RenderType" = "Opaque" } 10 | LOD 200 11 | 12 | CGPROGRAM 13 | // Physically based Standard lighting model 14 | #pragma surface surf Standard addshadow 15 | #pragma multi_compile_instancing 16 | #pragma instancing_options procedural:setup 17 | 18 | sampler2D _MainTex; 19 | 20 | struct Input { 21 | float2 uv_MainTex; 22 | }; 23 | 24 | #ifdef UNITY_PROCEDURAL_INSTANCING_ENABLED 25 | StructuredBuffer positionBuffer; 26 | StructuredBuffer colorBuffer; 27 | #endif 28 | 29 | 30 | void rotate2D(inout float2 v, float r) 31 | { 32 | float s, c; 33 | sincos(r, s, c); 34 | v = float2(v.x * c - v.y * s, v.x * s + v.y * c); 35 | } 36 | 37 | void setup() 38 | { 39 | #ifdef UNITY_PROCEDURAL_INSTANCING_ENABLED 40 | float4 data = positionBuffer[unity_InstanceID]; 41 | 42 | float rotation = data.w * data.w * _Time.y * 0.5f; 43 | rotate2D(data.xz, rotation); 44 | 45 | unity_ObjectToWorld._11_21_31_41 = float4(data.w, 0, 0, 0); 46 | unity_ObjectToWorld._12_22_32_42 = float4(0, data.w, 0, 0); 47 | unity_ObjectToWorld._13_23_33_43 = float4(0, 0, data.w, 0); 48 | unity_ObjectToWorld._14_24_34_44 = float4(data.xyz, 1); 49 | unity_WorldToObject = unity_ObjectToWorld; 50 | unity_WorldToObject._14_24_34 *= -1; 51 | unity_WorldToObject._11_22_33 = 1.0f / unity_WorldToObject._11_22_33; 52 | #endif 53 | } 54 | 55 | half _Glossiness; 56 | half _Metallic; 57 | 58 | void surf(Input IN, inout SurfaceOutputStandard o) 59 | { 60 | float4 col = 1.0f; 61 | 62 | #ifdef UNITY_PROCEDURAL_INSTANCING_ENABLED 63 | //col.gb = (float)(unity_InstanceID % 256) / 255.0f; 64 | col = colorBuffer[unity_InstanceID]; 65 | #else 66 | //col.gb = float4(0, 0, 1, 1); 67 | col = float4(0, 0, 1, 1); 68 | #endif 69 | 70 | 71 | 72 | fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * col; 73 | o.Albedo = c.rgb; 74 | o.Metallic = _Metallic; 75 | o.Smoothness = _Glossiness; 76 | o.Alpha = c.a; 77 | } 78 | ENDCG 79 | } 80 | FallBack "Diffuse" 81 | } 82 | -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectExample/InstancedIndirectSurfaceShader.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 971e564f0c289ad49b0cdce97a9daf38 3 | timeCreated: 1481683330 4 | licenseType: Pro 5 | ShaderImporter: 6 | defaultTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectExample/InstancedIndirectTest.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttvertex/Unity-InstancedIndirectExamples/960604d705bd3f4db09773c07c4b36ac5e8dc295/Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectExample/InstancedIndirectTest.mat -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectExample/InstancedIndirectTest.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0a0f2521dca606b47b5a8ece5d77aadf 3 | timeCreated: 1481683451 4 | licenseType: Pro 5 | NativeFormatImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectNoBuffer.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 38754f0d2a2e3b744af39dd6fae2aae4 3 | folderAsset: yes 4 | timeCreated: 1488639118 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectNoBuffer/InstancedIndirectNoBuffer.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEngine.Rendering; 3 | 4 | /// 5 | /// This demo shows the use of the procedural instancing features to render objects 6 | /// without need of any position buffer. The values are calculated direclty inside the 7 | /// shader. 8 | /// The color buffer is used for debug only. 9 | /// 10 | public class InstancedIndirectNoBuffer : MonoBehaviour 11 | { 12 | public int gridDim = 1000; 13 | public int instanceCount = 0; 14 | public Mesh instanceMesh; 15 | public Material instanceMaterial; 16 | 17 | public ShadowCastingMode castShadows = ShadowCastingMode.Off; 18 | public bool receiveShadows = false; 19 | 20 | private ComputeBuffer argsBuffer; 21 | private ComputeBuffer colorBuffer; 22 | 23 | private uint[] args = new uint[5] { 0, 0, 0, 0, 0 }; 24 | 25 | void Start() 26 | { 27 | instanceCount = gridDim * gridDim; 28 | argsBuffer = new ComputeBuffer(5, sizeof(uint), ComputeBufferType.IndirectArguments); 29 | CreateBuffers(); 30 | } 31 | 32 | void Update() 33 | { 34 | Graphics.DrawMeshInstancedIndirect(instanceMesh, 0, instanceMaterial, instanceMesh.bounds, argsBuffer, 0, null, castShadows, receiveShadows); 35 | } 36 | 37 | void CreateBuffers() 38 | { 39 | if ( instanceCount < 1 ) instanceCount = 1; 40 | 41 | //instanceCount = Mathf.ClosestPowerOfTwo(instanceCount); 42 | instanceMesh.bounds = new Bounds(Vector3.zero, Vector3.one * 10000f); //avoid culling 43 | 44 | /// Colors - for debug only 45 | if (colorBuffer != null) colorBuffer.Release(); 46 | 47 | colorBuffer = new ComputeBuffer(instanceCount, 16); 48 | 49 | Vector4[] colors = new Vector4[instanceCount]; 50 | for (int i = 0; i < instanceCount; i++) 51 | colors[i] = Random.ColorHSV(); 52 | 53 | colorBuffer.SetData(colors); 54 | 55 | instanceMaterial.SetBuffer("colorBuffer", colorBuffer); 56 | 57 | // indirect args 58 | uint numIndices = (instanceMesh != null) ? (uint)instanceMesh.GetIndexCount(0) : 0; 59 | args[0] = numIndices; 60 | args[1] = (uint)instanceCount; 61 | argsBuffer.SetData(args); 62 | 63 | Shader.SetGlobalFloat("_Dim", gridDim); 64 | } 65 | 66 | void OnDisable() 67 | { 68 | if (colorBuffer != null) colorBuffer.Release(); 69 | colorBuffer = null; 70 | 71 | if (argsBuffer != null) argsBuffer.Release(); 72 | argsBuffer = null; 73 | } 74 | 75 | void OnGUI() 76 | { 77 | GUI.Label(new Rect(265, 12, 200, 30), "Instance Count: " + instanceCount.ToString("N0")); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectNoBuffer/InstancedIndirectNoBuffer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 20f1e530bbaf9124281b78e6988b83f8 3 | timeCreated: 1481682952 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectNoBuffer/InstancedIndirectNoBuffer.unity: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttvertex/Unity-InstancedIndirectExamples/960604d705bd3f4db09773c07c4b36ac5e8dc295/Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectNoBuffer/InstancedIndirectNoBuffer.unity -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectNoBuffer/InstancedIndirectNoBuffer.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b70673dfc77f1de46a1df6867043cb24 3 | timeCreated: 1481683507 4 | licenseType: Pro 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectNoBuffer/InstancedIndirectNoBufferSurfaceShader.shader: -------------------------------------------------------------------------------- 1 | Shader "Instanced/InstancedIndirectNoBuffer" 2 | { 3 | Properties{ 4 | _MainTex("Albedo (RGB)", 2D) = "white" {} 5 | _Glossiness("Smoothness", Range(0,1)) = 0.5 6 | _Metallic("Metallic", Range(0,1)) = 0.0 7 | } 8 | SubShader{ 9 | Tags{ "RenderType" = "Opaque" } 10 | LOD 200 11 | 12 | CGPROGRAM 13 | // Physically based Standard lighting model 14 | #pragma surface surf Standard addshadow 15 | #pragma multi_compile_instancing 16 | #pragma instancing_options procedural:setup 17 | 18 | sampler2D _MainTex; 19 | 20 | struct Input { 21 | float2 uv_MainTex; 22 | }; 23 | 24 | #ifdef UNITY_PROCEDURAL_INSTANCING_ENABLED 25 | StructuredBuffer colorBuffer; 26 | #endif 27 | float _Dim; 28 | 29 | float rand(in float2 uv) 30 | { 31 | float2 noise = (frac(sin(dot(uv ,float2(12.9898,78.233)*2.0)) * 43758.5453)); 32 | return abs(noise.x + noise.y) * 0.5; 33 | } 34 | 35 | void rotate2D(inout float2 v, float r) 36 | { 37 | float s, c; 38 | sincos(r, s, c); 39 | v = float2(v.x * c - v.y * s, v.x * s + v.y * c); 40 | } 41 | 42 | void setup() 43 | { 44 | #ifdef UNITY_PROCEDURAL_INSTANCING_ENABLED 45 | // this uv assumes the # of instances is _Dim * _Dim. 46 | // so we calculate the uv inside a grid of _Dim x _Dim elements. 47 | float2 uv = float2( floor(unity_InstanceID / _Dim) / _Dim, (unity_InstanceID % (int)_Dim) / _Dim); 48 | // in this case, _Dim can be replaced by the size in the world 49 | float4 position = float4((uv.x - 0.5) * _Dim, 0, (uv.y - 0.5) * _Dim, rand(uv)); 50 | float scale = position.w; 51 | 52 | float rotation = scale * scale * _Time.y * 0.5f; 53 | rotate2D(position.xz, rotation); 54 | 55 | unity_ObjectToWorld._11_21_31_41 = float4(scale, 0, 0, 0); 56 | unity_ObjectToWorld._12_22_32_42 = float4(0, scale, 0, 0); 57 | unity_ObjectToWorld._13_23_33_43 = float4(0, 0, scale, 0); 58 | unity_ObjectToWorld._14_24_34_44 = float4(position.xyz, 1); 59 | unity_WorldToObject = unity_ObjectToWorld; 60 | unity_WorldToObject._14_24_34 *= -1; 61 | unity_WorldToObject._11_22_33 = 1.0f / unity_WorldToObject._11_22_33; 62 | #endif 63 | } 64 | 65 | half _Glossiness; 66 | half _Metallic; 67 | 68 | void surf(Input IN, inout SurfaceOutputStandard o) 69 | { 70 | float4 col = 1.0f; 71 | 72 | #ifdef UNITY_PROCEDURAL_INSTANCING_ENABLED 73 | col = colorBuffer[unity_InstanceID]; 74 | #else 75 | col = float4(0, 0, 1, 1); 76 | #endif 77 | fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * col; 78 | o.Albedo = c.rgb; 79 | o.Metallic = _Metallic; 80 | o.Smoothness = _Glossiness; 81 | o.Alpha = c.a; 82 | } 83 | ENDCG 84 | } 85 | FallBack "Diffuse" 86 | } 87 | -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectNoBuffer/InstancedIndirectNoBufferSurfaceShader.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 971741a1304bb2b41b2e72e31af3d084 3 | timeCreated: 1481683330 4 | licenseType: Pro 5 | ShaderImporter: 6 | defaultTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectNoBuffer/InstancedIndirectNoBufferTest.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttvertex/Unity-InstancedIndirectExamples/960604d705bd3f4db09773c07c4b36ac5e8dc295/Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectNoBuffer/InstancedIndirectNoBufferTest.mat -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectNoBuffer/InstancedIndirectNoBufferTest.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2eb1300652a74a44285e06810ba59e1e 3 | timeCreated: 1481683451 4 | licenseType: Pro 5 | NativeFormatImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectShadowsIssue.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 16ffa2ef1b97d9444918d2a2d97add8a 3 | folderAsset: yes 4 | timeCreated: 1489672517 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectShadowsIssue/InstancedIndirectShadowsIssue.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEngine.Rendering; 3 | 4 | /// 5 | /// This demo shows the use of the procedural instancing features to render objects 6 | /// without need of any position buffer. The values are calculated direclty inside the 7 | /// shader. 8 | /// Shadowing is broken when more than one DrawMeshInstancedIndirect is made. 9 | /// - Tested with different materials, same materials. 10 | /// - Different bounds settings. 11 | /// - Same args buffer (for different draw calls with same mesh). 12 | /// - Different args buffers (with same mesh, and with different meshes). 13 | /// WorkAround: adding an unique mpb per draw call apparently works! 14 | /// 15 | /// The color buffer is used for debug only. 16 | /// 17 | public class InstancedIndirectShadowsIssue : MonoBehaviour 18 | { 19 | public int gridDim = 1000; 20 | public int instanceCount = 0; 21 | public Material instanceMaterial; 22 | 23 | public ShadowCastingMode castShadows = ShadowCastingMode.Off; 24 | public bool receiveShadows = false; 25 | 26 | private ComputeBuffer colorBuffer; 27 | 28 | private uint[] args = new uint[5] { 0, 0, 0, 0, 0 }; 29 | private Material[] materials; 30 | 31 | public Mesh[] meshes; 32 | private ComputeBuffer[] argsBuffers; 33 | public Shader shader; 34 | 35 | public bool[] render; 36 | 37 | MaterialPropertyBlock[] mpbs; 38 | 39 | void Start() 40 | { 41 | instanceCount = gridDim * gridDim; 42 | 43 | argsBuffers = new ComputeBuffer[meshes.Length]; 44 | for (int i = 0; i < meshes.Length; i++) 45 | { 46 | argsBuffers[i] = new ComputeBuffer(5, sizeof(uint), ComputeBufferType.IndirectArguments); 47 | } 48 | 49 | mpbs = new MaterialPropertyBlock[meshes.Length]; 50 | materials = new Material[meshes.Length]; 51 | for (int i = 0; i < materials.Length; i++) 52 | { 53 | materials[i] = new Material(instanceMaterial); 54 | mpbs[i] = new MaterialPropertyBlock(); 55 | } 56 | 57 | CreateBuffers(); 58 | } 59 | 60 | void Update() 61 | { 62 | 63 | for (int i = 0; i < meshes.Length; i++) 64 | { 65 | materials[i].SetFloat("_Dim", gridDim); 66 | materials[i].SetVector("_Pos", new Vector4(i * (gridDim + 10), 0, 0, 0)); 67 | materials[i].SetBuffer("colorBuffer", colorBuffer); 68 | 69 | /// this is the magic line. Uncomment this for shadows!! 70 | mpbs[i].SetFloat("_Bla", (float)i); 71 | 72 | if (render[i]) 73 | Graphics.DrawMeshInstancedIndirect(meshes[i], 0, materials[i], meshes[i].bounds, argsBuffers[i], 0, mpbs[i], castShadows, receiveShadows); 74 | } 75 | } 76 | 77 | void CreateBuffers() 78 | { 79 | /// Colors - for debug only 80 | if (colorBuffer != null) 81 | colorBuffer.Release(); 82 | 83 | colorBuffer = new ComputeBuffer(instanceCount, 16); 84 | 85 | Vector4[] colors = new Vector4[instanceCount]; 86 | for (int i = 0; i < instanceCount; i++) 87 | colors[i] = Random.ColorHSV(); 88 | 89 | colorBuffer.SetData(colors); 90 | 91 | // avoid culling 92 | for (int i = 0; i < meshes.Length; i++) 93 | { 94 | meshes[i].bounds = new Bounds(Vector3.zero, Vector3.one * 10000f); 95 | } 96 | 97 | // indirect args 98 | for (int i = 0; i < argsBuffers.Length; i++) 99 | { 100 | args[0] = meshes[i].GetIndexCount(0); 101 | args[1] = (uint)instanceCount; 102 | argsBuffers[i].SetData(args); 103 | } 104 | } 105 | 106 | void OnDestroy() 107 | { 108 | if (colorBuffer != null) 109 | colorBuffer.Release(); 110 | colorBuffer = null; 111 | 112 | for (int i = 0; i < argsBuffers.Length; i++) 113 | { 114 | if(argsBuffers[i] != null) 115 | argsBuffers[i].Release(); 116 | } 117 | argsBuffers = null; 118 | } 119 | 120 | void OnGUI() 121 | { 122 | GUI.Label(new Rect(265, 12, 200, 30), "Instance Count: " + instanceCount.ToString("N0")); 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectShadowsIssue/InstancedIndirectShadowsIssue.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d44ce7be82416414c93855550ccc2826 3 | timeCreated: 1481682952 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectShadowsIssue/InstancedIndirectShadowsIssue.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttvertex/Unity-InstancedIndirectExamples/960604d705bd3f4db09773c07c4b36ac5e8dc295/Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectShadowsIssue/InstancedIndirectShadowsIssue.mat -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectShadowsIssue/InstancedIndirectShadowsIssue.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 17ba879e8a154214db997257eecacd7e 3 | timeCreated: 1481683451 4 | licenseType: Pro 5 | NativeFormatImporter: 6 | mainObjectFileID: -1 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectShadowsIssue/InstancedIndirectShadowsIssue.unity: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttvertex/Unity-InstancedIndirectExamples/960604d705bd3f4db09773c07c4b36ac5e8dc295/Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectShadowsIssue/InstancedIndirectShadowsIssue.unity -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectShadowsIssue/InstancedIndirectShadowsIssue.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 18222df251a1b6842a704bacf05d93f2 3 | timeCreated: 1481683507 4 | licenseType: Pro 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectShadowsIssue/InstancedIndirectShadowsIssueSurfaceShader.shader: -------------------------------------------------------------------------------- 1 | Shader "Instanced/InstancedIndirectShadowsIssue" 2 | { 3 | Properties{ 4 | _MainTex("Albedo (RGB)", 2D) = "white" {} 5 | _Glossiness("Smoothness", Range(0,1)) = 0.5 6 | _Metallic("Metallic", Range(0,1)) = 0.0 7 | } 8 | SubShader{ 9 | Tags{ "RenderType" = "Opaque" } 10 | LOD 200 11 | 12 | CGPROGRAM 13 | // Physically based Standard lighting model 14 | #pragma surface surf Standard addshadow 15 | #pragma multi_compile_instancing 16 | #pragma instancing_options procedural:setup 17 | 18 | sampler2D _MainTex; 19 | 20 | struct Input { 21 | float2 uv_MainTex; 22 | }; 23 | 24 | #ifdef UNITY_PROCEDURAL_INSTANCING_ENABLED 25 | StructuredBuffer colorBuffer; 26 | #endif 27 | float _Dim; 28 | float4 _Pos; 29 | 30 | float rand(in float2 uv) 31 | { 32 | float2 noise = (frac(sin(dot(uv ,float2(12.9898,78.233)*2.0)) * 43758.5453)); 33 | return abs(noise.x + noise.y) * 0.5; 34 | } 35 | 36 | void rotate2D(inout float2 v, float r) 37 | { 38 | float s, c; 39 | sincos(r, s, c); 40 | v = float2(v.x * c - v.y * s, v.x * s + v.y * c); 41 | } 42 | 43 | void setup() 44 | { 45 | #ifdef UNITY_PROCEDURAL_INSTANCING_ENABLED 46 | // this uv assumes the # of instances is _Dim * _Dim. 47 | // so we calculate the uv inside a grid of _Dim x _Dim elements. 48 | float2 uv = float2( floor(unity_InstanceID / _Dim) / _Dim, (unity_InstanceID % (int)_Dim) / _Dim); 49 | // in this case, _Dim can be replaced by the size in the world 50 | float4 position = _Pos + float4(uv.x * _Dim * 2, 0, uv.y * _Dim * 2, 1); 51 | float scale = position.w; 52 | 53 | //float rotation = scale * scale * _Time.y * 0.5f; 54 | //rotate2D(position.xz, rotation); 55 | 56 | unity_ObjectToWorld._11_21_31_41 = float4(scale, 0, 0, 0); 57 | unity_ObjectToWorld._12_22_32_42 = float4(0, scale, 0, 0); 58 | unity_ObjectToWorld._13_23_33_43 = float4(0, 0, scale, 0); 59 | unity_ObjectToWorld._14_24_34_44 = float4(position.xyz, 1); 60 | unity_WorldToObject = unity_ObjectToWorld; 61 | unity_WorldToObject._14_24_34 *= -1; 62 | unity_WorldToObject._11_22_33 = 1.0f / unity_WorldToObject._11_22_33; 63 | #endif 64 | } 65 | 66 | half _Glossiness; 67 | half _Metallic; 68 | 69 | void surf(Input IN, inout SurfaceOutputStandard o) 70 | { 71 | float4 col = 1.0f; 72 | 73 | #ifdef UNITY_PROCEDURAL_INSTANCING_ENABLED 74 | col = colorBuffer[unity_InstanceID]; 75 | #else 76 | col = float4(0, 0, 1, 1); 77 | #endif 78 | fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * col; 79 | o.Albedo = c.rgb; 80 | o.Metallic = _Metallic; 81 | o.Smoothness = _Glossiness; 82 | o.Alpha = c.a; 83 | } 84 | ENDCG 85 | } 86 | FallBack "Diffuse" 87 | } 88 | -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/Assets/InstancedIndirectShadowsIssue/InstancedIndirectShadowsIssueSurfaceShader.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: dd0b9ef56a2ba204a8fe7b051dc47feb 3 | timeCreated: 1481683330 4 | licenseType: Pro 5 | ShaderImporter: 6 | defaultTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/ProjectSettings/AudioManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttvertex/Unity-InstancedIndirectExamples/960604d705bd3f4db09773c07c4b36ac5e8dc295/Demos-DrawMeshInstancedIndirect/ProjectSettings/AudioManager.asset -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/ProjectSettings/ClusterInputManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttvertex/Unity-InstancedIndirectExamples/960604d705bd3f4db09773c07c4b36ac5e8dc295/Demos-DrawMeshInstancedIndirect/ProjectSettings/ClusterInputManager.asset -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/ProjectSettings/DynamicsManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttvertex/Unity-InstancedIndirectExamples/960604d705bd3f4db09773c07c4b36ac5e8dc295/Demos-DrawMeshInstancedIndirect/ProjectSettings/DynamicsManager.asset -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/ProjectSettings/EditorBuildSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttvertex/Unity-InstancedIndirectExamples/960604d705bd3f4db09773c07c4b36ac5e8dc295/Demos-DrawMeshInstancedIndirect/ProjectSettings/EditorBuildSettings.asset -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/ProjectSettings/EditorSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttvertex/Unity-InstancedIndirectExamples/960604d705bd3f4db09773c07c4b36ac5e8dc295/Demos-DrawMeshInstancedIndirect/ProjectSettings/EditorSettings.asset -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/ProjectSettings/GraphicsSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttvertex/Unity-InstancedIndirectExamples/960604d705bd3f4db09773c07c4b36ac5e8dc295/Demos-DrawMeshInstancedIndirect/ProjectSettings/GraphicsSettings.asset -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/ProjectSettings/InputManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttvertex/Unity-InstancedIndirectExamples/960604d705bd3f4db09773c07c4b36ac5e8dc295/Demos-DrawMeshInstancedIndirect/ProjectSettings/InputManager.asset -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/ProjectSettings/NavMeshAreas.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttvertex/Unity-InstancedIndirectExamples/960604d705bd3f4db09773c07c4b36ac5e8dc295/Demos-DrawMeshInstancedIndirect/ProjectSettings/NavMeshAreas.asset -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/ProjectSettings/NetworkManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttvertex/Unity-InstancedIndirectExamples/960604d705bd3f4db09773c07c4b36ac5e8dc295/Demos-DrawMeshInstancedIndirect/ProjectSettings/NetworkManager.asset -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/ProjectSettings/Physics2DSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttvertex/Unity-InstancedIndirectExamples/960604d705bd3f4db09773c07c4b36ac5e8dc295/Demos-DrawMeshInstancedIndirect/ProjectSettings/Physics2DSettings.asset -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/ProjectSettings/ProjectSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttvertex/Unity-InstancedIndirectExamples/960604d705bd3f4db09773c07c4b36ac5e8dc295/Demos-DrawMeshInstancedIndirect/ProjectSettings/ProjectSettings.asset -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/ProjectSettings/ProjectVersion.txt: -------------------------------------------------------------------------------- 1 | m_EditorVersion: 2017.2.0f3 2 | -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/ProjectSettings/QualitySettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttvertex/Unity-InstancedIndirectExamples/960604d705bd3f4db09773c07c4b36ac5e8dc295/Demos-DrawMeshInstancedIndirect/ProjectSettings/QualitySettings.asset -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/ProjectSettings/TagManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttvertex/Unity-InstancedIndirectExamples/960604d705bd3f4db09773c07c4b36ac5e8dc295/Demos-DrawMeshInstancedIndirect/ProjectSettings/TagManager.asset -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/ProjectSettings/TimeManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttvertex/Unity-InstancedIndirectExamples/960604d705bd3f4db09773c07c4b36ac5e8dc295/Demos-DrawMeshInstancedIndirect/ProjectSettings/TimeManager.asset -------------------------------------------------------------------------------- /Demos-DrawMeshInstancedIndirect/ProjectSettings/UnityConnectSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttvertex/Unity-InstancedIndirectExamples/960604d705bd3f4db09773c07c4b36ac5e8dc295/Demos-DrawMeshInstancedIndirect/ProjectSettings/UnityConnectSettings.asset -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Noisecrime 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DrawMeshInstanceIndirect examples. 2 | Exploring the Unity 5.6 DrawMeshInstanceIndirect method to render large numbers of objects. 3 | 4 | ### InstancedIndirectExample 5 | The example on scene InstancedIndirectExample is a slightly expanded version of [Unity's sample](https://docs.unity3d.com/560/Documentation/ScriptReference/Graphics.DrawMeshInstancedIndirect.html) code provided by [noisecrime](https://github.com/noisecrime/Unity-InstancedIndirectExamples). The buffer is created in CPU and the position sampled in GPU. This approach is useful when the positions are static, otherwise the cost of update from CPU is very high. 6 | 7 | ### InstancedIndirectComputeExample 8 | The example on scene InstancedIndirectComputeExample demonstrates the use of Compute Shaders to generate position data. Compute Shaders are specially useful when the buffers need constant update, as the buffer remains in GPU and we can take advantage of many threads to perform the calculations. 9 | 10 | ### InstancedIndirectNoBuffer 11 | The example on scene InstancedIndirectNoBuffer shows how to position the objects on the fly, directly within the shader. This approach eliminates the use of any auxiliar buffer, and positions can be calculated directly in the surface shader. This is very attractive for when the calculations are simple and the number of instances is very high. 12 | 13 | ### InstancedIndirectComputeAppend 14 | The example on scene InstancedIndirectComputeAppend shows how to render instances when the number of elements is not known beforehand. 15 | A compute is dispatched with N threads but not all of them assign values to the position buffer. An AppendStructuredBuffer is used in this case [+info](https://msdn.microsoft.com/en-us/library/windows/desktop/ff471448(v=vs.85).aspx). As the CPU does not know how many instances were created, we use the CopyCount function to update the args buffer that is passed to the DrawMeshInstancedIndirect function. 16 | 17 | ### InstancedIndirectShadowsIssue 18 | 19 | There is an open issue in Unity 5.6b that, when issuing several drawcalls using DrawMeshInstancedIndirect the shadow is broken. The bug was reported [here](https://issuetracker.unity3d.com/issues/drawmeshinstanceindirect-wrong-computebuffer-being-passsed-to-consecutive-drawmesh-calls). A blog post discussing it can be found [here](https://forum.unity3d.com/threads/drawmeshinstancedindirect-example-comments-and-questions.446080/#post-2995966). 20 | Here's the workaround: 21 | 22 | * If you duplicate the shader file, and rename it. Add each duplicate to a different material, it works. Which indicates that Unity is having troubles differentiating among the materials, and is trying to batch them somehow. 23 | * So I had to find a way to force Unity disable whatever it was that was not separating the materials. Creating the material from code (using the shader or the original material) was not working 24 | * The uniforms I was passing with the materials were different from each other, but that didn't do it. 25 | * The only thing left was the MaterialPropertyBlock (which I wasn't using). Setting an empty mpb per draw call also didn't work. 26 | * What did work was to set an unique dummy variable per mpb, so that Unity will have to issue a different call. The variable doesn't even have to be used in the shader. 27 | 28 | for (int i = 0; i < meshes.Length; i++) 29 | { 30 | materials[i].SetFloat("_Dim", gridDim); 31 | ....... 32 | /// this is the magic line. Uncomment this for shadows!! 33 | mpbs[i].SetFloat("_Bla", (float)i); 34 | Graphics.DrawMeshInstancedIndirect(meshes[i], 0, materials[i], meshes[i].bounds, argsBuffers[i], 0, mpbs[i], castShadows, receiveShadows); 35 | } 36 | 37 | It is not ideal, but it works!! Image with 4 draw calls (one per different group). 38 | 39 | ![Screenshot](Untitled.png) 40 | 41 | 42 | 43 | ** NOTE: these are WIP demos. 44 | 45 | -------------------------------------------------------------------------------- /Untitled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttvertex/Unity-InstancedIndirectExamples/960604d705bd3f4db09773c07c4b36ac5e8dc295/Untitled.png --------------------------------------------------------------------------------