Skip to content

Commit 8473529

Browse files
committed
builtin hlsl shape shader functions
1 parent e54e8b1 commit 8473529

File tree

6 files changed

+255
-46
lines changed

6 files changed

+255
-46
lines changed

include/nbl/builtin/hlsl/shapes/aabb.hlsl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2018-2022 - DevSH Graphics Programming Sp. z O.O.
1+
// Copyright (C) 2018-2023 - DevSH Graphics Programming Sp. z O.O.
22
// This file is part of the "Nabla Engine".
33
// For conditions of distribution and use, see copyright notice in nabla.h
44
#ifndef _NBL_BUILTIN_HLSL_SHAPES_AABB_INCLUDED_
Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,33 @@
1+
// Copyright (C) 2018-2023 - DevSH Graphics Programming Sp. z O.O.
2+
// This file is part of the "Nabla Engine".
3+
// For conditions of distribution and use, see copyright notice in nabla.h
4+
#ifndef _NBL_BUILTIN_HLSL_SHAPES_CIRCLE_INCLUDED_
5+
#define _NBL_BUILTIN_HLSL_SHAPES_CIRCLE_INCLUDED_
6+
17
namespace nbl
28
{
39
namespace hlsl
410
{
511
namespace shapes
612
{
7-
struct Circle_t
8-
{
9-
float2 center;
10-
float radius;
13+
struct Circle_t
14+
{
15+
float2 center;
16+
float radius;
1117

12-
Circle_t(float2 center, float radius) :
13-
center(center),
14-
radius(radius)
15-
{}
18+
static Circle_t construct(float2 center, float radius)
19+
{
20+
Circle_t c = { center, radius };
21+
return c;
22+
}
1623

17-
float getSignedDistance(float2 p)
18-
{
19-
return distance(p, center) - radius;
20-
}
21-
};
24+
float signedDistance(float2 p)
25+
{
26+
return distance(p, center) - radius;
27+
}
28+
};
29+
}
2230
}
2331
}
24-
}
32+
33+
#endif
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
// Copyright (C) 2018-2023 - DevSH Graphics Programming Sp. z O.O.
2+
// This file is part of the "Nabla Engine".
3+
// For conditions of distribution and use, see copyright notice in nabla.h
4+
#ifndef _NBL_BUILTIN_HLSL_SHAPES_ELLIPSE_INCLUDED_
5+
#define _NBL_BUILTIN_HLSL_SHAPES_ELLIPSE_INCLUDED_
6+
7+
#include <nbl/builtin/hlsl/shapes/circle.hlsl>
8+
9+
namespace nbl
10+
{
11+
namespace hlsl
12+
{
13+
namespace shapes
14+
{
15+
float msign(in float x) { return (x < 0.0) ? -1.0 : 1.0; }
16+
// Ellipse Shape Centered at (0,0) and Major-Axis aligned with X-Axis
17+
struct Ellipse_t
18+
{
19+
float majorAxisLength;
20+
float eccentricity;
21+
22+
static Ellipse_t construct(float majorAxisLength, float eccentricity)
23+
{
24+
Ellipse_t ret = { majorAxisLength, eccentricity };
25+
return ret;
26+
}
27+
28+
// https://iquilezles.org/articles/ellipsedist/ with modifications to add rotation and different inputs and fixed degenerate points
29+
// major axis is in the direction of +x and minor axis is in the direction of +y
30+
// @param p should be in ellipse space -> center of ellipse is (0,0)
31+
float signedDistance(float2 p)
32+
{
33+
if (eccentricity == 1.0)
34+
return length(p) - majorAxisLength;
35+
36+
float minorAxisLength = majorAxisLength * eccentricity;
37+
float2 ab = float2(majorAxisLength, minorAxisLength);
38+
p = abs(p);
39+
40+
if (p.x > p.y) { p = p.yx; ab = ab.yx; }
41+
42+
float l = ab.y * ab.y - ab.x * ab.x;
43+
44+
float m = ab.x * p.x / l;
45+
float n = ab.y * p.y / l;
46+
float m2 = m * m;
47+
float n2 = n * n;
48+
49+
float c = (m2 + n2 - 1.0) / 3.0;
50+
float c3 = c * c * c;
51+
52+
float d = c3 + m2 * n2;
53+
float q = d + m2 * n2;
54+
float g = m + m * n2;
55+
56+
float co;
57+
58+
if (d < 0.0)
59+
{
60+
float h = acos(q / c3) / 3.0;
61+
float s = cos(h) + 2.0;
62+
float t = sin(h) * sqrt(3.0);
63+
float rx = sqrt(max(m2 - c * (s + t), 0.0));
64+
float ry = sqrt(max(m2 - c * (s - t), 0.0));
65+
co = ry + sign(l) * rx + abs(g) / (rx * ry);
66+
}
67+
else
68+
{
69+
float h = 2.0 * m * n * sqrt(d);
70+
float s = msign(q + h) * pow(abs(q + h), 1.0 / 3.0);
71+
float t = msign(q - h) * pow(abs(q - h), 1.0 / 3.0);
72+
float rx = -(s + t) - c * 4.0 + 2.0 * m2;
73+
float ry = (s - t) * sqrt(3.0);
74+
float rm = sqrt(max(rx * rx + ry * ry, 0.0));
75+
co = ry / sqrt(max(rm - rx, 0.0)) + 2.0 * g / rm;
76+
}
77+
co = (co - m) / 2.0;
78+
79+
float si = sqrt(max(1.0 - co * co, 0.0));
80+
81+
float2 r = ab * float2(co, si);
82+
83+
return length(r - p) * msign(p.y - r.y);
84+
}
85+
};
86+
87+
// Ellipse Outline
88+
struct EllipseOutline_t
89+
{
90+
float2 center;
91+
float2 majorAxis;
92+
float eccentricity;
93+
float thickness;
94+
95+
static EllipseOutline_t construct(float2 center, float2 majorAxis, float eccentricity, float thickness)
96+
{
97+
EllipseOutline_t ret = { center, majorAxis, eccentricity, thickness };
98+
return ret;
99+
}
100+
101+
float signedDistance(float2 p)
102+
{
103+
float majorAxisLength = length(majorAxis);
104+
float2 dir = majorAxis / majorAxisLength;
105+
p = p - center;
106+
p = mul(float2x2(dir.x, dir.y, -dir.y, dir.x), p);
107+
108+
float ellipseDist = Ellipse_t::construct(majorAxisLength, eccentricity).signedDistance(p);
109+
return abs(ellipseDist) - thickness;
110+
}
111+
};
112+
113+
// Ellipse Outline
114+
struct EllipseOutlineBounded_t
115+
{
116+
float2 center;
117+
float2 majorAxis;
118+
float2 bounds;
119+
float eccentricity;
120+
float thickness;
121+
122+
// @param bounds is in [0, 2PI]
123+
// bounds.y-bounds.x should be <= PI
124+
static EllipseOutlineBounded_t construct(float2 center, float2 majorAxis, float2 bounds, float eccentricity, float thickness)
125+
{
126+
EllipseOutlineBounded_t ret = { center, majorAxis, bounds, eccentricity, thickness };
127+
return ret;
128+
}
129+
130+
float signedDistance(float2 p)
131+
{
132+
float majorAxisLength = length(majorAxis);
133+
float2 dir = majorAxis / majorAxisLength;
134+
p = p - center;
135+
p = mul(float2x2(dir.x, dir.y, -dir.y, dir.x), p);
136+
137+
float2 pNormalized = normalize(p);
138+
float theta = atan2(pNormalized.y, -pNormalized.x * eccentricity) + nbl_hlsl_PI;
139+
140+
float minorAxisLength = majorAxisLength * eccentricity;
141+
142+
float2 startPoint = float2(majorAxisLength * cos(bounds.x), -minorAxisLength * sin(bounds.x));
143+
float2 endPoint = float2(majorAxisLength * cos(bounds.y), -minorAxisLength * sin(bounds.y));
144+
145+
float2 startTangent = float2(-majorAxisLength * sin(bounds.x), -minorAxisLength * cos(bounds.x));
146+
float2 endTangent = float2(-majorAxisLength * sin(bounds.y), -minorAxisLength * cos(bounds.y));
147+
float dotStart = dot(startTangent, float2(p - startPoint));
148+
float dotEnd = dot(endTangent, float2(p - endPoint));
149+
150+
if (dotStart > 0 && dotEnd < 0)
151+
{
152+
float ellipseDist = Ellipse_t::construct(majorAxisLength, eccentricity).signedDistance(p);
153+
return abs(ellipseDist) - thickness;
154+
}
155+
else
156+
{
157+
float sdCircle1 = Circle_t::construct(startPoint, thickness).signedDistance(p);
158+
float sdCircle2 = Circle_t::construct(endPoint, thickness).signedDistance(p);
159+
return min(sdCircle1, sdCircle2);
160+
}
161+
}
162+
};
163+
}
164+
}
165+
}
166+
167+
#endif
Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,39 @@
1+
// Copyright (C) 2018-2023 - DevSH Graphics Programming Sp. z O.O.
2+
// This file is part of the "Nabla Engine".
3+
// For conditions of distribution and use, see copyright notice in nabla.h
4+
#ifndef _NBL_BUILTIN_HLSL_SHAPES_LINE_INCLUDED_
5+
#define _NBL_BUILTIN_HLSL_SHAPES_LINE_INCLUDED_
6+
17
namespace nbl
28
{
39
namespace hlsl
410
{
511
namespace shapes
612
{
7-
struct Line_t
8-
{
9-
float2 start, end;
13+
struct Line_t
14+
{
15+
float2 start;
16+
float2 end;
17+
float thickness;
18+
19+
static Line_t construct(float2 start, float2 end, float thickness)
20+
{
21+
Line_t ret = { start, end, thickness };
22+
return ret;
23+
}
1024

11-
// https://www.shadertoy.com/view/stcfzn with modifications
12-
float getSignedDistance(float2 p, float thickness)
13-
{
14-
const float l = length(end - start);
15-
const float2 d = (end - start) / l;
16-
float2 q = p - (start + end) * 0.5;
17-
q = mul(float2x2(d.x, d.y, -d.y, d.x), q);
18-
q = abs(q) - float2(l * 0.5, thickness);
19-
return length(max(q, 0.0)) + min(max(q.x, q.y), 0.0);
20-
}
21-
};
25+
float signedDistance(float2 p)
26+
{
27+
const float l = length(end - start);
28+
const float2 d = (end - start) / l;
29+
float2 q = p - (start + end) * 0.5;
30+
q = mul(float2x2(d.x, d.y, -d.y, d.x), q);
31+
q = abs(q) - float2(l * 0.5, thickness);
32+
return length(max(q, 0.0)) + min(max(q.x, q.y), 0.0);
33+
}
34+
};
2235
}
2336
}
24-
}
37+
}
38+
39+
#endif
Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
// Copyright (C) 2018-2023 - DevSH Graphics Programming Sp. z O.O.
2+
// This file is part of the "Nabla Engine".
3+
// For conditions of distribution and use, see copyright notice in nabla.h
4+
#ifndef _NBL_BUILTIN_HLSL_SHAPES_ROUNDED_LINE_INCLUDED_
5+
#define _NBL_BUILTIN_HLSL_SHAPES_ROUNDED_LINE_INCLUDED_
6+
17
#include <nbl/builtin/hlsl/shapes/line.hlsl>
28
#include <nbl/builtin/hlsl/shapes/circle.hlsl>
39

