Hi, I'm new with openGL and I can't seems to make textures work properly. I need to cast shadows and I refer to this toturial for this purpose : http://fabiensanglard.net/shadowmapping/index.php. Since I try tu use the latest GLSL version, I had to change some pieces of code.
Before going further, so far, here is what I get without searching for shadows.
Attachment 698
For each instance of light, I have a framebuffer object and a texture attached to it.
Code :CLight::CLight(): m_type(POINT), m_intensity(1), m_ambient(0.5), m_diffuse(0.3, 0.6, 0.6), m_specular(0.3, 0.7, 0.7), m_enabled(true) { glGenTextures(1, &m_texId); glBindTexture(GL_TEXTURE_2D, m_texId); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 256, 256, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0); glBindTexture(GL_TEXTURE_2D, 0); glGenFramebuffers(1, &m_fboId); glBindFramebuffer(GL_FRAMEBUFFER, m_fboId); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_texId, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0); }
Before rendering, I TRY to get the view of each light by bindding the framebuffer before rendering.
Code :void CGLWidget::paintGL(){ //Shadow maps generation m_shadow.use(); //shadow program for(int a = 0; a < m_light.size(); a++){ CLight* current = m_light[a]; if(current->enabled()){ m_currentCamera = current; current->bindFB(); //glBindFramebuffer(GL_FRAMEBUFFER, m_fboId); drawObjects(); current->unbindFB(); //glBindFramebuffer(GL_FRAMEBUFFER, 0); } } //Draw final render m_render.use(); //render program m_currentCamera = &m_camera; drawObjects(); }
If I comment the final render part and don't bind the frame buffer I get this :
Attachment 699
Which is normal considering the shaders :
Code ://shadow.vertexShader #version 420 in vec3 position; uniform mat4 mvp; void main() { gl_Position = mvp * vec4(position, 1.0f); }
Code ://shadow.fragmentShader #version 420 out vec4 fragColor; void main (void) { fragColor = vec4(0.5, 0.5, 0.5, 1) ; }
When I keep the render part commented but uncomment the binding part I get a dark screen, which is once again normal, I guess. Thus I though my texture was correctly made and I tried to use it on the render's fragment shader.
Here is the method of CLight used just before drawing :
Code :void CLight::sendTo(CProgram* p_program, const CMVP* p_camera, int p_id){ //blabla //blabla p_program->sendUniform1i(QString("light[%1].type").arg(p_id), m_type); p_program->sendUniform4f(QString("light[%1].position").arg(p_id), position.x(), position.y(), position.z(), position.w()); p_program->sendUniform3f(QString("light[%1].direction").arg(p_id), direction.x(), direction.y(), direction.z()); p_program->sendUniform1i(QString("shadowMap[%1]").arg(p_id), p_id); //The cursed line p_program->sendUniform1f(QString("light[%1].intensity").arg(p_id), m_intensity); p_program->sendUniform1f(QString("light[%1].ambient").arg(p_id), m_ambient); p_program->sendUniform3f(QString("light[%1].diffuse").arg(p_id), m_diffuse.x(), m_diffuse.y(), m_diffuse.z()); p_program->sendUniform3f(QString("light[%1].specular").arg(p_id), m_specular.x(), m_specular.y(), m_specular.z()); p_program->sendUniformMatrix4fv(QString("light[%1].shadowMat").arg(p_id), 1, GL_TRUE, texMat); glActiveTexture(GL_TEXTURE0 + p_id); //Maybe some cursed lines again glBindTexture(GL_TEXTURE_2D, m_texId); // }
And here are the render shaders :
Code ://render.vertexShader #version 420 in vec3 position; in vec3 color; in vec3 normal; uniform mat4 mvp; uniform mat4 mv; uniform mat3 mvi; out vec4 vertexInitPosition; out vec4 vertexPosition; out vec3 vertexColor; out vec3 vertexNormal; void main() { int a; vertexInitPosition = vec4(position, 1); vertexPosition = mv * vec4(position, 1); vertexColor = color; vertexNormal = normalize(mvi * normal); gl_Position = mvp * vec4(position, 1.0f); }
Code ://render.fragmentShader #version 420 const int nbrLight = 8; in vec4 vertexInitPosition; in vec4 vertexPosition; in vec3 vertexColor; in vec3 vertexNormal; uniform int nbrLightUsed; uniform struct lightStruct { int type; vec4 position; vec3 direction; mat4 shadowMat; float intensity; float ambient; vec3 diffuse; vec3 specular; } light[nbrLight]; uniform sampler2D shadowMap[nbrLight]; out vec4 fragColor; void main (void) { int a; vec3 iDiff = vec3(0,0,0); vec3 iSpec = vec3(0,0,0); vec4 shadowCoord; for(a = 0; a < nbrLight && a < nbrLightUsed; a++){ //Compute shadows shadowCoord = light[a].shadowMat * vertexInitPosition; vec4 shadowCoordinateWdivide = shadowCoord / shadowCoord.w ; shadowCoordinateWdivide.z += 0.0005; float distanceFromLight = texture2D(shadowMap[a],shadowCoordinateWdivide.st).z; float shadow = 1.0; if (shadowCoord.w > 0.0 && distanceFromLight < shadowCoordinateWdivide.z) shadow = 0.5; //Compute rays vec3 L; if(light[a].type == 0) //Point light L = vec3(normalize(vertexPosition - light[a].position)); else if(light[a].type == 1) //Directionnal light L = normalize(light[a].direction); vec3 E = -normalize(vec3(vertexPosition)); vec3 R = normalize(reflect(L,vertexNormal)); //Add light iDiff = iDiff + shadow * light[a].diffuse * (light[a].intensity * (light[a].ambient + (1.0 - 0.5*light[a].ambient) * dot(-L, vertexNormal))); iSpec = iSpec + light[a].specular * (light[a].intensity * pow(max(dot(R,E),0.0),7.0)); } fragColor = vec4(iDiff + iSpec, 1) ; }
Everything works fine except the "Compute shadows" part. I'm sure my textureMatrix is correct because when I make my render only arround it, I get this :
Attachment 700
Thus, the last problem that remains is the integrity of the sampler2D used. I tried a render using only the z values of this sampler and got only 1.0 values. I also tried with empty samplers and got the same result.
I don't know what's wrong here, till then it was funny because I could tuch every data by hand. Now with textures it's different, I have no idea if the transfert from the framebuffer was a success nor the transfert vie glUniform1i().
Does anyone have an idea ?