实现线的径向渐变\分层样式
parent
a13c562885
commit
1905b66179
|
@ -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);
|
||||
metallicRoughness = vec2(0.8);
|
||||
// switch(int(elementData[styleIndex+3]))
|
||||
switch (0)
|
||||
metallicRoughness = vec2(0.8);
|
||||
uint headUint = floatBitsToUint(style[styleIndex+1]);
|
||||
vec4 head = unpackUnorm4x8(headUint);
|
||||
switch (int(head.a*100)%10)
|
||||
//switch (2)
|
||||
{
|
||||
/// Plain
|
||||
case 0: {
|
||||
elementColor = vec4(unpackUnorm4x8(floatBitsToUint(style[styleIndex + 2])).rgb, 1);
|
||||
metallicRoughness = vec2(unpackUnorm4x8(floatBitsToUint(style[styleIndex + 1])).rg);
|
||||
metallicRoughness = head.rg;
|
||||
elementColor = vec4(unpackUnorm4x8(floatBitsToUint(style[styleIndex+2])).rgb, 1);
|
||||
break;
|
||||
}
|
||||
/// RadialGradient
|
||||
case 1: {
|
||||
elementColor = vec4(mix(vec3(0), vec3(1), d), 1);
|
||||
metallicRoughness = vec2(0, 0.8);
|
||||
uint size = headUint%(1<<15);
|
||||
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;
|
||||
}
|
||||
case 2: {
|
||||
|
@ -987,8 +1022,9 @@ void main()
|
|||
else // Stroke
|
||||
{
|
||||
float minDistance = 1e38;
|
||||
// float lineType = elementData[styleIndex+4];
|
||||
float lineType = 2;
|
||||
vec4 styleHead = unpackUnorm4x8(floatBitsToUint(style[styleIndex+1]));
|
||||
float lineType = floor(styleHead.b*10);
|
||||
//float lineType = 2;
|
||||
int debugBegin = 0;
|
||||
for (uint pathIndex = 0; pathIndex < pathSize; pathIndex++)
|
||||
{
|
||||
|
|
|
@ -898,44 +898,76 @@ void drawLine(in float d, in uint styleIndex, out vec4 elementColor, out vec2 me
|
|||
{
|
||||
elementColor = vec4(1);
|
||||
metallicRoughness = vec2(0.8);
|
||||
//switch(int(elementData[styleIndex+3]))
|
||||
switch(0)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
elementColor = vec4(unpackUnorm4x8(floatBitsToUint(elementData[styleIndex+2])).rgb,1);
|
||||
metallicRoughness = vec2(unpackUnorm4x8(floatBitsToUint(elementData[styleIndex+1])).rg);
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
elementColor = vec4(mix(vec3(0), vec3(1), d), 1);
|
||||
metallicRoughness = vec2(0,0.8);
|
||||
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;
|
||||
}
|
||||
}
|
||||
uint headUint = floatBitsToUint(elementData[styleIndex+1]);
|
||||
vec4 head = unpackUnorm4x8(headUint);
|
||||
switch (int(head.a*100)%10)
|
||||
//switch (2)
|
||||
{
|
||||
/// Plain
|
||||
case 0: {
|
||||
metallicRoughness = head.rg;
|
||||
elementColor = vec4(unpackUnorm4x8(floatBitsToUint(elementData[styleIndex+2])).rgb, 1);
|
||||
break;
|
||||
}
|
||||
/// RadialGradient
|
||||
case 1: {
|
||||
uint size = headUint%(1<<15);
|
||||
bool gradual = (headUint&(1<<15))!=0;
|
||||
|
||||
uint lastData = floatBitsToUint(elementData[styleIndex+2+0*2]);
|
||||
float lastLevel = 0;
|
||||
vec2 lastMetallicRoughness = unpackUnorm4x8(lastData).rg;
|
||||
vec4 lastColor = vec4(unpackUnorm4x8(floatBitsToUint(elementData[styleIndex+3+0*2])).rgb, 1);
|
||||
|
||||
for(uint i = 0; i < size; i++)
|
||||
{
|
||||
uint data = floatBitsToUint(elementData[styleIndex+2+i*2]);
|
||||
float level = unpackUnorm2x16(data).y;
|
||||
vec4 currentColor = vec4(unpackUnorm4x8(floatBitsToUint(elementData[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;
|
||||
}
|
||||
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))
|
||||
|
|
|
@ -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<ElementStyleStrokeDemo>(0.02)
|
||||
std::make_shared<ElementStyleStrokeDemo>(0.02),
|
||||
std::make_shared<ElementStyleStrokeRadialGradientDemo>(0.02)
|
||||
};
|
||||
|
||||
vector<std::shared_ptr<Element>> element = {
|
||||
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]}),
|
||||
};
|
||||
Painting painting;
|
||||
|
|
|
@ -18,5 +18,23 @@ Renderer::ElementStyleStrokeDemo::ElementStyleStrokeDemo(float width)
|
|||
std::vector<BaseStyle> Renderer::ElementStyleStrokeDemo::toBaseStyles() const
|
||||
{
|
||||
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))) };
|
||||
}
|
|
@ -31,4 +31,14 @@ namespace Renderer
|
|||
protected:
|
||||
float width;
|
||||
};
|
||||
|
||||
class ElementStyleStrokeRadialGradientDemo : public ElementStyle
|
||||
{
|
||||
public:
|
||||
ElementStyleStrokeRadialGradientDemo(float width);
|
||||
virtual std::vector<BaseStyle> toBaseStyles() const override;
|
||||
protected:
|
||||
float width;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "MaterialStyleStroke.h"
|
||||
#include <QDebug>
|
||||
|
||||
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
|
||||
{
|
||||
return MaterialStrokeType::kPlain;
|
||||
|
@ -24,8 +30,43 @@ bool Renderer::StrokePlain::operator==(const MaterialStroke& m) const
|
|||
&& 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)
|
||||
: 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> v = { width };
|
||||
std::vector<GLfloat> v = { halfWidth };
|
||||
auto encoded = materialStroke->encoded();
|
||||
glm::vec4 head = glm::unpackUnorm4x8(glm::floatBitsToUint(encoded[0]));
|
||||
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));
|
||||
v.insert(v.end(), encoded.begin(), encoded.end());
|
||||
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;
|
||||
}
|
||||
|
||||
float Renderer::MaterialStyleStroke::getWidth() const
|
||||
float Renderer::MaterialStyleStroke::getHalfWidth() const
|
||||
{
|
||||
return width;
|
||||
return halfWidth;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
namespace Renderer
|
||||
{
|
||||
enum class MaterialStrokeType { kPlain, kLinearGradient, kRadialGradient};
|
||||
enum class MaterialStrokeType { kPlain = 0, kRadialGradient = 1, kLinearGradient = 2 };
|
||||
|
||||
class MaterialStroke
|
||||
{
|
||||
|
@ -17,6 +17,7 @@ namespace Renderer
|
|||
{
|
||||
public:
|
||||
StrokePlain(QColor color, float metallic, float roughness);
|
||||
StrokePlain(const Material& material);
|
||||
virtual MaterialStrokeType type() const override;
|
||||
virtual std::vector<GLfloat> encoded() const override;
|
||||
virtual bool operator==(const MaterialStroke&) const override;
|
||||
|
@ -27,12 +28,13 @@ namespace Renderer
|
|||
class StrokeRadialGradient : public MaterialStroke
|
||||
{
|
||||
public:
|
||||
StrokeRadialGradient(QColor color, float metallic, float roughness);
|
||||
StrokeRadialGradient(const std::map<float, Material>& materialMap, bool gradual);
|
||||
virtual MaterialStrokeType type() const override;
|
||||
virtual std::vector<GLfloat> encoded() 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 };
|
||||
|
@ -41,13 +43,13 @@ namespace Renderer
|
|||
class MaterialStyleStroke : public MaterialStyle
|
||||
{
|
||||
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 std::vector<GLfloat> encoded() const override;
|
||||
virtual bool operator==(const MaterialStyle&) const override;
|
||||
float getWidth() const;
|
||||
float getHalfWidth() const;
|
||||
protected:
|
||||
float width;
|
||||
float halfWidth;
|
||||
StrokeType strokeType;
|
||||
StrokeEndType endType;
|
||||
std::shared_ptr<MaterialStroke> materialStroke;
|
||||
|
|
|
@ -43,7 +43,7 @@ void Renderer::Painting::addElement(ElementWithTransform elementWithTransform)
|
|||
{
|
||||
qDebug() << "Build LineTree-------------------------------------------------------------------------------------------------------";
|
||||
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;
|
||||
std::vector<BvhTreeData> bvhLeaves = lineTree.getPointLineAndBvhTree(elementBuffer.pointBuffer, elementBuffer.lineBuffer);
|
||||
BvhTree bvhTree;
|
||||
|
|
|
@ -20,7 +20,7 @@ Renderer::ElementRenderer::ElementRenderer(QOpenGLWidget* glWidget)
|
|||
void Renderer::ElementRenderer::initialize()
|
||||
{
|
||||
initializeOpenGLFunctions();
|
||||
shader = std::make_shared<QOpenGLShaderProgram>();
|
||||
shader = std::make_unique<QOpenGLShaderProgram>();
|
||||
if (!shader->addShaderFromSourceFile(QOpenGLShader::Compute, ":/Shaders/element.comp"))
|
||||
qDebug() << "ERROR: " << shader->log();
|
||||
if (!shader->link())
|
||||
|
@ -37,30 +37,25 @@ std::vector<glm::vec2> generatePathBuffer(const QPainterPath& path)
|
|||
switch (element.type)
|
||||
{
|
||||
case QPainterPath::MoveToElement:
|
||||
qDebug() << "MoveToElement";
|
||||
pathBuffer.push_back(glm::vec2(std::numeric_limits<float>::infinity()));
|
||||
pathBuffer.push_back(glm::vec2(element.x, element.y));
|
||||
break;
|
||||
case QPainterPath::LineToElement:
|
||||
qDebug() << "LineToElement";
|
||||
{
|
||||
glm::vec2 end = glm::vec2(element.x, element.y);
|
||||
glm::vec2 mid = (pathBuffer.back() + end) / 2.f;
|
||||
pathBuffer.push_back(mid);
|
||||
pathBuffer.push_back(mid);
|
||||
pathBuffer.push_back(end);
|
||||
}
|
||||
{
|
||||
glm::vec2 end = glm::vec2(element.x, element.y);
|
||||
glm::vec2 mid = (pathBuffer.back() + end) / 2.f;
|
||||
pathBuffer.push_back(mid);
|
||||
pathBuffer.push_back(mid);
|
||||
pathBuffer.push_back(end);
|
||||
break;
|
||||
}
|
||||
case QPainterPath::CurveToElement:
|
||||
qDebug() << "CurveToElement";
|
||||
pathBuffer.push_back(glm::vec2(element.x, element.y));
|
||||
break;
|
||||
case QPainterPath::CurveToDataElement:
|
||||
qDebug() << "CurveToDataElement";
|
||||
pathBuffer.push_back(glm::vec2(element.x, element.y));
|
||||
break;
|
||||
}
|
||||
qDebug() << element;
|
||||
}
|
||||
return pathBuffer;
|
||||
}
|
||||
|
@ -95,11 +90,8 @@ QRectF calcBoundingRect(const QPainterPath& path, const std::vector<BaseStyle>&
|
|||
BaseTransform transform(originTransform.appliedTransformStyle(*baseStyle.transform));
|
||||
if (baseStyle.material->type() == MaterialStyleType::kStroke)
|
||||
{
|
||||
float halfWidth = std::static_pointer_cast<MaterialStyleStroke>(baseStyle.material)->getWidth() / 2;
|
||||
transform.bound.x -= halfWidth;
|
||||
transform.bound.y -= halfWidth;
|
||||
transform.bound.z += halfWidth;
|
||||
transform.bound.w += halfWidth;
|
||||
float halfWidth = std::static_pointer_cast<MaterialStyleStroke>(baseStyle.material)->getHalfWidth();
|
||||
transform.bound += glm::vec4(glm::vec2(-halfWidth), glm::vec2(halfWidth));
|
||||
}
|
||||
glm::vec2 points[] = {
|
||||
glm::vec2(transform.bound.x, transform.bound.y),
|
||||
|
|
|
@ -28,7 +28,7 @@ namespace Renderer
|
|||
std::pair<QImage, QPointF> drawElement(const QPainterPath& path, const ElementStyle& style, float pixelRatio, bool releaseContext = true);
|
||||
protected:
|
||||
QOpenGLWidget* glWidget;
|
||||
std::shared_ptr<QOpenGLShaderProgram> shader;
|
||||
std::unique_ptr<QOpenGLShaderProgram> shader;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
10
README.md
10
README.md
|
@ -19,15 +19,9 @@
|
|||
|
||||
### 场景渲染(Renderer)
|
||||
|
||||
采用 PBR (金属度-粗糙度) 材质模型,场景中存在一个方向光,可拖动滑动条调整光源方向观察材质效果。
|
||||
|
||||
已实现BVH加速结构的建立
|
||||
|
||||
已实现单图元的拆分,即划分网格并生成快捷段和缠绕增量
|
||||
采用 PBR (金属度-粗糙度) 材质模型,场景中存在一个方向光,可拖动滑动条调整光源方向观察材质效果
|
||||
|
||||
已实现由图元数据建立完整彩绘编码
|
||||
|
||||
已实现线的单侧描边
|
||||
|
||||
待完善图元样式的编解码
|
||||
已实现面的纯色样式,线的纯色、径向渐变/分层、单侧等样式
|
||||
|
||||
|
|
|
@ -2,25 +2,81 @@
|
|||
#include <QGuiApplication>
|
||||
#include <QtWidgets/QApplication>
|
||||
#include "ElementRendererTest.h"
|
||||
#include "Renderer/Painting/ElementStyle.h"
|
||||
|
||||
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||
using namespace Renderer;
|
||||
|
||||
namespace UnitTest
|
||||
{
|
||||
TEST_CLASS(ElementRendererTest)
|
||||
{
|
||||
public:
|
||||
TEST_METHOD(TestMethod1)
|
||||
{
|
||||
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||
QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
|
||||
char arg[] = "";
|
||||
char* argv[] = { arg };
|
||||
int argc = 1;
|
||||
QApplication a(argc, argv);
|
||||
TestGLWidget w;
|
||||
w.show();
|
||||
a.exec();
|
||||
}
|
||||
};
|
||||
TEST_CLASS(ElementRendererTest)
|
||||
{
|
||||
public:
|
||||
TEST_METHOD(TestStrokePlain)
|
||||
{
|
||||
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);
|
||||
Renderer::ElementStyleStrokeDemo style(2);
|
||||
TestGLWidget w(style);
|
||||
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();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -9,28 +9,36 @@
|
|||
|
||||
namespace UnitTest
|
||||
{
|
||||
class TestGLWidget : public QOpenGLWidget, protected QOpenGLFunctions
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
Renderer::ElementRenderer renderer;
|
||||
public:
|
||||
TestGLWidget(QWidget* parent = nullptr) : QOpenGLWidget(parent), renderer(this) {};
|
||||
void initializeGL() override
|
||||
{
|
||||
initializeOpenGLFunctions();
|
||||
renderer.initialize();
|
||||
};
|
||||
void paintGL() override
|
||||
{
|
||||
glClearColor(1.0, 1.0, 1.0, 1.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
QPainterPath path;
|
||||
QQuickSvgParser::parsePathDataFast("M100,100C-.5,100,0,100.5,0,0L40,.07C40,59.5,39.5,60,100,60Z", path);
|
||||
auto [img, pos] = renderer.drawElement(path, Renderer::ElementStyleStrokeDemo(2), 1, false);
|
||||
QPainter painter(this);
|
||||
painter.drawImage(pos, img);
|
||||
};
|
||||
void resizeGL(int w, int h) override {};
|
||||
};
|
||||
class TestGLWidget : public QOpenGLWidget, protected QOpenGLFunctions
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
Renderer::ElementRenderer renderer;
|
||||
Renderer::ElementStyle& style;
|
||||
public:
|
||||
TestGLWidget(Renderer::ElementStyle& style, QWidget* parent = nullptr)
|
||||
: QOpenGLWidget(parent), renderer(this), style(style) {};
|
||||
void initializeGL() override
|
||||
{
|
||||
initializeOpenGLFunctions();
|
||||
renderer.initialize();
|
||||
};
|
||||
void paintGL() override
|
||||
{
|
||||
glClearColor(1.0, 1.0, 1.0, 1.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
QPainterPath path;
|
||||
QQuickSvgParser::parsePathDataFast("M100,100C-.5,100,0,100.5,0,0L40,.07C40,59.5,39.5,60,100,60Z", path);
|
||||
/*QTransform transform;
|
||||
transform.scale(10, 10);
|
||||
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 {};
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue