vgpu-render 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/README.md +76 -26
  2. package/dist/curve.d.ts +1 -1
  3. package/dist/debug-draw-3d.d.ts +3 -3
  4. package/dist/debug-draw-3d.js +10 -10
  5. package/dist/{frame-recorder-2d.d.ts → frame-draw-list-2d.d.ts} +11 -11
  6. package/dist/{frame-recorder-2d.js → frame-draw-list-2d.js} +6 -6
  7. package/dist/{frame-recorder.d.ts → frame-draw-list.d.ts} +60 -8
  8. package/dist/{frame-recorder.js → frame-draw-list.js} +51 -10
  9. package/dist/geometry-generators.d.ts +2 -2
  10. package/dist/geometry-generators.js +1 -1
  11. package/dist/gpu-debug-draw-2d.d.ts +1 -1
  12. package/dist/gpu-debug-draw-3d.d.ts +1 -1
  13. package/dist/gpu-debug-draw-3d.js +4 -2
  14. package/dist/gpu-text-3d.d.ts +1 -1
  15. package/dist/gpu-text-3d.js +49 -2
  16. package/dist/index.d.ts +3 -3
  17. package/dist/index.js +2 -3
  18. package/dist/mesh-batch-3d.d.ts +1 -1
  19. package/dist/shape2d-shader.js +3 -2
  20. package/dist/text-atlas.d.ts +6 -4
  21. package/dist/text-atlas.js +9 -6
  22. package/dist/text-font.d.ts +48 -7
  23. package/dist/text-font.js +63 -11
  24. package/dist/text-layout.d.ts +63 -4
  25. package/dist/text-layout.js +58 -8
  26. package/dist/text-msdf-baked.d.ts +9 -4
  27. package/dist/text-msdf-baked.js +9 -4
  28. package/dist/text-msdf-font.d.ts +10 -4
  29. package/dist/text-msdf-font.js +9 -3
  30. package/dist/vector-math.d.ts +19 -0
  31. package/dist/vector-math.js +37 -0
  32. package/package.json +1 -1
  33. package/dist/layout-3d.d.ts +0 -227
  34. package/dist/layout-3d.js +0 -226
  35. package/dist/scene-examples.d.ts +0 -39
  36. package/dist/scene-examples.js +0 -200
  37. package/dist/scenes-2d.d.ts +0 -18
  38. package/dist/scenes-2d.js +0 -160
  39. package/dist/scenes-3d.d.ts +0 -46
  40. package/dist/scenes-3d.js +0 -1994
  41. package/dist/text-scenes.d.ts +0 -85
  42. package/dist/text-scenes.js +0 -338
