Built In Shader Templates

To reduce boilerplate code, pySSV includes a selection of shader templates which generate any platform/compiler specific code needed for the shader. These templates should handle most needs for scientific visualisation, but if you want to write your own shader templates to add new functionality or simplify your workflow refer to Writing Shader Templates for details on writing shader templates.

Built In Shader Uniforms

All built in shader templates include the global_uniforms.glsl library which defines a variety of useful shader uniforms which are set automatically by pySSV. It also includes any automatically defined uniforms (such as textures and render buffer textures).

float uTime

The current time since the shader was started in seconds.

int uFrame

The current frame number of the shader.

vec4 uResolution

The resolution of the render buffer this shader is rendering to.

vec2 uMouse

The current mouse position in pixel coordinates.

bool uMouseDown

Whether a mouse button is pressed.

mat4x4 uViewMat

The view matrix for the SSVCanvas’s main camera.

mat4x4 uProjMat

The projection matrix for the SSVCanvas’s main camera.

vec3 uViewDir

The view direction for the SSVCanvas’s main camera.

If SHADERTOY_COMPAT is #define before importing the global_uniforms.glsl file (which is the case in the Shadertoy template) then the following uniforms are also defined as aliases of the above uniforms.

iTime

= uTime

iFrame

= uFrame

iResolution

= uResolution

iMouse

= vec4(uMouse, uMouse*(uMouseDown?1.:-1.))

This doesn’t quite match the implementation of shadertoy, but it’s close enough for many shaders.

_DYNAMIC_UNIFORMS

This macro is defined automatically by pySSV and expands to include the declarations of all automatically declared uniforms, such as user-defined textures and render buffer textures.

Pixel Shader Template

#pragma SSV pixel

This template exposes a single entrypoint to a pixel shader.

Entrypoint Signature

vec4 entrypoint(vec2 fragPos)
Parameters:
  • fragPos – the position of the pixel being processed by this shader invocation in pixel coordinates.

Returns:

the pixel’s colour.

Template Arguments

entrypoint

positional

type: str

The name of the entrypoint function to pixel the shader.

--z_value

default: 0.999

type: float

The constant value to write into the depth buffer. 0 is close to the camera, 1 is far away.

Example

#pragma SSV pixel frag
// The entrypoint to the fragment shader
vec4 frag(vec2 fragPos)
{
    vec2 uv = fragPos.xy / uResolution.xy;

    return mix(uv.xyx, uv.yyx, sin(uTime)*0.5+0.5);
}

Vertex Shader Template

#pragma SSV vert

This template exposes a single entrypoint to a vertex shader.

Entrypoint Signature

VertexOutput mainVert()
Returns:

a VertexOutput struct containing the transformed vertex data.

struct VertexOutput
vec4 position
vec4 color

The shader is expected to take input from the following vertex attributes:

vec4 in_vert
vec4 in_color

Template Arguments

entrypoint

positional

type: str

The name of the entrypoint function to vertex the shader.

Example

#pragma SSV vert mainVert
VertexOutput mainVert()
{
    VertexOutput o;
    vec4 pos = vec4(in_vert, 1., 1.0);
    pos = uViewMat * pos;
    pos = uProjMat * pos;
    o.position = pos;
    o.color = vec4(in_color, 1.);
    return o;
}

ShaderToy Template

#pragma SSV shadertoy

This template exposes a single entrypoint to a pixel shader. It’s designed to mimic the API of ShaderToy

Entrypoint Signature

void mainImage(vec4 fragColor, vec2 fragCoord)
Parameters:
  • fragColor (out) – the pixel’s final colour.

  • fragPos – the position of the pixel being processed by this shader invocation in pixel coordinates.

Template Arguments

None

Example

#pragma SSV shadertoy
void mainImage(out vec4 fragColor, in vec2 fragCoord)
{
    // Normalized pixel coordinates (from 0 to 1)
    vec2 uv = fragCoord/iResolution.yy;
    // Colour changing over time
    vec3 col = sin(uv.xyx + iTime * vec3(3, 4, 5)) * 0.5 + 0.5;
    // Output to screen
    fragColor = vec4(vec3(col), 1.);
}

