From 3bf1444092849b8656989b8da65bf3ca7127aac9 Mon Sep 17 00:00:00 2001 From: wuyize Date: Tue, 23 Aug 2022 22:55:59 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E6=AD=A5=E5=AE=9E=E7=8E=B0Cascaded=20?= =?UTF-8?q?Shadow=20Maps?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ArchitectureColoredPainting.vcxproj | 5 + ...rchitectureColoredPainting.vcxproj.filters | 15 + ArchitectureColoredPainting/Camera.h | 3 + ArchitectureColoredPainting/Light.cpp | 137 +++++++++ ArchitectureColoredPainting/Light.h | 28 ++ ArchitectureColoredPainting/MainWindow.qrc | 3 + ArchitectureColoredPainting/Model.cpp | 24 ++ ArchitectureColoredPainting/Model.h | 9 + .../RendererWidget.cpp | 265 +++++++++++++----- ArchitectureColoredPainting/RendererWidget.h | 13 +- .../Shaders/depth_init.comp | 14 + .../Shaders/depth_mipmap.comp | 31 ++ .../Shaders/final.frag | 155 ++++++---- .../Shaders/model_shadow.frag | 33 +-- .../Shaders/model_shadow.geom | 24 ++ .../Shaders/model_shadow.vert | 13 +- 16 files changed, 610 insertions(+), 162 deletions(-) create mode 100644 ArchitectureColoredPainting/Light.cpp create mode 100644 ArchitectureColoredPainting/Light.h create mode 100644 ArchitectureColoredPainting/Shaders/depth_init.comp create mode 100644 ArchitectureColoredPainting/Shaders/depth_mipmap.comp create mode 100644 ArchitectureColoredPainting/Shaders/model_shadow.geom 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