From 5ed38e62a697ddce5802a082d2de02c29a664f7e Mon Sep 17 00:00:00 2001 From: i-saint Date: Fri, 19 Jan 2018 22:00:08 +0900 Subject: [PATCH] cleanup AlembicPointsRenderer --- .../Scripts/Importer/AlembicPointsRenderer.cs | 202 ++++-------------- .../UTJ/Alembic/Shaders/PointRenderer.cginc | 58 ++--- .../Alembic/Shaders/StandardInstanced.shader | 4 +- .../Shaders/TransparentInstanced.shader | 9 +- 4 files changed, 61 insertions(+), 212 deletions(-) diff --git a/AlembicImporter/Assets/UTJ/Alembic/Scripts/Importer/AlembicPointsRenderer.cs b/AlembicImporter/Assets/UTJ/Alembic/Scripts/Importer/AlembicPointsRenderer.cs index 147b3b0fc..db1134942 100644 --- a/AlembicImporter/Assets/UTJ/Alembic/Scripts/Importer/AlembicPointsRenderer.cs +++ b/AlembicImporter/Assets/UTJ/Alembic/Scripts/Importer/AlembicPointsRenderer.cs @@ -11,45 +11,19 @@ namespace UTJ.Alembic [ExecuteInEditMode] public class AlembicPointsRenderer : MonoBehaviour { - public enum InstancingMode - { - NoInstancing, -#if UNITY_5_5_OR_NEWER - Instancing, -#endif -#if UNITY_5_6_OR_NEWER - Procedural, -#endif - } - - public const int MaxInstancesParDraw = 1023; - [SerializeField] Mesh m_mesh; [SerializeField] Material[] m_materials; [SerializeField] ShadowCastingMode m_castShadows = ShadowCastingMode.Off; [SerializeField] bool m_receiveShadows = false; [SerializeField] float m_pointSize = 0.2f; - [SerializeField] InstancingMode m_instancingMode = -#if UNITY_5_5_OR_NEWER - InstancingMode.Instancing; -#else - InstancingMode.NoInstancing; -#endif [Tooltip("Use Alembic Points IDs as shader input")] [SerializeField] bool m_useAlembicIDs = false; - -#if UNITY_5_5_OR_NEWER - const string kAlembicProceduralInstancing = "ALEMBIC_PROCEDURAL_INSTANCING_ENABLED"; - Matrix4x4[] m_matrices; + float[] m_ids; - List m_mpbs; -#endif -#if UNITY_5_6_OR_NEWER ComputeBuffer m_cbPoints; ComputeBuffer m_cbIDs; ComputeBuffer[] m_cbArgs; int[] m_args = new int[5] { 0, 0, 0, 0, 0 }; -#endif #if UNITY_EDITOR bool m_dirty = false; #endif @@ -108,12 +82,13 @@ Material[] SetupMaterials() { m_materialsInternal = null; } - else if (m_materialsInternal == null || m_materialsInternal.Length == 0) + else if (m_materialsInternal == null || m_materialsInternal.Length != m_materials.Length) { m_materialsInternal = new Material[m_materials.Length]; for (int i = 0; i < m_materials.Length; ++i) { - m_materialsInternal[i] = new Material(m_materials[i]); + if (m_materials[i] != null) + m_materialsInternal[i] = new Material(m_materials[i]); } } return m_materialsInternal; @@ -141,44 +116,32 @@ public void Flush() var scale = trans.lossyScale; var pscale = scale * m_pointSize; - bool supportsInstancing = SystemInfo.supportsInstancing; -#if UNITY_5_6_OR_NEWER + bool supportsInstancing = SystemInfo.supportsInstancing && SystemInfo.supportsComputeShaders; int pidAlembicPoints = Shader.PropertyToID("_AlembicPoints"); -#endif -#if UNITY_5_5_OR_NEWER int pidAlembicIDs = Shader.PropertyToID("_AlembicIDs"); -#endif int pidTranslate = Shader.PropertyToID("_Translate"); int pidRotate = Shader.PropertyToID("_Rotate"); int pidScale = Shader.PropertyToID("_Scale"); int pidPointSize = Shader.PropertyToID("_PointSize"); - if (!supportsInstancing && m_instancingMode != InstancingMode.NoInstancing) + if (!supportsInstancing) { - Debug.LogWarning("AlembicPointsRenderer: Instancing is not supported on this system. fallback to InstancingMode.NoInstancing."); - m_instancingMode = InstancingMode.NoInstancing; + Debug.LogWarning("AlembicPointsRenderer: Instancing is not supported on this system."); + return; } for (int si = 0; si < num_submeshes; ++si) { var material = materials[si]; + if (material == null) + continue; material.SetVector(pidTranslate, pos); material.SetVector(pidRotate, new Vector4(rot.x, rot.y, rot.z, rot.w)); material.SetVector(pidScale, scale); material.SetFloat(pidPointSize, m_pointSize); } -#if UNITY_5_6_OR_NEWER - if (m_instancingMode == InstancingMode.Procedural && !SystemInfo.supportsComputeShaders) { - Debug.LogWarning("AlembicPointsRenderer: InstancingMode.Procedural is not supported on this system. fallback to InstancingMode.Instancing."); - m_instancingMode = InstancingMode.Instancing; - } - - if (supportsInstancing && m_instancingMode == InstancingMode.Procedural) - { - // Graphics.DrawMeshInstancedIndirect() route - // update argument buffer if (m_cbArgs == null || m_cbArgs.Length != num_submeshes) { @@ -243,135 +206,25 @@ public void Flush() args.SetData(m_args); var material = materials[si]; - material.EnableKeyword(kAlembicProceduralInstancing); + if (material == null) + continue; material.SetBuffer(pidAlembicPoints, m_cbPoints); - if (alembicIDsAvailable) { material.SetBuffer(pidAlembicIDs, m_cbIDs); } + if (alembicIDsAvailable) + material.SetBuffer(pidAlembicIDs, m_cbIDs); Graphics.DrawMeshInstancedIndirect(mesh, si, material, bounds, args, 0, null, m_castShadows, m_receiveShadows, layer); } } - else -#endif -#if UNITY_5_5_OR_NEWER - if (supportsInstancing && m_instancingMode == InstancingMode.Instancing) - { - // Graphics.DrawMeshInstanced() route - // Graphics.DrawMeshInstanced() can draw only up to 1023 instances. - // multiple drawcalls maybe required. - - int num_batches = (num_instances + MaxInstancesParDraw - 1) / MaxInstancesParDraw; - - if (m_matrices == null || m_matrices.Length != MaxInstancesParDraw) - { - m_matrices = new Matrix4x4[MaxInstancesParDraw]; - for (int i = 0; i < MaxInstancesParDraw; ++i) { m_matrices[i] = Matrix4x4.identity; } - } - - for (int si = 0; si < num_submeshes; ++si) - { - var material = materials[si]; - if (material.IsKeywordEnabled(kAlembicProceduralInstancing)) - { - material.DisableKeyword(kAlembicProceduralInstancing); - } - } - - // setup alembic point IDs - bool alembicIDsAvailable = false; - ulong[] ids = null; - if (m_useAlembicIDs) - { - ids = apc.abcIDs; - alembicIDsAvailable = ids != null && ids.Length == num_instances; - if (alembicIDsAvailable) - { - if (m_ids == null || m_ids.Length != MaxInstancesParDraw) - { - m_ids = new float[MaxInstancesParDraw]; - } - if (m_mpbs == null) - { - m_mpbs = new List(); - } - while (m_mpbs.Count < num_batches) - { - m_mpbs.Add(new MaterialPropertyBlock()); - } - } - } - - for (int ib = 0; ib < num_batches; ++ib) - { - int ibegin = ib * MaxInstancesParDraw; - int iend = System.Math.Min(ibegin + MaxInstancesParDraw, num_instances); - int n = iend - ibegin; - - // build matrices - for (int ii = 0; ii < n; ++ii) - { - var ppos = points[ibegin + ii]; - ppos.x *= scale.x; - ppos.y *= scale.y; - ppos.z *= scale.z; - ppos = (rot * ppos) + pos; - m_matrices[ii].SetTRS(ppos, rot, pscale); - } - - MaterialPropertyBlock mpb = null; - if (alembicIDsAvailable) - { - for (int ii = 0; ii < n; ++ii) - { - m_ids[ii] = ids[ibegin + ii]; - } - mpb = m_mpbs[ib]; - mpb.SetFloatArray(pidAlembicIDs, m_ids); - } - - // issue drawcalls - for (int si = 0; si < num_submeshes; ++si) - { - var material = materials[si]; - Graphics.DrawMeshInstanced(mesh, si, material, m_matrices, n, mpb, m_castShadows, m_receiveShadows, layer); - } - } - } - else -#endif - { - // Graphics.DrawMesh() route - // not use IDs in this case because it's too expensive... - - var matrix = Matrix4x4.identity; - for (int ii = 0; ii < num_instances; ++ii) - { - var ppos = points[ii]; - ppos.x *= scale.x; - ppos.y *= scale.y; - ppos.z *= scale.z; - ppos = (rot * ppos) + pos; - matrix.SetTRS(ppos, rot, pscale); - - // issue drawcalls - for (int si = 0; si < num_submeshes; ++si) - { - var material = materials[si]; - Graphics.DrawMesh(mesh, matrix, material, layer, null, si, null, m_castShadows, m_receiveShadows); - } - } - } } public void Release() { -#if UNITY_5_6_OR_NEWER if (m_cbArgs != null) { foreach(var cb in m_cbArgs) { cb.Release(); } m_cbArgs = null; } if (m_cbPoints != null) { m_cbPoints.Release(); m_cbPoints = null; } if (m_cbIDs != null) { m_cbIDs.Release(); m_cbIDs = null; } -#endif } @@ -388,7 +241,6 @@ void LateUpdate() #endif } -#if UNITY_EDITOR void OnDrawGizmos() { // force draw particles while paused. @@ -405,6 +257,32 @@ void OnDrawGizmos() m_materialsInternal = null; } } + + private void Start() + { +#if UNITY_EDITOR + if (m_mesh == null) + { + var cubeGO = GameObject.CreatePrimitive(PrimitiveType.Cube); + m_mesh = cubeGO.GetComponent().sharedMesh; + DestroyImmediate(cubeGO); + } + if (m_materials != null) + { + bool allNull = true; + foreach (var m in m_materials) + if (m_materials != null) + allNull = false; + if (allNull) + m_materials = null; + } + if (m_materials == null) + { + var mat = new Material(AssetDatabase.LoadAssetAtPath("Assets/UTJ/Alembic/Shaders/StandardInstanced.shader")); + mat.name = "Default Alembic Points"; + m_materials = new Material[] { mat }; + } #endif + } } } diff --git a/AlembicImporter/Assets/UTJ/Alembic/Shaders/PointRenderer.cginc b/AlembicImporter/Assets/UTJ/Alembic/Shaders/PointRenderer.cginc index 3d8b2e2c4..4e4c6ff61 100644 --- a/AlembicImporter/Assets/UTJ/Alembic/Shaders/PointRenderer.cginc +++ b/AlembicImporter/Assets/UTJ/Alembic/Shaders/PointRenderer.cginc @@ -1,44 +1,12 @@ -// Upgrade NOTE: upgraded instancing buffer 'A' to new syntax. -// Upgrade NOTE: upgraded instancing buffer 'Props' to new syntax. - #include "UnityCG.cginc" -#if defined(UNITY_SUPPORT_INSTANCING) && !defined(UNITY_INSTANCING_ENABLED) && !defined(UNITY_PROCEDURAL_INSTANCING_ENABLED) && (SHADER_TARGET >= 45 && defined(ALEMBIC_PROCEDURAL_INSTANCING_ENABLED)) - #define UNITY_SUPPORT_INSTANCING - #define UNITY_PROCEDURAL_INSTANCING_ENABLED - - uint unity_InstanceID; - #define UNITY_VERTEX_INPUT_INSTANCE_ID uint instanceID : SV_InstanceID; - #define UNITY_SETUP_INSTANCE_ID(v) unity_InstanceID = v.instanceID; -#endif - - float3 _Translate; float4 _Rotate; float3 _Scale; float _PointSize; -float _AlembicID; - #ifdef UNITY_SUPPORT_INSTANCING - #ifdef UNITY_PROCEDURAL_INSTANCING_ENABLED - StructuredBuffer _AlembicPoints; - StructuredBuffer _AlembicIDs; - #else - UNITY_INSTANCING_BUFFER_START (Props) - UNITY_DEFINE_INSTANCED_PROP (float, _AlembicIDs) -#define _AlembicIDs_arr Props - UNITY_INSTANCING_BUFFER_END(Props) - #endif -#elif !defined(UNITY_VERTEX_INPUT_INSTANCE_ID) - // for pre-5.5 - #define UNITY_VERTEX_INPUT_INSTANCE_ID - #define UNITY_INSTANCING_BUFFER_START(A, B) - #define UNITY_DEFINE_INSTANCED_PROP(A, B) -#define B_arr A - #define UNITY_ACCESS_INSTANCED_PROP(A_arr, A) - #define UNITY_INSTANCING_BUFFER_END(A) - #define UNITY_SETUP_INSTANCE_ID(A) - #define UNITY_TRANSFER_INSTANCE_ID(A, B) +StructuredBuffer _AlembicPoints; +StructuredBuffer _AlembicIDs; #endif float GetPointSize() @@ -100,30 +68,30 @@ float3 Rotate(float4 q, float3 p) return p + (a * q.w + b) * 2.0; } -float3 GetAlembicPoint() +float3 GetAlembicPoint(int iid) { return -#ifdef UNITY_PROCEDURAL_INSTANCING_ENABLED - Rotate(_Rotate, _AlembicPoints[unity_InstanceID] * _Scale) + _Translate; +#ifdef UNITY_SUPPORT_INSTANCING + Rotate(_Rotate, _AlembicPoints[iid] * _Scale) + _Translate; #else - float3(unity_ObjectToWorld[0][3], unity_ObjectToWorld[1][3], unity_ObjectToWorld[2][3]); + float3(0,0,0); #endif } -float GetAlembicID() +float GetAlembicID(int iid) { return -#if defined(UNITY_INSTANCING_ENABLED) || defined(UNITY_PROCEDURAL_INSTANCING_ENABLED) - _AlembicIDs[unity_InstanceID]; +#ifdef UNITY_SUPPORT_INSTANCING + _AlembicIDs[iid]; #else - _AlembicID; + 0; #endif } -float4x4 GetPointMatrix() +float4x4 GetPointMatrix(int iid) { -#ifdef UNITY_PROCEDURAL_INSTANCING_ENABLED - float3 ppos = GetAlembicPoint(); +#ifdef UNITY_SUPPORT_INSTANCING + float3 ppos = GetAlembicPoint(iid); float4 prot = _Rotate; float3 pscale = _Scale * _PointSize; return mul(mul(Translate44(ppos), Rotate44(prot)), Scale44(pscale)); diff --git a/AlembicImporter/Assets/UTJ/Alembic/Shaders/StandardInstanced.shader b/AlembicImporter/Assets/UTJ/Alembic/Shaders/StandardInstanced.shader index 2c6c0aaa2..7a8b9adc1 100644 --- a/AlembicImporter/Assets/UTJ/Alembic/Shaders/StandardInstanced.shader +++ b/AlembicImporter/Assets/UTJ/Alembic/Shaders/StandardInstanced.shader @@ -14,7 +14,7 @@ #pragma surface surf Standard fullforwardshadows addshadow #pragma target 3.0 #pragma multi_compile_instancing - #pragma instancing_options assumeuniformscaling maxcount:1023 procedural:setup + #pragma instancing_options assumeuniformscaling procedural:setup #include "PointRenderer.cginc" fixed4 _Color; @@ -30,7 +30,7 @@ #ifdef UNITY_PROCEDURAL_INSTANCING_ENABLED void setup() { - unity_ObjectToWorld = GetPointMatrix(); + unity_ObjectToWorld = GetPointMatrix(unity_InstanceID); unity_WorldToObject = unity_ObjectToWorld; unity_WorldToObject._14_24_34 *= -1; unity_WorldToObject._11_22_33 = 1.0f / unity_WorldToObject._11_22_33; diff --git a/AlembicImporter/Assets/UTJ/Alembic/Shaders/TransparentInstanced.shader b/AlembicImporter/Assets/UTJ/Alembic/Shaders/TransparentInstanced.shader index f0c92ea44..8ad567ea5 100644 --- a/AlembicImporter/Assets/UTJ/Alembic/Shaders/TransparentInstanced.shader +++ b/AlembicImporter/Assets/UTJ/Alembic/Shaders/TransparentInstanced.shader @@ -25,8 +25,7 @@ #pragma vertex vert #pragma fragment frag #pragma multi_compile_instancing - #pragma instancing_options assumeuniformscaling maxcount:1023 - #pragma multi_compile ___ ALEMBIC_PROCEDURAL_INSTANCING_ENABLED + #pragma instancing_options assumeuniformscaling #pragma target 4.5 #include "PointRenderer.cginc" @@ -51,7 +50,11 @@ UNITY_SETUP_INSTANCE_ID(v); float4 vertex = v.vertex; - vertex = mul(mul(UNITY_MATRIX_VP, GetPointMatrix()), vertex); +#ifdef UNITY_PROCEDURAL_INSTANCING_ENABLED + vertex = mul(mul(UNITY_MATRIX_VP, GetPointMatrix(unity_InstanceID)), vertex); +#else + vertex = mul(UNITY_MATRIX_VP, vertex); +#endif v2f o; o.vertex = vertex;