서피스 툰 셰이더 #1

 

<툰 쉐이더 적용 전>


We're gonna set a custom lighting function

1) 우리가 설정 가능한 조명기능을 설정해주도록 한다.

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
Shader "Custom/ToonShaderPratice"
{
    Properties
    {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
 
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 200
 
        CGPROGRAM
        // Physically based Standard lighting model, and enable shadows on all light types
        #pragma surface surf Standard fullforwardshadows
        #pragma target 3.0
 
        sampler2D _MainTex;
        half4 _Color;
 
        half4 LightingToonLighting(SurfaceOutput s, half3 lightDir, half atten) 
        {
 
        }
        struct Input
        {
            float2 uv_MainTex;
        };
        void surf (Input IN, inout SurfaceOutputStandard o)
        {
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
            o.Albedo = c.rgb;
        }
        ENDCG
    }
    FallBack "Diffuse"
}
 
cs



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
Shader "Custom/ToonShader"
{
    Properties
    {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 200
 
        CGPROGRAM
        #pragma surface surf ToonLighting
 
        // Use shader model 3.0 target, to get nicer looking lighting
        #pragma target 3.0
 
        sampler2D _MainTex;
        half4 _Color;
 
        half4 LightingToonLighting(SurfaceOutput s, half3 lightDir ,half atten)
        {
            float NdotL = saturate(dot(s.Normal, lightDir))* atten;
            float toonL = step(0.5, NdotL);
            return half4(toonL,toonL,toonL,1);
 
        }
        
        struct Input
        {
            float2 uv_MainTex;
        };
 
 
        void surf(Input IN, inout SurfaceOutput o)
        {
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex)* _Color;
            //o.Albedo = c.rgb;
        }
        ENDCG
    }
    FallBack "Diffuse"
}
 
cs



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
Shader "Custom/ToonShader"
{
    Properties
    {
        _LitOffset("Lit Offset",Range(0,1))=0.25
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 200
 
        CGPROGRAM
        #pragma surface surf ToonLighting
 
        // Use shader model 3.0 target, to get nicer looking lighting
        #pragma target 3.0
 
        sampler2D _MainTex;
        half4 _Color;
        half _LitOffset;
 
        half4 LightingToonLighting(SurfaceOutput s, half3 lightDir ,half atten)
        {
            float NdotL = saturate(dot(s.Normal, lightDir))* atten;
            float toonL = step(_LitOffset, NdotL);
            return half4(s.Albedo * toonL,1);
 
        }
        
        struct Input
        {
            float2 uv_MainTex;
        };
 
 
        void surf(Input IN, inout SurfaceOutput o)
        {
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex)* _Color;
            o.Albedo = c.rgb;
        }
        ENDCG
    }
    FallBack "Diffuse"
}
 
cs


우리의 음영을 향상시키기 위해 우리는 표면에서 완전히 어두운 부분을 원하지 않는다.

_SSColor 은 "피부" 아래 인물의 색감이라고 생각하다. 그리고 그늘진 부분에서 우리는 알베도를 사용한다.

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
Shader "Custom/ToonShader"
{
    Properties
    {
        _LitOffset("Lit Offset",Range(0,1))=0.25
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _SSSTex("SSS Map",2D) = "black" {}
        _SSSColor("SSS Tint",Color) = (1,1,1,1)
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 200
 
        CGPROGRAM
        #pragma surface surf ToonLighting
 
        // Use shader model 3.0 target, to get nicer looking lighting
        #pragma target 3.0
 
        sampler2D _MainTex;
        sampler2D _SSSTex;
        half4 _Color;
        half _LitOffset;
        half _SSSColor;
 
        struct CustomSurfaceOutput {
            half3 Albedo;
            half3 Normal;
            half3 Emission;
            half Alpha;
            half3 SSS;
        };
 
        half4 LightingToonLighting(CustomSurfaceOutput s, half3 lightDir ,half atten)
        {
            float NdotL = saturate(dot(s.Normal, lightDir))* atten;
            float toonL = step(_LitOffset, NdotL);
            half3 albedoColor = lerp(s.Albedo * s.SSS, s.Albedo *toonL, toonL);
            return half4(albedoColor,1);
 
        }
        
        struct Input
        {
            float2 uv_MainTex;
        };
 
 
        void surf(Input IN, inout CustomSurfaceOutput o)
        {
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex)* _Color;
            o.Albedo = c.rgb;
            o.SSS = tex2D(_SSSTex, IN.uv_MainTex) * _SSSColor;
        }
        ENDCG
    }
    FallBack "Diffuse"
}
 
 
cs

