C# 在HLSL中绘制超椭圆
更新:关于如何使用Superformula绘制的答案在末尾 我需要画一个圆形的矩形,比如这个,使用。 当能够轻松绘制任何位置时,绘制一个: 但在HLSL中,如果你不能,我会被困在绘制或不绘制像素的条件上: 以下是HLSL代码:C# 在HLSL中绘制超椭圆,c#,math,hlsl,ellipse,C#,Math,Hlsl,Ellipse,更新:关于如何使用Superformula绘制的答案在末尾 我需要画一个圆形的矩形,比如这个,使用。 当能够轻松绘制任何位置时,绘制一个: 但在HLSL中,如果你不能,我会被困在绘制或不绘制像素的条件上: 以下是HLSL代码: sampler2D input : register(s0); /// <summary>Explain the purpose of this variable.</summary> /// <minValue>0.0<
sampler2D input : register(s0);
/// <summary>Explain the purpose of this variable.</summary>
/// <minValue>0.0</minValue>
/// <maxValue>10.0</maxValue>
/// <defaultValue>4.0</defaultValue>
float N : register(C1);
static const float pi = 3.1415926535f;
float2 superEllipse(float n, float a, float b, float theta)
{
float ct = cos(theta);
float st = sin(theta);
float x = a * sign(ct) * pow(abs(ct), 2.0f / n);
float y = b * sign(st) * pow(abs(st), 2.0f / n);
return float2(x, y);
}
float4 main(float2 uv : TEXCOORD) : COLOR
{
float2 uv1 = uv * float2(2.0f, 2.0f) - float2(1.0f, 1.0f);
float angle = degrees(atan2(uv1.y, uv1.x)) + 180.0f;
float tMax = pi * 2.0f;
float theta = 1.0f / 360.0f * angle * tMax;
float2 se = superEllipse(N, 1, 1, theta);
float angle1 = degrees(atan2(se.y, se.x)) + 180.0f;
float2 zero = float2(0.0f, 0.0f);
float dist1 = distance(se, zero);
float dist2 = distance(uv1, zero);
float4 color = float4(0, 0, 0, 1);
if(dist2 <= dist1)
color += float4(0, 1, 0, 1);
return color;
}
2d输入:寄存器(s0);
///解释此变量的用途。
/// 0.0
/// 10.0
/// 4.0
浮点N:寄存器(C1);
静态常数浮点pi=3.1415926535f;
浮点2超椭圆(浮点n、浮点a、浮点b、浮点θ)
{
浮动电流互感器=cos(θ);
浮点数st=sin(θ);
浮动x=a*符号(ct)*功率(abs(ct),2.0f/n);
浮动y=b*符号(st)*功率(abs(st),2.0f/n);
返回浮点数2(x,y);
}
浮动4主(浮动2 uv:TEXCOORD):颜色
{
浮动2 uv1=uv*浮动2(2.0f,2.0f)-浮动2(1.0f,1.0f);
浮动角度=度(atan2(uv1.y,uv1.x))+180.0f;
浮动tMax=pi*2.0f;
浮动θ=1.0f/360.0f*角度*tMax;
float2se=超椭圆(N,1,1,θ);
浮动角度1=度(atan2(东南向,东南向))+180.0f;
浮动2零=浮动2(0.0f,0.0f);
浮动距离1=距离(se,零);
浮动距离2=距离(uv1,零);
float4颜色=float4(0,0,0,1);
如果(dist2出现问题是因为超椭圆(θ)
返回一个角度不一定是θ的点。例如,超椭圆(3.6)
返回一个角度为3.2弧度的点。
因此,在您的main()
函数中,比较uv1
和se
的大小是没有意义的,因为它们有不同的角度
请参见。扫掠直线表示传递到超椭圆的角度,曲线的末端表示新点实际放置的位置。新点很少位于扫掠线上
如果您对超椭圆使用极坐标方程,而不是参数方程,那么您可以使用它来执行距离测试。方便的是,有这样一个方程:
您只需要编写代码并将其放在主函数中
float4 main(float2 uv : TEXCOORD) : COLOR
{
float2 uv1 = uv * float2(2.0f, 2.0f) - float2(1.0f, 1.0f);
float angle = degrees(atan2(uv1.y, uv1.x)) + 180.0f;
//to do: implement equation shown above. Use `angle` for theta.
//`m` should be 4 if you want a four-pronged shape.
float magnitude = ???
float2 zero = float2(0.0f, 0.0f);
float dist1 = distance(uv1, zero);
float4 color = float4(0,0,0,1);
if (dist1 <= magnitude) //uv is inside the superellipse
color += float4(0,1,0,1);
return color;
}
float4 main(float2 uv:TEXCOORD):颜色
{
浮动2 uv1=uv*浮动2(2.0f,2.0f)-浮动2(1.0f,1.0f);
浮动角度=度(atan2(uv1.y,uv1.x))+180.0f;
//要做的事情:实现上面所示的等式。用“角度”表示θ。
//`如果你想要四叉的形状,m应该是4。
浮动幅度=???
浮动2零=浮动2(0.0f,0.0f);
浮动距离1=距离(uv1,零);
float4颜色=float4(0,0,0,1);
如果(dist1)我试图实现它,(代码在问题的末尾),但是M对我来说是不正确的,我真的必须降低它以获得一个基本形状。另一件事我忘了提到(也更新了问题)我需要画一个圆形的矩形,但显然超公式没有这样做,或者是这样吗?参考:,当你得到五点星的形状时,你对M,N,a和B的设置是什么?它们应该是4,0.5,1和1。另外,你应该取sin和cos的绝对值-这是垂直条所表示的。超公式ula应该能够绘制超椭圆所能绘制的任何形状,因此圆角矩形是可能的。因此,请注意您的单位是否为mt
。在HLSL中,是否sin
和cos
需要以度或弧度为单位的参数?如果是弧度,角度
应仅定义为atan2(uv1.y,uv1.x)
值为M=0.9,N1=0.5,但使用弧度和绝对值,它现在可以工作了,谢谢!
sampler2D input : register(s0);
/// <summary>Explain the purpose of this variable.</summary>
/// <minValue>0.0</minValue>
/// <maxValue>8.0</maxValue>
/// <defaultValue>1.0</defaultValue>
float A : register(C0);
/// <summary>Explain the purpose of this variable.</summary>
/// <minValue>0.0</minValue>
/// <maxValue>8.0</maxValue>
/// <defaultValue>1.0</defaultValue>
float B : register(C1);
/// <summary>Explain the purpose of this variable.</summary>
/// <minValue>0.0</minValue>
/// <maxValue>8.0</maxValue>
/// <defaultValue>1.0</defaultValue>
float M : register(C2);
/// <summary>Explain the purpose of this variable.</summary>
/// <minValue>0.0, 0.0, 0.0</minValue>
/// <maxValue>8.0, 8.0, 8.0</maxValue>
/// <defaultValue>1.0, 1.0, 1.0</defaultValue>
float3 N : register(C3);
float4 main(float2 uv : TEXCOORD) : COLOR
{
float2 uv1 = uv * float2(2.0f, 2.0f) - float2(1.0f, 1.0f);
float angle = degrees(atan2(uv1.y, uv1.x)) + 180.0f;
float mt = M * angle / 4.0f;
float magnitude = pow((pow((cos(mt) / A), N.y) + pow((sin(mt) / B), N.z)), -(1.0f / N.x));
float2 zero = float2(0.0f, 0.0f);
float dist1 = distance(uv1, zero);
float4 color = float4(0, 0, 0, 1);
if(dist1 <= magnitude)
color += float4(dist1, 1, 0, 1);
return color;
}
sampler2D input : register(s0);
/// <summary>Explain the purpose of this variable.</summary>
/// <minValue>0.0</minValue>
/// <maxValue>8.0</maxValue>
/// <defaultValue>1.0</defaultValue>
float A : register(C0);
/// <summary>Explain the purpose of this variable.</summary>
/// <minValue>0.0</minValue>
/// <maxValue>8.0</maxValue>
/// <defaultValue>1.0</defaultValue>
float B : register(C1);
/// <summary>Explain the purpose of this variable.</summary>
/// <minValue>0.0</minValue>
/// <maxValue>8.0</maxValue>
/// <defaultValue>8.0</defaultValue>
float M : register(C2);
/// <summary>Explain the purpose of this variable.</summary>
/// <minValue>0.0, 0.0, 0.0</minValue>
/// <maxValue>8.0, 8.0, 8.0</maxValue>
/// <defaultValue>1.0, 1.0, 1.0</defaultValue>
float3 N : register(C3);
float4 main(float2 uv : TEXCOORD) : COLOR
{
float2 uv1 = uv * float2(2.0f, 2.0f) - float2(1.0f, 1.0f);
float angle = atan2(uv1.y, uv1.x);
float mt = M * angle / 4.0f;
float magnitude = pow((pow((abs(cos(mt)) / A), N.y) + pow((abs(sin(mt)) / B), N.z)), -(1.0f / N.x));
float2 zero = float2(0.0f, 0.0f);
float dist1 = distance(uv1, zero);
float4 color = float4(0, 0, 0, 1);
float alpha = 1.0f / magnitude * dist1;
if(dist1 <= magnitude)
color += float4(1, 0.5, 0, 1);
return color;
}
float4 main(float2 uv : TEXCOORD) : COLOR
{
float2 uv1 = uv * float2(2.0f, 2.0f) - float2(1.0f, 1.0f);
float angle = degrees(atan2(uv1.y, uv1.x)) + 180.0f;
//to do: implement equation shown above. Use `angle` for theta.
//`m` should be 4 if you want a four-pronged shape.
float magnitude = ???
float2 zero = float2(0.0f, 0.0f);
float dist1 = distance(uv1, zero);
float4 color = float4(0,0,0,1);
if (dist1 <= magnitude) //uv is inside the superellipse
color += float4(0,1,0,1);
return color;
}