133 lines
6.8 KiB
C#
133 lines
6.8 KiB
C#
using UnityEngine;
|
|
using UnityEngine.Rendering;
|
|
using static Misaki.HdrpToon.UTSPropertyName;
|
|
|
|
namespace Misaki.HdrpToon
|
|
{
|
|
internal class UTSAPI
|
|
{
|
|
private enum RenderPriority
|
|
{
|
|
Opaque = RenderQueue.Geometry,
|
|
OpaqueDecal = RenderQueue.Geometry + 225, // Opaque Decal mean Opaque that can receive decal
|
|
OpaqueAlphaTest = RenderQueue.AlphaTest,
|
|
OpaqueDecalAlphaTest = RenderQueue.AlphaTest + 25,
|
|
// Warning: we must not change Geometry last value to stay compatible with occlusion
|
|
OpaqueLast = RenderQueue.GeometryLast,
|
|
|
|
AfterPostprocessOpaque = RenderQueue.GeometryLast + 1,
|
|
AfterPostprocessOpaqueAlphaTest = RenderQueue.GeometryLast + 10,
|
|
|
|
TransparentFirst = RenderQueue.Transparent - 100,
|
|
Transparent = RenderQueue.Transparent,
|
|
TransparentLast = RenderQueue.Transparent + 100,
|
|
}
|
|
|
|
public static void SetupPass(Material material)
|
|
{
|
|
material.SetShaderPassEnabled(UTSPassName.HAIR_SHADOW_CASTER_PASS_NAME, (MaterialType)material.GetInteger(SurfaceOptions.MATERIAL_TYPE) == MaterialType.FrontHair);
|
|
material.SetShaderPassEnabled(UTSPassName.HAIR_BLENDING_TARGET_PASS_NAME, material.GetInteger(SurfaceOptions.HAIR_BLENDING_TARGET) == 1);
|
|
}
|
|
|
|
public static void SetupKeywords(Material material)
|
|
{
|
|
var surfaceType = (SurfaceType)material.GetInteger(SurfaceOptions.SURFACE_TYPE);
|
|
var cullMode = (CullMode)material.GetInteger(SurfaceOptions.CULL_MODE);
|
|
var doubleSidedEnable = cullMode == CullMode.Off;
|
|
|
|
CoreUtils.SetKeyword(material, "_SURFACE_TYPE_TRANSPARENT", surfaceType == SurfaceType.Transparent);
|
|
CoreUtils.SetKeyword(material, "_DOUBLESIDED_ON", doubleSidedEnable);
|
|
}
|
|
|
|
public static void SetupProperties(Material material)
|
|
{
|
|
var surfaceType = (SurfaceType)material.GetInteger(SurfaceOptions.SURFACE_TYPE);
|
|
var cullMode = (CullMode)material.GetInteger(SurfaceOptions.CULL_MODE);
|
|
|
|
// Surface type
|
|
var isTransparent = surfaceType == SurfaceType.Transparent;
|
|
var isAlphaClip = material.GetInteger(SurfaceOptions.ALPHA_CLIP_ENABLE) == 1;
|
|
|
|
var renderQueue = isTransparent ? RenderPriority.Transparent : (isAlphaClip ? RenderPriority.OpaqueAlphaTest : RenderPriority.Opaque);
|
|
material.SetInteger(InternalProperties.SURFACE_TYPE, isTransparent ? 1 : 0);
|
|
material.renderQueue = (int)renderQueue;
|
|
|
|
// We only do clip for alpha clip in depth pre-pass once. Z test for GBuffer and forward pass need to set to equal to make sure alpha clip works correctly.
|
|
if (isAlphaClip)
|
|
{
|
|
material.SetInteger(InternalProperties.ZTEST_GBUFFER, (int)CompareFunction.Equal);
|
|
}
|
|
else
|
|
{
|
|
material.SetInteger(InternalProperties.ZTEST_GBUFFER, (int)CompareFunction.LessEqual);
|
|
}
|
|
|
|
if (isTransparent)
|
|
{
|
|
material.SetInteger(InternalProperties.ZTEST_DEPTH_EQUAL_FOR_OPAQUE, material.GetInteger(InternalProperties.ZTEST_TRANSPARENT));
|
|
|
|
material.SetOverrideTag("RenderType", "Transparent");
|
|
// TODO: Z write for transparent.
|
|
material.SetInteger(InternalProperties.ZWRITE, 0);
|
|
material.SetInteger(InternalProperties.DEST_BLEND2, (int)BlendMode.OneMinusSrcAlpha);
|
|
|
|
//TODO: Implement additive and pre-multiply mode.
|
|
material.SetInteger(InternalProperties.SRC_BLEND, (int)BlendMode.One);
|
|
material.SetInteger(InternalProperties.DEST_BLEND, (int)BlendMode.OneMinusSrcAlpha);
|
|
material.SetInteger(InternalProperties.ALPHA_SRC_BLEND, (int)BlendMode.One);
|
|
material.SetInteger(InternalProperties.ALPHA_DEST_BLEND, (int)BlendMode.OneMinusSrcAlpha);
|
|
}
|
|
else
|
|
{
|
|
material.SetInteger(InternalProperties.ZTEST_DEPTH_EQUAL_FOR_OPAQUE, (int)CompareFunction.Equal);
|
|
|
|
material.SetOverrideTag("RenderType", isAlphaClip ? "TransparentCutout" : "");
|
|
|
|
material.SetInteger(InternalProperties.SRC_BLEND, (int)BlendMode.One);
|
|
material.SetInteger(InternalProperties.DEST_BLEND, (int)BlendMode.Zero);
|
|
material.SetInteger(InternalProperties.DEST_BLEND2, (int)BlendMode.Zero);
|
|
// Caution: we need to setup One for src and Zero for Dst for all element as users could switch from transparent to Opaque and keep remaining value.
|
|
// Unity will disable Blending based on these default value.
|
|
// Note that for after postprocess we setup 0 in opacity inside the shaders, so we correctly end with 0 in opacity for the compositing pass
|
|
material.SetInteger(InternalProperties.ALPHA_SRC_BLEND, (int)BlendMode.One);
|
|
material.SetInteger(InternalProperties.ALPHA_DEST_BLEND, (int)BlendMode.Zero);
|
|
material.SetInteger(InternalProperties.ZWRITE, 1);
|
|
}
|
|
|
|
// Double sided
|
|
var isBackFaceEnable = material.GetInteger(InternalProperties.TRANSPARENT_BACKFACE_ENABLE) == 1 && surfaceType == SurfaceType.Transparent;
|
|
var doubleSidedEnable = cullMode == CullMode.Off;
|
|
|
|
if (doubleSidedEnable)
|
|
{
|
|
var doubleSidedNormalMode = (DoubleSidedMode)material.GetInteger(SurfaceOptions.DOUBLE_SIDED_NORMAL_MODE);
|
|
switch (doubleSidedNormalMode)
|
|
{
|
|
case DoubleSidedMode.None:
|
|
material.SetVector(InternalProperties.DOUBLE_SIDED_CONSTANTS, new Vector4(1.0f, 1.0f, 1.0f, 0.0f));
|
|
break;
|
|
|
|
case DoubleSidedMode.Mirror:
|
|
material.SetVector(InternalProperties.DOUBLE_SIDED_CONSTANTS, new Vector4(1.0f, 1.0f, -1.0f, 0.0f));
|
|
break;
|
|
|
|
case DoubleSidedMode.Flip:
|
|
material.SetVector(InternalProperties.DOUBLE_SIDED_CONSTANTS, new Vector4(-1.0f, -1.0f, -1.0f, 0.0f));
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (isBackFaceEnable)
|
|
{
|
|
material.SetInt(InternalProperties.CULL_MODE_FORWARD, (int)CullMode.Back);
|
|
}
|
|
else
|
|
{
|
|
material.SetInteger(InternalProperties.CULL_MODE_FORWARD, (int)(doubleSidedEnable ? CullMode.Off : cullMode));
|
|
}
|
|
|
|
// TODO: Setup stencil value. Currently it produce noticeable jittering when surface type is transparent.
|
|
// This is caused by taa, _StencilWriteMask need to include StencilUsage.ExcludeFromTUAndAA when surface type is transparent.
|
|
}
|
|
}
|
|
} |