@@ -11,45 +11,19 @@ namespace UTJ.Alembic
1111 [ ExecuteInEditMode ]
1212 public class AlembicPointsRenderer : MonoBehaviour
1313 {
14- public enum InstancingMode
15- {
16- NoInstancing ,
17- #if UNITY_5_5_OR_NEWER
18- Instancing ,
19- #endif
20- #if UNITY_5_6_OR_NEWER
21- Procedural,
22- #endif
23- }
24-
25- public const int MaxInstancesParDraw = 1023 ;
26-
2714 [ SerializeField ] Mesh m_mesh ;
2815 [ SerializeField ] Material [ ] m_materials ;
2916 [ SerializeField ] ShadowCastingMode m_castShadows = ShadowCastingMode . Off ;
3017 [ SerializeField ] bool m_receiveShadows = false ;
3118 [ SerializeField ] float m_pointSize = 0.2f ;
32- [ SerializeField ] InstancingMode m_instancingMode =
33- #if UNITY_5_5_OR_NEWER
34- InstancingMode . Instancing ;
35- #else
36- InstancingMode . NoInstancing ;
37- #endif
3819 [ Tooltip ( "Use Alembic Points IDs as shader input" ) ]
3920 [ SerializeField ] bool m_useAlembicIDs = false ;
40-
41- #if UNITY_5_5_OR_NEWER
42- const string kAlembicProceduralInstancing = "ALEMBIC_PROCEDURAL_INSTANCING_ENABLED" ;
43- Matrix4x4 [ ] m_matrices ;
21+
4422 float [ ] m_ids ;
45- List < MaterialPropertyBlock > m_mpbs ;
46- #endif
47- #if UNITY_5_6_OR_NEWER
4823 ComputeBuffer m_cbPoints ;
4924 ComputeBuffer m_cbIDs ;
5025 ComputeBuffer [ ] m_cbArgs ;
5126 int [ ] m_args = new int [ 5 ] { 0 , 0 , 0 , 0 , 0 } ;
52- #endif
5327#if UNITY_EDITOR
5428 bool m_dirty = false ;
5529#endif
@@ -108,12 +82,13 @@ Material[] SetupMaterials()
10882 {
10983 m_materialsInternal = null ;
11084 }
111- else if ( m_materialsInternal == null || m_materialsInternal . Length == 0 )
85+ else if ( m_materialsInternal == null || m_materialsInternal . Length != m_materials . Length )
11286 {
11387 m_materialsInternal = new Material [ m_materials . Length ] ;
11488 for ( int i = 0 ; i < m_materials . Length ; ++ i )
11589 {
116- m_materialsInternal [ i ] = new Material ( m_materials [ i ] ) ;
90+ if ( m_materials [ i ] != null )
91+ m_materialsInternal [ i ] = new Material ( m_materials [ i ] ) ;
11792 }
11893 }
11994 return m_materialsInternal ;
@@ -141,44 +116,32 @@ public void Flush()
141116 var scale = trans . lossyScale ;
142117 var pscale = scale * m_pointSize ;
143118
144- bool supportsInstancing = SystemInfo . supportsInstancing ;
145- #if UNITY_5_6_OR_NEWER
119+ bool supportsInstancing = SystemInfo . supportsInstancing && SystemInfo . supportsComputeShaders ;
146120 int pidAlembicPoints = Shader . PropertyToID ( "_AlembicPoints" ) ;
147- #endif
148- #if UNITY_5_5_OR_NEWER
149121 int pidAlembicIDs = Shader . PropertyToID ( "_AlembicIDs" ) ;
150- #endif
151122 int pidTranslate = Shader . PropertyToID ( "_Translate" ) ;
152123 int pidRotate = Shader . PropertyToID ( "_Rotate" ) ;
153124 int pidScale = Shader . PropertyToID ( "_Scale" ) ;
154125 int pidPointSize = Shader . PropertyToID ( "_PointSize" ) ;
155126
156- if ( ! supportsInstancing && m_instancingMode != InstancingMode . NoInstancing )
127+ if ( ! supportsInstancing )
157128 {
158- Debug . LogWarning ( "AlembicPointsRenderer: Instancing is not supported on this system. fallback to InstancingMode.NoInstancing. " ) ;
159- m_instancingMode = InstancingMode . NoInstancing ;
129+ Debug . LogWarning ( "AlembicPointsRenderer: Instancing is not supported on this system." ) ;
130+ return ;
160131 }
161132
162133 for ( int si = 0 ; si < num_submeshes ; ++ si )
163134 {
164135 var material = materials [ si ] ;
136+ if ( material == null )
137+ continue ;
165138 material . SetVector ( pidTranslate , pos ) ;
166139 material . SetVector ( pidRotate , new Vector4 ( rot . x , rot . y , rot . z , rot . w ) ) ;
167140 material . SetVector ( pidScale , scale ) ;
168141 material . SetFloat ( pidPointSize , m_pointSize ) ;
169142 }
170143
171- #if UNITY_5_6_OR_NEWER
172- if ( m_instancingMode == InstancingMode . Procedural && ! SystemInfo . supportsComputeShaders )
173144 {
174- Debug . LogWarning ( "AlembicPointsRenderer: InstancingMode.Procedural is not supported on this system. fallback to InstancingMode.Instancing." ) ;
175- m_instancingMode = InstancingMode . Instancing ;
176- }
177-
178- if ( supportsInstancing && m_instancingMode == InstancingMode . Procedural )
179- {
180- // Graphics.DrawMeshInstancedIndirect() route
181-
182145 // update argument buffer
183146 if ( m_cbArgs == null || m_cbArgs . Length != num_submeshes )
184147 {
@@ -243,135 +206,25 @@ public void Flush()
243206 args . SetData ( m_args ) ;
244207
245208 var material = materials [ si ] ;
246- material . EnableKeyword ( kAlembicProceduralInstancing ) ;
209+ if ( material == null )
210+ continue ;
247211 material . SetBuffer ( pidAlembicPoints , m_cbPoints ) ;
248- if ( alembicIDsAvailable ) { material . SetBuffer ( pidAlembicIDs , m_cbIDs ) ; }
212+ if ( alembicIDsAvailable )
213+ material . SetBuffer ( pidAlembicIDs , m_cbIDs ) ;
249214 Graphics . DrawMeshInstancedIndirect ( mesh , si , material ,
250215 bounds , args , 0 , null , m_castShadows , m_receiveShadows , layer ) ;
251216 }
252217 }
253- else
254- #endif
255- #if UNITY_5_5_OR_NEWER
256- if ( supportsInstancing && m_instancingMode == InstancingMode . Instancing )
257- {
258- // Graphics.DrawMeshInstanced() route
259- // Graphics.DrawMeshInstanced() can draw only up to 1023 instances.
260- // multiple drawcalls maybe required.
261-
262- int num_batches = ( num_instances + MaxInstancesParDraw - 1 ) / MaxInstancesParDraw ;
263-
264- if ( m_matrices == null || m_matrices . Length != MaxInstancesParDraw )
265- {
266- m_matrices = new Matrix4x4 [ MaxInstancesParDraw ] ;
267- for ( int i = 0 ; i < MaxInstancesParDraw ; ++ i ) { m_matrices [ i ] = Matrix4x4 . identity ; }
268- }
269-
270- for ( int si = 0 ; si < num_submeshes ; ++ si )
271- {
272- var material = materials [ si ] ;
273- if ( material . IsKeywordEnabled ( kAlembicProceduralInstancing ) )
274- {
275- material . DisableKeyword ( kAlembicProceduralInstancing ) ;
276- }
277- }
278-
279- // setup alembic point IDs
280- bool alembicIDsAvailable = false ;
281- ulong [ ] ids = null ;
282- if ( m_useAlembicIDs )
283- {
284- ids = apc . abcIDs ;
285- alembicIDsAvailable = ids != null && ids . Length == num_instances ;
286- if ( alembicIDsAvailable )
287- {
288- if ( m_ids == null || m_ids . Length != MaxInstancesParDraw )
289- {
290- m_ids = new float [ MaxInstancesParDraw ] ;
291- }
292- if ( m_mpbs == null )
293- {
294- m_mpbs = new List < MaterialPropertyBlock > ( ) ;
295- }
296- while ( m_mpbs . Count < num_batches )
297- {
298- m_mpbs . Add ( new MaterialPropertyBlock ( ) ) ;
299- }
300- }
301- }
302-
303- for ( int ib = 0 ; ib < num_batches ; ++ ib )
304- {
305- int ibegin = ib * MaxInstancesParDraw ;
306- int iend = System . Math . Min ( ibegin + MaxInstancesParDraw , num_instances ) ;
307- int n = iend - ibegin ;
308-
309- // build matrices
310- for ( int ii = 0 ; ii < n ; ++ ii )
311- {
312- var ppos = points [ ibegin + ii ] ;
313- ppos . x *= scale . x ;
314- ppos . y *= scale . y ;
315- ppos . z *= scale . z ;
316- ppos = ( rot * ppos ) + pos ;
317- m_matrices [ ii ] . SetTRS ( ppos , rot , pscale ) ;
318- }
319-
320- MaterialPropertyBlock mpb = null ;
321- if ( alembicIDsAvailable )
322- {
323- for ( int ii = 0 ; ii < n ; ++ ii )
324- {
325- m_ids [ ii ] = ids [ ibegin + ii ] ;
326- }
327- mpb = m_mpbs [ ib ] ;
328- mpb . SetFloatArray ( pidAlembicIDs , m_ids ) ;
329- }
330-
331- // issue drawcalls
332- for ( int si = 0 ; si < num_submeshes ; ++ si )
333- {
334- var material = materials [ si ] ;
335- Graphics . DrawMeshInstanced ( mesh , si , material , m_matrices , n , mpb , m_castShadows , m_receiveShadows , layer ) ;
336- }
337- }
338- }
339- else
340- #endif
341- {
342- // Graphics.DrawMesh() route
343- // not use IDs in this case because it's too expensive...
344-
345- var matrix = Matrix4x4 . identity ;
346- for ( int ii = 0 ; ii < num_instances ; ++ ii )
347- {
348- var ppos = points [ ii ] ;
349- ppos . x *= scale . x ;
350- ppos . y *= scale . y ;
351- ppos . z *= scale . z ;
352- ppos = ( rot * ppos ) + pos ;
353- matrix . SetTRS ( ppos , rot , pscale ) ;
354-
355- // issue drawcalls
356- for ( int si = 0 ; si < num_submeshes ; ++ si )
357- {
358- var material = materials [ si ] ;
359- Graphics . DrawMesh ( mesh , matrix , material , layer , null , si , null , m_castShadows , m_receiveShadows ) ;
360- }
361- }
362- }
363218 }
364219
365220 public void Release ( )
366221 {
367- #if UNITY_5_6_OR_NEWER
368222 if ( m_cbArgs != null ) {
369223 foreach ( var cb in m_cbArgs ) { cb . Release ( ) ; }
370224 m_cbArgs = null ;
371225 }
372226 if ( m_cbPoints != null ) { m_cbPoints . Release ( ) ; m_cbPoints = null ; }
373227 if ( m_cbIDs != null ) { m_cbIDs . Release ( ) ; m_cbIDs = null ; }
374- #endif
375228 }
376229
377230
@@ -388,7 +241,6 @@ void LateUpdate()
388241#endif
389242 }
390243
391- #if UNITY_EDITOR
392244 void OnDrawGizmos ( )
393245 {
394246 // force draw particles while paused.
@@ -405,6 +257,32 @@ void OnDrawGizmos()
405257 m_materialsInternal = null ;
406258 }
407259 }
260+
261+ private void Start ( )
262+ {
263+ #if UNITY_EDITOR
264+ if ( m_mesh == null )
265+ {
266+ var cubeGO = GameObject . CreatePrimitive ( PrimitiveType . Cube ) ;
267+ m_mesh = cubeGO . GetComponent < MeshFilter > ( ) . sharedMesh ;
268+ DestroyImmediate ( cubeGO ) ;
269+ }
270+ if ( m_materials != null )
271+ {
272+ bool allNull = true ;
273+ foreach ( var m in m_materials )
274+ if ( m_materials != null )
275+ allNull = false ;
276+ if ( allNull )
277+ m_materials = null ;
278+ }
279+ if ( m_materials == null )
280+ {
281+ var mat = new Material ( AssetDatabase . LoadAssetAtPath < Shader > ( "Assets/UTJ/Alembic/Shaders/StandardInstanced.shader" ) ) ;
282+ mat . name = "Default Alembic Points" ;
283+ m_materials = new Material [ ] { mat } ;
284+ }
408285#endif
286+ }
409287 }
410288}
0 commit comments