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!
// 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;
}