~ubuntu-branches/ubuntu/oneiric/mesa-demos/oneiric

« back to all changes in this revision

Viewing changes to src/demos/arbfplight.c

  • Committer: Bazaar Package Importer
  • Author(s): Christopher James Halse Rogers
  • Date: 2010-09-27 16:18:27 UTC
  • Revision ID: james.westby@ubuntu.com-20100927161827-1yfgolc1oy9sjhi8
Tags: upstream-8.0.1
ImportĀ upstreamĀ versionĀ 8.0.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Use GL_ARB_fragment_program and GL_ARB_vertex_program to implement
 
3
 * simple per-pixel lighting.
 
4
 *
 
5
 * Brian Paul
 
6
 * 17 April 2003
 
7
 */
 
8
 
 
9
#include <assert.h>
 
10
#include <string.h>
 
11
#include <stdio.h>
 
12
#include <stdlib.h>
 
13
#include <math.h>
 
14
#include <GL/glew.h>
 
15
#include <GL/glut.h>
 
16
 
 
17
 
 
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;
 
22
 
 
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;
 
28
static GLint Win;
 
29
 
 
30
static GLint T0 = 0;
 
31
static GLint Frames = 0;
 
32
 
 
33
static GLfloat Xrot = 0, Yrot = 0;
 
34
 
 
35
 
 
36
/* These must match the indexes used in the fragment program */
 
37
#define LIGHTPOS 3
 
38
 
 
39
/* Set to one to test ARB_fog_linear program option */
 
40
#define DO_FRAGMENT_FOG 0
 
41
 
 
42
static void normalize (GLfloat *dst, const GLfloat *src)
 
43
{
 
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;
 
48
}
 
49
 
 
50
static void Redisplay( void )
 
51
{
 
52
   glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
 
53
 
 
54
   if (PixelLight) {
 
55
      GLfloat pos[4];
 
56
 
 
57
      normalize( pos, LightPos );
 
58
      pos[3] = LightPos[3];
 
59
      glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB,
 
60
                                         LIGHTPOS, pos);
 
61
      glEnable(GL_FRAGMENT_PROGRAM_ARB);
 
62
      glEnable(GL_VERTEX_PROGRAM_ARB);
 
63
      glDisable(GL_LIGHTING);
 
64
   }
 
65
   else {
 
66
      glLightfv(GL_LIGHT0, GL_POSITION, LightPos);
 
67
      glDisable(GL_FRAGMENT_PROGRAM_ARB);
 
68
      glDisable(GL_VERTEX_PROGRAM_ARB);
 
69
      glEnable(GL_LIGHTING);
 
70
   }
 
71
 
 
72
   glPushMatrix();
 
73
   glRotatef(Xrot, 1, 0, 0);
 
74
   glRotatef(Yrot, 0, 1, 0);
 
75
   glutSolidSphere(2.0, 10, 5);
 
76
   glPopMatrix();
 
77
 
 
78
   glutSwapBuffers();
 
79
 
 
80
   Frames++;
 
81
 
 
82
   if (Anim) {
 
83
      GLint t = glutGet(GLUT_ELAPSED_TIME);
 
84
      if (t - T0 >= 5000) {
 
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);
 
88
         fflush(stdout);
 
89
         T0 = t;
 
90
         Frames = 0;
 
91
      }
 
92
   }
 
93
}
 
94
 
 
95
 
 
96
static void Idle(void)
 
97
{
 
98
   LightPos[0] += Delta;
 
99
   if (LightPos[0] > 25.0)
 
100
      Delta = -1.0;
 
101
   else if (LightPos[0] <- 25.0)
 
102
      Delta = 1.0;
 
103
   glutPostRedisplay();
 
104
}
 
105
 
 
106
 
 
107
static void Reshape( int width, int height )
 
108
{
 
109
   glViewport( 0, 0, width, height );
 
110
   glMatrixMode( GL_PROJECTION );
 
111
   glLoadIdentity();
 
112
   glFrustum( -1.0, 1.0, -1.0, 1.0, 5.0, 25.0 );
 
113
   glMatrixMode( GL_MODELVIEW );
 
114
   glLoadIdentity();
 
115
   glTranslatef( 0.0, 0.0, -15.0 );
 
116
}
 
117
 
 
118
 
 
119
static void Key( unsigned char key, int x, int y )
 
120
{
 
121
   (void) x;
 
122
   (void) y;
 
123
   switch (key) {
 
124
     case ' ':
 
125
     case 'a':
 
126
        Anim = !Anim;
 
127
        if (Anim)
 
128
           glutIdleFunc(Idle);
 
129
        else
 
130
           glutIdleFunc(NULL);
 
131
        break;
 
132
      case 'x':
 
133
         LightPos[0] -= 1.0;
 
134
         break;
 
135
      case 'X':
 
136
         LightPos[0] += 1.0;
 
137
         break;
 
138
      case 'w':
 
139
         Wire = !Wire;
 
140
         if (Wire)
 
141
            glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
 
142
         else
 
143
            glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
 
144
         break;
 
145
      case 'p':
 
146
         PixelLight = !PixelLight;
 
147
         if (PixelLight) {
 
148
            printf("Per-pixel lighting\n");
 
149
         }
 
150
         else {
 
151
            printf("Conventional lighting\n");
 
152
         }
 
153
         break;
 
154
      case 27:
 
155
         glDeleteProgramsARB(1, &VertProg);
 
156
         glDeleteProgramsARB(1, &FragProg);
 
157
         glutDestroyWindow(Win);
 
158
         exit(0);
 
159
         break;
 
160
   }
 
161
   glutPostRedisplay();
 
162
}
 
