采样最接近的可用mipmap

dev-VirtualTexture
wuyize 2023-02-22 12:49:46 +08:00
parent 6a02f68514
commit 063be364c2
9 changed files with 85 additions and 56 deletions

View File

@ -7,24 +7,15 @@ uniform ivec2 pixelOffset;
layout(rgba8, binding = 0) uniform image2D gBaseColor; layout(rgba8, binding = 0) uniform image2D gBaseColor;
layout(rg8, binding = 1) uniform image2D gMetallicRoughness; layout(rg8, binding = 1) uniform image2D gMetallicRoughness;
layout(std430, binding = 1) buffer paintingOffsetBuffer layout(std430, binding = 0) buffer bvhBuffer
{
/**********************
** @x paintingBvhRoot
** @y paintingBvhLength
**********************/
uvec2 paintingOffsets[];
};
layout(std430, binding = 2) buffer bvhBuffer
{ {
uvec2 bvhChildren[]; uvec2 bvhChildren[];
}; };
layout(std430, binding = 3) buffer bvhBoundBuffer layout(std430, binding = 1) buffer bvhBoundBuffer
{ {
vec4 bvhBound[]; vec4 bvhBound[];
}; };
layout(std430, binding = 4) buffer elementOffsetBuffer layout(std430, binding = 2) buffer elementOffsetBuffer
{ {
/********************** /**********************
** @[0] elementBvhRoot ** @[0] elementBvhRoot
@ -34,11 +25,11 @@ layout(std430, binding = 4) buffer elementOffsetBuffer
**********************/ **********************/
uvec4 elementOffset[]; uvec4 elementOffset[];
}; };
layout(std430, binding = 5) buffer elementIndexBuffer layout(std430, binding = 3) buffer elementIndexBuffer
{ {
uint elementIndexs[]; //ÏߺÍÃæ uint elementIndexs[]; //ÏߺÍÃæ
}; };
layout(std430, binding = 6) buffer elementDataBuffer layout(std430, binding = 4) buffer elementDataBuffer
{ {
float elementData[]; //µãºÍStyle float elementData[]; //µãºÍStyle
}; };
@ -1182,14 +1173,12 @@ bool drawElement(uint elementIndex, vec2 localUV, out vec3 color, out vec2 metal
void main() void main()
{ {
//ivec2 pixelLocation = ivec2(((gl_LocalInvocationID.xy)*imageSize(gPaintingIndex)/gl_WorkGroupSize.xy + gl_WorkGroupID.xy).xy); ivec2 pixelLocation = ivec2(pixelOffset + gl_GlobalInvocationID.xy);
ivec2 pixelLocation = ivec2(gl_GlobalInvocationID.xy); vec2 uv = (pixelLocation + vec2(0.5)) / imageSize(gBaseColor);
//imageStore(gBaseColor, pixelLocation, vec4(uv,1,1));
vec2 uv = (pixelOffset + pixelLocation + vec2(0.5)) / imageSize(gBaseColor); //imageStore(gMetallicRoughness, pixelLocation, vec4(uv,1,1));
imageStore(gBaseColor, ivec2( pixelOffset + pixelLocation), vec4(uv,1,1)); //return;
imageStore(gMetallicRoughness, ivec2( pixelOffset + pixelLocation), vec4(uv,1,1)); uv = vec2(1)-uv*2;
return;
uv= uv*2-vec2(1);
//vec2 uv = imageLoad(gPaintingTexCoord, pixelLocation).rg; //vec2 uv = imageLoad(gPaintingTexCoord, pixelLocation).rg;
vec3 debugBVH = vec3(0); vec3 debugBVH = vec3(0);

View File

@ -1,4 +1,5 @@
#version 450 core #version 450 core
#extension GL_ARB_sparse_texture2 : enable
uniform sampler2D texture_basecolor; uniform sampler2D texture_basecolor;
uniform sampler2D texture_metallic_roughness; uniform sampler2D texture_metallic_roughness;
@ -16,7 +17,10 @@ in vec3 Normal;
void main() void main()
{ {
gBaseColor = texture(texture_basecolor, TexCoords); float lod = textureQueryLod(texture_basecolor, TexCoords).x;
while(!sparseTexelsResidentARB(sparseTextureLodARB(texture_basecolor, TexCoords, lod, gBaseColor))&&lod<textureQueryLevels(texture_basecolor))
lod++;
if(gBaseColor.a<0.4) if(gBaseColor.a<0.4)
discard; discard;
//gBaseColor = vec4( vec3(1),1 ); //gBaseColor = vec4( vec3(1),1 );
@ -24,7 +28,11 @@ void main()
gPosition = WorldPos; gPosition = WorldPos;
gNormal = normalize(Normal); gNormal = normalize(Normal);
//gMetallicRoughness = vec2(0,1); //gMetallicRoughness = vec2(0,1);
gMetallicRoughness = texture(texture_metallic_roughness, TexCoords).rg; lod = textureQueryLod(texture_metallic_roughness, TexCoords).x;
vec4 mt;
while(!sparseTexelsResidentARB(sparseTextureLodARB(texture_metallic_roughness, TexCoords, lod, mt))&&lod<textureQueryLevels(texture_metallic_roughness))
lod++;
gMetallicRoughness = mt.rg;
//gPaintingIndex = 1; //gPaintingIndex = 1;
gPaintingIndex = 0; gPaintingIndex = 0;
gPaintingTexCoord = vec2(1., 1.) - TexCoords * 2; gPaintingTexCoord = vec2(1., 1.) - TexCoords * 2;

View File

@ -148,8 +148,10 @@ std::unique_ptr<Drawable> Model::processMesh(aiMesh* mesh, const aiScene* scene,
} }
} }
//m_mesh->paintingIndex = loadPainting(std::string(str.C_Str())); m_mesh->paintingIndex = loadPainting(std::string(str.C_Str()));
std::tie(m_mesh->textureBasecolor, m_mesh->textureMetallicRoughness) = loadPainting(std::string(str.C_Str())); auto& handle = vtManager->paintings[m_mesh->paintingIndex];
m_mesh->textureBasecolor = handle.baseColor;
m_mesh->textureMetallicRoughness = handle.metallicRoughness;
m_mesh->setupMesh(); m_mesh->setupMesh();
return m_mesh; return m_mesh;
} }
@ -225,7 +227,7 @@ GLuint Model::loadMaterialTextures(aiMaterial* mat, aiTextureType type)
return texture.textureId(); return texture.textureId();
} }
std::tuple<GLuint, GLuint> Renderer::Model::loadPainting(std::string path) GLuint Renderer::Model::loadPainting(std::string path)
{ {
auto iter = paintingLoaded.find(path); auto iter = paintingLoaded.find(path);
if (iter != paintingLoaded.end()) if (iter != paintingLoaded.end())
@ -327,7 +329,7 @@ std::tuple<GLuint, GLuint> Renderer::Model::loadPainting(std::string path)
//painting.addElement(element[1], QVector4D(-0.7, 0.2, -0.2, 0.7), 0, 0); //painting.addElement(element[1], QVector4D(-0.7, 0.2, -0.2, 0.7), 0, 0);
//painting.addElement(element[2], QVector4D(0.2, -0.8, 0.8, -0.1), 0, 0); //painting.addElement(element[2], QVector4D(0.2, -0.8, 0.8, -0.1), 0, 0);
painting.generateBuffers(); painting.generateBuffers(glFunc);
///////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////
std::vector<GLuint> bvhChildren0 = { std::vector<GLuint> bvhChildren0 = {
//root //root
@ -466,7 +468,7 @@ std::tuple<GLuint, GLuint> Renderer::Model::loadPainting(std::string path)
//GLuint index = paintingHelper->addPainting(painting); //GLuint index = paintingHelper->addPainting(painting);
//paintingLoaded.insert({ path, index }); //paintingLoaded.insert({ path, index });
auto ids = vtManager->createVirtualTexture(painting); auto index = vtManager->createVirtualTexture(painting);
paintingLoaded.emplace(path, ids); paintingLoaded.emplace(path, index);
return ids; return index;
} }

View File

@ -29,7 +29,7 @@ namespace Renderer
VirtualTextureManager* vtManager = nullptr; VirtualTextureManager* vtManager = nullptr;
/* 模型数据 */ /* 模型数据 */
std::unordered_map<std::string, std::tuple<GLuint, GLuint>> paintingLoaded; std::unordered_map<std::string, GLuint> paintingLoaded;
std::unordered_map<std::string, QOpenGLTexture> texturesLoaded; std::unordered_map<std::string, QOpenGLTexture> texturesLoaded;
std::vector<std::unique_ptr<Drawable>> meshes; std::vector<std::unique_ptr<Drawable>> meshes;
@ -47,6 +47,6 @@ namespace Renderer
//加载材质纹理 //加载材质纹理
GLuint loadMaterialTextures(aiMaterial* mat, aiTextureType type); GLuint loadMaterialTextures(aiMaterial* mat, aiTextureType type);
std::tuple<GLuint, GLuint> loadPainting(std::string path); GLuint loadPainting(std::string path);
}; };
} }

