132001f49Smrg/**
232001f49Smrg * "Mandelbrot" shader demo.  Uses the example shaders from
332001f49Smrg * chapter 15 (or 18) of the OpenGL Shading Language "orange" book.
432001f49Smrg * 15 Jan 2007
532001f49Smrg */
632001f49Smrg
732001f49Smrg#include <assert.h>
832001f49Smrg#include <string.h>
932001f49Smrg#include <stdio.h>
1032001f49Smrg#include <stdlib.h>
1132001f49Smrg#include <math.h>
1232001f49Smrg#include <GL/glew.h>
1332001f49Smrg#include "glut_wrap.h"
1432001f49Smrg#include "shaderutil.h"
1532001f49Smrg
1632001f49Smrg
1732001f49Smrgstatic char *FragProgFile = "CH18-mandel.frag";
1832001f49Smrgstatic char *VertProgFile = "CH18-mandel.vert";
1932001f49Smrg
2032001f49Smrg/* program/shader objects */
2132001f49Smrgstatic GLuint fragShader;
2232001f49Smrgstatic GLuint vertShader;
2332001f49Smrgstatic GLuint program;
2432001f49Smrg
2532001f49Smrg
2632001f49Smrgstatic struct uniform_info Uniforms[] = {
2732001f49Smrg   /* vert */
2832001f49Smrg   { "LightPosition",        1, GL_FLOAT_VEC3, { 0.1, 0.1, 9.0, 0}, -1 },
2932001f49Smrg   { "SpecularContribution", 1, GL_FLOAT, { 0.5, 0, 0, 0 }, -1 },
3032001f49Smrg   { "DiffuseContribution",  1, GL_FLOAT, { 0.5, 0, 0, 0 }, -1 },
3132001f49Smrg   { "Shininess",            1, GL_FLOAT, { 20.0, 0, 0, 0 }, -1 },
3232001f49Smrg   /* frag */
3332001f49Smrg   { "MaxIterations",        1, GL_FLOAT, { 12, 0, 0, 0 }, -1 },
3432001f49Smrg   { "Zoom",                 1, GL_FLOAT, { 0.125, 0, 0, 0 }, -1 },
3532001f49Smrg   { "Xcenter",              1, GL_FLOAT, { -1.5, 0, 0, 0 }, -1 },
3632001f49Smrg   { "Ycenter",              1, GL_FLOAT, { .005, 0, 0, 0 }, -1 },
3732001f49Smrg   { "InnerColor",           1, GL_FLOAT_VEC3, { 1, 0, 0, 0 }, -1 },
3832001f49Smrg   { "OuterColor1",          1, GL_FLOAT_VEC3, { 0, 1, 0, 0 }, -1 },
3932001f49Smrg   { "OuterColor2",          1, GL_FLOAT_VEC3, { 0, 0, 1, 0 }, -1 },
4032001f49Smrg   END_OF_UNIFORMS
4132001f49Smrg};
4232001f49Smrg
4332001f49Smrgstatic GLint win = 0;
4432001f49Smrg
4532001f49Smrgstatic GLfloat xRot = 0.0f, yRot = 0.0f, zRot = 0.0f;
4632001f49Smrg
4732001f49Smrgstatic GLint uZoom, uXcenter, uYcenter;
4832001f49Smrgstatic GLfloat zoom = 1.0, xCenter = -1.5, yCenter = 0.0;
4932001f49Smrg
5032001f49Smrg
5132001f49Smrgstatic void
5232001f49SmrgRedisplay(void)
5332001f49Smrg{
5432001f49Smrg   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
5532001f49Smrg
5632001f49Smrg   /* set interactive uniform parameters */
5732001f49Smrg   glUniform1fv(uZoom, 1, &zoom);
5832001f49Smrg   glUniform1fv(uXcenter, 1, &xCenter);
5932001f49Smrg   glUniform1fv(uYcenter, 1, &yCenter);
6032001f49Smrg
6132001f49Smrg   glPushMatrix();
6232001f49Smrg   glRotatef(xRot, 1.0f, 0.0f, 0.0f);
6332001f49Smrg   glRotatef(yRot, 0.0f, 1.0f, 0.0f);
6432001f49Smrg   glRotatef(zRot, 0.0f, 0.0f, 1.0f);
6532001f49Smrg
6632001f49Smrg   glBegin(GL_POLYGON);
6732001f49Smrg   glTexCoord2f(0, 0);   glVertex2f(-1, -1);
6832001f49Smrg   glTexCoord2f(1, 0);   glVertex2f( 1, -1);
6932001f49Smrg   glTexCoord2f(1, 1);   glVertex2f( 1,  1);
7032001f49Smrg   glTexCoord2f(0, 1);   glVertex2f(-1,  1);
7132001f49Smrg   glEnd();
7232001f49Smrg
7332001f49Smrg   glPopMatrix();
7432001f49Smrg
7532001f49Smrg   glutSwapBuffers();
7632001f49Smrg}
7732001f49Smrg
7832001f49Smrg
7932001f49Smrgstatic void
8032001f49SmrgReshape(int width, int height)
8132001f49Smrg{
8232001f49Smrg   glViewport(0, 0, width, height);
8332001f49Smrg   glMatrixMode(GL_PROJECTION);
8432001f49Smrg   glLoadIdentity();
8532001f49Smrg   glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0);
8632001f49Smrg   glMatrixMode(GL_MODELVIEW);
8732001f49Smrg   glLoadIdentity();
8832001f49Smrg   glTranslatef(0.0f, 0.0f, -6.0f);
8932001f49Smrg}
9032001f49Smrg
9132001f49Smrg
9232001f49Smrgstatic void
9332001f49SmrgCleanUp(void)
9432001f49Smrg{
9532001f49Smrg   glDeleteShader(fragShader);
9632001f49Smrg   glDeleteShader(vertShader);
9732001f49Smrg   glDeleteProgram(program);
9832001f49Smrg   glutDestroyWindow(win);
9932001f49Smrg}
10032001f49Smrg
10132001f49Smrg
10232001f49Smrgstatic void
10332001f49SmrgKey(unsigned char key, int x, int y)
10432001f49Smrg{
10532001f49Smrg  (void) x;
10632001f49Smrg  (void) y;
10732001f49Smrg
10832001f49Smrg   switch(key) {
10932001f49Smrg   case 'z':
11032001f49Smrg      zoom *= 0.9;
11132001f49Smrg      break;
11232001f49Smrg   case 'Z':
11332001f49Smrg      zoom /= 0.9;
11432001f49Smrg      break;
11532001f49Smrg   case 27:
11632001f49Smrg      CleanUp();
11732001f49Smrg      exit(0);
11832001f49Smrg      break;
11932001f49Smrg   }
12032001f49Smrg   glutPostRedisplay();
12132001f49Smrg}
12232001f49Smrg
12332001f49Smrg
12432001f49Smrgstatic void
12532001f49SmrgSpecialKey(int key, int x, int y)
12632001f49Smrg{
12732001f49Smrg   const GLfloat step = 0.1 * zoom;
12832001f49Smrg
12932001f49Smrg  (void) x;
13032001f49Smrg  (void) y;
13132001f49Smrg
13232001f49Smrg   switch(key) {
13332001f49Smrg   case GLUT_KEY_UP:
13432001f49Smrg      yCenter += step;
13532001f49Smrg      break;
13632001f49Smrg   case GLUT_KEY_DOWN:
13732001f49Smrg      yCenter -= step;
13832001f49Smrg      break;
13932001f49Smrg   case GLUT_KEY_LEFT:
14032001f49Smrg      xCenter -= step;
14132001f49Smrg      break;
14232001f49Smrg   case GLUT_KEY_RIGHT:
14332001f49Smrg      xCenter += step;
14432001f49Smrg      break;
14532001f49Smrg   }
14632001f49Smrg   glutPostRedisplay();
14732001f49Smrg}
14832001f49Smrg
14932001f49Smrg
15032001f49Smrgstatic void
15132001f49SmrgInit(void)
15232001f49Smrg{
15332001f49Smrg   if (!ShadersSupported())
15432001f49Smrg      exit(1);
15532001f49Smrg
15632001f49Smrg   vertShader = CompileShaderFile(GL_VERTEX_SHADER, VertProgFile);
15732001f49Smrg   fragShader = CompileShaderFile(GL_FRAGMENT_SHADER, FragProgFile);
15832001f49Smrg   program = LinkShaders(vertShader, fragShader);
15932001f49Smrg
16032001f49Smrg   glUseProgram(program);
16132001f49Smrg
16232001f49Smrg   SetUniformValues(program, Uniforms);
16332001f49Smrg   PrintUniforms(Uniforms);
16432001f49Smrg
16532001f49Smrg   uZoom = glGetUniformLocation(program, "Zoom");
16632001f49Smrg   uXcenter = glGetUniformLocation(program, "Xcenter");
16732001f49Smrg   uYcenter = glGetUniformLocation(program, "Ycenter");
16832001f49Smrg
16932001f49Smrg   assert(glGetError() == 0);
17032001f49Smrg
17132001f49Smrg   glClearColor(0.4f, 0.4f, 0.8f, 0.0f);
17232001f49Smrg
17332001f49Smrg   printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER));
17432001f49Smrg
17532001f49Smrg   assert(glIsProgram(program));
17632001f49Smrg   assert(glIsShader(fragShader));
17732001f49Smrg   assert(glIsShader(vertShader));
17832001f49Smrg
17932001f49Smrg   glColor3f(1, 0, 0);
18032001f49Smrg}
18132001f49Smrg
18232001f49Smrg
18332001f49Smrgstatic void
18432001f49SmrgParseOptions(int argc, char *argv[])
18532001f49Smrg{
18632001f49Smrg   int i;
18732001f49Smrg   for (i = 1; i < argc; i++) {
18832001f49Smrg      if (strcmp(argv[i], "-fs") == 0) {
18932001f49Smrg         FragProgFile = argv[i+1];
19032001f49Smrg      }
19132001f49Smrg      else if (strcmp(argv[i], "-vs") == 0) {
19232001f49Smrg         VertProgFile = argv[i+1];
19332001f49Smrg      }
19432001f49Smrg   }
19532001f49Smrg}
19632001f49Smrg
19732001f49Smrg
19832001f49Smrgint
19932001f49Smrgmain(int argc, char *argv[])
20032001f49Smrg{
20132001f49Smrg   glutInit(&argc, argv);
20232001f49Smrg   glutInitWindowSize(400, 400);
20332001f49Smrg   glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
20432001f49Smrg   win = glutCreateWindow(argv[0]);
20532001f49Smrg   glewInit();
20632001f49Smrg   glutReshapeFunc(Reshape);
20732001f49Smrg   glutKeyboardFunc(Key);
20832001f49Smrg   glutSpecialFunc(SpecialKey);
20932001f49Smrg   glutDisplayFunc(Redisplay);
21032001f49Smrg   ParseOptions(argc, argv);
21132001f49Smrg   Init();
21232001f49Smrg   glutMainLoop();
21332001f49Smrg   return 0;
21432001f49Smrg}
21532001f49Smrg
216