初步实现Cascaded Shadow Maps
parent
0efd3b1dbc
commit
3bf1444092
|
@ -87,6 +87,7 @@
|
|||
<ItemGroup>
|
||||
<ClCompile Include="BvhTree.cpp" />
|
||||
<ClCompile Include="Camera.cpp" />
|
||||
<ClCompile Include="Light.cpp" />
|
||||
<ClCompile Include="Mesh.cpp" />
|
||||
<ClCompile Include="Model.cpp" />
|
||||
<ClCompile Include="PaintingHelper.cpp" />
|
||||
|
@ -102,11 +103,14 @@
|
|||
<QtMoc Include="RendererWidget.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Shaders\depth_init.comp" />
|
||||
<None Include="Shaders\depth_mipmap.comp" />
|
||||
<None Include="Shaders\final.frag" />
|
||||
<None Include="Shaders\final.vert" />
|
||||
<None Include="Shaders\model.frag" />
|
||||
<None Include="Shaders\model.vert" />
|
||||
<None Include="Shaders\model_shadow.frag" />
|
||||
<None Include="Shaders\model_shadow.geom" />
|
||||
<None Include="Shaders\model_shadow.vert" />
|
||||
<None Include="Shaders\painting.comp" />
|
||||
<None Include="Shaders\painting.frag" />
|
||||
|
@ -118,6 +122,7 @@
|
|||
<ClInclude Include="BvhTree.h" />
|
||||
<ClInclude Include="Camera.h" />
|
||||
<ClInclude Include="Drawable.h" />
|
||||
<ClInclude Include="Light.h" />
|
||||
<ClInclude Include="Mesh.h" />
|
||||
<ClInclude Include="Model.h" />
|
||||
<ClInclude Include="PaintingHelper.h" />
|
||||
|
|
|
@ -64,6 +64,9 @@
|
|||
<ClCompile Include="PaintingHelper.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Light.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<QtMoc Include="RendererWidget.h">
|
||||
|
@ -104,6 +107,15 @@
|
|||
<None Include="Shaders\model_shadow.vert">
|
||||
<Filter>Resource Files\Shaders</Filter>
|
||||
</None>
|
||||
<None Include="Shaders\depth_mipmap.comp">
|
||||
<Filter>Resource Files\Shaders</Filter>
|
||||
</None>
|
||||
<None Include="Shaders\depth_init.comp">
|
||||
<Filter>Resource Files\Shaders</Filter>
|
||||
</None>
|
||||
<None Include="Shaders\model_shadow.geom">
|
||||
<Filter>Resource Files\Shaders</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Camera.h">
|
||||
|
@ -127,5 +139,8 @@
|
|||
<ClInclude Include="PaintingHelper.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Light.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -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);
|
||||
|
|
|
@ -0,0 +1,137 @@
|
|||
#include "Light.h"
|
||||
#include <qDebug>
|
||||
|
||||
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<QVector4D> Light::getFrustumCornersWorldSpace(const QMatrix4x4& projview)
|
||||
{
|
||||
const auto inv = projview.inverted();
|
||||
|
||||
std::vector<QVector4D> 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<QVector4D> 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<QVector4D> 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<float>::max();
|
||||
float maxX = std::numeric_limits<float>::min();
|
||||
float minY = std::numeric_limits<float>::max();
|
||||
float maxY = std::numeric_limits<float>::min();
|
||||
float minZ = std::numeric_limits<float>::max();
|
||||
float maxZ = std::numeric_limits<float>::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<QMatrix4x4> Light::getLightSpaceMatrices()
|
||||
{
|
||||
std::vector<QMatrix4x4> 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;
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <QVector3D>
|
||||
#include <QVector4D>
|
||||
#include <QMatrix4x4>
|
||||
#include <QtMath>
|
||||
#include <QOpenGLFunctions_4_5_Compatibility>
|
||||
#include "Camera.h"
|
||||
#include "Model.h"
|
||||
|
||||
class Light
|
||||
{
|
||||
public:
|
||||
QVector3D lightDirection = QVector3D(0.2, 4, 1).normalized();
|
||||
std::vector<float> shadowCascadeLevels;
|
||||
std::vector<float> frustumSizes;
|
||||
Model* model;
|
||||
Light(Camera* camera);
|
||||
std::vector<QVector4D> getFrustumCornersWorldSpace(const QMatrix4x4& projview);
|
||||
std::vector<QVector4D> getFrustumCornersWorldSpace(const QMatrix4x4& proj, const QMatrix4x4& view);
|
||||
QMatrix4x4 getLightSpaceMatrix(const float nearPlane, const float farPlane);
|
||||
std::vector<QMatrix4x4> getLightSpaceMatrices();
|
||||
private:
|
||||
Camera* camera;
|
||||
|
||||
};
|
||||
|
|
@ -12,5 +12,8 @@
|
|||
<file>Shaders/painting.comp</file>
|
||||
<file>Shaders/model_shadow.frag</file>
|
||||
<file>Shaders/model_shadow.vert</file>
|
||||
<file>Shaders/depth_mipmap.comp</file>
|
||||
<file>Shaders/depth_init.comp</file>
|
||||
<file>Shaders/model_shadow.geom</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
class Model
|
||||
{
|
||||
public:
|
||||
std::vector<QVector3D> AABB;
|
||||
|
||||
void draw();
|
||||
void drawShadow();
|
||||
void destroy();
|
||||
|
@ -29,6 +31,13 @@ private:
|
|||
QVector<Drawable*> meshes; //网格
|
||||
QDir directory; //模型所在路径
|
||||
|
||||
float minX = std::numeric_limits<float>::max();
|
||||
float maxX = std::numeric_limits<float>::min();
|
||||
float minY = std::numeric_limits<float>::max();
|
||||
float maxY = std::numeric_limits<float>::min();
|
||||
float minZ = std::numeric_limits<float>::max();
|
||||
float maxZ = std::numeric_limits<float>::min();
|
||||
|
||||
//递归遍历结点
|
||||
void processNode(aiNode* node, const aiScene* scene, aiMatrix4x4 mat4 = aiMatrix4x4());
|
||||
|
||||
|
|
|
@ -5,10 +5,13 @@
|
|||
#include <sstream>
|
||||
#include <QScreen>
|
||||
#include <QGuiApplication>
|
||||
#include <random>
|
||||
|
||||
|
||||
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<QVector3D> rsmSampleCoordsAndWeights;
|
||||
//std::default_random_engine e;
|
||||
//std::uniform_real_distribution<float> 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<QOpenGLFunctions_4_5_Compatibility>());
|
||||
|
||||
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<QMatrix4x4> 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();
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <QOpenGLFramebufferObject>
|
||||
#include <QKeyEvent>
|
||||
#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<int> 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;
|
||||
|
|
|
@ -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));
|
||||
}
|
|
@ -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)));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
||||
}
|
|
@ -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();
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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);
|
||||
}
|
Loading…
Reference in New Issue