blob: a0ce7f3f5bce3de68597f0d293b04b86e8d500e6 [file] [log] [blame]
Michal Krol36997512006-02-15 10:58:52 +00001/*
2 * Use GL_ARB_fragment_shader and GL_ARB_vertex_shader to implement
Michal Krol6acf1e92006-04-25 10:11:59 +00003 * simple per-pixel lighting.
4 *
5 * Michal Krol
Michal Krolcc159162006-02-21 12:35:06 +00006 * 20 February 2006
Michal Krol6acf1e92006-04-25 10:11:59 +00007 *
Michal Krol36997512006-02-15 10:58:52 +00008 * Based on the original demo by:
9 * Brian Paul
10 * 17 April 2003
Michal Krol6acf1e92006-04-25 10:11:59 +000011 */
12
13#ifdef WIN32
14#include <windows.h>
Michal Krol36541932006-02-18 15:11:18 +000015#endif
Michal Krol36997512006-02-15 10:58:52 +000016
17#include <stdio.h>
Michal Krol6acf1e92006-04-25 10:11:59 +000018#include <stdlib.h>
Michal Krol1616f5b2006-08-02 14:46:50 +000019#include <math.h>
Michal Krol36541932006-02-18 15:11:18 +000020#include <GL/gl.h>
Michal Krol6acf1e92006-04-25 10:11:59 +000021#include <GL/glut.h>
22#include <GL/glext.h>
23
24#ifdef WIN32
25#define GETPROCADDRESS wglGetProcAddress
26#else
27#define GETPROCADDRESS glutGetProcAddress
28#endif
Michal Krol36997512006-02-15 10:58:52 +000029
30static GLfloat diffuse[4] = { 0.5f, 0.5f, 1.0f, 1.0f };
31static GLfloat specular[4] = { 0.8f, 0.8f, 0.8f, 1.0f };
32static GLfloat lightPos[4] = { 0.0f, 10.0f, 20.0f, 1.0f };
33static GLfloat delta = 1.0f;
34
35static GLhandleARB fragShader;
Michal Krol6acf1e92006-04-25 10:11:59 +000036static GLhandleARB vertShader;
37static GLhandleARB program;
38
39static GLint uLightPos;
40static GLint uDiffuse;
41static GLint uSpecular;
Michal Krol36997512006-02-15 10:58:52 +000042
43static GLboolean anim = GL_TRUE;
44static GLboolean wire = GL_FALSE;
45static GLboolean pixelLight = GL_TRUE;
46
47static GLint t0 = 0;
48static GLint frames = 0;
49
Michal Krol6acf1e92006-04-25 10:11:59 +000050static GLfloat xRot = 0.0f, yRot = 0.0f;
51
52static PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB = NULL;
53static PFNGLSHADERSOURCEARBPROC glShaderSourceARB = NULL;
54static PFNGLCOMPILESHADERARBPROC glCompileShaderARB = NULL;
55static PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB = NULL;
56static PFNGLATTACHOBJECTARBPROC glAttachObjectARB = NULL;
57static PFNGLLINKPROGRAMARBPROC glLinkProgramARB = NULL;
58static PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB = NULL;
59static PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB = NULL;
Michal Krol1616f5b2006-08-02 14:46:50 +000060static PFNGLUNIFORM3FVARBPROC glUniform3fvARB = NULL;
61static PFNGLUNIFORM3FVARBPROC glUniform4fvARB = NULL;
62
63static void normalize (GLfloat *dst, const GLfloat *src)
64{
Brian4a285482007-04-26 07:46:38 -060065 GLfloat len = sqrt (src[0] * src[0] + src[1] * src[1] + src[2] * src[2]);
Michal Krol1616f5b2006-08-02 14:46:50 +000066 dst[0] = src[0] / len;
67 dst[1] = src[1] / len;
68 dst[2] = src[2] / len;
69}
Michal Krol36997512006-02-15 10:58:52 +000070
71static void Redisplay (void)
72{
73 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
74
Michal Krol6acf1e92006-04-25 10:11:59 +000075 if (pixelLight)
76 {
Michal Krol1616f5b2006-08-02 14:46:50 +000077 GLfloat vec[3];
78
Michal Krol6acf1e92006-04-25 10:11:59 +000079 glUseProgramObjectARB (program);
Michal Krol1616f5b2006-08-02 14:46:50 +000080 normalize (vec, lightPos);
81 glUniform3fvARB (uLightPos, 1, vec);
Michal Krol36997512006-02-15 10:58:52 +000082 glDisable(GL_LIGHTING);
83 }
Michal Krol6acf1e92006-04-25 10:11:59 +000084 else
85 {
Michal Krol36997512006-02-15 10:58:52 +000086 glUseProgramObjectARB (0);
87 glLightfv (GL_LIGHT0, GL_POSITION, lightPos);
88 glEnable(GL_LIGHTING);
89 }
90
91 glPushMatrix ();
92 glRotatef (xRot, 1.0f, 0.0f, 0.0f);
93 glRotatef (yRot, 0.0f, 1.0f, 0.0f);
Michal Krol6acf1e92006-04-25 10:11:59 +000094 glutSolidSphere (2.0, 10, 5);
Michal Krol36997512006-02-15 10:58:52 +000095 glPopMatrix ();
96
97 glutSwapBuffers();
98 frames++;
99
Michal Krol6acf1e92006-04-25 10:11:59 +0000100 if (anim)
Michal Krol36997512006-02-15 10:58:52 +0000101 {
102 GLint t = glutGet (GLUT_ELAPSED_TIME);
Michal Krol6acf1e92006-04-25 10:11:59 +0000103 if (t - t0 >= 5000)
Michal Krol36997512006-02-15 10:58:52 +0000104 {
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", frames, seconds, fps);
Keith Whitwelle6479c62009-02-24 12:02:24 +0000108 fflush(stdout);
Michal Krol36997512006-02-15 10:58:52 +0000109 t0 = t;
110 frames = 0;
111 }
112 }
113}
114
115static void Idle (void)
116{
117 lightPos[0] += delta;
118 if (lightPos[0] > 25.0f || lightPos[0] < -25.0f)
119 delta = -delta;
120 glutPostRedisplay ();
121}
122
123static void Reshape (int width, int height)
124{
125 glViewport (0, 0, width, height);
126 glMatrixMode (GL_PROJECTION);
127 glLoadIdentity ();
128 glFrustum (-1.0, 1.0, -1.0, 1.0, 5.0, 25.0);
129 glMatrixMode (GL_MODELVIEW);
130 glLoadIdentity ();
131 glTranslatef (0.0f, 0.0f, -15.0f);
132}
133
134static void Key (unsigned char key, int x, int y)
135{
136 (void) x;
Michal Krol6acf1e92006-04-25 10:11:59 +0000137 (void) y;
Michal Krol36997512006-02-15 10:58:52 +0000138
Michal Krol6acf1e92006-04-25 10:11:59 +0000139 switch (key)
Michal Krol36997512006-02-15 10:58:52 +0000140 {
141 case ' ':
142 case 'a':
143 anim = !anim;
144 if (anim)
145 glutIdleFunc (Idle);
146 else
147 glutIdleFunc (NULL);
148 break;
149 case 'x':
150 lightPos[0] -= 1.0f;
151 break;
152 case 'X':
153 lightPos[0] += 1.0f;
154 break;
155 case 'w':
156 wire = !wire;
157 if (wire)
158 glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
159 else
160 glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
161 break;
162 case 'p':
163 pixelLight = !pixelLight;
164 if (pixelLight)
165 printf ("Per-pixel lighting\n");
166 else
167 printf ("Conventional lighting\n");
168 break;
169 case 27:
170 exit(0);
171 break;
172 }
173 glutPostRedisplay ();
174}
175
176static void SpecialKey (int key, int x, int y)
177{
Michal Krol6acf1e92006-04-25 10:11:59 +0000178 const GLfloat step = 3.0f;
Michal Krol36997512006-02-15 10:58:52 +0000179
180 (void) x;
Michal Krol6acf1e92006-04-25 10:11:59 +0000181 (void) y;
Michal Krol36997512006-02-15 10:58:52 +0000182
Michal Krol6acf1e92006-04-25 10:11:59 +0000183 switch (key)
Michal Krol36997512006-02-15 10:58:52 +0000184 {
185 case GLUT_KEY_UP:
186 xRot -= step;
187 break;
188 case GLUT_KEY_DOWN:
189 xRot += step;
190 break;
191 case GLUT_KEY_LEFT:
192 yRot -= step;
193 break;
194 case GLUT_KEY_RIGHT:
195 yRot += step;
196 break;
197 }
198 glutPostRedisplay ();
199}
200
201static void Init (void)
202{
Michal Krol1616f5b2006-08-02 14:46:50 +0000203 static const char *fragShaderText =
204 "uniform vec3 lightPos;\n"
205 "uniform vec4 diffuse;\n"
206 "uniform vec4 specular;\n"
207 "varying vec3 normal;\n"
208 "void main () {\n"
209 " // Compute dot product of light direction and normal vector\n"
210 " float dotProd = max (dot (lightPos, normalize (normal)), 0.0);\n"
211 " // Compute diffuse and specular contributions\n"
michala1b42852007-10-27 18:42:20 +0100212#if 1
Michal Krol1616f5b2006-08-02 14:46:50 +0000213 " gl_FragColor = diffuse * dotProd + specular * pow (dotProd, 20.0);\n"
Brian2727cfd2007-09-29 10:44:05 -0600214#elif 1 /* test IF/ELSE/ENDIF */
Brian9405ec62007-09-28 21:04:56 -0600215 " if (normal.y > 0.0) { \n"
216 " gl_FragColor = diffuse * dotProd + specular * pow (dotProd, 20.0);\n"
217 " } \n"
218 " else { \n"
219 " if (normal.x < 0.0) { \n"
220 " gl_FragColor = vec4(1, 0, 0, 0); \n"
221 " } \n"
222 " else { \n"
223 " gl_FragColor = vec4(1, 1, 0, 0); \n"
224 " } \n"
225 " } \n"
Brian2727cfd2007-09-29 10:44:05 -0600226#elif 1 /* test LOOP */
227 " while (1) { \n"
228 " if (normal.y >= 0.0) { \n"
229 " gl_FragColor = vec4(1, 0, 0, 0); \n"
230 " break; \n"
231 " } else { \n"
232 " gl_FragColor = diffuse * dotProd + specular * pow (dotProd, 20.0);\n"
233 " break; \n"
234 " } \n"
235 " } \n"
Brian9405ec62007-09-28 21:04:56 -0600236#endif
Michal Krol1616f5b2006-08-02 14:46:50 +0000237 "}\n"
238 ;
239 static const char *vertShaderText =
240 "varying vec3 normal;\n"
241 "void main () {\n"
242 " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
243 " normal = gl_NormalMatrix * gl_Normal;\n"
244 "}\n"
245 ;
Michal Krol6acf1e92006-04-25 10:11:59 +0000246
247 if (!glutExtensionSupported ("GL_ARB_fragment_shader"))
Michal Krol36997512006-02-15 10:58:52 +0000248 {
249 printf ("Sorry, this demo requires GL_ARB_fragment_shader\n");
250 exit(1);
Michal Krol6acf1e92006-04-25 10:11:59 +0000251 }
252 if (!glutExtensionSupported ("GL_ARB_shader_objects"))
253 {
254 printf ("Sorry, this demo requires GL_ARB_shader_objects\n");
255 exit(1);
256 }
257 if (!glutExtensionSupported ("GL_ARB_shading_language_100"))
258 {
259 printf ("Sorry, this demo requires GL_ARB_shading_language_100\n");
260 exit(1);
261 }
262 if (!glutExtensionSupported ("GL_ARB_vertex_shader"))
263 {
264 printf ("Sorry, this demo requires GL_ARB_vertex_shader\n");
265 exit(1);
Michal Krol36997512006-02-15 10:58:52 +0000266 }
267
Michal Krol6acf1e92006-04-25 10:11:59 +0000268 glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC) GETPROCADDRESS ("glCreateShaderObjectARB");
269 glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC) GETPROCADDRESS ("glShaderSourceARB");
270 glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC) GETPROCADDRESS ("glCompileShaderARB");
271 glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC) GETPROCADDRESS ("glCreateProgramObjectARB");
272 glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC) GETPROCADDRESS ("glAttachObjectARB");
273 glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC) GETPROCADDRESS ("glLinkProgramARB");
274 glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC) GETPROCADDRESS ("glUseProgramObjectARB");
275 glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC) GETPROCADDRESS ("glGetUniformLocationARB");
Michal Krol1616f5b2006-08-02 14:46:50 +0000276 glUniform3fvARB = (PFNGLUNIFORM3FVARBPROC) GETPROCADDRESS ("glUniform3fvARB");
277 glUniform4fvARB = (PFNGLUNIFORM3FVARBPROC) GETPROCADDRESS ("glUniform4fvARB");
Michal Krol6acf1e92006-04-25 10:11:59 +0000278
279 fragShader = glCreateShaderObjectARB (GL_FRAGMENT_SHADER_ARB);
280 glShaderSourceARB (fragShader, 1, &fragShaderText, NULL);
Michal Krol36997512006-02-15 10:58:52 +0000281 glCompileShaderARB (fragShader);
Michal Krol6acf1e92006-04-25 10:11:59 +0000282
283 vertShader = glCreateShaderObjectARB (GL_VERTEX_SHADER_ARB);
284 glShaderSourceARB (vertShader, 1, &vertShaderText, NULL);
285 glCompileShaderARB (vertShader);
286
287 program = glCreateProgramObjectARB ();
288 glAttachObjectARB (program, fragShader);
289 glAttachObjectARB (program, vertShader);
290 glLinkProgramARB (program);
291 glUseProgramObjectARB (program);
292
293 uLightPos = glGetUniformLocationARB (program, "lightPos");
294 uDiffuse = glGetUniformLocationARB (program, "diffuse");
295 uSpecular = glGetUniformLocationARB (program, "specular");
296
Michal Krol1616f5b2006-08-02 14:46:50 +0000297 glUniform4fvARB (uDiffuse, 1, diffuse);
298 glUniform4fvARB (uSpecular, 1, specular);
Michal Krol36997512006-02-15 10:58:52 +0000299
300 glClearColor (0.3f, 0.3f, 0.3f, 0.0f);
301 glEnable (GL_DEPTH_TEST);
Michal Krol6acf1e92006-04-25 10:11:59 +0000302 glEnable (GL_LIGHT0);
Michal Krol36997512006-02-15 10:58:52 +0000303 glEnable (GL_LIGHTING);
304 glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse);
305 glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, specular);
306 glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, 20.0f);
307
308 printf ("GL_RENDERER = %s\n", (const char *) glGetString (GL_RENDERER));
309 printf ("Press p to toggle between per-pixel and per-vertex lighting\n");
310}
311
312int main (int argc, char *argv[])
313{
Michal Krol36997512006-02-15 10:58:52 +0000314 glutInitWindowSize (200, 200);
Brian Paul263f4322009-12-18 08:12:55 -0700315 glutInit (&argc, argv);
Michal Krol36997512006-02-15 10:58:52 +0000316 glutInitDisplayMode (GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
317 glutCreateWindow (argv[0]);
318 glutReshapeFunc (Reshape);
319 glutKeyboardFunc (Key);
320 glutSpecialFunc (SpecialKey);
321 glutDisplayFunc (Redisplay);
322 if (anim)
323 glutIdleFunc (Idle);
324 Init ();
325 glutMainLoop ();
326 return 0;
327}
Michal Krol6acf1e92006-04-25 10:11:59 +0000328