Renderer图元变换改用矩阵

dev-LayerStyle
wuyize 2023-03-18 20:13:17 +08:00
parent 84bddf4447
commit fd1baf42f6
10 changed files with 182 additions and 198 deletions

View File

@ -20,22 +20,25 @@ layout(std430, binding = 1) buffer bvhBoundBuffer
{ {
vec4 bvhBound[]; vec4 bvhBound[];
}; };
layout(std430, binding = 2) buffer elementOffsetBuffer layout(std430, binding = 2) buffer elementTranformBuffer
{
mat3x2 elementTranform[];
};
layout(std430, binding = 3) buffer elementOffsetBuffer
{ {
/** /**
* @[0] elementBvhRoot * @[0] elementBvhRoot
* @[1] styleOffset * @[1] styleOffset
* @[2] pointsOffset * @[2] pointsOffset
* @[3] linesOffset * @[3] linesOffset
*/ */
uint elementOffset[][5]; uint elementOffset[][4];
}; };
layout(std430, binding = 3) buffer elementIndexBuffer layout(std430, binding = 4) buffer elementIndexBuffer
{ {
uint elementIndexs[]; // ÏߺÍÃæ uint elementIndexs[]; // ÏߺÍÃæ
}; };
layout(std430, binding = 4) buffer elementDataBuffer layout(std430, binding = 5) buffer elementDataBuffer
{ {
float elementData[]; // µãºÍStyle float elementData[]; // µãºÍStyle
}; };
@ -1115,15 +1118,11 @@ bool fillElement(vec2 localUV, uint contourIndex, uint linesOffset, uint pointsO
} }
bool strokeElement(vec2 localUV, uint contourIndex, uint linesOffset, uint pointsOffset, uint styleIndex, bool strokeElement(vec2 localUV, uint contourIndex, uint linesOffset, uint pointsOffset, uint styleIndex,
float widthHeightRatio, inout vec4 elementColor, inout vec2 metallicRoughness) inout vec4 elementColor, inout vec2 metallicRoughness)
{ {
bool hitElement = false; bool hitElement = false;
float strokeWidth = elementData[styleIndex]; float strokeWidth = elementData[styleIndex];
vec2 size = normalize(vec2(widthHeightRatio, 1)) + vec2(2 * strokeWidth);
vec2 ratio = widthHeightRatio < 1 ? vec2(widthHeightRatio, 1) : vec2(1, 1 / widthHeightRatio);
localUV *= ratio;
float minDistance = 1e38; float minDistance = 1e38;
uint lineCount = elementIndexs[contourIndex]; uint lineCount = elementIndexs[contourIndex];
vec4 styleHead = unpackUnorm4x8(floatBitsToUint(elementData[styleIndex + 1])); vec4 styleHead = unpackUnorm4x8(floatBitsToUint(elementData[styleIndex + 1]));
@ -1149,17 +1148,13 @@ bool strokeElement(vec2 localUV, uint contourIndex, uint linesOffset, uint point
mat4x2 p = mat4x2 p =
mat4x2(elementData[pxIndex[0]], elementData[pyIndex[0]], elementData[pxIndex[1]], elementData[pyIndex[1]], mat4x2(elementData[pxIndex[0]], elementData[pyIndex[0]], elementData[pxIndex[1]], elementData[pyIndex[1]],
elementData[pxIndex[2]], elementData[pyIndex[2]], elementData[pxIndex[3]], elementData[pyIndex[3]]); elementData[pxIndex[2]], elementData[pyIndex[2]], elementData[pxIndex[3]], elementData[pyIndex[3]]);
p[0] *= ratio;
p[1] *= ratio;
p[2] *= ratio;
p[3] *= ratio;
vec2 tangentBeginNext = vec2(0); vec2 tangentBeginNext = vec2(0);
if (contourIterator + 1 < contourIndex + 1 + lineCount) if (contourIterator + 1 < contourIndex + 1 + lineCount)
{ {
uint lineIndex = elementIndexs[contourIterator + 1]; uint lineIndex = elementIndexs[contourIterator + 1];
uint pLocation = linesOffset + 3 * lineIndex; uint pLocation = linesOffset + 3 * lineIndex;
//vec2 percent = unpackUnorm2x16(elementIndexs[pLocation + 2]); // vec2 percent = unpackUnorm2x16(elementIndexs[pLocation + 2]);
uvec4 pxIndex = uvec4(pointsOffset) + uvec4 pxIndex = uvec4(pointsOffset) +
2 * uvec4(elementIndexs[pLocation] >> 16, elementIndexs[pLocation] & 0xFFFF, 2 * uvec4(elementIndexs[pLocation] >> 16, elementIndexs[pLocation] & 0xFFFF,
elementIndexs[pLocation + 1] >> 16, elementIndexs[pLocation + 1] & 0xFFFF); elementIndexs[pLocation + 1] >> 16, elementIndexs[pLocation + 1] & 0xFFFF);
@ -1168,10 +1163,6 @@ bool strokeElement(vec2 localUV, uint contourIndex, uint linesOffset, uint point
mat4x2 pNext = mat4x2(elementData[pxIndex[0]], elementData[pyIndex[0]], elementData[pxIndex[1]], mat4x2 pNext = mat4x2(elementData[pxIndex[0]], elementData[pyIndex[0]], elementData[pxIndex[1]],
elementData[pyIndex[1]], elementData[pxIndex[2]], elementData[pyIndex[2]], elementData[pyIndex[1]], elementData[pxIndex[2]], elementData[pyIndex[2]],
elementData[pxIndex[3]], elementData[pyIndex[3]]); elementData[pxIndex[3]], elementData[pyIndex[3]]);
pNext[0] *= ratio;
pNext[1] *= ratio;
pNext[2] *= ratio;
pNext[3] *= ratio;
if (pNext[0] == pNext[1] && pNext[2] == pNext[3]) if (pNext[0] == pNext[1] && pNext[2] == pNext[3])
{ {
@ -1179,7 +1170,7 @@ bool strokeElement(vec2 localUV, uint contourIndex, uint linesOffset, uint point
pNext[2] = pNext[1]; pNext[2] = pNext[1];
} }
//if(pNext[0]!=p[3]) // if(pNext[0]!=p[3])
// break; // break;
if (pNext[0] != pNext[1]) if (pNext[0] != pNext[1])
tangentBeginNext = normalize(pNext[0] - pNext[1]); tangentBeginNext = normalize(pNext[0] - pNext[1]);
@ -1221,11 +1212,11 @@ bool strokeElement(vec2 localUV, uint contourIndex, uint linesOffset, uint point
bool hit = d < minDistance; bool hit = d < minDistance;
if (onBegin) if (onBegin)
hit = hit = hit && shouldFillBeginCap(localUV, contourIterator == contourIndex + 1, endType, p[0],
hit && shouldFillBeginCap(localUV, contourIterator == contourIndex + 1, endType, p[0], tangentBegin, p3Last - p2Last); tangentBegin, p3Last - p2Last);
if (onEnd) if (onEnd)
hit = hit && hit = hit && shouldFillEndCap(localUV, tangentBeginNext == vec2(0), endType, p[3], tangentEnd,
shouldFillEndCap(localUV, tangentBeginNext==vec2(0), endType, p[3], tangentEnd, tangentBeginNext); tangentBeginNext);
if (hit) if (hit)
{ {
@ -1272,7 +1263,7 @@ bool strokeElement(vec2 localUV, uint contourIndex, uint linesOffset, uint point
return hitElement; return hitElement;
} }
bool drawElement(uint elementIndex, vec2 localUV, vec2 scale, out vec3 color, out vec2 metallicRoughness, bool drawElement(uint elementIndex, vec2 localUV, out vec3 color, out vec2 metallicRoughness,
inout vec3 debugBVH = vec3(0)) inout vec3 debugBVH = vec3(0))
{ {
bool hitElement = false; bool hitElement = false;
@ -1284,7 +1275,7 @@ bool drawElement(uint elementIndex, vec2 localUV, vec2 scale, out vec3 color, ou
uint styleIndex = currentOffset[1]; uint styleIndex = currentOffset[1];
uint pointsOffset = currentOffset[2]; uint pointsOffset = currentOffset[2];
uint linesOffset = currentOffset[3]; uint linesOffset = currentOffset[3];
float widthHeightRatio = uintBitsToFloat(currentOffset[4]); // float widthHeightRatio = uintBitsToFloat(currentOffset[4]);
elementStack.top = 0; elementStack.top = 0;
uint elementBvhIndex = 0; uint elementBvhIndex = 0;
@ -1317,7 +1308,7 @@ bool drawElement(uint elementIndex, vec2 localUV, vec2 scale, out vec3 color, ou
else // Ïß else // Ïß
{ {
hitElement = strokeElement(localUV, contourIndex, linesOffset, pointsOffset, styleIndex, hitElement = strokeElement(localUV, contourIndex, linesOffset, pointsOffset, styleIndex,
widthHeightRatio, elementColor, metallicRoughness); elementColor, metallicRoughness);
} }
elementBvhIndex = elementBvhLength; elementBvhIndex = elementBvhLength;
@ -1357,7 +1348,7 @@ void main()
vec3 debugBVH = vec3(0); vec3 debugBVH = vec3(0);
// bool debugHit = false; // bool debugHit = false;
//vec4 color = vec4(0.76, 0.33, 0.15, -1); // vec4 color = vec4(0.76, 0.33, 0.15, -1);
vec4 color = vec4(backgroundColor, -1); vec4 color = vec4(backgroundColor, -1);
vec2 metallicRoughness = vec2(0, 0.8); vec2 metallicRoughness = vec2(0, 0.8);
stack.top = 0; stack.top = 0;
@ -1371,50 +1362,40 @@ void main()
visitTime++; visitTime++;
vec4 bound = bvhBound[index]; vec4 bound = bvhBound[index];
uint leftChild = bvhChildren[index].x; uint leftChild = bvhChildren[index].x;
if (all(lessThan(bound.xy, uv)) && all(lessThan(uv, bound.zw)))
{
if (any(greaterThan(bound.xy + vec2(0.005), uv)) || any(greaterThan(uv, bound.zw - vec2(0.005))))
debugBVH.g += 0.3;
if (leftChild >= bvhLength) if (leftChild >= bvhLength)
{ {
uint transformIndex = leftChild - 0x80000000;
uint zIndex = bvhChildren[index].y >> 18; uint zIndex = bvhChildren[index].y >> 18;
bvec2 flip = bvec2(bvhChildren[index].y & (1 << 16), bvhChildren[index].y & (1 << 17)); uint elementIndex = bvhChildren[index].y - zIndex;
float angle = (float(bvhChildren[index].y & ((1 << 16) - 1)) / 65535.0) * 2 * PI; mat3x2 transform = elementTranform[transformIndex];
mat2 rotation = {{cos(angle), -sin(angle)}, {sin(angle), cos(angle)}}; vec2 localUV =
vec2 localUV = uv - (bound.xy + bound.zw) / 2; (mat3(vec3(transform[0], 0), vec3(transform[1], 0), vec3(transform[2], 1)) * vec3(uv, 1)).xy;
localUV = rotation * localUV;
vec2 scale = (bound.zw - bound.xy) / 2;
localUV /= scale;
if (all(lessThan(vec2(-1), localUV)) && all(lessThan(localUV, vec2(1))) && zIndex > color.w)
{
// if (any(greaterThan(bound.xy+vec2(0.005), uv)) || any(greaterThan(uv, bound.zw-vec2(0.005))))
if (any(greaterThan(vec2(-1) + vec2(0.005), localUV)) ||
any(greaterThan(localUV, vec2(1) - vec2(0.005))))
debugBVH.g += 0.3;
// uint elementIndex = leftChild - bvhLength;
// debugBVH.bg += 0.5 * (localUV + vec2(1));
// debugBVH = vec3(0);
if (flip.x)
localUV.x = -localUV.x;
if (flip.y)
localUV.y = -localUV.y;
vec3 elementColor; vec3 elementColor;
vec2 elementMetallicRoughness; vec2 elementMetallicRoughness;
if (drawElement(leftChild - 0x80000000, localUV, scale, elementColor, elementMetallicRoughness, if (drawElement(elementIndex, localUV, elementColor, elementMetallicRoughness,
debugBVH)) debugBVH))
{ {
color = vec4(elementColor, zIndex); color = vec4(elementColor, zIndex);
metallicRoughness = elementMetallicRoughness; metallicRoughness = elementMetallicRoughness;
} }
} //if(elementIndex == 1 && transformIndex==1)
// color = vec4(1,1,0,1);
index = bvhLength; index = bvhLength;
} }
else if (all(lessThan(bound.xy, uv)) && all(lessThan(uv, bound.zw))) else
{ {
if (any(greaterThan(bound.xy + vec2(0.005), uv)) || any(greaterThan(uv, bound.zw - vec2(0.005))))
debugBVH.g += 0.3;
// debugBVH.r += 0.02;
stack.push(index); stack.push(index);
index = leftChild; index = leftChild;
} }
}
else else
index = bvhLength; index = bvhLength;
} }
@ -1428,7 +1409,7 @@ void main()
imageStore(gBaseColor, pixelLocation, vec4(color.rgb, 1)); imageStore(gBaseColor, pixelLocation, vec4(color.rgb, 1));
imageStore(gMetallicRoughness, pixelLocation, vec4(metallicRoughness, 0, 1)); imageStore(gMetallicRoughness, pixelLocation, vec4(metallicRoughness, 0, 1));
return; //return;
if (/*color.a!=-1&&*/ debugBVH == vec3(0)) if (/*color.a!=-1&&*/ debugBVH == vec3(0))
{ {
// imageStore(gBaseColor, pixelLocation, vec4(vec3(1, 1, 0),1)); // imageStore(gBaseColor, pixelLocation, vec4(vec3(1, 1, 0),1));

View File

@ -99,7 +99,10 @@ FolderLayerWrapper* PaintingUtil::handleLayerWrapper(LayerWrapper* nowLayer, QTr
qDebug() << painterPath; qDebug() << painterPath;
bound = painterPath.boundingRect(); bound = painterPath.boundingRect();
qDebug() << bound; qDebug() << bound;
elementTrans.center = glm::vec2(
// TODO 改用矩阵
/* elementTrans.center = glm::vec2(
(2 * bound.center().x() - screenSize.width()) / screenSize.width(), (2 * bound.center().x() - screenSize.width()) / screenSize.width(),
(2 * bound.center().y() - screenSize.height()) / screenSize.height() (2 * bound.center().y() - screenSize.height()) / screenSize.height()
); );
@ -114,7 +117,7 @@ FolderLayerWrapper* PaintingUtil::handleLayerWrapper(LayerWrapper* nowLayer, QTr
nowLayer->property.flipVertically nowLayer->property.flipVertically
); );
qDebug() << elementTrans.scale.x << elementTrans.scale.y; qDebug() << elementTrans.scale.x << elementTrans.scale.y;
painting.addElement(element, elementTrans); painting.addElement(element, elementTrans);*/
return nullptr; return nullptr;
} }

View File

@ -16,6 +16,7 @@
#include <ThirdPartyLib/qquick/qquicksvgparser_p.h> #include <ThirdPartyLib/qquick/qquicksvgparser_p.h>
#include <util/PaintingUtil.h> #include <util/PaintingUtil.h>
#include "Painting/MaterialStyleStroke.h" #include "Painting/MaterialStyleStroke.h"
#include <glm/gtc/matrix_transform.hpp>
using namespace Renderer; using namespace Renderer;
using std::vector; using std::vector;
@ -100,7 +101,7 @@ void Renderer::Model::loadModel(QString path)
void Renderer::Model::unloadModel() void Renderer::Model::unloadModel()
{ {
paintingMap.clear(); paintingMap.clear();
for(auto& i: paintingLoaded) for (auto& i : paintingLoaded)
vtManager->deleteVirtualTexture(i.second); vtManager->deleteVirtualTexture(i.second);
paintingLoaded.clear(); paintingLoaded.clear();
texturesLoaded.clear(); texturesLoaded.clear();
@ -280,13 +281,13 @@ GLuint Renderer::Model::loadPainting(std::string path)
if (path == "0.json") if (path == "0.json")
{ {
painting.addElement(*element[0], ElementTransform{ glm::vec2(-0.45,-0.45), glm::vec2(0.5,0.5) / 2.f, 0, glm::bvec2(false), 0 }); //painting.addElement(*element[0], ElementTransform{ glm::vec2(-0.45,-0.45), glm::vec2(0.5,0.5) / 2.f, 0, glm::bvec2(false), 0 });
painting.addElement(*element[1], ElementTransform{ glm::vec2(-0.45, 0.45), glm::vec2(0.5,0.5) / 2.f, 0, glm::bvec2(false), 0 }); //painting.addElement(*element[1], ElementTransform{ glm::vec2(-0.45, 0.45), glm::vec2(0.5,0.5) / 2.f, 0, glm::bvec2(false), 0 });
painting.addElement(*element[2], ElementTransform{ glm::vec2(0.50,-0.45), glm::vec2(0.6,0.7) / 2.f, 0, glm::bvec2(false), 0 }); //painting.addElement(*element[2], ElementTransform{ glm::vec2(0.50,-0.45), glm::vec2(0.6,0.7) / 2.f, 0, glm::bvec2(false), 0 });
} }
else if (path == "1.json") else if (path == "1.json")
{ {
painting.backgroundColor = QColor(196, 81, 35); //painting.backgroundColor = QColor(196, 81, 35);
float widths[] = { 0.22, 0.22 * 0.25 / 0.15, 0.22 * 0.25 / 0.15 }; float widths[] = { 0.22, 0.22 * 0.25 / 0.15, 0.22 * 0.25 / 0.15 };
QPainterPath painterPaths[6]; QPainterPath painterPaths[6];
for (int i = 0; i < 6; i++) for (int i = 0; i < 6; i++)
@ -322,14 +323,39 @@ GLuint Renderer::Model::loadPainting(std::string path)
std::make_shared<StyleStrokeRadialGradient>(widths[1], StrokeType::kRightSide), std::make_shared<StyleStrokeRadialGradient>(widths[1], StrokeType::kRightSide),
std::make_shared<StyleStrokeRadialGradient>(widths[2], StrokeType::kLeftSide), std::make_shared<StyleStrokeRadialGradient>(widths[2], StrokeType::kLeftSide),
}; };
vector<std::shared_ptr<Element>> element = { std::map<float, Material> materialMap = {
std::make_shared<Element>(Element{ contours[0].first, style[0], contours[0].second}), {0.09, Material{QColor(255,255,255),0,0.8}},
std::make_shared<Element>(Element{ contours[1].first, style[1], contours[1].second}), {0.63, Material{QColor(165,176,207),0,0.8}},
std::make_shared<Element>(Element{ contours[2].first, style[2], contours[2].second}), {1.00, Material{QColor(58,64,151),0,0.8}}
}; };
painting.addElement(*element[0], ElementTransform{ glm::vec2(-0.45,0.45), glm::vec2(0.25), 0, glm::bvec2(false), 0 }); vector<std::shared_ptr<BaseElement>> element = {
painting.addElement(*element[1], ElementTransform{ glm::vec2(-0.535,0.33), glm::vec2(0.15), 0, glm::bvec2(false), 0 }); std::make_shared<BaseElement>(contours[0].first, std::make_shared<MaterialStyleStroke>(
painting.addElement(*element[2], ElementTransform{ glm::vec2(-0.535,0.23), glm::vec2(0.15), 0, glm::bvec2(false), 0 }); widths[0], StrokeType::kLeftSide, StrokeEndType::kFlat, std::make_shared<StrokeRadialGradient>(materialMap, false))),
std::make_shared<BaseElement>(contours[1].first, std::make_shared<MaterialStyleStroke>(
widths[1], StrokeType::kRightSide, StrokeEndType::kFlat, std::make_shared<StrokeRadialGradient>(materialMap, false))),
std::make_shared<BaseElement>(contours[2].first, std::make_shared<MaterialStyleStroke>(
widths[2], StrokeType::kLeftSide, StrokeEndType::kFlat, std::make_shared<StrokeRadialGradient>(materialMap, false))),
};
QTransform trans = QTransform::fromScale(0.3, 0.3).inverted();
glm::mat3x2 mat(trans.m11(), trans.m12(), trans.m21(), trans.m22(), trans.m31(), trans.m32());
trans = QTransform::fromTranslate(0.5, 0).scale(0.3, 0.3).inverted();
glm::mat3x2 mat2(trans.m11(), trans.m12(), trans.m21(), trans.m22(), trans.m31(), trans.m32());
//mat = glm::mat3x2(11, 22, 33, 44, 55, 66);
//mat2 = glm::mat3x2(1, 2, 3, 4, 5, 6);
qDebug() << std::format("\n{} {} {}\n {} {} {}\n{} {} {}",
trans.m11(), trans.m21(), trans.m31(),
trans.m12(), trans.m22(), trans.m32(),
trans.m13(), trans.m23(), trans.m33()).c_str();
//painting.addElement(*element[0], ElementTransform{ glm::vec4(-1,-1,1,1), mat, 0});
painting.addElement(*element[1], ElementTransform{ glm::vec4(-1,-1,0,1), mat, 0 });
painting.addElement(*element[2], ElementTransform{ glm::vec4(0,-1,1,1), mat2, 0 });
//painting.addElement(*element[0], ElementTransform{ glm::vec2(-0.45,0.45), glm::vec2(0.25), 0, glm::bvec2(false), 0 });
//painting.addElement(*element[1], ElementTransform{ glm::vec2(-0.535,0.33), glm::vec2(0.15), 0, glm::bvec2(false), 0 });
//painting.addElement(*element[2], ElementTransform{ glm::vec2(-0.535,0.23), glm::vec2(0.15), 0, glm::bvec2(false), 0 });
} }
else else
{ {
@ -337,7 +363,7 @@ GLuint Renderer::Model::loadPainting(std::string path)
{ {
float x = (float)rand() / RAND_MAX * 2 - 1; float x = (float)rand() / RAND_MAX * 2 - 1;
float y = (float)rand() / RAND_MAX * 2 - 1; float y = (float)rand() / RAND_MAX * 2 - 1;
painting.addElement(*element[i % 3], ElementTransform{ glm::vec2(x,y), glm::vec2(0.025), (float)rand() / RAND_MAX * 360, glm::bvec2(false), 0 }); //painting.addElement(*element[i % 3], ElementTransform{ glm::vec2(x,y), glm::vec2(0.025), (float)rand() / RAND_MAX * 360, glm::bvec2(false), 0 });
} }
} }
} }

View File

@ -1,16 +1,16 @@
#include "Element.h" #include "Element.h"
void Renderer::ElementTransform::applyTransformStyle(const TransformStyle& t) //void Renderer::ElementTransform::applyTransformStyle(const TransformStyle& t)
{ //{
center += t.translation; // /*center += t.translation;
scale *= t.scale; // scale *= t.scale;
rotation += t.rotation; // rotation += t.rotation;
flip ^= t.flip; // flip ^= t.flip;*/
} //}
//
Renderer::ElementTransform Renderer::ElementTransform::appliedTransformStyle(const TransformStyle& t) const //Renderer::ElementTransform Renderer::ElementTransform::appliedTransformStyle(const TransformStyle& t) const
{ //{
ElementTransform result = *this; // ElementTransform result = *this;
result.applyTransformStyle(t); // result.applyTransformStyle(t);
return result; // return result;
} //}

View File

@ -18,14 +18,15 @@ namespace Renderer
struct ElementTransform struct ElementTransform
{ {
glm::vec2 center; //glm::vec2 center;
//glm::vec2 size; //glm::vec2 scale; /// 相对于画布
glm::vec2 scale; /// 相对于画布 //float rotation; /// 角度制
float rotation; /// 角度制 //glm::bvec2 flip;
glm::bvec2 flip; glm::vec4 bound; /// 包围盒,不影响变换
glm::mat3x2 transform; /// 逆变换
GLuint zIndex; GLuint zIndex;
void applyTransformStyle(const TransformStyle& t); //void applyTransformStyle(const TransformStyle& t);
ElementTransform appliedTransformStyle(const TransformStyle& t) const; //ElementTransform appliedTransformStyle(const TransformStyle& t) const;
}; };
} }

View File

@ -53,87 +53,40 @@ void Renderer::Painting::addElement(ElementWithTransform elementWithTransform)
elementPool.insert({ element, 0 }); elementPool.insert({ element, 0 });
} }
elements.push_back(elementWithTransform); elements.push_back(elementWithTransform);
elementTransformPool.emplace(elementWithTransform.transform.transform, 0);
} }
void Renderer::Painting::addElement(const Element& element, const ElementTransform& transform) void Renderer::Painting::addElement(const BaseElement& element, const ElementTransform& transform)
{ {
auto contour = element.contour; addElement({ element , transform });
auto it = elementStyleMap.find(element.style);
if (it == elementStyleMap.end())
{
std::vector<BaseStyle> baseStyles;
for (auto& style : element.style->toBaseStyles())
{
auto [iter, _] = styleSet.insert(style.material);
baseStyles.push_back(BaseStyle{ style.transform, *iter });
}
it = elementStyleMap.insert({ element.style, baseStyles }).first;
}
for (int i = 0; i < it->second.size(); i++)
{
auto& style = it->second[i];
ElementTransform trans = transform;
trans.applyTransformStyle(*style.transform);
trans.zIndex = trans.zIndex * 10 + i;
addElement(ElementWithTransform{ BaseElement{element.contour, style.material, element.ratio}, trans });
}
} }
Renderer::BaseTransform::BaseTransform(ElementTransform t) BvhTreeData Painting::encodeElementLeaf(const ElementWithTransform& e)
: bound(glm::vec4(t.center - t.scale, t.center + t.scale))
, rotation(t.rotation)
, flip(t.flip)
, zIndex(t.zIndex)
{ {
} QVector4D bound(e.transform.bound.x, e.transform.bound.y, e.transform.bound.z, e.transform.bound.w);
GLuint rightSon = elementPool[e.element] + (e.transform.zIndex << 18);
void Renderer::Painting::addElement(std::shared_ptr<Element> element, QVector4D bound, float rotation, int zIndex) return { bound, elementTransformPool[e.transform.transform], rightSon };
{
}
BvhTreeData Painting::encodeElementLeaf(ElementWithTransform e)
{
glm::vec4 bound;
switch (e.element.style->type())
{
case MaterialStyleType::kStroke:
{
auto w = std::static_pointer_cast<MaterialStyleStroke>(e.element.style)->getHalfWidth();
glm::vec2 size = e.element.ratio < 1 ? glm::vec2(e.element.ratio, 1) : glm::vec2(1, 1 / e.element.ratio);
glm::vec2 scale = size * e.transform.scale;
bound = glm::vec4(e.transform.center - scale, e.transform.center + scale);
break;
}
case MaterialStyleType::kFill:
{
bound = glm::vec4(e.transform.center - e.transform.scale, e.transform.center + e.transform.scale);
break;
}
}
//bound = glm::vec4(e.transform.center - e.transform.scale, e.transform.center + e.transform.scale);
GLuint rightSon = (GLuint)(glm::mod(e.transform.rotation, 360.f) / 360.f * (1 << 16))
+ (e.transform.flip.x << 16) + (e.transform.flip.y << 17) + (e.transform.zIndex << 18);
return BvhTreeData(QVector4D(bound.x, bound.y, bound.z, bound.w), elementPool[e.element], rightSon);
} }
void Painting::generateBuffers(QOpenGLFunctions_4_5_Core* glFunc) void Painting::generateBuffers(QOpenGLFunctions_4_5_Core* glFunc)
{ {
qDebug() << "Element Count: " << elementPool.size(); qDebug() << "Element Count: " << elementPool.size();
qDebug() << "Coutour Count: " << contourPool.size(); qDebug() << "Contour Count: " << contourPool.size();
qDebug() << " Style Count: " << stylePool.size(); qDebug() << " Style Count: " << stylePool.size();
bvhChildren.clear(); bvhChildren.clear();
bvhBounds.clear(); bvhBounds.clear();
elementTransform.clear();
elementOffsets.clear(); elementOffsets.clear();
elementIndex.clear(); elementIndex.clear();
elementData.clear(); elementData.clear();
for (int index = 0; auto & i : elementPool) for (int index = 0; auto & i : elementPool)
{
i.second = index++; i.second = index++;
} for (int index = 0; auto & i : elementTransformPool)
i.second = index++;
std::vector<BvhTreeData> rootBvhTreeData; std::vector<BvhTreeData> rootBvhTreeData;
for (auto& i : elements) for (auto& i : elements)
@ -162,30 +115,35 @@ void Painting::generateBuffers(QOpenGLFunctions_4_5_Core* glFunc)
elementData.insert(elementData.end(), encodedStyle.begin(), encodedStyle.end()); elementData.insert(elementData.end(), encodedStyle.begin(), encodedStyle.end());
} }
for (auto & i : elementTransformPool)
elementTransform.emplace_back(i.first);
for (auto& i : elementPool) for (auto& i : elementPool)
{ {
//qDebug() <<"element:" << i.second; //qDebug() <<"element:" << i.second;
//std::shared_ptr<ContourBuffer> contourBuffer = i.first.style->type() == MaterialStyleType::kStroke ? contourPool[i.first.contour].second : contourPool[i.first.contour].first; //std::shared_ptr<ContourBuffer> contourBuffer = i.first.style->type() == MaterialStyleType::kStroke ? contourPool[i.first.contour].second : contourPool[i.first.contour].first;
auto& contourBuffer = contourPool[{i.first.contour, i.first.style->type()}]; auto& contourBuffer = contourPool[{i.first.contour, i.first.style->type()}];
elementOffsets.push_back({ contourBuffer.bvhOffset, stylePool[i.first.style], contourBuffer.pointsOffset, contourBuffer.linesOffset, glm::floatBitsToUint(i.first.ratio) }); elementOffsets.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(6, buffers.data()); glFunc->glCreateBuffers(7, buffers.data());
GLuint& bvhSSBO = buffers[0]; GLuint& bvhSSBO = buffers[0];
GLuint& bvhBoundSSBO = buffers[1]; GLuint& bvhBoundSSBO = buffers[1];
GLuint& elementOffsetSSBO = buffers[2]; GLuint& elementTransformSSBO = buffers[2];
GLuint& elementIndexSSBO = buffers[3]; GLuint& elementOffsetSSBO = buffers[3];
GLuint& elementDataSSBO = buffers[4]; GLuint& elementIndexSSBO = buffers[4];
GLuint& backgroundColorUBO = buffers[5]; GLuint& elementDataSSBO = buffers[5];
GLuint& backgroundColorUBO = buffers[6];
glFunc->glNamedBufferData(buffers[0], bvhChildren.size() * sizeof(bvhChildren[0]), bvhChildren.data(), GL_STATIC_READ); glFunc->glNamedBufferData(buffers[0], bvhChildren.size() * sizeof(bvhChildren[0]), bvhChildren.data(), GL_STATIC_READ);
glFunc->glNamedBufferData(buffers[1], bvhBounds.size() * sizeof(bvhBounds[0]), bvhBounds.data(), GL_STATIC_READ); glFunc->glNamedBufferData(buffers[1], bvhBounds.size() * sizeof(bvhBounds[0]), bvhBounds.data(), GL_STATIC_READ);
glFunc->glNamedBufferData(buffers[2], elementOffsets.size() * sizeof(elementOffsets[0]), elementOffsets.data(), GL_STATIC_READ); glFunc->glNamedBufferData(buffers[2], elementTransform.size() * sizeof(elementTransform[0]), elementTransform.data(), GL_STATIC_READ);
glFunc->glNamedBufferData(buffers[3], elementIndex.size() * sizeof(elementIndex[0]), elementIndex.data(), GL_STATIC_READ); glFunc->glNamedBufferData(buffers[3], elementOffsets.size() * sizeof(elementOffsets[0]), elementOffsets.data(), GL_STATIC_READ);
glFunc->glNamedBufferData(buffers[4], elementData.size() * sizeof(elementData[0]), elementData.data(), GL_STATIC_READ); glFunc->glNamedBufferData(buffers[4], elementIndex.size() * sizeof(elementIndex[0]), elementIndex.data(), GL_STATIC_READ);
glFunc->glNamedBufferData(buffers[5], elementData.size() * sizeof(elementData[0]), elementData.data(), GL_STATIC_READ);
glm::vec3 color(backgroundColor.redF(), backgroundColor.greenF(), backgroundColor.blueF()); glm::vec3 color(backgroundColor.redF(), backgroundColor.greenF(), backgroundColor.blueF());
glFunc->glNamedBufferData(buffers[5], sizeof(glm::vec3), &color, GL_STATIC_READ); glFunc->glNamedBufferData(buffers[6], sizeof(glm::vec3), &color, GL_STATIC_READ);
} }
GLuint Renderer::Painting::getElementCount() GLuint Renderer::Painting::getElementCount()
@ -223,3 +181,17 @@ bool Renderer::Painting::CompareMaterialStyle::operator()(const std::shared_ptr<
else else
return left < right; return left < right;
} }
std::size_t Renderer::Painting::HashMat3x2::operator()(const glm::mat3x2& mat) const
{
std::size_t result = 0;
constexpr long long P = 998244353;
long long base = 1;
for (int i = 0; i < 3; i++)
for (int j = 0; j < 2; j++)
{
result += base * mat[i][j];
base *= P;
}
return result;
}

View File

@ -15,24 +15,13 @@ namespace Renderer
{ {
std::shared_ptr<Contour> contour; std::shared_ptr<Contour> contour;
std::shared_ptr<MaterialStyle> style; std::shared_ptr<MaterialStyle> style;
float ratio; /// ¿í¸ß±È
bool operator<(const BaseElement& e) const; bool operator<(const BaseElement& e) const;
}; };
struct BaseTransform
{
glm::vec4 bound;
float rotation;
glm::bvec2 flip;
GLuint zIndex;
BaseTransform(ElementTransform t);
};
struct ElementWithTransform struct ElementWithTransform
{ {
BaseElement element; BaseElement element;
ElementTransform transform; ElementTransform transform;
//BaseTransform transform;
}; };
struct ContourBuffer struct ContourBuffer
@ -52,7 +41,6 @@ namespace Renderer
GLuint styleOffset; GLuint styleOffset;
GLuint pointsOffset; GLuint pointsOffset;
GLuint linesOffset; GLuint linesOffset;
GLuint ratio;
}; };
class Painting class Painting
@ -60,16 +48,16 @@ namespace Renderer
public: public:
std::vector<GLuint> bvhChildren; std::vector<GLuint> bvhChildren;
std::vector<QVector4D> bvhBounds; std::vector<QVector4D> bvhBounds;
std::vector<glm::mat3x2> elementTransform;
std::vector<ElementOffset> elementOffsets; std::vector<ElementOffset> elementOffsets;
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, 6> buffers; std::array<GLuint, 7> buffers;
QColor backgroundColor; QColor backgroundColor;
Painting(QColor backgroundColor = Qt::white); Painting(QColor backgroundColor = Qt::white);
void addElement(const Element& element, const ElementTransform& transform); void addElement(const BaseElement& element, const ElementTransform& transform);
void addElement(std::shared_ptr<Element> element, QVector4D bound, float rotation, int zIndex);
void generateBuffers(QOpenGLFunctions_4_5_Core* glFunc); void generateBuffers(QOpenGLFunctions_4_5_Core* glFunc);
GLuint getElementCount(); GLuint getElementCount();
private: private:
@ -77,14 +65,15 @@ namespace Renderer
std::unordered_map<std::tuple<std::shared_ptr<Contour>, MaterialStyleType>, ContourBuffer, ContourHash> contourPool; std::unordered_map<std::tuple<std::shared_ptr<Contour>, MaterialStyleType>, ContourBuffer, ContourHash> contourPool;
struct CompareMaterialStyle { bool operator()(const std::shared_ptr<MaterialStyle>&, const std::shared_ptr<MaterialStyle>&) const; }; struct CompareMaterialStyle { bool operator()(const std::shared_ptr<MaterialStyle>&, const std::shared_ptr<MaterialStyle>&) const; };
std::set<std::shared_ptr<MaterialStyle>, CompareMaterialStyle> styleSet; std::set<std::shared_ptr<MaterialStyle>, CompareMaterialStyle> styleSet;
std::unordered_map<std::shared_ptr<ElementStyle>, std::vector<BaseStyle>> elementStyleMap;
std::unordered_map<std::shared_ptr<MaterialStyle>, GLuint> stylePool; std::unordered_map<std::shared_ptr<MaterialStyle>, GLuint> stylePool;
struct HashMat3x2 { std::size_t operator()(const glm::mat3x2&) const; };
std::unordered_map<glm::mat3x2, GLuint, HashMat3x2> elementTransformPool;
std::map<BaseElement, GLuint> elementPool; std::map<BaseElement, GLuint> elementPool;
std::vector<ElementWithTransform> elements; std::vector<ElementWithTransform> elements;
void addElement(ElementWithTransform element); void addElement(ElementWithTransform element);
void insertContourBuffer(ContourBuffer& buffer); void insertContourBuffer(ContourBuffer& buffer);
BvhTreeData encodeElementLeaf(ElementWithTransform e); BvhTreeData encodeElementLeaf(const ElementWithTransform& e);
}; };
} }

