Handle shader options of any type
This commit is contained in:
parent
2f9e495739
commit
02a12d9328
|
|
@ -1,6 +1,6 @@
|
||||||
option HAS_DIFFUSE_TEXTURE: bool;
|
option HasDiffuseTexture: bool = false;
|
||||||
option HAS_ALPHA_TEXTURE: bool;
|
option HasAlphaTexture: bool = false;
|
||||||
option ALPHA_TEST: bool;
|
option AlphaTest: bool = false;
|
||||||
|
|
||||||
[layout(std140)]
|
[layout(std140)]
|
||||||
struct BasicSettings
|
struct BasicSettings
|
||||||
|
|
@ -57,15 +57,15 @@ struct OutputData
|
||||||
fn main(input: InputData) -> OutputData
|
fn main(input: InputData) -> OutputData
|
||||||
{
|
{
|
||||||
let diffuseColor = settings.DiffuseColor;
|
let diffuseColor = settings.DiffuseColor;
|
||||||
const if (HAS_DIFFUSE_TEXTURE)
|
const if (HasDiffuseTexture)
|
||||||
// TODO: diffuseColor *= MaterialDiffuseMap.Sample(input.uv)
|
// TODO: diffuseColor *= MaterialDiffuseMap.Sample(input.uv)
|
||||||
diffuseColor = diffuseColor * MaterialDiffuseMap.Sample(input.uv);
|
diffuseColor = diffuseColor * MaterialDiffuseMap.Sample(input.uv);
|
||||||
|
|
||||||
const if (HAS_ALPHA_TEXTURE)
|
const if (HasAlphaTexture)
|
||||||
// TODO: diffuseColor.w *= MaterialAlphaMap.Sample(input.uv)).x
|
// TODO: diffuseColor.w *= MaterialAlphaMap.Sample(input.uv)).x
|
||||||
diffuseColor = vec4<f32>(diffuseColor.x, diffuseColor.y, diffuseColor.z, (MaterialAlphaMap.Sample(input.uv)).x * diffuseColor.w);
|
diffuseColor = vec4<f32>(diffuseColor.x, diffuseColor.y, diffuseColor.z, (MaterialAlphaMap.Sample(input.uv)).x * diffuseColor.w);
|
||||||
|
|
||||||
const if (ALPHA_TEST)
|
const if (AlphaTest)
|
||||||
{
|
{
|
||||||
if (diffuseColor.w < settings.AlphaThreshold)
|
if (diffuseColor.w < settings.AlphaThreshold)
|
||||||
discard;
|
discard;
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ NAZARA_REQUEST_DEDICATED_GPU()
|
||||||
|
|
||||||
const char shaderSource[] = R"(
|
const char shaderSource[] = R"(
|
||||||
|
|
||||||
option red: bool;
|
option red: bool = false;
|
||||||
|
|
||||||
[layout(std140)]
|
[layout(std140)]
|
||||||
struct Data
|
struct Data
|
||||||
|
|
@ -109,7 +109,6 @@ int main()
|
||||||
}
|
}
|
||||||
|
|
||||||
Nz::ShaderWriter::States states;
|
Nz::ShaderWriter::States states;
|
||||||
states.enabledOptions = 0;
|
|
||||||
states.optimize = true;
|
states.optimize = true;
|
||||||
|
|
||||||
auto fragVertShader = device->InstantiateShaderModule(Nz::ShaderStageType::Fragment | Nz::ShaderStageType::Vertex, Nz::ShaderLanguage::NazaraShader, shaderSource, sizeof(shaderSource), states);
|
auto fragVertShader = device->InstantiateShaderModule(Nz::ShaderStageType::Fragment | Nz::ShaderStageType::Vertex, Nz::ShaderLanguage::NazaraShader, shaderSource, sizeof(shaderSource), states);
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ namespace Nz
|
||||||
inline void BasicMaterial::EnableAlphaTest(bool alphaTest)
|
inline void BasicMaterial::EnableAlphaTest(bool alphaTest)
|
||||||
{
|
{
|
||||||
NazaraAssert(HasAlphaTest(), "Material has no alpha test option");
|
NazaraAssert(HasAlphaTest(), "Material has no alpha test option");
|
||||||
m_material.EnableOption(m_optionIndexes.alphaTest, alphaTest);
|
m_material.SetOptionValue(m_optionIndexes.alphaTest, alphaTest);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const std::shared_ptr<Texture>& BasicMaterial::GetAlphaMap() const
|
inline const std::shared_ptr<Texture>& BasicMaterial::GetAlphaMap() const
|
||||||
|
|
@ -56,7 +56,11 @@ namespace Nz
|
||||||
inline bool BasicMaterial::IsAlphaTestEnabled() const
|
inline bool BasicMaterial::IsAlphaTestEnabled() const
|
||||||
{
|
{
|
||||||
NazaraAssert(HasAlphaTest(), "Material has no alpha test option");
|
NazaraAssert(HasAlphaTest(), "Material has no alpha test option");
|
||||||
return m_material.IsOptionEnabled(m_optionIndexes.alphaTest);
|
const auto& optionOpt = m_material.GetOptionValue(m_optionIndexes.alphaTest);
|
||||||
|
if (std::holds_alternative<ShaderAst::NoValue>(optionOpt))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return std::get<bool>(optionOpt);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool BasicMaterial::HasAlphaMap() const
|
inline bool BasicMaterial::HasAlphaMap() const
|
||||||
|
|
@ -91,7 +95,7 @@ namespace Nz
|
||||||
m_material.SetTexture(m_textureIndexes.alpha, std::move(alphaMap));
|
m_material.SetTexture(m_textureIndexes.alpha, std::move(alphaMap));
|
||||||
|
|
||||||
if (m_optionIndexes.hasDiffuseMap != MaterialSettings::InvalidIndex)
|
if (m_optionIndexes.hasDiffuseMap != MaterialSettings::InvalidIndex)
|
||||||
m_material.EnableOption(m_optionIndexes.hasAlphaMap, hasAlphaMap);
|
m_material.SetOptionValue(m_optionIndexes.hasAlphaMap, hasAlphaMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void BasicMaterial::SetAlphaSampler(TextureSamplerInfo alphaSampler)
|
inline void BasicMaterial::SetAlphaSampler(TextureSamplerInfo alphaSampler)
|
||||||
|
|
@ -107,7 +111,7 @@ namespace Nz
|
||||||
m_material.SetTexture(m_textureIndexes.diffuse, std::move(diffuseMap));
|
m_material.SetTexture(m_textureIndexes.diffuse, std::move(diffuseMap));
|
||||||
|
|
||||||
if (m_optionIndexes.hasDiffuseMap != MaterialSettings::InvalidIndex)
|
if (m_optionIndexes.hasDiffuseMap != MaterialSettings::InvalidIndex)
|
||||||
m_material.EnableOption(m_optionIndexes.hasDiffuseMap, hasDiffuseMap);
|
m_material.SetOptionValue(m_optionIndexes.hasDiffuseMap, hasDiffuseMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void BasicMaterial::SetDiffuseSampler(TextureSamplerInfo diffuseSampler)
|
inline void BasicMaterial::SetDiffuseSampler(TextureSamplerInfo diffuseSampler)
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
#include <Nazara/Graphics/MaterialPipeline.hpp>
|
#include <Nazara/Graphics/MaterialPipeline.hpp>
|
||||||
#include <Nazara/Renderer/Texture.hpp>
|
#include <Nazara/Renderer/Texture.hpp>
|
||||||
#include <Nazara/Renderer/TextureSampler.hpp>
|
#include <Nazara/Renderer/TextureSampler.hpp>
|
||||||
|
#include <Nazara/Shader/Ast/ConstantValue.hpp>
|
||||||
#include <Nazara/Utility/UniformBuffer.hpp>
|
#include <Nazara/Utility/UniformBuffer.hpp>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
@ -45,7 +46,6 @@ namespace Nz
|
||||||
inline void EnableDepthClamp(bool depthClamp);
|
inline void EnableDepthClamp(bool depthClamp);
|
||||||
inline void EnableDepthWrite(bool depthWrite);
|
inline void EnableDepthWrite(bool depthWrite);
|
||||||
inline void EnableFaceCulling(bool faceCulling);
|
inline void EnableFaceCulling(bool faceCulling);
|
||||||
inline void EnableOption(std::size_t optionIndex, bool enable);
|
|
||||||
inline void EnableScissorTest(bool scissorTest);
|
inline void EnableScissorTest(bool scissorTest);
|
||||||
inline void EnableStencilTest(bool stencilTest);
|
inline void EnableStencilTest(bool stencilTest);
|
||||||
|
|
||||||
|
|
@ -61,6 +61,7 @@ namespace Nz
|
||||||
inline FaceSide GetFaceCulling() const;
|
inline FaceSide GetFaceCulling() const;
|
||||||
inline FaceFilling GetFaceFilling() const;
|
inline FaceFilling GetFaceFilling() const;
|
||||||
inline float GetLineWidth() const;
|
inline float GetLineWidth() const;
|
||||||
|
inline const ShaderAst::ConstantValue& GetOptionValue(std::size_t optionIndex) const;
|
||||||
inline const std::shared_ptr<MaterialPipeline>& GetPipeline() const;
|
inline const std::shared_ptr<MaterialPipeline>& GetPipeline() const;
|
||||||
inline const MaterialPipelineInfo& GetPipelineInfo() const;
|
inline const MaterialPipelineInfo& GetPipelineInfo() const;
|
||||||
inline float GetPointSize() const;
|
inline float GetPointSize() const;
|
||||||
|
|
@ -82,7 +83,6 @@ namespace Nz
|
||||||
inline bool IsDepthClampEnabled() const;
|
inline bool IsDepthClampEnabled() const;
|
||||||
inline bool IsDepthWriteEnabled() const;
|
inline bool IsDepthWriteEnabled() const;
|
||||||
inline bool IsFaceCullingEnabled() const;
|
inline bool IsFaceCullingEnabled() const;
|
||||||
inline bool IsOptionEnabled(std::size_t optionIndex) const;
|
|
||||||
inline bool IsScissorTestEnabled() const;
|
inline bool IsScissorTestEnabled() const;
|
||||||
inline bool IsStencilTestEnabled() const;
|
inline bool IsStencilTestEnabled() const;
|
||||||
|
|
||||||
|
|
@ -92,6 +92,7 @@ namespace Nz
|
||||||
inline void SetFaceCulling(FaceSide faceSide);
|
inline void SetFaceCulling(FaceSide faceSide);
|
||||||
inline void SetFaceFilling(FaceFilling filling);
|
inline void SetFaceFilling(FaceFilling filling);
|
||||||
inline void SetLineWidth(float lineWidth);
|
inline void SetLineWidth(float lineWidth);
|
||||||
|
inline void SetOptionValue(std::size_t optionIndex, ShaderAst::ConstantValue value);
|
||||||
inline void SetPointSize(float pointSize);
|
inline void SetPointSize(float pointSize);
|
||||||
inline void SetPrimitiveMode(PrimitiveMode mode);
|
inline void SetPrimitiveMode(PrimitiveMode mode);
|
||||||
inline void SetTexture(std::size_t textureIndex, std::shared_ptr<Texture> texture);
|
inline void SetTexture(std::size_t textureIndex, std::shared_ptr<Texture> texture);
|
||||||
|
|
@ -126,11 +127,11 @@ namespace Nz
|
||||||
bool dataInvalidated = true;
|
bool dataInvalidated = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::array<ShaderAst::ConstantValue, 64> m_optionValues;
|
||||||
std::shared_ptr<const MaterialSettings> m_settings;
|
std::shared_ptr<const MaterialSettings> m_settings;
|
||||||
std::vector<MaterialTexture> m_textures;
|
std::vector<MaterialTexture> m_textures;
|
||||||
std::vector<UniformBuffer> m_uniformBuffers;
|
std::vector<UniformBuffer> m_uniformBuffers;
|
||||||
mutable std::shared_ptr<MaterialPipeline> m_pipeline;
|
mutable std::shared_ptr<MaterialPipeline> m_pipeline;
|
||||||
UInt64 m_enabledOptions;
|
|
||||||
mutable MaterialPipelineInfo m_pipelineInfo;
|
mutable MaterialPipelineInfo m_pipelineInfo;
|
||||||
ShaderBindingPtr m_shaderBinding;
|
ShaderBindingPtr m_shaderBinding;
|
||||||
bool m_forceCommandBufferRegeneration;
|
bool m_forceCommandBufferRegeneration;
|
||||||
|
|
|
||||||
|
|
@ -182,15 +182,6 @@ namespace Nz
|
||||||
InvalidatePipeline();
|
InvalidatePipeline();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void MaterialPass::EnableOption(std::size_t optionIndex, bool enable)
|
|
||||||
{
|
|
||||||
if (TestBit<UInt64>(m_enabledOptions, optionIndex) != enable)
|
|
||||||
{
|
|
||||||
m_enabledOptions = ToggleBit<UInt64>(m_enabledOptions, optionIndex);
|
|
||||||
InvalidatePipeline();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Enable/Disable scissor test for this material
|
* \brief Enable/Disable scissor test for this material
|
||||||
*
|
*
|
||||||
|
|
@ -315,6 +306,12 @@ namespace Nz
|
||||||
return m_pipelineInfo.lineWidth;
|
return m_pipelineInfo.lineWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline const ShaderAst::ConstantValue& MaterialPass::GetOptionValue(std::size_t optionIndex) const
|
||||||
|
{
|
||||||
|
assert(optionIndex < m_optionValues.size());
|
||||||
|
return m_optionValues[optionIndex];
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Gets the render states
|
* \brief Gets the render states
|
||||||
* \return Constant reference to the render states
|
* \return Constant reference to the render states
|
||||||
|
|
@ -461,11 +458,6 @@ namespace Nz
|
||||||
return m_pipelineInfo.faceCulling;
|
return m_pipelineInfo.faceCulling;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool MaterialPass::IsOptionEnabled(std::size_t optionIndex) const
|
|
||||||
{
|
|
||||||
return TestBit<UInt64>(m_enabledOptions, optionIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Checks whether this material has scissor test enabled
|
* \brief Checks whether this material has scissor test enabled
|
||||||
* \return true If it is the case
|
* \return true If it is the case
|
||||||
|
|
@ -562,6 +554,16 @@ namespace Nz
|
||||||
InvalidatePipeline();
|
InvalidatePipeline();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void MaterialPass::SetOptionValue(std::size_t optionIndex, ShaderAst::ConstantValue value)
|
||||||
|
{
|
||||||
|
assert(optionIndex < m_optionValues.size());
|
||||||
|
if (m_optionValues[optionIndex] != value)
|
||||||
|
{
|
||||||
|
m_optionValues[optionIndex] = std::move(value);
|
||||||
|
InvalidatePipeline();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Sets the point size for this material
|
* \brief Sets the point size for this material
|
||||||
*
|
*
|
||||||
|
|
@ -654,3 +656,4 @@ namespace Nz
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <Nazara/Graphics/DebugOff.hpp>
|
#include <Nazara/Graphics/DebugOff.hpp>
|
||||||
|
#include "MaterialPass.hpp"
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
#include <Nazara/Graphics/Enums.hpp>
|
#include <Nazara/Graphics/Enums.hpp>
|
||||||
#include <Nazara/Graphics/MaterialSettings.hpp>
|
#include <Nazara/Graphics/MaterialSettings.hpp>
|
||||||
#include <Nazara/Renderer/RenderPipeline.hpp>
|
#include <Nazara/Renderer/RenderPipeline.hpp>
|
||||||
|
#include <Nazara/Shader/Ast/ConstantValue.hpp>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
|
@ -23,8 +24,8 @@ namespace Nz
|
||||||
{
|
{
|
||||||
struct Shader
|
struct Shader
|
||||||
{
|
{
|
||||||
|
std::array<ShaderAst::ConstantValue, 32> optionValues;
|
||||||
std::shared_ptr<UberShader> uberShader;
|
std::shared_ptr<UberShader> uberShader;
|
||||||
Nz::UInt64 enabledOptions = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<Shader> shaders;
|
std::vector<Shader> shaders;
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ namespace Nz
|
||||||
|
|
||||||
for (std::size_t i = 0; i < lhs.shaders.size(); ++i)
|
for (std::size_t i = 0; i < lhs.shaders.size(); ++i)
|
||||||
{
|
{
|
||||||
if (lhs.shaders[i].enabledOptions != rhs.shaders[i].enabledOptions)
|
if (lhs.shaders[i].optionValues != rhs.shaders[i].optionValues)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (lhs.shaders[i].uberShader != rhs.shaders[i].uberShader)
|
if (lhs.shaders[i].uberShader != rhs.shaders[i].uberShader)
|
||||||
|
|
@ -73,7 +73,9 @@ namespace std
|
||||||
|
|
||||||
for (const auto& shader : pipelineInfo.shaders)
|
for (const auto& shader : pipelineInfo.shaders)
|
||||||
{
|
{
|
||||||
Nz::HashCombine(seed, shader.enabledOptions);
|
for (const auto& value : shader.optionValues)
|
||||||
|
Nz::HashCombine(seed, value);
|
||||||
|
|
||||||
Nz::HashCombine(seed, shader.uberShader.get());
|
Nz::HashCombine(seed, shader.uberShader.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ namespace Nz
|
||||||
|
|
||||||
static constexpr std::size_t InvalidIndex = std::numeric_limits<std::size_t>::max();
|
static constexpr std::size_t InvalidIndex = std::numeric_limits<std::size_t>::max();
|
||||||
|
|
||||||
static void BuildOption(std::vector<Option>& options, const std::vector<std::shared_ptr<UberShader>>& uberShaders, std::string optionName, const std::string& shaderOptionName);
|
static inline void BuildOption(std::vector<Option>& options, const std::vector<std::shared_ptr<UberShader>>& uberShaders, std::string optionName, const std::string& shaderOptionName);
|
||||||
|
|
||||||
struct Builder
|
struct Builder
|
||||||
{
|
{
|
||||||
|
|
@ -69,7 +69,7 @@ namespace Nz
|
||||||
struct Option
|
struct Option
|
||||||
{
|
{
|
||||||
std::string name;
|
std::string name;
|
||||||
std::array<UInt64, ShaderStageTypeCount> enabledOptions;
|
std::vector<std::optional<std::size_t>> optionIndexByShader;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct UniformVariable
|
struct UniformVariable
|
||||||
|
|
|
||||||
|
|
@ -168,22 +168,23 @@ namespace Nz
|
||||||
|
|
||||||
inline void MaterialSettings::BuildOption(std::vector<Option>& options, const std::vector<std::shared_ptr<UberShader>>& uberShaders, std::string optionName, const std::string& shaderOptionName)
|
inline void MaterialSettings::BuildOption(std::vector<Option>& options, const std::vector<std::shared_ptr<UberShader>>& uberShaders, std::string optionName, const std::string& shaderOptionName)
|
||||||
{
|
{
|
||||||
std::array<UInt64, ShaderStageTypeCount> shaderOptions;
|
std::vector<std::optional<std::size_t>> shaderOptions;
|
||||||
shaderOptions.fill(0);
|
|
||||||
|
|
||||||
for (std::size_t i = 0; i < ShaderStageTypeCount; ++i)
|
for (std::size_t shaderIndex = 0; shaderIndex < uberShaders.size(); ++shaderIndex)
|
||||||
{
|
{
|
||||||
for (const auto& uberShader : uberShaders)
|
const auto& uberShader = uberShaders[shaderIndex];
|
||||||
|
|
||||||
|
const UberShader::Option* optionData;
|
||||||
|
if (uberShader->HasOption(shaderOptionName, &optionData))
|
||||||
{
|
{
|
||||||
if (uberShader->GetSupportedStages() & static_cast<ShaderStageType>(i))
|
if (shaderIndex >= shaderOptions.size())
|
||||||
{
|
shaderOptions.resize(shaderIndex + 1);
|
||||||
assert(shaderOptions[i] == 0);
|
|
||||||
shaderOptions[i] |= uberShader->GetOptionFlagByName(shaderOptionName);
|
shaderOptions[shaderIndex] = optionData->index;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (std::any_of(shaderOptions.begin(), shaderOptions.end(), [&](UInt64 flags) { return flags != 0; }))
|
if (std::any_of(shaderOptions.begin(), shaderOptions.end(), [&](std::optional<std::size_t> optionIndex) { return optionIndex.has_value(); }))
|
||||||
{
|
{
|
||||||
options.push_back({
|
options.push_back({
|
||||||
std::move(optionName),
|
std::move(optionName),
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,10 @@
|
||||||
#define NAZARA_UBER_SHADER_HPP
|
#define NAZARA_UBER_SHADER_HPP
|
||||||
|
|
||||||
#include <Nazara/Prerequisites.hpp>
|
#include <Nazara/Prerequisites.hpp>
|
||||||
|
#include <Nazara/Core/Algorithm.hpp>
|
||||||
#include <Nazara/Core/Bitset.hpp>
|
#include <Nazara/Core/Bitset.hpp>
|
||||||
#include <Nazara/Graphics/Config.hpp>
|
#include <Nazara/Graphics/Config.hpp>
|
||||||
|
#include <Nazara/Renderer/RenderPipeline.hpp>
|
||||||
#include <Nazara/Shader/Ast/Nodes.hpp>
|
#include <Nazara/Shader/Ast/Nodes.hpp>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
|
@ -20,21 +22,45 @@ namespace Nz
|
||||||
class NAZARA_GRAPHICS_API UberShader
|
class NAZARA_GRAPHICS_API UberShader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
struct Config;
|
||||||
|
struct Option;
|
||||||
UberShader(ShaderStageTypeFlags shaderStages, const ShaderAst::StatementPtr& shaderAst);
|
UberShader(ShaderStageTypeFlags shaderStages, const ShaderAst::StatementPtr& shaderAst);
|
||||||
~UberShader() = default;
|
~UberShader() = default;
|
||||||
|
|
||||||
UInt64 GetOptionFlagByName(const std::string& optionName) const;
|
|
||||||
|
|
||||||
inline ShaderStageTypeFlags GetSupportedStages() const;
|
inline ShaderStageTypeFlags GetSupportedStages() const;
|
||||||
|
|
||||||
const std::shared_ptr<ShaderModule>& Get(UInt64 combination);
|
const std::shared_ptr<ShaderModule>& Get(const Config& config);
|
||||||
|
|
||||||
|
inline bool HasOption(const std::string& optionName, Pointer<const Option>* option = nullptr) const;
|
||||||
|
|
||||||
|
static constexpr std::size_t MaximumOptionValue = 32;
|
||||||
|
|
||||||
|
struct Config
|
||||||
|
{
|
||||||
|
std::array<ShaderAst::ConstantValue, MaximumOptionValue> optionValues;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ConfigEqual
|
||||||
|
{
|
||||||
|
inline bool operator()(const Config& lhs, const Config& rhs) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ConfigHasher
|
||||||
|
{
|
||||||
|
inline std::size_t operator()(const Config& config) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Option
|
||||||
|
{
|
||||||
|
std::size_t index;
|
||||||
|
ShaderAst::ExpressionType type;
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unordered_map<UInt64 /*combination*/, std::shared_ptr<ShaderModule>> m_combinations;
|
std::unordered_map<Config, std::shared_ptr<ShaderModule>, ConfigHasher, ConfigEqual> m_combinations;
|
||||||
std::unordered_map<std::string, std::size_t> m_optionIndexByName;
|
std::unordered_map<std::string, Option> m_optionIndexByName;
|
||||||
ShaderAst::StatementPtr m_shaderAst;
|
ShaderAst::StatementPtr m_shaderAst;
|
||||||
ShaderStageTypeFlags m_shaderStages;
|
ShaderStageTypeFlags m_shaderStages;
|
||||||
UInt64 m_combinationMask;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,38 @@ namespace Nz
|
||||||
{
|
{
|
||||||
return m_shaderStages;
|
return m_shaderStages;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool UberShader::HasOption(const std::string& optionName, Pointer<const Option>* option) const
|
||||||
|
{
|
||||||
|
auto it = m_optionIndexByName.find(optionName);
|
||||||
|
if (it == m_optionIndexByName.end())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (option)
|
||||||
|
*option = &it->second;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool UberShader::ConfigEqual::operator()(const Config& lhs, const Config& rhs) const
|
||||||
|
{
|
||||||
|
for (std::size_t i = 0; i < lhs.optionValues.size(); ++i)
|
||||||
|
{
|
||||||
|
if (lhs.optionValues[i] != rhs.optionValues[i])
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::size_t UberShader::ConfigHasher::operator()(const Config& config) const
|
||||||
|
{
|
||||||
|
std::size_t hash = 0;
|
||||||
|
for (std::size_t i = 0; i < config.optionValues.size(); ++i)
|
||||||
|
HashCombine(hash, config.optionValues[i]);
|
||||||
|
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <Nazara/Graphics/DebugOff.hpp>
|
#include <Nazara/Graphics/DebugOff.hpp>
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
#include <Nazara/Shader/Config.hpp>
|
#include <Nazara/Shader/Config.hpp>
|
||||||
#include <Nazara/Shader/Ast/AstCloner.hpp>
|
#include <Nazara/Shader/Ast/AstCloner.hpp>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace Nz::ShaderAst
|
namespace Nz::ShaderAst
|
||||||
|
|
@ -36,7 +37,6 @@ namespace Nz::ShaderAst
|
||||||
struct Options
|
struct Options
|
||||||
{
|
{
|
||||||
std::function<const ConstantValue&(std::size_t constantId)> constantQueryCallback;
|
std::function<const ConstantValue&(std::size_t constantId)> constantQueryCallback;
|
||||||
std::optional<UInt64> enabledOptions = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,10 @@
|
||||||
|
|
||||||
namespace Nz::ShaderAst
|
namespace Nz::ShaderAst
|
||||||
{
|
{
|
||||||
|
using NoValue = std::monostate;
|
||||||
|
|
||||||
using ConstantTypes = TypeList<
|
using ConstantTypes = TypeList<
|
||||||
|
NoValue,
|
||||||
bool,
|
bool,
|
||||||
float,
|
float,
|
||||||
Int32,
|
Int32,
|
||||||
|
|
|
||||||
|
|
@ -302,7 +302,7 @@ namespace Nz::ShaderAst
|
||||||
|
|
||||||
std::optional<std::size_t> optIndex;
|
std::optional<std::size_t> optIndex;
|
||||||
std::string optName;
|
std::string optName;
|
||||||
ExpressionPtr initialValue;
|
ExpressionPtr defaultValue;
|
||||||
ExpressionType optType;
|
ExpressionType optType;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ namespace Nz::ShaderAst
|
||||||
struct Options
|
struct Options
|
||||||
{
|
{
|
||||||
std::unordered_set<std::string> reservedIdentifiers;
|
std::unordered_set<std::string> reservedIdentifiers;
|
||||||
UInt64 enabledOptions = 0;
|
std::unordered_map<std::size_t, ConstantValue> optionValues;
|
||||||
bool makeVariableNameUnique = false;
|
bool makeVariableNameUnique = false;
|
||||||
bool removeOptionDeclaration = true;
|
bool removeOptionDeclaration = true;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ namespace Nz
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char* GetFlipYUniformName();
|
static const char* GetFlipYUniformName();
|
||||||
static ShaderAst::StatementPtr Sanitize(ShaderAst::Statement& ast, UInt64 enabledOptions, std::string* error = nullptr);
|
static ShaderAst::StatementPtr Sanitize(ShaderAst::Statement& ast, std::unordered_map<std::size_t, ShaderAst::ConstantValue> optionValues, std::string* error = nullptr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Append(const ShaderAst::ExpressionType& type);
|
void Append(const ShaderAst::ExpressionType& type);
|
||||||
|
|
|
||||||
|
|
@ -198,7 +198,7 @@ namespace Nz::ShaderBuilder
|
||||||
auto declareOptionNode = std::make_unique<ShaderAst::DeclareOptionStatement>();
|
auto declareOptionNode = std::make_unique<ShaderAst::DeclareOptionStatement>();
|
||||||
declareOptionNode->optName = std::move(name);
|
declareOptionNode->optName = std::move(name);
|
||||||
declareOptionNode->optType = std::move(type);
|
declareOptionNode->optType = std::move(type);
|
||||||
declareOptionNode->initialValue = std::move(initialValue);
|
declareOptionNode->defaultValue = std::move(initialValue);
|
||||||
|
|
||||||
return declareOptionNode;
|
return declareOptionNode;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,9 @@
|
||||||
|
|
||||||
#include <Nazara/Prerequisites.hpp>
|
#include <Nazara/Prerequisites.hpp>
|
||||||
#include <Nazara/Shader/Config.hpp>
|
#include <Nazara/Shader/Config.hpp>
|
||||||
|
#include <Nazara/Shader/Ast/ConstantValue.hpp>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_set>
|
#include <unordered_map>
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
|
|
@ -26,7 +27,7 @@ namespace Nz
|
||||||
|
|
||||||
struct States
|
struct States
|
||||||
{
|
{
|
||||||
Nz::UInt64 enabledOptions = 0;
|
std::unordered_map<std::size_t, ShaderAst::ConstantValue> optionValues;
|
||||||
bool optimize = false;
|
bool optimize = false;
|
||||||
bool sanitized = false;
|
bool sanitized = false;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -63,8 +63,6 @@ namespace Nz
|
||||||
UInt32 GetPointerTypeId(const ShaderAst::ExpressionType& type, SpirvStorageClass storageClass) const;
|
UInt32 GetPointerTypeId(const ShaderAst::ExpressionType& type, SpirvStorageClass storageClass) const;
|
||||||
UInt32 GetTypeId(const ShaderAst::ExpressionType& type) const;
|
UInt32 GetTypeId(const ShaderAst::ExpressionType& type) const;
|
||||||
|
|
||||||
bool IsOptionEnabled(std::size_t optionIndex) const;
|
|
||||||
|
|
||||||
UInt32 RegisterConstant(const ShaderAst::ConstantValue& value);
|
UInt32 RegisterConstant(const ShaderAst::ConstantValue& value);
|
||||||
UInt32 RegisterFunctionType(const ShaderAst::DeclareFunctionStatement& functionNode);
|
UInt32 RegisterFunctionType(const ShaderAst::DeclareFunctionStatement& functionNode);
|
||||||
UInt32 RegisterPointerType(ShaderAst::ExpressionType type, SpirvStorageClass storageClass);
|
UInt32 RegisterPointerType(ShaderAst::ExpressionType type, SpirvStorageClass storageClass);
|
||||||
|
|
|
||||||
|
|
@ -1,597 +0,0 @@
|
||||||
{
|
|
||||||
"buffers": [
|
|
||||||
{
|
|
||||||
"bindingIndex": 0,
|
|
||||||
"name": "viewerData",
|
|
||||||
"setIndex": 0,
|
|
||||||
"structIndex": 2,
|
|
||||||
"type": "UniformBufferObject"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"bindingIndex": 0,
|
|
||||||
"name": "instanceData",
|
|
||||||
"setIndex": 1,
|
|
||||||
"structIndex": 1,
|
|
||||||
"type": "UniformBufferObject"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"bindingIndex": 0,
|
|
||||||
"name": "settings",
|
|
||||||
"setIndex": 2,
|
|
||||||
"structIndex": 0,
|
|
||||||
"type": "UniformBufferObject"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"conditions": [
|
|
||||||
{
|
|
||||||
"name": "HAS_DIFFUSE_TEXTURE"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "HAS_ALPHA_TEXTURE"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "ALPHA_TEST"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"connections": [
|
|
||||||
{
|
|
||||||
"in_id": "{fc7542b2-5752-4891-98c1-35b498da257b}",
|
|
||||||
"in_index": 1,
|
|
||||||
"out_id": "{743930bd-1d81-4d4c-b7ec-175a34838d69}",
|
|
||||||
"out_index": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"in_id": "{359a78e1-df0d-467f-907e-7bff04a55db5}",
|
|
||||||
"in_index": 0,
|
|
||||||
"out_id": "{becdd0d4-2b28-44f5-86c2-2ed6b846326c}",
|
|
||||||
"out_index": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"in_id": "{359a78e1-df0d-467f-907e-7bff04a55db5}",
|
|
||||||
"in_index": 3,
|
|
||||||
"out_id": "{93fdbb4c-bc81-4100-89a9-b465793099b9}",
|
|
||||||
"out_index": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"in_id": "{7750a050-b116-4e1b-bd89-b194c366d256}",
|
|
||||||
"in_index": 1,
|
|
||||||
"out_id": "{ca2c2ac5-39e0-4814-9432-fbf3e20d3cad}",
|
|
||||||
"out_index": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"in_id": "{bed466d8-5ed0-4e8a-bba7-1c809cb4c3f7}",
|
|
||||||
"in_index": 1,
|
|
||||||
"out_id": "{07a43c79-67e2-46b1-87d4-e00d2da22820}",
|
|
||||||
"out_index": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"in_id": "{6fcfbcd0-c2df-41dd-bb50-74b455b9021f}",
|
|
||||||
"in_index": 0,
|
|
||||||
"out_id": "{7750a050-b116-4e1b-bd89-b194c366d256}",
|
|
||||||
"out_index": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"in_id": "{d7acd173-9188-43b5-bfa1-31f17dff44ad}",
|
|
||||||
"in_index": 1,
|
|
||||||
"out_id": "{1f9d52d7-4f44-4d96-8edb-fbc1239a93bb}",
|
|
||||||
"out_index": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"in_id": "{be3547ff-0bf3-4701-9c27-c21e9d1322c3}",
|
|
||||||
"in_index": 0,
|
|
||||||
"out_id": "{92d95fe0-84f6-4d27-91ea-992d5f73c04e}",
|
|
||||||
"out_index": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"in_id": "{fc7542b2-5752-4891-98c1-35b498da257b}",
|
|
||||||
"in_index": 0,
|
|
||||||
"out_id": "{bb071807-e65e-4c31-acf0-d296efa665fa}",
|
|
||||||
"out_index": 3
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"in_id": "{92d95fe0-84f6-4d27-91ea-992d5f73c04e}",
|
|
||||||
"in_index": 0,
|
|
||||||
"out_id": "{359a78e1-df0d-467f-907e-7bff04a55db5}",
|
|
||||||
"out_index": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"in_id": "{359a78e1-df0d-467f-907e-7bff04a55db5}",
|
|
||||||
"in_index": 2,
|
|
||||||
"out_id": "{becdd0d4-2b28-44f5-86c2-2ed6b846326c}",
|
|
||||||
"out_index": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"in_id": "{becdd0d4-2b28-44f5-86c2-2ed6b846326c}",
|
|
||||||
"in_index": 0,
|
|
||||||
"out_id": "{e1f86d56-eb21-4267-9075-e6b0cc875a6d}",
|
|
||||||
"out_index": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"in_id": "{7750a050-b116-4e1b-bd89-b194c366d256}",
|
|
||||||
"in_index": 0,
|
|
||||||
"out_id": "{f9ba0cce-3b85-4f95-a79e-a2f64d955d89}",
|
|
||||||
"out_index": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"in_id": "{93fdbb4c-bc81-4100-89a9-b465793099b9}",
|
|
||||||
"in_index": 0,
|
|
||||||
"out_id": "{6fcfbcd0-c2df-41dd-bb50-74b455b9021f}",
|
|
||||||
"out_index": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"in_id": "{359a78e1-df0d-467f-907e-7bff04a55db5}",
|
|
||||||
"in_index": 1,
|
|
||||||
"out_id": "{becdd0d4-2b28-44f5-86c2-2ed6b846326c}",
|
|
||||||
"out_index": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"in_id": "{e1f86d56-eb21-4267-9075-e6b0cc875a6d}",
|
|
||||||
"in_index": 1,
|
|
||||||
"out_id": "{07a43c79-67e2-46b1-87d4-e00d2da22820}",
|
|
||||||
"out_index": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"in_id": "{3cdb5bb1-f572-4055-a1af-460b152b0c13}",
|
|
||||||
"in_index": 0,
|
|
||||||
"out_id": "{d7acd173-9188-43b5-bfa1-31f17dff44ad}",
|
|
||||||
"out_index": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"in_id": "{fbaddbbe-f9cd-4e8d-b7a8-40c10c96f580}",
|
|
||||||
"in_index": 0,
|
|
||||||
"out_id": "{ac98a68f-0160-4189-af31-b8278e7c119c}",
|
|
||||||
"out_index": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"in_id": "{e1f86d56-eb21-4267-9075-e6b0cc875a6d}",
|
|
||||||
"in_index": 0,
|
|
||||||
"out_id": "{bed466d8-5ed0-4e8a-bba7-1c809cb4c3f7}",
|
|
||||||
"out_index": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"in_id": "{93fdbb4c-bc81-4100-89a9-b465793099b9}",
|
|
||||||
"in_index": 1,
|
|
||||||
"out_id": "{becdd0d4-2b28-44f5-86c2-2ed6b846326c}",
|
|
||||||
"out_index": 3
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"in_id": "{d7acd173-9188-43b5-bfa1-31f17dff44ad}",
|
|
||||||
"in_index": 0,
|
|
||||||
"out_id": "{fc7542b2-5752-4891-98c1-35b498da257b}",
|
|
||||||
"out_index": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"in_id": "{bed466d8-5ed0-4e8a-bba7-1c809cb4c3f7}",
|
|
||||||
"in_index": 0,
|
|
||||||
"out_id": "{fbaddbbe-f9cd-4e8d-b7a8-40c10c96f580}",
|
|
||||||
"out_index": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"in_id": "{92d95fe0-84f6-4d27-91ea-992d5f73c04e}",
|
|
||||||
"in_index": 1,
|
|
||||||
"out_id": "{e1f86d56-eb21-4267-9075-e6b0cc875a6d}",
|
|
||||||
"out_index": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"in_id": "{fbaddbbe-f9cd-4e8d-b7a8-40c10c96f580}",
|
|
||||||
"in_index": 1,
|
|
||||||
"out_id": "{5e4c18b3-9a7f-4c0e-abe4-778be151ad06}",
|
|
||||||
"out_index": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"in_id": "{bb071807-e65e-4c31-acf0-d296efa665fa}",
|
|
||||||
"in_index": 0,
|
|
||||||
"out_id": "{92d95fe0-84f6-4d27-91ea-992d5f73c04e}",
|
|
||||||
"out_index": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"inputs": [
|
|
||||||
{
|
|
||||||
"locationIndex": 0,
|
|
||||||
"name": "vertUV",
|
|
||||||
"role": "TexCoord",
|
|
||||||
"roleIndex": 0,
|
|
||||||
"type": "Float2"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"nodes": [
|
|
||||||
{
|
|
||||||
"id": "{becdd0d4-2b28-44f5-86c2-2ed6b846326c}",
|
|
||||||
"model": {
|
|
||||||
"name": "vec_decompose",
|
|
||||||
"preview_enabled": false,
|
|
||||||
"preview_height": 64,
|
|
||||||
"preview_width": 64,
|
|
||||||
"variable_name": ""
|
|
||||||
},
|
|
||||||
"position": {
|
|
||||||
"x": 1005.0000000000002,
|
|
||||||
"y": 201.76
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "{fbaddbbe-f9cd-4e8d-b7a8-40c10c96f580}",
|
|
||||||
"model": {
|
|
||||||
"name": "SampleTexture",
|
|
||||||
"preview_enabled": false,
|
|
||||||
"preview_height": 64,
|
|
||||||
"preview_width": 64,
|
|
||||||
"variable_name": ""
|
|
||||||
},
|
|
||||||
"position": {
|
|
||||||
"x": 167.75,
|
|
||||||
"y": 473.97222222222194
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "{ac98a68f-0160-4189-af31-b8278e7c119c}",
|
|
||||||
"model": {
|
|
||||||
"name": "Texture",
|
|
||||||
"preview_enabled": true,
|
|
||||||
"preview_height": 64,
|
|
||||||
"preview_width": 64,
|
|
||||||
"texture": "MaterialDiffuseMap",
|
|
||||||
"variable_name": ""
|
|
||||||
},
|
|
||||||
"position": {
|
|
||||||
"x": -10.194444444444457,
|
|
||||||
"y": 445
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "{be3547ff-0bf3-4701-9c27-c21e9d1322c3}",
|
|
||||||
"model": {
|
|
||||||
"name": "Output",
|
|
||||||
"output": "RenderTarget0",
|
|
||||||
"preview_enabled": true,
|
|
||||||
"preview_height": 128,
|
|
||||||
"preview_width": 128,
|
|
||||||
"variable_name": ""
|
|
||||||
},
|
|
||||||
"position": {
|
|
||||||
"x": 2598.5,
|
|
||||||
"y": 293.33333333333326
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "{93fdbb4c-bc81-4100-89a9-b465793099b9}",
|
|
||||||
"model": {
|
|
||||||
"name": "float_mul",
|
|
||||||
"preview_enabled": false,
|
|
||||||
"preview_height": 64,
|
|
||||||
"preview_width": 64,
|
|
||||||
"variable_name": ""
|
|
||||||
},
|
|
||||||
"position": {
|
|
||||||
"x": 1209.686666666667,
|
|
||||||
"y": 316.4066666666666
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "{bed466d8-5ed0-4e8a-bba7-1c809cb4c3f7}",
|
|
||||||
"model": {
|
|
||||||
"name": "vec_mul",
|
|
||||||
"preview_enabled": false,
|
|
||||||
"preview_height": 64,
|
|
||||||
"preview_width": 64,
|
|
||||||
"variable_name": ""
|
|
||||||
},
|
|
||||||
"position": {
|
|
||||||
"x": 377.1388888888888,
|
|
||||||
"y": 507.83333333333337
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "{07a43c79-67e2-46b1-87d4-e00d2da22820}",
|
|
||||||
"model": {
|
|
||||||
"buffer": "settings",
|
|
||||||
"field": "DiffuseColor",
|
|
||||||
"name": "BufferField",
|
|
||||||
"preview_enabled": false,
|
|
||||||
"preview_height": 64,
|
|
||||||
"preview_width": 64,
|
|
||||||
"variable_name": ""
|
|
||||||
},
|
|
||||||
"position": {
|
|
||||||
"x": 135.11111111111126,
|
|
||||||
"y": 643.5277777777775
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "{e1f86d56-eb21-4267-9075-e6b0cc875a6d}",
|
|
||||||
"model": {
|
|
||||||
"condition_name": "HAS_DIFFUSE_TEXTURE",
|
|
||||||
"name": "ConditionalExpression",
|
|
||||||
"preview_enabled": true,
|
|
||||||
"preview_height": 128,
|
|
||||||
"preview_width": 128,
|
|
||||||
"variable_name": ""
|
|
||||||
},
|
|
||||||
"position": {
|
|
||||||
"x": 602.5,
|
|
||||||
"y": 566.5
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "{ca2c2ac5-39e0-4814-9432-fbf3e20d3cad}",
|
|
||||||
"model": {
|
|
||||||
"input": "vertUV",
|
|
||||||
"name": "Input",
|
|
||||||
"preview_enabled": false,
|
|
||||||
"preview_height": 64,
|
|
||||||
"preview_width": 64,
|
|
||||||
"variable_name": ""
|
|
||||||
},
|
|
||||||
"position": {
|
|
||||||
"x": 646.0466666666667,
|
|
||||||
"y": 47.54000000000002
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "{f9ba0cce-3b85-4f95-a79e-a2f64d955d89}",
|
|
||||||
"model": {
|
|
||||||
"name": "Texture",
|
|
||||||
"preview_enabled": true,
|
|
||||||
"preview_height": 64,
|
|
||||||
"preview_width": 64,
|
|
||||||
"texture": "MaterialAlphaMap",
|
|
||||||
"variable_name": ""
|
|
||||||
},
|
|
||||||
"position": {
|
|
||||||
"x": 592.2799999999996,
|
|
||||||
"y": -30.780000000000058
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "{7750a050-b116-4e1b-bd89-b194c366d256}",
|
|
||||||
"model": {
|
|
||||||
"name": "SampleTexture",
|
|
||||||
"preview_enabled": false,
|
|
||||||
"preview_height": 64,
|
|
||||||
"preview_width": 64,
|
|
||||||
"variable_name": ""
|
|
||||||
},
|
|
||||||
"position": {
|
|
||||||
"x": 819.5933333333332,
|
|
||||||
"y": 6.606666666666669
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "{6fcfbcd0-c2df-41dd-bb50-74b455b9021f}",
|
|
||||||
"model": {
|
|
||||||
"name": "vec_decompose",
|
|
||||||
"preview_enabled": false,
|
|
||||||
"preview_height": 64,
|
|
||||||
"preview_width": 64,
|
|
||||||
"variable_name": ""
|
|
||||||
},
|
|
||||||
"position": {
|
|
||||||
"x": 1011.3799999999998,
|
|
||||||
"y": 21.560000000000016
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "{359a78e1-df0d-467f-907e-7bff04a55db5}",
|
|
||||||
"model": {
|
|
||||||
"name": "vec_compose4",
|
|
||||||
"preview_enabled": false,
|
|
||||||
"preview_height": 64,
|
|
||||||
"preview_width": 64,
|
|
||||||
"variable_name": ""
|
|
||||||
},
|
|
||||||
"position": {
|
|
||||||
"x": 1373.82,
|
|
||||||
"y": 198.09999999999997
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "{92d95fe0-84f6-4d27-91ea-992d5f73c04e}",
|
|
||||||
"model": {
|
|
||||||
"condition_name": "HAS_ALPHA_TEXTURE",
|
|
||||||
"name": "ConditionalExpression",
|
|
||||||
"preview_enabled": true,
|
|
||||||
"preview_height": 128,
|
|
||||||
"preview_width": 128,
|
|
||||||
"variable_name": ""
|
|
||||||
},
|
|
||||||
"position": {
|
|
||||||
"x": 1619.8933333333334,
|
|
||||||
"y": 447.44000000000005
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "{bb071807-e65e-4c31-acf0-d296efa665fa}",
|
|
||||||
"model": {
|
|
||||||
"name": "vec_decompose",
|
|
||||||
"preview_enabled": false,
|
|
||||||
"preview_height": 64,
|
|
||||||
"preview_width": 64,
|
|
||||||
"variable_name": ""
|
|
||||||
},
|
|
||||||
"position": {
|
|
||||||
"x": 2270,
|
|
||||||
"y": 67
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "{3cdb5bb1-f572-4055-a1af-460b152b0c13}",
|
|
||||||
"model": {
|
|
||||||
"name": "Discard",
|
|
||||||
"preview_enabled": false,
|
|
||||||
"preview_height": 64,
|
|
||||||
"preview_width": 64,
|
|
||||||
"variable_name": ""
|
|
||||||
},
|
|
||||||
"position": {
|
|
||||||
"x": 2694,
|
|
||||||
"y": 4
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "{d7acd173-9188-43b5-bfa1-31f17dff44ad}",
|
|
||||||
"model": {
|
|
||||||
"condition_name": "ALPHA_TEST",
|
|
||||||
"name": "ConditionalExpression",
|
|
||||||
"preview_enabled": true,
|
|
||||||
"preview_height": 128,
|
|
||||||
"preview_width": 128,
|
|
||||||
"variable_name": ""
|
|
||||||
},
|
|
||||||
"position": {
|
|
||||||
"x": 2240,
|
|
||||||
"y": -174
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "{1f9d52d7-4f44-4d96-8edb-fbc1239a93bb}",
|
|
||||||
"model": {
|
|
||||||
"name": "bool_constant",
|
|
||||||
"preview_enabled": false,
|
|
||||||
"preview_height": 64,
|
|
||||||
"preview_width": 64,
|
|
||||||
"value": false,
|
|
||||||
"variable_name": ""
|
|
||||||
},
|
|
||||||
"position": {
|
|
||||||
"x": 2005,
|
|
||||||
"y": -99
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "{fc7542b2-5752-4891-98c1-35b498da257b}",
|
|
||||||
"model": {
|
|
||||||
"name": "float_lt",
|
|
||||||
"preview_enabled": false,
|
|
||||||
"preview_height": 64,
|
|
||||||
"preview_width": 64,
|
|
||||||
"variable_name": ""
|
|
||||||
},
|
|
||||||
"position": {
|
|
||||||
"x": 2000,
|
|
||||||
"y": -241
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "{743930bd-1d81-4d4c-b7ec-175a34838d69}",
|
|
||||||
"model": {
|
|
||||||
"buffer": "settings",
|
|
||||||
"field": "AlphaThreshold",
|
|
||||||
"name": "BufferField",
|
|
||||||
"preview_enabled": false,
|
|
||||||
"preview_height": 64,
|
|
||||||
"preview_width": 64,
|
|
||||||
"variable_name": ""
|
|
||||||
},
|
|
||||||
"position": {
|
|
||||||
"x": 1675,
|
|
||||||
"y": -254
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "{5e4c18b3-9a7f-4c0e-abe4-778be151ad06}",
|
|
||||||
"model": {
|
|
||||||
"input": "vertUV",
|
|
||||||
"name": "Input",
|
|
||||||
"preview_enabled": false,
|
|
||||||
"preview_height": 64,
|
|
||||||
"preview_width": 64,
|
|
||||||
"variable_name": ""
|
|
||||||
},
|
|
||||||
"position": {
|
|
||||||
"x": -5,
|
|
||||||
"y": 542
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"locationIndex": 0,
|
|
||||||
"name": "RenderTarget0",
|
|
||||||
"type": "Float4"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"structs": [
|
|
||||||
{
|
|
||||||
"members": [
|
|
||||||
{
|
|
||||||
"name": "AlphaThreshold",
|
|
||||||
"type": "Float"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "DiffuseColor",
|
|
||||||
"type": "Float4"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"name": "BasicSettings"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"members": [
|
|
||||||
{
|
|
||||||
"name": "worldMatrix",
|
|
||||||
"type": "Mat4x4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "invWorldMatrix",
|
|
||||||
"type": "Mat4x4"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"name": "InstanceData"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"members": [
|
|
||||||
{
|
|
||||||
"name": "projectionMatrix",
|
|
||||||
"type": "Mat4x4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "invProjectionMatrix",
|
|
||||||
"type": "Mat4x4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "viewMatrix",
|
|
||||||
"type": "Mat4x4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "invViewMatrix",
|
|
||||||
"type": "Mat4x4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "viewProjMatrix",
|
|
||||||
"type": "Mat4x4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "invViewProjMatrix",
|
|
||||||
"type": "Mat4x4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "renderTargetSize",
|
|
||||||
"type": "Float2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "invRenderTargetSize",
|
|
||||||
"type": "Float2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "eyePosition",
|
|
||||||
"type": "Float3"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"name": "ViewerData"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"textures": [
|
|
||||||
{
|
|
||||||
"bindingIndex": 2,
|
|
||||||
"name": "MaterialAlphaMap",
|
|
||||||
"setIndex": 2,
|
|
||||||
"type": "Sampler2D"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"bindingIndex": 1,
|
|
||||||
"name": "MaterialDiffuseMap",
|
|
||||||
"setIndex": 2,
|
|
||||||
"type": "Sampler2D"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"type": "Fragment"
|
|
||||||
}
|
|
||||||
|
|
@ -1,349 +0,0 @@
|
||||||
{
|
|
||||||
"buffers": [
|
|
||||||
{
|
|
||||||
"bindingIndex": 0,
|
|
||||||
"name": "viewerData",
|
|
||||||
"setIndex": 0,
|
|
||||||
"structIndex": 2,
|
|
||||||
"type": "UniformBufferObject"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"bindingIndex": 0,
|
|
||||||
"name": "instanceData",
|
|
||||||
"setIndex": 1,
|
|
||||||
"structIndex": 1,
|
|
||||||
"type": "UniformBufferObject"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"bindingIndex": 0,
|
|
||||||
"name": "settings",
|
|
||||||
"setIndex": 2,
|
|
||||||
"structIndex": 0,
|
|
||||||
"type": "UniformBufferObject"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"conditions": [
|
|
||||||
],
|
|
||||||
"connections": [
|
|
||||||
{
|
|
||||||
"in_id": "{1bb9712b-8bff-4398-9e4e-fba79a04df0e}",
|
|
||||||
"in_index": 1,
|
|
||||||
"out_id": "{a2fff9e2-af6e-4c7f-80ee-ca3492f3c5ab}",
|
|
||||||
"out_index": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"in_id": "{62731a4b-f054-4f78-82da-08d2584e51ab}",
|
|
||||||
"in_index": 1,
|
|
||||||
"out_id": "{7ac65f09-7f55-4a6e-9380-1bee5213f079}",
|
|
||||||
"out_index": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"in_id": "{62731a4b-f054-4f78-82da-08d2584e51ab}",
|
|
||||||
"in_index": 0,
|
|
||||||
"out_id": "{1bb9712b-8bff-4398-9e4e-fba79a04df0e}",
|
|
||||||
"out_index": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"in_id": "{43ce1867-629f-442b-a672-540fa67f1446}",
|
|
||||||
"in_index": 0,
|
|
||||||
"out_id": "{33840c70-4e37-4127-bab0-23c4a4cb6d7f}",
|
|
||||||
"out_index": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"in_id": "{1bb9712b-8bff-4398-9e4e-fba79a04df0e}",
|
|
||||||
"in_index": 0,
|
|
||||||
"out_id": "{d8f4d14a-c67a-470f-87bf-8f60d9513c3b}",
|
|
||||||
"out_index": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"in_id": "{63bb13f0-55e3-451b-860e-568b65e09b04}",
|
|
||||||
"in_index": 0,
|
|
||||||
"out_id": "{62731a4b-f054-4f78-82da-08d2584e51ab}",
|
|
||||||
"out_index": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"in_id": "{7ac65f09-7f55-4a6e-9380-1bee5213f079}",
|
|
||||||
"in_index": 0,
|
|
||||||
"out_id": "{c3b906bc-d230-4026-a32e-34c00eaf4481}",
|
|
||||||
"out_index": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"in_id": "{d8f4d14a-c67a-470f-87bf-8f60d9513c3b}",
|
|
||||||
"in_index": 0,
|
|
||||||
"out_id": "{d32dfb1d-c8a4-4315-a710-90d2a51f68e8}",
|
|
||||||
"out_index": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"in_id": "{d8f4d14a-c67a-470f-87bf-8f60d9513c3b}",
|
|
||||||
"in_index": 1,
|
|
||||||
"out_id": "{c6058af1-6913-4218-a9b9-11adb5cdffa0}",
|
|
||||||
"out_index": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"inputs": [
|
|
||||||
{
|
|
||||||
"locationIndex": 0,
|
|
||||||
"name": "inPos",
|
|
||||||
"role": "Position",
|
|
||||||
"roleIndex": 0,
|
|
||||||
"type": "Float3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"locationIndex": 1,
|
|
||||||
"name": "inTexCoord",
|
|
||||||
"role": "TexCoord",
|
|
||||||
"roleIndex": 0,
|
|
||||||
"type": "Float2"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"nodes": [
|
|
||||||
{
|
|
||||||
"id": "{43ce1867-629f-442b-a672-540fa67f1446}",
|
|
||||||
"model": {
|
|
||||||
"name": "Output",
|
|
||||||
"output": "vertUV",
|
|
||||||
"preview_enabled": false,
|
|
||||||
"preview_height": 128,
|
|
||||||
"preview_width": 128,
|
|
||||||
"variable_name": ""
|
|
||||||
},
|
|
||||||
"position": {
|
|
||||||
"x": 243,
|
|
||||||
"y": 292
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "{33840c70-4e37-4127-bab0-23c4a4cb6d7f}",
|
|
||||||
"model": {
|
|
||||||
"input": "inTexCoord",
|
|
||||||
"name": "Input",
|
|
||||||
"preview_enabled": false,
|
|
||||||
"preview_height": 64,
|
|
||||||
"preview_width": 64,
|
|
||||||
"variable_name": ""
|
|
||||||
},
|
|
||||||
"position": {
|
|
||||||
"x": 82,
|
|
||||||
"y": 287
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "{d8f4d14a-c67a-470f-87bf-8f60d9513c3b}",
|
|
||||||
"model": {
|
|
||||||
"name": "mat4_mul",
|
|
||||||
"preview_enabled": false,
|
|
||||||
"preview_height": 64,
|
|
||||||
"preview_width": 64,
|
|
||||||
"variable_name": ""
|
|
||||||
},
|
|
||||||
"position": {
|
|
||||||
"x": 248,
|
|
||||||
"y": 424
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "{1bb9712b-8bff-4398-9e4e-fba79a04df0e}",
|
|
||||||
"model": {
|
|
||||||
"name": "mat4_mul",
|
|
||||||
"preview_enabled": false,
|
|
||||||
"preview_height": 64,
|
|
||||||
"preview_width": 64,
|
|
||||||
"variable_name": ""
|
|
||||||
},
|
|
||||||
"position": {
|
|
||||||
"x": 463,
|
|
||||||
"y": 496
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "{c3b906bc-d230-4026-a32e-34c00eaf4481}",
|
|
||||||
"model": {
|
|
||||||
"input": "inPos",
|
|
||||||
"name": "Input",
|
|
||||||
"preview_enabled": false,
|
|
||||||
"preview_height": 64,
|
|
||||||
"preview_width": 64,
|
|
||||||
"variable_name": ""
|
|
||||||
},
|
|
||||||
"position": {
|
|
||||||
"x": 54,
|
|
||||||
"y": 675
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "{62731a4b-f054-4f78-82da-08d2584e51ab}",
|
|
||||||
"model": {
|
|
||||||
"name": "mat4vec_mul",
|
|
||||||
"preview_enabled": false,
|
|
||||||
"preview_height": 64,
|
|
||||||
"preview_width": 64,
|
|
||||||
"variable_name": ""
|
|
||||||
},
|
|
||||||
"position": {
|
|
||||||
"x": 699,
|
|
||||||
"y": 512
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "{7ac65f09-7f55-4a6e-9380-1bee5213f079}",
|
|
||||||
"model": {
|
|
||||||
"name": "cast_vec4",
|
|
||||||
"preview_enabled": false,
|
|
||||||
"preview_height": 64,
|
|
||||||
"preview_width": 64,
|
|
||||||
"value": [
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0
|
|
||||||
],
|
|
||||||
"variable_name": ""
|
|
||||||
},
|
|
||||||
"position": {
|
|
||||||
"x": 345,
|
|
||||||
"y": 668
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "{63bb13f0-55e3-451b-860e-568b65e09b04}",
|
|
||||||
"model": {
|
|
||||||
"name": "PositionOutputValue",
|
|
||||||
"preview_enabled": false,
|
|
||||||
"preview_height": 64,
|
|
||||||
"preview_width": 64,
|
|
||||||
"variable_name": ""
|
|
||||||
},
|
|
||||||
"position": {
|
|
||||||
"x": 930,
|
|
||||||
"y": 524
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "{d32dfb1d-c8a4-4315-a710-90d2a51f68e8}",
|
|
||||||
"model": {
|
|
||||||
"buffer": "viewerData",
|
|
||||||
"field": "projectionMatrix",
|
|
||||||
"name": "BufferField",
|
|
||||||
"preview_enabled": false,
|
|
||||||
"preview_height": 64,
|
|
||||||
"preview_width": 64,
|
|
||||||
"variable_name": ""
|
|
||||||
},
|
|
||||||
"position": {
|
|
||||||
"x": 21,
|
|
||||||
"y": 374
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "{c6058af1-6913-4218-a9b9-11adb5cdffa0}",
|
|
||||||
"model": {
|
|
||||||
"buffer": "viewerData",
|
|
||||||
"field": "viewMatrix",
|
|
||||||
"name": "BufferField",
|
|
||||||
"preview_enabled": false,
|
|
||||||
"preview_height": 64,
|
|
||||||
"preview_width": 64,
|
|
||||||
"variable_name": ""
|
|
||||||
},
|
|
||||||
"position": {
|
|
||||||
"x": 25,
|
|
||||||
"y": 456
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "{a2fff9e2-af6e-4c7f-80ee-ca3492f3c5ab}",
|
|
||||||
"model": {
|
|
||||||
"buffer": "instanceData",
|
|
||||||
"field": "worldMatrix",
|
|
||||||
"name": "BufferField",
|
|
||||||
"preview_enabled": false,
|
|
||||||
"preview_height": 64,
|
|
||||||
"preview_width": 64,
|
|
||||||
"variable_name": ""
|
|
||||||
},
|
|
||||||
"position": {
|
|
||||||
"x": 27,
|
|
||||||
"y": 538
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"locationIndex": 0,
|
|
||||||
"name": "vertUV",
|
|
||||||
"type": "Float2"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"structs": [
|
|
||||||
{
|
|
||||||
"members": [
|
|
||||||
{
|
|
||||||
"name": "AlphaThreshold",
|
|
||||||
"type": "Float"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "DiffuseColor",
|
|
||||||
"type": "Float4"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"name": "BasicSettings"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"members": [
|
|
||||||
{
|
|
||||||
"name": "worldMatrix",
|
|
||||||
"type": "Mat4x4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "invWorldMatrix",
|
|
||||||
"type": "Mat4x4"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"name": "InstanceData"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"members": [
|
|
||||||
{
|
|
||||||
"name": "projectionMatrix",
|
|
||||||
"type": "Mat4x4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "invProjectionMatrix",
|
|
||||||
"type": "Mat4x4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "viewMatrix",
|
|
||||||
"type": "Mat4x4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "invViewMatrix",
|
|
||||||
"type": "Mat4x4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "viewProjMatrix",
|
|
||||||
"type": "Mat4x4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "invViewProjMatrix",
|
|
||||||
"type": "Mat4x4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "renderTargetSize",
|
|
||||||
"type": "Float2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "invRenderTargetSize",
|
|
||||||
"type": "Float2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "eyePosition",
|
|
||||||
"type": "Float3"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"name": "ViewerData"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"textures": [
|
|
||||||
],
|
|
||||||
"type": "Vertex"
|
|
||||||
}
|
|
||||||
|
|
@ -160,19 +160,19 @@ namespace Nz
|
||||||
if (optionIndexes)
|
if (optionIndexes)
|
||||||
optionIndexes->hasDiffuseMap = settings.options.size();
|
optionIndexes->hasDiffuseMap = settings.options.size();
|
||||||
|
|
||||||
MaterialSettings::BuildOption(settings.options, settings.shaders, "HasDiffuseMap", "HAS_DIFFUSE_TEXTURE");
|
MaterialSettings::BuildOption(settings.options, settings.shaders, "HasDiffuseMap", "HasDiffuseTexture");
|
||||||
|
|
||||||
// HasAlphaMap
|
// HasAlphaMap
|
||||||
if (optionIndexes)
|
if (optionIndexes)
|
||||||
optionIndexes->hasAlphaMap = settings.options.size();
|
optionIndexes->hasAlphaMap = settings.options.size();
|
||||||
|
|
||||||
MaterialSettings::BuildOption(settings.options, settings.shaders, "HasAlphaMap", "HAS_ALPHA_TEXTURE");
|
MaterialSettings::BuildOption(settings.options, settings.shaders, "HasAlphaMap", "HasAlphaTexture");
|
||||||
|
|
||||||
// AlphaTest
|
// AlphaTest
|
||||||
if (optionIndexes)
|
if (optionIndexes)
|
||||||
optionIndexes->alphaTest = settings.options.size();
|
optionIndexes->alphaTest = settings.options.size();
|
||||||
|
|
||||||
MaterialSettings::BuildOption(settings.options, settings.shaders, "AlphaTest", "ALPHA_TEST");
|
MaterialSettings::BuildOption(settings.options, settings.shaders, "AlphaTest", "AlphaTest");
|
||||||
|
|
||||||
return settings;
|
return settings;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,6 @@ namespace Nz
|
||||||
*/
|
*/
|
||||||
MaterialPass::MaterialPass(std::shared_ptr<const MaterialSettings> settings) :
|
MaterialPass::MaterialPass(std::shared_ptr<const MaterialSettings> settings) :
|
||||||
m_settings(std::move(settings)),
|
m_settings(std::move(settings)),
|
||||||
m_enabledOptions(0),
|
|
||||||
m_forceCommandBufferRegeneration(false),
|
m_forceCommandBufferRegeneration(false),
|
||||||
m_pipelineUpdated(false),
|
m_pipelineUpdated(false),
|
||||||
m_shaderBindingUpdated(false)
|
m_shaderBindingUpdated(false)
|
||||||
|
|
@ -99,23 +98,20 @@ namespace Nz
|
||||||
void MaterialPass::UpdatePipeline() const
|
void MaterialPass::UpdatePipeline() const
|
||||||
{
|
{
|
||||||
for (auto& shader : m_pipelineInfo.shaders)
|
for (auto& shader : m_pipelineInfo.shaders)
|
||||||
shader.enabledOptions = 0;
|
shader.optionValues.fill(ShaderAst::NoValue{});
|
||||||
|
|
||||||
const auto& options = m_settings->GetOptions();
|
const auto& options = m_settings->GetOptions();
|
||||||
for (std::size_t optionIndex = 0; optionIndex < options.size(); ++optionIndex)
|
for (std::size_t optionIndex = 0; optionIndex < options.size(); ++optionIndex)
|
||||||
{
|
{
|
||||||
if (TestBit<UInt64>(m_enabledOptions, optionIndex))
|
const auto& option = options[optionIndex];
|
||||||
|
assert(option.optionIndexByShader.size() <= m_pipelineInfo.shaders.size());
|
||||||
|
|
||||||
|
for (std::size_t shaderIndex = 0; shaderIndex < option.optionIndexByShader.size(); ++shaderIndex)
|
||||||
{
|
{
|
||||||
for (auto& shader : m_pipelineInfo.shaders)
|
if (!option.optionIndexByShader[shaderIndex].has_value())
|
||||||
{
|
continue;
|
||||||
ShaderStageTypeFlags supportedStages = shader.uberShader->GetSupportedStages();
|
|
||||||
for (std::size_t i = 0; i < ShaderStageTypeCount; ++i)
|
m_pipelineInfo.shaders[shaderIndex].optionValues[optionIndex] = m_optionValues[optionIndex];
|
||||||
{
|
|
||||||
ShaderStageType shaderStage = static_cast<ShaderStageType>(i);
|
|
||||||
if (supportedStages & shaderStage)
|
|
||||||
shader.enabledOptions |= options[optionIndex].enabledOptions[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -45,14 +45,18 @@ namespace Nz
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderPipelineInfo renderPipelineInfo;
|
RenderPipelineInfo renderPipelineInfo;
|
||||||
static_cast<RenderStates&>(renderPipelineInfo).operator=(m_pipelineInfo); // Not the line I4m the most proud of
|
static_cast<RenderStates&>(renderPipelineInfo).operator=(m_pipelineInfo); // Not the line I'm the most proud of
|
||||||
|
|
||||||
renderPipelineInfo.pipelineLayout = m_pipelineInfo.settings->GetRenderPipelineLayout();
|
renderPipelineInfo.pipelineLayout = m_pipelineInfo.settings->GetRenderPipelineLayout();
|
||||||
|
|
||||||
for (const auto& shader : m_pipelineInfo.shaders)
|
for (const auto& shader : m_pipelineInfo.shaders)
|
||||||
{
|
{
|
||||||
if (shader.uberShader)
|
if (shader.uberShader)
|
||||||
renderPipelineInfo.shaderModules.push_back(shader.uberShader->Get(shader.enabledOptions));
|
{
|
||||||
|
UberShader::Config config{ shader.optionValues };
|
||||||
|
|
||||||
|
renderPipelineInfo.shaderModules.push_back(shader.uberShader->Get(config));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
renderPipelineInfo.vertexBuffers = vertexBuffers;
|
renderPipelineInfo.vertexBuffers = vertexBuffers;
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
option HAS_DIFFUSE_TEXTURE: bool;
|
option HasDiffuseTexture: bool = false;
|
||||||
option HAS_ALPHA_TEXTURE: bool;
|
option HasAlphaTexture: bool = false;
|
||||||
option ALPHA_TEST: bool;
|
option AlphaTest: bool = false;
|
||||||
|
|
||||||
const HasUV = HAS_DIFFUSE_TEXTURE || HAS_ALPHA_TEXTURE;
|
const HasUV = HasDiffuseTexture || HasAlphaTexture;
|
||||||
|
|
||||||
[layout(std140)]
|
[layout(std140)]
|
||||||
struct BasicSettings
|
struct BasicSettings
|
||||||
|
|
@ -56,15 +56,15 @@ struct FragOut
|
||||||
fn main(input: FragIn) -> FragOut
|
fn main(input: FragIn) -> FragOut
|
||||||
{
|
{
|
||||||
let diffuseColor = settings.DiffuseColor;
|
let diffuseColor = settings.DiffuseColor;
|
||||||
const if (HAS_DIFFUSE_TEXTURE)
|
const if (HasDiffuseTexture)
|
||||||
// TODO: diffuseColor *= MaterialDiffuseMap.Sample(input.uv)
|
// TODO: diffuseColor *= MaterialDiffuseMap.Sample(input.uv)
|
||||||
diffuseColor = diffuseColor * MaterialDiffuseMap.Sample(input.uv);
|
diffuseColor = diffuseColor * MaterialDiffuseMap.Sample(input.uv);
|
||||||
|
|
||||||
const if (HAS_ALPHA_TEXTURE)
|
const if (HasAlphaTexture)
|
||||||
// TODO: diffuseColor.w *= MaterialAlphaMap.Sample(input.uv)).x
|
// TODO: diffuseColor.w *= MaterialAlphaMap.Sample(input.uv)).x
|
||||||
diffuseColor = vec4<f32>(diffuseColor.x, diffuseColor.y, diffuseColor.z, MaterialAlphaMap.Sample(input.uv).x * diffuseColor.w);
|
diffuseColor = vec4<f32>(diffuseColor.x, diffuseColor.y, diffuseColor.z, MaterialAlphaMap.Sample(input.uv).x * diffuseColor.w);
|
||||||
|
|
||||||
const if (ALPHA_TEST)
|
const if (AlphaTest)
|
||||||
{
|
{
|
||||||
if (diffuseColor.w < settings.AlphaThreshold)
|
if (diffuseColor.w < settings.AlphaThreshold)
|
||||||
discard;
|
discard;
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
option HAS_DIFFUSE_TEXTURE: bool;
|
option HasDiffuseTexture: bool = false;
|
||||||
option HAS_ALPHA_TEXTURE: bool;
|
option HasAlphaTexture: bool = false;
|
||||||
option ALPHA_TEST: bool;
|
option AlphaTest: bool = false;
|
||||||
|
|
||||||
const HasUV = ALPHA_TEST && (HAS_DIFFUSE_TEXTURE || HAS_ALPHA_TEXTURE);
|
const HasUV = AlphaTest && (HasDiffuseTexture || HasAlphaTexture);
|
||||||
|
|
||||||
[layout(std140)]
|
[layout(std140)]
|
||||||
struct BasicSettings
|
struct BasicSettings
|
||||||
|
|
@ -47,15 +47,15 @@ struct FragIn
|
||||||
[location(0), cond(HasUV)] uv: vec2<f32>
|
[location(0), cond(HasUV)] uv: vec2<f32>
|
||||||
}
|
}
|
||||||
|
|
||||||
[entry(frag), cond(ALPHA_TEST)]
|
[entry(frag), cond(AlphaTest)]
|
||||||
fn main(input: FragIn)
|
fn main(input: FragIn)
|
||||||
{
|
{
|
||||||
let alpha = settings.DiffuseColor.a;
|
let alpha = settings.DiffuseColor.a;
|
||||||
const if (HAS_DIFFUSE_TEXTURE)
|
const if (HasDiffuseTexture)
|
||||||
// TODO: alpha *= MaterialDiffuseMap.Sample(input.uv).a;
|
// TODO: alpha *= MaterialDiffuseMap.Sample(input.uv).a;
|
||||||
alpha = alpha * MaterialDiffuseMap.Sample(input.uv).a;
|
alpha = alpha * MaterialDiffuseMap.Sample(input.uv).a;
|
||||||
|
|
||||||
const if (HAS_ALPHA_TEXTURE)
|
const if (HasAlphaTexture)
|
||||||
// TODO: alpha *= MaterialAlphaMap.Sample(input.uv).x
|
// TODO: alpha *= MaterialAlphaMap.Sample(input.uv).x
|
||||||
alpha = alpha * MaterialAlphaMap.Sample(input.uv).x;
|
alpha = alpha * MaterialAlphaMap.Sample(input.uv).x;
|
||||||
|
|
||||||
|
|
@ -64,7 +64,7 @@ fn main(input: FragIn)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dummy fragment shader (TODO: Add a way to delete stage?)
|
// Dummy fragment shader (TODO: Add a way to delete stage?)
|
||||||
[entry(frag), cond(!ALPHA_TEST)]
|
[entry(frag), cond(!AlphaTest)]
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
||||||
// Vertex stage
|
// Vertex stage
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,11 @@ namespace Nz
|
||||||
|
|
||||||
callbacks.onOptionDeclaration = [&](const std::string& optionName, const ShaderAst::ExpressionType& optionType)
|
callbacks.onOptionDeclaration = [&](const std::string& optionName, const ShaderAst::ExpressionType& optionType)
|
||||||
{
|
{
|
||||||
m_optionIndexByName[optionName] = optionCount;
|
m_optionIndexByName[optionName] = Option{
|
||||||
|
optionCount,
|
||||||
|
optionType
|
||||||
|
};
|
||||||
|
|
||||||
optionCount++;
|
optionCount++;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -43,36 +47,26 @@ namespace Nz
|
||||||
if (m_shaderStages & supportedStageType != m_shaderStages)
|
if (m_shaderStages & supportedStageType != m_shaderStages)
|
||||||
throw std::runtime_error("shader doesn't support all required shader stages");
|
throw std::runtime_error("shader doesn't support all required shader stages");
|
||||||
|
|
||||||
if (optionCount >= 64)
|
if (optionCount >= MaximumOptionValue)
|
||||||
throw std::runtime_error("Too many conditions");
|
throw std::runtime_error("Too many shader options (at most " + std::to_string(MaximumOptionValue) + " are supported)");
|
||||||
|
|
||||||
m_combinationMask = std::numeric_limits<UInt64>::max();
|
|
||||||
m_combinationMask <<= optionCount;
|
|
||||||
m_combinationMask = ~m_combinationMask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UInt64 UberShader::GetOptionFlagByName(const std::string& optionName) const
|
const std::shared_ptr<ShaderModule>& UberShader::Get(const Config& config)
|
||||||
{
|
{
|
||||||
auto it = m_optionIndexByName.find(optionName);
|
auto it = m_combinations.find(config);
|
||||||
if (it == m_optionIndexByName.end())
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return SetBit<UInt64>(0, it->second);
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::shared_ptr<ShaderModule>& UberShader::Get(UInt64 combination)
|
|
||||||
{
|
|
||||||
combination &= m_combinationMask;
|
|
||||||
|
|
||||||
auto it = m_combinations.find(combination);
|
|
||||||
if (it == m_combinations.end())
|
if (it == m_combinations.end())
|
||||||
{
|
{
|
||||||
ShaderWriter::States states;
|
ShaderWriter::States states;
|
||||||
states.enabledOptions = combination;
|
|
||||||
|
for (std::size_t i = 0; i < MaximumOptionValue; ++i)
|
||||||
|
{
|
||||||
|
if (!std::holds_alternative<ShaderAst::NoValue>(config.optionValues[i]))
|
||||||
|
states.optionValues[i] = config.optionValues[i];
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_ptr<ShaderModule> stage = Graphics::Instance()->GetRenderDevice()->InstantiateShaderModule(m_shaderStages, *m_shaderAst, std::move(states));
|
std::shared_ptr<ShaderModule> stage = Graphics::Instance()->GetRenderDevice()->InstantiateShaderModule(m_shaderStages, *m_shaderAst, std::move(states));
|
||||||
|
|
||||||
it = m_combinations.emplace(combination, std::move(stage)).first;
|
it = m_combinations.emplace(config, std::move(stage)).first;
|
||||||
}
|
}
|
||||||
|
|
||||||
return it->second;
|
return it->second;
|
||||||
|
|
|
||||||
|
|
@ -116,7 +116,7 @@ namespace Nz::ShaderAst
|
||||||
StatementPtr AstCloner::Clone(DeclareOptionStatement& node)
|
StatementPtr AstCloner::Clone(DeclareOptionStatement& node)
|
||||||
{
|
{
|
||||||
auto clone = std::make_unique<DeclareOptionStatement>();
|
auto clone = std::make_unique<DeclareOptionStatement>();
|
||||||
clone->initialValue = CloneExpression(node.initialValue);
|
clone->defaultValue = CloneExpression(node.defaultValue);
|
||||||
clone->optIndex = node.optIndex;
|
clone->optIndex = node.optIndex;
|
||||||
clone->optName = node.optName;
|
clone->optName = node.optName;
|
||||||
clone->optType = node.optType;
|
clone->optType = node.optType;
|
||||||
|
|
|
||||||
|
|
@ -697,7 +697,9 @@ namespace Nz::ShaderAst
|
||||||
{
|
{
|
||||||
using T = std::decay_t<decltype(arg)>;
|
using T = std::decay_t<decltype(arg)>;
|
||||||
|
|
||||||
if constexpr (std::is_same_v<T, bool> || std::is_same_v<T, float> || std::is_same_v<T, Int32> || std::is_same_v<T, UInt32>)
|
if constexpr (std::is_same_v<T, NoValue>)
|
||||||
|
throw std::runtime_error("invalid type (value expected)");
|
||||||
|
else if constexpr (std::is_same_v<T, bool> || std::is_same_v<T, float> || std::is_same_v<T, Int32> || std::is_same_v<T, UInt32>)
|
||||||
constantValues.push_back(arg);
|
constantValues.push_back(arg);
|
||||||
else if constexpr (std::is_same_v<T, Vector2f> || std::is_same_v<T, Vector2i32>)
|
else if constexpr (std::is_same_v<T, Vector2f> || std::is_same_v<T, Vector2i32>)
|
||||||
{
|
{
|
||||||
|
|
@ -815,9 +817,6 @@ namespace Nz::ShaderAst
|
||||||
|
|
||||||
ExpressionPtr AstOptimizer::Clone(ConditionalExpression& node)
|
ExpressionPtr AstOptimizer::Clone(ConditionalExpression& node)
|
||||||
{
|
{
|
||||||
if (!m_options.enabledOptions)
|
|
||||||
return AstCloner::Clone(node);
|
|
||||||
|
|
||||||
auto cond = CloneExpression(node.condition);
|
auto cond = CloneExpression(node.condition);
|
||||||
if (cond->GetType() != NodeType::ConstantValueExpression)
|
if (cond->GetType() != NodeType::ConstantValueExpression)
|
||||||
throw std::runtime_error("conditional expression condition must be a constant expression");
|
throw std::runtime_error("conditional expression condition must be a constant expression");
|
||||||
|
|
@ -884,9 +883,6 @@ namespace Nz::ShaderAst
|
||||||
|
|
||||||
StatementPtr AstOptimizer::Clone(ConditionalStatement& node)
|
StatementPtr AstOptimizer::Clone(ConditionalStatement& node)
|
||||||
{
|
{
|
||||||
if (!m_options.enabledOptions)
|
|
||||||
return AstCloner::Clone(node);
|
|
||||||
|
|
||||||
auto cond = CloneExpression(node.condition);
|
auto cond = CloneExpression(node.condition);
|
||||||
if (cond->GetType() != NodeType::ConstantValueExpression)
|
if (cond->GetType() != NodeType::ConstantValueExpression)
|
||||||
throw std::runtime_error("conditional expression condition must be a constant expression");
|
throw std::runtime_error("conditional expression condition must be a constant expression");
|
||||||
|
|
|
||||||
|
|
@ -134,8 +134,8 @@ namespace Nz::ShaderAst
|
||||||
|
|
||||||
void AstRecursiveVisitor::Visit(DeclareOptionStatement& node)
|
void AstRecursiveVisitor::Visit(DeclareOptionStatement& node)
|
||||||
{
|
{
|
||||||
if (node.initialValue)
|
if (node.defaultValue)
|
||||||
node.initialValue->Visit(*this);
|
node.defaultValue->Visit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AstRecursiveVisitor::Visit(DeclareStructStatement& /*node*/)
|
void AstRecursiveVisitor::Visit(DeclareStructStatement& /*node*/)
|
||||||
|
|
|
||||||
|
|
@ -140,19 +140,20 @@ namespace Nz::ShaderAst
|
||||||
Value(value);
|
Value(value);
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(std::variant_size_v<decltype(node.value)> == 10);
|
static_assert(std::variant_size_v<decltype(node.value)> == 11);
|
||||||
switch (typeIndex)
|
switch (typeIndex)
|
||||||
{
|
{
|
||||||
case 0: SerializeValue(bool()); break;
|
case 0: break;
|
||||||
case 1: SerializeValue(float()); break;
|
case 1: SerializeValue(bool()); break;
|
||||||
case 2: SerializeValue(Int32()); break;
|
case 2: SerializeValue(float()); break;
|
||||||
case 3: SerializeValue(UInt32()); break;
|
case 3: SerializeValue(Int32()); break;
|
||||||
case 4: SerializeValue(Vector2f()); break;
|
case 4: SerializeValue(UInt32()); break;
|
||||||
case 5: SerializeValue(Vector3f()); break;
|
case 5: SerializeValue(Vector2f()); break;
|
||||||
case 6: SerializeValue(Vector4f()); break;
|
case 6: SerializeValue(Vector3f()); break;
|
||||||
case 7: SerializeValue(Vector2i32()); break;
|
case 7: SerializeValue(Vector4f()); break;
|
||||||
case 8: SerializeValue(Vector3i32()); break;
|
case 8: SerializeValue(Vector2i32()); break;
|
||||||
case 9: SerializeValue(Vector4i32()); break;
|
case 9: SerializeValue(Vector3i32()); break;
|
||||||
|
case 10: SerializeValue(Vector4i32()); break;
|
||||||
default: throw std::runtime_error("unexpected data type");
|
default: throw std::runtime_error("unexpected data type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -261,7 +262,7 @@ namespace Nz::ShaderAst
|
||||||
OptVal(node.optIndex);
|
OptVal(node.optIndex);
|
||||||
Value(node.optName);
|
Value(node.optName);
|
||||||
Type(node.optType);
|
Type(node.optType);
|
||||||
Node(node.initialValue);
|
Node(node.defaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AstSerializerBase::Serialize(DeclareStructStatement& node)
|
void AstSerializerBase::Serialize(DeclareStructStatement& node)
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,9 @@ namespace Nz::ShaderAst
|
||||||
{
|
{
|
||||||
using T = std::decay_t<decltype(arg)>;
|
using T = std::decay_t<decltype(arg)>;
|
||||||
|
|
||||||
if constexpr (std::is_same_v<T, bool>)
|
if constexpr (std::is_same_v<T, NoValue>)
|
||||||
|
return NoType{};
|
||||||
|
else if constexpr (std::is_same_v<T, bool>)
|
||||||
return PrimitiveType::Boolean;
|
return PrimitiveType::Boolean;
|
||||||
else if constexpr (std::is_same_v<T, float>)
|
else if constexpr (std::is_same_v<T, float>)
|
||||||
return PrimitiveType::Float32;
|
return PrimitiveType::Float32;
|
||||||
|
|
|
||||||
|
|
@ -583,6 +583,9 @@ namespace Nz::ShaderAst
|
||||||
|
|
||||||
ExpressionPtr SanitizeVisitor::Clone(ConstantValueExpression& node)
|
ExpressionPtr SanitizeVisitor::Clone(ConstantValueExpression& node)
|
||||||
{
|
{
|
||||||
|
if (std::holds_alternative<NoValue>(node.value))
|
||||||
|
throw std::runtime_error("expected a value");
|
||||||
|
|
||||||
auto clone = static_unique_pointer_cast<ConstantValueExpression>(AstCloner::Clone(node));
|
auto clone = static_unique_pointer_cast<ConstantValueExpression>(AstCloner::Clone(node));
|
||||||
clone->cachedExpressionType = GetExpressionType(clone->value);
|
clone->cachedExpressionType = GetExpressionType(clone->value);
|
||||||
|
|
||||||
|
|
@ -980,12 +983,17 @@ namespace Nz::ShaderAst
|
||||||
auto clone = static_unique_pointer_cast<DeclareOptionStatement>(AstCloner::Clone(node));
|
auto clone = static_unique_pointer_cast<DeclareOptionStatement>(AstCloner::Clone(node));
|
||||||
clone->optType = ResolveType(clone->optType);
|
clone->optType = ResolveType(clone->optType);
|
||||||
|
|
||||||
if (clone->initialValue && clone->optType != GetExpressionType(*clone->initialValue))
|
if (clone->defaultValue && clone->optType != GetExpressionType(*clone->defaultValue))
|
||||||
throw AstError{ "option " + clone->optName + " initial expression must be of the same type than the option" };
|
throw AstError{ "option " + clone->optName + " default expression must be of the same type than the option" };
|
||||||
|
|
||||||
std::size_t optionIndex = m_context->nextOptionIndex++;
|
std::size_t optionIndex = m_context->nextOptionIndex++;
|
||||||
|
|
||||||
clone->optIndex = RegisterConstant(clone->optName, TestBit(m_context->options.enabledOptions, optionIndex));
|
if (auto optionValueIt = m_context->options.optionValues.find(optionIndex); optionValueIt != m_context->options.optionValues.end())
|
||||||
|
clone->optIndex = RegisterConstant(clone->optName, optionValueIt->second);
|
||||||
|
else if (clone->defaultValue)
|
||||||
|
clone->optIndex = RegisterConstant(clone->optName, ComputeConstantValue(*clone->defaultValue));
|
||||||
|
else
|
||||||
|
throw AstError{ "missing option " + clone->optName + " value (has no default value)" };
|
||||||
|
|
||||||
if (m_context->options.removeOptionDeclaration)
|
if (m_context->options.removeOptionDeclaration)
|
||||||
return ShaderBuilder::NoOp();
|
return ShaderBuilder::NoOp();
|
||||||
|
|
@ -1186,8 +1194,6 @@ namespace Nz::ShaderAst
|
||||||
return m_context->constantValues[constantId];
|
return m_context->constantValues[constantId];
|
||||||
};
|
};
|
||||||
|
|
||||||
optimizerOptions.enabledOptions = m_context->options.enabledOptions;
|
|
||||||
|
|
||||||
// Run optimizer on constant value to hopefully retrieve a single constant value
|
// Run optimizer on constant value to hopefully retrieve a single constant value
|
||||||
return static_unique_pointer_cast<T>(ShaderAst::Optimize(node, optimizerOptions));
|
return static_unique_pointer_cast<T>(ShaderAst::Optimize(node, optimizerOptions));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,6 @@ namespace Nz
|
||||||
std::optional<ShaderStageType> selectedStage;
|
std::optional<ShaderStageType> selectedStage;
|
||||||
std::unordered_map<std::size_t, FunctionData> functions;
|
std::unordered_map<std::size_t, FunctionData> functions;
|
||||||
ShaderAst::DeclareFunctionStatement* entryPoint = nullptr;
|
ShaderAst::DeclareFunctionStatement* entryPoint = nullptr;
|
||||||
UInt64 enabledOptions = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Builtin
|
struct Builtin
|
||||||
|
|
@ -139,6 +138,7 @@ namespace Nz
|
||||||
|
|
||||||
std::optional<ShaderStageType> stage;
|
std::optional<ShaderStageType> stage;
|
||||||
std::stringstream stream;
|
std::stringstream stream;
|
||||||
|
std::unordered_map<std::size_t, ShaderAst::ConstantValue> optionValues;
|
||||||
std::unordered_map<std::size_t, ShaderAst::StructDescription*> structs;
|
std::unordered_map<std::size_t, ShaderAst::StructDescription*> structs;
|
||||||
std::unordered_map<std::size_t, std::string> variableNames;
|
std::unordered_map<std::size_t, std::string> variableNames;
|
||||||
std::vector<InOutField> inputFields;
|
std::vector<InOutField> inputFields;
|
||||||
|
|
@ -147,7 +147,6 @@ namespace Nz
|
||||||
const GlslWriter::BindingMapping& bindingMapping;
|
const GlslWriter::BindingMapping& bindingMapping;
|
||||||
PreVisitor previsitor;
|
PreVisitor previsitor;
|
||||||
const States* states = nullptr;
|
const States* states = nullptr;
|
||||||
UInt64 enabledOptions = 0;
|
|
||||||
bool isInEntryPoint = false;
|
bool isInEntryPoint = false;
|
||||||
unsigned int indentLevel = 0;
|
unsigned int indentLevel = 0;
|
||||||
};
|
};
|
||||||
|
|
@ -155,7 +154,7 @@ namespace Nz
|
||||||
std::string GlslWriter::Generate(std::optional<ShaderStageType> shaderStage, ShaderAst::Statement& shader, const BindingMapping& bindingMapping, const States& states)
|
std::string GlslWriter::Generate(std::optional<ShaderStageType> shaderStage, ShaderAst::Statement& shader, const BindingMapping& bindingMapping, const States& states)
|
||||||
{
|
{
|
||||||
State state(bindingMapping);
|
State state(bindingMapping);
|
||||||
state.enabledOptions = states.enabledOptions;
|
state.optionValues = states.optionValues;
|
||||||
state.stage = shaderStage;
|
state.stage = shaderStage;
|
||||||
|
|
||||||
m_currentState = &state;
|
m_currentState = &state;
|
||||||
|
|
@ -168,7 +167,7 @@ namespace Nz
|
||||||
ShaderAst::Statement* targetAst;
|
ShaderAst::Statement* targetAst;
|
||||||
if (!states.sanitized)
|
if (!states.sanitized)
|
||||||
{
|
{
|
||||||
sanitizedAst = Sanitize(shader, states.enabledOptions);
|
sanitizedAst = Sanitize(shader, states.optionValues);
|
||||||
targetAst = sanitizedAst.get();
|
targetAst = sanitizedAst.get();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -182,7 +181,6 @@ namespace Nz
|
||||||
targetAst = optimizedAst.get();
|
targetAst = optimizedAst.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
state.previsitor.enabledOptions = states.enabledOptions;
|
|
||||||
state.previsitor.selectedStage = shaderStage;
|
state.previsitor.selectedStage = shaderStage;
|
||||||
targetAst->Visit(state.previsitor);
|
targetAst->Visit(state.previsitor);
|
||||||
|
|
||||||
|
|
@ -203,11 +201,11 @@ namespace Nz
|
||||||
return s_flipYUniformName;
|
return s_flipYUniformName;
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderAst::StatementPtr GlslWriter::Sanitize(ShaderAst::Statement& ast, UInt64 enabledOptions, std::string* error)
|
ShaderAst::StatementPtr GlslWriter::Sanitize(ShaderAst::Statement& ast, std::unordered_map<std::size_t, ShaderAst::ConstantValue> optionValues, std::string* error)
|
||||||
{
|
{
|
||||||
// Always sanitize for reserved identifiers
|
// Always sanitize for reserved identifiers
|
||||||
ShaderAst::SanitizeVisitor::Options options;
|
ShaderAst::SanitizeVisitor::Options options;
|
||||||
options.enabledOptions = enabledOptions;
|
options.optionValues = std::move(optionValues);
|
||||||
options.makeVariableNameUnique = true;
|
options.makeVariableNameUnique = true;
|
||||||
options.reservedIdentifiers = {
|
options.reservedIdentifiers = {
|
||||||
// All reserved GLSL keywords as of GLSL ES 3.2
|
// All reserved GLSL keywords as of GLSL ES 3.2
|
||||||
|
|
@ -837,7 +835,9 @@ namespace Nz
|
||||||
if constexpr (std::is_same_v<T, Vector2i32> || std::is_same_v<T, Vector3i32> || std::is_same_v<T, Vector4i32>)
|
if constexpr (std::is_same_v<T, Vector2i32> || std::is_same_v<T, Vector3i32> || std::is_same_v<T, Vector4i32>)
|
||||||
Append("i"); //< for ivec
|
Append("i"); //< for ivec
|
||||||
|
|
||||||
if constexpr (std::is_same_v<T, bool>)
|
if constexpr (std::is_same_v<T, ShaderAst::NoValue>)
|
||||||
|
throw std::runtime_error("invalid type (value expected)");
|
||||||
|
else if constexpr (std::is_same_v<T, bool>)
|
||||||
Append((arg) ? "true" : "false");
|
Append((arg) ? "true" : "false");
|
||||||
else if constexpr (std::is_same_v<T, float> || std::is_same_v<T, Int32> || std::is_same_v<T, UInt32>)
|
else if constexpr (std::is_same_v<T, float> || std::is_same_v<T, Int32> || std::is_same_v<T, UInt32>)
|
||||||
Append(std::to_string(arg));
|
Append(std::to_string(arg));
|
||||||
|
|
|
||||||
|
|
@ -643,7 +643,9 @@ namespace Nz
|
||||||
{
|
{
|
||||||
using T = std::decay_t<decltype(arg)>;
|
using T = std::decay_t<decltype(arg)>;
|
||||||
|
|
||||||
if constexpr (std::is_same_v<T, bool>)
|
if constexpr (std::is_same_v<T, ShaderAst::NoValue>)
|
||||||
|
throw std::runtime_error("invalid type (value expected)");
|
||||||
|
else if constexpr (std::is_same_v<T, bool>)
|
||||||
Append((arg) ? "true" : "false");
|
Append((arg) ? "true" : "false");
|
||||||
else if constexpr (std::is_same_v<T, float> || std::is_same_v<T, Int32> || std::is_same_v<T, UInt32>)
|
else if constexpr (std::is_same_v<T, float> || std::is_same_v<T, Int32> || std::is_same_v<T, UInt32>)
|
||||||
Append(std::to_string(arg));
|
Append(std::to_string(arg));
|
||||||
|
|
@ -733,10 +735,10 @@ namespace Nz
|
||||||
RegisterConstant(*node.optIndex, node.optName);
|
RegisterConstant(*node.optIndex, node.optName);
|
||||||
|
|
||||||
Append("option ", node.optName, ": ", node.optType);
|
Append("option ", node.optName, ": ", node.optType);
|
||||||
if (node.initialValue)
|
if (node.defaultValue)
|
||||||
{
|
{
|
||||||
Append(" = ");
|
Append(" = ");
|
||||||
node.initialValue->Visit(*this);
|
node.defaultValue->Visit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
Append(";");
|
Append(";");
|
||||||
|
|
|
||||||
|
|
@ -418,7 +418,9 @@ namespace Nz
|
||||||
{
|
{
|
||||||
using T = std::decay_t<decltype(arg)>;
|
using T = std::decay_t<decltype(arg)>;
|
||||||
|
|
||||||
if constexpr (std::is_same_v<T, bool>)
|
if constexpr (std::is_same_v<T, ShaderAst::NoValue>)
|
||||||
|
throw std::runtime_error("invalid type (value expected)");
|
||||||
|
else if constexpr (std::is_same_v<T, bool>)
|
||||||
return ConstantBool{ arg };
|
return ConstantBool{ arg };
|
||||||
else if constexpr (std::is_same_v<T, float> || std::is_same_v<T, Int32> || std::is_same_v<T, UInt32>)
|
else if constexpr (std::is_same_v<T, float> || std::is_same_v<T, Int32> || std::is_same_v<T, UInt32>)
|
||||||
return ConstantScalar{ arg };
|
return ConstantScalar{ arg };
|
||||||
|
|
|
||||||
|
|
@ -463,7 +463,7 @@ namespace Nz
|
||||||
if (!states.sanitized)
|
if (!states.sanitized)
|
||||||
{
|
{
|
||||||
ShaderAst::SanitizeVisitor::Options options;
|
ShaderAst::SanitizeVisitor::Options options;
|
||||||
options.enabledOptions = states.enabledOptions;
|
options.optionValues = states.optionValues;
|
||||||
|
|
||||||
sanitizedAst = ShaderAst::Sanitize(shader, options);
|
sanitizedAst = ShaderAst::Sanitize(shader, options);
|
||||||
targetAst = sanitizedAst.get();
|
targetAst = sanitizedAst.get();
|
||||||
|
|
@ -653,11 +653,6 @@ namespace Nz
|
||||||
return m_currentState->constantTypeCache.GetId(*m_currentState->constantTypeCache.BuildType(type));
|
return m_currentState->constantTypeCache.GetId(*m_currentState->constantTypeCache.BuildType(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SpirvWriter::IsOptionEnabled(std::size_t optionIndex) const
|
|
||||||
{
|
|
||||||
return TestBit<Nz::UInt64>(m_context.states->enabledOptions, optionIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
UInt32 SpirvWriter::RegisterConstant(const ShaderAst::ConstantValue& value)
|
UInt32 SpirvWriter::RegisterConstant(const ShaderAst::ConstantValue& value)
|
||||||
{
|
{
|
||||||
return m_currentState->constantTypeCache.Register(*m_currentState->constantTypeCache.BuildConstant(value));
|
return m_currentState->constantTypeCache.Register(*m_currentState->constantTypeCache.BuildConstant(value));
|
||||||
|
|
|
||||||
|
|
@ -55,29 +55,24 @@ void CodeOutputWidget::Refresh()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Nz::UInt64 enabledOptions = 0;
|
Nz::ShaderWriter::States states;
|
||||||
|
|
||||||
for (std::size_t i = 0; i < m_shaderGraph.GetOptionCount(); ++i)
|
for (std::size_t i = 0; i < m_shaderGraph.GetOptionCount(); ++i)
|
||||||
{
|
states.optionValues[i] = m_shaderGraph.IsOptionEnabled(i);
|
||||||
if (m_shaderGraph.IsOptionEnabled(i))
|
|
||||||
enabledOptions = Nz::SetBit<Nz::UInt64>(enabledOptions, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
Nz::ShaderAst::StatementPtr shaderAst = m_shaderGraph.ToAst();
|
Nz::ShaderAst::StatementPtr shaderAst = m_shaderGraph.ToAst();
|
||||||
|
|
||||||
if (m_optimisationCheckbox->isChecked())
|
if (m_optimisationCheckbox->isChecked())
|
||||||
{
|
{
|
||||||
shaderAst = Nz::ShaderAst::Sanitize(*shaderAst);
|
Nz::ShaderAst::SanitizeVisitor::Options sanitizeOptions;
|
||||||
|
sanitizeOptions.optionValues = states.optionValues;
|
||||||
|
|
||||||
Nz::ShaderAst::AstOptimizer::Options optimOptions;
|
shaderAst = Nz::ShaderAst::Sanitize(*shaderAst, sanitizeOptions);
|
||||||
optimOptions.enabledOptions = enabledOptions;
|
|
||||||
|
|
||||||
Nz::ShaderAst::AstOptimizer optimiser;
|
Nz::ShaderAst::AstOptimizer optimiser;
|
||||||
shaderAst = optimiser.Optimise(*shaderAst, optimOptions);
|
shaderAst = optimiser.Optimise(*shaderAst);
|
||||||
}
|
}
|
||||||
|
|
||||||
Nz::ShaderWriter::States states;
|
|
||||||
states.enabledOptions = enabledOptions;
|
|
||||||
|
|
||||||
std::string output;
|
std::string output;
|
||||||
OutputLanguage outputLang = static_cast<OutputLanguage>(m_outputLang->currentIndex());
|
OutputLanguage outputLang = static_cast<OutputLanguage>(m_outputLang->currentIndex());
|
||||||
switch (outputLang)
|
switch (outputLang)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue