236 lines
6.0 KiB
C#
236 lines
6.0 KiB
C#
//////////////////////////////////////////////////////
|
|
// MicroSplat
|
|
// Copyright (c) Jason Booth
|
|
//////////////////////////////////////////////////////
|
|
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
namespace JBooth.MicroSplat
|
|
{
|
|
[ExecuteAlways]
|
|
public class MicroSplatDecal : MonoBehaviour
|
|
{
|
|
|
|
public enum SplatMode
|
|
{
|
|
SplatMap,
|
|
StreamMap,
|
|
}
|
|
|
|
public enum NormalBlend
|
|
{
|
|
Replace,
|
|
Blend
|
|
}
|
|
|
|
public enum AlbedoBlend
|
|
{
|
|
Blend,
|
|
Multiply2X
|
|
}
|
|
|
|
public MicroSplatDecalReceiver targetObject;
|
|
public int textureIndex = 0;
|
|
public int splatTextureIndex = 0;
|
|
public float albedoOpacity = 1;
|
|
public float smoothnessOpacity = 1;
|
|
public float heightBlend = 0;
|
|
public float normalOpacity = 1;
|
|
public float splatOpacity = 0;
|
|
public Color tint = Color.white;
|
|
public AlbedoBlend albedoBlend = AlbedoBlend.Blend;
|
|
|
|
public SplatMode splatMode = SplatMode.SplatMap;
|
|
public NormalBlend normalBlend = NormalBlend.Replace;
|
|
|
|
#if __MICROSPLAT_TESSELLATION__
|
|
public float tessOpacity = 1;
|
|
public float tessOffset = 0;
|
|
#endif
|
|
|
|
public int sortOrder = 0;
|
|
|
|
#if UNITY_EDITOR
|
|
public static Color staticGizmoColor = new Color(1, 1, 0, 0.35f);
|
|
public static Color staticGizmoSelectedColor = new Color(1, 1, 0, 0.5f);
|
|
public static Color dynamicGizmoColor = new Color(1, 0.25f, 0, 0.35f);
|
|
public static Color dynamicGizmoSelectedColor = new Color(1, 0.25f, 0, 0.5f);
|
|
|
|
public enum GizmoMode
|
|
{
|
|
Hide,
|
|
ShowAll,
|
|
Selected
|
|
}
|
|
public static GizmoMode gizmoMode = GizmoMode.ShowAll;
|
|
#endif
|
|
|
|
public Vector4 splatIndexes = new Vector4(0, 1, 2, 3);
|
|
|
|
|
|
|
|
[SerializeField]
|
|
bool _dynamic = false;
|
|
public bool dynamic
|
|
{
|
|
set
|
|
{
|
|
if (value != _dynamic)
|
|
{
|
|
if (enabled)
|
|
{
|
|
OnDisable();
|
|
}
|
|
_dynamic = value;
|
|
if (enabled)
|
|
{
|
|
OnEnable();
|
|
}
|
|
}
|
|
}
|
|
get
|
|
{
|
|
return _dynamic;
|
|
}
|
|
}
|
|
|
|
#if UNITY_EDITOR
|
|
bool registeredAsDynamic;
|
|
|
|
#endif
|
|
|
|
public void GetShaderData(out Vector4 data1, out Vector4 data2)
|
|
{
|
|
float tessellationData = 0;
|
|
#if __MICROSPLAT_TESSELLATION__
|
|
// pack together
|
|
tessellationData = Mathf.Floor(tessOffset * 256) + tessOpacity * 0.95f;
|
|
#endif
|
|
// encode bool into sign
|
|
float splatOpacityAndMode = (splatOpacity + 1) * ((splatMode == SplatMode.SplatMap) ? 1 : -1);
|
|
// encode normal mode into sign of normal opacity
|
|
float normalOpacityAndBlend = (normalOpacity + 1) * ((normalBlend == NormalBlend.Replace) ? 1 : -1);
|
|
float albedoOpacityAndBlend = (albedoOpacity + 1) * ((albedoBlend == AlbedoBlend.Blend) ? 1 : -1);
|
|
float textureAndSplatIndex = splatTextureIndex * 100 + textureIndex;
|
|
data1 = new Vector4(textureAndSplatIndex, transform.lossyScale.y, splatOpacityAndMode, tessellationData);
|
|
data2 = new Vector4(albedoOpacityAndBlend, normalOpacityAndBlend, smoothnessOpacity, heightBlend);
|
|
|
|
}
|
|
|
|
void InitDecal()
|
|
{
|
|
oldMtx = transform.localToWorldMatrix;
|
|
|
|
if (targetObject != null)
|
|
{
|
|
#if UNITY_EDITOR
|
|
registeredAsDynamic =
|
|
#endif
|
|
targetObject.RegisterDecal(this);
|
|
}
|
|
}
|
|
|
|
private void OnEnable()
|
|
{
|
|
InitDecal();
|
|
}
|
|
|
|
private void Start()
|
|
{
|
|
InitDecal();
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
if (targetObject != null)
|
|
{
|
|
targetObject.UnregisterDecal(this);
|
|
}
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
OnDisable();
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
OnDisable();
|
|
OnEnable();
|
|
}
|
|
|
|
#if UNITY_EDITOR
|
|
void OnDrawGizmos()
|
|
{
|
|
if (gizmoMode == GizmoMode.ShowAll)
|
|
{
|
|
if (registeredAsDynamic)
|
|
Gizmos.color = dynamicGizmoColor;
|
|
else
|
|
Gizmos.color = staticGizmoColor;
|
|
|
|
Gizmos.matrix = transform.localToWorldMatrix;
|
|
Gizmos.DrawCube(Vector3.zero, Vector3.one);
|
|
Gizmos.color = new Color(0, 0, 0, Gizmos.color.a * 1.2f);
|
|
Gizmos.DrawWireCube(Vector3.zero, Vector3.one);
|
|
}
|
|
}
|
|
|
|
void OnDrawGizmosSelected()
|
|
{
|
|
if (gizmoMode != GizmoMode.Hide)
|
|
{
|
|
if (registeredAsDynamic)
|
|
Gizmos.color = dynamicGizmoSelectedColor;
|
|
else
|
|
Gizmos.color = staticGizmoSelectedColor;
|
|
Gizmos.matrix = transform.localToWorldMatrix;
|
|
Gizmos.DrawCube(Vector3.zero, Vector3.one);
|
|
Gizmos.color = new Color(0, 0, 0, Gizmos.color.a * 1.5f);
|
|
Gizmos.DrawWireCube(Vector3.zero, Vector3.one);
|
|
}
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
Matrix4x4 oldMtx;
|
|
|
|
void UpdateRendering()
|
|
{
|
|
if (targetObject != null && targetObject.msObj != null)
|
|
{
|
|
MicroSplatTerrain mst = targetObject.msObj as MicroSplatTerrain;
|
|
if (mst != null)
|
|
{
|
|
targetObject.UpdateDecalInCache(mst.terrain.transform.position, mst.terrain.terrainData.size, this, oldMtx);
|
|
oldMtx = transform.localToWorldMatrix;
|
|
}
|
|
#if __MICROSPLAT_MESHTERRAIN__
|
|
MicroSplatMeshTerrain meshTerrain = targetObject.msObj as MicroSplatMeshTerrain;
|
|
if (meshTerrain != null)
|
|
{
|
|
targetObject.UpdateDecalInCache(meshTerrain.transform.position, meshTerrain.GetBounds().size, this, oldMtx);
|
|
oldMtx = transform.localToWorldMatrix;
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
if (transform.hasChanged)
|
|
{
|
|
transform.hasChanged = false;
|
|
|
|
UpdateRendering();
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
} |