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 |
|
|
|
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 |
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(which is Vulkan-only: see the TODO entry).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 (
ShaderMaterialhas no WGSL emission path yet).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.
What is not yet web-compatible:
ShaderMaterial: Vulkan-only. The WGSL emission path is tracked inTODO.md(## Tier 2 / Architectural).
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.