버텍스 쉐이더를 이용한 외곽선 만들기
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"
}
'기술면(CG) > 3D프로그램' 카테고리의 다른 글
유니티 쉐이더 기초 12 (0) | 2025.02.07 |
---|---|
유니티 쉐이더 기초 11 (0) | 2025.02.07 |
FBX를 Biped로 만들어주는 스크립트 (0) | 2025.02.07 |
Xgen에서 아프로헤어 만들기 튜토리얼 (0) | 2025.01.19 |
헤어 텍스쳐링 프로그램, hair stand designer (0) | 2025.01.19 |