Added shadow maps
This commit is contained in:
1 parent
a47306533e
commit
d8795ec076
15 files changed
+880
-6
No files matched your search
@@ -0,0 +1,124 @@
|
||||
#include "ShadowMap.h"
|
||||
#include "Environment.h"
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
|
||||
namespace ZL {
|
||||
|
||||
// Build a look-at view matrix (column-major, same convention as the engine).
|
||||
static Eigen::Matrix4f lookAt(const Eigen::Vector3f& eye,
|
||||
const Eigen::Vector3f& center,
|
||||
const Eigen::Vector3f& up) {
|
||||
Eigen::Vector3f f = (center - eye).normalized();
|
||||
Eigen::Vector3f s = f.cross(up).normalized();
|
||||
Eigen::Vector3f u = s.cross(f);
|
||||
|
||||
Eigen::Matrix4f m = Eigen::Matrix4f::Identity();
|
||||
m(0, 0) = s.x(); m(0, 1) = s.y(); m(0, 2) = s.z();
|
||||
m(1, 0) = u.x(); m(1, 1) = u.y(); m(1, 2) = u.z();
|
||||
m(2, 0) = -f.x(); m(2, 1) = -f.y(); m(2, 2) = -f.z();
|
||||
|
||||
m(0, 3) = -s.dot(eye);
|
||||
m(1, 3) = -u.dot(eye);
|
||||
m(2, 3) = f.dot(eye);
|
||||
return m;
|
||||
}
|
||||
|
||||
// Build an orthographic projection matrix that matches the engine's
|
||||
// MakeOrthoMatrix(xmin, xmax, ymin, ymax, zNear, zFar) exactly.
|
||||
static Eigen::Matrix4f ortho(float left, float right,
|
||||
float bottom, float top,
|
||||
float zNear, float zFar) {
|
||||
float width = right - left;
|
||||
float height = top - bottom;
|
||||
float depthRange = zFar - zNear;
|
||||
|
||||
Eigen::Matrix4f m = Eigen::Matrix4f::Zero();
|
||||
m(0, 0) = 2.0f / width;
|
||||
m(1, 1) = 2.0f / height;
|
||||
m(2, 2) = -1.0f / depthRange;
|
||||
m(0, 3) = -(right + left) / width;
|
||||
m(1, 3) = -(top + bottom) / height;
|
||||
m(2, 3) = zNear / depthRange;
|
||||
m(3, 3) = 1.0f;
|
||||
return m;
|
||||
}
|
||||
|
||||
ShadowMap::ShadowMap(int res, float orthoSz, float zNear, float zFar)
|
||||
: resolution(res)
|
||||
, orthoSize(orthoSz)
|
||||
, nearPlane(zNear)
|
||||
, farPlane(zFar)
|
||||
, lightDirection(Eigen::Vector3f(-0.5f, -1.0f, -0.3f).normalized())
|
||||
, lightViewMatrix(Eigen::Matrix4f::Identity())
|
||||
, lightProjectionMatrix(Eigen::Matrix4f::Identity())
|
||||
, lightSpaceMatrix(Eigen::Matrix4f::Identity())
|
||||
{
|
||||
glGenFramebuffers(1, &fbo);
|
||||
|
||||
glGenTextures(1, &depthTexture);
|
||||
glBindTexture(GL_TEXTURE_2D, depthTexture);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT,
|
||||
resolution, resolution, 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_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
|
||||
GL_TEXTURE_2D, depthTexture, 0);
|
||||
|
||||
// No color buffer for this FBO — depth only.
|
||||
glDrawBuffer(GL_NONE);
|
||||
glReadBuffer(GL_NONE);
|
||||
|
||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
||||
std::cerr << "Error: Shadow map framebuffer is not complete!" << std::endl;
|
||||
}
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
ShadowMap::~ShadowMap() {
|
||||
if (fbo) glDeleteFramebuffers(1, &fbo);
|
||||
if (depthTexture) glDeleteTextures(1, &depthTexture);
|
||||
}
|
||||
|
||||
void ShadowMap::setLightDirection(const Eigen::Vector3f& dir) {
|
||||
lightDirection = dir.normalized();
|
||||
}
|
||||
|
||||
void ShadowMap::updateLightSpaceMatrix(const Eigen::Vector3f& sceneCenter) {
|
||||
// Place the light "camera" looking at the scene center from the light direction.
|
||||
Eigen::Vector3f lightPos = sceneCenter - lightDirection * (farPlane * 0.5f);
|
||||
|
||||
// Choose an up vector that isn't parallel to the light direction.
|
||||
Eigen::Vector3f up(0.0f, 1.0f, 0.0f);
|
||||
if (std::abs(lightDirection.dot(up)) > 0.99f) {
|
||||
up = Eigen::Vector3f(0.0f, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
lightViewMatrix = lookAt(lightPos, sceneCenter, up);
|
||||
|
||||
lightProjectionMatrix = ortho(
|
||||
-orthoSize, orthoSize,
|
||||
-orthoSize, orthoSize,
|
||||
nearPlane, farPlane);
|
||||
|
||||
lightSpaceMatrix = lightProjectionMatrix * lightViewMatrix;
|
||||
}
|
||||
|
||||
void ShadowMap::bind() {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
glViewport(0, 0, resolution, resolution);
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
void ShadowMap::unbind() {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glViewport(0, 0, Environment::width, Environment::height);
|
||||
}
|
||||
|
||||
} // namespace ZL
|
||||
@@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
#include "render/OpenGlExtensions.h"
|
||||
#include <Eigen/Dense>
|
||||
|
||||
namespace ZL {
|
||||
|
||||
class ShadowMap {
|
||||
private:
|
||||
GLuint fbo = 0;
|
||||
GLuint depthTexture = 0;
|
||||
int resolution;
|
||||
|
||||
Eigen::Vector3f lightDirection;
|
||||
Eigen::Matrix4f lightViewMatrix;
|
||||
Eigen::Matrix4f lightProjectionMatrix;
|
||||
Eigen::Matrix4f lightSpaceMatrix;
|
||||
|
||||
float orthoSize;
|
||||
float nearPlane;
|
||||
float farPlane;
|
||||
|
||||
public:
|
||||
ShadowMap(int resolution = 2048, float orthoSize = 40.0f,
|
||||
float zNear = 0.1f, float zFar = 100.0f);
|
||||
~ShadowMap();
|
||||
|
||||
ShadowMap(const ShadowMap&) = delete;
|
||||
ShadowMap& operator=(const ShadowMap&) = delete;
|
||||
|
||||
void setLightDirection(const Eigen::Vector3f& dir);
|
||||
void updateLightSpaceMatrix(const Eigen::Vector3f& sceneCenter);
|
||||
|
||||
void bind();
|
||||
void unbind();
|
||||
|
||||
GLuint getDepthTexture() const { return depthTexture; }
|
||||
int getResolution() const { return resolution; }
|
||||
const Eigen::Matrix4f& getLightSpaceMatrix() const { return lightSpaceMatrix; }
|
||||
const Eigen::Matrix4f& getLightViewMatrix() const { return lightViewMatrix; }
|
||||
const Eigen::Matrix4f& getLightProjectionMatrix() const { return lightProjectionMatrix; }
|
||||
const Eigen::Vector3f& getLightDirection() const { return lightDirection; }
|
||||
};
|
||||
|
||||
} // namespace ZL
|
||||
Reference in new issue
Block a user