blob: 1c016cc75e941d4c9a90079399776271239903f2 [file] [log] [blame]
Brian Paul24ea2c22006-11-03 00:04:06 +00001/**
2 * Test OpenGL 2.0 vertex/fragment shaders.
3 * Brian Paul
4 * 1 November 2006
5 *
6 * Based on ARB version by:
7 * Michal Krol
8 * 20 February 2006
9 *
10 * Based on the original demo by:
11 * Brian Paul
12 * 17 April 2003
13 */
14
15#include <assert.h>
16#include <string.h>
17#include <stdio.h>
18#include <stdlib.h>
19#include <math.h>
20#include <GL/gl.h>
21#include <GL/glut.h>
22#include <GL/glext.h>
23
24static GLfloat diffuse[4] = { 0.5f, 0.5f, 1.0f, 1.0f };
25static GLfloat specular[4] = { 0.8f, 0.8f, 0.8f, 1.0f };
26static GLfloat lightPos[4] = { 0.0f, 10.0f, 20.0f, 1.0f };
27static GLfloat delta = 1.0f;
28
29static GLuint fragShader;
30static GLuint vertShader;
31static GLuint program;
32
33static GLint uLightPos;
34static GLint uDiffuse;
35static GLint uSpecular;
36
37static GLint win = 0;
38static GLboolean anim = GL_TRUE;
39static GLboolean wire = GL_FALSE;
40static GLboolean pixelLight = GL_TRUE;
41
42static GLint t0 = 0;
43static GLint frames = 0;
44
45static GLfloat xRot = 0.0f, yRot = 0.0f;
46
47static PFNGLCREATESHADERPROC glCreateShader_func = NULL;
48static PFNGLSHADERSOURCEPROC glShaderSource_func = NULL;
49static PFNGLGETSHADERSOURCEPROC glGetShaderSource_func = NULL;
50static PFNGLCOMPILESHADERPROC glCompileShader_func = NULL;
51static PFNGLCREATEPROGRAMPROC glCreateProgram_func = NULL;
52static PFNGLDELETEPROGRAMPROC glDeleteProgram_func = NULL;
53static PFNGLDELETESHADERPROC glDeleteShader_func = NULL;
54static PFNGLATTACHSHADERPROC glAttachShader_func = NULL;
55static PFNGLLINKPROGRAMPROC glLinkProgram_func = NULL;
56static PFNGLUSEPROGRAMPROC glUseProgram_func = NULL;
57static PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation_func = NULL;
58static PFNGLISPROGRAMPROC glIsProgram_func = NULL;
59static PFNGLISSHADERPROC glIsShader_func = NULL;
60static PFNGLUNIFORM3FVPROC glUniform3fv_func = NULL;
61static PFNGLUNIFORM3FVPROC glUniform4fv_func = NULL;
62
63
64
65static void
66normalize(GLfloat *dst, const GLfloat *src)
67{
68 GLfloat len = sqrtf(src[0] * src[0] + src[1] * src[1] + src[2] * src[2]);
69 dst[0] = src[0] / len;
70 dst[1] = src[1] / len;
71 dst[2] = src[2] / len;
72}
73
74
75static void
76Redisplay(void)
77{
78 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
79
80 if (pixelLight) {
81 GLfloat vec[3];
82 glUseProgram_func(program);
83 normalize(vec, lightPos);
84 glUniform3fv_func(uLightPos, 1, vec);
85 glDisable(GL_LIGHTING);
86 }
87 else {
88 glUseProgram_func(0);
89 glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
90 glEnable(GL_LIGHTING);
91 }
92
93 glPushMatrix();
94 glRotatef(xRot, 1.0f, 0.0f, 0.0f);
95 glRotatef(yRot, 0.0f, 1.0f, 0.0f);
96 glutSolidSphere(2.0, 10, 5);
97 glPopMatrix();
98
99 glutSwapBuffers();
100 frames++;
101
102 if (anim) {
103 GLint t = glutGet(GLUT_ELAPSED_TIME);
104 if (t - t0 >= 5000) {
105 GLfloat seconds =(GLfloat)(t - t0) / 1000.0f;
106 GLfloat fps = frames / seconds;
107 printf("%d frames in %6.3f seconds = %6.3f FPS\n",
108 frames, seconds, fps);
109 t0 = t;
110 frames = 0;
111 }
112 }
113}
114
115
116static void
117Idle(void)
118{
119 lightPos[0] += delta;
120 if (lightPos[0] > 25.0f || lightPos[0] < -25.0f)
121 delta = -delta;
122 glutPostRedisplay();
123}
124
125
126static void
127Reshape(int width, int height)
128{
129 glViewport(0, 0, width, height);
130 glMatrixMode(GL_PROJECTION);
131 glLoadIdentity();
132 glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0);
133 glMatrixMode(GL_MODELVIEW);
134 glLoadIdentity();
135 glTranslatef(0.0f, 0.0f, -15.0f);
136}
137
138
139static void
140CleanUp(void)
141{
142 glDeleteShader_func(fragShader);
143 glDeleteShader_func(vertShader);
144 glDeleteProgram_func(program);
145 glutDestroyWindow(win);
146}
147
148
149static void
150Key(unsigned char key, int x, int y)
151{
152 (void) x;
153 (void) y;
154
155 switch(key) {
156 case ' ':
157 case 'a':
158 anim = !anim;
159 if (anim)
160 glutIdleFunc(Idle);
161 else
162 glutIdleFunc(NULL);
163 break;
164 case 'x':
165 lightPos[0] -= 1.0f;
166 break;
167 case 'X':
168 lightPos[0] += 1.0f;
169 break;
170 case 'w':
171 wire = !wire;
172 if (wire)
173 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
174 else
175 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
176 break;
177 case 'p':
178 pixelLight = !pixelLight;
179 if (pixelLight)
180 printf("Per-pixel lighting\n");
181 else
182 printf("Conventional lighting\n");
183 break;
184 case 27:
185 CleanUp();
186 exit(0);
187 break;
188 }
189 glutPostRedisplay();
190}
191
192
193static void
194SpecialKey(int key, int x, int y)
195{
196 const GLfloat step = 3.0f;
197
198 (void) x;
199 (void) y;
200
201 switch(key) {
202 case GLUT_KEY_UP:
203 xRot -= step;
204 break;
205 case GLUT_KEY_DOWN:
206 xRot += step;
207 break;
208 case GLUT_KEY_LEFT:
209 yRot -= step;
210 break;
211 case GLUT_KEY_RIGHT:
212 yRot += step;
213 break;
214 }
215 glutPostRedisplay();
216}
217
218
219static void
220Init(void)
221{
222 static const char *fragShaderText =
223 "uniform vec3 lightPos;\n"
224 "uniform vec4 diffuse;\n"
225 "uniform vec4 specular;\n"
226 "varying vec3 normal;\n"
227 "void main() {\n"
228 " // Compute dot product of light direction and normal vector\n"
229 " float dotProd = max(dot(lightPos, normalize(normal)), 0.0);\n"
230 " // Compute diffuse and specular contributions\n"
231 " gl_FragColor = diffuse * dotProd + specular * pow(dotProd, 20.0);\n"
232 "}\n";
233 static const char *vertShaderText =
234 "varying vec3 normal;\n"
235 "void main() {\n"
236 " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
237 " normal = gl_NormalMatrix * gl_Normal;\n"
238 "}\n";
239
240
241 const char *version;
242
243 version = (const char *) glGetString(GL_VERSION);
244 if (version[0] != '2' || version[1] != '.') {
245 printf("Warning: this program expects OpenGL 2.0\n");
246 /*exit(1);*/
247 }
248
249
250 glCreateShader_func = (PFNGLCREATESHADERPROC) glutGetProcAddress("glCreateShader");
251 glDeleteShader_func = (PFNGLDELETESHADERPROC) glutGetProcAddress("glDeleteShader");
252 glDeleteProgram_func = (PFNGLDELETEPROGRAMPROC) glutGetProcAddress("glDeleteProgram");
253 glShaderSource_func = (PFNGLSHADERSOURCEPROC) glutGetProcAddress("glShaderSource");
254 glGetShaderSource_func = (PFNGLGETSHADERSOURCEPROC) glutGetProcAddress("glGetShaderSource");
255 glCompileShader_func = (PFNGLCOMPILESHADERPROC) glutGetProcAddress("glCompileShader");
256 glCreateProgram_func = (PFNGLCREATEPROGRAMPROC) glutGetProcAddress("glCreateProgram");
257 glAttachShader_func = (PFNGLATTACHSHADERPROC) glutGetProcAddress("glAttachShader");
258 glLinkProgram_func = (PFNGLLINKPROGRAMPROC) glutGetProcAddress("glLinkProgram");
259 glUseProgram_func = (PFNGLUSEPROGRAMPROC) glutGetProcAddress("glUseProgram");
260 glGetUniformLocation_func = (PFNGLGETUNIFORMLOCATIONPROC) glutGetProcAddress("glGetUniformLocation");
261 glIsProgram_func = (PFNGLISPROGRAMPROC) glutGetProcAddress("glIsProgram");
262 glIsShader_func = (PFNGLISSHADERPROC) glutGetProcAddress("glIsShader");
263 glUniform3fv_func = (PFNGLUNIFORM3FVPROC) glutGetProcAddress("glUniform3fv");
264 glUniform4fv_func = (PFNGLUNIFORM3FVPROC) glutGetProcAddress("glUniform4fv");
265
266 fragShader = glCreateShader_func(GL_FRAGMENT_SHADER);
267 glShaderSource_func(fragShader, 1, &fragShaderText, NULL);
268 glCompileShader_func(fragShader);
269
270 vertShader = glCreateShader_func(GL_VERTEX_SHADER);
271 glShaderSource_func(vertShader, 1, &vertShaderText, NULL);
272 glCompileShader_func(vertShader);
273
274 program = glCreateProgram_func();
275 glAttachShader_func(program, fragShader);
276 glAttachShader_func(program, vertShader);
277 glLinkProgram_func(program);
278 glUseProgram_func(program);
279
280 uLightPos = glGetUniformLocation_func(program, "lightPos");
281 uDiffuse = glGetUniformLocation_func(program, "diffuse");
282 uSpecular = glGetUniformLocation_func(program, "specular");
283
284 glUniform4fv_func(uDiffuse, 1, diffuse);
285 glUniform4fv_func(uSpecular, 1, specular);
286
287 glClearColor(0.3f, 0.3f, 0.3f, 0.0f);
288 glEnable(GL_DEPTH_TEST);
289 glEnable(GL_LIGHT0);
290 glEnable(GL_LIGHTING);
291 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse);
292 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular);
293 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 20.0f);
294
295 printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER));
296 printf("Press p to toggle between per-pixel and per-vertex lighting\n");
297
298 /* test glGetShaderSource() */
299 {
300 GLsizei len = strlen(fragShaderText) + 1;
301 GLsizei lenOut;
302 GLchar *src =(GLchar *) malloc(len * sizeof(GLchar));
303 glGetShaderSource_func(fragShader, 0, NULL, src);
304 glGetShaderSource_func(fragShader, len, &lenOut, src);
305 assert(len == lenOut + 1);
306 assert(strcmp(src, fragShaderText) == 0);
307 free(src);
308 }
309
310 assert(glIsProgram_func(program));
311 assert(glIsShader_func(fragShader));
312 assert(glIsShader_func(vertShader));
313}
314
315
316int
317main(int argc, char *argv[])
318{
319 glutInit(&argc, argv);
320 glutInitWindowPosition( 0, 0);
321 glutInitWindowSize(200, 200);
322 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
323 win = glutCreateWindow(argv[0]);
324 glutReshapeFunc(Reshape);
325 glutKeyboardFunc(Key);
326 glutSpecialFunc(SpecialKey);
327 glutDisplayFunc(Redisplay);
328 if (anim)
329 glutIdleFunc(Idle);
330 Init();
331 glutMainLoop();
332 return 0;
333}
334