simvx.graphics.materials.custom_shader¶
Custom shader material system: user-facing API for custom GLSL shaders.
Provides ShaderMaterial for per-object custom shaders, UniformBuffer for GPU-side uniform data, and ShaderMaterialManager for pipeline caching and hot-reload.
Module Contents¶
Classes¶
User-facing custom shader material. |
|
GPU buffer for custom shader uniforms (std140 layout). |
|
Caches custom-shader pipelines and drives the desktop custom-shader pass. |
Data¶
API¶
- simvx.graphics.materials.custom_shader.__all__¶
[‘ShaderMaterial’, ‘UniformBuffer’, ‘ShaderMaterialManager’]
- simvx.graphics.materials.custom_shader.log¶
‘getLogger(…)’
- class simvx.graphics.materials.custom_shader.ShaderMaterial(vertex_path: str | pathlib.Path | None = None, fragment_path: str | pathlib.Path | None = None, *, vertex_source: str | None = None, fragment_source: str | None = None, language: str = 'glsl', wgsl_vertex: str | None = None, wgsl_fragment: str | None = None, wgsl_vertex_path: str | pathlib.Path | None = None, wgsl_fragment_path: str | pathlib.Path | None = None)[source]¶
User-facing custom shader material.
Allows using custom GLSL vertex/fragment shaders with user-defined uniforms. Works alongside the engine’s existing uber-shader pipeline by creating its own separate Vulkan pipeline.
Example::
mat = ShaderMaterial( vertex_path="shaders/wave.vert", fragment_path="shaders/gradient.frag", ) mat.set_uniform("time", 0.0) mat.set_uniform("colour", (1.0, 0.5, 0.2, 1.0))Or with inline source::
mat = ShaderMaterial( vertex_source=""" #version 450 layout(location=0) in vec3 pos; void main() { gl_Position = vec4(pos, 1.0); } """, fragment_source=""" #version 450 layout(location=0) out vec4 out_color; void main() { out_color = vec4(1.0, 0.0, 0.0, 1.0); } """, )Initialization
- set_uniform(name: str, value: Any) None[source]¶
Set a shader uniform by name.
Supported types: float, int, vec2, vec3, vec4, mat4, and numpy arrays. Type is inferred automatically from the value.
- set_uniform_typed(name: str, value: Any, utype: str) None[source]¶
Set a uniform with an explicit GLSL type string.
- compile(device: Any, shader_dir: pathlib.Path | None = None) None[source]¶
Compile shaders to SPIR-V and create Vulkan shader modules.
Uses file paths if provided, otherwise writes inline source to temp files for compilation via glslc.
Args: device: Vulkan logical device handle. shader_dir: Base directory for resolving relative shader paths and includes.
- resolve_wgsl(base_dir: pathlib.Path | None = None) tuple[str | None, str | None][source]¶
Return (vertex_wgsl, fragment_wgsl) for the web escape hatch, or (None, None).
Inline
wgsl_vertex/wgsl_fragmenttake precedence over their*_pathcounterparts. Used by the web exporter to skip naga transpilation when hand-written WGSL is supplied. A partial escape hatch (only one stage) is an error: both stages must be provided together.
- property has_wgsl_escape_hatch: bool[source]¶
Whether hand-written WGSL is supplied for both stages (web only).
- get_pipeline_key() tuple[source]¶
Return a hashable key unique to this shader combination.
Used for pipeline caching in ShaderMaterialManager.
- class simvx.graphics.materials.custom_shader.UniformBuffer(max_size: int = 1024)[source]¶
GPU buffer for custom shader uniforms (std140 layout).
Manages a host-visible Vulkan buffer and descriptor set for binding user-defined uniforms to a custom shader pipeline.
The buffer is laid out according to std140 rules so it can be directly consumed by a GLSL uniform block.
Initialization
- create(device: Any, physical_device: Any) None[source]¶
Create the GPU buffer and descriptor resources.
- update(device: Any, uniform_data: dict[str, Any], uniform_types: dict[str, str]) None[source]¶
Upload uniform values to the GPU buffer using std140 layout.
Args: device: Vulkan logical device. uniform_data: Name-to-value mapping of uniforms. uniform_types: Name-to-GLSL-type mapping (e.g. {“time”: “float”}).
- class simvx.graphics.materials.custom_shader.ShaderMaterialManager[source]¶
Caches custom-shader pipelines and drives the desktop custom-shader pass.
Tracks all registered ShaderMaterial instances and their compiled pipelines. Pipelines are cached by the shader source/path combination so that multiple objects sharing the same shaders reuse one pipeline.
The manager also owns the shared per-frame camera UBO (group0) and a per-frame transforms SSBO (group1) used by every custom-shader draw. Per-material uniforms live in a group2 UBO created lazily per material.
The descriptor layout ABI is identical to the web WebGPU custom-shader ABI: group0 camera UBO, group1 transforms SSBO addressed by
gl_InstanceIndex, group2 per-material UBO (+ separated textures/samplers at binding 1.., not yet wired for the canary).Initialization
- register_material(material: simvx.graphics.materials.custom_shader.ShaderMaterial) None[source]¶
Track a ShaderMaterial for hot-reload monitoring.
- get_or_create_pipeline(material: simvx.graphics.materials.custom_shader.ShaderMaterial, device: Any, physical_device: Any, render_pass: Any, extent: tuple[int, int], shader_dir: pathlib.Path | None = None) tuple[Any, Any][source]¶
Get a cached pipeline for this material, or compile and create one.
Uses the unified ABI layouts: group0 camera UBO, group1 transforms SSBO, group2 per-material UBO. Returns
(VkPipeline, VkPipelineLayout).
- get_uniform_buffer(material: simvx.graphics.materials.custom_shader.ShaderMaterial) simvx.graphics.materials.custom_shader.UniformBuffer | None[source]¶
Get the per-material (group2) UniformBuffer for a material, if any.
- update_uniforms(material: simvx.graphics.materials.custom_shader.ShaderMaterial, device: Any) None[source]¶
Upload current uniform values for a material to its group2 GPU buffer.
- draw(cmd: Any, submissions: list, device: Any, physical_device: Any, render_pass: Any, extent: tuple[int, int], view: numpy.ndarray, proj: numpy.ndarray, registry: Any, shader_dir: pathlib.Path | None = None, frame_globals_buf: Any = None, gbuffer: bool = False) None[source]¶
Draw all ShaderMaterial-backed submissions inside the main render pass.
submissionsis the renderer’s per-frame[(mesh_handle, transform, material_id, shader_material)]list. Each submission is drawn individually (one transforms-SSBO slot per draw, addressed viagl_InstanceIndex), binding the cached custom pipeline, the shared camera UBO (group0), the transforms SSBO (group1), and the per-material UBO (group2). Per-material pipeline switching is the cost of the custom-shader path.
- check_hot_reload(device: Any, physical_device: Any, render_pass: Any, extent: tuple[int, int], shader_dir: pathlib.Path | None = None) list[simvx.graphics.materials.custom_shader.ShaderMaterial][source]¶
Check all registered materials for source file changes and recompile.
Returns a list of materials that were recompiled.