ngsolve-webgpu 0.0.4__tar.gz → 0.0.5__tar.gz

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 (51) hide show
  1. {ngsolve_webgpu-0.0.4/ngsolve_webgpu.egg-info → ngsolve_webgpu-0.0.5}/PKG-INFO +1 -1
  2. {ngsolve_webgpu-0.0.4 → ngsolve_webgpu-0.0.5}/docs/functions.ipynb +13 -0
  3. {ngsolve_webgpu-0.0.4 → ngsolve_webgpu-0.0.5}/ngsolve_webgpu/_version.py +2 -2
  4. {ngsolve_webgpu-0.0.4 → ngsolve_webgpu-0.0.5}/ngsolve_webgpu/cf.py +63 -2
  5. {ngsolve_webgpu-0.0.4 → ngsolve_webgpu-0.0.5}/ngsolve_webgpu/geometry.py +9 -6
  6. {ngsolve_webgpu-0.0.4 → ngsolve_webgpu-0.0.5}/ngsolve_webgpu/jupyter.py +5 -1
  7. {ngsolve_webgpu-0.0.4 → ngsolve_webgpu-0.0.5}/ngsolve_webgpu/mesh.py +40 -23
  8. {ngsolve_webgpu-0.0.4 → ngsolve_webgpu-0.0.5}/ngsolve_webgpu/shaders/eval/common.wgsl +1 -1
  9. {ngsolve_webgpu-0.0.4 → ngsolve_webgpu-0.0.5}/ngsolve_webgpu/shaders/eval/trig.wgsl +11 -8
  10. {ngsolve_webgpu-0.0.4 → ngsolve_webgpu-0.0.5}/ngsolve_webgpu/shaders/geo_edge.wgsl +25 -9
  11. {ngsolve_webgpu-0.0.4 → ngsolve_webgpu-0.0.5}/ngsolve_webgpu/shaders/shader.wgsl +34 -35
  12. {ngsolve_webgpu-0.0.4 → ngsolve_webgpu-0.0.5/ngsolve_webgpu.egg-info}/PKG-INFO +1 -1
  13. {ngsolve_webgpu-0.0.4 → ngsolve_webgpu-0.0.5}/.github/workflows/deploy.yml +0 -0
  14. {ngsolve_webgpu-0.0.4 → ngsolve_webgpu-0.0.5}/.gitignore +0 -0
  15. {ngsolve_webgpu-0.0.4 → ngsolve_webgpu-0.0.5}/LICENSE +0 -0
  16. {ngsolve_webgpu-0.0.4 → ngsolve_webgpu-0.0.5}/docs/Quickstart.ipynb +0 -0
  17. {ngsolve_webgpu-0.0.4 → ngsolve_webgpu-0.0.5}/docs/_static/custom.css +0 -0
  18. {ngsolve_webgpu-0.0.4 → ngsolve_webgpu-0.0.5}/docs/_static/logo.svg +0 -0
  19. {ngsolve_webgpu-0.0.4 → ngsolve_webgpu-0.0.5}/docs/_static/logo_dark.png +0 -0
  20. {ngsolve_webgpu-0.0.4 → ngsolve_webgpu-0.0.5}/docs/conf.py +0 -0
  21. {ngsolve_webgpu-0.0.4 → ngsolve_webgpu-0.0.5}/docs/index.rst +0 -0
  22. {ngsolve_webgpu-0.0.4 → ngsolve_webgpu-0.0.5}/docs/mesh.ipynb +0 -0
  23. {ngsolve_webgpu-0.0.4 → ngsolve_webgpu-0.0.5}/ngsolve_webgpu/__init__.py +0 -0
  24. {ngsolve_webgpu-0.0.4 → ngsolve_webgpu-0.0.5}/ngsolve_webgpu/animate.py +0 -0
  25. {ngsolve_webgpu-0.0.4 → ngsolve_webgpu-0.0.5}/ngsolve_webgpu/clipping.py +0 -0
  26. {ngsolve_webgpu-0.0.4 → ngsolve_webgpu-0.0.5}/ngsolve_webgpu/isosurface.py +0 -0
  27. {ngsolve_webgpu-0.0.4 → ngsolve_webgpu-0.0.5}/ngsolve_webgpu/lic.py +0 -0
  28. {ngsolve_webgpu-0.0.4 → ngsolve_webgpu-0.0.5}/ngsolve_webgpu/shaders/clipping/common.wgsl +0 -0
  29. {ngsolve_webgpu-0.0.4 → ngsolve_webgpu-0.0.5}/ngsolve_webgpu/shaders/clipping/compute.wgsl +0 -0
  30. {ngsolve_webgpu-0.0.4 → ngsolve_webgpu-0.0.5}/ngsolve_webgpu/shaders/clipping/render.wgsl +0 -0
  31. {ngsolve_webgpu-0.0.4 → ngsolve_webgpu-0.0.5}/ngsolve_webgpu/shaders/compute.wgsl +0 -0
  32. {ngsolve_webgpu-0.0.4 → ngsolve_webgpu-0.0.5}/ngsolve_webgpu/shaders/elements3d.wgsl +0 -0
  33. {ngsolve_webgpu-0.0.4 → ngsolve_webgpu-0.0.5}/ngsolve_webgpu/shaders/eval/seg.wgsl +0 -0
  34. {ngsolve_webgpu-0.0.4 → ngsolve_webgpu-0.0.5}/ngsolve_webgpu/shaders/eval/tet.wgsl +0 -0
  35. {ngsolve_webgpu-0.0.4 → ngsolve_webgpu-0.0.5}/ngsolve_webgpu/shaders/geo_face.wgsl +0 -0
  36. {ngsolve_webgpu-0.0.4 → ngsolve_webgpu-0.0.5}/ngsolve_webgpu/shaders/geo_vertex.wgsl +0 -0
  37. {ngsolve_webgpu-0.0.4 → ngsolve_webgpu-0.0.5}/ngsolve_webgpu/shaders/isosurface/compute.wgsl +0 -0
  38. {ngsolve_webgpu-0.0.4 → ngsolve_webgpu-0.0.5}/ngsolve_webgpu/shaders/isosurface/negative_clipping.wgsl +0 -0
  39. {ngsolve_webgpu-0.0.4 → ngsolve_webgpu-0.0.5}/ngsolve_webgpu/shaders/isosurface/negative_surface.wgsl +0 -0
  40. {ngsolve_webgpu-0.0.4 → ngsolve_webgpu-0.0.5}/ngsolve_webgpu/shaders/isosurface/render.wgsl +0 -0
  41. {ngsolve_webgpu-0.0.4 → ngsolve_webgpu-0.0.5}/ngsolve_webgpu/shaders/line_integral_convolution.wgsl +0 -0
  42. {ngsolve_webgpu-0.0.4 → ngsolve_webgpu-0.0.5}/ngsolve_webgpu/shaders/mesh.wgsl +0 -0
  43. {ngsolve_webgpu-0.0.4 → ngsolve_webgpu-0.0.5}/ngsolve_webgpu/shaders/numbers.wgsl +0 -0
  44. {ngsolve_webgpu-0.0.4 → ngsolve_webgpu-0.0.5}/ngsolve_webgpu/shaders/uniforms.wgsl +0 -0
  45. {ngsolve_webgpu-0.0.4 → ngsolve_webgpu-0.0.5}/ngsolve_webgpu.egg-info/SOURCES.txt +0 -0
  46. {ngsolve_webgpu-0.0.4 → ngsolve_webgpu-0.0.5}/ngsolve_webgpu.egg-info/dependency_links.txt +0 -0
  47. {ngsolve_webgpu-0.0.4 → ngsolve_webgpu-0.0.5}/ngsolve_webgpu.egg-info/top_level.txt +0 -0
  48. {ngsolve_webgpu-0.0.4 → ngsolve_webgpu-0.0.5}/pyproject.toml +0 -0
  49. {ngsolve_webgpu-0.0.4 → ngsolve_webgpu-0.0.5}/redraw.ipynb +0 -0
  50. {ngsolve_webgpu-0.0.4 → ngsolve_webgpu-0.0.5}/setup.cfg +0 -0
  51. {ngsolve_webgpu-0.0.4 → ngsolve_webgpu-0.0.5}/webgpu.ipynb +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ngsolve_webgpu