@@ -7,21 +13,28 @@ namespace hlsl
713
{
814
namespace shapes
915
{
10-
struct RoundedLine_t
11-
{
12-
float2 start, end;
16+
struct RoundedLine_t
17+
{
18+
float2 start;
19+
float2 end;
20+
float thickness;
21+
22+
static RoundedLine_t construct(float2 start, float2 end, float thickness)
23+
{
24+
RoundedLine_t ret = { start, end, thickness };
25+
return ret;
26+
}
1327

14-
float getSignedDistance(float2 p, float thickness)
15-
{
16-
Circle_t startCircle = {start, thickness};
17-
Circle_t endCircle = {end, thickness};
18-
Line_t mainLine = {start, end};
19-
const float startCircleSD = startCircle.getSignedDistance(p);
20-
const float endCircleSD = endCircle.getSignedDistance(p);
21-
const float lineSD = mainLine.getSignedDistance(p, thickness);
22-
return min(lineSD, min(startCircleSD, endCircleSD));
23-
}
24-
};
28+
float signedDistance(float2 p)
29+
{
30+
const float startCircleSD = Circle_t::construct(start, thickness).signedDistance(p);
31+
const float endCircleSD = Circle_t::construct(end, thickness).signedDistance(p);
32+
const float lineSD = Line_t::construct(start, end, thickness).signedDistance(p);
33+
return min(lineSD, min(startCircleSD, endCircleSD));
34+
}
35+
};
2536
}
2637
}
27-
}
38+
}
39+
40+
#endif

src/nbl/builtin/CMakeLists.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,11 +126,16 @@ set(NBL_RESOURCES_TO_EMBED
126126
"nbl/builtin/glsl/scene/animation.glsl"
127127
"nbl/builtin/glsl/scene/keyframe.glsl"
128128
"nbl/builtin/glsl/scene/node.glsl"
129-
# shapes
129+
# shapes glsl
130130
"nbl/builtin/glsl/shapes/aabb.glsl"
131131
"nbl/builtin/glsl/shapes/frustum.glsl"
132132
"nbl/builtin/glsl/shapes/rectangle.glsl"
133133
"nbl/builtin/glsl/shapes/triangle.glsl"
134+
# shapes hlsl
135+
"nbl/builtin/hlsl/shapes/circle.hlsl"
136+
"nbl/builtin/hlsl/shapes/ellipse.hlsl"
137+
"nbl/builtin/hlsl/shapes/line.hlsl"
138+
"nbl/builtin/hlsl/shapes/rounded_line.hlsl"
134139
# skinning
135140
"nbl/builtin/glsl/skinning/cache_descriptor_set.glsl"
136141
"nbl/builtin/glsl/skinning/cache_update.comp"

0 commit comments

Comments
 (0)