Improved the shadows with a larger texture, PCF for the edges, and only calculating the shadows once.
This commit is contained in:
parent
621c355876
commit
4747d297e8
4 changed files with 49 additions and 25 deletions
|
|
@ -84,11 +84,11 @@
|
||||||
{"model": "human", "position": [1.28, 0.0, 1.85],
|
{"model": "human", "position": [1.28, 0.0, 1.85],
|
||||||
"rotation": {"angle": 0.0, "axes": [1.0, 1.0, 1.0]},
|
"rotation": {"angle": 0.0, "axes": [1.0, 1.0, 1.0]},
|
||||||
"scale": 1.0,
|
"scale": 1.0,
|
||||||
"material": "shiny"},
|
"material": "default"},
|
||||||
{"model": "human", "position": [3.13, 0.80, 3.04],
|
{"model": "human", "position": [3.13, 0.80, 3.04],
|
||||||
"rotation": {"angle": 0.0, "axes": [1.0, 1.0, 1.0]},
|
"rotation": {"angle": 0.0, "axes": [1.0, 1.0, 1.0]},
|
||||||
"scale": 1.0,
|
"scale": 1.0,
|
||||||
"material": "shiny"},
|
"material": "default"},
|
||||||
{"model": "window", "position": [1.5, 0.25, 0.0],
|
{"model": "window", "position": [1.5, 0.25, 0.0],
|
||||||
"rotation": {"angle": 90.0, "axes": [1.0,0.0,0.0]},
|
"rotation": {"angle": 90.0, "axes": [1.0,0.0,0.0]},
|
||||||
"scale": 1.0,
|
"scale": 1.0,
|
||||||
|
|
@ -107,8 +107,6 @@
|
||||||
},
|
},
|
||||||
"light": {
|
"light": {
|
||||||
"directional": [
|
"directional": [
|
||||||
],
|
|
||||||
"positioned": [
|
|
||||||
{
|
{
|
||||||
"position": [-2.0, 4.0, -1.0],
|
"position": [-2.0, 4.0, -1.0],
|
||||||
"direction":[0.0, 0.0, 0.0],
|
"direction":[0.0, 0.0, 0.0],
|
||||||
|
|
@ -123,6 +121,8 @@
|
||||||
"on": true
|
"on": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"positioned": [
|
||||||
|
],
|
||||||
"spot": [
|
"spot": [
|
||||||
],
|
],
|
||||||
"camera": {
|
"camera": {
|
||||||
|
|
|
||||||
|
|
@ -16,17 +16,31 @@ float ShadowCalculation(vec4 fragPosLightSpace, float bias)
|
||||||
{
|
{
|
||||||
// perform perspective divide
|
// perform perspective divide
|
||||||
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
|
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
|
||||||
|
|
||||||
// transform to [0,1] range
|
// transform to [0,1] range
|
||||||
projCoords = projCoords * 0.5 + 0.5;
|
projCoords = projCoords * 0.5 + 0.5;
|
||||||
|
|
||||||
|
// avoid the frustrum
|
||||||
|
if(projCoords.z > 1.0) return 0.0;
|
||||||
|
|
||||||
// get closest depth value from light's perspective (using [0,1] range fragPosLight as coords)
|
// get closest depth value from light's perspective (using [0,1] range fragPosLight as coords)
|
||||||
float closestDepth = texture(shadowMap, projCoords.xy).r;
|
float closestDepth = texture(shadowMap, projCoords.xy).r;
|
||||||
|
|
||||||
// get depth of current fragment from light's perspective
|
// get depth of current fragment from light's perspective
|
||||||
float currentDepth = projCoords.z;
|
float currentDepth = projCoords.z;
|
||||||
|
|
||||||
// check whether current frag pos is in shadow
|
// check whether current frag pos is in shadow
|
||||||
|
// PCF
|
||||||
|
float shadow = 0.0;
|
||||||
|
vec2 texelSize = 1.0 / textureSize(shadowMap, 0);
|
||||||
|
for(int x = -1; x <= 1; ++x) {
|
||||||
|
for(int y = -1; y <= 1; ++y) {
|
||||||
|
float pcfDepth = texture(shadowMap, projCoords.xy + vec2(x, y) * texelSize).r;
|
||||||
|
shadow += currentDepth - bias > pcfDepth ? 1.0 : 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
float shadow = currentDepth - bias > closestDepth ? 1.0 : 0.0;
|
return shadow / 9.0;
|
||||||
|
|
||||||
return shadow;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
|
|
|
||||||
|
|
@ -53,9 +53,17 @@ void Scene::render_scene(GLFWwindow* window, Shader& with_shader) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::render_shadows(GLFWwindow* window) {
|
void Scene::render_shadows(GLFWwindow* window) {
|
||||||
// temporarily use the config.json positioned even though this is doing a directional
|
|
||||||
auto& light_pos = light.positioned.at(0).position;
|
|
||||||
|
|
||||||
|
glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT);
|
||||||
|
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, depth_FBO);
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glClear(GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
// temporarily use the config.json positioned even though this is doing a directional
|
||||||
|
for(auto& dir_light : light.directional) {
|
||||||
|
auto& light_pos = dir_light.position;
|
||||||
glm::mat4 proj = glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, depth_near_plane, depth_far_plane);
|
glm::mat4 proj = glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, depth_near_plane, depth_far_plane);
|
||||||
glm::mat4 view = glm::lookAt(light_pos, glm::vec3(0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
|
glm::mat4 view = glm::lookAt(light_pos, glm::vec3(0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
|
||||||
|
|
||||||
|
|
@ -66,14 +74,8 @@ void Scene::render_shadows(GLFWwindow* window) {
|
||||||
depth_shader.setFloat("near_plane", depth_near_plane);
|
depth_shader.setFloat("near_plane", depth_near_plane);
|
||||||
depth_shader.setFloat("far_plane", depth_far_plane);
|
depth_shader.setFloat("far_plane", depth_far_plane);
|
||||||
|
|
||||||
glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT);
|
|
||||||
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, depth_FBO);
|
|
||||||
glEnable(GL_DEPTH_TEST);
|
|
||||||
glClear(GL_DEPTH_BUFFER_BIT);
|
|
||||||
|
|
||||||
render_scene(window, depth_shader);
|
render_scene(window, depth_shader);
|
||||||
|
}
|
||||||
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
|
@ -84,7 +86,10 @@ void Scene::render_shadows(GLFWwindow* window) {
|
||||||
void Scene::render(GLFWwindow* window) {
|
void Scene::render(GLFWwindow* window) {
|
||||||
auto& with_shader = reflect_on ? reflect_shader : shader;
|
auto& with_shader = reflect_on ? reflect_shader : shader;
|
||||||
|
|
||||||
|
if(!shadows_rendered) {
|
||||||
|
shadows_rendered = true;
|
||||||
render_shadows(window);
|
render_shadows(window);
|
||||||
|
}
|
||||||
|
|
||||||
// set depth_map on TEXTURE0
|
// set depth_map on TEXTURE0
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
|
@ -94,7 +99,7 @@ void Scene::render(GLFWwindow* window) {
|
||||||
with_shader.setInt("shadowMap", 0);
|
with_shader.setInt("shadowMap", 0);
|
||||||
// NOTE: in the shader is it viewPos or cameraPos?
|
// NOTE: in the shader is it viewPos or cameraPos?
|
||||||
with_shader.setVec3("viewPos", camera.position);
|
with_shader.setVec3("viewPos", camera.position);
|
||||||
with_shader.setVec3("lightPos", light.positioned.at(0).position);
|
with_shader.setVec3("lightPos", light.directional.at(0).position);
|
||||||
with_shader.setMat4("lightSpaceMatrix", light_space);
|
with_shader.setMat4("lightSpaceMatrix", light_space);
|
||||||
|
|
||||||
framebuffer.begin();
|
framebuffer.begin();
|
||||||
|
|
@ -153,8 +158,11 @@ void Scene::init_shadows() {
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, SHADOW_WIDTH, SHADOW_HEIGHT, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
|
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_MIN_FILTER, GL_NEAREST);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
// set to clamp border with a color of one to remove the frustrum culled part of the shadow
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
|
||||||
|
float border_color[4]{1.0f, 1.0f, 1.0f, 1.0f};
|
||||||
|
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border_color);
|
||||||
|
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth_map, 0);
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth_map, 0);
|
||||||
glDrawBuffer(GL_NONE);
|
glDrawBuffer(GL_NONE);
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ struct Scene {
|
||||||
Shader depth_dbg_shader{{"shaders/33-shadow_dbg.vert.glsl", "shaders/33-shadow_dbg.frag.glsl", ""}};
|
Shader depth_dbg_shader{{"shaders/33-shadow_dbg.vert.glsl", "shaders/33-shadow_dbg.frag.glsl", ""}};
|
||||||
unsigned int depth_FBO = UINT_MAX;
|
unsigned int depth_FBO = UINT_MAX;
|
||||||
unsigned int depth_map = UINT_MAX;
|
unsigned int depth_map = UINT_MAX;
|
||||||
const unsigned int SHADOW_WIDTH = 1024, SHADOW_HEIGHT = 1024;
|
const unsigned int SHADOW_WIDTH = 1024 * 8, SHADOW_HEIGHT = 1024 * 8;
|
||||||
float near_plane = 1.0f;
|
float near_plane = 1.0f;
|
||||||
float far_plane = 100.0f;
|
float far_plane = 100.0f;
|
||||||
|
|
||||||
|
|
@ -74,6 +74,8 @@ struct Scene {
|
||||||
unsigned int quadVAO = UINT_MAX;
|
unsigned int quadVAO = UINT_MAX;
|
||||||
unsigned int quadVBO = UINT_MAX;
|
unsigned int quadVBO = UINT_MAX;
|
||||||
|
|
||||||
|
bool shadows_rendered = false;
|
||||||
|
|
||||||
Scene(components::Scene& config):
|
Scene(components::Scene& config):
|
||||||
shader{config.shader},
|
shader{config.shader},
|
||||||
reflect_shader{config.reflect_shader},
|
reflect_shader{config.reflect_shader},
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue