diff --git a/Shader/phong.fsh b/Shader/phong.fsh index 74564e1..efe797c 100644 --- a/Shader/phong.fsh +++ b/Shader/phong.fsh @@ -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; @@ -26,6 +30,50 @@ uniform float fogEnd; uniform vec4 fogColor; uniform vec3 cameraCenter; +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 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; +} + +float distanceToBorder(vec2 vector) { + float xDistance = min(vector.x, 1.0-vector.x); + float yDistance = min(vector.y, 1.0-vector.y); + return min(xDistance, yDistance); +} + void main() { vec3 ambientColor = ambientFactor * ambientColor; @@ -59,18 +107,17 @@ void main() } // shadows - float bias = 0.001*tan(acos(clamp(dot(vNormal, -directionalLightVector), 0.0, 1.0))); - bias = clamp(bias, 0.0, 0.01); - vec3 biasedShadowCoord = vec3(shadowCoord); - biasedShadowCoord.z = shadowCoord.z - bias; float visibility = 1.0; - if (shadowCoord.x > 0.0 && shadowCoord.x < 1.0) { - if (shadowCoord.y > 0.0 && shadowCoord.y < 1.0) { - visibility = texture(shadowMap, biasedShadowCoord); - //if (texture(shadowMap, vec3(shadowCoord), bias) < shadowCoord.z) { - //visibility = 0.5; - //} + if (distanceToBorder(shadowCoord_middle.xy) <= 0.5 && distanceToBorder(shadowCoord_middle.xy) > 0.0) { + if (distanceToBorder(shadowCoord_near.xy) <= 0.5 && distanceToBorder(shadowCoord_near.xy) > 0.0) { + visibility = sampleShadow(shadowMap_near, shadowCoord_near); } + else { + visibility = sampleShadow(shadowMap_middle, shadowCoord_middle); + } + } + else { + visibility = sampleShadow(shadowMap_far, shadowCoord_far); } specularColor *= visibility; diff --git a/Shader/phong.vsh b/Shader/phong.vsh index df35a04..d2f840e 100644 --- a/Shader/phong.vsh +++ b/Shader/phong.vsh @@ -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); } diff --git a/graphics.cc b/graphics.cc index 9f2bf18..a506a64 100644 --- a/graphics.cc +++ b/graphics.cc @@ -29,19 +29,41 @@ void Graphics::init() { lightingShader = ShaderProgramCreator("phong").attributeLocations( vao->getAttributeLocations()).create(); - depthTexture = SharedTexture2D( new Texture2D(glm::vec2(windowSize.x, windowSize.y), 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->setWrapS(GL_CLAMP_TO_EDGE); + depthTexture_near->setWrapT(GL_CLAMP_TO_EDGE); + 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->setWrapS(GL_CLAMP_TO_EDGE); + depthTexture_middle->setWrapT(GL_CLAMP_TO_EDGE); + 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->setWrapS(GL_CLAMP_TO_EDGE); + depthTexture_far->setWrapT(GL_CLAMP_TO_EDGE); + 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,23 +77,44 @@ 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); - glCullFace(GL_FRONT); depthShader->use(); glm::vec3 sunVector = (level->getCameraCenter()->getPosition() + level->getDirectionalLight()->getPosition()); - glm::mat4 depthViewProjectionMatrix = glm::ortho(-20, 20, -20, 20, -20, 40) * + glm::mat4 depthViewProjectionMatrix_near = glm::ortho(-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(-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(-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"); } // final render pass glBindFramebuffer(GL_FRAMEBUFFER, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glCullFace(GL_BACK); lightingShader->use(); @@ -87,10 +130,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) { @@ -144,7 +193,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) { diff --git a/graphics.hh b/graphics.hh index 73aa112..a807d11 100644 --- a/graphics.hh +++ b/graphics.hh @@ -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 diff --git a/material.cc b/material.cc index b8639fd..d084f5e 100644 --- a/material.cc +++ b/material.cc @@ -3,6 +3,7 @@ Material::Material(std::string filePath, float ambientFactor, float diffuseFactor, float specularFactor, float shininess) { reference = ACGL::OpenGL::Texture2DFileManager::the()->get(ACGL::OpenGL::Texture2DCreator(filePath)); + reference->generateMipmaps(); this->ambientFactor = ambientFactor; this->diffuseFactor = diffuseFactor; this->specularFactor = specularFactor;