View File

@ -105,13 +105,12 @@ BvhTreeData Painting::encodeElementLeaf(ElementWithTransform e)
return BvhTreeData(bound, elementPool[e.element], rightSon); return BvhTreeData(bound, elementPool[e.element], rightSon);
} }
void Painting::generateBuffers() void Painting::generateBuffers(QOpenGLFunctions_4_5_Compatibility* glFunc)
{ {
qDebug() << "Element Count: " << elementPool.size(); qDebug() << "Element Count: " << elementPool.size();
qDebug() << "Coutour Count: " << contourPool.size(); qDebug() << "Coutour Count: " << contourPool.size();
qDebug() << " Style Count: " << stylePool.size(); qDebug() << " Style Count: " << stylePool.size();
bvhChildren.clear(); bvhChildren.clear();
bvhBounds.clear(); bvhBounds.clear();
elementOffset.clear(); elementOffset.clear();
@ -161,6 +160,19 @@ void Painting::generateBuffers()
elementOffset.push_back({ contourBuffer->bvhOffset, stylePool[i.first.style], contourBuffer->pointsOffset, contourBuffer->linesOffset }); elementOffset.push_back({ contourBuffer->bvhOffset, stylePool[i.first.style], contourBuffer->pointsOffset, contourBuffer->linesOffset });
//std::cout << std::format("{} {} {} {}\n", contourBuffer->bvhOffset, stylePool[i.first->style], contourBuffer->pointsOffset, contourBuffer->linesOffset); //std::cout << std::format("{} {} {} {}\n", contourBuffer->bvhOffset, stylePool[i.first->style], contourBuffer->pointsOffset, contourBuffer->linesOffset);
} }
glFunc->glCreateBuffers(5, buffers.data());
GLuint& bvhSSBO = buffers[0];
GLuint& bvhBoundSSBO = buffers[1];
GLuint& elementOffsetSSBO = buffers[2];
GLuint& elementIndexSSBO = buffers[3];
GLuint& elementDataSSBO = buffers[4];
glFunc->glNamedBufferData(bvhSSBO, bvhChildren.size() * sizeof(GLuint), bvhChildren.data(), GL_STATIC_READ);
glFunc->glNamedBufferData(bvhBoundSSBO, bvhBounds.size() * sizeof(QVector4D), bvhBounds.data(), GL_STATIC_READ);
glFunc->glNamedBufferData(elementOffsetSSBO, elementOffset.size() * sizeof(glm::uvec4), elementOffset.data(), GL_STATIC_READ);
glFunc->glNamedBufferData(elementIndexSSBO, elementIndex.size() * sizeof(GLuint), elementIndex.data(), GL_STATIC_READ);
glFunc->glNamedBufferData(elementDataSSBO, elementData.size() * sizeof(GLfloat), elementData.data(), GL_STATIC_READ);
} }
GLuint Renderer::Painting::getElementCount() GLuint Renderer::Painting::getElementCount()

