using System;
using UnityEngine;
using UnityEngine.Rendering;
namespace sc.terrain.proceduralpainter
{
[Serializable]
public class Modifier : ScriptableObject
{
[HideInInspector]
public bool enabled = true;
[HideInInspector]
public string label;
[HideInInspector]
public BlendMode blendMode;
[HideInInspector]
[Range(0f, 100f)]
public float opacity = 100;
public enum FilterPass
{
Height,
Slope,
Curvature,
TextureMask,
Noise,
Direction
}
[HideInInspector]
public FilterPass passIndex;
public enum BlendMode
{
Multiply,
Add,
Subtract,
Min,
Max
}
private static int SrcFactorID = Shader.PropertyToID("_SrcFactor");
private static int DstFactorID = Shader.PropertyToID("_DstFactor");
private static int BlendOpID = Shader.PropertyToID("_BlendOp");
private static int OpacityID = Shader.PropertyToID("_Opacity");
public static void SetBlendMode(Material mat, BlendMode mode)
{
//Note: The source is actually the current filter, destination the result from previous filters
//Meaning operations are reversed
switch (mode)
{
case BlendMode.Multiply:
{
mat.SetInt(SrcFactorID, (int)UnityEngine.Rendering.BlendMode.DstColor);
mat.SetInt(DstFactorID, (int)UnityEngine.Rendering.BlendMode.SrcColor);
mat.SetInt(BlendOpID, (int)BlendOp.Multiply);
} break;
case BlendMode.Add:
{
mat.SetInt(SrcFactorID, (int)UnityEngine.Rendering.BlendMode.SrcColor);
mat.SetInt(DstFactorID, (int)UnityEngine.Rendering.BlendMode.DstColor);
mat.SetInt(BlendOpID, (int)BlendOp.Add);
} break;
case BlendMode.Subtract:
{
mat.SetInt(SrcFactorID, (int)UnityEngine.Rendering.BlendMode.SrcColor);
mat.SetInt(DstFactorID, (int)UnityEngine.Rendering.BlendMode.DstColor);
mat.SetInt(BlendOpID, (int)BlendOp.ReverseSubtract);
} break;
case BlendMode.Min:
{
mat.SetInt(SrcFactorID, (int)UnityEngine.Rendering.BlendMode.SrcColor);
mat.SetInt(DstFactorID, (int)UnityEngine.Rendering.BlendMode.DstColor);
mat.SetInt(BlendOpID, (int)BlendOp.Min);
} break;
case BlendMode.Max:
{
mat.SetInt(SrcFactorID, (int)UnityEngine.Rendering.BlendMode.SrcColor);
mat.SetInt(DstFactorID, (int)UnityEngine.Rendering.BlendMode.DstColor);
mat.SetInt(BlendOpID, (int)BlendOp.Max);
} break;
default:
throw new ArgumentOutOfRangeException(nameof(mode), mode, null);
}
}
///
/// Set any material properties here. Base implementation must be called, it sets the blend mode and opacity
///
public virtual void Configure(Material material)
{
SetBlendMode(material, blendMode);
material.SetFloat(OpacityID, opacity * 0.01f);
}
public virtual void Execute(RenderTexture target)
{
if (!enabled || opacity == 0) return;
//Debug.Log("Executing: " + this.name + ". SRC: " + source.name + " DEST: " + destination.name + ". Pass: " + passIndex);
Graphics.Blit(null, target, ModifierStack.filterMat, (int)passIndex);
}
}
}