diff --git a/data/shader/phong.fsh b/data/shader/phong.fsh index c06210b..2cea077 100644 --- a/data/shader/phong.fsh +++ b/data/shader/phong.fsh @@ -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)); diff --git a/data/shader/phong.vsh b/data/shader/phong.vsh index f0361a8..ce86ebb 100644 --- a/data/shader/phong.vsh +++ b/data/shader/phong.vsh @@ -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); } diff --git a/graphics.cc b/graphics.cc index 7247ebf..5ff9e67 100644 --- a/graphics.cc +++ b/graphics.cc @@ -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(3); + framebuffer_directional = std::vector(3); + for (unsigned int i = 0; isetMinFilter(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; isetDepthTexture(depth_directionalMaps.at(i)); + framebuffer_directional.at(i)->validate(); + } + + lightingShader->use(); + + for (unsigned int i = 0; isetTexture("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(10); for (unsigned int i = 0; iuse(); - - lightingShader->setTexture("shadowMap", depthTexture, 1); if (level->getLights()->size() > 0) { for(unsigned int i = 0; isetTexture("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 depthViewProjectionMatrices = std::vector(framebuffer_directional.size()); glm::vec3 sunVector = (level->getCameraCenter()->getPosition() + level->getDirectionalLight()->getPosition()); - glm::mat4 depthViewProjectionMatrix = glm::ortho(-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; ibind(); + 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(-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 depthBiasVPs = std::vector(depthViewProjectionMatrices.size()); + for (unsigned int i = 0; isetUniform("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 shadowVPs = std::vector(); - 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; iresize(glm::vec2(windowSize.x, windowSize.y)); + } } glm::mat4 Graphics::buildViewMatrix(Level* level) { diff --git a/graphics.hh b/graphics.hh index c3f4ff6..ad15594 100644 --- a/graphics.hh +++ b/graphics.hh @@ -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 depth_directionalMaps; + std::vector framebuffer_directional; std::vector depth_cubeMaps; ACGL::OpenGL::SharedFrameBufferObject framebuffer_cube; ACGL::OpenGL::SharedVertexArrayObject flame_positions;