132001f49Smrg/**
232001f49Smrg * blinking-teapot demo. It displays a teapot whose color go from blue to pink.
332001f49Smrg * The color variation is handled by uniform buffer object.
432001f49Smrg * Sources mostly from http://www.jotschi.de/?p=427 which uses UBO SPEC example
532001f49Smrg *
632001f49Smrg * Vincent Lejeune 2011
732001f49Smrg */
832001f49Smrg
932001f49Smrg#include <stdio.h>
1032001f49Smrg#include <stdlib.h>
1132001f49Smrg#include <string.h>
1232001f49Smrg#include <GL/glew.h>
1332001f49Smrg#include "glut_wrap.h"
1432001f49Smrg#include "shaderutil.h"
1532001f49Smrg
1632001f49Smrg
1732001f49Smrgstatic int mouse_old_x, mouse_old_y;
1832001f49Smrgstatic int mouse_buttons = 0;
1932001f49Smrgstatic float rotate_x = 0.0, rotate_y = 0.0;
2032001f49Smrgstatic float translate_z = -2.0;
2132001f49Smrg
2232001f49Smrgstatic float delta = 0.01;
2332001f49Smrgstatic GLfloat wf, hf;
2432001f49Smrg
2532001f49Smrg
2632001f49Smrgstatic const GLchar *names[] = { "SurfaceColor", "WarmColor", "CoolColor",
2732001f49Smrg  "DiffuseWarm", "DiffuseCool"
2832001f49Smrg};
2932001f49Smrg
3032001f49Smrgstatic GLuint buffer_id, uniformBlockIndex, uindex, vshad_id, fshad_id,
3132001f49Smrg  prog_id;
3232001f49Smrg
3332001f49Smrgstatic GLsizei uniformBlockSize;
3432001f49Smrgstatic GLint singleSize;
3532001f49Smrgstatic GLint offset;
3632001f49Smrg
3732001f49Smrgstatic const GLfloat colors[] =
3832001f49Smrg  { 0.45, 0.45, 1, 1, 0.45, 0.45, 1, 1, 0.75, 0.75, 0.75, 1,
3932001f49Smrg  0.0, 0.0, 1.0, 1, 0.0, 1.0, 0.0, 1,
4032001f49Smrg};
4132001f49Smrg
4232001f49Smrgstatic GLfloat teapot_color = 1;
4332001f49Smrg
4432001f49Smrgstatic void
4532001f49Smrgreshape (int w, int h)
4632001f49Smrg{
4732001f49Smrg  wf = (GLfloat) w;
4832001f49Smrg  hf = (GLfloat) h;
4932001f49Smrg  glMatrixMode (GL_PROJECTION);
5032001f49Smrg  glLoadIdentity ();
5132001f49Smrg  gluPerspective (60.0, wf / hf, 0.1, 100.0);
5232001f49Smrg}
5332001f49Smrg
5432001f49Smrgstatic void
5532001f49Smrginit_opengl (void)
5632001f49Smrg{
5732001f49Smrg
5832001f49Smrg  if (!ShadersSupported ())
5932001f49Smrg    exit (1);
6032001f49Smrg
6132001f49Smrg  if (!glutExtensionSupported("GL_ARB_uniform_buffer_object")) {
6232001f49Smrg     printf("GL_ARB_uniform_buffer_object is required.\n");
6332001f49Smrg     exit(1);
6432001f49Smrg  }
6532001f49Smrg
6632001f49Smrg  vshad_id = CompileShaderFile (GL_VERTEX_SHADER, "blinking-teapot.vert");
6732001f49Smrg  fshad_id = CompileShaderFile (GL_FRAGMENT_SHADER, "blinking-teapot.frag");
6832001f49Smrg  prog_id = LinkShaders (vshad_id, fshad_id);
6932001f49Smrg
7032001f49Smrg  UseProgram (prog_id);
7132001f49Smrg
7232001f49Smrg  reshape (680, 400);
7332001f49Smrg
7432001f49Smrg  glGenBuffers (1, &buffer_id);
7532001f49Smrg
7632001f49Smrg  glBindBuffer (GL_UNIFORM_BUFFER, buffer_id);
7732001f49Smrg  glBufferData (GL_UNIFORM_BUFFER, uniformBlockSize, NULL, GL_DYNAMIC_DRAW);
7832001f49Smrg
7932001f49Smrg  glBindBufferBase (GL_UNIFORM_BUFFER, 0, buffer_id);
8032001f49Smrg  glUniformBlockBinding (prog_id, uniformBlockIndex, 0);
8132001f49Smrg
8232001f49Smrg  glGetUniformIndices (prog_id, 1, &names[2], &uindex);
8332001f49Smrg
8432001f49Smrg  glGetActiveUniformsiv (prog_id, 1, &uindex, GL_UNIFORM_OFFSET, &offset);
8532001f49Smrg  glGetActiveUniformsiv (prog_id, 1, &uindex, GL_UNIFORM_SIZE, &singleSize);
8632001f49Smrg
8732001f49Smrg  glViewport (0, 0, 680, 400);
8832001f49Smrg  glBufferData (GL_UNIFORM_BUFFER, 80, colors, GL_DYNAMIC_DRAW);
8932001f49Smrg}
9032001f49Smrg
9132001f49Smrgstatic void
9232001f49Smrgrender (void)
9332001f49Smrg{
9432001f49Smrg  glClearColor (0.0, 0.0, 0.0, 0.0);
9532001f49Smrg  glClear (GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
9632001f49Smrg  glUseProgram (prog_id);
9732001f49Smrg  glEnable (GL_DEPTH_TEST);
9832001f49Smrg
9932001f49Smrg  glMatrixMode (GL_MODELVIEW);
10032001f49Smrg  glLoadIdentity ();
10132001f49Smrg  glTranslatef (0.0, 0.0, translate_z);
10232001f49Smrg  glRotatef (rotate_x, 1.0, 0.0, 0.0);
10332001f49Smrg  glRotatef (rotate_y, 0.0, 1.0, 0.0);
10432001f49Smrg  glColor3f (1.0, 1.0, 1.0);
10532001f49Smrg
10632001f49Smrg  glBindBuffer (GL_UNIFORM_BUFFER, buffer_id);
10732001f49Smrg  glBufferSubData (GL_UNIFORM_BUFFER, offset, 4 * singleSize, &teapot_color);
10832001f49Smrg
10932001f49Smrg  glFrontFace (GL_CW);
11032001f49Smrg  glutSolidTeapot (0.6);
11132001f49Smrg  glFrontFace (GL_CCW);
11232001f49Smrg  glutSwapBuffers ();
11332001f49Smrg  glutPostRedisplay ();
11432001f49Smrg
11532001f49Smrg  teapot_color += delta;
11632001f49Smrg
11732001f49Smrg  if (teapot_color > 1.0)
11832001f49Smrg    {
11932001f49Smrg      delta = -0.01;
12032001f49Smrg    }
12132001f49Smrg
12232001f49Smrg  if (teapot_color < 0.0)
12332001f49Smrg    {
12432001f49Smrg      delta = +0.01;
12532001f49Smrg    }
12632001f49Smrg
12732001f49Smrg}
12832001f49Smrg
12932001f49Smrgstatic void
13032001f49Smrgmouse (int button, int state, int x, int y)
13132001f49Smrg{
13232001f49Smrg  if (state == GLUT_DOWN)
13332001f49Smrg    {
13432001f49Smrg      mouse_buttons |= 1 << button;
13532001f49Smrg    }
13632001f49Smrg  else if (state == GLUT_UP)
13732001f49Smrg    {
13832001f49Smrg      mouse_buttons = 0;
13932001f49Smrg    }
14032001f49Smrg
14132001f49Smrg  mouse_old_x = x;
14232001f49Smrg  mouse_old_y = y;
14332001f49Smrg  glutPostRedisplay ();
14432001f49Smrg}
14532001f49Smrg
14632001f49Smrgstatic void
14732001f49Smrgmotion (int x, int y)
14832001f49Smrg{
14932001f49Smrg  float dx, dy;
15032001f49Smrg  dx = x - mouse_old_x;
15132001f49Smrg  dy = y - mouse_old_y;
15232001f49Smrg
15332001f49Smrg  if (mouse_buttons & 1)
15432001f49Smrg    {
15532001f49Smrg      rotate_x += dy * 0.2;
15632001f49Smrg      rotate_y += dx * 0.2;
15732001f49Smrg    }
15832001f49Smrg  else if (mouse_buttons & 4)
15932001f49Smrg    {
16032001f49Smrg      translate_z += dy * 0.01;
16132001f49Smrg    }
16232001f49Smrg
16332001f49Smrg  mouse_old_x = x;
16432001f49Smrg  mouse_old_y = y;
16532001f49Smrg}
16632001f49Smrg
16732001f49Smrgint
16832001f49Smrgmain (int argc, char **argv)
16932001f49Smrg{
17032001f49Smrg  glutInit (&argc, argv);
17132001f49Smrg  glutInitWindowSize (400, 400);
17232001f49Smrg  glutInitDisplayMode (GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
17332001f49Smrg  glutCreateWindow ("UBO Example");
17432001f49Smrg
17532001f49Smrg  glutDisplayFunc (render);
17632001f49Smrg  glutMouseFunc (mouse);
17732001f49Smrg  glutMotionFunc (motion);
17832001f49Smrg  glewInit ();
17932001f49Smrg  init_opengl ();
18032001f49Smrg  glutMainLoop ();
18132001f49Smrg  return 0;
18232001f49Smrg}
183