C# 在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<

更新:关于如何使用Superformula绘制的答案在末尾

我需要画一个圆形的矩形,比如这个,使用。

当能够轻松绘制任何位置时,绘制一个:

但在HLSL中,如果你不能,我会被困在绘制或不绘制像素的条件上:

以下是HLSL代码:

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