unity shader 繪製鐘錶

1:效果圖如下

 

2:shader代碼如下:

Shader "Unlit/clock"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        hors("hors",int) = 13
        mins("mins",int) = 30
        secs("secs",int) = 30
        mils("mils",int) = 30

    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag


            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;

            int hors;
            int mins;
            int secs;
            int mils;

            float lerpLine(float2 _LP1,float2 _LP2,float2 pos,float width) {
                
                if(dot(pos - _LP1, _LP2- _LP1)>=0)
                {
                    float d = 1;
                    
                    d = abs((_LP2.y - _LP1.y)*pos.x + (_LP1.x - _LP2.x)*pos.y + _LP2.x*_LP1.y - _LP2.y*_LP1.x) / sqrt(pow(_LP2.y - _LP1.y, 2) + pow(_LP1.x - _LP2.x, 2));
                    
                     
                    if (d < width)
                    {
                        return min(1, abs(width - d) / width*2);
                    }
                    else {
                        return 0;
                    }
                }
                else {
                    return 0;
                }
                
            }

            fixed3 backColor(float2 uv)
            {
                fixed3 nightColor = fixed3(0.2, 0.2, 0.2) + 0.1*uv.y;
                fixed3 dayColor = fixed3(0.5, 0.6, 0.7) + 0.2*uv.y;
                fixed3 col = lerp(nightColor, dayColor, smoothstep(5.0, 7.0, hors) -
                    smoothstep(19.0, 21.0, hors));

                return col;
            }

            fixed3 drawCircle(float2 uv,float2 pos,float radio, float radio1,float width, float width1) {
                float dis = distance(uv, pos);

                //時針 分針 秒針
                if (dis >= radio1 + width1)
                {

                    float3 col = lerp(fixed3(0, 0, 0), fixed3(1, 1, 1), min(1, (radio - dis) * 200));

                    int hor = hors % 12;
                    float hor_angle = (90.0 - 30.0 * hor - mins / 600.0) / 57.29578;
                    float min_angle = (90.0 - mins*6 - secs/60.0) / 57.29578;
                    float sec_angle = (90.0 - secs * 6) / 57.29578;

                    if (dis < 0.15)
                    {
                        //時針
                        float lerpV = lerpLine(pos, float2(0.15*cos(hor_angle) + pos.x, 0.15*sin(hor_angle) + pos.y), uv, 0.005);
                        if(lerpV>0)
                            return lerp(col, float3(0, 0, 0), lerpV);
                    }
                    if (dis < 0.25)
                    {
                        //分針
                        float lerpV = lerpLine(pos, float2(0.25*cos(min_angle) + pos.x, 0.25*sin(min_angle) + pos.y), uv, 0.005);
                        if (lerpV > 0)
                            return lerp(col, float3(0, 0, 0), lerpV);
                    }
                    if (dis < 0.35)
                    {
                        //秒針
                        float lerpV = lerpLine(pos, float2(0.35*cos(sec_angle) +  pos.x, 0.35*sin(sec_angle) + pos.y), uv, 0.002);
                        if (lerpV > 0)
                            return lerp(col, float3(1, 0, 0), lerpV);
                    }
                }
                
                if (dis < radio1) {
                    //內圈裏
                    return lerp(fixed3(0, 0, 0),fixed3(0.75, 0.75, 0.75),(radio1 - dis)*500);
                }
                else if(dis< radio1 + width1){
                    //內圈邊
                    return lerp(fixed3(0, 0, 0),fixed3(1, 1, 1),max(0,1/(radio1 + width1 - dis)*0.0008));
                }
                else {

                    float3 col = lerp(fixed3(0, 0, 0), fixed3(1, 1, 1), min(1, (radio - dis) * 200));
                    if (dis <= radio)
                    {
                        //外圈裏
                        if (dis >= radio - 0.08)
                        {
                            //刻度
                            float2 direction = uv - pos;

                            float angle = acos(dot(normalize(direction), float2(1, 0)));
                            float angle_d = angle * 57.29577 % 30;
                            
                            if (angle_d < 0.6 || angle_d>29.4)
                            {
                                //刻度長針
                                if (dis >= radio - 0.06)
                                {
                                    if (angle_d <1)
                                    {
                                        return lerp(col, fixed3(0, 0, 0), min(1, (0.6 - (abs(angle_d))) / 0.5));
                                    }
                                    else {
                                        return lerp(col, fixed3(0, 0, 0), min(1, ((abs(angle_d) - 29.4)) / 0.5));
                                    }
                                }
                                
                                
                            }
                            else {
                                //刻度短針
                                if (dis >= radio - 0.04)
                                {
                                    float angle_d1 = angle * 57.29577 % 6;
                                    if (angle_d1<0.4 || angle_d1>5.6)
                                    {
                                        if (angle_d1 < 0.4)
                                        {
                                            return lerp(col,fixed3(0, 0, 0), min(1, (0.4- angle_d1) / 0.5));
                                        }
                                        else {
                                            return lerp(col,fixed3(0, 0, 0), min(1, (angle_d1 - 5.6) / 0.5));
                                        }
                                        
                                    }
                                }
                                
                            }
                        }
                        
                        
                        return col;
                    }
                    else if (dis >= radio && dis < radio + width)
                    {
                        //外圈邊
                        return fixed3(0, 0, 0);
                    }
                    else {
                        //外圈外
                        return lerp(fixed3(0, 0, 0), backColor(uv), min(1, (dis - radio - width) * 200));
                    }
                }
                
            }

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                // sample the texture
                fixed3 col = drawCircle(i.uv,float2(0.5,0.5),0.4,0.02,0.013,0.01);

                return fixed4(col,0);
            }
            ENDCG
        }
    }
}
 

 

3:unity代碼如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class clock : MonoBehaviour
{
    public Material mat;
    public int Hour = 0;
    public int Minute = 0;
    public int Second = 0;
    // Start is called before the first frame update
    void Start()
    {
        mat.SetInt("hors", Hour);
        mat.SetInt("mins", Minute);
        mat.SetInt("secs", Second);
    }

    // Update is called once per frame
    void Update()
    {
        if(System.DateTime.Now.Hour!= Hour)
        {
            Hour = System.DateTime.Now.Hour;
            mat.SetInt("hors", Hour);
        }
        if (System.DateTime.Now.Minute != Minute)
        {
            Minute = System.DateTime.Now.Minute;
            mat.SetInt("mins", Minute);
        }
        if (System.DateTime.Now.Second != Second)
        {
            Second = System.DateTime.Now.Second;
            mat.SetInt("secs", Second);
        }
    }
}


本人qq:344810449,歡迎探討研究。

有unity,shader,小程序等需求也可以聯繫本人,非常樂於助人。

如果覺得還不錯給博主來個小驚喜,純屬自願,不強求:

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章