blob: fb510cccc8ad4ef670bc605e79e1e02f4c51f173 [file] [log] [blame]
Brian Paul4cef8812003-04-07 23:05:50 +00001/*
2 * Use GL_NV_fragment_program to implement per-pixel lighting.
3 *
4 * Brian Paul
5 * 7 April 2003
6 */
7
8#include <assert.h>
9#include <string.h>
10#include <stdio.h>
11#include <stdlib.h>
12#include <math.h>
13#define GL_GLEXT_PROTOTYPES
14#include <GL/glut.h>
15
16
17static GLfloat Diffuse[4] = { 0.5, 0.5, 1.0, 1.0 };
18static GLfloat Specular[4] = { 0.8, 0.8, 0.8, 1.0 };
19static GLfloat LightPos[4] = { 0.0, 10.0, 20.0, 1.0 };
20static GLfloat Delta = 1.0;
21
22static GLuint FragProg;
23static GLuint VertProg;
24static GLboolean Anim = GL_TRUE;
25static GLboolean Wire = GL_FALSE;
26static GLboolean PixelLight = GL_TRUE;
Brianbc74cb42007-04-20 11:59:18 -060027static GLint Win;
Brian Paul4cef8812003-04-07 23:05:50 +000028static GLfloat Xrot = 0, Yrot = 0;
29
30
31#define NAMED_PARAMETER4FV(prog, name, v) \
32 glProgramNamedParameter4fvNV(prog, strlen(name), (const GLubyte *) name, v)
33
34
35static void Display( void )
36{
37 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
38
39 if (PixelLight) {
Brian Paula4a31c52005-01-09 17:39:36 +000040#if defined(GL_NV_fragment_program)
Brian Paul4cef8812003-04-07 23:05:50 +000041 NAMED_PARAMETER4FV(FragProg, "LightPos", LightPos);
42 glEnable(GL_FRAGMENT_PROGRAM_NV);
43 glEnable(GL_VERTEX_PROGRAM_NV);
Brian Paula4a31c52005-01-09 17:39:36 +000044#endif
Brian Paul4cef8812003-04-07 23:05:50 +000045 glDisable(GL_LIGHTING);
46 }
47 else {
48 glLightfv(GL_LIGHT0, GL_POSITION, LightPos);
Brian Paula4a31c52005-01-09 17:39:36 +000049#if defined(GL_NV_fragment_program)
Brian Paul4cef8812003-04-07 23:05:50 +000050 glDisable(GL_FRAGMENT_PROGRAM_NV);
51 glDisable(GL_VERTEX_PROGRAM_NV);
Brian Paula4a31c52005-01-09 17:39:36 +000052#endif
Brian Paul4cef8812003-04-07 23:05:50 +000053 glEnable(GL_LIGHTING);
54 }
55
56 glPushMatrix();
57 glRotatef(Xrot, 1, 0, 0);
58 glRotatef(Yrot, 0, 1, 0);
59
Brian Paul4cef8812003-04-07 23:05:50 +000060#if 1
61 glutSolidSphere(2.0, 10, 5);
62#else
63 {
64 GLUquadricObj *q = gluNewQuadric();
65 gluQuadricNormals(q, GL_SMOOTH);
66 gluQuadricTexture(q, GL_TRUE);
67 glRotatef(90, 1, 0, 0);
68 glTranslatef(0, 0, -1);
69 gluCylinder(q, 1.0, 1.0, 2.0, 24, 1);
70 gluDeleteQuadric(q);
71 }
72#endif
73
74 glPopMatrix();
75
76 glutSwapBuffers();
77}
78
79
80static void Idle(void)
81{
82 LightPos[0] += Delta;
83 if (LightPos[0] > 25.0)
84 Delta = -1.0;
85 else if (LightPos[0] <- 25.0)
86 Delta = 1.0;
87 glutPostRedisplay();
88}
89
90
91static void Reshape( int width, int height )
92{
93 glViewport( 0, 0, width, height );
94 glMatrixMode( GL_PROJECTION );
95 glLoadIdentity();
96 glFrustum( -1.0, 1.0, -1.0, 1.0, 5.0, 25.0 );
97 /*glOrtho( -2.0, 2.0, -2.0, 2.0, 5.0, 25.0 );*/
98 glMatrixMode( GL_MODELVIEW );
99 glLoadIdentity();
100 glTranslatef( 0.0, 0.0, -15.0 );
101}
102
103
104static void Key( unsigned char key, int x, int y )
105{
106 (void) x;
107 (void) y;
108 switch (key) {
109 case ' ':
110 Anim = !Anim;
111 if (Anim)
112 glutIdleFunc(Idle);
113 else
114 glutIdleFunc(NULL);
115 break;
116 case 'x':
117 LightPos[0] -= 1.0;
118 break;
119 case 'X':
120 LightPos[0] += 1.0;
121 break;
122 case 'w':
123 Wire = !Wire;
124 if (Wire)
125 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
126 else
127 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
128 break;
129 case 'p':
130 PixelLight = !PixelLight;
131 if (PixelLight) {
132 printf("Per-pixel lighting\n");
133 }
134 else {
135 printf("Conventional lighting\n");
136 }
137 break;
138 case 27:
Brianbc74cb42007-04-20 11:59:18 -0600139 glutDestroyWindow(Win);
Brian Paul4cef8812003-04-07 23:05:50 +0000140 exit(0);
Brian Paul4cef8812003-04-07 23:05:50 +0000141 }
142 glutPostRedisplay();
143}
144
145static void SpecialKey( int key, int x, int y )
146{
147 const GLfloat step = 3.0;
148 (void) x;
149 (void) y;
150 switch (key) {
151 case GLUT_KEY_UP:
152 Xrot -= step;
153 break;
154 case GLUT_KEY_DOWN:
155 Xrot += step;
156 break;
157 case GLUT_KEY_LEFT:
158 Yrot -= step;
159 break;
160 case GLUT_KEY_RIGHT:
161 Yrot += step;
162 break;
163 }
164 glutPostRedisplay();
165}
166
167
168static void Init( void )
169{
170 static const char *fragProgramText =
171 "!!FP1.0\n"
172 "DECLARE Diffuse; \n"
173 "DECLARE Specular; \n"
174 "DECLARE LightPos; \n"
175
176 "# Compute normalized LightPos, put it in R0\n"
177 "DP3 R0.x, LightPos, LightPos;\n"
178 "RSQ R0.y, R0.x;\n"
179 "MUL R0, LightPos, R0.y;\n"
180
181 "# Compute normalized normal, put it in R1\n"
182 "DP3 R1, f[TEX0], f[TEX0]; \n"
183 "RSQ R1.y, R1.x;\n"
184 "MUL R1, f[TEX0], R1.y;\n"
185
186 "# Compute dot product of light direction and normal vector\n"
Brian Paul244adeb2004-12-15 00:54:17 +0000187 "DP3_SAT R2, R0, R1;"
Brian Paul4cef8812003-04-07 23:05:50 +0000188
189 "MUL R3, Diffuse, R2; # diffuse attenuation\n"
190
191 "POW R4, R2.x, {20.0}.x; # specular exponent\n"
192
193 "MUL R5, Specular, R4; # specular attenuation\n"
194
195 "ADD o[COLR], R3, R5; # add diffuse and specular colors\n"
196 "END \n"
197 ;
198
199 static const char *vertProgramText =
200 "!!VP1.0\n"
201 "# typical modelview/projection transform\n"
202 "DP4 o[HPOS].x, c[0], v[OPOS] ;\n"
203 "DP4 o[HPOS].y, c[1], v[OPOS] ;\n"
204 "DP4 o[HPOS].z, c[2], v[OPOS] ;\n"
205 "DP4 o[HPOS].w, c[3], v[OPOS] ;\n"
206 "# transform normal by inv transpose of modelview, put in tex0\n"
Brian Paul254e2012003-08-31 18:57:17 +0000207 "DP3 o[TEX0].x, c[4], v[NRML] ;\n"
208 "DP3 o[TEX0].y, c[5], v[NRML] ;\n"
209 "DP3 o[TEX0].z, c[6], v[NRML] ;\n"
210 "DP3 o[TEX0].w, c[7], v[NRML] ;\n"
Brian Paul4cef8812003-04-07 23:05:50 +0000211 "END\n";
212 ;
213
214 if (!glutExtensionSupported("GL_NV_vertex_program")) {
215 printf("Sorry, this demo requires GL_NV_vertex_program\n");
216 exit(1);
217 }
218 if (!glutExtensionSupported("GL_NV_fragment_program")) {
219 printf("Sorry, this demo requires GL_NV_fragment_program\n");
220 exit(1);
221 }
222
Brian Paula4a31c52005-01-09 17:39:36 +0000223#if defined(GL_NV_fragment_program)
Brian Paul4cef8812003-04-07 23:05:50 +0000224 glGenProgramsNV(1, &FragProg);
Brian Paulf8f830d2003-05-30 15:42:22 +0000225 assert(FragProg > 0);
Brian Paul4cef8812003-04-07 23:05:50 +0000226 glGenProgramsNV(1, &VertProg);
Brian Paulf8f830d2003-05-30 15:42:22 +0000227 assert(VertProg > 0);
Brian Paul4cef8812003-04-07 23:05:50 +0000228
229 /*
230 * Fragment program
231 */
232 glLoadProgramNV(GL_FRAGMENT_PROGRAM_NV, FragProg,
233 strlen(fragProgramText),
234 (const GLubyte *) fragProgramText);
235 assert(glIsProgramNV(FragProg));
236 glBindProgramNV(GL_FRAGMENT_PROGRAM_NV, FragProg);
237
238 NAMED_PARAMETER4FV(FragProg, "Diffuse", Diffuse);
239 NAMED_PARAMETER4FV(FragProg, "Specular", Specular);
240
241 /*
242 * Vertex program
243 */
244 glLoadProgramNV(GL_VERTEX_PROGRAM_NV, VertProg,
245 strlen(vertProgramText),
246 (const GLubyte *) vertProgramText);
247 assert(glIsProgramNV(VertProg));
248 glBindProgramNV(GL_VERTEX_PROGRAM_NV, VertProg);
249 glTrackMatrixNV(GL_VERTEX_PROGRAM_NV, 0, GL_MODELVIEW_PROJECTION_NV, GL_IDENTITY_NV);
250 glTrackMatrixNV(GL_VERTEX_PROGRAM_NV, 4, GL_MODELVIEW, GL_INVERSE_TRANSPOSE_NV);
Brian Paula4a31c52005-01-09 17:39:36 +0000251#endif
Brian Paul4cef8812003-04-07 23:05:50 +0000252
253 /*
254 * Misc init
255 */
256 glClearColor(0.3, 0.3, 0.3, 0.0);
Brian Paul4cef8812003-04-07 23:05:50 +0000257 glEnable(GL_DEPTH_TEST);
258 glEnable(GL_LIGHT0);
259 glEnable(GL_LIGHTING);
260 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, Diffuse);
261 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, Specular);
262 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 20.0);
263
264 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
265 printf("Press p to toggle between per-pixel and per-vertex lighting\n");
266}
267
268
269int main( int argc, char *argv[] )
270{
271 glutInit( &argc, argv );
272 glutInitWindowPosition( 0, 0 );
273 glutInitWindowSize( 200, 200 );
274 glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH );
Brianbc74cb42007-04-20 11:59:18 -0600275 Win = glutCreateWindow(argv[0]);
Brian Paul4cef8812003-04-07 23:05:50 +0000276 glutReshapeFunc( Reshape );
277 glutKeyboardFunc( Key );
278 glutSpecialFunc( SpecialKey );
279 glutDisplayFunc( Display );
280 if (Anim)
281 glutIdleFunc(Idle);
282 Init();
283 glutMainLoop();
284 return 0;
285}