Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #ifdef _WIN32
- #include "windows.h"
- #endif
- #include "GL/glut.h"
- #ifdef _WIN32
- #include "glext.h"
- #endif
- #include <cmath>
- #include <stdio.h>
- #ifdef _WIN32
- // As microsoft did not maintain openGL after version 1.1, Windows platform need to go throught this crap ; macosX and Linux are fine.
- // This block simply retries openGL function needed for this example.
- // I recommend to use GLEW instead of going this way. This is done this way only to ease beginner's compilation and portability
- PFNGLACTIVETEXTUREARBPROC glActiveTextureARB;
- // FrameBuffer (FBO) gen, bin and texturebind
- PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT ;
- PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT ;
- PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT ;
- PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT ;
- // Shader functions
- PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB ;
- PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB ;
- PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB ;
- PFNGLSHADERSOURCEARBPROC glShaderSourceARB ;
- PFNGLCOMPILESHADERARBPROC glCompileShaderARB ;
- PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB;
- PFNGLATTACHOBJECTARBPROC glAttachObjectARB ;
- PFNGLLINKPROGRAMARBPROC glLinkProgramARB ;
- PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB ;
- PFNGLUNIFORM1IARBPROC glUniform1iARB ;
- PFNGLUNIFORM1FARBPROC glUniform1fARB ;
- //PFNGLACTIVETEXTUREARBPROC glActiveTextureARB;
- PFNGLGETINFOLOGARBPROC glGetInfoLogARB ;
- void getOpenGLFunctionPointers(void)
- {
- // FBO
- glActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC)wglGetProcAddress("glActiveTextureARB");
- glGenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC) wglGetProcAddress("glGenFramebuffersEXT");
- glBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC) wglGetProcAddress("glBindFramebufferEXT");
- glFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)wglGetProcAddress("glFramebufferTexture2DEXT");
- glCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)wglGetProcAddress("glCheckFramebufferStatusEXT");
- //Shaders
- glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC)wglGetProcAddress("glCreateProgramObjectARB");
- glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC)wglGetProcAddress("glUseProgramObjectARB");
- glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC)wglGetProcAddress("glCreateShaderObjectARB");
- glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC)wglGetProcAddress("glShaderSourceARB");
- glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC)wglGetProcAddress("glCompileShaderARB");
- glGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC)wglGetProcAddress("glGetObjectParameterivARB");
- glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC)wglGetProcAddress("glAttachObjectARB");
- glGetInfoLogARB = (PFNGLGETINFOLOGARBPROC)wglGetProcAddress("glGetInfoLogARB");
- glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC)wglGetProcAddress("glLinkProgramARB");
- glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC)wglGetProcAddress("glGetUniformLocationARB");
- glUniform1iARB = (PFNGLUNIFORM1IARBPROC)wglGetProcAddress("glUniform1iARB");
- glUniform1fARB = (PFNGLUNIFORM1FARBPROC)wglGetProcAddress("glUniform1fARB");
- }
- #endif
- // Expressed as float so gluPerspective division returns a float and not 0 (640/480 != 640.0/480.0).
- #define RENDER_WIDTH 640.0
- #define RENDER_HEIGHT 480.0
- #define SHADOW_MAP_RATIO 2
- //Camera position
- float p_camera[3] = {35,25,5};
- //Camera lookAt
- float l_camera[3] = {0,-11,-25};
- //Light position
- float p_light[3] = {3,16,0};
- //Light lookAt
- float l_light[3] = {0,0,-5};
- //Light mouvement circle radius
- float light_mvnt = 30.0f;
- // Hold id of the framebuffer for light POV rendering
- GLuint fboId;
- // Z values will be rendered to this texture when using fboId framebuffer
- GLuint depthTextureId;
- // Use to activate/disable shadowShader
- GLhandleARB shadowShaderId;
- GLuint shadowMapUniform;
- GLuint shadowMapStepXUniform;
- GLuint shadowMapStepYUniform;
- // Loading shader function
- GLhandleARB loadShader(char* filename, unsigned int type)
- {
- FILE *pfile;
- GLhandleARB handle;
- const GLcharARB* files[1];
- // shader Compilation variable
- GLint result; // Compilation code result
- GLint errorLoglength ;
- char* errorLogText;
- GLsizei actualErrorLogLength;
- char buffer[400000];
- memset(buffer,0,400000);
- // This will raise a warning on MS compiler
- pfile = fopen(filename, "rb");
- if(!pfile)
- {
- printf("Sorry, can't open file: '%s'.\n", filename);
- exit(0);
- }
- fread(buffer,sizeof(char),400000,pfile);
- //printf("%s\n",buffer);
- fclose(pfile);
- handle = glCreateShaderObjectARB(type);
- if (!handle)
- {
- //We have failed creating the vertex shader object.
- printf("Failed creating vertex shader object from file: %s.",filename);
- exit(0);
- }
- files[0] = (const GLcharARB*)buffer;
- glShaderSourceARB(
- handle, //The handle to our shader
- 1, //The number of files.
- files, //An array of const char * data, which represents the source code of theshaders
- NULL);
- glCompileShaderARB(handle);
- //Compilation checking.
- glGetObjectParameterivARB(handle, GL_OBJECT_COMPILE_STATUS_ARB, &result);
- // If an error was detected.
- if (!result)
- {
- //We failed to compile.
- printf("Shader '%s' failed compilation.\n",filename);
- //Attempt to get the length of our error log.
- glGetObjectParameterivARB(handle, GL_OBJECT_INFO_LOG_LENGTH_ARB, &errorLoglength);
- //Create a buffer to read compilation error message
- errorLogText = (char*) malloc(sizeof(char) * errorLoglength);
- //Used to get the final length of the log.
- glGetInfoLogARB(handle, errorLoglength, &actualErrorLogLength, errorLogText);
- // Display errors.
- printf("%s\n",errorLogText);
- // Free the buffer malloced earlier
- free(errorLogText);
- }
- return handle;
- }
- void loadShadowShader()
- {
- GLhandleARB vertexShaderHandle;
- GLhandleARB fragmentShaderHandle;
- vertexShaderHandle = loadShader("VertexShader.c",GL_VERTEX_SHADER);
- fragmentShaderHandle = loadShader("FragmentShader.c",GL_FRAGMENT_SHADER);
- shadowShaderId = glCreateProgramObjectARB();
- glAttachObjectARB(shadowShaderId,vertexShaderHandle);
- glAttachObjectARB(shadowShaderId,fragmentShaderHandle);
- glLinkProgramARB(shadowShaderId);
- shadowMapUniform = glGetUniformLocationARB(shadowShaderId,"ShadowMap");
- shadowMapStepXUniform = glGetUniformLocationARB(shadowShaderId,"xPixelOffset");
- shadowMapStepYUniform = glGetUniformLocationARB(shadowShaderId,"yPixelOffset");
- }
- void generateShadowFBO()
- {
- int shadowMapWidth = RENDER_WIDTH * SHADOW_MAP_RATIO;
- int shadowMapHeight = RENDER_HEIGHT * SHADOW_MAP_RATIO;
- //GLfloat borderColor[4] = {0,0,0,0};
- GLenum FBOstatus;
- // Try to use a texture depth component
- glGenTextures(1, &depthTextureId);
- glBindTexture(GL_TEXTURE_2D, depthTextureId);
- // GL_LINEAR does not make sense for depth texture. However, next tutorial shows usage of GL_LINEAR and PCF. Using GL_NEAREST
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- // Remove artefact on the edges of the shadowmap
- glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
- glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
- // This is to allow usage of shadow2DProj function in the shader
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
- glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY);
- // No need to force GL_DEPTH_COMPONENT24, drivers usually give you the max precision if available
- glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, shadowMapWidth, shadowMapHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0);
- glBindTexture(GL_TEXTURE_2D, 0);
- // create a framebuffer object
- glGenFramebuffersEXT(1, &fboId);
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboId);
- // Instruct openGL that we won't bind a color texture with the currently binded FBO
- glDrawBuffer(GL_NONE);
- glReadBuffer(GL_NONE);
- // attach the texture to FBO depth attachment point
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,GL_TEXTURE_2D, depthTextureId, 0);
- // check FBO status
- FBOstatus = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
- if(FBOstatus != GL_FRAMEBUFFER_COMPLETE_EXT)
- printf("GL_FRAMEBUFFER_COMPLETE_EXT failed, CANNOT use FBO\n");
- // switch back to window-system-provided framebuffer
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
- }
- void setupMatrices(float position_x,float position_y,float position_z,float lookAt_x,float lookAt_y,float lookAt_z)
- {
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- gluPerspective(45,RENDER_WIDTH/RENDER_HEIGHT,10,40000);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- gluLookAt(position_x,position_y,position_z,lookAt_x,lookAt_y,lookAt_z,0,1,0);
- }
- // This update only change the position of the light.
- //int elapsedTimeCounter = 0;
- void update(void)
- {
- //printf("%d\n",glutGet(GLUT_ELAPSED_TIME));
- p_light[0] = light_mvnt * cos(glutGet(GLUT_ELAPSED_TIME)/2000.0);
- p_light[2] = light_mvnt * sin(glutGet(GLUT_ELAPSED_TIME)/2000.0);
- //p_light[0] = light_mvnt * cos(4000/1000.0);
- //p_light[2] = light_mvnt * sin(4000/1000.0);
- //p_light[0] = light_mvnt * cos(3000/1000.0);
- //p_light[2] = light_mvnt * sin(3000/1000.0);
- }
- void setTextureMatrix(void)
- {
- static double modelView[16];
- static double projection[16];
- // This is matrix transform every coordinate x,y,z
- // x = x* 0.5 + 0.5
- // y = y* 0.5 + 0.5
- // z = z* 0.5 + 0.5
- // Moving from unit cube [-1,1] to [0,1]
- const GLdouble bias[16] = {
- 0.5, 0.0, 0.0, 0.0,
- 0.0, 0.5, 0.0, 0.0,
- 0.0, 0.0, 0.5, 0.0,
- 0.5, 0.5, 0.5, 1.0};
- // Grab modelview and transformation matrices
- glGetDoublev(GL_MODELVIEW_MATRIX, modelView);
- glGetDoublev(GL_PROJECTION_MATRIX, projection);
- glMatrixMode(GL_TEXTURE);
- glActiveTextureARB(GL_TEXTURE7);
- glLoadIdentity();
- glLoadMatrixd(bias);
- // concatating all matrice into one.
- glMultMatrixd (projection);
- glMultMatrixd (modelView);
- // Go back to normal matrix mode
- glMatrixMode(GL_MODELVIEW);
- }
- // During translation, we also have to maintain the GL_TEXTURE8, used in the shadow shader
- // to determine if a vertex is in the shadow.
- void startTranslate(float x,float y,float z)
- {
- glPushMatrix();
- glTranslatef(x,y,z);
- glMatrixMode(GL_TEXTURE);
- glActiveTextureARB(GL_TEXTURE7);
- glPushMatrix();
- glTranslatef(x,y,z);
- }
- void endTranslate()
- {
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
- }
- void drawObjects(void)
- {
- // Ground
- glColor4f(0.3f,0.3f,0.3f,1);
- glBegin(GL_QUADS);
- glVertex3f(-45,2,-45);
- glVertex3f(-45,2, 55);
- glVertex3f( 55,2, 55);
- glVertex3f( 55,2,-45);
- glEnd();
- glColor4f(0.9f,0.9f,0.9f,1);
- // Instead of calling glTranslatef, we need a custom function that also maintain the light matrix
- startTranslate(0,4,-16);
- glutSolidCube(4);
- endTranslate();
- startTranslate(0,4,-5);
- //glutSolidCube(4);
- glutSolidSphere(4,40,40);
- endTranslate();
- }
- void renderScene(void)
- {
- update();
- //First step: Render from the light POV to a FBO, story depth values only
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,fboId); //Rendering offscreen
- //Using the fixed pipeline to render to the depthbuffer
- glUseProgramObjectARB(0);
- // In the case we render the shadowmap to a higher resolution, the viewport must be modified accordingly.
- glViewport(0,0,RENDER_WIDTH * SHADOW_MAP_RATIO,RENDER_HEIGHT* SHADOW_MAP_RATIO);
- // Clear previous frame values
- glClear( GL_DEPTH_BUFFER_BIT);
- //Disable color rendering, we only want to write to the Z-Buffer
- glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
- setupMatrices(p_light[0],p_light[1],p_light[2],l_light[0],l_light[1],l_light[2]);
- // Culling switching, rendering only backface, this is done to avoid self-shadowing
- glCullFace(GL_FRONT);
- drawObjects();
- //Save modelview/projection matrice into texture7, also add a biais
- setTextureMatrix();
- // Now rendering from the camera POV, using the FBO to generate shadows
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,0);
- glViewport(0,0,RENDER_WIDTH,RENDER_HEIGHT);
- //Enabling color write (previously disabled for light POV z-buffer rendering)
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- // Clear previous frame values
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- //Using the shadow shader
- glUseProgramObjectARB(shadowShaderId);
- glUniform1iARB(shadowMapUniform,7);
- glUniform1fARB(shadowMapStepXUniform,1.0/ (RENDER_WIDTH * SHADOW_MAP_RATIO));
- glUniform1fARB(shadowMapStepYUniform,1.0/ (RENDER_HEIGHT * SHADOW_MAP_RATIO));
- glActiveTextureARB(GL_TEXTURE7);
- glBindTexture(GL_TEXTURE_2D,depthTextureId);
- setupMatrices(p_camera[0],p_camera[1],p_camera[2],l_camera[0],l_camera[1],l_camera[2]);
- glCullFace(GL_BACK);
- drawObjects();
- // DEBUG only. this piece of code draw the depth buffer onscreen
- /*
- glUseProgramObjectARB(0);
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glOrtho(-RENDER_WIDTH/2,RENDER_WIDTH/2,-RENDER_HEIGHT/2,RENDER_HEIGHT/2,1,20);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- glColor4f(1,1,1,1);
- glActiveTextureARB(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D,depthTextureId);
- glEnable(GL_TEXTURE_2D);
- glTranslated(0,0,-1);
- glBegin(GL_QUADS);
- glTexCoord2d(0,0);glVertex3f(0,0,0);
- glTexCoord2d(1,0);glVertex3f(RENDER_WIDTH/2,0,0);
- glTexCoord2d(1,1);glVertex3f(RENDER_WIDTH/2,RENDER_HEIGHT/2,0);
- glTexCoord2d(0,1);glVertex3f(0,RENDER_HEIGHT/2,0);
- glEnd();
- glDisable(GL_TEXTURE_2D);
- */
- glutSwapBuffers();
- }
- void processNormalKeys(unsigned char key, int x, int y) {
- if (key == 27)
- exit(0);
- }
- int main(int argc, char** argv)
- {
- glutInit(&argc, argv);
- glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH);
- glutInitWindowPosition(100,100);
- glutInitWindowSize(RENDER_WIDTH,RENDER_HEIGHT);
- glutCreateWindow("GLSL Shadow mapping");
- // This call will grab openGL extension function pointers.
- // This is not necessary for macosx and linux
- #ifdef _WIN32
- getOpenGLFunctionPointers();
- #endif
- generateShadowFBO();
- loadShadowShader();
- // This is important, if not here, FBO's depthbuffer won't be populated.
- glEnable(GL_DEPTH_TEST);
- glClearColor(0,0,0,1.0f);
- glEnable(GL_CULL_FACE);
- glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
- glutDisplayFunc(renderScene);
- glutIdleFunc(renderScene);
- glutKeyboardFunc(processNormalKeys);
- glutMainLoop();
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement