원래 이걸 보면서 홀로그렘을 만들고 있었다. 

https://sharpcoderblog.com/blog/create-a-hologram-effect-in-unity-3d 

 

Hologram Effect in Unity 3D

Hologram Effect is widely used in many popular games such as Halo series, Call of Duty: Advanced Warfare, Half Life 2 etc. In this tutorial I will be showing how to create a ...

sharpcoderblog.com

이 쉐이더를 그냥 에셋 스토어에서 굴러다니는 좀비 모델에 테스트 해봤다.  

와! 홀로그렘 좀비! 

이렇게 만들고 있었는데 기획자분이 줄무늬 없는 그런 홀로그렘은 원하셔서 눈물을 머금고 텍스쳐 부분을 빼봤는데

 

세상에 

 

 

 

 

 

구강구조 TMI.... 

저는 당신의 구강구조를 알고싶지 않습니다 좀비 선생님.. 

 

 

 

 

내부 구조가 있는 모델은 알파로 투명하게 만들면 내부 구조가 보일 수 밖에 없다. 

예전에 알파가 대환장파티라는걸 공부해 둬서 다행이다. 

 

darkcatgame.tistory.com/31

 

Unity Shader - Alpha 이론 & 문제 해결

게임을 만드는데 있어서 반투명 그래픽은 필수적이며 여러가지 활용하는 곳이 많습니다, 반투명이라는 것은 뒤의 픽셀과 블렌딩(Blending)된다는 의미입니다. 이번 포스팅에서는 알파에 관한 이

darkcatgame.tistory.com

이 블로그를 참고해서 고쳤다. 

이 부분을 참고했음

 

결론은 간단하게 말하자면 2pass로 Zwrite On , Off 하면 되는 문제이다.

근데 원래 있던 코드를 2Pass 적용하는데 코드가 복잡해서 잘 안됐다. 쉐이더 코드를 읽을줄은 아는데 전체적으로 뜯어 고치는건 아직 어렵다..

그래서 처음 썼던 쉐이더코드 말고 해당 블로그에서 2Pass 를 통해 처리하는 코드를 토대로 정말 간단한 림 라이트를 고치는 방향으로 갔다.

 

darkcatgame님의 코드에서

이렇게 수정했다. 

Shader "Custom/RimLight"
{
    Properties
    {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _RimPower ("RimPower" , Range(1, 5) ) = 3
     
    }
    SubShader
    {
        Tags { "RenderType"="Transparent" "Queue" = "Transparent" }
        
        ZWrite on    //! zwrite는 기본적으로 켜져있지만 확실하게 코드를 짜줍니다.
        ColorMask 0    //! 렌더하지 않습니다.
        CGPROGRAM
 
        #pragma surface surf _NoLit nolight keepalpha noambient noforwardadd nolightmap novertexlights noshadow        //! 최적화 코드
 
        struct Input
        {
            float2 color:COLOR;
        };
 
        void surf (Input IN, inout SurfaceOutput o)
        {
        }
        float4 Lighting_NoLit(SurfaceOutput s, float3 lightDir, float atten)    //! 커스텀 라이트 함수를 만들어 아무런 연산을 하지 않습니다.
        {
            return 0.0f;
        }
        ENDCG
        
 
        ZWrite off
        CGPROGRAM
 
        #pragma surface surf Lambert alpha:blend
 
        sampler2D _MainTex;
        fixed4 _Color;
        float _RimPower;

        struct Input
        {
            float2 uv_MainTex;
            float3 viewDir;
        };
 
        
 
        void surf(Input IN, inout SurfaceOutput o)
        {
            // 여기에서 따로 림라이트를 만들어서 홀로그램을 만들자
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex );
            //o.Albedo = c.rgb;
            float rim = saturate(dot(o.Normal, IN.viewDir));
            rim = pow(1-rim,_RimPower);
            o.Emission = _Color;
            o.Alpha = rim;
        }
        ENDCG
    }
    FallBack "Diffuse"
}

 

