Unity가 곡선 진행률 표시줄을 생성합니다.

Unity가 곡선 진행률 표시줄을 생성합니다.

  안녕하세요 여러분, 제 이름은 A Zhao입니다.
  Unity 엔진을 사용하여 진행바를 만들다가 가끔 문제가 발생하는데, 진행바가 단순한 가로, 세로, 원형이 아닌 임의의 불규칙한 모양이라면 어떻게 해야 할까요? 예를 들어:
여기에 이미지 설명을 삽입하세요.

1. 생산방법

1. 준비물

  이 진행률 표시줄의 원리는 매우 간단하며, 이 경로를 따라 회색조를 변경하는 그림이 필요합니다. 이 그림은 아마도 다음과 같을 것입니다.
여기에 이미지 설명을 삽입하세요.
여기에 이미지 설명을 삽입하세요.

  여기서는 RGB 채널을 회색조로 사용하고 알파 채널을 표시 범위로 사용했습니다. 함께 결합하면 Unity의 그림은 다음과 같습니다.
여기에 이미지 설명을 삽입하세요.

  물론 사진을 사용하는 다른 방법도 있습니다. 예를 들어 진행률 표시줄에 그라데이션 색상이나 텍스처를 표시하려는 경우 사진의 RGB 채널을 텍스처 사진으로 사용한 다음 알파 채널을 사용할 수 있습니다. 결국 그레이스케일 변경은 하나의 채널만 사용하면 충분하므로 세 개의 RGB 채널을 사용할 필요가 없습니다.

2. 계산과정

목적:
1. UI에서 사용할 수 있습니다.
2. 이미지의 이미지를 입력으로 사용합니다.
3. 이미지 색상의 RGB 채널을 진행률 표시줄의 색상으로 사용합니다.
4. 이미지 색상의 A 채널을 사용합니다. 진행률 표시줄 표시의 진행률 컨트롤 이미지
여기에 이미지 설명을 삽입하세요.

  색상 계산은 매우 간단합니다. 정점 색상의 RGB를 직접 가져오면 됩니다. 순수한 RGB 색상이 보기에 좋지 않다고 생각되면 디스플레이용으로 다른 색상의 사진을 만들 수도 있습니다.
  다음은 진행률 표시줄을 마스킹하는 효과입니다. 여기서는 이미지의 RGB 색상의 회색조 그라데이션을 직접 사용했기 때문에 먼저 RGB 회색조를 사용했습니다. 위에서 언급한 것처럼 RGB 색상을 사용하여 패턴화된 진행률 표시줄 그림을 만들려면 이 진행에 실제로 RGB 색상 대신 RGB 색상을 사용할 수 있으며 그림의 알파 채널을 회색조로 사용할 수도 있습니다.
여기에 이미지 설명을 삽입하세요.여기에 이미지 설명을 삽입하세요.

  무슨 일이 있어도 이미지의 회색조 값을 얻은 다음 진행 상황을 제어하려는 값을 입력하고 이 값과 회색조 값을 사용하여 뺄셈을 수행한 다음 단계 기능을 사용하여 표시 범위를 제어합니다. 전환 지점에서 그라데이션 효과를 원할 경우 SmoothStep 기능을 사용할 수 있습니다. 경로를 따라 회색조 그라데이션이 적용되므로 입력 값이 변경되면 표시 범위가 회색조 경로를 따라 변경됩니다.
  마지막으로 Step의 결과를 표시할 RGB 색상과 결합하여 표시된 Alpha 값으로 사용하여 진행률 표시줄의 최종 표시 색상과 범위를 얻습니다.

3. 그레이스케일 그라디언트 맵 제작

  이 방법의 어려움은 셰이더를 쓰는 것이 아니라 재료를 제작하는 것입니다.
  이 이미지를 생성하기 위해 3D 방법을 사용했습니다. 먼저 패치를 생성하고 수평 세그먼트 수를 1000으로 설정했습니다.
여기에 이미지 설명을 삽입하세요.

  그런 다음 UV를 확장하면 패치의 가장 왼쪽 u 좌표는 0이고 가장 오른쪽 u 좌표는 1입니다. 그런 다음 왼쪽에서 오른쪽으로 그라디언트 맵을 만듭니다. 패치에 그라디언트 맵을 할당합니다.
여기에 이미지 설명을 삽입하세요.

  마지막으로 경로 변형을 통해 패치가 경로를 따라 늘어져 모양을 얻습니다.
여기에 이미지 설명을 삽입하세요.

마지막으로 이 모델을 렌더링한 후 위의 그래디언트 회색조 이미지를 얻습니다.

  이렇게 하면 균일하게 분포된 회색조 이미지를 거의 얻을 수 없지만 100% 정확하지는 않습니다. 예를 들어, 진행률 표시줄에 눈금을 그린 다음 백분율을 입력하려고 하는데 이미지의 회색조가 해당 백분율에 도달하는 경우와 같이 백분율 변화와 완전히 일치하는 회색조 이미지를 얻으려면 다음을 수행해야 합니다. 이 이미지를 만드는 다른 방법을 생각해 보세요.

3. 셰이더 소스 코드

Shader "azhao/CurveProgress"
{
    
    
	Properties
	{
    
    
		[PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {
    
    }
		_Color ("Tint", Color) = (1,1,1,1)
		
		_StencilComp ("Stencil Comparison", Float) = 8
		_Stencil ("Stencil ID", Float) = 0
		_StencilOp ("Stencil Operation", Float) = 0
		_StencilWriteMask ("Stencil Write Mask", Float) = 255
		_StencilReadMask ("Stencil Read Mask", Float) = 255

		_ColorMask ("Color Mask", Float) = 15

		[Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip ("Use Alpha Clip", Float) = 0
		_min("min", Range( -1 , 1)) = 0
		_max("max", Range( 0 , 1)) = 1
		[HideInInspector] _texcoord( "", 2D ) = "white" {
    
    }

	}

	SubShader
	{
    
    
		LOD 0

		Tags {
    
     "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "PreviewType"="Plane" "CanUseSpriteAtlas"="True" }
		
		Stencil
		{
    
    
			Ref [_Stencil]
			ReadMask [_StencilReadMask]
			WriteMask [_StencilWriteMask]
			CompFront [_StencilComp]
			PassFront [_StencilOp]
			FailFront Keep
			ZFailFront Keep
			CompBack Always
			PassBack Keep
			FailBack Keep
			ZFailBack Keep
		}


		Cull Off
		Lighting Off
		ZWrite Off
		ZTest [unity_GUIZTestMode]
		Blend SrcAlpha OneMinusSrcAlpha
		ColorMask [_ColorMask]

		
		Pass
		{
    
    
			Name "Default"
		CGPROGRAM
			
			#pragma vertex vert
			#pragma fragment frag
			#pragma target 3.0

			#include "UnityCG.cginc"
			#include "UnityUI.cginc"

			#pragma multi_compile __ UNITY_UI_CLIP_RECT
			#pragma multi_compile __ UNITY_UI_ALPHACLIP
			
			#define ASE_NEEDS_FRAG_COLOR

			
			struct appdata_t
			{
    
    
				float4 vertex   : POSITION;
				float4 color    : COLOR;
				float2 texcoord : TEXCOORD0;
				UNITY_VERTEX_INPUT_INSTANCE_ID
				
			};

			struct v2f
			{
    
    
				float4 vertex   : SV_POSITION;
				fixed4 color    : COLOR;
				half2 texcoord  : TEXCOORD0;
				float4 worldPosition : TEXCOORD1;
				UNITY_VERTEX_INPUT_INSTANCE_ID
				UNITY_VERTEX_OUTPUT_STEREO
				
			};
			
			uniform fixed4 _Color;
			uniform fixed4 _TextureSampleAdd;
			uniform float4 _ClipRect;
			uniform sampler2D _MainTex;
			uniform float4 _MainTex_ST;
			uniform float _min;
			uniform float _max;

			
			v2f vert( appdata_t IN  )
			{
    
    
				v2f OUT;
				UNITY_SETUP_INSTANCE_ID( IN );
                UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);
				UNITY_TRANSFER_INSTANCE_ID(IN, OUT);
				OUT.worldPosition = IN.vertex;
				
				
				OUT.worldPosition.xyz +=  float3( 0, 0, 0 ) ;
				OUT.vertex = UnityObjectToClipPos(OUT.worldPosition);

				OUT.texcoord = IN.texcoord;
				
				OUT.color = IN.color * _Color;
				return OUT;
			}

			fixed4 frag(v2f IN  ) : SV_Target
			{
    
    
				float2 uv_MainTex = IN.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
				float4 tex2DNode1 = tex2D( _MainTex, uv_MainTex );
				float grayVal = Luminance(tex2DNode1.rgb);
				float remapVal = ( grayVal - ( 1.0 - (0.0 + (( IN.color.a + 0.01 ) - 0.0) * (( _max + 1.0 ) - 0.0) / (1.0 - 0.0)) ) );
				float smoothstepVal = smoothstep( _min , _max , remapVal);
				float4 color = (float4(IN.color.r , IN.color.g , IN.color.b , ( tex2DNode1.a * smoothstepVal )));
				
			
				#ifdef UNITY_UI_CLIP_RECT
                color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect);
                #endif
				
				#ifdef UNITY_UI_ALPHACLIP
				clip (color.a - 0.001);
				#endif

				return color;
			}
		ENDCG
		}
	}
	
	
	
}

추천

출처blog.csdn.net/liweizhao/article/details/133105955