diff --git a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj
index d1a31e2..3480a6f 100644
--- a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj
+++ b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj
@@ -162,6 +162,7 @@
+
@@ -253,6 +254,7 @@
+
diff --git a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters
index 70a7d95..1da6526 100644
--- a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters
+++ b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters
@@ -282,6 +282,9 @@
Source Files
+
+ Source Files\Renderer\Preview
+
@@ -570,6 +573,9 @@
Header Files
+
+ Header Files\Renderer\Preview
+
diff --git a/ArchitectureColoredPainting/src/Editor/EditorWidget.cpp b/ArchitectureColoredPainting/src/Editor/EditorWidget.cpp
index f20efa6..629ae62 100644
--- a/ArchitectureColoredPainting/src/Editor/EditorWidget.cpp
+++ b/ArchitectureColoredPainting/src/Editor/EditorWidget.cpp
@@ -69,10 +69,12 @@ void EditorWidget::initFileMenu()
auto* actionOpen = new QAction(QStringLiteral("打开"), fileMenuButton);
auto* actionSave = new QAction(QStringLiteral("保存"), fileMenuButton);
auto* actionSaveAs = new QAction(QStringLiteral("另存为"), fileMenuButton);
+ auto* actionExport = new QAction(QStringLiteral("导出"), fileMenuButton);
fileMenuButton->addMenuAction(actionCreate);
fileMenuButton->addMenuAction(actionOpen);
fileMenuButton->addMenuAction(actionSave);
fileMenuButton->addMenuAction(actionSaveAs);
+ fileMenuButton->addMenuAction(actionExport);
connect(actionCreate, &QAction::triggered, [this] {
static int count = 0;
const int prevCount = this->tabWidget->count();
@@ -108,6 +110,13 @@ void EditorWidget::initFileMenu()
item->saveAs(fileName);
}
});
+ connect(actionExport, &QAction::triggered, this, [this] {
+ auto* item = dynamic_cast(this->tabWidget->currentWidget());
+ if (item != nullptr)
+ {
+ item->exportAs();
+ }
+ });
}
void EditorWidget::initProjectMenu()
diff --git a/ArchitectureColoredPainting/src/Editor/EditorWidgetItem.cpp b/ArchitectureColoredPainting/src/Editor/EditorWidgetItem.cpp
index d6f4f60..2d5af08 100644
--- a/ArchitectureColoredPainting/src/Editor/EditorWidgetItem.cpp
+++ b/ArchitectureColoredPainting/src/Editor/EditorWidgetItem.cpp
@@ -1,126 +1,131 @@
#include "EditorWidgetItem.h"
#include "EditorWidget.h"
#include "DataManager/ProjectDataManager.h"
+#include "../Renderer/Preview/PaintingRenderer.h"
+#include "util/PaintingUtil.h"
#include
#include
#include
#include
+#include
+#include
+#include
-EditorWidgetItem::EditorWidgetItem(QString filePath,QWidget *parent) : QWidget(parent)
+EditorWidgetItem::EditorWidgetItem(QString filePath, QWidget* parent) : QWidget(parent)
{
- QImage x;
- this->parent = parent;
- displayLayer = nullptr;
- displayElement = nullptr;
- ui.setupUi(this);
- previewWindow = ui.Preview;
- treeWidget = ui.LayerTree;
- this->filePath = filePath;
- elementInfoDisplayWidget = ui.ElementDisplay;
- layerInfoDisplayWidget = ui.LayerDisplay;
- elementInfoDisplayWidget->enableEdit();
- qDebug() << layerInfoDisplayWidget;
- qDebug() << elementInfoDisplayWidget;
- auto centralRefresh = [this]() {
- layerInfoDisplayWidget->refresh();
- treeWidget->refresh();
+ QImage x;
+ this->parent = parent;
+ displayLayer = nullptr;
+ displayElement = nullptr;
+ ui.setupUi(this);
+ previewWindow = ui.Preview;
+ treeWidget = ui.LayerTree;
+ this->filePath = filePath;
+ elementInfoDisplayWidget = ui.ElementDisplay;
+ layerInfoDisplayWidget = ui.LayerDisplay;
+ elementInfoDisplayWidget->enableEdit();
+ qDebug() << layerInfoDisplayWidget;
+ qDebug() << elementInfoDisplayWidget;
+ auto centralRefresh = [this]() {
+ layerInfoDisplayWidget->refresh();
+ treeWidget->refresh();
previewWindow->refresh();
elementInfoDisplayWidget->lazyRefresh();
- };
- connect(previewWindow, &PreviewWindow::triggerCentralRefresh, centralRefresh);
+ };
+ connect(previewWindow, &PreviewWindow::triggerCentralRefresh, centralRefresh);
connect(layerInfoDisplayWidget, &InfoDisplayWidget::triggerCentralRefresh, centralRefresh);
connect(elementInfoDisplayWidget, &ElementPoolWidget::triggerCentralRefresh, centralRefresh);
connect(treeWidget, &LayerTreeWidget::triggerCentralRefresh, centralRefresh);
- connect(previewWindow, &PreviewWindow::refreshElementPreviewByIndex, elementInfoDisplayWidget, &ElementPoolWidget::refreshPictureByIndex);
+ connect(previewWindow, &PreviewWindow::refreshElementPreviewByIndex, elementInfoDisplayWidget, &ElementPoolWidget::refreshPictureByIndex);
connect(treeWidget, &LayerTreeWidget::displayLayerChange, previewWindow, &PreviewWindow::currentLayerChanged);
//connect(treeWidget, &LayerTreeWidget::requireRefreshElementWidget, elementInfoDisplayWidget, &ElementPoolWidget::refresh);
// connect(layerInfoDisplayWidget, &InfoDisplayWidget::requireRefreshElementWidget, elementInfoDisplayWidget, &ElementPoolWidget::refresh);
- connect(treeWidget, &LayerTreeWidget::displayLayerChange, this, &EditorWidgetItem::onLayerChange);
- // connect(layerInfoDisplayWidget, &InfoDisplayWidget::requireRefreshPreview, this,
- // &EditorWidgetItem::triggerRefreshPreview);
- // connect(treeWidget, &LayerTreeWidget::requireRefreshPreview, this,
- // &EditorWidgetItem::triggerRefreshPreview);
- //connect(layerInfoDisplayWidget, &InfoDisplayWidget::requireSelfRefresh, layerInfoDisplayWidget, &InfoDisplayWidget::triggerSelfRefresh);
- // connect(elementInfoDisplayWidget, &ElementPoolWidget::refreshLayerTree, treeWidget, &LayerTreeWidget::refresh);
- // &EditorWidget::triggerRefreshPreview);
- // test
- QFile settingFile;
- //settingFile.setFileName("../data.json");
+ connect(treeWidget, &LayerTreeWidget::displayLayerChange, this, &EditorWidgetItem::onLayerChange);
+ // connect(layerInfoDisplayWidget, &InfoDisplayWidget::requireRefreshPreview, this,
+ // &EditorWidgetItem::triggerRefreshPreview);
+ // connect(treeWidget, &LayerTreeWidget::requireRefreshPreview, this,
+ // &EditorWidgetItem::triggerRefreshPreview);
+ //connect(layerInfoDisplayWidget, &InfoDisplayWidget::requireSelfRefresh, layerInfoDisplayWidget, &InfoDisplayWidget::triggerSelfRefresh);
+ // connect(elementInfoDisplayWidget, &ElementPoolWidget::refreshLayerTree, treeWidget, &LayerTreeWidget::refresh);
+ // &EditorWidget::triggerRefreshPreview);
+ // test
+ QFile settingFile;
+ //settingFile.setFileName("../data.json");
settingFile.setFileName(filePath);
- settingFile.open(QFile::ReadOnly);
- QByteArray setting = settingFile.readAll().trimmed();
- QJsonParseError jError;
- QJsonDocument jsonDoc(QJsonDocument::fromJson(setting, &jError));
- qDebug() << jsonDoc.object().value("height").toDouble();
- qDebug() << jError.errorString();
- ProjectData data;
- data.fileHome = QFileInfo(filePath).absolutePath();
- data.width = jsonDoc.object().value("height").toInt();
- data.height = jsonDoc.object().value("width").toInt();
- data.zoomX = 1.0;
- data.zoomY = 1.0;
- data.item = this;
- ProjectDataManager::Instance()->addProjectData(data);
- // end test
- QJsonObject source = jsonDoc.object();
+ settingFile.open(QFile::ReadOnly);
+ QByteArray setting = settingFile.readAll().trimmed();
+ QJsonParseError jError;
+ QJsonDocument jsonDoc(QJsonDocument::fromJson(setting, &jError));
+ qDebug() << jsonDoc.object().value("height").toDouble();
+ qDebug() << jError.errorString();
+ ProjectData data;
+ data.fileHome = QFileInfo(filePath).absolutePath();
+ data.width = jsonDoc.object().value("height").toInt();
+ data.height = jsonDoc.object().value("width").toInt();
+ data.zoomX = 1.0;
+ data.zoomY = 1.0;
+ data.item = this;
+ ProjectDataManager::Instance()->addProjectData(data);
+ // end test
+ QJsonObject source = jsonDoc.object();
elementManager = new ElementManager(source, QFileInfo(filePath).absolutePath());
- layerManager = new LayerManager(source, elementManager);
- elementInfoDisplayWidget->setElementManager(elementManager);
- treeWidget->elementManager = elementManager;
- //qDebug() << layerManager->toJson();
- previewWindow->initialize(layerManager,QSize(jsonDoc.object().value("width").toInt(),jsonDoc.object().value("height").toInt()));
- if (source.contains("metallic"))
- previewWindow->canvasMetallic = jsonDoc.object().value("metallic").toDouble();
- else
- previewWindow->canvasMetallic = 0;
- if (source.contains("roughness"))
- previewWindow->canvasRoughness = jsonDoc.object().value("roughness").toDouble();
- else
- previewWindow->canvasRoughness = 0.5;
-
-
- if (layerManager->getRoot() != nullptr)
- {
- treeWidget->root = layerManager->getRoot();
+ layerManager = new LayerManager(source, elementManager);
+ elementInfoDisplayWidget->setElementManager(elementManager);
+ treeWidget->elementManager = elementManager;
+ //qDebug() << layerManager->toJson();
+ previewWindow->initialize(layerManager, QSize(jsonDoc.object().value("width").toInt(), jsonDoc.object().value("height").toInt()));
+ if (source.contains("metallic"))
+ previewWindow->canvasMetallic = jsonDoc.object().value("metallic").toDouble();
+ else
+ previewWindow->canvasMetallic = 0;
+ if (source.contains("roughness"))
+ previewWindow->canvasRoughness = jsonDoc.object().value("roughness").toDouble();
+ else
+ previewWindow->canvasRoughness = 0.5;
+
+
+ if (layerManager->getRoot() != nullptr)
+ {
+ treeWidget->root = layerManager->getRoot();
treeWidget->refresh();
treeWidget->addTopLevelItem(treeWidget->root->getQTreeItem());
- }
- this->backgroundColor = source.value("background-color").toVariant().value();
+ }
+ this->backgroundColor = source.value("background-color").toVariant().value();
this->projectName = source.value("project-name").toString();
- qDebug() << this->backgroundColor;
- qDebug() << this->projectName;
+ qDebug() << this->backgroundColor;
+ qDebug() << this->projectName;
elementInfoDisplayWidget->refresh();
- QTimer::singleShot(300, this, [this, centralRefresh]() {
- handleBackgroundColorChange(this->backgroundColor);
- handleProjectNameChange(this->projectName);
- centralRefresh();
- });
+ QTimer::singleShot(300, this, [this, centralRefresh]() {
+ handleBackgroundColorChange(this->backgroundColor);
+ handleProjectNameChange(this->projectName);
+ centralRefresh();
+ });
}
EditorWidgetItem::~EditorWidgetItem()
{
}
-void EditorWidgetItem::paintEvent(QPaintEvent *event)
+void EditorWidgetItem::paintEvent(QPaintEvent* event)
{
- QPainter painter(this);
+ QPainter painter(this);
- // 设置画刷的颜色为灰色,并填充整个窗口区域
- painter.setBrush(Qt::gray);
- painter.drawRect(this->rect());
+ // 设置画刷的颜色为灰色,并填充整个窗口区域
+ painter.setBrush(Qt::gray);
+ painter.drawRect(this->rect());
}
-void EditorWidgetItem::onLayerChange(LayerWrapper *layer)
+void EditorWidgetItem::onLayerChange(LayerWrapper* layer)
{
- displayLayer = layer;
- // TODO : notify InfoDisplayWidget and update
- ui.LayerDisplay->setLayer(layer);
- this->update();
+ displayLayer = layer;
+ // TODO : notify InfoDisplayWidget and update
+ ui.LayerDisplay->setLayer(layer);
+ this->update();
}
void EditorWidgetItem::triggerRefreshPreview()
{
- previewWindow->update();
+ previewWindow->update();
}
void EditorWidgetItem::save() const
@@ -132,36 +137,103 @@ void EditorWidgetItem::saveAs(QString filePath) const
{
saveImpl(filePath);
QString srcHome = QFileInfo(this->filePath).absolutePath();
- if (!QDir(QFileInfo(filePath).absolutePath() + "/svg").exists())
- {
+ if (!QDir(QFileInfo(filePath).absolutePath() + "/svg").exists())
+ {
QDir().mkdir(QFileInfo(filePath).absolutePath() + "/svg");
- }
- for (auto& ele : elementManager->elements)
- {
- auto e = dynamic_cast(ele);
- if (e != nullptr)
- {
- QString fileName = e->jsonSource["data"].toObject()["include"].toString();
- QString src = srcHome + fileName;
+ }
+ for (auto& ele : elementManager->elements)
+ {
+ auto e = dynamic_cast(ele);
+ if (e != nullptr)
+ {
+ QString fileName = e->jsonSource["data"].toObject()["include"].toString();
+ QString src = srcHome + fileName;
QString dst = QFileInfo(filePath).absolutePath() + fileName;
QFile::copy(src, dst);
- }
- }
-
+ }
+ }
+
+}
+
+void EditorWidgetItem::exportAs()
+{
+ const QString fileName = QFileDialog::getSaveFileName(this, QStringLiteral("导出"), QFileInfo(filePath).dir().filePath(projectName), QStringLiteral("PNG图像(*.png)"));
+ if (fileName.isEmpty())
+ return;
+
+ QtMaterialTextField widthTextField;
+ QtMaterialTextField heightTextField;
+ QtMaterialTextField supersampleTextField;
+ widthTextField.setLabel(QStringLiteral("宽度(像素)"));
+ heightTextField.setLabel(QStringLiteral("高度(像素)"));
+ supersampleTextField.setLabel(QStringLiteral("超采样(倍)"));
+
+ class FixedIntValidator : public QIntValidator
+ {
+ public:
+ explicit FixedIntValidator(QObject* parent = nullptr) : QIntValidator(parent) {}
+ explicit FixedIntValidator(int bottom, int top, QObject* parent = nullptr) : QIntValidator(
+ bottom, top, parent) {}
+
+ void fixup(QString& s) const override
+ {
+ s = QString::number(bottom());
+ }
+ };
+
+ widthTextField.setValidator(new FixedIntValidator(1, std::numeric_limits::max(), &widthTextField));
+ heightTextField.setValidator(new FixedIntValidator(1, std::numeric_limits::max(), &heightTextField));
+ supersampleTextField.setValidator(new QDoubleValidator(0.125, 128, 3));
+ widthTextField.setText(QString::number(previewWindow->referSize.width()));
+ heightTextField.setText(QString::number(previewWindow->referSize.height()));
+ supersampleTextField.setText(QString::number(2));
+
+ connect(&widthTextField, &QLineEdit::textChanged, [&](const QString& string) {
+ heightTextField.setText(QString::number(previewWindow->referSize.height() * string.toInt() / (double)previewWindow->referSize.width()));
+ });
+ connect(&heightTextField, &QLineEdit::textChanged, [&](const QString& string) {
+ widthTextField.setText(QString::number(previewWindow->referSize.width() * string.toInt() / (double)previewWindow->referSize.height()));
+ });
+
+ QDialog* dialog = new QDialog(this);
+ dialog->setMinimumSize(QSize(200, 200));
+ dialog->setWindowTitle(QStringLiteral("导出"));
+ dialog->setWindowFlag(Qt::WindowContextHelpButtonHint, false);
+ auto layout = new QVBoxLayout(dialog);
+ dialog->setLayout(layout);
+ layout->addWidget(&widthTextField);
+ layout->addWidget(&heightTextField);
+ layout->addWidget(&supersampleTextField);
+ auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, dialog);
+ buttonBox->button(QDialogButtonBox::Ok)->setText(QStringLiteral("确定"));
+ buttonBox->button(QDialogButtonBox::Cancel)->setText(QStringLiteral("取消"));
+ layout->addWidget(buttonBox);
+ connect(buttonBox, &QDialogButtonBox::accepted, [&] {
+ dialog->setCursor(Qt::WaitCursor);
+ auto painting = PaintingUtil::transfromToPainting(this->filePath);
+ Renderer::PaintingRenderer::instance().exportPainting(fileName, painting, QSize(widthTextField.text().toInt(), heightTextField.text().toInt()), supersampleTextField.text().toFloat());
+ dialog->unsetCursor();
+ dialog->accept();
+ });
+ connect(buttonBox, &QDialogButtonBox::rejected, [&] {
+ dialog->close();
+ });
+
+ dialog->exec();
}
void EditorWidgetItem::saveImpl(QString filePath) const
{
QJsonObject source1 = layerManager->toJson();
QJsonObject source2 = elementManager->toJson();
- QJsonObject json;
+ QJsonObject json;
json.insert("roughness", previewWindow->canvasRoughness);
json.insert("metallic", previewWindow->canvasMetallic);
json.insert("width", previewWindow->referSize.width());
json.insert("height", previewWindow->referSize.height());
json.insert("root-layer", source1.value("root-layer"));
- json.insert("elements", source2.value("elements"));
- json.insert("project-name", this->projectName);
+ json.insert("elements", source2.value("elements"));
+ json.insert("project-name", this->projectName);
json.insert("background-color", QJsonValue::fromVariant(QVariant::fromValue(this->backgroundColor)));
QJsonDocument doc(json);
QFile file(filePath);
@@ -179,17 +251,17 @@ void EditorWidgetItem::handleBackgroundColorChange(const QColor& color)
void EditorWidgetItem::handleProjectNameChange(const QString& name)
{
this->projectName = name;
- auto parent = dynamic_cast(this->parent);
- qDebug() << name << " " << parent<<" "<(this->parent);
+ qDebug() << name << " " << parent << " " << this;
+ if (parent != nullptr)
+ {
parent->renameTab(this, name);
- }
+ }
}
void EditorWidgetItem::handleCanvasSizeChange(const QSize& size)
{
- previewWindow->resize(size);
+ previewWindow->resize(size);
}
void EditorWidgetItem::handleCanvasRoughnessChange(const float& roughness)
@@ -204,7 +276,7 @@ void EditorWidgetItem::handleCanvasMetallicChange(const float& metallic)
QSize EditorWidgetItem::getCanvasReferSize() const
{
- return previewWindow->referSize;
+ return previewWindow->referSize;
}
float EditorWidgetItem::getCanvasRoughness() const
diff --git a/ArchitectureColoredPainting/src/Editor/EditorWidgetItem.h b/ArchitectureColoredPainting/src/Editor/EditorWidgetItem.h
index 92097dc..b95c0df 100644
--- a/ArchitectureColoredPainting/src/Editor/EditorWidgetItem.h
+++ b/ArchitectureColoredPainting/src/Editor/EditorWidgetItem.h
@@ -32,7 +32,7 @@ class EditorWidgetItem : public QWidget
GraphicElement *displayElement;
QWidget* parent;
void saveImpl(QString filePath)const;
-public:
+ public:
// PROJECT INFO
QString filePath;
QString projectName;
@@ -43,7 +43,8 @@ public:
~EditorWidgetItem();
void paintEvent(QPaintEvent *event) override;
void save() const;
- void saveAs(QString filePath)const;
+ void saveAs(QString filePath) const;
+ void exportAs();
void handleBackgroundColorChange(const QColor& color);
void handleProjectNameChange(const QString& name);
void handleCanvasSizeChange(const QSize& size);
diff --git a/ArchitectureColoredPainting/src/Renderer/Preview/PaintingRenderer.cpp b/ArchitectureColoredPainting/src/Renderer/Preview/PaintingRenderer.cpp
new file mode 100644
index 0000000..3b90fea
--- /dev/null
+++ b/ArchitectureColoredPainting/src/Renderer/Preview/PaintingRenderer.cpp
@@ -0,0 +1,82 @@
+#include "PaintingRenderer.h"
+#include
+
+Renderer::PaintingRenderer& Renderer::PaintingRenderer::instance()
+{
+ static PaintingRenderer renderer;
+ return renderer;
+}
+
+bool Renderer::PaintingRenderer::exportPainting(const QString& path, Painting& painting, const QSize& size, float supersampling)
+{
+ std::unique_lock lock(drawMutex);
+ draw.wait(lock, [&] {return drawFinished; });
+ drawFinished = false;
+ this->path = path;
+ this->painting = &painting;
+ this->size = size;
+ this->supersampling = supersampling;
+ needDraw = true;
+ draw.notify_all();
+ draw.wait(lock, [&] {return drawFinished; });
+ return true;
+}
+
+Renderer::PaintingRenderer::PaintingRenderer()
+{
+ surface.create();
+ thread = std::jthread([&](std::stop_token stop) {
+ std::stop_callback cb(stop, [&] {
+ draw.notify_all();
+ });
+
+ QOpenGLContext context;
+ context.create();
+ context.makeCurrent(&surface);
+
+ auto gl = context.versionFunctions();
+ shader = std::make_unique();
+ if (!shader->addShaderFromSourceFile(QOpenGLShader::Compute, ":/Shaders/painting.comp"))
+ qDebug() << "ERROR: " << shader->log();
+ if (!shader->link())
+ qDebug() << "ERROR: " << shader->log();
+
+ initialized = true;
+
+ while (!stop.stop_requested())
+ {
+ std::unique_lock lock(drawMutex);
+ draw.wait(lock, [&] {return needDraw || stop.stop_requested(); });
+ if (needDraw)
+ {
+ needDraw = false;
+ painting->generateBuffers(gl);
+ QSize renderSize = size * supersampling;
+ auto fbo = QOpenGLFramebufferObject(renderSize, QOpenGLFramebufferObject::NoAttachment, GL_TEXTURE_2D);
+ fbo.bind();
+ gl->glClearColor(0, 0, 0, 0);
+ gl->glClear(GL_COLOR_BUFFER_BIT);
+ fbo.release();
+
+ shader->bind();
+ for (int i = 0; i < 6; i++)
+ gl->glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, painting->buffers[i]);
+ gl->glBindBufferBase(GL_UNIFORM_BUFFER, 1, painting->buffers[6]);
+ gl->glUniform2i(gl->glGetUniformLocation(shader->programId(), "pixelOffset"), 0, 0);
+ gl->glBindImageTexture(0, fbo.texture(), 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8);
+ gl->glBindImageTexture(1, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
+ gl->glDispatchCompute((GLuint)ceil(renderSize.width() / 8.), (GLuint)ceil(renderSize.height() / 8.), 1);
+ shader->release();
+ auto image = fbo.toImage(true);
+ image.scaled(size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation).save(path, "PNG", 100);
+ gl->glDeleteBuffers(7, painting->buffers.data());
+ drawFinished = true;
+ }
+ draw.notify_all();
+ }
+ context.doneCurrent();
+ });
+
+ while (!initialized)
+ std::this_thread::yield();
+}
diff --git a/ArchitectureColoredPainting/src/Renderer/Preview/PaintingRenderer.h b/ArchitectureColoredPainting/src/Renderer/Preview/PaintingRenderer.h
new file mode 100644
index 0000000..3c92cfc
--- /dev/null
+++ b/ArchitectureColoredPainting/src/Renderer/Preview/PaintingRenderer.h
@@ -0,0 +1,35 @@
+#pragma once
+#include
+#include
+#include
+#include "../Painting/Painting.h"
+#include
+
+namespace Renderer
+{
+ class PaintingRenderer
+ {
+ public:
+ static PaintingRenderer& instance();
+ bool exportPainting(const QString& path, Painting& painting, const QSize& size, float supersampling = 2.f);
+ protected:
+ std::unique_ptr shader;
+ std::jthread thread;
+ QOffscreenSurface surface;
+ QOpenGLContext context;
+ std::atomic initialized = false;
+ bool drawFinished = true;
+ bool needDraw = false;
+ std::condition_variable draw;
+ std::mutex drawMutex;
+ Painting* painting;
+ QString path;
+ QSize size;
+ float supersampling;
+ std::pair result;
+
+ PaintingRenderer();
+ };
+
+}
+
diff --git a/ArchitectureColoredPainting/src/Renderer/VirtualTextureManager.cpp b/ArchitectureColoredPainting/src/Renderer/VirtualTextureManager.cpp
index c59249f..ff2b6ba 100644
--- a/ArchitectureColoredPainting/src/Renderer/VirtualTextureManager.cpp
+++ b/ArchitectureColoredPainting/src/Renderer/VirtualTextureManager.cpp
@@ -211,7 +211,7 @@ void Renderer::VirtualTextureManager::pageCommitmentById(const glm::u16vec2& pag
program.bind();
for (int i = 0; i < 6; i++)
gl->BindBufferBase(GL_SHADER_STORAGE_BUFFER, i, painting.buffers[i]);
- glMain->BindBufferBase(GL_UNIFORM_BUFFER, 1, painting.buffers[6]);
+ gl->BindBufferBase(GL_UNIFORM_BUFFER, 1, painting.buffers[6]);
gl->Uniform2i(gl->GetUniformLocation(program.programId(), "pixelOffset"), static_cast(pageSize) * page.x, static_cast(pageSize) * page.y);
gl->BindImageTexture(0, painting.baseColor, level, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8);
gl->BindImageTexture(1, painting.metallicRoughness, level, GL_FALSE, 0, GL_READ_WRITE, GL_RG8);
diff --git a/UnitTest/EPaperTest.cpp b/UnitTest/EPaperTest.cpp
new file mode 100644
index 0000000..4030a52
--- /dev/null
+++ b/UnitTest/EPaperTest.cpp
@@ -0,0 +1,36 @@
+#include "EPaperTest.h"
+#include "CppUnitTest.h"
+#include
+#include
+#include
+
+using namespace Microsoft::VisualStudio::CppUnitTestFramework;
+
+namespace UnitTest
+{
+ TEST_CLASS(EPaperTest)
+ {
+ private:
+ char* argv[1];
+ int argc;
+ public:
+ EPaperTest() :argv{ (char*)"" }, argc(1) {}
+
+ TEST_METHOD(TestBothSidesRound)
+ {
+ QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+ QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
+ QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
+ QApplication a(argc, argv);
+ QLabel w;
+ w.setFixedSize({296,128});
+ QImage image(QSize(296, 128), QImage::Format_RGB32);
+ image.fill(Qt::red);
+ w.setPixmap(QPixmap::fromImage(image));
+ w.show();
+ a.exec();
+ }
+ };
+
+
+}
diff --git a/UnitTest/EPaperTest.h b/UnitTest/EPaperTest.h
new file mode 100644
index 0000000..6f70f09
--- /dev/null
+++ b/UnitTest/EPaperTest.h
@@ -0,0 +1 @@
+#pragma once
diff --git a/UnitTest/PaintingTest.cpp b/UnitTest/PaintingTest.cpp
index 29ae33a..3a23819 100644
--- a/UnitTest/PaintingTest.cpp
+++ b/UnitTest/PaintingTest.cpp
@@ -3,6 +3,8 @@
#include
#include "Renderer/Painting/Painting.h"
#include "Renderer/Painting/MaterialStyleStroke.h"
+#include "Renderer/Preview/PaintingRenderer.h"
+#include
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace Renderer;
@@ -17,35 +19,11 @@ namespace UnitTest
public:
PaintingTest() :argv{ (char*)"" }, argc(1) {}
- TEST_METHOD_INITIALIZE(initialize)
- {
- QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
- QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
- QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
- }
TEST_METHOD(TestBothSidesRound)
{
- QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
- QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
- QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
- QApplication a(argc, argv);
- class StyleStrokeRadialGradient : public Renderer::ElementStyle
- {
- virtual std::vector toBaseStyles() const override
- {
- std::map materialMap = {
- {0.20, Material{QColor(255,255,255)}},
- {0.60, Material{QColor(165,176,207)}},
- {1.00, Material{QColor(58,64,151)}}
- };
- return { BaseStyle(std::make_shared(),
- std::make_shared(60, StrokeType::kBothSides, StrokeEndType::kRound,
- std::make_shared(materialMap, false))) };
- }
- } style;
- TestPaintingGLWidget w(style);
- w.show();
- a.exec();
+ QApplication app(argc, argv);
+ auto painting = PaintingUtil::transfromToPainting("E:\\3D Objects\\dougong\\paintings\\Test1\\Test1.json");
+ PaintingRenderer::instance().exportPainting("E:\\3D Objects\\dougong\\paintings\\Test1\\Test1.png", painting, QSize(5910, 10940));
}
};
diff --git a/UnitTest/UnitTest.vcxproj b/UnitTest/UnitTest.vcxproj
index ee2464b..078bcf5 100644
--- a/UnitTest/UnitTest.vcxproj
+++ b/UnitTest/UnitTest.vcxproj
@@ -111,6 +111,7 @@
input
%(Filename).moc
+
input
@@ -136,6 +137,9 @@
+
+
+
diff --git a/UnitTest/UnitTest.vcxproj.filters b/UnitTest/UnitTest.vcxproj.filters
index df5ed3f..5e548ff 100644
--- a/UnitTest/UnitTest.vcxproj.filters
+++ b/UnitTest/UnitTest.vcxproj.filters
@@ -54,5 +54,13 @@
Source Files
+
+ Source Files
+
+
+
+
+ Header Files
+
\ No newline at end of file