dev-LayerStyle
yang.yongquan 2023-03-15 11:25:14 +08:00
commit 73e63f3817
10 changed files with 1253 additions and 1003 deletions

View File

@ -893,7 +893,7 @@ bool angleLargeThanPi(vec2 a, vec2 b)
/************************************************************************************/
void drawLine(in float d, inout uint styleIndex, out vec4 elementColor, out vec2 metallicRoughness)
void drawLine(in float d, uint styleIndex, out vec4 elementColor, out vec2 metallicRoughness)
{
elementColor = vec4(1);
metallicRoughness = vec2(0.8);
@ -969,14 +969,38 @@ void drawLine(in float d, inout uint styleIndex, out vec4 elementColor, out vec2
}
}
bool shouldFillBeginCap(vec2 localUV, bool onVeryBegin, int endType, vec2 p3, vec2 tangentBegin, vec2 tangentEndLast)
void nextStyleIndex(inout uint styleIndex)
{
uint headUint = floatBitsToUint(style[styleIndex + 1]);
vec4 head = unpackUnorm4x8(headUint);
switch (int(head.a * 100) % 10)
{
/// Plain
case 0: {
styleIndex += 3;
break;
}
/// RadialGradient
case 1: {
uint size = headUint % (1 << 15);
styleIndex += 2 + size * 2;
break;
}
case 2: {
break;
}
}
}
bool shouldFillBeginCap(vec2 localUV, bool onVeryBegin, int endType, vec2 p0, vec2 tangentBegin, vec2 tangentEndLast)
{
vec2 normal;
if (onVeryBegin)
{
if (endType == 0)
if (endType%2 == 0)
return true;
else if (endType == 1)
else if (endType%2 == 1)
normal = normalize(mat2(0, 1, -1, 0) * (-tangentBegin));
}
else
@ -985,17 +1009,26 @@ bool shouldFillBeginCap(vec2 localUV, bool onVeryBegin, int endType, vec2 p3, ve
vec2 normalNow = normalize(mat2(0, 1, -1, 0) * (-tangentBegin));
normal = normalLast + normalNow;
}
return angleLargeThanPi(normal, localUV - p3);
return angleLargeThanPi(normal, localUV - p0);
}
bool shouldFillEndCap(vec2 localUV, int endType, vec2 p0, vec2 tangentEnd)
bool shouldFillEndCap(vec2 localUV, bool onVeryEnd, int endType, vec2 p3, vec2 tangentEnd, vec2 tangentBeginNext)
{
vec2 normal;
if (endType == 0)
return true;
else if (endType == 1)
normal = normalize(mat2(0, 1, -1, 0) * tangentEnd);
return angleLargeThanPi(localUV - p0, normal);
if (onVeryEnd)
{
if ((endType/2)%2 == 0)
return true;
else if ((endType/2)%2 == 1)
normal = normalize(mat2(0, 1, -1, 0) * tangentEnd);
}
else
{
vec2 normalLast = normalize(mat2(0, 1, -1, 0) * tangentEnd);
vec2 normalNow = normalize(mat2(0, 1, -1, 0) * (-tangentBeginNext));
normal = normalLast + normalNow;
}
return angleLargeThanPi(localUV - p3, normal);
}
void main()
@ -1006,9 +1039,8 @@ void main()
vec4 color = vec4(0);
// if(isinf(path[0].x)) imageStore(gBaseColor, ivec2(pixelLocation),
// vec4(vec2(pixelLocation)/vec2(imageSize(gBaseColor)), 1,1)); return;
for (uint styleIndex = 0; styleIndex < styleSize; styleIndex++)
for (uint styleIndex = 0; styleIndex < styleSize;)
{
styleIndex += 6;
vec2 localUV = vec2(pixelLocation) / pixelRatio + leftTop;
@ -1047,6 +1079,7 @@ void main()
elementColor = vec4(unpackUnorm4x8(floatBitsToUint(style[++styleIndex])).rgb, 1);
}
}
}
else // Stroke
{
@ -1055,21 +1088,22 @@ void main()
float lineType = floor(styleHead.b * 10);
// float lineType = 2;
int endType = int(round(styleHead.b * 100)) % 10;
//endType = 1;
// endType = 1;
int debugBegin = 0;
bool onVeryBegin = false;
bool onVeryEnd = false;
vec2 tangentEndLast;
uint lastHitIndex = 0;
bool lastHitElement = false;
hitElement = false;
for (uint pathIndex = 0; pathIndex < pathSize; pathIndex++)
// for (uint pathIndex = 0; pathIndex < 4; pathIndex++)
//for (uint pathIndex = 0; pathIndex < 46; pathIndex++)
{
vec2 pTemp = path[pathIndex];
if (isinf(pTemp.x))
{
// TODO: ¼ì²âÊÇ·ñ·â±Õ²¢´¦Àí
if (hitElement && distance(localUV, p3Last) <= strokeWidth)
{
hitElement = shouldFillEndCap(localUV, endType, p3Last, tangentEndLast);
}
pBegin = path[++pathIndex];
p3Last = pBegin;
@ -1079,10 +1113,32 @@ void main()
}
mat4x2 p = mat4x2(p3Last, pTemp, path[++pathIndex], path[++pathIndex]);
vec2 tangentBeginNext;
if (pathIndex + 1 < pathSize)
{
vec2 pTemp = path[pathIndex + 1];
if (isinf(pTemp.x))
{
onVeryEnd = true;
}
else
{
onVeryEnd = false;
vec2 pNext[3] = {p[3], pTemp, path[pathIndex + 2]};
if (pNext[0] != pNext[1])
tangentBeginNext = normalize(pNext[0] - pNext[1]);
else
tangentBeginNext = normalize(pNext[0] - pNext[2]);
}
}
else
onVeryEnd = true;
float d = cubic_bezier_dis(localUV, p[0], p[1], p[2], p[3], true);
if (d <= strokeWidth)
{
bool onBegin = distance(localUV, p[0]) <= strokeWidth && p3Last == p[0];
bool onBegin = distance(localUV, p[0]) <= strokeWidth;
bool onEnd = distance(localUV, p[3]) <= strokeWidth;
vec2 tangentBegin;
vec2 tangentEnd;
if (p[0] != p[1])
@ -1094,11 +1150,14 @@ void main()
else
tangentEnd = normalize(p[3] - p[1]);
if (onBegin ? shouldFillBeginCap(localUV, onVeryBegin, endType, p[0], tangentBegin, p3Last - p2Last)
: d < minDistance)
bool hit = d < minDistance;
if (onBegin)
hit = hit &&
shouldFillBeginCap(localUV, onVeryBegin, endType, p[0], tangentBegin, tangentEndLast);
if (onEnd)
hit = hit && shouldFillEndCap(localUV, onVeryEnd, endType, p[3], tangentEnd, tangentBeginNext);
if (hit)
{
minDistance = min(minDistance, d);
bool reverse = p[3].y - p[0].y < 0.;
if (tangentBegin.y == 0.)
@ -1111,13 +1170,14 @@ void main()
if (lineType == 2 || (intTest % 2 == int(lineType)))
{
minDistance = min(minDistance, d);
lastHitElement = hitElement;
lastHitIndex = pathIndex;
hitElement = true;
// elementColor = vec4(1, 1, 0, 1);
vec2 metallicRoughness;
drawLine(minDistance / strokeWidth, styleIndex, elementColor, metallicRoughness);
}
else if (p3Last == p[0])
hitElement = false;
}
tangentEndLast = tangentEnd;
}
@ -1125,14 +1185,11 @@ void main()
p2Last = p[2];
onVeryBegin = false;
}
if (hitElement && distance(localUV, p3Last) <= strokeWidth)
{
hitElement = shouldFillEndCap(localUV, endType, p3Last, tangentEndLast);
}
nextStyleIndex(styleIndex);
}
if (hitElement)
color = elementColor;
styleIndex += 100;
}
if (color.a != 0)
imageStore(gBaseColor, ivec2(pixelLocation), color);

