You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity Shader实现环形圆形:解决圆形向中心挤压问题

问题解决:Unity Shader环形排列圆形的挤压与偏移问题

问题分析

你的核心问题出在宽高比的错误应用和UV坐标空间的不一致处理上:

  1. 错误地将center的x坐标乘以宽高比,导致整个UV空间偏移
  2. 对UV的x轴重复缩放(先减偏移再乘宽高比,后续又对圆的位置乘宽高比),导致圆形被挤压
  3. 角度计算使用了已经缩放后的UV,导致环形排列的逻辑错乱

修正方案

我们需要统一UV空间的处理,确保宽高比只在需要修正圆形形状的时候应用,而不是破坏整个坐标系统的中心和角度计算:

修正后的片元函数

fixed4 frag(v2f i) : SV_Target
{
    float aspectRatio = _ScreenParams.x / _ScreenParams.y;
    // 正确的UV中心,UV本身是0-1范围,中心就是(0.5,0.5)
    float2 center = float2(0.5, 0.5);
    float2 uv = i.uv - center;

    // 仅在计算距离时修正宽高比,保证圆形为正圆,不影响角度计算
    float2 uvForDistance = uv;
    uvForDistance.x *= aspectRatio;

    // 使用原始UV计算角度,确保环形排列的角度逻辑正确
    float angle = atan2(uv.y, uv.x);
    // 统一角度到0-2π范围,替代原有的三目判断
    angle = fmod(angle + UNITY_TWO_PI, UNITY_TWO_PI);

    // 计算每个小圆的间隔角度,确定目标位置
    float stepAngle = UNITY_TWO_PI / _CircleNumber;
    float targetAngle = floor(angle / stepAngle) * stepAngle + stepAngle * 0.5;
    float2 circlePos = _DistanceFromCenter * float2(cos(targetAngle), sin(targetAngle));

    // 用修正宽高比后的UV计算点到圆心的距离
    float distance = length(uvForDistance - circlePos * float2(aspectRatio, 1.0));
    float circlePattern = smoothstep(_CircleRadius, _CircleRadius + 0.01, distance);
    // 修正lerp顺序:距离小于半径时显示圆颜色,否则显示背景
    fixed4 result = lerp(_CircleColor, _BackgroundColor, circlePattern);

    return result;
}

关键修正点

  • 中心坐标修正:直接使用(0.5,0.5)作为UV中心,避免坐标偏移
  • 角度与距离分离处理:用原始UV计算角度保证环形布局正确,仅在距离计算时修正宽高比保证正圆
  • 角度步进优化:通过UNITY_TWO_PI / _CircleNumber计算小圆间隔角度,修复原代码角度逻辑错误
  • smoothstep逻辑修正:调整lerp顺序,让圆形显示逻辑符合预期

完整修正后的Shader代码

Shader "Magnality/Loading/LoadingCircle"
{
    Properties
    {
        _BackgroundColor("Background Color", Color) = (0, 0, 0, 0)
        _CircleColor("Circle Color", Color) = (1, 1, 1, 1)
        _CircleRadius("Circle Radius", Float) = 0.1
        _CircleNumber("Circle Number", Int) = 10
        _DistanceFromCenter("Distance from Center", Float) = 0.2

        [HideInInspector] _MainTex("Dummy Texture", 2D) = "white" { }
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" "Queue"="Transparent" }
        LOD 100
        Blend SrcAlpha OneMinusSrcAlpha // 支持透明背景设置

        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;
            };

            fixed4 _BackgroundColor;
            fixed4 _CircleColor;
            float _CircleRadius;
            int _CircleNumber;
            float _DistanceFromCenter;


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

            fixed4 frag(v2f i) : SV_Target
            {
                float aspectRatio = _ScreenParams.x / _ScreenParams.y;
                float2 center = float2(0.5, 0.5);
                float2 uv = i.uv - center;

                float2 uvForDistance = uv;
                uvForDistance.x *= aspectRatio;

                float angle = atan2(uv.y, uv.x);
                angle = fmod(angle + UNITY_TWO_PI, UNITY_TWO_PI);

                float stepAngle = UNITY_TWO_PI / _CircleNumber;
                float targetAngle = floor(angle / stepAngle) * stepAngle + stepAngle * 0.5;
                float2 circlePos = _DistanceFromCenter * float2(cos(targetAngle), sin(targetAngle));

                float distance = length(uvForDistance - circlePos * float2(aspectRatio, 1.0));
                float circlePattern = smoothstep(_CircleRadius, _CircleRadius + 0.01, distance);
                fixed4 result = lerp(_CircleColor, _BackgroundColor, circlePattern);

                return result;
            }
            ENDCG
        }
    } 
}

注:添加的透明混合标签用于支持背景透明需求,若不需要可移除Blend和Queue配置。

内容的提问来源于stack exchange,提问作者Magnality

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 15:45:07