Skip to content

Instantly share code, notes, and snippets.

@gamemachine
Created November 2, 2019 23:49
Show Gist options
  • Save gamemachine/0606a56361f019b8f11a69a1bde85adf to your computer and use it in GitHub Desktop.
Save gamemachine/0606a56361f019b8f11a69a1bde85adf to your computer and use it in GitHub Desktop.
using Sirenix.OdinInspector;
using System.Collections.Generic;
using Unity.Mathematics;
using UnityEngine;
namespace AiGame.Terrains
{
public class MicroSplatBoundsHole : MonoBehaviour
{
private const int MaxHoles = 50;
[SerializeField]
private MicroSplatTerrain MicroSplatTerrain;
[SerializeField]
private BoxCollider Collider;
[SerializeField]
private List<float3x2> Holes = new List<float3x2>();
private void Start()
{
MicroSplatTerrain.OnMaterialSync += OnMaterialSync;
MicroSplatTerrain.Sync();
}
private void OnMaterialSync(Material m)
{
MicroSplatTerrain.OnMaterialSync -= OnMaterialSync;
Vector4[] shaderArray = new Vector4[MaxHoles * 2];
int index = 0;
for (int i=0;i<Holes.Count;i++)
{
float3x2 hole = Holes[i];
shaderArray[index] = new Vector4(hole.c0.x, hole.c0.y, hole.c0.z);
index++;
shaderArray[index] = new Vector4(hole.c1.x, hole.c1.y, hole.c1.z);
index++;
}
m.SetVectorArray("_BoundsHoleArray", shaderArray);
m.SetInt("_BoundsHoleCount", Holes.Count);
}
[Button("SetHole")]
public void SetHole()
{
SetHole(Collider.bounds);
}
public void SetHole(Bounds bounds)
{
if (Holes.Count > MaxHoles)
{
throw new UnityException("MaxHoles exceeded");
}
Holes.Add(new float3x2(bounds.min, bounds.max));
MicroSplatTerrain.OnMaterialSync += OnMaterialSync;
MicroSplatTerrain.Sync();
}
[Button("ClearHoles")]
public void ClearHoles()
{
Holes.Clear();
MicroSplatTerrain.OnMaterialSync += OnMaterialSync;
MicroSplatTerrain.Sync();
}
}
}
// shader content
// Surface function should call ClipAllBounds with i.worldPos
// property
_BoundsHoleCount("BoundsHoleCount", Int) = 0
// shared
float4 _BoundsHoleArray[100];
int _BoundsHoleCount;
void ClipBounds(float3 min, float3 max, float3 pos) {
float a = step(min.x, pos.x);
float b = step(pos.x, max.x);
float c = step(min.y, pos.y);
float d = step(pos.y, max.y);
float e = step(min.z, pos.z);
float f = step(pos.z, max.z);
clip(5.0f - a - b - c - d - e - f);
}
void ClipAllBounds(float3 worldPos)
{
int index = 0;
for(int i=0;i<_BoundsHoleCount;i++)
{
float4 min = _BoundsHoleArray[index];
index++;
if (min.x > 0.0f)
{
float4 max = _BoundsHoleArray[index];
ClipBounds(min.xyz, max.xyz, worldPos);
}
index++;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment