Compare commits
2 Commits
2af2464745
...
e8ba774370
Author | SHA1 | Date |
---|---|---|
wuyize | e8ba774370 | |
wuyize | 994c711e34 |
|
@ -134,6 +134,7 @@
|
||||||
<ClCompile Include="src\Renderer\Painting\Painting.cpp" />
|
<ClCompile Include="src\Renderer\Painting\Painting.cpp" />
|
||||||
<ClCompile Include="src\Renderer\Painting\PaintingHelper.cpp" />
|
<ClCompile Include="src\Renderer\Painting\PaintingHelper.cpp" />
|
||||||
<ClCompile Include="src\Renderer\PaintingMesh.cpp" />
|
<ClCompile Include="src\Renderer\PaintingMesh.cpp" />
|
||||||
|
<ClCompile Include="src\Renderer\Preview\ElementRenderer.cpp" />
|
||||||
<ClCompile Include="src\Renderer\RendererGLWidget.cpp" />
|
<ClCompile Include="src\Renderer\RendererGLWidget.cpp" />
|
||||||
<ClCompile Include="src\Renderer\RendererWidget.cpp" />
|
<ClCompile Include="src\Renderer\RendererWidget.cpp" />
|
||||||
<ClCompile Include="src\Renderer\Painting\ShortCutTree.cpp" />
|
<ClCompile Include="src\Renderer\Painting\ShortCutTree.cpp" />
|
||||||
|
@ -153,6 +154,7 @@
|
||||||
<None Include="lightstyle.qss" />
|
<None Include="lightstyle.qss" />
|
||||||
<None Include="Shaders\depth_init.comp" />
|
<None Include="Shaders\depth_init.comp" />
|
||||||
<None Include="Shaders\depth_mipmap.comp" />
|
<None Include="Shaders\depth_mipmap.comp" />
|
||||||
|
<None Include="Shaders\element.comp" />
|
||||||
<None Include="Shaders\final.frag" />
|
<None Include="Shaders\final.frag" />
|
||||||
<None Include="Shaders\final.vert" />
|
<None Include="Shaders\final.vert" />
|
||||||
<None Include="Shaders\model.frag" />
|
<None Include="Shaders\model.frag" />
|
||||||
|
@ -160,7 +162,9 @@
|
||||||
<None Include="Shaders\model_shadow.frag" />
|
<None Include="Shaders\model_shadow.frag" />
|
||||||
<None Include="Shaders\model_shadow.geom" />
|
<None Include="Shaders\model_shadow.geom" />
|
||||||
<None Include="Shaders\model_shadow.vert" />
|
<None Include="Shaders\model_shadow.vert" />
|
||||||
<None Include="Shaders\painting.comp" />
|
<None Include="Shaders\painting.comp">
|
||||||
|
<FileType>Document</FileType>
|
||||||
|
</None>
|
||||||
<None Include="Shaders\painting.frag" />
|
<None Include="Shaders\painting.frag" />
|
||||||
<None Include="Shaders\painting.vert" />
|
<None Include="Shaders\painting.vert" />
|
||||||
<None Include="Shaders\shader.frag" />
|
<None Include="Shaders\shader.frag" />
|
||||||
|
@ -190,6 +194,7 @@
|
||||||
<ClInclude Include="src\Renderer\Painting\LineTree.h" />
|
<ClInclude Include="src\Renderer\Painting\LineTree.h" />
|
||||||
<ClInclude Include="src\Renderer\Painting\MaterialStyleStroke.h" />
|
<ClInclude Include="src\Renderer\Painting\MaterialStyleStroke.h" />
|
||||||
<ClInclude Include="src\Renderer\Painting\Painting.h" />
|
<ClInclude Include="src\Renderer\Painting\Painting.h" />
|
||||||
|
<ClInclude Include="src\Renderer\Preview\ElementRenderer.h" />
|
||||||
<ClInclude Include="src\SvgParser.h" />
|
<ClInclude Include="src\SvgParser.h" />
|
||||||
<QtMoc Include="src\TitleWidget.h" />
|
<QtMoc Include="src\TitleWidget.h" />
|
||||||
<QtMoc Include="src\IconWidget.h" />
|
<QtMoc Include="src\IconWidget.h" />
|
||||||
|
|
|
@ -59,6 +59,12 @@
|
||||||
<Filter Include="Source Files\Editor\util">
|
<Filter Include="Source Files\Editor\util">
|
||||||
<UniqueIdentifier>{96f98afe-4250-44cb-a505-682a1d5932c3}</UniqueIdentifier>
|
<UniqueIdentifier>{96f98afe-4250-44cb-a505-682a1d5932c3}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
<Filter Include="Source Files\Renderer\Preview">
|
||||||
|
<UniqueIdentifier>{2a8e109f-7791-46ad-8c86-fe22a651cbe7}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Header Files\Renderer\Preview">
|
||||||
|
<UniqueIdentifier>{7ead1a66-586a-4584-ae80-9e7a4e667364}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<QtUic Include="MainWindow.ui">
|
<QtUic Include="MainWindow.ui">
|
||||||
|
@ -195,6 +201,9 @@
|
||||||
<ClCompile Include="src\Editor\util\PainterPathUtil.cpp">
|
<ClCompile Include="src\Editor\util\PainterPathUtil.cpp">
|
||||||
<Filter>Source Files\Editor\util</Filter>
|
<Filter>Source Files\Editor\util</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Renderer\Preview\ElementRenderer.cpp">
|
||||||
|
<Filter>Source Files\Renderer\Preview</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<QtMoc Include="src\Renderer\RendererGLWidget.h">
|
<QtMoc Include="src\Renderer\RendererGLWidget.h">
|
||||||
|
@ -287,6 +296,9 @@
|
||||||
<Filter>Resource Files</Filter>
|
<Filter>Resource Files</Filter>
|
||||||
</None>
|
</None>
|
||||||
<None Include="..\data.json" />
|
<None Include="..\data.json" />
|
||||||
|
<None Include="Shaders\element.comp">
|
||||||
|
<Filter>Resource Files\Shaders</Filter>
|
||||||
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<QtUic Include="EditorWidget.ui">
|
<QtUic Include="EditorWidget.ui">
|
||||||
|
@ -392,6 +404,11 @@
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="src\Editor\util\PainterPathUtil.h">
|
<ClInclude Include="src\Editor\util\PainterPathUtil.h">
|
||||||
<Filter>Header Files\Editor\util</Filter>
|
<Filter>Header Files\Editor\util</Filter>
|
||||||
|
<ClInclude Include="src\Renderer\Painting\MaterialStyleStroke.h">
|
||||||
|
<Filter>Header Files\Renderer\Painting</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Renderer\Preview\ElementRenderer.h">
|
||||||
|
<Filter>Header Files\Renderer\Preview</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
<file>images/icon_window_restore.png</file>
|
<file>images/icon_window_restore.png</file>
|
||||||
<file>darkstyle.qss</file>
|
<file>darkstyle.qss</file>
|
||||||
<file>lightstyle.qss</file>
|
<file>lightstyle.qss</file>
|
||||||
|
<file>Shaders/element.comp</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
<qresource prefix="/qt/etc">
|
<qresource prefix="/qt/etc">
|
||||||
<file>qt.conf</file>
|
<file>qt.conf</file>
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,5 +1,5 @@
|
||||||
#include "GraphicElement.h"
|
#include "GraphicElement.h"
|
||||||
#include <util/SvgFileLoader.h>
|
#include "util/SvgFileLoader.h"
|
||||||
using namespace std;
|
using namespace std;
|
||||||
QPainterPath SimpleElement::getPaintObject() const
|
QPainterPath SimpleElement::getPaintObject() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -1 +1,16 @@
|
||||||
#include "Element.h"
|
#include "Element.h"
|
||||||
|
|
||||||
|
void Renderer::ElementTransform::applyTransformStyle(const TransformStyle& t)
|
||||||
|
{
|
||||||
|
center += t.translation;
|
||||||
|
size *= t.scale;
|
||||||
|
rotation += t.rotation;
|
||||||
|
flip ^= t.flip;
|
||||||
|
}
|
||||||
|
|
||||||
|
Renderer::ElementTransform Renderer::ElementTransform::appliedTransformStyle(const TransformStyle& t) const
|
||||||
|
{
|
||||||
|
ElementTransform result = *this;
|
||||||
|
result.applyTransformStyle(t);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
|
@ -21,5 +21,8 @@ namespace Renderer
|
||||||
float rotation; /// ½Ç¶ÈÖÆ
|
float rotation; /// ½Ç¶ÈÖÆ
|
||||||
glm::bvec2 flip;
|
glm::bvec2 flip;
|
||||||
GLuint zIndex;
|
GLuint zIndex;
|
||||||
|
|
||||||
|
void applyTransformStyle(const TransformStyle& t);
|
||||||
|
ElementTransform appliedTransformStyle(const TransformStyle& t) const;
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -79,10 +79,7 @@ void Renderer::Painting::addElement(const Element& element, const ElementTransfo
|
||||||
{
|
{
|
||||||
auto& style = it->second[i];
|
auto& style = it->second[i];
|
||||||
ElementTransform trans = transform;
|
ElementTransform trans = transform;
|
||||||
trans.center += style.transform->translation;
|
trans.applyTransformStyle(*style.transform);
|
||||||
trans.size *= style.transform->scale;
|
|
||||||
trans.rotation += style.transform->rotation;
|
|
||||||
trans.flip ^= style.transform->flip;
|
|
||||||
trans.zIndex = trans.zIndex * 10 + i;
|
trans.zIndex = trans.zIndex * 10 + i;
|
||||||
addElement(ElementWithTransform{ BaseElement{element.contour, style.material}, BaseTransform(trans) });
|
addElement(ElementWithTransform{ BaseElement{element.contour, style.material}, BaseTransform(trans) });
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,160 @@
|
||||||
|
#include "ElementRenderer.h"
|
||||||
|
#include <QOpenGLFramebufferObject>
|
||||||
|
#include <QOpenGLPaintDevice>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QSurface>
|
||||||
|
#include <QPainterPath>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <limits>
|
||||||
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
#include "../Painting/Element.h"
|
||||||
|
#include "../Painting/Painting.h"
|
||||||
|
#include "../Painting/MaterialStyleStroke.h"
|
||||||
|
using namespace Renderer;
|
||||||
|
|
||||||
|
Renderer::ElementRenderer::ElementRenderer(QOpenGLWidget* glWidget)
|
||||||
|
: glWidget(glWidget)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::ElementRenderer::initialize()
|
||||||
|
{
|
||||||
|
initializeOpenGLFunctions();
|
||||||
|
shader = std::make_shared<QOpenGLShaderProgram>();
|
||||||
|
if (!shader->addShaderFromSourceFile(QOpenGLShader::Compute, ":/Shaders/element.comp"))
|
||||||
|
qDebug() << "ERROR: " << shader->log();
|
||||||
|
if (!shader->link())
|
||||||
|
qDebug() << "ERROR: " << shader->log();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<glm::vec2> generatePathBuffer(const QPainterPath& path)
|
||||||
|
{
|
||||||
|
std::vector<glm::vec2> pathBuffer;
|
||||||
|
for (int i = 0; i < path.elementCount(); i++)
|
||||||
|
{
|
||||||
|
QPainterPath::Element element = path.elementAt(i);
|
||||||
|
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);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<GLfloat> generateStyleBuffer(const std::vector<BaseStyle>& styles)
|
||||||
|
{
|
||||||
|
std::vector<GLfloat> styleBuffer;
|
||||||
|
for (auto& style : styles)
|
||||||
|
{
|
||||||
|
styleBuffer.push_back(style.transform->translation.x);
|
||||||
|
styleBuffer.push_back(style.transform->translation.y);
|
||||||
|
styleBuffer.push_back(style.transform->scale.x);
|
||||||
|
styleBuffer.push_back(style.transform->scale.y);
|
||||||
|
styleBuffer.push_back(style.transform->rotation);
|
||||||
|
styleBuffer.push_back(glm::uintBitsToFloat(glm::packUnorm2x16(style.transform->flip)));
|
||||||
|
auto encoded = style.material->encoded();
|
||||||
|
styleBuffer.insert(styleBuffer.end(), encoded.begin(), encoded.end());
|
||||||
|
}
|
||||||
|
return styleBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF calcBoundingRect(const QPainterPath& path, const std::vector<BaseStyle>& styles)
|
||||||
|
{
|
||||||
|
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 };
|
||||||
|
|
||||||
|
glm::vec2 leftTop(std::numeric_limits<float>::max()), rightBottom(std::numeric_limits<float>::min());
|
||||||
|
|
||||||
|
for (auto& baseStyle : styles)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
glm::vec2 points[] = {
|
||||||
|
glm::vec2(transform.bound.x, transform.bound.y),
|
||||||
|
glm::vec2(transform.bound.x, transform.bound.w),
|
||||||
|
glm::vec2(transform.bound.z, transform.bound.w),
|
||||||
|
glm::vec2(transform.bound.z, transform.bound.y)
|
||||||
|
};
|
||||||
|
for (auto& point : points)
|
||||||
|
{
|
||||||
|
float angle = glm::radians(baseStyle.transform->rotation);
|
||||||
|
point = glm::mat2{ {cos(angle), -sin(angle)}, {sin(angle), cos(angle)} } *point;
|
||||||
|
leftTop = glm::min(leftTop, point);
|
||||||
|
rightBottom = glm::max(rightBottom, point);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return QRectF(QPointF(leftTop.x, leftTop.y), QPointF(rightBottom.x, rightBottom.y));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<QImage, QPointF> Renderer::ElementRenderer::drawElement(const QPainterPath& path, const ElementStyle& style, float pixelRatio, bool releaseContext)
|
||||||
|
{
|
||||||
|
auto baseStyles = style.toBaseStyles();
|
||||||
|
QRectF bound = calcBoundingRect(path, baseStyles);
|
||||||
|
QPointF leftTop = bound.topLeft();
|
||||||
|
QSize size(ceil(bound.width() * pixelRatio), ceil(bound.height() * pixelRatio));
|
||||||
|
|
||||||
|
auto pathBuffer = generatePathBuffer(path);
|
||||||
|
auto styleBuffer = generateStyleBuffer(baseStyles);
|
||||||
|
|
||||||
|
if (releaseContext) glWidget->makeCurrent();
|
||||||
|
|
||||||
|
GLuint ssbo[2];
|
||||||
|
glGenBuffers(2, ssbo);
|
||||||
|
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo[0]);
|
||||||
|
glBufferData(GL_SHADER_STORAGE_BUFFER, pathBuffer.size() * sizeof(glm::vec2), pathBuffer.data(), GL_STATIC_READ);
|
||||||
|
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo[1]);
|
||||||
|
glBufferData(GL_SHADER_STORAGE_BUFFER, styleBuffer.size() * sizeof(GLfloat), styleBuffer.data(), GL_STATIC_READ);
|
||||||
|
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
|
||||||
|
|
||||||
|
auto fbo = QOpenGLFramebufferObject(size, QOpenGLFramebufferObject::NoAttachment, GL_TEXTURE_2D);
|
||||||
|
fbo.bind();
|
||||||
|
glClearColor(0, 0, 0, 0);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
fbo.release();
|
||||||
|
|
||||||
|
shader->bind();
|
||||||
|
shader->setUniformValue("pathSize", (GLint)pathBuffer.size());
|
||||||
|
shader->setUniformValue("styleSize", (GLint)styleBuffer.size());
|
||||||
|
shader->setUniformValue("leftTop", leftTop);
|
||||||
|
shader->setUniformValue("pixelRatio", pixelRatio);
|
||||||
|
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 10, ssbo[0]);
|
||||||
|
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 11, ssbo[1]);
|
||||||
|
glBindImageTexture(0, fbo.texture(), 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8);
|
||||||
|
glDispatchCompute(ceil(size.width() / 8.), ceil(size.height() / 8.), 1);
|
||||||
|
shader->release();
|
||||||
|
|
||||||
|
auto image = fbo.toImage(false);
|
||||||
|
glDeleteBuffers(2, ssbo);
|
||||||
|
if (releaseContext) glWidget->doneCurrent();
|
||||||
|
return { image, leftTop };
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
#pragma once
|
||||||
|
#include <QOpenGLWidget>
|
||||||
|
#include <QOpenGLFunctions_4_5_Core>
|
||||||
|
#include <QOPenGLShaderProgram>
|
||||||
|
#include "../Painting/ElementStyle.h"
|
||||||
|
|
||||||
|
namespace Renderer
|
||||||
|
{
|
||||||
|
class ElementRenderer : protected QOpenGLFunctions_4_5_Core
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ElementRenderer(QOpenGLWidget* glWidget);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 须在initializeGL函数中调用
|
||||||
|
*/
|
||||||
|
void initialize();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 将图元绘制到QImage
|
||||||
|
* @param path 图元几何数据
|
||||||
|
* @param style 图元样式
|
||||||
|
* @param pixelRatio path中的单位坐标对应的像素大小
|
||||||
|
* @param releaseContext 若在initializeGL, resizeGL或paintGL中调用须传入false
|
||||||
|
* @return QImage 绘制得到的位图
|
||||||
|
* @return QPointF 位图原点(左上角)在QPainterPath坐标系下的坐标
|
||||||
|
*/
|
||||||
|
std::pair<QImage, QPointF> drawElement(const QPainterPath& path, const ElementStyle& style, float pixelRatio, bool releaseContext = true);
|
||||||
|
protected:
|
||||||
|
QOpenGLWidget* glWidget;
|
||||||
|
std::shared_ptr<QOpenGLShaderProgram> shader;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue