- 我使用Unity游戏引擎和着色器代码(我是初学者)。*
目标
我正在尝试创建一个圆圈的环,类似于下面的图片(我现在不关心颜色)。
的数据
- 问题 *
每一个圆圈似乎都向中心挤压,我不知道如何解决这个问题(见下文)。
的
我的设置
这个着色器的材质被应用到画布中的一个面板上,我使用的是uv(见下图)。
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
字符串
问题代码
我认为问题在于我在frag函数中计算长宽比、Angular 或距离的方式(见下文)。
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
}
}
}
型
任何建议都非常感谢。
1条答案
按热度按时间imzjd6km1#
看起来你的问题是来自你使用的变量
angle
-它被计算为屏幕中心和正在渲染的像素之间的Angular -但它被使用,好像它是屏幕中心和圆心之间的Angular 。圆心应该只在设定的Angular (例如,8个圆的0,45,90度等),而不是在代码中angle
变量指定的Angular 。一个更简单的方法是将问题缩小到一个象限,旋转Angular 变量,使其始终位于该象限内,然后在该象限内设置圆的位置。您可以将相对于中心的UV变量,然后旋转它,就像它是第一个“象限”的一部分一样,然后仅针对该情况求解。
例如,如果你想渲染8个圆,Angular 为3度,48度,93度等的像素都应该渲染出来-因为你试图创建的旋转对称,每45度应该是相同的,所以这些情况是相同的。所以你可以只将这些Angular 转换为一个最简单的情况,然后就像只有一个圆一样-你得到了旋转对称,它渲染了所有8个圆。
下面是该方法的一个粗略的工作示例:
字符串
它基本上和你的代码一样,但是它把圆的位置硬编码为
(_DistanceFromCenter, 0)
,然后把angle
转换为quadrantAngle
,只需要对它做一个模运算,这样Angular 总是在-0.5*(2PI/_CircleNumber)
和0.5*(2PI/_CircleNumber)
之间,以创建旋转对称,然后重新创建一个象限相对UV位置(qX
和qY
),以计算出到圆的距离。