Implemented cascaded shadow mapping.

This commit is contained in:
Faerbit 2014-12-04 17:19:58 +01:00
parent 0cb741dbc3
commit 1c687f5759
4 changed files with 119 additions and 41 deletions

View File

@ -3,12 +3,16 @@
in vec3 vNormal;
in vec2 vTexCoord;
in vec4 fragPosition;
in vec4 shadowCoord;
in vec4 shadowCoord_near;
in vec4 shadowCoord_middle;
in vec4 shadowCoord_far;
out vec4 oColor;
uniform sampler2D uTexture;
uniform sampler2DShadow shadowMap;
uniform sampler2DShadow shadowMap_near;
uniform sampler2DShadow shadowMap_middle;
uniform sampler2DShadow shadowMap_far;
uniform vec3 ambientColor;
uniform float ambientFactor;
uniform float diffuseFactor;
@ -45,6 +49,25 @@ vec2 poissonDisk[16] = vec2[](
vec2( 0.14383161, -0.14100790 )
);
float sampleShadow(sampler2DShadow shadowMap, vec4 shadowCoord) {
float visibility = 1.0;
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)/shadowCoord.w)));
}
if (visibility == 1.0-(directionalIntensity/16)*4)
{
visibility = 1.0-directionalIntensity;
}
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)/shadowCoord.w)));
}
}
return visibility;
}
void main()
{
vec3 ambientColor = ambientFactor * ambientColor;
@ -78,24 +101,22 @@ void main()
}
// shadows
float bias = 0.001*tan(acos(clamp(dot(vNormal, -directionalLightVector), 0.0, 1.0)));
bias = clamp(bias, 0.0, 0.01);
float visibility = 1.0;
if (shadowCoord.x > 0.0 && shadowCoord.x < 1.0) {
if (shadowCoord.y > 0.0 && shadowCoord.y < 1.0) {
for (int i=0; i<4; i++) {
visibility -= directionalIntensity/16*(1.0-texture(shadowMap, vec3(shadowCoord.xy + poissonDisk[i]/700.0, (shadowCoord.z - bias)/shadowCoord.w)));
if ((shadowCoord_far.x > 0.0 && shadowCoord_far.x < 1.0) &&
(shadowCoord_far.y > 0.0 && shadowCoord_far.y < 1.0)) {
if ((shadowCoord_middle.x > 0.0 && shadowCoord_middle.x < 1.0) &&
(shadowCoord_middle.y > 0.0 && shadowCoord_middle.y < 1.0)) {
if ((shadowCoord_near.x > 0.0 && shadowCoord_near.x < 1.0) &&
(shadowCoord_near.y > 0.0 && shadowCoord_near.y < 1.0)) {
visibility = sampleShadow(shadowMap_near, shadowCoord_near);
}
if (visibility == 1.0-(directionalIntensity/16)*4)
{
visibility = 1.0-directionalIntensity;
}
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)/shadowCoord.w)));
}
else {
visibility = sampleShadow(shadowMap_middle, shadowCoord_middle);
}
}
else {
visibility = sampleShadow(shadowMap_far, shadowCoord_far);
}
}
specularColor *= visibility;

View File

@ -2,7 +2,9 @@
uniform mat4 modelMatrix;
uniform mat4 lightingViewProjectionMatrix;
uniform mat4 shadowMVP;
uniform mat4 shadowMVP_near;
uniform mat4 shadowMVP_middle;
uniform mat4 shadowMVP_far;
in vec3 aPosition;
in vec3 aNormal;
@ -11,13 +13,17 @@ in vec2 aTexCoord;
out vec3 vNormal;
out vec2 vTexCoord;
out vec4 fragPosition;
out vec4 shadowCoord;
out vec4 shadowCoord_near;
out vec4 shadowCoord_middle;
out vec4 shadowCoord_far;
void main()
{
fragPosition = modelMatrix * vec4(aPosition, 1.0);
vNormal = inverse(transpose(mat3(modelMatrix))) * aNormal;
vTexCoord = aTexCoord;
shadowCoord = shadowMVP * modelMatrix * vec4(aPosition, 1.0);
shadowCoord_near = shadowMVP_near * modelMatrix * vec4(aPosition, 1.0);
shadowCoord_middle = shadowMVP_middle * modelMatrix * vec4(aPosition, 1.0);
shadowCoord_far = shadowMVP_far * modelMatrix * vec4(aPosition, 1.0);
gl_Position = lightingViewProjectionMatrix * modelMatrix * vec4(aPosition, 1.0);
}

