Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <math.h>
- #include <sys/time.h>
- #define GL_GLEXT_PROTOTYPES
- #include <GL/gl.h>
- #include <GL/glu.h>
- #include <GL/glut.h>
- float light_position[4] = {0.5, 0.5, 1.0, 1.0};
- float light_ambient [4] = {0.0, 0.0, 0.0, 1.0};
- float light_diffuse [4] = {1.0, 1.0, 1.0, 1.0};
- float light_specular[4] = {1.0, 1.0, 1.0, 1.0};
- float lightFOV_ = 90.0;
- float lightNear_ = 0.1;
- float lightFar_ = 20.0;
- float material_emission[4] = {0.0, 0.0, 0.0, 1.0};
- float material_ambient [4] = {0.2, 0.6, 0.2, 1.0};
- float material_diffuse [4] = {0.2, 0.6, 0.2, 1.0};
- float material_specular[4] = {0.3, 0.3, 0.3, 1.0};
- float material_shininess = 50.0;
- #define W 512
- #define H 512
- #define R 20
- #define N (2 * R + 1)
- GLuint indices[N-1][N-1][4];
- int width = 1;
- int height = 1;
- int key_state[0x100];
- double last = -1.0;
- float lightPos_[4] = {0.5, 0.5, 1.0, 1.0};
- GLuint shadowmap_, renderbuffer_, framebuffer_;
- void make_data(void)
- {
- float k = 0.1;
- static float verts[N][N][3];
- static float norms[N][N][3];
- for (int j = 0; j < N; j++) {
- for (int i = 0; i < N; i++) {
- float x = 1.5 * (i / (float) R - 1.0);
- float y = 1.5 * (j / (float) R - 1.0);
- float d = x * x + y * y + k;
- float z = k / d - 2.0;
- verts[j][i][0] = x;
- verts[j][i][1] = y;
- verts[j][i][2] = z;
- float d2 = d * d;
- float dx = 2 * k * x / d2;
- float dy = 2 * k * y / d2;
- float dz = 1.0;
- float m = sqrt(dx * dx + dy * dy + dz * dz);
- norms[j][i][0] = dx / m;
- norms[j][i][1] = dy / m;
- norms[j][i][2] = dz / m;
- }
- }
- glVertexPointer(3, GL_FLOAT, 0, (const GLvoid *) verts);
- glNormalPointer(GL_FLOAT, 0, (const GLvoid *) norms);
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_NORMAL_ARRAY);
- for (int j = 0; j < N-1; j++) {
- for (int i = 0; i < N-1; i++) {
- GLuint base = j * N + i;
- indices[j][i][0] = base;
- indices[j][i][1] = base + N;
- indices[j][i][2] = base + N + 1;
- indices[j][i][3] = base + 1;
- }
- }
- }
- void dump(void)
- {
- unsigned char surface[H][W][3];
- glReadPixels(0, 0, H, W, GL_RGB, GL_UNSIGNED_BYTE, surface);
- FILE *fp = fopen("dump.ppm","wb");
- fprintf(fp, "P6\n%d %d\n255\n", W, H);
- fwrite(surface, W * 3, H, fp);
- fclose(fp);
- }
- void swap(float m[16], int i, int j)
- {
- float mi = m[i];
- m[i] = m[j];
- m[j] = mi;
- }
- void transposeMatrix16(float m[16])
- {
- swap(m, 1, 4);
- swap(m, 2, 8);
- swap(m, 3,12);
- swap(m, 6, 9);
- swap(m, 7,13);
- swap(m,11,14);
- }
- const char *error(void)
- {
- GLenum status = glGetError();
- switch (status)
- {
- case GL_NO_ERROR: return NULL;
- case GL_INVALID_ENUM: return "Invalid Enum";
- case GL_INVALID_VALUE: return "Invalid Value";
- case GL_INVALID_OPERATION: return "Invalid Operation";
- case GL_STACK_OVERFLOW: return "Stack Overflow";
- case GL_STACK_UNDERFLOW: return "Stack Underflow";
- case GL_OUT_OF_MEMORY: return "Out of Memory";
- default: return "Unknown Error";
- }
- }
- void check(void)
- {
- for (;;) {
- const char *msg = error();
- if (!msg)
- break;
- fputs(msg, stderr);
- }
- }
- void init(void)
- {
- glFrontFace(GL_CCW);
- //glEnable(GL_CULL_FACE);
- glEnable(GL_DEPTH_TEST);
- glDepthFunc(GL_LEQUAL);
- glEnable(GL_LIGHTING);
- glMaterialfv(GL_FRONT, GL_EMISSION, material_emission);
- glMaterialfv(GL_FRONT, GL_AMBIENT, material_ambient);
- glMaterialfv(GL_FRONT, GL_DIFFUSE, material_diffuse);
- glMaterialfv(GL_FRONT, GL_SPECULAR, material_specular);
- glMaterialf( GL_FRONT, GL_SHININESS, material_shininess);
- glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
- glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
- glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
- glEnable(GL_LIGHT0);
- make_data();
- glGenTextures(1, &shadowmap_);
- glBindTexture(GL_TEXTURE_2D, shadowmap_);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, W, H, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
- glGenRenderbuffers(1, &renderbuffer_);
- glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer_);
- glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA, W, H);
- glGenFramebuffers(1, &framebuffer_);
- glBindFramebuffer(GL_FRAMEBUFFER, framebuffer_);
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer_);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadowmap_, 0);
- GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
- if (status != GL_FRAMEBUFFER_COMPLETE) {
- fprintf(stderr, "framebuffer fail\n");
- exit(1);
- }
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
- check();
- }
- void renderSceneElements(void)
- {
- glDrawElements(GL_QUADS, (N-1)*(N-1)*4, GL_UNSIGNED_INT, (const GLvoid*) indices);
- }
- void draw(void)
- {
- double lightAspect_ = 1.0 * width / height;
- // position the light
- glLightfv(GL_LIGHT0, GL_POSITION, lightPos_);
- // switch the framebuffer for the first pass
- glBindFramebuffer(GL_FRAMEBUFFER, framebuffer_);
- glViewport(0, 0, W, H);
- glClearColor(0.5, 0.2, 0.1, 1.0f);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- // set up the projection parameters from the light's POV
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glLoadIdentity();
- gluPerspective(lightFOV_, lightAspect_, lightNear_, lightFar_);
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glLoadIdentity();
- // translate to the light's position
- gluLookAt(lightPos_[0], lightPos_[1], lightPos_[2], 0.0, 0.0, -2.0, 0.0, 1.0, 0.0);
- // render the scene to get the depth information
- renderSceneElements();
- glPopMatrix();
- // end the projection modification
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- // switch back to the system framebuffer for the second pass
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
- glClearColor(1,1,1,1);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- glViewport(0, 0, W, H);
- // matrix defining the planes for S, T, R, Q components for texture generation
- float planeMatrix[16];
- glPushMatrix();
- glLoadIdentity();
- // compensate for the eye-coordinate to texture coordinate conversion: [-1,1] to [0,1]
- glTranslatef(0.5f, 0.5f, 0.499f);
- glScalef(0.5f, 0.5f, 0.5f);
- // do the perspective projection and translate to the light's position
- gluPerspective(lightFOV_, lightAspect_, lightNear_, lightFar_);
- gluLookAt(lightPos_[0], lightPos_[1], lightPos_[2], 0.0, 0.0, -2.0, 0.0, 1.0, 0.0);
- glGetFloatv(GL_MODELVIEW_MATRIX, planeMatrix);
- glPopMatrix();
- // go from OpenGL's column-major to row-major matrix form
- transposeMatrix16(planeMatrix);
- // set up the type for texture generation
- glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
- glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
- glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
- glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
- // data for texture generation
- glTexGenfv(GL_S, GL_OBJECT_PLANE, &planeMatrix[0]);
- glTexGenfv(GL_T, GL_OBJECT_PLANE, &planeMatrix[4]);
- glTexGenfv(GL_R, GL_OBJECT_PLANE, &planeMatrix[8]);
- glTexGenfv(GL_Q, GL_OBJECT_PLANE, &planeMatrix[12]);
- glEnable(GL_TEXTURE_GEN_S);
- glEnable(GL_TEXTURE_GEN_T);
- glEnable(GL_TEXTURE_GEN_R);
- glEnable(GL_TEXTURE_GEN_Q);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
- glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
- glEnable(GL_TEXTURE_2D);
- glBindTexture(GL_TEXTURE_2D, shadowmap_);
- glEnable(GL_LIGHTING);
- glEnable(GL_LIGHT0);
- renderSceneElements();
- glDisable(GL_LIGHTING);
- glDisable(GL_LIGHT0);
- glDisable(GL_TEXTURE_2D);
- glDisable(GL_TEXTURE_GEN_Q);
- glDisable(GL_TEXTURE_GEN_R);
- glDisable(GL_TEXTURE_GEN_T);
- glDisable(GL_TEXTURE_GEN_S);
- glutSwapBuffers();
- }
- void key(unsigned char key, int x, int y)
- {
- if (key == '\033')
- exit(0);
- }
- void special(int k, int x, int y)
- {
- if (k == GLUT_KEY_HOME)
- memcpy(lightPos_, light_position, sizeof(lightPos_));
- key_state[k] = 1;
- glutPostRedisplay();
- }
- void special_up(int k, int x, int y)
- {
- key_state[k] = 0;
- glutPostRedisplay();
- }
- void idle(void)
- {
- struct timeval tv;
- gettimeofday(&tv, NULL);
- double now = tv.tv_sec + tv.tv_usec * 1.0e-6;
- if (last <= 0)
- last = now;
- double t = now - last;
- last = now;
- double move = 1.0;
- for (int k = 0; k < 0x100; k++) {
- if (!key_state[k])
- continue;
- if (k == GLUT_KEY_LEFT) lightPos_[0] -= move * t;
- if (k == GLUT_KEY_RIGHT) lightPos_[0] += move * t;
- if (k == GLUT_KEY_DOWN) lightPos_[1] -= move * t;
- if (k == GLUT_KEY_UP) lightPos_[1] += move * t;
- if (k == GLUT_KEY_PAGE_DOWN) lightPos_[2] -= move * t;
- if (k == GLUT_KEY_PAGE_UP) lightPos_[2] += move * t;
- }
- glutPostRedisplay();
- }
- void resize(int w, int h)
- {
- if (h == 0)
- h = 1;
- width = w;
- height = h;
- glViewport(0, 0, w, h);
- glPushAttrib(GL_TRANSFORM_BIT);
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- gluPerspective(lightFOV_, 1.0 * w / h, lightNear_, lightFar_);
- glPopAttrib();
- }
- int main(int argc, char **argv)
- {
- glutInit(&argc, argv);
- glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
- glutInitWindowSize(W, H);
- glutCreateWindow("Shadow map");
- glutDisplayFunc(draw);
- glutReshapeFunc(resize);
- glutKeyboardFunc(key);
- glutSpecialFunc(special);
- glutSpecialUpFunc(special_up);
- glutIdleFunc(idle);
- init();
- glutMainLoop();
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement