UV 기본 개념

  • 2차원 좌표로 이루어진 float2 숫자
  • 0~1 범위로 표현할 수 있음.
  • UV 좌표는 xy와 RG와 동일하게 취급하므로, UV = XY = RG 이기도 함.

 

각 엔진이나 툴마다 UV 배치가 다르다. Unreal 엔진이나 DirectX는 좌측 상단이 float2(0,0) 이지만 Unity 엔진이나 OpenGL은 좌측 하단을 float2(0,0)로 나타낸다.

 

 

 

UV 시각적 확인

Quad 오브젝트를 하나 생성하고 텍스쳐 한 장 받는 것 외엔 아무 기능이 없는 쉐이더를 만들어, 메터리얼과 오브젝트에 적용하였다.

 

 

 

위 사각형에서 가장 좌측 하단 모서리의 Vertex에 들어 있는 UV는 (0.0,0.0) 이며 우측 하단은 (1.0,0.0)이다. 우측/좌측 상단 또한 이와 같은 방식으로 동일하다.

 

 

 

외부 인터페이스가 아닌, 유니티 내부로부터 _MainTex의 UV를 받아옴.
struct Input
{
    float2 uv_MainTex;
};​

 

선언된 UV를 text2D(sampler,UV)에 사용함.
fixed4 c = tex2D (_MainTex, IN.uv_MainTex);​

 

 

 

 

UV를 눈으로 확인할 수 있도록 다양한 방식으로 출력
  • U 출력
void surf (Input IN, inout SurfaceOutputStandard o)
 {
     fixed4 c = tex2D (_MainTex, IN.uv_MainTex);
     o.Albedo =IN.uv_MainTex.x;
     o.Alpha = c.a;
 }

 

 

 

  • V 출력

 

  • U와 V 동시에
    • U는 Red로 표현되고, V는 Green으로 표현
void surf (Input IN, inout SurfaceOutputStandard o)
{
    fixed4 c = tex2D (_MainTex, IN.uv_MainTex);
    o.Albedo = float3(IN.uv_MainTex.x, IN.uv_MainTex.y, 0);
    o.Alpha = c.a;
}

 

 

 

UV 연산


fixed4 c = tex2D (_MainTex, IN.uv_MainTex + 0.5);

 

UV에 0.5를 더하면 아래 사진처럼 텍스쳐가 왼쪽 아래로 밀려 내려온 것을 볼 수 있다.

 

 

 

💡텍스쳐의 Wrap Mode를 clamp로 바꾸면 UV를 벗어나는 영역에서도 텍스쳐가 계속 반복되어, UV를 이동시켜도 계속 연결되어 보일 수 있도록 함. Reapeat은 반복됨.

 

 

 

 

UV 응용 (Time 활용)


Time 관련 변수
https://docs.unity3d.com/2021.3/Documentation/Manual/SL-UnityShaderVariables.html

 

Uv에 숫자를 더하면? 이미지가 이동한다. 즉, Time 관련 변수를 활용하여 이미지를 지속해서 이동시켜 흘러가도록 보이게 할 수 있다.

 

더보기

fixed4 c = tex2D (_MainTex, IN.uv_MainTex + _Time.y);

  • X 방향으로 흘러가게 할 때
더보기

fixed4 c = tex2D (_MainTex, float2(IN.uv_MainTex.x + _Time.y, IN.uv_MainTex.y);

 

 

  • Y 방향으로 흘러가게 할 때
더보기

fixed4 c = tex2D(_MainTex, float2(IN.uv_MainT

ex.x, IN.uv_MainTex.y + _Time.y));

 

 

 

UV 활용 이펙트 제작

제작할 불 이펙트를 만들려면 주로 파티클을 사용하거나 시퀀스 이미지들을 겹쳐서 사용하는 두 가지의 방법을 적절히 응용해서 사용하곤 한다. 이번 파트에서는 쉐이더를 사용하여 불 이펙트를 만들 것이다.

 

o.Albedo를 o.Emission으로 변경하여 빛의 영향을 배제

 

 

 

알파 채널 활성화 (임시 작동)
아래와 같이 코드를 변경한다.
Tags { "RenderType"="Transparent" "Queue"="Transparent" }
LOD 200

CGPROGRAM
#pragma surface surf Standard alpha:fade​

 

 

 

 

_Time.y에 따라 이동하는 이미지 추가

 

 

 


두 장의 이미지 활용
void surf (Input IN, inout SurfaceOutputStandard o){
            fixed4 c = tex2D(_MainTex, IN.uv_MainTex);
            fixed4 d = tex2D(_MainTex2, float2(IN.uv_MainTex2.x, IN.uv_MainTex2.y - _Time.y));
            o.Emission = d.rgb * c.rgb;
            o.Alpha = c.a * d.a;
}​

 

 

 

 

 

 

UV 활용 이펙트 제작 (2)

위에서 제작한 불 이펙트를 업그레이드 해보기 위한 과정이다.
우선, 확실한 효과를 보기 위하여 불 이미지를 아래와 같이 체크 이미지로 변경하였으며 두 번째 이미지는 코드 내에서 _MainTex2 ("Albedo (RGB)", 2D) = "black" {}을 추가하여 검정색 이미지를 출력하도록 하였다.

 

 

 

아래와 같이 코드를 변경하여 c의 uv에 d.r을 더해주어도 아무 변화가 일어나지 않는다.
d는 float4(0,0,01)이기 때문이다.

 

 void surf (Input IN, inout SurfaceOutputStandard o)
 {
     fixed4 d = tex2D(_MainTex2, IN.uv_MainTex2);
     fixed4 c = tex2D(_MainTex, IN.uv_MainTex + d.r);
     o.Emission = c.rgb;
     o.Alpha = c.a;
 }
 ENDCG

 

 

d 텍스쳐의 색상에 따라 변경되는 이미지의 이동 범위

 

 

 

 

d 텍스쳐의 이미지에 따라 다르게 출력되는 c 텍스쳐의 이미지

 

 

 

 

  • 위로 흐르도록 코드 변경
void surf (Input IN, inout SurfaceOutputStandard o)
        {
            fixed4 d = tex2D(_MainTex2, float2(IN.uv_MainTex2.x, IN.uv_MainTex2.y - _Time.y));
            fixed4 c = tex2D(_MainTex, IN.uv_MainTex + d.r);
            o.Emission = c.rgb;
            o.Alpha = c.a;
        }

 

 

 

  • c 텍스쳐 이미지 불로 변경
오브젝트에 메터리얼(Material)과 쉐이더 적용

 

  1. 오브젝트 생성: (예시) GameObject > 3D Object > Sphere
  2. 쉐이더 생성:
  3. 메터리얼 생성:
  4. 적용:
    • 쉐이더->메터리얼 drag&drop / 메터리얼->화면 상의 오브젝트 drag&drop
    • 메터리얼의 Inspector에서 쉐이더 변경 / 오브젝트의 Inspector > Mesh Renderer > Meterials > Element 0 에 메터리얼 적용

 

쉐이더 코드


  • 쉐이더 코드를 더블 클릭하면 MonoDevelop 또는 VisualStudio 프로그램 실행
  • 기본 코드
    • Shader "Custom/NewSurfaceShader"에서 "Custom/NewSurfaceShader"는 메터리얼에서 선택할 수 있는 쉐이더의 이름이며 '/' 트리구조 생성

 

쉐이더 ProPerties

 Properties
    {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _Glossiness ("Smoothness", Range(0,1)) = 0.5
        _Metallic ("Metallic", Range(0,1)) = 0.0
    }
  • 쉐이더의 인터페이스인 Properties 영역
    • 이 부분에서 작성한 코드는 메터리얼의 인스펙터 인터페이스로 볼 수 있음.
    • 인터페이스를 만드는 방법
//Float을 받는 인터페이스
_Name ("display name", Range (min, max)) = number
_Name ("display name", Float) = number
_Name ("display name", int) = number

//Float4를 받는 인터페이스
_Name ("display name", Color) = (number, number, number, number)
_Name ("display name", Vector) = (number, number, number, number)

//기타 SampLer를 받는 인터페이스
_Name ("display name", 2D) = "name" { options }
_Name ("display name", Rect) = "name" { options }
_Name ("display name", Cube) = "name' { options }
_Name ("display name", 3D) = "name" { options }

 

1. Range
최솟값과 최댓값을 입력해주면 슬라이더가 나오는 명령

_Name ("display name", Range (min,max)) = number

 

2. Float
한 자리의 소수점을 입력받는 인터페이스

_Name ("display name", Float) = number

 

3. Color
R,G,B,A 4자리 숫자인 float4를 입력받는 인터페이스
_Name ("display name", Color) = (number,number,number,number)​

 

4. Vector
Color와 동일하게 float4를 숫자로 입력받지만, 색상이 아닌 값으로 입력받음
_Name ("display name", Vector) = (number,number,number,number)​

 

5. text2D
float 계열로 분류되지 않는 sampler들 (2D텍스쳐를 받는 인터페이스)
_Name ("display name", 2D) = "name" {options}​

 

 

 

색상 출력 및 연산


  • 유니티 자체 스크립트가 아닌 CG 언어를 이용하여 쉐이더를 짜는 CGPRGRAM ~ ENDCG 영역
 CGPROGRAM
        // Physically based Standard lighting model, and enable shadows on all light types
        #pragma surface surf Standard fullforwardshadows

        // Use shader model 3.0 target, to get nicer looking lighting
        #pragma target 3.0

        #pragma enable_d3d11_debug_symbols

        sampler2D _MainTex;

        struct Input
        {
            float2 uv_MainTex;
        };

        half _Glossiness;
        half _Metallic;
        fixed4 _Color;

        void surf (Input IN, inout SurfaceOutputStandard o)
        {
            // Albedo comes from a texture tinted by color
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
            o.Albedo = c.rgb;
            // Metallic and smoothness come from slider variables
            o.Metallic = _Metallic;
            o.Smoothness = _Glossiness;
            o.Alpha = c.a;
        }
        ENDCG

1. 설정 부분
전처리 또는 스니핏(snippet)이라 부름. 쉐이더의 조명 계산 설정이나 세부적인 분기를 정해주는 부분

// Physically based Standard lighting model, and enable shadows on all light types
#pragma surface surf Standard fullforwardshadows
// Use shader model 3.0 target, to get nicer looking lighting
#pragma target 3.0

2. Input 구조체
엔진으로부터 받아와야 할 데이터

struct Input{
            float2 uv_MainTex;
};

3. 함수 영역
색상이나 이미지가 출력되는 부분

void surf (Input IN, inout SurfaceOutputStandard o)
        {
            // Albedo comes from a texture tinted by color
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
            o.Albedo = c.rgb;
            // Metallic and smoothness come from slider variables
            o.Metallic = _Metallic;
            o.Smoothness = _Glossiness;
            o.Alpha = c.a;
        }
  • o.Albed: 빛의 영향을 받는 색이 출력
  • o.Emmision: 빛의 영향을 받지 않는 색이 출력위와 같이 변수를 사용하여 출력 색상 변경 또한 가능하다.
void surf (Input IN, inout SurfaceOutputStandard o) { 
	float4 test = float4(1,0,0,0); 
    fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color; 
    //o.Albedo = test.ggg; 
    //o.Albedo = test.b; 
    o.Albedo = test; 
    o.Alpha = c.a; }

 

 

외부의 입력값 출력


  • 색상 입력 받고 출력
    ex) properties에 _TestColor("TestColor", Color) = (1,1,1,1) 을 추가하여 인스펙터에 나타내고, float4 _TestColor; 로 변수를 추가한 뒤, surf 함수 내에서 o.Albedo = _TestColor.rgb;을 추가