View File

@ -88,13 +88,23 @@ QRectF calcBoundingRect(const QPainterPath& path, const std::vector<BaseStyle>&
{ {
QRectF bound = path.boundingRect(); QRectF bound = path.boundingRect();
ElementTransform originTransform{ glm::vec2(bound.center().x(), bound.center().y()), glm::vec2(bound.width(), bound.height()), 0, glm::bvec2(false), 0 }; //ElementTransform originTransform{ glm::vec2(bound.center().x(), bound.center().y()), glm::vec2(bound.width(), bound.height()), 0, glm::bvec2(false), 0 };
glm::vec2 leftTop(std::numeric_limits<float>::max()), rightBottom(std::numeric_limits<float>::min()); glm::vec2 leftTop(std::numeric_limits<float>::max()), rightBottom(std::numeric_limits<float>::min());
for (auto& baseStyle : styles) for (auto& baseStyle : styles)
{ {
BaseTransform transform(originTransform.appliedTransformStyle(*baseStyle.transform)); struct BaseTransform
{
glm::vec4 bound;
float rotation = 0;
glm::bvec2 flip = glm::bvec2(false);
GLuint zIndex = 0;
};
//BaseTransform transform(originTransform.appliedTransformStyle(*baseStyle.transform));
glm::vec2 center(bound.center().x(), bound.center().y());
glm::vec2 scale(bound.width(), bound.height());
BaseTransform transform{ glm::vec4(center - scale, center + scale) };
if (baseStyle.material->type() == MaterialStyleType::kStroke) if (baseStyle.material->type() == MaterialStyleType::kStroke)
{ {
float halfWidth = std::static_pointer_cast<MaterialStyleStroke>(baseStyle.material)->getHalfWidth(); float halfWidth = std::static_pointer_cast<MaterialStyleStroke>(baseStyle.material)->getHalfWidth();

View File

@ -124,9 +124,9 @@ std::uint16_t Renderer::VirtualTextureManager::createVirtualTexture(Painting pai
glMain->TextureParameteri(metallicRoughness, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glMain->TextureParameteri(metallicRoughness, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glMain->TextureStorage2D(metallicRoughness, levels, GL_RG8, GLsizei(textureSize), GLsizei(textureSize)); glMain->TextureStorage2D(metallicRoughness, levels, GL_RG8, GLsizei(textureSize), GLsizei(textureSize));
for (int i = 0; i < 5; i++) for (int i = 0; i < 6; i++)
glMain->BindBufferBase(GL_SHADER_STORAGE_BUFFER, i, painting.buffers[i]); glMain->BindBufferBase(GL_SHADER_STORAGE_BUFFER, i, painting.buffers[i]);
glMain->BindBufferBase(GL_UNIFORM_BUFFER, 1, painting.buffers[5]); glMain->BindBufferBase(GL_UNIFORM_BUFFER, 1, painting.buffers[6]);
for (auto level = levels - 1; level < levels; ++level) for (auto level = levels - 1; level < levels; ++level)
{ {
@ -170,8 +170,10 @@ void Renderer::VirtualTextureManager::deleteVirtualTexture(std::uint16_t id)
{ {
auto& painting = getPaintingHandle(id); auto& painting = getPaintingHandle(id);
glMain->DeleteTextures(2, (GLuint*)&painting); glMain->DeleteTextures(2, (GLuint*)&painting);
glMain->DeleteBuffers(7, painting.buffers.data());
painting.baseColor = 0; painting.baseColor = 0;
painting.metallicRoughness = 0; painting.metallicRoughness = 0;
painting.buffers.fill(0);
} }
Renderer::PaintingHandle& Renderer::VirtualTextureManager::getPaintingHandle(std::uint16_t id) Renderer::PaintingHandle& Renderer::VirtualTextureManager::getPaintingHandle(std::uint16_t id)
@ -207,9 +209,9 @@ void Renderer::VirtualTextureManager::pageCommitmentById(const glm::u16vec2& pag
if (commit) if (commit)
{ {
program.bind(); program.bind();
for (int i = 0; i < 5; i++) for (int i = 0; i < 6; i++)
gl->BindBufferBase(GL_SHADER_STORAGE_BUFFER, i, painting.buffers[i]); gl->BindBufferBase(GL_SHADER_STORAGE_BUFFER, i, painting.buffers[i]);
glMain->BindBufferBase(GL_UNIFORM_BUFFER, 1, painting.buffers[5]); glMain->BindBufferBase(GL_UNIFORM_BUFFER, 1, painting.buffers[6]);
gl->Uniform2i(gl->GetUniformLocation(program.programId(), "pixelOffset"), static_cast<GLsizei>(pageSize) * page.x, static_cast<GLsizei>(pageSize) * page.y); gl->Uniform2i(gl->GetUniformLocation(program.programId(), "pixelOffset"), static_cast<GLsizei>(pageSize) * page.x, static_cast<GLsizei>(pageSize) * page.y);
gl->BindImageTexture(0, painting.baseColor, level, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8); gl->BindImageTexture(0, painting.baseColor, level, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8);
gl->BindImageTexture(1, painting.metallicRoughness, level, GL_FALSE, 0, GL_READ_WRITE, GL_RG8); gl->BindImageTexture(1, painting.metallicRoughness, level, GL_FALSE, 0, GL_READ_WRITE, GL_RG8);

View File

@ -15,7 +15,7 @@ namespace Renderer
{ {
GLuint baseColor; GLuint baseColor;
GLuint metallicRoughness; GLuint metallicRoughness;
std::array<GLuint, 6> buffers; std::array<GLuint, 7> buffers;
}; };
class VirtualTextureManager class VirtualTextureManager