Improving Material shader code generation

This commit is contained in:
Dynamitos
2020-09-19 14:36:50 +02:00
parent 6814587b54
commit facbfed79c
72 changed files with 1049 additions and 329 deletions
+132
View File
@@ -0,0 +1,132 @@
#include "BRDF.h"
#include <sstream>
#include <fstream>
#include <nlohmann/json.hpp>
using namespace Seele;
using json = nlohmann::json;
List<BRDF*> BRDF::globalBRDFList;
BRDF::BRDF(const char* name)
: name(name)
{
globalBRDFList.add(this);
}
BRDF::~BRDF()
{
globalBRDFList.remove(globalBRDFList.find(this));
}
BRDF* BRDF::getBRDFByName(const std::string& name)
{
for(auto brdf : globalBRDFList)
{
if(name.compare(brdf->name) == 0)
{
return brdf;
}
}
return nullptr;
}
List<BRDF*> BRDF::getBRDFList()
{
return globalBRDFList;
}
BlinnPhong::BlinnPhong(const char* name)
: BRDF(name)
{
}
BlinnPhong::~BlinnPhong()
{
}
void BlinnPhong::generateMaterialCode(std::ofstream& codeStream, json codeJson)
{
std::stringstream accessorStream;
auto generateAccessor = [codeJson](std::stringstream& accessorStream, const std::string& key, const std::string& defaultVal)
{
if(codeJson.contains(key))
{
for(auto code : codeJson[key].items())
{
accessorStream << code.value().get<std::string>() << ";" << std::endl;
}
}
else
{
accessorStream << "return " << defaultVal << ";";
}
};
accessorStream << "float3 getBaseColor(MaterialFragmentParameter input) {\n";
generateAccessor(accessorStream, "baseColor", "float3(0, 0, 0)");
accessorStream << "}";
accessorStream << "float getMetallic(MaterialFragmentParameter input) {\n";
generateAccessor(accessorStream, "metallic", "0.f");
accessorStream << "}";
accessorStream << "float3 getNormal(MaterialFragmentParameter input) {\n";
generateAccessor(accessorStream, "normal", "float3(0, 1, 0)");
accessorStream << "}";
accessorStream << "float getSpecular(MaterialFragmentParameter input) {\n";
generateAccessor(accessorStream, "specular", "0.f");
accessorStream << "}";
accessorStream << "float getRoughness(MaterialFragmentParameter input) {\n";
generateAccessor(accessorStream, "roughness", "0.f");
accessorStream << "}";
accessorStream << "float getSheen(MaterialFragmentParameter input) {\n";
generateAccessor(accessorStream, "sheen", "0.f");
accessorStream << "}";
/*accessorStream << "float getSpecularTint(MaterialFragmentParameter input) {\n";
generateAccessor(accessorStream, "specularTint", "0.f");
accessorStream << "}";
accessorStream << "float getAnisotropic(MaterialFragmentParameter input) {\n";
generateAccessor(accessorStream, "anisotropic", "0.f");
accessorStream << "}";
accessorStream << "float getSheenTint(MaterialFragmentParameter input) {\n";
generateAccessor(accessorStream, "sheenTint", "0.f");
accessorStream << "}";
accessorStream << "float getClearCoat(MaterialFragmentParameter input) {\n";
generateAccessor(accessorStream, "clearCoat", "0.f");
accessorStream << "}";
accessorStream << "float getClearCoatGloss(MaterialFragmentParameter input) {\n";
generateAccessor(accessorStream, "clearCoatGloss", "0.f");
accessorStream << "}";*/
accessorStream << "float3 getWorldOffset() {\n";
generateAccessor(accessorStream, "worldOffset", "0.f");
accessorStream << "}";
codeStream << accessorStream.str();
codeStream << "typedef " << name << " BRDF;" << std::endl;
codeStream << name << " prepare(MaterialFragmentParameter geometry){" << std::endl;
codeStream << name << " result;" << std::endl;
codeStream << "result.baseColor = getBaseColor(geometry);" << std::endl;
codeStream << "result.metallic = getMetallic(geometry);" << std::endl;
codeStream << "result.normal = geometry.transformNormalTexture(getNormal(geometry));" << std::endl;
codeStream << "result.specular = getSpecular(geometry);" << std::endl;
codeStream << "result.roughness = getRoughness(geometry);" << std::endl;
codeStream << "result.sheen = getSheen(geometry);" << std::endl;
codeStream << "return result;" << std::endl;
codeStream << "}" << std::endl;
}
IMPLEMENT_BRDF(BlinnPhong);
+39
View File
@@ -0,0 +1,39 @@
#pragma once
#include "MinimalEngine.h"
#include "Containers/List.h"
#include <nlohmann/json_fwd.hpp>
namespace Seele
{
class BRDF
{
public:
static BRDF* getBRDFByName(const std::string& name);
static List<BRDF*> getBRDFList();
virtual void generateMaterialCode(std::ofstream& codeStream, nlohmann::json codeJson) = 0;
protected:
BRDF(const char* name);
virtual ~BRDF();
static List<BRDF*> globalBRDFList;
const char* name;
};
#define DECLARE_BRDF(inputClass) \
public: \
static inputClass staticType;
#define IMPLEMENT_BRDF(inputClass) \
inputClass inputClass::staticType( \
#inputClass);
class BlinnPhong : public BRDF
{
DECLARE_BRDF(BlinnPhong);
public:
virtual void generateMaterialCode(std::ofstream& codeStream, nlohmann::json codeJson);
protected:
BlinnPhong(const char* name);
virtual ~BlinnPhong();
};
} // namespace Seele
+2
View File
@@ -1,5 +1,7 @@
target_sources(SeeleEngine
PRIVATE
BRDF.h
BRDF.cpp
Material.h
Material.cpp
MaterialAsset.h
+17 -16
View File
@@ -1,6 +1,7 @@
#include "Material.h"
#include "Asset/AssetRegistry.h"
#include "Graphics/VertexShaderInput.h"
#include "BRDF.h"
#include <nlohmann/json.hpp>
#include <sstream>
#include <iostream>
@@ -45,13 +46,15 @@ void Material::compile()
auto& stream = getReadStream();
json j;
stream >> j;
std::stringstream codeStream;
materialName = j["name"].get<std::string>();
std::ofstream codeStream("./shaders/generated/"+materialName+".slang");
std::string profile = j["profile"].get<std::string>();
codeStream << "import VERTEX_INPUT_IMPORT;" << std::endl;
codeStream << "import LightEnv;" << std::endl;
codeStream << "import Material;" << std::endl;
codeStream << "import BRDF;" << std::endl;
codeStream << "import InputGeometry;" << std::endl;
codeStream << "import MaterialParameter;" << std::endl;
codeStream << "struct " << materialName << ": IMaterial {" << std::endl;
for(auto param : j["params"].items())
@@ -62,6 +65,7 @@ void Material::compile()
if(type.compare("float") == 0)
{
PFloatParameter p = new FloatParameter();
p->name = param.key();
if(default != param.value().end())
{
p->defaultValue = std::stof(default.value().get<std::string>());
@@ -71,6 +75,7 @@ void Material::compile()
else if(type.compare("float3") == 0)
{
PVectorParameter p = new VectorParameter();
p->name = param.key();
if(default != param.value().end())
{
p->defaultValue = parseVector(default.value().get<std::string>().c_str());
@@ -80,6 +85,7 @@ void Material::compile()
else if(type.compare("Texture2D") == 0)
{
PTextureParameter p = new TextureParameter();
p->name = param.key();
if(default != param.value().end())
{
@@ -89,37 +95,32 @@ void Material::compile()
else if(type.compare("SamplerState") == 0)
{
PSamplerParameter p = new SamplerParameter();
p->name = param.key();
parameters.add(p);
}
else
{
std::cout << "Error unsupported parameter type" << std::endl;
}
codeStream << type << " " << param.key();
codeStream << type << " " << param.key() << ";\n";
}
codeStream << "typedef " << profile << " BRDF;" << std::endl;
codeStream << profile << " prepare(MaterialPixelParameter geometry){" << std::endl;
codeStream << profile << " result;" << std::endl;
for(auto c : j["code"].items())
{
codeStream << c.value().get<std::string>() << std::endl;
}
codeStream << "}};" << std::endl;
materialCode = codeStream.str();
BRDF* brdf = BRDF::getBRDFByName(profile);
brdf->generateMaterialCode(codeStream, j["code"]);
codeStream << "};";
codeStream.close();
}
const Gfx::ShaderCollection* Material::getShaders(Gfx::RenderPassType renderPass, PVertexShaderInput vertexInput) const
const Gfx::ShaderCollection* Material::getShaders(Gfx::RenderPassType renderPass, VertexInputType* vertexInput) const
{
Gfx::ShaderPermutation permutation;
std::string materialName = getMaterialName();
std::string materialName = getFileName();
std::string vertexInputName = vertexInput->getName();
std::memcpy(permutation.materialName, materialName.c_str(), sizeof(permutation.materialName));
std::memcpy(permutation.materialName, vertexInputName.c_str(), sizeof(permutation.materialName));
return shaderMap.findShaders(Gfx::PermutationId(permutation));
}
Gfx::ShaderCollection& Material::createShaders(Gfx::PGraphics graphics, Gfx::RenderPassType renderPass, PVertexShaderInput vertexInput)
Gfx::ShaderCollection& Material::createShaders(Gfx::PGraphics graphics, Gfx::RenderPassType renderPass, VertexInputType* vertexInput)
{
std::lock_guard lock(shaderMapLock);
return shaderMap.createShaders(graphics, renderPass, this, vertexInput, false);
+6 -7
View File
@@ -4,7 +4,7 @@
namespace Seele
{
class VertexInputType;
class Material : public MaterialAsset
{
public:
@@ -14,18 +14,17 @@ public:
~Material();
virtual void save() override;
virtual void load() override;
virtual std::string getMaterialName() const { return materialName; }
inline std::string getCode() const { return materialCode; }
virtual PMaterial getRenderMaterial() { return this; }
const std::string& getName() {return materialName;}
const Gfx::ShaderCollection* getShaders(Gfx::RenderPassType renderPass, PVertexShaderInput vertexInput) const;
Gfx::ShaderCollection& createShaders(Gfx::PGraphics graphics, Gfx::RenderPassType renderPass, PVertexShaderInput vertexInput);
const Gfx::ShaderCollection* getShaders(Gfx::RenderPassType renderPass, VertexInputType* vertexInput) const;
Gfx::ShaderCollection& createShaders(Gfx::PGraphics graphics, Gfx::RenderPassType renderPass, VertexInputType* vertexInput);
void compile();
private:
static Gfx::ShaderMap shaderMap;
static std::mutex shaderMapLock;
void compile();
std::string materialName;
std::string materialCode;
friend class MaterialLoader;
};
DEFINE_REF(Material);
+2 -1
View File
@@ -6,6 +6,7 @@
namespace Seele
{
DECLARE_REF(VertexShaderInput);
DECLARE_REF(Material);
class MaterialAsset : public Asset
{
public:
@@ -15,7 +16,7 @@ public:
~MaterialAsset();
virtual void save() = 0;
virtual void load() = 0;
virtual std::string getMaterialName() const = 0;
virtual PMaterial getRenderMaterial() = 0;
Gfx::SeBlendOp getBlendMode() const {return Gfx::SE_BLEND_OP_END_RANGE;}
Gfx::MaterialShadingModel getShadingModel() const {return Gfx::MaterialShadingModel::DefaultLit;}
+2 -2
View File
@@ -31,9 +31,9 @@ void MaterialInstance::load()
}
inline std::string MaterialInstance::getMaterialName() const
PMaterial MaterialInstance::getRenderMaterial()
{
return baseMaterial->getMaterialName();
return baseMaterial;
}
PMaterial MaterialInstance::getBaseMaterial() const
+1 -1
View File
@@ -14,7 +14,7 @@ public:
~MaterialInstance();
virtual void save() override;
virtual void load() override;
inline std::string getMaterialName() const;
virtual PMaterial getRenderMaterial();
PMaterial getBaseMaterial() const;
Gfx::PDescriptorSet getDescriptor();
private: