본문 바로가기

Unity3D/shader_스터디

[Unity 쉐이더] vector, Custom Light

Vector 연산

Dot 연산

 

커스텀 라이트 (렘버트)

 

 

벡터의 덧셈 뺄셈

 

나 그래픽이라고!!!

 

친절하게 설명해주시는 영상 (앞부분에서 덧셈 참고)

www.youtube.com/watch?v=0Ho616gAijQ&t=380s

 

A+B

 

시점이 일치하는 벡터는

A벡터와 B벡터를 변으로 하는 평행사변형을 그리면 생기는 꼭짓점과 시점을 연결하면 A+B값이 나오게 됩니다.

 

또는 B벡터의 종점에 A벡터의 시점을 이을 경우 마찬가지로 A+B값이 나옵니다.

 

 

 

A-B

벡터의 -는 방향이 역으로 뒤집히게 됩니다. 좌표로 보면 1에서 -1로 이동한 것과 같죠.

 

 

벡터에는 위치값이 상관없기 때문에 위와 아래의 값은 같게 됩니다.

 


벡터의 내적 Inner Product

 

 

A · B= cosθ

 

벡터는 크기와 방향을 가지고 있어 일반적인 곱셈과 다릅니다. 

벡터의 내적은 스칼라곱(scalar product) 또는 내적을 구할 때 기호 ( · )을 사용해 dot Product라고 부르기도 합니다.

 

노말 벡터(n)와 라이트 벡터(d)의 크기가 1이라 가정하고 라이트 벡터를 뒤집어(1-x) 내적을 구하면 0도에서 180도 까지의 값이 나오게 됩니다.

 

 

 

그 후 구해진 내적의 값과 노말 벡터의 값을 통해 float1의 값이 나옵니다.

0˚=1  

90˚=0   

180˚=-1

숫자를 색으로 봤을 때 흰색에서 검정까지 나타나게 되죠. 

 

 

 

유의해야 할 점은 코사인 그래프의 곡선을 보면 알 수 있습니다. 45˚에서 그래프는 0.5의 위치에 있지 않습니다. 45˚에서 값은 0.7정도로 나오게 됩니다.

 


커스텀 라이트 제작

 

우선 저번 글 마지막에 진행했던, 라이트를 렘버트로 변경하는 과정에서부터 시작합니다.

이제 여기에 새로운 커스텀 라이트를 만들겁니다.

 

더보기
Shader "Custom/Lambert"
{
    Properties
    {
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }

        CGPROGRAM
        //Standard에서 Lambert로 변경합니다.
        #pragma surface surf Lambert
        #pragma target 3.0

        sampler2D _MainTex;

        struct Input
        {
            float2 uv_MainTex;
        };

        //SurfaceOutputStandard에서 SurfaceOutput으로 변경합니다.
        void surf (Input IN, inout SurfaceOutput o)
        {
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex);
            o.Albedo = c.rgb;
        }
        ENDCG
    }
    FallBack "Diffuse"
}

 

 

엠비언트를 끈 램버트 라이트입니다. 위의 이론에서 본 것과 같은 결과가 나옵니다.

반대편은 0이하의 수가 나오기 때문에 saturate 함수로 0~1값으로 잘라줍니다.

 

 

 

이제 진짜 커스텀 라이트를 만들어줍시다. Lambert를 지우고 새로 만들 라이트의 이름을 지어준 후 새로운 함수를 만들겁니다.

 

아래 내용은 라이트를 만들기 위한 유니티의 규칙이라고 보시면 됩니다.

SurfaceOutput 구조체와 라이트 벡터(lightDir), 감쇠 효과가(atten) 들어갑니다.

float4 LightingName(SurfaceOutput s,float3 lightDir, float atten)

 

 

1. 우선 dot을 통해 노말벡터와 라이트 백터의 내적을 구합니다.

 

2. 값이 -1까지 내려가는 것을 막기위해 saturate함수를 이용합니다.

 

싹둑

3. 구한 NdotL값과 SurfaceOutput에서 Albedo, 라이트 색상과 밝기 강도를 가져올 LightColor, 감쇠 효과를 줄 atten을 곱합니다.

 

4. 리턴으로 float4 알파값까지 포함하여 출력해줍니다.

 

 

 

ateen

 오브젝트에 의한 그림자, 거리에 따른 빛의 감쇠 효과를 나타냅니다. 다른 라이트와 같이 음영을 더하는 방식이라 색을 변경하려면 다른 색상을 더해주면 됩니다. 

 

 

 

포인트 라이트로 거리에 따른 감쇠 현상을 쉽게 볼 수 있습니다.

 

 

위의 내용을 아래와 같이 정리할 수 있습니다.

 


하프 램버트

벨브에서 개발한 Half-Life에서 처음 개발된 기술로 -1~1까지인 라이트를 0~1로 잘라서 사용하는 기존 램버트 방식과 달리 

*0.5+0.5 를 통해 0~1까지의 범위 내에서 더 부드럽게 표현 가능합니다.

빨간 그래프가 기존의 cos그래프 파란색이 *0.5+0.5 그래프

 

하프 램버트의 음영 강도를 높이려면 제곱을 이용해 1~0사이의 중간 값을 더 낮출 수 있습니다. 

 

 

전체 코드