Surf 함수에서 림라이트 연산을 하는 것 뿐이다. 매우 간단. 연산도 그렇게 많지 않아서

모바일에서도 크게 문제 없을 거 같다. 

 

결과물은 

 

 

후~~~ 편안

그리고 RimPower 변수를 하나 더 만들어서 정도도 조절 할 수 있게 했다. 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

'Unity > Shader' 카테고리의 다른 글

[ 쉐이더 ]요절복통 Alpha 이야기 ppt  (0) 2020.07.07
[Unity] post processing 적용방법  (0) 2020.02.26
[ Unity Shader ] RimLight 구현  (0) 2020.02.13

 

 

저번에 알파에 대한 수업자료로 만든 PPT를 올려본다. 

 

ppt 링크 : https://docs.google.com/presentation/d/1BELbWk9oHqKhuauq1vIGVuWtLTRxNYyjUCtzolHhz4s/edit#slide=id.g7dcd321d58_0_0

 

요절복통 alpha 이야기

요절복통 alpha 이야기

docs.google.com

 

 

포스트프로세싱 적용방법을 간단하게 정리해둔 곳이 없어보여서 한번 만들어봤습니다.

 

- 포스트프로세싱 플러그인을 설치해주세요. 

 

윈도우->Package Manager

(만약 Package Manager가 보이지 않는다면 에셋스토어에서 무료로 임포트 할 수 있습니다 ) 

 

 

로딩을 기다리다보면 전체 목록이 뜨게 됩니다.

Post Processing를 다운 받아주세요.

 

 

 

 

 

 

- 포스트 프로세싱 적용 방법

 

1. 후처리를 할 카메라에 Post-Process Layer 컴포넌트를 달아줍니다.

 

 

 

2. Layer 설정을 PostProcess로 바꿔줍니다. 

 

 

3. 그리고 후처리로 쓸 카메라의 레이어 또한 PostProcess로 맞춰줍니다.

 

4. PostProcess Volume을 추가합니다.

이것은 빈 오브젝트에 추가해도 되고 카메라에 추가해도 됩니다.

굳이 빈 오브젝트에 추가할 필요성을 못느껴 저는 카메라에 추가하겠습니다.

 

 

4.1 PostProcess Volume의 Rrofile은 어떤 후처리 효과를 낼 것인지

효과를 세팅해 놓은 파일을 넣을 곳입니다.

따라서 그 파일을 만들어줘야겠죠?

 

이제 그 파일을 만들어보겠습니다.

 

 

5. Project -> Create -> PostProcess Profile 생성을 해줍니다.

 

 

5.1 PostProcess Profile을 보면 이렇게 다양한 후처리 효과들이 있는것을 볼 수 있습니다.

 

6. profile에 아까 우리가 만든 PostProcess Profile을 넣어줍니다. 

 

7. 그리고 씬 전체에 적용하기 위해서 PostProcess Volime -> Is Global 체크해줍니다. 

 

 

 

이러면 적용이 완료됩니다.

 

다음 포스팅에서는 포스트프로세싱 기본 효과를 통해 구현할 수 있는 효과들을 소개해보려고 합니다

 

 

 

 

 

 

 

 

 

본 포스팅에서는

1. RimLight가 무엇인지

2. RimLight를 통해 어떤 효과를 기대 할 수 있는지

3. RimLight를 구현하기 위한 프레넬 공식

4. RimLight구현하는 방법

에 대해 알아보려 합니다. 

 


1. RimLight가 무엇인가? 

 

RimLight는 "모든 물체는 기울어질수록 반사가 심해진다" 라는 현상에서 부터 시작됩니다. 

 

이때 역광이 있을때 털이나 반투명 재질을 가진 물체들은 이 현상이 매우 강렬하게 나타납니다. 

 

사진 분야에서 이 현상을 RimLight 라고 합니다. 

 

