- Home /
How to move from Graphics.DrawMeshInstanced to Graphics.RenderMeshInstanced
I am trying to convert a working Graphics.DrawMeshInstanced call to Graphics.RenderMeshInstanced.
I was hoping to eventually switch it to use a NativeArray
that I populate from a burst Job, but I can't get the RenderMeshInstanced
call to work at all.
Anybody know the trick to it?
It doesn't throw errors, but nothing is rendering or showing in the frame debugger.
Answer by andrew-lukasik · Mar 21 at 07:12 PM
These 2 scripts results in exactly the same outcome while one is using Graphics.DrawMeshInstanced
and the other Graphics.RenderMeshInstanced
LetsDrawMeshInstanced.cs
using UnityEngine;
[ExecuteAlways]
public class LetsDrawMeshInstanced : MonoBehaviour
{
[SerializeField] Mesh _mesh = null;
[SerializeField] Material _material = null;
Matrix4x4[] _matrices = new Matrix4x4[100];
void Update ()
{
if( _mesh!=null && _material!=null )
{
UpdateMatrices();
Graphics.DrawMeshInstanced( _mesh , 0 , _material , _matrices );
}
}
void UpdateMatrices ()
{
Vector3 origin = transform.position;
float time = Time.time;
const float tau = Mathf.PI * 2f;
int numMatrices = _matrices.Length;
for( int i=0 ; i<numMatrices ; i++ )
{
float theta = (float)i / (float)(numMatrices-1) * tau;
_matrices[i] = Matrix4x4.TRS(
origin + new Vector3( 0 , Mathf.Sin(theta) , Mathf.Cos(theta) )*10f ,
Quaternion.Euler( new Vector3(333f,10f,333f)*time ) ,
Vector3.one
);
}
}
}
LetsRenderMeshInstanced.cs
using UnityEngine;
using Unity.Collections;
using Unity.Jobs;
using Unity.Mathematics;
using BurstCompile = Unity.Burst.BurstCompileAttribute;
[ExecuteAlways]
public class LetsRenderMeshInstanced : MonoBehaviour
{
[SerializeField] Mesh _mesh = null;
[SerializeField] Material _material = null;
NativeArray<float4x4> _matrices;
public JobHandle Dependency;
void OnEnable ()
{
_matrices = new NativeArray<float4x4>( 100 , Allocator.Persistent );
}
void OnDisable ()
{
Dependency.Complete();
if( _matrices.IsCreated ) _matrices.Dispose();
}
void Update ()
{
if( _mesh!=null && _material!=null )
{
// complete previous job
Dependency.Complete();
// render job results
RenderParams rp = new RenderParams( _material );
Graphics.RenderMeshInstanced( rp , _mesh , 0 , _matrices.Reinterpret<Matrix4x4>() );
// schedule new job:
var job = new UpdateMatrices{
Origin = transform.position ,
Time = Time.time ,
NumMatrices = _matrices.Length ,
Matrices = _matrices ,
};
Dependency = job.Schedule( _matrices.Length , 32 , Dependency );
}
}
[BurstCompile]
struct UpdateMatrices : IJobParallelFor
{
public float3 Origin;
public float Time;
public int NumMatrices;
[WriteOnly] public NativeArray<float4x4> Matrices;
void IJobParallelFor.Execute ( int i )
{
const float tau = math.PI * 2f;
float theta = (float)i / (float)(NumMatrices-1) * tau;
Matrices[i] = float4x4.TRS(
Origin + new float3( 0 , math.sin(theta) , math.cos(theta) )*10f ,
quaternion.Euler( math.radians(new float3(333f,10f,333f)*Time) ) ,
new float3(1,1,1)
);
}
}
}
Ah, so I tried Built-In just now like you, and it's working. I tried the same with URP and still no luck. I will dig around some more, but thank you for this and for including the job system example. I included a simplified version of LetsRenderMeshInstanced that works in Built-In but not URP for me.
using UnityEngine;
[ExecuteAlways]
public class LetsRenderMeshInstanced : MonoBehaviour
{
[SerializeField] Mesh _mesh = null;
[SerializeField] Material _material = null;
Matrix4x4[] _matrices = new Matrix4x4[100];
private RenderParams _renderParams;
void Update()
{
if (_mesh != null && _material != null)
{
if (_renderParams.material != _material)
{
_renderParams.material = _material;
}
UpdateMatrices();
Graphics.RenderMeshInstanced(_renderParams, _mesh, 0, _matrices);
}
}
void UpdateMatrices()
{
Vector3 origin = transform.position;
float time = Time.time;
const float tau = Mathf.PI * 2f;
int numMatrices = _matrices.Length;
for (int i = 0; i < numMatrices; i++)
{
float theta = (float)i / (float)(numMatrices - 1) * tau;
_matrices[i] = Matrix4x4.TRS(
origin + new Vector3(0, Mathf.Sin(theta), Mathf.Cos(theta)) * 10f,
Quaternion.Euler(new Vector3(333f, 10f, 333f) * time),
Vector3.one
);
}
}
}
if( _renderParams.material!=_material ) _renderParams = new RenderParams(_material);
should resolve the issue
It seems that the constructor accepting the material is setting some other necessary property values, especially...
renderingLayerMask = GraphicsSettings.defaultRenderingLayerMask
Yep that fixed it and seems to have fixed my original project as well. Thanks!
Your answer
Follow this Question
Related Questions
Will this script that does drawmeshinstancedprocedural actually work? 0 Answers
Will Camera.RenderWithShader work with Graphics.DrawMesh (and DrawMeshInstanced)? 0 Answers
How to attach a mesh created with Graphics.DrawMesh to a GameObject? 1 Answer
How to access full Shuriken simulation mesh for use with DrawMeshNow? 0 Answers
Graphics.DrawMeshInstanced Does Not Write to _CameraDepthNormalsTexture 1 Answer