实现PCF Shadow Map

dev-VirtualTexture
wuyize 2022-08-18 13:22:45 +08:00
parent 762fb474e5
commit 0efd3b1dbc
18 changed files with 408 additions and 123 deletions

View File

@ -106,6 +106,8 @@
<None Include="Shaders\final.vert" /> <None Include="Shaders\final.vert" />
<None Include="Shaders\model.frag" /> <None Include="Shaders\model.frag" />
<None Include="Shaders\model.vert" /> <None Include="Shaders\model.vert" />
<None Include="Shaders\model_shadow.frag" />
<None Include="Shaders\model_shadow.vert" />
<None Include="Shaders\painting.comp" /> <None Include="Shaders\painting.comp" />
<None Include="Shaders\painting.frag" /> <None Include="Shaders\painting.frag" />
<None Include="Shaders\painting.vert" /> <None Include="Shaders\painting.vert" />

View File

@ -98,6 +98,12 @@
<None Include="Shaders\painting.comp"> <None Include="Shaders\painting.comp">
<Filter>Resource Files\Shaders</Filter> <Filter>Resource Files\Shaders</Filter>
</None> </None>
<None Include="Shaders\model_shadow.frag">
<Filter>Resource Files\Shaders</Filter>
</None>
<None Include="Shaders\model_shadow.vert">
<Filter>Resource Files\Shaders</Filter>
</None>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="Camera.h"> <ClInclude Include="Camera.h">

View File

@ -3,5 +3,6 @@ class Drawable
{ {
public: public:
virtual void draw() = 0; virtual void draw() = 0;
virtual void drawShadow() = 0;
}; };

View File

