Hi guys
I got a bit of a challenge here. The shader shown below puts out a small quad for each of the 90 vertices sent to it to generate an arc line. I plan on supporting dash patterns based on line length in the pixel shader later, which means I need to place line length in the texture coordinates in the geometry shader. The problem is, this arc isn't always going to be perfectly circular. It can become compressed by the bounding rectangle into an ellipse. And so far my google searches have indicated that finding the length of an elliptical arc is no small task.
Anyone got any ideas?
[maxvertexcount(80)]
void GS_DRAWARC(point ARC_INPUTG arc[1], inout TriangleStream<PS_INPUT> triStream)
{
PS_INPUT v;
int n = 90;
float w1 = inset == 0 ? (width.x*0.5f) : 0.0f;
float w2 = inset == 0 ? -(width.x*0.5f) : -width.x;
float xr = arc[0].dim.z * 0.5f;
float yr = arc[0].dim.w * 0.5f;
float2 center = float2(arc[0].dim.x + xr, arc[0].dim.y + yr);
int inst = floor(arc[0].id / darray.y);
int id = arc[0].id % darray.y;
if (darray.x > 0)
{
if (darray.x == 1)
center.xy += float2(darraymod.xy*float(inst));
if (darray.x == 2)
center.xy += float2(fmod(darraymod.x*float(inst), darraymod.z), fmod(darraymod.y*float(inst), darraymod.z));
}
for (int i = 0; i <= 1; i++)
{
int stop = 0;
float end = arc[0].arc.x + arc[0].arc.y;
int j = id + i;
float a = ((float)j / n * 2.0f * 3.1415926f) * (end < 0 ? -1.0f : 1.0f);
if (abs(a) > abs(end))
{
a = end;
stop = 1;
}
float s, c;
sincos(a, s, c);
float r = 1.0f / sqrt(pow(c / xr, 2.0f) + pow(s / yr, 2.0f));
float r2 = r + (end < 0 ? w1 : w2);
float r1 = r + (end < 0 ? w2 : w1);
float _s, _c;
sincos(darraymod.w*float(inst), _s, _c);
float2x2 rot = { _c, -_s, _s, _c };
float2 _p = float2(r2*s, r2*-c) + center;
if (darray.x == 3)
_p = mul(_p, rot);
float4 p = mul(float4(_p*dscale, 0, 1.0f), dxform);
v.p = p*float4(dnorm*2.0f, 1.0f, 1.0f);
v.p.x -= 1.0f;
v.p.y = -v.p.y + 1.0f;
v.t = float2(0.5*s, 0.5*c) + float2(0.5f, 0.5f);
triStream.Append(v);
_p = float2(r1*s, r1*-c) + center;
if (darray.x == 3)
_p = mul(_p, rot);
p = mul(float4(_p*dscale, 0, 1.0f), dxform);
v.p = p*float4(dnorm*2.0f, 1.0f, 1.0f);
v.p.x -= 1.0f;
v.p.y = -v.p.y + 1.0f;
v.t = float2(0.5*s, 0.5*c) + float2(0.5f, 0.5f);
triStream.Append(v);
if (stop != 0)
{
triStream.RestartStrip();
break;
}
}
}
ย