당신이 보는 것처럼 우리는 우리가 질감으로 더럽힐 수 있는 그림자에 단정한 어두운 색을 가지고 있다.

그러나 문제는 있다 .만약 우리가 라이트 색을 바꾼다면 그것은 머테리얼에 영향을 미치지 않을 것이다.

간단한 해결책: 단지 밝은 색과 우리의 밝은 알베도를 곱하면 된다.




next problem : look at that It's totally flat even when it should have shadows between the plates

다음 문제: 저것 좀 봐. 접시 사이에 그림자가 있어야 하는데도 완전히 평평해.



We'll paint the vertices of our model to mark the should shaded parts and read that colors in our shader

우리는 우리 모델의 정점을 칠해서 음영처리 된 부분을 표시하고 그 색을 우리의 음영처리 된 부분에 읽을 것이다.



This is how our model looks like when we map the vertx color

vertx 색상의 지도를 만들 때 우리의 모델은 이렇게 보인다.



To fix it we use a fancy rick: Vertex color

그것을 고치기 위해 우리는 화려한 릭을 사용한다


Then mult our lighting by the occlussion given by the vertex and done

그 다음 버텍스에 의해 주어지는 오쿨루젼으로 우리의 조명을 여러 번 혼합하여 완성한다.


To improve it even more, we'll add a third map: Combined Map

한층 더 향상시키려면, 3개의 맵: 결합 맵을 추가한다


We'll map if a pixel it's glossy or not in it's Red channel

우리는 픽셀에 광택이 나는지 아닌지를 빨간 채널에서 매핑할 것이다.


We'll use again the dot product and get the specular lights

우리는 다시 도트 제품을 사용할 것이고, 투시 조명을 받을 것이다.


We'll need the view direction(facing of the camera)

우리는 전망 방향이 필요할 것이다.


With the pow function we'll control the size of our reflection

파워 기능으로 우리는 반사되는 크기를 조절할 것이다.

We add a prop to control the Specular size

우리는 시편 크기를 조절하기 위해 받침대를 추가한다.



Then we apply the light color and the light attenuation to our specular component and mult the Glossy from the CombMap

그리고 나서 우리는 밝은 색과 빛 감쇠를 우리의 시야에 있는 성분과 콤비맵의 여러 가지 광택에 바른다.



Caution: darker it's bigger. The smaller the exponent, the bigger the highlight

주의: 더 어둡다. 지수가 작을수록 하이라이트는 커진다.


Finally, to not waste any memory, let's put at use the Green and Alpha channels of the CombMap

마지막으로, 어떤 기억도 낭비하지 않기 위해 콤비맵의 그린과 알파 채널을 사용하자.


We'll use Green channel to add extra shadows.(Caution: if you don't make this texture correctly shadows could pixelate)

우리는 그린 채널을 사용하여 그림자를 더 추가할 것이다.

(주의: 이 질감을 정확하게 만들지 않으면 그림자가 화소화될 수 있음)


Now, the Alpha channel will be used as an InnerLine mask. Alpha 0 it's a line

이제 알파 채널은 이너라인 마스크로 사용될 것이다. 알파 0 선이다.


COOL TRICK: if you structure a surface shader like this, you can mix regular vertex/fragment passes with surface passes

COOL TRICK: 만약 당신이 표면 하드어를 이렇게 구조화한다면, 당신은 일반 정점/약점 패스와 표면 패스를 혼합할 수 있다.


Very easy trick. We get the normal, and offset the vertex position along it a little bit.. Fragment just returns black

매우 쉬운 속임수 우리는 정상과 정점 위치를 약간 상쇄한다. 파편이 그냥 검은색으로 돌아온다.


PRO TIP : Renormalize the normal, some models have normals whith! =1 magnitide. This could result in inconsistent outlines.

PRO TIP: 정상화를 다시 하고, 어떤 모델들은 표준적인 기동을 가지고 있다! =1자석 이렇게 되면 윤곽이 일관되지 않을 수 있다.


To fix it just cull the front faces. We'll render only the back of the surface

그것을 고치기 위해서 앞면만 도려낸다. 우리는 표면만 다듬을 것이다.



All left to do it's add some props to control the outline color and thickness

남은 것은 윤곽의 색과 두께를 조절하기 위한 소품 몇 가지를 더하는 것이다.

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
Shader "Custom/ToonShader"
{
    Properties
    {
        _LitOffset("Lit Offset",Range(0,1))=0.25
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _SSSTex("SSS Map",2D) = "black" {}
        _SSSColor("SSS Tint",Color) = (1,1,1,1)
        _CombMap("Comb Map",2D) = "white" {}
        _SpecPower("Specular Power",Range(0,100)) =20.0
        _SpecScale("Specular Scale",Range(0,10)) = 1.0
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 200
 
        CGPROGRAM
        #pragma surface surf ToonLighting
 
        // Use shader model 3.0 target, to get nicer looking lighting
        #pragma target 3.0
 
        sampler2D _MainTex;
        sampler2D _SSSTex;
        sampler2D _CombMap;
        half4 _Color;
        half4 _SSSColor;
        half _LitOffset;
        half _SpecPower;
        half _SpecScale;
 
    
 
 
        struct CustomSurfaceOutput {
            half3 Albedo;
            half3 Normal;
            half3 Emission;
            half Alpha;
            half3 SSS;
            half vertexOc;//
            half Glossy;
            half Glossiness;
            half Shadow;
            half InnerLine;
        };
 
        half4 LightingToonLighting(CustomSurfaceOutput s, half3 lightDir, half viewDir ,half atten)
        {
            float oc = step(0.9, s.vertexOc);
            float NdotL = saturate(dot(s.Normal, lightDir))* atten;
            float toonL = step(_LitOffset, NdotL)*s.Shadow * oc;
            half3 albedoColor = lerp(s.Albedo * s.SSS, s.Albedo* _LightColor0 *toonL, toonL);
            half3 specularColor = saturate(pow(dot(reflect(-lightDir, s.Normal), viewDir),s.Glossiness* _SpecPower))
                                * toonL * _LightColor0 * s.Glossy * _SpecScale;
 
            //return half4(s.Glossy, s.Glossy, s.Glossy);
            return half4( (albedoColor + specularColor)*s.InnerLine,1);
 
        }
        
        struct Input
        {
            float2 uv_MainTex;
            float4 vertColor : COLOR;
        };
 
 
        void surf(Input IN, inout CustomSurfaceOutput o)
        {
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex)* _Color;
            half4 comb = tex2D(_CombMap, IN.uv_MainTex);// *_SSSColor;
            o.Albedo = c.rgb;
            o.SSS = tex2D(_SSSTex, IN.uv_MainTex) * _SSSColor;
            o.vertexOc = IN.vertColor.r; //
            o.Glossy = comb.r;
            o.Glossiness = comb.b;
            o.Shadow = comb.g;
            o.InnerLine = comb.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}
 
cs




학습참고 https://www.youtube.com/watch?v=pMq--FUR5VE

반응형

+ Recent posts