@ -10,5 +10,7 @@
<file>Shaders/painting.frag</file> <file>Shaders/painting.frag</file>
<file>Shaders/painting.vert</file> <file>Shaders/painting.vert</file>
<file>Shaders/painting.comp</file> <file>Shaders/painting.comp</file>
<file>Shaders/model_shadow.frag</file>
<file>Shaders/model_shadow.vert</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@ -1,8 +1,9 @@
#include "Mesh.h" #include "Mesh.h"
Mesh::Mesh(QOpenGLFunctions_4_5_Compatibility* glFunc, QOpenGLShaderProgram* shaderProgram, aiMatrix4x4 model) Mesh::Mesh(QOpenGLFunctions_4_5_Compatibility* glFunc, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* shadowProgram, aiMatrix4x4 model)
: glFunc(glFunc) : glFunc(glFunc)
, shaderProgram(shaderProgram) , shaderProgram(shaderProgram)
, shadowProgram(shadowProgram)
, VBO(QOpenGLBuffer::VertexBuffer) , VBO(QOpenGLBuffer::VertexBuffer)
, EBO(QOpenGLBuffer::IndexBuffer) , EBO(QOpenGLBuffer::IndexBuffer)
, model((float*)&model) , model((float*)&model)
@ -26,8 +27,6 @@ void Mesh::draw()
for (unsigned int i = 0; i < textures.size(); i++) for (unsigned int i = 0; i < textures.size(); i++)
{ {
glFunc->glActiveTexture(GL_TEXTURE0 + i); // 在绑定之前激活相应的纹理单元 glFunc->glActiveTexture(GL_TEXTURE0 + i); // 在绑定之前激活相应的纹理单元
textures[i]->texture.bind(); textures[i]->texture.bind();
//qDebug() << name + number; //qDebug() << name + number;
shaderProgram->setUniformValue(textures[i]->type.toStdString().c_str(), i); shaderProgram->setUniformValue(textures[i]->type.toStdString().c_str(), i);
@ -40,6 +39,30 @@ void Mesh::draw()
shaderProgram->release(); shaderProgram->release();
} }
void Mesh::drawShadow()
{
shadowProgram->bind();
unsigned int diffuseNr = 1;
unsigned int specularNr = 1;
unsigned int normalNr = 1;
unsigned int heightNr = 1;
for (unsigned int i = 0; i < textures.size(); i++)
{
glFunc->glActiveTexture(GL_TEXTURE0 + i); // 在绑定之前激活相应的纹理单元
textures[i]->texture.bind();
//qDebug() << name + number;
shadowProgram->setUniformValue(textures[i]->type.toStdString().c_str(), i);
}
// 绘制网格
QOpenGLVertexArrayObject::Binder bind(&VAO);
shadowProgram->setUniformValue("model", model);
glFunc->glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
shadowProgram->release();
}
void Mesh::setupMesh() void Mesh::setupMesh()
{ {
shaderProgram->bind(); shaderProgram->bind();

View File

@ -45,11 +45,12 @@ public:
QVector<Texture*> textures; //纹理数据 QVector<Texture*> textures; //纹理数据
QMatrix4x4 model; //模型矩阵 QMatrix4x4 model; //模型矩阵
QOpenGLFunctions_4_5_Compatibility* glFunc; //opengl函数入口 QOpenGLFunctions_4_5_Compatibility* glFunc; //opengl函数入口
QOpenGLShaderProgram* shaderProgram; //着色器程序 QOpenGLShaderProgram* shaderProgram, * shadowProgram; //着色器程序
/* 函数 */ /* 函数 */
Mesh(QOpenGLFunctions_4_5_Compatibility* glFunc, QOpenGLShaderProgram* shaderProgram, aiMatrix4x4 model); Mesh(QOpenGLFunctions_4_5_Compatibility* glFunc, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* shadowProgram, aiMatrix4x4 model);
void draw() override; void draw() override;
void drawShadow() override;
void setupMesh(); void setupMesh();
private: private:

View File

@ -30,11 +30,12 @@ Model::Model(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shader
processNode(scene->mRootNode, scene); processNode(scene->mRootNode, scene);
} }
Model::Model(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* paintingProgram, PaintingHelper* paintingHelper) Model::Model(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* paintingProgram, QOpenGLShaderProgram* shadowProgram, PaintingHelper* paintingHelper)
: context(context) : context(context)
, glFunc(context->versionFunctions<QOpenGLFunctions_4_5_Compatibility>()) , glFunc(context->versionFunctions<QOpenGLFunctions_4_5_Compatibility>())
, shaderProgram(shaderProgram) , shaderProgram(shaderProgram)
, paintingProgram(paintingProgram) , paintingProgram(paintingProgram)
, shadowProgram(shadowProgram)
, paintingHelper(paintingHelper) , paintingHelper(paintingHelper)
, directory(path) , directory(path)
{ {
@ -71,6 +72,13 @@ void Model::draw() {
} }
} }
void Model::drawShadow() {
//shaderProgram->bind();
for (Drawable* mesh : meshes) {
mesh->drawShadow();
}
}
void Model::destroy() void Model::destroy()
{ {
context->doneCurrent(); context->doneCurrent();
@ -109,7 +117,7 @@ Drawable* Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 mod
{ {
qDebug() << str.C_Str() << "Replaced"; qDebug() << str.C_Str() << "Replaced";
// 初始化网格 // 初始化网格
PaintingMesh* m_mesh = new PaintingMesh(glFunc, paintingProgram, model); PaintingMesh* m_mesh = new PaintingMesh(glFunc, paintingProgram, shadowProgram, model);
// 遍历网格的每个顶点 // 遍历网格的每个顶点
for (unsigned int i = 0; i < mesh->mNumVertices; i++) for (unsigned int i = 0; i < mesh->mNumVertices; i++)
{ {
@ -258,7 +266,7 @@ Drawable* Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 mod
else else
{ {
// 初始化网格 // 初始化网格
Mesh* m_mesh = new Mesh(glFunc, shaderProgram, model); Mesh* m_mesh = new Mesh(glFunc, shaderProgram, shadowProgram, model);
// 遍历网格的每个顶点 // 遍历网格的每个顶点
for (unsigned int i = 0; i < mesh->mNumVertices; i++) for (unsigned int i = 0; i < mesh->mNumVertices; i++)
{ {

View File

@ -9,9 +9,10 @@ class Model
{ {
public: public:
void draw(); void draw();
void drawShadow();
void destroy(); void destroy();
static Model* createModel(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram); static Model* createModel(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram);
Model(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* paintingProgram, PaintingHelper* paintingHelper); Model(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* paintingProgram, QOpenGLShaderProgram* shadowProgram, PaintingHelper* paintingHelper);
private: private:
Model(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram); Model(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram);
@ -20,6 +21,7 @@ private:
QOpenGLFunctions_4_5_Compatibility* glFunc; QOpenGLFunctions_4_5_Compatibility* glFunc;
QOpenGLShaderProgram* shaderProgram = nullptr; QOpenGLShaderProgram* shaderProgram = nullptr;
QOpenGLShaderProgram* paintingProgram = nullptr; //彩绘着色器程序 QOpenGLShaderProgram* paintingProgram = nullptr; //彩绘着色器程序
QOpenGLShaderProgram* shadowProgram = nullptr;
PaintingHelper* paintingHelper = nullptr; PaintingHelper* paintingHelper = nullptr;
/* 模型数据 */ /* 模型数据 */

View File

@ -1,8 +1,9 @@
#include "PaintingMesh.h" #include "PaintingMesh.h"
PaintingMesh::PaintingMesh(QOpenGLFunctions_4_5_Compatibility* glFunc, QOpenGLShaderProgram* shaderProgram, aiMatrix4x4 model) PaintingMesh::PaintingMesh(QOpenGLFunctions_4_5_Compatibility* glFunc, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* shadowProgram, aiMatrix4x4 model)
: glFunc(glFunc) : glFunc(glFunc)
, shaderProgram(shaderProgram) , shaderProgram(shaderProgram)
, shadowProgram(shadowProgram)
, VBO(QOpenGLBuffer::VertexBuffer) , VBO(QOpenGLBuffer::VertexBuffer)
, EBO(QOpenGLBuffer::IndexBuffer) , EBO(QOpenGLBuffer::IndexBuffer)
, model((float*)&model) , model((float*)&model)
@ -10,14 +11,21 @@ PaintingMesh::PaintingMesh(QOpenGLFunctions_4_5_Compatibility* glFunc, QOpenGLSh
} }
void PaintingMesh::draw() void PaintingMesh::draw()
{ {
shaderProgram->bind(); shaderProgram->bind();
QOpenGLVertexArrayObject::Binder bind(&VAO); QOpenGLVertexArrayObject::Binder bind(&VAO);
shaderProgram->setUniformValue("model", model); shaderProgram->setUniformValue("model", model);
glFunc->glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0); glFunc->glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
glFunc->glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
shaderProgram->release(); shaderProgram->release();
} }
void PaintingMesh::drawShadow()
{
shadowProgram->bind();
QOpenGLVertexArrayObject::Binder bind(&VAO);
shadowProgram->setUniformValue("model", model);
glFunc->glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
shadowProgram->release();
}
void PaintingMesh::setupMesh() void PaintingMesh::setupMesh()
{ {
shaderProgram->bind(); shaderProgram->bind();

View File

@ -32,11 +32,12 @@ public:
QVector<unsigned int> indices; //索引数组 QVector<unsigned int> indices; //索引数组
QMatrix4x4 model; //模型矩阵 QMatrix4x4 model; //模型矩阵
QOpenGLFunctions_4_5_Compatibility* glFunc; //opengl函数入口 QOpenGLFunctions_4_5_Compatibility* glFunc; //opengl函数入口
QOpenGLShaderProgram* shaderProgram; //着色器程序 QOpenGLShaderProgram* shaderProgram, * shadowProgram; //着色器程序
GLuint paintingIndex; GLuint paintingIndex;
/* 函数 */ /* 函数 */
PaintingMesh(QOpenGLFunctions_4_5_Compatibility* glFunc, QOpenGLShaderProgram* shaderProgram, aiMatrix4x4 model); PaintingMesh(QOpenGLFunctions_4_5_Compatibility* glFunc, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* shadowProgram, aiMatrix4x4 model);
void draw() override; void draw() override;
void drawShadow() override;
void setupMesh(); void setupMesh();
private: private:

View File

@ -49,6 +49,14 @@ void RendererWidget::initializeGL()
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
glClearColor(0, 0, 0, 1); 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::Fragment, ":/Shaders/model_shadow.frag"))
qDebug() << "ERROR:" << shadowProgramPtr->log();
if (!shadowProgramPtr->link())
qDebug() << "ERROR:" << shadowProgramPtr->log();
modelProgramPtr = new QOpenGLShaderProgram; modelProgramPtr = new QOpenGLShaderProgram;
if (!modelProgramPtr->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shaders/model.vert")) if (!modelProgramPtr->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shaders/model.vert"))
qDebug() << "ERROR:" << modelProgramPtr->log(); qDebug() << "ERROR:" << modelProgramPtr->log();
@ -85,13 +93,14 @@ void RendererWidget::initializeGL()
finalProgramPtr->setUniformValue("gNormal", 1); finalProgramPtr->setUniformValue("gNormal", 1);
finalProgramPtr->setUniformValue("gPosition", 2); finalProgramPtr->setUniformValue("gPosition", 2);
finalProgramPtr->setUniformValue("gMetallicRoughness", 3); finalProgramPtr->setUniformValue("gMetallicRoughness", 3);
finalProgramPtr->setUniformValue("gShadowMap", 4);
finalProgramPtr->release(); finalProgramPtr->release();
paintingHelper = new PaintingHelper(QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_4_5_Compatibility>()); paintingHelper = new PaintingHelper(QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_4_5_Compatibility>());
model = new Model("Models/Sponza/Sponza.gltf", context(), modelProgramPtr, paintingProgramPtr, paintingHelper); model = new Model("Models/Sponza/Sponza.gltf", context(), modelProgramPtr, paintingProgramPtr, shadowProgramPtr, paintingHelper);
paintingHelper->allocateBuffers(); paintingHelper->allocateBuffers();
@ -127,13 +136,37 @@ void RendererWidget::initializeGL()
} }
QVector3D lightPositions[] = { QVector3D(0,0,0), QVector3D(100,100,100) ,QVector3D(-100,100,100) ,QVector3D(100,100,-100) }; QVector3D lightPositions[] = { 2000 * QVector3D(0.2, 4, 1).normalized(), QVector3D(100,100,100) ,QVector3D(-100,100,100) ,QVector3D(100,100,-100) };
QVector3D lightColors[] = { QVector3D(150000,150000,130000), QVector3D(0,0,0) ,QVector3D(0,0,0) ,QVector3D(0,0,0) }; QVector3D lightColors[] = { 10000000 * 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;
void RendererWidget::paintGL() void RendererWidget::paintGL()
{ {
QMatrix4x4 lightProjection;
lightProjection.ortho(-1200.0f, 1200.0f, -900.0f, 900.0f, 100.f, 5000.0f);
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;
QMatrix4x4 lightView;
lightView.lookAt(lightPositions[0], QVector3D(0, 0, 0), QVector3D(0, 1, 0));
if (shadowFboPtr->bind())
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(0, 0, shadowMapResolution, shadowMapResolution);
shadowProgramPtr->bind();
shadowProgramPtr->setUniformValue("projection", lightProjection);
shadowProgramPtr->setUniformValue("view", lightView);
shadowProgramPtr->release();
model->drawShadow();
shadowFboPtr->release();
}
if (fboPtr->bind()) if (fboPtr->bind())
{ {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(0, 0, frameWidth, frameHeight);
QMatrix4x4 projection; QMatrix4x4 projection;
projection.perspective(camera.Zoom, (float)width() / (float)height(), 10.f, 10000.0f); projection.perspective(camera.Zoom, (float)width() / (float)height(), 10.f, 10000.0f);
QMatrix4x4 view = camera.GetViewMatrix(); QMatrix4x4 view = camera.GetViewMatrix();
@ -156,7 +189,7 @@ void RendererWidget::paintGL()
glBindImageTexture(0, gbuffers[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8); 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(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); glBindImageTexture(2, gbuffers[4], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R16UI);
glBindImageTexture(3, gbuffers[5], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RG16F); glBindImageTexture(3, gbuffers[5], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RG32F);
glDispatchCompute(ceil(frameWidth / 8.), ceil(frameHeight / 8.), 1); glDispatchCompute(ceil(frameWidth / 8.), ceil(frameHeight / 8.), 1);
//glDispatchCompute(1,1, 1); //glDispatchCompute(1,1, 1);
@ -164,11 +197,13 @@ void RendererWidget::paintGL()
//QOpenGLFramebufferObject::blitFramebuffer(nullptr, QRect(0, 0, 2*width(), 2*height()), fboPtr, QRect(0, 0, 1156, 756)); //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); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(0, 0, frameWidth, frameHeight);
QOpenGLVertexArrayObject::Binder vaoBinder(&quadVAO); QOpenGLVertexArrayObject::Binder vaoBinder(&quadVAO);
finalProgramPtr->bind(); finalProgramPtr->bind();
finalProgramPtr->setUniformValue("camPos", camera.Position); finalProgramPtr->setUniformValue("camPos", camera.Position);
lightPositions[0] = camera.Position; finalProgramPtr->setUniformValue("lightSpaceMatrix", lightProjection * lightView);
//lightPositions[0] = camera.Position;
finalProgramPtr->setUniformValueArray("lightPositions", lightPositions, 4); finalProgramPtr->setUniformValueArray("lightPositions", lightPositions, 4);
finalProgramPtr->setUniformValueArray("lightColors", lightColors, 4); finalProgramPtr->setUniformValueArray("lightColors", lightColors, 4);
@ -181,6 +216,8 @@ void RendererWidget::paintGL()
glBindTexture(GL_TEXTURE_2D, gbuffers[2]); glBindTexture(GL_TEXTURE_2D, gbuffers[2]);
glActiveTexture(GL_TEXTURE3); glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D, gbuffers[3]); glBindTexture(GL_TEXTURE_2D, gbuffers[3]);
glActiveTexture(GL_TEXTURE4);
glBindTexture(GL_TEXTURE_2D, shadowGbuffers[3]);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
finalProgramPtr->release(); finalProgramPtr->release();
} }
@ -192,6 +229,7 @@ void RendererWidget::resizeGL(int width, int height)
qDebug() << frameWidth << "x" << frameHeight; qDebug() << frameWidth << "x" << frameHeight;
//qDebug() << devicePixelRatioF() << width << height; //qDebug() << devicePixelRatioF() << width << height;
//glViewport(0, 0, (GLint)devicePixelRatio()*width, (GLint)devicePixelRatio()*height); //glViewport(0, 0, (GLint)devicePixelRatio()*width, (GLint)devicePixelRatio()*height);
if (fboPtr != nullptr) if (fboPtr != nullptr)
delete fboPtr; delete fboPtr;
fboPtr = new QOpenGLFramebufferObject(frameWidth, frameHeight, QOpenGLFramebufferObject::Depth, GL_TEXTURE_2D); fboPtr = new QOpenGLFramebufferObject(frameWidth, frameHeight, QOpenGLFramebufferObject::Depth, GL_TEXTURE_2D);
@ -203,35 +241,37 @@ void RendererWidget::resizeGL(int width, int height)
fboPtr->addColorAttachment(frameWidth, frameHeight, GL_R16F); fboPtr->addColorAttachment(frameWidth, frameHeight, GL_R16F);
fboPtr->addColorAttachment(frameWidth, frameHeight, GL_RG16F);*/ fboPtr->addColorAttachment(frameWidth, frameHeight, GL_RG16F);*/
//BaseColor
gbuffers[0] = fboPtr->texture(); gbuffers[0] = fboPtr->texture();
glGenTextures(5, gbuffers + 1); glGenTextures(5, gbuffers + 1);
//Normal
glBindTexture(GL_TEXTURE_2D, gbuffers[1]); glBindTexture(GL_TEXTURE_2D, gbuffers[1]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, frameWidth, frameHeight, 0, GL_RGB, GL_FLOAT, NULL); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, frameWidth, frameHeight, 0, GL_RGB, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 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_MAG_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, gbuffers[1], 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, gbuffers[1], 0);
//Position
glBindTexture(GL_TEXTURE_2D, gbuffers[2]); glBindTexture(GL_TEXTURE_2D, gbuffers[2]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, frameWidth, frameHeight, 0, GL_RGB, GL_FLOAT, NULL); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, frameWidth, frameHeight, 0, GL_RGB, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 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_MAG_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, gbuffers[2], 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, gbuffers[2], 0);
//MetallicRoughness
glBindTexture(GL_TEXTURE_2D, gbuffers[3]); glBindTexture(GL_TEXTURE_2D, gbuffers[3]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RG8, frameWidth, frameHeight, 0, GL_RG, GL_UNSIGNED_BYTE, NULL); glTexImage2D(GL_TEXTURE_2D, 0, GL_RG8, frameWidth, frameHeight, 0, GL_RG, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 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_MAG_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, gbuffers[3], 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, gbuffers[3], 0);
//gPaintingIndex
glBindTexture(GL_TEXTURE_2D, gbuffers[4]); glBindTexture(GL_TEXTURE_2D, gbuffers[4]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_R16UI, frameWidth, frameHeight, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, NULL); glTexImage2D(GL_TEXTURE_2D, 0, GL_R16UI, frameWidth, frameHeight, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 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_MAG_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT4, GL_TEXTURE_2D, gbuffers[4], 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT4, GL_TEXTURE_2D, gbuffers[4], 0);
//PaintingTexCoord
glBindTexture(GL_TEXTURE_2D, gbuffers[5]); glBindTexture(GL_TEXTURE_2D, gbuffers[5]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RG16F, frameWidth, frameHeight, 0, GL_RG, GL_FLOAT, NULL); glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32F, frameWidth, frameHeight, 0, GL_RG, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 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_MAG_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT5, GL_TEXTURE_2D, gbuffers[5], 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT5, GL_TEXTURE_2D, gbuffers[5], 0);
@ -240,9 +280,53 @@ void RendererWidget::resizeGL(int width, int height)
glDrawBuffers(6, attachments); glDrawBuffers(6, attachments);
//gbuffers = fboPtr->textures(); //gbuffers = fboPtr->textures();
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
qDebug() << "Framebuffer not complete!";
fboPtr->release(); fboPtr->release();
} }
if (shadowFboPtr != nullptr)
delete shadowFboPtr;
shadowMapResolution = 1 * std::max(frameWidth, frameHeight);
shadowFboPtr = new QOpenGLFramebufferObject(shadowMapResolution, shadowMapResolution);
if (shadowFboPtr->bind())
{
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);
//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);
GLenum attachments[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
glDrawBuffers(3, attachments);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
qDebug() << "ShadowFramebuffer not complete!";
shadowFboPtr->release();
}
std::cout << "\033[?25l"; std::cout << "\033[?25l";
} }
@ -260,7 +344,7 @@ void RendererWidget::timerEvent(QTimerEvent* event)
if (accTime > 1.) if (accTime > 1.)
{ {
std::cout << " \r"; std::cout << " \r";
std::cout << "FPS: " << frameCnt / accTime << "\r"; std::cout << "FPS: " << frameCnt / accTime << " " << camera.Position.x() << " " << camera.Position.y() << " " << camera.Position.z() << "\r";
accTime = 0; accTime = 0;
frameCnt = 0; frameCnt = 0;
} }
@ -293,6 +377,15 @@ void RendererWidget::timerEvent(QTimerEvent* event)
if (pressedKeys.contains(Qt::Key_Space)) { if (pressedKeys.contains(Qt::Key_Space)) {
camera.ProcessKeyboard(UP, deltaTime); camera.ProcessKeyboard(UP, deltaTime);
} }
static int sunSpeed = 10;
sunPitch += sunSpeed * deltaTime ;
if (sunPitch > 120 || sunPitch < 65)
{
sunSpeed = -sunSpeed;
sunPitch += sunSpeed * deltaTime;
}
repaint(); repaint();
} }

View File

@ -35,12 +35,16 @@ private:
Camera camera; Camera camera;
clock_t lastFrame; clock_t lastFrame;
float deltaTime; float deltaTime;
int shadowMapResolution;
QOpenGLShaderProgram* shadowProgramPtr = nullptr;
QOpenGLShaderProgram* modelProgramPtr = nullptr; QOpenGLShaderProgram* modelProgramPtr = nullptr;
QOpenGLShaderProgram* paintingProgramPtr = nullptr; QOpenGLShaderProgram* paintingProgramPtr = nullptr;
QOpenGLShaderProgram* paintingCompProgramPtr = nullptr; QOpenGLShaderProgram* paintingCompProgramPtr = nullptr;
QOpenGLShaderProgram* finalProgramPtr = nullptr; QOpenGLShaderProgram* finalProgramPtr = nullptr;
QOpenGLFramebufferObject* fboPtr = nullptr; QOpenGLFramebufferObject* fboPtr = nullptr;
QOpenGLFramebufferObject* shadowFboPtr = nullptr;
GLuint gbuffers[6]; GLuint gbuffers[6];
GLuint shadowGbuffers[4];
QOpenGLBuffer quadVBO; QOpenGLBuffer quadVBO;
QOpenGLVertexArrayObject quadVAO; QOpenGLVertexArrayObject quadVAO;
Model* model; Model* model;

