Skip to content

Commit 8275e4f

Browse files
committed
1 step towards drawing quadratic beziers, it's shape struct and sdf function
1 parent 8efede6 commit 8275e4f

File tree

1 file changed

+83
-5
lines changed

1 file changed

+83
-5
lines changed

include/nbl/builtin/hlsl/shapes/beziers.hlsl

Lines changed: 83 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,25 +7,103 @@ namespace hlsl
77
{
88
namespace shapes
99
{
10-
struct CubicBezier
10+
float dot2( float2 v ) { return dot(v,v); }
11+
float cross2d( float2 a, float2 b ) { return a.x*b.y - a.y*b.x; }
12+
13+
struct QuadraticBezier
1114
{
12-
static CubicBezier construct()
15+
float2 A;
16+
float2 B;
17+
float2 C;
18+
float thickness;
19+
20+
static QuadraticBezier construct(float2 a, float2 b, float2 c, float thickness)
1321
{
22+
QuadraticBezier ret = { a, b, c, thickness };
23+
return ret;
1424
}
1525

16-
float signedDistance(float2 p)
26+
float signedDistance(float2 pos)
1727
{
28+
float2 a = B - A;
29+
float2 b = A - 2.0*B + C;
30+
float2 c = a * 2.0;
31+
float2 d = A - pos;
32+
33+
float kk = 1.0/dot(b,b);
34+
float kx = kk * dot(a,b);
35+
float ky = kk * (2.0*dot(a,a)+dot(d,b))/3.0;
36+
float kz = kk * dot(d,a);
37+
38+
float res = 0.0;
39+
float sgn = 0.0;
40+
41+
float p = ky - kx*kx;
42+
float q = kx*(2.0*kx*kx - 3.0*ky) + kz;
43+
float p3 = p*p*p;
44+
float q2 = q*q;
45+
float h = q2 + 4.0*p3;
46+
47+
if( h>=0.0 )
48+
{
49+
// 1 root
50+
h = sqrt(h);
51+
float2 x = (float2(h,-h)-q)/2.0;
52+
53+
#if 0
54+
// When p≈0 and p<0, h-q has catastrophic cancelation. So, we do
55+
// h=√(q²+4p³)=q·√(1+4p³/q²)=q·√(1+w) instead. Now we approximate
56+
// √ by a linear Taylor expansion into h≈q(1+½w) so that the q's
57+
// cancel each other in h-q. Expanding and simplifying further we
58+
// get x=float2(p³/q,-p³/q-q). And using a second degree Taylor
59+
// expansion instead: x=float2(k,-k-q) with k=(1-p³/q²)·p³/q
60+
if( abs(p)<0.001 )
61+
{
62+
float k = p3/q; // linear approx
63+
//float k = (1.0-p3/q2)*p3/q; // quadratic approx
64+
x = float2(k,-k-q);
65+
}
66+
#endif
67+
68+
float2 uv = sign(x)*pow(abs(x), float2(1.0/3.0, 1.0/3.0));
69+
float t = clamp( uv.x+uv.y-kx, 0.0, 1.0 );
70+
float2 q = d+(c+b*t)*t;
71+
res = dot2(q);
72+
sgn = cross2d(c+2.0*b*t,q);
73+
}
74+
else
75+
{ // 3 roots
76+
float z = sqrt(-p);
77+
float v = acos(q/(p*z*2.0))/3.0;
78+
float m = cos(v);
79+
float n = sin(v)*1.732050808;
80+
float3 t = clamp( float3(m+m,-n-m,n-m)*z-kx, 0.0, 1.0 );
81+
float2 qx=d+(c+b*t.x)*t.x; float dx=dot2(qx), sx = cross2d(c+2.0*b*t.x,qx);
82+
float2 qy=d+(c+b*t.y)*t.y; float dy=dot2(qy), sy = cross2d(c+2.0*b*t.y,qy);
83+
if( dx<dy ) { res=dx; sgn=sx; } else {res=dy; sgn=sy; }
84+
}
85+
86+
return sqrt( res )*sign(sgn);
1887
}
1988
};
2089

21-
struct QuadraticBezier
90+
struct CubicBezier
2291
{
23-
static QuadraticBezier construct()
92+
float2 a;
93+
float2 b;
94+
float2 c;
95+
float2 d;
96+
float thickness;
97+
98+
static CubicBezier construct(float2 a, float2 b, float2 c, float2 d, float thickness)
2499
{
100+
CubicBezier ret = { a, b, c, d, thickness };
101+
return ret;
25102
}
26103

27104
float signedDistance(float2 p)
28105
{
106+
return 0;
29107
}
30108
};
31109
}

0 commit comments

Comments
 (0)