diff --git a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj
index a28e3b0..5477d66 100644
--- a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj
+++ b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj
@@ -87,6 +87,7 @@
+
@@ -102,11 +103,14 @@
+
+
+
@@ -118,6 +122,7 @@
+
diff --git a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters
index bda151c..6d7562f 100644
--- a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters
+++ b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters
@@ -64,6 +64,9 @@
Source Files
+
+ Source Files
+
@@ -104,6 +107,15 @@
Resource Files\Shaders
+
+ Resource Files\Shaders
+
+
+ Resource Files\Shaders
+
+
+ Resource Files\Shaders
+
@@ -127,5 +139,8 @@
Header Files
+
+ Header Files
+
\ No newline at end of file
diff --git a/ArchitectureColoredPainting/Camera.h b/ArchitectureColoredPainting/Camera.h
index 896405b..df6541a 100644
--- a/ArchitectureColoredPainting/Camera.h
+++ b/ArchitectureColoredPainting/Camera.h
@@ -41,6 +41,9 @@ public:
float MovementSpeed;
float MouseSensitivity;
float Zoom;
+ float Ratio;
+ float NearPlane = 10.f;
+ float FarPlane = 10000.f;
// constructor with vectors
Camera(QVector3D position = QVector3D(0.0f, 0.0f, 0.0f), QVector3D up = QVector3D(0.0f, 1.0f, 0.0f), float yaw = YAW, float pitch = PITCH);
diff --git a/ArchitectureColoredPainting/Light.cpp b/ArchitectureColoredPainting/Light.cpp
new file mode 100644
index 0000000..5553046
--- /dev/null
+++ b/ArchitectureColoredPainting/Light.cpp
@@ -0,0 +1,137 @@
+#include "Light.h"
+#include
+
+Light::Light(Camera* camera)
+ : camera(camera)
+ , shadowCascadeLevels{ camera->FarPlane / 50.0f, camera->FarPlane / 25.0f, camera->FarPlane / 10.0f, camera->FarPlane / 2.0f }
+{
+}
+
+
+std::vector Light::getFrustumCornersWorldSpace(const QMatrix4x4& projview)
+{
+ const auto inv = projview.inverted();
+
+ std::vector frustumCorners;
+ for (unsigned int x = 0; x < 2; ++x)
+ {
+ for (unsigned int y = 0; y < 2; ++y)
+ {
+ for (unsigned int z = 0; z < 2; ++z)
+ {
+ const QVector4D pt = inv * QVector4D(2.0f * x - 1.0f, 2.0f * y - 1.0f, 2.0f * z - 1.0f, 1.0f);
+ frustumCorners.push_back(pt / pt.w());
+ }
+ }
+ }
+
+ return frustumCorners;
+}
+
+
+std::vector Light::getFrustumCornersWorldSpace(const QMatrix4x4& proj, const QMatrix4x4& view)
+{
+ return getFrustumCornersWorldSpace(proj * view);
+}
+
+QMatrix4x4 Light::getLightSpaceMatrix(const float nearPlane, const float farPlane)
+{
+ QMatrix4x4 proj;
+ proj.perspective(camera->Zoom, camera->Ratio, nearPlane, farPlane);
+
+ const std::vector corners = getFrustumCornersWorldSpace(proj, camera->GetViewMatrix());
+
+ QVector3D center = QVector3D(0, 0, 0);
+ for (const QVector4D& v : corners)
+ {
+ center += QVector3D(v);
+ }
+ center /= corners.size();
+
+
+ QVector3D right = QVector3D::crossProduct(lightDirection, QVector3D(1, 0, 0)).normalized();
+ QVector3D up = QVector3D::crossProduct(right, lightDirection).normalized();
+ QMatrix4x4 lightView;
+ //qDebug() << "lightDirection:" << lightDirection << "up:" << up;
+ lightView.lookAt(center, center - lightDirection, up);
+
+ float minX = std::numeric_limits::max();
+ float maxX = std::numeric_limits::min();
+ float minY = std::numeric_limits::max();
+ float maxY = std::numeric_limits::min();
+ float minZ = std::numeric_limits::max();
+ float maxZ = std::numeric_limits::min();
+ for (const QVector4D& v : corners)
+ {
+ QVector4D trf = lightView * v;
+ //qDebug() << v;
+ //qDebug() << trf;
+ minX = std::min(minX, trf.x());
+ maxX = std::max(maxX, trf.x());
+ minY = std::min(minY, trf.y());
+ maxY = std::max(maxY, trf.y());
+ minZ = std::min(minZ, -trf.z());
+ maxZ = std::max(maxZ, -trf.z());
+ }
+ for (const QVector3D& v : model->AABB)
+ {
+ const QVector4D trf = lightView * QVector4D(v, 1);
+ //qDebug() << v;
+ //qDebug() << trf;
+ //minX = std::min(minX, trf.x());
+ //maxX = std::max(maxX, trf.x());
+ //minY = std::min(minY, trf.y());
+ //maxY = std::max(maxY, trf.y());
+ minZ = std::min(minZ, -trf.z());
+ //maxZ = std::max(maxZ, trf.z());
+
+ }
+ //qDebug() << minZ;
+ // Tune this parameter according to the scene
+ /* constexpr float zMult = 10.0f;
+ if (minZ < 0)
+ {
+ minZ *= zMult;
+ }
+ else
+ {
+ minZ /= zMult;
+ }
+ if (maxZ < 0)
+ {
+ maxZ /= zMult;
+ }
+ else
+ {
+ maxZ *= zMult;
+ }*/
+
+ QMatrix4x4 lightProjection;
+ //qDebug() << minX<< maxX<< minY<< maxY<< minZ<< maxZ;
+ lightProjection.ortho(minX, maxX, minY, maxY, minZ, maxZ);
+ frustumSizes.push_back(std::max(maxX - minX, maxY - minY));
+ return lightProjection * lightView;
+}
+
+std::vector Light::getLightSpaceMatrices()
+{
+ std::vector ret;
+ frustumSizes.clear();
+ for (size_t i = 0; i < shadowCascadeLevels.size() + 1; ++i)
+ {
+ if (i == 0)
+ {
+ ret.push_back(getLightSpaceMatrix(camera->NearPlane, shadowCascadeLevels[i]));
+ }
+ else if (i < shadowCascadeLevels.size())
+ {
+ ret.push_back(getLightSpaceMatrix(shadowCascadeLevels[i - 1], shadowCascadeLevels[i]));
+ }
+ else
+ {
+ ret.push_back(getLightSpaceMatrix(shadowCascadeLevels[i - 1], camera->FarPlane));
+ }
+ }
+ return ret;
+}
+
diff --git a/ArchitectureColoredPainting/Light.h b/ArchitectureColoredPainting/Light.h
new file mode 100644
index 0000000..553b9f9
--- /dev/null
+++ b/ArchitectureColoredPainting/Light.h
@@ -0,0 +1,28 @@
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include "Camera.h"
+#include "Model.h"
+
+class Light
+{
+public:
+ QVector3D lightDirection = QVector3D(0.2, 4, 1).normalized();
+ std::vector shadowCascadeLevels;
+ std::vector frustumSizes;
+ Model* model;
+ Light(Camera* camera);
+ std::vector getFrustumCornersWorldSpace(const QMatrix4x4& projview);
+ std::vector getFrustumCornersWorldSpace(const QMatrix4x4& proj, const QMatrix4x4& view);
+ QMatrix4x4 getLightSpaceMatrix(const float nearPlane, const float farPlane);
+ std::vector getLightSpaceMatrices();
+private:
+ Camera* camera;
+
+};
+
diff --git a/ArchitectureColoredPainting/MainWindow.qrc b/ArchitectureColoredPainting/MainWindow.qrc
index 81f0012..7519888 100644
--- a/ArchitectureColoredPainting/MainWindow.qrc
+++ b/ArchitectureColoredPainting/MainWindow.qrc
@@ -12,5 +12,8 @@
Shaders/painting.comp
Shaders/model_shadow.frag
Shaders/model_shadow.vert
+ Shaders/depth_mipmap.comp
+ Shaders/depth_init.comp
+ Shaders/model_shadow.geom
diff --git a/ArchitectureColoredPainting/Model.cpp b/ArchitectureColoredPainting/Model.cpp
index b12f0e2..4b0c48d 100644
--- a/ArchitectureColoredPainting/Model.cpp
+++ b/ArchitectureColoredPainting/Model.cpp
@@ -52,6 +52,14 @@ Model::Model(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shader
qDebug() << "NumTextures: " << scene->mNumTextures;
directory.cdUp();
processNode(scene->mRootNode, scene);
+ AABB.push_back(QVector3D(minX, minY, minZ));
+ AABB.push_back(QVector3D(minX, minY, maxZ));
+ AABB.push_back(QVector3D(minX, maxY, minZ));
+ AABB.push_back(QVector3D(minX, maxY, maxZ));
+ AABB.push_back(QVector3D(maxX, minY, minZ));
+ AABB.push_back(QVector3D(maxX, minY, maxZ));
+ AABB.push_back(QVector3D(maxX, maxY, minZ));
+ AABB.push_back(QVector3D(maxX, maxY, maxZ));
}
Model::~Model() //销毁对象
@@ -123,6 +131,14 @@ Drawable* Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 mod
{
PaintingVertex vertex;
vertex.Position = QVector3D(mesh->mVertices[i].x, mesh->mVertices[i].y, mesh->mVertices[i].z);
+ minX = std::min(minX, vertex.Position.x());
+ maxX = std::max(maxX, vertex.Position.x());
+ minY = std::min(minY, vertex.Position.y());
+ maxY = std::max(maxY, vertex.Position.y());
+ minZ = std::min(minZ, vertex.Position.z());
+ maxZ = std::max(maxZ, vertex.Position.z());
+
+
// 法向量
if (mesh->mNormals)
vertex.Normal = QVector3D(mesh->mNormals[i].x, mesh->mNormals[i].y, mesh->mNormals[i].z);
@@ -278,6 +294,14 @@ Drawable* Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 mod
vector.setY(mesh->mVertices[i].y);
vector.setZ(mesh->mVertices[i].z);
vertex.Position = vector;
+ minX = std::min(minX, vertex.Position.x());
+ maxX = std::max(maxX, vertex.Position.x());
+ minY = std::min(minY, vertex.Position.y());
+ maxY = std::max(maxY, vertex.Position.y());
+ minZ = std::min(minZ, vertex.Position.z());
+ maxZ = std::max(maxZ, vertex.Position.z());
+
+
// 法向量
if (mesh->mNormals) {
vector.setX(mesh->mNormals[i].x);
diff --git a/ArchitectureColoredPainting/Model.h b/ArchitectureColoredPainting/Model.h
index 9272465..900dbf7 100644
--- a/ArchitectureColoredPainting/Model.h
+++ b/ArchitectureColoredPainting/Model.h
@@ -8,6 +8,8 @@
class Model
{
public:
+ std::vector AABB;
+
void draw();
void drawShadow();
void destroy();
@@ -29,6 +31,13 @@ private:
QVector meshes; //网格
QDir directory; //模型所在路径
+ float minX = std::numeric_limits::max();
+ float maxX = std::numeric_limits::min();
+ float minY = std::numeric_limits::max();
+ float maxY = std::numeric_limits::min();
+ float minZ = std::numeric_limits::max();
+ float maxZ = std::numeric_limits::min();
+
//递归遍历结点
void processNode(aiNode* node, const aiScene* scene, aiMatrix4x4 mat4 = aiMatrix4x4());
diff --git a/ArchitectureColoredPainting/RendererWidget.cpp b/ArchitectureColoredPainting/RendererWidget.cpp
index fcace69..3d171f2 100644
--- a/ArchitectureColoredPainting/RendererWidget.cpp
+++ b/ArchitectureColoredPainting/RendererWidget.cpp
@@ -5,10 +5,13 @@
#include
#include
#include
+#include
RendererWidget::RendererWidget(QWidget* parent)
- : QOpenGLWidget(parent), camera(QVector3D(0.0f, 100.0f, 0.0f))
+ : QOpenGLWidget(parent)
+ , camera(QVector3D(0.0f, 100.0f, 0.0f))
+ , light(&camera)
{
startTimer(1000 / QGuiApplication::primaryScreen()->refreshRate());
lastFrame = std::clock();
@@ -40,18 +43,21 @@ RendererWidget::~RendererWidget()
}
}
-
+QOpenGLTexture randomMap(QOpenGLTexture::Target2D);
void RendererWidget::initializeGL()
{
initializeOpenGLFunctions();
qDebug() << "GL_VERSION" << (char*)glGetString(GL_VERSION);
glEnable(GL_DEPTH_TEST);
+ glEnable(GL_CULL_FACE);
glClearColor(0, 0, 0, 1);
shadowProgramPtr = new QOpenGLShaderProgram;
if (!shadowProgramPtr->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shaders/model_shadow.vert"))
qDebug() << "ERROR:" << shadowProgramPtr->log();
+ if (!shadowProgramPtr->addShaderFromSourceFile(QOpenGLShader::Geometry, ":/Shaders/model_shadow.geom"))
+ qDebug() << "ERROR:" << shadowProgramPtr->log();
if (!shadowProgramPtr->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/Shaders/model_shadow.frag"))
qDebug() << "ERROR:" << shadowProgramPtr->log();
if (!shadowProgramPtr->link())
@@ -79,6 +85,18 @@ void RendererWidget::initializeGL()
if (!paintingCompProgramPtr->link())
qDebug() << "ERROR:" << paintingCompProgramPtr->log();
+ depthInitProgramPtr = new QOpenGLShaderProgram;
+ if (!depthInitProgramPtr->addShaderFromSourceFile(QOpenGLShader::Compute, ":/Shaders/depth_init.comp"))
+ qDebug() << "ERROR:" << depthInitProgramPtr->log();
+ if (!depthInitProgramPtr->link())
+ qDebug() << "ERROR:" << depthInitProgramPtr->log();
+
+ depthMipmapProgramPtr = new QOpenGLShaderProgram;
+ if (!depthMipmapProgramPtr->addShaderFromSourceFile(QOpenGLShader::Compute, ":/Shaders/depth_mipmap.comp"))
+ qDebug() << "ERROR:" << depthMipmapProgramPtr->log();
+ if (!depthMipmapProgramPtr->link())
+ qDebug() << "ERROR:" << depthMipmapProgramPtr->log();
+
finalProgramPtr = new QOpenGLShaderProgram;
if (!finalProgramPtr->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shaders/final.vert"))
qDebug() << "ERROR:" << finalProgramPtr->log();
@@ -88,12 +106,50 @@ void RendererWidget::initializeGL()
qDebug() << "ERROR:" << finalProgramPtr->log();
+ shadowProgramPtr->bind();
+ glGenBuffers(1, &lightSpaceMatricesUBO);
+ glBindBuffer(GL_UNIFORM_BUFFER, lightSpaceMatricesUBO);
+ glBufferData(GL_UNIFORM_BUFFER, sizeof(QMatrix4x4) * 16, nullptr, GL_STATIC_DRAW);
+ glBindBufferBase(GL_UNIFORM_BUFFER, 0, lightSpaceMatricesUBO);
+ glBindBuffer(GL_UNIFORM_BUFFER, 0);
+ shadowProgramPtr->release();
+
+
+ depthInitProgramPtr->bind();
+ depthInitProgramPtr->setUniformValue("depthBuffer", 6);
+ depthInitProgramPtr->release();
+
+
finalProgramPtr->bind();
finalProgramPtr->setUniformValue("gBaseColor", 0);
finalProgramPtr->setUniformValue("gNormal", 1);
finalProgramPtr->setUniformValue("gPosition", 2);
finalProgramPtr->setUniformValue("gMetallicRoughness", 3);
- finalProgramPtr->setUniformValue("gShadowMap", 4);
+ finalProgramPtr->setUniformValue("gDepth", 4);
+ finalProgramPtr->setUniformValue("gShadowMap", 5);
+
+
+
+ //std::vector rsmSampleCoordsAndWeights;
+ //std::default_random_engine e;
+ //std::uniform_real_distribution u(0, 1);
+ //int rsmSampleNum = 50;
+ //finalProgramPtr->setUniformValue("rsmSampleNum", rsmSampleNum);
+ //for (int i = 0; i < rsmSampleNum; ++i)
+ //{
+ // float xi1 = u(e);
+ // float xi2 = u(e);
+ // rsmSampleCoordsAndWeights.push_back(QVector3D(xi1 * sin(2 * M_PI * xi2), xi1 * cos(2 * M_PI * xi2), xi1 * xi1));
+ //}
+ ////QOpenGLTexture randomMap(QOpenGLTexture::Target2D);
+ //randomMap.create();
+ //randomMap.setSize(rsmSampleCoordsAndWeights.size());
+ //randomMap.setFormat(QOpenGLTexture::RGB8_UNorm);
+ //randomMap.allocateStorage();
+ //randomMap.setData(QOpenGLTexture::RGB, QOpenGLTexture::Float32, rsmSampleCoordsAndWeights.data());
+ //randomMap.setMinMagFilters(QOpenGLTexture::Nearest, QOpenGLTexture::Nearest);
+
+
finalProgramPtr->release();
@@ -101,7 +157,8 @@ void RendererWidget::initializeGL()
paintingHelper = new PaintingHelper(QOpenGLContext::currentContext()->versionFunctions());
model = new Model("Models/Sponza/Sponza.gltf", context(), modelProgramPtr, paintingProgramPtr, shadowProgramPtr, paintingHelper);
-
+ light.model = model;
+ qDebug() << model->AABB;
paintingHelper->allocateBuffers();
paintingCompProgramPtr->bind();
@@ -137,39 +194,59 @@ void RendererWidget::initializeGL()
}
QVector3D lightPositions[] = { 2000 * QVector3D(0.2, 4, 1).normalized(), QVector3D(100,100,100) ,QVector3D(-100,100,100) ,QVector3D(100,100,-100) };
-QVector3D lightColors[] = { 10000000 * QVector3D(0.7529,0.7450,0.6784).normalized(), QVector3D(0,0,0) ,QVector3D(0,0,0) ,QVector3D(0,0,0) };
+QVector3D lightColors[] = { 20 * QVector3D(0.7529,0.7450,0.6784).normalized(), QVector3D(0,0,0) ,QVector3D(0,0,0) ,QVector3D(0,0,0) };
static float sunPitch = 90, sunYaw = 80;
+static int sunSpeed = 10;
void RendererWidget::paintGL()
{
QMatrix4x4 lightProjection;
- lightProjection.ortho(-1200.0f, 1200.0f, -900.0f, 900.0f, 100.f, 5000.0f);
-
+ lightProjection.ortho(-1200.0f, 1200.0f, -900.0f, 900.0f, -2000.f, 5000.0f);
+
+ light.lightDirection.setX(cos(qDegreesToRadians(sunPitch)) * cos(qDegreesToRadians(sunYaw)));
+ light.lightDirection.setY(sin(qDegreesToRadians(sunPitch)));
+ light.lightDirection.setZ(cos(qDegreesToRadians(sunPitch)) * sin(qDegreesToRadians(sunYaw)));
+ light.lightDirection.normalize();
lightPositions[0].setX(cos(qDegreesToRadians(sunPitch)) * cos(qDegreesToRadians(sunYaw)));
lightPositions[0].setY(sin(qDegreesToRadians(sunPitch)));
lightPositions[0].setZ(cos(qDegreesToRadians(sunPitch)) * sin(qDegreesToRadians(sunYaw)));
- lightPositions[0] *= 2000;
+ //lightPositions[0] *= 2000;
QMatrix4x4 lightView;
lightView.lookAt(lightPositions[0], QVector3D(0, 0, 0), QVector3D(0, 1, 0));
- if (shadowFboPtr->bind())
+
+ const std::vector lightMatrices = light.getLightSpaceMatrices();
+ //qDebug() << lightMatrices;
+ glBindBuffer(GL_UNIFORM_BUFFER, lightSpaceMatricesUBO);
+
+ for (size_t i = 0; i < lightMatrices.size(); i++)
{
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glBufferSubData(GL_UNIFORM_BUFFER, i * 16 * sizeof(GLfloat), 16 * sizeof(GLfloat), lightMatrices[i].data());
+ }
+ //glBufferSubData(GL_UNIFORM_BUFFER, 0 * 16 * sizeof(GLfloat), 16 * sizeof(GLfloat), (lightProjection * lightView).data());
+ glBindBuffer(GL_UNIFORM_BUFFER, 0);
+ {
+ glBindFramebuffer(GL_FRAMEBUFFER, shadowFboHandle);
glViewport(0, 0, shadowMapResolution, shadowMapResolution);
- shadowProgramPtr->bind();
+ glClear(GL_DEPTH_BUFFER_BIT);
+ /*shadowProgramPtr->bind();
shadowProgramPtr->setUniformValue("projection", lightProjection);
shadowProgramPtr->setUniformValue("view", lightView);
- shadowProgramPtr->release();
-
+ shadowProgramPtr->setUniformValue("mainLightPositon", lightPositions[0]);
+ shadowProgramPtr->setUniformValue("mainLightColor", lightColors[0]);
+ shadowProgramPtr->release();*/
+ //glCullFace(GL_FRONT);
model->drawShadow();
- shadowFboPtr->release();
+ //glCullFace(GL_BACK);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
-
+ QMatrix4x4 projection;
+ projection.perspective(camera.Zoom, camera.Ratio, camera.NearPlane, camera.FarPlane);
+ QMatrix4x4 view = camera.GetViewMatrix();
if (fboPtr->bind())
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(0, 0, frameWidth, frameHeight);
- QMatrix4x4 projection;
- projection.perspective(camera.Zoom, (float)width() / (float)height(), 10.f, 10000.0f);
- QMatrix4x4 view = camera.GetViewMatrix();
+
modelProgramPtr->bind();
modelProgramPtr->setUniformValue("projection", projection);
modelProgramPtr->setUniformValue("view", view);
@@ -178,14 +255,15 @@ void RendererWidget::paintGL()
paintingProgramPtr->setUniformValue("projection", projection);
paintingProgramPtr->setUniformValue("view", view);
paintingProgramPtr->release();
-
model->draw();
+
+
fboPtr->release();
}
paintingCompProgramPtr->bind();
- glActiveTexture(GL_TEXTURE4);
- glBindTexture(GL_TEXTURE_2D, gbuffers[4]);
+ //glActiveTexture(GL_TEXTURE4);
+ //glBindTexture(GL_TEXTURE_2D, gbuffers[4]);
glBindImageTexture(0, gbuffers[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8);
glBindImageTexture(1, gbuffers[3], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RG8);
glBindImageTexture(2, gbuffers[4], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R16UI);
@@ -193,21 +271,44 @@ void RendererWidget::paintGL()
glDispatchCompute(ceil(frameWidth / 8.), ceil(frameHeight / 8.), 1);
//glDispatchCompute(1,1, 1);
+ paintingCompProgramPtr->release();
+
+ depthInitProgramPtr->bind();
+ glActiveTexture(GL_TEXTURE6);
+ glBindTexture(GL_TEXTURE_2D, gbuffers[6]);
+ glBindImageTexture(0, gbuffers[7], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
+ glDispatchCompute(ceil(depthWidth / 8.), ceil(depthHeight / 8.), 1);
+ depthInitProgramPtr->release();
+
+ depthMipmapProgramPtr->bind();
+ for (int i = 0; i <= 3; i++)
+ glBindImageTexture(i, gbuffers[7], i, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
+ glDispatchCompute(ceil(depthWidth / 2 / 8.), ceil(depthHeight / 2 / 8.), 1);
+ for (int i = 0; i <= 3; i++)
+ glBindImageTexture(i, gbuffers[7], i + 3, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
+ glDispatchCompute(ceil(depthWidth / 2 / 8 / 8.), ceil(depthHeight / 2 / 8 / 8.), 1);
+ depthMipmapProgramPtr->release();
+
- //QOpenGLFramebufferObject::blitFramebuffer(nullptr, QRect(0, 0, 2*width(), 2*height()), fboPtr, QRect(0, 0, 1156, 756));
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(0, 0, frameWidth, frameHeight);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
QOpenGLVertexArrayObject::Binder vaoBinder(&quadVAO);
finalProgramPtr->bind();
finalProgramPtr->setUniformValue("camPos", camera.Position);
- finalProgramPtr->setUniformValue("lightSpaceMatrix", lightProjection * lightView);
+ //finalProgramPtr->setUniformValue("lightSpaceMatrix", lightProjection * lightView);
//lightPositions[0] = camera.Position;
- finalProgramPtr->setUniformValueArray("lightPositions", lightPositions, 4);
- finalProgramPtr->setUniformValueArray("lightColors", lightColors, 4);
-
-
+ //finalProgramPtr->setUniformValueArray("lightPositions", lightPositions, 4);
+ //finalProgramPtr->setUniformValueArray("lightColors", lightColors, 4);
+ finalProgramPtr->setUniformValue("view", view);
+ finalProgramPtr->setUniformValue("farPlane", camera.FarPlane);
+ finalProgramPtr->setUniformValueArray("shadowCascadePlaneDistances", light.shadowCascadeLevels.data(), light.shadowCascadeLevels.size(), 1);
+ finalProgramPtr->setUniformValueArray("shadowBiases", light.frustumSizes.data(), light.frustumSizes.size(), 1);
+ //qDebug() << light.frustumSizes;
+ finalProgramPtr->setUniformValue("shadowCascadeCount", (GLint)light.shadowCascadeLevels.size());
+ finalProgramPtr->setUniformValue("mainLightDirection", light.lightDirection);
+ finalProgramPtr->setUniformValue("mainLightRadiance", lightColors[0]);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, gbuffers[0]);
glActiveTexture(GL_TEXTURE1);
@@ -217,7 +318,9 @@ void RendererWidget::paintGL()
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D, gbuffers[3]);
glActiveTexture(GL_TEXTURE4);
- glBindTexture(GL_TEXTURE_2D, shadowGbuffers[3]);
+ glBindTexture(GL_TEXTURE_2D, gbuffers[7]);
+ glActiveTexture(GL_TEXTURE5);
+ glBindTexture(GL_TEXTURE_2D_ARRAY, shadowGbuffer);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
finalProgramPtr->release();
}
@@ -227,24 +330,23 @@ void RendererWidget::resizeGL(int width, int height)
frameWidth = devicePixelRatioF() * width;
frameHeight = devicePixelRatioF() * height;
qDebug() << frameWidth << "x" << frameHeight;
+ camera.Ratio = (float)frameWidth / (float)frameHeight;
//qDebug() << devicePixelRatioF() << width << height;
//glViewport(0, 0, (GLint)devicePixelRatio()*width, (GLint)devicePixelRatio()*height);
if (fboPtr != nullptr)
+ {
+ glDeleteTextures(7, gbuffers + 1);
delete fboPtr;
- fboPtr = new QOpenGLFramebufferObject(frameWidth, frameHeight, QOpenGLFramebufferObject::Depth, GL_TEXTURE_2D);
+ }
+
+ fboPtr = new QOpenGLFramebufferObject(frameWidth, frameHeight, QOpenGLFramebufferObject::NoAttachment, GL_TEXTURE_2D);
if (fboPtr->bind())
{
- /*fboPtr->addColorAttachment(frameWidth, frameHeight, GL_RGB16F);
- fboPtr->addColorAttachment(frameWidth, frameHeight, GL_RGB16F);
- fboPtr->addColorAttachment(frameWidth, frameHeight, GL_RG8);
- fboPtr->addColorAttachment(frameWidth, frameHeight, GL_R16F);
- fboPtr->addColorAttachment(frameWidth, frameHeight, GL_RG16F);*/
-
//BaseColor
gbuffers[0] = fboPtr->texture();
- glGenTextures(5, gbuffers + 1);
+ glGenTextures(7, gbuffers + 1);
//Normal
glBindTexture(GL_TEXTURE_2D, gbuffers[1]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, frameWidth, frameHeight, 0, GL_RGB, GL_FLOAT, NULL);
@@ -275,6 +377,30 @@ void RendererWidget::resizeGL(int width, int height)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT5, GL_TEXTURE_2D, gbuffers[5], 0);
+ //Depth
+ glBindTexture(GL_TEXTURE_2D, gbuffers[6]);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, frameWidth, frameHeight, 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_CLAMP_TO_BORDER);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
+ glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, std::begin({ 1.0f, 1.0f, 1.0f, 1.0f }));
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, gbuffers[6], 0);
+
+ depthWidth = ceil(frameWidth / 64.) * 64;
+ depthHeight = ceil(frameHeight / 64.) * 64;
+ qDebug() << depthWidth << depthHeight;
+ glBindTexture(GL_TEXTURE_2D, gbuffers[7]);
+ for (int i = 0; i <= 6; i++)
+ glTexImage2D(GL_TEXTURE_2D, i, GL_R32F, depthWidth / pow(2, i), depthHeight / pow(2, i), 0, GL_RED, GL_FLOAT, NULL);
+ //glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, depthWidth, depthHeight, 0, GL_RED, GL_FLOAT, NULL);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 6);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST_MIPMAP_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
+ glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, std::begin({ 1.0f, 1.0f, 1.0f, 1.0f }));
GLenum attachments[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3, GL_COLOR_ATTACHMENT4, GL_COLOR_ATTACHMENT5 };
glDrawBuffers(6, attachments);
@@ -285,46 +411,43 @@ void RendererWidget::resizeGL(int width, int height)
fboPtr->release();
}
- if (shadowFboPtr != nullptr)
- delete shadowFboPtr;
- shadowMapResolution = 1 * std::max(frameWidth, frameHeight);
- shadowFboPtr = new QOpenGLFramebufferObject(shadowMapResolution, shadowMapResolution);
- if (shadowFboPtr->bind())
+
+ if (shadowFboHandle != 0)
{
+ glDeleteTextures(1, &shadowGbuffer);
+ glDeleteFramebuffers(1, &shadowFboHandle);
+ }
- shadowGbuffers[0] = shadowFboPtr->texture();
-
- glGenTextures(3, shadowGbuffers + 1);
- //Normal
- glBindTexture(GL_TEXTURE_2D, shadowGbuffers[1]);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, shadowMapResolution, shadowMapResolution, 0, GL_RGB, GL_FLOAT, NULL);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, shadowGbuffers[1], 0);
- //Position
- glBindTexture(GL_TEXTURE_2D, shadowGbuffers[2]);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, shadowMapResolution, shadowMapResolution, 0, GL_RGB, GL_FLOAT, NULL);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, shadowGbuffers[2], 0);
+ //shadowMapResolution = 1.5 * std::max(frameWidth, frameHeight);
+ shadowMapResolution = 4096;
+ glGenFramebuffers(1, &shadowFboHandle);
+ {
+ glBindFramebuffer(GL_FRAMEBUFFER, shadowFboHandle);
+ glGenTextures(1, &shadowGbuffer);
//Depth
- glBindTexture(GL_TEXTURE_2D, shadowGbuffers[3]);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32,
- shadowMapResolution, shadowMapResolution, 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_CLAMP_TO_BORDER);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadowGbuffers[3], 0);
+ glBindTexture(GL_TEXTURE_2D_ARRAY, shadowGbuffer);
+ glTexImage3D(
+ GL_TEXTURE_2D_ARRAY, 0, GL_DEPTH_COMPONENT32F, shadowMapResolution, shadowMapResolution, int(light.shadowCascadeLevels.size()) + 1,
+ 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr);
- GLenum attachments[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
- glDrawBuffers(3, attachments);
+ /*glBindTexture(GL_TEXTURE_2D, shadowGbuffer);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32,
+ shadowMapResolution, shadowMapResolution, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);*/
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
+ glTexParameterfv(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BORDER_COLOR, std::begin({ 1.0f, 1.0f, 1.0f, 1.0f }));
+ glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, shadowGbuffer, 0);
+ //glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadowGbuffer, 0);
+ glDrawBuffer(GL_NONE);
+ glReadBuffer(GL_NONE);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
qDebug() << "ShadowFramebuffer not complete!";
- shadowFboPtr->release();
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
@@ -378,14 +501,14 @@ void RendererWidget::timerEvent(QTimerEvent* event)
camera.ProcessKeyboard(UP, deltaTime);
}
- static int sunSpeed = 10;
- sunPitch += sunSpeed * deltaTime ;
+
+ sunPitch += sunSpeed * deltaTime;
if (sunPitch > 120 || sunPitch < 65)
{
sunSpeed = -sunSpeed;
sunPitch += sunSpeed * deltaTime;
}
-
+
repaint();
}
diff --git a/ArchitectureColoredPainting/RendererWidget.h b/ArchitectureColoredPainting/RendererWidget.h
index ce3ad52..33d81f1 100644
--- a/ArchitectureColoredPainting/RendererWidget.h
+++ b/ArchitectureColoredPainting/RendererWidget.h
@@ -8,6 +8,7 @@
#include
#include
#include "Camera.h"
+#include "Light.h"
#include "Model.h"
#include "PaintingHelper.h"
@@ -31,20 +32,26 @@ protected:
private:
int frameWidth, frameHeight;
+ int depthWidth, depthHeight;
QSet pressedKeys;
Camera camera;
+ Light light;
clock_t lastFrame;
float deltaTime;
int shadowMapResolution;
+
QOpenGLShaderProgram* shadowProgramPtr = nullptr;
QOpenGLShaderProgram* modelProgramPtr = nullptr;
QOpenGLShaderProgram* paintingProgramPtr = nullptr;
QOpenGLShaderProgram* paintingCompProgramPtr = nullptr;
+ QOpenGLShaderProgram* depthInitProgramPtr = nullptr;
+ QOpenGLShaderProgram* depthMipmapProgramPtr = nullptr;
QOpenGLShaderProgram* finalProgramPtr = nullptr;
QOpenGLFramebufferObject* fboPtr = nullptr;
- QOpenGLFramebufferObject* shadowFboPtr = nullptr;
- GLuint gbuffers[6];
- GLuint shadowGbuffers[4];
+ GLuint gbuffers[8];
+ GLuint shadowFboHandle = 0;
+ GLuint shadowGbuffer;
+ GLuint lightSpaceMatricesUBO;
QOpenGLBuffer quadVBO;
QOpenGLVertexArrayObject quadVAO;
Model* model;
diff --git a/ArchitectureColoredPainting/Shaders/depth_init.comp b/ArchitectureColoredPainting/Shaders/depth_init.comp
new file mode 100644
index 0000000..4331570
--- /dev/null
+++ b/ArchitectureColoredPainting/Shaders/depth_init.comp
@@ -0,0 +1,14 @@
+#version 450 core
+
+layout (local_size_x = 8, local_size_y = 8) in;
+
+uniform sampler2D depthBuffer;
+
+layout(r32f, binding = 0) uniform image2D gDepth;
+
+void main()
+{
+ ivec2 pixelLocation = ivec2(gl_GlobalInvocationID.xy);
+ float depth = textureLod(depthBuffer, vec2(pixelLocation)/textureSize(depthBuffer, 0), 0).r;
+ imageStore(gDepth, pixelLocation, vec4(depth));
+}
\ No newline at end of file
diff --git a/ArchitectureColoredPainting/Shaders/depth_mipmap.comp b/ArchitectureColoredPainting/Shaders/depth_mipmap.comp
new file mode 100644
index 0000000..25a0578
--- /dev/null
+++ b/ArchitectureColoredPainting/Shaders/depth_mipmap.comp
@@ -0,0 +1,31 @@
+#version 450 core
+
+layout (local_size_x = 8, local_size_y = 8) in;
+
+layout(r32f, binding = 0) uniform image2D gDepth[4];
+
+
+void main()
+{
+ ivec2 targetLocation = ivec2(gl_GlobalInvocationID.xy);
+ ivec2 sourceLocation = targetLocation * 2;
+ float depth0 = min(imageLoad(gDepth[0], sourceLocation).r, imageLoad(gDepth[0], sourceLocation+ivec2(0,1)).r);
+ float depth1 = min(imageLoad(gDepth[0], sourceLocation+ivec2(1,0)).r, imageLoad(gDepth[0], sourceLocation+ivec2(1,1)).r);
+ imageStore(gDepth[1], targetLocation, vec4(min(depth0,depth1)));
+ if(targetLocation.x%2==0 && targetLocation.y%2==0)
+ {
+ sourceLocation = targetLocation;
+ targetLocation /= 2;
+ float depth0 = min(imageLoad(gDepth[1], sourceLocation).r, imageLoad(gDepth[1], sourceLocation+ivec2(0,1)).r);
+ float depth1 = min(imageLoad(gDepth[1], sourceLocation+ivec2(1,0)).r, imageLoad(gDepth[1], sourceLocation+ivec2(1,1)).r);
+ imageStore(gDepth[2], targetLocation, vec4(min(depth0,depth1)));
+ if(targetLocation.x%2==0 && targetLocation.y%2==0)
+ {
+ sourceLocation = targetLocation;
+ targetLocation /= 2;
+ float depth0 = min(imageLoad(gDepth[2], sourceLocation).r, imageLoad(gDepth[2], sourceLocation+ivec2(0,1)).r);
+ float depth1 = min(imageLoad(gDepth[2], sourceLocation+ivec2(1,0)).r, imageLoad(gDepth[2], sourceLocation+ivec2(1,1)).r);
+ imageStore(gDepth[3], targetLocation, vec4(min(depth0,depth1)));
+ }
+ }
+}
\ No newline at end of file
diff --git a/ArchitectureColoredPainting/Shaders/final.frag b/ArchitectureColoredPainting/Shaders/final.frag
index 485922e..574b35b 100644
--- a/ArchitectureColoredPainting/Shaders/final.frag
+++ b/ArchitectureColoredPainting/Shaders/final.frag
@@ -8,12 +8,23 @@ uniform sampler2D gBaseColor;
uniform sampler2D gNormal;
uniform sampler2D gPosition;
uniform sampler2D gMetallicRoughness;
-uniform sampler2D gShadowMap;
+uniform sampler2D gDepth;
+uniform sampler2DArray gShadowMap;
+layout (std140, binding = 0) uniform LightSpaceMatrices
+{
+ mat4 lightSpaceMatrices[16];
+};
+uniform mat4 view;
+uniform float farPlane;
+uniform float shadowCascadePlaneDistances[16];
+uniform float shadowBiases[16];
+uniform int shadowCascadeCount;
+uniform vec3 mainLightDirection;
+uniform vec3 mainLightRadiance;
// lights
-uniform vec3 lightPositions[4];
-uniform vec3 lightColors[4];
-uniform mat4 lightSpaceMatrix;
+//uniform vec3 lightPositions[4];
+//uniform vec3 lightColors[4];
uniform vec3 camPos;
@@ -61,55 +72,100 @@ vec3 fresnelSchlick(float cosTheta, vec3 F0)
float Calculate_Avg_Dblockreceiver(vec2 projCoords , int AvgTextureSize)
{
- vec2 texelSize =1.0/ textureSize(gShadowMap, 0);
+ vec2 texelSize =1.0/ textureSize(gShadowMap, 0).xy;
float result=0.0f;
for(int i=-AvgTextureSize;i<=AvgTextureSize;++i)
{
for(int j=-AvgTextureSize;j<=AvgTextureSize;j++)
{
- result += texture(gShadowMap, projCoords+vec2(i,j)*texelSize).r;
+ result += texture(gShadowMap, vec3( projCoords+vec2(i,j)*texelSize, 0)).r;
}
}
return result/(AvgTextureSize*AvgTextureSize*2*2);
}
-float ShadowCalculation(vec4 fragPosLightSpace, float bias)
+float ShadowCalculation(vec3 fragPosWorldSpace, vec3 normal)
{
- // 执行透视除法
- vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
- // 变换到[0,1]的范围
- projCoords = projCoords * 0.5 + 0.5;
- // 取得最近点的深度(使用[0,1]范围下的fragPosLight当坐标)
- float closestDepth = texture(gShadowMap, projCoords.xy).r;
- // 取得当前片段在光源视角下的深度
- float currentDepth = projCoords.z;
+ // select cascade layer
+ vec4 fragPosViewSpace = view * vec4(fragPosWorldSpace, 1.0);
+ float depthValue = abs(fragPosViewSpace.z);
- vec2 texelSize = 1.0 / textureSize(gShadowMap, 0);
- float shadow = 0;
+ int layer = -1;
+ for (int i = 0; i < shadowCascadeCount; ++i)
+ {
+ if (depthValue < shadowCascadePlaneDistances[i])
+ {
+ layer = i;
+ break;
+ }
+ }
+ if (layer == -1)
+ {
+ layer = shadowCascadeCount;
+ }
- // 检查当前片段是否在阴影中
- //float shadow = 0;// currentDepth - bias > closestDepth ? 1.0 : 0.0;
- float fliterArea = 7;
- int fliterSingleX = int(fliterArea/2);
-
- for(int i=-fliterSingleX;i<=fliterSingleX;++i)
- {
- for(int j=-fliterSingleX;j<=fliterSingleX;j++)
- {
- // 采样周围点在ShadowMap中的深度
- float closestDepth = texture(gShadowMap, projCoords.xy+vec2(i,j)*texelSize).r;
- shadow += (currentDepth - bias) > closestDepth ? 1.0 : 0.0;
- }
- }
+ int pcfRadius = 3;
+ float normalBias = 4. /** (1+pcfRadius)*/ * shadowBiases[layer]*max((1.0 - dot(normal, mainLightDirection)), 0.1)/textureSize(gShadowMap, 0).x;
+ vec4 fragPosLightSpace = lightSpaceMatrices[layer] * vec4(fragPosWorldSpace+normal*normalBias, 1.0);
+ // perform perspective divide
+ vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
+ // transform to [0,1] range
+ projCoords = projCoords * 0.5 + 0.5;
- return shadow/(fliterArea*fliterArea);
- //return clamp(shadow/(fliterArea*fliterArea),0.,1.);
+ // get depth of current fragment from light's perspective
+ float currentDepth = projCoords.z;
+ // keep the shadow at 0.0 when outside the far_plane region of the light's frustum.
+ if (currentDepth > 1.0)
+ {
+ return 0.0;
+ }
+ // calculate bias (based on depth map resolution and slope)
+
+ //float bias = 1* max(0.05 * (1.0 - dot(normal, mainLightDirection)), 0.005);
+ //const float biasModifier = 0.5f;
+// if (layer == shadowCascadeCount)
+// {
+// bias *= 1 / (farPlane * biasModifier);
+// }
+// else
+// {
+// bias *= 1 / (shadowCascadePlaneDistances[layer] * biasModifier);
+// }
+
+ // PCF
+ float shadow = 0.0;
+ vec2 texelSize = 1.0 / vec2(textureSize(gShadowMap, 0));
+ for(int x = -pcfRadius; x <= pcfRadius; ++x)
+ {
+ for(int y = -pcfRadius; y <= pcfRadius; ++y)
+ {
+ float pcfDepth = texture(gShadowMap, vec3(projCoords.xy + vec2(x, y) * texelSize, layer)).r;
+ //shadow += (currentDepth - bias) > pcfDepth ? 1.0 : 0.0;
+ shadow += currentDepth > pcfDepth ? 1.0 : 0.0;
+ }
+ }
+ shadow /= (2*pcfRadius+1)*(2*pcfRadius+1);
+
+ return shadow;
}
+
void main()
{
- vec3 albedo = pow(texture(gBaseColor, TexCoords).rgb, vec3(2.2));
+
+ //FragColor = vec4(vec3(textureLod(gDepth, TexCoords, 1).x), 1.0);
+ //FragColor -= vec4(vec3(textureLod(gDepth, TexCoords, 0).x), 1.0);
+ //ivec2 depthCoords = ivec2(TexCoords*(textureSize(gDepth,0)-ivec2(1)) + vec2(0.5));
+ //float depth = texelFetch(gDepth, depthCoords/64, 6).x;
+ //depth -= texelFetch(gDepth, depthCoords, 0).x;
+ //FragColor = vec4(vec3(depth*10000),1);
+ //FragColor = vec4(vec3(textureSize(gShadowMap, 0)-vec3(1)),1);
+ //FragColor = vec4(texture(gBaseColor, TexCoords).rgb, 1);
+ //return;
+
+
+ vec3 albedo = pow(texture(gBaseColor, TexCoords).rgb, vec3(2.2));
float metallic = texture(gMetallicRoughness, TexCoords).r;
float roughness = texture(gMetallicRoughness, TexCoords).g;
@@ -119,7 +175,7 @@ void main()
if(WorldPos==vec3(0))
{
- vec3 color = lightColors[0];
+ vec3 color = mainLightRadiance;
color = color / (color + vec3(1.0));
color = pow(color, vec3(1.0/2.2));
@@ -128,7 +184,6 @@ void main()
return;
}
- vec4 FragPosLightSpace = lightSpaceMatrix * vec4(WorldPos, 1.0);
vec3 V = normalize(camPos - WorldPos);
@@ -138,13 +193,13 @@ void main()
// reflectance equation
vec3 Lo = vec3(0.0);
- int i = 0;
+
// calculate per-light radiance
- vec3 L = normalize(lightPositions[i] - WorldPos);
+ vec3 L = normalize(mainLightDirection);
vec3 H = normalize(V + L);
- float distance = length(lightPositions[i] - WorldPos);
- float attenuation = 1.0 / (distance * distance);
- vec3 radiance = lightColors[i] * attenuation;
+ //float distance = length(lightPositions[i] - WorldPos);
+ //float attenuation = 1.0 / (distance * distance);
+ vec3 radiance = mainLightRadiance ;//* attenuation;
// cook-torrance brdf
float NDF = DistributionGGX(N, H, roughness);
@@ -166,16 +221,22 @@ void main()
vec3 ambient = vec3(0.03) * albedo;
- float bias = 0.08 * max(0.05 * (1.0 - dot(N, L)), 0.005);
- float shadow = ShadowCalculation(FragPosLightSpace, bias);
- //vec3 color = ambient + Lo;
- vec3 color = ambient + (1.0 - shadow) * Lo;
+
+ //vec4 FragPosLightSpace = lightSpaceMatrix * vec4(WorldPos, 1.0);
+ //float bias = 0.08 * max(0.05 * (1.0 - dot(N, L)), 0.005);
+ float shadow = ShadowCalculation(WorldPos, N);
+
+ //vec3 color = ambient + Lo;
+ //vec3 color = indirect*1;
+ vec3 color = ambient + (1.0 - shadow) * Lo;
+ //vec3 color = (1.0 - shadow) * Lo;
+ //vec3 color = (1.0 - shadow) * Lo + indirect*10;
color = color / (color + vec3(1.0));
color = pow(color, vec3(1.0/2.2));
FragColor = vec4(color, 1.0);
//FragColor = vec4(vec3(shadow), 1);
- //FragColor = vec4(texture(gShadowMap, TexCoords).rgb, 1.0);
-
+ //FragColor = vec4(texture(gShadowNormal, TexCoords).rgb, 1.0);
+
}
\ No newline at end of file
diff --git a/ArchitectureColoredPainting/Shaders/model_shadow.frag b/ArchitectureColoredPainting/Shaders/model_shadow.frag
index 3040bd4..391e444 100644
--- a/ArchitectureColoredPainting/Shaders/model_shadow.frag
+++ b/ArchitectureColoredPainting/Shaders/model_shadow.frag
@@ -1,42 +1,13 @@
#version 450 core
-
uniform sampler2D texture_basecolor;
-uniform sampler2D texture_metallic_roughness;
-uniform sampler2D texture_normal;
-
-layout (location = 0) out vec4 gBaseColor;
-layout (location = 1) out vec3 gNormal;
-layout (location = 2) out vec3 gPosition;
in vec2 TexCoords;
-in vec3 WorldPos;
-in vec3 Normal;
-
-vec3 getNormalFromMap()
-{
- vec3 tangentNormal = texture(texture_normal, TexCoords).xyz * 2.0 - 1.0;
-
- vec3 Q1 = dFdx(WorldPos);
- vec3 Q2 = dFdy(WorldPos);
- vec2 st1 = dFdx(TexCoords);
- vec2 st2 = dFdy(TexCoords);
-
- vec3 N = normalize(Normal);
- vec3 T = normalize(Q1*st2.t - Q2*st1.t);
- vec3 B = -normalize(cross(N, T));
- mat3 TBN = mat3(T, B, N);
-
- return normalize(TBN * tangentNormal);
-}
void main()
{
//gBaseColor = vec4(1,0,0,1);
- gBaseColor = texture(texture_basecolor, TexCoords);
- if(gBaseColor.a<0.4)
+ vec4 baseColor = texture(texture_basecolor, TexCoords);
+ if(baseColor.a<0.4)
discard;
- gPosition = WorldPos;
- gNormal = getNormalFromMap();
-
}
\ No newline at end of file
diff --git a/ArchitectureColoredPainting/Shaders/model_shadow.geom b/ArchitectureColoredPainting/Shaders/model_shadow.geom
new file mode 100644
index 0000000..d2960c9
--- /dev/null
+++ b/ArchitectureColoredPainting/Shaders/model_shadow.geom
@@ -0,0 +1,24 @@
+#version 450 core
+
+layout(triangles, invocations = 5) in;
+layout(triangle_strip, max_vertices = 3) out;
+
+layout (std140, binding = 0) uniform LightSpaceMatrices
+{
+ mat4 lightSpaceMatrices[16];
+};
+
+in vec2 vTexCoords[];
+out vec2 TexCoords;
+
+void main()
+{
+ for (int i = 0; i < 3; ++i)
+ {
+ TexCoords = vTexCoords[i];
+ gl_Position = lightSpaceMatrices[gl_InvocationID] * gl_in[i].gl_Position;
+ gl_Layer = gl_InvocationID;
+ EmitVertex();
+ }
+ EndPrimitive();
+}
\ No newline at end of file
diff --git a/ArchitectureColoredPainting/Shaders/model_shadow.vert b/ArchitectureColoredPainting/Shaders/model_shadow.vert
index 8f4a748..872c519 100644
--- a/ArchitectureColoredPainting/Shaders/model_shadow.vert
+++ b/ArchitectureColoredPainting/Shaders/model_shadow.vert
@@ -3,19 +3,12 @@ layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
layout (location = 2) in vec2 aTexCoords;
-out vec2 TexCoords;
-out vec3 WorldPos;
-out vec3 Normal;
+out vec2 vTexCoords;
uniform mat4 model;
-uniform mat4 view;
-uniform mat4 projection;
void main()
{
- TexCoords = aTexCoords;
- WorldPos = vec3(model * vec4(aPos, 1.0));
- Normal = mat3(model) * aNormal;
-
- gl_Position = projection * view * vec4(WorldPos, 1.0);
+ vTexCoords = aTexCoords;
+ gl_Position = model * vec4(aPos, 1.0);
}
\ No newline at end of file