8.17会议存档

dev-VirtualTexture
wuyize 2022-08-17 13:08:34 +08:00
parent b37e5a0ee7
commit 1476da4cf8
14 changed files with 534 additions and 218 deletions

View File

@ -89,6 +89,7 @@
<ClCompile Include="Camera.cpp" />
<ClCompile Include="Mesh.cpp" />
<ClCompile Include="Model.cpp" />
<ClCompile Include="PaintingHelper.cpp" />
<ClCompile Include="PaintingMesh.cpp" />
<ClCompile Include="RendererWidget.cpp" />
<QtRcc Include="MainWindow.qrc" />
@ -117,6 +118,7 @@
<ClInclude Include="Drawable.h" />
<ClInclude Include="Mesh.h" />
<ClInclude Include="Model.h" />
<ClInclude Include="PaintingHelper.h" />
<ClInclude Include="PaintingMesh.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

View File

@ -61,6 +61,9 @@
<ClCompile Include="BvhTree.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="PaintingHelper.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<QtMoc Include="RendererWidget.h">
@ -115,5 +118,8 @@
<ClInclude Include="BvhTree.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="PaintingHelper.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -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<QOpenGLFunctions_4_5_Compatibility>())
, 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<QVector4D> 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<GLuint> children;
std::vector<QVector4D> bounds;
bvhTree.getBvhArray(children, bounds);
GLuint bvhChildren[] = { 7/*rootBVH长度*/,0/*与显存对齐*/,
std::vector<GLuint> 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<QVector4D> 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<QVector4D> 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<GLuint> children;
std::vector<QVector4D> 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<GLuint> 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<GLuint> 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<GLfloat> 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<GLuint>(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<Texture*> Model::loadMaterialTextures(aiMaterial* mat, aiTextureType type, QString typeName)
{
QVector<Texture*> textures;
for (unsigned int i = 0; i < mat->GetTextureCount(type); i++)

View File

@ -2,6 +2,7 @@
#include "Mesh.h"
#include "Drawable.h"
#include "PaintingHelper.h"
#include <QDir>
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<Texture*> textures_loaded; //纹理
QVector<Drawable*> meshes; //网格

View File

@ -0,0 +1,66 @@
#include "PaintingHelper.h"
PaintingHelper::PaintingHelper(QOpenGLFunctions_4_5_Compatibility* glFunc) :glFunc(glFunc)
{
}
int PaintingHelper::addPainting(GLuint paintingBvhLength, std::vector<GLuint> bvhChildren, std::vector<QVector4D> bvhBound, std::vector<GLuint> elementOffset, std::vector<GLuint> elementIndex, std::vector<GLfloat> 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);
}

View File

@ -0,0 +1,29 @@
#pragma once
#include <vector>
#include <QDebug>
#include <QVector4D>
#include <QOpenGLFunctions_4_5_Compatibility>
#include "BvhTree.h"
class PaintingHelper
{
private:
QOpenGLFunctions_4_5_Compatibility* glFunc;
GLuint paintingOffsetsSSBO, bvhSSBO, bvhBoundSSBO, elementOffsetSSBO, elementIndexSSBO, elementDataSSBO;
std::vector<GLuint> paintingOffsets;
std::vector<GLuint> bvhChildren;
std::vector<QVector4D> bvhBound;
std::vector<GLuint> elementOffset;
std::vector<GLuint> elementIndex;
std::vector<GLfloat> elementData;
int paintingCount = 0;
public:
PaintingHelper(QOpenGLFunctions_4_5_Compatibility* glFunc);
int addPainting(GLuint paintingBvhLength, std::vector<GLuint> bvhChildren, std::vector<QVector4D> bvhBound,
std::vector<GLuint> elementOffset, std::vector<GLuint> elementIndex, std::vector<GLfloat> elementData);
void allocateBuffers();
void bindPaintingBuffers();
};

View File

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

View File

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

View File

@ -6,6 +6,7 @@
#include <QScreen>
#include <QGuiApplication>
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<QOpenGLFunctions_4_5_Compatibility>());
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();
}

View File

@ -9,6 +9,7 @@
#include <QKeyEvent>
#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<GLuint> gbuffers;
GLuint gbuffers[6];
QOpenGLBuffer quadVBO;
QOpenGLVertexArrayObject quadVAO;
Model* model;
PaintingHelper* paintingHelper;
};

View File

@ -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];

View File

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

View File

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

View File

@ -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];i<elementOffset[elementIndex][2];i+=7)
// {
// if(tri_test(localUV, vec2(elementData[i],elementData[i+1]),
// vec2(elementData[i+2],elementData[i+3]), vec2(elementData[i+4],elementData[i+5]), true))
// {
// if(elementData[i+6]==0)
// {
// debugHit=true;
// }
// else if(elementData[i+6]==1)
// {
// 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;
// }
// 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);
}