diff --git a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj index 036489e..a28e3b0 100644 --- a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj +++ b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj @@ -106,6 +106,8 @@ + + diff --git a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters index 280e1a9..bda151c 100644 --- a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters +++ b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters @@ -98,6 +98,12 @@ Resource Files\Shaders + + Resource Files\Shaders + + + Resource Files\Shaders + diff --git a/ArchitectureColoredPainting/Drawable.h b/ArchitectureColoredPainting/Drawable.h index 0a4c784..583cf17 100644 --- a/ArchitectureColoredPainting/Drawable.h +++ b/ArchitectureColoredPainting/Drawable.h @@ -3,5 +3,6 @@ class Drawable { public: virtual void draw() = 0; + virtual void drawShadow() = 0; }; diff --git a/ArchitectureColoredPainting/MainWindow.qrc b/ArchitectureColoredPainting/MainWindow.qrc index fc1c47d..81f0012 100644 --- a/ArchitectureColoredPainting/MainWindow.qrc +++ b/ArchitectureColoredPainting/MainWindow.qrc @@ -10,5 +10,7 @@ Shaders/painting.frag Shaders/painting.vert Shaders/painting.comp + Shaders/model_shadow.frag + Shaders/model_shadow.vert diff --git a/ArchitectureColoredPainting/Mesh.cpp b/ArchitectureColoredPainting/Mesh.cpp index 39fc7d7..fb8531d 100644 --- a/ArchitectureColoredPainting/Mesh.cpp +++ b/ArchitectureColoredPainting/Mesh.cpp @@ -1,8 +1,9 @@ #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) , shaderProgram(shaderProgram) + , shadowProgram(shadowProgram) , VBO(QOpenGLBuffer::VertexBuffer) , EBO(QOpenGLBuffer::IndexBuffer) , model((float*)&model) @@ -26,8 +27,6 @@ void Mesh::draw() for (unsigned int i = 0; i < textures.size(); i++) { glFunc->glActiveTexture(GL_TEXTURE0 + i); // 在绑定之前激活相应的纹理单元 - - textures[i]->texture.bind(); //qDebug() << name + number; shaderProgram->setUniformValue(textures[i]->type.toStdString().c_str(), i); @@ -40,6 +39,30 @@ void Mesh::draw() 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() { shaderProgram->bind(); diff --git a/ArchitectureColoredPainting/Mesh.h b/ArchitectureColoredPainting/Mesh.h index 3103c50..a67214d 100644 --- a/ArchitectureColoredPainting/Mesh.h +++ b/ArchitectureColoredPainting/Mesh.h @@ -16,45 +16,46 @@ struct Vertex { - QVector3D Position; - QVector3D Normal; - QVector2D TexCoords; - QVector3D Tangent; - QVector3D Bitangent; + QVector3D Position; + QVector3D Normal; + QVector2D TexCoords; + QVector3D Tangent; + QVector3D Bitangent; }; struct Texture { - QOpenGLTexture texture; - QString type; - QString path; - Texture() :texture(QOpenGLTexture::Target2D) { - texture.create(); - texture.setWrapMode(QOpenGLTexture::DirectionS, QOpenGLTexture::Repeat); - texture.setWrapMode(QOpenGLTexture::DirectionT, QOpenGLTexture::Repeat); - texture.setMinMagFilters(QOpenGLTexture::LinearMipMapLinear, QOpenGLTexture::Linear); - } + QOpenGLTexture texture; + QString type; + QString path; + Texture() :texture(QOpenGLTexture::Target2D) { + texture.create(); + texture.setWrapMode(QOpenGLTexture::DirectionS, QOpenGLTexture::Repeat); + texture.setWrapMode(QOpenGLTexture::DirectionT, QOpenGLTexture::Repeat); + texture.setMinMagFilters(QOpenGLTexture::LinearMipMapLinear, QOpenGLTexture::Linear); + } }; class Mesh : public Drawable { public: - /* 网格数据 */ - QVector vertices; //顶点数据 - QVector indices; //索引数组 - QVector textures; //纹理数据 - QMatrix4x4 model; //模型矩阵 - QOpenGLFunctions_4_5_Compatibility* glFunc; //opengl函数入口 - QOpenGLShaderProgram* shaderProgram; //着色器程序 + /* 网格数据 */ + QVector vertices; //顶点数据 + QVector indices; //索引数组 + QVector textures; //纹理数据 + QMatrix4x4 model; //模型矩阵 + QOpenGLFunctions_4_5_Compatibility* glFunc; //opengl函数入口 + QOpenGLShaderProgram* shaderProgram, * shadowProgram; //着色器程序 - /* 函数 */ - Mesh(QOpenGLFunctions_4_5_Compatibility* glFunc, QOpenGLShaderProgram* shaderProgram, aiMatrix4x4 model); - void draw() override; - void setupMesh(); + /* 函数 */ + Mesh(QOpenGLFunctions_4_5_Compatibility* glFunc, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* shadowProgram, aiMatrix4x4 model); + void draw() override; + void drawShadow() override; + void setupMesh(); private: - /* 渲染数据 */ - QOpenGLVertexArrayObject VAO; - QOpenGLBuffer VBO, EBO; + /* 渲染数据 */ + QOpenGLVertexArrayObject VAO; + QOpenGLBuffer VBO, EBO; }; diff --git a/ArchitectureColoredPainting/Model.cpp b/ArchitectureColoredPainting/Model.cpp index 7ed80a3..b12f0e2 100644 --- a/ArchitectureColoredPainting/Model.cpp +++ b/ArchitectureColoredPainting/Model.cpp @@ -30,11 +30,12 @@ Model::Model(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shader 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) , glFunc(context->versionFunctions()) , shaderProgram(shaderProgram) , paintingProgram(paintingProgram) + , shadowProgram(shadowProgram) , paintingHelper(paintingHelper) , directory(path) { @@ -71,6 +72,13 @@ void Model::draw() { } } +void Model::drawShadow() { + //shaderProgram->bind(); + for (Drawable* mesh : meshes) { + mesh->drawShadow(); + } +} + void Model::destroy() { context->doneCurrent(); @@ -109,7 +117,7 @@ Drawable* Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 mod { 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++) { @@ -258,7 +266,7 @@ Drawable* Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 mod 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++) { diff --git a/ArchitectureColoredPainting/Model.h b/ArchitectureColoredPainting/Model.h index 818e186..9272465 100644 --- a/ArchitectureColoredPainting/Model.h +++ b/ArchitectureColoredPainting/Model.h @@ -9,9 +9,10 @@ class Model { public: void draw(); + void drawShadow(); void destroy(); 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: Model(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram); @@ -20,6 +21,7 @@ private: QOpenGLFunctions_4_5_Compatibility* glFunc; QOpenGLShaderProgram* shaderProgram = nullptr; QOpenGLShaderProgram* paintingProgram = nullptr; //彩绘着色器程序 + QOpenGLShaderProgram* shadowProgram = nullptr; PaintingHelper* paintingHelper = nullptr; /* 模型数据 */ diff --git a/ArchitectureColoredPainting/PaintingMesh.cpp b/ArchitectureColoredPainting/PaintingMesh.cpp index 56ad12d..5bc960c 100644 --- a/ArchitectureColoredPainting/PaintingMesh.cpp +++ b/ArchitectureColoredPainting/PaintingMesh.cpp @@ -1,8 +1,9 @@ #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) , shaderProgram(shaderProgram) + , shadowProgram(shadowProgram) , VBO(QOpenGLBuffer::VertexBuffer) , EBO(QOpenGLBuffer::IndexBuffer) , model((float*)&model) @@ -10,14 +11,21 @@ PaintingMesh::PaintingMesh(QOpenGLFunctions_4_5_Compatibility* glFunc, QOpenGLSh } void PaintingMesh::draw() { - shaderProgram->bind(); QOpenGLVertexArrayObject::Binder bind(&VAO); shaderProgram->setUniformValue("model", model); glFunc->glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0); - glFunc->glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); + 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() { shaderProgram->bind(); diff --git a/ArchitectureColoredPainting/PaintingMesh.h b/ArchitectureColoredPainting/PaintingMesh.h index eae18ce..348d97d 100644 --- a/ArchitectureColoredPainting/PaintingMesh.h +++ b/ArchitectureColoredPainting/PaintingMesh.h @@ -32,11 +32,12 @@ public: QVector indices; //索引数组 QMatrix4x4 model; //模型矩阵 QOpenGLFunctions_4_5_Compatibility* glFunc; //opengl函数入口 - QOpenGLShaderProgram* shaderProgram; //着色器程序 + QOpenGLShaderProgram* shaderProgram, * shadowProgram; //着色器程序 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 drawShadow() override; void setupMesh(); private: diff --git a/ArchitectureColoredPainting/RendererWidget.cpp b/ArchitectureColoredPainting/RendererWidget.cpp index b79b8ec..fcace69 100644 --- a/ArchitectureColoredPainting/RendererWidget.cpp +++ b/ArchitectureColoredPainting/RendererWidget.cpp @@ -49,6 +49,14 @@ void RendererWidget::initializeGL() glEnable(GL_DEPTH_TEST); 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; if (!modelProgramPtr->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shaders/model.vert")) qDebug() << "ERROR:" << modelProgramPtr->log(); @@ -85,15 +93,16 @@ void RendererWidget::initializeGL() finalProgramPtr->setUniformValue("gNormal", 1); finalProgramPtr->setUniformValue("gPosition", 2); finalProgramPtr->setUniformValue("gMetallicRoughness", 3); + finalProgramPtr->setUniformValue("gShadowMap", 4); finalProgramPtr->release(); - + paintingHelper = new PaintingHelper(QOpenGLContext::currentContext()->versionFunctions()); - 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(); paintingCompProgramPtr->bind(); paintingHelper->bindPaintingBuffers(); @@ -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 lightColors[] = { QVector3D(150000,150000,130000), QVector3D(0,0,0) ,QVector3D(0,0,0) ,QVector3D(0,0,0) }; +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) }; +static float sunPitch = 90, sunYaw = 80; 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()) { 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(); @@ -156,19 +189,21 @@ void RendererWidget::paintGL() 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); - 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(1,1, 1); //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); QOpenGLVertexArrayObject::Binder vaoBinder(&quadVAO); finalProgramPtr->bind(); 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("lightColors", lightColors, 4); @@ -181,6 +216,8 @@ void RendererWidget::paintGL() glBindTexture(GL_TEXTURE_2D, gbuffers[2]); glActiveTexture(GL_TEXTURE3); glBindTexture(GL_TEXTURE_2D, gbuffers[3]); + glActiveTexture(GL_TEXTURE4); + glBindTexture(GL_TEXTURE_2D, shadowGbuffers[3]); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); finalProgramPtr->release(); } @@ -192,6 +229,7 @@ void RendererWidget::resizeGL(int width, int height) qDebug() << frameWidth << "x" << frameHeight; //qDebug() << devicePixelRatioF() << width << height; //glViewport(0, 0, (GLint)devicePixelRatio()*width, (GLint)devicePixelRatio()*height); + if (fboPtr != nullptr) delete fboPtr; fboPtr = new QOpenGLFramebufferObject(frameWidth, frameHeight, QOpenGLFramebufferObject::Depth, GL_TEXTURE_2D); @@ -202,36 +240,38 @@ void RendererWidget::resizeGL(int width, int height) 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(5, gbuffers + 1); + //Normal glBindTexture(GL_TEXTURE_2D, gbuffers[1]); 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_MAG_FILTER, GL_NEAREST); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, gbuffers[1], 0); - + //Position 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_MAG_FILTER, GL_NEAREST); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, gbuffers[2], 0); - + //MetallicRoughness glBindTexture(GL_TEXTURE_2D, gbuffers[3]); 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_MAG_FILTER, GL_NEAREST); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, gbuffers[3], 0); - + //gPaintingIndex glBindTexture(GL_TEXTURE_2D, gbuffers[4]); 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_MAG_FILTER, GL_NEAREST); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT4, GL_TEXTURE_2D, gbuffers[4], 0); - + //PaintingTexCoord 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_MAG_FILTER, GL_NEAREST); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT5, GL_TEXTURE_2D, gbuffers[5], 0); @@ -239,10 +279,54 @@ void RendererWidget::resizeGL(int width, int height) GLenum attachments[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3, GL_COLOR_ATTACHMENT4, GL_COLOR_ATTACHMENT5 }; glDrawBuffers(6, attachments); //gbuffers = fboPtr->textures(); - + + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) + qDebug() << "Framebuffer not complete!"; 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"; } @@ -259,8 +343,8 @@ void RendererWidget::timerEvent(QTimerEvent* event) frameCnt++; if (accTime > 1.) { - std::cout << " \r"; - std::cout << "FPS: " << frameCnt / accTime << "\r"; + std::cout << " \r"; + std::cout << "FPS: " << frameCnt / accTime << " " << camera.Position.x() << " " << camera.Position.y() << " " << camera.Position.z() << "\r"; accTime = 0; frameCnt = 0; } @@ -293,6 +377,15 @@ void RendererWidget::timerEvent(QTimerEvent* event) if (pressedKeys.contains(Qt::Key_Space)) { camera.ProcessKeyboard(UP, deltaTime); } + + static int sunSpeed = 10; + 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 ba9d389..ce3ad52 100644 --- a/ArchitectureColoredPainting/RendererWidget.h +++ b/ArchitectureColoredPainting/RendererWidget.h @@ -35,12 +35,16 @@ private: Camera camera; clock_t lastFrame; float deltaTime; + int shadowMapResolution; + QOpenGLShaderProgram* shadowProgramPtr = nullptr; QOpenGLShaderProgram* modelProgramPtr = nullptr; QOpenGLShaderProgram* paintingProgramPtr = nullptr; QOpenGLShaderProgram* paintingCompProgramPtr = nullptr; QOpenGLShaderProgram* finalProgramPtr = nullptr; QOpenGLFramebufferObject* fboPtr = nullptr; + QOpenGLFramebufferObject* shadowFboPtr = nullptr; GLuint gbuffers[6]; + GLuint shadowGbuffers[4]; QOpenGLBuffer quadVBO; QOpenGLVertexArrayObject quadVAO; Model* model; diff --git a/ArchitectureColoredPainting/Shaders/final.frag b/ArchitectureColoredPainting/Shaders/final.frag index f0df30b..485922e 100644 --- a/ArchitectureColoredPainting/Shaders/final.frag +++ b/ArchitectureColoredPainting/Shaders/final.frag @@ -8,10 +8,12 @@ uniform sampler2D gBaseColor; uniform sampler2D gNormal; uniform sampler2D gPosition; uniform sampler2D gMetallicRoughness; +uniform sampler2D gShadowMap; // lights uniform vec3 lightPositions[4]; uniform vec3 lightColors[4]; +uniform mat4 lightSpaceMatrix; uniform vec3 camPos; @@ -19,95 +21,161 @@ const float PI = 3.14159265359; float DistributionGGX(vec3 N, vec3 H, float roughness) { - float a = roughness*roughness; - float a2 = a*a; - float NdotH = max(dot(N, H), 0.0); - float NdotH2 = NdotH*NdotH; + float a = roughness*roughness; + float a2 = a*a; + float NdotH = max(dot(N, H), 0.0); + float NdotH2 = NdotH*NdotH; - float nom = a2; - float denom = (NdotH2 * (a2 - 1.0) + 1.0); - denom = PI * denom * denom; + float nom = a2; + float denom = (NdotH2 * (a2 - 1.0) + 1.0); + denom = PI * denom * denom; - return nom / denom; + return nom / denom; } // ---------------------------------------------------------------------------- float GeometrySchlickGGX(float NdotV, float roughness) { - float r = (roughness + 1.0); - float k = (r*r) / 8.0; + float r = (roughness + 1.0); + float k = (r*r) / 8.0; - float nom = NdotV; - float denom = NdotV * (1.0 - k) + k; + float nom = NdotV; + float denom = NdotV * (1.0 - k) + k; - return nom / denom; + return nom / denom; } // ---------------------------------------------------------------------------- float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness) { - float NdotV = max(dot(N, V), 0.0); - float NdotL = max(dot(N, L), 0.0); - float ggx2 = GeometrySchlickGGX(NdotV, roughness); - float ggx1 = GeometrySchlickGGX(NdotL, roughness); + float NdotV = max(dot(N, V), 0.0); + float NdotL = max(dot(N, L), 0.0); + float ggx2 = GeometrySchlickGGX(NdotV, roughness); + float ggx1 = GeometrySchlickGGX(NdotL, roughness); - return ggx1 * ggx2; + return ggx1 * ggx2; } // ---------------------------------------------------------------------------- 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() { - vec3 albedo = pow(texture(gBaseColor, TexCoords).rgb, vec3(2.2)); - float metallic = texture(gMetallicRoughness, TexCoords).r; - float roughness = texture(gMetallicRoughness, TexCoords).g; + vec3 albedo = pow(texture(gBaseColor, TexCoords).rgb, vec3(2.2)); + float metallic = texture(gMetallicRoughness, TexCoords).r; + float roughness = texture(gMetallicRoughness, TexCoords).g; + + vec3 N = normalize(texture(gNormal, TexCoords).xyz); + vec3 WorldPos = texture(gPosition, TexCoords).xyz; - vec3 N = normalize(texture(gNormal, TexCoords).xyz); - vec3 WorldPos = texture(gPosition, TexCoords).xyz; - vec3 V = normalize(camPos - WorldPos); + if(WorldPos==vec3(0)) + { + vec3 color = lightColors[0]; - vec3 F0 = vec3(0.04); - F0 = mix(F0, albedo, metallic); + color = color / (color + vec3(1.0)); + color = pow(color, vec3(1.0/2.2)); - // reflectance equation - vec3 Lo = vec3(0.0); - for(int i = 0; i < 1; ++i) - { - // calculate per-light radiance - vec3 L = normalize(lightPositions[i] - WorldPos); - vec3 H = normalize(V + L); - float distance = length(lightPositions[i] - WorldPos); - float attenuation = 1.0 / (distance * distance); - vec3 radiance = lightColors[i] * attenuation; + FragColor = vec4(color, 1.0); + return; + } - // cook-torrance brdf - float NDF = DistributionGGX(N, H, roughness); - float G = GeometrySmith(N, V, L, roughness); - vec3 F = fresnelSchlick(clamp(dot(H, V),0.,1.), F0); - //F = clamp(F,vec3(0),vec3(1)); + vec4 FragPosLightSpace = lightSpaceMatrix * vec4(WorldPos, 1.0); - vec3 kS = F; - vec3 kD = vec3(1.0) - kS; - kD *= 1.0 - metallic; + vec3 V = normalize(camPos - WorldPos); - vec3 nominator = NDF * G * F; - float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.001; - vec3 specular = nominator / denominator; + vec3 F0 = vec3(0.04); + F0 = mix(F0, albedo, metallic); - // add to outgoing radiance Lo - float NdotL = max(dot(N, L), 0.0); - Lo += (kD * albedo / PI + specular) * radiance * NdotL; - - } + // reflectance equation + vec3 Lo = vec3(0.0); - vec3 ambient = vec3(0.03) * albedo; - vec3 color = ambient + Lo; + int i = 0; + // calculate per-light radiance + vec3 L = normalize(lightPositions[i] - WorldPos); + vec3 H = normalize(V + L); + float distance = length(lightPositions[i] - WorldPos); + float attenuation = 1.0 / (distance * distance); + vec3 radiance = lightColors[i] * attenuation; - color = color / (color + vec3(1.0)); - color = pow(color, vec3(1.0/2.2)); + // cook-torrance brdf + float NDF = DistributionGGX(N, H, roughness); + float G = GeometrySmith(N, V, L, roughness); + vec3 F = fresnelSchlick(clamp(dot(H, V),0.,1.), F0); + //F = clamp(F,vec3(0),vec3(1)); - FragColor = vec4(color, 1.0); - //FragColor = vec4(texture(gPainting, TexCoords).rgb, 1.0); + vec3 kS = F; + vec3 kD = vec3(1.0) - kS; + kD *= 1.0 - metallic; + + vec3 nominator = NDF * G * F; + float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.001; + vec3 specular = nominator / denominator; + + // add to outgoing radiance Lo + float NdotL = max(dot(N, L), 0.0); + Lo += (kD * albedo / PI + specular) * radiance * NdotL; + + 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; + + 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); } \ No newline at end of file diff --git a/ArchitectureColoredPainting/Shaders/model.vert b/ArchitectureColoredPainting/Shaders/model.vert index f294dc6..0306efb 100644 --- a/ArchitectureColoredPainting/Shaders/model.vert +++ b/ArchitectureColoredPainting/Shaders/model.vert @@ -6,11 +6,11 @@ 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; @@ -19,4 +19,5 @@ void main() gl_Position = projection * view * vec4(WorldPos, 1.0); + } \ No newline at end of file diff --git a/ArchitectureColoredPainting/Shaders/model_shadow.frag b/ArchitectureColoredPainting/Shaders/model_shadow.frag new file mode 100644 index 0000000..3040bd4 --- /dev/null +++ b/ArchitectureColoredPainting/Shaders/model_shadow.frag @@ -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(); + +} \ No newline at end of file diff --git a/ArchitectureColoredPainting/Shaders/model_shadow.vert b/ArchitectureColoredPainting/Shaders/model_shadow.vert new file mode 100644 index 0000000..8f4a748 --- /dev/null +++ b/ArchitectureColoredPainting/Shaders/model_shadow.vert @@ -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); +} \ No newline at end of file diff --git a/ArchitectureColoredPainting/Shaders/painting.comp b/ArchitectureColoredPainting/Shaders/painting.comp index 2037d52..50dc9c6 100644 --- a/ArchitectureColoredPainting/Shaders/painting.comp +++ b/ArchitectureColoredPainting/Shaders/painting.comp @@ -5,7 +5,7 @@ layout (local_size_x = 8, local_size_y = 8) in; layout(rgba8, binding = 0) uniform image2D gBaseColor; layout(rg8, binding = 1) uniform image2D gMetallicRoughness; 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 { diff --git a/README.md b/README.md index a3fe430..a92cd3f 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ vs2022椤圭洰 qt5.15.2 msvc 2019 64-bit -閲囩敤pbr鏉愯川锛岀幇鍦ㄦ湁涓涓厜婧愬拰鎽勫儚鏈虹粦瀹氾紝瓒充互鍒嗚鲸鍑轰笉鍚屾潗璐ㄧ殑鏁堟灉 +閲囩敤pbr鏉愯川锛岀幇鍦ㄦ湁涓涓殢鏃堕棿鍙樺寲鐨勬柟鍚戝厜骞舵坊鍔犱簡闃村奖 鎶婁竴鍧楀竷鏇挎崲鎴愪簡锛堝緟瀹屾垚鐨勶級褰╃粯绠$嚎锛岃PaintingMesh绫讳互鍙妏ainting鐫鑹插櫒 @@ -12,4 +12,6 @@ TODO锛 - [x] 鎸囧畾涓鍧楁潗璐ㄤ娇鐢ㄧ嫭绔嬬绾胯繘琛岀汗鐞嗛噰鏍 -- [ ] 褰╃粯鐨勮〃绀恒佽鍙栥侀噰鏍... \ No newline at end of file +- [ ] 褰╃粯鐨勮〃绀恒佽鍙栥侀噰鏍... + +- [x] PCF Shadow Map \ No newline at end of file