3
- Version: 0.0.4
3
+ Version: 0.0.5
4
4
  Summary: WebGPU/Pyodide based rendering tools for Netgen/NGSolve
5
5
  Author-email: Matthias Hochsteger <mhochsteger@cerbsim.com>, Christopher Lackner <clackner@cerbsim.com>
6
6
  License-Expression: LGPL-2.1-or-later
@@ -75,6 +75,19 @@
75
75
  "id": "8cea4e67-8bb6-4b10-8d13-696b0064cbef",
76
76
  "metadata": {},
77
77
  "outputs": [],
78
+ "source": [
79
+ "from ngsolve_webgpu.cf import FieldLines\n",
80
+ "cf = CF((-y,x,0.1))\n",
81
+ "fieldlines = FieldLines(cf, mesh)\n",
82
+ "scene = Draw([fieldlines])"
83
+ ]
84
+ },
85
+ {
86
+ "cell_type": "code",
87
+ "execution_count": null,
88
+ "id": "f7356d5f-1a45-48e1-815b-e11ff0461f17",
89
+ "metadata": {},
90
+ "outputs": [],
78
91
  "source": []
79
92
  }
80
93
  ],
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '0.0.4'
21
- __version_tuple__ = version_tuple = (0, 0, 4)
20
+ __version__ = version = '0.0.5'
21
+ __version_tuple__ = version_tuple = (0, 0, 5)
@@ -6,6 +6,7 @@ import numpy as np
6
6
  from webgpu.clipping import Clipping
