This is how it looks now:
This is the code that generate the shadow matrix an shaders source:
void shadow::calculateShadowMatrixFromLightPointOfView(vector3f lightPosition, vector3f lightDirection)
{
//this method, only bind the frame buffer:
//glBindFramebuffer(GL_FRAMEBUFFER, uiFramebuffer);
fboShadowMap.bindFramebuffer();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//this method only bind the shader
m_shader.bindShader();
//I'M not sure if this is ok..
float rangeX = globalData::windowWidth;
float rangeY = globalData::windowHeight;
m_ProjectionMatrix = glm::ortho<float>(-rangeX,rangeX,-rangeY,rangeY, 0.05f,400.0);
m_currentLigthPosition = glm::lookAt(
glm::vec3(lightPosition.x,lightPosition.y,lightPosition.z),
glm::vec3(
lightDirection.x,
lightDirection.y,
lightDirection.z
),
glm::vec3(0,1,0)
);
glm::mat4 biasMatrix(
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
);
mDepthBiasMVP = biasMatrix * m_ProjectionMatrix * m_currentLigthPosition;
}
This creates the frame buffer:
bool frameBuffer::createFrameBufferForDepthShadow(int width, int height)
{
if(uiFramebuffer != 0)return false;
iWidth = width;
iHeight = height;
glBindRenderbuffer(GL_RENDERBUFFER, uiFramebuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height);
glGenFramebuffers(1, &uiFramebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, uiFramebuffer);
tFramebufferTex.createTexture(width, height, true);
tFramebufferTex.setFiltering(TEXTURE_FILTER_MAG_NEAREST, TEXTURE_FILTER_MIN_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glBindFramebuffer(GL_FRAMEBUFFER, uiFramebuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, tFramebufferTex.getTextureID(), 0);
glDrawBuffer(GL_NONE);
// Always check that our framebuffer is ok
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
return false;
return true;
}
The width and height integers are 1024.
This creates the texture:
unsigned int CTexture::createTexture(int w,int h,bool isDepth)
{
glGenTextures(1,&uiTexture);
glBindTexture(GL_TEXTURE_2D,uiTexture);
glTexImage2D(GL_TEXTURE_2D,0,(!isDepth ? GL_RGBA8 : GL_DEPTH_COMPONENT),w,h,0,(isDepth ? GL_DEPTH_COMPONENT : GL_RGBA),GL_FLOAT,NULL);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_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_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
int i;
i=glGetError();
if(i!=0)
{
cout << "Error happened while loading the texture: " << i << "\n";
}
glGenSamplers(1, &uiSampler);
return uiTexture;
}
isDepth variable, is true when i use this function to construct de framebuffer.
Then in the shaders i use for shadows:
VERTEX SHADER:
#version 330 core
// Input vertex data, different for all executions of this shader.
layout(location = 0) in vec3 inPosition;
// Values that stay constant for the whole mesh.
uniform mat4 depthMVP;
void main(){
gl_Position = depthMVP*vec4(inPosition.xyz,1.0f);
}
FRAGMENT SHADER:
#version 330 core
// Output data
layout(location = 0) out float fragmentdepth;
void main(){
fragmentdepth = gl_FragCoord.z;
}
Finally to render shadow in the "world", i use this shaders:
VERTEX SHADER:
#version 330
uniform mat4 projectionMatrix;
uniform mat4 modelViewMatrix;
uniform mat4 normalMatrix;
uniform mat4 modelMatrix;
uniform mat4 DepthBiasMVP;
smooth out vec4 ShadowCoord;
layout (location = 0) in vec3 inPosition;
layout (location = 1) in vec2 inCoord;
layout (location = 2) in vec3 inNormal;
smooth out vec2 texCoord;
smooth out vec3 vNormal;
smooth out vec3 vEyeSpacePos;
smooth out vec3 vWorldPos;
uniform float objOpacity;
smooth out float fObjOpacity;
uniform vec3 objColor;
smooth out vec3 vObjColor;
void main()
{
vec4 vEyeSpacePosVertex = modelViewMatrix*vec4(inPosition, 1.0);
gl_Position = projectionMatrix*vEyeSpacePosVertex;
texCoord = inCoord;
vec4 vRes = normalMatrix*vec4(inNormal, 0.0);
vNormal = vRes.xyz;
vEyeSpacePos = vEyeSpacePosVertex.xyz;
vec4 vWorldPosVertex = modelMatrix*vec4(inPosition, 1.0);
vWorldPos = vWorldPosVertex.xyz;
ShadowCoord = DepthBiasMVP * vWorldPosVertex;
fObjOpacity = objOpacity;
vObjColor = objColor;
}
FRAGMENT SHADER
#version 330
smooth in vec2 texCoord;
smooth in vec3 vNormal;
smooth in vec3 vEyeSpacePos;
smooth in vec3 vWorldPos;
smooth in vec3 vObjColor;
smooth in float fObjOpacity;
struct material
{
float specularIntensity;
float specularPower;
};
uniform material m_material;
out vec4 outputColor;
uniform sampler2D gSampler;
vec4 totalLight = vec4(0.0,0.0,0.0,0.0);
float visibility = 1.0f;
struct DirectionalLight
{
vec3 vColor;
vec3 vPosition;
vec3 vDirection;
float fAmbientIntensity;
float fStrength;
};
vec4 getDirectionalLightColor(DirectionalLight dirLight, vec3 vNormal)
{
float fDiffuseIntensity = max(0.0, dot(normalize(vNormal), -dirLight.vDirection));
return vec4(dirLight.vColor*(dirLight.fAmbientIntensity+fDiffuseIntensity)*dirLight.fStrength, 1.0);
}
uniform DirectionalLight sunLight;
uniform sampler2D shadowMap;
smooth in vec4 ShadowCoord;
vec2 poissonDisk[16] = vec2[](
vec2( -0.94201624, -0.39906216 ),
vec2( 0.94558609, -0.76890725 ),
vec2( -0.094184101, -0.92938870 ),
vec2( 0.34495938, 0.29387760 ),
vec2( -0.91588581, 0.45771432 ),
vec2( -0.81544232, -0.87912464 ),
vec2( -0.38277543, 0.27676845 ),
vec2( 0.97484398, 0.75648379 ),
vec2( 0.44323325, -0.97511554 ),
vec2( 0.53742981, -0.47373420 ),
vec2( -0.26496911, -0.41893023 ),
vec2( 0.79197514, 0.19090188 ),
vec2( -0.24188840, 0.99706507 ),
vec2( -0.81409955, 0.91437590 ),
vec2( 0.19984126, 0.78641367 ),
vec2( 0.14383161, -0.14100790 )
);
float getVisibility(sampler2D shadowMap, vec4 vShadowCoord, float windowWidth, float windowHeight)
{
float visibility = 1.0;
float bias = 0.0012;
for (int i=0;i<4;i++)
{
int index = i;
vec4 vShadowSmooth = vec4(vShadowCoord.x + poissonDisk[index].x/windowWidth, vShadowCoord.y + poissonDisk[index].y/windowHeight, (vShadowCoord.z)/vShadowCoord.w, 1.0);
float fSub = texture(shadowMap, vShadowSmooth.st).r;
if(fSub<vShadowCoord.z-bias){
visibility -= 0.1*(1.0-fSub);
}
}
return visibility;
}
void main()
{
vec3 vNormalized = normalize(vNormal);
totalLight += getDirectionalLightColor(sunLight, vNormal);
visibility = getVisibility(shadowMap, ShadowCoord);
vec4 vTexColor = texture2D(gSampler, texCoord);
vTexColor.a = fObjOpacity;
vec4 vMixedColor = vTexColor*vec4(vObjColor,1.0);
outputColor = vec4(vMixedColor*totalLight*visibility);
}
As you can see in the pictures, the shadow have these horrible "acne" and i don know how to avoid it.
This is the order in wich the scene is rendered:
glViewport(0, 0, 1024, 1024);
//this function are described above
m_shadows->calculateShadowMatrixFromLightPointOfView(
dirLight->getPosition(),
dirLight->getDirection()
);
//render objects
glViewport(0, 0, globalData::windowWidth, globalData::windowHeight);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
//render objects