Add basis for variance shadow mapping
This commit is contained in:
parent
88611815e1
commit
3dcfc89b52
@ -60,9 +60,6 @@ vec2 get_parallax_offset_uv(vec2 uv, vec3 view_direction) {
|
||||
}
|
||||
|
||||
float get_shadow(vec4 fragPosLightSpace, vec3 normal) {
|
||||
// The bias varies depending on the angle to the light (the steeper the angle, the bigger the bias needs to be)
|
||||
mediump float bias = max(0.005 * (1.0 - dot(normal, fs_in.TangentLightDir)), 0.0005);
|
||||
|
||||
// perform perspective divide
|
||||
mediump vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
|
||||
// transform to [0,1] range
|
||||
@ -71,14 +68,25 @@ float get_shadow(vec4 fragPosLightSpace, vec3 normal) {
|
||||
// If we're outside of [0.0, 1.0] in the coordinates, return 0
|
||||
if (projCoords.x < 0.0 || projCoords.y < 0.0 || projCoords.x > 1.0 || projCoords.y > 1.0) return 0.0;
|
||||
|
||||
// Variance Shadow Map Calculation
|
||||
vec2 moments = texture(shadowMap, projCoords.xy).rg;
|
||||
|
||||
// get closest depth value from light's perspective (using [0,1] range fragPosLight as coords)
|
||||
mediump float closestDepth = texture(shadowMap, projCoords.xy).r;
|
||||
// get depth of current fragment from light's perspective
|
||||
mediump float currentDepth = projCoords.z;
|
||||
// check whether current frag pos is in shadow
|
||||
mediump float shadow = currentDepth - bias > closestDepth ? 1.0 : 0.0;
|
||||
float p = step(projCoords.z, moments.x);
|
||||
// We divide by this later, so make sure it's not exactly 0
|
||||
// It seems like it should always be 0.0, but due to interpolation it's not -- it increases with the deviation!
|
||||
float variance = max(moments.y - moments.x * moments.x, 0.00002);
|
||||
|
||||
return shadow;
|
||||
float d = projCoords.z - moments.x * 1.0; // bias should be "compare", what is that?
|
||||
float p_max = variance / (variance + d * d);
|
||||
|
||||
// If this pixel is exactly in the light, p is 1, so make sure we return that in that case
|
||||
// min() to make sure that it doesn't get greater than 1.0
|
||||
return 1.0 - min(max(p, p_max), 1.0);
|
||||
}
|
||||
|
||||
void main() {
|
||||
|
@ -2,6 +2,6 @@
|
||||
|
||||
void main()
|
||||
{
|
||||
// This happens implicitly anyways
|
||||
// gl_FragDepth = gl_FragCoord.z;
|
||||
// The mean and the mean squared, which we need to calculate the variance
|
||||
gl_FragColor = vec4(gl_FragCoord.z, gl_FragCoord.z * gl_FragCoord.z, 0.0, 0.0);
|
||||
}
|
@ -17,16 +17,16 @@ class DirectionalLight {
|
||||
// Create depth texture
|
||||
glGenTextures(1, &depth_map);
|
||||
glBindTexture(GL_TEXTURE_2D, depth_map);
|
||||
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);
|
||||
// R and G with 32 bit floats: stores mean and variance
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32F, SHADOW_WIDTH, SHADOW_HEIGHT, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
|
||||
// Attach depth texture as FBO's depth buffer
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, depth_map_fbo);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth_map, 0);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, depth_map, 0);
|
||||
glDrawBuffer(GL_NONE);
|
||||
glReadBuffer(GL_NONE);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
@ -43,8 +43,8 @@ class DirectionalLight {
|
||||
glBindTexture(GL_TEXTURE_2D, depth_map);
|
||||
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_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
|
||||
@ -96,8 +96,8 @@ class DirectionalLight {
|
||||
unsigned int depth_map;
|
||||
unsigned int depth_map_fbo;
|
||||
|
||||
const unsigned int SHADOW_WIDTH = 4096;
|
||||
const unsigned int SHADOW_HEIGHT = 4096;
|
||||
const unsigned int SHADOW_WIDTH = 2048;
|
||||
const unsigned int SHADOW_HEIGHT = 2048;
|
||||
|
||||
Gedeng::Shader shadow_shader;
|
||||
};
|
||||
|
@ -37,10 +37,10 @@ void renderQuad() {
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
class ShadowApp : public Gedeng::Application {
|
||||
class mesh3 : public Gedeng::Application {
|
||||
public:
|
||||
ShadowApp(unsigned long ms_per_update, unsigned int window_size_x, unsigned int window_size_y,
|
||||
Gedeng::String window_name)
|
||||
mesh3(unsigned long ms_per_update, unsigned int window_size_x, unsigned int window_size_y,
|
||||
Gedeng::String window_name)
|
||||
: Application(ms_per_update, window_size_x, window_size_y, window_name), particle_interval(0.2),
|
||||
number_of_steps(10.0), number_of_refinement_steps(10.0), bump_depth(0.1),
|
||||
render_shader(Gedeng::Shader("Shader/bump.vs", "Shader/bump.fs")),
|
||||
@ -53,7 +53,9 @@ class ShadowApp : public Gedeng::Application {
|
||||
particle_tex2("Resources/Textures/Particles/magic.png", Gedeng::Texture::Settings()),
|
||||
particle_tex3("Resources/Textures/Particles/smoke.png", Gedeng::Texture::Settings()),
|
||||
quad_mesh(Gedeng::QuadMesh(10.0)), light(glm::vec3(0.57735, -0.57735, 0.57735)),
|
||||
monkey_mesh("Resources/Meshes/Monkey.obj", Gedeng::ObjMesh::Settings()) {
|
||||
mesh1("Resources/Meshes/Monkey.obj", Gedeng::ObjMesh::Settings()),
|
||||
mesh2("Resources/Meshes/Monkey.obj", Gedeng::ObjMesh::Settings()),
|
||||
mesh3("Resources/Meshes/Monkey.obj", Gedeng::ObjMesh::Settings()) {
|
||||
particles.set_position(glm::vec3(0.0f, 0.0f, -10.0f));
|
||||
particles.set_velocity(glm::vec3(-2, 4, -2), glm::vec3(2, 6, 2));
|
||||
particles.set_gravity(glm::vec3(0, -4, 0));
|
||||
@ -67,10 +69,10 @@ class ShadowApp : public Gedeng::Application {
|
||||
camera.translate(glm::vec3(0.0, 2.0, 1.0));
|
||||
// camera.rotate(30, glm::vec3(1.0, 0.0, 0.0));
|
||||
|
||||
monkey_mesh.translate(glm::vec3(2.0, 3.0, -2.0));
|
||||
mesh1.translate(glm::vec3(2.0, 3.0, -2.0));
|
||||
}
|
||||
|
||||
~ShadowApp() = default;
|
||||
~mesh3() = default;
|
||||
|
||||
void fixed_update(double delta) override {
|
||||
camera.update(delta);
|
||||
@ -87,7 +89,7 @@ class ShadowApp : public Gedeng::Application {
|
||||
void dynamic_update(double delta) override {
|
||||
// Shadows
|
||||
light.clear_shadows();
|
||||
light.render_shadow(monkey_mesh);
|
||||
light.render_shadow(mesh1);
|
||||
light.render_shadow(quad_mesh);
|
||||
|
||||
glViewport(0, 0, 1920, 1080);
|
||||
@ -124,7 +126,7 @@ class ShadowApp : public Gedeng::Application {
|
||||
|
||||
// Props
|
||||
render_shader.use();
|
||||
monkey_mesh.render(render_shader);
|
||||
mesh1.render(render_shader);
|
||||
|
||||
/* // Render the light's depth map to a quad for debugging
|
||||
debug_shader.use();
|
||||
@ -159,10 +161,12 @@ class ShadowApp : public Gedeng::Application {
|
||||
Gedeng::ParticleSystem particles;
|
||||
|
||||
Gedeng::DirectionalLight light;
|
||||
Gedeng::ObjMesh monkey_mesh;
|
||||
Gedeng::ObjMesh mesh1;
|
||||
Gedeng::ObjMesh mesh2;
|
||||
Gedeng::ObjMesh mesh3;
|
||||
};
|
||||
|
||||
Gedeng::Application *Gedeng::create_application() {
|
||||
GG_CLIENT_INFO("Creating Application");
|
||||
return new ShadowApp(20, 1920, 1080, String("Parallax Demo"));
|
||||
return new mesh3(20, 1920, 1080, String("Parallax Demo"));
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user