View File

@ -8,10 +8,12 @@ uniform sampler2D gBaseColor;
uniform sampler2D gNormal; uniform sampler2D gNormal;
uniform sampler2D gPosition; uniform sampler2D gPosition;
uniform sampler2D gMetallicRoughness; uniform sampler2D gMetallicRoughness;
uniform sampler2D gShadowMap;
// lights // lights
uniform vec3 lightPositions[4]; uniform vec3 lightPositions[4];
uniform vec3 lightColors[4]; uniform vec3 lightColors[4];
uniform mat4 lightSpaceMatrix;
uniform vec3 camPos; uniform vec3 camPos;
@ -56,6 +58,55 @@ vec3 fresnelSchlick(float cosTheta, vec3 F0)
{ {
return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0); return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0);
} }
float Calculate_Avg_Dblockreceiver(vec2 projCoords , int AvgTextureSize)
{
vec2 texelSize =1.0/ textureSize(gShadowMap, 0);
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;
}
}
return result/(AvgTextureSize*AvgTextureSize*2*2);
}
float ShadowCalculation(vec4 fragPosLightSpace, float bias)
{
// 执行透视除法
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;
vec2 texelSize = 1.0 / textureSize(gShadowMap, 0);
float shadow = 0;
// 检查当前片段是否在阴影中
//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;
}
}
return shadow/(fliterArea*fliterArea);
//return clamp(shadow/(fliterArea*fliterArea),0.,1.);
}
void main() void main()
{ {
vec3 albedo = pow(texture(gBaseColor, TexCoords).rgb, vec3(2.2)); vec3 albedo = pow(texture(gBaseColor, TexCoords).rgb, vec3(2.2));
@ -65,6 +116,20 @@ void main()
vec3 N = normalize(texture(gNormal, TexCoords).xyz); vec3 N = normalize(texture(gNormal, TexCoords).xyz);
vec3 WorldPos = texture(gPosition, TexCoords).xyz; vec3 WorldPos = texture(gPosition, TexCoords).xyz;
if(WorldPos==vec3(0))
{
vec3 color = lightColors[0];
color = color / (color + vec3(1.0));
color = pow(color, vec3(1.0/2.2));
FragColor = vec4(color, 1.0);
return;
}
vec4 FragPosLightSpace = lightSpaceMatrix * vec4(WorldPos, 1.0);
vec3 V = normalize(camPos - WorldPos); vec3 V = normalize(camPos - WorldPos);
vec3 F0 = vec3(0.04); vec3 F0 = vec3(0.04);
@ -72,8 +137,8 @@ void main()
// reflectance equation // reflectance equation
vec3 Lo = vec3(0.0); vec3 Lo = vec3(0.0);
for(int i = 0; i < 1; ++i)
{ int i = 0;
// calculate per-light radiance // calculate per-light radiance
vec3 L = normalize(lightPositions[i] - WorldPos); vec3 L = normalize(lightPositions[i] - WorldPos);
vec3 H = normalize(V + L); vec3 H = normalize(V + L);
@ -99,15 +164,18 @@ void main()
float NdotL = max(dot(N, L), 0.0); float NdotL = max(dot(N, L), 0.0);
Lo += (kD * albedo / PI + specular) * radiance * NdotL; Lo += (kD * albedo / PI + specular) * radiance * NdotL;
}
vec3 ambient = vec3(0.03) * albedo; vec3 ambient = vec3(0.03) * albedo;
vec3 color = ambient + Lo;
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;
color = color / (color + vec3(1.0)); color = color / (color + vec3(1.0));
color = pow(color, vec3(1.0/2.2)); color = pow(color, vec3(1.0/2.2));
FragColor = vec4(color, 1.0); FragColor = vec4(color, 1.0);
//FragColor = vec4(texture(gPainting, TexCoords).rgb, 1.0); //FragColor = vec4(vec3(shadow), 1);
//FragColor = vec4(texture(gShadowMap, TexCoords).rgb, 1.0);
} }

