> For the complete documentation index, see [llms.txt](https://lee-seokhyun.gitbook.io/game-programming/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://lee-seokhyun.gitbook.io/game-programming/client/shader/roundedrect_shader/undefined.md).

# 구현 방법들

### 알파 마스크

둥근 사각형을 만드는 방법들은 여러가지가 있겠지만 흔히 사용되는 방법중에는 알파 마스크 기법이 있습니다.\
알파 마스크는 원본 이미지와 알파블렌딩 된 텍스쳐를 합성하여 원하는 위치의 픽셀을 렌더링에서 제외해 버리는 방법 입니다. 원본 이미지를 렌더링 할 때 알파값은 별도의 텍스쳐에서 읽어온 값으로 사용하는 것이죠.

![A=원본 이미지, B=모서리에 알파값을 가진 이미지, C=최종 이미지](/files/-LqF2QN5o9nR9KOYXJW9)

아래는 알파 마스크를 구현한 셰이더 코드 입니다.

```c
Shader "CustomMask/AlphaMask"
{
	Properties
	{
		_MainTex ("Texture", 2D) = "white" {}
		_AlphaTex ("AlphaTexture", 2D) = "white" {}
	}
	SubShader
	{
		Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
		LOD 100
   
		ZWrite Off
		Blend SrcAlpha OneMinusSrcAlpha

		Pass
		{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag

			#include "UnityCG.cginc"

			struct appdata_t {
				float4 vertex : POSITION;
				float2 texcoord : TEXCOORD0;
			};

			struct v2f {
				float4 vertex : SV_POSITION;
				half2 texcoord : TEXCOORD0;
			};

			sampler2D _MainTex;
			sampler2D _AlphaTex;
           
			float4 _MainTex_ST;
           
			v2f vert (appdata_t v)
			{
				v2f o;
				o.vertex = UnityObjectToClipPos(v.vertex);
				o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
				return o;
			}
           
			fixed4 frag (v2f i) : SV_Target
			{
				fixed4 col = tex2D(_MainTex, i.texcoord);
				fixed4 col2 = tex2D(_AlphaTex, i.texcoord);

				// rgb는 원본 텍스쳐에서,
				// 알파값은 알파 텍스쳐에서 가져온다.
				return fixed4(col.r, col.g, col.b, col2.a);
			}
			ENDCG
		}
	}
}
```

\
이 방법은 구현이 간단하지만 별도의 텍스쳐가 필요하다는 단점이 있습니다. 또한 텍스쳐가 그려진 모양대로 마스킹이 되기 때문에 다른 모양을 원한다면 또다른 텍스쳐가 필요하게 됩니다.

{% hint style="info" %}
알파값을 가진 이미지는 꼭 검은색일 필요는 없습니다. 어차피 알파성분만 사용할것이기 때문이죠. 따라서 RGBA중 R채널만 가진 이미지를 만들어 알파값으로 사용하는 최적화도 가능합니다.
{% endhint %}

<br>

### 수학적 계산 방법

알파텍스쳐를 사용하지 않고 수학적으로 모서리 영역을 계산하여 픽셀을 걸러내는 방법도 있습니다. 사각형의 모서리에 가상의 원을 그리고 그 원의 바깥쪽에 있는 픽셀들은 렌더링 하지 않는 방식으로 구현하는 것이죠.

기본적인 구현 방법은 다음과 같습니다.

* 이미지의 모서리에 일정 크기의 가상의 원이 있다고 가정합니다.
* 각각의 픽셀을 렌더링 할 때 해당 원의 바깥쪽에 있는지를 체크합니다.\
  (원의 중심에서 각 픽셀까지의 거리와 반지름의 길이를 비교)
* 바깥쪽이라고 판단되는 픽셀들은 렌더링에서 제외합니다(알파값을 주거나 discard를 시키는등).

![수학적 계산을 통한 둥근 사각형 렌더링 하기](/files/-LqFgU0EPSWokh4opoUv)

그림을 보면 간단해 보이지만 실제 코드로 구현하려면 신경써야 할 부분이 많습니다.

![](/files/-LqFjmWO9o2XYuYZs_cU)

위 그림처럼 반지름의 길이보다 더 큰 픽셀이라고 하더라도 제외하면 안되는 영역이 있습니다. 정확히 모서리쪽에 존재하는 픽셀들만 걸러내야 하는 것이죠.\
이 구현의 핵심 키워드는 벡터와 좌표변환 입니다.\
벡터는 3D렌더링에서 흔히 사용하는 개념이므로 크게 어려운것은 없습니다. 다만 좌표변환이 약간 헷갈릴 수 있는데 실제 셰이더 코드와 함께 원리를 살펴보도록 하겠습니다.
