Add PCF shadows

This commit is contained in:
s464910 2023-02-10 16:01:48 +01:00
parent cbec151054
commit 0d48e6ee37
7 changed files with 172 additions and 9 deletions

View File

@ -41,6 +41,8 @@
<None Include="shaders\shader_9_1.vert" /> <None Include="shaders\shader_9_1.vert" />
<None Include="shaders\shader_8_sun.frag" /> <None Include="shaders\shader_8_sun.frag" />
<None Include="shaders\shader_8_sun.vert" /> <None Include="shaders\shader_8_sun.vert" />
<None Include="shaders\shader_depth.frag" />
<None Include="shaders\shader_depth.vert" />
<None Include="shaders\test.frag" /> <None Include="shaders\test.frag" />
<None Include="shaders\test.vert" /> <None Include="shaders\test.vert" />
</ItemGroup> </ItemGroup>

View File

@ -109,5 +109,11 @@
<None Include="shaders\test.vert"> <None Include="shaders\test.vert">
<Filter>Shader Files</Filter> <Filter>Shader Files</Filter>
</None> </None>
<None Include="shaders\shader_depth.frag">
<Filter>Shader Files</Filter>
</None>
<None Include="shaders\shader_depth.vert">
<Filter>Shader Files</Filter>
</None>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -1,4 +1,4 @@
#version 430 core #version 430 core
float AMBIENT = 0.03; float AMBIENT = 0.03;
float PI = 3.14; float PI = 3.14;
@ -38,6 +38,25 @@ in vec3 sunDirTS;
in vec3 test; 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 DistributionGGX(vec3 normal, vec3 H, float roughness){
float a = roughness*roughness; float a = roughness*roughness;
float a2 = a*a; 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; 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() void main()
{ {
@ -125,9 +179,12 @@ void main()
attenuatedlightColor = angle_atenuation*spotlightColor/pow(length(spotlightPos-worldPos),2); attenuatedlightColor = angle_atenuation*spotlightColor/pow(length(spotlightPos-worldPos),2);
ilumination=ilumination+PBRLight(spotlightDir,attenuatedlightColor,normal,viewDir); ilumination=ilumination+PBRLight(spotlightDir,attenuatedlightColor,normal,viewDir);
//sun // obliczanie cienia
ilumination=ilumination+PBRLight(sunDir,sunColor,normal,viewDir); 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(vec3(1.0) - exp(-ilumination*exposition),1);
//outColor = vec4(roughness,metallic,0,1); //outColor = vec4(roughness,metallic,0,1);

View File

@ -1,4 +1,4 @@
#version 430 core #version 430 core
layout(location = 0) in vec3 vertexPosition; layout(location = 0) in vec3 vertexPosition;
layout(location = 1) in vec3 vertexNormal; layout(location = 1) in vec3 vertexNormal;
@ -8,6 +8,7 @@ layout(location = 4) in vec3 vertexBitangent;
uniform mat4 transformation; uniform mat4 transformation;
uniform mat4 modelMatrix; uniform mat4 modelMatrix;
uniform mat4 lightVP;
out vec3 vecNormal; out vec3 vecNormal;
out vec3 worldPos; out vec3 worldPos;
@ -22,6 +23,9 @@ out vec3 lightDirTS;
out vec3 spotlightDirTS; out vec3 spotlightDirTS;
out vec3 sunDirTS; out vec3 sunDirTS;
out vec4 sunSpacePos;
void main() void main()
{ {
worldPos = (modelMatrix* vec4(vertexPosition,1)).xyz; worldPos = (modelMatrix* vec4(vertexPosition,1)).xyz;
@ -40,4 +44,7 @@ void main()
spotlightDirTS = TBN*SL; spotlightDirTS = TBN*SL;
sunDirTS = TBN*sunDir; sunDirTS = TBN*sunDir;
// przeliczanie pozycji światła
sunSpacePos = lightVP * modelMatrix * vec4(vertexPosition, 1);
} }

View File

@ -0,0 +1,5 @@
#version 430 core
void main()
{
}

View File

@ -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);
}

View File

@ -43,6 +43,7 @@ GLuint program;
GLuint programSun; GLuint programSun;
GLuint programTest; GLuint programTest;
GLuint programTex; GLuint programTex;
GLuint programDepth;
Core::Shader_Loader shaderLoader; 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 sunDir = glm::vec3(-0.93633f, 0.351106, 0.003226f);
glm::vec3 sunColor = glm::vec3(0.9f, 0.9f, 0.7f)*5; 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 cameraPos = glm::vec3(0.479490f, 1.250000f, -2.124680f);
glm::vec3 cameraDir = glm::vec3(-0.354510f, 0.000000f, 0.935054f); 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, "spotlightPos"), spotlightPos.x, spotlightPos.y, spotlightPos.z);
glUniform3f(glGetUniformLocation(program, "spotlightColor"), spotlightColor.x, spotlightColor.y, spotlightColor.z); glUniform3f(glGetUniformLocation(program, "spotlightColor"), spotlightColor.x, spotlightColor.y, spotlightColor.z);
glUniform1f(glGetUniformLocation(program, "spotlightPhi"), spotlightPhi); 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); 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(); float time = glfwGetTime();
glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT); 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); glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0, 0, WIDTH, HEIGHT); glViewport(0, 0, WIDTH, HEIGHT);
@ -175,7 +237,9 @@ void renderScene(GLFWwindow* window)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
float time = glfwGetTime(); float time = glfwGetTime();
updateDeltaTime(time); updateDeltaTime(time);
renderShadowapSun();
// wywołanie funkcji renderowania depth mapy
renderShadowapSun(lightVP);
//space lamp //space lamp
glUseProgram(programSun); glUseProgram(programSun);
@ -265,11 +329,17 @@ void init(GLFWwindow* window)
{ {
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
// enable testowania mapy głębokości
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
program = shaderLoader.CreateProgram("shaders/shader_9_1.vert", "shaders/shader_9_1.frag"); program = shaderLoader.CreateProgram("shaders/shader_9_1.vert", "shaders/shader_9_1.frag");
programTest = shaderLoader.CreateProgram("shaders/test.vert", "shaders/test.frag"); programTest = shaderLoader.CreateProgram("shaders/test.vert", "shaders/test.frag");
programSun = shaderLoader.CreateProgram("shaders/shader_8_sun.vert", "shaders/shader_8_sun.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/sphere.obj", sphereContext);
loadModelToContext("./models/spaceship.obj", shipContext); loadModelToContext("./models/spaceship.obj", shipContext);
@ -289,6 +359,9 @@ void init(GLFWwindow* window)
loadModelToContext("./models/window.obj", models::windowContext); loadModelToContext("./models/window.obj", models::windowContext);
loadModelToContext("./models/test.obj", models::testContext); loadModelToContext("./models/test.obj", models::testContext);
// inicjalizacja mapy głębokości
initDepthMap();
} }
void shutdown(GLFWwindow* window) void shutdown(GLFWwindow* window)