# Custom Shaders `ShaderMaterial` lets you write custom GLSL vertex and fragment shaders for any `MeshInstance3D`. ## Basic Usage ```python from simvx.graphics.materials.custom_shader import ShaderMaterial from simvx.core import MeshInstance3D, Mesh mat = ShaderMaterial( vertex_source=""" #version 450 layout(location = 0) in vec3 position; layout(push_constant) uniform PC { mat4 mvp; }; void main() { gl_Position = mvp * vec4(position, 1.0); } """, fragment_source=""" #version 450 layout(location = 0) out vec4 frag_colour; layout(set = 2, binding = 0) uniform UBO { float time; vec3 tint; }; void main() { frag_colour = vec4(tint * (0.5 + 0.5 * sin(time)), 1.0); } """, ) mat.set_uniform("time", 0.0) mat.set_uniform("tint", (1.0, 0.3, 0.1)) cube = MeshInstance3D(mesh=Mesh.cube(), material=mat) self.add_child(cube) ``` Update uniforms each frame in `process()`: ```python def process(self, dt): mat.set_uniform("time", self.elapsed_time) ``` ## Loading from Files ```python mat = ShaderMaterial( vertex_path="shaders/wave.vert", fragment_path="shaders/wave.frag", ) ``` GLSL files are compiled to SPIR-V automatically via `glslc`. Hot-reload is supported — modified shader files are detected and recompiled at runtime. ## Uniforms Set uniforms by name. Types are inferred from the Python value: ```python mat.set_uniform("speed", 2.5) # float mat.set_uniform("offset", (1.0, 0.0)) # vec2 mat.set_uniform("colour", (1.0, 0.5, 0.0)) # vec3 mat.set_uniform("tint", (1.0, 0.5, 0.0, 1.0)) # vec4 mat.set_uniform("count", 10) # int ``` For explicit type control: ```python mat.set_uniform_typed("grid_size", (8, 8), "ivec2") ``` Supported types: `float`, `int`, `uint`, `vec2`, `vec3`, `vec4`, `ivec2`, `ivec3`, `ivec4`, `mat4`. ## Example See `packages/graphics/examples/3d_custom_shader.py` for custom ShaderMaterial with animated uniforms. ## API Reference See {py:mod}`simvx.graphics.materials.custom_shader` for the complete shader API.