Vertex/Pixel Shader Template

#pragma SSV vert_pixel

This template exposes an entrypoint to a vertex shader and an entrypoint to a pixel shader.

Entrypoint Signature

Vertex Stage

void mainVert()
Returns:

a VertexOutput struct containing the transformed vertex data.

The shader is expected to take input from the following vertex attributes:

vec4 in_vert
vec4 in_color

The shader is expected to take write to the following vertex attributes:

vec3 color
vec4 gl_Position

Pixel Stage

vec4 mainPixel(vec3 position)
Parameters:
  • position – the position written to gl_Position by the vertex shader.

Returns:

the final colour of the fragment.

The shader is expected to take input from the following interpolated vertex attributes:

vec4 color

Template Arguments

entrypoint_vert

positional

type: str

The name of the entrypoint function to vertex the shader.

entrypoint_pixel

positional

type: str

The name of the entrypoint function to pixel the shader.

Example

#pragma SSV vert_pixel vert pixel

#ifdef SHADER_STAGE_VERTEX
// Additional vertex->fragment interpolators can be defined as follows
layout(location = 3) out vec2 uv;

void vert() {
    uv = in_vert.xy;
    gl_Position = vec4(in_vert.xyz, 1.);
    gl_Position = uProjMat * uViewMat * gl_Position;
}
#endif // SHADER_STAGE_VERTEX

#ifdef SHADER_STAGE_FRAGMENT
// Make sure to also define any custom interpolators in the fragment stage
layout(location = 3) in vec2 uv;

vec4 pixel(vec3 pos) {
    vec3 col = vec3(0.);
    col.rg = uv;
    col.b = pos.z;
    return col;
}
#endif //SHADER_STAGE_FRAGMENT

Signed Distance Field Template

#pragma SSV sdf

This template exposes a single entrypoint to a pixel shader. It’s designed to mimic the API of ShaderToy

Entrypoint Signature

float map(vec3 pos)
Parameters:
  • pos – the position to sample sample the signed distance field at.

Returns:

the signed distance to the surface.

Template Arguments

entrypoint

positional

type: str

The name of the sdf function in the shader.

--camera_mode

choices: INTERACTIVE, AUTO

default: AUTO

How the camera should behave. INTERACTIVE, uses the canvas’ camera. AUTO, automatically rotates around the scene using the --camera_distance and --rotate_speed variables.

--camera_distance

default: 10.0

type: float

The distance of the camera from the centre of the distance field.

--rotate_speed

default: 0.1

type: float

The orbit speed of the camera around the SDF, in radians/second.

--raymarch_steps

default: 128

type: int

The number of raymarching steps to use when rendering, turn this up if the edges of surfaces look soft.

--raymarch_distance

default: 32.0

type: float

The maximum distance to raymarch.

--light_dir

default: normalize(vec3(0.5, 0.5, -0.9))

type: vec3

The maximum distance to raymarch.

--render_mode

choices: SOLID, DEPTH, XRAY, ISOLINES

default: SOLID

How the distance field should be rendered. Check the documentation for more information about each mode.

Example

#pragma SSV sdf sdf_main --camera_distance 2. --rotate_speed 1.5 --render_mode SOLID

// SDF taken from: https://iquilezles.org/articles/distfunctions/
float sdCappedTorus(vec3 p, vec2 sc, float ra, float rb) {
  p.x = abs(p.x);
  float k = (sc.y*p.x>sc.x*p.y) ? dot(p.xy,sc) : length(p.xy);
  return sqrt( dot(p,p) + ra*ra - 2.0*ra*k ) - rb;
}

float sdf_main(vec3 p) {
    float t = 2.*(sin(uTime)*0.5+0.5)+0.2;
    return sdCappedTorus(p, vec2(sin(t), cos(t)), 0.5, 0.2);
}

Point Cloud Template

#pragma SSV point_cloud

This template exposes a single entrypoint to a vertex shader. It treats input vertices as points and uses a geometry shader to turn each vertex into a camera-facing sprite.

Entrypoint Signature

VertexOutput vert()
Returns:

a VertexOutput struct containing the transformed vertex.

