2
* Use GL_ARB_fragment_program and GL_ARB_vertex_program to implement
3
* simple per-pixel lighting.
18
static GLfloat Diffuse[4] = { 0.5, 0.5, 1.0, 1.0 };
19
static GLfloat Specular[4] = { 0.8, 0.8, 0.8, 1.0 };
20
static GLfloat LightPos[4] = { 0.0, 10.0, 20.0, 1.0 };
21
static GLfloat Delta = 1.0;
23
static GLuint FragProg;
24
static GLuint VertProg;
25
static GLboolean Anim = GL_TRUE;
26
static GLboolean Wire = GL_FALSE;
27
static GLboolean PixelLight = GL_TRUE;
31
static GLint Frames = 0;
33
static GLfloat Xrot = 0, Yrot = 0;
36
/* These must match the indexes used in the fragment program */
39
/* Set to one to test ARB_fog_linear program option */
40
#define DO_FRAGMENT_FOG 0
42
static void normalize (GLfloat *dst, const GLfloat *src)
44
GLfloat len = sqrt (src[0] * src[0] + src[1] * src[1] + src[2] * src[2]);
45
dst[0] = src[0] / len;
46
dst[1] = src[1] / len;
47
dst[2] = src[2] / len;
50
static void Redisplay( void )
52
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
57
normalize( pos, LightPos );
59
glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB,
61
glEnable(GL_FRAGMENT_PROGRAM_ARB);
62
glEnable(GL_VERTEX_PROGRAM_ARB);
63
glDisable(GL_LIGHTING);
66
glLightfv(GL_LIGHT0, GL_POSITION, LightPos);
67
glDisable(GL_FRAGMENT_PROGRAM_ARB);
68
glDisable(GL_VERTEX_PROGRAM_ARB);
69
glEnable(GL_LIGHTING);
73
glRotatef(Xrot, 1, 0, 0);
74
glRotatef(Yrot, 0, 1, 0);
75
glutSolidSphere(2.0, 10, 5);
83
GLint t = glutGet(GLUT_ELAPSED_TIME);
85
GLfloat seconds = (t - T0) / 1000.0;
86
GLfloat fps = Frames / seconds;
87
printf("%d frames in %6.3f seconds = %6.3f FPS\n", Frames, seconds, fps);
96
static void Idle(void)
99
if (LightPos[0] > 25.0)
101
else if (LightPos[0] <- 25.0)
107
static void Reshape( int width, int height )
109
glViewport( 0, 0, width, height );
110
glMatrixMode( GL_PROJECTION );
112
glFrustum( -1.0, 1.0, -1.0, 1.0, 5.0, 25.0 );
113
glMatrixMode( GL_MODELVIEW );
115
glTranslatef( 0.0, 0.0, -15.0 );
119
static void Key( unsigned char key, int x, int y )
141
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
143
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
146
PixelLight = !PixelLight;
148
printf("Per-pixel lighting\n");
151
printf("Conventional lighting\n");
155
glDeleteProgramsARB(1, &VertProg);
156
glDeleteProgramsARB(1, &FragProg);
157
glutDestroyWindow(Win);
164
static void SpecialKey( int key, int x, int y )
166
const GLfloat step = 3.0;
187
/* A helper for finding errors in program strings */
188
static int FindLine( const char *program, int position )
191
for (i = 0; i < position; i++) {
192
if (program[i] == '\n')
199
static void Init( void )
203
/* Yes, this could be expressed more efficiently */
204
static const char *fragProgramText =
207
"OPTION ARB_fog_linear; \n"
209
"PARAM Diffuse = state.material.diffuse; \n"
210
"PARAM Specular = state.material.specular; \n"
211
"PARAM LightPos = program.local[3]; \n"
212
"TEMP normal, len; \n"
213
"TEMP dotProd, specAtten; \n"
214
"TEMP diffuseColor, specularColor; \n"
216
"# Compute normalized normal \n"
217
"DP3 len.x, fragment.texcoord[0], fragment.texcoord[0]; \n"
218
"RSQ len.y, len.x; \n"
219
"MUL normal.xyz, fragment.texcoord[0], len.y; \n"
221
"# Compute dot product of light direction and normal vector\n"
222
"DP3_SAT dotProd.x, LightPos, normal; # limited to [0,1]\n"
224
"MUL diffuseColor.xyz, Diffuse, dotProd.x; # diffuse attenuation\n"
226
"POW specAtten.x, dotProd.x, {20.0}.x; # specular exponent\n"
228
"MUL specularColor.xyz, Specular, specAtten.x; # specular attenuation\n"
230
"MOV result.color.w, Diffuse; \n"
232
"# need to clamp color to [0,1] before fogging \n"
233
"ADD_SAT result.color.xyz, diffuseColor, specularColor; # add colors\n"
235
"# clamping will be done after program's finished \n"
236
"ADD result.color.xyz, diffuseColor, specularColor; # add colors\n"
241
static const char *vertProgramText =
243
"ATTRIB pos = vertex.position; \n"
244
"ATTRIB norm = vertex.normal; \n"
245
"PARAM modelview[4] = { state.matrix.modelview }; \n"
246
"PARAM modelviewProj[4] = { state.matrix.mvp }; \n"
247
"PARAM invModelview[4] = { state.matrix.modelview.invtrans }; \n"
249
"# typical modelview/projection transform \n"
250
"DP4 result.position.x, pos, modelviewProj[0]; \n"
251
"DP4 result.position.y, pos, modelviewProj[1]; \n"
252
"DP4 result.position.z, pos, modelviewProj[2]; \n"
253
"DP4 result.position.w, pos, modelviewProj[3]; \n"
255
"# transform normal by inv transpose of modelview, put in tex0 \n"
256
"DP3 result.texcoord[0].x, norm, invModelview[0]; \n"
257
"DP3 result.texcoord[0].y, norm, invModelview[1]; \n"
258
"DP3 result.texcoord[0].z, norm, invModelview[2]; \n"
259
"DP3 result.texcoord[0].w, norm, invModelview[3]; \n"
262
"# compute fog coordinate = vertex eye-space Z coord (negated)\n"
263
"DP4 result.fogcoord, -pos, modelview[2]; \n"
268
if (!glutExtensionSupported("GL_ARB_vertex_program")) {
269
printf("Sorry, this demo requires GL_ARB_vertex_program\n");
272
if (!glutExtensionSupported("GL_ARB_fragment_program")) {
273
printf("Sorry, this demo requires GL_ARB_fragment_program\n");
280
glGenProgramsARB(1, &FragProg);
281
assert(FragProg > 0);
282
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, FragProg);
283
glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB,
284
GL_PROGRAM_FORMAT_ASCII_ARB,
285
strlen(fragProgramText),
286
(const GLubyte *) fragProgramText);
287
glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errorPos);
288
if (glGetError() != GL_NO_ERROR || errorPos != -1) {
289
int l = FindLine(fragProgramText, errorPos);
290
printf("Fragment Program Error (pos=%d line=%d): %s\n", errorPos, l,
291
(char *) glGetString(GL_PROGRAM_ERROR_STRING_ARB));
294
assert(glIsProgramARB(FragProg));
297
* Do some sanity tests
301
glProgramLocalParameter4dARB(GL_FRAGMENT_PROGRAM_ARB, 8,
302
10.0, 20.0, 30.0, 40.0);
303
glGetProgramLocalParameterdvARB(GL_FRAGMENT_PROGRAM_ARB, 8, v);
304
assert(v[0] == 10.0);
305
assert(v[1] == 20.0);
306
assert(v[2] == 30.0);
307
assert(v[3] == 40.0);
313
glGenProgramsARB(1, &VertProg);
314
assert(VertProg > 0);
315
glBindProgramARB(GL_VERTEX_PROGRAM_ARB, VertProg);
316
glProgramStringARB(GL_VERTEX_PROGRAM_ARB,
317
GL_PROGRAM_FORMAT_ASCII_ARB,
318
strlen(vertProgramText),
319
(const GLubyte *) vertProgramText);
320
glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errorPos);
321
if (glGetError() != GL_NO_ERROR || errorPos != -1) {
322
int l = FindLine(vertProgramText, errorPos);
323
printf("Vertex Program Error (pos=%d line=%d): %s\n", errorPos, l,
324
(char *) glGetString(GL_PROGRAM_ERROR_STRING_ARB));
327
assert(glIsProgramARB(VertProg));
332
glClearColor(0.3, 0.3, 0.3, 0.0);
333
glEnable(GL_DEPTH_TEST);
335
glEnable(GL_LIGHTING);
336
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, Diffuse);
337
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, Specular);
338
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 20.0);
342
/* Green-ish fog color */
343
static const GLfloat fogColor[4] = {0.5, 1.0, 0.5, 0};
344
glFogfv(GL_FOG_COLOR, fogColor);
345
glFogf(GL_FOG_START, 5.0);
346
glFogf(GL_FOG_END, 25.0);
350
printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
351
printf("Press p to toggle between per-pixel and per-vertex lighting\n");
355
int main( int argc, char *argv[] )
357
glutInitWindowSize( 200, 200 );
358
glutInit( &argc, argv );
359
glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH );
360
Win = glutCreateWindow(argv[0]);
362
glutReshapeFunc( Reshape );
363
glutKeyboardFunc( Key );
364
glutSpecialFunc( SpecialKey );
365
glutDisplayFunc( Redisplay );