Raw raster shader reference
This is the canonical shader contract for the Render Pipeline process. For GLSL syntax, generated declarations and portability, see GLSL runtime reference. For worked tasks, see Shader cookbook.
RAW_RASTER_PIPELINE is a score-specific format, not standard ISF. The fragment file contains the JSON header; the vertex file has the same stem (.fs / .vs or .frag / .vert). Declare resources and stage interfaces in the header rather than duplicating generated GLSL declarations. Shared controls and sampling helpers follow the ISF runtime contract; the raster interface below adds geometry, state and scene resources.
Minimal geometry shader
Fragment shader: VertexColor.fs
/*{
"ISFVSN": "2.0",
"MODE": "RAW_RASTER_PIPELINE",
"DESCRIPTION": "Render upstream geometry with vertex colors",
"CATEGORIES": ["3D"],
"VERTEX_INPUTS": [
{ "TYPE": "vec4", "NAME": "position" },
{ "TYPE": "vec4", "NAME": "color", "REQUIRED": false, "DEFAULT": [1, 1, 1, 1] }
],
"VERTEX_OUTPUTS": [ { "TYPE": "vec4", "NAME": "v_color" } ],
"FRAGMENT_INPUTS": [ { "TYPE": "vec4", "NAME": "v_color" } ],
"FRAGMENT_OUTPUTS": [ { "TYPE": "vec4", "NAME": "isf_FragColor" } ],
"PIPELINE_STATE": { "DEPTH_TEST": true, "DEPTH_WRITE": true, "TOPOLOGY": "triangles" }
}*/
void main() {
isf_FragColor = v_color;
}
Vertex shader: VertexColor.vs
void main() {
isf_vertShaderInit();
gl_Position = clipSpaceCorrMatrix
* VIEWPROJECTION_MATRIX
* MODEL_MATRIX
* vec4(position.xyz, 1.0);
v_color = color;
isf_vertShaderFinish();
}
isf_vertShaderInit() must be the first statement in main(). isf_vertShaderFinish() must be the last statement. They handle multiview plumbing and the one required clip-space correction for non-OpenGL backends. Do not add your own backend-specific Y flip.
Header fields
| Field | Description |
|---|---|
MODE |
Must be "RAW_RASTER_PIPELINE". |
VERTEX_INPUTS |
Geometry attributes read by the vertex shader. |
VERTEX_OUTPUTS |
Varyings written by the vertex shader. |
FRAGMENT_INPUTS |
Varyings read by the fragment shader. Must match vertex outputs. |
FRAGMENT_OUTPUTS |
Fragment outputs. Defaults to isf_FragColor. |
INPUTS |
UI controls, texture inputs, storage buffers, uniform buffers. |
OUTPUTS |
Offscreen outputs: color, depth, formats, layers, cubemaps, MSAA. |
PIPELINE_STATE |
Depth, blend, cull, topology, stencil, procedural draw controls. |
AUXILIARY |
Buffers and textures travelling with upstream geometry or scenes. |
TYPES |
User-defined struct layouts. |
MULTIVIEW |
Number of views for multiview rendering. |
EXECUTION_MODEL |
Repeated raster invocation: per mip, per layer, per cubemap face, manual. |
ALPHA, COMPOSITE, QUEUE, LAYER
|
Alpha and compositing / transparent layering controls. |
EXTENSIONS |
GLSL extensions to require. |
CLIP_DISTANCES, CULL_DISTANCES, DEPTH_LAYOUT, PRIMITIVE_DATA
|
Advanced raster features. |
Vertex inputs
VERTEX_INPUTS declare the attributes consumed by the vertex shader.
"VERTEX_INPUTS": [
{ "TYPE": "vec3", "NAME": "position", "SEMANTIC": "position" },
{ "TYPE": "vec3", "NAME": "normal", "SEMANTIC": "normal", "REQUIRED": false },
{ "TYPE": "vec2", "NAME": "uv", "SEMANTIC": "texcoord" },
{ "TYPE": "uint", "NAME": "draw_id", "SEMANTIC": "instance_draw_id" }
]
| Field | Description |
|---|---|
NAME |
GLSL variable name. |
TYPE |
GLSL input type: float, vectors, matrices, integer types, etc. |
LOCATION |
Optional explicit location. Auto-assigned if omitted; matrices consume multiple locations. |
SEMANTIC |
Attribute semantic to match in upstream geometry. Defaults to NAME. Use custom for exact-name matching. |
REQUIRED |
Default true. false allows a neutral fallback if upstream geometry lacks the attribute. |
DEFAULT |
Explicit fallback value used when REQUIRED: false. |
Standard semantic names include position, normal, texcoord, color, and tangent. Scene and CSF pipelines can also provide custom semantics such as translation, instance_draw_id, material indices, or particle data.
Varyings
VERTEX_OUTPUTS and FRAGMENT_INPUTS must match in order and type.
"VERTEX_OUTPUTS": [
{ "TYPE": "vec3", "NAME": "v_normal", "INTERPOLATION": "smooth" },
{ "TYPE": "uint", "NAME": "v_draw", "INTERPOLATION": "flat" }
],
"FRAGMENT_INPUTS": [
{ "TYPE": "vec3", "NAME": "v_normal", "INTERPOLATION": "smooth" },
{ "TYPE": "uint", "NAME": "v_draw", "INTERPOLATION": "flat" }
]
INTERPOLATION can be smooth, flat, noperspective, centroid, or sample.
Fragment outputs and render targets
Without FRAGMENT_OUTPUTS, the shader gets one vec4 isf_FragColor output.
"FRAGMENT_OUTPUTS": [
{ "TYPE": "vec4", "NAME": "color" },
{ "TYPE": "vec4", "NAME": "normalRoughness" }
],
"OUTPUTS": [
{ "NAME": "color", "TYPE": "color", "FORMAT": "rgba16f", "SAMPLES": 4 },
{ "NAME": "normalRoughness", "TYPE": "color", "FORMAT": "rgba16f" },
{ "NAME": "depth", "TYPE": "depth", "FORMAT": "d32f" }
]
Output fields:
| Field | Description |
|---|---|
NAME |
Output name. |
TYPE |
color or depth. |
FORMAT |
Texture format such as rgba8, rgba16f, rgba32f, r32f, d32f. |
WIDTH, HEIGHT
|
Fixed size or expression. |
LAYERS |
Texture array layer count. |
DEPTH |
3D texture depth. |
CUBEMAP |
Allocate as cubemap. |
GENERATE_MIPS |
Generate mipmaps after rendering. |
SAMPLES |
MSAA sample count. |
ALPHA, COMPOSITE
|
Per-output alpha / compositing policy. |
3D texture outputs cannot currently be written directly by raw raster; use Compute Shaders with EXECUTION_MODEL: 3D_IMAGE for true volumetric writes.
Color attachments sharing one framebuffer must have matching dimensions. The renderer uses the first explicit output size for the target; do not use different explicit sizes as a way to request independent MRT resolutions. Integer formats additionally depend on the Qt version and backend; see Graphics pipeline.
Controls and resource inputs
INPUTS supports normal ISF controls and richer graphics resources.
UI controls
"INPUTS": [
{ "NAME": "roughness", "TYPE": "float", "DEFAULT": 0.5, "MIN": 0.0, "MAX": 1.0 },
{ "NAME": "baseColor", "TYPE": "color", "DEFAULT": [1, 1, 1, 1] }
]
Texture inputs
{ "NAME": "albedo", "TYPE": "image", "FILTER": "linear", "WRAP": "repeat" }
{ "NAME": "env", "TYPE": "cubemap", "MIPMAP_MODE": "linear" }
Raw raster fragment shaders can use the same IMG_* helpers as ISF:
vec4 c = IMG_NORM_PIXEL(albedo, v_uv);
vec4 t = IMG_TEXEL(albedo, ivec2(10, 20));
vec4 e = IMG_CUBE(env, reflectDir);
Storage and uniform buffers
{
"NAME": "per_draws",
"TYPE": "storage",
"ACCESS": "read_only",
"VISIBILITY": "vertex",
"LAYOUT": [ { "NAME": "data", "TYPE": "PerDraw[]" } ]
}
{
"NAME": "cameraData",
"TYPE": "uniform",
"VISIBILITY": "vertex+fragment",
"LAYOUT": [ { "NAME": "viewProjection", "TYPE": "mat4" } ]
}
storage uses SSBOs. uniform uses std140 UBOs. VISIBILITY controls which shader stages can access the binding.
Built-in uniforms and macros
| Name | Type | Description |
|---|---|---|
TIME, TIMEDELTA, PROGRESS, FRAMEINDEX, PASSINDEX, RENDERSIZE, DATE, SAMPLERATE
|
ISF-style uniforms | Same as ISF. |
clipSpaceCorrMatrix |
mat4 |
Platform clip-space correction. Multiply clip-space output by it. |
MODEL_MATRIX |
mat4 |
Upstream geometry model transform. Identity on flattened scene path. |
VIEW_MATRIX |
mat4 |
Active camera view matrix. |
PROJECTION_MATRIX |
mat4 |
Active camera projection matrix. |
VIEWPROJECTION_MATRIX |
mat4 |
Projection × view for active camera / view index. |
CAMERA_POSITION |
vec3 |
Active camera world position. |
VIEW_INDEX |
int |
Multiview view index. 0 when not multiview. |
NUM_VIEWS |
int |
Multiview count when multiview is enabled. |
MSAA_SAMPLES |
int |
Active MSAA sample count. |
When a raw raster shader uses the built-in camera and does not declare its own camera binding, score injects a camera uniform block. The process gets a Camera geometry inlet when camera data can be connected.
Geometry path vs scene path
Geometry path
Use MODEL_MATRIX when a mesh, primitive, point cloud, or CSF geometry is connected directly to the Render Pipeline:
gl_Position = clipSpaceCorrMatrix * VIEWPROJECTION_MATRIX * MODEL_MATRIX * vec4(position.xyz, 1.0);
If no camera is connected, the injected camera block uses identity placeholders so simple geometry shaders still draw.
Scene path
Flattened scene renderers receive per-draw data in auxiliary buffers. In that path MODEL_MATRIX is intentionally identity; read the per-draw model matrix instead.
"VERTEX_INPUTS": [
{ "TYPE": "vec3", "NAME": "position" },
{ "TYPE": "uint", "NAME": "draw_id", "SEMANTIC": "instance_draw_id" }
],
"INPUTS": [
{ "NAME": "per_draws", "TYPE": "storage", "ACCESS": "read_only", "VISIBILITY": "vertex",
"LAYOUT": [ { "NAME": "data", "TYPE": "PerDraw[]" } ] }
],
"TYPES": [
{ "NAME": "PerDraw", "LAYOUT": [
{ "NAME": "model", "TYPE": "mat4" },
{ "NAME": "normal", "TYPE": "mat4" },
{ "NAME": "material_index", "TYPE": "uint" },
{ "NAME": "tag_hash", "TYPE": "uint" },
{ "NAME": "transform_slot", "TYPE": "uint" },
{ "NAME": "skeleton_offset", "TYPE": "uint" }
] }
]
mat4 model = per_draws.data[draw_id].model;
gl_Position = clipSpaceCorrMatrix * VIEWPROJECTION_MATRIX * model * vec4(position, 1.0);
Auxiliary scene data
Top-level AUXILIARY declares buffers and textures that are resolved from upstream geometry / scene data without creating score ports.
"AUXILIARY": [
{ "NAME": "scene_counts", "TYPE": "uniform",
"LAYOUT": [ { "NAME": "drawCount", "TYPE": "uint" } ] },
{ "NAME": "base_color", "TYPE": "texture", "FILTER": "linear" },
{ "NAME": "shadow_atlas", "TYPE": "image", "DEPTH": true, "COMPARE": "less" },
{ "NAME": "history", "TYPE": "storage_image", "FORMAT": "rgba16f", "ACCESS": "read_write",
"WIDTH": 1024, "HEIGHT": 1024 }
]
Auxiliary buffer entries default to SSBOs. Use TYPE: "uniform" for UBOs. Auxiliary texture types include image, texture, cubemap, image_cube, storage_image, storage_cube, storage_image_array, and storage_3d.
Pipeline state
PIPELINE_STATE controls the raster pipeline.
"PIPELINE_STATE": {
"DEPTH_TEST": true,
"DEPTH_WRITE": true,
"DEPTH_COMPARE": "less_equal",
"CULL_MODE": "back",
"FRONT_FACE": "ccw",
"POLYGON_MODE": "fill",
"TOPOLOGY": "triangles",
"BLEND": {
"ENABLE": true,
"SRC_COLOR": "src_alpha",
"DST_COLOR": "one_minus_src_alpha",
"OP_COLOR": "add",
"SRC_ALPHA": "one",
"DST_ALPHA": "one_minus_src_alpha",
"OP_ALPHA": "add"
}
}
Common fields:
| Field | Description |
|---|---|
DEPTH_TEST, DEPTH_WRITE, DEPTH_COMPARE
|
Depth state. |
DEPTH_BIAS, SLOPE_SCALED_DEPTH_BIAS
|
Depth bias. |
CULL_MODE |
none, front, or back. |
FRONT_FACE |
ccw or cw. |
POLYGON_MODE |
fill or line. |
LINE_WIDTH |
Line width where supported. |
TOPOLOGY |
triangles, triangle_strip, triangle_fan, lines, line_strip, points. |
VERTEX_COUNT, INSTANCE_COUNT
|
Procedural draw counts. |
BLEND |
One blend state for all outputs, or boolean shortcut. |
BLEND_PER_ATTACHMENT |
Per-output blend states. |
STENCIL_TEST and stencil masks / ops |
Stencil state. |
SHADING_RATE |
Variable-rate shading [w, h] where supported. |
If VERTEX_COUNT is set and VERTEX_INPUTS is empty, the pipeline performs a procedural draw driven by gl_VertexIndex / gl_InstanceIndex. If VERTEX_INPUTS is non-empty, the draw count is clamped to upstream geometry to avoid out-of-bounds reads.
Alpha, compositing, and transparency
Older development notes mention a TRANSPARENCY header block. The current parser instead exposes QUEUE and LAYER; TRANSPARENCY is not a supported current field. Use the private-target and resolve workflow below rather than relying on an ignored header key.
Declare what your color outputs contain:
{
"ALPHA": "premultiplied",
"COMPOSITE": "over",
"QUEUE": "transparent"
}
-
ALPHA:straightorpremultiplied. -
COMPOSITE:over,add,multiply,screen, orreplace. -
QUEUE:opaqueortransparent. Transparent inputs sharing a consumer are drawn after opaque ones.
When you declare explicit PIPELINE_STATE.BLEND, the blend state wins over COMPOSITE.
Layer shaders
LAYER lets a raw raster shader draw into private targets, then resolve into the consumer with a fullscreen resolve pass. This is useful for transparent effects, order-independent transparency approximations, depth-aware layers, and intermediate MRT composition.
"LAYER": {
"TARGETS": [
{ "NAME": "accum", "FORMAT": "rgba16f", "CLEAR": [0, 0, 0, 0], "COMPOSITE": "add" },
{ "NAME": "reveal", "FORMAT": "r16f", "CLEAR": [1, 0, 0, 0], "COMPOSITE": "multiply" }
],
"DEPTH_TEST": true,
"RESOLVE": { "OUTPUT": "isf_FragColor", "COMPOSITE": "over" }
}
In the fragment source, guard resolve-only code with #if defined(ISF_RESOLVE_PASS). LAYER_TEXEL(accum) reads the accumulation target at the current resolve pixel. Keep the geometry-pass writes in the other branch. Shader cookbook explains the complete weighted-transparency corpus example, including revealage blend factors.
RESOLVE.DEPTH_WRITE: true enables resolve depth writing; RESOLVE.DEPTH_INPUT instead names a depth input available to the resolve shader. These two options are mutually exclusive. An explicit resolve block requires an ISF_RESOLVE_PASS section in the source.
Layer shaders use SINGLE execution and cannot also declare OUTPUTS or multiview. The parser accepts at most eight private targets, with matching fragment output names and locations; the backend may support fewer attachments or formats. LAYER.TARGETS.BLEND and COMPOSITE are alternative declarations, not settings to combine on one target.
Execution models
Raw raster normally draws once per frame. EXECUTION_MODEL repeats the raster pass for specific targets.
"EXECUTION_MODEL": { "TYPE": "PER_CUBE_FACE", "TARGET": "env" }
| Type | Description |
|---|---|
SINGLE |
Default: one draw. |
PER_MIP |
Draw once per mip level of TARGET; PASSINDEX is the mip. |
PER_CUBE_FACE |
Draw six cubemap faces in GL cube-map order. TARGET must be a cubemap output. |
PER_LAYER |
Draw once per texture-array layer. |
MANUAL |
Draw COUNT times; COUNT is an expression. |
MULTIVIEW can render several layers / views in a single draw when the backend supports it. It is commonly used with CUBEMAP: true and MULTIVIEW: 6 for camera-array or IBL passes.
Primitive data
PRIMITIVE_DATA: true exposes generated fragment data:
"PRIMITIVE_DATA": true
The fragment shader receives:
PRIMITIVE_ID // primitive index
BARYCENTRIC // triangle barycentric coordinate
The runtime expands indexed and strip meshes as needed so primitive IDs and barycentrics are stable.
Clip, cull, and depth layout
Advanced depth / culling fields:
{
"CLIP_DISTANCES": 2,
"CULL_DISTANCES": 1,
"DEPTH_LAYOUT": "greater"
}
-
CLIP_DISTANCES: declaresgl_ClipDistance[N]for user clip planes. -
CULL_DISTANCES: declaresgl_CullDistance[N]for per-primitive culling. -
DEPTH_LAYOUT: conservative-depth qualifier forgl_FragDepth:any,greater,less, orunchanged.
Examples
Textured mesh
/*{
"ISFVSN": "2.0",
"MODE": "RAW_RASTER_PIPELINE",
"VERTEX_INPUTS": [
{ "TYPE": "vec4", "NAME": "position" },
{ "TYPE": "vec2", "NAME": "texcoord" }
],
"VERTEX_OUTPUTS": [ { "TYPE": "vec2", "NAME": "v_uv" } ],
"FRAGMENT_INPUTS": [ { "TYPE": "vec2", "NAME": "v_uv" } ],
"FRAGMENT_OUTPUTS": [ { "TYPE": "vec4", "NAME": "isf_FragColor" } ],
"INPUTS": [ { "NAME": "tex", "TYPE": "image" } ]
}*/
void main() {
isf_FragColor = IMG_NORM_PIXEL(tex, v_uv);
}
void main() {
isf_vertShaderInit();
gl_Position = clipSpaceCorrMatrix * VIEWPROJECTION_MATRIX * MODEL_MATRIX * position;
v_uv = texcoord;
isf_vertShaderFinish();
}
Procedural points
{
"MODE": "RAW_RASTER_PIPELINE",
"VERTEX_INPUTS": [],
"VERTEX_OUTPUTS": [ { "TYPE": "vec4", "NAME": "v_color" } ],
"FRAGMENT_INPUTS": [ { "TYPE": "vec4", "NAME": "v_color" } ],
"PIPELINE_STATE": { "TOPOLOGY": "points", "VERTEX_COUNT": 65536 }
}
In the vertex shader, use gl_VertexIndex to compute point positions.
Cubemap output
{
"MODE": "RAW_RASTER_PIPELINE",
"OUTPUTS": [
{ "NAME": "env", "TYPE": "color", "FORMAT": "rgba16f", "CUBEMAP": true, "GENERATE_MIPS": true, "WIDTH": 512, "HEIGHT": 512 }
],
"MULTIVIEW": 6
}
Use VIEW_INDEX to select per-face camera data, or connect a Camera Array to the Camera inlet.