Skip to content

Instantly share code, notes, and snippets.

@EliCDavis
Created May 7, 2022 17:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save EliCDavis/d8f69f42e01a953631c86bb336868649 to your computer and use it in GitHub Desktop.
Save EliCDavis/d8f69f42e01a953631c86bb336868649 to your computer and use it in GitHub Desktop.
Random Instancing Garbage
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DrawMeshInstancedDemo : MonoBehaviour {
[SerializeField]
private Color color1;
[SerializeField]
private Color color2;
public int population;
public Vector3 range;
public Vector3 sizeMin;
public Vector3 sizeMax;
public Material material;
private Matrix4x4[] matrices;
private MaterialPropertyBlock block;
[SerializeField]
private Mesh mesh;
[SerializeField]
private Mesh mesh2;
private void Setup() {
// Mesh mesh = CreateQuad();
// this.mesh = mesh;
matrices = new Matrix4x4[population];
Vector4[] colors = new Vector4[population];
block = new MaterialPropertyBlock();
for (int i = 0; i < population; i++) {
// Build matrix.
Vector3 position = new Vector3(Random.Range(-range.x, range.x), Random.Range(-range.y, range.y), Random.Range(-range.z, range.z));
position.y = Terrain.activeTerrain.SampleHeight(position) - 1.3f;
Quaternion rotation = Quaternion.Euler(Random.Range(-4, 4), Random.Range(-180, 180), Random.Range(-4, 4));
var sizeRange = sizeMax - sizeMin;
Vector3 scale = sizeMin + new Vector3(Random.Range(0, sizeRange.x), Random.Range(0, sizeRange.y), Random.Range(0, sizeRange.z));
var mat = Matrix4x4.TRS(position, rotation, scale);
matrices[i] = mat;
colors[i] = Color.Lerp(Color.red, Color.blue, Random.value);
}
// Custom shader needed to read these!!
block.SetVectorArray("_Colors", colors);
}
// private Mesh CreateQuad(float width = 1f, float height = 1f) {
// // Create a quad mesh.
// // See source for implementation.
// }
private void Start() {
Setup();
}
private void Update() {
// Draw a bunch of meshes each frame.
Graphics.DrawMeshInstanced(mesh, 0, material, matrices, population, block);
Graphics.DrawMeshInstanced(mesh2, 0, material, matrices, population, block);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DrawMeshInstancedIndirectDemo : MonoBehaviour
{
[SerializeField]
private Color color1;
[SerializeField]
private Color color2;
public int population;
public Vector3 range;
public Vector3 sizeMin;
public Vector3 sizeMax;
public Material material;
private ComputeBuffer meshPropertiesBuffer;
private ComputeBuffer argsBuffer;
[SerializeField]
private Mesh mesh;
private Bounds bounds;
private struct MeshProperties
{
public Matrix4x4 mat;
public Vector4 color;
public static int Size()
{
return
sizeof(float) * 4 * 4 + // matrix;
sizeof(float) * 4; // color;
}
}
private void Setup()
{
// Boundary surrounding the meshes we will be drawing. Used for occlusion.
bounds = new Bounds(transform.position, Vector3.one + range);
InitializeBuffers();
}
private void InitializeBuffers()
{
uint[] args = new uint[5] { 0, 0, 0, 0, 0 };
args[0] = (uint)mesh.GetIndexCount(0);
args[1] = (uint)population;
args[2] = (uint)mesh.GetIndexStart(0);
args[3] = (uint)mesh.GetBaseVertex(0);
argsBuffer = new ComputeBuffer(1, args.Length * sizeof(uint), ComputeBufferType.IndirectArguments);
argsBuffer.SetData(args);
// Initialize buffer with the given population.
MeshProperties[] properties = new MeshProperties[population];
for (int i = 0; i < population; i++)
{
MeshProperties props = new MeshProperties();
Vector3 position = new Vector3(Random.Range(-range.x, range.x), Random.Range(-range.y, range.y), Random.Range(-range.z, range.z));
position.y = Terrain.activeTerrain.SampleHeight(position) - 1.3f;
Quaternion rotation = Quaternion.Euler(Random.Range(-4, 4), Random.Range(-180, 180), Random.Range(-4, 4));
var sizeRange = sizeMax - sizeMin;
Vector3 scale = sizeMin + new Vector3(Random.Range(0, sizeRange.x), Random.Range(0, sizeRange.y), Random.Range(0, sizeRange.z));
props.mat = Matrix4x4.TRS(position, rotation, scale);
props.color = Color.Lerp(color1, color2, Random.value);
properties[i] = props;
}
meshPropertiesBuffer = new ComputeBuffer(population, MeshProperties.Size());
meshPropertiesBuffer.SetData(properties);
material.SetBuffer("_Properties", meshPropertiesBuffer);
}
private void Start()
{
Setup();
}
private void Update()
{
Graphics.DrawMeshInstancedIndirect(mesh, 0, material, bounds, argsBuffer);
}
private void OnDisable()
{
// Release gracefully.
if (meshPropertiesBuffer != null)
{
meshPropertiesBuffer.Release();
}
meshPropertiesBuffer = null;
if (argsBuffer != null)
{
argsBuffer.Release();
}
argsBuffer = null;
}
}
Shader "Custom/InstancedIndirectColor" {
Properties
{
_MainTex ("_MainTex (RGBA)", 2D) = "white" {}
}
SubShader {
Tags { "RenderType" = "Opaque" }
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/SurfaceInput.hlsl"
#include "UnityCG.cginc"
struct appdata_t {
float4 vertex : POSITION;
float4 color : COLOR;
float2 uv : TEXCOORD0;
};
struct v2f {
float4 vertex : SV_POSITION;
fixed4 color : COLOR;
float2 uv : TEXCOORD0;
};
struct MeshProperties {
float4x4 mat;
float4 color;
};
sampler2D _MainTex;
float4 _MainTex_ST;
StructuredBuffer<MeshProperties> _Properties;
v2f vert(appdata_t i, uint instanceID: SV_InstanceID) {
v2f o;
float4 pos = mul(_Properties[instanceID].mat, i.vertex);
o.vertex = UnityObjectToClipPos(pos);
o.color = _Properties[instanceID].color;
o.uv = TRANSFORM_TEX(i.uv, _MainTex);
return o;
}
fixed4 frag(v2f i) : SV_Target {
float4 col = tex2D(_MainTex, i.uv);
return col * i.color;
}
ENDCG
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment