Files
Seele/src/Engine/Material/Material.cpp
T

163 lines
5.7 KiB
C++
Raw Normal View History

2020-05-05 01:51:13 +02:00
#include "Material.h"
2020-06-02 11:46:18 +02:00
#include "Asset/AssetRegistry.h"
2020-08-11 21:23:20 +02:00
#include "Graphics/VertexShaderInput.h"
2020-09-19 14:36:50 +02:00
#include "BRDF.h"
2021-01-19 15:30:00 +01:00
#include "Window/WindowManager.h"
2020-05-05 01:51:13 +02:00
#include <nlohmann/json.hpp>
2020-06-02 11:46:18 +02:00
#include <sstream>
2020-08-11 22:38:19 +02:00
#include <iostream>
2020-05-05 01:51:13 +02:00
2020-08-11 21:23:20 +02:00
Gfx::ShaderMap Material::shaderMap;
std::mutex Material::shaderMapLock;
2020-05-05 01:51:13 +02:00
using namespace Seele;
using json = nlohmann::json;
Material::Material()
{
}
Material::Material(const std::string& directory, const std::string& name)
2020-06-02 11:46:18 +02:00
: MaterialAsset(directory, name)
2020-05-05 01:51:13 +02:00
{
}
2020-06-08 01:44:47 +02:00
Material::Material(const std::filesystem::path& fullPath)
2020-06-02 11:46:18 +02:00
: MaterialAsset(fullPath)
{
2020-05-05 01:51:13 +02:00
}
Material::~Material()
{
}
void Material::save()
{
}
void Material::load()
{
}
2020-06-02 11:46:18 +02:00
2020-05-05 01:51:13 +02:00
void Material::compile()
{
2020-10-03 11:00:10 +02:00
layout = WindowManager::getGraphics()->createDescriptorLayout();
2020-05-05 01:51:13 +02:00
auto& stream = getReadStream();
json j;
stream >> j;
2020-06-02 11:46:18 +02:00
materialName = j["name"].get<std::string>();
2020-10-03 11:00:10 +02:00
//Shader file needs to conform to the slang standard, which prohibits _
materialName.erase(std::remove(materialName.begin(), materialName.end(), '_'), materialName.end());
2020-09-19 14:36:50 +02:00
std::ofstream codeStream("./shaders/generated/"+materialName+".slang");
2020-06-02 11:46:18 +02:00
std::string profile = j["profile"].get<std::string>();
2020-09-19 14:36:50 +02:00
codeStream << "import VERTEX_INPUT_IMPORT;" << std::endl;
2020-06-02 11:46:18 +02:00
codeStream << "import LightEnv;" << std::endl;
codeStream << "import Material;" << std::endl;
codeStream << "import BRDF;" << std::endl;
2020-09-19 14:36:50 +02:00
codeStream << "import MaterialParameter;" << std::endl;
2020-05-05 01:51:13 +02:00
2020-06-02 11:46:18 +02:00
codeStream << "struct " << materialName << ": IMaterial {" << std::endl;
2020-10-03 11:00:10 +02:00
uint32 uniformBufferOffset = 0;
2021-01-19 15:30:00 +01:00
uint32 bindingCounter = 0; // Uniform buffers are always binding 0
uniformBinding = -1;
2020-06-02 11:46:18 +02:00
for(auto param : j["params"].items())
{
std::string type = param.value()["type"].get<std::string>();
auto default = param.value().find("default");
if(type.compare("float") == 0)
{
2020-10-03 11:00:10 +02:00
PFloatParameter p = new FloatParameter(param.key(), uniformBufferOffset, 0);
codeStream << "layout(offset = " << uniformBufferOffset << ")";
2021-01-19 15:30:00 +01:00
if(uniformBinding == -1)
{
layout->addDescriptorBinding(bindingCounter, Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
uniformBinding = bindingCounter++;
}
2020-10-03 11:00:10 +02:00
uniformBufferOffset += 4;
2020-06-02 11:46:18 +02:00
if(default != param.value().end())
{
2020-10-03 11:00:10 +02:00
p->data = std::stof(default.value().get<std::string>());
2020-06-02 11:46:18 +02:00
}
parameters.add(p);
}
else if(type.compare("float3") == 0)
{
2020-10-03 11:00:10 +02:00
PVectorParameter p = new VectorParameter(param.key(), uniformBufferOffset, 0);
codeStream << "layout(offset = " << uniformBufferOffset << ")";
2021-01-19 15:30:00 +01:00
if(uniformBinding == -1)
{
layout->addDescriptorBinding(bindingCounter, Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
uniformBinding = bindingCounter++;
}
2020-10-03 11:00:10 +02:00
uniformBufferOffset += 12;
2020-06-02 11:46:18 +02:00
if(default != param.value().end())
{
2020-10-03 11:00:10 +02:00
p->data = parseVector(default.value().get<std::string>().c_str());
2020-06-02 11:46:18 +02:00
}
parameters.add(p);
}
else if(type.compare("Texture2D") == 0)
{
2020-10-03 11:00:10 +02:00
PTextureParameter p = new TextureParameter(param.key(), 0, bindingCounter);
layout->addDescriptorBinding(bindingCounter++, Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
2020-06-02 11:46:18 +02:00
if(default != param.value().end())
{
2020-10-03 11:00:10 +02:00
p->data = AssetRegistry::findTexture(default.value().get<std::string>());
}
else
{
p->data = AssetRegistry::findTexture(""); // this will return placeholder texture
2020-06-02 11:46:18 +02:00
}
parameters.add(p);
}
else if(type.compare("SamplerState") == 0)
{
2020-10-03 11:00:10 +02:00
PSamplerParameter p = new SamplerParameter(param.key(), 0, bindingCounter);
layout->addDescriptorBinding(bindingCounter++, Gfx::SE_DESCRIPTOR_TYPE_SAMPLER);
SamplerCreateInfo createInfo;
p->data = WindowManager::getGraphics()->createSamplerState(createInfo);
2020-06-02 11:46:18 +02:00
parameters.add(p);
}
else
{
std::cout << "Error unsupported parameter type" << std::endl;
}
2020-09-19 14:36:50 +02:00
codeStream << type << " " << param.key() << ";\n";
2020-06-02 11:46:18 +02:00
}
2020-10-03 11:00:10 +02:00
uniformDataSize = uniformBufferOffset;
if(uniformDataSize != 0)
{
uniformData = new uint8[uniformDataSize];
UniformBufferCreateInfo uniformInitializer;
uniformInitializer.resourceData.data = uniformData;
uniformInitializer.resourceData.size = uniformDataSize;
uniformBuffer = WindowManager::getGraphics()->createUniformBuffer(uniformInitializer);
2020-10-03 11:00:10 +02:00
}
layout->create();
descriptorSet = layout->allocatedDescriptorSet();
updateDescriptorData();
2020-09-19 14:36:50 +02:00
BRDF* brdf = BRDF::getBRDFByName(profile);
brdf->generateMaterialCode(codeStream, j["code"]);
codeStream << "};";
codeStream.close();
2020-08-11 21:23:20 +02:00
}
2020-09-19 14:36:50 +02:00
const Gfx::ShaderCollection* Material::getShaders(Gfx::RenderPassType renderPass, VertexInputType* vertexInput) const
2020-08-11 21:23:20 +02:00
{
Gfx::ShaderPermutation permutation;
2020-10-03 11:00:10 +02:00
permutation.passType = renderPass;
2020-09-19 14:36:50 +02:00
std::string materialName = getFileName();
2020-08-11 21:23:20 +02:00
std::string vertexInputName = vertexInput->getName();
std::memcpy(permutation.materialName, materialName.c_str(), sizeof(permutation.materialName));
2020-10-03 11:00:10 +02:00
std::memcpy(permutation.vertexInputName, vertexInputName.c_str(), sizeof(permutation.vertexInputName));
2020-08-11 21:23:20 +02:00
return shaderMap.findShaders(Gfx::PermutationId(permutation));
}
2020-09-19 14:36:50 +02:00
Gfx::ShaderCollection& Material::createShaders(Gfx::PGraphics graphics, Gfx::RenderPassType renderPass, VertexInputType* vertexInput)
2020-08-11 21:23:20 +02:00
{
std::lock_guard lock(shaderMapLock);
return shaderMap.createShaders(graphics, renderPass, this, vertexInput, false);
}