vcti-shader-fringe
The fringe colormap shader feature: the fragment-stage math that turns a value into a colour.
Overview
A fringe plot colours a 3D model by the values at its nodes and elements. Drawing
one means mapping each fragment's value to an RGBA colour — and that last step is
what vcti-shader-fringe is.
A colormap here is a list of bands. Each band covers a half-open value range
[lower, upper) and carries the colours across it. Two ideas fall out of that
and keep the lookup small:
- A band whose two colours are equal is a constant band. There is no separate discrete mode — a ramp between one colour and itself is that colour.
- Below-range, above-range and no-value are ordinary bands too, appended to cover the rest of the number line, so the lookup has no special case for them.
A colormap also carries fallback colours, for the ways a value can have no band to come from: it is NaN, no band covers it, or the band that does is misconfigured. Each points at a different fix, so each gets its own colour.
There are two variants, and the data chooses which. A continuous result — a
displacement magnitude, a von Mises stress — is a float, interpolates across a
band, and uses Colormap. A discrete category — a material id, a part number —
is an exact integer, takes one colour per band, and uses DiscreteColormap.
Colouring an id through the float path works until it passes 2²⁴, where
neighbouring ids collapse onto the same number and take the same colour; the
integer path is exact to 2³¹.
Around that math the package declares two things — the specs saying what the
math needs supplied, and the ShaderDefinition saying what the feature is —
and ships the same lookup written in Python. Nothing here compiles or runs a
shader; a build step does that, using what this package declares.
The Python version is there for two reasons. The tests run it and the compiled shader over the same values and check the colours come out identical — that is how the shader is verified. And whatever draws the legend can call it directly, so the colour blocks in the legend always match the colours on the model.
Installation
pip install vcti-shader-fringe
Requires Python 3.12, 3.13, or 3.14, matching vcti-shader-base, and so does
the test extra. Only the gl extra — the GL binding the shader tests need to
execute anything — is narrower in practice: on 3.14 it builds moderngl's
glcontext from source for want of a cp314 wheel, so those tests are run on 3.12
or 3.13.
In requirements.txt
vcti-shader-fringe>=1.0.0
In pyproject.toml dependencies
dependencies = [
"vcti-shader-fringe>=1.0.0",
]
Quick Start
What the feature is
from vcti.shader.fringe import DEFINITION, SLANG_DIR, fragment_uniforms
DEFINITION.id # 'fringe'
DEFINITION.role # StageRole.FRAGMENT
DEFINITION.slang_modules # ('colormap.slang',) — a shader does `import colormap;`
SLANG_DIR # pass to the compiler as an import search path
[u.name for u in fragment_uniforms()]
# ['u_bandBounds', 'u_numBands', 'u_lowerColors', 'u_upperColors',
# 'u_interpModes', 'u_interpSteps', 'u_nanColor']
A continuous colormap
linear_bands() turns bounds and a palette into ramped bands;
with_edge_bands() frames them so the list covers the whole number line:
from vcti.shader.fringe import Colormap, linear_bands, with_edge_bands
PALETTE = [(0.0, 0.26, 0.62, 1.0), (0.65, 0.84, 0.85, 1.0), (0.6, 0.0, 0.0, 1.0)]
GREY = (0.83, 0.83, 0.83, 1.0)
colormap = Colormap(
with_edge_bands(
linear_bands([0.0, 1.0, 2.0], PALETTE), # one colour per bound
below_color=PALETTE[0],
above_color=PALETTE[-1],
no_value_color=GREY,
no_value_lower=1e30,
)
)
colormap.validate() # raises ValueError on a gap, overlap, or bad log bound
constant_bands() gives banded contours instead — one colour per band rather
than per bound. A constant band is simply one whose two colours are equal, so
there is no separate mode to select.
A discrete colormap
from vcti.shader.fringe import DiscreteBand, DiscreteColormap, category_bands
materials = DiscreteColormap(category_bands([STEEL, ALUMINIUM, COPPER]))
by_id = DiscreteColormap(( # raw solver ids, in ranges
DiscreteBand(1_000_000, 2_000_000, STEEL),
DiscreteBand(2_000_000, 3_000_000, ALUMINIUM),
))
Looking up a colour
fringe_color() is the Python version of the shipped Slang lookup:
from vcti.shader.fringe import fringe_color
fringe_color(5.0, colormap) # halfway through the linear band
fringe_color(31.6, colormap) # the geometric midpoint of the log band
fringe_color(-1.0, colormap) # below the range -> BLUE
fringe_color(3.402823466e38, colormap) # the no-value sentinel -> GREY
fringe_color(float("nan"), colormap) # not a number -> the NaN colour
Handing it to the GPU
colormap.uniforms()
# {'u_bandBounds': [(-inf, 0.0), (0.0, 10.0), ...], 'u_numBands': 5, ...}
Arrays are padded to MAX_BANDS; the shader reads only the first u_numBands.
Key API
| Name | What it is |
|---|---|
DEFINITION |
the ShaderDefinition the feature declares itself with |
SLANG_DIR |
the installed slang/ directory — an import search path |
fragment_uniforms(kind) |
the uniforms a shader declares, per variant |
fragment_inputs(kind) |
the vertex attribute the integer variant reads |
fragment_outputs() |
the fragColor output the feature writes |
ValueType |
FLOAT or INT — which variant a shader is built for |
Band |
one half-open range, its two colours, and its interpolation mode |
Colormap |
a band list, three fallback colours, and an optional step count |
DiscreteBand |
one half-open range of integer categories and its colour |
DiscreteColormap |
a band list and the colour for a category none holds |
Colormap.validate() |
raises on a gap, an overlap, or a log band reaching zero |
Colormap.uniforms() |
the {uniform: value} mapping, padded to MAX_BANDS |
linear_bands() |
bounds + one colour each → ramped bands |
constant_bands() |
bounds + one colour per band → flat bands |
category_bands() |
one band per consecutive integer category |
with_edge_bands() |
frames authored bands with below/above/no-value |
fringe_color(value, colormap) |
the colour a fragment takes — same result as the shader |
fringe_color_int(value, colormap) |
the same, for integer categories |
band_color(), band_parameter() |
the same, for a single band already in hand |
InterpMode |
LINEAR or LOG |
INTERP_MODES |
the same as a name-to-number map, as published on the spec |
MAX_BANDS |
band-array capacity, shared with the Slang module |
colormap.slang publishes applyFringe, applyFringeInt and
fringeBandColor. All take every value as an argument — nothing in the module
reads a uniform, so a shipped shader and the test probes run the same code from
different sources.
Dependencies
vcti-shader-base— theShaderDefinitionrecord and the spec types, itself zero-dependency.
Nothing else at runtime. vcti-shader-compiler and numpy are test-only:
the tests run the shader on a GPU and compare it against the Python version,
but declaring the feature needs neither.
Documentation
| If you want to… | Read |
|---|---|
| Get started using the package | Quick Start above |
| Build the colormaps a viewer actually ships | docs/patterns.md |
| Understand the colour model and the decisions behind it | docs/design.md |
| Navigate or modify the source | docs/source-guide.md |
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file vcti_shader_fringe-1.0.1.tar.gz.
File metadata
- Download URL: vcti_shader_fringe-1.0.1.tar.gz
- Upload date:
- Size: 31.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
faa7e37fa2623adab56d090b9dca7bd90ba88a3f51d6d311ddc93aaed94b104f
|
|
| MD5 |
97b5a3e20e6f51d5e91bbe1ce458c16c
|
|
| BLAKE2b-256 |
9aea6aa786f4014afb7fa1bfca5e61a33dbbc17fd5f04528213adf16e6d2cf68
|
Provenance
The following attestation bundles were made for vcti_shader_fringe-1.0.1.tar.gz:
Publisher:
release.yml on vcollab/vcti-python-shader-fringe
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
vcti_shader_fringe-1.0.1.tar.gz -
Subject digest:
faa7e37fa2623adab56d090b9dca7bd90ba88a3f51d6d311ddc93aaed94b104f - Sigstore transparency entry: 2494740594
- Sigstore integration time:
-
Permalink:
vcollab/vcti-python-shader-fringe@6b184bfa6739adad175134f2d7a76b06e5ec4fb5 -
Branch / Tag:
refs/tags/v1.0.1 - Owner: https://github.com/vcollab
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@6b184bfa6739adad175134f2d7a76b06e5ec4fb5 -
Trigger Event:
push
-
Statement type:
File details
Details for the file vcti_shader_fringe-1.0.1-py3-none-any.whl.
File metadata
- Download URL: vcti_shader_fringe-1.0.1-py3-none-any.whl
- Upload date:
- Size: 19.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
36efcb0b8da0f18418899291a9818c176591b07280453f6ee7bc7a154a5761ca
|
|
| MD5 |
2d74a0b93fd9dbccecaebe780db32bf3
|
|
| BLAKE2b-256 |
7b318b86877c97c9dd8cbb12c0ccd5045eb171922479a1767f434a970ddad4ec
|
Provenance
The following attestation bundles were made for vcti_shader_fringe-1.0.1-py3-none-any.whl:
Publisher:
release.yml on vcollab/vcti-python-shader-fringe
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
vcti_shader_fringe-1.0.1-py3-none-any.whl -
Subject digest:
36efcb0b8da0f18418899291a9818c176591b07280453f6ee7bc7a154a5761ca - Sigstore transparency entry: 2494740613
- Sigstore integration time:
-
Permalink:
vcollab/vcti-python-shader-fringe@6b184bfa6739adad175134f2d7a76b06e5ec4fb5 -
Branch / Tag:
refs/tags/v1.0.1 - Owner: https://github.com/vcollab
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@6b184bfa6739adad175134f2d7a76b06e5ec4fb5 -
Trigger Event:
push
-
Statement type: