1.2 Sample OpenGL GLUT Application

If you plan to use Sh with OpenGL to program shaders, you should take a look at glutex, a simple application that combines GLUT, OpenGL, and Sh. This application is available from the Sh website. The main program of glutex is given in its entirety in Listing ??, below. Note in particular the use of shInit, shBind, and shUpdate. You can use this program as a starting point for developing your own applications. For development and testing of shaders, however, shrike provides much more functionality.

#include <sh/sh.hpp>
#include <GL/glut.h>
#include <GL/glext.h>
#include <GL/glu.h>
#include "Camera.hpp"

using namespace SH;

ShMatrix4x4f MV, MD, VM;  // transformations
ShPoint3f light_pv;       // VCS light source position

Camera camera;  // camera object (see Camera.hpp)

ShProgram vsh, fsh; // vertex and fragment shader objects

// Glut data
int buttons[5] = GLUT_UP, GLUT_UP, GLUT_UP, GLUT_UP, GLUT_UP;
int cur_x, cur_y;  // for trackball

// initialize program objects for shaders
void init_shaders()

  vsh = SH_BEGIN_PROGRAM("gpu:vertex") 
    ShInputNormal3f nm;     // MCS normal
    ShInputPoint4f pm;      // MCS position

    ShOutputNormal3f nv;    // VCS normal
    ShOutputVector3f lv;    // VCS light vector
    ShOutputPosition4f pd;  // DCS position

    ShPoint3f pv = (MV|pm)(0,1,2); // Compute viewspace position
    lv = light_pv - pv; // Compute light direction in view space
    pd = MD|pm; // Transform position to device space
    nv = normalize((nm|VM)(0,1,2)); // Transform normal to view space
   SH_END;

  // declare and initialize diffuse color
  ShColor3f kd = ShColor3f(0.5, 0.7, 0.9);

  fsh = SH_BEGIN_PROGRAM("gpu:fragment") 
    ShInputNormal3f nv;  // VCS normal
    ShInputVector3f lv;  // VCS light vector

    ShOutputColor3f c;   // fragment color

    // normalize interpolated vectors to unit length
    nv = normalize(nv);
    lv = normalize(lv);
    // per-pixel diffuse lighting model
    c = kd * pos(nv|lv);
   SH_END;


// GLUT callback
//    draw using glut teapot (which has several faults, but)
void display ()

  // make sure Sh uniform parameters are synchronized
  shUpdate();

  // clear framebuffer
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  // draw teapot
  glFrontFace(GL_CW);
  glutSolidTeapot(2.5);
  glFrontFace(GL_CCW);

  // swap front and back buffers
  glutSwapBuffers();


void setup_view ()

  MV = camera.shModelView();
  VM = inverse(MV);
  MD = camera.shModelViewProjection(ShMatrix4x4f());


// GLUT callback
//    called on window resize
void reshape (int width, int height)

  glViewport(0, 0, width, height);
  setup_view();


// GLUT callback
//    called on mouse movement
void motion (int x, int y)

  const double factor = 20.0;
  bool changed = false;

  // process UI events
  if (buttons[GLUT_LEFT_BUTTON] == GLUT_DOWN) 
    // rotate camera orientation using left mouse button
    camera.orbit(cur_x, cur_y, x, y,
                 glutGet(GLUT_WINDOW_WIDTH),
                 glutGet(GLUT_WINDOW_HEIGHT));
    changed = true;
  
  if (buttons[GLUT_MIDDLE_BUTTON] == GLUT_DOWN) 
    // track camera forward and back using middle mouse button
    camera.move(0, 0, (y - cur_y)/factor);
    changed = true;
  
  if (buttons[GLUT_RIGHT_BUTTON] == GLUT_DOWN) 
    // pan camera using right mouse button
    camera.move((x - cur_x)/factor, (cur_y - y)/factor, 0);
    changed = true;
  

  // update everything
  if (changed) 
    setup_view();
    glutPostRedisplay();
  


void mouse (int button, int state, int x, int y)

  buttons[button] = state;
  cur_x = x;
  cur_y = y;


int main (int argc, char** argv)

  // set up GLUT
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
  glutInitWindowSize(512, 512);
  glutCreateWindow("glutex: Sh Example");

  // register callback functions
  glutDisplayFunc(display);
  glutReshapeFunc(reshape);
  glutMouseFunc(mouse);
  glutMotionFunc(motion);

  // initialize Sh
  shInit();
  // set up default GPU backend (optional)
  shSetBackend("arb");

  // initialize OpenGL state, turn on shader support
  glEnable(GL_DEPTH_TEST);
  glEnable(GL_VERTEX_PROGRAM_ARB);
  glEnable(GL_FRAGMENT_PROGRAM_ARB);
  glClearColor(0.0, 0.0, 0.0, 1.0);
  setup_view();

  // Place the camera at its initial position
  camera.move(0.0, 0.0, -15.0);

  // Set up the light position
  qv = ShPoint3f(5.0, 5.0, 5.0);

  // define our shader programs
  init_shaders();

  // bind shaders
  shBind(vsh);
  shBind(fsh);

  // hand over event processing to GLUT
  glutMainLoop();


Note: This manual is available as a bound book from AK Peters, including better formatting, in-depth examples, and about 200 pages not available on-line.