struct VertexOutput
vec4 position
float size

The size of the sprite representing the point.

vec4 color

The shader is expected to take input from the following vertex attributes:

vec4 in_vert
vec4 in_color

Template Arguments

None

Example

#pragma SSV point_cloud mainPoint
VertexOutput mainPoint()
{
    VertexOutput o;
    vec4 pos = vec4(in_vert, 1.0);
    pos = uViewMat * pos;
    pos = uProjMat * pos;
    o.position = pos;
    o.color = vec4(in_color, 1.);
    o.size = 30.0/uResolution.x;
    return o;
}

Render Test

#pragma SSV render_test

This template generates a simple pixel shader which displays a colour changing gradient. Useful as a shorthand to make a quick shader to test the rendering system.

Entrypoint Signature

None

Template Arguments

None

Example

#pragma SSV render_test

Geometry Shader Template

#pragma SSV geometry

This template exposes an entrypoint to a vertex shader and an entrypoint to a geometry shader. It treats input vertices as points which are processed by the user defined vertex shader and can then be turned into triangle primitives by the user defined geometry shader.

Entrypoint Signature

Vertex Stage

VertexOutput vert()

Where VertexOutput is substituted for the value of --vertex_output_struct.

returns:

a <VertexOutput> struct containing the transformed vertex.

If the --vertex_output_struct argument isn’t set then the <VertexOutput> struct is as follows:

struct DefaultVertexOutput
vec4 position
vec4 color
float size

The size of the sprite representing the point.

If the --custom_vertex_input flag isn’t specified then the vertex shader is expected to take input from the following vertex attributes:

vec4 in_vert
vec4 in_color

Geometry Stage

void geo(VertexOutput i)
Parameters:
  • i – the struct containing the processed vertex data

The geometry function is expected to write to these output variables before each call to EmitVertex():

vec4 gl_Position

The transformed (clip space) position of the vertex to emit.

vec4 out_color

The final colour of the vertex to be emitted.

The geometry function is responsible for calling EmitVertex() and EndPrimitive() as needed and must not emit more vertices in a single invocation than what is specified in --geo_max_vertices (default=4).

Template Arguments

entrypoint_vert

positional

type: str

The name of the entrypoint function to vertex the shader.

entrypoint_geo

positional

type: str

The name of the entrypoint function to geometry the shader.

--vertex_output_struct

default: DefaultVertexOutput

type: float

The name of the struct containing data to be transferred from the vertex stage to the geometry stage.

--geo_max_vertices

default: 4

type: const int

The maximum number of vertices which can be output be the geometry stage per input vertex. Must be a constant.

--custom_vertex_input

type: flag

When this flag is passed, the default vertex input attributes are not created and must be declared by the user.

Example

#pragma SSV geometry mainPoint mainGeo
#ifdef SHADER_STAGE_VERTEX
DefaultVertexOutput mainPoint()
{
    DefaultVertexOutput o;
    // Transform the points using the camera matrices
    vec4 pos = vec4(in_vert, 1.0);
    pos = uViewMat * pos;
    pos = uProjMat * pos;
    o.position = pos;
    o.color = vec4(in_color, 1.);
    o.size = 10.0/uResolution.x;
    return o;
}
#endif // SHADER_STAGE_VERTEX
#ifdef SHADER_STAGE_GEOMETRY
void mainGeo(DefaultVertexOutput i) {
    // Generate a quad for each point
    vec4 position = i.position;
    float size = i.size;
    out_color = i.color;
    vec4 aspect_ratio = vec4(1., uResolution.x/uResolution.y, 1., 1.);
    gl_Position = position + size * vec4(-1., -1., 0.0, 0.0) * aspect_ratio;
    EmitVertex();
    gl_Position = position + size * vec4(1., -1., 0.0, 0.0) * aspect_ratio;
    EmitVertex();
    gl_Position = position + size * vec4(-1., 1., 0.0, 0.0) * aspect_ratio;
    EmitVertex();
    gl_Position = position + size * vec4(1., 1., 0.0, 0.0) * aspect_ratio;
    EmitVertex();
    EndPrimitive();
}
#endif // SHADER_STAGE_GEOMETRY