Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 5 of 5

Thread: Shadow mapping

  1. #1
    Newbie Newbie
    Join Date
    Jun 2013
    Posts
    3

    Shadow mapping

    Hi! For the last couple of weeks I've been trying to render a simple scene with 3 objects, using phong shading model and simple shadow mapping. I found many tutorials and tried many things, but I still can't show any shadows currently. It's my first OpenGL project at all and unfortunately I'm completely stuck at this point.

    I post my code here for reference. I would be very glad to receive any help or advice to make it work!

    Code :
    // MAIN
    #include "ShaderUtil.h"
     
    GLfloat camPosition [] = {-8.0f, 6.0f, 8.0f};
    GLfloat lightPosition [] = {6.5f, 4.0f, 10.0f};  
     
    const int shadowMapSize = 512;
     
    GLuint shadowMapTexture, shdrProgram;
     
    int width = 720, height = 480;
     
    GLfloat lightProjMatrix[16], lightViewMatrix[16];
    GLfloat camProjMatrix[16], camViewMatrix[16];
     
    void calculateMatrices()
    {
    	glMatrixMode(GL_MODELVIEW);
     
    	glPushMatrix();
     
    	glLoadIdentity();
    	gluPerspective(45.0f, (float)width/height, 1.0f, 100.0f);
    	glGetFloatv(GL_MODELVIEW_MATRIX, camProjMatrix);
     
    	glLoadIdentity();
    	gluLookAt(camPosition[0], camPosition[1], camPosition[2], 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
    	glGetFloatv(GL_MODELVIEW_MATRIX, camViewMatrix);
     
    	glLoadIdentity();
    	gluPerspective(45.0f, (float)width/height, 1.0f, 100.0f);
    	glGetFloatv(GL_MODELVIEW_MATRIX, lightProjMatrix);
     
    	glLoadIdentity();
    	gluLookAt(lightPosition[0], lightPosition[1], lightPosition[2], 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
    	glGetFloatv(GL_MODELVIEW_MATRIX, lightViewMatrix);
     
    	glPopMatrix();
    }
     
    void changeSize(int w, int h) 
    {
    	if (h == 0)
    		h = 1;
    	width = w;
    	height = h;
     
    	glMatrixMode(GL_PROJECTION);
    	glLoadIdentity();
    	glViewport(0, 0, width, height);
    	gluPerspective(45, 1.0 * width / height, 1, 1000);
     
    	calculateMatrices();
    }
     
    void renderObjects() 
    {
    	//Plane
    	glPushMatrix();
    	glTranslatef(3, 0, -1);
    	glScalef(1.5, 0.05, 1.1);
    	glutSolidCube(8);
    	glPopMatrix();
     
    	//Teapot
    	glPushMatrix();
    	glTranslatef(3, 1.5, 1);
    	glutSolidTeapot(1);
    	glPopMatrix();
     
    	//Sphere
    	glPushMatrix();
    	glTranslatef(-1, 1.5, 1);
    	glutSolidSphere(1, 30, 30);
    	glPopMatrix();
    }
     
    void renderScene()
    { 
    	//First pass - from light's point of view
    	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     
    	glMatrixMode(GL_PROJECTION);
    	glLoadMatrixf(lightProjMatrix);
    	glMatrixMode(GL_MODELVIEW);
    	glLoadMatrixf(lightViewMatrix);
    	glViewport(0, 0, shadowMapSize, shadowMapSize); 
    	glShadeModel(GL_FLAT); // Flat shading for speed
    	glColorMask(0, 0, 0, 0); // Disable writing of frame buffer color components
     
    	renderObjects();
     
    	//Read the depth buffer into the shadow map texture	
    	glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, shadowMapSize, shadowMapSize); 
     
    	//restore states
    	glShadeModel(GL_SMOOTH);
    	glColorMask(1, 1, 1, 1);
     
    	//2nd pass - Draw from camera's point of view
    	glClear(GL_DEPTH_BUFFER_BIT);
    	glMatrixMode(GL_PROJECTION);
    	glLoadMatrixf(camProjMatrix);	
    	glMatrixMode(GL_MODELVIEW);
    	glLoadMatrixf(camViewMatrix);
    	glViewport(0, 0, width, height);
     
    	renderObjects(); 
     
    	//Calculate texture matrix for projection 
    	const GLfloat bias []  = {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};	
     
    	glMatrixMode(GL_TEXTURE);
    	glLoadMatrixf(bias);
    	glMultMatrixf(lightProjMatrix);
    	glMultMatrixf(lightViewMatrix);	
    	glMatrixMode(GL_MODELVIEW);
     
    	GLint matLoc = glGetUniformLocation(shdrProgram,"lightingMatrix");
    	glUniform1fv(matLoc, 2, bias);
     
    	glutSwapBuffers();
    }
     
    void init()
    {
    	glEnable(GL_DEPTH_TEST);   
    	glClearColor(0.0f, 0.0f, 0.4f, 0.0f);  
    	glDepthFunc(GL_LESS); 
    	glEnable(GL_MULTISAMPLE); 
     
    	// Create the shadow map texture
           glGenTextures(1, &shadowMapTexture);
           glBindTexture(GL_TEXTURE_2D, shadowMapTexture);
           glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, shadowMapSize, shadowMapSize, 
    		0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
           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);
           glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
           glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
           glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
           glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY);
     
    	// Set directional light 
    	GLfloat lightAmbient[] = {0.5f, 0.5f, 0.5f, 1.0f};
    	GLfloat lightDiffuse[] = {0.7f, 0.7f, 0.7f, 1.0f};
    	GLfloat lightSspecular[] = {0.33f, 0.33f, 0.33f, 1.0f};
    	glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmbient);
    	glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiffuse);
    	glLightfv(GL_LIGHT0, GL_SPECULAR, lightSspecular);	
    	glLightfv(GL_LIGHT0, GL_POSITION, lightPosition); 
     
    	// Set material 
    	GLfloat matrlAmbient[] = {0.0f, .6f, 0.7f, 1.0f};   
            GLfloat matrlDiffuse[] = {1.f, .5f, 0.1f, 1.0f};
    	GLfloat matrlSpecular[] = { 0.7f, 0.55f, 0.7f, 1.0f };
    	GLfloat matrlShininess = 80.0f;
    	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, matrlAmbient);
    	glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, matrlDiffuse);
    	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, matrlSpecular); 
    	glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, matrlShininess);
    }
     
    int main(int argc, char **argv) 
    {
    	// Init window
    	glutInit(&argc, argv);
    	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_MULTISAMPLE);
    	glutInitWindowPosition(100, 100);
    	glutInitWindowSize(width, height);
    	glutCreateWindow("GLSL Project");
    	glutDisplayFunc(renderScene);
    	glutIdleFunc(renderScene);
    	glutReshapeFunc(changeSize); 
     
    	init();
     
    	glewExperimental = GL_TRUE;
            glewInit(); 
     
    	shdrProgram = ShaderUtil::loadShaders("shdr_shadow.vert", "shdr_shadow.frag");
     
    	glutMainLoop();
     
    	return 0;
    }
     
    // VERTEX SHADER 
    varying vec4 ProjShadow;
    varying vec4 diffuse,ambient;
    varying vec3 normal,lightDir,halfVector;
    uniform mat4 lightingMatrix;
     
    void main()
    {
    	normal = normalize(gl_NormalMatrix * gl_Normal);
     
    	lightDir = normalize(vec3(gl_LightSource[0].position));
     
    	halfVector = normalize(gl_LightSource[0].halfVector.xyz);
     
    	diffuse = gl_FrontMaterial.diffuse * gl_LightSource[0].diffuse;
    	ambient = gl_FrontMaterial.ambient * gl_LightSource[0].ambient;
    	ambient += gl_LightModel.ambient * gl_FrontMaterial.ambient;
     
    	//ProjShadow = gl_TextureMatrix[1] * gl_Vertex;
    	//gl_Position = ftransform();
     
    	ProjShadow = lightingMatrix * gl_Vertex;
            gl_Position = ftransform(); //gl_ModelViewProjectionMatrix * gl_Vertex;
    }
     
    //FRAGMENT SHADER
    uniform sampler2DShadow ShadowMap;
    varying vec4 ProjShadow;
    varying vec4 diffuse, ambient;
    varying vec3 normal, lightDir, halfVector;
     
    void main()
    {
    	vec3 n, halfV;
    	float NdotL, NdotHV;
     
    	vec4 color = ambient;
     
    	n = normalize(normal);
     
    	NdotL = max(dot(n, lightDir), 0.0);
     
    	if (NdotL > 0.0) {
    		color += diffuse * NdotL;
     
    		halfV = normalize(halfVector);
    		NdotHV = max(dot(n, halfV), 0.0);
    		color += gl_FrontMaterial.specular * gl_LightSource[0].specular * pow(NdotHV, gl_FrontMaterial.shininess);
    	}
     
    	color *= shadow2DProj(ShadowMap, ProjShadow).r ;
     
    	gl_FragColor = color;
    }

  2. #2
    Senior Member OpenGL Guru Dark Photon's Avatar
    Join Date
    Oct 2004
    Location
    Druidia
    Posts
    3,211
    Some random things I noticed in your code. If these don't pan out, you just need to be systematic in nailing down where the problem is. For instance, first determining whether the problem is with the rendering of the shadow map, or the application.

    Your commented out use of the shadow matrix (via texture matrix) looks like it might be reasonable, given the unusual assumption that it takes WORLD-space coords as input (in your case, takes WORLD-space to biased light CLIP-space). However, gl_TextureMatrix[1] in the shader presumes that you loaded the matrix into the GL_TEXTURE matrix on texture unit 1, not 0. However, I don't see any glActiveTexture calls in your code. If you use a std GLSL uniform (vs. a legacy) you can get rid of this annoyance (see below).

    Also in your shader, you're feeding gl_Vertex into this texture matrix transformation (assigning to ProjShadow, which is used for the depth lookup and comparison). This implies gl_Vertex is a WORLD-space coordinate position. Is it? This is not usually the case. And it does not appear so in your code (you are using operations which update the MODELING component of the MODELVIEW transform (e.g. Translate/Scale/Push/Pop/etc.)

    Also in the code where you apparently gave up on passing the shadow matrix via texture matrix, you're trying to load a 4x4 matrix with glUniform1fv. Besides the fact that what you're passing in doesn't look useful, the way you pass a 4x4 matrix is with glUniformMatrix4fv. You can pass your shadow matrix into a std uniform (instead of a legacy built-in uniform like gl_TextureMatrix) after you get this working.

  3. #3
    Newbie Newbie
    Join Date
    Jun 2013
    Posts
    3
    Thank you, I'll check all the thing you've pointed out!

  4. #4
    Newbie Newbie
    Join Date
    Jun 2013
    Posts
    3
    I've tried some new things in my project recently and managed to achieve a bit different results, although still not the results I need.
    I think I have some problems with the way I set my projection and view matrices for the first render pass (from the light's view), but I can't figure out what and where.
    I'm sure there are still more or less random things or deprecated functions and etc. in my code, but I'm just trying to understand how to make it work for now. I would really appreciate very much any helpful comment or idea. Thank you indeed!

    fragment shader - https://docs.google.com/file/d/0BxXO...it?usp=sharing
    vertex shader - https://docs.google.com/file/d/0BxXO...it?usp=sharing
    main cpp - https://docs.google.com/file/d/0BxXO...it?usp=sharing
    resulting picture - https://docs.google.com/file/d/0BxXO...it?usp=sharing

  5. #5
    Intern Newbie
    Join Date
    Mar 2013
    Posts
    42
    You have to update and uniform your mvp matrix before you render an object.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •