Opaque, AlphaTest, Transparent(AlphaBlend)을 셰이더를 분리하지 않고 사용하기 위해서 다음과 같은 형태로 Blend State 값을 외부에서 제어하는 형태를 사용하고 있다.
Shader "MyCustom/Blend"
{
Properties
{
[Enum(UnityEngine.Rendering.Blending)]_SrcBlend("SrcBlend", Float) = 1
[Enum(UnityEngine.Rendering.Blending)]_DstBlend("DstBlend", Float) = 0
}
SubShader
{
Tags { "RenderType"="Opaque" }
Blend [_SrcBlend][_DstBlend]
Pass
{
...
보통 재질을 분리하여 제작한다는데, 내가 보기에 굳이 Shader를 여러 개 작성해야 할 필요가 있는지 모르겠다. 그래서 이런 식으로 재질 특성에 관계없이 하나의 Shader로 처리할 때 문제가 될 수 있는 부분이 무엇이 있을지 생각해보았다.
Blend State가 변경됨에 따라 PipelineState(뭔지 잘 모름)를 다시 작성해야 한다던가 하는 문제가 있으려나? 이쪽은 Vulkan 같은 API 동작을 확인해봐야 자세히 알 수 있을 것 같다. 이는 나중에 찾아보고 추가하는 걸로.
PipelineState 아니면 문제가 될 수 있는 건 Opaque, AlphaTest 재질에서 사실상 BlendState가 비활성화되어야 하는데, 비활성화되지 않고 남아있는 경우 Output Merger에서 Fragment Shader의 리턴 픽셀과 Frame Buffer의 픽셀 간 추가 연산이 실행되는 비용이 잠재적 문제라 할 수 있다.
그렇다면 Blend Off를 하는 방법은 뭐가 있을까?
명시적으로 SubShader에서 Blend Off라고 쓰는 건 동작하는데, 외부 Material Property로 제어하는 방법은 없었다.
Shader "MyCustom/Blend"
{
Properties
{
[Enum(UnityEngine.Rendering.Blending)]_SrcBlend("SrcBlend", Float) = 1
[Enum(UnityEngine.Rendering.Blending)]_DstBlend("DstBlend", Float) = 0
}
SubShader
{
Tags { "RenderType"="Opaque" }
Blend Off
Pass
{
...
BlendMode Enum을 살펴봐도 Off를 하는 조건은 딱히 없었다.
namespace UnityEngine.Rendering
{
/// <summary>
/// <para>Blend mode for controlling the blending.</para>
/// </summary>
[NativeHeader("Runtime/GfxDevice/GfxDeviceTypes.h")]
public enum BlendMode
{
/// <summary>
/// <para>Blend factor is (0, 0, 0, 0).</para>
/// </summary>
Zero,
/// <summary>
/// <para>Blend factor is (1, 1, 1, 1).</para>
/// </summary>
One,
/// <summary>
/// <para>Blend factor is (Rd, Gd, Bd, Ad).</para>
/// </summary>
DstColor,
/// <summary>
/// <para>Blend factor is (Rs, Gs, Bs, As).</para>
/// </summary>
SrcColor,
/// <summary>
/// <para>Blend factor is (1 - Rd, 1 - Gd, 1 - Bd, 1 - Ad).</para>
/// </summary>
OneMinusDstColor,
/// <summary>
/// <para>Blend factor is (As, As, As, As).</para>
/// </summary>
SrcAlpha,
/// <summary>
/// <para>Blend factor is (1 - Rs, 1 - Gs, 1 - Bs, 1 - As).</para>
/// </summary>
OneMinusSrcColor,
/// <summary>
/// <para>Blend factor is (Ad, Ad, Ad, Ad).</para>
/// </summary>
DstAlpha,
/// <summary>
/// <para>Blend factor is (1 - Ad, 1 - Ad, 1 - Ad, 1 - Ad).</para>
/// </summary>
OneMinusDstAlpha,
/// <summary>
/// <para>Blend factor is (f, f, f, 1); where f = min(As, 1 - Ad).</para>
/// </summary>
SrcAlphaSaturate,
/// <summary>
/// <para>Blend factor is (1 - As, 1 - As, 1 - As, 1 - As).</para>
/// </summary>
OneMinusSrcAlpha,
}
}
그렇다면 이 셰이더는 항상 Blend Option이 활성화된 상태로 동작할까?
만약 항상 Blend가 활성화되어 있다면 Transparent가 아닌 Material은 항상 불필요한 성능 코스트를 쓰고 있다는 얘기이고 이는 수정해야할 사항이다.
https://forum.unity.com/threads/is-there-extra-performance-cost-for-blend-one-zero.1154021/
https://forum.unity.com/threads/toggle-blend-srcalpha-oneminussrcalpha-in-a-custominspector.317690/
유니티 공식 답변이 달린 쓰레드인데, Blend One Zero는 Blend를 비활성화 시킨다고 한다.
그리고 유니티 직원은 아닌 것 같은데 항상 보이는 이 봉골루스 아저씨 답글도 있다.
https://forum.unity.com/threads/blend-zero-one-one-zero-question.430454/
결론적으로 Blend One Zero 사용은 Blend Off로 대체 되므로 염려하는 Opaque 및 AlphaTest 재질에서의 Blend Enable 문제는 없다.
'TA' 카테고리의 다른 글
(작성중) [Unity] URP환경에서 GPU Instancing Tool 만들기 (0) | 2025.01.20 |
---|---|
[Unity] Custom Shadow System 제작하기 (1) - 커스텀 그림자 제작의 필요성 (0) | 2024.12.30 |
(작성중) [Unity] Irradiance Volume 만들기 (짭 Adaptive Probe Volume) (0) | 2024.12.29 |
그래픽 리소스 / 렌더링 최적화에 대한 생각 (0) | 2024.06.09 |
[Unity] 유니티의 Curve 구현에 대한 추측과 Curve 데이터 활용 (0) | 2023.12.03 |