分离出彩绘管线

dev-VirtualTexture
wuyize 2022-07-25 16:23:09 +08:00
parent 549a91ec72
commit 3a600ec440
16 changed files with 517 additions and 228 deletions

View File

@ -88,6 +88,7 @@
<ClCompile Include="Camera.cpp" />
<ClCompile Include="Mesh.cpp" />
<ClCompile Include="Model.cpp" />
<ClCompile Include="PaintingMesh.cpp" />
<ClCompile Include="RendererWidget.cpp" />
<QtRcc Include="MainWindow.qrc" />
<QtUic Include="MainWindow.ui" />
@ -103,13 +104,17 @@
<None Include="Shaders\final.vert" />
<None Include="Shaders\model.frag" />
<None Include="Shaders\model.vert" />
<None Include="Shaders\painting.frag" />
<None Include="Shaders\painting.vert" />
<None Include="Shaders\shader.frag" />
<None Include="Shaders\shader.vert" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="Camera.h" />
<ClInclude Include="Drawable.h" />
<ClInclude Include="Mesh.h" />
<ClInclude Include="Model.h" />
<ClInclude Include="PaintingMesh.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Condition="Exists('$(QtMsBuild)\qt.targets')">

View File

@ -55,6 +55,9 @@
<ClCompile Include="Model.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="PaintingMesh.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<QtMoc Include="RendererWidget.h">
@ -80,6 +83,12 @@
<None Include="Shaders\final.frag">
<Filter>Resource Files\Shaders</Filter>
</None>
<None Include="Shaders\painting.frag">
<Filter>Resource Files\Shaders</Filter>
</None>
<None Include="Shaders\painting.vert">
<Filter>Resource Files\Shaders</Filter>
</None>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Camera.h">
@ -91,5 +100,11 @@
<ClInclude Include="Model.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="PaintingMesh.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Drawable.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -0,0 +1,7 @@
#pragma once
class Drawable
{
public:
virtual void draw() = 0;
};

View File

@ -7,5 +7,7 @@
<file>Shaders/final.frag</file>
<file>Shaders/final.vert</file>
<file>container.jpg</file>
<file>Shaders/painting.frag</file>
<file>Shaders/painting.vert</file>
</qresource>
</RCC>

View File

@ -5,16 +5,19 @@ Mesh::Mesh(QOpenGLFunctions_4_5_Compatibility* glFunc, QOpenGLShaderProgram* sha
, 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()
{
shaderProgram->bind();
unsigned int diffuseNr = 1;
unsigned int specularNr = 1;
unsigned int normalNr = 1;
@ -34,10 +37,12 @@ void Mesh::Draw()
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();
@ -51,6 +56,7 @@ void Mesh::setupMesh()
EBO.allocate(indices.data(), indices.size() * sizeof(unsigned int));
shaderProgram->enableAttributeArray(0);
shaderProgram->setAttributeBuffer(0, GL_FLOAT, 0, 3, sizeof(Vertex));
@ -60,10 +66,12 @@ void Mesh::setupMesh()
shaderProgram->enableAttributeArray(2);
shaderProgram->setAttributeBuffer(2, GL_FLOAT, offsetof(Vertex, TexCoords), 2, sizeof(Vertex));
shaderProgram->enableAttributeArray(1);
shaderProgram->enableAttributeArray(3);
shaderProgram->setAttributeBuffer(3, GL_FLOAT, offsetof(Vertex, Tangent), 3, sizeof(Vertex));
shaderProgram->enableAttributeArray(1);
shaderProgram->enableAttributeArray(4);
shaderProgram->setAttributeBuffer(4, GL_FLOAT, offsetof(Vertex, Bitangent), 3, sizeof(Vertex));
VAO.release();
shaderProgram->release();
}

View File

@ -12,6 +12,7 @@
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/postprocess.h>
#include "Drawable.h"
struct Vertex
{
@ -35,7 +36,8 @@ struct Texture
}
};
class Mesh {
class Mesh : public Drawable
{
public:
/* 网格数据 */
QVector<Vertex> vertices; //顶点数据
@ -47,7 +49,7 @@ public:
/* 函数 */
Mesh(QOpenGLFunctions_4_5_Compatibility* glFunc, QOpenGLShaderProgram* shaderProgram, aiMatrix4x4 model);
void Draw();
void draw() override;
void setupMesh();
private:

View File

@ -4,6 +4,7 @@
#include <QOpenGLContext>
#include <QTextCodec>
#include <iostream>
#include "PaintingMesh.h"
Model::Model(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram)
: context(context)
@ -25,6 +26,27 @@ Model::Model(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shader
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) {
@ -37,9 +59,9 @@ Model::~Model() //
}
void Model::draw() {
shaderProgram->bind();
for (Mesh* mesh : meshes) {
mesh->Draw();
//shaderProgram->bind();
for (Drawable* mesh : meshes) {
mesh->draw();
}
}
@ -71,7 +93,53 @@ void Model::processNode(aiNode* node, const aiScene* scene, aiMatrix4x4 mat4)
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)
{
aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];
aiString str;
material->GetTexture(aiTextureType_BASE_COLOR, 0, &str);
if (paintingProgram != nullptr && std::strcmp(str.C_Str(), "17876391417123941155.jpg")==0)
{
qDebug() << str.C_Str();
// 初始化网格
PaintingMesh* m_mesh = new PaintingMesh(QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_4_5_Compatibility>(), 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);
// 纹理坐标
if (mesh->mTextureCoords[0])
vertex.TexCoords = QVector2D(mesh->mTextureCoords[0][i].x, mesh->mTextureCoords[0][i].y);
if (mesh->mTangents)
vertex.Tangent = QVector3D(mesh->mTangents[i].x, mesh->mTangents[i].y, mesh->mTangents[i].z);
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<QOpenGLFunctions_4_5_Compatibility>(), shaderProgram, model);
@ -133,8 +201,6 @@ Mesh* Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 model)
}
// 处理材质
aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];
QVector<Texture*> diffuseMaps = loadMaterialTextures(material, aiTextureType_BASE_COLOR, "texture_basecolor");
for (auto& it : diffuseMaps)
m_mesh->textures.push_back(it);
@ -151,6 +217,9 @@ Mesh* Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 model)
return m_mesh;
}
}
QVector<Texture*> Model::loadMaterialTextures(aiMaterial* mat, aiTextureType type, QString typeName)
{
QVector<Texture*> textures;

View File

@ -1,6 +1,7 @@
#pragma once
#include "Mesh.h"
#include "Drawable.h"
#include <QDir>
class Model
@ -9,23 +10,24 @@ public:
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; //着色器程序
QOpenGLShaderProgram* shaderProgram = nullptr;
QOpenGLShaderProgram* paintingProgram = nullptr; //彩绘着色器程序
/* 模型数据 */
QVector<Texture*> textures_loaded; //纹理
QVector<Mesh*> meshes; //网格
QVector<Drawable*> meshes; //网格
QDir directory; //模型所在路径
//递归遍历结点
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<Texture*> loadMaterialTextures(aiMaterial* mat, aiTextureType type, QString typeName);

View File

@ -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();
}

