Advertisement
Guest User

OpenGL shadow map example

a guest
Jul 27th, 2013
142
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <math.h>
  5. #include <sys/time.h>
  6.  
  7. #define GL_GLEXT_PROTOTYPES
  8. #include <GL/gl.h>
  9. #include <GL/glu.h>
  10. #include <GL/glut.h>
  11.  
  12. float light_position[4]  = {0.5, 0.5, 1.0, 1.0};
  13. float light_ambient [4]  = {0.0, 0.0, 0.0, 1.0};
  14. float light_diffuse [4]  = {1.0, 1.0, 1.0, 1.0};
  15. float light_specular[4]  = {1.0, 1.0, 1.0, 1.0};
  16.  
  17. float lightFOV_ = 90.0;
  18. float lightNear_ = 0.1;
  19. float lightFar_ = 20.0;
  20.  
  21. float material_emission[4]  = {0.0, 0.0, 0.0, 1.0};
  22. float material_ambient [4]  = {0.2, 0.6, 0.2, 1.0};
  23. float material_diffuse [4]  = {0.2, 0.6, 0.2, 1.0};
  24. float material_specular[4]  = {0.3, 0.3, 0.3, 1.0};
  25. float material_shininess = 50.0;
  26.  
  27. #define W 512
  28. #define H 512
  29.  
  30. #define R 20
  31. #define N (2 * R + 1)
  32.  
  33. GLuint indices[N-1][N-1][4];
  34.  
  35. int width = 1;
  36. int height = 1;
  37. int key_state[0x100];
  38. double last = -1.0;
  39. float lightPos_[4] = {0.5, 0.5, 1.0, 1.0};
  40.  
  41. GLuint shadowmap_, renderbuffer_, framebuffer_;
  42.  
  43. void make_data(void)
  44. {
  45.     float k = 0.1;
  46.  
  47.     static float verts[N][N][3];
  48.     static float norms[N][N][3];
  49.     for (int j = 0; j < N; j++) {
  50.     for (int i = 0; i < N; i++) {
  51.         float x = 1.5 * (i / (float) R - 1.0);
  52.         float y = 1.5 * (j / (float) R - 1.0);
  53.         float d = x * x + y * y + k;
  54.         float z = k / d - 2.0;
  55.         verts[j][i][0] = x;
  56.         verts[j][i][1] = y;
  57.         verts[j][i][2] = z;
  58.         float d2 = d * d;
  59.         float dx = 2 * k * x / d2;
  60.         float dy = 2 * k * y / d2;
  61.         float dz = 1.0;
  62.         float m = sqrt(dx * dx + dy * dy + dz * dz);
  63.         norms[j][i][0] = dx / m;
  64.         norms[j][i][1] = dy / m;
  65.         norms[j][i][2] = dz / m;
  66.     }
  67.     }
  68.  
  69.     glVertexPointer(3, GL_FLOAT, 0, (const GLvoid *) verts);
  70.     glNormalPointer(GL_FLOAT, 0, (const GLvoid *) norms);
  71.     glEnableClientState(GL_VERTEX_ARRAY);
  72.     glEnableClientState(GL_NORMAL_ARRAY);
  73.  
  74.     for (int j = 0; j < N-1; j++) {
  75.     for (int i = 0; i < N-1; i++) {
  76.         GLuint base = j * N + i;
  77.         indices[j][i][0] = base;
  78.         indices[j][i][1] = base + N;
  79.         indices[j][i][2] = base + N + 1;
  80.         indices[j][i][3] = base + 1;
  81.     }
  82.     }
  83. }
  84.  
  85. void dump(void)
  86. {
  87.     unsigned char surface[H][W][3];
  88.  
  89.     glReadPixels(0, 0, H, W, GL_RGB, GL_UNSIGNED_BYTE, surface);
  90.     FILE *fp = fopen("dump.ppm","wb");
  91.     fprintf(fp, "P6\n%d %d\n255\n", W, H);
  92.     fwrite(surface, W * 3, H, fp);
  93.     fclose(fp);
  94. }
  95.  
  96. void swap(float m[16], int i, int j)
  97. {
  98.     float mi = m[i];
  99.     m[i] = m[j];
  100.     m[j] = mi;
  101. }
  102.  
  103. void transposeMatrix16(float m[16])
  104. {
  105.     swap(m, 1, 4);
  106.     swap(m, 2, 8);
  107.     swap(m, 3,12);
  108.     swap(m, 6, 9);
  109.     swap(m, 7,13);
  110.     swap(m,11,14);
  111. }
  112.  
  113. const char *error(void)
  114. {
  115.     GLenum status = glGetError();
  116.  
  117.     switch (status)
  118.     {
  119.     case GL_NO_ERROR:       return NULL;
  120.     case GL_INVALID_ENUM:   return "Invalid Enum";
  121.     case GL_INVALID_VALUE:  return "Invalid Value";
  122.     case GL_INVALID_OPERATION:  return "Invalid Operation";
  123.     case GL_STACK_OVERFLOW: return "Stack Overflow";
  124.     case GL_STACK_UNDERFLOW:    return "Stack Underflow";
  125.     case GL_OUT_OF_MEMORY:  return "Out of Memory";
  126.     default:            return "Unknown Error";
  127.     }
  128. }
  129.  
  130. void check(void)
  131. {
  132.     for (;;) {
  133.     const char *msg = error();
  134.     if (!msg)
  135.         break;
  136.     fputs(msg, stderr);
  137.     }
  138. }
  139.  
  140. void init(void)
  141. {
  142.     glFrontFace(GL_CCW);
  143.     //glEnable(GL_CULL_FACE);
  144.  
  145.     glEnable(GL_DEPTH_TEST);
  146.     glDepthFunc(GL_LEQUAL);
  147.  
  148.     glEnable(GL_LIGHTING);
  149.  
  150.     glMaterialfv(GL_FRONT, GL_EMISSION,  material_emission);
  151.     glMaterialfv(GL_FRONT, GL_AMBIENT,   material_ambient);
  152.     glMaterialfv(GL_FRONT, GL_DIFFUSE,   material_diffuse);
  153.     glMaterialfv(GL_FRONT, GL_SPECULAR,  material_specular);
  154.     glMaterialf( GL_FRONT, GL_SHININESS, material_shininess);
  155.  
  156.     glLightfv(GL_LIGHT0, GL_AMBIENT,  light_ambient);
  157.     glLightfv(GL_LIGHT0, GL_DIFFUSE,  light_diffuse);
  158.     glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
  159.  
  160.     glEnable(GL_LIGHT0);
  161.  
  162.     make_data();
  163.  
  164.     glGenTextures(1, &shadowmap_);
  165.     glBindTexture(GL_TEXTURE_2D, shadowmap_);
  166.     glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, W, H, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
  167.  
  168.     glGenRenderbuffers(1, &renderbuffer_);
  169.     glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer_);
  170.     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA, W, H);
  171.  
  172.     glGenFramebuffers(1, &framebuffer_);
  173.     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer_);
  174.     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer_);
  175.     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadowmap_, 0);
  176.  
  177.     GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
  178.     if (status != GL_FRAMEBUFFER_COMPLETE) {
  179.     fprintf(stderr, "framebuffer fail\n");
  180.     exit(1);
  181.     }
  182.  
  183.     glBindFramebuffer(GL_FRAMEBUFFER, 0);
  184.  
  185.     check();
  186. }
  187.  
  188. void renderSceneElements(void)
  189. {
  190.     glDrawElements(GL_QUADS, (N-1)*(N-1)*4, GL_UNSIGNED_INT, (const GLvoid*) indices);
  191. }
  192.  
  193. void draw(void)
  194. {
  195.     double lightAspect_ = 1.0 * width / height;
  196.  
  197.     // position the light
  198.     glLightfv(GL_LIGHT0, GL_POSITION, lightPos_);
  199.  
  200.     // switch the framebuffer for the first pass
  201.     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer_);
  202.     glViewport(0, 0, W, H);
  203.     glClearColor(0.5, 0.2, 0.1, 1.0f);
  204.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  205.  
  206.  
  207.     // set up the projection parameters from the light's POV
  208.     glMatrixMode(GL_PROJECTION);
  209.     glPushMatrix();
  210.     glLoadIdentity();
  211.     gluPerspective(lightFOV_, lightAspect_, lightNear_, lightFar_);
  212.  
  213.     glMatrixMode(GL_MODELVIEW);
  214.     glPushMatrix();
  215.     glLoadIdentity();
  216.     // translate to the light's position
  217.     gluLookAt(lightPos_[0], lightPos_[1], lightPos_[2], 0.0, 0.0, -2.0, 0.0, 1.0, 0.0);
  218.  
  219.     // render the scene to get the depth information
  220.     renderSceneElements();
  221.     glPopMatrix();
  222.  
  223.     // end the projection modification
  224.     glMatrixMode(GL_PROJECTION);
  225.     glPopMatrix();
  226.     glMatrixMode(GL_MODELVIEW);
  227.  
  228.     // switch back to the system framebuffer for the second pass
  229.     glBindFramebuffer(GL_FRAMEBUFFER, 0);
  230.     glClearColor(1,1,1,1);
  231.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  232.     glViewport(0, 0, W, H);
  233.  
  234.     // matrix defining the planes for S, T, R, Q components for texture generation
  235.     float planeMatrix[16];
  236.     glPushMatrix();
  237.     glLoadIdentity();
  238.     // compensate for the eye-coordinate to texture coordinate conversion: [-1,1] to [0,1]
  239.     glTranslatef(0.5f, 0.5f, 0.499f);
  240.     glScalef(0.5f, 0.5f, 0.5f);
  241.  
  242.     // do the perspective projection and translate to the light's position
  243.     gluPerspective(lightFOV_, lightAspect_, lightNear_, lightFar_);
  244.     gluLookAt(lightPos_[0], lightPos_[1], lightPos_[2], 0.0, 0.0, -2.0, 0.0, 1.0, 0.0);
  245.  
  246.     glGetFloatv(GL_MODELVIEW_MATRIX, planeMatrix);
  247.     glPopMatrix();
  248.  
  249.     // go from OpenGL's column-major to row-major matrix form
  250.     transposeMatrix16(planeMatrix);
  251.  
  252.     // set up the type for texture generation
  253.     glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
  254.     glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
  255.     glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
  256.     glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
  257.  
  258.     // data for texture generation
  259.     glTexGenfv(GL_S, GL_OBJECT_PLANE, &planeMatrix[0]);
  260.     glTexGenfv(GL_T, GL_OBJECT_PLANE, &planeMatrix[4]);
  261.     glTexGenfv(GL_R, GL_OBJECT_PLANE, &planeMatrix[8]);
  262.     glTexGenfv(GL_Q, GL_OBJECT_PLANE, &planeMatrix[12]);
  263.  
  264.     glEnable(GL_TEXTURE_GEN_S);
  265.     glEnable(GL_TEXTURE_GEN_T);
  266.     glEnable(GL_TEXTURE_GEN_R);
  267.     glEnable(GL_TEXTURE_GEN_Q);
  268.  
  269.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  270.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  271.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  272.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  273.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
  274.     glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE);
  275.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
  276.  
  277.     glEnable(GL_TEXTURE_2D);
  278.     glBindTexture(GL_TEXTURE_2D, shadowmap_);
  279.  
  280.     glEnable(GL_LIGHTING);
  281.     glEnable(GL_LIGHT0);
  282.  
  283.     renderSceneElements();
  284.  
  285.     glDisable(GL_LIGHTING);
  286.     glDisable(GL_LIGHT0);
  287.  
  288.     glDisable(GL_TEXTURE_2D);
  289.  
  290.     glDisable(GL_TEXTURE_GEN_Q);
  291.     glDisable(GL_TEXTURE_GEN_R);
  292.     glDisable(GL_TEXTURE_GEN_T);
  293.     glDisable(GL_TEXTURE_GEN_S);
  294.  
  295.     glutSwapBuffers();
  296. }
  297.  
  298. void key(unsigned char key, int x, int y)
  299. {
  300.     if (key == '\033')
  301.     exit(0);
  302. }
  303.  
  304. void special(int k, int x, int y)
  305. {
  306.     if (k == GLUT_KEY_HOME)
  307.     memcpy(lightPos_, light_position, sizeof(lightPos_));
  308.     key_state[k] = 1;
  309.     glutPostRedisplay();
  310. }
  311.  
  312. void special_up(int k, int x, int y)
  313. {
  314.     key_state[k] = 0;
  315.     glutPostRedisplay();
  316. }
  317.  
  318. void idle(void)
  319. {
  320.     struct timeval tv;
  321.     gettimeofday(&tv, NULL);
  322.     double now = tv.tv_sec + tv.tv_usec * 1.0e-6;
  323.  
  324.     if (last <= 0)
  325.         last = now;
  326.     double t = now - last;
  327.     last = now;
  328.  
  329.     double move = 1.0;
  330.  
  331.     for (int k = 0; k < 0x100; k++) {
  332.         if (!key_state[k])
  333.             continue;
  334.         if (k == GLUT_KEY_LEFT)      lightPos_[0] -= move * t;
  335.         if (k == GLUT_KEY_RIGHT)     lightPos_[0] += move * t;
  336.         if (k == GLUT_KEY_DOWN)      lightPos_[1] -= move * t;
  337.         if (k == GLUT_KEY_UP)        lightPos_[1] += move * t;
  338.         if (k == GLUT_KEY_PAGE_DOWN) lightPos_[2] -= move * t;
  339.         if (k == GLUT_KEY_PAGE_UP)   lightPos_[2] += move * t;
  340.     }
  341.  
  342.     glutPostRedisplay();
  343. }
  344.  
  345. void resize(int w, int h)
  346. {
  347.     if (h == 0)
  348.         h = 1;
  349.  
  350.     width = w;
  351.     height = h;
  352.  
  353.     glViewport(0, 0, w, h);
  354.     glPushAttrib(GL_TRANSFORM_BIT);
  355.     glMatrixMode(GL_PROJECTION);
  356.     glLoadIdentity();
  357.     gluPerspective(lightFOV_, 1.0 * w / h, lightNear_, lightFar_);
  358.     glPopAttrib();
  359. }
  360.  
  361. int main(int argc, char **argv)
  362. {
  363.     glutInit(&argc, argv);
  364.  
  365.     glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
  366.     glutInitWindowSize(W, H);
  367.  
  368.     glutCreateWindow("Shadow map");
  369.  
  370.     glutDisplayFunc(draw);
  371.     glutReshapeFunc(resize);
  372.     glutKeyboardFunc(key);
  373.     glutSpecialFunc(special);
  374.     glutSpecialUpFunc(special_up);
  375.     glutIdleFunc(idle);
  376.  
  377.     init();
  378.  
  379.     glutMainLoop();
  380.  
  381.     return 0;
  382. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement