Hi
Very confused about instancing trying to make a lot of grass for a game thought id try this approach but …
First the meshes only exist for 1 frame? so they have to be constantly called in update is this right or is there some other command than the one im using in the code below that has the mesh continue to exist ?This code slows my fps down to 5 without me looking at the generated meshes.
using UnityEngine;
using System.Collections;
public class drawm : MonoBehaviour {
public Mesh mesh;
public Material material;
int a=0;
public void Update() {
for (int a = 0; a < 100000; a++) {
int b = a;
int c=a;
transform.position = new Vector3 (b, 0, c);
Graphics.DrawMesh (mesh, transform.position, Quaternion.identity, material, 0);
}
}
}
I looked on github and found this one project that looks promising it is able to run at 60 fps with 100k meshes and 1 million is need to slow it down to the abovementioned 5 fps.But not too clued in on coding so could someone tell me what about the code helps it do that and can that code be integrated into my above sample?
Couple issues with this code below.
First it only works with unity meshes if i try put in any other mesh its invisible.
Second it only works with its shader if i put in any other shader it doesn’t work.
Third the shader isn’t a cutout is it possible to convert it to a cutout shade and will still work with the code?
And lastly and this totally confuses me the instanceCount amount it used to start with was 100k i tried setting the instancecount to 1000 at initiation but that didn’t work so i put the line in the Start which does restrict it but wjhat i don’t see is where is instructs the instancecount to be 100k between the initiation line and the start one?
// https://docs.unity3d.com/560/Documentation/ScriptReference/Graphics.DrawMeshInstancedIndirect.html
using UnityEngine;
public class InstancedIndirectExample : MonoBehaviour
{
public int instanceCount = 1000;
public Mesh instanceMesh;
public Material instanceMaterial;
private int cachedInstanceCount = -1;
private ComputeBuffer positionBuffer;
private ComputeBuffer argsBuffer;
private ComputeBuffer colorBuffer;
private uint[] args = new uint[5] { 0, 0, 0, 0, 0 };
void Start()
{
argsBuffer = new ComputeBuffer(1, args.Length * sizeof(uint), ComputeBufferType.IndirectArguments);
UpdateBuffers();
instanceCount = 1000;?????????
}
void Update()
{
// Update starting position buffer
if (cachedInstanceCount != instanceCount) UpdateBuffers();
// Pad input
if (Input.GetAxisRaw("Horizontal") != 0.0f) instanceCount = (int)Mathf.Clamp(instanceCount + Input.GetAxis("Horizontal") * 40000, 1.0f, 5000000.0f);
// Render
// instanceMaterial.SetBuffer("positionBuffer", positionBuffer);
Graphics.DrawMeshInstancedIndirect(instanceMesh, 0, instanceMaterial, new Bounds(Vector3.zero, new Vector3(100.0f, 100.0f, 100.0f)), argsBuffer);
}
void OnGUI()
{
GUI.Label(new Rect(265, 12, 200, 30), "Instance Count: " + instanceCount.ToString("N0"));
instanceCount = (int)GUI.HorizontalSlider(new Rect(25, 20, 200, 30), (float)instanceCount, 1.0f, 5000000.0f);
}
void UpdateBuffers()
{
if ( instanceCount < 1 ) instanceCount = 1;
// Positions & Colors
if (positionBuffer != null) positionBuffer.Release();
if (colorBuffer != null) colorBuffer.Release();
positionBuffer = new ComputeBuffer(instanceCount, 16);
colorBuffer = new ComputeBuffer(instanceCount, 4*4);
Vector4[] positions = new Vector4[instanceCount];
Vector4[] colors = new Vector4[instanceCount];
for (int i=0; i < instanceCount; i++)
{
float angle = Random.Range(0.0f, Mathf.PI * 2.0f);
float distance = Random.Range(20.0f, 100.0f);
float height = Random.Range(-2.0f, 2.0f);
float size = Random.Range(0.05f, 0.25f);
positions[i] = new Vector4(Mathf.Sin(angle) * distance, height, Mathf.Cos(angle) * distance, size);
colors[i] = new Vector4( Random.value, Random.value, Random.value, 1f );
}
positionBuffer.SetData(positions);
colorBuffer.SetData(colors);
instanceMaterial.SetBuffer("positionBuffer", positionBuffer);
instanceMaterial.SetBuffer("colorBuffer", colorBuffer);
// indirect args
uint numIndices = (instanceMesh != null) ? (uint)instanceMesh.GetIndexCount(0) : 0;
args[0] = numIndices;
args[1] = (uint)instanceCount;
argsBuffer.SetData(args);
cachedInstanceCount = instanceCount;
}
void OnDisable()
{
if (positionBuffer != null) positionBuffer.Release();
positionBuffer = null;
if (colorBuffer != null) colorBuffer.Release();
colorBuffer = null;
if (argsBuffer != null) argsBuffer.Release();
argsBuffer = null;
}
}
And the shader code
Shader "Instanced/InstancedIndirectSurfaceShader"
{
Properties{
_MainTex("Albedo (RGB)", 2D) = "white" {}
_Glossiness("Smoothness", Range(0,1)) = 0.5
_Metallic("Metallic", Range(0,1)) = 0.0
}
SubShader{
Tags{ "RenderType" = "Opaque" }
LOD 200
CGPROGRAM
// Physically based Standard lighting model
#pragma surface surf Standard addshadow
#pragma multi_compile_instancing
#pragma instancing_options procedural:setup
sampler2D _MainTex;
struct Input {
float2 uv_MainTex;
};
#ifdef UNITY_PROCEDURAL_INSTANCING_ENABLED
StructuredBuffer<float4> positionBuffer;
StructuredBuffer<float4> colorBuffer;
#endif
void rotate2D(inout float2 v, float r)
{
float s, c;
sincos(r, s, c);
v = float2(v.x * c - v.y * s, v.x * s + v.y * c);
}
void setup()
{
#ifdef UNITY_PROCEDURAL_INSTANCING_ENABLED
float4 data = positionBuffer[unity_InstanceID];
float rotation = data.w * data.w * _Time.y * 0.5f;
rotate2D(data.xz, rotation);
unity_ObjectToWorld._11_21_31_41 = float4(data.w, 0, 0, 0);
unity_ObjectToWorld._12_22_32_42 = float4(0, data.w, 0, 0);
unity_ObjectToWorld._13_23_33_43 = float4(0, 0, data.w, 0);
unity_ObjectToWorld._14_24_34_44 = float4(data.xyz, 1);
unity_WorldToObject = unity_ObjectToWorld;
unity_WorldToObject._14_24_34 *= -1;
unity_WorldToObject._11_22_33 = 1.0f / unity_WorldToObject._11_22_33;
#endif
}
half _Glossiness;
half _Metallic;
void surf(Input IN, inout SurfaceOutputStandard o)
{
float4 col = 1.0f;
#ifdef UNITY_PROCEDURAL_INSTANCING_ENABLED
//col.gb = (float)(unity_InstanceID % 256) / 255.0f;
col = colorBuffer[unity_InstanceID];
#else
//col.gb = float4(0, 0, 1, 1);
col = float4(0, 0, 1, 1);
#endif
fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * col;
o.Albedo = c.rgb;
o.Metallic = _Metallic;
o.Smoothness = _Glossiness;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
I tried using this shader with my example but the fps remained at 5.
I know its a lot to ask but if someone is feeling helpful if you could explain a couple of these thing to me in layman terms if possible.
Thx in advance