Files
Seele/src/Editor/Asset/MaterialLoader.cpp
T

249 lines
8.7 KiB
C++
Raw Normal View History

2020-06-02 11:46:18 +02:00
#include "MaterialLoader.h"
#include "Graphics/Graphics.h"
2023-02-24 22:09:07 +01:00
#include "Asset/MaterialAsset.h"
#include "Asset/AssetRegistry.h"
2023-01-21 18:43:21 +01:00
#include "Material/Material.h"
#include "Window/WindowManager.h"
#include "Material/ShaderExpression.h"
2023-02-24 22:09:07 +01:00
#include "Asset/TextureAsset.h"
2023-01-21 18:43:21 +01:00
#include <nlohmann/json.hpp>
2020-06-02 11:46:18 +02:00
using namespace Seele;
2023-01-21 18:43:21 +01:00
using json = nlohmann::json;
2020-06-02 11:46:18 +02:00
MaterialLoader::MaterialLoader(Gfx::PGraphics graphics)
2020-09-19 14:36:50 +02:00
: graphics(graphics)
2020-06-02 11:46:18 +02:00
{
2023-02-24 22:09:07 +01:00
PMaterialAsset placeholderAsset = new MaterialAsset();
import(MaterialImportArgs{
2023-02-01 22:13:04 +01:00
.filePath = std::filesystem::absolute("./shaders/Placeholder.asset"),
.importPath = "",
2023-02-24 22:09:07 +01:00
}, placeholderAsset);
AssetRegistry::get().assetRoot->materials[""] = placeholderAsset;
2020-06-02 11:46:18 +02:00
}
MaterialLoader::~MaterialLoader()
{
}
2023-02-01 22:13:04 +01:00
void MaterialLoader::importAsset(MaterialImportArgs args)
2020-06-02 11:46:18 +02:00
{
2023-02-01 22:13:04 +01:00
std::filesystem::path assetPath = args.filePath.filename();
2021-11-11 20:12:50 +01:00
assetPath.replace_extension("asset");
2023-02-13 14:56:13 +01:00
PMaterialAsset asset = new MaterialAsset(args.importPath, assetPath.stem().string());
2021-11-11 20:12:50 +01:00
asset->setStatus(Asset::Status::Loading);
2023-02-13 14:56:13 +01:00
AssetRegistry::get().registerMaterial(asset);
2023-02-01 22:13:04 +01:00
import(args, asset);
2021-11-11 20:12:50 +01:00
}
2023-02-01 22:13:04 +01:00
void MaterialLoader::import(MaterialImportArgs args, PMaterialAsset asset)
2021-11-11 20:12:50 +01:00
{
2023-07-31 21:43:20 +02:00
auto jsonstream = std::ifstream(args.filePath.c_str());
2023-01-21 18:43:21 +01:00
json j;
2023-07-31 21:43:20 +02:00
jsonstream >> j;
2023-01-21 18:43:21 +01:00
std::string materialName = j["name"].get<std::string>() + "Material";
2023-01-29 18:58:59 +01:00
Gfx::PDescriptorLayout layout = graphics->createDescriptorLayout(materialName + "Layout");
2023-01-21 18:43:21 +01:00
//Shader file needs to conform to the slang standard, which prohibits _
materialName.erase(std::remove(materialName.begin(), materialName.end(), '_'), materialName.end());
materialName.erase(std::remove(materialName.begin(), materialName.end(), '.'), materialName.end());
2023-02-24 22:09:07 +01:00
2023-01-21 18:43:21 +01:00
uint32 uniformBufferOffset = 0;
uint32 bindingCounter = 0; // Uniform buffers are always binding 0
uint32 uniformBinding = -1;
2023-02-24 22:09:07 +01:00
Map<int32, PShaderExpression> expressions;
int32 key = 0;
int32 auxKey = -1;
Map<std::string, PShaderParameter> parameters;
2023-01-21 18:43:21 +01:00
for(auto param : j["params"].items())
{
std::string type = param.value()["type"].get<std::string>();
auto defaultValue = param.value().find("default");
// TODO: ALIGNMENT RULES
if(type.compare("float") == 0)
{
PFloatParameter p = new FloatParameter(param.key(), uniformBufferOffset, 0);
2023-02-24 22:09:07 +01:00
p->key = auxKey;
2023-01-21 18:43:21 +01:00
if(uniformBinding == -1)
{
layout->addDescriptorBinding(bindingCounter, Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
uniformBinding = bindingCounter++;
}
uniformBufferOffset += 4;
if(defaultValue != param.value().end())
{
p->data = std::stof(defaultValue.value().get<std::string>());
}
2023-02-24 22:09:07 +01:00
expressions[auxKey--] = p;
parameters[param.key()] = p;
2023-01-21 18:43:21 +01:00
}
// TODO: ALIGNMENT RULES
else if(type.compare("float3") == 0)
{
PVectorParameter p = new VectorParameter(param.key(), uniformBufferOffset, 0);
2023-02-24 22:09:07 +01:00
p->key = auxKey;
2023-01-21 18:43:21 +01:00
if(uniformBinding == -1)
{
layout->addDescriptorBinding(bindingCounter, Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
uniformBinding = bindingCounter++;
}
uniformBufferOffset += 12;
if(defaultValue != param.value().end())
{
p->data = parseVector(defaultValue.value().get<std::string>().c_str());
}
2023-02-24 22:09:07 +01:00
expressions[auxKey--] = p;
parameters[param.key()] = p;
2023-01-21 18:43:21 +01:00
}
else if(type.compare("Texture2D") == 0)
{
PTextureParameter p = new TextureParameter(param.key(), 0, bindingCounter);
2023-02-24 22:09:07 +01:00
p->key = auxKey;
2023-01-21 18:43:21 +01:00
layout->addDescriptorBinding(bindingCounter++, Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
if(defaultValue != param.value().end())
{
std::string defaultString = defaultValue.value().get<std::string>();
p->data = AssetRegistry::findTexture(defaultString);
}
if(p->data == nullptr)
{
p->data = AssetRegistry::findTexture(""); // this will return placeholder texture
}
2023-02-24 22:09:07 +01:00
expressions[auxKey--] = p;
parameters[param.key()] = p;
2023-01-21 18:43:21 +01:00
}
else if(type.compare("SamplerState") == 0)
{
PSamplerParameter p = new SamplerParameter(param.key(), 0, bindingCounter);
2023-02-24 22:09:07 +01:00
p->key = auxKey;
2023-01-21 18:43:21 +01:00
layout->addDescriptorBinding(bindingCounter++, Gfx::SE_DESCRIPTOR_TYPE_SAMPLER);
2023-01-29 18:58:59 +01:00
p->data = graphics->createSamplerState({});
2023-02-24 22:09:07 +01:00
expressions[auxKey--] = p;
parameters[param.key()] = p;
2023-01-21 18:43:21 +01:00
}
else
{
std::cout << "Error unsupported parameter type" << std::endl;
}
}
uint32 uniformDataSize = uniformBufferOffset;
2023-02-24 22:09:07 +01:00
auto referenceExpression = [&auxKey, &expressions](json obj) -> PShaderExpression
{
if(obj.is_string())
{
PConstantExpression c = new ConstantExpression(obj.get<std::string>(), ExpressionType::UNKNOWN);
c->key = auxKey;
expressions[auxKey--] = c;
return c;
}
else
{
return expressions[obj.get<uint32>()];
}
};
MaterialNode mat;
for(auto param : j["code"].items())
{
auto obj = param.value();
std::string exp = obj["exp"].get<std::string>();
if(exp.compare("Add") == 0)
{
PAddExpression p = new AddExpression();
p->key = key;
p->inputs["lhs"].source = referenceExpression(obj["lhs"])->key;
p->inputs["rhs"].source = referenceExpression(obj["rhs"])->key;
expressions[key++] = p;
}
if(exp.compare("Sub") == 0)
{
PSubExpression p = new SubExpression();
p->key = key;
p->inputs["lhs"].source = referenceExpression(obj["lhs"])->key;
p->inputs["rhs"].source = referenceExpression(obj["rhs"])->key;
expressions[key++] = p;
}
if(exp.compare("Mul") == 0)
{
PMulExpression p = new MulExpression();
p->key = key;
p->inputs["lhs"].source = referenceExpression(obj["lhs"])->key;
p->inputs["rhs"].source = referenceExpression(obj["rhs"])->key;
expressions[key++] = p;
}
if(exp.compare("Swizzle") == 0)
{
PSwizzleExpression p = new SwizzleExpression();
p->key = key;
p->inputs["target"].source = referenceExpression(obj["target"])->key;
int32 i = 0;
for(auto c : obj["comp"].items())
{
p->comp[i++] = c.value().get<uint32>();
}
expressions[key++] = p;
}
if(exp.compare("Sample") == 0)
{
PSampleExpression p = new SampleExpression();
p->key = key;
p->inputs["texture"].source = parameters[obj["texture"].get<std::string>()]->key;
p->inputs["sampler"].source = parameters[obj["sampler"].get<std::string>()]->key;
p->inputs["coords"].source = referenceExpression(obj["coords"])->key;
expressions[key++] = p;
}
if(exp.compare("BRDF") == 0)
{
mat.profile = obj["profile"].get<std::string>();
for(auto val : obj["values"].items())
{
mat.variables[val.key()] = referenceExpression(val.value());
}
}
}
2023-01-21 18:43:21 +01:00
layout->create();
2023-02-24 22:09:07 +01:00
Array<PShaderExpression> codeExp;
for(const auto& [_, e] : expressions)
{
codeExp.add(e);
}
Array<PShaderParameter> params;
for(const auto& [_, p] : parameters)
{
params.add(p);
}
2023-01-21 18:43:21 +01:00
asset->material = new Material(
2023-01-29 18:58:59 +01:00
graphics,
2023-02-24 22:09:07 +01:00
std::move(params),
2023-01-21 18:43:21 +01:00
std::move(layout),
uniformDataSize,
uniformBinding,
2023-02-24 22:09:07 +01:00
materialName,
std::move(codeExp),
std::move(mat)
2023-01-21 18:43:21 +01:00
);
2023-07-31 21:43:20 +02:00
2023-02-24 22:09:07 +01:00
asset->material->compile();
2023-01-21 18:43:21 +01:00
graphics->getShaderCompiler()->registerMaterial(asset->material);
asset->setStatus(Asset::Status::Ready);
2023-07-31 21:43:20 +02:00
if (asset->getName().empty())
{
return;
}
auto stream = AssetRegistry::createWriteStream((std::filesystem::path(asset->folderPath) / asset->getName()).string().append(".asset"), std::ios::binary);
ArchiveBuffer archive;
Serialization::save(archive, MaterialAsset::IDENTIFIER);
Serialization::save(archive, asset->getName());
Serialization::save(archive, asset->getFolderPath());
asset->save(archive);
archive.writeToStream(stream);
2022-04-15 23:45:44 +02:00
////co_return;
2020-06-02 11:46:18 +02:00
}
2020-10-03 11:00:10 +02:00
2021-10-19 23:04:38 +02:00
PMaterialAsset MaterialLoader::getPlaceHolderMaterial()
2020-10-03 11:00:10 +02:00
{
return placeholderMaterial;
}