overhauled physics engine
This commit is contained in:
@@ -2,8 +2,12 @@ target_sources(Engine
|
||||
PRIVATE
|
||||
BRDF.h
|
||||
BRDF.cpp
|
||||
MaterialAsset.h
|
||||
MaterialAsset.cpp
|
||||
Material.h
|
||||
Material.cpp
|
||||
MaterialInstance.h
|
||||
MaterialInstance.cpp
|
||||
MaterialInterface.h
|
||||
MaterialInterface.cpp
|
||||
ShaderExpression.h
|
||||
ShaderExpression.cpp)
|
||||
|
||||
@@ -11,6 +15,8 @@ target_sources(Engine
|
||||
PUBLIC FILE_SET HEADERS
|
||||
FILES
|
||||
BRDF.h
|
||||
MaterialAsset.h
|
||||
Material.h
|
||||
MaterialInstance.h
|
||||
MaterialInterface.h
|
||||
ShaderExpression.h)
|
||||
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
#include "Material.h"
|
||||
#include "Window/WindowManager.h"
|
||||
#include "MaterialInstance.h"
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
Gfx::ShaderMap Material::shaderMap;
|
||||
std::mutex Material::shaderMapLock;
|
||||
|
||||
Material::Material(Array<PShaderParameter> parameter, Gfx::PDescriptorLayout layout, uint32 uniformDataSize, uint32 uniformBinding, std::string materialName)
|
||||
: MaterialInterface(parameter, uniformDataSize, uniformBinding)
|
||||
, layout(layout)
|
||||
, materialName(materialName)
|
||||
{
|
||||
}
|
||||
|
||||
Material::~Material()
|
||||
{
|
||||
}
|
||||
|
||||
Gfx::PDescriptorSet Material::createDescriptorSet()
|
||||
{
|
||||
Gfx::PDescriptorSet descriptorSet = layout->allocateDescriptorSet();
|
||||
BulkResourceData uniformUpdate = {
|
||||
.size = uniformDataSize,
|
||||
.data = (uint8*)uniformData.data(),
|
||||
};
|
||||
for(auto param : parameters)
|
||||
{
|
||||
param->updateDescriptorSet(descriptorSet, uniformData.data());
|
||||
}
|
||||
if(uniformUpdate.size != 0)
|
||||
{
|
||||
uniformBuffer->updateContents(uniformUpdate);
|
||||
descriptorSet->updateBuffer(uniformBinding, uniformBuffer);
|
||||
}
|
||||
descriptorSet->writeChanges();
|
||||
return descriptorSet;
|
||||
}
|
||||
|
||||
PMaterialInstance Material::instantiate()
|
||||
{
|
||||
return new MaterialInstance(this);
|
||||
}
|
||||
|
||||
const Gfx::ShaderCollection* Material::getShaders(Gfx::RenderPassType renderPass, VertexInputType* vertexInput) const
|
||||
{
|
||||
Gfx::ShaderPermutation permutation;
|
||||
permutation.passType = renderPass;
|
||||
std::string vertexInputName = vertexInput->getName();
|
||||
std::memcpy(permutation.materialName, materialName.c_str(), sizeof(permutation.materialName));
|
||||
std::memcpy(permutation.vertexInputName, vertexInputName.c_str(), sizeof(permutation.vertexInputName));
|
||||
return shaderMap.findShaders(Gfx::PermutationId(permutation));
|
||||
}
|
||||
|
||||
Gfx::ShaderCollection& Material::createShaders(Gfx::PGraphics graphics, Gfx::RenderPassType renderPass, VertexInputType* vertexInput)
|
||||
{
|
||||
std::scoped_lock l(shaderMapLock);
|
||||
return shaderMap.createShaders(graphics, renderPass, this, vertexInput, false);
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
#include "MaterialInterface.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
DECLARE_REF(MaterialInstance)
|
||||
class Material : public MaterialInterface
|
||||
{
|
||||
public:
|
||||
Material(Array<PShaderParameter> parameter, Gfx::PDescriptorLayout layout, uint32 uniformDataSize, uint32 uniformBinding, std::string materialName);
|
||||
virtual ~Material();
|
||||
virtual Gfx::PDescriptorSet createDescriptorSet();
|
||||
virtual Gfx::PDescriptorLayout getDescriptorLayout() const { return layout; }
|
||||
virtual const std::string& getName() { return materialName; }
|
||||
|
||||
PMaterialInstance instantiate();
|
||||
|
||||
virtual const Gfx::ShaderCollection* getShaders(Gfx::RenderPassType renderPass, VertexInputType* vertexInput) const;
|
||||
virtual Gfx::ShaderCollection& createShaders(Gfx::PGraphics graphics, Gfx::RenderPassType renderPass, VertexInputType* vertexInput);
|
||||
private:
|
||||
static Gfx::ShaderMap shaderMap;
|
||||
static std::mutex shaderMapLock;
|
||||
|
||||
Gfx::PDescriptorLayout layout;
|
||||
std::string materialName;
|
||||
// With draw-indirect, we batch vertex data into big vertex buffers
|
||||
// Gfx::PVertexDataManager vertexData;
|
||||
|
||||
friend class MaterialInstance;
|
||||
};
|
||||
DEFINE_REF(Material)
|
||||
} // namespace Seele
|
||||
@@ -1,189 +0,0 @@
|
||||
#include "MaterialAsset.h"
|
||||
#include "Window/WindowManager.h"
|
||||
#include "Asset/AssetRegistry.h"
|
||||
#include "Asset/TextureAsset.h"
|
||||
#include "BRDF.h"
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
Seele::Gfx::ShaderMap MaterialAsset::shaderMap;
|
||||
std::mutex MaterialAsset::shaderMapLock;
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
MaterialAsset::MaterialAsset()
|
||||
{
|
||||
}
|
||||
|
||||
MaterialAsset::MaterialAsset(const std::string& directory, const std::string& name)
|
||||
: Asset(directory, name)
|
||||
{
|
||||
}
|
||||
|
||||
MaterialAsset::MaterialAsset(const std::filesystem::path& fullPath)
|
||||
: Asset(fullPath)
|
||||
{
|
||||
}
|
||||
|
||||
MaterialAsset::~MaterialAsset()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void MaterialAsset::save()
|
||||
{
|
||||
assert(false && "TODO");
|
||||
}
|
||||
|
||||
void MaterialAsset::load()
|
||||
{
|
||||
setStatus(Status::Loading);
|
||||
auto stream = getReadStream();
|
||||
json j;
|
||||
stream >> j;
|
||||
materialName = j["name"].get<std::string>() + "Material";
|
||||
layout = WindowManager::getGraphics()->createDescriptorLayout(materialName + "Layout");
|
||||
//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());
|
||||
std::ofstream codeStream("./shaders/generated/"+materialName+".slang");
|
||||
std::string profile = j["profile"].get<std::string>();
|
||||
|
||||
codeStream << "import Material;" << std::endl;
|
||||
codeStream << "import BRDF;" << std::endl;
|
||||
codeStream << "import MaterialParameter;" << std::endl << std::endl;
|
||||
|
||||
codeStream << "struct " << materialName << " : IMaterial {" << std::endl;
|
||||
uint32 uniformBufferOffset = 0;
|
||||
uint32 bindingCounter = 0; // Uniform buffers are always binding 0
|
||||
uniformBinding = -1;
|
||||
for(auto param : j["params"].items())
|
||||
{
|
||||
std::string type = param.value()["type"].get<std::string>();
|
||||
auto defaultValue = param.value().find("default");
|
||||
if(type.compare("float") == 0)
|
||||
{
|
||||
PFloatParameter p = new FloatParameter(param.key(), uniformBufferOffset, 0);
|
||||
codeStream << "\tlayout(offset = " << uniformBufferOffset << ")";
|
||||
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>());
|
||||
}
|
||||
parameters.add(p);
|
||||
}
|
||||
else if(type.compare("float3") == 0)
|
||||
{
|
||||
PVectorParameter p = new VectorParameter(param.key(), uniformBufferOffset, 0);
|
||||
codeStream << "\tlayout(offset = " << uniformBufferOffset << ")";
|
||||
if(uniformBinding == -1)
|
||||
{
|
||||
layout->addDescriptorBinding(bindingCounter, Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
|
||||
uniformBinding = bindingCounter++;
|
||||
}
|
||||
uniformBufferOffset += 12;
|
||||
if(defaultValue != param.value().end())
|
||||
{
|
||||
p->data = Math::parseVector(defaultValue.value().get<std::string>().c_str());
|
||||
}
|
||||
parameters.add(p);
|
||||
}
|
||||
else if(type.compare("Texture2D") == 0)
|
||||
{
|
||||
PTextureParameter p = new TextureParameter(param.key(), 0, bindingCounter);
|
||||
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
|
||||
}
|
||||
parameters.add(p);
|
||||
}
|
||||
else if(type.compare("SamplerState") == 0)
|
||||
{
|
||||
PSamplerParameter p = new SamplerParameter(param.key(), 0, bindingCounter);
|
||||
layout->addDescriptorBinding(bindingCounter++, Gfx::SE_DESCRIPTOR_TYPE_SAMPLER);
|
||||
p->data = WindowManager::getGraphics()->createSamplerState({});
|
||||
parameters.add(p);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Error unsupported parameter type" << std::endl;
|
||||
}
|
||||
codeStream << "\t" << type << " " << param.key() << ";\n";
|
||||
}
|
||||
uniformDataSize = uniformBufferOffset;
|
||||
if(uniformDataSize != 0)
|
||||
{
|
||||
uniformData = new uint8[uniformDataSize];
|
||||
UniformBufferCreateInfo uniformInitializer;
|
||||
uniformInitializer.resourceData.data = uniformData;
|
||||
uniformInitializer.resourceData.size = uniformDataSize;
|
||||
uniformBuffer = WindowManager::getGraphics()->createUniformBuffer(uniformInitializer);
|
||||
}
|
||||
BRDF* brdf = BRDF::getBRDFByName(profile);
|
||||
brdf->generateMaterialCode(codeStream, j["code"]);
|
||||
codeStream << "};";
|
||||
codeStream.close();
|
||||
layout->create();
|
||||
setStatus(Status::Ready);
|
||||
}
|
||||
|
||||
|
||||
void MaterialAsset::beginFrame()
|
||||
{
|
||||
}
|
||||
|
||||
void MaterialAsset::endFrame()
|
||||
{
|
||||
}
|
||||
|
||||
Gfx::PDescriptorSet MaterialAsset::createDescriptorSet()
|
||||
{
|
||||
Gfx::PDescriptorSet descriptorSet = layout->allocateDescriptorSet();
|
||||
BulkResourceData uniformUpdate;
|
||||
uniformUpdate.size = uniformDataSize;
|
||||
uniformUpdate.data = uniformData;
|
||||
for(auto param : parameters)
|
||||
{
|
||||
param->updateDescriptorSet(descriptorSet, uniformData);
|
||||
}
|
||||
if(uniformUpdate.size != 0)
|
||||
{
|
||||
uniformBuffer->updateContents(uniformUpdate);
|
||||
descriptorSet->updateBuffer(uniformBinding, uniformBuffer);
|
||||
}
|
||||
descriptorSet->writeChanges();
|
||||
return descriptorSet;
|
||||
}
|
||||
|
||||
|
||||
const Gfx::ShaderCollection* MaterialAsset::getShaders(Gfx::RenderPassType renderPass, VertexInputType* vertexInput) const
|
||||
{
|
||||
Gfx::ShaderPermutation permutation;
|
||||
permutation.passType = renderPass;
|
||||
std::string vertexInputName = vertexInput->getName();
|
||||
std::memcpy(permutation.materialName, materialName.c_str(), sizeof(permutation.materialName));
|
||||
std::memcpy(permutation.vertexInputName, vertexInputName.c_str(), sizeof(permutation.vertexInputName));
|
||||
return shaderMap.findShaders(Gfx::PermutationId(permutation));
|
||||
}
|
||||
|
||||
Gfx::ShaderCollection& MaterialAsset::createShaders(Gfx::PGraphics graphics, Gfx::RenderPassType renderPass, VertexInputType* vertexInput)
|
||||
{
|
||||
std::scoped_lock l(shaderMapLock);
|
||||
return shaderMap.createShaders(graphics, renderPass, this, vertexInput, false);
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
#pragma once
|
||||
#include "Asset/Asset.h"
|
||||
#include "Graphics/GraphicsResources.h"
|
||||
#include "ShaderExpression.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
DECLARE_REF(VertexShaderInput)
|
||||
class MaterialAsset : public Asset
|
||||
{
|
||||
public:
|
||||
MaterialAsset();
|
||||
MaterialAsset(const std::string &directory, const std::string &name);
|
||||
MaterialAsset(const std::filesystem::path &fullPath);
|
||||
~MaterialAsset();
|
||||
virtual void beginFrame();
|
||||
virtual void endFrame();
|
||||
virtual void save() override;
|
||||
virtual void load() override;
|
||||
Gfx::SeBlendOp getBlendMode() const {return Gfx::SE_BLEND_OP_END_RANGE;}
|
||||
Gfx::MaterialShadingModel getShadingModel() const {return Gfx::MaterialShadingModel::DefaultLit;}
|
||||
|
||||
Gfx::PDescriptorSet createDescriptorSet();
|
||||
|
||||
Gfx::PDescriptorLayout getDescriptorLayout() const { return layout; }
|
||||
// The name of the generated material shader, opposed to the name of the .asset file
|
||||
const std::string& getName() {return materialName;}
|
||||
|
||||
const Gfx::ShaderCollection* getShaders(Gfx::RenderPassType renderPass, VertexInputType* vertexInput) const;
|
||||
Gfx::ShaderCollection& createShaders(Gfx::PGraphics graphics, Gfx::RenderPassType renderPass, VertexInputType* vertexInput);
|
||||
private:
|
||||
static Gfx::ShaderMap shaderMap;
|
||||
static std::mutex shaderMapLock;
|
||||
|
||||
//For now its simply the collection of parameters, since there is no point for expressions
|
||||
Array<PShaderParameter> parameters;
|
||||
Gfx::PDescriptorLayout layout;
|
||||
Gfx::PUniformBuffer uniformBuffer;
|
||||
uint32 uniformDataSize;
|
||||
uint8* uniformData;
|
||||
int32 uniformBinding;
|
||||
std::string materialName;
|
||||
// With draw-indirect, we batch vertex data into big vertex buffers
|
||||
// Gfx::PVertexDataManager vertexData;
|
||||
};
|
||||
DEFINE_REF(MaterialAsset)
|
||||
} // namespace Seele
|
||||
@@ -0,0 +1,55 @@
|
||||
#include "MaterialInstance.h"
|
||||
#include "Material.h"
|
||||
#include "Graphics/Graphics.h"
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
MaterialInstance::MaterialInstance(PMaterial baseMaterial)
|
||||
: MaterialInterface(baseMaterial->parameters, baseMaterial->uniformDataSize, baseMaterial->uniformBinding)
|
||||
, baseMaterial(baseMaterial)
|
||||
{
|
||||
}
|
||||
|
||||
MaterialInstance::~MaterialInstance()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Gfx::PDescriptorSet MaterialInstance::createDescriptorSet()
|
||||
{
|
||||
Gfx::PDescriptorSet descriptorSet = baseMaterial->layout->allocateDescriptorSet();
|
||||
BulkResourceData uniformUpdate;
|
||||
uniformUpdate.size = uniformDataSize;
|
||||
uniformUpdate.data = (uint8*)uniformData.data();
|
||||
for(auto param : parameters)
|
||||
{
|
||||
param->updateDescriptorSet(descriptorSet, uniformData.data());
|
||||
}
|
||||
if(uniformUpdate.size != 0)
|
||||
{
|
||||
uniformBuffer->updateContents(uniformUpdate);
|
||||
descriptorSet->updateBuffer(uniformBinding, uniformBuffer);
|
||||
}
|
||||
descriptorSet->writeChanges();
|
||||
return descriptorSet;
|
||||
}
|
||||
|
||||
Gfx::PDescriptorLayout MaterialInstance::getDescriptorLayout() const
|
||||
{
|
||||
return baseMaterial->getDescriptorLayout();
|
||||
}
|
||||
|
||||
const std::string& MaterialInstance::getName()
|
||||
{
|
||||
return baseMaterial->getName();
|
||||
}
|
||||
|
||||
const Gfx::ShaderCollection* Seele::MaterialInstance::getShaders(Gfx::RenderPassType renderPass, VertexInputType* vertexInput) const
|
||||
{
|
||||
return baseMaterial->getShaders(renderPass, vertexInput);
|
||||
}
|
||||
|
||||
Gfx::ShaderCollection& Seele::MaterialInstance::createShaders(Gfx::PGraphics graphics, Gfx::RenderPassType renderPass, VertexInputType* vertexInput)
|
||||
{
|
||||
return baseMaterial->createShaders(graphics, renderPass, vertexInput);
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
#include "MaterialInterface.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
DECLARE_REF(Material)
|
||||
class MaterialInstance : public MaterialInterface
|
||||
{
|
||||
public:
|
||||
MaterialInstance(PMaterial baseMaterial);
|
||||
virtual ~MaterialInstance();
|
||||
virtual Gfx::PDescriptorSet createDescriptorSet();
|
||||
virtual Gfx::PDescriptorLayout getDescriptorLayout() const;
|
||||
|
||||
// The name of the generated material shader, opposed to the name of the .asset file
|
||||
virtual const std::string& getName();
|
||||
virtual const Gfx::ShaderCollection* getShaders(Gfx::RenderPassType renderPass, VertexInputType* vertexInput) const;
|
||||
virtual Gfx::ShaderCollection& createShaders(Gfx::PGraphics graphics, Gfx::RenderPassType renderPass, VertexInputType* vertexInput);
|
||||
|
||||
private:
|
||||
PMaterial baseMaterial;
|
||||
};
|
||||
DEFINE_REF(MaterialInstance)
|
||||
} // namespace Seele
|
||||
@@ -0,0 +1,39 @@
|
||||
#include "MaterialInterface.h"
|
||||
#include "Window/WindowManager.h"
|
||||
#include "Graphics/Graphics.h"
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
MaterialInterface::MaterialInterface(Array<PShaderParameter> parameter, uint32 uniformDataSize, uint32 uniformBinding)
|
||||
: parameters(parameter)
|
||||
, uniformDataSize(uniformDataSize)
|
||||
, uniformBinding(uniformBinding)
|
||||
{
|
||||
if(uniformDataSize != 0)
|
||||
{
|
||||
uniformData.resize(uniformDataSize);
|
||||
UniformBufferCreateInfo uniformInitializer = {
|
||||
.resourceData = {
|
||||
.size = uniformDataSize,
|
||||
.data = nullptr,
|
||||
}
|
||||
};
|
||||
uniformBuffer = WindowManager::getGraphics()->createUniformBuffer(uniformInitializer);
|
||||
}
|
||||
}
|
||||
|
||||
MaterialInterface::~MaterialInterface()
|
||||
{
|
||||
}
|
||||
|
||||
PShaderParameter MaterialInterface::getParameter(const std::string& name)
|
||||
{
|
||||
for (auto param : parameters)
|
||||
{
|
||||
if(param->name.compare(name) == 0)
|
||||
{
|
||||
return param;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
#include "ShaderExpression.h"
|
||||
#include "Graphics/GraphicsResources.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
DECLARE_NAME_REF(Gfx, DescriptorLayout)
|
||||
DECLARE_NAME_REF(Gfx, UniformBuffer)
|
||||
class MaterialInterface
|
||||
{
|
||||
public:
|
||||
MaterialInterface(Array<PShaderParameter> parameter, uint32 uniformDataSize, uint32 uniformBinding);
|
||||
virtual ~MaterialInterface();
|
||||
PShaderParameter getParameter(const std::string& name);
|
||||
virtual Gfx::PDescriptorSet createDescriptorSet() = 0;
|
||||
virtual Gfx::PDescriptorLayout getDescriptorLayout() const = 0;
|
||||
|
||||
// The name of the generated material shader, opposed to the name of the .asset file
|
||||
virtual const std::string& getName() = 0;
|
||||
virtual const Gfx::ShaderCollection* getShaders(Gfx::RenderPassType renderPass, VertexInputType* vertexInput) const = 0;
|
||||
virtual Gfx::ShaderCollection& createShaders(Gfx::PGraphics graphics, Gfx::RenderPassType renderPass, VertexInputType* vertexInput) = 0;
|
||||
protected:
|
||||
//For now its simply the collection of parameters, since there is no point for expressions
|
||||
Array<PShaderParameter> parameters;
|
||||
Gfx::PUniformBuffer uniformBuffer;
|
||||
uint32 uniformDataSize;
|
||||
Array<uint8> uniformData;
|
||||
int32 uniformBinding;
|
||||
};
|
||||
DEFINE_REF(MaterialInterface)
|
||||
} // namespace Seele
|
||||
@@ -40,7 +40,7 @@ VectorParameter::~VectorParameter()
|
||||
|
||||
void VectorParameter::updateDescriptorSet(Gfx::PDescriptorSet, uint8* dst)
|
||||
{
|
||||
std::memcpy(dst + byteOffset, &data, sizeof(Math::Vector));
|
||||
std::memcpy(dst + byteOffset, &data, sizeof(Vector));
|
||||
}
|
||||
|
||||
TextureParameter::TextureParameter(std::string name, uint32 byteOffset, uint32 binding)
|
||||
|
||||
@@ -36,7 +36,7 @@ struct FloatParameter : public ShaderParameter
|
||||
DEFINE_REF(FloatParameter)
|
||||
struct VectorParameter : public ShaderParameter
|
||||
{
|
||||
Math::Vector data;
|
||||
Vector data;
|
||||
VectorParameter(std::string name, uint32 byteOffset, uint32 binding);
|
||||
virtual ~VectorParameter();
|
||||
virtual void updateDescriptorSet(Gfx::PDescriptorSet descriptorSet, uint8* dst) override;
|
||||
|
||||
Reference in New Issue
Block a user