림 라이트 예제 이미지1

 

림 라이트 예제 이미지 2

두 예제 이미지를 보면 머리카락이나 옷 부분을 보면 역광에 반사가 심해져 윤곽선 같은 느낌이 나는걸 볼 수 있습니다.

 

이것이 RimLight 입니다. 

 


 

2. RimLight를 통해 어떤 효과를 기대 할 수 있는지

기본적으로 게임에서는

1. 배경과 캐릭터의 분리나 강조 효과

2. 캐릭터가 선택 되었을 때나 특정 상태를 표현하기 위한 이펙트

3. 셀 세이딩 효과 같은 특수한 효과를 위해

과장되도록 사용합니다. 

 

 

RimLight 효과가 적용 되기 전 

 

RimLight가 적용된 이후

RimLight 예제 이미지 처럼 외곽선 부분이 강조된걸 볼 수 있습니다.

이 때문에 배경과 캐릭터가 구분 되는 효과를 볼 수 있습니다.

 

 


 

3. RimLight를 구현하기 위한 프레넬 공식

 

프레넬?

 

프레넬 방정식(Fresnel equations) 또는 프레넬 공식(Fresnel's formulas)은 반사계수와 투과계수에 관한것으로 한 매질과 광학적 특성 즉, 굴절률이 다른 매질의 계면에서 반사 또는 투과 진폭을 입사진폭으로 나눈 값을 말한다. 프랑스의 물리학자 오귀스탱 장 프레넬이 유도하였다.

( 위키백과 )

 

라고 하는데

 

프레넬은 아주 쉽게 말해서 각 재질에 따른 반사 정도를 나타냈다고 이해합시다...

실제로 프레넬은 프로그램에서 대체로 빛을 반사하는 값의 정도를 조절하는 값인 경우가 많다.

 

 

근데 RimLight를 구현하는데 왜 갑자기 프레넬이 튀어 나오냐구요?

 

 

왜냐면 RimLight는 결국 역광에서 나온 빛이 반사가 되어 생긴 현상이기 때문입니다. ( 글쓴이의 얕은 추론의 결론... )

따라서 반사와 투과에 대한 공식인 프레넬은 림라이트를 포함하는 개념입니다. ( 이것은 아래 레퍼런스 참고..!)

 

 

 

 


3. RimLight 구현

RimLight를 구현하는 과정을 간략하게 정리해보려합니다.

 

 

 

a. RimLight은 Lembert 공식(  N Dot L ) 에서 L을 V로 바꾼것

b. 그 결과값을 1 - 결과값 으로 뒤집어 버린다.

c. 그리고 POW를 통해 값을 급격하게 높혀버린다. 이를 통해 외곽선이 뚜렷하게 보이는 것

 

 


 

테스트 모델은 이 에셋을 이용합니다.

https://assetstore.unity.com/packages/essentials/asset-packs/the-blacksmith-characters-39941

 

 

The Blacksmith: Characters - Asset Store

This package includes the characters from “The Blacksmith” short film: - The Blacksmith character - The Challenger character - Hair Shader - Wrinkle maps - Unique character shadows - Plane reflections Please visit this blog post for more information: "The

assetstore.unity.com

 

이름 : 빡빡이 아조씨

캐릭터에 메테리얼이 많이 붙어있기 때문에 머리만 남겨두고 진행합니다. 

1. 프레넬 공식 기본 코드

 

유니티에서 Standard Shader로 생성을 한 후 

라이팅을 Lambert로 하고 환경광을 제거해줍시다.

그리고 쓸데 없는 부분들은 싹 정리 해줍시다. ( 코드 1 )

 

코드 1 : 라이팅을 Lambert로 만들어줬다.

 

아 참고로 더이상 스탠다드 라이팅이 아니기 때문에 Inout에서

SurfaceOutputStandard 쪽에 문제가 생길겁니다. 이것을 SurfaceOutput로 바꿔줘야 합니다.

 

 


그 다음

 

 알베도를 0으로 만들어서 검정색으로 만들어 봅시다. 

왜 검정색으로 만드냐면 라이팅 효과를 제대로 보면서 하고 싶기 때문입니다.

나중에 다시 rgb를 넣어줘서 피부를 되찾아줄겁니다. 

 

위 코드의 결과값입니다.

 

 

마치 코난의 범인 실루엣 같습니다.

이 대머리 아조씨는 어떤 사연을 가지고 살인을 저질렀을까요.

코난의 추리로 사건의 전말이 모두 까발려지고 울먹이면서 어떤 구구절절한 사연을 이야기할지 기대가 됩니다. 

 

 


 

 

RimLight는 Lambert 공식 ( N Dot L ) 에서  L을 V로 바꿔 카메라 벡터를 빛 처럼 받게 합니다. 

 

Lambert 라이트 기본 개념

여기서 L (라이트벡터) 대신 V (뷰 벡터)( 카메라 벡터 ) 로 바꾸면 어떻게 될까요?

원래 빛을 무시하고 카메라를 빛처럼 인식하게 됩니다. 

 

따라서 광원에 따라서 빛이 생기는 것이 아닌 카메라에 따라 빛이 생기는 것입니다.

 

그렇다면 카메라 벡터를 가지고 와야겠죠? 

 

Input에 viewdir (뷰벡터)를 추가합니다. ( 코드 2 ) 

 

코드 2 : viewDir 추가 

 

그리고 ( N dot V ) 값을 Emission에 넣어줍니다. ( 코드 3 )

 

 

 

 코드 3 

 

 

결과값을 봅시다. 

코드3의 결과값

코난에게 구구절절하게 사연을 말하고 자신의 죄를 씻어내기 위해 하얀 죄수복을 입게 되었군요. ( 개소리 ) 

 

( N dot V )라서 카메라가 마치 조명인것 처럼 인식을 하고 있습니다. 

 

 


 

 

( N dot V ) 의 결과값을 뒤집어 줍니다. ( 코드 4 )

 

 

 

코드4

 

 

코드4의 결과값 

결과값을 뒤집어 ( 반전 ) 시켜줘 제일 밝은 부분이 어두운 부분이 되어버렸습니다. 

 

이 상태에서 제일 흰 부분의 영역을 좁히면 RimLight 현상을 구현해볼수 있지 않을까요??? 

 


흰 부분의 영역을 좁히려면 어떻게 해야할까요? 

 

바로 제곱을 통해 영역을 좁힐 수 있습니다. 

 

제곱을 하게 되면

 

 

이런 일정한 값을 가지고 있는 그래프를 

 

 

이렇게 휘게 만들 수 있습니다. 

 

 

 

더 자세하게 보자면 

 

 0.5 부분에서는 값의 변화율이 굉장히 적습니다.

하지만 그 이후부터는 엄청난 변화율을 보여주게 됩니다. 

따라서 값이 극단적으로 변하게 된다고 보면 됩니다. 

 

자! 이 지식을 가지고 다음으로 넘어가 봅시다!

 

rim 값을 제곱해봅시다. ( 코드 5 ) 

pow함수를 통해 제곱이 가능합니다.

코드5: 제곱을 해줬다. 

 

값이 균등하게 바뀌는 것이 아니라 극단적으로 확 변하게 되었습니다. 

 

따라서 

 

코드4의 결과값 

 

제곱을 해준 코드 5의 결과값

 

검은색 부분의 영역은 많아 지고 흰색 부분의 영역이 좁아지는 것입니다.

 

 

 

 

 

완성 코드

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
Shader "Custom/RimLight_Re1"
{
    Properties
    {
        _Color ("Color"Color= (1,1,1,1)
        _MainTex ("Albedo (RGB)"2D= "white" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
 
        CGPROGRAM
        #pragma surface surf Lambert noambient
        #pragma target 3.0
 
        sampler2D _MainTex;
 
        struct Input
        {
            float2 uv_MainTex;
            float3 viewDir;
        };
 
   
        fixed4 _Color;
 
    
 
        void surf (Input IN, inout SurfaceOutput o)
        {
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;// //  
            o.Albedo = 0;
 
            float rim  = dot(o.Normal , IN.viewDir);
            rim = pow ( 1-rim , 3);
            o.Emission = rim;
            
            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}
 
cs

 

 

 

 

 


 

- RimLight를 더 완성해보자 ! 

 

프레넬 기본형에 컬러랑 파워 추가해봅시다. ( 코드 6 )

 

코드 6
코드 6의 메테리얼 설정값

이렇게 해서 인스펙터창에서 값을 설정 할 수 있게 되었습니다. 

컬러도 조절 할 수 있어서 

코드 6 결과값

이렇게 깜직한 핫핑크 빡빡이 아조씨가 되었습니다.

 

핫핑크 아조씨의 피부를 다시 입혀줍시다.

 

피부 텍스처와 노말맵 텍스처를 받아와야 합니다. ( 코드 7 )

 

코드 7 : 

알베도에 값을 0에서 c.rgb로 바꿔주고

노말맵을 받아왔습니다.

 

코드 7 결과값

 

 


 

내적의 값이 -1 ~ 1 까지 되어 나중에 빛 연산을 해도 비정상적으로 어두운 상황을 막기 위해 

saturate 함수로 0~1까지 값을 짤라줍니다. ( 코드 8 )

 

 

코드 8 

 

 

 

- 최종 코드 -

 

 

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
Shader "Custom/RimLight_Re1"
{
    Properties
    {
        _Color ("Color"Color= (1,1,1,1)
        _MainTex ("Albedo (RGB)"2D= "white" {}
        _RimPower("RimPower" , Range(0,10)) = 0 
        _NormalMap ("NormalMap",2D ) = "white" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
 
        CGPROGRAM
        #pragma surface surf Lambert noambient
        #pragma target 3.0
 
        struct Input
        {
            float2 uv_MainTex;
            float2 uv_NormalMap;
 
            float3 viewDir;
        };
   
        fixed4 _Color;
        float _RimPower;
        sampler2D _MainTex;
        sampler2D _NormalMap;
 
    
        void surf (Input IN, inout SurfaceOutput o)
        {
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex);
            o.Albedo = c.rgb;
 
            o.Normal = UnpackNormal(tex2D (_NormalMap, IN.uv_NormalMap));// //
 
            float rim  = saturate(dot(o.Normal , IN.viewDir));
            rim = pow ( 1-rim , _RimPower);
            o.Emission = rim * _Color.rgb;
 
            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}
 
cs

 

 

 


다음 포스팅은 RImLight를 활용한 홀로그렘을 제작해보려합니다.

 

 

 

레퍼런스 :

1. 유니티쉐이더 스타트업

2. https://meshmason.tistory.com/9

 

 

[Blender] 프레넬(Fresnel)이란 무엇인가

3D 툴을 다루다 보면 언젠가 한 번쯤은 들어보았거나, 반드시 이해해야만 하는 문제에 봉착할 수 있는 개념이 Fresnel이다. 아무래도 3D 물체에 재질을 입힐 때 여러가지 값을 설정해야만 되는데, 재질이란 것이..

meshmason.tistory.com

3. https://lifeisforu.tistory.com/384

 

[ PBR 이란 무엇인가 ] 17. Fresnel 이란?

주의 : 잘못된 내용이 포함되어 있을 수 있으므로 이상하면 참고자료를 확인하세요. [ PBR 이란 무엇인가 ] Fresnel 이란? 프레넬 공식이란? 앞서 [ [ 번역 ] 모든 것은 프레넬을 가집니다 ] 와 [ Reflection 에..

lifeisforu.tistory.com

 

 

 

 

+ Recent posts