File diff suppressed because it is too large Load Diff

View File

@ -62,15 +62,15 @@ QPainterPath PainterPathUtil::monotonization(QPainterPath& painterPath) {
return resPath;
}
std::pair<QPainterPath, float> PainterPathUtil::normalized(const QPainterPath& path)
std::pair<QPainterPath, float> PainterPathUtil::normalized(const QPainterPath& path, float width)
{
auto rect = path.boundingRect();
return { (QTransform::fromTranslate(-rect.center().x(), -rect.center().y()) * QTransform::fromScale(1 / (rect.width() / 1.999999), -1 / (rect.height() / 1.999999))).map(path),
return { (QTransform::fromTranslate(-rect.center().x(), -rect.center().y()) * QTransform::fromScale(1 / (rect.width() / 1.999999), -1 / (rect.height() / 1.999999)) * QTransform::fromScale(1 / (1 + width),1 / (1 + width))).map(path),
rect.width() / rect.height() };
}
std::pair<std::vector<std::vector<Renderer::Point>>, float> PainterPathUtil::toNormalizedLines(const QPainterPath& path)
std::pair<std::vector<std::vector<Renderer::Point>>, float> PainterPathUtil::toNormalizedLines(const QPainterPath& path, float width)
{
auto [p, ratio] = normalized(path);
auto [p, ratio] = normalized(path, width);
return { transformToLines(p), ratio };
}

View File

@ -8,7 +8,7 @@ class PainterPathUtil
public:
static std::vector<std::vector<Renderer::Point>> transformToLines(const QPainterPath& painterPath);
static QPainterPath monotonization(QPainterPath& painterPath);
static std::pair<QPainterPath, float> normalized(const QPainterPath& path);
static std::pair<std::vector<std::vector<Renderer::Point>>, float> toNormalizedLines(const QPainterPath& path);
static std::pair<QPainterPath, float> normalized(const QPainterPath& path, float width = 0);
static std::pair<std::vector<std::vector<Renderer::Point>>, float> toNormalizedLines(const QPainterPath& path, float width = 0);
};

View File

@ -15,6 +15,7 @@
#include "../Editor/util/SvgFileLoader.h"
#include <ThirdPartyLib/qquick/qquicksvgparser_p.h>
#include <util/PaintingUtil.h>
#include "Painting/MaterialStyleStroke.h"
using namespace Renderer;
using std::vector;
@ -157,14 +158,13 @@ std::unique_ptr<Drawable> Model::processMesh(aiMesh* mesh, const aiScene* scene,
for (auto& v : vertices)
{
//qDebug() << v.TexCoords.x << v.TexCoords.y;
v.TexCoords = (v.TexCoords - leftBottom) / (rightTop - leftBottom);
qDebug() << v.TexCoords.x << v.TexCoords.y;
//qDebug() << v.TexCoords.x << v.TexCoords.y;
}
mesh->vertices = vertices;
mesh->indices = indices;
mesh->paintingId = loadPainting(paintingPath);
auto& handle = vtManager->getPaintingHandle(mesh->paintingId);
mesh->textureBasecolor = handle.baseColor;

View File

@ -104,7 +104,11 @@ std::unique_ptr<MaterialStyle> Renderer::MaterialStyleStroke::clone() const
bool Renderer::MaterialStyleStroke::operator==(const MaterialStyle& m) const
{
return type() == m.type() && *materialStroke == *static_cast<const MaterialStyleStroke&>(m).materialStroke;
return type() == m.type()
&& halfWidth == static_cast<const MaterialStyleStroke&>(m).halfWidth
&& strokeType == static_cast<const MaterialStyleStroke&>(m).strokeType
&& endType == static_cast<const MaterialStyleStroke&>(m).endType
&& *materialStroke == *static_cast<const MaterialStyleStroke&>(m).materialStroke;
}
float Renderer::MaterialStyleStroke::getHalfWidth() const

View File

@ -43,7 +43,7 @@ namespace Renderer
};
enum class StrokeType { kBothSides = 2, kLeftSide = 1, kRightSide = 0 };
enum class StrokeEndType { kRound = 0, kFlat = 1 };
enum class StrokeEndType { kRound = 0b00, kFlat = 0b11, kRoundFlat = 0b10, kFlatRound = 0b01 };
class MaterialStyleStroke : public MaterialStyle
{
@ -54,7 +54,7 @@ namespace Renderer
virtual std::unique_ptr<MaterialStyle> clone() const override;
virtual bool operator==(const MaterialStyle&) const override;
float getHalfWidth() const;
//protected:
float halfWidth;
StrokeType strokeType;
StrokeEndType endType;

View File

@ -77,6 +77,7 @@ std::vector<GLfloat> generateStyleBuffer(const std::vector<BaseStyle>& styles)
styleBuffer.push_back(glm::uintBitsToFloat(glm::packUnorm2x16(style.transform->flip)));
auto encoded = style.material->encoded();
styleBuffer.insert(styleBuffer.end(), encoded.begin(), encoded.end());
qDebug() << "style size" << styleBuffer.size();
}
return styleBuffer;
}

