From 0d48e6ee3732de2029c32c558a8b74f49f4111c6 Mon Sep 17 00:00:00 2001 From: s464910 Date: Fri, 10 Feb 2023 16:01:48 +0100 Subject: [PATCH] Add PCF shadows --- cw 9/grk-cw9.vcxproj | 2 + cw 9/grk-cw9.vcxproj.filters | 6 +++ cw 9/shaders/shader_9_1.frag | 63 ++++++++++++++++++++++++-- cw 9/shaders/shader_9_1.vert | 9 +++- cw 9/shaders/shader_depth.frag | 5 ++ cw 9/shaders/shader_depth.vert | 13 ++++++ cw 9/src/ex_9_1.hpp | 83 ++++++++++++++++++++++++++++++++-- 7 files changed, 172 insertions(+), 9 deletions(-) create mode 100644 cw 9/shaders/shader_depth.frag create mode 100644 cw 9/shaders/shader_depth.vert diff --git a/cw 9/grk-cw9.vcxproj b/cw 9/grk-cw9.vcxproj index b51b6a7..40b6dd9 100644 --- a/cw 9/grk-cw9.vcxproj +++ b/cw 9/grk-cw9.vcxproj @@ -41,6 +41,8 @@ + + diff --git a/cw 9/grk-cw9.vcxproj.filters b/cw 9/grk-cw9.vcxproj.filters index a2b8ba9..4fe3a9a 100644 --- a/cw 9/grk-cw9.vcxproj.filters +++ b/cw 9/grk-cw9.vcxproj.filters @@ -109,5 +109,11 @@ Shader Files + + Shader Files + + + Shader Files + \ No newline at end of file diff --git a/cw 9/shaders/shader_9_1.frag b/cw 9/shaders/shader_9_1.frag index 550f6c1..295bef9 100644 --- a/cw 9/shaders/shader_9_1.frag +++ b/cw 9/shaders/shader_9_1.frag @@ -1,4 +1,4 @@ -#version 430 core +#version 430 core float AMBIENT = 0.03; float PI = 3.14; @@ -38,6 +38,25 @@ in vec3 sunDirTS; in vec3 test; +// wektor przechowujący punkt widzenia światła +in vec4 sunSpacePos; + +// mapa przechowująca wartość cieni +uniform sampler2D shadowMap; + +// zmienne przechowujące szerokość i wysokość mapy cieni +uniform float shadowMapWidth; +uniform float shadowMapHeight; + +// zmienne do PCF - Percentage Closer Filtering + +// promień pixeli - np. 2 oznacza badanie na szerokość 5 bo 2 + 1 + 2 +const int pcfCount = 8; + +// ilość wszystkich pixeli - (2 * promień + 1) ^ 2 +const float totalTexels = (pcfCount * 2.0 + 1.0) * (pcfCount * 2.0 + 1.0); + + float DistributionGGX(vec3 normal, vec3 H, float roughness){ float a = roughness*roughness; float a2 = a*a; @@ -98,6 +117,41 @@ vec3 PBRLight(vec3 lightDir, vec3 radiance, vec3 normal, vec3 V){ return (kD * color / PI + specular) * radiance * NdotL; } +// metoda obliczająca cień za pomocą PCF + +float calculateShadow(vec4 lightPos, sampler2D Shadow_Map){ + // ujednorodnienie pozycji światła + vec3 _lightPos = lightPos.xyz/lightPos.w; + + // skalowanie z wartości (-1, 1) do wartości (0, 1) + _lightPos = _lightPos * 0.5 + 0.5; + + // ustalenie wielości texeli + double TexelWidth = 1.0/shadowMapWidth; + double TexelHeight = 1.0/shadowMapHeight; + + vec2 TexelSize = vec2(TexelWidth, TexelHeight); + + // zmienna przechowująca wartość cienia + float shadowSum = 0.0; + + // algorytm PCF + for (int y = -pcfCount ; y <= pcfCount ; y++) { + for (int x = -pcfCount ; x <= pcfCount ; x++) { + // liczymi wartości (x, y) z przesunięciem + vec2 Offset = vec2(x, y) * TexelSize; + + // sprawdzenie wartości z dpeth map oraz przypisanie odpowiedniej wartości dla shadow + float shadow = _lightPos.z > texture(Shadow_Map, _lightPos.xy + Offset).r + 0.001 ? 1.0 : 0.0; + + // dodanie wartości do shadow + shadowSum += shadow; + } + } + + // zwrócenie średniej wartości cieni z wszystkich pixeli wokół + return ((shadowSum/totalTexels)/lightPos.w); +} void main() { @@ -125,9 +179,12 @@ void main() attenuatedlightColor = angle_atenuation*spotlightColor/pow(length(spotlightPos-worldPos),2); ilumination=ilumination+PBRLight(spotlightDir,attenuatedlightColor,normal,viewDir); - //sun - ilumination=ilumination+PBRLight(sunDir,sunColor,normal,viewDir); + // obliczanie cienia + float shadow = calculateShadow(sunSpacePos, shadowMap); + //sun + // zaaplikowanie cienia do koloru światła. + ilumination = ilumination + PBRLight(sunDir,sunColor * (1.0 - shadow), normal, viewDir); outColor = vec4(vec3(1.0) - exp(-ilumination*exposition),1); //outColor = vec4(roughness,metallic,0,1); diff --git a/cw 9/shaders/shader_9_1.vert b/cw 9/shaders/shader_9_1.vert index 750196d..b730af8 100644 --- a/cw 9/shaders/shader_9_1.vert +++ b/cw 9/shaders/shader_9_1.vert @@ -1,4 +1,4 @@ -#version 430 core +#version 430 core layout(location = 0) in vec3 vertexPosition; layout(location = 1) in vec3 vertexNormal; @@ -8,6 +8,7 @@ layout(location = 4) in vec3 vertexBitangent; uniform mat4 transformation; uniform mat4 modelMatrix; +uniform mat4 lightVP; out vec3 vecNormal; out vec3 worldPos; @@ -22,6 +23,9 @@ out vec3 lightDirTS; out vec3 spotlightDirTS; out vec3 sunDirTS; +out vec4 sunSpacePos; + + void main() { worldPos = (modelMatrix* vec4(vertexPosition,1)).xyz; @@ -40,4 +44,7 @@ void main() spotlightDirTS = TBN*SL; sunDirTS = TBN*sunDir; + // przeliczanie pozycji światła + sunSpacePos = lightVP * modelMatrix * vec4(vertexPosition, 1); + } diff --git a/cw 9/shaders/shader_depth.frag b/cw 9/shaders/shader_depth.frag new file mode 100644 index 0000000..ad0b0dd --- /dev/null +++ b/cw 9/shaders/shader_depth.frag @@ -0,0 +1,5 @@ +#version 430 core + +void main() +{ +} \ No newline at end of file diff --git a/cw 9/shaders/shader_depth.vert b/cw 9/shaders/shader_depth.vert new file mode 100644 index 0000000..c018240 --- /dev/null +++ b/cw 9/shaders/shader_depth.vert @@ -0,0 +1,13 @@ +#version 430 core + +layout(location = 0) in vec3 vertexPosition; +layout(location = 1) in vec3 vertexNormal; +layout(location = 2) in vec2 vertexTexCoord; + +uniform mat4 viewProjectionMatrix; +uniform mat4 modelMatrix; + +void main() +{ + gl_Position = viewProjectionMatrix * modelMatrix * vec4(vertexPosition, 1.0); +} \ No newline at end of file diff --git a/cw 9/src/ex_9_1.hpp b/cw 9/src/ex_9_1.hpp index 36f1cdc..ea0aa7e 100644 --- a/cw 9/src/ex_9_1.hpp +++ b/cw 9/src/ex_9_1.hpp @@ -43,6 +43,7 @@ GLuint program; GLuint programSun; GLuint programTest; GLuint programTex; +GLuint programDepth; Core::Shader_Loader shaderLoader; @@ -53,6 +54,10 @@ glm::vec3 sunPos = glm::vec3(-4.740971f, 2.149999f, 0.369280f); glm::vec3 sunDir = glm::vec3(-0.93633f, 0.351106, 0.003226f); glm::vec3 sunColor = glm::vec3(0.9f, 0.9f, 0.7f)*5; +// macierz light view point - punkt widzenia światła +glm::mat4 lightVP = glm::ortho(-4.f, 2.5f, -2.f, 5.f, 1.0f, 30.0f) * glm::lookAt(sunPos, sunPos - sunDir, glm::vec3(0, 1, 0)); + + glm::vec3 cameraPos = glm::vec3(0.479490f, 1.250000f, -2.124680f); glm::vec3 cameraDir = glm::vec3(-0.354510f, 0.000000f, 0.935054f); @@ -151,19 +156,76 @@ void drawObjectPBR(Core::RenderContext& context, glm::mat4 modelMatrix, glm::vec glUniform3f(glGetUniformLocation(program, "spotlightPos"), spotlightPos.x, spotlightPos.y, spotlightPos.z); glUniform3f(glGetUniformLocation(program, "spotlightColor"), spotlightColor.x, spotlightColor.y, spotlightColor.z); glUniform1f(glGetUniformLocation(program, "spotlightPhi"), spotlightPhi); + + + glUniform1f(glGetUniformLocation(program, "shadowMapWidth"), SHADOW_WIDTH); + glUniform1f(glGetUniformLocation(program, "shadowMapHeight"), SHADOW_HEIGHT); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, depthMap); + glUniformMatrix4fv(glGetUniformLocation(program, "lightVP"), 1, GL_FALSE, (float*)&lightVP); + Core::DrawContext(context); } -void renderShadowapSun() { + +// metoda inicjalizująca mapę głębokości +void initDepthMap() { + glGenFramebuffers(1, &depthMapFBO); + + 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); +} + +// metoda renderująca obiekt na mapie głębokości +void drawObjectDepth(Core::RenderContext& context, glm::mat4 modelMatrix, glm::mat4 viewProjectionMatrix) { + glUniformMatrix4fv(glGetUniformLocation(programDepth, "modelMatrix"), 1, GL_FALSE, (float*)&modelMatrix); + glUniformMatrix4fv(glGetUniformLocation(programDepth, "viewProjectionMatrix"), 1, GL_FALSE, (float*)&viewProjectionMatrix); + Core::DrawContext(context); +} + +// renderowanie mapy głębokości +void renderShadowapSun(glm::mat4 lightViewPointMatrix) { float time = glfwGetTime(); glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT); - //uzupelnij o renderowanie glebokosci do tekstury - - + //ustawianie przestrzeni rysowania + glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT); + //bindowanie FBO + glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO); + //czyszczenie mapy głębokości + glClear(GL_DEPTH_BUFFER_BIT); + //ustawianie programu depth + glUseProgram(programDepth); + // umieszczenie w mapie wszystkich modeli które mają rzucać cień + drawObjectDepth(models::bedContext, glm::mat4(), lightViewPointMatrix); + drawObjectDepth(models::chairContext, glm::mat4(), lightViewPointMatrix); + drawObjectDepth(models::deskContext, glm::mat4(), lightViewPointMatrix); + drawObjectDepth(models::doorContext, glm::mat4(), lightViewPointMatrix); + drawObjectDepth(models::drawerContext, glm::mat4(), lightViewPointMatrix); + drawObjectDepth(models::marbleBustContext, glm::mat4(), lightViewPointMatrix); + drawObjectDepth(models::materaceContext, glm::mat4(), lightViewPointMatrix); + drawObjectDepth(models::pencilsContext, glm::mat4(), lightViewPointMatrix); + drawObjectDepth(models::planeContext, glm::mat4(), lightViewPointMatrix); + drawObjectDepth(models::roomContext, glm::mat4(), lightViewPointMatrix); + drawObjectDepth(models::windowContext, glm::mat4(), lightViewPointMatrix); + glUseProgram(0); glBindFramebuffer(GL_FRAMEBUFFER, 0); glViewport(0, 0, WIDTH, HEIGHT); @@ -175,7 +237,9 @@ void renderScene(GLFWwindow* window) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); float time = glfwGetTime(); updateDeltaTime(time); - renderShadowapSun(); + + // wywołanie funkcji renderowania depth mapy + renderShadowapSun(lightVP); //space lamp glUseProgram(programSun); @@ -265,10 +329,16 @@ void init(GLFWwindow* window) { glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); + // enable testowania mapy głębokości glEnable(GL_DEPTH_TEST); + + program = shaderLoader.CreateProgram("shaders/shader_9_1.vert", "shaders/shader_9_1.frag"); programTest = shaderLoader.CreateProgram("shaders/test.vert", "shaders/test.frag"); programSun = shaderLoader.CreateProgram("shaders/shader_8_sun.vert", "shaders/shader_8_sun.frag"); + + // program odpowiadający za generowanie mapy głębokości + programDepth = shaderLoader.CreateProgram("shaders/shader_depth.vert", "shaders/shader_depth.frag"); loadModelToContext("./models/sphere.obj", sphereContext); loadModelToContext("./models/spaceship.obj", shipContext); @@ -289,6 +359,9 @@ void init(GLFWwindow* window) loadModelToContext("./models/window.obj", models::windowContext); loadModelToContext("./models/test.obj", models::testContext); + // inicjalizacja mapy głębokości + initDepthMap(); + } void shutdown(GLFWwindow* window)