blob: 2e91139bdd432694afa5b2f1f1b85e9ad6276b3a [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 Krol36541932006-02-18 15:11:18 +00006 * 17 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;
37
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 PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB = NULL;
48static PFNGLSHADERSOURCEARBPROC glShaderSourceARB = NULL;
49static PFNGLCOMPILESHADERARBPROC glCompileShaderARB = NULL;
50static PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB = NULL;
51static PFNGLATTACHOBJECTARBPROC glAttachObjectARB = NULL;
52static PFNGLLINKPROGRAMARBPROC glLinkProgramARB = NULL;
53static PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB = NULL;
54
55static void Redisplay (void)
56{
57 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
58
59 if (pixelLight)
60 {
61 glUseProgramObjectARB (program);
62 /* XXX source from uniform lightPos */
63 glTexCoord4fv (lightPos);
64 glDisable(GL_LIGHTING);
65 }
66 else
67 {
68 glUseProgramObjectARB (0);
69 glLightfv (GL_LIGHT0, GL_POSITION, lightPos);
70 glEnable(GL_LIGHTING);
71 }
72
73 glPushMatrix ();
74 glRotatef (xRot, 1.0f, 0.0f, 0.0f);
75 glRotatef (yRot, 0.0f, 1.0f, 0.0f);
76 glutSolidSphere (2.0, 10, 5);
77 glPopMatrix ();
78
79 glutSwapBuffers();
80 frames++;
81
82 if (anim)
83 {
84 GLint t = glutGet (GLUT_ELAPSED_TIME);
85 if (t - t0 >= 5000)
86 {
87 GLfloat seconds = (GLfloat) (t - t0) / 1000.0f;
88 GLfloat fps = frames / seconds;
89 printf ("%d frames in %6.3f seconds = %6.3f FPS\n", frames, seconds, fps);
90 t0 = t;
91 frames = 0;
92 }
93 }
94}
95
96static void Idle (void)
97{
98 lightPos[0] += delta;
99 if (lightPos[0] > 25.0f || lightPos[0] < -25.0f)
100 delta = -delta;
101 glutPostRedisplay ();
102}
103
104static void Reshape (int width, int height)
105{
106 glViewport (0, 0, width, height);
107 glMatrixMode (GL_PROJECTION);
108 glLoadIdentity ();
109 glFrustum (-1.0, 1.0, -1.0, 1.0, 5.0, 25.0);
110 glMatrixMode (GL_MODELVIEW);
111 glLoadIdentity ();
112 glTranslatef (0.0f, 0.0f, -15.0f);
113}
114
115static void Key (unsigned char key, int x, int y)
116{
117 (void) x;
118 (void) y;
119
120 switch (key)
121 {
122 case ' ':
123 case 'a':
124 anim = !anim;
125 if (anim)
126 glutIdleFunc (Idle);
127 else
128 glutIdleFunc (NULL);
129 break;
130 case 'x':
131 lightPos[0] -= 1.0f;
132 break;
133 case 'X':
134 lightPos[0] += 1.0f;
135 break;
136 case 'w':
137 wire = !wire;
138 if (wire)
139 glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
140 else
141 glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
142 break;
143 case 'p':
144 pixelLight = !pixelLight;
145 if (pixelLight)
146 printf ("Per-pixel lighting\n");
147 else
148 printf ("Conventional lighting\n");
149 break;
150 case 27:
151 exit(0);
152 break;
153 }
154 glutPostRedisplay ();
155}
156
157static void SpecialKey (int key, int x, int y)
158{
159 const GLfloat step = 3.0f;
160
161 (void) x;
162 (void) y;
163
164 switch (key)
165 {
166 case GLUT_KEY_UP:
167 xRot -= step;
168 break;
169 case GLUT_KEY_DOWN:
170 xRot += step;
171 break;
172 case GLUT_KEY_LEFT:
173 yRot -= step;
174 break;
175 case GLUT_KEY_RIGHT:
176 yRot += step;
177 break;
178 }
179 glutPostRedisplay ();
180}
181
182static void Init (void)
183{
184 static const char *fragShaderText =
185 "void main () {\n"
186
187 /* XXX source from uniform lightPos */
188 " vec4 lightPos;\n"
189 " lightPos = gl_TexCoord[1];\n"
190
191 /* XXX source from uniform diffuse */
192 " vec4 diffuse;\n"
Michal Krol36541932006-02-18 15:11:18 +0000193 " diffuse = vec4 (0.5, 0.5, 1.0, 1.0);\n"
Michal Krol36997512006-02-15 10:58:52 +0000194
195 /* XXX source from uniform specular */
196 " vec4 specular;\n"
Michal Krol36541932006-02-18 15:11:18 +0000197 " specular = vec4 (0.8, 0.8, 0.8, 1.0);\n"
Michal Krol36997512006-02-15 10:58:52 +0000198
Michal Krol36997512006-02-15 10:58:52 +0000199 " // Compute dot product of light direction and normal vector\n"
200 " float dotProd;\n"
Michal Krol36541932006-02-18 15:11:18 +0000201 " dotProd = clamp (dot (normalize (lightPos).xyz, normalize (gl_TexCoord[0]).xyz), 0.0, 1.0);\n"
Michal Krol36997512006-02-15 10:58:52 +0000202 " // Compute diffuse and specular contributions\n"
203 " gl_FragColor = diffuse * dotProd + specular * pow (dotProd, 20.0);\n"
204 "}\n"
205 ;
206 static const char *vertShaderText =
207 "void main () {\n"
208 " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
Michal Krol36541932006-02-18 15:11:18 +0000209 " gl_TexCoord[0] = vec4 (gl_NormalMatrix * gl_Normal, 1.0);\n"
Michal Krol36997512006-02-15 10:58:52 +0000210
211 /* XXX source from uniform lightPos */
212 " gl_TexCoord[1] = gl_MultiTexCoord0;\n"
213 "}\n"
214 ;
215
216 if (!glutExtensionSupported ("GL_ARB_fragment_shader"))
217 {
218 printf ("Sorry, this demo requires GL_ARB_fragment_shader\n");
219 exit(1);
220 }
221 if (!glutExtensionSupported ("GL_ARB_shader_objects"))
222 {
223 printf ("Sorry, this demo requires GL_ARB_shader_objects\n");
224 exit(1);
225 }
226 if (!glutExtensionSupported ("GL_ARB_shading_language_100"))
227 {
228 printf ("Sorry, this demo requires GL_ARB_shading_language_100\n");
229 exit(1);
230 }
231 if (!glutExtensionSupported ("GL_ARB_vertex_shader"))
232 {
233 printf ("Sorry, this demo requires GL_ARB_vertex_shader\n");
234 exit(1);
235 }
236
Michal Krol36541932006-02-18 15:11:18 +0000237 glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC) GETPROCADDRESS ("glCreateShaderObjectARB");
238 glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC) GETPROCADDRESS ("glShaderSourceARB");
239 glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC) GETPROCADDRESS ("glCompileShaderARB");
240 glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC) GETPROCADDRESS ("glCreateProgramObjectARB");
241 glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC) GETPROCADDRESS ("glAttachObjectARB");
242 glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC) GETPROCADDRESS ("glLinkProgramARB");
243 glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC) GETPROCADDRESS ("glUseProgramObjectARB");
Michal Krol36997512006-02-15 10:58:52 +0000244
245 fragShader = glCreateShaderObjectARB (GL_FRAGMENT_SHADER_ARB);
246 glShaderSourceARB (fragShader, 1, &fragShaderText, NULL);
247 glCompileShaderARB (fragShader);
248
249 vertShader = glCreateShaderObjectARB (GL_VERTEX_SHADER_ARB);
250 glShaderSourceARB (vertShader, 1, &vertShaderText, NULL);
251 glCompileShaderARB (vertShader);
252
253 program = glCreateProgramObjectARB ();
254 glAttachObjectARB (program, fragShader);
255 glAttachObjectARB (program, vertShader);
256 glLinkProgramARB (program);
257 glUseProgramObjectARB (program);
258
259 glClearColor (0.3f, 0.3f, 0.3f, 0.0f);
260 glEnable (GL_DEPTH_TEST);
261 glEnable (GL_LIGHT0);
262 glEnable (GL_LIGHTING);
263 glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse);
264 glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, specular);
265 glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, 20.0f);
266
267 printf ("GL_RENDERER = %s\n", (const char *) glGetString (GL_RENDERER));
268 printf ("Press p to toggle between per-pixel and per-vertex lighting\n");
269}
270
271int main (int argc, char *argv[])
272{
273 glutInit (&argc, argv);
274 glutInitWindowPosition ( 0, 0);
275 glutInitWindowSize (200, 200);
276 glutInitDisplayMode (GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
277 glutCreateWindow (argv[0]);
278 glutReshapeFunc (Reshape);
279 glutKeyboardFunc (Key);
280 glutSpecialFunc (SpecialKey);
281 glutDisplayFunc (Redisplay);
282 if (anim)
283 glutIdleFunc (Idle);
284 Init ();
285 glutMainLoop ();
286 return 0;
287}
288