View File

@ -1,11 +1,13 @@
#pragma once #pragma once
#include <vector> #include <vector>
#include <array>
#include <set> #include <set>
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include "Line.h" #include "Line.h"
#include "BvhTree.h" #include "BvhTree.h"
#include "ElementStyle.h" #include "ElementStyle.h"
#include "Element.h" #include "Element.h"
#include <QOpenGLFunctions_4_5_Compatibility>
namespace Renderer namespace Renderer
{ {
@ -64,12 +66,13 @@ namespace Renderer
std::vector<GLuint> elementIndex; std::vector<GLuint> elementIndex;
std::vector<GLfloat> elementData; std::vector<GLfloat> elementData;
int paintingId = 0; int paintingId = 0;
std::array<GLuint, 5> buffers;
Painting(); Painting();
void addElement(ElementWithTransform element); void addElement(ElementWithTransform element);
void addElement(const Element& element, const ElementTransform& transform); void addElement(const Element& element, const ElementTransform& transform);
void addElement(std::shared_ptr<Element> element, QVector4D bound, float rotation, int zIndex); void addElement(std::shared_ptr<Element> element, QVector4D bound, float rotation, int zIndex);
void generateBuffers(); void generateBuffers(QOpenGLFunctions_4_5_Compatibility* glFunc);
GLuint getElementCount(); GLuint getElementCount();
private: private:
std::unordered_map<std::shared_ptr<Contour>, std::pair<std::shared_ptr<ContourBuffer>/*Ãæ*/, std::shared_ptr<ContourBuffer>/*Ïß*/>> contourPool; std::unordered_map<std::shared_ptr<Contour>, std::pair<std::shared_ptr<ContourBuffer>/*Ãæ*/, std::shared_ptr<ContourBuffer>/*Ïß*/>> contourPool;

View File

@ -75,10 +75,10 @@ void RendererGLWidget::setModel()
//model = new Model("E:\\3D Objects\\gallery_gltf\\gallery_gltf.gltf", context(), modelProgramPtr, paintingProgramPtr, shadowProgramPtr, paintingHelper); //model = new Model("E:\\3D Objects\\gallery_gltf\\gallery_gltf.gltf", context(), modelProgramPtr, paintingProgramPtr, shadowProgramPtr, paintingHelper);
light.model = model; light.model = model;
qDebug() << model->AABB; qDebug() << model->AABB;
paintingHelper->allocateBuffers(); //paintingHelper->allocateBuffers();
paintingCompProgramPtr->bind(); //paintingCompProgramPtr->bind();
paintingHelper->bindPaintingBuffers(); //paintingHelper->bindPaintingBuffers();
paintingCompProgramPtr->release(); //paintingCompProgramPtr->release();
doneCurrent(); doneCurrent();
} }

