Reintroduced cascaded shadow mapping while also fixing it. The old bug with popping shadows should be fixed now.

This commit is contained in:
Faerbit 2015-02-28 14:40:54 +01:00
parent 7ff11e1105
commit 2da70f156d
4 changed files with 97 additions and 48 deletions

View File

@ -3,12 +3,16 @@
in vec3 vNormal;
in vec2 vTexCoord;
in vec4 fragPosition;
in vec4 shadowCoord;
in vec4 shadowCoord0;
in vec4 shadowCoord1;
in vec4 shadowCoord2;
out vec4 oColor;
uniform sampler2D uTexture;
uniform sampler2DShadow shadowMap;
uniform sampler2DShadow shadowMap_directional0;
uniform sampler2DShadow shadowMap_directional1;
uniform sampler2DShadow shadowMap_directional2;
uniform samplerCubeShadow shadowMap_cube0;
uniform samplerCubeShadow shadowMap_cube1;
uniform samplerCubeShadow shadowMap_cube2;
@ -61,7 +65,7 @@ float sampleDirectionalShadow(sampler2DShadow shadowMap, vec4 shadowCoord) {
float bias = 0.001*tan(acos(clamp(dot(vNormal, -directionalLightVector), 0.0, 1.0)));
bias = clamp(bias, 0.0, 0.01);
for (int i=0; i<4; i++) {
visibility -= directionalIntensity/16*(1.0-texture(shadowMap, vec3(shadowCoord.xy + poissonDisk[i]/700.0, shadowCoord.z - bias)));
visibility -= directionalIntensity/16*(1.0-texture(shadowMap, vec3(shadowCoord.xy + poissonDisk[i]/800.0, shadowCoord.z - bias)));
}
if (visibility == 1.0-(directionalIntensity/16)*4)
{
@ -69,7 +73,7 @@ float sampleDirectionalShadow(sampler2DShadow shadowMap, vec4 shadowCoord) {
}
else if (visibility != 1.0) {
for (int i=0; i<12; i++) {
visibility -= directionalIntensity/16*(1.0-texture(shadowMap, vec3(shadowCoord.xy + poissonDisk[i]/700.0, shadowCoord.z - bias)));
visibility -= directionalIntensity/16*(1.0-texture(shadowMap, vec3(shadowCoord.xy + poissonDisk[i]/800.0, shadowCoord.z - bias)));
}
}
return visibility;
@ -101,7 +105,18 @@ void main()
// direction lighting
if(length(directionalLightVector)>0.0f) {
vec3 directionalVector = normalize(directionalLightVector);
float directionalVisibility = sampleDirectionalShadow(shadowMap, shadowCoord);
float directionalVisibility = 1.0f;
if (distanceToBorder(shadowCoord1.xy) <= 0.5 && distanceToBorder(shadowCoord1.xy) > 0.0) {
if (distanceToBorder(shadowCoord0.xy) <= 0.5 && distanceToBorder(shadowCoord0.xy) > 0.0) {
directionalVisibility = sampleDirectionalShadow(shadowMap_directional0, shadowCoord0);
}
else {
directionalVisibility = sampleDirectionalShadow(shadowMap_directional1, shadowCoord1);
}
}
else {
directionalVisibility = sampleDirectionalShadow(shadowMap_directional2, shadowCoord2);
}
diffuseColor += clamp(dot(normalize(vNormal), directionalVector)
*diffuseFactor*directionalIntensity*directionalColor, 0.0, 1.0)*directionalVisibility;
vec3 cameraVector = normalize(camera - vec3(fragPosition));

View File

@ -11,13 +11,17 @@ in vec2 aTexCoord;
out vec3 vNormal;
out vec2 vTexCoord;
out vec4 fragPosition;
out vec4 shadowCoord;
out vec4 shadowCoord0;
out vec4 shadowCoord1;
out vec4 shadowCoord2;
void main()
{
fragPosition = modelMatrix * vec4(aPosition, 1.0);
vNormal = inverse(transpose(mat3(modelMatrix))) * aNormal;
vTexCoord = aTexCoord;
shadowCoord = shadowMVPs[0] * vec4(aPosition, 1.0);
shadowCoord0 = shadowMVPs[0] * vec4(aPosition, 1.0);
shadowCoord1 = shadowMVPs[1] * vec4(aPosition, 1.0);
shadowCoord2 = shadowMVPs[2] * vec4(aPosition, 1.0);
gl_Position = modelViewProjectionMatrix * vec4(aPosition, 1.0);
}

View File

@ -58,26 +58,40 @@ void Graphics::init(Level* level) {
flameShader = ShaderProgramCreator("flame")
.attributeLocations(flame_positions->getAttributeLocations()).create();
depthTexture = SharedTexture2D( new Texture2D(windowSize, GL_DEPTH_COMPONENT24));
depthTexture->setMinFilter(GL_NEAREST);
depthTexture->setMagFilter(GL_NEAREST);
depthTexture->setWrapS(GL_CLAMP_TO_EDGE);
depthTexture->setWrapT(GL_CLAMP_TO_EDGE);
depthTexture->setCompareMode(GL_COMPARE_REF_TO_TEXTURE);
framebuffer = SharedFrameBufferObject(new FrameBufferObject());
framebuffer->setDepthTexture(depthTexture);
framebuffer->validate();
glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &number_of_texture_units);
printf("Your graphics card supports %d texture units.\n", number_of_texture_units);
// Exit if we need more texture units
if (number_of_texture_units < 12) {
printf("You need at least 12 texture units to run this application. Exiting\n");
if (number_of_texture_units < 14) {
printf("You need at least 14 texture units to run this application. Exiting\n");
exit(-1);
}
// always generate and bind 32 cube maps, because otherwise the shader won't work
depth_directionalMaps = std::vector<SharedTexture2D>(3);
framebuffer_directional = std::vector<SharedFrameBufferObject>(3);
for (unsigned int i = 0; i<depth_directionalMaps.size(); i++) {
depth_directionalMaps.at(i) = SharedTexture2D( new Texture2D(windowSize, GL_DEPTH_COMPONENT24));
depth_directionalMaps.at(i)->setMinFilter(GL_NEAREST);
depth_directionalMaps.at(i)->setMagFilter(GL_NEAREST);
depth_directionalMaps.at(i)->setWrapS(GL_CLAMP_TO_EDGE);
depth_directionalMaps.at(i)->setWrapT(GL_CLAMP_TO_EDGE);
depth_directionalMaps.at(i)->setCompareMode(GL_COMPARE_REF_TO_TEXTURE);
}
for (unsigned int i = 0; i<framebuffer_directional.size(); i++) {
framebuffer_directional.at(i) = SharedFrameBufferObject(new FrameBufferObject());
framebuffer_directional.at(i)->setDepthTexture(depth_directionalMaps.at(i));
framebuffer_directional.at(i)->validate();
}
lightingShader->use();
for (unsigned int i = 0; i<depth_directionalMaps.size(); i++) {
// start with texture unit 1 because the first is reserved for the texture
lightingShader->setTexture("shadowMap_directional" + std::to_string(i), depth_directionalMaps.at(i), i+1);
}
// always generate and bind 10 cube maps, because otherwise the shader won't work
depth_cubeMaps = std::vector<ACGL::OpenGL::SharedTextureCubeMap>(10);
for (unsigned int i = 0; i<depth_cubeMaps.size(); i++) {
depth_cubeMaps.at(i) = SharedTextureCubeMap(new TextureCubeMap(glm::vec2(cube_size, cube_size), GL_DEPTH_COMPONENT24));
@ -90,14 +104,11 @@ void Graphics::init(Level* level) {
framebuffer_cube = SharedFrameBufferObject(new FrameBufferObject());
lightingShader->use();
lightingShader->setTexture("shadowMap", depthTexture, 1);
if (level->getLights()->size() > 0) {
for(unsigned int i = 0; i<depth_cubeMaps.size(); i++){
// start with texture unit 2 because the first two are used by the texture and the directional shadow map
lightingShader->setTexture("shadowMap_cube" + std::to_string(i), depth_cubeMaps.at(i), i+2);
// start with texture unit 4 because the first four are used by the texture and the directional shadow map
lightingShader->setTexture("shadowMap_cube" + std::to_string(i), depth_cubeMaps.at(i), i+4);
}
}
updateClosestLights();
@ -137,19 +148,34 @@ void Graphics::render(double time)
}
}
}
// render depth texture for sun
// render depth textures for sun
depthShader->use();
glViewport(0, 0, windowSize.x, windowSize.y);
// far pass
framebuffer->bind();
glClear(GL_DEPTH_BUFFER_BIT);
std::vector<glm::mat4> depthViewProjectionMatrices = std::vector<glm::mat4>(framebuffer_directional.size());
glm::vec3 sunVector = (level->getCameraCenter()->getPosition() + level->getDirectionalLight()->getPosition());
glm::mat4 depthViewProjectionMatrix = glm::ortho<float>(-farPlane/1.5f, farPlane/1.5f, -farPlane/1.5f, farPlane/1.5f, -farPlane/1.5f, farPlane/1.5f) *
glm::lookAt(sunVector, level->getCameraCenter()->getPosition(), glm::vec3(0,1,0));
level->render(depthShader, false, &depthViewProjectionMatrix);
if (!framebuffer->isFrameBufferObjectComplete()) {
printf("Framebuffer incomplete, unknown error occured during shadow generation!\n");
for (unsigned int i = 0; i<framebuffer_directional.size(); i++) {
framebuffer_directional.at(i)->bind();
glClear(GL_DEPTH_BUFFER_BIT);
float projection_size = 0.0f;
switch(i) {
case 0:
projection_size = 10.0f;
break;
case 1:
projection_size = 30.0f;
break;
case 2:
projection_size = farPlane/1.5f;
break;
}
depthViewProjectionMatrices.at(i) = glm::ortho<float>(-projection_size, projection_size, -projection_size, projection_size, -farPlane/1.5f, projection_size) *
glm::lookAt(sunVector, level->getCameraCenter()->getPosition(), glm::vec3(0,1,0));
level->render(depthShader, false, &depthViewProjectionMatrices.at(i));
if (!framebuffer_directional.at(i)->isFrameBufferObjectComplete()) {
printf("Framebuffer incomplete, unknown error occured during shadow generation!\n");
}
}
// final render pass
@ -172,12 +198,17 @@ void Graphics::render(double time)
// convert texture to homogenouse coordinates
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
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
);
glm::mat4 depthBiasVP = biasMatrix*depthViewProjectionMatrix;
std::vector<glm::mat4> depthBiasVPs = std::vector<glm::mat4>(depthViewProjectionMatrices.size());
for (unsigned int i = 0; i<depthBiasVPs.size(); i++) {
depthBiasVPs.at(i) = biasMatrix * depthViewProjectionMatrices.at(i);
}
lightingShader->setUniform("farPlane", farPlane);
// set fog Parameters
@ -191,11 +222,8 @@ void Graphics::render(double time)
//set view and projection matrix
glm::mat4 lightingViewProjectionMatrix = glm::perspective(1.571f, (float)windowSize.x/(float)windowSize.y, 0.1f, farPlane) * buildViewMatrix(level);
std::vector<glm::mat4> shadowVPs = std::vector<glm::mat4>();
shadowVPs.push_back(depthBiasVP);
// render the level
level->render(lightingShader, true, &lightingViewProjectionMatrix, &shadowVPs);
level->render(lightingShader, true, &lightingViewProjectionMatrix, &depthBiasVPs);
// cull faces to get consistent color while using alpha
// cull front faces because normals are on the wrong side
@ -284,7 +312,9 @@ void Graphics::updateLights() {
void Graphics::resize(glm::uvec2 windowSize) {
this->windowSize = windowSize;
depthTexture->resize(glm::vec2(windowSize.x, windowSize.y));
for (unsigned int i = 0; i<depth_directionalMaps.size(); i++) {
depth_directionalMaps.at(i)->resize(glm::vec2(windowSize.x, windowSize.y));
}
}
glm::mat4 Graphics::buildViewMatrix(Level* level) {

View File

@ -32,8 +32,8 @@ class Graphics {
ACGL::OpenGL::SharedShaderProgram depthCubeShader;
ACGL::OpenGL::SharedShaderProgram depthShader;
ACGL::OpenGL::SharedShaderProgram flameShader;
ACGL::OpenGL::SharedTexture2D depthTexture;
ACGL::OpenGL::SharedFrameBufferObject framebuffer;
std::vector<ACGL::OpenGL::SharedTexture2D> depth_directionalMaps;
std::vector<ACGL::OpenGL::SharedFrameBufferObject> framebuffer_directional;
std::vector<ACGL::OpenGL::SharedTextureCubeMap> depth_cubeMaps;
ACGL::OpenGL::SharedFrameBufferObject framebuffer_cube;
ACGL::OpenGL::SharedVertexArrayObject flame_positions;