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.
- ncca/ngl/PrimData/pack_arrays.py +2 -3
- ncca/ngl/__init__.py +3 -4
- ncca/ngl/base_mesh.py +28 -20
- ncca/ngl/image.py +1 -3
- ncca/ngl/mat2.py +79 -53
- ncca/ngl/mat3.py +104 -185
- ncca/ngl/mat4.py +144 -309
- ncca/ngl/prim_data.py +42 -36
- ncca/ngl/primitives.py +2 -2
- ncca/ngl/pyside_event_handling_mixin.py +0 -108
- ncca/ngl/quaternion.py +69 -36
- ncca/ngl/shader.py +0 -116
- ncca/ngl/shader_program.py +94 -117
- ncca/ngl/texture.py +5 -2
- ncca/ngl/util.py +7 -0
- ncca/ngl/vec2.py +58 -292
- ncca/ngl/vec2_array.py +79 -28
- ncca/ngl/vec3.py +59 -340
- ncca/ngl/vec3_array.py +76 -23
- ncca/ngl/vec4.py +90 -190
- ncca/ngl/vec4_array.py +78 -27
- ncca/ngl/vector_base.py +542 -0
- ncca/ngl/webgpu/__init__.py +20 -0
- ncca/ngl/webgpu/__main__.py +640 -0
- ncca/ngl/webgpu/__main__.py.backup +640 -0
- ncca/ngl/webgpu/base_webgpu_pipeline.py +354 -0
- ncca/ngl/webgpu/custom_shader_pipeline.py +288 -0
- ncca/ngl/webgpu/instanced_geometry_pipeline.py +594 -0
- ncca/ngl/webgpu/line_pipeline.py +405 -0
- ncca/ngl/webgpu/pipeline_factory.py +190 -0
- ncca/ngl/webgpu/pipeline_shaders.py +497 -0
- ncca/ngl/webgpu/point_list_pipeline.py +349 -0
- ncca/ngl/webgpu/point_pipeline.py +336 -0
- ncca/ngl/webgpu/triangle_pipeline.py +419 -0
- ncca/ngl/webgpu/webgpu_constants.py +31 -0
- ncca/ngl/webgpu/webgpu_widget.py +322 -0
- ncca/ngl/webgpu/wip/REFACTORING_SUMMARY.md +82 -0
- ncca/ngl/webgpu/wip/UNIFIED_SYSTEM.md +314 -0
- ncca/ngl/webgpu/wip/buffer_manager.py +396 -0
- ncca/ngl/webgpu/wip/pipeline_config.py +463 -0
- ncca/ngl/webgpu/wip/shader_constants.py +328 -0
- ncca/ngl/webgpu/wip/shader_templates.py +563 -0
- ncca/ngl/webgpu/wip/unified_examples.py +390 -0
- ncca/ngl/webgpu/wip/unified_factory.py +449 -0
- ncca/ngl/webgpu/wip/unified_pipeline.py +469 -0
- ncca/ngl/widgets/__init__.py +18 -2
- ncca/ngl/widgets/__main__.py +2 -1
- ncca/ngl/widgets/lookatwidget.py +2 -1
- ncca/ngl/widgets/mat4widget.py +2 -2
- ncca/ngl/widgets/vec2widget.py +1 -1
- ncca/ngl/widgets/vec3widget.py +1 -0
- {ncca_ngl-0.3.4.dist-info → ncca_ngl-0.5.0.dist-info}/METADATA +3 -2
- ncca_ngl-0.5.0.dist-info/RECORD +105 -0
- ncca/ngl/widgets/transformation_widget.py +0 -299
- ncca_ngl-0.3.4.dist-info/RECORD +0 -82
- {ncca_ngl-0.3.4.dist-info → ncca_ngl-0.5.0.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,497 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
@dataclass
|
|
5
|
+
class ShaderConfig:
|
|
6
|
+
"""Configuration for generating WGSL shaders"""
|
|
7
|
+
|
|
8
|
+
name: str
|
|
9
|
+
geometry_type: str # 'point', 'line', 'triangle', 'instanced', 'point_list'
|
|
10
|
+
colour_mode: str # 'single', 'multi'
|
|
11
|
+
has_lighting: bool = False
|
|
12
|
+
has_uv: bool = False
|
|
13
|
+
has_size: bool = False
|
|
14
|
+
has_view_matrix: bool = False
|
|
15
|
+
has_instance_transform: bool = False
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
# Shader component templates
|
|
19
|
+
UNIFORMS_BASE = """
|
|
20
|
+
@group(0) @binding(0) var<uniform> uniforms : Uniforms;
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
UNIFORMS_MVP = """
|
|
24
|
+
struct Uniforms
|
|
25
|
+
{{
|
|
26
|
+
MVP : mat4x4<f32>,
|
|
27
|
+
{additional_fields}
|
|
28
|
+
}};
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
UNIFORMS_MVP_VIEW = """
|
|
32
|
+
struct Uniforms
|
|
33
|
+
{{
|
|
34
|
+
MVP : mat4x4<f32>,
|
|
35
|
+
ViewMatrix : mat4x4<f32>,
|
|
36
|
+
{additional_fields}
|
|
37
|
+
}};
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
VERTEX_IN_POSITION = """
|
|
41
|
+
struct VertexIn {{
|
|
42
|
+
@location(0) position: vec3<f32>,
|
|
43
|
+
{colour_input}
|
|
44
|
+
}};
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
VERTEX_IN_INSTANCED = """
|
|
48
|
+
struct InstanceData {{
|
|
49
|
+
@location(0) position: vec3<f32>,
|
|
50
|
+
{colour_input}
|
|
51
|
+
@location(2) instance_id: f32,
|
|
52
|
+
}};
|
|
53
|
+
|
|
54
|
+
struct GeometryVertex {{
|
|
55
|
+
@location(3) geometry_position: vec3<f32>,
|
|
56
|
+
@location(4) geometry_normal: vec3<f32>,
|
|
57
|
+
@location(5) geometry_uv: vec2<f32>,
|
|
58
|
+
}};
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
VERTEX_OUT_BASE = """
|
|
62
|
+
struct VertexOut {{
|
|
63
|
+
@builtin(position) position: vec4<f32>,
|
|
64
|
+
{colour_output}
|
|
65
|
+
{uv_output}
|
|
66
|
+
{normal_output}
|
|
67
|
+
{world_pos_output}
|
|
68
|
+
}};
|
|
69
|
+
"""
|
|
70
|
+
|
|
71
|
+
QUAD_OFFSETS = """
|
|
72
|
+
let quad_offsets = array<vec2<f32>, 4>(
|
|
73
|
+
vec2<f32>(-1.0, -1.0), // bottom-left
|
|
74
|
+
vec2<f32>(1.0, -1.0), // bottom-right
|
|
75
|
+
vec2<f32>(-1.0, 1.0), // top-left
|
|
76
|
+
vec2<f32>(1.0, 1.0) // top-right
|
|
77
|
+
);
|
|
78
|
+
"""
|
|
79
|
+
|
|
80
|
+
CAMERA_EXTRACTION = """
|
|
81
|
+
// Extract camera right and up vectors from view matrix
|
|
82
|
+
let cameraRight = normalize(vec3<f32>(uniforms.ViewMatrix[0][0], uniforms.ViewMatrix[1][0], uniforms.ViewMatrix[2][0]));
|
|
83
|
+
let cameraUp = normalize(vec3<f32>(uniforms.ViewMatrix[0][1], uniforms.ViewMatrix[1][1], uniforms.ViewMatrix[2][1]));
|
|
84
|
+
"""
|
|
85
|
+
|
|
86
|
+
LIGHTING_CALCULATION = """
|
|
87
|
+
// Light properties
|
|
88
|
+
let light_direction = normalize(vec3<f32>(0.5, 1.0, 0.3)); // World space light direction
|
|
89
|
+
let light_color = vec3<f32>(1.0, 1.0, 1.0); // White light
|
|
90
|
+
let ambient_intensity = 0.15; // Lower ambient for better contrast
|
|
91
|
+
let diffuse_intensity = 0.85; // Higher diffuse for stronger lighting
|
|
92
|
+
|
|
93
|
+
// Ambient component (base illumination)
|
|
94
|
+
let ambient = vec3<f32>(ambient_intensity);
|
|
95
|
+
|
|
96
|
+
// Diffuse component (Lambertian reflection)
|
|
97
|
+
let normal = normalize(fragData.fragNormal);
|
|
98
|
+
let n_dot_l = max(dot(normal, light_direction), 0.0);
|
|
99
|
+
let diffuse = light_color * n_dot_l * diffuse_intensity;
|
|
100
|
+
|
|
101
|
+
// Combine lighting components
|
|
102
|
+
let final_lighting = ambient + diffuse;
|
|
103
|
+
"""
|
|
104
|
+
|
|
105
|
+
CIRCLE_DISCARD = """
|
|
106
|
+
let center = vec2<f32>(0.5, 0.5); // Center of the quad in UV space
|
|
107
|
+
let dist = distance(fragData.uv, center); // Distance from center
|
|
108
|
+
let radius = 0.5; // Circle radius (quad is 1.0 in UV space)
|
|
109
|
+
|
|
110
|
+
if (dist > radius)
|
|
111
|
+
{{
|
|
112
|
+
discard; // Remove pixels outside the circle
|
|
113
|
+
}}
|
|
114
|
+
"""
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def _build_uniforms(config: ShaderConfig) -> str:
|
|
118
|
+
"""Build uniform structure based on configuration"""
|
|
119
|
+
additional_fields = []
|
|
120
|
+
|
|
121
|
+
if config.geometry_type == "point":
|
|
122
|
+
if config.colour_mode == "single":
|
|
123
|
+
additional_fields.append(" ColourSize: vec4<f32>,")
|
|
124
|
+
else:
|
|
125
|
+
additional_fields.extend([
|
|
126
|
+
" size: f32,",
|
|
127
|
+
" padding: u32,",
|
|
128
|
+
" padding2: u32,",
|
|
129
|
+
" padding3: u32,",
|
|
130
|
+
])
|
|
131
|
+
elif config.geometry_type in ["line", "triangle", "point_list"]:
|
|
132
|
+
if config.colour_mode == "single":
|
|
133
|
+
additional_fields.extend([" Colour: vec3<f32>,", " padding: f32,"])
|
|
134
|
+
elif config.geometry_type == "instanced":
|
|
135
|
+
if config.colour_mode == "single":
|
|
136
|
+
additional_fields.extend([
|
|
137
|
+
" colour: vec3<f32>,",
|
|
138
|
+
" padding: f32,",
|
|
139
|
+
" instance_transform: mat4x4<f32>,",
|
|
140
|
+
])
|
|
141
|
+
else:
|
|
142
|
+
additional_fields.append(" instance_transform: mat4x4<f32>,")
|
|
143
|
+
|
|
144
|
+
base_template = UNIFORMS_MVP_VIEW if config.has_view_matrix else UNIFORMS_MVP
|
|
145
|
+
return base_template.format(additional_fields="\n".join(additional_fields) if additional_fields else "")
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def _build_vertex_input(config: ShaderConfig) -> str:
|
|
149
|
+
"""Build vertex input structure based on configuration"""
|
|
150
|
+
if config.geometry_type == "instanced":
|
|
151
|
+
if config.colour_mode == "single":
|
|
152
|
+
colour_input = " @location(1) colour: vec3<f32>, // Provided but ignored"
|
|
153
|
+
else:
|
|
154
|
+
colour_input = " @location(1) colour: vec3<f32>,"
|
|
155
|
+
|
|
156
|
+
return VERTEX_IN_INSTANCED.format(colour_input=colour_input)
|
|
157
|
+
else:
|
|
158
|
+
# For lines, use 'pos' instead of 'position' to match original shaders
|
|
159
|
+
if config.geometry_type == "line":
|
|
160
|
+
position_input = " @location(0) pos: vec3<f32>,"
|
|
161
|
+
colour_input = " @location(1) color: vec3<f32>," if config.colour_mode == "multi" else ""
|
|
162
|
+
elif config.geometry_type == "triangle":
|
|
163
|
+
position_input = " @location(0) pos: vec3<f32>,"
|
|
164
|
+
colour_input = " @location(1) color: vec3<f32>," if config.colour_mode == "multi" else ""
|
|
165
|
+
else:
|
|
166
|
+
position_input = " @location(0) position: vec3<f32>,"
|
|
167
|
+
colour_input = " @location(1) colour: vec3<f32>," if config.colour_mode == "multi" else ""
|
|
168
|
+
|
|
169
|
+
return f"""
|
|
170
|
+
struct VertexIn {{
|
|
171
|
+
{position_input}
|
|
172
|
+
{colour_input}
|
|
173
|
+
}};
|
|
174
|
+
"""
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def _build_vertex_output(config: ShaderConfig) -> str:
|
|
178
|
+
"""Build vertex output structure based on configuration"""
|
|
179
|
+
outputs = []
|
|
180
|
+
|
|
181
|
+
if config.colour_mode == "multi":
|
|
182
|
+
if config.geometry_type in ["point", "point_list"]:
|
|
183
|
+
outputs.append(" @location(0) fragColour: vec3<f32>,")
|
|
184
|
+
elif config.geometry_type in ["line", "triangle"]:
|
|
185
|
+
outputs.append(" @location(0) color: vec3<f32>,")
|
|
186
|
+
elif config.geometry_type == "instanced":
|
|
187
|
+
outputs.append(" @location(0) fragColour: vec3<f32>,")
|
|
188
|
+
|
|
189
|
+
if config.has_uv:
|
|
190
|
+
outputs.append(" @location(1) uv: vec2<f32>,")
|
|
191
|
+
|
|
192
|
+
if config.has_lighting:
|
|
193
|
+
if config.geometry_type == "instanced" and config.colour_mode == "single":
|
|
194
|
+
outputs = [
|
|
195
|
+
" @location(0) fragNormal: vec3<f32>,",
|
|
196
|
+
" @location(1) fragUV: vec2<f32>,",
|
|
197
|
+
" @location(2) worldPos: vec3<f32>,",
|
|
198
|
+
]
|
|
199
|
+
else:
|
|
200
|
+
start_idx = len(outputs)
|
|
201
|
+
outputs.append(f" @location({start_idx}) fragNormal: vec3<f32>,")
|
|
202
|
+
outputs.append(f" @location({start_idx + 1}) fragUV: vec2<f32>,")
|
|
203
|
+
outputs.append(f" @location({start_idx + 2}) worldPos: vec3<f32>,")
|
|
204
|
+
|
|
205
|
+
colour_output = ""
|
|
206
|
+
uv_output = ""
|
|
207
|
+
normal_output = ""
|
|
208
|
+
world_pos_output = ""
|
|
209
|
+
|
|
210
|
+
for output in outputs:
|
|
211
|
+
if "fragColour" in output or "color" in output:
|
|
212
|
+
colour_output = output
|
|
213
|
+
elif "uv" in output and "fragUV" not in output:
|
|
214
|
+
uv_output = output
|
|
215
|
+
elif "fragNormal" in output:
|
|
216
|
+
normal_output = output
|
|
217
|
+
elif "fragUV" in output:
|
|
218
|
+
uv_output = output
|
|
219
|
+
elif "worldPos" in output:
|
|
220
|
+
world_pos_output = output
|
|
221
|
+
|
|
222
|
+
return VERTEX_OUT_BASE.format(
|
|
223
|
+
colour_output=colour_output,
|
|
224
|
+
uv_output=uv_output,
|
|
225
|
+
normal_output=normal_output,
|
|
226
|
+
world_pos_output=world_pos_output,
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
def _build_vertex_main(config: ShaderConfig) -> str:
|
|
231
|
+
"""Build vertex shader main function"""
|
|
232
|
+
if config.geometry_type == "point":
|
|
233
|
+
return _build_point_vertex(config)
|
|
234
|
+
elif config.geometry_type in ["line", "triangle", "point_list"]:
|
|
235
|
+
return _build_simple_vertex(config)
|
|
236
|
+
elif config.geometry_type == "instanced":
|
|
237
|
+
return _build_instanced_vertex(config)
|
|
238
|
+
return ""
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
def _build_point_vertex(config: ShaderConfig) -> str:
|
|
242
|
+
"""Build point sprite vertex shader"""
|
|
243
|
+
size_source = "uniforms.size" if config.colour_mode == "multi" else "uniforms.ColourSize.w"
|
|
244
|
+
|
|
245
|
+
return f"""
|
|
246
|
+
@vertex
|
|
247
|
+
fn vertex_main(input: VertexIn, @builtin(vertex_index) vertex_index: u32) -> VertexOut {{
|
|
248
|
+
var output: VertexOut;
|
|
249
|
+
{QUAD_OFFSETS}
|
|
250
|
+
|
|
251
|
+
{CAMERA_EXTRACTION if config.has_view_matrix else ""}
|
|
252
|
+
|
|
253
|
+
// Calculate billboard offset in world space
|
|
254
|
+
let offset2D = quad_offsets[vertex_index] * {size_source};
|
|
255
|
+
let offset3D = cameraRight * offset2D.x + cameraUp * offset2D.y;
|
|
256
|
+
let worldPos = input.position + offset3D;
|
|
257
|
+
|
|
258
|
+
output.position = uniforms.MVP * vec4<f32>(worldPos, 1.0);
|
|
259
|
+
{(" output.fragColour = input.colour;" if config.colour_mode == "multi" else "")}
|
|
260
|
+
// convert offset from -1 -> 1 to 0 -> 1 for uv
|
|
261
|
+
output.uv = quad_offsets[vertex_index] * 0.5 + 0.5;
|
|
262
|
+
|
|
263
|
+
return output;
|
|
264
|
+
}}
|
|
265
|
+
"""
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
def _build_simple_vertex(config: ShaderConfig) -> str:
|
|
269
|
+
"""Build simple vertex shader for lines, triangles, point lists"""
|
|
270
|
+
# Use the correct attribute names based on geometry type
|
|
271
|
+
if config.geometry_type in ["line", "triangle"]:
|
|
272
|
+
position_source = "input.pos"
|
|
273
|
+
colour_source = "input.color"
|
|
274
|
+
else:
|
|
275
|
+
position_source = "input.position"
|
|
276
|
+
colour_source = "input.colour" if config.geometry_type == "point_list" else "input.color"
|
|
277
|
+
|
|
278
|
+
colour_output = ""
|
|
279
|
+
if config.colour_mode == "multi" and config.geometry_type == "point_list":
|
|
280
|
+
colour_output = f" output.fragColour = {colour_source};"
|
|
281
|
+
elif config.colour_mode == "multi" and config.geometry_type in ["line", "triangle"]:
|
|
282
|
+
colour_output = f" output.color = {colour_source};"
|
|
283
|
+
|
|
284
|
+
return f"""
|
|
285
|
+
@vertex
|
|
286
|
+
fn vertex_main(input: VertexIn) -> VertexOut {{
|
|
287
|
+
var output: VertexOut;
|
|
288
|
+
output.position = uniforms.MVP * vec4<f32>({position_source}, 1.0);
|
|
289
|
+
{colour_output}
|
|
290
|
+
|
|
291
|
+
return output;
|
|
292
|
+
}}
|
|
293
|
+
"""
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
def _build_instanced_vertex(config: ShaderConfig) -> str:
|
|
297
|
+
"""Build instanced vertex shader"""
|
|
298
|
+
return f"""
|
|
299
|
+
@vertex
|
|
300
|
+
fn vertex_main(instance_data: InstanceData, geom_vertex: GeometryVertex, @builtin(vertex_index) vertex_index: u32) -> VertexOut {{
|
|
301
|
+
var output: VertexOut;
|
|
302
|
+
|
|
303
|
+
// Transform geometry vertex by instance transform and position
|
|
304
|
+
let transformed_vertex = uniforms.instance_transform * vec4<f32>(geom_vertex.geometry_position, 1.0);
|
|
305
|
+
let world_position = transformed_vertex.xyz + instance_data.position;
|
|
306
|
+
|
|
307
|
+
output.position = uniforms.MVP * vec4<f32>(world_position, 1.0);
|
|
308
|
+
{(" output.fragColour = instance_data.colour;" if config.colour_mode == "multi" else "")}
|
|
309
|
+
|
|
310
|
+
// Transform normal by instance transform (skip translation)
|
|
311
|
+
let normal_matrix = mat3x3<f32>(
|
|
312
|
+
uniforms.instance_transform[0].xyz,
|
|
313
|
+
uniforms.instance_transform[1].xyz,
|
|
314
|
+
uniforms.instance_transform[2].xyz
|
|
315
|
+
);
|
|
316
|
+
output.fragNormal = normalize(normal_matrix * geom_vertex.geometry_normal);
|
|
317
|
+
output.fragUV = geom_vertex.geometry_uv;
|
|
318
|
+
output.worldPos = world_position;
|
|
319
|
+
|
|
320
|
+
return output;
|
|
321
|
+
}}
|
|
322
|
+
"""
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
def _build_fragment_main(config: ShaderConfig) -> str:
|
|
326
|
+
"""Build fragment shader main function"""
|
|
327
|
+
if config.geometry_type == "point":
|
|
328
|
+
return _build_point_fragment(config)
|
|
329
|
+
elif config.geometry_type == "instanced":
|
|
330
|
+
return _build_instanced_fragment(config)
|
|
331
|
+
else:
|
|
332
|
+
return _build_simple_fragment(config)
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
def _build_point_fragment(config: ShaderConfig) -> str:
|
|
336
|
+
"""Build point sprite fragment shader"""
|
|
337
|
+
colour_source = "fragData.fragColour" if config.colour_mode == "multi" else "uniforms.ColourSize.xyz"
|
|
338
|
+
|
|
339
|
+
return f"""
|
|
340
|
+
@fragment
|
|
341
|
+
fn fragment_main(fragData: VertexOut) -> @location(0) vec4<f32>
|
|
342
|
+
{{
|
|
343
|
+
{CIRCLE_DISCARD if config.has_uv else ""}
|
|
344
|
+
|
|
345
|
+
return vec4<f32>({colour_source}, 1.0);
|
|
346
|
+
}}
|
|
347
|
+
"""
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
def _build_simple_fragment(config: ShaderConfig) -> str:
|
|
351
|
+
"""Build simple fragment shader for lines, triangles, point lists"""
|
|
352
|
+
if config.colour_mode == "single":
|
|
353
|
+
return """
|
|
354
|
+
@fragment
|
|
355
|
+
fn fragment_main() -> @location(0) vec4<f32> {
|
|
356
|
+
return vec4<f32>(uniforms.Colour, 1.0);
|
|
357
|
+
}
|
|
358
|
+
"""
|
|
359
|
+
else:
|
|
360
|
+
# Use the correct output attribute name based on geometry type
|
|
361
|
+
if config.geometry_type == "point_list":
|
|
362
|
+
colour_source = "fragData.fragColour"
|
|
363
|
+
else:
|
|
364
|
+
colour_source = "fragData.color"
|
|
365
|
+
return f"""
|
|
366
|
+
@fragment
|
|
367
|
+
fn fragment_main(fragData: VertexOut) -> @location(0) vec4<f32>
|
|
368
|
+
{{
|
|
369
|
+
return vec4<f32>({colour_source}, 1.0);
|
|
370
|
+
}}
|
|
371
|
+
"""
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
def _build_instanced_fragment(config: ShaderConfig) -> str:
|
|
375
|
+
"""Build instanced fragment shader with lighting"""
|
|
376
|
+
colour_source = "uniforms.colour" if config.colour_mode == "single" else "fragData.fragColour"
|
|
377
|
+
|
|
378
|
+
return f"""
|
|
379
|
+
@fragment
|
|
380
|
+
fn fragment_main(fragData: VertexOut) -> @location(0) vec4<f32>
|
|
381
|
+
{{
|
|
382
|
+
// Enhanced diffuse lighting calculation
|
|
383
|
+
|
|
384
|
+
{LIGHTING_CALCULATION}
|
|
385
|
+
|
|
386
|
+
// Apply lighting to the fragment color
|
|
387
|
+
let lit_color = {colour_source} * final_lighting;
|
|
388
|
+
|
|
389
|
+
return vec4<f32>(lit_color, 1.0);
|
|
390
|
+
}}
|
|
391
|
+
"""
|
|
392
|
+
|
|
393
|
+
|
|
394
|
+
def generate_shader(config: ShaderConfig) -> str:
|
|
395
|
+
"""Generate complete WGSL shader from configuration"""
|
|
396
|
+
uniforms = _build_uniforms(config)
|
|
397
|
+
vertex_in = _build_vertex_input(config)
|
|
398
|
+
vertex_out = _build_vertex_output(config)
|
|
399
|
+
vertex_main = _build_vertex_main(config)
|
|
400
|
+
fragment_main = _build_fragment_main(config)
|
|
401
|
+
|
|
402
|
+
return f"""
|
|
403
|
+
{UNIFORMS_BASE}
|
|
404
|
+
{uniforms}
|
|
405
|
+
|
|
406
|
+
{vertex_in}
|
|
407
|
+
|
|
408
|
+
{vertex_out}
|
|
409
|
+
|
|
410
|
+
{vertex_main}
|
|
411
|
+
|
|
412
|
+
{fragment_main}
|
|
413
|
+
"""
|
|
414
|
+
|
|
415
|
+
|
|
416
|
+
# Generate all existing shaders using the new system
|
|
417
|
+
POINT_SHADER_MULTI_COLOURED = generate_shader(
|
|
418
|
+
ShaderConfig(
|
|
419
|
+
name="POINT_SHADER_MULTI_COLOURED",
|
|
420
|
+
geometry_type="point",
|
|
421
|
+
colour_mode="multi",
|
|
422
|
+
has_uv=True,
|
|
423
|
+
has_view_matrix=True,
|
|
424
|
+
)
|
|
425
|
+
)
|
|
426
|
+
|
|
427
|
+
POINT_SHADER_SINGLE_COLOUR = generate_shader(
|
|
428
|
+
ShaderConfig(
|
|
429
|
+
name="POINT_SHADER_SINGLE_COLOUR",
|
|
430
|
+
geometry_type="point",
|
|
431
|
+
colour_mode="single",
|
|
432
|
+
has_uv=True,
|
|
433
|
+
has_view_matrix=True,
|
|
434
|
+
)
|
|
435
|
+
)
|
|
436
|
+
|
|
437
|
+
INSTANCED_SHADER_MULTI_COLOURED = generate_shader(
|
|
438
|
+
ShaderConfig(
|
|
439
|
+
name="INSTANCED_SHADER_MULTI_COLOURED",
|
|
440
|
+
geometry_type="instanced",
|
|
441
|
+
colour_mode="multi",
|
|
442
|
+
has_lighting=True,
|
|
443
|
+
has_view_matrix=True,
|
|
444
|
+
has_instance_transform=True,
|
|
445
|
+
)
|
|
446
|
+
)
|
|
447
|
+
|
|
448
|
+
INSTANCED_SHADER_SINGLE_COLOUR = generate_shader(
|
|
449
|
+
ShaderConfig(
|
|
450
|
+
name="INSTANCED_SHADER_SINGLE_COLOUR",
|
|
451
|
+
geometry_type="instanced",
|
|
452
|
+
colour_mode="single",
|
|
453
|
+
has_lighting=True,
|
|
454
|
+
has_view_matrix=True,
|
|
455
|
+
has_instance_transform=True,
|
|
456
|
+
)
|
|
457
|
+
)
|
|
458
|
+
|
|
459
|
+
LINE_SHADER_SINGLE_COLOUR = generate_shader(
|
|
460
|
+
ShaderConfig(name="LINE_SHADER_SINGLE_COLOUR", geometry_type="line", colour_mode="single")
|
|
461
|
+
)
|
|
462
|
+
|
|
463
|
+
LINE_SHADER_MULTI_COLOURED = generate_shader(
|
|
464
|
+
ShaderConfig(name="LINE_SHADER_MULTI_COLOURED", geometry_type="line", colour_mode="multi")
|
|
465
|
+
)
|
|
466
|
+
|
|
467
|
+
POINT_LIST_SHADER_MULTI_COLOURED = generate_shader(
|
|
468
|
+
ShaderConfig(
|
|
469
|
+
name="POINT_LIST_SHADER_MULTI_COLOURED",
|
|
470
|
+
geometry_type="point_list",
|
|
471
|
+
colour_mode="multi",
|
|
472
|
+
)
|
|
473
|
+
)
|
|
474
|
+
|
|
475
|
+
POINT_LIST_SHADER_SINGLE_COLOUR = generate_shader(
|
|
476
|
+
ShaderConfig(
|
|
477
|
+
name="POINT_LIST_SHADER_SINGLE_COLOUR",
|
|
478
|
+
geometry_type="point_list",
|
|
479
|
+
colour_mode="single",
|
|
480
|
+
)
|
|
481
|
+
)
|
|
482
|
+
|
|
483
|
+
TRIANGLE_SHADER_SINGLE_COLOUR = generate_shader(
|
|
484
|
+
ShaderConfig(
|
|
485
|
+
name="TRIANGLE_SHADER_SINGLE_COLOUR",
|
|
486
|
+
geometry_type="triangle",
|
|
487
|
+
colour_mode="single",
|
|
488
|
+
)
|
|
489
|
+
)
|
|
490
|
+
|
|
491
|
+
TRIANGLE_SHADER_MULTI_COLOURED = generate_shader(
|
|
492
|
+
ShaderConfig(
|
|
493
|
+
name="TRIANGLE_SHADER_MULTI_COLOURED",
|
|
494
|
+
geometry_type="triangle",
|
|
495
|
+
colour_mode="multi",
|
|
496
|
+
)
|
|
497
|
+
)
|