Improving Material shader code generation
This commit is contained in:
@@ -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);
|
||||
@@ -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
|
||||
@@ -1,5 +1,7 @@
|
||||
target_sources(SeeleEngine
|
||||
PRIVATE
|
||||
BRDF.h
|
||||
BRDF.cpp
|
||||
Material.h
|
||||
Material.cpp
|
||||
MaterialAsset.h
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user