实现线的径向渐变\分层样式

dev-VirtualTexture
wuyize 2023-02-10 13:48:30 +08:00
parent a13c562885
commit 1905b66179
13 changed files with 321 additions and 131 deletions

View File

@ -893,21 +893,56 @@ bool angleLargeThanPi(vec2 a, vec2 b)
/************************************************************************************/ /************************************************************************************/
void drawLine(in float d, in uint styleIndex, out vec4 elementColor, out vec2 metallicRoughness) void drawLine(in float d, inout uint styleIndex, out vec4 elementColor, out vec2 metallicRoughness)
{ {
elementColor = vec4(1); elementColor = vec4(1);
metallicRoughness = vec2(0.8); metallicRoughness = vec2(0.8);
// switch(int(elementData[styleIndex+3])) uint headUint = floatBitsToUint(style[styleIndex+1]);
switch (0) vec4 head = unpackUnorm4x8(headUint);
switch (int(head.a*100)%10)
//switch (2)
{ {
/// Plain
case 0: { case 0: {
elementColor = vec4(unpackUnorm4x8(floatBitsToUint(style[styleIndex + 2])).rgb, 1); metallicRoughness = head.rg;
metallicRoughness = vec2(unpackUnorm4x8(floatBitsToUint(style[styleIndex + 1])).rg); elementColor = vec4(unpackUnorm4x8(floatBitsToUint(style[styleIndex+2])).rgb, 1);
break; break;
} }
/// RadialGradient
case 1: { case 1: {
elementColor = vec4(mix(vec3(0), vec3(1), d), 1); uint size = headUint%(1<<15);
metallicRoughness = vec2(0, 0.8); bool gradual = (headUint&(1<<15))!=0;
uint lastData = floatBitsToUint(style[styleIndex+2+0*2]);
float lastLevel = 0;
vec2 lastMetallicRoughness = unpackUnorm4x8(lastData).rg;
vec4 lastColor = vec4(unpackUnorm4x8(floatBitsToUint(style[styleIndex+3+0*2])).rgb, 1);
for(uint i = 0; i < size; i++)
{
uint data = floatBitsToUint(style[styleIndex+2+i*2]);
float level = unpackUnorm2x16(data).y;
vec4 currentColor = vec4(unpackUnorm4x8(floatBitsToUint(style[styleIndex+3+i*2])).rgb, 1);
vec2 currentMetallicRoughness = unpackUnorm4x8(data).rg;
if (d <= level)
{
if(gradual)
{
float a = (d-lastLevel)/(level-lastLevel);
elementColor = mix(lastColor, currentColor, a);
metallicRoughness = mix(lastMetallicRoughness, currentMetallicRoughness, a);
}
else
{
elementColor = currentColor;
metallicRoughness = currentMetallicRoughness;
}
break;
}
lastMetallicRoughness = currentMetallicRoughness;
lastColor = currentColor;
lastLevel = level;
}
break; break;
} }
case 2: { case 2: {
@ -987,8 +1022,9 @@ void main()
else // Stroke else // Stroke
{ {
float minDistance = 1e38; float minDistance = 1e38;
// float lineType = elementData[styleIndex+4]; vec4 styleHead = unpackUnorm4x8(floatBitsToUint(style[styleIndex+1]));
float lineType = 2; float lineType = floor(styleHead.b*10);
//float lineType = 2;
int debugBegin = 0; int debugBegin = 0;
for (uint pathIndex = 0; pathIndex < pathSize; pathIndex++) for (uint pathIndex = 0; pathIndex < pathSize; pathIndex++)
{ {

View File

@ -898,44 +898,76 @@ void drawLine(in float d, in uint styleIndex, out vec4 elementColor, out vec2 me
{ {
elementColor = vec4(1); elementColor = vec4(1);
metallicRoughness = vec2(0.8); metallicRoughness = vec2(0.8);
//switch(int(elementData[styleIndex+3])) uint headUint = floatBitsToUint(elementData[styleIndex+1]);
switch(0) vec4 head = unpackUnorm4x8(headUint);
{ switch (int(head.a*100)%10)
case 0: //switch (2)
{ {
elementColor = vec4(unpackUnorm4x8(floatBitsToUint(elementData[styleIndex+2])).rgb,1); /// Plain
metallicRoughness = vec2(unpackUnorm4x8(floatBitsToUint(elementData[styleIndex+1])).rg); case 0: {
break; metallicRoughness = head.rg;
} elementColor = vec4(unpackUnorm4x8(floatBitsToUint(elementData[styleIndex+2])).rgb, 1);
case 1: break;
{ }
elementColor = vec4(mix(vec3(0), vec3(1), d), 1); /// RadialGradient
metallicRoughness = vec2(0,0.8); case 1: {
break; uint size = headUint%(1<<15);
} bool gradual = (headUint&(1<<15))!=0;
case 2:
{ uint lastData = floatBitsToUint(elementData[styleIndex+2+0*2]);
float levels[] = {0.25,0.5,0.75}; float lastLevel = 0;
vec3 colors[] = {vec3(1,0,0), vec3(0,1,0), vec3(0,0,1), vec3(1,1,0)}; vec2 lastMetallicRoughness = unpackUnorm4x8(lastData).rg;
int i = 0; vec4 lastColor = vec4(unpackUnorm4x8(floatBitsToUint(elementData[styleIndex+3+0*2])).rgb, 1);
while(i<3)
{ for(uint i = 0; i < size; i++)
if(d<levels[i]) {
{ uint data = floatBitsToUint(elementData[styleIndex+2+i*2]);
elementColor = vec4(colors[i], 1); float level = unpackUnorm2x16(data).y;
metallicRoughness = vec2(0,0.8); vec4 currentColor = vec4(unpackUnorm4x8(floatBitsToUint(elementData[styleIndex+3+i*2])).rgb, 1);
break; vec2 currentMetallicRoughness = unpackUnorm4x8(data).rg;
} if (d <= level)
i++; {
} if(gradual)
if(i==3) {
{ float a = (d-lastLevel)/(level-lastLevel);
elementColor = vec4(colors[i], 1); elementColor = mix(lastColor, currentColor, a);
metallicRoughness = vec2(0,0.8); metallicRoughness = mix(lastMetallicRoughness, currentMetallicRoughness, a);
} }
break; else
} {
} elementColor = currentColor;
metallicRoughness = currentMetallicRoughness;
}
break;
}
lastMetallicRoughness = currentMetallicRoughness;
lastColor = currentColor;
lastLevel = level;
}
break;
}
case 2: {
float levels[] = {0.25, 0.5, 0.75};
vec3 colors[] = {vec3(1, 0, 0), vec3(0, 1, 0), vec3(0, 0, 1), vec3(1, 1, 0)};
int i = 0;
while (i < 3)
{
if (d < levels[i])
{
elementColor = vec4(colors[i], 1);
metallicRoughness = vec2(0, 0.8);
break;
}
i++;
}
if (i == 3)
{
elementColor = vec4(colors[i], 1);
metallicRoughness = vec2(0, 0.8);
}
break;
}
}
} }
bool drawElement(uint elementIndex, vec2 localUV, out vec3 color, out vec2 metallicRoughness, inout vec3 debugBVH = vec3(0)) bool drawElement(uint elementIndex, vec2 localUV, out vec3 color, out vec2 metallicRoughness, inout vec3 debugBVH = vec3(0))

View File

@ -390,14 +390,15 @@ GLuint Renderer::Model::loadPainting(std::string path)
// }), // }),
//}; //};
vector<std::shared_ptr<ElementStyle>> style = { vector<std::shared_ptr<ElementStyle>> style = {
std::make_shared<ElementStyleFillDemo>(), std::make_shared<ElementStyleFillDemo>(),
std::make_shared<ElementStyleStrokeDemo>(0.02) std::make_shared<ElementStyleStrokeDemo>(0.02),
std::make_shared<ElementStyleStrokeRadialGradientDemo>(0.02)
}; };
vector<std::shared_ptr<Element>> element = { vector<std::shared_ptr<Element>> element = {
std::make_shared<Element>(Element{ contour[0], style[0]}), std::make_shared<Element>(Element{ contour[0], style[0]}),
std::make_shared<Element>(Element{ contour[1], style[1]}), std::make_shared<Element>(Element{ contour[1], style[2]}),
std::make_shared<Element>(Element{ contour[2], style[0]}), std::make_shared<Element>(Element{ contour[2], style[0]}),
}; };
Painting painting; Painting painting;

View File

@ -18,5 +18,23 @@ Renderer::ElementStyleStrokeDemo::ElementStyleStrokeDemo(float width)
std::vector<BaseStyle> Renderer::ElementStyleStrokeDemo::toBaseStyles() const std::vector<BaseStyle> Renderer::ElementStyleStrokeDemo::toBaseStyles() const
{ {
return { BaseStyle(std::make_shared<TransformStyle>(), return { BaseStyle(std::make_shared<TransformStyle>(),
std::make_shared<MaterialStyleStroke>(width, StrokeType::kLeftSide, StrokeEndType::kRound, std::make_shared<StrokePlain>(QColor(0, 0, 255), 0, 0.8))) }; std::make_shared<MaterialStyleStroke>(width, StrokeType::kBothSides, StrokeEndType::kRound, std::make_shared<StrokePlain>(QColor(0, 0, 255), 0, 0.8))) };
} }
Renderer::ElementStyleStrokeRadialGradientDemo::ElementStyleStrokeRadialGradientDemo(float width)
: width(width)
{
}
std::vector<BaseStyle> Renderer::ElementStyleStrokeRadialGradientDemo::toBaseStyles() const
{
std::map<float, Material> materialMap = {
{0.25, Material{QColor(255,0,0)}},
{0.50, Material{QColor(0,255,0)}},
{0.75, Material{QColor(0,0,255)}},
{1.00, Material{QColor(255,255,0)}},
};
return { BaseStyle(std::make_shared<TransformStyle>(),
std::make_shared<MaterialStyleStroke>(width, StrokeType::kLeftSide, StrokeEndType::kRound,
std::make_shared<StrokeRadialGradient>(materialMap, false))) };
}

View File

@ -31,4 +31,14 @@ namespace Renderer
protected: protected:
float width; float width;
}; };
class ElementStyleStrokeRadialGradientDemo : public ElementStyle
{
public:
ElementStyleStrokeRadialGradientDemo(float width);
virtual std::vector<BaseStyle> toBaseStyles() const override;
protected:
float width;
};
} }

View File

@ -1,4 +1,5 @@
#include "MaterialStyleStroke.h" #include "MaterialStyleStroke.h"
#include <QDebug>
using namespace Renderer; using namespace Renderer;
@ -7,6 +8,11 @@ Renderer::StrokePlain::StrokePlain(QColor color, float metallic, float roughness
{ {
} }
Renderer::StrokePlain::StrokePlain(const Material& material)
: material(material)
{
}
MaterialStrokeType Renderer::StrokePlain::type() const MaterialStrokeType Renderer::StrokePlain::type() const
{ {
return MaterialStrokeType::kPlain; return MaterialStrokeType::kPlain;
@ -24,8 +30,43 @@ bool Renderer::StrokePlain::operator==(const MaterialStroke& m) const
&& material == static_cast<const StrokePlain&>(m).material; && material == static_cast<const StrokePlain&>(m).material;
} }
Renderer::StrokeRadialGradient::StrokeRadialGradient(const std::map<float, Material>& materialMap, bool gradual)
: materialMap(materialMap), gradual(gradual)
{
}
MaterialStrokeType Renderer::StrokeRadialGradient::type() const
{
return MaterialStrokeType::kRadialGradient;
}
std::vector<GLfloat> Renderer::StrokeRadialGradient::encoded() const
{
GLuint head = materialMap.size() + (gradual ? (1 << 15) : 0);
std::vector<GLfloat> result = { glm::uintBitsToFloat(head) };
for (auto& pair : materialMap)
{
auto [color, metallicRoughness] = pair.second.toVec();
GLuint i = glm::packUnorm4x8(glm::vec4(metallicRoughness, 0, 0));
glm::vec2 v = glm::unpackUnorm2x16(i);
v.y = pair.first;
result.push_back(glm::uintBitsToFloat(glm::packUnorm2x16(v)));
result.push_back(glm::uintBitsToFloat(glm::packUnorm4x8(color)));
qDebug() << pair.first;
}
return result;
}
bool Renderer::StrokeRadialGradient::operator==(const MaterialStroke& m) const
{
return type() == m.type()
&& gradual == static_cast<const StrokeRadialGradient&>(m).gradual
&& materialMap == static_cast<const StrokeRadialGradient&>(m).materialMap;
}
Renderer::MaterialStyleStroke::MaterialStyleStroke(float width, StrokeType strokeType, StrokeEndType endType, std::shared_ptr<MaterialStroke> materialStroke) Renderer::MaterialStyleStroke::MaterialStyleStroke(float width, StrokeType strokeType, StrokeEndType endType, std::shared_ptr<MaterialStroke> materialStroke)
: width(width), strokeType(strokeType), endType(endType), materialStroke(materialStroke) : halfWidth(width/2), strokeType(strokeType), endType(endType), materialStroke(materialStroke)
{ {
} }
@ -36,11 +77,11 @@ MaterialStyleType Renderer::MaterialStyleStroke::type() const
std::vector<GLfloat> Renderer::MaterialStyleStroke::encoded() const std::vector<GLfloat> Renderer::MaterialStyleStroke::encoded() const
{ {
std::vector<GLfloat> v = { width }; std::vector<GLfloat> v = { halfWidth };
auto encoded = materialStroke->encoded(); auto encoded = materialStroke->encoded();
glm::vec4 head = glm::unpackUnorm4x8(glm::floatBitsToUint(encoded[0])); glm::vec4 head = glm::unpackUnorm4x8(glm::floatBitsToUint(encoded[0]));
head.b = (float)strokeType / 10. + (float)endType / 100.; head.b = (float)strokeType / 10. + (float)endType / 100.;
head.a = 1; /// Ô¤Áô head.a = 0.6 /*ʹµÃpackºóСÓÚ0*/ + (float)materialStroke->type() / 100.;
encoded[0] = glm::uintBitsToFloat(glm::packUnorm4x8(head)); encoded[0] = glm::uintBitsToFloat(glm::packUnorm4x8(head));
v.insert(v.end(), encoded.begin(), encoded.end()); v.insert(v.end(), encoded.begin(), encoded.end());
return v; return v;
@ -51,9 +92,9 @@ bool Renderer::MaterialStyleStroke::operator==(const MaterialStyle& m) const
return type() == m.type() && *materialStroke == *static_cast<const MaterialStyleStroke&>(m).materialStroke; return type() == m.type() && *materialStroke == *static_cast<const MaterialStyleStroke&>(m).materialStroke;
} }
float Renderer::MaterialStyleStroke::getWidth() const float Renderer::MaterialStyleStroke::getHalfWidth() const
{ {
return width; return halfWidth;
} }

View File

@ -3,7 +3,7 @@
namespace Renderer namespace Renderer
{ {
enum class MaterialStrokeType { kPlain, kLinearGradient, kRadialGradient}; enum class MaterialStrokeType { kPlain = 0, kRadialGradient = 1, kLinearGradient = 2 };
class MaterialStroke class MaterialStroke
{ {
@ -17,6 +17,7 @@ namespace Renderer
{ {
public: public:
StrokePlain(QColor color, float metallic, float roughness); StrokePlain(QColor color, float metallic, float roughness);
StrokePlain(const Material& material);
virtual MaterialStrokeType type() const override; virtual MaterialStrokeType type() const override;
virtual std::vector<GLfloat> encoded() const override; virtual std::vector<GLfloat> encoded() const override;
virtual bool operator==(const MaterialStroke&) const override; virtual bool operator==(const MaterialStroke&) const override;
@ -27,12 +28,13 @@ namespace Renderer
class StrokeRadialGradient : public MaterialStroke class StrokeRadialGradient : public MaterialStroke
{ {
public: public:
StrokeRadialGradient(QColor color, float metallic, float roughness); StrokeRadialGradient(const std::map<float, Material>& materialMap, bool gradual);
virtual MaterialStrokeType type() const override; virtual MaterialStrokeType type() const override;
virtual std::vector<GLfloat> encoded() const override; virtual std::vector<GLfloat> encoded() const override;
virtual bool operator==(const MaterialStroke&) const override; virtual bool operator==(const MaterialStroke&) const override;
//std::map< std::map<float, Material> materialMap;
bool gradual = true;
}; };
enum class StrokeType { kBothSides = 2, kLeftSide = 1, kRightSide = 0 }; enum class StrokeType { kBothSides = 2, kLeftSide = 1, kRightSide = 0 };
@ -41,13 +43,13 @@ namespace Renderer
class MaterialStyleStroke : public MaterialStyle class MaterialStyleStroke : public MaterialStyle
{ {
public: public:
MaterialStyleStroke(float width, StrokeType strokeType, StrokeEndType endType, std::shared_ptr<MaterialStroke> materialStroke); MaterialStyleStroke(float width, StrokeType strokeType, StrokeEndType endType, std::shared_ptr<MaterialStroke> materialStroke);
virtual MaterialStyleType type() const override; virtual MaterialStyleType type() const override;
virtual std::vector<GLfloat> encoded() const override; virtual std::vector<GLfloat> encoded() const override;
virtual bool operator==(const MaterialStyle&) const override; virtual bool operator==(const MaterialStyle&) const override;
float getWidth() const; float getHalfWidth() const;
protected: protected:
float width; float halfWidth;
StrokeType strokeType; StrokeType strokeType;
StrokeEndType endType; StrokeEndType endType;
std::shared_ptr<MaterialStroke> materialStroke; std::shared_ptr<MaterialStroke> materialStroke;

View File

@ -43,7 +43,7 @@ void Renderer::Painting::addElement(ElementWithTransform elementWithTransform)
{ {
qDebug() << "Build LineTree-------------------------------------------------------------------------------------------------------"; qDebug() << "Build LineTree-------------------------------------------------------------------------------------------------------";
LineTree lineTree(maxLineCount); LineTree lineTree(maxLineCount);
lineTree.buildLineTree(*element.contour, std::static_pointer_cast<MaterialStyleStroke>(element.style)->getWidth()); lineTree.buildLineTree(*element.contour, std::static_pointer_cast<MaterialStyleStroke>(element.style)->getHalfWidth());
ContourBuffer elementBuffer; ContourBuffer elementBuffer;
std::vector<BvhTreeData> bvhLeaves = lineTree.getPointLineAndBvhTree(elementBuffer.pointBuffer, elementBuffer.lineBuffer); std::vector<BvhTreeData> bvhLeaves = lineTree.getPointLineAndBvhTree(elementBuffer.pointBuffer, elementBuffer.lineBuffer);
BvhTree bvhTree; BvhTree bvhTree;

View File

@ -20,7 +20,7 @@ Renderer::ElementRenderer::ElementRenderer(QOpenGLWidget* glWidget)
void Renderer::ElementRenderer::initialize() void Renderer::ElementRenderer::initialize()
{ {
initializeOpenGLFunctions(); initializeOpenGLFunctions();
shader = std::make_shared<QOpenGLShaderProgram>(); shader = std::make_unique<QOpenGLShaderProgram>();
if (!shader->addShaderFromSourceFile(QOpenGLShader::Compute, ":/Shaders/element.comp")) if (!shader->addShaderFromSourceFile(QOpenGLShader::Compute, ":/Shaders/element.comp"))
qDebug() << "ERROR: " << shader->log(); qDebug() << "ERROR: " << shader->log();
if (!shader->link()) if (!shader->link())
@ -37,30 +37,25 @@ std::vector<glm::vec2> generatePathBuffer(const QPainterPath& path)
switch (element.type) switch (element.type)
{ {
case QPainterPath::MoveToElement: case QPainterPath::MoveToElement:
qDebug() << "MoveToElement";
pathBuffer.push_back(glm::vec2(std::numeric_limits<float>::infinity())); pathBuffer.push_back(glm::vec2(std::numeric_limits<float>::infinity()));
pathBuffer.push_back(glm::vec2(element.x, element.y)); pathBuffer.push_back(glm::vec2(element.x, element.y));
break; break;
case QPainterPath::LineToElement: case QPainterPath::LineToElement:
qDebug() << "LineToElement"; {
{ glm::vec2 end = glm::vec2(element.x, element.y);
glm::vec2 end = glm::vec2(element.x, element.y); glm::vec2 mid = (pathBuffer.back() + end) / 2.f;
glm::vec2 mid = (pathBuffer.back() + end) / 2.f; pathBuffer.push_back(mid);
pathBuffer.push_back(mid); pathBuffer.push_back(mid);
pathBuffer.push_back(mid); pathBuffer.push_back(end);
pathBuffer.push_back(end);
}
break; break;
}
case QPainterPath::CurveToElement: case QPainterPath::CurveToElement:
qDebug() << "CurveToElement";
pathBuffer.push_back(glm::vec2(element.x, element.y)); pathBuffer.push_back(glm::vec2(element.x, element.y));
break; break;
case QPainterPath::CurveToDataElement: case QPainterPath::CurveToDataElement:
qDebug() << "CurveToDataElement";
pathBuffer.push_back(glm::vec2(element.x, element.y)); pathBuffer.push_back(glm::vec2(element.x, element.y));
break; break;
} }
qDebug() << element;
} }
return pathBuffer; return pathBuffer;
} }
@ -95,11 +90,8 @@ QRectF calcBoundingRect(const QPainterPath& path, const std::vector<BaseStyle>&
BaseTransform transform(originTransform.appliedTransformStyle(*baseStyle.transform)); BaseTransform transform(originTransform.appliedTransformStyle(*baseStyle.transform));
if (baseStyle.material->type() == MaterialStyleType::kStroke) if (baseStyle.material->type() == MaterialStyleType::kStroke)
{ {
float halfWidth = std::static_pointer_cast<MaterialStyleStroke>(baseStyle.material)->getWidth() / 2; float halfWidth = std::static_pointer_cast<MaterialStyleStroke>(baseStyle.material)->getHalfWidth();
transform.bound.x -= halfWidth; transform.bound += glm::vec4(glm::vec2(-halfWidth), glm::vec2(halfWidth));
transform.bound.y -= halfWidth;
transform.bound.z += halfWidth;
transform.bound.w += halfWidth;
} }
glm::vec2 points[] = { glm::vec2 points[] = {
glm::vec2(transform.bound.x, transform.bound.y), glm::vec2(transform.bound.x, transform.bound.y),

View File

@ -28,7 +28,7 @@ namespace Renderer
std::pair<QImage, QPointF> drawElement(const QPainterPath& path, const ElementStyle& style, float pixelRatio, bool releaseContext = true); std::pair<QImage, QPointF> drawElement(const QPainterPath& path, const ElementStyle& style, float pixelRatio, bool releaseContext = true);
protected: protected:
QOpenGLWidget* glWidget; QOpenGLWidget* glWidget;
std::shared_ptr<QOpenGLShaderProgram> shader; std::unique_ptr<QOpenGLShaderProgram> shader;
}; };
} }

View File

@ -19,15 +19,9 @@
### 场景渲染Renderer ### 场景渲染Renderer
采用 PBR (金属度-粗糙度) 材质模型,场景中存在一个方向光,可拖动滑动条调整光源方向观察材质效果。 采用 PBR (金属度-粗糙度) 材质模型,场景中存在一个方向光,可拖动滑动条调整光源方向观察材质效果
已实现BVH加速结构的建立
已实现单图元的拆分,即划分网格并生成快捷段和缠绕增量
已实现由图元数据建立完整彩绘编码 已实现由图元数据建立完整彩绘编码
已实现线的单侧描边 已实现面的纯色样式,线的纯色、径向渐变/分层、单侧等样式
待完善图元样式的编解码

View File

@ -2,25 +2,81 @@
#include <QGuiApplication> #include <QGuiApplication>
#include <QtWidgets/QApplication> #include <QtWidgets/QApplication>
#include "ElementRendererTest.h" #include "ElementRendererTest.h"
#include "Renderer/Painting/ElementStyle.h"
using namespace Microsoft::VisualStudio::CppUnitTestFramework; using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace Renderer;
namespace UnitTest namespace UnitTest
{ {
TEST_CLASS(ElementRendererTest) TEST_CLASS(ElementRendererTest)
{ {
public: public:
TEST_METHOD(TestMethod1) TEST_METHOD(TestStrokePlain)
{ {
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
char arg[] = ""; QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
char* argv[] = { arg }; char* argv[] = { (char*)"" };
int argc = 1; int argc = 1;
QApplication a(argc, argv); QApplication a(argc, argv);
TestGLWidget w; Renderer::ElementStyleStrokeDemo style(2);
w.show(); TestGLWidget w(style);
a.exec(); w.show();
} a.exec();
}; }
TEST_METHOD(TestStrokeRadialGradient1)
{
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
char* argv[] = { (char*)"" };
int argc = 1;
QApplication a(argc, argv);
class StyleStrokeRadialGradient : public Renderer::ElementStyle
{
virtual std::vector<Renderer::BaseStyle> toBaseStyles() const override
{
std::map<float, Material> materialMap = {
{0.25, Material{QColor(255,0,0)}},
{0.50, Material{QColor(0,255,0)}},
{0.75, Material{QColor(0,0,255)}},
{1.00, Material{QColor(255,255,0)}},
};
return { BaseStyle(std::make_shared<TransformStyle>(),
std::make_shared<MaterialStyleStroke>(4, StrokeType::kLeftSide, StrokeEndType::kRound,
std::make_shared<StrokeRadialGradient>(materialMap, false))) };
}
} style;
TestGLWidget w(style);
w.show();
a.exec();
}
TEST_METHOD(TestStrokeRadialGradient2)
{
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
char* argv[] = { (char*)"" };
int argc = 1;
QApplication a(argc, argv);
class StyleStrokeRadialGradient : public Renderer::ElementStyle
{
virtual std::vector<Renderer::BaseStyle> toBaseStyles() const override
{
std::map<float, Material> materialMap = {
{0.50, Material{QColor(0,255,0)}},
{0.75, Material{QColor(0,0,255)}},
{1.00, Material{QColor(255,255,0)}},
};
return { BaseStyle(std::make_shared<TransformStyle>(),
std::make_shared<MaterialStyleStroke>(4, StrokeType::kLeftSide, StrokeEndType::kRound,
std::make_shared<StrokeRadialGradient>(materialMap, true))) };
}
} style;
TestGLWidget w(style);
w.show();
a.exec();
}
};
} }

View File

@ -9,28 +9,36 @@
namespace UnitTest namespace UnitTest
{ {
class TestGLWidget : public QOpenGLWidget, protected QOpenGLFunctions class TestGLWidget : public QOpenGLWidget, protected QOpenGLFunctions
{ {
Q_OBJECT Q_OBJECT
private: private:
Renderer::ElementRenderer renderer; Renderer::ElementRenderer renderer;
public: Renderer::ElementStyle& style;
TestGLWidget(QWidget* parent = nullptr) : QOpenGLWidget(parent), renderer(this) {}; public:
void initializeGL() override TestGLWidget(Renderer::ElementStyle& style, QWidget* parent = nullptr)
{ : QOpenGLWidget(parent), renderer(this), style(style) {};
initializeOpenGLFunctions(); void initializeGL() override
renderer.initialize(); {
}; initializeOpenGLFunctions();
void paintGL() override renderer.initialize();
{ };
glClearColor(1.0, 1.0, 1.0, 1.0); void paintGL() override
glClear(GL_COLOR_BUFFER_BIT); {
QPainterPath path; glClearColor(1.0, 1.0, 1.0, 1.0);
QQuickSvgParser::parsePathDataFast("M100,100C-.5,100,0,100.5,0,0L40,.07C40,59.5,39.5,60,100,60Z", path); glClear(GL_COLOR_BUFFER_BIT);
auto [img, pos] = renderer.drawElement(path, Renderer::ElementStyleStrokeDemo(2), 1, false); QPainterPath path;
QPainter painter(this); QQuickSvgParser::parsePathDataFast("M100,100C-.5,100,0,100.5,0,0L40,.07C40,59.5,39.5,60,100,60Z", path);
painter.drawImage(pos, img); /*QTransform transform;
}; transform.scale(10, 10);
void resizeGL(int w, int h) override {}; transform.map(path);*/
}; float pixelRatio = 30;
auto [img, pos] = renderer.drawElement(path, style, pixelRatio, false);
QPainter painter(this);
painter.setRenderHint(QPainter::SmoothPixmapTransform);
painter.setRenderHint(QPainter::HighQualityAntialiasing);
painter.drawImage(QRectF(QPointF(0, 0), img.size()/devicePixelRatioF()), img);
};
void resizeGL(int w, int h) override {};
};
} }