ncca-ngl 0.3.4__py3-none-any.whl → 0.5.0__py3-none-any.whl

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 (56) hide show
  1. ncca/ngl/PrimData/pack_arrays.py +2 -3
  2. ncca/ngl/__init__.py +3 -4
  3. ncca/ngl/base_mesh.py +28 -20
  4. ncca/ngl/image.py +1 -3
  5. ncca/ngl/mat2.py +79 -53
  6. ncca/ngl/mat3.py +104 -185
  7. ncca/ngl/mat4.py +144 -309
  8. ncca/ngl/prim_data.py +42 -36
  9. ncca/ngl/primitives.py +2 -2
  10. ncca/ngl/pyside_event_handling_mixin.py +0 -108
  11. ncca/ngl/quaternion.py +69 -36
  12. ncca/ngl/shader.py +0 -116
  13. ncca/ngl/shader_program.py +94 -117
  14. ncca/ngl/texture.py +5 -2
  15. ncca/ngl/util.py +7 -0
  16. ncca/ngl/vec2.py +58 -292
  17. ncca/ngl/vec2_array.py +79 -28
  18. ncca/ngl/vec3.py +59 -340
  19. ncca/ngl/vec3_array.py +76 -23
  20. ncca/ngl/vec4.py +90 -190
  21. ncca/ngl/vec4_array.py +78 -27
  22. ncca/ngl/vector_base.py +542 -0
  23. ncca/ngl/webgpu/__init__.py +20 -0
  24. ncca/ngl/webgpu/__main__.py +640 -0
  25. ncca/ngl/webgpu/__main__.py.backup +640 -0
  26. ncca/ngl/webgpu/base_webgpu_pipeline.py +354 -0
  27. ncca/ngl/webgpu/custom_shader_pipeline.py +288 -0
  28. ncca/ngl/webgpu/instanced_geometry_pipeline.py +594 -0
  29. ncca/ngl/webgpu/line_pipeline.py +405 -0
  30. ncca/ngl/webgpu/pipeline_factory.py +190 -0
  31. ncca/ngl/webgpu/pipeline_shaders.py +497 -0
  32. ncca/ngl/webgpu/point_list_pipeline.py +349 -0
  33. ncca/ngl/webgpu/point_pipeline.py +336 -0
  34. ncca/ngl/webgpu/triangle_pipeline.py +419 -0
  35. ncca/ngl/webgpu/webgpu_constants.py +31 -0
  36. ncca/ngl/webgpu/webgpu_widget.py +322 -0
  37. ncca/ngl/webgpu/wip/REFACTORING_SUMMARY.md +82 -0
  38. ncca/ngl/webgpu/wip/UNIFIED_SYSTEM.md +314 -0
  39. ncca/ngl/webgpu/wip/buffer_manager.py +396 -0
  40. ncca/ngl/webgpu/wip/pipeline_config.py +463 -0
  41. ncca/ngl/webgpu/wip/shader_constants.py +328 -0
  42. ncca/ngl/webgpu/wip/shader_templates.py +563 -0
  43. ncca/ngl/webgpu/wip/unified_examples.py +390 -0
  44. ncca/ngl/webgpu/wip/unified_factory.py +449 -0
  45. ncca/ngl/webgpu/wip/unified_pipeline.py +469 -0
  46. ncca/ngl/widgets/__init__.py +18 -2
  47. ncca/ngl/widgets/__main__.py +2 -1
  48. ncca/ngl/widgets/lookatwidget.py +2 -1
  49. ncca/ngl/widgets/mat4widget.py +2 -2
  50. ncca/ngl/widgets/vec2widget.py +1 -1
  51. ncca/ngl/widgets/vec3widget.py +1 -0
  52. {ncca_ngl-0.3.4.dist-info → ncca_ngl-0.5.0.dist-info}/METADATA +3 -2
  53. ncca_ngl-0.5.0.dist-info/RECORD +105 -0
  54. ncca/ngl/widgets/transformation_widget.py +0 -299
  55. ncca_ngl-0.3.4.dist-info/RECORD +0 -82
  56. {ncca_ngl-0.3.4.dist-info → ncca_ngl-0.5.0.dist-info}/WHEEL +0 -0