View File

@ -12,9 +12,11 @@ Renderer::RendererWidget::RendererWidget(QWidget* parent)
auto openAction = new QAction(QStringLiteral("´ò¿ª"), menu);
auto saveAction = new QAction(QStringLiteral("±£´æ"), menu);
auto testAction = new QAction(QStringLiteral("²âÊÔ"), menu);
auto test2Action = new QAction(QStringLiteral("²âÊÔ2"), menu);
menu->addAction(openAction);
menu->addAction(saveAction);
menu->addAction(testAction);
menu->addAction(test2Action);
ui.openButton->setHaloVisible(false);
ui.openButton->setOverlayStyle(::Material::TintedOverlay);
@ -47,7 +49,9 @@ Renderer::RendererWidget::RendererWidget(QWidget* parent)
QObject::connect(testAction, &QAction::triggered, [&] {
ui.openGLWidget->setModel("Models/Sponza/Sponza.gltf");
});
QObject::connect(test2Action, &QAction::triggered, [&] {
ui.openGLWidget->setModel("E:\\3D Objects\\Gate\\Gate.gltf");
});
ui.horizontalSlider->setValue(105);
ui.horizontalSlider_2->setValue(80);
ui.exposureSlider->setValue(60);

View File

@ -10,6 +10,8 @@ using namespace Renderer;
namespace UnitTest
{
void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg);
TEST_CLASS(ElementRendererStokeTypeTest)
{
private:
@ -20,6 +22,7 @@ namespace UnitTest
TEST_METHOD_INITIALIZE(initialize)
{
qInstallMessageHandler(messageHandler);
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
@ -108,6 +111,27 @@ namespace UnitTest
w.show();
a.exec();
}
TEST_METHOD(TestRightSideFlatRound)
{
QApplication a(argc, argv);
class StyleStrokeRadialGradient : public Renderer::ElementStyle
{
virtual std::vector<Renderer::BaseStyle> toBaseStyles() const override
{
std::map<float, Material> materialMap = {
{0.20, Material{QColor(255,255,255)}},
{0.60, Material{QColor(165,176,207)}},
{1.00, Material{QColor(58,64,151)}}
};
return { BaseStyle(std::make_shared<TransformStyle>(),
std::make_shared<MaterialStyleStroke>(160, StrokeType::kRightSide, StrokeEndType::kFlatRound,
std::make_shared<StrokeRadialGradient>(materialMap, false))) };
}
} style;
TestGLWidget w(style);
w.show();
a.exec();
}
};
TEST_CLASS(ElementRendererStokeMaterialTest)