View File

@ -29,19 +29,35 @@ void Graphics::init() {
lightingShader = ShaderProgramCreator("phong").attributeLocations(
vao->getAttributeLocations()).create();
depthTexture = SharedTexture2D( new Texture2D(windowSize, GL_DEPTH24_STENCIL8));
depthTexture->setMinFilter(GL_LINEAR);
depthTexture->setMagFilter(GL_LINEAR);
depthTexture->setCompareMode(GL_COMPARE_REF_TO_TEXTURE);
framebuffer = SharedFrameBufferObject(new FrameBufferObject());
framebuffer->setDepthTexture(depthTexture);
framebuffer->validate();
depthShader = ShaderProgramCreator("depth")
.attributeLocations(vao->getAttributeLocations())
.fragmentDataLocations(framebuffer->getAttachmentLocations())
.create();
.attributeLocations(vao->getAttributeLocations()).create();
depthTexture_near = SharedTexture2D( new Texture2D(windowSize, GL_DEPTH24_STENCIL8));
depthTexture_near->setMinFilter(GL_NEAREST);
depthTexture_near->setMagFilter(GL_NEAREST);
depthTexture_near->setCompareMode(GL_COMPARE_REF_TO_TEXTURE);
framebuffer_near = SharedFrameBufferObject(new FrameBufferObject());
framebuffer_near->setDepthTexture(depthTexture_near);
framebuffer_near->validate();
depthTexture_middle = SharedTexture2D( new Texture2D(windowSize, GL_DEPTH24_STENCIL8));
depthTexture_middle->setMinFilter(GL_NEAREST);
depthTexture_middle->setMagFilter(GL_NEAREST);
depthTexture_middle->setCompareMode(GL_COMPARE_REF_TO_TEXTURE);
framebuffer_middle = SharedFrameBufferObject(new FrameBufferObject());
framebuffer_middle->setDepthTexture(depthTexture_middle);
framebuffer_middle->validate();
depthTexture_far = SharedTexture2D( new Texture2D(windowSize, GL_DEPTH24_STENCIL8));
depthTexture_far->setMinFilter(GL_NEAREST);
depthTexture_far->setMagFilter(GL_NEAREST);
depthTexture_far->setCompareMode(GL_COMPARE_REF_TO_TEXTURE);
framebuffer_far = SharedFrameBufferObject(new FrameBufferObject());
framebuffer_far->setDepthTexture(depthTexture_far);
framebuffer_far->validate();
}
GLFWwindow* Graphics::getWindow() {
@ -55,15 +71,38 @@ glm::uvec2 Graphics::getWindowSize() {
void Graphics::render(Level* level)
{
// render depth texture for sun
framebuffer->bind();
// near pass
framebuffer_near->bind();
glClear(GL_DEPTH_BUFFER_BIT);
depthShader->use();
glm::vec3 sunVector = (level->getCameraCenter()->getPosition() + level->getDirectionalLight()->getPosition());
glm::mat4 depthViewProjectionMatrix = glm::ortho<float>(-20, 20, -20, 20, -20, 40) *
glm::mat4 depthViewProjectionMatrix_near = glm::ortho<float>(-5, 5, -5, 5, -5, 5) *
glm::lookAt(sunVector, level->getCameraCenter()->getPosition(), glm::vec3(0,1,0));
depthShader->setUniform("viewProjectionMatrix", depthViewProjectionMatrix);
depthShader->setUniform("viewProjectionMatrix", depthViewProjectionMatrix_near);
level->render(depthShader, false);
if (!framebuffer->isFrameBufferObjectComplete()) {
if (!framebuffer_near->isFrameBufferObjectComplete()) {
printf("Framebuffer incomplete, unknown error occured during shadow generation!\n");
}
// middle pass
framebuffer_middle->bind();
glClear(GL_DEPTH_BUFFER_BIT);
glm::mat4 depthViewProjectionMatrix_middle = glm::ortho<float>(-20, 20, -20, 20, -20, 20) *
glm::lookAt(sunVector, level->getCameraCenter()->getPosition(), glm::vec3(0,1,0));
depthShader->setUniform("viewProjectionMatrix", depthViewProjectionMatrix_middle);
level->render(depthShader, false);
if (!framebuffer_middle->isFrameBufferObjectComplete()) {
printf("Framebuffer incomplete, unknown error occured during shadow generation!\n");
}
// far pass
framebuffer_far->bind();
glClear(GL_DEPTH_BUFFER_BIT);
glm::mat4 depthViewProjectionMatrix_far = glm::ortho<float>(-farPlane/2.0f, farPlane/2.0f, -farPlane/2.0f, farPlane/2.0f, -farPlane/2.0f, farPlane/2.0f) *
glm::lookAt(sunVector, level->getCameraCenter()->getPosition(), glm::vec3(0,1,0));
depthShader->setUniform("viewProjectionMatrix", depthViewProjectionMatrix_far);
level->render(depthShader, false);
if (!framebuffer_far->isFrameBufferObjectComplete()) {
printf("Framebuffer incomplete, unknown error occured during shadow generation!\n");
}
@ -85,10 +124,16 @@ void Graphics::render(Level* level)
0.0, 0.0, 0.5, 0.0,
0.5, 0.5, 0.5, 1.0
);
glm::mat4 depthBiasMVP = biasMatrix*depthViewProjectionMatrix;
glm::mat4 depthBiasMVP_near = biasMatrix*depthViewProjectionMatrix_near;
glm::mat4 depthBiasMVP_middle = biasMatrix*depthViewProjectionMatrix_middle;
glm::mat4 depthBiasMVP_far = biasMatrix*depthViewProjectionMatrix_far;
lightingShader->setUniform("shadowMVP", depthBiasMVP);
lightingShader->setTexture("shadowMap", depthTexture, 1);
lightingShader->setUniform("shadowMVP_near", depthBiasMVP_near);
lightingShader->setTexture("shadowMap_near", depthTexture_near, 1);
lightingShader->setUniform("shadowMVP_middle", depthBiasMVP_middle);
lightingShader->setTexture("shadowMap_middle", depthTexture_middle, 2);
lightingShader->setUniform("shadowMVP_far", depthBiasMVP_far);
lightingShader->setTexture("shadowMap_far", depthTexture_far, 3);
//set lighting parameters
if (level->getLights().size() > 0) {
@ -142,7 +187,9 @@ void Graphics::render(Level* level)
void Graphics::resize(glm::uvec2 windowSize) {
this->windowSize = windowSize;
depthTexture->resize(glm::vec2(windowSize.x, windowSize.y));
depthTexture_near->resize(glm::vec2(windowSize.x, windowSize.y));
depthTexture_middle->resize(glm::vec2(windowSize.x, windowSize.y));
depthTexture_far->resize(glm::vec2(windowSize.x, windowSize.y));
}
glm::mat4 Graphics::buildFrustum( float phiInDegree, float _near, float _far, float aspectRatio) {

View File

@ -30,8 +30,12 @@ class Graphics {
GLFWwindow* window;
ACGL::OpenGL::SharedShaderProgram lightingShader;
ACGL::OpenGL::SharedShaderProgram depthShader;
ACGL::OpenGL::SharedTexture2D depthTexture;
ACGL::OpenGL::SharedFrameBufferObject framebuffer;
ACGL::OpenGL::SharedTexture2D depthTexture_near;
ACGL::OpenGL::SharedFrameBufferObject framebuffer_near;
ACGL::OpenGL::SharedTexture2D depthTexture_middle;
ACGL::OpenGL::SharedFrameBufferObject framebuffer_middle;
ACGL::OpenGL::SharedTexture2D depthTexture_far;
ACGL::OpenGL::SharedFrameBufferObject framebuffer_far;
};
#endif