2023-01-21 18:43:21 +01:00
|
|
|
#include "Material.h"
|
2024-04-15 13:48:34 +02:00
|
|
|
#include "Graphics/Enums.h"
|
2023-01-29 18:58:59 +01:00
|
|
|
#include "Graphics/Graphics.h"
|
2023-11-15 17:42:57 +01:00
|
|
|
#include "Graphics/Shader.h"
|
2024-06-09 12:20:04 +02:00
|
|
|
#include "MaterialInstance.h"
|
|
|
|
|
#include "Serialization/Serialization.h"
|
|
|
|
|
#include "Window/WindowManager.h"
|
2024-01-16 19:24:49 +01:00
|
|
|
#include <fstream>
|
2023-01-21 18:43:21 +01:00
|
|
|
|
2024-06-09 12:20:04 +02:00
|
|
|
|
2023-01-21 18:43:21 +01:00
|
|
|
using namespace Seele;
|
|
|
|
|
|
2024-05-09 08:41:46 +02:00
|
|
|
std::atomic_uint64_t Material::materialIdCounter = 0;
|
|
|
|
|
Array<PMaterial> Material::materials;
|
|
|
|
|
|
2024-06-09 12:20:04 +02:00
|
|
|
Material::Material() {}
|
2023-01-21 18:43:21 +01:00
|
|
|
|
2024-06-09 12:20:04 +02:00
|
|
|
Material::Material(Gfx::PGraphics graphics, Gfx::ODescriptorLayout layout, uint32 uniformDataSize, uint32 uniformBinding,
|
|
|
|
|
std::string materialName, Array<OShaderExpression> expressions, Array<std::string> parameter, MaterialNode brdf)
|
|
|
|
|
: graphics(graphics), uniformDataSize(uniformDataSize), uniformBinding(uniformBinding), instanceId(0), layout(std::move(layout)),
|
|
|
|
|
materialName(materialName), codeExpressions(std::move(expressions)), parameters(std::move(parameter)), brdf(std::move(brdf)),
|
|
|
|
|
materialId(materialIdCounter++) {
|
2024-05-09 08:41:46 +02:00
|
|
|
materials.add(this);
|
2023-01-21 18:43:21 +01:00
|
|
|
}
|
|
|
|
|
|
2024-06-09 12:20:04 +02:00
|
|
|
Material::~Material() {}
|
|
|
|
|
|
|
|
|
|
OMaterialInstance Material::instantiate() {
|
|
|
|
|
return new MaterialInstance(instanceId++, graphics, codeExpressions, parameters, uniformBinding, uniformDataSize);
|
2023-01-21 18:43:21 +01:00
|
|
|
}
|
|
|
|
|
|
2024-06-09 12:20:04 +02:00
|
|
|
void Material::save(ArchiveBuffer& buffer) const {
|
2023-11-01 13:38:49 +01:00
|
|
|
Serialization::save(buffer, uniformDataSize);
|
|
|
|
|
Serialization::save(buffer, uniformBinding);
|
|
|
|
|
Serialization::save(buffer, instanceId);
|
2023-04-09 16:39:53 +02:00
|
|
|
Serialization::save(buffer, materialName);
|
2023-07-13 21:01:20 +02:00
|
|
|
Serialization::save(buffer, codeExpressions);
|
2023-11-01 13:38:49 +01:00
|
|
|
Serialization::save(buffer, parameters);
|
2023-07-13 21:01:20 +02:00
|
|
|
Serialization::save(buffer, brdf);
|
2024-04-19 18:23:36 +02:00
|
|
|
Serialization::save(buffer, layout->getName());
|
2023-02-13 14:56:13 +01:00
|
|
|
const auto& bindings = layout->getBindings();
|
|
|
|
|
Serialization::save(buffer, bindings.size());
|
2024-06-09 12:20:04 +02:00
|
|
|
for (const auto& binding : bindings) {
|
2023-02-13 14:56:13 +01:00
|
|
|
Serialization::save(buffer, binding.binding);
|
|
|
|
|
Serialization::save(buffer, binding.descriptorType);
|
2024-04-15 13:48:34 +02:00
|
|
|
Serialization::save(buffer, binding.textureType);
|
|
|
|
|
Serialization::save(buffer, binding.descriptorCount);
|
|
|
|
|
Serialization::save(buffer, binding.bindingFlags);
|
2023-02-13 14:56:13 +01:00
|
|
|
Serialization::save(buffer, binding.shaderStages);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-09 12:20:04 +02:00
|
|
|
void Material::load(ArchiveBuffer& buffer) {
|
2023-02-13 14:56:13 +01:00
|
|
|
graphics = buffer.getGraphics();
|
2023-11-01 13:38:49 +01:00
|
|
|
Serialization::load(buffer, uniformDataSize);
|
|
|
|
|
Serialization::load(buffer, uniformBinding);
|
|
|
|
|
Serialization::load(buffer, instanceId);
|
2023-02-13 14:56:13 +01:00
|
|
|
Serialization::load(buffer, materialName);
|
2023-11-01 13:38:49 +01:00
|
|
|
Serialization::load(buffer, codeExpressions);
|
|
|
|
|
Serialization::load(buffer, parameters);
|
|
|
|
|
Serialization::load(buffer, brdf);
|
2024-04-19 18:23:36 +02:00
|
|
|
std::string descriptorName;
|
|
|
|
|
Serialization::load(buffer, descriptorName);
|
2023-02-13 14:56:13 +01:00
|
|
|
uint64 numBindings;
|
|
|
|
|
Serialization::load(buffer, numBindings);
|
2024-04-19 18:23:36 +02:00
|
|
|
layout = graphics->createDescriptorLayout(descriptorName);
|
2024-06-09 12:20:04 +02:00
|
|
|
for (uint64 i = 0; i < numBindings; ++i) {
|
2023-02-13 14:56:13 +01:00
|
|
|
uint32 binding;
|
|
|
|
|
Serialization::load(buffer, binding);
|
|
|
|
|
|
2024-04-15 13:48:34 +02:00
|
|
|
Gfx::SeDescriptorType descriptorType;
|
|
|
|
|
Serialization::load(buffer, descriptorType);
|
|
|
|
|
|
|
|
|
|
Gfx::SeImageViewType textureType;
|
|
|
|
|
Serialization::load(buffer, textureType);
|
2023-02-13 14:56:13 +01:00
|
|
|
|
|
|
|
|
uint32 descriptorCount;
|
|
|
|
|
Serialization::load(buffer, descriptorCount);
|
|
|
|
|
|
2024-04-15 13:48:34 +02:00
|
|
|
Gfx::SeDescriptorBindingFlags bindingFlags;
|
|
|
|
|
Serialization::load(buffer, bindingFlags);
|
2023-02-13 14:56:13 +01:00
|
|
|
|
|
|
|
|
Gfx::SeShaderStageFlags shaderStages;
|
|
|
|
|
Serialization::load(buffer, shaderStages);
|
|
|
|
|
|
2024-06-09 12:20:04 +02:00
|
|
|
layout->addDescriptorBinding(Gfx::DescriptorBinding{
|
|
|
|
|
.binding = binding,
|
|
|
|
|
.descriptorType = descriptorType,
|
|
|
|
|
.textureType = textureType,
|
|
|
|
|
.descriptorCount = descriptorCount,
|
|
|
|
|
.bindingFlags = bindingFlags,
|
|
|
|
|
.shaderStages = shaderStages,
|
|
|
|
|
});
|
2023-02-13 14:56:13 +01:00
|
|
|
}
|
|
|
|
|
layout->create();
|
2024-05-12 19:36:32 +02:00
|
|
|
materialId = materialIdCounter++;
|
2023-01-21 18:43:21 +01:00
|
|
|
}
|
|
|
|
|
|
2024-06-09 12:20:04 +02:00
|
|
|
void Material::compile() {
|
|
|
|
|
std::ofstream codeStream("./shaders/generated/" + materialName + ".slang");
|
2023-02-24 22:09:07 +01:00
|
|
|
codeStream << "import BRDF;\n";
|
|
|
|
|
codeStream << "import MaterialParameter;\n";
|
2024-04-26 19:32:38 +02:00
|
|
|
codeStream << "struct " << materialName << "{\n";
|
2024-06-09 12:20:04 +02:00
|
|
|
for (const auto& parameter : parameters) {
|
|
|
|
|
PShaderParameter handle =
|
|
|
|
|
PShaderExpression(*codeExpressions.find([¶meter](const OShaderExpression& exp) { return exp->key == parameter; }));
|
2023-11-05 10:36:01 +01:00
|
|
|
handle->generateDeclaration(codeStream);
|
2023-02-24 22:09:07 +01:00
|
|
|
}
|
|
|
|
|
codeStream << "\ttypedef " << brdf.profile << " BRDF;\n";
|
2023-11-11 13:56:12 +01:00
|
|
|
codeStream << "\t" << brdf.profile << " prepare(MaterialParameter input) {\n";
|
2023-02-24 22:09:07 +01:00
|
|
|
codeStream << "\t\t" << brdf.profile << " result;\n";
|
2023-11-05 10:36:01 +01:00
|
|
|
Map<std::string, std::string> varState;
|
2023-11-11 22:39:17 +01:00
|
|
|
// initialize variable state
|
2024-06-09 12:20:04 +02:00
|
|
|
for (const auto& expr : codeExpressions) {
|
2023-11-17 22:31:26 +01:00
|
|
|
codeStream << "\t\t" << expr->evaluate(varState);
|
2023-02-24 22:09:07 +01:00
|
|
|
}
|
2024-06-09 12:20:04 +02:00
|
|
|
for (const auto& [name, exp] : brdf.variables) {
|
2023-11-17 22:31:26 +01:00
|
|
|
codeStream << "\t\tresult." << name << " = " << varState[exp] << ";" << std::endl;
|
2023-02-24 22:09:07 +01:00
|
|
|
}
|
|
|
|
|
codeStream << "\t\treturn result;\n";
|
|
|
|
|
codeStream << "\t}\n";
|
|
|
|
|
codeStream << "};\n";
|
2024-04-26 19:32:38 +02:00
|
|
|
codeStream << "layout(set=4)";
|
|
|
|
|
codeStream << "ParameterBlock<" << materialName << "> pMaterial;";
|
2023-11-05 10:36:01 +01:00
|
|
|
graphics->getShaderCompiler()->registerMaterial(this);
|
2023-02-24 22:09:07 +01:00
|
|
|
}
|