blob: 1164f2d6606929da15a1803b65e88bf84c16c30e [file] [log] [blame]
Michal Krol36997512006-02-15 10:58:52 +00001/*
2 * Use GL_ARB_fragment_shader and GL_ARB_vertex_shader to implement
3 * simple per-pixel lighting.
4 *
5 * Michal Krol
Michal Krolcc159162006-02-21 12:35:06 +00006 * 20 February 2006
Michal Krol36997512006-02-15 10:58:52 +00007 *
8 * Based on the original demo by:
9 * Brian Paul
10 * 17 April 2003
Michal Krol36541932006-02-18 15:11:18 +000011 */
12
13#ifdef WIN32
14#include <windows.h>
15#endif
Michal Krol36997512006-02-15 10:58:52 +000016
17#include <stdio.h>
Michal Krol36541932006-02-18 15:11:18 +000018#include <stdlib.h>
19#include <GL/gl.h>
Michal Krol36997512006-02-15 10:58:52 +000020#include <GL/glut.h>
Michal Krol36541932006-02-18 15:11:18 +000021#include <GL/glext.h>
22
23#ifdef WIN32
24#define GETPROCADDRESS wglGetProcAddress
25#else
26#define GETPROCADDRESS glutGetProcAddress
27#endif
Michal Krol36997512006-02-15 10:58:52 +000028
29static GLfloat diffuse[4] = { 0.5f, 0.5f, 1.0f, 1.0f };
30static GLfloat specular[4] = { 0.8f, 0.8f, 0.8f, 1.0f };
31static GLfloat lightPos[4] = { 0.0f, 10.0f, 20.0f, 1.0f };
32static GLfloat delta = 1.0f;
33
34static GLhandleARB fragShader;
35static GLhandleARB vertShader;
36static GLhandleARB program;
Michal Krolcc159162006-02-21 12:35:06 +000037
38static GLint uLightPos;
39static GLint uDiffuse;
40static GLint uSpecular;
Michal Krol36997512006-02-15 10:58:52 +000041
42static GLboolean anim = GL_TRUE;
43static GLboolean wire = GL_FALSE;
44static GLboolean pixelLight = GL_TRUE;
45
46static GLint t0 = 0;
47static GLint frames = 0;
48
49static GLfloat xRot = 0.0f, yRot = 0.0f;
50
51static PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB = NULL;
52static PFNGLSHADERSOURCEARBPROC glShaderSourceARB = NULL;
53static PFNGLCOMPILESHADERARBPROC glCompileShaderARB = NULL;
54static PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB = NULL;
55static PFNGLATTACHOBJECTARBPROC glAttachObjectARB = NULL;
56static PFNGLLINKPROGRAMARBPROC glLinkProgramARB = NULL;
Michal Krolcc159162006-02-21 12:35:06 +000057static PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB = NULL;
58static PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB = NULL;
59static PFNGLUNIFORM4FVARBPROC glUniform4fvARB = NULL;
Michal Krol36997512006-02-15 10:58:52 +000060
61static void Redisplay (void)
62{
63 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
64
65 if (pixelLight)
66 {
67 glUseProgramObjectARB (program);
Michal Krolcc159162006-02-21 12:35:06 +000068 glUniform4fvARB (uLightPos, 1, lightPos);
Michal Krol36997512006-02-15 10:58:52 +000069 glDisable(GL_LIGHTING);
70 }
71 else
72 {
73 glUseProgramObjectARB (0);
74 glLightfv (GL_LIGHT0, GL_POSITION, lightPos);
75 glEnable(GL_LIGHTING);
76 }
77
78 glPushMatrix ();
79 glRotatef (xRot, 1.0f, 0.0f, 0.0f);
80 glRotatef (yRot, 0.0f, 1.0f, 0.0f);
81 glutSolidSphere (2.0, 10, 5);
82 glPopMatrix ();
83
84 glutSwapBuffers();
85 frames++;
86
87 if (anim)
88 {
89 GLint t = glutGet (GLUT_ELAPSED_TIME);
90 if (t - t0 >= 5000)
91 {
92 GLfloat seconds = (GLfloat) (t - t0) / 1000.0f;
93 GLfloat fps = frames / seconds;
94 printf ("%d frames in %6.3f seconds = %6.3f FPS\n", frames, seconds, fps);
95 t0 = t;
96 frames = 0;
97 }
98 }
99}
100
101static void Idle (void)
102{
103 lightPos[0] += delta;
104 if (lightPos[0] > 25.0f || lightPos[0] < -25.0f)
105 delta = -delta;
106 glutPostRedisplay ();
107}
108
109static void Reshape (int width, int height)
110{
111 glViewport (0, 0, width, height);
112 glMatrixMode (GL_PROJECTION);
113 glLoadIdentity ();
114 glFrustum (-1.0, 1.0, -1.0, 1.0, 5.0, 25.0);
115 glMatrixMode (GL_MODELVIEW);
116 glLoadIdentity ();
117 glTranslatef (0.0f, 0.0f, -15.0f);
118}
119
120static void Key (unsigned char key, int x, int y)
121{
122 (void) x;
123 (void) y;
124
125 switch (key)
126 {
127 case ' ':
128 case 'a':
129 anim = !anim;
130 if (anim)
131 glutIdleFunc (Idle);
132 else
133 glutIdleFunc (NULL);
134 break;
135 case 'x':
136 lightPos[0] -= 1.0f;
137 break;
138 case 'X':
139 lightPos[0] += 1.0f;
140 break;
141 case 'w':
142 wire = !wire;
143 if (wire)
144 glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
145 else
146 glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
147 break;
148 case 'p':
149 pixelLight = !pixelLight;
150 if (pixelLight)
151 printf ("Per-pixel lighting\n");
152 else
153 printf ("Conventional lighting\n");
154 break;
155 case 27:
156 exit(0);
157 break;
158 }
159 glutPostRedisplay ();
160}
161
162static void SpecialKey (int key, int x, int y)
163{
164 const GLfloat step = 3.0f;
165
166 (void) x;
167 (void) y;
168
169 switch (key)
170 {
171 case GLUT_KEY_UP:
172 xRot -= step;
173 break;
174 case GLUT_KEY_DOWN:
175 xRot += step;
176 break;
177 case GLUT_KEY_LEFT:
178 yRot -= step;
179 break;
180 case GLUT_KEY_RIGHT:
181 yRot += step;
182 break;
183 }
184 glutPostRedisplay ();
185}
186
187static void Init (void)
188{
Michal Krolcc159162006-02-21 12:35:06 +0000189 static const char *fragShaderText =
190 "uniform vec4 lightPos;\n"
191 "uniform vec4 diffuse;\n"
192 "uniform vec4 specular;\n"
Michal Krol36997512006-02-15 10:58:52 +0000193 "void main () {\n"
Michal Krol36997512006-02-15 10:58:52 +0000194 " // Compute dot product of light direction and normal vector\n"
195 " float dotProd;\n"
Michal Krol36541932006-02-18 15:11:18 +0000196 " dotProd = clamp (dot (normalize (lightPos).xyz, normalize (gl_TexCoord[0]).xyz), 0.0, 1.0);\n"
Michal Krol36997512006-02-15 10:58:52 +0000197 " // Compute diffuse and specular contributions\n"
198 " gl_FragColor = diffuse * dotProd + specular * pow (dotProd, 20.0);\n"
199 "}\n"
200 ;
201 static const char *vertShaderText =
202 "void main () {\n"
203 " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
Michal Krol36541932006-02-18 15:11:18 +0000204 " gl_TexCoord[0] = vec4 (gl_NormalMatrix * gl_Normal, 1.0);\n"
Michal Krol36997512006-02-15 10:58:52 +0000205 "}\n"
206 ;
207
208 if (!glutExtensionSupported ("GL_ARB_fragment_shader"))
209 {
210 printf ("Sorry, this demo requires GL_ARB_fragment_shader\n");
211 exit(1);
212 }
213 if (!glutExtensionSupported ("GL_ARB_shader_objects"))
214 {
215 printf ("Sorry, this demo requires GL_ARB_shader_objects\n");
216 exit(1);
217 }
218 if (!glutExtensionSupported ("GL_ARB_shading_language_100"))
219 {
220 printf ("Sorry, this demo requires GL_ARB_shading_language_100\n");
221 exit(1);
222 }
223 if (!glutExtensionSupported ("GL_ARB_vertex_shader"))
224 {
225 printf ("Sorry, this demo requires GL_ARB_vertex_shader\n");
226 exit(1);
227 }
228
Michal Krol36541932006-02-18 15:11:18 +0000229 glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC) GETPROCADDRESS ("glCreateShaderObjectARB");
230 glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC) GETPROCADDRESS ("glShaderSourceARB");
231 glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC) GETPROCADDRESS ("glCompileShaderARB");
232 glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC) GETPROCADDRESS ("glCreateProgramObjectARB");
233 glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC) GETPROCADDRESS ("glAttachObjectARB");
234 glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC) GETPROCADDRESS ("glLinkProgramARB");
235 glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC) GETPROCADDRESS ("glUseProgramObjectARB");
Michal Krolcc159162006-02-21 12:35:06 +0000236 glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC) GETPROCADDRESS ("glGetUniformLocationARB");
237 glUniform4fvARB = (PFNGLUNIFORM4FVARBPROC) GETPROCADDRESS ("glUniform4fvARB");
Michal Krol36997512006-02-15 10:58:52 +0000238
239 fragShader = glCreateShaderObjectARB (GL_FRAGMENT_SHADER_ARB);
240 glShaderSourceARB (fragShader, 1, &fragShaderText, NULL);
241 glCompileShaderARB (fragShader);
242
243 vertShader = glCreateShaderObjectARB (GL_VERTEX_SHADER_ARB);
244 glShaderSourceARB (vertShader, 1, &vertShaderText, NULL);
245 glCompileShaderARB (vertShader);
246
247 program = glCreateProgramObjectARB ();
248 glAttachObjectARB (program, fragShader);
249 glAttachObjectARB (program, vertShader);
250 glLinkProgramARB (program);
251 glUseProgramObjectARB (program);
Michal Krolcc159162006-02-21 12:35:06 +0000252
253 uLightPos = glGetUniformLocationARB (program, "lightPos");
254 uDiffuse = glGetUniformLocationARB (program, "diffuse");
255 uSpecular = glGetUniformLocationARB (program, "specular");
256
257 glUniform4fvARB (uDiffuse, 1, diffuse);
258 glUniform4fvARB (uSpecular, 1, specular);
Michal Krol36997512006-02-15 10:58:52 +0000259
260 glClearColor (0.3f, 0.3f, 0.3f, 0.0f);
261 glEnable (GL_DEPTH_TEST);
262 glEnable (GL_LIGHT0);
263 glEnable (GL_LIGHTING);
264 glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse);
265 glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, specular);
266 glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, 20.0f);
267
268 printf ("GL_RENDERER = %s\n", (const char *) glGetString (GL_RENDERER));
269 printf ("Press p to toggle between per-pixel and per-vertex lighting\n");
270}
271
272int main (int argc, char *argv[])
273{
274 glutInit (&argc, argv);
275 glutInitWindowPosition ( 0, 0);
276 glutInitWindowSize (200, 200);
277 glutInitDisplayMode (GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
278 glutCreateWindow (argv[0]);
279 glutReshapeFunc (Reshape);
280 glutKeyboardFunc (Key);
281 glutSpecialFunc (SpecialKey);
282 glutDisplayFunc (Redisplay);
283 if (anim)
284 glutIdleFunc (Idle);
285 Init ();
286 glutMainLoop ();
287 return 0;
288}
289