(유니티 빌트인 렌더 파이프라인 - Vertex&Fragment 및 Surface 셰이더 사용)
개요
유령 캐릭터를 만들면서, 캐릭터를 조금 더 '유령답게' 만들어주기 위해서 유령의 끝 부분을 그라디언트를 적용해 투명하게 하거나, 색을 그라데이션으로 적용할 수 있게 셰이더를 작업해야 했습니다. 다만 중요한 점은 '가볍게' 만들기였습니다.
회사 분께 조언을 받았는데, 방법은 크게 두가지로 정리되었어요.
- 캐릭터를 정면 프로젝션한 별도 UV 채널을 추가해서, 해당 UV를 기반으로 그라데이션을 만드는 방법
- 버텍스 데이터의 y좌표값을 활용해서 버텍스 컬러에 그라데이션을 적용하는 방법
'가볍게'라는 중점에 맞게, 별도 UV채널을 사용해 연산하는 첫 번째 방식보다는,
UV채널을 추가하지 않고, 버텍스 셰이더에서 연산해주는 두 번째 방식으로 진행하기로 결정했습니다.
문제는 맨날 픽셀 셰이더만 만졌지 버텍스 셰이더를 작성해본 적은 없다는 거였는데...
버텍스 좌표 시각화
일단 버텍스의 위치 값에 어떻게 접근할 수 있는지 체크하고, 버텍스 y 위치를 시각화 할 수 있는지 간단하게 버텍스 프래그먼트 셰이더를 통해 슬라이더 값보다 버텍스의 y좌표값이 낮으면 검정색으로 표현되도록 해 확인했습니다.
Shader "Custom/Sample_VertFrag"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_ChangePoint ("Point for vertex color", Range(-1,1)) = 0 // 버텍스 컬러를 설정해주는 기준점
}
SubShader
{
Tags { "RenderType"="Opaque" }
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
fixed4 color : COLOR; // Color 추가
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
fixed4 color : COLOR; // Color 추가
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
float _ChangePoint;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.color = v.vertex.y > _ChangePoint;
// 버텍스 좌표의 y값이 _ChangePoint 보다 클 경우 버텍스의 색상을 하얀색,
// 아닐 경우엔 검정색으로 설정
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv);
col = i.color; // 최종 색상값을 버텍스 컬러로 대체
return col;
}
ENDCG
}
}
}
아래 유니티 매뉴얼 내용을 참고하며 작성했습니다!
버텍스 프로그램에 버텍스 데이터 제공하기 - Unity 매뉴얼
Cg/HLSL 버텍스 프로그램에서 메시 버텍스 데이터는 버텍스 셰이더 함수에 입력으로 전달됩니다. 각 입력에는 입력에 대해 지정된 시맨틱이 있어야 합니다. 예를 들어, POSITION 입력은 버텍스 포지
docs.unity3d.com
버텍스 데이터 시각화 - Unity 매뉴얼
빌트인 렌더 파이프라인에 대한 예제 셰이더는 버텍스 데이터를 시각화하는 다양한 방법을 보여줍니다.
docs.unity3d.com
버텍스 좌표 기반 그라디언트 생성 및 Surface 셰이더로 코드 옮기기
버텍스 위치를 시각화할 수 있다는 걸 확인했으니, 단순하게 그라디언트 색이 적용될 버텍스의 버텍스 컬러에 그라데이션 색상 범위에서 어디에 위치해주었는지 그 색상 값을 넣어주면 그라데이션을 만들 수 있을 거라고 생각했습니다.
그리고, 그라데이션이 시작하는 지점과 끝나는 지점을 프로퍼티로 선언해 그라데이션이 적용되는 범위를 조절할 수 있게 하면 됩니다.
// Vertex Gradient Shader
fixed4 _Color;
fixed4 _StartColor;
float _StartPos;
float _EndPos;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
float interpolValue;
float range = _EndPos - _StartPos;
interpolValue = clamp((_EndPos - v.vertex.y) / range, 0, 1);
// 버텍스가 그라디언트 상에서 어디에 위치하고 있는지를 구하고,
// clamp 로 값이 0과 1을 벗어나지 않도록 고정
o.color = lerp(_StartColor, _Color, interpolValue);
// 버텍스 컬러에 그라디언트 상의 위치에 맞게 색상을 적용
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
버텍스 좌표를 기반으로 하는 부드러운 그라데이션이 만들어졌습니다! 🎉
버텍스들 사이의 픽셀 색상들은 래스터라이저에 의해 버텍스 컬러 값을 기준으로 보간되어 적용됩니다.
정상 동작을 확인했으니, 라이팅을 쉽게 적용할 수 있게 서페이스 셰이더로 옮겨줍니다.
이 과정에서, 서페이스 내부에 버텍스 셰이더를 사용한다고 선언해주고, 구조체에 컬러 변수를 추가해줍니다.
Shader "Custom/Surface_VertexGradientShader"
{
Properties
{
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_Glossiness ("Smoothness", Range(0,1)) = 0.5
_Metallic ("Metallic", Range(0,1)) = 0.0
// 프로퍼티 추가
[Space]
[Header(Gradation Option)]
[Space]
_StartColor ("Gradation Start Color", Color) = (1,1,1,1)
_EndColor ("Gradation End Color", Color) = (1,1,1,1)
_StartPos ("Gradation Start Position", Range(-1,1)) = 0
_EndPos ("Gradation End Position", Range(-1,1)) = 0
}
SubShader
{
Tags { "RenderType"="Transparent" "Queue"="Transparent"}
Blend SrcAlpha OneMinusSrcAlpha
// RenderType / RenderQueue / Blend 추가 및 변경
CGPROGRAM
#pragma surface surf Standard vertex:vert alpha:blend
// 버텍스 셰이더 사용을 위해 vertex:vert 구문 추가
// 알파값이 적용되도록 alpha:blend 구문 추가
#pragma target 3.0
sampler2D _MainTex;
struct Input
{
float2 uv_MainTex;
float4 color : COLOR; // color 변수 추가
};
// Vertex Gradient Shader
half _StartPos;
half _EndPos;
fixed4 _StartColor;
fixed4 _EndColor;
void vert (inout appdata_full v)
{
float interpolValue;
float range = _EndPos - _StartPos;
interpolValue = clamp((_EndPos - v.vertex.y) / range, 0, 1);
v.color = lerp(_EndColor, _StartColor, interpolValue);
}
// Vertex Gradient Shader End
half _Glossiness;
half _Metallic;
UNITY_INSTANCING_BUFFER_START(Props)
UNITY_INSTANCING_BUFFER_END(Props)
void surf (Input IN, inout SurfaceOutputStandard o)
{
fixed4 c = tex2D (_MainTex, IN.uv_MainTex);
o.Albedo = c.rgb * IN.color.rgb; // 버텍스 컬러의 rgb값 적용
o.Metallic = _Metallic;
o.Smoothness = _Glossiness;
o.Alpha = c.a * IN.color.a; // 버텍스 컬러의 알파값 적용
}
ENDCG
}
FallBack "Diffuse"
}
작성된 셰이더를 유령 캐릭터에 적용해주면, 글의 초반부에 있던 하단 부분이 반투명한 무서운 유령이 완성됩니다! 👻
GitHub - rkato0128/ShaderStudy_Unity
Contribute to rkato0128/ShaderStudy_Unity development by creating an account on GitHub.
github.com
'Graphics > Unity' 카테고리의 다른 글
Chat GPT로 유니티 셰이더 만들기 (0) | 2023.02.20 |
---|---|
사각형 패턴 셰이더 만들기 (0) | 2023.01.11 |