diff --git a/OpenGL/playground/output b/OpenGL/playground/output index 6674933..4047b67 100755 Binary files a/OpenGL/playground/output and b/OpenGL/playground/output differ diff --git a/OpenGL/playground/resources/shaders/phong.frag b/OpenGL/playground/resources/shaders/phong.frag index 0efa591..f7d6b5e 100644 --- a/OpenGL/playground/resources/shaders/phong.frag +++ b/OpenGL/playground/resources/shaders/phong.frag @@ -2,27 +2,46 @@ in vec3 Normal; in vec3 FragPos; +in vec4 FragPosLightSpace; uniform vec3 lightPos; -vec3 viewPos = vec3(0.0, 0.0, 0.0); out vec4 outColour; +uniform sampler2D diffuseTexture; +uniform sampler2D shadowMap; + +vec3 viewPos = vec3(0.0, 0.0, 0.0); vec3 objectColour = vec3(0.58, 0.61, 0.627); vec3 lightColour = vec3(0.1, 0.45, 0.9); +float calculateShadow(vec4 fragPosLightSpace) { + // perform perspective divide + vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w; + // transform to [0,1] range + projCoords = projCoords * 0.5 + 0.5; + // get closest depth value from light's perspective (using [0,1] range fragPosLight as coords) + float closestDepth = texture(shadowMap, projCoords.xy).r; + // get depth of current fragment from light's perspective + float currentDepth = projCoords.z; + // check whether current frag pos is in shadow + float shadow = currentDepth > closestDepth ? 1.0 : 0.0; + + return shadow; +} + void main() { - vec3 norm = normalize(Normal); + vec3 normal = normalize(Normal); vec3 lightDir = normalize(lightPos - FragPos); - float diff = max(dot(norm, lightDir), 0.0); + float diff = max(dot(normal, lightDir), 0.0); vec3 diffuse = diff * lightColour; float specularStrength = 5; vec3 viewDir = normalize(viewPos - FragPos); - vec3 reflectDir = reflect(-lightDir, norm); + vec3 reflectDir = reflect(-lightDir, normal); float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32); vec3 specular = specularStrength * spec * lightColour; @@ -31,6 +50,8 @@ void main() { float ambientStrength = 0.2; vec3 ambient = ambientStrength * lightColour; - vec3 result = (ambient + diffuse + specular) * objectColour; + float shadow = calculateShadow(FragPosLightSpace); + vec3 result = (ambient + (1.0 - shadow) * (diffuse + specular)) * objectColour; + outColour = vec4(result, 1.0); } diff --git a/OpenGL/playground/resources/shaders/phong.vert b/OpenGL/playground/resources/shaders/phong.vert index a18e40c..e59af72 100644 --- a/OpenGL/playground/resources/shaders/phong.vert +++ b/OpenGL/playground/resources/shaders/phong.vert @@ -5,13 +5,17 @@ in vec3 normal; out vec3 Normal; out vec3 FragPos; +out vec4 FragPosLightSpace; uniform mat4 model; uniform mat4 view; uniform mat4 proj; +uniform mat4 lightSpaceMatrix; + void main() { gl_Position = proj * view * model * vec4(position, 1.0); FragPos = vec3(model * vec4(position, 1.0)); + FragPosLightSpace = lightSpaceMatrix * vec4(FragPos, 1.0); Normal = mat3(model) * normal; } diff --git a/OpenGL/playground/resources/shaders/shadowmap.frag b/OpenGL/playground/resources/shaders/shadowmap.frag new file mode 100644 index 0000000..a963b55 --- /dev/null +++ b/OpenGL/playground/resources/shaders/shadowmap.frag @@ -0,0 +1,7 @@ +#version 330 + +out float fragdepth; + +void main(){ + gl_FragDepth = gl_FragCoord.z; +} diff --git a/OpenGL/playground/resources/shaders/shadowmap.vert b/OpenGL/playground/resources/shaders/shadowmap.vert new file mode 100644 index 0000000..39a2f35 --- /dev/null +++ b/OpenGL/playground/resources/shaders/shadowmap.vert @@ -0,0 +1,10 @@ +#version 330 + +in vec3 vertPos; + +uniform mat4 lightSpaceMatrix; +uniform mat4 model; + +void main() { + gl_Position = lightSpaceMatrix * model * vec4(vertPos, 1.0); +} diff --git a/OpenGL/playground/src/main.cpp b/OpenGL/playground/src/main.cpp index 738fd56..9426553 100644 --- a/OpenGL/playground/src/main.cpp +++ b/OpenGL/playground/src/main.cpp @@ -90,6 +90,11 @@ int main(int argc, char** argv) { SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 32); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + // MXAA + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4); + SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "4"); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 5); @@ -102,7 +107,6 @@ int main(int argc, char** argv) { glContext = SDL_GL_CreateContext(window); SDL_GL_SetSwapInterval(1); - gladLoadGLLoader(SDL_GL_GetProcAddress); // SDL_SetRelativeMouseMode(SDL_TRUE); // SDL_WarpMouseInWindow(window, 0, 0); @@ -169,6 +173,7 @@ int main(int argc, char** argv) { GLint uniTrans = glGetUniformLocation(simpleShader.getProgram(), "model"); glUniformMatrix4fv(uniTrans, 1, GL_FALSE, glm::value_ptr(model)); + // View matrice glm::mat4 view = glm::lookAt( glm::vec3(1.0f, 1.0f, 1.0f), @@ -180,45 +185,73 @@ int main(int argc, char** argv) { glUniformMatrix4fv(uniView, 1, GL_FALSE, glm::value_ptr(view)); // Projection matrice - // glm::mat4 proj = glm::perspective(glm::radians(45.0f), 640.0f / 480.0f, 1.0f, 1000.0f);//camera.perspective; glm::mat4 proj = glm::perspective(glm::radians(45.0f), 1280.0f / 720.0f, 1.0f, 1000.0f);//camera.perspective; // Get uniform and send it to the GPU GLint uniProj = glGetUniformLocation(simpleShader.getProgram(), "proj"); glUniformMatrix4fv(uniProj, 1, GL_FALSE, glm::value_ptr(proj)); - glm::vec3 lightPos = {100.0f, 100.0f, 0.0f}; //100.0f}; + glm::vec3 lightPos = {300.0f, 300.0f, 0.0f}; //100.0f}; + + // Make shadowmap + + glm::vec3 lightInvDir = glm::vec3(0.5f, 2, 2); + + // Compute the MVP matrix from the light's point of view + glm::mat4 depthProjectionMatrix = glm::ortho(-10,10,-10,10,-10,20); + glm::mat4 depthViewMatrix = glm::lookAt(lightInvDir, glm::vec3(0,0,0), glm::vec3(0,1,0)); + glm::mat4 depthModelMatrix = glm::mat4(1.0); + glm::mat4 depthMVP = depthProjectionMatrix * depthViewMatrix * depthModelMatrix; + + Shader depthShader{ logger }; + depthShader.load("./resources/shaders/shadowmap").attatch().link().use(); + + GLuint unilightSpaceMatrix = glGetUniformLocation(depthShader.getProgram(), "lightSpaceMatrix"); + GLint uniLightTrans = glGetUniformLocation(depthShader.getProgram(), "model"); + glUniformMatrix4fv(uniLightTrans, 1, GL_FALSE, glm::value_ptr(model)); + + GLuint depthMapFBO; + glGenFramebuffers(1, &depthMapFBO); + + const unsigned int SHADOW_WIDTH = 1280, SHADOW_HEIGHT = 720; + + unsigned int depthMap; + glGenTextures(1, &depthMap); + glBindTexture(GL_TEXTURE_2D, depthMap); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, + SHADOW_WIDTH, SHADOW_HEIGHT, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + + glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthMap, 0); + glDrawBuffer(GL_NONE); + glReadBuffer(GL_NONE); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + GLint uniLight = glGetUniformLocation(simpleShader.getProgram(), "lightpos"); - glUniformMatrix4fv(uniLight, 1, GL_FALSE, glm::value_ptr(lightPos)); + glUniformMatrix3fv(uniLight, 1, GL_FALSE, glm::value_ptr(lightPos)); + + + GLint uniMlightSpaceMatrix = glGetUniformLocation(simpleShader.getProgram(), "lightSpaceMatrix"); + simpleShader.use(); glEnable(GL_DEPTH_TEST); + glEnable(GL_MULTISAMPLE); SDL_Event event; + logger << LOGGER_ENDL; while (isWindowOpen) { FPSCount(logger); // Update tick (60ups) if (UPSTimer()) { const Uint8 *state = SDL_GetKeyboardState(NULL); - - if (state[SDL_SCANCODE_W]) { - camera.pos.z += 0.01f * sin(glm::radians(camera.rot.y)); - camera.pos.x += 0.01f * cos(glm::radians(camera.rot.y)); - } - if (state[SDL_SCANCODE_S]) { - camera.pos.z -= 0.01f * sin(glm::radians(camera.rot.y)); - camera.pos.x -= 0.01f * cos(glm::radians(camera.rot.y)); - } - if (state[SDL_SCANCODE_A]) { - camera.pos.z -= 0.01f * cos(glm::radians(camera.rot.y)); - camera.pos.x += 0.01f * sin(glm::radians(camera.rot.y)); - } - if (state[SDL_SCANCODE_D]) { - camera.pos.z += 0.01f * cos(glm::radians(camera.rot.y)); - camera.pos.x -= 0.01f * sin(glm::radians(camera.rot.y)); - } - + if (state[SDL_SCANCODE_Q]) { model = glm::rotate(model, glm::radians(-1.5f), glm::vec3(0.0f, 1.0f, 0.0f)); glUniformMatrix4fv(uniTrans, 1, GL_FALSE, glm::value_ptr(model)); @@ -229,9 +262,6 @@ int main(int argc, char** argv) { glUniformMatrix4fv(uniTrans, 1, GL_FALSE, glm::value_ptr(model)); } - // glm::mat4 view = camera.getViewProj(); - // glUniformMatrix4fv(uniView, 1, GL_FALSE, glm::value_ptr(view)); - UpdateClock = SDL_GetTicks(); } @@ -248,12 +278,37 @@ int main(int argc, char** argv) { } } - // Clear + // 1. first render to depth map + glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT); + glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO); + glClear(GL_DEPTH_BUFFER_BIT); + depthShader.use(); + + float near_plane = 1.0f, far_plane = 1000.0f; + glm::mat4 lightProjection = glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, near_plane, far_plane); + + glm::mat4 lightView = glm::lookAt(glm::vec3(-2.0f, 4.0f, -1.0f), + glm::vec3( 0.0f, 0.0f, 0.0f), + glm::vec3( 0.0f, 1.0f, 0.0f)); + glm::mat4 lightSpaceMatrix = lightProjection * lightView; + + glUniformMatrix4fv(unilightSpaceMatrix, 1, GL_FALSE, glm::value_ptr(lightSpaceMatrix)); + glDrawElements(GL_TRIANGLES, elements.size(), GL_UNSIGNED_SHORT, 0); + + + glViewport(0, 0, 1280, 720); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glClear(GL_DEPTH_BUFFER_BIT); const float clear[] = {0.1f, 0.45f, 0.9f, 1.0f}; glClearBufferfv(GL_COLOR, 0, clear); - glClear(GL_DEPTH_BUFFER_BIT); - // Draw + simpleShader.use(); + + glUniformMatrix4fv(uniMlightSpaceMatrix, 1, GL_FALSE, glm::value_ptr(lightSpaceMatrix)); + + + glBindTexture(GL_TEXTURE_2D, depthMap); glDrawElements(GL_TRIANGLES, elements.size(), GL_UNSIGNED_SHORT, 0); + // Swap SDL_GL_SwapWindow(window); }