Archived
1
Fork 0

Add actual material editing

This commit is contained in:
Joshua Goins 2018-12-25 08:32:38 -05:00
parent c110ee96a3
commit bcd5609b9b
15 changed files with 246 additions and 11 deletions

View file

@ -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
View file

@ -0,0 +1,4 @@
{
"color": "1,1,1",
"albedoTexture": ""
}

View file

@ -24,7 +24,7 @@
{
"type": "Mesh",
"path": "sphere.obj",
"material": "test.material"
"material": "basic.material"
}
]
},

View file

@ -1,3 +1,4 @@
{
"color": "1,1,1",
"albedoTexture": "tile.jpg"
}

View file

@ -4,6 +4,7 @@
#include <glm/glm.hpp>
struct MaterialAsset {
glm::vec3 color = glm::vec3(1);
std::string albedoTexturePath;
VkImage albedoImage = nullptr;

View file

@ -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;

View file

@ -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);
}

View file

@ -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(

View file

@ -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);

View file

@ -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);
}

View file

@ -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_,

View file

@ -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)

View 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;
};

View 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);
}

View file

@ -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);
}