Flat Shader(Unlit

Unity의 객체는 삼각형으로 구성됩니다.

왼쪽: Unity의 와이어프레임 보기, 오른쪽: 각 삼각형의 상대 좌표

따라서 삼각형을 취하고 모든 점의 법선을 동일하게 설정하면 삼각형은 평평합니다.


효과를 위해서는 먼저 셰이더 파일을 만들고 벡터 속성을 추가하여 빛의 방향을 지정하기만 하면 됩니다.

셰이더 코드 내에서 주 조명의 방향을 얻는 방법이 있지만 단순성을 위해 속성으로 취급되었습니다.

Unity에서 삼각형 데이터를 얻으려면 지오메트리 셰이더를 사용해야 합니다.

라이팅되지 않은 셰이더를 처음 생성할 때 버텍스 셰이더와 픽셀 셰이더만 있습니다.

지오메트리 셰이더를 추가해야 합니다.

Pass
{
	CGPROGRAM
    #pragma vertex vert
    #pragma fragment frag
    #pragma geometry Geometry // 추가하는 부분

각 점의 법선을 변경해야 하므로 다음으로 정점을 받는 응용 프로그램 데이터에 법선을 추가해야 합니다.

	struct appdata
	{
		float4 vertex : POSITION;
		float3 normal : NORMAL; // 추가하는 부분
		float2 uv : TEXCOORD0;
	};
처음 생성될 때 정점 셰이더는 픽셀 셰이더에 v2f 구조를 전달해야 합니다.

지오메트리 셰이더는 정점 셰이더와 픽셀 셰이더 사이에 있습니다.

지오메트리 셰이더에서 이를 수정하려면 v2f 구조에도 일반 값을 입력해야 합니다.

쉬운 처리를 위해 정상적인 값이 필요하므로 이 값도 입력해야 합니다.

struct v2f
{
	float2 uv : TEXCOORD0;
	float3 worldPosition : TEXCOORD1;
	float3 normal : NORMAL; // 추가하는 부분
	float4 vertex : SV_POSITION;
};
TEXCOORD1에 저장된 worldPosition은 삼각형의 상대 좌표를 세계 좌표로 변환하기 위한 값입니다.

구조를 변경했다면 함수 부분을 작성해야 합니다.

v2f vert (appdata v)
{
	v2f o;
	o.vertex = UnityObjectToClipPos(v.vertex);
	o.uv = TRANSFORM_TEX(v.uv, _MainTex);
	o.normal = v.normal;
	o.worldPosition = mul(unity_ObjectToWorld, v.vertex).xyz;
	UNITY_TRANSFER_FOG(o,o.vertex);
	return o;
}

위는 기본 정점 셰이더의 수정된 버전입니다.

먼저 입력 정점의 정상 값을 저장합니다.

o.worldPosition = mul(unity_ObjectToWorld, v.vertex).xyz;

이 부분에서 각 정점의 상대 좌표는 Unity 내에서 세계 좌표로 변환됩니다.

버텍스 셰이더는 이 지점에서 종료되며 지오메트리 셰이더를 수정합니다.

.

아래는 지오메트리 셰이더 부분입니다.

(maxvertexcount(3))
void Geometry(triangle v2f input(3), inout TriangleStream<v2f> OutputStream)
{
    v2f test = (v2f)0;
    float3 normal = normalize(cross(input(1).worldPosition.xyz - input(0).worldPosition.xyz,
                                 input(2).worldPosition.xyz - input(0).worldPosition.xyz));
    for (int i = 0; i < 3; i++)
    {
        test.normal = normal;
	 test.vertex = input(i).vertex;
	 test.uv = input(i).uv;
	 OutputStream.Append(test);
    }				
}
먼저 픽셀 셰이더에 전달할 v2f 구조를 만듭니다.

다음은 삼각형의 각 꼭짓점의 법선값을 균형있게 맞추는 과정입니다.


각 점과 외적을 이용하여 삼각형의 법선 벡터를 구하고 그 값을 각 삼각형에 대입한다.

.

삼각형을 평면화하는 셰이더이므로 픽셀 셰이더에서 큰 변경이 필요하지 않습니다.

하지만 Unlit 셰이더는 기본적으로 빛을 처리하지 않기 때문에

가벼운 부분의 가공이 필요합니다.

.

fixed4 frag (v2f i) : SV_Target
{
    // sample the texture
    fixed4 col = tex2D(_MainTex, i.uv);
    float normalDot = dot(i.normal, normalize(_lightDir.xyz));    //추가하는 부분
    return col * normalDot;
}

위 속성에 더해진 빛의 방향 벡터와 전달된 점 좌표의 내적이 normalDot에 저장되고,

마지막 반환 부분의 곱셈에 가벼운 처리가 적용됩니다.