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

View File

@ -1,4 +1,5 @@
#version 450 core
#extension GL_ARB_sparse_texture2 : enable
uniform sampler2D texture_basecolor;
uniform sampler2D texture_metallic_roughness;
@ -16,7 +17,10 @@ in vec3 Normal;
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)
discard;
//gBaseColor = vec4( vec3(1),1 );
@ -24,7 +28,11 @@ void main()
gPosition = WorldPos;
gNormal = normalize(Normal);
//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 = 0;
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()));
std::tie(m_mesh->textureBasecolor, m_mesh->textureMetallicRoughness) = loadPainting(std::string(str.C_Str()));
m_mesh->paintingIndex = 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();
return m_mesh;
}
@ -225,7 +227,7 @@ GLuint Model::loadMaterialTextures(aiMaterial* mat, aiTextureType type)
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);
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[2], QVector4D(0.2, -0.8, 0.8, -0.1), 0, 0);
painting.generateBuffers();
painting.generateBuffers(glFunc);
/////////////////////////////////////////////////////////////////////////////////////////////////
std::vector<GLuint> bvhChildren0 = {
//root
@ -466,7 +468,7 @@ std::tuple<GLuint, GLuint> Renderer::Model::loadPainting(std::string path)
//GLuint index = paintingHelper->addPainting(painting);
//paintingLoaded.insert({ path, index });
auto ids = vtManager->createVirtualTexture(painting);
paintingLoaded.emplace(path, ids);
return ids;
auto index = vtManager->createVirtualTexture(painting);
paintingLoaded.emplace(path, index);
return index;
}

View File

@ -29,7 +29,7 @@ namespace Renderer
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::vector<std::unique_ptr<Drawable>> meshes;
@ -47,6 +47,6 @@ namespace Renderer
//加载材质纹理
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);
}
void Painting::generateBuffers()
void Painting::generateBuffers(QOpenGLFunctions_4_5_Compatibility* glFunc)
{
qDebug() << "Element Count: " << elementPool.size();
qDebug() << "Coutour Count: " << contourPool.size();
qDebug() << " Style Count: " << stylePool.size();
bvhChildren.clear();
bvhBounds.clear();
elementOffset.clear();
@ -161,6 +160,19 @@ void Painting::generateBuffers()
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);
}
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()

View File

@ -1,11 +1,13 @@
#pragma once
#include <vector>
#include <array>
#include <set>
#include <glm/glm.hpp>
#include "Line.h"
#include "BvhTree.h"
#include "ElementStyle.h"
#include "Element.h"
#include <QOpenGLFunctions_4_5_Compatibility>
namespace Renderer
{
@ -64,12 +66,13 @@ namespace Renderer
std::vector<GLuint> elementIndex;
std::vector<GLfloat> elementData;
int paintingId = 0;
std::array<GLuint, 5> buffers;
Painting();
void addElement(ElementWithTransform element);
void addElement(const Element& element, const ElementTransform& transform);
void addElement(std::shared_ptr<Element> element, QVector4D bound, float rotation, int zIndex);
void generateBuffers();
void generateBuffers(QOpenGLFunctions_4_5_Compatibility* glFunc);
GLuint getElementCount();
private:
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);
light.model = model;
qDebug() << model->AABB;
paintingHelper->allocateBuffers();
paintingCompProgramPtr->bind();
paintingHelper->bindPaintingBuffers();
paintingCompProgramPtr->release();
//paintingHelper->allocateBuffers();
//paintingCompProgramPtr->bind();
//paintingHelper->bindPaintingBuffers();
//paintingCompProgramPtr->release();
doneCurrent();
}

View File

@ -44,12 +44,13 @@ Renderer::VirtualTextureManager::VirtualTextureManager(GladGLContext* gl)
qDebug() << "ERROR:" << program.log();
if (!program.link())
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];
gl->CreateTextures(GL_TEXTURE_2D, 2, textures);
@ -57,20 +58,27 @@ std::tuple<GLuint, GLuint> Renderer::VirtualTextureManager::createVirtualTexture
GLuint& metallicRoughness = textures[1];
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_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->TextureStorage2D(baseColor, levels, GL_RGBA8, GLsizei(textureSize), GLsizei(textureSize));
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_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->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);
for (GLsizei j = 0; j < levelSize / pageSize; ++j)
@ -87,14 +95,14 @@ std::tuple<GLuint, GLuint> Renderer::VirtualTextureManager::createVirtualTexture
program.bind();
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(1, metallicRoughness, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RG8);
gl->BindImageTexture(0, baseColor, level, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8);
gl->BindImageTexture(1, metallicRoughness, level, GL_FALSE, 0, GL_READ_WRITE, GL_RG8);
gl->DispatchCompute(pageSize / 8, pageSize / 8, 1);
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
{
struct PaintingHandle
{
GLuint baseColor;
GLuint metallicRoughness;
std::array<GLuint, 5> buffers;
};
class VirtualTextureManager
{
public:
static constexpr GLsizei textureSize = 16384;
std::vector<PaintingHandle> paintings;
VirtualTextureManager(GladGLContext* gl);
/**
* @brief
* @param painting
* @return 0 baseColor
* @return 1 metallicRoughness
* @brief
* @param painting
* @return paintings
*/
std::tuple<GLuint, GLuint> createVirtualTexture(Painting painting);
GLuint createVirtualTexture(Painting painting);
private:
GladGLContext* gl;
GLint pageSize;
QOpenGLShaderProgram program;
};
}