@@ -0,0 +1,449 @@
1
+ """
2
+ Simplified factory for WebGPU pipelines with configuration-driven approach.
3
+ Provides easy creation of unified pipelines with predefined and custom configurations.
4
+ """
5
+
6
+ from typing import Dict, Optional, Type
7
+
8
+ import wgpu
9
+
10
+ from .base_webgpu_pipeline import BaseWebGPUPipeline
11
+ from .pipeline_config import (
12
+ PipelineConfig,
13
+ PipelineConfigBuilder,
14
+ PredefinedConfigs,
15
+ PrimitiveType,
16
+ ColorMode,
17
+ RenderMode,
18
+ create_pipeline_config,
19
+ )
20
+ from .unified_pipeline import UnifiedWebGPUPipeline
21
+ from .shader_templates import (
22
+ ShaderTemplate,
23
+ PrimitiveType as ShaderPrimitiveType,
24
+ shader_registry,
25
+ )
26
+
27
+
28
+ class UnifiedPipelineFactory:
29
+ """
30
+ Simplified factory for creating unified WebGPU pipelines.
31
+
32
+ Provides easy methods for creating common pipeline types and supports
33
+ custom configurations and user-defined shaders.
34
+ """
35
+
36
+ def __init__(self, device: wgpu.GPUDevice):
37
+ """
38
+ Initialize factory with WebGPU device.
39
+
40
+ Args:
41
+ device: WebGPU device for pipeline creation
42
+ """
43
+ self.device = device
44
+ self._custom_templates: Dict[str, Type[ShaderTemplate]] = {}
45
+
46
+ # Predefined pipeline creation methods
47
+
48
+ def create_point_single_colour(self, **kwargs) -> UnifiedWebGPUPipeline:
49
+ """Create single color point pipeline with billboarding."""
50
+ config = PredefinedConfigs.point_single_colour()
51
+ return self.create_pipeline(config, **kwargs)
52
+
53
+ def create_point_multi_colour(self, **kwargs) -> UnifiedWebGPUPipeline:
54
+ """Create multi-color point pipeline with billboarding."""
55
+ config = PredefinedConfigs.point_multi_colour()
56
+ return self.create_pipeline(config, **kwargs)
57
+
58
+ def create_line_single_colour(self, **kwargs) -> UnifiedWebGPUPipeline:
59
+ """Create single color line pipeline."""
60
+ config = PredefinedConfigs.line_single_colour()
61
+ return self.create_pipeline(config, **kwargs)
62
+
63
+ def create_line_multi_colour(self, **kwargs) -> UnifiedWebGPUPipeline:
64
+ """Create multi-color line pipeline."""
65
+ config = PredefinedConfigs.line_multi_colour()
66
+ return self.create_pipeline(config, **kwargs)
67
+
68
+ def create_triangle_single_colour(self, **kwargs) -> UnifiedWebGPUPipeline:
69
+ """Create single color triangle pipeline."""
70
+ config = PredefinedConfigs.triangle_single_colour()
71
+ return self.create_pipeline(config, **kwargs)
72
+
73
+ def create_triangle_multi_colour(self, **kwargs) -> UnifiedWebGPUPipeline:
74
+ """Create multi-color triangle pipeline."""
75
+ config = PredefinedConfigs.triangle_multi_colour()
76
+ return self.create_pipeline(config, **kwargs)
77
+
78
+ def create_triangle_strip_single_colour(self, **kwargs) -> UnifiedWebGPUPipeline:
79
+ """Create single color triangle strip pipeline."""
80
+ config = PredefinedConfigs.triangle_strip_single_colour()
81
+ return self.create_pipeline(config, **kwargs)
82
+
83
+ def create_triangle_strip_multi_colour(self, **kwargs) -> UnifiedWebGPUPipeline:
84
+ """Create multi-color triangle strip pipeline."""
85
+ config = PredefinedConfigs.triangle_strip_multi_colour()
86
+ return self.create_pipeline(config, **kwargs)
87
+
88
+ # Flexible configuration methods
89
+
90
+ def create_from_builder(
91
+ self, builder: PipelineConfigBuilder
92
+ ) -> UnifiedWebGPUPipeline:
93
+ """Create pipeline from configuration builder."""
94
+ config = builder.build()
95
+ return self.create_pipeline(config)
96
+
97
+ def create_pipeline(
98
+ self, config: PipelineConfig, **kwargs
99
+ ) -> UnifiedWebGPUPipeline:
100
+ """
101
+ Create pipeline from configuration.
102
+
103
+ Args:
104
+ config: Pipeline configuration
105
+ **kwargs: Additional configuration overrides
106
+
107
+ Returns:
108
+ Created unified pipeline
109
+ """
110
+ # Apply any configuration overrides
111
+ if kwargs:
112
+ config = self._apply_config_overrides(config, **kwargs)
113
+
114
+ return UnifiedWebGPUPipeline(self.device, config)
115
+
116
+ def create_custom(
117
+ self,
118
+ primitive_type: PrimitiveType,
119
+ color_mode: ColorMode,
120
+ topology: Optional[wgpu.PrimitiveTopology] = None,
121
+ render_mode: RenderMode = RenderMode.STANDARD,
122
+ **kwargs,
123
+ ) -> UnifiedWebGPUPipeline:
124
+ """
125
+ Create custom pipeline with specified parameters.
126
+
127
+ Args:
128
+ primitive_type: Type of primitive to render
129
+ color_mode: Color rendering mode
130
+ topology: WebGPU primitive topology
131
+ render_mode: Special rendering mode
132
+ **kwargs: Additional configuration options
133
+
134
+ Returns:
135
+ Created unified pipeline
136
+ """
137
+ config = create_pipeline_config(
138
+ primitive_type=primitive_type,
139
+ color_mode=color_mode,
140
+ topology=topology,
141
+ render_mode=render_mode,
142
+ **kwargs,
143
+ )
144
+
145
+ return self.create_pipeline(config)
146
+
147
+ def create_with_custom_shaders(
148
+ self,
149
+ vertex_shader: str,
150
+ fragment_shader: str,
151
+ primitive_type: PrimitiveType = PrimitiveType.TRIANGLE,
152
+ color_mode: ColorMode = ColorMode.MULTI,
153
+ topology: Optional[wgpu.PrimitiveTopology] = None,
154
+ **kwargs,
155
+ ) -> UnifiedWebGPUPipeline:
156
+ """
157
+ Create pipeline with custom user-defined shaders.
158
+
159
+ Args:
160
+ vertex_shader: Custom WGSL vertex shader code
161
+ fragment_shader: Custom WGSL fragment shader code
162
+ primitive_type: Type of primitive to render
163
+ color_mode: Color rendering mode
164
+ topology: WebGPU primitive topology
165
+ **kwargs: Additional configuration options
166
+
167
+ Returns:
168
+ Created unified pipeline with custom shaders
169
+ """
170
+ config = create_pipeline_config(
171
+ primitive_type=primitive_type,
172
+ color_mode=color_mode,
173
+ topology=topology,
174
+ custom_vertex_shader=vertex_shader,
175
+ custom_fragment_shader=fragment_shader,
176
+ **kwargs,
177
+ )
178
+
179
+ return self.create_pipeline(config)
180
+
181
+ def create_with_vertex_shader(
182
+ self,
183
+ vertex_shader: str,
184
+ primitive_type: PrimitiveType = PrimitiveType.TRIANGLE,
185
+ color_mode: ColorMode = ColorMode.MULTI,
186
+ topology: Optional[wgpu.PrimitiveTopology] = None,
187
+ **kwargs,
188
+ ) -> UnifiedWebGPUPipeline:
189
+ """
190
+ Create pipeline with custom vertex shader (uses template fragment shader).
191
+
192
+ Args:
193
+ vertex_shader: Custom WGSL vertex shader code
194
+ primitive_type: Type of primitive to render
195
+ color_mode: Color rendering mode
196
+ topology: WebGPU primitive topology
197
+ **kwargs: Additional configuration options
198
+
199
+ Returns:
200
+ Created unified pipeline with custom vertex shader
201
+ """
202
+ config = create_pipeline_config(
203
+ primitive_type=primitive_type,
204
+ color_mode=color_mode,
205
+ topology=topology,
206
+ custom_vertex_shader=vertex_shader,
207
+ **kwargs,
208
+ )
209
+
210
+ return self.create_pipeline(config)
211
+
212
+ def create_with_fragment_shader(
213
+ self,
214
+ fragment_shader: str,
215
+ primitive_type: PrimitiveType = PrimitiveType.TRIANGLE,
216
+ color_mode: ColorMode = ColorMode.MULTI,
217
+ topology: Optional[wgpu.PrimitiveTopology] = None,
218
+ **kwargs,
219
+ ) -> UnifiedWebGPUPipeline:
220
+ """
221
+ Create pipeline with custom fragment shader (uses template vertex shader).
222
+
223
+ Args:
224
+ fragment_shader: Custom WGSL fragment shader code
225
+ primitive_type: Type of primitive to render
226
+ color_mode: Color rendering mode
227
+ topology: WebGPU primitive topology
228
+ **kwargs: Additional configuration options
229
+
230
+ Returns:
231
+ Created unified pipeline with custom fragment shader
232
+ """
233
+ config = create_pipeline_config(
234
+ primitive_type=primitive_type,
235
+ color_mode=color_mode,
236
+ topology=topology,
237
+ custom_fragment_shader=fragment_shader,
238
+ **kwargs,
239
+ )
240
+
241
+ return self.create_pipeline(config)
242
+
243
+ # Advanced customization methods
244
+
245
+ def register_custom_template(
246
+ self, name: str, template_class: Type[ShaderTemplate]
247
+ ) -> None:
248
+ """
249
+ Register a custom shader template.
250
+
251
+ Args:
252
+ name: Name for the template
253
+ template_class: Shader template class
254
+ """
255
+ self._custom_templates[name] = template_class
256
+ # Register with global shader registry
257
+ shader_registry.register_template(
258
+ ShaderPrimitiveType(template_class.__name__.lower()), template_class()
259
+ )
260
+
261
+ def create_with_custom_template(
262
+ self,
263
+ template_name: str,
264
+ primitive_type: PrimitiveType,
265
+ color_mode: ColorMode,
266
+ **kwargs,
267
+ ) -> UnifiedWebGPUPipeline:
268
+ """
269
+ Create pipeline using custom shader template.
270
+
271
+ Args:
272
+ template_name: Name of registered custom template
273
+ primitive_type: Type of primitive to render
274
+ color_mode: Color rendering mode
275
+ **kwargs: Additional configuration options
276
+
277
+ Returns:
278
+ Created unified pipeline using custom template
279
+ """
280
+ if template_name not in self._custom_templates:
281
+ raise ValueError(f"Custom template '{template_name}' not registered")
282
+
283
+ config = create_pipeline_config(
284
+ primitive_type=primitive_type,
285
+ color_mode=color_mode,
286
+ **kwargs,
287
+ )
288
+
289
+ return self.create_pipeline(config)
290
+
291
+ # Utility methods
292
+
293
+ def _apply_config_overrides(
294
+ self, config: PipelineConfig, **kwargs
295
+ ) -> PipelineConfig:
296
+ """Apply configuration overrides to create new config."""
297
+ # Create builder from existing config
298
+ builder = PipelineConfigBuilder()
299
+
300
+ # Copy existing settings
301
+ builder.primitive(config.primitive_type)
302
+ builder.color_mode(config.color_mode)
303
+ builder.topology(config.topology)
304
+ builder.render_mode(config.render_mode)
305
+ builder.texture_format(config.texture_format)
306
+ builder.depth_format(config.depth_format)
307
+ builder.msaa(config.msaa_sample_count)
308
+ builder.data_type(config.data_type)
309
+ builder.stride(config.stride)
310
+ builder.cull_mode(config.cull_mode)
311
+ builder.front_face(config.front_face)
312
+
313
+ # Apply custom configurations
314
+ if config.custom_vertex_shader:
315
+ builder.custom_shaders(vertex_shader=config.custom_vertex_shader)
316
+ if config.custom_fragment_shader:
317
+ builder.custom_shaders(fragment_shader=config.custom_fragment_shader)
318
+ if config.custom_uniforms:
319
+ builder.custom_uniforms(config.custom_uniforms)
320
+ if config.custom_attributes:
321
+ builder.custom_attributes(config.custom_attributes)
322
+ if config.buffer_layouts:
323
+ for layout in config.buffer_layouts:
324
+ builder.buffer_layout(layout)
325
+
326
+ # Apply overrides
327
+ for key, value in kwargs.items():
328
+ if hasattr(builder, key) and callable(getattr(builder, key)):
329
+ method = getattr(builder, key)
330
+ if key in ["custom_shaders", "custom_uniforms", "custom_attributes"]:
331
+ method(value)
332
+ else:
333
+ method(value)
334
+
335
+ return builder.build()
336
+
337
+
338
+ # Backward compatibility factory
339
+ class PipelineFactory(UnifiedPipelineFactory):
340
+ """Backward compatible factory class."""
341
+
342
+ def __init__(self, device: wgpu.GPUDevice):
343
+ """Initialize backward compatible factory."""
344
+ super().__init__(device)
345
+
346
+ # Maintain legacy registry for compatibility
347
+ self._pipeline_registry = {}
348
+
349
+ def register_pipeline(self, pipeline_type, pipeline_class) -> None:
350
+ """Register pipeline for backward compatibility."""
351
+ self._pipeline_registry[pipeline_type] = pipeline_class
352
+
353
+ def create_legacy_pipeline(self, pipeline_type, **kwargs) -> BaseWebGPUPipeline:
354
+ """Create pipeline using legacy registry."""
355
+ if pipeline_type not in self._pipeline_registry:
356
+ raise ValueError(f"Unknown pipeline type: {pipeline_type}")
357
+
358
+ pipeline_class = self._pipeline_registry[pipeline_type]
359
+ return pipeline_class(self.device, **kwargs)
360
+
361
+
362
+ # Global factory instance
363
+ _global_factory: Optional[UnifiedPipelineFactory] = None
364
+
365
+
366
+ def get_factory(device: Optional[wgpu.GPUDevice] = None) -> UnifiedPipelineFactory:
367
+ """Get or create global factory instance."""
368
+ global _global_factory
369
+
370
+ if _global_factory is None:
371
+ if device is None:
372
+ raise ValueError("Device must be provided for first factory creation")
373
+ _global_factory = UnifiedPipelineFactory(device)
374
+
375
+ return _global_factory
376
+
377
+
378
+ # Convenience functions for quick pipeline creation
379
+ def create_point_pipeline(
380
+ device: wgpu.GPUDevice,
381
+ multi_colour: bool = True,
382
+ **kwargs,
383
+ ) -> UnifiedWebGPUPipeline:
384
+ """Quick creation of point pipeline."""
385
+ factory = UnifiedPipelineFactory(device)
386
+ if multi_colour:
387
+ return factory.create_point_multi_colour(**kwargs)
388
+ else:
389
+ return factory.create_point_single_colour(**kwargs)
390
+
391
+
392
+ def create_line_pipeline(
393
+ device: wgpu.GPUDevice,
394
+ multi_colour: bool = True,
395
+ **kwargs,
396
+ ) -> UnifiedWebGPUPipeline:
397
+ """Quick creation of line pipeline."""
398
+ factory = UnifiedPipelineFactory(device)
399
+ if multi_colour:
400
+ return factory.create_line_multi_colour(**kwargs)
401
+ else:
402
+ return factory.create_line_single_colour(**kwargs)
403
+
404
+
405
+ def create_triangle_pipeline(
406
+ device: wgpu.GPUDevice,
407
+ multi_colour: bool = True,
408
+ triangle_strip: bool = False,
409
+ **kwargs,
410
+ ) -> UnifiedWebGPUPipeline:
411
+ """Quick creation of triangle pipeline."""
412
+ factory = UnifiedPipelineFactory(device)
413
+
414
+ if triangle_strip:
415
+ if multi_colour:
416
+ return factory.create_triangle_strip_multi_colour(**kwargs)
417
+ else:
418
+ return factory.create_triangle_strip_single_colour(**kwargs)
419
+ else:
420
+ if multi_colour:
421
+ return factory.create_triangle_multi_colour(**kwargs)
422
+ else:
423
+ return factory.create_triangle_single_colour(**kwargs)
424
+
425
+
426
+ def create_instanced_geometry_pipeline(
427
+ device: wgpu.GPUDevice,
428
+ multi_colour: bool = True,
429
+ **kwargs,
430
+ ) -> UnifiedWebGPUPipeline:
431
+ """Quick creation of instanced geometry pipeline."""
432
+ from .pipeline_config import PrimitiveType, ColorMode, RenderMode
433
+
434
+ factory = UnifiedPipelineFactory(device)
435
+
436
+ if multi_colour:
437
+ return factory.create_custom(
438
+ primitive_type=PrimitiveType.TRIANGLE,
439
+ color_mode=ColorMode.MULTI,
440
+ render_mode=RenderMode.INSTANCED,
441
+ **kwargs,
442
+ )
443
+ else:
444
+ return factory.create_custom(
445
+ primitive_type=PrimitiveType.TRIANGLE,
446
+ color_mode=ColorMode.SINGLE,
447
+ render_mode=RenderMode.INSTANCED,
448
+ **kwargs,
449
+ )