Unity/수업내용
Unity 수업내용 21.07.15. Shader 기초 - Bump, Rim, Hologram
HappyFrog
2021. 7. 15. 12:12

우선 내가 사용할 텍스쳐를 임포트시켰다.
그리고 Shaders폴더와 Materials폴더를 생성한다.

- 그리고 Fire라는 Material과 Shader를 만들어준다.
- Shader는 Standard Surface Shader형식으로 만들자.

- 이어서 씬에 Quad를 만들어주자.
- Quad에 Fire Material을 적용시키자.
Shader "Custom/Fire"
{
Properties
{
_MainTex ("Albedo (RGB)", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Opaque" }
CGPROGRAM
#pragma surface surf Standard fullforwardshadows
sampler2D _MainTex;
struct Input
{
float2 uv_MainTex;
};
void surf (Input IN, inout SurfaceOutputStandard o)
{
fixed4 c = tex2D (_MainTex, IN.uv_MainTex);
o.Albedo = c.rgb;
}
ENDCG
}
FallBack "Diffuse"
}


- 그리고 해당 쉐이더 스크립트에서 필요없는 부분을 위 코드와 같이 모두 지워준다.
- 그리고 Material에 FireTest텍스쳐를 넣어주자.
- 위와 같이 씬에서 불 텍스쳐가 보일것이다.
Shader "Custom/Fire"
{
Properties
{
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_MainTex2("Albedo2 (RGB)", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Transparent" "Queue" = "Transparent"}
CGPROGRAM
#pragma surface surf Standard alpha:fade
sampler2D _MainTex;
sampler2D _MainTex2;
struct Input
{
float2 uv_MainTex;
float2 uv_MainTex2;
};
void surf (Input IN, inout SurfaceOutputStandard o)
{
fixed4 d = tex2D(_MainTex2, IN.uv_MainTex2);
fixed4 c = tex2D (_MainTex, IN.uv_MainTex);
o.Albedo = c.rgb;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
- 그리고 텍스쳐를 한장 더 받을 수 있도록 해준다.
- 이어서 렌더타입과 큐를 설정해준 뒤 알파값이 0인부분을 잘라내주는 alpha:fade를 작성해준다.
- 이 때 surf안에 o.Alpha = c.a;를 작성해주어야 제대로 출력된다. => 안그러면 전부 다 투명하게 나옴


- 그리고 surf에서 텍스쳐 1과 2를 섞어서 출력할 수 있도록 코드를 작성한다.
- c는 Fire이며 d는 새로 넣은 숫자판 텍스쳐이다.
- IN.uv_MainTex + d.r은 UV좌표에 d의 rgb중 r값을 더해주는 것이고
- d의 UV값은 _Time.y때문에 시간에 따라 값이 바뀐다.
- 그러면 위 짤과 같이 상승하는 듯한 효과를 줄 수 있다.
- 이것을 이용하여 불이 타오르는 효과를 줄 수있다.


- 따라서 2번텍스쳐에 효과로 넣을 텍스쳐를 넣어주고 코드를 살짝 수정한다.
- c2.r값에 0.01을 곱한 이유는 c2.r을 그대로 곱하면 값이 너무 커서 크게 일그러지게 된다.
- 투명도도 겹치는부분만 출력해주기 위하여 서로의 텍스쳐의 Alpha값을 곱해주어서 출력한다. (색깔도 맞춰주기 위해 마찬가지.)


- 0분의 1로 만들어주지 않으면 왼쪽과같이 크게 일그러지게 된다.
몬스터에는 vertex를 이용하여 표면을 조정해보자.

Shader "Custom/Skeleton"
{
Properties
{
_MainTex("Albedo (RGB)", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType" = "Opaque"}
CGPROGRAM
#pragma surface surf Standard
sampler2D _MainTex;
struct Input
{
float2 uv_MainTex;
};
void surf(Input IN, inout SurfaceOutputStandard o)
{
fixed4 c = tex2D(_MainTex, IN.uv_MainTex);
o.Albedo = c.rgb;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
- 우선 마찬가지로 Material과 Shader를 만들어준다.
- 쉐이더 스크립트에서 텍스쳐를 한장만 받도록 하고 필요없는 부분을 모두 삭제해준다.


- 그리고 램버트 형식을 사용하기위해 스크립트를 수정한다.
- 표면을 vertex를 이용하여 내가 원하는 대로 늘리거나 줄일 수 있는 형식이다.
- 결과는 오른쪽 사진과 같이 뼈대는 그대로인데 표면은 지방이마냥 부풀어 오른 모습을 확인할 수 있다.
- 해당코드는 해당 객체의 vertex의 normal(굴곡이라고 표현해야하나)방향의 0.01을 곱한 값만큼 증가시키겠다는 뜻이다.
- *주의 메서드 이름 vert는 반드시 vertex:"이름"의 이름과 일치해야한다.

이번엔 커스텀라이트를 사용해보자.(커스텀이라 해봤자 빛효과를 없앨것이다.)

- 프라그마에서 커스텀라이트를 사용한다고 선언하고
- 그림자와 환경광을 없애준다.(noambient)

- 그리고 surf의 내용을 없애고 커스텀라이트 메서드를 만들어준 뒤 내용으로는 까맣게 출력한다는 코드를 작성한다.
- * 주의 커스텀라이트로 선언한 이름과 메서드의 "Lighting+'이름'"의 이름은 일치해야한다.

이어서 2pass를 사용해보자. 두개의 쉐이더를 동시에 사용하는 것이다.
Shader "Custom/Skeleton"
{
Properties
{
_MainTex("Albedo (RGB)", 2D) = "white" {}
_Color("Color", Color) = (0,0,0,0)
}
SubShader
{
Tags { "RenderType" = "Opaque"}
Cull Front
CGPROGRAM
#pragma surface surf _NoLight vertex:Vert noshadow noambient
sampler2D _MainTex;
float4 _Color;
void Vert(inout appdata_full v)
{
v.vertex.xyz += v.normal.xyz * 0.001f;
}
struct Input
{
float2 uv_MainTex;
};
void surf(Input IN, inout SurfaceOutput o)
{
}
float4 Lighting_NoLight(SurfaceOutput s, float3 lightdir, float atten)
{
float4 result;
result = _Color;
return result;
}
ENDCG
Cull Back
CGPROGRAM
#pragma surface surf Lambert
sampler2D _MainTex;
struct Input
{
float2 uv_MainTex;
};
void surf(Input IN, inout SurfaceOutput o)
{
float4 c = tex2D(_MainTex, IN.uv_MainTex);
o.Albedo = c.rgb;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
- 2pass를 사용할 때 주의점은
- 1. CGPROGRAM과 ENDCG로 pass가 끝나는 지점을 명확히 설정해야하며
- 2. Culling을 이용하여 어떤 쉐이더가 어떤식으로 출력이 될건지 순서를 정해주어야 한다.
- 3. 렌더타입과 커스텀프로퍼티는 1pass에서 한 번만 선언해도 된다.
- 위 코드에서는 1pass에서는 커스텀 라이트를 이용하여 외곽선을 출력하였고
- 2pass에서는 본체의 텍스쳐를 표현했다.


이번엔 Hologram을 만들어보자. 무기에 적용시킬것이다.

Shader "Custom/Sword"
{
Properties
{
_MainTex("Albedo (RGB)", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType" = "Opaque" }
CGPROGRAM
#pragma surface surf Standard fullforwardshadows
sampler2D _MainTex;
struct Input
{
float2 uv_MainTex;
};
void surf(Input IN, inout SurfaceOutputStandard o)
{
fixed4 c = tex2D(_MainTex, IN.uv_MainTex);
o.Albedo = c.rgb;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
- 앞선 글들과 마찬가지로 Material을 만들고 Shader를 적용시킨 뒤 해당 Material을 무기에 적용시켜준다.
- 그리고 텍스쳐 한장만 받게 만들고 필요없는 코드를 모두 지운다.
이제 반투명하게 구현해보자.


- 렌더타입, 큐 = transparent로 설정해준다.
- surf의 inout을 SurfaceOutput으로 변경해준다.
- alpha:fade적용 및 환경광을 제거한다.
- 모두 완료됐다면 오른쪽과 같이 투명하게 보인다.


- Albedo(색깔)을 제거해주자.
- 이어서 카메라 시야각(Vector3)을 사용하기 위해 Input안에 viewDir을 선언해준다.
- 그리고 rim을 구해준다.
- 구한 rim을 제곱식을 이용하여 자연스러운 효과를 연출해준다.

Shader "Custom/Sword"
{
Properties
{
_MainTex("Albedo (RGB)", 2D) = "white" {}
_Color("Color", Color) = (0,0,0,0)
}
SubShader
{
Tags { "RenderType" = "Transparent" "Queue" = "Transparent"}
CGPROGRAM
#pragma surface surf Lambert alpha:fade noambient
sampler2D _MainTex;
float4 _Color;
struct Input
{
float2 uv_MainTex;
float3 viewDir;
};
void surf(Input IN, inout SurfaceOutput o)
{
fixed4 c = tex2D(_MainTex, IN.uv_MainTex);
float rim = saturate(dot(o.Normal, IN.viewDir));
rim = pow(1 - rim, 3);
o.Emission = _Color.rgb;
o.Alpha = rim;
}
ENDCG
}
FallBack "Diffuse"
}
- 해당 칼에 색을 입히고 싶다면 Albedo나 Emission을 사용해주면 된다. => _Color를 추가했음



- frac은 소수점 이하를 반환해주는 함수이다.
- 그리고 rim에 월드좌표 일부와 시간값을 사용하여 frac시키면 새로운 효과를 줄 수 있다.