Skip to content

Shader Modifiers

Guillaume Sabran edited this page Dec 13, 2016 · 2 revisions

Goal

Make it easy to customize main generic shader logic by inserting small snippets of code

Usage

  • in the main shader code, include commented lines that might be replaced by a modifier. The lines are:
    • // header modifier here: where functions, uniforms etc should be defined
    • // body modifier here: where vertex / fragment level logic should run
  • shader modifier definition:
    • the header / main separation is done by:
      • putting all lines before #pragma body in the header, and the one after in the main. If no #pragma body is specified, default is in main.
      • putting all uniforms in the header.

Example

  • Vertex shader
// main.vsh
attribute vec4 position;
attribute vec2 texCoord;

uniform mat4 u_projection;
uniform mat4 u_modelview;

varying vec2 v_coord;
// header modifier here

void main() {
    v_coord.x = texCoord.y;
    v_coord.y = texCoord.x;

    gl_Position = u_projection * u_modelview * position;
    // body modifier here
}
  • Fragment shader
// main.fsh
precision mediump float;
uniform mediump vec3 u_color;
varying mediump vec2 v_coord;
// header modifier here

void main() {
    gl_FragColor = vec4(u_color, 1.0);
    // body modifier here
}

So all that program does it to set a solid color on the object. Let change that:

  • Fragment modifier code
// modifier.fsh
uniform vec3 u_color2;
gl_FragColor.rgb = v_coord.x * u_color2 + (1.0 - v_coord.x) * gl_FragColor.rgb;
  • Or equivalently
// modifier.fsh
uniform vec3 u_color2;
# pragma body
gl_FragColor.rgb = v_coord.x * u_color2 + (1.0 - v_coord.x) * gl_FragColor.rgb;
  • Code
do {
  // use a shader that sample from an image
  let vShader = try DDDFragmentShader(from: "main", withExtention: "vsh")
  let fShader = try DDDFragmentShader(from: "main", withExtention: "fsh")
  let fModifier = try String(contentsOf: Bundle.main.url(forResource: "modifier", withExtension: "fsh")!)
  let program = try DDDShaderProgram(vertex: vShader, fragment: fShader, modifier: [.fragment: fModifier])
  node.material.shaderProgram = program

  node.material.set(vec3: GLKVector3(v: (0, 0 ,1)), for: "u_color")
  node.material.set(vec3: GLKVector3(v: (1, 0 ,0)), for: "u_color2")
} catch {
  print("could not set shaders: \(error)")
}