C#/수업내용

2020.06.22. 수업내용 - Shader

dev_sr 2020. 6. 22. 14:03

Shader
픽셀의 색을 정해주는 함수

 

Rendering Pipe
3D 공간안에 있는 물체를 어떻게 스크린에 표현하는가
(Vertex (면을 구성하는 점) 이 어디에 있는지
어떻게 변환하는지)

 

1. 로컬 좌표계
-모델 좌표계

2. 월드 좌표계
- 모델이 월드에 어디에 있는가

3. 뷰 변환
-스크린->월드 , 월드->스크린 / 뷰포트를 통한 방법

4. 후면 추려내기 back-face culling
- 캐릭터 앞쪽만 렌더링함

5. 조명 계산

6. 테셀레이션
GPU에서 정점을 자유자재로 증가, 감소?

7. 클리핑
-안보이는 곳 짤라냄

8. 투영
-원근투영-perspective
-직교투영 -Orthographic

9. 뷰포트 변환 (정규좌표계)

10. 래스터라이즈
-변환이 끝난 폴리곤을 화면에 보여줄 픽셀로 계산

11. 텍스쳐 적용 
UV좌표계를 이용해서 텍스쳐를 입혀줌

12. 렌더 백엔드
-안티 앨리어싱 등

13. 출력

 

 

픽셀 쉐이더 
-픽셀의 색을 결정해주는 함수를 작성해놓은 것


빛의 3원색
R G B 다 더하면 흰색 (가산혼합)

색의 3원색
C Y M 다 더하면 검정색

 

 

 

 

 

Unity - Manual: ShaderLab: Properties

ShaderLab: Properties Shaders can define a list of parameters to be set by artists in Unity’s material inspector. The Properties block in the shader file defines them. Syntax Properties Properties { Property [Property ...] } Defines the property block. I

docs.unity3d.com

 

float 값으로 바꿀 때는 255로 나눠준다 

흰색 (255, 255, 255) / 255 = (1.0, 1.0, 1.0)
검정 (0, 0, 0) / 255 = (0, 0, 0)
노란색 (255, 255, 0) / 255 = (1.0, 1.0, 0)

대부분 float4 로 계산
흰색 반투명 : float4(1.0, 1.0, 1.0, 0.5) // R,G,B, Alpha

회색과 회색을 더하면 흰색이 된다.
float3(0.5, 0.5, 0.5) + float3(0.5, 0.5, 0.5) = float3(1.0, 1.0, 1.0)

 

 

컬러의 곱셈과 나눗셈 
회색 * 회색 
float3(0.5, 0.5, 0.5) * float3(0.5, 0.5, 0.5) = float3(0.25, 0.25, 0.25)
어두운 회색이 된다.


컬러의 반전 
1에서 어떤 색을 빼면 그 색이 반전 된다.
ex) 1 - 빨간색 float(1.0, 0, 0)  = float3(0, 1, 1)
흰색은 반전되지 않는다.

 

 

쉐이더 작성 방법

1. ShaderLab 구문

 

ShaderLab 구문 - Unity 매뉴얼

Unity의 모든 셰이더 파일은 “ShaderLab”이라는 선언형 언어로 작성되어 있습니다. 이 파일에서 중첩 중괄호 구문은 셰이더를 서술하는 다양한 요소를 선언합니다. 예를 들어, 어떤 셰이더 프로퍼

docs.unity3d.com

매우가볍고 하드웨어 호환성이 좋지만 기능이 상당히 제한적

 

 

2. SufaceShader
CG 프로그래밍 언어를 알아야함
-그래픽 카드마다 지원하는 언어를 각각 알아야함

 

 

3. Vertex & Fragment Shader 작성 
- 메뉴얼 모드 : 하나부터 10까지 다 작성

 

 

새로운 shader 스크립트를 만들고 새로운 메테리얼을 만들어서 쉐이더 스크립트를 메테리얼에

드래그앤 드롭으로 적용시킨다.

메테리얼을 다시 오브젝트에 어싸인한다.

 

shader 스크립트

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
Shader "NewShader"
{   
    
    //1. shaderLab 이라는 유니티 자체 프로그래밍 언어로 구성
    //실제로 인터페이스로 뚫려서 외부에서 값을 수정할 수 있음
    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
    }
 
    //2. 유니티 스크립트
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 200
        
        //3. CG 언어로 구성(마이크로그래픽스) - 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
 
        sampler2D _MainTex;
 
        //엔진으로부터 받아오는 데이터
        struct Input
        {
            float2 uv_MainTex;
        };
 
        //전역변수
        half _Glossiness;
        half _Metallic;
        fixed4 _Color;
 
        // Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
        // See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
        // #pragma instancing_options assumeuniformscaling
        UNITY_INSTANCING_BUFFER_START(Props)
            // put more per-instance properties here
        UNITY_INSTANCING_BUFFER_END(Props)
        
 
        //여기서 계산 다함, 화면에 출력할 수 있는 값을 만들어냄
                    //Input IN: 유니티에서 전달받은 값
                    //SurfaceOutputStandard 유니티 내에서 CG를 처리할 수 있는 API (CG에서 받은 값)
                    // o : 멤버에 접근
        void surf (Input IN, inout SurfaceOutputStandard o)
        {
            //테스트 변수(지역변수)
            float r = 1;
            float2 gg = float2(0.50);
            float3  bbb = float3(101);
            float4 test = float4(1001);
 
            // Albedo comes from a texture tinted by color
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
            //o.Albedo = float3(0, 0, 0);   //조명 연산
            //o.Emission = float3(0.5, 0.5, 0.5)+ float3(0.5, 0.5, 0.5);   //조명 연산X 순수한 색계산
            //o.Emission = float3(1, 0, 0) + float3(0, 1, 0); //노란색 (1,1,0)
            //o.Emission = float3(1, 0, 0) * float3(0, 1, 0); //검정 (0,0,0)
            //o.Emission = float3(0.5, 0.5, 0.5) * float3(0.5, 0.5, 0.5); //더 어두운 회색(0.25,0.25,0.25)
            //o.Emission = float3(1, 0, 0) + float3(1, 0, 0); //메모리상엔 (2,0,0) 실제로 보이는 건 (1,0,0)
            //o.Emission = float3(1, 0, 0) + 1; //1 (1,1,1) 연산하는 건 언제나 가능 ->흰색 (1,1,1)
            //o.Emission = float3(1, 0, 0) - 1; //1 (1,1,1) 연산하는 건 언제나 가능 ->검정 (0,-1,-1)
            //알베도와 이미션을 같이 하면 최종적으로 색이 더해진다-> 더 밝아진다.
 
            //o.Emission = test;  //변수의 값을 넣어도 잘 적용이 된다.
            //o.Emission = test.rgb;  //테스트 float4 에서 알파를 뺀 rgb만 사용하겠다.
            //o.Emission = test.grb;  //rgb의 순서를 바꾸어 사용할 수도 있다.
            //o.Emission = test.rrr; //이것도 가능 (1,1,1)
            //o.Emission = test.b; // (0,0,0)
 
            //o.Emission = float3(0, gg); //(0,0.5,0) 어두운 초록색
            //o.Emission = float3(bbb.b, gg.r, r.r); //분홍색 (1,0.5,1)
            //o.Emission = float3(1, 0.5, 1);   //분홍색
 
            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}