163
 
 
164
static void SpecialKey( int key, int x, int y )
 
165
{
 
166
   const GLfloat step = 3.0;
 
167
   (void) x;
 
168
   (void) y;
 
169
   switch (key) {
 
170
      case GLUT_KEY_UP:
 
171
         Xrot -= step;
 
172
         break;
 
173
      case GLUT_KEY_DOWN:
 
174
         Xrot += step;
 
175
         break;
 
176
      case GLUT_KEY_LEFT:
 
177
         Yrot -= step;
 
178
         break;
 
179
      case GLUT_KEY_RIGHT:
 
180
         Yrot += step;
 
181
         break;
 
182
   }
 
183
   glutPostRedisplay();
 
184
}
 
185
 
 
186
 
 
187
/* A helper for finding errors in program strings */
 
188
static int FindLine( const char *program, int position )
 
189
{
 
190
   int i, line = 1;
 
191
   for (i = 0; i < position; i++) {
 
192
      if (program[i] == '\n')
 
193
         line++;
 
194
   }
 
195
   return line;
 
196
}
 
197
 
 
198
 
 
199
static void Init( void )
 
200
{
 
201
   GLint errorPos;
 
202
 
 
203
   /* Yes, this could be expressed more efficiently */
 
204
   static const char *fragProgramText =
 
205
      "!!ARBfp1.0\n"
 
206
#if DO_FRAGMENT_FOG
 
207
      "OPTION ARB_fog_linear; \n"
 
208
#endif
 
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"
 
215
 
 
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"
 
220
 
 
221
      "# Compute dot product of light direction and normal vector\n"
 
222
      "DP3_SAT dotProd.x, LightPos, normal;             # limited to [0,1]\n"
 
223
 
 
224
      "MUL diffuseColor.xyz, Diffuse, dotProd.x;            # diffuse attenuation\n"
 
225
 
 
226
      "POW specAtten.x, dotProd.x, {20.0}.x;          # specular exponent\n"
 
227
 
 
228
      "MUL specularColor.xyz, Specular, specAtten.x;      # specular attenuation\n"
 
229
 
 
230
      "MOV result.color.w, Diffuse; \n"
 
231
#if DO_FRAGMENT_FOG
 
232
      "# need to clamp color to [0,1] before fogging \n"
 
233
      "ADD_SAT result.color.xyz, diffuseColor, specularColor; # add colors\n"
 
234
#else
 
235
      "# clamping will be done after program's finished \n"
 
236
      "ADD result.color.xyz, diffuseColor, specularColor; # add colors\n"
 
237
#endif
 
238
      "END \n"
 
239
      ;
 
240
 
 
241
   static const char *vertProgramText =
 
242
      "!!ARBvp1.0\n"
 
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"
 
248
 
 
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"
 
254
 
 
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"
 
260
 
 
261
#if DO_FRAGMENT_FOG
 
262
      "# compute fog coordinate = vertex eye-space Z coord (negated)\n"
 
263
      "DP4 result.fogcoord, -pos, modelview[2]; \n"
 
264
#endif
 
265
      "END\n";
 
266
      ;
 
267
 
 
268
   if (!glutExtensionSupported("GL_ARB_vertex_program")) {
 
269
      printf("Sorry, this demo requires GL_ARB_vertex_program\n");
 
270
      exit(1);
 
271
   }
 
272
   if (!glutExtensionSupported("GL_ARB_fragment_program")) {
 
273
      printf("Sorry, this demo requires GL_ARB_fragment_program\n");
 
274
      exit(1);
 
275
   }
 
276
         
 
277
   /*
 
278
    * Fragment program
 
279
    */
 
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));
 
292
      exit(0);
 
293
   }
 
294
   assert(glIsProgramARB(FragProg));
 
295
 
 
296
   /*
 
297
    * Do some sanity tests
 
298
    */
 
299
   {
 
300
      GLdouble v[4];
 
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);
 
308
   }
 
309
 
 
310
   /*
 
311
    * Vertex program
 
312
    */
 
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));
 
325
      exit(0);
 
326
   }
 
327
   assert(glIsProgramARB(VertProg));
 
328
 
 
329
   /*
 
330
    * Misc init
 
331
    */
 
332
   glClearColor(0.3, 0.3, 0.3, 0.0);
 
333
   glEnable(GL_DEPTH_TEST);
 
334
   glEnable(GL_LIGHT0);
 
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);
 
339
 
 
340
#if DO_FRAGMENT_FOG
 
341
   {
 
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);
 
347
   }
 
348
#endif
 
349
 
 
350
   printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
 
351
   printf("Press p to toggle between per-pixel and per-vertex lighting\n");
 
352
}
 
353
 
 
354
 
 
355
int main( int argc, char *argv[] )
 
356
{
 
357
   glutInitWindowSize( 200, 200 );
 
358
   glutInit( &argc, argv );
 
359
   glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH );
 
360
   Win = glutCreateWindow(argv[0]);
 
361
   glewInit();
 
362
   glutReshapeFunc( Reshape );
 
363
   glutKeyboardFunc( Key );
 
364
   glutSpecialFunc( SpecialKey );
 
365
   glutDisplayFunc( Redisplay );
 
366
   if (Anim)
 
367
      glutIdleFunc(Idle);
 
368
   Init();
 
369
   glutMainLoop();
 
370
   return 0;
 
371
}