2 * Use GL_ARB_fragment_shader and GL_ARB_vertex_shader to implement
3 * simple per-pixel lighting.
8 * Based on the original demo by:
25 #define GETPROCADDRESS wglGetProcAddress
27 #define GETPROCADDRESS glutGetProcAddress
30 static GLfloat diffuse
[4] = { 0.5f
, 0.5f
, 1.0f
, 1.0f
};
31 static GLfloat specular
[4] = { 0.8f
, 0.8f
, 0.8f
, 1.0f
};
32 static GLfloat lightPos
[4] = { 0.0f
, 10.0f
, 20.0f
, 1.0f
};
33 static GLfloat delta
= 1.0f
;
35 static GLhandleARB fragShader
;
36 static GLhandleARB vertShader
;
37 static GLhandleARB program
;
39 static GLint uLightPos
;
40 static GLint uDiffuse
;
41 static GLint uSpecular
;
43 static GLboolean anim
= GL_TRUE
;
44 static GLboolean wire
= GL_FALSE
;
45 static GLboolean pixelLight
= GL_TRUE
;
48 static GLint frames
= 0;
50 static GLfloat xRot
= 0.0f
, yRot
= 0.0f
;
52 static PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB
= NULL
;
53 static PFNGLSHADERSOURCEARBPROC glShaderSourceARB
= NULL
;
54 static PFNGLCOMPILESHADERARBPROC glCompileShaderARB
= NULL
;
55 static PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB
= NULL
;
56 static PFNGLATTACHOBJECTARBPROC glAttachObjectARB
= NULL
;
57 static PFNGLLINKPROGRAMARBPROC glLinkProgramARB
= NULL
;
58 static PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB
= NULL
;
59 static PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB
= NULL
;
60 static PFNGLUNIFORM3FVARBPROC glUniform3fvARB
= NULL
;
61 static PFNGLUNIFORM3FVARBPROC glUniform4fvARB
= NULL
;
63 static void normalize (GLfloat
*dst
, const GLfloat
*src
)
65 GLfloat len
= sqrt (src
[0] * src
[0] + src
[1] * src
[1] + src
[2] * src
[2]);
66 dst
[0] = src
[0] / len
;
67 dst
[1] = src
[1] / len
;
68 dst
[2] = src
[2] / len
;
71 static void Redisplay (void)
73 glClear (GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
79 glUseProgramObjectARB (program
);
80 normalize (vec
, lightPos
);
81 glUniform3fvARB (uLightPos
, 1, vec
);
82 glDisable(GL_LIGHTING
);
86 glUseProgramObjectARB (0);
87 glLightfv (GL_LIGHT0
, GL_POSITION
, lightPos
);
88 glEnable(GL_LIGHTING
);
92 glRotatef (xRot
, 1.0f
, 0.0f
, 0.0f
);
93 glRotatef (yRot
, 0.0f
, 1.0f
, 0.0f
);
94 glutSolidSphere (2.0, 10, 5);
102 GLint t
= glutGet (GLUT_ELAPSED_TIME
);
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
);
115 static void Idle (void)
117 lightPos
[0] += delta
;
118 if (lightPos
[0] > 25.0f
|| lightPos
[0] < -25.0f
)
120 glutPostRedisplay ();
123 static void Reshape (int width
, int height
)
125 glViewport (0, 0, width
, height
);
126 glMatrixMode (GL_PROJECTION
);
128 glFrustum (-1.0, 1.0, -1.0, 1.0, 5.0, 25.0);
129 glMatrixMode (GL_MODELVIEW
);
131 glTranslatef (0.0f
, 0.0f
, -15.0f
);
134 static void Key (unsigned char key
, int x
, int y
)
158 glPolygonMode (GL_FRONT_AND_BACK
, GL_LINE
);
160 glPolygonMode (GL_FRONT_AND_BACK
, GL_FILL
);
163 pixelLight
= !pixelLight
;
165 printf ("Per-pixel lighting\n");
167 printf ("Conventional lighting\n");
173 glutPostRedisplay ();
176 static void SpecialKey (int key
, int x
, int y
)
178 const GLfloat step
= 3.0f
;
198 glutPostRedisplay ();
201 static void Init (void)
203 static const char *fragShaderText
=
204 "uniform vec3 lightPos;\n"
205 "uniform vec4 diffuse;\n"
206 "uniform vec4 specular;\n"
207 "varying vec3 normal;\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"
213 " gl_FragColor = diffuse * dotProd + specular * pow (dotProd, 20.0);\n"
214 #elif 1 /* test IF/ELSE/ENDIF */
215 " if (normal.y > 0.0) { \n"
216 " gl_FragColor = diffuse * dotProd + specular * pow (dotProd, 20.0);\n"
219 " if (normal.x < 0.0) { \n"
220 " gl_FragColor = vec4(1, 0, 0, 0); \n"
223 " gl_FragColor = vec4(1, 1, 0, 0); \n"
226 #elif 1 /* test LOOP */
228 " if (normal.y >= 0.0) { \n"
229 " gl_FragColor = vec4(1, 0, 0, 0); \n"
232 " gl_FragColor = diffuse * dotProd + specular * pow (dotProd, 20.0);\n"
239 static const char *vertShaderText
=
240 "varying vec3 normal;\n"
242 " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
243 " normal = gl_NormalMatrix * gl_Normal;\n"
247 if (!glutExtensionSupported ("GL_ARB_fragment_shader"))
249 printf ("Sorry, this demo requires GL_ARB_fragment_shader\n");
252 if (!glutExtensionSupported ("GL_ARB_shader_objects"))
254 printf ("Sorry, this demo requires GL_ARB_shader_objects\n");
257 if (!glutExtensionSupported ("GL_ARB_shading_language_100"))
259 printf ("Sorry, this demo requires GL_ARB_shading_language_100\n");
262 if (!glutExtensionSupported ("GL_ARB_vertex_shader"))
264 printf ("Sorry, this demo requires GL_ARB_vertex_shader\n");
268 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");
276 glUniform3fvARB
= (PFNGLUNIFORM3FVARBPROC
) GETPROCADDRESS ("glUniform3fvARB");
277 glUniform4fvARB
= (PFNGLUNIFORM3FVARBPROC
) GETPROCADDRESS ("glUniform4fvARB");
279 fragShader
= glCreateShaderObjectARB (GL_FRAGMENT_SHADER_ARB
);
280 glShaderSourceARB (fragShader
, 1, &fragShaderText
, NULL
);
281 glCompileShaderARB (fragShader
);
283 vertShader
= glCreateShaderObjectARB (GL_VERTEX_SHADER_ARB
);
284 glShaderSourceARB (vertShader
, 1, &vertShaderText
, NULL
);
285 glCompileShaderARB (vertShader
);
287 program
= glCreateProgramObjectARB ();
288 glAttachObjectARB (program
, fragShader
);
289 glAttachObjectARB (program
, vertShader
);
290 glLinkProgramARB (program
);
291 glUseProgramObjectARB (program
);
293 uLightPos
= glGetUniformLocationARB (program
, "lightPos");
294 uDiffuse
= glGetUniformLocationARB (program
, "diffuse");
295 uSpecular
= glGetUniformLocationARB (program
, "specular");
297 glUniform4fvARB (uDiffuse
, 1, diffuse
);
298 glUniform4fvARB (uSpecular
, 1, specular
);
300 glClearColor (0.3f
, 0.3f
, 0.3f
, 0.0f
);
301 glEnable (GL_DEPTH_TEST
);
302 glEnable (GL_LIGHT0
);
303 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
);
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");
312 int main (int argc
, char *argv
[])
314 glutInitWindowSize (200, 200);
315 glutInit (&argc
, argv
);
316 glutInitDisplayMode (GLUT_RGB
| GLUT_DOUBLE
| GLUT_DEPTH
);
317 glutCreateWindow (argv
[0]);
318 glutReshapeFunc (Reshape
);
319 glutKeyboardFunc (Key
);
320 glutSpecialFunc (SpecialKey
);
321 glutDisplayFunc (Redisplay
);