- 게임이 시작되면 매 프레임마다 특정한 경로(PipeLine)를 따라 계산되고 화면에 그려진다.
- 기본적으로 그려지는 순서는 '계산이 끝난 것을 그린다'라는 원칙을 따르기 때문에 어떤 것이 먼저 그려질 지 알 수 없다.
1.000···
~0.000···
의 숫자로 나타내며 이를 흑백으로 표현한 그림이 Z버퍼이다. ☑️ Buffering
- 그래픽 카드는 눈에 보이지 않는 여러 버퍼를 렌더링 한다.
- G버퍼, Back 버퍼, 스탠실 버퍼··· 등
- 동영상 시청 시 인터넷이 느리면 버퍼링 이라고 뜨면서 영상을 받는 과정!
_CameraDepthTexture
를 사용하면 그래픽 카드에서 Z버퍼를 받아올 수 있다.Shader "Custom/DepthShader"
{
SubShader
{
Tags { "RenderType"="Opaque" }
CGPROGRAM
#pragma surface surf Lambert noambient noshadow
#pragma target 3.0
sampler2D _CameraDepthTexture;
struct Input
{
float4 screenPos;
};
void surf (Input IN, inout SurfaceOutput o)
{
float2 sPos = float2(IN.screenPos.x, IN.screenPos.y) / IN.screenPos.w;
float4 Depth = tex2D(_CameraDepthTexture, sPos);
o.Emission = Depth.r;
o.Alpha = 1;
}
ENDCG
}
FallBack off
}
☑️ 이 문제를 해결하기 위해서는
- 불투명(Opaque) 오브젝트는 먼저 그린다.
- 반투명(Transparent) 오브젝트는 나중에 그린다.
- 문제가 해결된 듯 보이지만, 반투명끼리의 문제도 나타난다.
- 반투명 오브젝트들끼리는 '멀리 있는 것'부터 가까운 것까지 정렬하여 차례대로 그린다. 이것을 알파 소팅
Alpha Sorting
이라고 한다.
☑️ 반투명이 들어갔을 때의 악영향
- 반투명 오브젝트들은 불투명한 오브젝트가 다 그려질 때 까지 대기
- 반투명 오브젝트들끼리 거리를 체크하는 연산
- 만약 앞에 커다란 오브젝트가 있다면 그 뒤의 불투명 오브젝트는 그려지지 않아 절약되지만, 반투명 오브젝트는 뒤에서부터 그리게 되므로 오히려 계산이 더 무거워진다.
- Deferred Rendering에서는 아예 반투명을 처리할 수 없어서 Forward Rendering으로 반투명을 따로 그려야 한다.
Shader "Custom/AlphaBlendShader"
{
Properties
{
_MainTex ("Albedo (RGB)", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Opaque" }
CGPROGRAM
#pragma surface surf Lambert
sampler2D _MainTex;
struct Input
{
float2 uv_MainTex;
};
void surf (Input IN, inout SurfaceOutput o)
{
fixed4 c = tex2D (_MainTex, IN.uv_MainTex);
o.Albedo = c.rgb;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
알파 블렌딩 쉐이더로 바꾸고, Quad를 뒤집어도 이미지가 보이도록 cull off
도 추가한다.
바닥에 Plane을 설치해보면, 그림자가 Quad 모양으로 생기는데 이를 해결하기 위해서 Fallback "diffuse"
코드를 Transparent 계열의 쉐이더 이름으로 수정한다.
FallBack "Legacy Shader/Transparent/VertexLit"
☑️Fallback
- '이 쉐이더를 표현하지 못할 하드웨어에서는
Fallback
에 있는 쉐이더를 사용해라'라는 의미를 가진 '예비용' 쉐이더- 그림자 Pass와도 연결되어 있다는 것을 위 상황을 통해 짐작할 수 있다.
위의 쉐이더로 알파 블렌딩을 가동시켰지만 아직 알파의 문제는 해결되지 않았다.
아래와 같이 텍스쳐를 빼고 로봇에 적용시켜보면, cull off
때문에 앞뒷면이 전부 렌더링되는 상태에서 그림 그려지는 순서가 엉망이 된 모습이다.
cull off
를 빼더라도 뒤에 가려져야할 오브젝트가 앞으로 그려지는 현상이 나타난다.
분명 반투명 오브젝트들은 뒤에서부터 앞으로 그리는데 무슨 현상일까?
확인을 위해 동일한 쉐이더를 적용한 쿼드 이미지 3장을 나란히 놓았다. 맨 뒤에 있는 것이 먼저 그려져 문제 없어 나타난다.
하지만 뒤에 있는 쿼드를 옆으로 이동시키면 맨 앞으로 튀어나와 그려진다
알파 블렌딩은 카메라의 위치에서 각 오브젝트는 피봇점의 거리를 구해서 카메라에서 먼 것부터 그린다. 아래 두 이미지 중 왼쪽은 1이 가장 짧고, 3이 가장 길어서 3, 2, 1 순서로 그린다. 하지만 오른쪽 이미지는 2가 가장 짧기 때문에 3, 1, 2 순서로 그려지는 것이다.
위와 같은 문제는 오브젝트의 크기게 극명하게 다른 경우에도 자주 나타난다. (피봇점을 중심으로 하기 때문)
알파 소팅을 써봤자 완벽하게 앞 뒤를 제대로 판정할 수 없으니, 알파를 썼을 때 문제는 늘 발생한다.
그래서 이러한 상황을 피하고자 알파 블렌딩을 이용하는 Transparent 계열에 쉐이더들에게 z버퍼에 자신의 위치값을 입력하지 않는 기능이 추가된다. zwrite를 off한다.
알파 블렌딩 처리가 되어 있는 쿼드끼리 앞뒤가 잘못 연산되더라도, z버퍼에 아예 값을 쓰질 않으니 사각형 쿼드 모양으로 잘리지 않고 오브젝트의 앞뒤만 바뀌게 된다.
✅ 알파 블렌딩 총정리
- 불투명
Opaque
오브젝트는 먼저 그린다.- 반투명
Transparent
오브젝트는 나중에 그린다.- 반투명 오브젝트들끼리는 뒤에서부터 그린다.
- 알파 소팅을 써봤자 완벽하게 앞뒤를 판정할 수 없으니, 알파를 썼을 때 문제는 늘 일어난다.
- 알파 블렌딩
Transparent
을 사용하였을 때에는 zwrite를 하지 않는다.❗ 이 문제들을 해결하기 위해 각종 방법이 연구되고 있다.
☑️ 알파 테스팅 가동
_Color
- Color 구문의 인자를 사용하여 그림자를 그리기 때문에 필요하다._Cutoff
- 각 픽셀의 '잘라버릴' 정도를 구한다.
0.5로 하면 회색을 기준으로 더 어두운 알파는 찍히지 않고, 더 밝은 알파는 알파가 없는 것처럼 그려진다."Queue"="AlphaTest"
- 일반 오브젝트Geometry
와 반투명Transparent
의 사이를 의미한다.
즉, [일반 불투명 오브젝트 ➡️ 알파 테스팅 ➡️ 알파 블렌딩] 순서대로 그려진다.