기술면(CG)/3D프로그램

유니티쉐이더 기초 10

치비씨 2025. 2. 7. 19:22

버텍스 쉐이더를 이용한 외곽선 만들기

Shader "Custom/ToonRender"

{

Properties

{

_MainTex("Albedo(RGB)",2D) = "white"{}

}

SubShader

{

Tags { "RenderType"="Opaque" }

cull front

//앞면을 날리고 뒷면을 보여줌. cull off의 경우 2 side

CGPROGRAM

#pragma surface surf Nolight vertex:vert noshadow noambient

//vertex:vert=버텍스 쉐이더가 vert라는 함수이름으로 시작된다는 것을 #pragma에 알려주고 void로 시작하는 vert 이름의 함수를 만듦(void는 return이 필요없음)

void vert(inout appdata_full v) {

//유니티에 미리 선언된 구조체로, 버텍스가 가지고 있는 정보를 구조체로 만든 것.

appdata_base

:위치, 노멀과 하나의 텍스쳐 좌표계

appdata_tan

:위치, 탄젠트, 노멀과 하나의 텍스쳐 좌표계

appdata_full

:위치, 탄젠트, 노멀, 4개의 텍스쳐 좌표계와 버텍스 컬러

v.vertex.xyz = v.vertex.xyz + v.normal.xyz*0.001;

//버텍스의 x,y,z좌표축을 노멀값0.001을 곱한만큼 더해주겠다는 의미.

}

struct Input

{

float4 color:COLOR;

};

void surf(Input IN, inout SurfaceOutput o)

{}

float4 LightingNolight (SurfaceOutput s, float3 lightDir, float atten){

return float4(0,0,0,1);

}

ENDCG

//2nd Pass

cull back

//cull back은 뒷면을 날리고 앞면을 살림

CGPROGRAM

#pragma surface surf Lambert

sampler2D _MainTex;

struct Input

{

float2 uv_MainTex;

};

void surf(Input IN, inout SurfaceOutput o)

{

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

o.Albedo = c.rgb;

o.Alpha = c.a;

}

ENDCG

}

FallBack "Diffuse"

}

텍스쳐를 넣어준 상태로 셀식으로 음영만들기

Shader "Custom/ToonRender"

{

Properties

{

_MainTex("Albedo(RGB)",2D) = "white"{}

_BumpTex("NormalMap",2D) = "bump"{}

}

SubShader

{

Tags { "RenderType"="Opaque" }

cull front

CGPROGRAM

#pragma surface surf Nolight vertex:vert noshadow noambient

void vert(inout appdata_full v) {

v.vertex.xyz = v.vertex.xyz + v.normal.xyz*0.001;

}

struct Input

{

float4 color:COLOR;

};

void surf(Input IN, inout SurfaceOutput o)

{}

float4 LightingNolight (SurfaceOutput s, float3 lightDir, float atten){

return float4(0,0,0,1);

}

ENDCG

//2nd Pass

cull back

CGPROGRAM

#pragma surface surf Toon noambient

sampler2D _MainTex;

sampler2D _BumpTex;

struct Input

{

float2 uv_MainTex;

float2 uv_BumpTex;

};

void surf(Input IN, inout SurfaceOutput o)

{

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

o.Albedo = c.rgb;

o.Normal = UnpackNormal(tex2D(_BumpTex, IN.uv_BumpTex));

o.Alpha = c.a;

}

float4 LightingToon(SurfaceOutput s, float3 lightDir, float atten) {

float ndotl = dot(s.Normal, lightDir) *0.5 + 0.5;

ndotl = ndotl * 3;

ndotl = ceil(ndotl) / 2;

//빛의 벡터를 받는 라이팅툰.

float ndotl = dot(s.Normal, lightDir) *0.5 + 0.5;=>노멀과 라이트의 내적연산이 A라면, AX0,5+0.5의 값만큼 출력한다.

내적연산은 3배로 강화되고

거기서 2의 값으로 나눠 표현된다.(2단계의 음영을 가진다는 의미)=>숫자를 변형해 원하는 효과를 얻을 수 있다.

if (ndotl > 0.7)

{

ndotl = 1;

}

else if (ndotl > 0.4)

{

ndotl = 0.3;

}

else

{

ndotl = 0;

}

라는 if구문으로 원하는 효과를 얻을 수 도 있다.

ndolt의 값이 0.7보다 높다면 1로 적용하고, 그 외의 값이 0.4보다 높다면 0.4으로 적용하고, 그 외에는 0으로 적용하라는 명령.

float4 final;

final.rgb = s.Albedo *ndotl * _LightColor0.rgb;

final.a = s.Alpha;

return final;

}

ENDCG

}

FallBack "Diffuse"

}