先看效果:
大致思路:先绘制矩形,旋转UV达到转动效果,极坐标转换绘制刻度。
graph节点:
着色器代码:
Shader "CustomURP/TimeText"
{
Properties
{
_Secondsdeg("Secondsdeg",float) = 0
_Minutesg("Minutesg",float) = 0
_Hourdeg("Hourdeg",float) = 0
}
SubShader
{
tags{"RenderType"="Opaque" "RenderPipeline"="UniversalPipeline"}
Pass
{
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
struct Attributes
{
float3 positionOS:POSITION;
half2 uv:TEXCOORD0;
};
struct Varyings
{
float4 positionHCS:SV_POSITION;
half2 uv:TEXCOORD0;
};
CBUFFER_START(UnityPerMaterial)
float _Secondsdeg;
float _Minutesg;
float _Hourdeg;
CBUFFER_END
void Unity_Rotate_Radians_float(float2 UV, float Rotation, out float2 Out) //旋转
{
float2 Center = float2(.5, .5);
UV -= Center;
float s = sin(Rotation);
float c = cos(Rotation);
float2x2 rMatrix = float2x2(c, -s, s, c);
rMatrix *= 0.5;
rMatrix += 0.5;
rMatrix = rMatrix * 2 - 1;
UV.xy = mul(UV.xy, rMatrix);
UV += Center;
Out = UV;
}
void Unity_RoundedRectangle_float(float2 UV, float Width, float Height, out float Out) //矩形绘制
{
float Radius = max(min(min(2, abs(Width)), abs(Height)), 1e-5);
float2 uv = abs(UV * 2 - 1) - float2(Width, Height) + Radius;
float d = length(max(0, uv)) / Radius;
Out = saturate((1 - d) / fwidth(d));
}
void Unity_PolarCoordinates_float(float2 UV, float2 Center, float RadialScale, out float2 Out) //极坐标转换
{
float2 delta = UV - Center;
float radius = length(delta) * 2 * RadialScale;
float angle = atan2(delta.x, delta.y) * 1.0/6.28;
Out = float2(radius, angle);
}
void Unity_DrawPointer_float(float2 UV, float Rotate,float Width, float Height, float Step, out float Out) //指针绘制
{
float mask;
float rot = -2 * frac(Rotate) * 3.14;
Unity_Rotate_Radians_float(UV,rot,UV);
Unity_RoundedRectangle_float(UV,Width,Height,mask);
Out = mask * step(Step, UV.y);
}
void Unity_DrawTimeScale_float(float2 UV, float RadialScale, float Partition, float2 Scale, out float Out) //刻度绘制
{
float mask,mask1,mask2;
Unity_PolarCoordinates_float(UV,float2(0.5,0.5),RadialScale,UV);
Unity_RoundedRectangle_float(UV,Scale.y,3,mask);
mask1 = frac(UV.y * Partition);
mask2 = step(mask1,Scale.x);
mask1 = step((1-mask1),Scale.x);
mask *= mask1 + mask2;
Out = mask;
}
Varyings vert(Attributes IN)
{
Varyings o;
o.positionHCS = TransformObjectToHClip(IN.positionOS.xyz);
o.uv = IN.uv;
return o;
}
half4 frag(Varyings IN):SV_Target
{
//指针绘制
float secondsdeg,minutesg,hourdeg;
//秒针
Unity_DrawPointer_float(IN.uv,_Secondsdeg,0.01,0.8,0.41,secondsdeg);
//分针
Unity_DrawPointer_float(IN.uv,_Minutesg,0.02,0.65,0.46,minutesg);
//时针
Unity_DrawPointer_float(IN.uv,_Hourdeg,0.031,0.3,0.46,hourdeg);
//刻度绘制
float longpartition,minipartition;
//大刻度
Unity_DrawTimeScale_float(IN.uv,0.56,12,float2(0.05,0.05),longpartition);
//小刻度
Unity_DrawTimeScale_float(IN.uv,0.56,60,float2(0.05,0.05),minipartition);
return saturate(secondsdeg + minutesg + hourdeg + longpartition + minipartition * 0.5);
}
ENDHLSL
}
}
}
时间传递代码:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Clockcode : MonoBehaviour
{
[SerializeField]
bool SecondRun;
TimeSpan time;
float hourdeg, minutesg, secondsdeg;
Material material;
void Awake()
{
time = DateTime.Now.TimeOfDay;
hourdeg = (float)time.TotalHours / 12f;
minutesg = (float)time.TotalMinutes / 60f;
if (SecondRun)
{
secondsdeg = (float)time.TotalSeconds / 60f;
}
else
{
secondsdeg = DateTime.Now.Second / 60f;
}
material.SetFloat("_Secondsdeg", secondsdeg);
material.SetFloat("_Minutesg", minutesg);
material.SetFloat("_Hourdeg", hourdeg);
}
// Start is called before the first frame update
void Start()
{
material = GetComponent<Renderer>().material;
}
// Update is called once per frame
void Update()
{
Debug.Log(DateTime.Now.Hour + ":" + DateTime.Now.Minute + ":" + DateTime.Now.Second);
Awake();
}
}