初始化
This commit is contained in:
662
Assets/Plugins/Easy performant outline/Scripts/OutlineEffect.cs
Normal file
662
Assets/Plugins/Easy performant outline/Scripts/OutlineEffect.cs
Normal file
@@ -0,0 +1,662 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace EPOOutline
|
||||
{
|
||||
public static class OutlineEffect
|
||||
{
|
||||
public static readonly int FillRefHash = Shader.PropertyToID("_FillRef");
|
||||
public static readonly int ColorMaskHash = Shader.PropertyToID("_ColorMask");
|
||||
public static readonly int OutlineRefHash = Shader.PropertyToID("_OutlineRef");
|
||||
public static readonly int RefHash = Shader.PropertyToID("_Ref");
|
||||
public static readonly int EffectSizeHash = Shader.PropertyToID("_EffectSize");
|
||||
public static readonly int CullHash = Shader.PropertyToID("_Cull");
|
||||
public static readonly int ZTestHash = Shader.PropertyToID("_ZTest");
|
||||
public static readonly int ColorHash = Shader.PropertyToID("_EPOColor");
|
||||
public static readonly int ScaleHash = Shader.PropertyToID("_Scale");
|
||||
public static readonly int ShiftHash = Shader.PropertyToID("_Shift");
|
||||
public static readonly int InfoBufferHash = Shader.PropertyToID("_InfoBuffer");
|
||||
public static readonly int ComparisonHash = Shader.PropertyToID("_Comparison");
|
||||
public static readonly int ReadMaskHash = Shader.PropertyToID("_ReadMask");
|
||||
public static readonly int OperationHash = Shader.PropertyToID("_Operation");
|
||||
public static readonly int CutoutThresholdHash = Shader.PropertyToID("_CutoutThreshold");
|
||||
public static readonly int CutoutMaskHash = Shader.PropertyToID("_CutoutMask");
|
||||
public static readonly int TextureIndexHash = Shader.PropertyToID("_TextureIndex");
|
||||
public static readonly int CutoutTextureHash = Shader.PropertyToID("_CutoutTexture");
|
||||
public static readonly int CutoutTextureSTHash = Shader.PropertyToID("_CutoutTexture_ST");
|
||||
public static readonly int SrcBlendHash = Shader.PropertyToID("_SrcBlend");
|
||||
public static readonly int DstBlendHash = Shader.PropertyToID("_DstBlend");
|
||||
|
||||
private static Material OutlineMaterial;
|
||||
private static Material ObstacleMaterial;
|
||||
private static Material FillMaskMaterial;
|
||||
private static Material ZPrepassMaterial;
|
||||
private static Material DilateMaterial;
|
||||
private static Material BlurMaterial;
|
||||
private static Material FinalBlitMaterial;
|
||||
private static Material BasicBlitMaterial;
|
||||
private static Material ClearStencilMaterial;
|
||||
|
||||
private static RTHandleSystem system;
|
||||
|
||||
public static RTHandleSystem HandleSystem
|
||||
{
|
||||
get
|
||||
{
|
||||
if (system != null)
|
||||
return system;
|
||||
|
||||
system = new RTHandleSystem();
|
||||
system.Initialize(1, 1);
|
||||
|
||||
return system;
|
||||
}
|
||||
}
|
||||
|
||||
private struct OutlineTargetGroup
|
||||
{
|
||||
public readonly Outlinable Outlinable;
|
||||
public readonly OutlineTarget Target;
|
||||
|
||||
public OutlineTargetGroup(Outlinable outlinable, OutlineTarget target)
|
||||
{
|
||||
Outlinable = outlinable;
|
||||
Target = target;
|
||||
}
|
||||
}
|
||||
|
||||
private static List<OutlineTargetGroup> targets = new List<OutlineTargetGroup>();
|
||||
|
||||
private static List<string> keywords = new List<string>();
|
||||
|
||||
private static Material LoadMaterial(string shaderName)
|
||||
{
|
||||
var material = new Material(Resources.Load<Shader>(string.Format("Easy performant outline/Shaders/{0}", shaderName)));
|
||||
if (SystemInfo.supportsInstancing)
|
||||
material.enableInstancing = true;
|
||||
|
||||
return material;
|
||||
}
|
||||
|
||||
[RuntimeInitializeOnLoadMethod]
|
||||
private static void InitMaterials()
|
||||
{
|
||||
if (ObstacleMaterial == null)
|
||||
ObstacleMaterial = LoadMaterial("Obstacle");
|
||||
|
||||
if (OutlineMaterial == null)
|
||||
OutlineMaterial = LoadMaterial("Outline");
|
||||
|
||||
if (ZPrepassMaterial == null)
|
||||
ZPrepassMaterial = LoadMaterial("ZPrepass");
|
||||
|
||||
if (DilateMaterial == null)
|
||||
DilateMaterial = LoadMaterial("Dilate");
|
||||
|
||||
if (BlurMaterial == null)
|
||||
BlurMaterial = LoadMaterial("Blur");
|
||||
|
||||
if (FinalBlitMaterial == null)
|
||||
FinalBlitMaterial = LoadMaterial("FinalBlit");
|
||||
|
||||
if (BasicBlitMaterial == null)
|
||||
BasicBlitMaterial = LoadMaterial("BasicBlit");
|
||||
|
||||
if (FillMaskMaterial == null)
|
||||
FillMaskMaterial = LoadMaterial("Fills/FillMask");
|
||||
|
||||
if (ClearStencilMaterial == null)
|
||||
ClearStencilMaterial = LoadMaterial("ClearStencil");
|
||||
}
|
||||
|
||||
private static void Postprocess(OutlineParameters parameters, RTHandle first, RTHandle second, Material material, int iterations, int eyeSlice, bool additionalShift, float shiftValue, ref int stencil, Rect viewport, float scale)
|
||||
{
|
||||
if (iterations <= 0)
|
||||
return;
|
||||
|
||||
parameters.Buffer.SetGlobalInt(ComparisonHash, (int)CompareFunction.Equal);
|
||||
|
||||
for (var index = 1; index <= iterations; index++)
|
||||
{
|
||||
parameters.Buffer.SetGlobalInt(RefHash, stencil);
|
||||
|
||||
var shift = (additionalShift ? (float)index : 1.0f);
|
||||
|
||||
parameters.Buffer.SetGlobalVector(ShiftHash, new Vector4(shift * scale, 0));
|
||||
Blit(parameters, first, second, first, material, shiftValue, eyeSlice, -1, viewport);
|
||||
|
||||
stencil = (stencil + 1) % 255;
|
||||
parameters.Buffer.SetGlobalInt(RefHash, stencil);
|
||||
|
||||
parameters.Buffer.SetGlobalVector(ShiftHash, new Vector4(0, shift * scale));
|
||||
Blit(parameters, second, first, first, material, shiftValue, eyeSlice, -1, viewport);
|
||||
|
||||
stencil = (stencil + 1) % 255;
|
||||
}
|
||||
}
|
||||
|
||||
private static void Blit(OutlineParameters parameters, RTHandle source, RTHandle destination, RTHandle destinationDepth, Material material, float effectSize, int eyeSlice, int pass = -1, Rect? viewport = null)
|
||||
{
|
||||
parameters.Buffer.SetGlobalFloat(EffectSizeHash, effectSize);
|
||||
BlitUtility.Blit(parameters, source, destination, destinationDepth, eyeSlice, material, pass, viewport);
|
||||
}
|
||||
|
||||
private static void Draw(OutlineParameters parameters, RTHandle destination, RTHandle destinationDepth, Material material, float effectSize, int eyeSlice, int pass = -1, Rect? viewport = null)
|
||||
{
|
||||
parameters.Buffer.SetGlobalFloat(EffectSizeHash, effectSize);
|
||||
BlitUtility.Draw(parameters, destination, destinationDepth, eyeSlice, material, pass, viewport);
|
||||
}
|
||||
|
||||
private static float GetBlurShift(BlurType blurType, int iterationsCount)
|
||||
{
|
||||
switch (blurType)
|
||||
{
|
||||
case BlurType.Box:
|
||||
return (float)(iterationsCount * 0.65f) + 1.0f;
|
||||
case BlurType.Gaussian5x5:
|
||||
return 3.0f * + iterationsCount;
|
||||
case BlurType.Gaussian9x9:
|
||||
return 5.0f + iterationsCount;
|
||||
case BlurType.Gaussian13x13:
|
||||
return 7.0f + iterationsCount;
|
||||
default:
|
||||
throw new ArgumentException("Unknown blur type");
|
||||
}
|
||||
}
|
||||
|
||||
private static float GetMaskingValueForMode(OutlinableDrawingMode mode)
|
||||
{
|
||||
if ((mode & OutlinableDrawingMode.Mask) != 0)
|
||||
return 0.6f;
|
||||
|
||||
return (mode & OutlinableDrawingMode.Obstacle) != 0 ? 0.25f : 1.0f;
|
||||
}
|
||||
|
||||
private static float ComputeEffectShift(OutlineParameters parameters)
|
||||
{
|
||||
var effectShift = GetBlurShift(parameters.BlurType, parameters.BlurIterations) * parameters.BlurShift + parameters.DilateIterations * 4.0f * parameters.DilateShift;
|
||||
return effectShift * 1.1f;
|
||||
}
|
||||
|
||||
private static void PrepareTargets(OutlineParameters parameters)
|
||||
{
|
||||
targets.Clear();
|
||||
|
||||
foreach (var outlinable in parameters.OutlinablesToRender)
|
||||
{
|
||||
for (var index = 0; index < outlinable.OutlineTargets.Count; index++)
|
||||
{
|
||||
var target = outlinable.OutlineTargets[index];
|
||||
var renderer = target.Renderer;
|
||||
if (!target.IsVisible)
|
||||
{
|
||||
if ((outlinable.DrawingMode & OutlinableDrawingMode.GenericMask) == 0 || renderer == null)
|
||||
continue;
|
||||
}
|
||||
|
||||
targets.Add(new OutlineTargetGroup(outlinable, target));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetupOutline(OutlineParameters parameters)
|
||||
{
|
||||
parameters.Buffer.SetRenderTarget(parameters.Handles.Target, -1);
|
||||
parameters.Buffer.ClearRenderTarget(true, true, Color.clear);
|
||||
|
||||
parameters.Buffer.SetGlobalVector(ScaleHash, parameters.Scale);
|
||||
PrepareTargets(parameters);
|
||||
InitMaterials();
|
||||
var expectedEffectShift = ComputeEffectShift(parameters);
|
||||
var effectShift = expectedEffectShift + 3;
|
||||
var finalBlitEffectShift = expectedEffectShift;
|
||||
|
||||
var eyeDepthSlice = RenderTargetUtility.GetDepthSliceForEye(parameters.EyeMask);
|
||||
|
||||
parameters.Buffer.SetRenderTarget(parameters.Handles.PrimaryTarget, -1);
|
||||
parameters.Buffer.ClearRenderTarget(true, true, Color.clear);
|
||||
|
||||
parameters.Buffer.SetRenderTarget(parameters.Handles.SecondaryTarget, -1);
|
||||
parameters.Buffer.ClearRenderTarget(true, true, Color.clear);
|
||||
|
||||
if (parameters.UseInfoBuffer)
|
||||
{
|
||||
parameters.Buffer.SetRenderTarget(parameters.Handles.InfoTarget, -1);
|
||||
parameters.Buffer.ClearRenderTarget(true, true, Color.clear);
|
||||
|
||||
parameters.Buffer.SetRenderTarget(parameters.Handles.PrimaryInfoBufferTarget, -1);
|
||||
parameters.Buffer.ClearRenderTarget(true, true, Color.clear);
|
||||
|
||||
parameters.Buffer.SetRenderTarget(parameters.Handles.SecondaryInfoBufferTarget, -1);
|
||||
parameters.Buffer.ClearRenderTarget(true, true, Color.clear);
|
||||
}
|
||||
|
||||
parameters.Buffer.SetGlobalInt(SrcBlendHash, (int)BlendMode.One);
|
||||
parameters.Buffer.SetGlobalInt(DstBlendHash, (int)BlendMode.Zero);
|
||||
|
||||
var outlineRef = 1;
|
||||
parameters.Buffer.SetGlobalInt(OutlineRefHash, outlineRef);
|
||||
|
||||
SetupDilateKeyword(parameters);
|
||||
|
||||
var scaledViewVector = new Vector2Int(parameters.ScaledBufferWidth, parameters.ScaledBufferHeight);
|
||||
|
||||
BlitUtility.PrepareForRendering(parameters);
|
||||
|
||||
parameters.Buffer.SetRenderTarget(parameters.Handles.Target, parameters.DepthTarget, eyeDepthSlice);
|
||||
parameters.Buffer.ClearRenderTarget(false, true, Color.clear);
|
||||
parameters.Buffer.SetViewport(parameters.Viewport);
|
||||
|
||||
DrawOutlineables(parameters, CompareFunction.LessEqual, x => true, x => Color.clear, x => ZPrepassMaterial, RenderStyle.FrontBack | RenderStyle.Single, OutlinableDrawingMode.ZOnly);
|
||||
|
||||
parameters.Buffer.DisableShaderKeyword(KeywordsUtility.GetEnabledInfoBufferKeyword());
|
||||
|
||||
if (parameters.UseInfoBuffer)
|
||||
{
|
||||
parameters.Buffer.EnableShaderKeyword(KeywordsUtility.GetInfoBufferStageKeyword());
|
||||
|
||||
parameters.Buffer.SetRenderTarget(parameters.Handles.InfoTarget, parameters.DepthTarget, eyeDepthSlice);
|
||||
parameters.Buffer.ClearRenderTarget(false, true, Color.clear);
|
||||
parameters.Buffer.SetViewport(parameters.Viewport);
|
||||
|
||||
DrawOutlineables(parameters, CompareFunction.Always, x => x.OutlineParameters.Enabled, x => new Color(x.OutlineParameters.DilateShift, x.OutlineParameters.BlurShift, 0, 1),
|
||||
x => OutlineMaterial,
|
||||
RenderStyle.Single,
|
||||
OutlinableDrawingMode.Normal);
|
||||
|
||||
DrawOutlineables(parameters, CompareFunction.NotEqual, x => x.BackParameters.Enabled, x => new Color(x.BackParameters.DilateShift, x.BackParameters.BlurShift, 0, 1),
|
||||
x => OutlineMaterial,
|
||||
RenderStyle.FrontBack);
|
||||
|
||||
DrawOutlineables(parameters, CompareFunction.LessEqual, x => x.FrontParameters.Enabled, x => new Color(x.FrontParameters.DilateShift, x.FrontParameters.BlurShift, 0, 1),
|
||||
x => OutlineMaterial,
|
||||
RenderStyle.FrontBack,
|
||||
OutlinableDrawingMode.Normal);
|
||||
|
||||
DrawOutlineables(parameters, CompareFunction.LessEqual, x => true, x => new Color(0, 0, GetMaskingValueForMode(x.DrawingMode), 1),
|
||||
x => ObstacleMaterial,
|
||||
RenderStyle.Single | RenderStyle.FrontBack,
|
||||
OutlinableDrawingMode.Obstacle | OutlinableDrawingMode.Mask);
|
||||
|
||||
parameters.Buffer.SetGlobalInt(ComparisonHash, (int)CompareFunction.Always);
|
||||
parameters.Buffer.SetGlobalInt(OperationHash, (int)StencilOp.Keep);
|
||||
Blit(parameters,
|
||||
parameters.Handles.InfoTarget,
|
||||
parameters.Handles.PrimaryInfoBufferTarget,
|
||||
parameters.Handles.PrimaryInfoBufferTarget,
|
||||
BasicBlitMaterial, effectShift,
|
||||
-1, -1, new Rect(0, 0, scaledViewVector.x, scaledViewVector.y));
|
||||
|
||||
var iterationsCount =
|
||||
(parameters.DilateQuality == DilateQuality.Base
|
||||
? parameters.DilateIterations
|
||||
: parameters.DilateIterations * 2) + parameters.BlurIterations;
|
||||
|
||||
var infoRef = 0;
|
||||
Postprocess(parameters, parameters.Handles.PrimaryInfoBufferTarget, parameters.Handles.SecondaryInfoBufferTarget, DilateMaterial, iterationsCount,
|
||||
eyeDepthSlice,
|
||||
true,
|
||||
effectShift, ref infoRef,
|
||||
new Rect(0, 0, scaledViewVector.x, scaledViewVector.y),
|
||||
1.0f);
|
||||
|
||||
parameters.Buffer.SetRenderTarget(parameters.Handles.InfoTarget, parameters.DepthTarget, eyeDepthSlice);
|
||||
parameters.Buffer.SetViewport(parameters.Viewport);
|
||||
|
||||
parameters.Buffer.SetGlobalTexture(InfoBufferHash, parameters.Handles.PrimaryInfoBufferTarget);
|
||||
|
||||
parameters.Buffer.DisableShaderKeyword(KeywordsUtility.GetInfoBufferStageKeyword());
|
||||
}
|
||||
|
||||
if (parameters.UseInfoBuffer)
|
||||
parameters.Buffer.EnableShaderKeyword(KeywordsUtility.GetEnabledInfoBufferKeyword());
|
||||
|
||||
parameters.Buffer.SetRenderTarget(parameters.Handles.Target, parameters.DepthTarget, eyeDepthSlice);
|
||||
parameters.Buffer.ClearRenderTarget(false, true, Color.clear);
|
||||
parameters.Buffer.SetViewport(parameters.Viewport);
|
||||
|
||||
var drawnOutlinablesCount = 0;
|
||||
drawnOutlinablesCount += DrawOutlineables(parameters, CompareFunction.Always, x => x.OutlineParameters.Enabled, x => x.OutlineParameters.Color,
|
||||
x => OutlineMaterial,
|
||||
RenderStyle.Single, OutlinableDrawingMode.Normal);
|
||||
|
||||
drawnOutlinablesCount += DrawOutlineables(parameters, CompareFunction.NotEqual, x => x.BackParameters.Enabled, x => x.BackParameters.Color,
|
||||
x => OutlineMaterial,
|
||||
RenderStyle.FrontBack, OutlinableDrawingMode.Normal);
|
||||
|
||||
drawnOutlinablesCount += DrawOutlineables(parameters, CompareFunction.LessEqual, x => x.FrontParameters.Enabled, x => x.FrontParameters.Color,
|
||||
x => OutlineMaterial,
|
||||
RenderStyle.FrontBack, OutlinableDrawingMode.Normal);
|
||||
|
||||
var postProcessingRef = 0;
|
||||
if (drawnOutlinablesCount > 0)
|
||||
{
|
||||
parameters.Buffer.SetGlobalInt(ComparisonHash, (int)CompareFunction.Always);
|
||||
parameters.Buffer.SetGlobalInt(OperationHash, (int)StencilOp.Keep);
|
||||
Blit(parameters, parameters.Handles.Target,
|
||||
parameters.Handles.PrimaryTarget,
|
||||
parameters.Handles.PrimaryTarget,
|
||||
BasicBlitMaterial, effectShift, eyeDepthSlice, -1,
|
||||
new Rect(0, 0, scaledViewVector.x, scaledViewVector.y));
|
||||
|
||||
Postprocess(parameters, parameters.Handles.PrimaryTarget, parameters.Handles.SecondaryTarget, DilateMaterial, parameters.DilateIterations, eyeDepthSlice, false, effectShift, ref postProcessingRef,
|
||||
new Rect(0, 0, scaledViewVector.x, scaledViewVector.y),
|
||||
parameters.DilateShift);
|
||||
}
|
||||
|
||||
parameters.Buffer.SetViewport(parameters.Viewport);
|
||||
|
||||
if (drawnOutlinablesCount > 0)
|
||||
{
|
||||
SetupBlurKeyword(parameters);
|
||||
Postprocess(parameters, parameters.Handles.PrimaryTarget, parameters.Handles.SecondaryTarget,
|
||||
BlurMaterial, parameters.BlurIterations, eyeDepthSlice, false,
|
||||
effectShift,
|
||||
ref postProcessingRef,
|
||||
new Rect(0, 0, scaledViewVector.x, scaledViewVector.y),
|
||||
parameters.BlurShift);
|
||||
}
|
||||
|
||||
parameters.Buffer.SetGlobalTexture(Shader.PropertyToID("_Mask"), parameters.Handles.Target);
|
||||
|
||||
Blit(parameters,
|
||||
parameters.Handles.PrimaryTarget,
|
||||
parameters.Target,
|
||||
parameters.DepthTarget,
|
||||
FinalBlitMaterial,
|
||||
finalBlitEffectShift, eyeDepthSlice, -1,
|
||||
parameters.Viewport);
|
||||
|
||||
DrawFill(parameters, parameters.Target);
|
||||
|
||||
Draw(parameters,
|
||||
parameters.Target,
|
||||
parameters.DepthTarget,
|
||||
ClearStencilMaterial,
|
||||
finalBlitEffectShift, eyeDepthSlice, -1,
|
||||
parameters.Viewport);
|
||||
}
|
||||
|
||||
private static void SetupDilateKeyword(OutlineParameters parameters)
|
||||
{
|
||||
KeywordsUtility.GetAllDilateKeywords(keywords);
|
||||
foreach (var keyword in keywords)
|
||||
parameters.Buffer.DisableShaderKeyword(keyword);
|
||||
|
||||
parameters.Buffer.EnableShaderKeyword(KeywordsUtility.GetDilateQualityKeyword(parameters.DilateQuality));
|
||||
}
|
||||
|
||||
private static void SetupBlurKeyword(OutlineParameters parameters)
|
||||
{
|
||||
KeywordsUtility.GetAllBlurKeywords(keywords);
|
||||
foreach (var keyword in keywords)
|
||||
parameters.Buffer.DisableShaderKeyword(keyword);
|
||||
|
||||
parameters.Buffer.EnableShaderKeyword(KeywordsUtility.GetBlurKeyword(parameters.BlurType));
|
||||
}
|
||||
|
||||
private static int DrawOutlineables(OutlineParameters parameters, CompareFunction function, Func<Outlinable, bool> shouldRender, Func<Outlinable, Color> colorProvider, Func<Outlinable, Material> materialProvider, RenderStyle styleMask, OutlinableDrawingMode modeMask = OutlinableDrawingMode.Normal)
|
||||
{
|
||||
var drawnCount = 0;
|
||||
parameters.Buffer.SetGlobalInt(ZTestHash, (int)function);
|
||||
|
||||
SetMaskingMasking(parameters.Buffer, ComplexMaskingMode.None);
|
||||
var complexMaskingMode = ComplexMaskingMode.None;
|
||||
|
||||
foreach (var targetGroup in targets)
|
||||
{
|
||||
var outlinable = targetGroup.Outlinable;
|
||||
if ((int)(outlinable.RenderStyle & styleMask) == 0)
|
||||
continue;
|
||||
|
||||
if ((int)(outlinable.DrawingMode & modeMask) == 0)
|
||||
continue;
|
||||
|
||||
if ((function == CompareFunction.NotEqual || function == CompareFunction.Always) &&
|
||||
outlinable.ComplexMaskingMode != complexMaskingMode)
|
||||
{
|
||||
SetMaskingMasking(parameters.Buffer, outlinable.ComplexMaskingMode);
|
||||
complexMaskingMode = outlinable.ComplexMaskingMode;
|
||||
}
|
||||
|
||||
var color = shouldRender(outlinable) ? colorProvider(outlinable) : Color.clear;
|
||||
|
||||
parameters.Buffer.SetGlobalColor(ColorHash, color);
|
||||
var target = targetGroup.Target;
|
||||
|
||||
parameters.Buffer.SetGlobalInt(ColorMaskHash, 255);
|
||||
|
||||
SetupCutout(parameters, target);
|
||||
SetupCull(parameters, target);
|
||||
|
||||
drawnCount++;
|
||||
|
||||
var materialToUse = materialProvider(outlinable);
|
||||
parameters.Buffer.DrawRenderer(target.Renderer, materialToUse, target.ShiftedSubmeshIndex);
|
||||
}
|
||||
|
||||
SetMaskingMasking(parameters.Buffer, ComplexMaskingMode.None);
|
||||
|
||||
return drawnCount;
|
||||
}
|
||||
|
||||
private static void SetMaskingMasking(CommandBufferWrapper buffer, ComplexMaskingMode maskingMode)
|
||||
{
|
||||
buffer.DisableShaderKeyword(KeywordsUtility.GetBackKeyword(ComplexMaskingMode.MaskingMode));
|
||||
buffer.DisableShaderKeyword(KeywordsUtility.GetBackKeyword(ComplexMaskingMode.ObstaclesMode));
|
||||
|
||||
if (maskingMode != ComplexMaskingMode.None)
|
||||
buffer.EnableShaderKeyword(KeywordsUtility.GetBackKeyword(maskingMode));
|
||||
}
|
||||
|
||||
private static void DrawFill(OutlineParameters parameters, RTHandle targetSurface)
|
||||
{
|
||||
var eye = RenderTargetUtility.GetDepthSliceForEye(parameters.EyeMask);
|
||||
parameters.Buffer.SetRenderTarget(targetSurface, parameters.DepthTarget, eye);
|
||||
parameters.Buffer.SetViewport(parameters.Viewport);
|
||||
|
||||
var singleMask = 1;
|
||||
var frontMask = 2;
|
||||
var backMask = 3;
|
||||
|
||||
parameters.Buffer.SetGlobalInt(ZTestHash, (int)CompareFunction.Greater);
|
||||
parameters.Buffer.SetGlobalInt(FillRefHash, backMask);
|
||||
foreach (var outlinable in parameters.OutlinablesToRender)
|
||||
{
|
||||
if ((outlinable.DrawingMode & OutlinableDrawingMode.Normal) == 0)
|
||||
continue;
|
||||
|
||||
for (var index = 0; index < outlinable.OutlineTargets.Count; index++)
|
||||
{
|
||||
var target = outlinable.OutlineTargets[index];
|
||||
if (!target.IsVisible)
|
||||
continue;
|
||||
|
||||
var renderer = target.Renderer;
|
||||
if (!outlinable.NeedsFillMask)
|
||||
continue;
|
||||
|
||||
SetupCutout(parameters, target);
|
||||
SetupCull(parameters, target);
|
||||
|
||||
parameters.Buffer.DrawRenderer(renderer, FillMaskMaterial, target.ShiftedSubmeshIndex);
|
||||
}
|
||||
}
|
||||
|
||||
parameters.Buffer.SetGlobalInt(ZTestHash, (int)CompareFunction.LessEqual);
|
||||
parameters.Buffer.SetGlobalInt(FillRefHash, frontMask);
|
||||
foreach (var outlinable in parameters.OutlinablesToRender)
|
||||
{
|
||||
if ((outlinable.DrawingMode & OutlinableDrawingMode.Normal) == 0)
|
||||
continue;
|
||||
|
||||
for (var index = 0; index < outlinable.OutlineTargets.Count; index++)
|
||||
{
|
||||
var target = outlinable.OutlineTargets[index];
|
||||
if (!target.IsVisible)
|
||||
continue;
|
||||
|
||||
if (!outlinable.NeedsFillMask)
|
||||
continue;
|
||||
|
||||
var renderer = target.Renderer;
|
||||
SetupCutout(parameters, target);
|
||||
SetupCull(parameters, target);
|
||||
|
||||
parameters.Buffer.DrawRenderer(renderer, FillMaskMaterial, target.ShiftedSubmeshIndex);
|
||||
}
|
||||
}
|
||||
|
||||
var currentMaskingMode = ComplexMaskingMode.None;
|
||||
SetMaskingMasking(parameters.Buffer, ComplexMaskingMode.None);
|
||||
|
||||
foreach (var outlinable in parameters.OutlinablesToRender)
|
||||
{
|
||||
if ((outlinable.DrawingMode & OutlinableDrawingMode.Normal) == 0)
|
||||
continue;
|
||||
|
||||
if (outlinable.ComplexMaskingMode != currentMaskingMode)
|
||||
{
|
||||
SetMaskingMasking(parameters.Buffer, outlinable.ComplexMaskingMode);
|
||||
currentMaskingMode = ComplexMaskingMode.None;
|
||||
}
|
||||
|
||||
if (outlinable.RenderStyle == RenderStyle.FrontBack)
|
||||
{
|
||||
if ((outlinable.BackParameters.FillPass.Material == null || !outlinable.BackParameters.Enabled) &&
|
||||
(outlinable.FrontParameters.FillPass.Material == null || !outlinable.FrontParameters.Enabled))
|
||||
continue;
|
||||
|
||||
var frontMaterial = outlinable.FrontParameters.FillPass.Material;
|
||||
parameters.Buffer.SetGlobalInt(FillRefHash, frontMask);
|
||||
if (frontMaterial != null && outlinable.FrontParameters.Enabled)
|
||||
{
|
||||
for (var index = 0; index < outlinable.OutlineTargets.Count; index++)
|
||||
{
|
||||
var target = outlinable.OutlineTargets[index];
|
||||
if (!target.IsVisible)
|
||||
continue;
|
||||
|
||||
var renderer = target.Renderer;
|
||||
SetupCutout(parameters, target);
|
||||
SetupCull(parameters, target);
|
||||
|
||||
parameters.Buffer.DrawRenderer(renderer, frontMaterial, target.ShiftedSubmeshIndex);
|
||||
}
|
||||
}
|
||||
|
||||
var backMaterial = outlinable.BackParameters.FillPass.Material;
|
||||
parameters.Buffer.SetGlobalInt(FillRefHash, backMask);
|
||||
if (backMaterial == null || !outlinable.BackParameters.Enabled)
|
||||
continue;
|
||||
|
||||
for (var index = 0; index < outlinable.OutlineTargets.Count; index++)
|
||||
{
|
||||
var target = outlinable.OutlineTargets[index];
|
||||
if (!target.IsVisible)
|
||||
continue;
|
||||
|
||||
var renderer = target.Renderer;
|
||||
SetupCutout(parameters, target);
|
||||
SetupCull(parameters, target);
|
||||
|
||||
parameters.Buffer.DrawRenderer(renderer, backMaterial, target.ShiftedSubmeshIndex);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (outlinable.OutlineParameters.FillPass.Material == null)
|
||||
continue;
|
||||
|
||||
if (!outlinable.OutlineParameters.Enabled)
|
||||
continue;
|
||||
|
||||
parameters.Buffer.SetGlobalInt(ZTestHash, (int)CompareFunction.Always);
|
||||
parameters.Buffer.SetGlobalInt(FillRefHash, singleMask);
|
||||
var fillMaterial = outlinable.OutlineParameters.FillPass.Material;
|
||||
|
||||
for (var index = 0; index < outlinable.OutlineTargets.Count; index++)
|
||||
{
|
||||
var target = outlinable.OutlineTargets[index];
|
||||
if (!target.IsVisible)
|
||||
continue;
|
||||
|
||||
var renderer = target.Renderer;
|
||||
SetupCutout(parameters, target);
|
||||
SetupCull(parameters, target);
|
||||
|
||||
parameters.Buffer.DrawRenderer(renderer, fillMaterial, target.ShiftedSubmeshIndex);
|
||||
}
|
||||
}
|
||||
|
||||
if (outlinable.ComplexMaskingMode != ComplexMaskingMode.None)
|
||||
SetMaskingMasking(parameters.Buffer, ComplexMaskingMode.None);
|
||||
}
|
||||
}
|
||||
|
||||
private static void SetupCutout(OutlineParameters parameters, OutlineTarget target)
|
||||
{
|
||||
if (target.Renderer == null)
|
||||
return;
|
||||
|
||||
var mask = new Vector4(
|
||||
(target.CutoutMask & ColorMask.R) != ColorMask.None ? 1.0f : 0.0f,
|
||||
(target.CutoutMask & ColorMask.G) != ColorMask.None ? 1.0f : 0.0f,
|
||||
(target.CutoutMask & ColorMask.B) != ColorMask.None ? 1.0f : 0.0f,
|
||||
(target.CutoutMask & ColorMask.A) != ColorMask.None ? 1.0f : 0.0f);
|
||||
|
||||
parameters.Buffer.SetGlobalVector(CutoutMaskHash, mask);
|
||||
|
||||
if (target.Renderer is SpriteRenderer spriteRenderer)
|
||||
{
|
||||
var sprite = spriteRenderer.sprite;
|
||||
if (sprite == null || sprite.texture == null)
|
||||
{
|
||||
parameters.Buffer.DisableShaderKeyword(KeywordsUtility.GetCutoutKeyword());
|
||||
return;
|
||||
}
|
||||
|
||||
parameters.Buffer.EnableShaderKeyword(KeywordsUtility.GetCutoutKeyword());
|
||||
parameters.Buffer.SetGlobalFloat(CutoutThresholdHash, target.CutoutThreshold);
|
||||
var rt = parameters.TextureHandleMap[spriteRenderer.sprite.texture];
|
||||
parameters.Buffer.SetGlobalTexture(CutoutTextureHash, rt);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (target.IsValidForCutout)
|
||||
{
|
||||
var sharedMaterial = target.SharedMaterial;
|
||||
|
||||
parameters.Buffer.EnableShaderKeyword(KeywordsUtility.GetCutoutKeyword());
|
||||
parameters.Buffer.SetGlobalFloat(CutoutThresholdHash, target.CutoutThreshold);
|
||||
|
||||
var offset = sharedMaterial.GetTextureOffset(target.CutoutTextureId);
|
||||
var scale = sharedMaterial.GetTextureScale(target.CutoutTextureId);
|
||||
|
||||
parameters.Buffer.SetGlobalVector(CutoutTextureSTHash, new Vector4(scale.x, scale.y, offset.x, offset.y));
|
||||
|
||||
var texture = target.CutoutTexture;
|
||||
if (texture == null || texture.dimension != TextureDimension.Tex2DArray)
|
||||
parameters.Buffer.DisableShaderKeyword(KeywordsUtility.GetTextureArrayCutoutKeyword());
|
||||
else
|
||||
{
|
||||
parameters.Buffer.SetGlobalFloat(TextureIndexHash, target.CutoutTextureIndex);
|
||||
parameters.Buffer.EnableShaderKeyword(KeywordsUtility.GetTextureArrayCutoutKeyword());
|
||||
}
|
||||
|
||||
parameters.Buffer.SetGlobalTexture(CutoutTextureHash, parameters.TextureHandleMap[texture]);
|
||||
}
|
||||
else
|
||||
parameters.Buffer.DisableShaderKeyword(KeywordsUtility.GetCutoutKeyword());
|
||||
|
||||
}
|
||||
|
||||
private static void SetupCull(OutlineParameters parameters, OutlineTarget target)
|
||||
{
|
||||
parameters.Buffer.SetGlobalInt(CullHash, (int)target.CullMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user