@@ -1,200 +0,0 @@
1
- // Columns whose reference variants are only approximated by this vgpu port are flagged false so the
2
- // gallery never claims parity it does not have: grid boundary (`outer`) handling still differs.
3
- const approximated = /outer/;
4
- const column = (label, samples) => ({
5
- label,
6
- samples,
7
- implemented: !approximated.test(label),
8
- });
9
- const width = ["width = 1.0", "width = 2.0", "width = 5.5", "width = 10.0"];
10
- const joints = ["none", "round", "bevel", "miter"];
11
- const dash = ["dash = 0.10 / 0.10", "dash = 0.20 / 0.10", "dash = 0.40 / 0.15", "dash = 0.04 / 0.12"];
12
- const normal = ["base", "alpha", "color", "wide"];
13
- const rotation = Array.from({ length: 8 }, (_, index) => `step ${index}`);
14
- // Arrow example samples copied from `examples/arrow.gd` `_get_sample_label`.
15
- const arrowWidth = ["w = 1.0", "w = 2.0", "w = 5.5", "w = 10.0"];
16
- const arrowDir = ["-63 deg", "-22 deg", "22 deg", "63 deg"];
17
- const arrowHeadAngle = ["20 deg", "30 deg", "45 deg", "76 deg"];
18
- const arrowJoints = ["NONE", "ROUND", "BEVEL", "MITER"];
19
- const arrowHeadLength = ["head = 0.12", "head = 0.22", "head = 0.34", "head = 0.46"];
20
- const arrowDash = ["0.10 / 0.10", "0.20 / 0.10", "0.40 / 0.15", "0.04 / 0.12"];
21
- const radius = ["0.18", "0.28", "0.38", "0.50"];
22
- const segments = ["8", "16", "32", "64"];
23
- const jointNote = "Round, bevel and miter joins are rebuilt in the vertex stage from the reference joint shaders.";
24
- const shapeWidth = ["w = 1.0", "w = 2.0", "w = 5.5", "w = 10.0"];
25
- const shapeRadius = ["r = 0.18", "r = 0.28", "r = 0.38", "r = 0.50"];
26
- const capsuleRadius = ["r = 0.16", "r = 0.24", "r = 0.32", "r = 0.40"];
27
- const shapeSegments = ["8 seg", "16 seg", "32 seg", "64 seg"];
28
- const smallSegments = ["3 seg", "4 seg", "8 seg", "16 seg"];
29
- const sideSegments = ["3 side", "4 side", "8 side", "16 side"];
30
- const capsuleSideSegments = ["1 side", "2 side", "4 side", "8 side"];
31
- const coneHeights = ["h = 0.45", "h = 0.65", "h = 0.85", "h = 1.05"];
32
- const cylinderHalfHeights = ["hh = 0.225", "hh = 0.325", "hh = 0.425", "hh = 0.525"];
33
- const capsuleHalfHeights = ["hh = 0.000", "hh = 0.125", "hh = 0.225", "hh = 0.350"];
34
- const yAxisSegments = ["y = 0", "y = 1", "y = 2", "y = 6"];
35
- const zAxisSegments = ["z = 0", "z = 1", "z = 2", "z = 6"];
36
- // Row labels copied from `examples/index.gd` ROW_LABELS (the full API matrix).
37
- const indexRows = {
38
- line: ["draw_line", "draw_line_n", "draw_line_d", "draw_line_n_d"],
39
- ray: ["draw_ray", "draw_ray_n", "draw_ray_d", "draw_ray_n_d"],
40
- arrow: ["draw_arrow", "draw_arrow_n", "draw_arrow_line", "draw_arrow_line_n", "draw_arrow_line_d", "draw_arrow_line_n_d"],
41
- axes: ["draw_axes", "draw_axes_n"],
42
- line_list: ["draw_line_list", "draw_line_list_n"],
43
- strip: ["draw_line_strip", "draw_line_strip_n", "draw_line_strip_d", "draw_line_strip_n_d"],
44
- loop: ["draw_line_loop", "draw_line_loop_n", "draw_line_loop_d", "draw_line_loop_n_d"],
45
- curve: ["draw_curve", "draw_curve_d"],
46
- grid: ["draw_grid", "draw_grid_n"],
47
- rect: ["draw_rect", "draw_rect_s", "draw_rect_n", "draw_rect_d", "draw_rect_n_d"],
48
- box: ["draw_box", "draw_box_s", "draw_box_n", "draw_box_d", "draw_box_n_d"],
49
- circle: ["draw_circle", "draw_circle_s", "draw_circle_n", "draw_circle_d", "draw_circle_n_d"],
50
- arc: ["draw_arc", "draw_arc_n", "draw_arc_d", "draw_arc_n_d"],
51
- sphere: ["draw_sphere", "draw_sphere_s", "draw_sphere_n", "draw_sphere_d", "draw_sphere_n_d"],
52
- cone: ["draw_cone", "draw_cone_s", "draw_cone_n"],
53
- cylinder: ["draw_cylinder", "draw_cylinder_s", "draw_cylinder_n"],
54
- capsule: ["draw_capsule", "draw_capsule_n"],
55
- };
56
- // `world_space_width.gd` ROW_LABELS: same matrix without the `*_s` solid columns.
57
- const worldWidthRows = {
58
- ...indexRows,
59
- rect: ["draw_rect", "draw_rect_n", "draw_rect_d", "draw_rect_n_d"],
60
- box: ["draw_box", "draw_box_n", "draw_box_d", "draw_box_n_d"],
61
- circle: ["draw_circle", "draw_circle_n", "draw_circle_d", "draw_circle_n_d"],
62
- sphere: ["draw_sphere", "draw_sphere_n", "draw_sphere_d", "draw_sphere_n_d"],
63
- cone: ["draw_cone", "draw_cone_n"],
64
- cylinder: ["draw_cylinder", "draw_cylinder_n"],
65
- };
66
- // Column structure copied from the reference scenes. Capsule has no `_s` column.
67
- const solidExamples = [
68
- {
69
- id: "sphere",
70
- title: "Sphere",
71
- description: "Sphere wire and solid meshes across width, radius, segment, axis, dash, joint and normal rows.",
72
- notes: "Reference has 14 columns including y/z axis and sphere_s; the UV generator approximates the independent axis ring counts.",
73
- implemented: true,
74
- columns: [
75
- column("sphere(width)", shapeWidth),
76
- column("sphere(radius)", shapeRadius),
77
- column("sphere(segments)", shapeSegments),
78
- column("sphere(y axis)", yAxisSegments),
79
- column("sphere(z axis)", zAxisSegments),
80
- column("sphere(rotation)", rotation),
81
- column("sphere(joint)", joints),
82
- column("sphere_d(dash)", dash),
83
- column("sphere_d(joint)", joints),
84
- column("sphere_n", normal),
85
- column("sphere_n(joint)", joints),
86
- column("sphere_n_d(dash)", dash),
87
- column("sphere_n_d(joint)", joints),
88
- column("sphere_s", rotation),
89
- ],
90
- },
91
- {
92
- id: "cone",
93
- title: "Cone",
94
- description: "Cone wire and solid meshes across width, radius, height, segment, rotation, joint and normal rows.",
95
- notes: "Reference has 10 columns including cone_s; the generator uses one segment count for the base ring and side lines.",
96
- implemented: true,
97
- columns: [
98
- column("cone(width)", shapeWidth),
99
- column("cone(radius)", shapeRadius),
100
- column("cone(height)", coneHeights),
101
- column("cone(segments)", smallSegments),
102
- column("cone(side segments)", sideSegments),
103
- column("cone(rotation)", rotation),
104
- column("cone(joint)", joints),
105
- column("cone_n", normal),
106
- column("cone_n(joint)", joints),
107
- column("cone_s", rotation),
108
- ],
109
- },
110
- {
111
- id: "cylinder",
112
- title: "Cylinder",
113
- description: "Cylinder wire and solid meshes across width, radius, half height, segment, rotation, joint and normal rows.",
114
- notes: "Reference has 10 columns including cylinder_s; the generator uses one segment count for the base ring and side lines.",
115
- implemented: true,
116
- columns: [
117
- column("cylinder(width)", shapeWidth),
118
- column("cylinder(radius)", shapeRadius),
119
- column("cylinder(half height)", cylinderHalfHeights),
120
- column("cylinder(segments)", smallSegments),
121
- column("cylinder(side segments)", sideSegments),
122
- column("cylinder(rotation)", rotation),
123
- column("cylinder(joint)", joints),
124
- column("cylinder_n", normal),
125
- column("cylinder_n(joint)", joints),
126
- column("cylinder_s", rotation),
127
- ],
128
- },
129
- {
130
- id: "capsule",
131
- title: "Capsule",
132
- description: "Capsule wire meshes across width, radius, half height, segment, rotation, joint and normal rows.",
133
- notes: "Reference has 9 columns and no solid column: the capsule reference has no solid variant.",
134
- implemented: true,
135
- columns: [
136
- column("capsule(width)", shapeWidth),
137
- column("capsule(radius)", capsuleRadius),
138
- column("capsule(half height)", capsuleHalfHeights),
139
- column("capsule(segments)", shapeSegments),
140
- column("capsule(side segments)", capsuleSideSegments),
141
- column("capsule(rotation)", rotation),
142
- column("capsule(joint)", joints),
143
- column("capsule_n", normal),
144
- column("capsule_n(joint)", joints),
145
- ],
146
- },
147
- ];
148
- export const SCENE_EXAMPLES = [
149
- { id: "index", title: "Index", description: "The DebugDraw3D API matrix: 17 primitive columns with the reference per-column row sets.", notes: "Overview of every primitive family; row labels mirror the reference draw calls.", implemented: true, columns: ["line", "ray", "arrow", "axes", "line_list", "strip", "loop", "curve", "grid", "rect", "box", "circle", "arc", "sphere", "cone", "cylinder", "capsule"].map((label) => column(label, indexRows[label])) },
150
- { id: "line", title: "Line", description: "Widths, alpha, dashes, strip and loop joints, dashed joints, and normal-aware lines.", notes: jointNote, implemented: true, columns: [column("line(width)", width), column("line(alpha)", ["alpha = 1.00", "alpha = 0.65", "alpha = 0.35", "alpha = 0.10"]), column("line_d(dash)", dash), column("strip(joint)", joints), column("loop(joint)", joints), column("strip_d(joint)", joints), column("line_n(normal)", normal)] },
151
- { id: "arrow", title: "Arrow", description: "Arrow direction, width, head length, head angle, joints, normal-aware arrows, and arrow-line variants.", notes: jointNote + " Head angle and length are wired to arrow geometry.", implemented: true, columns: [column("arrow(width)", arrowWidth), column("arrow(dir)", arrowDir), column("arrow(head angle)", arrowHeadAngle), column("arrow(joint)", arrowJoints), column("arrow_n", normal), column("arrow_n(joint)", arrowJoints), column("arrow_line(width)", arrowWidth), column("arrow_line(head length)", arrowHeadLength), column("arrow_line(head angle)", arrowHeadAngle), column("arrow_line(rotation)", rotation), column("arrow_line(joint)", arrowJoints), column("arrow_line_d(dash)", arrowDash), column("arrow_line_d(joint)", arrowJoints), column("arrow_line_n", normal), column("arrow_line_n(joint)", arrowJoints), column("arrow_line_n_d(dash)", arrowDash), column("arrow_line_n_d(joint)", arrowJoints)] },
152
- { id: "axes", title: "Axes", description: "Axis length, width, rotation, and normal-aware axis variants.", implemented: true, columns: [column("axes(length)", ["0.35", "0.55", "0.75", "1.00"]), column("axes(width)", width), column("axes(rotation)", rotation), column("axes_n(length)", ["0.35", "0.55", "0.75", "1.00"]), column("axes_n(width)", width), column("axes_n(rotation)", rotation)] },
153
- { id: "grid", title: "Grid", description: "Grid width, cell count, spacing, skew, outer edges, rotation, color, and normal rows.", notes: "Column spacing follows each column's measured bounds; rendered skew and outer edges use the library grid semantics.", implemented: true, columns: [column("grid(width)", ["w = 1.0", "w = 2.0", "w = 5.5", "w = 10.0"]), column("grid(cells)", ["4 x 4", "6 x 4", "10 x 3", "3 x 8"]), column("grid(spacing)", ["0.20 x 0.20", "0.28 x 0.28", "0.42 x 0.22", "0.55 x 0.28"]), column("grid(skew)", ["none", "0.28 / 0.00", "-0.28 / 0.00", "0.28 / -0.18"]), column("grid(outer)", ["none", "X", "Z", "XZ"]), column("grid(rotation)", ["step 0", "step 1", "step 2", "step 3", "step 4", "step 5"]), column("grid(color)", ["base", "alpha", "color", "blue"]), column("grid_n", normal)] },
154
- { id: "rect", title: "Rect", description: "Wire and solid rectangles with size, rotation, joints, dashes, and normal variants.", notes: jointNote, implemented: true, columns: [column("rect(width)", width), column("rect(size)", ["0.50 × 0.40", "0.80 × 0.40", "0.50 × 0.70", "0.55 × 0.55"]), column("rect(rotation)", rotation), column("rect(joint)", joints), column("rect_d(dash)", dash), column("rect_d(joint)", joints), column("rect_n", normal), column("rect_n_d(dash)", dash), column("rect_n(joint)", joints), column("rect_s(solid)", rotation)] },
155
- { id: "box", title: "Box", description: "Wire and solid boxes with size, rotation, dashes, and normal variants.", implemented: true, columns: [column("box(width)", width), column("box(size)", ["0.50 × 0.40 × 0.40", "0.80 × 0.40 × 0.40", "0.50 × 0.60 × 0.40", "0.50 × 0.40 × 0.60"]), column("box(rotation)", rotation), column("box_d(dash)", dash), column("box_n", normal), column("box_n_d(dash)", dash), column("box_s(solid)", rotation)] },
156
- { id: "circle", title: "Circle", description: "Circle width, radius, segment count, rotation, joints, dashes, solid and normal variants.", notes: jointNote, implemented: true, columns: [column("circle(width)", width), column("circle(radius)", radius), column("circle(segments)", segments), column("circle(rotation)", rotation), column("circle(joint)", joints), column("circle_d(dash)", dash), column("circle_d(joint)", joints), column("circle_n", normal), column("circle_n_d(dash)", dash), column("circle_n(joint)", joints), column("circle_s(solid)", segments)] },
157
- { id: "arc", title: "Arc", description: "Arc width, radius, angle, segments, rotation, joints, dashes, and normal variants.", notes: jointNote, implemented: true, columns: [column("arc(width)", width), column("arc(radius)", radius), column("arc(angle)", ["90°", "180°", "270°", "360°"]), column("arc(segments)", segments), column("arc(rotation)", rotation), column("arc(joint)", joints), column("arc_d(dash)", dash), column("arc_d(joint)", joints), column("arc_n", normal), column("arc_n_d(dash)", dash), column("arc_n(joint)", joints)] },
158
- { id: "curve", title: "Curve", description: "Curve widths, shape, transform, tolerance, closed paths, joints and dashes.", notes: jointNote + " Cubic Bezier control points are sampled adaptively from the tolerance row, and the construction band draws the reference anchor and control markers.", implemented: true, columns: [column("curve(width)", width), column("curve(shape)", ["mild", "soft", "base", "wide"]), column("curve(transform)", rotation), column("curve(tolerance)", ["0.04", "0.08", "0.16", "0.32"]), column("curve(closed)", ["open", "closed", "small", "wide"]), column("curve(joint)", joints), column("curve_d(dash)", dash), column("curve_d(joint)", joints)] },
159
- ...solidExamples,
160
- { id: "world_space_width", title: "World Space Width", description: "The 17-column primitive matrix rendered with world-space line widths and without the `*_s` solid columns.", notes: "Widths are `_world_width(px) = px * 0.01`; row labels mirror the reference.", implemented: true, columns: ["line", "ray", "arrow", "axes", "line_list", "strip", "loop", "curve", "grid", "rect", "box", "circle", "arc", "sphere", "cone", "cylinder", "capsule"].map((label) => column(label, worldWidthRows[label])) },
161
- { id: "text-compare", title: "Text Compare", description: "A matrix of one sentence: rows are glyph sources, columns are font sizes.", notes: "Not a reference port: there is no upstream text API, so this is vgpu's own capability. Transposed relative to the line/circle matrices — text grows sideways, so six source columns would be wider than a camera wants to frame. Read down a column to compare encodings at one size, across a row to compare sizes under one encoding. The last row is a fixed-orientation block rather than a camera-facing one, so it foreshortens as you orbit. Every row floats above the grid plane, which writes depth and would otherwise clip it.", implemented: true, group: "text", columns: [column("glyph source", ["bitmap 1x", "bitmap 4x", "sdf 1x", "sdf 4x", "msdf outline", "msdf baked"]), column("font size", ["16 px", "24 px", "36 px"]), column("placement", ["world-billboard", "world-plane", "foreshortens"]), column("what changes", ["coverage interpolation", "supersampled coverage", "distance reconstruction", "per-edge distance", "prebaked at 24 px"])] },
162
- { id: "text-encodings", title: "Text Encodings", description: "One sentence from four glyph sources, at two sizes, plus the outline pair.", notes: "Not a reference port: there is no upstream text API, so this is vgpu's own capability. Every block takes the default source — the one that rasterises each glyph at the size it covers on screen — except the columns that name one, so the page doubles as the gallery's own quality check. The lower band repeats the same ink at more than twice the size, which is where a coverage source and a distance field stop looking alike.", implemented: true, group: "text", hideGrid: true, columns: [column("source", ["bitmap 1x", "sdf 4x", "msdf 2x", "msdf baked"]), column("what changes", ["coverage interpolation", "distance reconstruction", "per-edge distance", "prebaked at 24 px"]), column("outline", ["reads the true distance in alpha", "samples coverage in eight directions"])] },
163
- { id: "text-scale", title: "Text Scale", description: "One sentence at six sizes, over three raster strategies at one size.", notes: "Not a reference port. The top row puts 26 px under the screen-driven ladder, a fixed 1x raster and a fixed 4x raster; the rows below run 8 px to 96 px, so the rung changes — and the absence of a soft step between them — are visible in one frame. The first strategy is what a caller gets by default.", implemented: true, group: "text", hideGrid: true, columns: [column("raster", ["screen decides the rung", "fixed 1x", "fixed 4x"]), column("sizes", ["8 px", "12 px", "18 px", "28 px", "48 px", "96 px"])] },
164
- { id: "text-world-zoom", title: "Text World Zoom", description: "Four sources in world space, made to be magnified with the camera.", notes: "Not a reference port. Screen-space text cannot be magnified — a larger block is simply a request for a new rasterisation — so world-space rows are the only honest test of what a source does past the size its glyphs were built at. Scroll to move the camera in and out: a coverage source runs into the texels it stored, a distance field keeps rebuilding the edge from them.", implemented: true, group: "text", hideGrid: false, columns: [column("source", ["bitmap 1x", "bitmap 4x", "sdf 4x", "msdf baked"]), column("past its raster", ["shows the stored texels", "shows smaller texels", "rebuilds the edge", "rebuilds from a 24 px page"])] },
165
- { id: "text-layout", title: "Text Layout", description: "Wrapping, justification, bounds, line height, letter spacing and spans.", notes: "Not a reference port. The layout follows the documented wrapping and justification semantics, and `docs/text-reference.md` records how each capability is verified. Each row is one capability, labelled on the left, and every bounded row draws the box it wrapped into — a wrapping rule is unreadable without it.", implemented: true, group: "text", hideGrid: true, columns: [column("capability", ["word wrap", "character wrap", "justify", "line height", "letter spacing", "spans"]), column("option", ["lineBreak", "lineBreak", "justify", "lineHeight", "letterSpacing", "TextSpan"])] },
166
- { id: "text-anchor", title: "Text Anchors", description: "The nine anchors against the position a block is handed and the bounds it lands in.", notes: "Not a reference port. The plus is the position the block is given, the box is the bounds it laid out into, and the label names the anchor — so both of the things an anchor moves between are visible at once.", implemented: true, group: "text", hideGrid: true, columns: [column("anchor", ["top-left", "top-center", "top-right", "center-left", "center", "center-right", "bottom-left", "bottom-center", "bottom-right"])] },
167
- { id: "text-cjk", title: "Text CJK", description: "Wrapping per character, kinsoku, mixed scripts and four sizes.", notes: "Not a reference port. CJK has no spaces to break at, so the layout breaks between characters and applies kinsoku: a closing mark never opens a line and an opening bracket never ends one, and the narrow column is tuned so those rules have to act. The family is the bundled latin face, and the canvas falls back to a system CJK face for the ideographs — the same arrangement a system font fallback provides.", implemented: true, group: "text", hideGrid: true, columns: [column("rule", ["per character", "kinsoku", "mixed script"]), column("sizes", ["12 px", "18 px", "28 px", "48 px"])] },
168
- {
169
- id: "2d-gizmos",
170
- title: "2D Gizmos",
171
- description: "Immediate-mode 2D strokes in the camera-centred world2d space: lines, rays, joined strips, boxes, rounded boxes, circles, ellipses, arcs, crosses, arrows, curves and a grid.",
172
- notes: "Not a reference port: this page is built directly on frame.d2. world2d puts the origin at the canvas centre, +y up, one unit per canvas pixel before the camera's pan and zoom. Drag to pan, scroll to zoom.",
173
- implemented: true,
174
- family: "2d",
175
- // The 2D grid is part of what these pages demonstrate, so it opens on even if the
176
- // previous page had it off.
177
- hideGrid: false,
178
- view2d: { width: 1080, height: 640 },
179
- columns: [
180
- column("stroke", ["line", "ray", "linestrip", "rect", "roundedRect", "circle", "ellipse", "arc", "cross", "arrow", "curve", "grid"]),
181
- column("option", ["width", "joint", "dash", "fill", "strokeWidth", "startAngle", "sweep", "rotation", "space"]),
182
- ],
183
- },
184
- {
185
- id: "2d-shapes",
186
- title: "2D Shapes",
187
- description: "Twelve 2D primitives as filled shapes, with their stroked outlines underneath.",
188
- notes: "Not a reference port: this page is built on frame.d2 shape primitives. Each shape is one instanced quad evaluated as a signed distance field, so an outline width is a pixel count at any zoom and nothing is triangulated on the CPU. Drag to pan, scroll to zoom.",
189
- implemented: true,
190
- family: "2d",
191
- // The 2D grid is part of what these pages demonstrate, so it opens on even if the
192
- // previous page had it off.
193
- hideGrid: false,
194
- view2d: { width: 1260, height: 560 },
195
- columns: [
196
- column("filled", ["circle", "sector", "segment", "ellipse", "annulus", "capsule", "rhombus", "rect", "polygon", "triangle", "segment2d", "polyline2d"]),
197
- column("ring", ["circle", "sector", "segment", "ellipse", "annulus", "capsule", "rhombus", "rect", "polygon", "triangle"]),
198
- ],
199
- },
200
- ];
@@ -1,18 +0,0 @@
1
- /**
2
- * reference 2D reference pages.
3
- *
4
- * These are vgpu's own capability pages built on `frame.d2`, not ports of a reference: the
5
- * reference has no 2D API, so the models are reference `2d_gizmos` and `2d_shapes`. That also
6
- * means the coordinate convention is reference: the origin sits at the canvas centre, +y points up,
7
- * and one world unit covers one canvas pixel before the 2D camera's pan and zoom.
8
- *
9
- * Two conventions carry over from the text pages: a page heading in the top-left corner (a
10
- * screen-space block, so the labels stay put while the 2D camera pans), and one shape per column
11
- * with the row meaning stated once.
12
- */
13
- import type { FrameRecorder } from "./frame-recorder.js";
14
- /**
15
- * Dispatches the 2D pages. Returns false for every other id so `buildScene` can fall through to
16
- * the 3D scenes.
17
- */
18
- export declare function buildScene2D(id: string, recorder: FrameRecorder, time: number): boolean;
package/dist/scenes-2d.js DELETED
@@ -1,160 +0,0 @@
1
- /**
2
- * reference 2D reference pages.
3
- *
4
- * These are vgpu's own capability pages built on `frame.d2`, not ports of a reference: the
5
- * reference has no 2D API, so the models are reference `2d_gizmos` and `2d_shapes`. That also
6
- * means the coordinate convention is reference: the origin sits at the canvas centre, +y points up,
7
- * and one world unit covers one canvas pixel before the 2D camera's pan and zoom.
8
- *
9
- * Two conventions carry over from the text pages: a page heading in the top-left corner (a
10
- * screen-space block, so the labels stay put while the 2D camera pans), and one shape per column
11
- * with the row meaning stated once.
12
- */
13
- const TITLE = [0.92, 0.95, 1, 1];
14
- const HINT = [0.55, 0.62, 0.72, 1];
15
- const GRID = [0.32, 0.36, 0.44, 0.55];
16
- const FILL = [0.93, 0.95, 0.98, 1];
17
- const RING = [0.55, 0.72, 1, 1];
18
- const WARM = [1, 0.72, 0.36, 1];
19
- const COOL = [0.42, 0.86, 0.78, 1];
20
- const ACCENT = [1, 0.55, 0.66, 1];
21
- const ACTION = [0.98, 0.86, 0.42, 1];
22
- /** Page heading: a screen-space title and note, fixed to the top-left corner. */
23
- function heading(recorder, title, note) {
24
- recorder.text([24, 16, 0], title, { space: "screen", fontSize: 17, anchor: "top-left", color: TITLE });
25
- recorder.text([24, 38, 0], note, { space: "screen", fontSize: 12, anchor: "top-left", color: HINT });
26
- }
27
- /**
28
- * Dispatches the 2D pages. Returns false for every other id so `buildScene` can fall through to
29
- * the 3D scenes.
30
- */
31
- export function buildScene2D(id, recorder, time) {
32
- switch (id) {
33
- case "2d-gizmos":
34
- gizmos2D(recorder, time);
35
- return true;
36
- case "2d-shapes":
37
- shapes2D(recorder);
38
- return true;
39
- default:
40
- return false;
41
- }
42
- }
43
- /** The twelve reference 2D primitives, filled in one row and outlined in the next. */
44
- function shapes2D(recorder) {
45
- heading(recorder, "2D Shapes", "filled row, ring row · drag to pan, scroll to zoom");
46
- const d2 = recorder.d2;
47
- const columns = 12;
48
- const spacing = 100;
49
- const startX = -((columns - 1) * spacing) / 2;
50
- for (let index = 0; index < columns; index++) {
51
- const x = startX + index * spacing;
52
- drawShape(d2, index, [x, 110], true);
53
- // The two polyline shapes have no interior to outline.
54
- if (index < 10)
55
- drawShape(d2, index, [x, -110], false);
56
- }
57
- }
58
- /** One column of `shapes2D`, in the order reference `2d_shapes` example lists them. */
59
- function drawShape(d2, shape, center, filled) {
60
- const style = { fill: filled, strokeWidth: 4, color: filled ? FILL : RING };
61
- const [x, y] = center;
62
- switch (shape) {
63
- case 0: // Circle::new(50)
64
- d2.circle(center, 50, style);
65
- return;
66
- case 1: // CircularSector::new(50, 1.0)
67
- d2.sector(center, 50, { ...style, sweep: 1.0 });
68
- return;
69
- case 2: // CircularSegment::new(50, 1.25)
70
- d2.segment(center, 50, { ...style, sweep: 1.25 });
71
- return;
72
- case 3: // Ellipse::new(25, 50)
73
- d2.ellipse(center, [25, 50], style);
74
- return;
75
- case 4: // Annulus::new(25, 50)
76
- d2.annulus(center, 25, 50, style);
77
- return;
78
- case 5: // Capsule2d::new(25, 50)
79
- d2.capsule(center, 25, 50, style);
80
- return;
81
- case 6: // Rhombus::new(75, 100)
82
- d2.rhombus(center, [75, 100], style);
83
- return;
84
- case 7: // Rectangle::new(50, 100)
85
- d2.rect(center, [50, 100], style);
86
- return;
87
- case 8: // RegularPolygon::new(50, 6)
88
- d2.polygon(center, 50, 6, style);
89
- return;
90
- case 9: // Triangle2d::new(Vec2::Y * 50, Vec2::new(-50, -50), Vec2::new(50, -50))
91
- d2.triangle([x, y + 50], [x - 50, y - 50], [x + 50, y - 50], style);
92
- return;
93
- case 10: // Segment2d::new(Vec2::new(-50, 50), Vec2::new(50, -50))
94
- d2.line([x - 50, y + 50], [x + 50, y - 50], { width: 8, color: filled ? FILL : RING });
95
- return;
96
- default: // Polyline2d::new([(-50, 50), (0, -50), (50, 50)])
97
- d2.lineStrip([[x - 50, y + 50], [x, y - 50], [x + 50, y + 50]], {
98
- width: 8,
99
- joint: "round",
100
- color: filled ? FILL : RING,
101
- });
102
- }
103
- }
104
- /** reference `2d_gizmos` example, rebuilt with the stroke and shape primitives. */
105
- function gizmos2D(recorder, time) {
106
- heading(recorder, "2D Gizmos", "strokes and outlined shapes · drag to pan, scroll to zoom");
107
- const d2 = recorder.d2;
108
- // Background grid, drawn first so the strokes sit on top of it.
109
- const cell = 60;
110
- for (let index = -6; index <= 6; index++) {
111
- d2.line([index * cell, -260], [index * cell, 260], { width: 1, color: GRID });
112
- d2.line([-380, index * cell], [380, index * cell], { width: 1, color: GRID });
113
- }
114
- // line and ray.
115
- d2.line([-460, 200], [-300, 200], { width: 5, color: ACTION });
116
- d2.ray([-460, 140], [160, -40], { width: 5, color: COOL });
117
- // Joined strip (round joints) and a dashed stroke with the same width.
118
- d2.lineStrip([[-460, 60], [-410, 0], [-360, 60], [-310, 0], [-260, 60]], { width: 6, joint: "round", color: RING });
119
- d2.line([-460, -20], [-260, -20], { width: 6, dash: [20, 14, 0], color: RING });
120
- // Outlined boxes, one with rounded corners.
121
- d2.rect([-120, 170], [120, 80], { fill: false, strokeWidth: 4, color: WARM });
122
- d2.roundedRect([-120, 40], [140, 80], 26, { fill: false, strokeWidth: 4, color: WARM });
123
- d2.grid([-120, -100], [4, 3], [40, 40], { width: 2, color: WARM });
124
- // Circle, ellipse and an arc.
125
- d2.circle([120, 170], 55, { fill: false, strokeWidth: 4, color: ACCENT });
126
- d2.ellipse([120, 60], [75, 35], { fill: false, strokeWidth: 4, color: ACCENT });
127
- d2.arc([120, -80], 55, { fill: false, strokeWidth: 4, startAngle: 0.4, sweep: 2.2, color: ACCENT });
128
- // Cross marker.
129
- for (const [x, y] of [[340, 200], [400, 200], [370, 170], [370, 230]]) {
130
- d2.point([x, y], { size: 4, round: true, color: ACTION });
131
- }
132
- cross(d2, [340, 170], 34, ACTION);
133
- cross(d2, [340, 230], 34, ACTION);
134
- // Arrow: a shaft plus a filled triangle head that swings with time.
135
- const angle = 1.1 + Math.sin(time * 0.9) * 0.5;
136
- const origin = [330, 60];
137
- const tip = [origin[0] + Math.cos(angle) * 140, origin[1] + Math.sin(angle) * 140];
138
- const ux = Math.cos(angle);
139
- const uy = Math.sin(angle);
140
- const back = 22;
141
- const spread = 11;
142
- d2.line(origin, tip, { width: 5, color: ACTION });
143
- d2.triangle(tip, [tip[0] - ux * back - uy * spread, tip[1] - uy * back + ux * spread], [tip[0] - ux * back + uy * spread, tip[1] - uy * back - ux * spread], { color: ACTION });
144
- // A travelling sine curve, sampled into a strip.
145
- const wave = [];
146
- for (let step = 0; step <= 64; step++) {
147
- const x = -460 + step * 12;
148
- wave.push([x, -170 + Math.sin((x + time * 90) / 55) * 34]);
149
- }
150
- d2.lineStrip(wave, { width: 4, color: COOL });
151
- // Outlined hexagon and a filled diamond, the two closed shapes reference example draws last.
152
- d2.polygon([330, -170], 60, 6, { fill: false, strokeWidth: 4, color: WARM });
153
- d2.rhombus([450, -170], [90, 110], { color: ACCENT });
154
- }
155
- /** Two crossing strokes, reference `cross_2d`. */
156
- function cross(d2, center, size, color) {
157
- const [x, y] = center;
158
- d2.line([x - size, y], [x + size, y], { width: 3, color });
159
- d2.line([x, y - size], [x, y + size], { width: 3, color });
160
- }
@@ -1,46 +0,0 @@
1
- import type { FrameRecorder, Vec3, Color } from "./frame-recorder.js";
2
- export type SceneContext = {
3
- readonly time: number;
4
- readonly lineJoint?: "none" | "round" | "bevel" | "miter";
5
- };
6
- declare function lineColumnX(column: number): number;
7
- declare function lineRowZ(row: number): number;
8
- declare function lineStart(column: number, row: number): Vec3;
9
- declare function lineEnd(column: number, row: number): Vec3;
10
- declare function referenceStripPoints(column: number, row: number): Vec3[];
11
- declare function referenceLoopPoints(column: number, row: number): Vec3[];
12
- declare function circleColumnX(column: number): number;
13
- /** Raw reference layout data, exported so tests and future 3D labels share one source. */
14
- export declare const CIRCLE_REFERENCE: {
15
- readonly columns: 11;
16
- readonly columnSpacing: 2;
17
- readonly columnOffset: 0.5;
18
- readonly rowSpacing: 0.82;
19
- readonly radiusRowSpacing: 1.15;
20
- readonly startZ: -0.45;
21
- readonly radius: 0.32;
22
- readonly baseWidth: 2;
23
- readonly sceneOffset: Vec3;
24
- readonly solidColor: Color;
25
- readonly columnX: typeof circleColumnX;
26
- readonly center: (column: number, row: number) => Vec3;
27
- };
28
- /** Raw reference layout data for the Line example. */
29
- export declare const LINE_REFERENCE: {
30
- readonly columns: 7;
31
- readonly columnSpacing: 2;
32
- readonly rowSpacing: 0.78;
33
- readonly startZ: -0.45;
34
- readonly length: 1.1;
35
- readonly stripHalfDepth: 0.18;
36
- readonly loopHalfDepth: 0.25;
37
- readonly sceneOffset: Vec3;
38
- readonly columnX: typeof lineColumnX;
39
- readonly rowZ: typeof lineRowZ;
40
- readonly start: typeof lineStart;
41
- readonly end: typeof lineEnd;
42
- readonly strip: typeof referenceStripPoints;
43
- readonly loop: typeof referenceLoopPoints;
44
- };
45
- export declare function buildScene(id: string, recorder: FrameRecorder, time: number, lineJoint?: SceneContext["lineJoint"]): void;
46
- export {};