1/**
2 * blinking-teapot demo. It displays a teapot whose color go from blue to pink.
3 * The color variation is handled by uniform buffer object.
4 * Sources mostly from http://www.jotschi.de/?p=427 which uses UBO SPEC example
5 *
6 * Vincent Lejeune 2011
7 */
8
9#include <stdio.h>
10#include <stdlib.h>
11#include <string.h>
12#include <GL/glew.h>
13#include "glut_wrap.h"
14#include "shaderutil.h"
15
16
17static int mouse_old_x, mouse_old_y;
18static int mouse_buttons = 0;
19static float rotate_x = 0.0, rotate_y = 0.0;
20static float translate_z = -2.0;
21
22static float delta = 0.01;
23static GLfloat wf, hf;
24
25
26static const GLchar *names[] = { "SurfaceColor", "WarmColor", "CoolColor",
27  "DiffuseWarm", "DiffuseCool"
28};
29
30static GLuint buffer_id, uniformBlockIndex, uindex, vshad_id, fshad_id,
31  prog_id;
32
33static GLsizei uniformBlockSize;
34static GLint singleSize;
35static GLint offset;
36
37static const GLfloat colors[] =
38  { 0.45, 0.45, 1, 1, 0.45, 0.45, 1, 1, 0.75, 0.75, 0.75, 1,
39  0.0, 0.0, 1.0, 1, 0.0, 1.0, 0.0, 1,
40};
41
42static GLfloat teapot_color = 1;
43
44static void
45reshape (int w, int h)
46{
47  wf = (GLfloat) w;
48  hf = (GLfloat) h;
49  glMatrixMode (GL_PROJECTION);
50  glLoadIdentity ();
51  gluPerspective (60.0, wf / hf, 0.1, 100.0);
52}
53
54static void
55init_opengl (void)
56{
57
58  if (!ShadersSupported ())
59    exit (1);
60
61  if (!glutExtensionSupported("GL_ARB_uniform_buffer_object")) {
62     printf("GL_ARB_uniform_buffer_object is required.\n");
63     exit(1);
64  }
65
66  vshad_id = CompileShaderFile (GL_VERTEX_SHADER, "blinking-teapot.vert");
67  fshad_id = CompileShaderFile (GL_FRAGMENT_SHADER, "blinking-teapot.frag");
68  prog_id = LinkShaders (vshad_id, fshad_id);
69
70  UseProgram (prog_id);
71
72  reshape (680, 400);
73
74  glGenBuffers (1, &buffer_id);
75
76  glBindBuffer (GL_UNIFORM_BUFFER, buffer_id);
77  glBufferData (GL_UNIFORM_BUFFER, uniformBlockSize, NULL, GL_DYNAMIC_DRAW);
78
79  glBindBufferBase (GL_UNIFORM_BUFFER, 0, buffer_id);
80  glUniformBlockBinding (prog_id, uniformBlockIndex, 0);
81
82  glGetUniformIndices (prog_id, 1, &names[2], &uindex);
83
84  glGetActiveUniformsiv (prog_id, 1, &uindex, GL_UNIFORM_OFFSET, &offset);
85  glGetActiveUniformsiv (prog_id, 1, &uindex, GL_UNIFORM_SIZE, &singleSize);
86
87  glViewport (0, 0, 680, 400);
88  glBufferData (GL_UNIFORM_BUFFER, 80, colors, GL_DYNAMIC_DRAW);
89}
90
91static void
92render (void)
93{
94  glClearColor (0.0, 0.0, 0.0, 0.0);
95  glClear (GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
96  glUseProgram (prog_id);
97  glEnable (GL_DEPTH_TEST);
98
99  glMatrixMode (GL_MODELVIEW);
100  glLoadIdentity ();
101  glTranslatef (0.0, 0.0, translate_z);
102  glRotatef (rotate_x, 1.0, 0.0, 0.0);
103  glRotatef (rotate_y, 0.0, 1.0, 0.0);
104  glColor3f (1.0, 1.0, 1.0);
105
106  glBindBuffer (GL_UNIFORM_BUFFER, buffer_id);
107  glBufferSubData (GL_UNIFORM_BUFFER, offset, 4 * singleSize, &teapot_color);
108
109  glFrontFace (GL_CW);
110  glutSolidTeapot (0.6);
111  glFrontFace (GL_CCW);
112  glutSwapBuffers ();
113  glutPostRedisplay ();
114
115  teapot_color += delta;
116
117  if (teapot_color > 1.0)
118    {
119      delta = -0.01;
120    }
121
122  if (teapot_color < 0.0)
123    {
124      delta = +0.01;
125    }
126
127}
128
129static void
130mouse (int button, int state, int x, int y)
131{
132  if (state == GLUT_DOWN)
133    {
134      mouse_buttons |= 1 << button;
135    }
136  else if (state == GLUT_UP)
137    {
138      mouse_buttons = 0;
139    }
140
141  mouse_old_x = x;
142  mouse_old_y = y;
143  glutPostRedisplay ();
144}
145
146static void
147motion (int x, int y)
148{
149  float dx, dy;
150  dx = x - mouse_old_x;
151  dy = y - mouse_old_y;
152
153  if (mouse_buttons & 1)
154    {
155      rotate_x += dy * 0.2;
156      rotate_y += dx * 0.2;
157    }
158  else if (mouse_buttons & 4)
159    {
160      translate_z += dy * 0.01;
161    }
162
163  mouse_old_x = x;
164  mouse_old_y = y;
165}
166
167int
168main (int argc, char **argv)
169{
170  glutInit (&argc, argv);
171  glutInitWindowSize (400, 400);
172  glutInitDisplayMode (GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
173  glutCreateWindow ("UBO Example");
174
175  glutDisplayFunc (render);
176  glutMouseFunc (mouse);
177  glutMotionFunc (motion);
178  glewInit ();
179  init_opengl ();
180  glutMainLoop ();
181  return 0;
182}
183