이전에는 SDF를 이용해서 간단한 폰트 출력을 해보았으니 이번에는 셰이더를 이용해서 글자에 다양한 효과들을 적용시켜 보려고 한다.
물론 그냥 만들어진 텍스쳐 그대로 출력해도 되긴 하지만
기왕이면 글자의 두께와 색상 등등도 커스텀 가능하게 하고 다양한 효과들도 적용되는것이 좋으니 한번 만들어 보려고 한다.
1. SoftEdge
우선 첫번째는 기본적인 폰트 출력이다.
PS_OUTPUT SoftEdge(VS_OUTPUT In)
{
PS_OUTPUT Out;
float4 color = float4(0, 0, 0, 0);
float alpha = tex2D(_FontSampler, In.TexCoord0).a;
float Thickness = clamp(1 - _FontWidth, 0, 1);
float t = alpha / Thickness;
t = t * t * t;
t = clamp(t, 0.0, 1.0);
color = lerp(float4(0, 0, 0, 0), _baseColor, t);
Out.Color = color;
Out.EmissiveColor = float4(0, 0, 0, color.a);
return Out;
}
우선 현재 내가 사용하고 있는 SDF폰트 텍스쳐는 글자 중심의 알파값이 1이고 글자 중심에서 외곽으로 멀어질수록 알파값이 0에 가까워지며 점점 옅어지는 형식이다.
따라서 해당 알파값에 글자 두께(Thickness)를 나눠주고 해당 값을 0~1값으로 클램프 해주면
글자 중심에서 Thickness값 까지는 알파값이 1이 되고 Thickness값에서 멀어질수록 점점 알파값이 0에 가까워지게 된다.
이제 해당 값을 이용해서 설정된 폰트 색상을 적절히 설정해주면 완성이다.
3. Outline
PS_OUTPUT OutlineDraw(VS_OUTPUT In)
{
PS_OUTPUT Out;
float4 color = float4(0, 0, 0, 0);
float alpha = tex2D(_FontSampler, In.TexCoord0).a;
float d = alpha;
float fontWidth = clamp(1 - _FontWidth, 0, 1);
float outlineWidth = clamp(1 - _OutlineWidth, 0, 1);
float totalWidth = clamp(1 - (_FontWidth + _OutlineWidth), 0, 1);
if (d < totalWidth)
{
float t = d / (totalWidth);
t = t * t * t * t;
color = lerp(float4(0, 0, 0, 0), _borderColor, t);
}
else if (d < fontWidth)
{
float t = d / (fontWidth);
t = t * t * t * t;
color = lerp(_borderColor, _baseColor, t);
}
else
{
color = _baseColor;
}
Out.Color = color;
Out.EmissiveColor = float4(0, 0, 0, color.a);
return Out;
}
아웃라인 출력에서 글자의 총 두께는 글자 두께 + 외곽선 두께 이렇게 계산되어지고 그냥 기본 출력과 다르게 3가지 구역으로 나눠서 출력을 해준다.
아웃라인 없이 온전히 글자만 그려지는 안쪽영역, 글자에서 아웃라인으로 넘어가는 부분, 나머지 아웃라인을 그려주는 부분 이렇게 색상이 변화하면서 부드럽게 보간이 필요한 부분에 따라서 3가지 영역으로 나눠서 출력해주게 된다.
해당 부분들을 제외한 나머지 부분들은 위에서 설명했던 기본 폰트 출력과 같은 방식으로 출력해주기만 하면 된다.
5. Neon
PS_OUTPUT NeonDraw(VS_OUTPUT In)
{
PS_OUTPUT Out;
float4 color = float4(0, 0, 0, 0);
float d = tex2D(_FontSampler, In.TexCoord0).a - clamp(1 - (_FontWidth + 0.2), 0, 1);
if (d > -_BorderWidth && d < _BorderWidth)
{
float t = d / _BorderWidth; //[-1:0:1]
t = 1 - abs(t); //[0:1:0]
color = lerp(float4(0, 0, 0, 0), _borderColor, t);
color.rgb += pow(t, _NeonPower) * _NeonBrightness;
}
color.a = color.a * _baseColor.a;
Out.Color = color;
Out.EmissiveColor = float4(0, 0, 0, color.a);
return Out;
}
위 셰이더는 마치 네온사인 같은 결과를 보여준다.
해당 효과를 만들기 위해서는 일단 글자의 알파값에서 _FontWidth 값을 빼준다.
그러면 글자가 끝나는 부분의 알파값이 0이 되고 글자 안쪽이 양수값 글자 바깥쪽이 음수값이 되게 된다.
그러면 해당 값에 abs 연산을 해주고 One Minus 연산을 해주면 글자가 끝나는 부분의 알파값이 자연스럽게 0~1~0
이렇게 바뀌게 된다.
그러곤 원하는 글자 색상을 입혀주고 더 밝게 빛나는 것처럼 보이게 하기 위해서 밝기를 적당히 조절해주면 완성이다.
6. DropShadow
PS_OUTPUT NewDropShadowFrag(VS_OUTPUT In)
{
PS_OUTPUT Out;
float4 color = float4(0, 0, 0, 0);
float d = tex2D(_FontSampler, In.TexCoord0).a;
float d2 = tex2D(_FontSampler, In.TexCoord0 + _ShadowDist * _MainTex_TexelSize.xy).a;
float Thickness = clamp(1 - _FontWidth, 0, 1);
float fill_t = saturate((d) / Thickness);
fill_t = fill_t * fill_t * fill_t;
float shadow_t = saturate((d2) / Thickness);
shadow_t = shadow_t * shadow_t * shadow_t;
color = lerp(color, _borderColor, shadow_t);
color = lerp(color, _baseColor, fill_t);
color.a = color.a * _baseColor.a;
Out.Color = color;
Out.EmissiveColor = float4(0, 0, 0, color.a);
return Out;
}
그림자 출력도 간단하게 출력이 가능하다.
그저 기본 텍스쳐와 기본 텍스쳐에서 _ShadowDist만큼 이동시킨 텍스쳐 이렇게 두가지의 알파값을 가지고
기본 폰트 출력과 같은 방법으로 두번 그려주면 간단하게 출력이 가능하다.
'회사에서 살아남기' 카테고리의 다른 글
SDFFont 사용하기 (4) (0) | 2023.11.02 |
---|---|
SDFFont 사용하기 (3) (0) | 2023.10.31 |
SDFFont 사용하기 (2) (0) | 2023.10.31 |
SDFFont 사용하기 (1) (0) | 2023.10.31 |