shadow_sampler.c revision 32001f49
1/**
2 * Test shadow2DRectProj() and shadow2D() functions.
3 * Brian Paul
4 * 11 April 2007
5 */
6
7#define GL_GLEXT_PROTOTYPES
8#include <assert.h>
9#include <string.h>
10#include <stdio.h>
11#include <stdlib.h>
12#include <math.h>
13#include <GL/glew.h>
14#include "glut_wrap.h"
15
16
17/** Use GL_RECTANGLE texture (with projective texcoords)? */
18#define USE_RECT 01
19
20#define TEXSIZE 16
21
22
23static char *FragProgFile = NULL;
24static char *VertProgFile = NULL;
25
26static GLuint fragShader;
27static GLuint vertShader;
28static GLuint program;
29
30static GLint uTexture2D;
31static GLint uTextureRect;
32
33static GLint win = 0;
34
35static GLenum Filter = GL_LINEAR;
36
37static void
38CheckError(int line)
39{
40   GLenum err = glGetError();
41   if (err) {
42      printf("GL Error %s (0x%x) at line %d\n",
43             gluErrorString(err), (int) err, line);
44   }
45}
46
47
48static void
49PrintString(const char *s)
50{
51   while (*s) {
52      glutBitmapCharacter(GLUT_BITMAP_8_BY_13, (int) *s);
53      s++;
54   }
55}
56
57
58static void
59Redisplay(void)
60{
61   CheckError(__LINE__);
62   glClear(GL_COLOR_BUFFER_BIT);
63
64   glPushMatrix();
65
66   CheckError(__LINE__);
67   glUseProgram(program);
68   CheckError(__LINE__);
69
70   glBegin(GL_POLYGON);
71#if USE_RECT
72   /* scale coords by two to test projection */
73   glTexCoord4f(        0,         0,   0, 2.0);  glVertex2f(-1, -1);
74   glTexCoord4f(2*TEXSIZE,         0, 2*1, 2.0);  glVertex2f( 1, -1);
75   glTexCoord4f(2*TEXSIZE, 2*TEXSIZE, 2*1, 2.0);  glVertex2f( 1,  1);
76   glTexCoord4f(        0, 2*TEXSIZE,   0, 2.0);  glVertex2f(-1,  1);
77#else
78   glTexCoord3f(0, 0, 0);  glVertex2f(-1, -1);
79   glTexCoord3f(1, 0, 1);  glVertex2f( 1, -1);
80   glTexCoord3f(1, 1, 1);  glVertex2f( 1,  1);
81   glTexCoord3f(0, 1, 0);  glVertex2f(-1,  1);
82#endif
83   glEnd();
84
85   glPopMatrix();
86
87   glUseProgram(0);
88   glWindowPos2iARB(80, 20);
89   PrintString("white   black   white   black");
90
91   {
92      GLfloat pix[4];
93      glReadPixels(120, 150, 1, 1, GL_RGBA, GL_FLOAT, pix);
94      printf("Pixel(120, 150): %f %f %f %f\n", pix[0], pix[1], pix[2], pix[3]);
95      glReadPixels(180, 150, 1, 1, GL_RGBA, GL_FLOAT, pix);
96      printf("Pixel(180, 150): %f %f %f %f\n", pix[0], pix[1], pix[2], pix[3]);
97      glReadPixels(220, 150, 1, 1, GL_RGBA, GL_FLOAT, pix);
98      printf("Pixel(220, 150): %f %f %f %f\n", pix[0], pix[1], pix[2], pix[3]);
99      glReadPixels(280, 150, 1, 1, GL_RGBA, GL_FLOAT, pix);
100      printf("Pixel(280, 150): %f %f %f %f\n", pix[0], pix[1], pix[2], pix[3]);
101   }
102
103   glutSwapBuffers();
104}
105
106
107static void
108Reshape(int width, int height)
109{
110   glViewport(0, 0, width, height);
111   glMatrixMode(GL_PROJECTION);
112   glLoadIdentity();
113   glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0);
114   glMatrixMode(GL_MODELVIEW);
115   glLoadIdentity();
116   glTranslatef(0.0f, 0.0f, -8.0f);
117}
118
119
120static void
121CleanUp(void)
122{
123   glDeleteShader(fragShader);
124   glDeleteShader(vertShader);
125   glDeleteProgram(program);
126   glutDestroyWindow(win);
127}
128
129
130static void
131Key(unsigned char key, int x, int y)
132{
133  (void) x;
134  (void) y;
135
136   switch(key) {
137   case 27:
138      CleanUp();
139      exit(0);
140      break;
141   }
142   glutPostRedisplay();
143}
144
145
146static void
147MakeTexture(void)
148{
149   GLfloat image[TEXSIZE][TEXSIZE];
150   GLuint i, j;
151
152   for (i = 0; i < TEXSIZE; i++) {
153      for (j = 0; j < TEXSIZE; j++) {
154         if (j < (TEXSIZE / 2)) {
155            image[i][j] = 0.25;
156         }
157         else {
158            image[i][j] = 0.75;
159         }
160      }
161   }
162
163   glActiveTexture(GL_TEXTURE0); /* unit 0 */
164   glBindTexture(GL_TEXTURE_2D, 42);
165   glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, TEXSIZE, TEXSIZE, 0,
166                GL_DEPTH_COMPONENT, GL_FLOAT, image);
167   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
168   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, Filter);
169   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, Filter);
170   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB,
171                   GL_COMPARE_R_TO_TEXTURE_ARB);
172   CheckError(__LINE__);
173
174   glActiveTexture(GL_TEXTURE1); /* unit 1 */
175   glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 43);
176   glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_DEPTH_COMPONENT,
177                TEXSIZE, 10, 0,/*16x10*/
178                GL_DEPTH_COMPONENT, GL_FLOAT, image);
179   glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, Filter);
180   glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, Filter);
181   glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_COMPARE_MODE_ARB,
182                   GL_COMPARE_R_TO_TEXTURE_ARB);
183   CheckError(__LINE__);
184}
185
186
187static void
188LoadAndCompileShader(GLuint shader, const char *text)
189{
190   GLint stat;
191   glShaderSource(shader, 1, (const GLchar **) &text, NULL);
192   glCompileShader(shader);
193   glGetShaderiv(shader, GL_COMPILE_STATUS, &stat);
194   if (!stat) {
195      GLchar log[1000];
196      GLsizei len;
197      glGetShaderInfoLog(shader, 1000, &len, log);
198      fprintf(stderr, "fslight: problem compiling shader:\n%s\n", log);
199      exit(1);
200   }
201}
202
203
204/**
205 * Read a shader from a file.
206 */
207static void
208ReadShader(GLuint shader, const char *filename)
209{
210   const int max = 100*1000;
211   int n;
212   char *buffer = (char*) malloc(max);
213   FILE *f = fopen(filename, "r");
214   if (!f) {
215      fprintf(stderr, "fslight: Unable to open shader file %s\n", filename);
216      exit(1);
217   }
218
219   n = fread(buffer, 1, max, f);
220   printf("fslight: read %d bytes from shader file %s\n", n, filename);
221   if (n > 0) {
222      buffer[n] = 0;
223      LoadAndCompileShader(shader, buffer);
224   }
225
226   fclose(f);
227   free(buffer);
228}
229
230
231static void
232CheckLink(GLuint prog)
233{
234   GLint stat;
235   glGetProgramiv(prog, GL_LINK_STATUS, &stat);
236   if (!stat) {
237      GLchar log[1000];
238      GLsizei len;
239      glGetProgramInfoLog(prog, 1000, &len, log);
240      fprintf(stderr, "Linker error:\n%s\n", log);
241   }
242}
243
244
245static void
246Init(void)
247{
248   static const char *fragShaderText =
249      "uniform sampler2DShadow shadowTex2D; \n"
250      "uniform sampler2DRectShadow shadowTexRect; \n"
251      "void main() {\n"
252#if USE_RECT
253      "   gl_FragColor = shadow2DRectProj(shadowTexRect, gl_TexCoord[0]); \n"
254#else
255      "   gl_FragColor = shadow2D(shadowTex2D, gl_TexCoord[0].xyz); \n"
256#endif
257      "}\n";
258   static const char *vertShaderText =
259      "void main() {\n"
260      "   gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
261      "   gl_TexCoord[0] = gl_MultiTexCoord0; \n"
262      "}\n";
263
264#if USE_RECT
265   if (!glutExtensionSupported("GL_ARB_texture_rectangle")) {
266      printf("This program requires GL_ARB_texture_rectangle\n");
267      exit(1);
268   }
269#endif
270
271   if (!GLEW_VERSION_2_0) {
272      printf("This program requires OpenGL 2.x\n");
273      exit(1);
274   }
275   printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER));
276
277   fragShader = glCreateShader(GL_FRAGMENT_SHADER);
278   if (FragProgFile)
279      ReadShader(fragShader, FragProgFile);
280   else
281      LoadAndCompileShader(fragShader, fragShaderText);
282
283   vertShader = glCreateShader(GL_VERTEX_SHADER);
284   if (VertProgFile)
285      ReadShader(vertShader, VertProgFile);
286   else
287      LoadAndCompileShader(vertShader, vertShaderText);
288
289   program = glCreateProgram();
290   glAttachShader(program, fragShader);
291   glAttachShader(program, vertShader);
292   glLinkProgram(program);
293   CheckLink(program);
294   glUseProgram(program);
295
296   uTexture2D = glGetUniformLocation(program, "shadowTex2D");
297   uTextureRect = glGetUniformLocation(program, "shadowTexRect");
298   printf("uTexture2D %d  uTextureRect %d\n", uTexture2D, uTextureRect);
299   if (uTexture2D >= 0) {
300      glUniform1i(uTexture2D, 0);  /* use texture unit 0 */
301   }
302   if (uTextureRect >= 0) {
303      glUniform1i(uTextureRect, 1);  /* use texture unit 0 */
304   }
305   CheckError(__LINE__);
306
307   glClearColor(0.3f, 0.3f, 0.3f, 0.0f);
308   glColor3f(1, 1, 1);
309
310   MakeTexture();
311   CheckError(__LINE__);
312}
313
314
315static void
316ParseOptions(int argc, char *argv[])
317{
318   int i;
319   for (i = 1; i < argc; i++) {
320      if (strcmp(argv[i], "-fs") == 0) {
321         FragProgFile = argv[i+1];
322      }
323      else if (strcmp(argv[i], "-vs") == 0) {
324         VertProgFile = argv[i+1];
325      }
326   }
327}
328
329
330int
331main(int argc, char *argv[])
332{
333   glutInit(&argc, argv);
334   glutInitWindowSize(400, 300);
335   glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
336   win = glutCreateWindow(argv[0]);
337   glewInit();
338   glutReshapeFunc(Reshape);
339   glutKeyboardFunc(Key);
340   glutDisplayFunc(Redisplay);
341   ParseOptions(argc, argv);
342   Init();
343   glutMainLoop();
344   return 0;
345}
346
347
348