psychopy.tools.gltools.embedShaderSourceDefs

psychopy.tools.gltools.embedShaderSourceDefs(shaderSrc, defs)[source]

Embed preprocessor definitions into GLSL source code.

This function generates and inserts #define statements into existing GLSL source code, allowing one to use GLSL preprocessor statements to alter program source at compile time.

Passing {'MAX_LIGHTS': 8, 'NORMAL_MAP': False} to defs will create and insert the following #define statements into shaderSrc:

#define MAX_LIGHTS 8
#define NORMAL_MAP 0

As per the GLSL specification, the #version directive must be specified at the top of the file before any other statement (with the exception of comments). If a #version directive is present, generated #define statements will be inserted starting at the following line. If no #version directive is found in shaderSrc, the statements will be prepended to shaderSrc.

Using preprocessor directives, multiple shader program routines can reside in the same source text if enclosed by #ifdef and #endif statements as shown here:

#ifdef VERTEX
    // vertex shader code here ...
#endif

#ifdef FRAGMENT
    // pixel shader code here ...
#endif

Both the vertex and fragment shader can be built from the same GLSL code listing by setting either VERTEX or FRAGMENT as True:

vertexShader = gltools.compileShaderObjectARB(
    gltools.embedShaderSourceDefs(glslSource, {'VERTEX': True}),
    GL.GL_VERTEX_SHADER_ARB)
fragmentShader = gltools.compileShaderObjectARB(
    gltools.embedShaderSourceDefs(glslSource, {'FRAGMENT': True}),
    GL.GL_FRAGMENT_SHADER_ARB)

In addition, #ifdef blocks can be used to prune render code paths. Here, this GLSL snippet shows a shader having diffuse color sampled from a texture is conditional on DIFFUSE_TEXTURE being True, if not, the material color is used instead:

#ifdef DIFFUSE_TEXTURE
    uniform sampler2D diffuseTexture;
#endif
...
#ifdef DIFFUSE_TEXTURE
    // sample color from texture
    vec4 diffuseColor = texture2D(diffuseTexture, gl_TexCoord[0].st);
#else
    // code path for no textures, just output material color
    vec4 diffuseColor = gl_FrontMaterial.diffuse;
#endif

This avoids needing to provide two separate GLSL program sources to build shaders to handle cases where a diffuse texture is or isn’t used.

Parameters:
  • shaderSrc (str) – GLSL shader source code.

  • defs (dict) – Names and values to generate #define statements. Keys must all be valid GLSL preprocessor variable names of type str. Values can only be int, float, str, bytes, or bool types. Boolean values True and False are converted to integers 1 and 0, respectively.

Returns:

GLSL source code with #define statements inserted.

Return type:

str

Examples

Defining MAX_LIGHTS as 8 in a fragment shader program at runtime:

fragSrc = embedShaderSourceDefs(fragSrc, {'MAX_LIGHTS': 8})
fragShader = compileShaderObjectARB(fragSrc, GL_FRAGMENT_SHADER_ARB)

Back to top