实现线的径向渐变\分层样式
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);
|
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++)
|
||||||
{
|
{
|
||||||
|
|
|
@ -898,40 +898,72 @@ 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)
|
||||||
|
//switch (2)
|
||||||
{
|
{
|
||||||
case 0:
|
/// Plain
|
||||||
{
|
case 0: {
|
||||||
elementColor = vec4(unpackUnorm4x8(floatBitsToUint(elementData[styleIndex+2])).rgb,1);
|
metallicRoughness = head.rg;
|
||||||
metallicRoughness = vec2(unpackUnorm4x8(floatBitsToUint(elementData[styleIndex+1])).rg);
|
elementColor = vec4(unpackUnorm4x8(floatBitsToUint(elementData[styleIndex+2])).rgb, 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 1:
|
/// 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++)
|
||||||
{
|
{
|
||||||
elementColor = vec4(mix(vec3(0), vec3(1), d), 1);
|
uint data = floatBitsToUint(elementData[styleIndex+2+i*2]);
|
||||||
metallicRoughness = vec2(0,0.8);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
case 2:
|
lastMetallicRoughness = currentMetallicRoughness;
|
||||||
{
|
lastColor = currentColor;
|
||||||
float levels[] = {0.25,0.5,0.75};
|
lastLevel = level;
|
||||||
vec3 colors[] = {vec3(1,0,0), vec3(0,1,0), vec3(0,0,1), vec3(1,1,0)};
|
}
|
||||||
|
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;
|
int i = 0;
|
||||||
while(i<3)
|
while (i < 3)
|
||||||
{
|
{
|
||||||
if(d<levels[i])
|
if (d < levels[i])
|
||||||
{
|
{
|
||||||
elementColor = vec4(colors[i], 1);
|
elementColor = vec4(colors[i], 1);
|
||||||
metallicRoughness = vec2(0,0.8);
|
metallicRoughness = vec2(0, 0.8);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
if(i==3)
|
if (i == 3)
|
||||||
{
|
{
|
||||||
elementColor = vec4(colors[i], 1);
|
elementColor = vec4(colors[i], 1);
|
||||||
metallicRoughness = vec2(0,0.8);
|
metallicRoughness = vec2(0, 0.8);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -392,12 +392,13 @@ 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;
|
||||||
|
|
|
@ -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))) };
|
||||||
}
|
}
|
|
@ -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;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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 };
|
||||||
|
@ -45,9 +47,9 @@ namespace Renderer
|
||||||
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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
10
README.md
10
README.md
|
@ -19,15 +19,9 @@
|
||||||
|
|
||||||
### 场景渲染(Renderer)
|
### 场景渲染(Renderer)
|
||||||
|
|
||||||
采用 PBR (金属度-粗糙度) 材质模型,场景中存在一个方向光,可拖动滑动条调整光源方向观察材质效果。
|
采用 PBR (金属度-粗糙度) 材质模型,场景中存在一个方向光,可拖动滑动条调整光源方向观察材质效果
|
||||||
|
|
||||||
已实现BVH加速结构的建立
|
|
||||||
|
|
||||||
已实现单图元的拆分,即划分网格并生成快捷段和缠绕增量
|
|
||||||
|
|
||||||
已实现由图元数据建立完整彩绘编码
|
已实现由图元数据建立完整彩绘编码
|
||||||
|
|
||||||
已实现线的单侧描边
|
已实现面的纯色样式,线的纯色、径向渐变/分层、单侧等样式
|
||||||
|
|
||||||
待完善图元样式的编解码
|
|
||||||
|
|
||||||
|
|
|
@ -2,23 +2,79 @@
|
||||||
#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);
|
||||||
|
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
||||||
QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
|
QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
|
||||||
char arg[] = "";
|
char* argv[] = { (char*)"" };
|
||||||
char* argv[] = { arg };
|
|
||||||
int argc = 1;
|
int argc = 1;
|
||||||
QApplication a(argc, argv);
|
QApplication a(argc, argv);
|
||||||
TestGLWidget w;
|
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();
|
w.show();
|
||||||
a.exec();
|
a.exec();
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,8 +14,10 @@ namespace UnitTest
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
private:
|
private:
|
||||||
Renderer::ElementRenderer renderer;
|
Renderer::ElementRenderer renderer;
|
||||||
|
Renderer::ElementStyle& style;
|
||||||
public:
|
public:
|
||||||
TestGLWidget(QWidget* parent = nullptr) : QOpenGLWidget(parent), renderer(this) {};
|
TestGLWidget(Renderer::ElementStyle& style, QWidget* parent = nullptr)
|
||||||
|
: QOpenGLWidget(parent), renderer(this), style(style) {};
|
||||||
void initializeGL() override
|
void initializeGL() override
|
||||||
{
|
{
|
||||||
initializeOpenGLFunctions();
|
initializeOpenGLFunctions();
|
||||||
|
@ -27,9 +29,15 @@ namespace UnitTest
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
QPainterPath path;
|
QPainterPath path;
|
||||||
QQuickSvgParser::parsePathDataFast("M100,100C-.5,100,0,100.5,0,0L40,.07C40,59.5,39.5,60,100,60Z", 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);
|
/*QTransform transform;
|
||||||
|
transform.scale(10, 10);
|
||||||
|
transform.map(path);*/
|
||||||
|
float pixelRatio = 30;
|
||||||
|
auto [img, pos] = renderer.drawElement(path, style, pixelRatio, false);
|
||||||
QPainter painter(this);
|
QPainter painter(this);
|
||||||
painter.drawImage(pos, img);
|
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 {};
|
void resizeGL(int w, int h) override {};
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue