sysl3d 0.1.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 (91) hide show
  1. sysl/__init__.py +81 -0
  2. sysl/shader/__init__.py +37 -0
  3. sysl/shader/evaluate.py +49 -0
  4. sysl/shader/evaluate_multipass.py +269 -0
  5. sysl/shader/evaluate_shader_trace.py +349 -0
  6. sysl/shader/evaluate_singlepass.py +865 -0
  7. sysl/shader/global_shader_context.py +497 -0
  8. sysl/shader/local_shader_context.py +123 -0
  9. sysl/shader/param_evaluate.py +202 -0
  10. sysl/shader/shader_mod_ext.py +239 -0
  11. sysl/shader/shader_module.py +99 -0
  12. sysl/shader/shader_templates/__init__.py +13 -0
  13. sysl/shader/shader_templates/common.py +91 -0
  14. sysl/shader/shader_templates/functions/__init__.py +15 -0
  15. sysl/shader/shader_templates/functions/combinator_templates.py +446 -0
  16. sysl/shader/shader_templates/functions/combinators.py +143 -0
  17. sysl/shader/shader_templates/functions/grid_functions.py +250 -0
  18. sysl/shader/shader_templates/functions/material_functions.py +123 -0
  19. sysl/shader/shader_templates/functions/shader_functions_2d.py +944 -0
  20. sysl/shader/shader_templates/functions/shader_functions_3d.py +685 -0
  21. sysl/shader/shader_templates/functions/transforms.py +294 -0
  22. sysl/shader/shader_templates/future_shaders.md +132 -0
  23. sysl/shader/shader_templates/imfx_shaders/__init__.py +15 -0
  24. sysl/shader/shader_templates/imfx_shaders/aa_pass.py +32 -0
  25. sysl/shader/shader_templates/imfx_shaders/all_outline.py +118 -0
  26. sysl/shader/shader_templates/imfx_shaders/basic_third_pass.py +22 -0
  27. sysl/shader/shader_templates/imfx_shaders/dither.py +54 -0
  28. sysl/shader/shader_templates/imfx_shaders/fxaa.py +77 -0
  29. sysl/shader/shader_templates/imfx_shaders/part_outline.py +51 -0
  30. sysl/shader/shader_templates/imfx_shaders/part_outline_nobg.py +53 -0
  31. sysl/shader/shader_templates/imfx_shaders/selection_highlight.py +87 -0
  32. sysl/shader/shader_templates/multipass/__init__.py +1 -0
  33. sysl/shader/shader_templates/multipass/sdf_trace.py +217 -0
  34. sysl/shader/shader_templates/strace_v1.py +369 -0
  35. sysl/shader/shader_templates/strace_v1_post_trace.py +271 -0
  36. sysl/shader/shader_templates/strace_v2.py +145 -0
  37. sysl/shader/shader_templates/strace_v3/__init__.py +11 -0
  38. sysl/shader/shader_templates/strace_v3/lighting.py +490 -0
  39. sysl/shader/shader_templates/strace_v3/main.py +235 -0
  40. sysl/shader/shader_templates/strace_v3/main_multipass.py +344 -0
  41. sysl/shader/shader_templates/strace_v3/materials.py +559 -0
  42. sysl/shader/shader_templates/strace_v3/tone_mapping.py +192 -0
  43. sysl/shader/shader_templates/strace_v3/utils.py +300 -0
  44. sysl/shader/shader_templates/strace_v4/README.md +14 -0
  45. sysl/shader/shader_templates/strace_v4/__init__.py +9 -0
  46. sysl/shader/shader_templates/strace_v4/lighting.py +444 -0
  47. sysl/shader/shader_templates/strace_v4/main.py +260 -0
  48. sysl/shader/shader_templates/strace_v4/main_multipass.py +243 -0
  49. sysl/shader/shader_templates/strace_v4/materials.py +487 -0
  50. sysl/shader/shader_templates/strace_v5.py +363 -0
  51. sysl/shader/shader_templates/strace_v6.py +312 -0
  52. sysl/shader/utils/conversion.py +49 -0
  53. sysl/shader/utils/texture.py +405 -0
  54. sysl/shader/utils/ubo.py +818 -0
  55. sysl/shader_runtime/__init__.py +58 -0
  56. sysl/shader_runtime/generate_shader_html.py +650 -0
  57. sysl/shader_runtime/offline_render.py +605 -0
  58. sysl/shader_runtime/templates/PRIMITIVE_EDITING.md +204 -0
  59. sysl/shader_runtime/templates/base.html.j2 +82 -0
  60. sysl/shader_runtime/templates/common_script.js.html.j2 +348 -0
  61. sysl/shader_runtime/templates/controls.html.j2 +303 -0
  62. sysl/shader_runtime/templates/multibuffer_shader_v2.html.j2 +71 -0
  63. sysl/shader_runtime/templates/primitive_editing.js.html.j2 +792 -0
  64. sysl/shader_runtime/templates/primitive_tracking.js.html.j2 +234 -0
  65. sysl/shader_runtime/templates/regl_script.js.html.j2 +126 -0
  66. sysl/shader_runtime/templates/shader_vis.html.j2 +35 -0
  67. sysl/shader_runtime/templates/static_shader.frag +355 -0
  68. sysl/shader_runtime/templates/twgl_multibuffer_script_simple.js.html.j2 +554 -0
  69. sysl/shader_runtime/templates/twgl_script.js.html.j2 +172 -0
  70. sysl/shader_runtime/templates/twgl_texture_loader.js.j2 +201 -0
  71. sysl/shader_runtime/templates/ubo_animation.js.html.j2 +468 -0
  72. sysl/shader_runtime/templates/ubo_animation_controls.html.j2 +116 -0
  73. sysl/shader_runtime/templates/ubo_controls.html.j2 +105 -0
  74. sysl/shader_runtime/templates/ubo_editor.js.html.j2 +485 -0
  75. sysl/shader_runtime/templates/ubo_loader.js.html.j2 +221 -0
  76. sysl/symbolic/__init__.py +4 -0
  77. sysl/symbolic/base.py +139 -0
  78. sysl/symbolic/fields.py +157 -0
  79. sysl/symbolic/mat_solid_combinators.py +33 -0
  80. sysl/symbolic/materials.py +203 -0
  81. sysl/torch_compute/__init__.py +20 -0
  82. sysl/torch_compute/evaluate_mat_expr.py +225 -0
  83. sysl/torch_compute/maps.py +63 -0
  84. sysl/torch_compute/mat_combinators.py +325 -0
  85. sysl/torch_compute/mat_functions.py +94 -0
  86. sysl/utils.py +208 -0
  87. sysl3d-0.1.0.dist-info/METADATA +325 -0
  88. sysl3d-0.1.0.dist-info/RECORD +91 -0
  89. sysl3d-0.1.0.dist-info/WHEEL +5 -0
  90. sysl3d-0.1.0.dist-info/licenses/LICENSE +21 -0
  91. sysl3d-0.1.0.dist-info/top_level.txt +1 -0
sysl/__init__.py ADDED
@@ -0,0 +1,81 @@
1
+ """
2
+ SySL: Symbolic Scene Language
3
+
4
+ A library for converting symbolic scene expressions into GLSL shader code
5
+ for sphere-traced rendering and interactive WebGL visualization.
6
+
7
+ Example:
8
+ >>> import geolipi.symbolic as gls
9
+ >>> import sysl.symbolic as sls
10
+ >>> from sysl.shader import evaluate_to_shader
11
+ >>> from sysl.shader_runtime import create_shader_html
12
+ >>>
13
+ >>> # Create a simple scene
14
+ >>> sphere = gls.Sphere3D((1.0,))
15
+ >>> material = sls.MaterialV4((1.0, 0.0, 0.0), (0.0, 0.0, 0.0), (0.5, 0.3, 0.0))
16
+ >>> scene = sls.MatSolidV4(sphere, material)
17
+ >>>
18
+ >>> # Generate shader code
19
+ >>> shader_code, uniforms, textures = evaluate_to_shader(scene)
20
+ >>>
21
+ >>> # Create interactive HTML
22
+ >>> html = create_shader_html(shader_code, uniforms, textures)
23
+ """
24
+
25
+ from importlib.metadata import PackageNotFoundError, version
26
+
27
+ try:
28
+ __version__ = version("sysl")
29
+ except PackageNotFoundError:
30
+ __version__ = "0.0.0"
31
+ __author__ = "Aditya Ganeshan"
32
+
33
+ # =============================================================================
34
+ # Public API
35
+ # =============================================================================
36
+
37
+ # Shader evaluation
38
+ from .shader import evaluate_to_shader, DEFAULT_SETTINGS, RenderMode
39
+
40
+ # Shader runtime (HTML generation, offline rendering)
41
+ from .shader_runtime import (
42
+ create_shader_html,
43
+ create_multibuffer_shader_html,
44
+ make_jupyter_compatible_html,
45
+ )
46
+
47
+ # Conditionally import offline rendering (requires moderngl)
48
+ try:
49
+ from .shader_runtime import render_single_pass, render_multipass
50
+ _HAS_OFFLINE_RENDER = True
51
+ except ImportError:
52
+ _HAS_OFFLINE_RENDER = False
53
+
54
+ # Symbolic module (re-export for convenience)
55
+ from . import symbolic
56
+
57
+ __all__ = [
58
+ # Version info
59
+ "__version__",
60
+ "__author__",
61
+ # Shader evaluation
62
+ "evaluate_to_shader",
63
+ "DEFAULT_SETTINGS",
64
+ "RenderMode",
65
+ # HTML generation
66
+ "create_shader_html",
67
+ "create_multibuffer_shader_html",
68
+ "make_jupyter_compatible_html",
69
+ # Symbolic module
70
+ "symbolic",
71
+ ]
72
+
73
+ # Add offline rendering to exports if available
74
+ if _HAS_OFFLINE_RENDER:
75
+ __all__.extend(["render_single_pass", "render_multipass"])
76
+
77
+
78
+
79
+
80
+
81
+
@@ -0,0 +1,37 @@
1
+ """
2
+ SySL Shader Generation Package.
3
+
4
+ This package converts symbolic SySL expressions into GLSL shader code.
5
+ Importing this module registers all shader modules (primitives, combinators,
6
+ transforms, materials, and rendering pipelines) in the global shader registry.
7
+
8
+ Main Entry Points:
9
+ - evaluate_to_shader: Convert expression to shader code
10
+ - DEFAULT_SETTINGS: Default configuration for shader generation
11
+ - RenderMode: Constants for render mode selection (V1-V6)
12
+
13
+ Example:
14
+ >>> from sysl.shader import evaluate_to_shader, DEFAULT_SETTINGS
15
+ >>> shader_code, uniforms, textures = evaluate_to_shader(expression)
16
+ """
17
+
18
+ # =============================================================================
19
+ # Shader Module Registration
20
+ # =============================================================================
21
+ # These imports register shader modules in the global SMMap registry.
22
+ # They are imported for their side effects (decorator-based registration).
23
+ from .shader_templates import *
24
+ # =============================================================================
25
+ # Public API
26
+ # =============================================================================
27
+
28
+ from .evaluate import evaluate_to_shader, DEFAULT_SETTINGS
29
+ from .shader_templates.common import RenderMode
30
+
31
+ __all__ = [
32
+ # Main entry point
33
+ "evaluate_to_shader",
34
+ "DEFAULT_SETTINGS",
35
+ # Render mode constants
36
+ "RenderMode",
37
+ ]
@@ -0,0 +1,49 @@
1
+ """
2
+ Main entry point for evaluating SySL expressions to shader code.
3
+
4
+ This module provides a unified interface for converting symbolic expressions
5
+ into GLSL shader code, supporting both single-pass and multi-pass rendering modes.
6
+ """
7
+
8
+ from typing import Dict, Any, List
9
+ import geolipi.symbolic as gls
10
+ import sysl.symbolic as sls
11
+
12
+ from .evaluate_singlepass import evaluate_singlepass
13
+ from .evaluate_multipass import evaluate_multipass
14
+ from .shader_templates.common import RenderMode
15
+ from .utils.conversion import convert_solid_types
16
+
17
+ DEFAULT_SETTINGS = {
18
+ "render_mode": RenderMode.DEFAULT,
19
+ "variables": {
20
+ "_ADD_FLOOR_PLANE": False,
21
+ "_RAYCAST_MAX_STEPS": 200,
22
+ "_RAYCAST_CONSERVATIVE_STEPPING_RATE": 0.99,
23
+ "_AA": 1,
24
+ "castShadows": True,
25
+ },
26
+ "extract_vars": False,
27
+ "use_define_vars": False
28
+ }
29
+
30
+ def evaluate_to_shader(expression: gls.GLFunction | gls.GLExpr,
31
+ mode: str = "singlepass",
32
+ settings: Dict[str, Any] | None = None,
33
+ insert_types: bool=True,
34
+ *args, **kwargs) -> List[Dict[str, Any]] | str:
35
+
36
+ if settings is None:
37
+ settings = DEFAULT_SETTINGS
38
+ render_mode = settings.get("render_mode", RenderMode.DEFAULT)
39
+ if insert_types:
40
+ expression = convert_solid_types(expression, render_mode)
41
+
42
+ if mode == "singlepass":
43
+ shader_output = evaluate_singlepass(expression, settings, *args, **kwargs)
44
+ elif mode == "multipass":
45
+ shader_output = evaluate_multipass(expression, settings, *args, **kwargs)
46
+ else:
47
+ raise ValueError(f"Invalid mode: {mode}")
48
+
49
+ return shader_output
@@ -0,0 +1,269 @@
1
+ """
2
+ Multi-pass shader evaluation for SySL expressions.
3
+
4
+ Multi-pass rendering separates the rendering pipeline into distinct phases:
5
+ 1. First pass: SDF ray tracing to compute intersection distance and primitive ID
6
+ 2. Second pass: Material evaluation and shading at intersection points
7
+ 3. Third pass: Screen-space post-processing (outlines, dithering, etc.)
8
+ 4. Fourth pass (optional): Anti-aliasing downsampling
9
+
10
+ This approach enables more complex rendering effects and better performance
11
+ for certain scene configurations.
12
+ """
13
+
14
+ import sympy as sp
15
+ from typing import Dict, Any, Tuple, Union as type_union
16
+ import geolipi.symbolic as gls
17
+ import sysl.symbolic as sls
18
+ from .global_shader_context import GlobalShaderContext
19
+ from .local_shader_context import SCENE_EXPR_PROPS
20
+ from .param_evaluate import _inline_parse_param_from_expr
21
+ from .shader_templates import imfx_shaders as imfx_shaders
22
+ from .shader_templates.common import RenderMode
23
+ from ..utils import recursive_sm_to_smg
24
+ from .evaluate_singlepass import rec_shader_eval
25
+ from .evaluate_shader_trace import rec_sdf_shader_eval
26
+
27
+ # Maps render mode to the corresponding post-trace shader module name
28
+ posttrace_map = {
29
+ RenderMode.V1: "mainImage_post_trace_v1",
30
+ RenderMode.V2: "mainImage_post_trace_v2",
31
+ RenderMode.V3: "mainImage_post_trace_v3",
32
+ RenderMode.V4: "mainImage_post_trace_v4",
33
+ RenderMode.V5: "mainImage_post_trace_v5",
34
+ RenderMode.V6: "mainImage_post_trace_v6",
35
+ }
36
+ def evaluate_multipass(expression: gls.GLFunction | gls.GLExpr,
37
+ settings: Dict[str, Any] | None = None,
38
+ return_shader_context: bool=False,
39
+ primitive_editing_mode: bool=False,
40
+ prim_expr: gls.GLFunction | gls.GLExpr | None = None,
41
+ map_first_pass_smg: bool=True,
42
+ post_process_shader: bool=None) -> type_union[Tuple[str, Dict[str, Any]], Tuple[str, Dict[str, Any], Any]]:
43
+
44
+ all_shader_bundles = []
45
+ all_global_sc = []
46
+ render_mode = settings.get("render_mode", RenderMode.DEFAULT)
47
+ extract_vars = settings.get("extract_vars", False)
48
+ set_to_ubo = settings.get("set_to_ubo", False)
49
+ set_param_to_texture = settings.get("set_param_to_texture", False)
50
+ AA = settings.get("variables", {}).get("_AA", 1)
51
+
52
+ if primitive_editing_mode:
53
+ exclude_class_set = (gls.UniformVariable, sls.MaterialV4)
54
+ else:
55
+ exclude_class_set = (gls.UniformVariable, )
56
+ # ================ FIRST PASS ================
57
+ global_sc = GlobalShaderContext()
58
+ if map_first_pass_smg:
59
+ first_pass_expression = recursive_sm_to_smg(expression)
60
+ else:
61
+ first_pass_expression = expression
62
+ if extract_vars:
63
+ varnamed_expr, _, var_map_base = first_pass_expression._get_varnamed_expr(exclude_class_set=exclude_class_set)
64
+ global_sc.create_var_map(var_map_base, set_to_ubo=set_to_ubo, set_param_to_texture=set_param_to_texture)
65
+ global_sc = rec_sdf_shader_eval(varnamed_expr, global_sc=global_sc)
66
+ else:
67
+ global_sc = rec_sdf_shader_eval(first_pass_expression, global_sc=global_sc)
68
+
69
+
70
+ # Do not link textures for the first pass.
71
+ if primitive_editing_mode:
72
+ # We need some uniforms.
73
+ gc_prim = GlobalShaderContext()
74
+ gc_prim = rec_sdf_shader_eval(prim_expr, global_sc=gc_prim)
75
+ global_sc.uniforms.update(gc_prim.uniforms)
76
+
77
+ global_sc.resolve_codebook()
78
+ global_sc.add_shader_module("main_sdf_trace", AA=AA)
79
+ shader_code = global_sc.emit_shader_code(settings, version="sdf_trace")
80
+ uniforms = global_sc.get_uniforms()
81
+ textures = global_sc.get_textures()
82
+
83
+ cur_res = uniforms['resolution']['init_value']
84
+ width = cur_res[0] * AA
85
+ height = cur_res[1] * AA
86
+
87
+ shader_bundle = {
88
+ "shader_code": shader_code,
89
+ "uniforms": uniforms,
90
+ "textures": textures,
91
+ "input_FBOs": [],
92
+ "output_FBO": {"name": "distance_travelled", "width": width, "height": height, "type": "vec4"}
93
+ }
94
+ all_shader_bundles.append(shader_bundle)
95
+ all_global_sc.append(global_sc)
96
+
97
+ # ================ SECOND PASS ================
98
+
99
+ if render_mode in [RenderMode.V3, RenderMode.V4, RenderMode.V5]:
100
+ global_sc = GlobalShaderContext()
101
+ global_sc.push_codebook("GEOM_EXPRESSION", SCENE_EXPR_PROPS)
102
+ if extract_vars:
103
+ varnamed_expr, _, var_map_base = expression._get_varnamed_expr(exclude_class_set=exclude_class_set)
104
+ global_sc.create_var_map(var_map_base, set_to_ubo=set_to_ubo, set_param_to_texture=set_param_to_texture)
105
+ global_sc = rec_sdf_shader_eval(varnamed_expr, global_sc=global_sc)
106
+ else:
107
+ global_sc = rec_sdf_shader_eval(expression, global_sc=global_sc)
108
+ global_sc.resolve_codebook() # This will finish and add the function.
109
+ global_sc.push_codebook("SCENE_EXPRESSION", SCENE_EXPR_PROPS)
110
+ else:
111
+ global_sc = GlobalShaderContext()
112
+
113
+ if extract_vars:
114
+ global_sc.create_var_map(var_map_base, set_to_ubo=set_to_ubo, set_param_to_texture=set_param_to_texture)
115
+ global_sc = rec_shader_eval(varnamed_expr, global_sc=global_sc)
116
+ else:
117
+ global_sc = rec_shader_eval(expression, global_sc=global_sc)
118
+ if primitive_editing_mode:
119
+ global_sc.uniforms.update(gc_prim.uniforms)
120
+ global_sc.resolve_codebook()
121
+
122
+ if render_mode == RenderMode.V3:
123
+ global_sc.resolve_material_stack(version=render_mode)
124
+ global_sc.add_shader_module(posttrace_map[render_mode], AA=AA)
125
+
126
+ shader_code = global_sc.emit_shader_code(settings, version="post_sdf_trace")
127
+ uniforms = global_sc.get_uniforms()
128
+ textures = global_sc.get_textures()
129
+
130
+ cur_res = uniforms['resolution']['init_value']
131
+ width_2 = cur_res[0] * AA
132
+ height_2 = cur_res[1] * AA
133
+
134
+ output_name = "intermediate_image"
135
+ shader_bundle = {
136
+ "shader_code": shader_code,
137
+ "uniforms": uniforms,
138
+ "textures": textures,
139
+ "input_FBOs": [{"name": "distance_travelled", "width": width, "height": height, "type": "vec4"}],
140
+ "output_FBO": {"name": output_name, "width": width_2, "height": height_2, "type": "vec4"}
141
+ }
142
+ all_shader_bundles.append(shader_bundle)
143
+ all_global_sc.append(global_sc)
144
+
145
+ # ================ THIRD PASS ================
146
+ third_bundles, output_name = create_third_pass_shader_bundle(
147
+ settings, width_2, height_2, output_name,
148
+ post_process_shader=post_process_shader, AA=AA
149
+ )
150
+ all_shader_bundles.extend(third_bundles)
151
+
152
+ # ================ FOURTH PASS (AA) ================
153
+ aa_bundle = create_aa_pass_shader_bundle(width_2, height_2, AA, output_name)
154
+ if aa_bundle:
155
+ all_shader_bundles.append(aa_bundle)
156
+ if return_shader_context:
157
+ return all_shader_bundles, all_global_sc
158
+ else:
159
+ return all_shader_bundles
160
+
161
+
162
+ def create_third_pass_shader_bundle(settings: Dict[str, Any],
163
+ width: int,
164
+ height: int,
165
+ input_image_name: str,
166
+ post_process_shader: list | None = None,
167
+ AA: int = 1,
168
+ include_distance_texture: bool = True) -> Tuple[Dict[str, Any], str]:
169
+ """
170
+ Create the third pass shader bundle for post-processing.
171
+
172
+ Args:
173
+ settings: Settings dictionary containing variables like outline_nhbd
174
+ width: Width of the input/output FBOs
175
+ height: Height of the input/output FBOs
176
+ input_image_name: Name of the input image FBO (e.g., "intermediate_image")
177
+ post_process_shader: List of post-process shader names, or None for basic pass
178
+ AA: Anti-aliasing factor (1 = no AA)
179
+ include_distance_texture: Whether to include distance_travelled as input FBO
180
+
181
+ Returns:
182
+ Tuple of (shader_bundle, output_name)
183
+ """
184
+ if post_process_shader is None:
185
+ post_process_shader = []
186
+ post_fx_args = dict(
187
+ nhbd=settings.get("variables", {}).get("outline_nhbd", 1),
188
+ dither_intensity_factor=settings.get("variables", {}).get("DITHER_INTENSITY_FACTOR", 0.5),
189
+ )
190
+
191
+ if AA > 1:
192
+ output_name = "image_AA"
193
+ else:
194
+ output_name = "image"
195
+ all_shader_bundles = []
196
+ # Create input output seq:
197
+ input_names = [input_image_name] + [f"interm_{i}" for i in range(len(post_process_shader) - 1)]
198
+ output_names = [f"interm_{i}" for i in range(len(post_process_shader) - 1)] + [output_name]
199
+ if post_process_shader:
200
+ for ind, shader_name in enumerate(post_process_shader):
201
+ cur_args = {x:y for x, y in post_fx_args.items()}
202
+ cur_args["input_name"] = input_names[ind]
203
+ if shader_name not in imfx_shaders.lookup_map:
204
+ raise ValueError(f"Invalid post process shader: {shader_name}")
205
+ shader_code = imfx_shaders.lookup_map[shader_name].substitute(**cur_args)
206
+ if include_distance_texture:
207
+ input_FBOs = [
208
+ {"name": "distance_travelled", "width": width, "height": height, "type": "vec4"},
209
+ {"name": input_names[ind], "width": width, "height": height, "type": "vec4"}
210
+ ]
211
+ else:
212
+ input_FBOs = [{"name": input_names[ind], "width": width, "height": height, "type": "vec4"}]
213
+
214
+ shader_bundle = {
215
+ "shader_code": shader_code,
216
+ "uniforms": {},
217
+ "textures": {},
218
+ "input_FBOs": input_FBOs,
219
+ "output_FBO": {"name": output_names[ind], "width": width, "height": height, "type": "vec4"}
220
+ }
221
+ all_shader_bundles.append(shader_bundle)
222
+ else:
223
+ cur_args = {x:y for x, y in post_fx_args.items()}
224
+ cur_args["input_name"] = input_image_name
225
+ shader_code = imfx_shaders.basic_third_pass.BASIC_THIRD_PASS_SHADER.substitute(**cur_args)
226
+ input_FBOs = [{"name": input_image_name, "width": width, "height": height, "type": "vec4"}]
227
+ shader_bundle = {
228
+ "shader_code": shader_code,
229
+ "uniforms": {},
230
+ "textures": {},
231
+ "input_FBOs": input_FBOs,
232
+ "output_FBO": {"name": output_name, "width": width, "height": height, "type": "vec4"}
233
+ }
234
+ all_shader_bundles.append(shader_bundle)
235
+
236
+ return all_shader_bundles, output_name
237
+
238
+
239
+ def create_aa_pass_shader_bundle(width: int,
240
+ height: int,
241
+ AA: int,
242
+ input_image_name: str = "image_AA") -> Dict[str, Any] | None:
243
+ """
244
+ Create the AA (anti-aliasing) pass shader bundle for downsampling.
245
+
246
+ Args:
247
+ width: Width of the input FBO (AA-scaled)
248
+ height: Height of the input FBO (AA-scaled)
249
+ AA: Anti-aliasing factor
250
+ input_image_name: Name of the input image FBO (default "image_AA")
251
+
252
+ Returns:
253
+ shader_bundle if AA > 1, otherwise None
254
+ """
255
+ if AA <= 1:
256
+ return None
257
+
258
+ resolution = width // AA
259
+ shader_code = imfx_shaders.fxaa.fxaa_shader(AA).substitute(resolution=resolution)
260
+ shader_bundle = {
261
+ "shader_code": shader_code,
262
+ "uniforms": {},
263
+ "textures": {},
264
+ "input_FBOs": [{"name": input_image_name, "width": width, "height": height, "type": "vec4"}],
265
+ "output_FBO": {"name": "image", "width": width // AA, "height": height // AA, "type": "vec4"}
266
+ }
267
+
268
+ return shader_bundle
269
+