7
7
  from webgpu.colormap import Colormap
8
8
  from webgpu.renderer import Renderer, RenderOptions, check_timestamp
9
+ from webgpu.shapes import ShapeRenderer, generate_cylinder
9
10
  from webgpu.utils import (
10
11
  BufferBinding,
11
12
  UniformBinding,
@@ -178,8 +179,16 @@ class FunctionData:
178
179
  return self.mesh_data.num_elements
179
180
 
180
181
  @property
181
- def curvature_subdivision(self):
182
- return self.mesh_data.curvature_subdivision
182
+ def subdivision(self):
183
+ return self.mesh_data.subdivision
184
+
185
+ @property
186
+ def curvature_data(self):
187
+ return self.mesh_data.curvature_data
188
+
189
+ @property
190
+ def deformation_data(self):
191
+ return self.mesh_data.deformation_data
183
192
 
184
193
  def _create_data(self):
185
194
  self.gpu_2d = None
@@ -280,6 +289,7 @@ class CFRenderer(MeshElements2d):
280
289
  self.colormap.set_min_max(self.data.minval, self.data.maxval, set_autoscale=False)
281
290
  self.colormap._update_and_create_render_pipeline(options)
282
291
  self.component_buffer = buffer_from_array(np.array([self.component], np.int32))
292
+ self.shader_defines["MAX_EVAL_ORDER"] = self.data.order
283
293
 
284
294
  def get_bounding_box(self):
285
295
  return self.data.get_bounding_box()
@@ -359,3 +369,54 @@ class VectorCFRenderer(VectorRenderer):
359
369
  [values[:, 0], values[:, 1], np.zeros_like(values[:, 0])], dtype=np.float32
360
370
  ).T.reshape(-1)
361
371
  super().update(options)
372
+
373
+
374
+ class FieldLines(ShapeRenderer):
375
+ def __init__(
376
+ self,
377
+ cf,
378
+ start_region: ngs.Region | ngs.Mesh,
379
+ num_lines: int = 100,
380
+ length: float = 0.5,
381
+ max_points_per_line: float = 500,
382
+ thickness: float = 0.0015,
383
+ tolerance: float = 0.0005,
384
+ direction: int = 0,
385
+ ):
386
+ self.fieldline_options = {
387
+ "thickness": thickness,
388
+ "num_lines": num_lines,
389
+ "length": length,
390
+ "max_points_per_line": max_points_per_line,
391
+ "tolerance": tolerance,
392
+ "direction": direction,
393
+ }
394
+ self.cf = cf
395
+ if isinstance(start_region, ngs.Mesh):
396
+ self.mesh = start_region
397
+ self.start_region = start_region.Materials(".*")
398
+ else:
399
+ self.start_region = start_region
400
+ self.mesh = start_region.mesh
401
+
402
+ bbox = self.mesh.ngmesh.bounding_box
403
+ thickness = (bbox[1] - bbox[0]).Norm() * thickness
404
+
405
+ cyl = generate_cylinder(8, thickness, 1.0, top_face=False, bottom_face=False)
406
+
407
+ super().__init__(cyl, None, None)
408
+ self.scale_mode = ShapeRenderer.SCALE_Z
409
+
410
+ def get_bounding_box(self):
411
+ pmin, pmax = self.mesh.ngmesh.bounding_box
412
+ return ([pmin[0], pmin[1], pmin[2]], [pmax[0], pmax[1], pmax[2]])
413
+
414
+ def update(self, options):
415
+ from ngsolve.webgui import FieldLines
416
+
417
+ data = FieldLines(self.cf, self.start_region, **self.fieldline_options)
418
+ self.positions = data["pstart"]
419
+ self.directions = data["pend"]
420
+ self.directions = self.directions - self.positions
421
+ self.values = data["value"]
422
+ super().update(options)
@@ -71,7 +71,6 @@ class BaseGeometryRenderer(Renderer):
71
71
 
72
72
  class GeometryFaceRenderer(BaseGeometryRenderer):
73
73
  n_vertices: int = 3
74
- depthBias: int = 1
75
74
  clipping: Clipping | None = None
76
75
 
77
76
  def __init__(self, geo):
@@ -93,7 +92,7 @@ class GeometryFaceRenderer(BaseGeometryRenderer):
93
92
  def update(self, options, vis_data):
94
93
  self.bounding_box = (vis_data["min"], vis_data["max"])
95
94
  verts = vis_data["vertices"]
