Advertisement
Guest User

OpenGL Shadow Map

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