blob: 5429fe33750a3cc5d5395c390f558b31a4a581a3 [file] [log] [blame]
Brian Paul5366b012003-07-21 04:22:59 +00001/*
2 * Test the GL_MESA_program_debug extension
3 */
4
5
6#include <assert.h>
7#include <string.h>
8#include <stdio.h>
9#include <stdlib.h>
10#include <math.h>
11#define GL_GLEXT_PROTOTYPES
12#include <GL/glut.h>
13
14
15
16static const GLubyte *
17find_line_column(const GLubyte *string, const GLubyte *pos,
18 GLint *line, GLint *col)
19{
20 const GLubyte *lineStart = string;
21 const GLubyte *p = string;
22 GLubyte *s;
23 int len;
24
25 *line = 1;
26
27 while (p != pos) {
28 if (*p == (GLubyte) '\n') {
29 (*line)++;
30 lineStart = p + 1;
31 }
32 p++;
33 }
34
35 *col = (pos - lineStart) + 1;
36
37 /* return copy of this line */
38 while (*p != 0 && *p != '\n')
39 p++;
40 len = p - lineStart;
41 s = (GLubyte *) malloc(len + 1);
42 memcpy(s, lineStart, len);
43 s[len] = 0;
44
45 return s;
46}
47
48
49static void Debugger(GLenum target, GLvoid *data)
50{
51 GLint pos;
52 const GLubyte *ln;
53 GLint line, column;
54 GLfloat v[4];
55
56 assert(target == GL_FRAGMENT_PROGRAM_NV);
57
58 glGetIntegerv(GL_FRAGMENT_PROGRAM_POSITION_MESA, &pos);
59
60 ln = find_line_column((const GLubyte *) data, (const GLubyte *) data + pos,
61 &line, &column);
62 printf("%d:%d: %s\n", line, column, (char *) ln);
63
64 glGetProgramRegisterfvMESA(GL_FRAGMENT_PROGRAM_NV,
65 2, (const GLubyte *) "R0", v);
66 printf(" R0 = %g, %g, %g, %g\n", v[0], v[1], v[2], v[3]);
67 glGetProgramRegisterfvMESA(GL_FRAGMENT_PROGRAM_NV,
68 7, (const GLubyte *) "f[WPOS]", v);
69 printf(" o[WPOS] = %g, %g, %g, %g\n", v[0], v[1], v[2], v[3]);
70 glGetProgramRegisterfvMESA(GL_FRAGMENT_PROGRAM_NV,
71 7, (const GLubyte *) "o[COLR]", v);
72 printf(" o[COLR] = %g, %g, %g, %g\n", v[0], v[1], v[2], v[3]);
73
74 free((void *) ln);
75}
76
77
78
79
80/**********************************************************************/
81
82static GLfloat Diffuse[4] = { 0.5, 0.5, 1.0, 1.0 };
83static GLfloat Specular[4] = { 0.8, 0.8, 0.8, 1.0 };
84static GLfloat LightPos[4] = { 0.0, 10.0, 20.0, 1.0 };
85static GLfloat Delta = 1.0;
86
87static GLuint FragProg;
88static GLuint VertProg;
89static GLboolean Anim = GL_TRUE;
90static GLboolean Wire = GL_FALSE;
91static GLboolean PixelLight = GL_TRUE;
92
93static GLfloat Xrot = 0, Yrot = 0;
94
95
96#define NAMED_PARAMETER4FV(prog, name, v) \
97 glProgramNamedParameter4fvNV(prog, strlen(name), (const GLubyte *) name, v)
98
99
100static void Display( void )
101{
102 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
103
104 if (PixelLight) {
105 NAMED_PARAMETER4FV(FragProg, "LightPos", LightPos);
106 glEnable(GL_FRAGMENT_PROGRAM_NV);
107 glEnable(GL_VERTEX_PROGRAM_NV);
108 glDisable(GL_LIGHTING);
109 }
110 else {
111 glLightfv(GL_LIGHT0, GL_POSITION, LightPos);
112 glDisable(GL_FRAGMENT_PROGRAM_NV);
113 glDisable(GL_VERTEX_PROGRAM_NV);
114 glEnable(GL_LIGHTING);
115 }
116
117 glPushMatrix();
118 glRotatef(Xrot, 1, 0, 0);
119 glRotatef(Yrot, 0, 1, 0);
120
121#if 1
122 glutSolidSphere(2.0, 10, 5);
123#else
124 {
125 GLUquadricObj *q = gluNewQuadric();
126 gluQuadricNormals(q, GL_SMOOTH);
127 gluQuadricTexture(q, GL_TRUE);
128 glRotatef(90, 1, 0, 0);
129 glTranslatef(0, 0, -1);
130 gluCylinder(q, 1.0, 1.0, 2.0, 24, 1);
131 gluDeleteQuadric(q);
132 }
133#endif
134
135 glPopMatrix();
136
137 glutSwapBuffers();
138}
139
140
141static void Idle(void)
142{
143 LightPos[0] += Delta;
144 if (LightPos[0] > 25.0)
145 Delta = -1.0;
146 else if (LightPos[0] <- 25.0)
147 Delta = 1.0;
148 glutPostRedisplay();
149}
150
151
152static void Reshape( int width, int height )
153{
154 glViewport( 0, 0, width, height );
155 glMatrixMode( GL_PROJECTION );
156 glLoadIdentity();
157 glFrustum( -1.0, 1.0, -1.0, 1.0, 5.0, 25.0 );
158 /*glOrtho( -2.0, 2.0, -2.0, 2.0, 5.0, 25.0 );*/
159 glMatrixMode( GL_MODELVIEW );
160 glLoadIdentity();
161 glTranslatef( 0.0, 0.0, -15.0 );
162}
163
164
165static void Key( unsigned char key, int x, int y )
166{
167 (void) x;
168 (void) y;
169 switch (key) {
170 case ' ':
171 Anim = !Anim;
172 if (Anim)
173 glutIdleFunc(Idle);
174 else
175 glutIdleFunc(NULL);
176 break;
177 case 'x':
178 LightPos[0] -= 1.0;
179 break;
180 case 'X':
181 LightPos[0] += 1.0;
182 break;
183 case 'w':
184 Wire = !Wire;
185 if (Wire)
186 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
187 else
188 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
189 break;
190 case 'p':
191 PixelLight = !PixelLight;
192 if (PixelLight) {
193 printf("Per-pixel lighting\n");
194 }
195 else {
196 printf("Conventional lighting\n");
197 }
198 break;
199 case 27:
200 exit(0);
201 break;
202 }
203 glutPostRedisplay();
204}
205
206static void SpecialKey( int key, int x, int y )
207{
208 const GLfloat step = 3.0;
209 (void) x;
210 (void) y;
211 switch (key) {
212 case GLUT_KEY_UP:
213 Xrot -= step;
214 break;
215 case GLUT_KEY_DOWN:
216 Xrot += step;
217 break;
218 case GLUT_KEY_LEFT:
219 Yrot -= step;
220 break;
221 case GLUT_KEY_RIGHT:
222 Yrot += step;
223 break;
224 }
225 glutPostRedisplay();
226}
227
228
229static void Init( void )
230{
231 static const char *fragProgramText =
232 "!!FP1.0\n"
233 "DECLARE Diffuse; \n"
234 "DECLARE Specular; \n"
235 "DECLARE LightPos; \n"
236
237 "# Compute normalized LightPos, put it in R0\n"
238 "DP3 R0.x, LightPos, LightPos;\n"
239 "RSQ R0.y, R0.x;\n"
240 "MUL R0, LightPos, R0.y;\n"
241
242 "# Compute normalized normal, put it in R1\n"
243 "DP3 R1, f[TEX0], f[TEX0]; \n"
244 "RSQ R1.y, R1.x;\n"
245 "MUL R1, f[TEX0], R1.y;\n"
246
247 "# Compute dot product of light direction and normal vector\n"
248 "DP3 R2, R0, R1;\n"
249
250 "MUL R3, Diffuse, R2; # diffuse attenuation\n"
251
252 "POW R4, R2.x, {20.0}.x; # specular exponent\n"
253
254 "MUL R5, Specular, R4; # specular attenuation\n"
255
256 "ADD o[COLR], R3, R5; # add diffuse and specular colors\n"
257 "END \n"
258 ;
259
260 static const char *vertProgramText =
261 "!!VP1.0\n"
262 "# typical modelview/projection transform\n"
263 "DP4 o[HPOS].x, c[0], v[OPOS] ;\n"
264 "DP4 o[HPOS].y, c[1], v[OPOS] ;\n"
265 "DP4 o[HPOS].z, c[2], v[OPOS] ;\n"
266 "DP4 o[HPOS].w, c[3], v[OPOS] ;\n"
267 "# transform normal by inv transpose of modelview, put in tex0\n"
268 "DP4 o[TEX0].x, c[4], v[NRML] ;\n"
269 "DP4 o[TEX0].y, c[5], v[NRML] ;\n"
270 "DP4 o[TEX0].z, c[6], v[NRML] ;\n"
271 "DP4 o[TEX0].w, c[7], v[NRML] ;\n"
272 "END\n";
273 ;
274
275 if (!glutExtensionSupported("GL_NV_vertex_program")) {
276 printf("Sorry, this demo requires GL_NV_vertex_program\n");
277 exit(1);
278 }
279 if (!glutExtensionSupported("GL_NV_fragment_program")) {
280 printf("Sorry, this demo requires GL_NV_fragment_program\n");
281 exit(1);
282 }
283
284 glGenProgramsNV(1, &FragProg);
285 assert(FragProg > 0);
286 glGenProgramsNV(1, &VertProg);
287 assert(VertProg > 0);
288
289 /*
290 * Fragment program
291 */
292 glLoadProgramNV(GL_FRAGMENT_PROGRAM_NV, FragProg,
293 strlen(fragProgramText),
294 (const GLubyte *) fragProgramText);
295 assert(glIsProgramNV(FragProg));
296 glBindProgramNV(GL_FRAGMENT_PROGRAM_NV, FragProg);
297
298 NAMED_PARAMETER4FV(FragProg, "Diffuse", Diffuse);
299 NAMED_PARAMETER4FV(FragProg, "Specular", Specular);
300
301 /*
302 * Vertex program
303 */
304 glLoadProgramNV(GL_VERTEX_PROGRAM_NV, VertProg,
305 strlen(vertProgramText),
306 (const GLubyte *) vertProgramText);
307 assert(glIsProgramNV(VertProg));
308 glBindProgramNV(GL_VERTEX_PROGRAM_NV, VertProg);
309 glTrackMatrixNV(GL_VERTEX_PROGRAM_NV, 0, GL_MODELVIEW_PROJECTION_NV, GL_IDENTITY_NV);
310 glTrackMatrixNV(GL_VERTEX_PROGRAM_NV, 4, GL_MODELVIEW, GL_INVERSE_TRANSPOSE_NV);
311
312 /*
313 * Misc init
314 */
315 glClearColor(0.3, 0.3, 0.3, 0.0);
316 glEnable(GL_DEPTH_TEST);
317 glEnable(GL_LIGHT0);
318 glEnable(GL_LIGHTING);
319 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, Diffuse);
320 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, Specular);
321 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 20.0);
322
323 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
324 printf("Press p to toggle between per-pixel and per-vertex lighting\n");
325
326#ifdef GL_MESA_program_debug
327 glProgramCallbackMESA(GL_FRAGMENT_PROGRAM_ARB, Debugger,
328 (GLvoid *) fragProgramText);
329 glEnable(GL_FRAGMENT_PROGRAM_CALLBACK_MESA);
330#endif
331}
332
333
334int main( int argc, char *argv[] )
335{
336 glutInit( &argc, argv );
337 glutInitWindowPosition( 0, 0 );
338 glutInitWindowSize( 200, 200 );
339 glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH );
340 glutCreateWindow(argv[0]);
341 glutReshapeFunc( Reshape );
342 glutKeyboardFunc( Key );
343 glutSpecialFunc( SpecialKey );
344 glutDisplayFunc( Display );
345 if (Anim)
346 glutIdleFunc(Idle);
347 Init();
348 glutMainLoop();
349 return 0;
350}