8.2 Set Shader Callback Point

For the DX9 and OpenGL2 drivers, HOOPS provides the Driver callback point set shader. This callback point is triggered whenever the driver wants to set a shader. If you subscribe to this callback point, your callback function must always set a shader when it is called. To learn how to define and set a callback, please the programming guide section on callbacks.

8.2.1 The Set Shader callback function

The set shader callback function prototype is as follows:

void shadercallback(
    HIC_Rendition const *in_nr,
    HIC_Driver_Shader_Type driver_type,
    HIC_Driver_Shader_Geometry_Type geom_type,
    HIC_Driver_Shader_Geometry_Bits geom_bits,
    void const *geometry)

Your callback function can use each of the five parameters in the function signature to help determine whether or not to set a shader and which shader to set.

  • HIC_Rendition: is the net rendition.
  • HIC_Driver_Shader_Type: indicates which driver is running. Possible values are :
    • HIC_Driver_Shader_Type_DX9. HOOPS supports Shader Model 2 for this driver.
    • HIC_Driver_Shader_Type_OGL2. HOOPS support GLSL 1.20 for this driver.
  • HIC_Driver_Shader_Geometry_Type: indicates the type of geometry that the driver is trying to draw.
  • HIC_Driver_Shader_Geometry_Bits: is a bitfield that reflects what the geometry has, such as normals, vertex colors, vertex params, etc. In general, geom_bits is 0, geometry itself should be queried via HIC_Show functions. However, if you have segment level display lists enabled, HOOPS draws a compiled display list with a null geometry structure. In this case, the geom_bits field is the only method to query what was originally on the geometry.
  • void const *geometry: is a pointer to the geometry, and should be cast as one of the following HIC types depending on geom_type:
    • HIC_Tristrip if geom_type is HIC_Driver_Shader_Geometry_Type_FACES
    • HIC_Polyedge if geom_type is HIC_Driver_Shader_Geometry_Type_EDGES or HIC_Driver_Shader_Geometry_Type_LINES
    • HIC_Polymarker if HIC_Driver_Shader_Geometry_Type_MARKERS

8.2.2 Set a Custom Shader with I.M. Functions

Once you have determined what shader you would like to use, HOOPS provides a set of I.M. functions that packages the shader information so that it can be set on the driver. Before you can set a shader, it needs to be compiled using the function HIC_Driver_Compile_Shader. Here, you must pass whether the shader is a vertex or pixel shader and a character buffer containing the shader's source code as well as the rendition. Please note that for DX9, the vertex shader's main function must be called "vs_main" while the pixel shader's main function "ps_main". For OpenGL2, the main function of each shader should be just "main". HIC_Driver_Compile_Shader compiles the supplied shader source and then returns a handle to the resulting shader.

static void shader_callback(HIC_Rendition const                 *in_nr, 
                         HIC_Driver_Shader_Type                 driver_type, 
                         HIC_Driver_Shader_Geometry_Type        geom_type,
                         HIC_Driver_Shader_Geometry_Bits        geom_bits,
                         void const                             *geometry)
{
    static HC_POINTER_SIZED_INT vs_handle;
    static HC_POINTER_SIZED_INT ps_handle;

    // handling the dx9 case
    if (driver_type != HIC_Driver_Shader_Type_DX9)
        return;

    // Ensure we have tristrip geometry
    HIC_Tristrip * ts = (HIC_Tristrip *) geometry;
    if (!ts || geom_type != HIC_Driver_Shader_Geometry_Type_FACES)
        return;

    // Compile and set shaders
    if (!vs_handle) {
    
        //reading in the code for our shaders
        char *vs_source = read_in_vertex_shader();
        char *ps_source = read_in_pixel_shader();

        vs_handle = HIC_Driver_Compile_Shader(nr, HIC_Shader_Type_VERTEX_SHADER, vs_source);
        ps_handle = HIC_Driver_Compile_Shader(nr, HIC_Shader_Type_PIXEL_SHADER, ps_source);

        assert(vs_handle);
        assert(ps_handle);

        delete [] vs_source;
        delete [] ps_source;
    }
...
}

As seen in the sample code above in the shader_callback function, we only read in and compile the vertex and pixel shaders the first time. Then, in subsequent calls, we used the handle for the compiled shader again. Once the shader code has been compiled, HIC_Driver_Set_Shader is called passing the handle for the shader as well as the shader type.

    bool set_uniforms = HIC_Driver_Set_Shader(nr, HIC_Shader_Type_VERTEX_SHADER, vs_handle;
    set_uniforms |= HIC_Driver_Set_Shader(nr, HIC_Shader_Type_PIXEL_SHADER, ps_handle);

In the code above, we record the value that HIC_Driver_Set_Shader returns. If this value is true, constants uniforms need to be reset due to shader switching. When a custom shader is registered, HOOPS will not load anything at all into the constant table. All constant table management will be done on the developer's side.

The following values are the developer's responsibility:

  • modelling and projection matrices
  • lights
  • materials
  • textures including binding, enabling, sampling
  • constant table and uniforms
  • cutting planes
  • fog

The following values are HOOPS' responsibility:

  • alpha blending state (on/off)
  • culling state (off/cw/ccw)
  • viewport / scissor

In the sample code below, the shader_callback function handles setting the modelling and projection matrix and lights for the vertex shaders.

...
    if (set_uniforms) {
        // Query face color
        float input_color[4];
        input_color[0] = HIC_Show_Face_Color_Red(nr);
        input_color[1] = HIC_Show_Face_Color_Green(nr);
        input_color[2] = HIC_Show_Face_Color_Blue(nr);
        input_color[3] = HIC_Show_Face_Opacity(nr);

        // Query model/proj matrices
        float projection_matrix[16], modelview_matrix[16];
        HIC_Driver_Show_Shader_Projection_Matrix(nr, projection_matrix);
        HIC_Driver_Show_Shader_Modelview_Matrix(nr, modelview_matrix);      

        // Setup a distant light vector
        float distant_light[3] = {0, 0, -1};

        HIC_Driver_Set_Shader_Matrix(nr, HIC_Shader_Type_VERTEX_SHADER, "matProj", 1, projection_matrix);
        HIC_Driver_Set_Shader_Matrix(nr, HIC_Shader_Type_VERTEX_SHADER, "matWorldView", 1, modelview_matrix);       
        HIC_Driver_Set_Shader_Vector(nr, HIC_Shader_Type_VERTEX_SHADER, "inputColor", 4, 1, input_color);
        HIC_Driver_Set_Shader_Vector(nr, HIC_Shader_Type_VERTEX_SHADER, "light1", 3, 1, distant_light);

    }

In the sample code above, we use sever HOOPS I.M. functions to set shader uniforms. They are:

  • HIC_Driver_Set_Shader_Integer
  • HIC_Driver_Set_Shader_Float
  • HIC_Driver_Set_Shader_Vector
  • HIC_Driver_Set_Shader_Matrix

HOOPS also provides the following functions to help users set up shader constants to be more consistent with HOOPS' internal shaders:

  • HIC_Driver_Show_Shader_Modelview_Matrix
  • HIC_Driver_Show_Shader_Projection_Matrix

Next

Previous

Index