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>
|
2023-11-05 10:36:01 +01:00
|
|
|
#include <format>
|
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-11-05 10:36:01 +01:00
|
|
|
OMaterialAsset placeholderAsset = new MaterialAsset();
|
2023-02-24 22:09:07 +01:00
|
|
|
import(MaterialImportArgs{
|
2023-11-05 11:47:22 +01:00
|
|
|
.filePath = std::filesystem::absolute("./shaders/Placeholder.json"),
|
2023-02-01 22:13:04 +01:00
|
|
|
.importPath = "",
|
2023-02-24 22:09:07 +01:00
|
|
|
}, placeholderAsset);
|
2023-11-05 10:36:01 +01:00
|
|
|
AssetRegistry::get().assetRoot->materials[""] = std::move(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-11-05 10:36:01 +01:00
|
|
|
OMaterialAsset asset = new MaterialAsset(args.importPath, assetPath.stem().string());
|
2021-11-11 20:12:50 +01:00
|
|
|
asset->setStatus(Asset::Status::Loading);
|
2023-11-05 10:36:01 +01:00
|
|
|
PMaterialAsset ref = asset;
|
|
|
|
|
AssetRegistry::get().registerMaterial(std::move(asset));
|
|
|
|
|
import(args, ref);
|
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-11-05 10:36:01 +01:00
|
|
|
Gfx::ODescriptorLayout 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());
|
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
|
2023-11-06 14:47:21 +01:00
|
|
|
int32 uniformBinding = -1;
|
2023-11-11 22:39:17 +01:00
|
|
|
Array<OShaderExpression> expressions;
|
2023-11-05 10:36:01 +01:00
|
|
|
uint32 key = 0;
|
|
|
|
|
uint32 auxKey = 0;
|
|
|
|
|
Array<std::string> parameters;
|
|
|
|
|
for(auto& param : j["params"].items())
|
2023-01-21 18:43:21 +01:00
|
|
|
{
|
|
|
|
|
std::string type = param.value()["type"].get<std::string>();
|
|
|
|
|
auto defaultValue = param.value().find("default");
|
|
|
|
|
// TODO: ALIGNMENT RULES
|
|
|
|
|
if(type.compare("float") == 0)
|
|
|
|
|
{
|
2023-11-12 14:46:22 +01:00
|
|
|
OFloatParameter p = new FloatParameter(param.key(), uniformBufferOffset, uniformBinding);
|
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-11-05 10:36:01 +01:00
|
|
|
parameters.add(p->key);
|
2023-11-11 22:39:17 +01:00
|
|
|
expressions.add(std::move(p));
|
2023-01-21 18:43:21 +01:00
|
|
|
}
|
|
|
|
|
// TODO: ALIGNMENT RULES
|
|
|
|
|
else if(type.compare("float3") == 0)
|
|
|
|
|
{
|
2023-11-12 14:46:22 +01:00
|
|
|
OVectorParameter p = new VectorParameter(param.key(), uniformBufferOffset, uniformBinding);
|
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-11-05 10:36:01 +01:00
|
|
|
parameters.add(p->key);
|
2023-11-11 22:39:17 +01:00
|
|
|
expressions.add(std::move(p));
|
2023-01-21 18:43:21 +01:00
|
|
|
}
|
|
|
|
|
else if(type.compare("Texture2D") == 0)
|
|
|
|
|
{
|
2023-11-05 10:36:01 +01:00
|
|
|
OTextureParameter p = new TextureParameter(param.key(), 0, bindingCounter);
|
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-11-05 10:36:01 +01:00
|
|
|
parameters.add(p->key);
|
2023-11-11 22:39:17 +01:00
|
|
|
expressions.add(std::move(p));
|
2023-01-21 18:43:21 +01:00
|
|
|
}
|
|
|
|
|
else if(type.compare("SamplerState") == 0)
|
|
|
|
|
{
|
2023-11-05 10:36:01 +01:00
|
|
|
OSamplerParameter p = new SamplerParameter(param.key(), 0, bindingCounter);
|
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-11-05 10:36:01 +01:00
|
|
|
parameters.add(p->key);
|
2023-11-11 22:39:17 +01:00
|
|
|
expressions.add(std::move(p));
|
2023-01-21 18:43:21 +01:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
std::cout << "Error unsupported parameter type" << std::endl;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
uint32 uniformDataSize = uniformBufferOffset;
|
2023-11-05 10:36:01 +01:00
|
|
|
auto referenceExpression = [&auxKey, &expressions](json obj) -> std::string
|
2023-02-24 22:09:07 +01:00
|
|
|
{
|
|
|
|
|
if(obj.is_string())
|
|
|
|
|
{
|
2023-11-05 10:36:01 +01:00
|
|
|
std::string str = obj.get<std::string>();
|
2023-11-11 22:39:17 +01:00
|
|
|
if (expressions.find([&str, &expressions](const OShaderExpression& exp) {return exp->key == str; }) != expressions.end())
|
2023-11-05 10:36:01 +01:00
|
|
|
{
|
|
|
|
|
return str;
|
|
|
|
|
}
|
|
|
|
|
OConstantExpression c = new ConstantExpression(str, ExpressionType::UNKNOWN);
|
|
|
|
|
std::string name = std::format("Const{0}", auxKey++);
|
|
|
|
|
c->key = name;
|
2023-11-11 22:39:17 +01:00
|
|
|
expressions.add(std::move(c));
|
2023-11-05 10:36:01 +01:00
|
|
|
return name;
|
2023-02-24 22:09:07 +01:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2023-11-05 10:36:01 +01:00
|
|
|
return std::format("{0}", obj.get<uint32>());
|
2023-02-24 22:09:07 +01:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
MaterialNode mat;
|
|
|
|
|
|
2023-11-05 10:36:01 +01:00
|
|
|
for(auto& param : j["code"].items())
|
2023-02-24 22:09:07 +01:00
|
|
|
{
|
2023-11-05 10:36:01 +01:00
|
|
|
auto& obj = param.value();
|
2023-02-24 22:09:07 +01:00
|
|
|
std::string exp = obj["exp"].get<std::string>();
|
|
|
|
|
if(exp.compare("Add") == 0)
|
|
|
|
|
{
|
2023-11-05 10:36:01 +01:00
|
|
|
OAddExpression p = new AddExpression();
|
|
|
|
|
std::string name = std::format("{0}", key++);
|
|
|
|
|
p->key = name;
|
|
|
|
|
p->inputs["lhs"].source = referenceExpression(obj["lhs"]);
|
|
|
|
|
p->inputs["rhs"].source = referenceExpression(obj["rhs"]);
|
2023-11-11 22:39:17 +01:00
|
|
|
expressions.add(std::move(p));
|
2023-02-24 22:09:07 +01:00
|
|
|
}
|
|
|
|
|
if(exp.compare("Sub") == 0)
|
|
|
|
|
{
|
2023-11-05 10:36:01 +01:00
|
|
|
OSubExpression p = new SubExpression();
|
|
|
|
|
std::string name = std::format("{0}", key++);
|
|
|
|
|
p->key = name;
|
|
|
|
|
p->inputs["lhs"].source = referenceExpression(obj["lhs"]);
|
|
|
|
|
p->inputs["rhs"].source = referenceExpression(obj["rhs"]);
|
2023-11-11 22:39:17 +01:00
|
|
|
expressions.add(std::move(p));
|
2023-02-24 22:09:07 +01:00
|
|
|
}
|
|
|
|
|
if(exp.compare("Mul") == 0)
|
|
|
|
|
{
|
2023-11-05 10:36:01 +01:00
|
|
|
OMulExpression p = new MulExpression();
|
|
|
|
|
std::string name = std::format("{0}", key++);
|
|
|
|
|
p->key = name;
|
|
|
|
|
p->inputs["lhs"].source = referenceExpression(obj["lhs"]);
|
|
|
|
|
p->inputs["rhs"].source = referenceExpression(obj["rhs"]);
|
2023-11-11 22:39:17 +01:00
|
|
|
expressions.add(std::move(p));
|
2023-02-24 22:09:07 +01:00
|
|
|
}
|
|
|
|
|
if(exp.compare("Swizzle") == 0)
|
|
|
|
|
{
|
2023-11-05 10:36:01 +01:00
|
|
|
OSwizzleExpression p = new SwizzleExpression();
|
2023-11-11 22:39:17 +01:00
|
|
|
std::string name = std::format("{0}", key++);
|
2023-11-05 10:36:01 +01:00
|
|
|
p->key = name;
|
|
|
|
|
p->inputs["target"].source = referenceExpression(obj["target"]);
|
2023-02-24 22:09:07 +01:00
|
|
|
int32 i = 0;
|
2023-11-05 10:36:01 +01:00
|
|
|
for(auto& c : obj["comp"].items())
|
2023-02-24 22:09:07 +01:00
|
|
|
{
|
|
|
|
|
p->comp[i++] = c.value().get<uint32>();
|
|
|
|
|
}
|
2023-11-11 22:39:17 +01:00
|
|
|
expressions.add(std::move(p));
|
2023-02-24 22:09:07 +01:00
|
|
|
}
|
|
|
|
|
if(exp.compare("Sample") == 0)
|
|
|
|
|
{
|
2023-11-05 10:36:01 +01:00
|
|
|
OSampleExpression p = new SampleExpression();
|
2023-11-11 22:39:17 +01:00
|
|
|
std::string name = std::format("{0}", key++);
|
2023-11-05 10:36:01 +01:00
|
|
|
p->key = name;
|
|
|
|
|
p->inputs["texture"].source = referenceExpression(obj["texture"]);
|
|
|
|
|
p->inputs["sampler"].source = referenceExpression(obj["sampler"]);
|
|
|
|
|
p->inputs["coords"].source = referenceExpression(obj["coords"]);
|
2023-11-11 22:39:17 +01:00
|
|
|
expressions.add(std::move(p));
|
2023-02-24 22:09:07 +01:00
|
|
|
}
|
|
|
|
|
if(exp.compare("BRDF") == 0)
|
|
|
|
|
{
|
|
|
|
|
mat.profile = obj["profile"].get<std::string>();
|
2023-11-05 10:36:01 +01:00
|
|
|
for(auto& val : obj["values"].items())
|
2023-02-24 22:09:07 +01:00
|
|
|
{
|
2023-11-06 14:47:21 +01:00
|
|
|
mat.variables[val.key()] = referenceExpression(val.value());
|
2023-02-24 22:09:07 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-01-21 18:43:21 +01:00
|
|
|
layout->create();
|
|
|
|
|
asset->material = new Material(
|
2023-01-29 18:58:59 +01:00
|
|
|
graphics,
|
2023-01-21 18:43:21 +01:00
|
|
|
std::move(layout),
|
|
|
|
|
uniformDataSize,
|
|
|
|
|
uniformBinding,
|
2023-02-24 22:09:07 +01:00
|
|
|
materialName,
|
2023-11-05 10:36:01 +01:00
|
|
|
std::move(expressions),
|
|
|
|
|
std::move(parameters),
|
2023-02-24 22:09:07 +01:00
|
|
|
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;
|
|
|
|
|
}
|