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:
./shader_demo red.vert
./shader_demo color.vert
./shader_demo flatten_wavy.vert
./shader_demo toon.vert toon.frag
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
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: ----------------------------------------- */