일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- ColorGradingLutPass
- 프로그래밍 기초
- 벡터
- Specular
- Virtual Byte
- 메모리 누수
- Windows Build
- 개인 바이트
- Three(Two) Tone Shading
- C언어
- AppSW
- OculusMotionVectorPass
- Cell Look
- 작업 집합
- 게임 수학
- URP로 변경
- ASW(Application SpaceWarp)
- 가상 바이트
- Rim Light
- Private Bytes
- 3d
- Cell Shader
- VR
- Toon Shader
- Cartoon Rendering
- URP
- working set
- Today
- Total
WinCNT
Fill Amount 기능이 있는 간단 Bar Gauge UI 셰이더 만들어보기! 본문
서론
매우 슬프게도 VR에서는 Canvas나 관련 컴포넌트(Image 등)의 성능이 좀 많이 떨어진다
하지만 UI가 없는 건 아니라 열심히 구현해야 한다는 게 또 힘든 점
아무튼 이번에는 HP Bar 등의 Gauge UI!
Alpha Test를 이용해서 일반적인 Qaud에 Gauge UI 셰이더를 만들어봤기에 정리해보고자 한다
Bar Gauge UI Shader의 목표
여기서 Bar Gauge란 HP 같은 상하, 혹은 좌우로 움직이는 UI를 말한다
이번 태스크의 목표는 머티리얼의 Fill Amount란 값을 조정하는 것만으로 움직이게 하는 것였다
일단 다음과 같이 Bar Gauge의 Backgound가 있고, 조정된 위치에 Bar Gauge의 텍스처도 있기 때문에 별 다른 위치 조정도 하지 않는 것도 중요했다
Bar Gauge UI Shader의 샘플
우선 샘플부터!
Shader "CustomUI/BarGauge"
{
Properties
{
[Header(Base Settings)][Space(5)]
_BaseMap ("Base Map", 2D) = "white" { }
_BaseColor("Base Color", Color) = (1,1,1,1)
_Cutoff ("Cutoff", Range(0.0, 1.0)) = 0.5
[Header(Gauge Settings)][Space(5)]
_FillAmount ("Fill Amount", Range(0, 1)) = 1.0
[Toggle] _Reverse ("Reverse", float) = 0
[Toggle] _UpDown ("Up-Down", float) = 0
_FillStart ("Fill Start", Range(0, 1)) = 0
_FillEnd ("Fill End", Range(0, 1)) = 1
[Header(Advanced Settings)][Space(5)]
[HideInInspector][Toggle] _ALPHATEST ("Alpha Test", float) = 1.0
[Enum(UnityEngine.Rendering.CullMode)] _CullMode ("Cull Mode", Float) = 2 // Back
[Enum(UnityEngine.Rendering.CompareFunction)] _ZTest("ZTest", Float) = 4 // LEqual
[Enum(Off, 0, On, 1)] _ZWrite("ZWrite", Float) = 0 // Off
}
SubShader
{
Tags
{
"RenderType" = "Opaque"
"RenderPipeline" = "UniversalPipeline"
}
Pass
{
Name "Universal Forward"
Tags
{
"LightMode" = "UniversalForward"
}
Cull [_CullMode]
ZTest [_ZTest]
ZWrite [_ZWrite]
AlphaToMask On
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma shader_feature_local_fragment _ALPHATEST_ON
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
TEXTURE2D(_BaseMap);
SAMPLER(sampler_BaseMap);
CBUFFER_START(UnityPerMaterial)
half4 _BaseColor;
float _FillAmount;
float _Reverse;
float _UpDown;
float _FillStart;
float _FillEnd;
half _Cutoff;
float4 _BaseMap_ST;
CBUFFER_END
struct Attributes
{
float4 positionOS : POSITION;
float2 UV : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct Varyings
{
float4 PositionHCS : SV_POSITION;
float2 UV : TEXCOORD0;
float2 GaugeUV : TEXCOORD1;
UNITY_VERTEX_INPUT_INSTANCE_ID
UNITY_VERTEX_OUTPUT_STEREO
};
Varyings vert(Attributes IN)
{
Varyings OUT;
ZERO_INITIALIZE(Varyings, OUT);
UNITY_SETUP_INSTANCE_ID(IN);
UNITY_TRANSFER_INSTANCE_ID(IN, OUT);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);
OUT.PositionHCS = TransformObjectToHClip(IN.positionOS.xyz);
OUT.UV = TRANSFORM_TEX(IN.UV, _BaseMap);
// Fill Ammount
// Remap 0~1 => Start~End
_FillAmount = _FillStart + _FillAmount * (_FillEnd - _FillStart);
OUT.GaugeUV = lerp(
-IN.UV + _FillAmount,
IN.UV - (1.0 - _FillAmount),
_Reverse
);
return OUT;
}
half4 frag(Varyings IN) : SV_Target
{
UNITY_SETUP_INSTANCE_ID(IN);
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(IN);
half4 outColor = half4(0.0, 0.0, 0.0, 1.0);
const half4 baseTex = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, IN.UV);
outColor.rgb = baseTex.rgb * _BaseColor.rgb;
outColor.a = AlphaDiscard(baseTex.a, _Cutoff);
clip(lerp(IN.GaugeUV.x, IN.GaugeUV.y, _UpDown));
return outColor;
}
ENDHLSL
}
}
FallBack "Hidden/Universal Render Pipeline/FallbackError"
}
Bar Gauge UI Shader에 대략적인 설명
사실 기본적인 방식은 Fill Amount 값에 맞춰서 Alpha Test을 하면 된다
여기서 궁리한 것은 HP Bar 텍스처의 빈 공간(위치 조정을 안 하기 위해 어쩔 수 없는)을 어떻게 처리할까 정도이다
이리저리 삽질한 결과, Start와 End 값을 받아서 Fill Amount를 Remapping하니 잘 작동했다
그리고 처음에는 모두 프래그먼트 셰이더에 구현했지만, 최적화를 위해 대부분의 계산을 버텍스 셰이더로 옮겼다
그 외에는 lerp를 이용해서 Fill Amount의 방향을 반전시키거나(_Reverse) 상하/좌우를 바꾸는(_UpDown) 것도 가능하게 했다
결과
아무튼 짜잔~!
마무리
이걸로 태스크 끝!
이라고 생각했던 시기가 저에게도 있었습니다…
잘 보니 업무 중에는 타이머 같이 한바퀴 도는 UI도 있었다
흑흑…이건 완전히 다른 방식을 취해야 할 거 같은데…
이건 이어서 다른 글에서 정리해보고자 한다
참고 사이트
이번엔 딱히 없는 듯?
'Unity > URP or Shader 관련' 카테고리의 다른 글
Alpha 값으로 Blue Noise를 이용한 Dither를 해보자! (0) | 2024.06.24 |
---|---|
Fill Amount 기능이 있는 간단(?) Dial Gauge UI(가칭) 셰이더 만들어보기! (1) | 2024.06.16 |
Vignette를 불투명 Mesh와 반투명 Mesh로 나눠서 구현해보자! (0) | 2024.04.08 |
URP에서 간단하게 Stencil Buffer를 사용해서 Magic Card 만들어보기! (0) | 2024.03.13 |
URP에서 Additional Lights(Point Light, Spot Light) 적용해보기! (0) | 2024.03.06 |