Materials¶
simvx.core.Material is the backend-agnostic material data SimVX feeds to
both Vulkan and the WebGPU runtime. It carries colour, PBR parameters,
blending mode, flags (wireframe, double-sided, unlit), and up to five
texture maps.
from simvx.core import Material
red = Material(colour=(1, 0, 0, 1))
glass = Material(colour=(0.6, 0.9, 1.0, 0.4), blend="alpha")
brick = Material(albedo_map="textures/brick.png", roughness=0.8)
Constructor¶
Argument |
Type |
Default |
Notes |
|---|---|---|---|
|
RGBA (or RGB) in 0-1 |
|
Multiplied by albedo at shade time |
|
|
|
PBR metallic factor |
|
|
|
PBR roughness factor |
|
|
|
Pipeline derivative selector |
|
|
|
Alpha-test threshold for |
|
|
|
Force |
|
|
|
Disable backface culling |
|
|
|
Skip lighting; use raw albedo |
|
|
|
Diffuse texture |
|
|
|
Tangent-space normal map |
|
|
|
Packed B=metal, G=rough |
|
|
|
RGB emissive |
|
|
|
Ambient occlusion |
|
3- or 4-tuple |
|
RGB or RGB+intensity |
|
|
|
Scalar multiplier; folds into slot 4 |
|
|
|
Applied to every map: |
|
|
|
Per-axis UV scale |
|
|
|
Counter-clockwise about the UV origin |
Texture sources¶
Every *_map kwarg accepts three forms:
Filesystem / asset URI (str)¶
Material(albedo_map="assets/brick.png")
Material(albedo_map="pkg://my_game.assets/brick.png") # importlib.resources URI
The backend’s TextureManager resolves the path, decodes the image, and
caches by (source, filter).
Embedded image bytes (bytes)¶
with open("brick.png", "rb") as f:
Material(albedo_map=f.read())
Useful when bundling a single-file game export: the bytes ship in the Python source.
NumPy ndarray (in-memory texture)¶
import numpy as np
# 256x256 procedural ramp, RGBA uint8
ramp = np.zeros((256, 256, 4), dtype=np.uint8)
ramp[..., 0] = np.linspace(0, 255, 256, dtype=np.uint8)[None, :]
ramp[..., 3] = 255
Material(albedo_map=ramp, unlit=True)
# 2D height-tinted gradient, float32 in [0, 1]
gradient = np.zeros((1, 256, 4), dtype=np.float32)
gradient[..., 0] = np.linspace(0.1, 1.0, 256) # R rises with height
gradient[..., 3] = 1.0 # opaque
Material(albedo_map=gradient)
The constructor coerces ndarray sources to uint8 at construction:
uint8→ passed through unchanged.float32/float64in[0, 1]→ scaled by 255 touint8.floatoutside[0, 1]→ WARNING logged, clipped, then scaled.Other dtypes →
TypeError.
This guarantees the GPU sees byte-per-channel data on every backend.
Used by¶
Shipped ports relying on Material(albedo_map=ndarray):
Procedural Planets: bakes an HSL height-and-latitude ramp into a 1D texture so the planet shader can sample without a custom
ShaderMaterial.Q1K3: bakes per-room palette ramps for the retro look.
HexGL: bakes a track-side speed-strip texture.
Use this pattern when:
You need procedural / parameterised shading on the web target without a custom shader (or your
ShaderMaterialuses separated textures / transparency, which fall back on web: see below).You don’t want to ship binary asset files in a code-first port.
The texture is small enough that numpy generation is cheaper than disk I/O.
Web export compatibility¶
The Material data shape is identical across Vulkan and WebGPU.
albedo_map=ndarray is fully supported on web: the numpy buffer ships
through the resource channel as a KIND_TEXTURE upload. No additional
configuration required.
ShaderMaterial is partly web-compatible: opaque, UBO-only shaders are
transpiled GLSL→WGSL at export (build-time naga) and render through a
per-material pipeline. Shaders using separated textures (group(2)
binding 1+) or transparency warn and fall back to the underlying
Material on web; export with --strict to fail instead of degrading.
Inspector visibility¶
All Material constructor arguments are stored as plain Python attributes
on the instance (no Property descriptors yet). The editor inspector
renders the colour swatch and PBR sliders via a custom material widget;
texture-map fields are read-only and show the source URI / “ndarray
({H}x{W}, dtype)” summary.