Add actual material editing
This commit is contained in:
parent
c110ee96a3
commit
bcd5609b9b
15 changed files with 246 additions and 11 deletions
|
@ -126,6 +126,7 @@ add_data(Graph
|
|||
data/empty.world
|
||||
data/player.obj
|
||||
data/sphere.obj
|
||||
data/matpreview.world)
|
||||
data/matpreview.world
|
||||
data/basic.material)
|
||||
|
||||
add_subdirectory(tools)
|
||||
|
|
4
data/basic.material
Normal file
4
data/basic.material
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"color": "1,1,1",
|
||||
"albedoTexture": ""
|
||||
}
|
|
@ -24,7 +24,7 @@
|
|||
{
|
||||
"type": "Mesh",
|
||||
"path": "sphere.obj",
|
||||
"material": "test.material"
|
||||
"material": "basic.material"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
{
|
||||
"color": "1,1,1",
|
||||
"albedoTexture": "tile.jpg"
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <glm/glm.hpp>
|
||||
|
||||
struct MaterialAsset {
|
||||
glm::vec3 color = glm::vec3(1);
|
||||
std::string albedoTexturePath;
|
||||
|
||||
VkImage albedoImage = nullptr;
|
||||
|
|
|
@ -169,6 +169,7 @@ private:
|
|||
void createPresentationRenderPass();
|
||||
void createDescriptorPool();
|
||||
void createMaterialSetLayout();
|
||||
void createEmptyMaterialSet();
|
||||
|
||||
GraphicsConfig config_;
|
||||
|
||||
|
@ -202,6 +203,13 @@ private:
|
|||
|
||||
VkDescriptorSetLayout materialSetLayout_ = nullptr;
|
||||
|
||||
VkImage emptyImage_ = nullptr;
|
||||
VkDeviceMemory emptyMemory_ = nullptr;
|
||||
VkImageView emptyImageView_ = nullptr;
|
||||
VkSampler emptySampler_ = nullptr;
|
||||
|
||||
VkDescriptorSet emptyMaterialSet_ = nullptr;
|
||||
|
||||
WorldPass* worldPass_ = nullptr;
|
||||
PostPass* postPass_ = nullptr;
|
||||
DoFPass* dofPass_ = nullptr;
|
||||
|
|
|
@ -7,6 +7,11 @@ layout(location = 3) in vec2 inUV;
|
|||
|
||||
layout(location = 0) out vec4 outColor;
|
||||
|
||||
layout(push_constant) uniform PushConstants {
|
||||
mat4 m;
|
||||
vec3 c;
|
||||
} pushConstants;
|
||||
|
||||
struct Light {
|
||||
vec4 position, color;
|
||||
};
|
||||
|
@ -85,5 +90,9 @@ void main() {
|
|||
diffuse += add;
|
||||
}
|
||||
|
||||
outColor = vec4(vec3(0.1) + diffuse * texture(albedoSampler, inUV).rgb, 1.0);
|
||||
vec3 matColor = pushConstants.c;
|
||||
if(textureSize(albedoSampler, 0).x > 1)
|
||||
matColor *= texture(albedoSampler, inUV).rgb;
|
||||
|
||||
outColor = vec4((matColor * vec3(0.1)) + diffuse * matColor, 1.0);
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ layout(set = 0, binding = 0) uniform SceneInfo {
|
|||
|
||||
layout(push_constant) uniform PushConstants {
|
||||
mat4 m;
|
||||
vec3 c;
|
||||
} pushConstants;
|
||||
|
||||
const mat4 biasMat = mat4(
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "mesh.h"
|
||||
#include "material.h"
|
||||
#include "renderer.h"
|
||||
#include "stringutils.h"
|
||||
|
||||
MeshAsset* AssetManager::loadMesh(const std::string& path) {
|
||||
std::string fixedPath = "data/" + path;
|
||||
|
@ -57,6 +58,14 @@ MaterialAsset* AssetManager::loadMaterial(const std::string& path) {
|
|||
file >> json;
|
||||
|
||||
MaterialAsset* material = new MaterialAsset();
|
||||
|
||||
auto tokens = tokenize(json["color"]);
|
||||
|
||||
material->color[0] = atof(tokens[0].c_str());
|
||||
material->color[1] = atof(tokens[1].c_str());
|
||||
material->color[2] = atof(tokens[2].c_str());
|
||||
|
||||
if(json["albedoTexture"].get<std::string>().length() > 0)
|
||||
material->albedoTexturePath = "data/" + json["albedoTexture"].get<std::string>();
|
||||
|
||||
renderer->fillMaterialBuffers(material);
|
||||
|
|
|
@ -27,6 +27,7 @@ Renderer::Renderer(GraphicsConfig config) : config_(config) {
|
|||
createPresentationRenderPass();
|
||||
createDescriptorPool();
|
||||
createMaterialSetLayout();
|
||||
createEmptyMaterialSet();
|
||||
|
||||
shadowPass_ = new ShadowPass(*this);
|
||||
worldPass_ = new WorldPass(*this);
|
||||
|
@ -1233,8 +1234,11 @@ void Renderer::fillMeshBuffers(MeshAsset* mesh) {
|
|||
void Renderer::fillMaterialBuffers(MaterialAsset* material) {
|
||||
int width = 0, height = 0, channels = 0;
|
||||
stbi_uc* pixels = stbi_load(material->albedoTexturePath.c_str(), &width, &height, &channels, STBI_rgb_alpha);
|
||||
if(pixels == nullptr)
|
||||
return; // haha what
|
||||
if(pixels == nullptr) {
|
||||
material->set = emptyMaterialSet_;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
VkImageCreateInfo imageCreateInfo = {};
|
||||
imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
||||
|
@ -1546,3 +1550,87 @@ void Renderer::createMaterialSetLayout() {
|
|||
|
||||
vkCreateDescriptorSetLayout(device_, &createInfo, nullptr, &materialSetLayout_);
|
||||
}
|
||||
|
||||
void Renderer::createEmptyMaterialSet() {
|
||||
VkImageCreateInfo imageCreateInfo = {};
|
||||
imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
||||
imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
|
||||
imageCreateInfo.extent.width = 1;
|
||||
imageCreateInfo.extent.height = 1;
|
||||
imageCreateInfo.extent.depth = 1;
|
||||
imageCreateInfo.mipLevels = 1;
|
||||
imageCreateInfo.arrayLayers = 1;
|
||||
imageCreateInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
|
||||
imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
imageCreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||
imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
|
||||
vkCreateImage(device_, &imageCreateInfo, nullptr, &emptyImage_);
|
||||
|
||||
VkMemoryRequirements memRequirements;
|
||||
vkGetImageMemoryRequirements(device_, emptyImage_, &memRequirements);
|
||||
|
||||
VkMemoryAllocateInfo allocInfo = {};
|
||||
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||
allocInfo.allocationSize = memRequirements.size;
|
||||
allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
|
||||
vkAllocateMemory(device_, &allocInfo, nullptr, &emptyMemory_);
|
||||
vkBindImageMemory(device_, emptyImage_, emptyMemory_, 0);
|
||||
|
||||
char img[4] = {0};
|
||||
|
||||
uploadImageData(
|
||||
emptyImage_,
|
||||
1,
|
||||
1,
|
||||
4,
|
||||
img
|
||||
);
|
||||
|
||||
VkImageViewCreateInfo createInfo = {};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||
createInfo.image = emptyImage_;
|
||||
createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
createInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
|
||||
createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
createInfo.subresourceRange.levelCount = 1;
|
||||
createInfo.subresourceRange.layerCount = 1;
|
||||
|
||||
vkCreateImageView(device_, &createInfo, nullptr, &emptyImageView_);
|
||||
|
||||
VkSamplerCreateInfo samplerInfo = {};
|
||||
samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
|
||||
samplerInfo.magFilter = VK_FILTER_LINEAR;
|
||||
samplerInfo.minFilter = VK_FILTER_LINEAR;
|
||||
samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
|
||||
samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
|
||||
samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
|
||||
samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
|
||||
samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
|
||||
|
||||
vkCreateSampler(device_, &samplerInfo, nullptr, &emptySampler_);
|
||||
|
||||
VkDescriptorSetAllocateInfo setAllocInfo = {};
|
||||
setAllocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
||||
setAllocInfo.descriptorPool = descriptorPool_;
|
||||
setAllocInfo.descriptorSetCount = 1;
|
||||
setAllocInfo.pSetLayouts = &materialSetLayout_;
|
||||
|
||||
vkAllocateDescriptorSets(device_, &setAllocInfo, &emptyMaterialSet_);
|
||||
|
||||
VkDescriptorImageInfo albedoImageInfo = {};
|
||||
albedoImageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
albedoImageInfo.imageView = emptyImageView_;
|
||||
albedoImageInfo.sampler = emptySampler_;
|
||||
|
||||
VkWriteDescriptorSet albedoDescriptorWrite = {};
|
||||
albedoDescriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
albedoDescriptorWrite.descriptorCount = 1;
|
||||
albedoDescriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
albedoDescriptorWrite.dstSet = emptyMaterialSet_;
|
||||
albedoDescriptorWrite.pImageInfo = &albedoImageInfo;
|
||||
|
||||
vkUpdateDescriptorSets(device_, 1, &albedoDescriptorWrite, 0, nullptr);
|
||||
}
|
||||
|
|
|
@ -79,7 +79,9 @@ void WorldPass::render(VkCommandBuffer commandBuffer, RenderCollection& collecti
|
|||
glm::mat4 m(1.0f);
|
||||
m = glm::translate(m, mesh.transform->position);
|
||||
|
||||
vkCmdPushConstants(commandBuffer, pipelineLayout_, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(glm::mat4), &m);
|
||||
vkCmdPushConstants(commandBuffer, pipelineLayout_, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(glm::mat4), &m);
|
||||
|
||||
vkCmdPushConstants(commandBuffer, pipelineLayout_, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(glm::mat4), sizeof(glm::vec3), &mesh.mesh->material->color);
|
||||
|
||||
VkDeviceSize offsets[] = {0};
|
||||
vkCmdBindVertexBuffers(commandBuffer, 0, 1, &mesh.mesh->mesh->vertexBuffer, offsets);
|
||||
|
@ -294,8 +296,8 @@ void WorldPass::createPipeline() {
|
|||
dynamicState.pDynamicStates = dynamicStates.data();
|
||||
|
||||
VkPushConstantRange mvpPushConstant = {};
|
||||
mvpPushConstant.size = sizeof(glm::mat4);
|
||||
mvpPushConstant.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
||||
mvpPushConstant.size = sizeof(glm::mat4) + sizeof(glm::vec3);
|
||||
mvpPushConstant.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
|
||||
const std::array<VkDescriptorSetLayout, 2> setLayouts = {
|
||||
setLayout_,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
set(INCLUDE_FILES
|
||||
include/renderwindow.h)
|
||||
include/renderwindow.h
|
||||
include/coloredit.h)
|
||||
|
||||
qt5_wrap_cpp(EDITOR_SRC ${INCLUDE_FILES})
|
||||
|
||||
|
@ -7,6 +8,7 @@ add_library(EditorCommon
|
|||
src/qt.cpp
|
||||
src/renderwindow.cpp
|
||||
src/editorstyle.cpp
|
||||
src/coloredit.cpp
|
||||
${EDITOR_SRC})
|
||||
target_include_directories(EditorCommon PUBLIC include)
|
||||
target_link_libraries(EditorCommon PRIVATE Engine Qt5::Widgets)
|
||||
|
|
17
tools/common/include/coloredit.h
Normal file
17
tools/common/include/coloredit.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
#include <QColorDialog>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
class ColorEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ColorEdit(glm::vec3& ref, QWidget* parent = nullptr);
|
||||
|
||||
signals:
|
||||
void onValueChanged();
|
||||
|
||||
private:
|
||||
glm::vec3& reference;
|
||||
};
|
64
tools/common/src/coloredit.cpp
Normal file
64
tools/common/src/coloredit.cpp
Normal file
|
@ -0,0 +1,64 @@
|
|||
#include "coloredit.h"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QPushButton>
|
||||
|
||||
QColor fromVec3(glm::vec3 vec) {
|
||||
int r = 0, g = 0, b = 0;
|
||||
|
||||
if(vec.x != 0)
|
||||
r = static_cast<int>(255.0f * vec.x);
|
||||
|
||||
if(vec.y != 0)
|
||||
g = static_cast<int>(255.0f * vec.y);
|
||||
|
||||
if(vec.z != 0)
|
||||
b = static_cast<int>(255.0f * vec.z);
|
||||
|
||||
return QColor::fromRgb(r, g, b);
|
||||
}
|
||||
|
||||
glm::vec3 fromQColor(QColor color) {
|
||||
glm::vec3 vec;
|
||||
|
||||
int r, g, b, a;
|
||||
color.getRgb(&r, &g, &b, &a);
|
||||
|
||||
vec.x = r / 255.0f;
|
||||
vec.y = g / 255.0f;
|
||||
vec.z = b / 255.0f;
|
||||
|
||||
return vec;
|
||||
}
|
||||
|
||||
ColorEdit::ColorEdit(glm::vec3& ref, QWidget* parent) : QWidget(parent), reference(ref) {
|
||||
QHBoxLayout* itemsLayout = new QHBoxLayout(this);
|
||||
|
||||
QPushButton* colorButton = new QPushButton();
|
||||
colorButton->setFlat(true);
|
||||
|
||||
QPalette pal = colorButton->palette();
|
||||
pal.setColor(QPalette::Button, fromVec3(reference));
|
||||
|
||||
colorButton->setAutoFillBackground(true);
|
||||
colorButton->setPalette(pal);
|
||||
colorButton->update();
|
||||
|
||||
connect(colorButton, &QPushButton::clicked, [=](bool) {
|
||||
QColor oldcolor = fromVec3(reference);
|
||||
|
||||
QColor newcolor = QColorDialog::getColor(oldcolor);
|
||||
|
||||
reference = fromQColor(newcolor);
|
||||
|
||||
QPalette newpal = colorButton->palette();
|
||||
newpal.setColor(QPalette::Button, newcolor);
|
||||
|
||||
colorButton->setPalette(newpal);
|
||||
colorButton->update();
|
||||
|
||||
emit onValueChanged();
|
||||
});
|
||||
|
||||
itemsLayout->addWidget(colorButton);
|
||||
}
|
|
@ -5,9 +5,16 @@
|
|||
#include <QMenu>
|
||||
#include <QAction>
|
||||
#include <QVulkanWindow>
|
||||
#include <QHBoxLayout>
|
||||
#include <QGridLayout>
|
||||
#include <QLabel>
|
||||
|
||||
#include "renderwindow.h"
|
||||
#include "renderer.h"
|
||||
#include "coloredit.h"
|
||||
#include "ecs.h"
|
||||
#include "worldmanager.h"
|
||||
#include "material.h"
|
||||
|
||||
MainWindow::MainWindow(Context& context) : context(context) {
|
||||
setWindowTitle("Material Editor");
|
||||
|
@ -56,6 +63,27 @@ MainWindow::MainWindow(Context& context) : context(context) {
|
|||
fileMenu->addAction(quitAction);
|
||||
}
|
||||
|
||||
QWidget* centralWidget = new QWidget();
|
||||
setCentralWidget(centralWidget);
|
||||
|
||||
QHBoxLayout* layout = new QHBoxLayout();
|
||||
centralWidget->setLayout(layout);
|
||||
|
||||
QGridLayout* attributesLayout = new QGridLayout();
|
||||
attributesLayout->setAlignment(Qt::AlignTop);
|
||||
attributesLayout->setSpacing(0);
|
||||
layout->addLayout(attributesLayout);
|
||||
|
||||
QLabel* label = new QLabel("Color");
|
||||
attributesLayout->addWidget(label, 0, 0);
|
||||
|
||||
auto meshComponents = ECS::getWorldComponents<MeshComponent>(worldManager.getCurrentWorld());
|
||||
|
||||
auto& [id, mesh] = meshComponents[0];
|
||||
|
||||
ColorEdit* colorEdit = new ColorEdit(mesh->material->color);
|
||||
attributesLayout->addWidget(colorEdit, 0, 1);
|
||||
|
||||
instance = new QVulkanInstance();
|
||||
instance->setVkInstance(context.renderer->getInstance());
|
||||
instance->create();
|
||||
|
@ -64,6 +92,6 @@ MainWindow::MainWindow(Context& context) : context(context) {
|
|||
window->setVulkanInstance(instance);
|
||||
|
||||
QWidget* wrapper = QWidget::createWindowContainer(window);
|
||||
setCentralWidget(wrapper);
|
||||
layout->addWidget(wrapper);
|
||||
}
|
||||
|
||||
|
|
Reference in a new issue