Example 24

Example 24

The program displays a teapot by default. To enable a shader program simply pass it a vertex and fragment shader source file as follows:

use: ./shader_demo <vert_src_path> <frag_src_path>

If you leave off a fragment shader, it will only load the vertex file. Here are some examples:

Red

./shader_demo red.vert
ex_24/red.png

Color

./shader_demo color.vert
ex_24/color.png

Flatten and Wavy

./shader_demo flatten_wavy.vert
ex_24/flatten_wavy.png

Toon

./shader_demo toon.vert toon.frag
ex_24/toon.png

Fireworks

To use this demo, you must first edit shader_demo.c by switching the shader node render function and reorganizing the graph. To do this simply uncomment the two lines in the source code and comment the corresponding ones and recompile.

./shader_demo fireworks.vert fireworks.frag
ex_24/fireworks.png

Source Code

shader_demo.c:

/* Peter Bui
 * CSE 40166 Computer Graphics (Fall 2010)
 * Example 24: shader demo 
 */

#include "ssg.h"
 
#include <stdio.h>
#include <time.h>

/* Custom render functions -------------------------------------------------- */

#define NPARTICLES   200
#define MAX_VELOCITY 10 
#define MAX_TIMEOUT  5000

void
fireworks_render(SSG_Node *n)
{
    SSG_Shader *s = (SSG_Shader *)ssg_node_data(n);

    static float v[NPARTICLES][3];
    static int prev_time = 0;

    int next_time;
    int p, c;

    /* Generate random velocities */
    next_time = glutGet(GLUT_ELAPSED_TIME);
    if (prev_time == 0 || next_time - prev_time > MAX_TIMEOUT) {
        for (p = 0; p < NPARTICLES; p++) {
            for (c = 0; c < 3; c++) {
                v[p][c] = rand() % MAX_VELOCITY;

                if (c != 1)
                    v[p][c] -= (MAX_VELOCITY/2);
            }
        }
        prev_time = next_time;
    }

    /* Render velocities */
    glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
    glBegin(GL_POINTS); {
        for (p = 0; p < NPARTICLES; p++)
            glVertex3fv(v[p]);
    } glEnd();
    
    /* Set shader uniform variables */
    GLint ctloc, mtloc;

    ctloc = glGetUniformLocation(ssg_shader_program(s), "CurrentTime");
    mtloc = glGetUniformLocation(ssg_shader_program(s), "MaxTime");
    
    glUniform1f(ctloc, next_time - prev_time);
    glUniform1f(mtloc, MAX_TIMEOUT);
}

void
time_render(SSG_Node *n)
{
    SSG_Shader *s = (SSG_Shader *)ssg_node_data(n);
    GLint etloc;

    /* Set shader uniform variable */
    etloc = glGetUniformLocation(ssg_shader_program(s), "ElapsedTime");
    glUniform1f(etloc, glutGet(GLUT_ELAPSED_TIME));
}

/* Main execution ----------------------------------------------------------- */

int 
main(int argc, char *argv[])
{
    SSG_Node *root = NULL;
    SSG_Node *teapot = NULL;
    SSG_Node *shader = NULL;
    SSG_Viewer *viewer = NULL;
    char *vert_src_path = NULL;
    char *frag_src_path = NULL;

    srand(time(NULL));
    
    /* Parse command line arguments */
    if (argc > 3) {
        fprintf(stderr, "use: %s <vert_src_path> <frag_src_path>\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    if (argc <= 3) 
        vert_src_path = argv[1];
    if (argc == 3) 
        frag_src_path = argv[2];
    
    /* Create viewer */
    viewer = ssg_viewer_create("shader demo", 640, 480);
    ssg_viewer_initialize(viewer, &argc, argv);

    /* Create nodes */
    root   = ssg_node_create(NULL, SSG_NODE_RENDER, NULL);
    shader = ssg_node_create(time_render, SSG_NODE_SHADER, ssg_shader_create(vert_src_path, frag_src_path));
    //shader = ssg_node_create(fireworks_render, SSG_NODE_SHADER, ssg_shader_create(vert_src_path, frag_src_path));
    teapot = ssg_teapot_create();

    /* Organize graph */
    ssg_node_connect(root, shader);
    ssg_node_connect(shader, teapot);
    //ssg_node_connect(root, teapot);

    /* Show graph */
    ssg_viewer_show(viewer, root); 

    return (EXIT_SUCCESS);
}

/* vim: set sts=4 sw=4 ts=8 ft=cpp: ----------------------------------------- */

Files