View File

@ -44,12 +44,13 @@ Renderer::VirtualTextureManager::VirtualTextureManager(GladGLContext* gl)
qDebug() << "ERROR:" << program.log(); qDebug() << "ERROR:" << program.log();
if (!program.link()) if (!program.link())
qDebug() << "ERROR:" << program.log(); qDebug() << "ERROR:" << program.log();
} }
std::tuple<GLuint, GLuint> Renderer::VirtualTextureManager::createVirtualTexture(Painting painting) GLuint Renderer::VirtualTextureManager::createVirtualTexture(Painting painting)
{ {
const GLsizei levels = static_cast<GLsizei>(glm::log2(textureSize) + static_cast<size_t>(1)); const GLsizei levels = glm::log2(textureSize / pageSize) + 1;
qDebug() << "levels:" << levels;
GLuint textures[2]; GLuint textures[2];
gl->CreateTextures(GL_TEXTURE_2D, 2, textures); gl->CreateTextures(GL_TEXTURE_2D, 2, textures);
@ -57,20 +58,27 @@ std::tuple<GLuint, GLuint> Renderer::VirtualTextureManager::createVirtualTexture
GLuint& metallicRoughness = textures[1]; GLuint& metallicRoughness = textures[1];
gl->TextureParameteri(baseColor, GL_TEXTURE_SPARSE_ARB, GL_TRUE); gl->TextureParameteri(baseColor, GL_TEXTURE_SPARSE_ARB, GL_TRUE);
gl->TextureParameteri(baseColor, GL_TEXTURE_BASE_LEVEL, 0);
gl->TextureParameteri(baseColor, GL_TEXTURE_MAX_LEVEL, levels - 1);
gl->TextureParameteri(baseColor, GL_TEXTURE_WRAP_S, GL_REPEAT); gl->TextureParameteri(baseColor, GL_TEXTURE_WRAP_S, GL_REPEAT);
gl->TextureParameteri(baseColor, GL_TEXTURE_WRAP_T, GL_REPEAT); gl->TextureParameteri(baseColor, GL_TEXTURE_WRAP_T, GL_REPEAT);
gl->TextureParameteri(baseColor, GL_TEXTURE_MIN_FILTER, GL_LINEAR); gl->TextureParameteri(baseColor, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
gl->TextureParameteri(baseColor, GL_TEXTURE_MAG_FILTER, GL_LINEAR); gl->TextureParameteri(baseColor, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
gl->TextureStorage2D(baseColor, levels, GL_RGBA8, GLsizei(textureSize), GLsizei(textureSize)); gl->TextureStorage2D(baseColor, levels, GL_RGBA8, GLsizei(textureSize), GLsizei(textureSize));
gl->TextureParameteri(metallicRoughness, GL_TEXTURE_SPARSE_ARB, GL_TRUE); gl->TextureParameteri(metallicRoughness, GL_TEXTURE_SPARSE_ARB, GL_TRUE);
gl->TextureParameteri(metallicRoughness, GL_TEXTURE_BASE_LEVEL, 0);
gl->TextureParameteri(metallicRoughness, GL_TEXTURE_MAX_LEVEL, levels - 1);
gl->TextureParameteri(metallicRoughness, GL_TEXTURE_WRAP_S, GL_REPEAT); gl->TextureParameteri(metallicRoughness, GL_TEXTURE_WRAP_S, GL_REPEAT);
gl->TextureParameteri(metallicRoughness, GL_TEXTURE_WRAP_T, GL_REPEAT); gl->TextureParameteri(metallicRoughness, GL_TEXTURE_WRAP_T, GL_REPEAT);
gl->TextureParameteri(metallicRoughness, GL_TEXTURE_MIN_FILTER, GL_LINEAR); gl->TextureParameteri(metallicRoughness, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
gl->TextureParameteri(metallicRoughness, GL_TEXTURE_MAG_FILTER, GL_LINEAR); gl->TextureParameteri(metallicRoughness, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
gl->TextureStorage2D(metallicRoughness, levels, GL_RG8, GLsizei(textureSize), GLsizei(textureSize)); gl->TextureStorage2D(metallicRoughness, levels, GL_RG8, GLsizei(textureSize), GLsizei(textureSize));
for (std::size_t level = 0; level < 1; ++level) for (int i = 0; i < 5; i++)
gl->BindBufferBase(GL_SHADER_STORAGE_BUFFER, i, painting.buffers[i]);
for (auto level = levels - 1; level < levels; ++level)
{ {
GLsizei levelSize = (textureSize >> level); GLsizei levelSize = (textureSize >> level);
for (GLsizei j = 0; j < levelSize / pageSize; ++j) for (GLsizei j = 0; j < levelSize / pageSize; ++j)
@ -87,14 +95,14 @@ std::tuple<GLuint, GLuint> Renderer::VirtualTextureManager::createVirtualTexture
program.bind(); program.bind();
gl->Uniform2i(gl->GetUniformLocation(program.programId(), "pixelOffset"), static_cast<GLsizei>(pageSize) * i, static_cast<GLsizei>(pageSize) * j); gl->Uniform2i(gl->GetUniformLocation(program.programId(), "pixelOffset"), static_cast<GLsizei>(pageSize) * i, static_cast<GLsizei>(pageSize) * j);
gl->BindImageTexture(0, baseColor, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8); gl->BindImageTexture(0, baseColor, level, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8);
gl->BindImageTexture(1, metallicRoughness, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RG8); gl->BindImageTexture(1, metallicRoughness, level, GL_FALSE, 0, GL_READ_WRITE, GL_RG8);
gl->DispatchCompute(pageSize / 8, pageSize / 8, 1); gl->DispatchCompute(pageSize / 8, pageSize / 8, 1);
program.release(); program.release();
} }
} }
paintings.emplace_back(baseColor, metallicRoughness, painting.buffers);
return { baseColor, metallicRoughness }; return paintings.size() - 1;
} }

View File

@ -6,25 +6,32 @@ struct GladGLContext;
namespace Renderer namespace Renderer
{ {
struct PaintingHandle
{
GLuint baseColor;
GLuint metallicRoughness;
std::array<GLuint, 5> buffers;
};
class VirtualTextureManager class VirtualTextureManager
{ {
public: public:
static constexpr GLsizei textureSize = 16384; static constexpr GLsizei textureSize = 16384;
std::vector<PaintingHandle> paintings;
VirtualTextureManager(GladGLContext* gl); VirtualTextureManager(GladGLContext* gl);
/** /**
* @brief * @brief
* @param painting * @param painting
* @return 0 baseColor * @return paintings
* @return 1 metallicRoughness
*/ */
std::tuple<GLuint, GLuint> createVirtualTexture(Painting painting); GLuint createVirtualTexture(Painting painting);
private: private:
GladGLContext* gl; GladGLContext* gl;
GLint pageSize; GLint pageSize;
QOpenGLShaderProgram program; QOpenGLShaderProgram program;
}; };
} }