Skip to content
cjcliffe edited this page Nov 28, 2011 · 1 revision

CubicVR.CustomShader

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.

Constructor:

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):

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

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();

#if !LIGHT_DEPTH_PASS
  vertexNormalOut = matrixNormal * cubicvr_normal();
  
  cubicvr_lighting();
#endif
}

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

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

#if !LIGHT_DEPTH_PASS
  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);
#else
  gl_FragColor = cubicvr_depthPack(texCoord);
#endif
}

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.

Methods:

ready()

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.

Example:

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

        myScene.render();
    });

Returns:

true if ready, false if not.

getShader( )

Get the Shader object that the CustomShader is utilizing internally.

Returns:

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];
        } 

        myScene.render();
    });
Clone this wiki locally