View File

@ -0,0 +1,47 @@
#pragma once
#include <QOpenGLFunctions_4_5_Compatibility>
#include <QString>
#include <QVector>
#include <QVector2D>
#include <QVector3D>
#include <QOpenGLShaderProgram>
#include <QOpenGLBuffer>
#include <QOpenGLVertexArrayObject>
#include <QOpenGLTexture>
#include <QOpenGLWidget>
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/postprocess.h>
#include "Drawable.h"
struct PaintingVertex
{
QVector3D Position;
QVector3D Normal;
QVector2D TexCoords;
QVector3D Tangent;
QVector3D Bitangent;
};
class PaintingMesh : public Drawable
{
public:
/* 网格数据 */
QVector<PaintingVertex> vertices; //顶点数据
QVector<unsigned int> 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;
};

View File

@ -15,13 +15,28 @@ RendererWidget::RendererWidget(QWidget* parent)
RendererWidget::~RendererWidget()
{
if (modelProgramPtr == nullptr)
return;
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();
}
}
void RendererWidget::initializeGL()
@ -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();
}
//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,17 +161,21 @@ 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();
}
}
void RendererWidget::timerEvent(QTimerEvent* event)
{
clock_t currentFrame = std::clock();

View File

@ -32,6 +32,7 @@ private:
clock_t lastFrame;
float deltaTime;
QOpenGLShaderProgram* modelProgramPtr = nullptr;
QOpenGLShaderProgram* paintingProgramPtr = nullptr;
QOpenGLShaderProgram* finalProgramPtr = nullptr;
QOpenGLFramebufferObject* fboPtr = nullptr;
QOpenGLBuffer quadVBO;

View File

@ -108,5 +108,4 @@ void main()
color = pow(color, vec3(1.0/2.2));
FragColor = vec4(color, 1.0);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -2,8 +2,12 @@
采用pbr材质现在有一个光源和摄像机绑定足以分辨出不同材质的效果
把一块布替换成了待完成的彩绘管线见PaintingMesh类以及painting着色器
TODO
- [x] 改用延迟渲染
- [ ] 指定一块材质使用独立管线进行纹理采样
- [x] 指定一块材质使用独立管线进行纹理采样
- [ ] 彩绘的表示、读取、采样...