Ronja 님의 허락을 받고 번역한 튜토리얼입니다. 원문은 위 링크에서 확인하실 수 있습니다.
몇몇 부분은 생략·추가하였습니다.
의역과 오역이 넘쳐날 수 있으니 편하게 봐주시고 잘못된 부분은 알려주시면 감사하겠습니다!
목차
- 개요
- 투명 재질의 렌더 타입과 렌더 큐
- 블렌딩 모드
- Z Writing 비활성화
개요
색상을 화면 위에 칠하는 것 말고도, 색상을 칠하기 이전에 화면에 그려진 색상을 남겨서 그려지는 물체가 반투명해 보이도록 할 수 있습니다. 조명이 적용되지 않는 기본 셰이더에서 이러한 효과를 어떻게 구현할 수 있는지 설명해보겠습니다.
투명도를 구현하는 방법을 이해하기 위해서는, 셰이더 작성의 기본 내용을 알고 있어야 합니다. 이번 튜토리얼에서는, 텍스처를 구현하는 튜토리얼의 결과 부분부터 이어서 시작할 것입니다.
본 튜토리얼에서는 새 색상과 기존 색상이라는 단어를 주로 사용합니다. '새 색상 = Source Value', '기존 색상 = Destination Value' 와 같은 의미로 사용하고 있으니, 기억해주시면 이해에 도움이 되실 것 같습니다.
투명 재질의 렌더 타입과 렌더 큐
투명한 물체가 알맞게 렌더되도록 만들기 위해서는, 유니티에게 이 물체가 투명하다고 알려줘야 합니다. 이를 위해서 렌더 타입과 렌더 큐를 변경해야 합니다. 렌더 큐를 변경함으로써, 이 메테리얼이 불투명한 메테리얼들보다 나중에 렌더되게 만들 수 있습니다. 그렇지 않으면, 투명한 물체 뒤의 불투명한 물체가 투명한 물체를 가리며 그 위에 그려질 수 있습니다.
Tags{ "RenderType"="Transparent" "Queue"="Transparent"}
블렌딩 모드
다음으로 블렌딩 모드를 정의해줍니다. 블렌딩 모드는 기존의 색상과 새로운 색상을 어떻게 블렌딩할지를 결정합니다. 블렌드 모드는 두가지 키워드로 정의되는데, 첫 번째 키워드는 새 색상과 곱해지는 값이고, 두 번째는 기존 색상에 곱해지는 값입니다. 색상에 키워드의 값들을 연산한 뒤에는, 서로 더한 뒤 그 결과값이 화면에 그려지게 됩니다.
불투명한 재질을 렌더할 때, 블렌딩 모드는 One Zero 를 사용하게 됩니다. 기존 색상을 전부 버리고 (Zero), 불투명한 재질의 새로운 색상값만을 사용 (One) 하기 때문입니다. 투명한 재질에서는, 알파 값 (이전까진 사용하지 않았던 컬러값의 네 번째 숫자) 을 베이스로 블렌딩을 수행합니다. 따라서 첫 번째 블렌딩 값은 소스 알파 값으로 설정해줍니다. 그리고 두 번째 밸류는 그 반전값이 되어야 하므로, 1에서 소스 알파값을 빼준 값을 사용합니다.
소스 알파 값은 해당 재질의 물체가 불투명하게 그려지는 정도를 정의하고, 1 - 소스 알파 값으론 해당 물체 뒤의 색상값들이 얼마나 나타날지를 설정해주게 됩니다.
블렌딩 모드는 서브셰이더 내 또는 셰이더 패스에서 정의될 수 있지만, HLSL 영역의 바깥에 위치해야합니다.
Blend SrcAlpha OneMinusSrcAlpha
다른 블렌딩 인자들 (나중에 설명할 예정인 몇 가지 블렌딩 속성을 포함한) 은 유니티 문서에서 찾아볼 수 있습니다.
동작하는 방식을 이해하실 수 있도록 작은 예시 두가지를 보여드리겠습니다.
프래그먼트 셰이더에서 0.5의 알파값을 반환할 때, 블렌딩 연산은 새 색상의 절반을 가져와 기존 색상의 절반 (1 - 0.5 = 0.5) 과 서로 균등히 혼합하게 됩니다. (검정색 위에 하얀색을 그릴 때, 결과값은 중간 정도의 회색이 됩니다.)
프래그먼트 셰이더에서 0.9의 알파값을 반환하면, 블렌딩 연산은 새 색상의 90%를 가져와 기존 색상 10%와 더해 기존 색상이 어렴풋이 보이게 만듭니다.
이러한 변경사항만으로 셰이더를 투명 재질을 표현하는 데 사용할 수 있습니다. 프래그먼트 셰이더에서 알파 채널을 남겨두었기 떄문에, 틴트 컬러의 알파 값을 설정하고 이를 메테리얼의 알파 값으로 사용할 수 있습니다. (알파 채널이 없는 텍스처를 사용할 경우)
Z Writing 비활성화
여기서 더 해줘야할 작은 것은, Z Writing 을 비활성화 하는 것입니다. 보통 오브젝트가 렌더될 때, 카메라부터 오브젝트의 거리를 텍스처에 기록해 뒤에 있는 다른 오브젝트들이 해당 오브젝트의 앞에 그려지지 않도록 합니다. 그러나 투명한 오브젝트의 경우 이는 제대로 동작하지 않습니다. 투명한 오브젝트들은 그 뒤에 있는 오브젝트들을 완전히 가리지 않기 때문입니다. (이를 위해서 가장 먼 오브젝트부터 렌더하고 가장 가까운 오브젝트를 마지막에 렌더하게 됩니다. 다만 유니티는 이를 자동으로 처리해주기 때문에 걱정할 필요는 없습니다.)
Z 버퍼에 작성할 것인지의 여부는 서브셰이더 또는 셰이더 패스에서 정의할 수 있습니다.
Blend SrcAlpha OneMinusSrcAlpha
ZWrite Off
텍스처가 알파 채널을 가지고 있을 때, 아래의 셰이더는 텍스처의 알파 값도 사용해서 텍스처의 알파값이 낮은 부분은 투명하게 보이게 만들어줍니다.
Shader "Tutorial/006_Basic_Transparency"
{
Properties
{
_Color ("Tint", Color) = (0, 0, 0, 1)
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Transparent" "Queue"="Transparent"}
Blend SrcAlpha OneMinusSrcAlpha
ZWrite off
Pass
{
CGPROGRAM
#include "UnityCG.cginc"
#pragma vertex vert
#pragma fragment frag
sampler2D _MainTex;
float4 _MainTex_ST;
fixed4 _Color;
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float4 position : SV_POSITION;
float2 uv : TEXCOORD0;
};
v2f vert(appdata v)
{
v2f o;
o.position = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
fixed4 frag(v2f i) : SV_TARGET
{
fixed4 col = tex2D(_MainTex, i.uv);
col *= _Color;
return col;
}
ENDCG
}
}
}
'Graphics > Ronja's Unity Shader tutorials' 카테고리의 다른 글
평면 매핑 (Planar Mapping) (0) | 2024.05.05 |
---|---|
스프라이트 셰이더 (0) | 2024.03.03 |
유니티 서피스 셰이더 기본 (0) | 2023.11.19 |
기본 셰이더 (0) | 2023.08.06 |
변수 (0) | 2023.04.22 |