From 3a600ec44038789b2c2df454d02d68af73806475 Mon Sep 17 00:00:00 2001 From: wuyize Date: Mon, 25 Jul 2022 16:23:09 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=86=E7=A6=BB=E5=87=BA=E5=BD=A9=E7=BB=98?= =?UTF-8?q?=E7=AE=A1=E7=BA=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ArchitectureColoredPainting.vcxproj | 5 + ...rchitectureColoredPainting.vcxproj.filters | 15 + ArchitectureColoredPainting/Drawable.h | 7 + ArchitectureColoredPainting/MainWindow.qrc | 2 + ArchitectureColoredPainting/Mesh.cpp | 102 ++--- ArchitectureColoredPainting/Mesh.h | 6 +- ArchitectureColoredPainting/Model.cpp | 359 +++++++++++------- ArchitectureColoredPainting/Model.h | 38 +- ArchitectureColoredPainting/PaintingMesh.cpp | 56 +++ ArchitectureColoredPainting/PaintingMesh.h | 47 +++ .../RendererWidget.cpp | 60 ++- ArchitectureColoredPainting/RendererWidget.h | 1 + .../Shaders/final.frag | 1 - .../Shaders/painting.frag | 18 + .../Shaders/painting.vert | 22 ++ README.md | 6 +- 16 files changed, 517 insertions(+), 228 deletions(-) create mode 100644 ArchitectureColoredPainting/Drawable.h create mode 100644 ArchitectureColoredPainting/PaintingMesh.cpp create mode 100644 ArchitectureColoredPainting/PaintingMesh.h create mode 100644 ArchitectureColoredPainting/Shaders/painting.frag create mode 100644 ArchitectureColoredPainting/Shaders/painting.vert diff --git a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj index d89b5f2..b04115d 100644 --- a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj +++ b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj @@ -88,6 +88,7 @@ + @@ -103,13 +104,17 @@ + + + + diff --git a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters index 8e6f9a5..2cc8f3c 100644 --- a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters +++ b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters @@ -55,6 +55,9 @@ Source Files + + Source Files + @@ -80,6 +83,12 @@ Resource Files\Shaders + + Resource Files\Shaders + + + Resource Files\Shaders + @@ -91,5 +100,11 @@ Header Files + + Header Files + + + Header Files + \ No newline at end of file diff --git a/ArchitectureColoredPainting/Drawable.h b/ArchitectureColoredPainting/Drawable.h new file mode 100644 index 0000000..0a4c784 --- /dev/null +++ b/ArchitectureColoredPainting/Drawable.h @@ -0,0 +1,7 @@ +#pragma once +class Drawable +{ +public: + virtual void draw() = 0; +}; + diff --git a/ArchitectureColoredPainting/MainWindow.qrc b/ArchitectureColoredPainting/MainWindow.qrc index abee18a..c7f85b4 100644 --- a/ArchitectureColoredPainting/MainWindow.qrc +++ b/ArchitectureColoredPainting/MainWindow.qrc @@ -7,5 +7,7 @@ Shaders/final.frag Shaders/final.vert container.jpg + Shaders/painting.frag + Shaders/painting.vert diff --git a/ArchitectureColoredPainting/Mesh.cpp b/ArchitectureColoredPainting/Mesh.cpp index adb5fdc..39fc7d7 100644 --- a/ArchitectureColoredPainting/Mesh.cpp +++ b/ArchitectureColoredPainting/Mesh.cpp @@ -1,69 +1,77 @@ #include "Mesh.h" Mesh::Mesh(QOpenGLFunctions_4_5_Compatibility* glFunc, QOpenGLShaderProgram* shaderProgram, aiMatrix4x4 model) - : glFunc(glFunc) - , shaderProgram(shaderProgram) - , VBO(QOpenGLBuffer::VertexBuffer) - , EBO(QOpenGLBuffer::IndexBuffer) + : glFunc(glFunc) + , shaderProgram(shaderProgram) + , VBO(QOpenGLBuffer::VertexBuffer) + , EBO(QOpenGLBuffer::IndexBuffer) + , model((float*)&model) { - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 4; j++) { - this->model(i, j) = model[i][j]; - } - } + //for (int i = 0; i < 4; i++) { + // for (int j = 0; j < 4; j++) { + // this->model(i, j) = model[i][j]; + // } + //} } -void Mesh::Draw() +void Mesh::draw() { - unsigned int diffuseNr = 1; - unsigned int specularNr = 1; - unsigned int normalNr = 1; - unsigned int heightNr = 1; + shaderProgram->bind(); - 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); - } - // 绘制网格 + unsigned int diffuseNr = 1; + unsigned int specularNr = 1; + unsigned int normalNr = 1; + unsigned int heightNr = 1; - QOpenGLVertexArrayObject::Binder bind(&VAO); - shaderProgram->setUniformValue("model", model); - glFunc->glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0); + 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); + } + // 绘制网格 + + QOpenGLVertexArrayObject::Binder bind(&VAO); + shaderProgram->setUniformValue("model", model); + glFunc->glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0); + + shaderProgram->release(); } void Mesh::setupMesh() { + shaderProgram->bind(); + VAO.create(); + VAO.bind(); - VAO.create(); - VAO.bind(); + VBO.create(); + EBO.create(); - VBO.create(); - EBO.create(); + VBO.bind(); + VBO.allocate(vertices.data(), vertices.size() * sizeof(Vertex)); - VBO.bind(); - VBO.allocate(vertices.data(), vertices.size() * sizeof(Vertex)); - - EBO.bind(); - EBO.allocate(indices.data(), indices.size() * sizeof(unsigned int)); + EBO.bind(); + EBO.allocate(indices.data(), indices.size() * sizeof(unsigned int)); - shaderProgram->enableAttributeArray(0); - shaderProgram->setAttributeBuffer(0, GL_FLOAT, 0, 3, sizeof(Vertex)); - shaderProgram->enableAttributeArray(1); - shaderProgram->setAttributeBuffer(1, GL_FLOAT, offsetof(Vertex, Normal), 3, sizeof(Vertex)); + shaderProgram->enableAttributeArray(0); + shaderProgram->setAttributeBuffer(0, GL_FLOAT, 0, 3, sizeof(Vertex)); - shaderProgram->enableAttributeArray(2); - shaderProgram->setAttributeBuffer(2, GL_FLOAT, offsetof(Vertex, TexCoords), 2, sizeof(Vertex)); + shaderProgram->enableAttributeArray(1); + shaderProgram->setAttributeBuffer(1, GL_FLOAT, offsetof(Vertex, Normal), 3, sizeof(Vertex)); - shaderProgram->enableAttributeArray(1); - shaderProgram->setAttributeBuffer(3, GL_FLOAT, offsetof(Vertex, Tangent), 3, sizeof(Vertex)); + shaderProgram->enableAttributeArray(2); + shaderProgram->setAttributeBuffer(2, GL_FLOAT, offsetof(Vertex, TexCoords), 2, sizeof(Vertex)); - shaderProgram->enableAttributeArray(1); - shaderProgram->setAttributeBuffer(4, GL_FLOAT, offsetof(Vertex, Bitangent), 3, sizeof(Vertex)); - VAO.release(); + shaderProgram->enableAttributeArray(3); + shaderProgram->setAttributeBuffer(3, GL_FLOAT, offsetof(Vertex, Tangent), 3, sizeof(Vertex)); + + shaderProgram->enableAttributeArray(4); + shaderProgram->setAttributeBuffer(4, GL_FLOAT, offsetof(Vertex, Bitangent), 3, sizeof(Vertex)); + + VAO.release(); + shaderProgram->release(); } diff --git a/ArchitectureColoredPainting/Mesh.h b/ArchitectureColoredPainting/Mesh.h index 5ecdddc..3103c50 100644 --- a/ArchitectureColoredPainting/Mesh.h +++ b/ArchitectureColoredPainting/Mesh.h @@ -12,6 +12,7 @@ #include #include #include +#include "Drawable.h" struct Vertex { @@ -35,7 +36,8 @@ struct Texture } }; -class Mesh { +class Mesh : public Drawable +{ public: /* 网格数据 */ QVector vertices; //顶点数据 @@ -47,7 +49,7 @@ public: /* 函数 */ Mesh(QOpenGLFunctions_4_5_Compatibility* glFunc, QOpenGLShaderProgram* shaderProgram, aiMatrix4x4 model); - void Draw(); + void draw() override; void setupMesh(); private: diff --git a/ArchitectureColoredPainting/Model.cpp b/ArchitectureColoredPainting/Model.cpp index a42945e..4e74aa9 100644 --- a/ArchitectureColoredPainting/Model.cpp +++ b/ArchitectureColoredPainting/Model.cpp @@ -4,189 +4,258 @@ #include #include #include +#include "PaintingMesh.h" Model::Model(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram) - : context(context) - , shaderProgram(shaderProgram) - , directory(path) + : context(context) + , shaderProgram(shaderProgram) + , directory(path) { - Assimp::Importer import; - const aiScene* scene = import.ReadFile(directory.absolutePath().toUtf8(), aiProcess_Triangulate | aiProcess_FlipUVs); - if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) - { - qDebug() << "ERROR::ASSIMP::" << import.GetErrorString() << endl; - return; - } - qDebug() << directory.absolutePath() << "Loaded Successfully"; - qDebug() << "NumMeshes: " << scene->mNumMeshes; - qDebug() << "NumMaterials: " << scene->mNumMaterials; - qDebug() << "NumTextures: " << scene->mNumTextures; - directory.cdUp(); - processNode(scene->mRootNode, scene); + Assimp::Importer import; + const aiScene* scene = import.ReadFile(directory.absolutePath().toUtf8(), aiProcess_Triangulate | aiProcess_FlipUVs); + if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) + { + qDebug() << "ERROR::ASSIMP::" << import.GetErrorString() << endl; + return; + } + qDebug() << directory.absolutePath() << "Loaded Successfully"; + qDebug() << "NumMeshes: " << scene->mNumMeshes; + qDebug() << "NumMaterials: " << scene->mNumMaterials; + qDebug() << "NumTextures: " << scene->mNumTextures; + directory.cdUp(); + processNode(scene->mRootNode, scene); +} + +Model::Model(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* paintingProgram) + : context(context) + , shaderProgram(shaderProgram) + , paintingProgram(paintingProgram) + , directory(path) +{ + Assimp::Importer import; + const aiScene* scene = import.ReadFile(directory.absolutePath().toUtf8(), aiProcess_Triangulate | aiProcess_FlipUVs); + if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) + { + qDebug() << "ERROR::ASSIMP::" << import.GetErrorString() << endl; + return; + } + qDebug() << directory.absolutePath() << "Loaded Successfully"; + qDebug() << "NumMeshes: " << scene->mNumMeshes; + qDebug() << "NumMaterials: " << scene->mNumMaterials; + qDebug() << "NumTextures: " << scene->mNumTextures; + directory.cdUp(); + processNode(scene->mRootNode, scene); } Model::~Model() //销毁对象 { - for (auto& it : textures_loaded) { - it->texture.destroy(); - delete it; - } - for (auto& it : meshes) { - delete it; - } + for (auto& it : textures_loaded) { + it->texture.destroy(); + delete it; + } + for (auto& it : meshes) { + delete it; + } } void Model::draw() { - shaderProgram->bind(); - for (Mesh* mesh : meshes) { - mesh->Draw(); - } + //shaderProgram->bind(); + for (Drawable* mesh : meshes) { + mesh->draw(); + } } void Model::destroy() { - context->doneCurrent(); - delete this; + context->doneCurrent(); + delete this; } Model* Model::createModel(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram) { - return new Model(path, context, shaderProgram); + return new Model(path, context, shaderProgram); } void Model::processNode(aiNode* node, const aiScene* scene, aiMatrix4x4 mat4) { - // 处理节点所有的网格(如果有的话) - for (unsigned int i = 0; i < node->mNumMeshes; i++) - { - aiMesh* mesh = scene->mMeshes[node->mMeshes[i]]; - meshes.push_back(processMesh(mesh, scene, mat4)); + // 处理节点所有的网格(如果有的话) + for (unsigned int i = 0; i < node->mNumMeshes; i++) + { + aiMesh* mesh = scene->mMeshes[node->mMeshes[i]]; + meshes.push_back(processMesh(mesh, scene, mat4)); - } - // 接下来对它的子节点重复这一过程 - for (unsigned int i = 0; i < node->mNumChildren; i++) - { - processNode(node->mChildren[i], scene, mat4 * node->mChildren[i]->mTransformation); - } + } + // 接下来对它的子节点重复这一过程 + for (unsigned int i = 0; i < node->mNumChildren; i++) + { + processNode(node->mChildren[i], scene, mat4 * node->mChildren[i]->mTransformation); + } } -Mesh* Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 model) +Drawable* Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 model) { - // 初始化网格 - Mesh* m_mesh = new Mesh(QOpenGLContext::currentContext()->versionFunctions(), shaderProgram, model); - // 遍历网格的每个顶点 - for (unsigned int i = 0; i < mesh->mNumVertices; i++) - { - Vertex vertex; - QVector3D vector; //将assimp的数据转化为QtOpenGL支持的数据 + aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex]; - // 位置 - vector.setX(mesh->mVertices[i].x); - vector.setY(mesh->mVertices[i].y); - vector.setZ(mesh->mVertices[i].z); - vertex.Position = vector; - // 法向量 - if (mesh->mNormals) { - vector.setX(mesh->mNormals[i].x); - vector.setY(mesh->mNormals[i].y); - vector.setZ(mesh->mNormals[i].z); - vertex.Normal = vector; - } - // 纹理坐标 - if (mesh->mTextureCoords[0]) // does the mesh contain texture coordinates? - { - QVector2D vec; - //一个顶点最多可以包含8个不同的纹理坐标。因此我们假设我们不用 - //使用一个顶点可以有多个纹理坐标的模型,所以我们总是取第一个集合(0)。 - vec.setX(mesh->mTextureCoords[0][i].x); - vec.setY(mesh->mTextureCoords[0][i].y); - vertex.TexCoords = vec; - } - else { - vertex.TexCoords = QVector2D(0, 0); - } - if (mesh->mTangents) { - // tangent - vector.setX(mesh->mTangents[i].x); - vector.setY(mesh->mTangents[i].y); - vector.setZ(mesh->mTangents[i].z); - vertex.Tangent = vector; - } - if (mesh->mBitangents) { - vector.setX(mesh->mBitangents[i].x); - vector.setY(mesh->mBitangents[i].y); - vector.setZ(mesh->mBitangents[i].z); - vertex.Bitangent = vector; - } - // bitangent - m_mesh->vertices.push_back(vertex); - } + aiString str; + material->GetTexture(aiTextureType_BASE_COLOR, 0, &str); - for (unsigned int i = 0; i < mesh->mNumFaces; i++) - { - aiFace face = mesh->mFaces[i]; - // 将所有面的索引数据添加到索引数组中 - for (unsigned int j = 0; j < face.mNumIndices; j++) { - m_mesh->indices.push_back(face.mIndices[j]); - } - } + if (paintingProgram != nullptr && std::strcmp(str.C_Str(), "17876391417123941155.jpg")==0) + { + qDebug() << str.C_Str(); + // 初始化网格 + PaintingMesh* m_mesh = new PaintingMesh(QOpenGLContext::currentContext()->versionFunctions(), paintingProgram, model); + // 遍历网格的每个顶点 + for (unsigned int i = 0; i < mesh->mNumVertices; i++) + { + PaintingVertex vertex; + vertex.Position = QVector3D(mesh->mVertices[i].x, mesh->mVertices[i].y, mesh->mVertices[i].z); + // 法向量 + if (mesh->mNormals) + vertex.Normal = QVector3D(mesh->mNormals[i].x, mesh->mNormals[i].y, mesh->mNormals[i].z); - // 处理材质 - aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex]; + // 纹理坐标 + if (mesh->mTextureCoords[0]) + vertex.TexCoords = QVector2D(mesh->mTextureCoords[0][i].x, mesh->mTextureCoords[0][i].y); - QVector diffuseMaps = loadMaterialTextures(material, aiTextureType_BASE_COLOR, "texture_basecolor"); - for (auto& it : diffuseMaps) - m_mesh->textures.push_back(it); + if (mesh->mTangents) + vertex.Tangent = QVector3D(mesh->mTangents[i].x, mesh->mTangents[i].y, mesh->mTangents[i].z); - QVector metalnessMaps = loadMaterialTextures(material, aiTextureType_METALNESS, "texture_metallic_roughness"); - for (auto& it : metalnessMaps) - m_mesh->textures.push_back(it); + if (mesh->mBitangents) + vertex.Bitangent = QVector3D(mesh->mBitangents[i].x, mesh->mBitangents[i].y, mesh->mBitangents[i].z);; + + m_mesh->vertices.push_back(vertex); + } + + for (unsigned int i = 0; i < mesh->mNumFaces; i++) + { + aiFace face = mesh->mFaces[i]; + // 将所有面的索引数据添加到索引数组中 + for (unsigned int j = 0; j < face.mNumIndices; j++) { + m_mesh->indices.push_back(face.mIndices[j]); + } + } + + m_mesh->setupMesh(); + return m_mesh; + } + else + { + // 初始化网格 + Mesh* m_mesh = new Mesh(QOpenGLContext::currentContext()->versionFunctions(), shaderProgram, model); + // 遍历网格的每个顶点 + for (unsigned int i = 0; i < mesh->mNumVertices; i++) + { + Vertex vertex; + QVector3D vector; //将assimp的数据转化为QtOpenGL支持的数据 + + // 位置 + vector.setX(mesh->mVertices[i].x); + vector.setY(mesh->mVertices[i].y); + vector.setZ(mesh->mVertices[i].z); + vertex.Position = vector; + // 法向量 + if (mesh->mNormals) { + vector.setX(mesh->mNormals[i].x); + vector.setY(mesh->mNormals[i].y); + vector.setZ(mesh->mNormals[i].z); + vertex.Normal = vector; + } + // 纹理坐标 + if (mesh->mTextureCoords[0]) // does the mesh contain texture coordinates? + { + QVector2D vec; + //一个顶点最多可以包含8个不同的纹理坐标。因此我们假设我们不用 + //使用一个顶点可以有多个纹理坐标的模型,所以我们总是取第一个集合(0)。 + vec.setX(mesh->mTextureCoords[0][i].x); + vec.setY(mesh->mTextureCoords[0][i].y); + vertex.TexCoords = vec; + } + else { + vertex.TexCoords = QVector2D(0, 0); + } + if (mesh->mTangents) { + // tangent + vector.setX(mesh->mTangents[i].x); + vector.setY(mesh->mTangents[i].y); + vector.setZ(mesh->mTangents[i].z); + vertex.Tangent = vector; + } + if (mesh->mBitangents) { + vector.setX(mesh->mBitangents[i].x); + vector.setY(mesh->mBitangents[i].y); + vector.setZ(mesh->mBitangents[i].z); + vertex.Bitangent = vector; + } + // bitangent + m_mesh->vertices.push_back(vertex); + } + + for (unsigned int i = 0; i < mesh->mNumFaces; i++) + { + aiFace face = mesh->mFaces[i]; + // 将所有面的索引数据添加到索引数组中 + for (unsigned int j = 0; j < face.mNumIndices; j++) { + m_mesh->indices.push_back(face.mIndices[j]); + } + } + + // 处理材质 + QVector diffuseMaps = loadMaterialTextures(material, aiTextureType_BASE_COLOR, "texture_basecolor"); + for (auto& it : diffuseMaps) + m_mesh->textures.push_back(it); + + QVector metalnessMaps = loadMaterialTextures(material, aiTextureType_METALNESS, "texture_metallic_roughness"); + for (auto& it : metalnessMaps) + m_mesh->textures.push_back(it); + + QVector normalMaps = loadMaterialTextures(material, aiTextureType_NORMALS, "texture_normal"); + for (auto& it : normalMaps) + m_mesh->textures.push_back(it); + + m_mesh->setupMesh(); + return m_mesh; + } - QVector normalMaps = loadMaterialTextures(material, aiTextureType_NORMALS, "texture_normal"); - for (auto& it : normalMaps) - m_mesh->textures.push_back(it); - m_mesh->setupMesh(); - return m_mesh; } QVector Model::loadMaterialTextures(aiMaterial* mat, aiTextureType type, QString typeName) { - QVector textures; + QVector textures; - for (unsigned int i = 0; i < mat->GetTextureCount(type); i++) - { - //qDebug() << typeName; - aiString str; - mat->GetTexture(type, i, &str); + for (unsigned int i = 0; i < mat->GetTextureCount(type); i++) + { + //qDebug() << typeName; + aiString str; + mat->GetTexture(type, i, &str); - // 检查纹理是否在之前加载过,如果是,则继续到下一个迭代:跳过加载新纹理 - bool skip = false; - for (unsigned int j = 0; j < textures_loaded.size(); j++) - { - if (std::strcmp(textures_loaded[j]->path.toStdString().c_str(), str.C_Str()) == 0) - { - textures.push_back(textures_loaded[j]); - skip = true; //【优化】 带有相同filepath的纹理已经加载,继续到下一个 - break; - } - } - if (!skip) - { // 如果材质还没有加载,加载它 - Texture* texture = new Texture; - QImage data(directory.filePath(str.C_Str())); - if (!data.isNull()) { - texture->texture.setData(data); - texture->type = typeName; - texture->path = str.C_Str(); - textures.push_back(texture); - textures_loaded.push_back(texture); // store it as texture loaded for entire model, to ensure we won't unnecesery load duplicate textures. - } - else { - qDebug() << "未能成功加载纹理:" << directory.filePath(str.C_Str()); - } - } - } - return textures; + // 检查纹理是否在之前加载过,如果是,则继续到下一个迭代:跳过加载新纹理 + bool skip = false; + for (unsigned int j = 0; j < textures_loaded.size(); j++) + { + if (std::strcmp(textures_loaded[j]->path.toStdString().c_str(), str.C_Str()) == 0) + { + textures.push_back(textures_loaded[j]); + skip = true; //【优化】 带有相同filepath的纹理已经加载,继续到下一个 + break; + } + } + if (!skip) + { // 如果材质还没有加载,加载它 + Texture* texture = new Texture; + QImage data(directory.filePath(str.C_Str())); + if (!data.isNull()) { + texture->texture.setData(data); + texture->type = typeName; + texture->path = str.C_Str(); + textures.push_back(texture); + textures_loaded.push_back(texture); // store it as texture loaded for entire model, to ensure we won't unnecesery load duplicate textures. + } + else { + qDebug() << "未能成功加载纹理:" << directory.filePath(str.C_Str()); + } + } + } + return textures; } diff --git a/ArchitectureColoredPainting/Model.h b/ArchitectureColoredPainting/Model.h index c60fd17..c414a06 100644 --- a/ArchitectureColoredPainting/Model.h +++ b/ArchitectureColoredPainting/Model.h @@ -1,34 +1,36 @@ #pragma once #include "Mesh.h" +#include "Drawable.h" #include class Model { public: - void draw(); - void destroy(); - static Model* createModel(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram); - + void draw(); + void destroy(); + static Model* createModel(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram); + Model(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* paintingProgram); private: - Model(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram); - ~Model(); - QOpenGLContext* context; //opengl函数入口 - QOpenGLShaderProgram* shaderProgram; //着色器程序 + Model(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram); - /* 模型数据 */ - QVectortextures_loaded; //纹理 - QVector meshes; //网格 - QDir directory; //模型所在路径 + ~Model(); + QOpenGLContext* context; //opengl函数入口 + QOpenGLShaderProgram* shaderProgram = nullptr; + QOpenGLShaderProgram* paintingProgram = nullptr; //彩绘着色器程序 + /* 模型数据 */ + QVector textures_loaded; //纹理 + QVector meshes; //网格 + QDir directory; //模型所在路径 - //递归遍历结点 - void processNode(aiNode* node, const aiScene* scene, aiMatrix4x4 mat4 = aiMatrix4x4()); + //递归遍历结点 + void processNode(aiNode* node, const aiScene* scene, aiMatrix4x4 mat4 = aiMatrix4x4()); - //加载网格 - Mesh* processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 model); + //加载网格 + Drawable* processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 model); - //加载材质纹理 - QVector loadMaterialTextures(aiMaterial* mat, aiTextureType type, QString typeName); + //加载材质纹理 + QVector loadMaterialTextures(aiMaterial* mat, aiTextureType type, QString typeName); }; diff --git a/ArchitectureColoredPainting/PaintingMesh.cpp b/ArchitectureColoredPainting/PaintingMesh.cpp new file mode 100644 index 0000000..763c928 --- /dev/null +++ b/ArchitectureColoredPainting/PaintingMesh.cpp @@ -0,0 +1,56 @@ +#include "PaintingMesh.h" + +PaintingMesh::PaintingMesh(QOpenGLFunctions_4_5_Compatibility* glFunc, QOpenGLShaderProgram* shaderProgram, aiMatrix4x4 model) + : glFunc(glFunc) + , shaderProgram(shaderProgram) + , VBO(QOpenGLBuffer::VertexBuffer) + , EBO(QOpenGLBuffer::IndexBuffer) + , model((float*)&model) +{ +} +void PaintingMesh::draw() +{ + + shaderProgram->bind(); + QOpenGLVertexArrayObject::Binder bind(&VAO); + shaderProgram->setUniformValue("model", model); + glFunc->glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0); + shaderProgram->release(); +} +void PaintingMesh::setupMesh() +{ + shaderProgram->bind(); + VAO.create(); + VAO.bind(); + + VBO.create(); + EBO.create(); + + VBO.bind(); + VBO.allocate(vertices.data(), vertices.size() * sizeof(PaintingVertex)); + + EBO.bind(); + EBO.allocate(indices.data(), indices.size() * sizeof(unsigned int)); + + + shaderProgram->enableAttributeArray(0); + shaderProgram->setAttributeBuffer(0, GL_FLOAT, 0, 3, sizeof(PaintingVertex)); + + shaderProgram->enableAttributeArray(1); + shaderProgram->setAttributeBuffer(1, GL_FLOAT, offsetof(PaintingVertex, Normal), 3, sizeof(PaintingVertex)); + + shaderProgram->enableAttributeArray(2); + shaderProgram->setAttributeBuffer(2, GL_FLOAT, offsetof(PaintingVertex, TexCoords), 2, sizeof(PaintingVertex)); + + shaderProgram->enableAttributeArray(1); + shaderProgram->setAttributeBuffer(3, GL_FLOAT, offsetof(PaintingVertex, Tangent), 3, sizeof(PaintingVertex)); + + shaderProgram->enableAttributeArray(1); + shaderProgram->setAttributeBuffer(4, GL_FLOAT, offsetof(PaintingVertex, Bitangent), 3, sizeof(PaintingVertex)); + + + VAO.release(); + + shaderProgram->release(); + +} diff --git a/ArchitectureColoredPainting/PaintingMesh.h b/ArchitectureColoredPainting/PaintingMesh.h new file mode 100644 index 0000000..c2a44cd --- /dev/null +++ b/ArchitectureColoredPainting/PaintingMesh.h @@ -0,0 +1,47 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "Drawable.h" + +struct PaintingVertex +{ + QVector3D Position; + QVector3D Normal; + QVector2D TexCoords; + QVector3D Tangent; + QVector3D Bitangent; +}; + +class PaintingMesh : public Drawable +{ +public: + /* 网格数据 */ + QVector vertices; //顶点数据 + QVector indices; //索引数组 + QMatrix4x4 model; //模型矩阵 + QOpenGLFunctions_4_5_Compatibility* glFunc; //opengl函数入口 + QOpenGLShaderProgram* shaderProgram; //着色器程序 + + /* 函数 */ + PaintingMesh(QOpenGLFunctions_4_5_Compatibility* glFunc, QOpenGLShaderProgram* shaderProgram, aiMatrix4x4 model); + void draw() override; + void setupMesh(); + +private: + /* 渲染数据 */ + QOpenGLVertexArrayObject VAO; + QOpenGLBuffer VBO, EBO; + +}; diff --git a/ArchitectureColoredPainting/RendererWidget.cpp b/ArchitectureColoredPainting/RendererWidget.cpp index 0660128..918d9c0 100644 --- a/ArchitectureColoredPainting/RendererWidget.cpp +++ b/ArchitectureColoredPainting/RendererWidget.cpp @@ -15,12 +15,27 @@ RendererWidget::RendererWidget(QWidget* parent) RendererWidget::~RendererWidget() { - if (modelProgramPtr == nullptr) - return; - makeCurrent(); - delete modelProgramPtr; - modelProgramPtr = nullptr; - doneCurrent(); + if (modelProgramPtr != nullptr) + { + makeCurrent(); + delete modelProgramPtr; + modelProgramPtr = nullptr; + doneCurrent(); + } + if (paintingProgramPtr != nullptr) + { + makeCurrent(); + delete paintingProgramPtr; + paintingProgramPtr = nullptr; + doneCurrent(); + } + if (finalProgramPtr != nullptr) + { + makeCurrent(); + delete finalProgramPtr; + finalProgramPtr = nullptr; + doneCurrent(); + } } @@ -39,6 +54,14 @@ void RendererWidget::initializeGL() if (!modelProgramPtr->link()) qDebug() << "ERROR:" << modelProgramPtr->log(); + paintingProgramPtr = new QOpenGLShaderProgram; + if (!paintingProgramPtr->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shaders/painting.vert")) + qDebug() << "ERROR:" << paintingProgramPtr->log(); + if (!paintingProgramPtr->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/Shaders/painting.frag")) + qDebug() << "ERROR:" << paintingProgramPtr->log(); + if (!paintingProgramPtr->link()) + qDebug() << "ERROR:" << paintingProgramPtr->log(); + finalProgramPtr = new QOpenGLShaderProgram; if (!finalProgramPtr->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shaders/final.vert")) qDebug() << "ERROR:" << finalProgramPtr->log(); @@ -54,7 +77,7 @@ void RendererWidget::initializeGL() finalProgramPtr->setUniformValue("gMetallicRoughness", 3); finalProgramPtr->release(); - model = Model::createModel("Models/Sponza/Sponza.gltf", context(), modelProgramPtr); + model = new Model("Models/Sponza/Sponza.gltf", context(), modelProgramPtr, paintingProgramPtr); quadVAO.create(); QOpenGLVertexArrayObject::Binder vaoBinder(&quadVAO); @@ -87,15 +110,20 @@ QVector3D lightPositions[] = { QVector3D(0,0,0), QVector3D(100,100,100) ,QVector QVector3D lightColors[] = { QVector3D(150000,150000,130000), QVector3D(0,0,0) ,QVector3D(0,0,0) ,QVector3D(0,0,0) }; void RendererWidget::paintGL() { - fboPtr->bind(); + if (fboPtr->bind()) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + QMatrix4x4 view = camera.GetViewMatrix(); modelProgramPtr->bind(); - modelProgramPtr->setUniformValue("view", camera.GetViewMatrix()); - model->draw(); + modelProgramPtr->setUniformValue("view", view); modelProgramPtr->release(); + paintingProgramPtr->bind(); + paintingProgramPtr->setUniformValue("view", view); + paintingProgramPtr->release(); + model->draw(); + fboPtr->release(); } - fboPtr->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); @@ -133,15 +161,19 @@ void RendererWidget::resizeGL(int width, int height) fboPtr->addColorAttachment(devicePixelRatio() * width, devicePixelRatio() * height, GL_RG); GLenum attachments[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3 }; glDrawBuffers(4, attachments); - fboPtr->bind(); + if (fboPtr->bind()) { - modelProgramPtr->bind(); QMatrix4x4 projection; projection.perspective(camera.Zoom, (float)width / (float)height, 10.f, 10000.0f); + modelProgramPtr->bind(); modelProgramPtr->setUniformValue("projection", projection); modelProgramPtr->release(); + paintingProgramPtr->bind(); + paintingProgramPtr->setUniformValue("projection", projection); + paintingProgramPtr->release(); + fboPtr->release(); } - fboPtr->release(); + } void RendererWidget::timerEvent(QTimerEvent* event) diff --git a/ArchitectureColoredPainting/RendererWidget.h b/ArchitectureColoredPainting/RendererWidget.h index ea254c8..ba6d4cc 100644 --- a/ArchitectureColoredPainting/RendererWidget.h +++ b/ArchitectureColoredPainting/RendererWidget.h @@ -32,6 +32,7 @@ private: clock_t lastFrame; float deltaTime; QOpenGLShaderProgram* modelProgramPtr = nullptr; + QOpenGLShaderProgram* paintingProgramPtr = nullptr; QOpenGLShaderProgram* finalProgramPtr = nullptr; QOpenGLFramebufferObject* fboPtr = nullptr; QOpenGLBuffer quadVBO; diff --git a/ArchitectureColoredPainting/Shaders/final.frag b/ArchitectureColoredPainting/Shaders/final.frag index 869800b..d2fd4b4 100644 --- a/ArchitectureColoredPainting/Shaders/final.frag +++ b/ArchitectureColoredPainting/Shaders/final.frag @@ -108,5 +108,4 @@ void main() color = pow(color, vec3(1.0/2.2)); FragColor = vec4(color, 1.0); - } \ No newline at end of file diff --git a/ArchitectureColoredPainting/Shaders/painting.frag b/ArchitectureColoredPainting/Shaders/painting.frag new file mode 100644 index 0000000..2ac91c6 --- /dev/null +++ b/ArchitectureColoredPainting/Shaders/painting.frag @@ -0,0 +1,18 @@ +#version 330 core + +layout (location = 0) out vec4 gBaseColor; +layout (location = 1) out vec3 gNormal; +layout (location = 2) out vec3 gPosition; +layout (location = 3) out vec2 gMetallicRoughness; + +in vec2 TexCoords; +in vec3 WorldPos; +in vec3 Normal; + +void main() +{ + gBaseColor = vec4(TexCoords,1,1); + gPosition = WorldPos; + gNormal = Normal; + gMetallicRoughness = vec2(0,0); +} \ No newline at end of file diff --git a/ArchitectureColoredPainting/Shaders/painting.vert b/ArchitectureColoredPainting/Shaders/painting.vert new file mode 100644 index 0000000..8e2587b --- /dev/null +++ b/ArchitectureColoredPainting/Shaders/painting.vert @@ -0,0 +1,22 @@ +#version 330 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/README.md b/README.md index 53d85ce..81e3fb4 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,12 @@ 閲囩敤pbr鏉愯川锛岀幇鍦ㄦ湁涓涓厜婧愬拰鎽勫儚鏈虹粦瀹氾紝瓒充互鍒嗚鲸鍑轰笉鍚屾潗璐ㄧ殑鏁堟灉 +鎶婁竴鍧楀竷鏇挎崲鎴愪簡锛堝緟瀹屾垚鐨勶級褰╃粯绠$嚎锛岃PaintingMesh绫讳互鍙妏ainting鐫鑹插櫒 + TODO锛 - [x] 鏀圭敤寤惰繜娓叉煋 -- [ ] 鎸囧畾涓鍧楁潗璐ㄤ娇鐢ㄧ嫭绔嬬绾胯繘琛岀汗鐞嗛噰鏍 \ No newline at end of file +- [x] 鎸囧畾涓鍧楁潗璐ㄤ娇鐢ㄧ嫭绔嬬绾胯繘琛岀汗鐞嗛噰鏍 + +- [ ] 褰╃粯鐨勮〃绀恒佽鍙栥侀噰鏍... \ No newline at end of file