즉, 인터페이스에서 원하는 타입의 변수를 생성한 후, SubShader 코드에 선언하고, surf함수에서 변수를 사용하면 출력 가능

 

유니티 쉐이더 작성

ShaderLab으로만 작성

  • ShaderLab 문법만 이용해서 작성하는 방법
  • 장점: 매우 가볍고 하드웨어 호환성이 좋음
    단점: 기능이 부족하며 자체 문법으로 이루어져 있어, 다른 쉐이더 문법과 거의 호환되지 않음. 고급 기법 구현 불가

Surface Shader로 작성

  • ShaderLab 스크립트와 함께 일부분은 CG 쉐이더 코드를 사용
  • 장점: 조명과 버텍스 쉐이더의 복잡한 부분은 스크립트가 자동 처리하며 픽셀 쉐이더 부분만 간편하게 작성할 수도 있어서 편리함.
    단점: 최적화에 무리가 있으며 일정 수준 이상의 고급 기법은 구현 불가

Vertex & Fragment Shader로 작성

  • ShaderLab 스크립트와 CG 쉐이더 코드를 모두 사용하며 보다 본격적인 쉐이더 작성 방법
  • 제대로 된 CG 쉐이더 방식으로 버텍스의 좌표 변환부터 제대로 처리해야 작동
  • 장점: 최적화와 고급 기법 표현에 유리

+ Recent posts