View File

@ -19,4 +19,5 @@ void main()
gl_Position = projection * view * vec4(WorldPos, 1.0); gl_Position = projection * view * vec4(WorldPos, 1.0);
} }

View File

@ -0,0 +1,42 @@
#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)
discard;
gPosition = WorldPos;
gNormal = getNormalFromMap();
}

View File

@ -0,0 +1,21 @@
#version 450 core
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;
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);
}

View File

@ -5,7 +5,7 @@ layout (local_size_x = 8, local_size_y = 8) in;
layout(rgba8, binding = 0) uniform image2D gBaseColor; layout(rgba8, binding = 0) uniform image2D gBaseColor;
layout(rg8, binding = 1) uniform image2D gMetallicRoughness; layout(rg8, binding = 1) uniform image2D gMetallicRoughness;
layout(r16ui, binding = 2) uniform uimage2D gPaintingIndex; layout(r16ui, binding = 2) uniform uimage2D gPaintingIndex;
layout(rg16f, binding = 3) uniform image2D gPaintingTexCoord; layout(rg32f, binding = 3) uniform image2D gPaintingTexCoord;
layout(std430, binding = 1) buffer paintingOffsetBuffer layout(std430, binding = 1) buffer paintingOffsetBuffer
{ {

View File

@ -2,7 +2,7 @@
vs2022项目 qt5.15.2 msvc 2019 64-bit vs2022项目 qt5.15.2 msvc 2019 64-bit
采用pbr材质现在有一个光源和摄像机绑定,足以分辨出不同材质的效果 采用pbr材质现在有一个随时间变化的方向光并添加了阴影
把一块布替换成了待完成的彩绘管线见PaintingMesh类以及painting着色器 把一块布替换成了待完成的彩绘管线见PaintingMesh类以及painting着色器
@ -13,3 +13,5 @@ TODO
- [x] 指定一块材质使用独立管线进行纹理采样 - [x] 指定一块材质使用独立管线进行纹理采样
- [ ] 彩绘的表示、读取、采样... - [ ] 彩绘的表示、读取、采样...
- [x] PCF Shadow Map