# 3-1 [Alpha To Coverage, UV정보를 Pixel Shader에 출력]

Ricon·2024년 8월 8일

URP Shader Basic

목록 보기
10/17

본 게시물은 Unity Korea 채널의 URP Shader Training 시리즈와 강의에 사용된 도큐먼트를 공부하며 정리한 게시물입니다.

강의 링크
도큐먼트 링크


Alpha To Coverage

Forward Rendering을 사용하는 Multi Sample Anti Aliasing(MSAA)을 사용하는 경우, Alpha To Coverage 기능을 사용해 알파 채널 Texture의 AA를 적용할 수 있다.

MSAA가 Mesh 외곽에만 AA를 적용하고, Alpha처럼 Texture 안의 이미지에 대한 AA를 적용할 수 없기 때문에, 이와 같은 방식으로 AA를 적용한다.

Pass
{
	AlphaToMask On
}

MSDN에서는 이를 Alpha-To-Coverage로 정의하고 있으며, 아래와 같이 설명하고 있다.

Alph-To-Coverage는 표면 내의 가장자리는 정의하기 위해 알파 투명도를 사용하는, 겹치는 다각형이 여러개 있는 빽빽한 나뭇잎과 같은 상황에 가장 유용한 멀티 샘플링 기술입니다.

D3D11_BLEND_DESC1 또는 D3D11_BLEND_DESC의 AlphaToCoverageEnable 멤버를 사용하여, 런타임이 출력 레지스터 SV_Target0의 .a 구성요소(Alpha)를 Pixel Shader에서 n-step 커버리지 마스트 (n-sample RenderTaget 제공)로 변환할지 여부를 전환 할 수 있습니다.
런타임은 모든 활성 RenderTarget에서 업데이트 할 샘플을 결정하기 위해 프리미티브의 픽셀에 대한 일반적인 샘플 커버리지(Sample Mask외에)로 이 마스크의 AND 연산을 수행하게 됩니다.

Pixel Shader가 SV_Coverage를 출력하는 경우, 런타임을 Alpha-To-Coverage를 비활성화 합니다.

예시

Properties에서 Enum으로 토글 제어 가능

[Enum(Off, 0, On, 1)] _Mask("Alpha to Coverage", float) = 0

Pass
{
	AlphaToMask [_Mask]
}

전체 코드

// Shader 시작. 셰이더의 폴더와 이름을 여기서 결정합니다.
Shader "URPTraining/12_AlphaToCoverage"
{
	Properties
	{
		// Properties Block : 셰이더에서 사용할 변수를 선언하고 이를 material inspector에 노출시킵니다
		_TintColor("Test Color", Color) = (1, 1, 1, 1)
		_Intensity("Range Sample", Range(0, 1)) = 0.5
		_MainTex("Main Texture", 2D) = "white"{}

		[Enum(UnityEngine.Rendering.BlendMode)] _SrcBlend("Src Blend", float) = 1
		[Enum(UnityEngine.Rendering.BlendMode)] _DstBlend("Dst Blend", float) = 0

		[Enum(UnityEngine.Rendering.CullMode)] _CullMode("Cull Mode", float) = 1

		[Enum(Off, 0, On, 1)] _ZWrite ("ZWrite", float) = 0
		[Enum(UnityEngine.Rendering.CompareFunction)] _ZTest("ZTest", float) = 0

		_Factor("Factor", int) = 0
		_Units("Units", int) = 0

		[Enum(Off, 0, On, 1)] _Mask ("Alpha To Coverage", float) = 0

		_Alpha("Alpha", Range(0, 1)) = 0.5
	}

	SubShader
	{
		Tags
		{
			//Render type과 Render Queue를 여기서 결정합니다.
			"RenderPipeline" = "UniversalPipeline"
			"RederType" = "Transparent"
			"Queue" = "Transparent"
		}
		Pass
		{
			Blend [_SrcBlend] [_DstBlend]
			Cull [_Cull]
			ZWrite  [_ZWrite]
			ZTest [_ZTest]

			Offset [_Factor],[_Units]

			AlphaToMask [_Mask]

			Name "Universal Forward"
			Tags { "LightMode" = "UniversalForward"}

			HLSLPROGRAM
			#pragma prefer_hlslcc gles
			#pragma exclude_renderers d3d11_9x
			#pragma vertex vert
			#pragma fragment frag

			//cg shader는 .cginc를 hlsl shader는 .hlsl을 include하게 됩니다.
			#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"

			//vertex buffer에서 읽어올 정보를 선언합니다. 
			struct VertexInput
			{
				float4 vertex	: POSITION;
				float2 uv		: TEXCOORD0;
			};

			//보간기를 통해 버텍스 셰이더에서 픽셀 셰이더로 전달할 정보를 선언합니다.
			struct VertexOutput
			{
				float4 vertex	: SV_POSITION;
				float2 uv		: TEXCOORD0;
			};

			half4 _TintColor;
			float _Intensity;
			float _Alpha;

			float4 _MainTex_ST;
			Texture2D _MainTex;
			SamplerState sampler_MainTex;

			//버텍스 셰이더
			VertexOutput vert(VertexInput v)
			{
				VertexOutput o;
				o.vertex = TransformObjectToHClip(v.vertex.xyz);
				o.uv = v.uv.xy * _MainTex_ST.xy + _MainTex_ST.zw;

				return o;
			}
			
			//픽셀 셰이더
			half4 frag(VertexOutput i) : SV_TARGET
			{
				float4 color = _MainTex.Sample(sampler_MainTex, i.uv);
				color.rgb += _TintColor * _Intensity;
				color.a = color.a * _Alpha;

				return color;
			}

			ENDHLSL
		}
	}
}

AlphaToMask Off

AlphaToMask On


UV 정보를 Pixel Shader에 출력

기본 UV값을 Pixel Shader에 출력

Shader "URPTraining/13_UVtoPixelShader"
{
	Properties
	{
	}

	SubShader
	{
		Tags
		{
			"RenderPipeline" = "UniversalPipeline"
			"RederType" = "Opaque"
			"Queue" = "Geometry"
		}
		Pass
		{
			Name "Universal Forward"
			Tags { "LightMode" = "UniversalForward"}

			HLSLPROGRAM
			#pragma prefer_hlslcc gles
			#pragma exclude_renderers d3d11_9x
			#pragma vertex vert
			#pragma fragment frag

			#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"

			struct VertexInput
			{
				float4 vertex	: POSITION;
				float2 uv		: TEXCOORD0;
			};

			struct VertexOutput
			{
				float4 vertex	: SV_POSITION;
				float2 uv		: TEXCOORD0;
			};

			VertexOutput vert(VertexInput v)
			{
				VertexOutput o;
				o.vertex = TransformObjectToHClip(v.vertex.xyz);
				o.uv = v.uv.xy;

				return o;
			}
			
			half4 frag(VertexOutput i) : SV_TARGET
			{
				float4 color = float4(i.uv.x, i.uv.y, 0, 1);
				return color;
			}

			ENDHLSL
		}
	}
}

이제 이를 U값만 Mesh에 출력

half4 frag(VertexOutput i) : SV_TARGET
{
	//float4 color = float4(i.uv.x, i.uv.y, 0, 1);
	float4 color = i.uv.x;
	return color;
}

이를 V값을 기준으로 위와 아래를 Gamma Correction이 적용된 그라데이션으로 출력해본다.
추가 자료 : [감마가 어디감마]

half4 frag(VertexOutput i) : SV_TARGET
{
	float4 color = (i.uv.y > 0.5) ? color = pow(i.uv.x, 2.2) : i.uv.x;
	return color;
}

0개의 댓글