Skip to content


Subversion checkout URL

You can clone with
Download ZIP


cjcliffe edited this page · 1 revision


The CustomShader class is used to encapsulate a user-defined shader that can be applied to a Material. CustomShader will automatically parse the given script and extract the uniforms and attributes and self-bind them to the CustomShader object. Self-binding includes support for structures, arrays and arrays of structures as well as utilizing #define statements for dynamically compiled structure sizes.


CustomShader( obj_init )

Construction is simple and takes only a vertex and fragment shader script tag ID containing script or a src='' URL for retrieval plus optional functions for initialization and update.

Example of script inclusion (HTML):

        <script id="vs" src="noise.vs" type="x-shader/x-vertex"></script>
        <script id="fs" src="noise.fs" type="x-shader/x-fragment"></script>

Javascript usage:

    var myShader = new CubicVR.CustomShader({
        vertex:   "#vs",    // Vertex Shader source or ID of <script> tag containing source or src='' url.
        fragment: "#fs",    // Fragment Shader source or ID of <script> tag containing source or src='' url.
        init: function(shader) {    // function called upon initialization of the shader
            // ... useful for setting one-time values here same way as ready() scope

    // Apply the custom shader to a material
    var customMaterial = new CubicVR.Material({
        shader: myShader

By utilizing the code at the end of the Core shaders (CubicVR_Core.vs, CubicVR_Core.fs) to create your own you can start your material with a fully functional version of the CubicVR GLSL material and lighting pipeline with minimal effort. By using this code to start your shaders will support the material parameters, shadows, morphing and lighting that the internal shaders can do without the need for additional bindings or tedious definitions.

The following is the minimal code from those files required to produce a compatible CustomShader material. No additional code from the Core shader files is required as it will be prefixed automatically at runtime.

Standard Vertex shader: (copied from last lines of CubicVR_Core.vs)

void main(void) 
  vertexTexCoordOut = cubicvr_texCoord();

  gl_Position =  matrixProjection * matrixModelView * cubicvr_transform();

  vertexNormalOut = matrixNormal * cubicvr_normal();


Standard Fragment shader: (copied from last lines of CubicVR_Core.fs)

void main(void) 
  vec2 texCoord = cubicvr_texCoord();

  vec4 color = cubicvr_color(texCoord);
  vec3 normal = cubicvr_normal(texCoord);

  color = cubicvr_environment(color,normal,texCoord);
  color = cubicvr_lighting(color,normal,texCoord);

  gl_FragColor = clamp(color,0.0,1.0);
  gl_FragColor = cubicvr_depthPack(texCoord);

You may leave out the depth pass conditions but if the check for LIGHT_DEPTH_PASS is omitted CubicVR.js will bypass your custom shader and use it's internal shaders for shadow and depth passes. The available uniforms and attributes will be listed in the CubicVR_Core shader source -- if you wish to use the internal parameters take note of any #ifdef statements used to control logic as they will apply to your usage as well.



If the shader has been successfully compiled and parsed this function will return true. This is used to ensure that a shader is loaded and bound prior to attempting to set any values, otherwise they may fail.


    CubicVR.MainLoop(function(timer, gl) {
        if (myShader.ready()) {
            // Just assign the value, CustomShader handles the rest.
            myShader.myTimer.value = timer.getSeconds();



true if ready, false if not.

getShader( )

Get the Shader object that the CustomShader is utilizing internally.


CubicVR Shader object if ready(), null otherwise.

Utilizing CustomShader Variables:

Assignment of variables is simple, if you added the variable to your shader source and it was successfully compiled and ready() returns true it will be available to set.

Shader source (example snippet of part where uniforms are defined):

    #define somePointsSize 3

    struct myType
        vec3 a;
        float b;
        mat4 c;

    uniform float myTimer;           // standard type
    uniform myType myStruct;         // structure
    uniform myType myStructArray[3]; // array of structure
    uniform vec3 somePoints[somePointsSize];   // array of standard type via define

    // ... 

Would yield the following accessable variables and usage:

    CubicVR.MainLoop(function(timer, gl) {
        if (myShader.ready()) {

            // standard type
            myShader.myTimer.value = timer.getSeconds();

            // structure
            myShader.myStruct.a.value = [0,1,2];
            myShader.myStruct.b.value = 10.5;
            myShader.myStruct.c.value = [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1];

            // array of structure
            myShader.myStructArray[0].a.value = [2,3,4];
            myShader.myStructArray[1].b.value = 20.6;
            myShader.myStructArray[2].c.value = [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1];

            // array of standard type
            myShader.somePoints[0].value = [0, 1, 2];
            myShader.somePoints[1].value = [2, 3, 4];
            myShader.somePoints[2].value = [4, 5, 6];

Something went wrong with that request. Please try again.