我正在使用带有着色器代码的Unity游戏引擎(我是初学者)。
目标
我正在尝试创建一个圆圈,类似于下图(我现在不关心颜色)。
问题
每个圆圈似乎都被压向中心,我不知道如何解决这个问题(见下文)。
我的设置
该着色器的材质应用于画布内的面板,我使用的是 uv 的材质(见下文)。
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
问题代码
我认为问题在于我在 frag 函数中计算纵横比、角度或距离的方式(见下文)。
fixed4 frag(v2f i) : SV_Target
{
float aspectRatio = _ScreenParams.x / _ScreenParams.y;
float2 center = (0.5 * aspectRatio, 0.5);
float2 uv = i.uv - center;
uv.x *= aspectRatio;
float angle = atan2(uv.y, uv.x);
angle = (angle < 0) ? (angle + UNITY_TWO_PI) : angle;
float circleX = _DistanceFromCenter * cos(angle * _CircleNumber);
float circleY = _DistanceFromCenter * sin(angle * _CircleNumber);
float distance = length(uv - float2(circleX, circleY) * aspectRatio);
float circlePattern = smoothstep(_CircleRadius, _CircleRadius + 0.01, distance);
fixed4 smallCircleColor = _CircleColor;
fixed4 result = lerp(_BackgroundColor, smallCircleColor, circlePattern);
return result;
}
我试图改变计算纵横比的方式,但是我所做的任何事情都会使其远离中心,所以我只是坚持使用我能得到的最接近的东西。
完整代码
请参阅下面的完整脚本。
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" }
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;
};
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 = (0.5 * aspectRatio, 0.5);
float2 uv = i.uv - center;
uv.x *= aspectRatio;
float angle = atan2(uv.y, uv.x);
angle = (angle < 0) ? (angle + UNITY_TWO_PI) : angle;
float circleX = _DistanceFromCenter * cos(angle * _CircleNumber);
float circleY = _DistanceFromCenter * sin(angle * _CircleNumber);
float distance = length(uv - float2(circleX, circleY) * aspectRatio);
float circlePattern = smoothstep(_CircleRadius, _CircleRadius + 0.01, distance);
fixed4 smallCircleColor = _CircleColor;
fixed4 result = lerp(_BackgroundColor, smallCircleColor, circlePattern);
return result;
}
ENDCG
}
}
}
非常感谢任何建议。
看起来您的问题来自于您对变量
angle
的使用 - 它的计算方式是屏幕中心和正在渲染的像素之间的角度 - 但它的使用方式就好像它是屏幕中心之间的角度一样和圆的中心。圆心只能位于设定的角度(例如 0、45、90 等度),而不是代码中 angle
变量指定的角度。
一种更简单的方法是将问题简化为一个象限并旋转角度变量,使其始终位于该象限中,然后为该象限内的圆设定一个固定位置。您可以获取相对于中心的 UV 变量,然后旋转它,就好像它是第一个“象限”的一部分一样,然后针对这种情况求解它。
这是该方法的一个工作示例:
fixed4 frag(v2f i) : SV_Target
{
float aspectRatio = _ScreenParams.x / _ScreenParams.y;
float2 center = (0.5 * aspectRatio, 0.5);
float2 uv = i.uv - center;
uv.x *= aspectRatio;
float angle = atan2(uv.y, uv.x);
angle = (angle < 0) ? (angle + UNITY_TWO_PI) : angle;
float quadrantSize = UNITY_TWO_PI / _CircleNumber;
float quadrantAngle = (angle) % (quadrantSize) - quadrantSize/2;
float uvLength = length(uv);
float qX = uvLength * cos(quadrantAngle);
float qY = uvLength * sin(quadrantAngle);
float circleX = _DistanceFromCenter;
float circleY = 0;
float dist = distance(float2(qX, qY), float2(circleX, circleY) * aspectRatio);
float circlePattern = smoothstep(_CircleRadius, _CircleRadius + 0.01, dist);
fixed4 smallCircleColor = _CircleColor;
fixed4 result = lerp(_BackgroundColor, smallCircleColor, circlePattern);
return result;
}
它与您的代码基本相同,但它将圆位置硬编码为
(_DistanceFromCenter, 0)
,并通过仅对其进行取模将angle
转换为quadrantAngle
,以便角度始终在-0.5*(2PI/_CircleNumber)
和0.5*(2PI/_CircleNumber)
之间,创建旋转对称,然后重新创建相对于象限的 UV 位置(qX
和 qY
)。