diff --git a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj index f506146..036489e 100644 --- a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj +++ b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj @@ -89,6 +89,7 @@ + @@ -117,6 +118,7 @@ + diff --git a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters index a2b13fe..280e1a9 100644 --- a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters +++ b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters @@ -61,6 +61,9 @@ Source Files + + Source Files + @@ -115,5 +118,8 @@ Header Files + + Header Files + \ No newline at end of file diff --git a/ArchitectureColoredPainting/Model.cpp b/ArchitectureColoredPainting/Model.cpp index c1d2930..7ed80a3 100644 --- a/ArchitectureColoredPainting/Model.cpp +++ b/ArchitectureColoredPainting/Model.cpp @@ -14,11 +14,12 @@ Model::Model(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shader , shaderProgram(shaderProgram) , directory(path) { - Assimp::Importer import; - const aiScene* scene = import.ReadFile(directory.absolutePath().toUtf8(), aiProcess_Triangulate | aiProcess_FlipUVs); + + Assimp::Importer importer; + const aiScene* scene = importer.ReadFile(directory.absolutePath().toUtf8(), aiProcess_Triangulate | aiProcess_FlipUVs); if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) { - qDebug() << "ERROR::ASSIMP::" << import.GetErrorString() << endl; + qDebug() << "ERROR::ASSIMP::" << importer.GetErrorString() << endl; return; } qDebug() << directory.absolutePath() << "Loaded Successfully"; @@ -29,18 +30,19 @@ Model::Model(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shader processNode(scene->mRootNode, scene); } -Model::Model(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* paintingProgram) +Model::Model(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* paintingProgram, PaintingHelper* paintingHelper) : context(context) , glFunc(context->versionFunctions()) , shaderProgram(shaderProgram) , paintingProgram(paintingProgram) + , paintingHelper(paintingHelper) , directory(path) { - Assimp::Importer import; - const aiScene* scene = import.ReadFile(directory.absolutePath().toUtf8(), aiProcess_Triangulate | aiProcess_FlipUVs); + Assimp::Importer importer; + const aiScene* scene = importer.ReadFile(directory.absolutePath().toUtf8(), aiProcess_Triangulate | aiProcess_FlipUVs); if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) { - qDebug() << "ERROR::ASSIMP::" << import.GetErrorString() << endl; + qDebug() << "ERROR::ASSIMP::" << importer.GetErrorString() << endl; return; } qDebug() << directory.absolutePath() << "Loaded Successfully"; @@ -139,21 +141,39 @@ Drawable* Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 mod } } + BvhTree bvhTree; + std::vector initBound; + for (int i = 0; i < 30000; i++) + { + float x = (float)rand() / RAND_MAX * 2 - 1; + float y = (float)rand() / RAND_MAX * 2 - 1; + float z = 0.01 + x;//(float)rand() / RAND_MAX * (0.1) + x; + float w = 0.01 + y;//(float)rand() / RAND_MAX * (0.1) + y; + initBound.push_back(QVector4D(x, y, z, w)); + } + /* initBound.push_back(QVector4D(-0.8, -0.8, -0.7, -0.7)); + initBound.push_back(QVector4D(-0.8, 0.7, -0.7, 0.8)); + initBound.push_back(QVector4D(0.7, -0.8, 0.8, -0.7)); + initBound.push_back(QVector4D(0.7, 0.7, 0.8, 0.8));*/ + bvhTree.buildBvhTree(initBound.data(), initBound.size()); + std::vector children; + std::vector bounds; + bvhTree.getBvhArray(children, bounds); - GLuint bvhChildren[] = { 7/*rootBVH长度*/,0/*与显存对齐*/, + std::vector bvhChildren = { //root 1,2, 3,4, 5,6, - 7,0, 7,30. / 360 * 65536 + 1 * 65536 /*右儿子用来表示旋转角度和层数*/, 8,0, 7,0, + 7,0, 7,GLuint(30. / 360 * 65536 + 1 * 65536) /*右儿子用来表示旋转角度和zIndex*/, 8,0, 7,0, //elememt0 1,2, - 5 + 28/*contour索引,由于contour不定长,这里需要给到contour在elementIndex中位置*/,5 + 12/*style索引,在elementData中位置*/, 3,4, - 5 + 36,5 + 12, 5 + 32,5 + 12, + 5 + 0/*contour索引*/,5 + 12/*style索引,在elementData中位置*/, 3,4, + 5 + 2,5 + 12, 5 + 1,5 + 12, //elememt1 1 + 0/*line索引,element中第几条*/,1 + 25 }; - QVector4D bvhBound[] = { + std::vector bvhBounds = { //root QVector4D(-1,-1,1,1), QVector4D(-0.9,-0.9,-0.1,0.9), QVector4D(0.1, -0.9,0.9,0.9), @@ -165,56 +185,22 @@ Drawable* Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 mod //elememt1 QVector4D(-1,0,1,1), }; - - BvhTree bvhTree; - std::vector initBound; - for (int i = 0; i < 2000; i++) - { - float x = (float)rand() / RAND_MAX * 2 - 1; - float y = (float)rand() / RAND_MAX * 2 - 1; - float z = 0.1+x;//(float)rand() / RAND_MAX * (0.1) + x; - float w = 0.1+y;//(float)rand() / RAND_MAX * (0.1) + y; - initBound.push_back(QVector4D(x,y,z,w)); - } - /* initBound.push_back(QVector4D(-0.8, -0.8, -0.7, -0.7)); - initBound.push_back(QVector4D(-0.8, 0.7, -0.7, 0.8)); - initBound.push_back(QVector4D(0.7, -0.8, 0.8, -0.7)); - initBound.push_back(QVector4D(0.7, 0.7, 0.8, 0.8));*/ - bvhTree.buildBvhTree(initBound.data(), initBound.size()); - std::vector children; - std::vector bounds; - bvhTree.getBvhArray(children, bounds); - qDebug() << children; - qDebug() << bounds; - - glFunc->glGenBuffers(1, &m_mesh->bvhSSBO); - glFunc->glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_mesh->bvhSSBO); - glFunc->glBufferData(GL_SHADER_STORAGE_BUFFER, children.size()*sizeof(GLuint), children.data(), GL_DYNAMIC_DRAW); - glFunc->glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); - - glFunc->glGenBuffers(1, &m_mesh->bvhBoundSSBO); - glFunc->glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_mesh->bvhBoundSSBO); - glFunc->glBufferData(GL_SHADER_STORAGE_BUFFER, bounds.size()*sizeof(QVector4D), bounds.data(), GL_DYNAMIC_DRAW); - glFunc->glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); - - GLuint elementOffset[] = { + std::vector elementOffset = { //element0 7, //elementBvhRoot 5, //elementBvhLength 0, //pointsOffset 0, //linesOffset + 28, //contoursOffset //element1 12, //elementBvhRoot 1, //elementBvhLength 19, //pointsOffset 40, //linesOffset + 44 //contoursOffset }; - glFunc->glGenBuffers(1, &m_mesh->elementOffsetSSBO); - glFunc->glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_mesh->elementOffsetSSBO); - glFunc->glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(elementOffset), elementOffset, GL_DYNAMIC_DRAW); - glFunc->glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); - GLuint elementIndex[] = { + std::vector elementIndex = { //element0 //lines, 全部当作三阶贝塞尔, 每条线四个点索引 4,2,2,0, @@ -224,22 +210,16 @@ Drawable* Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 mod 4,4,5,5, 1,1,3,3, 3,3,5,5, - //contours, 第一个元素指明轮廓段数,后面为lines索引 - 3, 0,1,2, - 3, 2,3,4, - 3, 3,5,6, - + //contours, 每个轮廓三个线索引 + 0,1,2, + 2,3,4, + 3,5,6, //element2 //lines 0,1,2 }; - glFunc->glGenBuffers(1, &m_mesh->elementIndexSSBO); - glFunc->glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_mesh->elementIndexSSBO); - glFunc->glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(elementIndex), elementIndex, GL_DYNAMIC_DRAW); - glFunc->glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); - - GLfloat elementData[] = { + std::vector elementData = { //element0 //points -1,0.5, -1,-0.5, 0,1, 0,-1, 1,0.5, 1,-0.5, @@ -266,11 +246,11 @@ Drawable* Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 mod //strokeFillColorMetallicRoughness 0,1,0, 0,0.8 }; - glFunc->glGenBuffers(1, &m_mesh->elementDataSSBO); - glFunc->glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_mesh->elementDataSSBO); - glFunc->glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(elementData), elementData, GL_DYNAMIC_DRAW); - glFunc->glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); + //m_mesh->paintingIndex = paintingHelper->addPainting(bounds.size(), std::vector(children.begin()+2, children.end()), bounds, + // elementOffset, elementIndex, elementData); + m_mesh->paintingIndex = paintingHelper->addPainting(7, bvhChildren, bvhBounds, + elementOffset, elementIndex, elementData); m_mesh->setupMesh(); return m_mesh; @@ -358,6 +338,7 @@ Drawable* Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 mod QVector Model::loadMaterialTextures(aiMaterial* mat, aiTextureType type, QString typeName) { + QVector textures; for (unsigned int i = 0; i < mat->GetTextureCount(type); i++) diff --git a/ArchitectureColoredPainting/Model.h b/ArchitectureColoredPainting/Model.h index 3206614..818e186 100644 --- a/ArchitectureColoredPainting/Model.h +++ b/ArchitectureColoredPainting/Model.h @@ -2,6 +2,7 @@ #include "Mesh.h" #include "Drawable.h" +#include "PaintingHelper.h" #include class Model @@ -10,7 +11,7 @@ public: void draw(); void destroy(); static Model* createModel(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram); - Model(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* paintingProgram); + Model(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* paintingProgram, PaintingHelper* paintingHelper); private: Model(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram); @@ -19,6 +20,8 @@ private: QOpenGLFunctions_4_5_Compatibility* glFunc; QOpenGLShaderProgram* shaderProgram = nullptr; QOpenGLShaderProgram* paintingProgram = nullptr; //彩绘着色器程序 + PaintingHelper* paintingHelper = nullptr; + /* 模型数据 */ QVector textures_loaded; //纹理 QVector meshes; //网格 diff --git a/ArchitectureColoredPainting/PaintingHelper.cpp b/ArchitectureColoredPainting/PaintingHelper.cpp new file mode 100644 index 0000000..7ec9261 --- /dev/null +++ b/ArchitectureColoredPainting/PaintingHelper.cpp @@ -0,0 +1,66 @@ +#include "PaintingHelper.h" + + +PaintingHelper::PaintingHelper(QOpenGLFunctions_4_5_Compatibility* glFunc) :glFunc(glFunc) +{ + +} + +int PaintingHelper::addPainting(GLuint paintingBvhLength, std::vector bvhChildren, std::vector bvhBound, std::vector elementOffset, std::vector elementIndex, std::vector elementData) +{ + this->paintingOffsets.push_back(0);//paintingBvhRoot + this->paintingOffsets.push_back(paintingBvhLength); + + this->bvhChildren.insert(this->bvhChildren.end(), bvhChildren.begin(), bvhChildren.end()); + this->bvhBound.insert(this->bvhBound.end(), bvhBound.begin(), bvhBound.end()); + this->elementOffset.insert(this->elementOffset.end(), elementOffset.begin(), elementOffset.end()); + this->elementIndex.insert(this->elementIndex.end(), elementIndex.begin(), elementIndex.end()); + this->elementData.insert(this->elementData.end(), elementData.begin(), elementData.end()); + + return ++paintingCount; +} + +void PaintingHelper::allocateBuffers() +{ + glFunc->glGenBuffers(1, &paintingOffsetsSSBO); + glFunc->glBindBuffer(GL_SHADER_STORAGE_BUFFER, paintingOffsetsSSBO); + glFunc->glBufferData(GL_SHADER_STORAGE_BUFFER, paintingOffsets.size() * sizeof(GLuint), paintingOffsets.data(), GL_DYNAMIC_DRAW); + glFunc->glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); + + glFunc->glGenBuffers(1, &bvhSSBO); + glFunc->glBindBuffer(GL_SHADER_STORAGE_BUFFER, bvhSSBO); + glFunc->glBufferData(GL_SHADER_STORAGE_BUFFER, bvhChildren.size() * sizeof(GLuint), bvhChildren.data(), GL_DYNAMIC_DRAW); + glFunc->glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); + + glFunc->glGenBuffers(1, &bvhBoundSSBO); + glFunc->glBindBuffer(GL_SHADER_STORAGE_BUFFER, bvhBoundSSBO); + glFunc->glBufferData(GL_SHADER_STORAGE_BUFFER, bvhBound.size() * sizeof(QVector4D), bvhBound.data(), GL_DYNAMIC_DRAW); + glFunc->glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); + + + glFunc->glGenBuffers(1, &elementOffsetSSBO); + glFunc->glBindBuffer(GL_SHADER_STORAGE_BUFFER, elementOffsetSSBO); + glFunc->glBufferData(GL_SHADER_STORAGE_BUFFER, elementOffset.size() * sizeof(GLuint), elementOffset.data(), GL_DYNAMIC_DRAW); + glFunc->glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); + + + glFunc->glGenBuffers(1, &elementIndexSSBO); + glFunc->glBindBuffer(GL_SHADER_STORAGE_BUFFER, elementIndexSSBO); + glFunc->glBufferData(GL_SHADER_STORAGE_BUFFER, elementIndex.size() * sizeof(GLuint), elementIndex.data(), GL_DYNAMIC_DRAW); + glFunc->glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); + + glFunc->glGenBuffers(1, &elementDataSSBO); + glFunc->glBindBuffer(GL_SHADER_STORAGE_BUFFER, elementDataSSBO); + glFunc->glBufferData(GL_SHADER_STORAGE_BUFFER, elementData.size() * sizeof(GLfloat), elementData.data(), GL_DYNAMIC_DRAW); + glFunc->glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); +} + +void PaintingHelper::bindPaintingBuffers() +{ + glFunc->glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, paintingOffsetsSSBO); + glFunc->glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, bvhSSBO); + glFunc->glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, bvhBoundSSBO); + glFunc->glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, elementOffsetSSBO); + glFunc->glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, elementIndexSSBO); + glFunc->glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 6, elementDataSSBO); +} diff --git a/ArchitectureColoredPainting/PaintingHelper.h b/ArchitectureColoredPainting/PaintingHelper.h new file mode 100644 index 0000000..b8dc972 --- /dev/null +++ b/ArchitectureColoredPainting/PaintingHelper.h @@ -0,0 +1,29 @@ +#pragma once + +#include +#include +#include +#include +#include "BvhTree.h" + +class PaintingHelper +{ +private: + QOpenGLFunctions_4_5_Compatibility* glFunc; + GLuint paintingOffsetsSSBO, bvhSSBO, bvhBoundSSBO, elementOffsetSSBO, elementIndexSSBO, elementDataSSBO; + std::vector paintingOffsets; + std::vector bvhChildren; + std::vector bvhBound; + std::vector elementOffset; + std::vector elementIndex; + std::vector elementData; + int paintingCount = 0; + +public: + PaintingHelper(QOpenGLFunctions_4_5_Compatibility* glFunc); + int addPainting(GLuint paintingBvhLength, std::vector bvhChildren, std::vector bvhBound, + std::vector elementOffset, std::vector elementIndex, std::vector elementData); + void allocateBuffers(); + void bindPaintingBuffers(); +}; + diff --git a/ArchitectureColoredPainting/PaintingMesh.cpp b/ArchitectureColoredPainting/PaintingMesh.cpp index 0c51a8d..56ad12d 100644 --- a/ArchitectureColoredPainting/PaintingMesh.cpp +++ b/ArchitectureColoredPainting/PaintingMesh.cpp @@ -14,13 +14,6 @@ void PaintingMesh::draw() shaderProgram->bind(); QOpenGLVertexArrayObject::Binder bind(&VAO); shaderProgram->setUniformValue("model", model); - - glFunc->glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, bvhSSBO); - glFunc->glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, bvhBoundSSBO); - glFunc->glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, elementOffsetSSBO); - glFunc->glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, elementIndexSSBO); - glFunc->glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, elementDataSSBO); - glFunc->glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0); glFunc->glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); shaderProgram->release(); diff --git a/ArchitectureColoredPainting/PaintingMesh.h b/ArchitectureColoredPainting/PaintingMesh.h index e5eebd2..eae18ce 100644 --- a/ArchitectureColoredPainting/PaintingMesh.h +++ b/ArchitectureColoredPainting/PaintingMesh.h @@ -33,9 +33,7 @@ public: QMatrix4x4 model; //模型矩阵 QOpenGLFunctions_4_5_Compatibility* glFunc; //opengl函数入口 QOpenGLShaderProgram* shaderProgram; //着色器程序 - - GLuint bvhSSBO, bvhBoundSSBO, elementOffsetSSBO, elementIndexSSBO, elementDataSSBO; - + GLuint paintingIndex; /* 函数 */ PaintingMesh(QOpenGLFunctions_4_5_Compatibility* glFunc, QOpenGLShaderProgram* shaderProgram, aiMatrix4x4 model); void draw() override; diff --git a/ArchitectureColoredPainting/RendererWidget.cpp b/ArchitectureColoredPainting/RendererWidget.cpp index 4f0fcc6..b79b8ec 100644 --- a/ArchitectureColoredPainting/RendererWidget.cpp +++ b/ArchitectureColoredPainting/RendererWidget.cpp @@ -6,6 +6,7 @@ #include #include + RendererWidget::RendererWidget(QWidget* parent) : QOpenGLWidget(parent), camera(QVector3D(0.0f, 100.0f, 0.0f)) { @@ -84,10 +85,20 @@ void RendererWidget::initializeGL() finalProgramPtr->setUniformValue("gNormal", 1); finalProgramPtr->setUniformValue("gPosition", 2); finalProgramPtr->setUniformValue("gMetallicRoughness", 3); - finalProgramPtr->setUniformValue("gPainting", 4); finalProgramPtr->release(); - model = new Model("Models/Sponza/Sponza.gltf", context(), modelProgramPtr, paintingProgramPtr); + + + paintingHelper = new PaintingHelper(QOpenGLContext::currentContext()->versionFunctions()); + + model = new Model("Models/Sponza/Sponza.gltf", context(), modelProgramPtr, paintingProgramPtr, paintingHelper); + + + paintingHelper->allocateBuffers(); + paintingCompProgramPtr->bind(); + paintingHelper->bindPaintingBuffers(); + paintingCompProgramPtr->release(); + quadVAO.create(); QOpenGLVertexArrayObject::Binder vaoBinder(&quadVAO); @@ -143,9 +154,12 @@ void RendererWidget::paintGL() glActiveTexture(GL_TEXTURE4); glBindTexture(GL_TEXTURE_2D, gbuffers[4]); glBindImageTexture(0, gbuffers[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8); - glBindImageTexture(1, gbuffers[3], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RG16); - glBindImageTexture(2, gbuffers[4], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); + 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); + 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)); @@ -167,8 +181,6 @@ 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, gbuffers[4]); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); finalProgramPtr->release(); } @@ -185,13 +197,48 @@ void RendererWidget::resizeGL(int width, int height) fboPtr = new QOpenGLFramebufferObject(frameWidth, frameHeight, QOpenGLFramebufferObject::Depth, GL_TEXTURE_2D); if (fboPtr->bind()) { + /*fboPtr->addColorAttachment(frameWidth, frameHeight, GL_RGB16F); fboPtr->addColorAttachment(frameWidth, frameHeight, GL_RGB16F); - fboPtr->addColorAttachment(frameWidth, frameHeight, GL_RGB16F); - fboPtr->addColorAttachment(frameWidth, frameHeight, GL_RG16); - fboPtr->addColorAttachment(frameWidth, frameHeight, GL_RGBA32F); - GLenum attachments[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3, GL_COLOR_ATTACHMENT4 }; - glDrawBuffers(5, attachments); - gbuffers = fboPtr->textures(); + fboPtr->addColorAttachment(frameWidth, frameHeight, GL_RG8); + fboPtr->addColorAttachment(frameWidth, frameHeight, GL_R16F); + fboPtr->addColorAttachment(frameWidth, frameHeight, GL_RG16F);*/ + + gbuffers[0] = fboPtr->texture(); + + glGenTextures(5, gbuffers+1); + 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); + + glBindTexture(GL_TEXTURE_2D, gbuffers[2]); + 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_ATTACHMENT2, GL_TEXTURE_2D, gbuffers[2], 0); + + 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); + + 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); + + glBindTexture(GL_TEXTURE_2D, gbuffers[5]); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RG16F, 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); + + 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(); fboPtr->release(); } diff --git a/ArchitectureColoredPainting/RendererWidget.h b/ArchitectureColoredPainting/RendererWidget.h index 7a07611..ba9d389 100644 --- a/ArchitectureColoredPainting/RendererWidget.h +++ b/ArchitectureColoredPainting/RendererWidget.h @@ -9,6 +9,7 @@ #include #include "Camera.h" #include "Model.h" +#include "PaintingHelper.h" class RendererWidget : public QOpenGLWidget, protected QOpenGLFunctions_4_5_Compatibility { @@ -39,9 +40,10 @@ private: QOpenGLShaderProgram* paintingCompProgramPtr = nullptr; QOpenGLShaderProgram* finalProgramPtr = nullptr; QOpenGLFramebufferObject* fboPtr = nullptr; - QVector gbuffers; + GLuint gbuffers[6]; QOpenGLBuffer quadVBO; QOpenGLVertexArrayObject quadVAO; Model* model; + PaintingHelper* paintingHelper; }; diff --git a/ArchitectureColoredPainting/Shaders/final.frag b/ArchitectureColoredPainting/Shaders/final.frag index 2d28b67..f0df30b 100644 --- a/ArchitectureColoredPainting/Shaders/final.frag +++ b/ArchitectureColoredPainting/Shaders/final.frag @@ -8,7 +8,7 @@ uniform sampler2D gBaseColor; uniform sampler2D gNormal; uniform sampler2D gPosition; uniform sampler2D gMetallicRoughness; -uniform sampler2D gPainting; + // lights uniform vec3 lightPositions[4]; uniform vec3 lightColors[4]; diff --git a/ArchitectureColoredPainting/Shaders/model.frag b/ArchitectureColoredPainting/Shaders/model.frag index bb6a470..dac9416 100644 --- a/ArchitectureColoredPainting/Shaders/model.frag +++ b/ArchitectureColoredPainting/Shaders/model.frag @@ -9,7 +9,7 @@ layout (location = 0) out vec4 gBaseColor; layout (location = 1) out vec3 gNormal; layout (location = 2) out vec3 gPosition; layout (location = 3) out vec2 gMetallicRoughness; -layout(location = 4) out vec3 gPainting; +layout (location = 4) out uint gPaintingIndex; in vec2 TexCoords; in vec3 WorldPos; @@ -43,6 +43,6 @@ void main() gPosition = WorldPos; gNormal = getNormalFromMap(); gMetallicRoughness = texture(texture_metallic_roughness, TexCoords).bg; - gPainting = vec3(0); + gPaintingIndex = 0; } \ No newline at end of file diff --git a/ArchitectureColoredPainting/Shaders/painting.comp b/ArchitectureColoredPainting/Shaders/painting.comp index ac913ac..2037d52 100644 --- a/ArchitectureColoredPainting/Shaders/painting.comp +++ b/ArchitectureColoredPainting/Shaders/painting.comp @@ -3,43 +3,50 @@ layout (local_size_x = 8, local_size_y = 8) in; layout(rgba8, binding = 0) uniform image2D gBaseColor; -layout(rg16, binding = 1) uniform image2D gMetallicRoughness; -layout(rgba32f, binding = 2) uniform image2D gPainting; +layout(rg8, binding = 1) uniform image2D gMetallicRoughness; +layout(r16ui, binding = 2) uniform uimage2D gPaintingIndex; +layout(rg16f, binding = 3) uniform image2D gPaintingTexCoord; - - -layout(std430, binding = 1) buffer bvhBuffer +layout(std430, binding = 1) buffer paintingOffsetBuffer +{ + /********************** + ** @x paintingBvhRoot + ** @y paintingBvhLength + **********************/ + uvec2 paintingOffsets[]; +}; + +layout(std430, binding = 2) buffer bvhBuffer { - uint bvhLength; uvec2 bvhChildren[]; }; -layout(std430, binding = 2) buffer bvhBoundBuffer +layout(std430, binding = 3) buffer bvhBoundBuffer { vec4 bvhBound[]; }; -layout(std430, binding = 3) buffer elementOffsetBuffer +layout(std430, binding = 4) buffer elementOffsetBuffer { /********************** - ** @x elementBvhRoot - ** @y elementBvhLength - ** @z pointsOffset - ** @w linesOffset + ** @[0] elementBvhRoot + ** @[1] elementBvhLength + ** @[2] pointsOffset + ** @[3] linesOffset + ** @[4] contoursOffset **********************/ - uvec4 elementOffset[]; + uint elementOffset[][5]; }; -layout(std430, binding = 4) buffer elementIndexBuffer +layout(std430, binding = 5) buffer elementIndexBuffer { uint elementIndexs[]; //线和面 }; -layout(std430, binding = 5) buffer elementDataBuffer +layout(std430, binding = 6) buffer elementDataBuffer { float elementData[]; //点和Style }; - const float PI = 3.14159265358979; -const uint STACK_SIZE = 30; +const uint STACK_SIZE = 16; struct Stack { @@ -79,21 +86,287 @@ struct Stack } stack, elementStack; +// Modified from http://tog.acm.org/resources/GraphicsGems/gems/Roots3And4.c +// Credits to Doublefresh for hinting there +int solve_quadric(vec2 coeffs, inout vec2 roots) +{ + + // normal form: x^2 + px + q = 0 + float p = coeffs[1] / 2.; + float q = coeffs[0]; + + float D = p * p - q; + + if (D < 0.) + { + return 0; + } + else + { + roots[0] = -sqrt(D) - p; + roots[1] = sqrt(D) - p; + + return 2; + } +} + +// From Trisomie21 +// But instead of his cancellation fix i'm using a newton iteration +int solve_cubic(vec3 coeffs, inout vec3 r) +{ + + float a = coeffs[2]; + float b = coeffs[1]; + float c = coeffs[0]; + + float p = b - a * a / 3.0; + float q = a * (2.0 * a * a - 9.0 * b) / 27.0 + c; + float p3 = p * p * p; + float d = q * q + 4.0 * p3 / 27.0; + float offset = -a / 3.0; + if (d >= 0.0) + { // Single solution + float z = sqrt(d); + float u = (-q + z) / 2.0; + float v = (-q - z) / 2.0; + u = sign(u) * pow(abs(u), 1.0 / 3.0); + v = sign(v) * pow(abs(v), 1.0 / 3.0); + r[0] = offset + u + v; + + // Single newton iteration to account for cancellation + float f = ((r[0] + a) * r[0] + b) * r[0] + c; + float f1 = (3. * r[0] + 2. * a) * r[0] + b; + + r[0] -= f / f1; + + return 1; + } + float u = sqrt(-p / 3.0); + float v = acos(-sqrt(-27.0 / p3) * q / 2.0) / 3.0; + float m = cos(v), n = sin(v) * 1.732050808; + + // Single newton iteration to account for cancellation + //(once for every root) + r[0] = offset + u * (m + m); + r[1] = offset - u * (n + m); + r[2] = offset + u * (n - m); + + vec3 f = ((r + a) * r + b) * r + c; + vec3 f1 = (3. * r + 2. * a) * r + b; + + r -= f / f1; + + return 3; +} + + +int segment_int_test(vec2 uv, vec2 p0, vec2 p1) +{ + p0 -= uv; + p1 -= uv; + + int ret; + + if (p0.y * p1.y < 0.) + { + vec2 nor = p0 - p1; + nor = vec2(nor.y, -nor.x); + + float sgn; + + if (p0.y > p1.y) + { + sgn = 1.; + } + else + { + sgn = -1.; + } + + if (dot(nor, p0) * sgn < 0.) + { + ret = 0; + } + else + { + ret = 1; + } + } + else + { + ret = 0; + } + + return ret; +} + +int cubic_bezier_int_test(vec2 uv, vec2 p0, vec2 p1, vec2 p2, vec2 p3) +{ + + float cu = (-p0.y + 3. * p1.y - 3. * p2.y + p3.y); + float qu = (3. * p0.y - 6. * p1.y + 3. * p2.y); + float li = (-3. * p0.y + 3. * p1.y); + float co = p0.y - uv.y; + + vec3 roots = vec3(1e38); + int n_roots; + + int n_ints = 0; + + if (uv.x < min(min(p0.x, p1.x), min(p2.x, p3.x))) + { + if (uv.y >= min(p0.y, p3.y) && uv.y <= max(p0.y, p3.y)) + { + n_ints = 1; + } + } + else + { + + if (abs(cu) < .0001) + { + n_roots = solve_quadric(vec2(co / qu, li / qu), roots.xy); + } + else + { + n_roots = solve_cubic(vec3(co / cu, li / cu, qu / cu), roots); + } + + for (int i = 0; i < n_roots; i++) + { + if (roots[i] >= 0. && roots[i] <= 1.) + { + float x_pos = -p0.x + 3. * p1.x - 3. * p2.x + p3.x; + x_pos = x_pos * roots[i] + 3. * p0.x - 6. * p1.x + 3. * p2.x; + x_pos = x_pos * roots[i] + -3. * p0.x + 3. * p1.x; + x_pos = x_pos * roots[i] + p0.x; + + if (x_pos > uv.x) + { + n_ints++; + } + } + } + } + + return n_ints; +} + + +vec3 drawElement(uint elementIndex, vec2 localUV, inout vec3 debugBVH = vec3(0)) +{ + vec4 elementColor = vec4(0); + + uint currentOffset[5] = elementOffset[elementIndex]; + uint elementBvhRoot = currentOffset[0]; + uint elementBvhLength = currentOffset[1]; + uint pointsOffset = currentOffset[2]; + uint linesOffset = currentOffset[3]; + uint contoursOffset = currentOffset[4]; + + elementStack.top = 0; + uint elementBvhIndex = 0; + while (elementBvhIndex < elementBvhLength || !elementStack.empty()) + { + + while (elementBvhIndex < elementBvhLength) + { + vec4 bound = bvhBound[elementBvhRoot + elementBvhIndex]; + uint leftChild = bvhChildren[elementBvhRoot + elementBvhIndex].x; + + if (all(lessThan(bound.xy, localUV)) && all(lessThan(localUV, bound.zw))) + { + if (leftChild >= elementBvhLength) + { + debugBVH.g += 0.5; + + uint styleIndex = bvhChildren[elementBvhRoot + elementBvhIndex].y - elementBvhLength; + // for(int i = 0; i<200;i++) + if (elementData[styleIndex] == 0.) //面 + { + uint contourIndex = leftChild - elementBvhLength; + + uint num_its = 0; + + uint contourIterator = contoursOffset + contourIndex*3; + if(elementIndexs[contourIterator]==elementIndexs[contourIterator+1]) + contourIterator++; + for (;contourIterator < contoursOffset + contourIndex*3 + 3; contourIterator++) + { + uint lineIndex = elementIndexs[contourIterator]; + uint p0Index = elementIndexs[linesOffset + 4 * lineIndex]; + uint p1Index = elementIndexs[linesOffset + 4 * lineIndex + 1]; + uint p2Index = elementIndexs[linesOffset + 4 * lineIndex + 2]; + uint p3Index = elementIndexs[linesOffset + 4 * lineIndex + 3]; + + vec2 p0 = vec2(elementData[pointsOffset + 2 * p0Index], + elementData[pointsOffset + 2 * p0Index + 1]); + vec2 p1 = vec2(elementData[pointsOffset + 2 * p1Index], + elementData[pointsOffset + 2 * p1Index + 1]); + vec2 p2 = vec2(elementData[pointsOffset + 2 * p2Index], + elementData[pointsOffset + 2 * p2Index + 1]); + vec2 p3 = vec2(elementData[pointsOffset + 2 * p3Index], + elementData[pointsOffset + 2 * p3Index + 1]); + + if (p0 == p1 && p2 == p3) + { + num_its += segment_int_test(localUV, p0, p3); + } + + else + num_its += cubic_bezier_int_test(localUV, p0, p1, p2, p3); + } + + if (num_its % 2 == 1) + { + elementColor = vec4(1); + //debugHit = true; + } + } + else if (elementData[styleIndex] == 1) //线 + { + } + + elementBvhIndex = elementBvhLength; + } + else + { + // debugBVH.b += 0.2; + elementStack.push(elementBvhIndex); + elementBvhIndex = leftChild; + } + } + else + elementBvhIndex = elementBvhLength; + } + if (!elementStack.empty()) + { + elementStack.getTop(elementBvhIndex); + elementStack.pop(); + elementBvhIndex = bvhChildren[elementBvhRoot + elementBvhIndex].y; + } + } + return elementColor.xyz; +} + void main() { + //ivec2 pixelLocation = ivec2(((gl_LocalInvocationID.xy)*imageSize(gPaintingIndex)/gl_WorkGroupSize.xy + gl_WorkGroupID.xy).xy); ivec2 pixelLocation = ivec2(gl_GlobalInvocationID.xy); - if(imageLoad(gPainting, pixelLocation).r==0) + uint paintingIndex = imageLoad(gPaintingIndex, pixelLocation).r; + if(paintingIndex==0) return; imageStore(gMetallicRoughness, pixelLocation, vec4(0 /*金属度*/, 0.8 /*粗糙度*/, 0, 1)); - vec2 uv = imageLoad(gPainting, pixelLocation).gb; + vec2 uv = imageLoad(gPaintingTexCoord, pixelLocation).rg; vec3 debugBVH = vec3(0); bool debugHit = false; stack.top = 0; uint index = 0, visitTime = 0; + uint bvhLength = paintingOffsets[paintingIndex-1].y; while (index < bvhLength || !stack.empty()) { while (index < bvhLength) @@ -115,10 +388,10 @@ void main() if (zIndex == 1) debugBVH = vec3(1, 0, 1); uint elementIndex = leftChild - bvhLength; - debugBVH.bg += 0.5 * (localUV + vec2(1)); - // debugBVH = vec3(0); - - //debugHit = drawElement(leftChild - bvhLength, localUV, debugBVH) == vec3(1); + debugBVH.bg += 0.5 * (localUV + vec2(1)); + + debugBVH = vec3(0); + debugHit = drawElement(leftChild - bvhLength, localUV, debugBVH) == vec3(1); } @@ -126,7 +399,7 @@ void main() } else if (all(lessThan(bound.xy, uv)) && all(lessThan(uv, bound.zw))) { - debugBVH.r += 0.2; + debugBVH.r += 0.02; stack.push(index); index = leftChild; } diff --git a/ArchitectureColoredPainting/Shaders/painting.frag b/ArchitectureColoredPainting/Shaders/painting.frag index 2c66ebf..0c2f200 100644 --- a/ArchitectureColoredPainting/Shaders/painting.frag +++ b/ArchitectureColoredPainting/Shaders/painting.frag @@ -4,12 +4,29 @@ layout(location = 0) out vec4 gBaseColor; layout(location = 1) out vec3 gNormal; layout(location = 2) out vec3 gPosition; layout(location = 3) out vec2 gMetallicRoughness; -layout(location = 4) out vec3 gPainting; +layout(location = 4) out uint gPaintingIndex; +layout(location = 5) out vec2 gPaintingTexCoord; in vec2 TexCoords; in vec3 WorldPos; in vec3 Normal; +void main() +{ + + gBaseColor = vec4( vec3(1),1 ); + // mainImage(gBaseColor, vec2(1.,1.)-TexCoords); + gPosition = WorldPos; + gNormal = normalize(Normal); + // gMetallicRoughness = vec2(1, 46./255); + gMetallicRoughness = vec2(0); + gPaintingIndex = 1; + gPaintingTexCoord = vec2(1., 1.) - TexCoords * 2; + return; + +} + + layout(std430, binding = 1) buffer bvhBuffer { uint bvhLength; @@ -628,104 +645,3 @@ vec3 drawElement(uint elementIndex, vec2 localUV, inout vec3 debugBVH = vec3(0)) -void main() -{ - - gBaseColor = vec4( vec3(1,0,0),1 ); - // mainImage(gBaseColor, vec2(1.,1.)-TexCoords); - gPosition = WorldPos; - gNormal = normalize(Normal); - // gMetallicRoughness = vec2(1, 46./255); - gMetallicRoughness = vec2(0 /*金属度*/, 0.8 /*粗糙度*/); - gPainting = vec3(1, vec2(1., 1.) - TexCoords * 2); - return; - // gBaseColor = vec4(TexCoords,1,1); - // gBaseColor = vec4(240./255, 220./255,157./255,1); - // gBaseColor = vec4(bvh[0].bound==vec4(0,0,1,1)); - - //vec2 uv = vec2(1., 1.) - TexCoords * 2; - vec2 uv = vec2(0., -0.7) ; - vec3 debugBVH = vec3(0); - bool debugHit = false; - stack.top = 0; - uint index = 0, visitTime = 0; - while (index < bvhLength || !stack.empty()) - { - while (index < bvhLength) - { - visitTime++; - vec4 bound = bvhBound[index]; - uint leftChild = bvhChildren[index].x; - if (leftChild >= bvhLength) - { - uint zIndex = bvhChildren[index].y / 65535; - float angle = (bvhChildren[index].y / 65535. - zIndex) * 2 * PI; - - mat2 rotation = {{cos(angle), -sin(angle)}, {sin(angle), cos(angle)}}; - vec2 localUV = uv - (bound.xy + bound.zw) / 2; - localUV = rotation * localUV; - localUV /= (bound.zw - bound.xy) / 2; - if (all(lessThan(vec2(-1), localUV)) && all(lessThan(localUV, vec2(1)))) - { - if (zIndex == 1) - debugBVH = vec3(1, 0, 1); - uint elementIndex = leftChild - bvhLength; - debugBVH.bg += 0.5 * (localUV + vec2(1)); - // debugBVH = vec3(0); - - //debugHit = drawElement(leftChild - bvhLength, localUV, debugBVH) == vec3(1); - - - // mainImage(debugBVH,localUV); - - // for(uint i=elementOffset[elementIndex][1];i0) - // debugHit=true; - // } - // else - // { - // if(bezier_sd(localUV, vec2(elementData[i],elementData[i+1]), - // vec2(elementData[i+2],elementData[i+3]), vec2(elementData[i+4],elementData[i+5]))>0) - // debugHit=true; - // } - // - // } - // } - } - - index = bvhLength; - } - else if (all(lessThan(bound.xy, uv)) && all(lessThan(uv, bound.zw))) - { - debugBVH.r += 0.2; - stack.push(index); - index = leftChild; - } - else - index = bvhLength; - } - if (!stack.empty()) - { - stack.getTop(index); - stack.pop(); - index = bvhChildren[index].y; - } - } - - if (debugHit) - gBaseColor = vec4(vec3(1, 1, 0), 1); - else - gBaseColor = vec4(vec3(int(visitTime)-9), 1); - -} \ No newline at end of file