analysis of ShadowMapping Sample with GLSL
来源:互联网 发布:手绘板绘图软件 编辑:程序博客网 时间:2024/04/29 20:56
This example is from http://www.fabiensanglard.net/shadowmapping/index.php
#ifdef _WIN32
#include "windows.h"
#endif
#include "GLUT/glut.h"
#ifdef _WIN32
#include "glext.h"
#endif
#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 ;
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");
}
#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] = {32,20,0};
//Camera lookAt
float l_camera[3] = {2,0,-10};
//Light position
float p_light[3] = {3,20,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;
// 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 = 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);
// get locatin of uniform variable in fragment shader
shadowMapUniform = glGetUniformLocationARB(shadowShaderId,"ShadowMap");
}
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
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 );
//glTexParameterfv( GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor );
// 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)
{
p_light[0] = light_mvnt * cos(glutGet(GLUT_ELAPSED_TIME)/1000.0);
p_light[2] = light_mvnt * sin(glutGet(GLUT_ELAPSED_TIME)/1000.0);
//p_light[0] = light_mvnt * cos(3652/1000.0);
//p_light[2] = light_mvnt * sin(3652/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] = { // transform [-1, 1] to [0, 1]
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); // 切换到texture matrix stack
glActiveTextureARB(GL_TEXTURE7); // 激活 Texture7
// save (bias * project * modelview) product of below matrices into 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(-35,2,-35);
glVertex3f(-35,2, 15);
glVertex3f( 15,2, 15);
glVertex3f( 15,2,-35);
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);
endTranslate();
}
void renderScene(void)
{
update();
// render to depth to texture(depthTextureId)
//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, only render depth
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
// 建立以光源位置和方向向量为向量基确定的light_modelviewmatrix 和
// light_projectmatrix in setupMatrices
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(); // save T = biasM * light_ProjM * light_ModelViewM into texture7
// 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)
// enable color render
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);
// Specify the value of a uniform variable for the current program object
glUniform1iARB(shadowMapUniform, 7);
glActiveTextureARB(GL_TEXTURE7);
// bind texture object (depthTextureId) into texture unit 7, sampler will sample from
// texture7 by above glUniform1iARB(shadowMapUniform, 7);
glBindTexture(GL_TEXTURE_2D, depthTextureId);
// 建立相机的modelview_matrix 和 project_matrix
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();
}
// VertexShader.c
// Used for shadow lookup
varying vec4 ShadowCoord;
void main()
{
// the texture Matrix ( bias * light_project_matrix * light_modelview_matrix ) was saved into texture7
// here we got it.
// calc its coord in light of light_space
ShadowCoord= gl_TextureMatrix[7] * gl_Vertex;
gl_Position = ftransform();
gl_FrontColor = gl_Color;
}
// FragmentShader.c
uniform sampler2D ShadowMap; // texture7 sampler by set above glUniform1iARB(shadowMapUniform, 7);
varying vec4 ShadowCoord;
void main()
{
// do perspective division against vertex coord based light_space.
vec4 shadowCoordinateWdivide = ShadowCoord / ShadowCoord.w ;
// Used to lower moiré pattern and self-shadowing
shadowCoordinateWdivide.z += 0.0005;
// get depth rendered from sampler
float distanceFromLight = texture2D(ShadowMap,shadowCoordinateWdivide.st).z;
float shadow = 1.0;
if (ShadowCoord.w > 0.0) // determine color factor in light of depth value comparision.
shadow = distanceFromLight < shadowCoordinateWdivide.z ? 0.5 : 1.0 ;
gl_FragColor = shadow * gl_Color;
}
- analysis of ShadowMapping Sample with GLSL
- SHADOWMAPPING与GLSL
- An Overview of Survival Analysis using Complex Sample Data
- Main Steps of Antenna Analysis with HFSS
- My Fluid Simulation (SPH) Sample (3) – Optical Effects using GLSL, and Integration of Physical Model
- Implementation with OpenKnowledge Stage1 – Analysis of Chii`s work
- Big Data : Analysis of problems with traditional architecture
- Sequence of shopping carts in-depth analysis with R(1)
- Analysis of Drifting Dynamics with Neural Network Hidden Markov Models
- Using GLSL with SDL
- BUMPMAPPING WITH GLSL
- Unity ShadowMapping
- Sequence of shopping carts in-depth analysis with R(3)– Sequence of events
- JMS sample with glassfish
- lingo sample code for liveness analysis
- Android Input Method Sample Code Analysis
- Usage sample of unix signal to handle function call with a timeout value.
- Lighting with GLSL Phong Model
- usb_control_msg
- 10月15日面试之某华
- 初学Linux_Ubuntu 13.04安装与配置
- java项目打包(尤其用到fatjar插件)
- Error while registering Oracle JDBC Diagnosability MBean.
- analysis of ShadowMapping Sample with GLSL
- Hibernate--hibernate.hbm2ddl.auto配置详解
- android adb shell 命令大全
- flash and vc++制作精美界面程序
- Agri-Net
- extjs中Toolbar工具栏的用法
- mysql的python api
- 测试
- 获取浏览器窗口的高度和宽度