96
- self.n_instances = len(verts) // 6
95
+ self.n_instances = len(verts) // 9
97
96
  normals = vis_data["normals"]
98
97
  indices = vis_data["indices"]
99
98
  if self.colors is None:
@@ -122,11 +121,15 @@ class GeometryEdgeRenderer(BaseGeometryRenderer):
122
121
  topology: PrimitiveTopology = PrimitiveTopology.triangle_strip
123
122
  clipping: Clipping | None = None
124
123
 
124
+ # make sure that edges are rendered on top of faces
125
+ depthBias: int = -5
126
+ depthBiasSlopeScale: int = -5
127
+
125
128
  def __init__(self, geo):
126
129
  self.geo = geo
127
130
  super().__init__(label="GeometryEdges")
128
131
  self.active = True
129
- self.thickness = 0.02
132
+ self.thickness = 0.015
130
133
  self._buffers = {}
131
134
 
132
135
  def set_colors(self, colors):
@@ -160,7 +163,6 @@ class GeometryEdgeRenderer(BaseGeometryRenderer):
160
163
  class GeometryVertexRenderer(BaseGeometryRenderer):
161
164
  n_vertices: int = 4
162
165
  topology: PrimitiveTopology = PrimitiveTopology.triangle_strip
163
- depthBias: int = 0
164
166
  clipping: Clipping | None = None
165
167
 
166
168
  def __init__(self, geo):
@@ -214,7 +216,6 @@ class GeometryRenderer(MultipleRenderer):
214
216
 
215
217
  def update(self, options: RenderOptions):
216
218
  vis_data = self.geo._visualizationData()
217
- self.bounding_box = (vis_data["min"] + 1e-7, vis_data["max"] - 1e-7)
218
219
 
219
220
  for ro in self.render_objects:
220
221
  ro.update(options, vis_data)
@@ -222,7 +223,9 @@ class GeometryRenderer(MultipleRenderer):
222
223
  self.canvas = options.canvas
223
224
 
224
225
  def get_bounding_box(self):
225
- return self.bounding_box
226
+ pmin, pmax = self.geo.shape.bounding_box
227
+ return ([pmin[0], pmin[1], pmin[2]],
228
+ [pmax[0], pmax[1], pmax[2]])
226
229
 
227
230
  def render(self, encoder):
228
231
  for r in self.render_objects:
@@ -107,6 +107,7 @@ def Draw(
107
107
  order: int = 2,
108
108
  vectors=None,
109
109
  deformation=None,
110
+ subdivision: int | None = None,
110
111
  **kwargs,
111
112
  ):
112
113
  """
@@ -171,7 +172,10 @@ def Draw(
171
172
  render_objects.append(vcf)
172
173
 
173
174
  if deformation:
174
- mesh_data.deformation_data = FunctionData(mesh_data, deformation, order=order)
175
+ mesh_data.deformation_data = FunctionData(mesh_data, deformation, order=min(order, 3))
176
+
177
+ if subdivision is not None:
178
+ mesh_data.subdivision = subdivision
175
179
 
176
180
  scene = wj.Draw(render_objects, width, height)
177
181
  if dim == 3:
@@ -1,6 +1,8 @@
1
1
  from enum import Enum
2
+
2
3
  import netgen.meshing
3
4
  import numpy as np
5
+ from webgpu.clipping import Clipping
4
6
  from webgpu.font import Font
5
7
  from webgpu.renderer import Renderer, RenderOptions, check_timestamp
6
8
 
@@ -9,13 +11,12 @@ from webgpu.uniforms import UniformBase, ct
9
11
  from webgpu.utils import (
10
12
  BufferBinding,
11
13
  UniformBinding,
12
- read_shader_file,
13
14
  buffer_from_array,
14
- uniform_from_array,
15
15
  get_device,
16
+ read_shader_file,
17
+ uniform_from_array,
16
18
  )
17
19
  from webgpu.webgpu_api import *
18
- from webgpu.clipping import Clipping
19
20
 
20
21
 
21
22
  class Binding:
@@ -27,7 +28,7 @@ class Binding:
27
28
  VERTICES = 12
28
29
  TRIGS_INDEX = 13
29
30
  CURVATURE_VALUES_2D = 14
30
- CURVATURE_SUBDIVISION = 15
31
+ SUBDIVISION = 15
31
32
  DEFORMATION_VALUES = 16
32
33
  DEFORMATION_SCALE = 17
33
34
 
@@ -95,7 +96,7 @@ class MeshData:
95
96
  num_elements: dict[str | ElType, int]
96
97
  elements: dict[str | ElType, np.ndarray]
97
98
  gpu_elements: dict[str | ElType, Buffer]
98
- curvature_subdivision: int
99
+ subdivision: int
99
100
 
100
101
  mesh: netgen.meshing.Mesh
101
102
  curvature_data = None
@@ -121,7 +122,7 @@ class MeshData:
121
122
  self.num_elements = {}
122
123
  self.elements = {}
123
124
  self.gpu_elements = {}
124
- self.curvature_subdivision = None
125
+ self.subdivision = None
125
126
  self._deformation_scale = 1
126
127
 
127
128
  @property
@@ -227,27 +228,34 @@ class MeshData:
227
228
  if self.deformation_data is not None:
228
229
  curve_order = max(curve_order, self.deformation_data.order)
229
230
  if curve_order > 1:
230
- from .cf import FunctionData
231
231
  import ngsolve as ngs
232
232
 
233
+ from .cf import FunctionData
234
+
233
235
  cf = ngs.CF((ngs.x, ngs.y, ngs.z))
234
236
  self.curvature_data = FunctionData(self, cf, curve_order)
235
237
  else:
236
- if self.curvature_subdivision is None:
237
- self.curvature_subdivision = 1
238
- if self.curvature_subdivision is None:
238
+ if self.subdivision is None:
239
+ self.subdivision = 1
240
+ if self.subdivision is None:
239
241
  deformation_order = 1
240
242
  if self.deformation_data:
241
243
  deformation_order = self.deformation_data.order
242
- subdiv = max(curve_order, deformation_order)
243
- if subdiv > 1:
244
- subdiv *= 2
245
- self.curvature_subdivision = subdiv
244
+ order = max(curve_order, deformation_order)
245
+ if order > 3:
246
+ subdiv = (order + 2) // 3 + 1
247
+ elif order > 1:
248
+ subdiv = 3
249
+ else:
250
+ subdiv = 1
251
+ self.subdivision = subdiv
246
252
 
247
253
  self._last_mesh_timestamp = mesh._timestamp
248
254
 
249
255
  def get_bounding_box(self):
250
- return (self.pmin, self.pmax)
256
+ pmin, pmax = self.mesh.bounding_box
257
+ return ([pmin[0], pmin[1], pmin[2]],
258
+ [pmax[0], pmax[1], pmax[2]])
251
259
 
252
260
  def get_buffers(self):
253
261
  for eltype in self.elements:
@@ -255,10 +263,10 @@ class MeshData:
255
263
  self.gpu_elements[eltype] = buffer_from_array(
256
264
  self.elements[eltype], label="mesh_" + str(eltype)
257
265
  )
258
- if "curvature_subdivision" not in self.gpu_elements:
259
- self.gpu_elements["curvature_subdivision"] = uniform_from_array(
260
- np.array([self.curvature_subdivision], dtype=np.uint32),
261
- label="curvature_subdivision",
266
+ if "subdivision" not in self.gpu_elements:
267
+ self.gpu_elements["subdivision"] = uniform_from_array(
268
+ np.array([self.subdivision], dtype=np.uint32),
269
+ label="subdivision",
262
270
  )
263
271
  if "deformation_scale" not in self.gpu_elements:
264
272
  self.gpu_elements["deformation_scale"] = uniform_from_array(
@@ -283,8 +291,8 @@ class MeshElements2d(Renderer):
283
291
  def update(self, options: RenderOptions):
284
292
  self.clipping.update(options)
285
293
  self.data.update(options)
286
- self.curvature_subdivision = self.data.curvature_subdivision
287
- self.n_vertices = 3 * self.curvature_subdivision**2
294
+ self.subdivision = self.data.subdivision
295
+ self.n_vertices = 3 * self.subdivision**2
288
296
 
289
297
  self._buffers = self.data.get_buffers()
290
298
  self.n_instances = self.data.num_elements[ElType.TRIG]
@@ -292,6 +300,14 @@ class MeshElements2d(Renderer):
292
300
  np.array(self.color, dtype=np.float32), label="color_uniform"
293
301
  )
294
302
 
303
+ order = 1
304
+ if self.data.curvature_data:
305
+ order = max(order, self.data.curvature_data.order)
306
+ if self.data.deformation_data:
307
+ order = max(order, self.data.deformation_data.order)
308
+
309
+ self.shader_defines = {"MAX_EVAL_ORDER": 1, "MAX_EVAL_ORDER_VEC3": order + 1}
310
+
295
311
  def get_bounding_box(self):
296
312
  return self.data.get_bounding_box()
297
313
 
@@ -303,7 +319,7 @@ class MeshElements2d(Renderer):
303
319
  BufferBinding(Binding.CURVATURE_VALUES_2D, self._buffers["curvature_2d"]),
304
320
  BufferBinding(Binding.DEFORMATION_VALUES, self._buffers["deformation_2d"]),
305
321
  UniformBinding(Binding.DEFORMATION_SCALE, self._buffers["deformation_scale"]),
306
- UniformBinding(Binding.CURVATURE_SUBDIVISION, self._buffers["curvature_subdivision"]),
322
+ UniformBinding(Binding.SUBDIVISION, self._buffers["subdivision"]),
307
323
  ]
308
324
  if hasattr(self, "color_uniform"):
309
325
  bindings.append(BufferBinding(54, self.color_uniform))
@@ -315,6 +331,7 @@ class MeshElements2d(Renderer):
315
331
 
316
332
  class MeshWireframe2d(MeshElements2d):
317
333
  depthBias: int = 0
334
+ depthBiasSlopeScale: float = 0.
318
335
  topology: PrimitiveTopology = PrimitiveTopology.line_strip
319
336
  color = (0, 0, 0, 1)
320
337
  fragment_entry_point: str = "fragmentWireframe2d"
@@ -322,7 +339,7 @@ class MeshWireframe2d(MeshElements2d):
322
339
 
323
340
  def update(self, options: RenderOptions):
324
341
  super().update(options)
325
- self.n_vertices = 3 * self.curvature_subdivision + 1
342
+ self.n_vertices = 3 * self.subdivision + 1
326
343
 
327
344
 
328
345
  class El3dUniform(UniformBase):
@@ -1,7 +1,7 @@
1
1
  @group(0) @binding(13) var<storage> u_function_values_3d : array<f32>;
2
2
  @group(0) @binding(10) var<storage> u_function_values_2d : array<f32>;
3
3
  @group(0) @binding(14) var<storage> u_curvature_values_2d : array<f32>;
4
- @group(0) @binding(15) var<uniform> u_curvature_subdivision : u32;
4
+ @group(0) @binding(15) var<uniform> u_subdivision : u32;
5
5
  @group(0) @binding(16) var<storage> u_deformation_values_2d : array<f32>;
6
6
  @group(0) @binding(17) var<uniform> u_deformation_scale : f32;
7
7
  @group(0) @binding(55) var<storage> u_function_component: i32;
@@ -1,11 +1,14 @@
1
1
  #import ngsolve/eval/common
2
2
 
3
+ const N_DOFS_TRIG: u32 = (@MAX_EVAL_ORDER@+1) * (@MAX_EVAL_ORDER@ + 2) / 2;
4
+ const N_DOFS_TRIG_VEC3: u32 = (@MAX_EVAL_ORDER_VEC3@+1) * (@MAX_EVAL_ORDER_VEC3@ + 2) / 2;
5
+
3
6
  fn evalTrig(data: ptr<storage, array<f32>, read>, id: u32, icomp: i32, lam: vec2<f32>) -> f32 {
4
7
  var order: i32 = i32((*data)[1]);
5
8
  let ncomp: u32 = u32((*data)[0]);
6
9
  var ndof: u32 = u32((order + 1) * (order + 2) / 2);
7
10
 
8
- var v: array<f32, 28>;
11
+ var v: array<f32, N_DOFS_TRIG>;
9
12
  let offset: u32 = ndof * id * ncomp + VALUES_OFFSET;
10
13
  let stride: u32 = ncomp;
11
14
 
@@ -40,9 +43,9 @@ fn evalTrig(data: ptr<storage, array<f32>, read>, id: u32, icomp: i32, lam: vec2
40
43
  return v[0];
41
44
  }
42
45
 
43
- fn _evalTrigVec3Data(order: i32, data: array<vec3f, 28>, lam: vec2f, dy: i32) -> vec3f {
46
+ fn _evalTrigVec3Data(order: i32, data: array<vec3f, N_DOFS_TRIG_VEC3>, lam: vec2f, dy: i32) -> vec3f {
44
47
  let b = vec3f(lam.x, lam.y, 1.0 - lam.x - lam.y);
45
- var v: array<vec3f, 28> = data;
48
+ var v: array<vec3f, N_DOFS_TRIG_VEC3> = data;
46
49
 
47
50
  for (var n = order; n > 0; n--) {
48
51
  var i0 = 0;
@@ -62,7 +65,7 @@ fn evalTrigVec3(data: ptr<storage, array<f32>, read>, id: u32, lam: vec2<f32>) -
62
65
  let ncomp: u32 = u32((*data)[0]);
63
66
  var ndof: u32 = u32((order + 1) * (order + 2) / 2);
64
67
 
65
- var v: array<vec3f, 28>;
68
+ var v: array<vec3f, N_DOFS_TRIG_VEC3>;
66
69
  let offset: u32 = ndof * id * ncomp + VALUES_OFFSET;
67
70
  let stride: u32 = ncomp;
68
71
 
@@ -81,7 +84,7 @@ fn evalTrigVec3Grad(data: ptr<storage, array<f32>, read>, id: u32, lam: vec2<f32
81
84
  var ndof: u32 = u32((order + 1) * (order + 2) / 2);
82
85
  let dy = order + 1;
83
86
 
84
- var v: array<vec3f, 28>;
87
+ var v: array<vec3f, N_DOFS_TRIG_VEC3>;
85
88
  let offset: u32 = ndof * id * ncomp + VALUES_OFFSET;
86
89
  let stride: u32 = ncomp;
87
90
 
@@ -94,12 +97,12 @@ fn evalTrigVec3Grad(data: ptr<storage, array<f32>, read>, id: u32, lam: vec2<f32
94
97
  var result: mat3x3<f32>;
95
98
 
96
99
  result[0] = _evalTrigVec3Data(order, v, lam, dy);
97
- var vd: array<vec3f, 28>;
100
+ var vd: array<vec3f, N_DOFS_TRIG_VEC3>;
98
101
 
99
102
  var i0 = 0;
100
103
  for (var iy = 0; iy < order; iy++) {
101
104
  for (var ix = 0; ix < order - iy; ix++) {
102
- vd[i0 + ix] = v[i0 + ix + 1] - v[i0 + ix];
105
+ vd[i0 + ix] = v[i0 + ix] - v[i0 + ix + dy - iy];
103
106
  }
104
107
  i0 += dy - iy;
105
108
  }
@@ -109,7 +112,7 @@ fn evalTrigVec3Grad(data: ptr<storage, array<f32>, read>, id: u32, lam: vec2<f32
109
112
  i0 = 0;
110
113
  for (var iy = 0; iy < order; iy++) {
111
114
  for (var ix = 0; ix < order - iy; ix++) {
112
- vd[i0 + ix] = v[i0 + ix + dy - iy] - v[i0 + ix + 1];
115
+ vd[i0 + ix] = v[i0 + ix + 1] - v[i0 + ix + dy - iy];
113
116
  }
114
117
  i0 += dy - iy;
115
118
  }
@@ -23,19 +23,35 @@ fn vertex_main(@builtin(vertex_index) vertId: u32,
23
23
  let p2 = vec3f(u_vertices[instanceId * 6 + 3],
24
24
  u_vertices[instanceId * 6 + 4],
25
25
  u_vertices[instanceId * 6 + 5]);
26
- let tp1 = cameraMapPoint(p1);
27
- let tp2 = cameraMapPoint(p2);
28
- let v = normalize(tp2.xy*tp1.w - tp1.xy*tp2.w);
29
- let v2 = vec2<f32>(-v.y, v.x);
30
- var pos: vec4<f32>;
26
+
27
+ // thick lines in screen space,
28
+ // see https://www.iquilezles.org/www/articles/thicklines/thicklines.htm
29
+ var tp1 = cameraMapPoint(p1);
30
+ var tp2 = cameraMapPoint(p2);
31
+ var sp1 = tp1.xy/tp1.w;
32
+ var sp2 = tp2.xy/tp2.w;
33
+ sp1.x *= u_camera.aspect;
34
+ sp2.x *= u_camera.aspect;
35
+ let v = normalize(sp2 - sp1);
36
+ var normal = vec2<f32>(-v.y, v.x) * u_thickness * 0.5;
37
+ normal.x = normal.x / u_camera.aspect;
38
+ var pos : vec4<f32>;
31
39
  if(vertId == 0) {
32
- pos = vec4<f32>(tp1.xy + (-0.5*v.xy + v2) * u_thickness/2.*tp1.w, tp1.zw); }
40
+ pos = tp1;
41
+ normal = -normal;
42
+ }
33
43
  else if(vertId == 1) {
34
- pos = vec4<f32>(tp1.xy + (-0.5*v.xy + - v2) * u_thickness/2.*tp1.w, tp1.zw); }
44
+ pos = tp1;
45
+ }
35
46
  else if(vertId == 2) {
36
- pos = vec4<f32>(tp2.xy + (0.5*v.xy + v2) * u_thickness/2.*tp2.w, tp2.zw); }
47
+ pos = tp2;
48
+ normal = -normal;
49
+ }
37
50
  else {
38
- pos = vec4<f32>(tp2.xy + (0.5*v.xy - v2) * u_thickness/2.*tp2.w, tp2.zw); }
51
+ pos = tp2;
52
+ }
53
+
54
+ pos = vec4<f32>(pos.xy + normal*pos.w, pos.zw);
39
55
 
40
56
  return GeoEdgeInput(pos, u_indices[instanceId]);
41
57
  }
@@ -38,7 +38,7 @@ fn vertexEdgeP1(@builtin(vertex_index) vertexId: u32, @builtin(instance_index) e
38
38
  }
39
39
 
40
40
  fn calcTrig(p: array<vec3<f32>, 3>, vertexId: u32, trigId: u32) -> VertexOutput2d {
41
- let subdivision = u_curvature_subdivision;
41
+ let subdivision = u_subdivision;
42
42
  let h = 1.0 / f32(subdivision);
43
43
 
44
44
  var lam = vec2f(0.0, 0.0);
@@ -51,14 +51,16 @@ fn calcTrig(p: array<vec3<f32>, 3>, vertexId: u32, trigId: u32) -> VertexOutput2
51
51
 
52
52
  if subdivision == 1 {
53
53
  position = p[vertexId];
54
- normal = cross(p[1] - p[0], p[2] - p[0]);
55
54
  if (u_deformation_values_2d[0] != -1.) {
56
55
  let pos_and_gradients = u_deformation_scale * evalTrigVec3Grad(&u_deformation_values_2d, trigId, lam);
57
- position += pos_and_gradients[0];
58
- var v1 = p[1] - p[0] + pos_and_gradients[1];
59
- var v2 = p[2] - p[0] + pos_and_gradients[2];
56
+ position += u_deformation_scale * pos_and_gradients[0];
57
+ var v1 = p[0] - p[2] + u_deformation_scale * pos_and_gradients[1];
58
+ var v2 = p[1] - p[2] + u_deformation_scale * pos_and_gradients[2];
60
59
  normal = normalize(cross(v1, v2));
61
60
  }
61
+ else {
62
+ normal = cross(p[1] - p[0], p[2] - p[0]);
63
+ }
62
64
  } else {
63
65
  var subTrigId: u32 = vertexId / 3u;
64
66
  var ix = subTrigId % subdivision;
@@ -115,46 +117,43 @@ fn vertexWireframe2d(@builtin(vertex_index) vertexId: u32, @builtin(instance_ind
115
117
  vec3<f32>(vertices[vid[2] ], vertices[vid[2] + 1], vertices[vid[2] + 2])
116
118
  );
117
119
 
118
- let subdivision = u_curvature_subdivision;
120
+ let subdivision = u_subdivision;
119
121
  let h = 1./ f32(subdivision);
120
122
  var lam = vec2f(0.0, 0.0);
121
123
  var position: vec3f;
124
+ var side = vertexId / subdivision;
125
+ if (side >= 2u) {
126
+ side = 2u;
127
+ }
128
+ var subId = vertexId - subdivision * side;
129
+ if(side == 0u)
130
+ {
131
+ lam[0] = h * f32(subId);
132
+ lam[1] = 0.;
133
+ }
134
+ else {
135
+ if(side == 1u)
136
+ {
137
+ lam[0] = 1.0 - h * f32(subId);
138
+ lam[1] = h * f32(subId);
139
+ }
140
+ else
141
+ {
142
+ lam[0] = 0.;
143
+ lam[1] = 1. - h * f32(subId);
144
+ }
145
+ }
122
146
  if(subdivision == 1)
123
147
  {
124
- position = p[vertexId % 3];
125
- if (u_deformation_values_2d[0] != -1.) {
126
- position += u_deformation_scale * evalTrigVec3(&u_deformation_values_2d, trigId, lam);
127
- }
148
+ position = p[(vertexId+2)%3u];
128
149
  }
129
150
  else
130
151
  {
131
- var side = vertexId / subdivision;
132
- if (side >= 2u) {
133
- side = 2u;
134
- }
135
- var subId = vertexId - subdivision * side;
136
- if(side == 0u)
137
- {
138
- lam[0] = h * f32(subId);
139
- lam[1] = 0.;
140
- }
141
- else {
142
- if(side == 1u)
143
- {
144
- lam[0] = 1.0 - h * f32(subId);
145
- lam[1] = h * f32(subId);
146
- }
147
- else
148
- {
149
- lam[0] = 0.;
150
- lam[1] = 1. - h * f32(subId);
151
- }
152
- }
153
152
  position = evalTrigVec3(&u_curvature_values_2d, trigId, lam);
154
- if (u_deformation_values_2d[0] != -1.) {
155
- position += u_deformation_scale * evalTrigVec3(&u_deformation_values_2d, trigId, lam);
156
- }
157
153
  }
154
+ if (u_deformation_values_2d[0] != -1.) {
155
+ position += u_deformation_scale * evalTrigVec3(&u_deformation_values_2d, trigId, lam);
156
+ }
158
157
  return VertexOutput2d(cameraMapPoint(position), position, lam, trigId,
159
158
  normalize(cross(p[1] - p[0], p[2] - p[0])));
160
159
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ngsolve_webgpu
3
- Version: 0.0.4
3
+ Version: 0.0.5
4
4
  Summary: WebGPU/Pyodide based rendering tools for Netgen/NGSolve
5
5
  Author-email: Matthias Hochsteger <mhochsteger@cerbsim.com>, Christopher Lackner <clackner@cerbsim.com>
6
6
  License-Expression: LGPL-2.1-or-later
File without changes
File without changes