Add Phong lighting (WIP)
This commit is contained in:
parent
504249e70f
commit
b0a3941f4e
|
|
@ -65,8 +65,7 @@ fn main(input: FragIn) -> FragOut
|
||||||
|
|
||||||
let outputColor = vec4<f32>(0.0, 0.0, 0.0, 1.0);
|
let outputColor = vec4<f32>(0.0, 0.0, 0.0, 1.0);
|
||||||
|
|
||||||
let i = 0;
|
for i in 0 -> SampleCount
|
||||||
while (i < SampleCount)
|
|
||||||
{
|
{
|
||||||
uv -= deltaUV;
|
uv -= deltaUV;
|
||||||
let sample = occluderTexture.Sample(uv);
|
let sample = occluderTexture.Sample(uv);
|
||||||
|
|
@ -75,7 +74,6 @@ fn main(input: FragIn) -> FragOut
|
||||||
outputColor += sample;
|
outputColor += sample;
|
||||||
|
|
||||||
illuminationDecay *= settings.decay;
|
illuminationDecay *= settings.decay;
|
||||||
i += 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let output: FragOut;
|
let output: FragOut;
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ int main()
|
||||||
meshParams.center = true;
|
meshParams.center = true;
|
||||||
meshParams.storage = Nz::DataStorage::Software;
|
meshParams.storage = Nz::DataStorage::Software;
|
||||||
meshParams.matrix = Nz::Matrix4f::Rotate(Nz::EulerAnglesf(0.f, -90.f, 0.f)) * Nz::Matrix4f::Scale(Nz::Vector3f(0.002f));
|
meshParams.matrix = Nz::Matrix4f::Rotate(Nz::EulerAnglesf(0.f, -90.f, 0.f)) * Nz::Matrix4f::Scale(Nz::Vector3f(0.002f));
|
||||||
meshParams.vertexDeclaration = Nz::VertexDeclaration::Get(Nz::VertexLayout::XYZ_UV);
|
meshParams.vertexDeclaration = Nz::VertexDeclaration::Get(Nz::VertexLayout::XYZ_Normal_UV);
|
||||||
|
|
||||||
std::shared_ptr<Nz::RenderDevice> device = Nz::Graphics::Instance()->GetRenderDevice();
|
std::shared_ptr<Nz::RenderDevice> device = Nz::Graphics::Instance()->GetRenderDevice();
|
||||||
|
|
||||||
|
|
@ -64,16 +64,16 @@ int main()
|
||||||
|
|
||||||
std::shared_ptr<Nz::Material> material = std::make_shared<Nz::Material>();
|
std::shared_ptr<Nz::Material> material = std::make_shared<Nz::Material>();
|
||||||
|
|
||||||
std::shared_ptr<Nz::MaterialPass> materialPass = std::make_shared<Nz::MaterialPass>(Nz::BasicMaterial::GetSettings());
|
std::shared_ptr<Nz::MaterialPass> materialPass = std::make_shared<Nz::MaterialPass>(Nz::PhongLightingMaterial::GetSettings());
|
||||||
materialPass->EnableDepthBuffer(true);
|
materialPass->EnableDepthBuffer(true);
|
||||||
materialPass->EnableFaceCulling(true);
|
materialPass->EnableFaceCulling(true);
|
||||||
|
|
||||||
material->AddPass("ForwardPass", materialPass);
|
material->AddPass("ForwardPass", materialPass);
|
||||||
|
|
||||||
Nz::BasicMaterial basicMat(*materialPass);
|
Nz::PhongLightingMaterial phongMat(*materialPass);
|
||||||
basicMat.EnableAlphaTest(false);
|
phongMat.EnableAlphaTest(false);
|
||||||
basicMat.SetAlphaMap(Nz::Texture::LoadFromFile(resourceDir / "alphatile.png", texParams));
|
phongMat.SetAlphaMap(Nz::Texture::LoadFromFile(resourceDir / "alphatile.png", texParams));
|
||||||
basicMat.SetDiffuseMap(Nz::Texture::LoadFromFile(resourceDir / "Spaceship/Texture/diffuse.png", texParams));
|
phongMat.SetDiffuseMap(Nz::Texture::LoadFromFile(resourceDir / "Spaceship/Texture/diffuse.png", texParams));
|
||||||
|
|
||||||
Nz::Model model(std::move(gfxMesh), spaceshipMesh->GetAABB());
|
Nz::Model model(std::move(gfxMesh), spaceshipMesh->GetAABB());
|
||||||
for (std::size_t i = 0; i < model.GetSubMeshCount(); ++i)
|
for (std::size_t i = 0; i < model.GetSubMeshCount(); ++i)
|
||||||
|
|
@ -93,6 +93,8 @@ int main()
|
||||||
Nz::WorldInstancePtr modelInstance2 = std::make_shared<Nz::WorldInstance>();
|
Nz::WorldInstancePtr modelInstance2 = std::make_shared<Nz::WorldInstance>();
|
||||||
modelInstance2->UpdateWorldMatrix(Nz::Matrix4f::Translate(Nz::Vector3f::Forward() * 2 + Nz::Vector3f::Right()));
|
modelInstance2->UpdateWorldMatrix(Nz::Matrix4f::Translate(Nz::Vector3f::Forward() * 2 + Nz::Vector3f::Right()));
|
||||||
|
|
||||||
|
model.UpdateScissorBox(Nz::Recti(Nz::Vector2i(window.GetSize())));
|
||||||
|
|
||||||
Nz::ForwardFramePipeline framePipeline;
|
Nz::ForwardFramePipeline framePipeline;
|
||||||
framePipeline.RegisterViewer(&camera, 0);
|
framePipeline.RegisterViewer(&camera, 0);
|
||||||
framePipeline.RegisterInstancedDrawable(modelInstance, &model, 0xFFFFFFFF);
|
framePipeline.RegisterInstancedDrawable(modelInstance, &model, 0xFFFFFFFF);
|
||||||
|
|
@ -124,7 +126,7 @@ int main()
|
||||||
|
|
||||||
case Nz::WindowEventType::KeyPressed:
|
case Nz::WindowEventType::KeyPressed:
|
||||||
if (event.key.virtualKey == Nz::Keyboard::VKey::A)
|
if (event.key.virtualKey == Nz::Keyboard::VKey::A)
|
||||||
basicMat.EnableAlphaTest(!basicMat.IsAlphaTestEnabled());
|
phongMat.EnableAlphaTest(!phongMat.IsAlphaTestEnabled());
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -190,9 +192,9 @@ int main()
|
||||||
if (!frame)
|
if (!frame)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Nz::UploadPool& uploadPool = frame.GetUploadPool();
|
|
||||||
|
|
||||||
viewerInstance.UpdateViewMatrix(Nz::Matrix4f::ViewMatrix(viewerPos, camAngles));
|
viewerInstance.UpdateViewMatrix(Nz::Matrix4f::ViewMatrix(viewerPos, camAngles));
|
||||||
|
viewerInstance.UpdateEyePosition(viewerPos);
|
||||||
|
|
||||||
framePipeline.InvalidateViewer(&camera);
|
framePipeline.InvalidateViewer(&camera);
|
||||||
|
|
||||||
framePipeline.Render(frame);
|
framePipeline.Render(frame);
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ namespace Nz
|
||||||
friend class MaterialPipeline;
|
friend class MaterialPipeline;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
struct UniformOffsets;
|
struct BasicUniformOffsets;
|
||||||
|
|
||||||
BasicMaterial(MaterialPass& material);
|
BasicMaterial(MaterialPass& material);
|
||||||
~BasicMaterial() = default;
|
~BasicMaterial() = default;
|
||||||
|
|
@ -48,10 +48,10 @@ namespace Nz
|
||||||
inline void SetDiffuseMap(std::shared_ptr<Texture> diffuseMap);
|
inline void SetDiffuseMap(std::shared_ptr<Texture> diffuseMap);
|
||||||
inline void SetDiffuseSampler(TextureSamplerInfo diffuseSampler);
|
inline void SetDiffuseSampler(TextureSamplerInfo diffuseSampler);
|
||||||
|
|
||||||
static inline const UniformOffsets& GetOffsets();
|
static inline const BasicUniformOffsets& GetOffsets();
|
||||||
static inline const std::shared_ptr<MaterialSettings>& GetSettings();
|
static inline const std::shared_ptr<MaterialSettings>& GetSettings();
|
||||||
|
|
||||||
struct UniformOffsets
|
struct BasicUniformOffsets
|
||||||
{
|
{
|
||||||
std::size_t alphaThreshold;
|
std::size_t alphaThreshold;
|
||||||
std::size_t diffuseColor;
|
std::size_t diffuseColor;
|
||||||
|
|
@ -59,38 +59,59 @@ namespace Nz
|
||||||
};
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
struct OptionIndexes
|
struct NoInit {};
|
||||||
|
|
||||||
|
inline BasicMaterial(MaterialPass& material, NoInit);
|
||||||
|
|
||||||
|
struct BasicOptionIndexes
|
||||||
{
|
{
|
||||||
std::size_t alphaTest;
|
std::size_t alphaTest;
|
||||||
std::size_t hasAlphaMap;
|
std::size_t hasAlphaMap;
|
||||||
std::size_t hasDiffuseMap;
|
std::size_t hasDiffuseMap;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TextureIndexes
|
struct BasicTextureIndexes
|
||||||
{
|
{
|
||||||
std::size_t alpha;
|
std::size_t alpha;
|
||||||
std::size_t diffuse;
|
std::size_t diffuse;
|
||||||
};
|
};
|
||||||
|
|
||||||
static MaterialSettings::Builder Build(const UniformOffsets& offsets, std::vector<UInt8> defaultValues, std::vector<std::shared_ptr<UberShader>> uberShaders, std::size_t* uniformBlockIndex = nullptr, OptionIndexes* optionIndexes = nullptr, TextureIndexes* textureIndexes = nullptr);
|
struct BasicBuildOptions
|
||||||
|
{
|
||||||
|
// Common
|
||||||
|
std::vector<UInt8> defaultValues;
|
||||||
|
std::size_t* uniformBlockIndex = nullptr;
|
||||||
|
std::vector<std::shared_ptr<UberShader>> shaders;
|
||||||
|
|
||||||
|
// Basic
|
||||||
|
BasicUniformOffsets basicOffsets;
|
||||||
|
BasicOptionIndexes* basicOptionIndexes = nullptr;
|
||||||
|
BasicTextureIndexes* basicTextureIndexes = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline MaterialPass& GetMaterial();
|
||||||
|
inline const MaterialPass& GetMaterial() const;
|
||||||
|
|
||||||
|
static MaterialSettings::Builder Build(BasicBuildOptions& options);
|
||||||
static std::vector<std::shared_ptr<UberShader>> BuildShaders();
|
static std::vector<std::shared_ptr<UberShader>> BuildShaders();
|
||||||
static std::pair<UniformOffsets, FieldOffsets> BuildUniformOffsets();
|
static std::pair<BasicUniformOffsets, FieldOffsets> BuildUniformOffsets();
|
||||||
|
|
||||||
|
std::size_t m_uniformBlockIndex;
|
||||||
|
BasicOptionIndexes m_basicOptionIndexes;
|
||||||
|
BasicTextureIndexes m_basicTextureIndexes;
|
||||||
|
BasicUniformOffsets m_basicUniformOffsets;
|
||||||
|
|
||||||
|
static std::shared_ptr<MaterialSettings> s_basicMaterialSettings;
|
||||||
|
static std::size_t s_uniformBlockIndex;
|
||||||
|
static BasicOptionIndexes s_basicOptionIndexes;
|
||||||
|
static BasicTextureIndexes s_basicTextureIndexes;
|
||||||
|
static BasicUniformOffsets s_basicUniformOffsets;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static bool Initialize();
|
static bool Initialize();
|
||||||
static void Uninitialize();
|
static void Uninitialize();
|
||||||
|
|
||||||
MaterialPass& m_material;
|
MaterialPass& m_material;
|
||||||
std::size_t m_uniformBlockIndex;
|
|
||||||
OptionIndexes m_optionIndexes;
|
|
||||||
TextureIndexes m_textureIndexes;
|
|
||||||
UniformOffsets m_uniformOffsets;
|
|
||||||
|
|
||||||
static std::shared_ptr<MaterialSettings> s_materialSettings;
|
|
||||||
static std::size_t s_uniformBlockIndex;
|
|
||||||
static OptionIndexes s_optionIndexes;
|
|
||||||
static TextureIndexes s_textureIndexes;
|
|
||||||
static UniformOffsets s_uniformOffsets;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,11 @@
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
|
inline BasicMaterial::BasicMaterial(MaterialPass& material, NoInit) :
|
||||||
|
m_material(material)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Enable/Disable alpha test for this material
|
* \brief Enable/Disable alpha test for this material
|
||||||
*
|
*
|
||||||
|
|
@ -26,37 +31,37 @@ 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.SetOptionValue(m_optionIndexes.alphaTest, alphaTest);
|
m_material.SetOptionValue(m_basicOptionIndexes.alphaTest, alphaTest);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const std::shared_ptr<Texture>& BasicMaterial::GetAlphaMap() const
|
inline const std::shared_ptr<Texture>& BasicMaterial::GetAlphaMap() const
|
||||||
{
|
{
|
||||||
NazaraAssert(HasAlphaMap(), "Material has no alpha texture slot");
|
NazaraAssert(HasAlphaMap(), "Material has no alpha texture slot");
|
||||||
return m_material.GetTexture(m_textureIndexes.alpha);
|
return m_material.GetTexture(m_basicTextureIndexes.alpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const TextureSamplerInfo& BasicMaterial::GetAlphaSampler() const
|
inline const TextureSamplerInfo& BasicMaterial::GetAlphaSampler() const
|
||||||
{
|
{
|
||||||
NazaraAssert(HasAlphaMap(), "Material has no alpha texture slot");
|
NazaraAssert(HasAlphaMap(), "Material has no alpha texture slot");
|
||||||
return m_material.GetTextureSampler(m_textureIndexes.alpha);
|
return m_material.GetTextureSampler(m_basicTextureIndexes.alpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const std::shared_ptr<Texture>& BasicMaterial::GetDiffuseMap() const
|
inline const std::shared_ptr<Texture>& BasicMaterial::GetDiffuseMap() const
|
||||||
{
|
{
|
||||||
NazaraAssert(HasDiffuseMap(), "Material has no alpha texture slot");
|
NazaraAssert(HasDiffuseMap(), "Material has no alpha texture slot");
|
||||||
return m_material.GetTexture(m_textureIndexes.diffuse);
|
return m_material.GetTexture(m_basicTextureIndexes.diffuse);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const TextureSamplerInfo& BasicMaterial::GetDiffuseSampler() const
|
inline const TextureSamplerInfo& BasicMaterial::GetDiffuseSampler() const
|
||||||
{
|
{
|
||||||
NazaraAssert(HasDiffuseMap(), "Material has no alpha texture slot");
|
NazaraAssert(HasDiffuseMap(), "Material has no alpha texture slot");
|
||||||
return m_material.GetTextureSampler(m_textureIndexes.diffuse);
|
return m_material.GetTextureSampler(m_basicTextureIndexes.diffuse);
|
||||||
}
|
}
|
||||||
|
|
||||||
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");
|
||||||
const auto& optionOpt = m_material.GetOptionValue(m_optionIndexes.alphaTest);
|
const auto& optionOpt = m_material.GetOptionValue(m_basicOptionIndexes.alphaTest);
|
||||||
if (std::holds_alternative<ShaderAst::NoValue>(optionOpt))
|
if (std::holds_alternative<ShaderAst::NoValue>(optionOpt))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
@ -65,69 +70,79 @@ namespace Nz
|
||||||
|
|
||||||
inline bool BasicMaterial::HasAlphaMap() const
|
inline bool BasicMaterial::HasAlphaMap() const
|
||||||
{
|
{
|
||||||
return m_textureIndexes.alpha != MaterialSettings::InvalidIndex;
|
return m_basicTextureIndexes.alpha != MaterialSettings::InvalidIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool BasicMaterial::HasAlphaTest() const
|
inline bool BasicMaterial::HasAlphaTest() const
|
||||||
{
|
{
|
||||||
return m_optionIndexes.alphaTest != MaterialSettings::InvalidIndex;
|
return m_basicOptionIndexes.alphaTest != MaterialSettings::InvalidIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool BasicMaterial::HasAlphaTestThreshold() const
|
inline bool BasicMaterial::HasAlphaTestThreshold() const
|
||||||
{
|
{
|
||||||
return m_uniformOffsets.alphaThreshold != MaterialSettings::InvalidIndex;
|
return m_basicUniformOffsets.alphaThreshold != MaterialSettings::InvalidIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool BasicMaterial::HasDiffuseColor() const
|
inline bool BasicMaterial::HasDiffuseColor() const
|
||||||
{
|
{
|
||||||
return m_uniformOffsets.diffuseColor != MaterialSettings::InvalidIndex;
|
return m_basicUniformOffsets.diffuseColor != MaterialSettings::InvalidIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool BasicMaterial::HasDiffuseMap() const
|
inline bool BasicMaterial::HasDiffuseMap() const
|
||||||
{
|
{
|
||||||
return m_textureIndexes.diffuse != MaterialSettings::InvalidIndex;
|
return m_basicTextureIndexes.diffuse != MaterialSettings::InvalidIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void BasicMaterial::SetAlphaMap(std::shared_ptr<Texture> alphaMap)
|
inline void BasicMaterial::SetAlphaMap(std::shared_ptr<Texture> alphaMap)
|
||||||
{
|
{
|
||||||
NazaraAssert(HasAlphaMap(), "Material has no alpha map slot");
|
NazaraAssert(HasAlphaMap(), "Material has no alpha map slot");
|
||||||
bool hasAlphaMap = (alphaMap != nullptr);
|
bool hasAlphaMap = (alphaMap != nullptr);
|
||||||
m_material.SetTexture(m_textureIndexes.alpha, std::move(alphaMap));
|
m_material.SetTexture(m_basicTextureIndexes.alpha, std::move(alphaMap));
|
||||||
|
|
||||||
if (m_optionIndexes.hasDiffuseMap != MaterialSettings::InvalidIndex)
|
if (m_basicOptionIndexes.hasDiffuseMap != MaterialSettings::InvalidIndex)
|
||||||
m_material.SetOptionValue(m_optionIndexes.hasAlphaMap, hasAlphaMap);
|
m_material.SetOptionValue(m_basicOptionIndexes.hasAlphaMap, hasAlphaMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void BasicMaterial::SetAlphaSampler(TextureSamplerInfo alphaSampler)
|
inline void BasicMaterial::SetAlphaSampler(TextureSamplerInfo alphaSampler)
|
||||||
{
|
{
|
||||||
NazaraAssert(HasAlphaMap(), "Material has no alpha map slot");
|
NazaraAssert(HasAlphaMap(), "Material has no alpha map slot");
|
||||||
m_material.SetTextureSampler(m_textureIndexes.alpha, std::move(alphaSampler));
|
m_material.SetTextureSampler(m_basicTextureIndexes.alpha, std::move(alphaSampler));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void BasicMaterial::SetDiffuseMap(std::shared_ptr<Texture> diffuseMap)
|
inline void BasicMaterial::SetDiffuseMap(std::shared_ptr<Texture> diffuseMap)
|
||||||
{
|
{
|
||||||
NazaraAssert(HasDiffuseMap(), "Material has no diffuse map slot");
|
NazaraAssert(HasDiffuseMap(), "Material has no diffuse map slot");
|
||||||
bool hasDiffuseMap = (diffuseMap != nullptr);
|
bool hasDiffuseMap = (diffuseMap != nullptr);
|
||||||
m_material.SetTexture(m_textureIndexes.diffuse, std::move(diffuseMap));
|
m_material.SetTexture(m_basicTextureIndexes.diffuse, std::move(diffuseMap));
|
||||||
|
|
||||||
if (m_optionIndexes.hasDiffuseMap != MaterialSettings::InvalidIndex)
|
if (m_basicOptionIndexes.hasDiffuseMap != MaterialSettings::InvalidIndex)
|
||||||
m_material.SetOptionValue(m_optionIndexes.hasDiffuseMap, hasDiffuseMap);
|
m_material.SetOptionValue(m_basicOptionIndexes.hasDiffuseMap, hasDiffuseMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void BasicMaterial::SetDiffuseSampler(TextureSamplerInfo diffuseSampler)
|
inline void BasicMaterial::SetDiffuseSampler(TextureSamplerInfo diffuseSampler)
|
||||||
{
|
{
|
||||||
NazaraAssert(HasDiffuseMap(), "Material has no diffuse map slot");
|
NazaraAssert(HasDiffuseMap(), "Material has no diffuse map slot");
|
||||||
m_material.SetTextureSampler(m_textureIndexes.diffuse, std::move(diffuseSampler));
|
m_material.SetTextureSampler(m_basicTextureIndexes.diffuse, std::move(diffuseSampler));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline MaterialPass& BasicMaterial::GetMaterial()
|
||||||
|
{
|
||||||
|
return m_material;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const MaterialPass& BasicMaterial::GetMaterial() const
|
||||||
|
{
|
||||||
|
return m_material;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const std::shared_ptr<MaterialSettings>& BasicMaterial::GetSettings()
|
inline const std::shared_ptr<MaterialSettings>& BasicMaterial::GetSettings()
|
||||||
{
|
{
|
||||||
return s_materialSettings;
|
return s_basicMaterialSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline auto BasicMaterial::GetOffsets() -> const UniformOffsets&
|
inline auto BasicMaterial::GetOffsets() -> const BasicUniformOffsets&
|
||||||
{
|
{
|
||||||
return s_uniformOffsets;
|
return s_basicUniformOffsets;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ namespace Nz
|
||||||
static bool Initialize();
|
static bool Initialize();
|
||||||
static void Uninitialize();
|
static void Uninitialize();
|
||||||
|
|
||||||
static std::shared_ptr<MaterialSettings> s_materialSettings;
|
static std::shared_ptr<MaterialSettings> s_basicMaterialSettings;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ namespace Nz
|
||||||
{
|
{
|
||||||
inline const std::shared_ptr<MaterialSettings>& DepthMaterial::GetSettings()
|
inline const std::shared_ptr<MaterialSettings>& DepthMaterial::GetSettings()
|
||||||
{
|
{
|
||||||
return s_materialSettings;
|
return s_basicMaterialSettings;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
|
class AbstractBuffer;
|
||||||
class CommandBufferBuilder;
|
class CommandBufferBuilder;
|
||||||
class RenderElement;
|
class RenderElement;
|
||||||
class RenderFrame;
|
class RenderFrame;
|
||||||
|
|
@ -25,13 +26,20 @@ namespace Nz
|
||||||
class NAZARA_GRAPHICS_API ElementRenderer
|
class NAZARA_GRAPHICS_API ElementRenderer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
struct RenderStates;
|
||||||
|
|
||||||
ElementRenderer() = default;
|
ElementRenderer() = default;
|
||||||
virtual ~ElementRenderer();
|
virtual ~ElementRenderer();
|
||||||
|
|
||||||
virtual std::unique_ptr<ElementRendererData> InstanciateData() = 0;
|
virtual std::unique_ptr<ElementRendererData> InstanciateData() = 0;
|
||||||
virtual void Prepare(const ViewerInstance& viewerInstance, ElementRendererData& rendererData, RenderFrame& currentFrame, const Pointer<const RenderElement>* elements, std::size_t elementCount);
|
virtual void Prepare(const ViewerInstance& viewerInstance, ElementRendererData& rendererData, RenderFrame& currentFrame, const RenderStates& renderStates, const Pointer<const RenderElement>* elements, std::size_t elementCount);
|
||||||
virtual void Render(const ViewerInstance& viewerInstance, ElementRendererData& rendererData, CommandBufferBuilder& commandBuffer, const Pointer<const RenderElement>* elements, std::size_t elementCount) = 0;
|
virtual void Render(const ViewerInstance& viewerInstance, ElementRendererData& rendererData, CommandBufferBuilder& commandBuffer, const Pointer<const RenderElement>* elements, std::size_t elementCount) = 0;
|
||||||
virtual void Reset(ElementRendererData& rendererData, RenderFrame& currentFrame);
|
virtual void Reset(ElementRendererData& rendererData, RenderFrame& currentFrame);
|
||||||
|
|
||||||
|
struct RenderStates
|
||||||
|
{
|
||||||
|
std::shared_ptr<AbstractBuffer> lightData;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NAZARA_GRAPHICS_API ElementRendererData
|
struct NAZARA_GRAPHICS_API ElementRendererData
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,15 @@
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
|
enum class BasicLightType
|
||||||
|
{
|
||||||
|
Directional,
|
||||||
|
Point,
|
||||||
|
Spot,
|
||||||
|
|
||||||
|
Max = Spot
|
||||||
|
};
|
||||||
|
|
||||||
enum class BasicRenderElement
|
enum class BasicRenderElement
|
||||||
{
|
{
|
||||||
SpriteChain = 0,
|
SpriteChain = 0,
|
||||||
|
|
@ -54,6 +63,7 @@ namespace Nz
|
||||||
enum class PredefinedShaderBinding
|
enum class PredefinedShaderBinding
|
||||||
{
|
{
|
||||||
InstanceDataUbo,
|
InstanceDataUbo,
|
||||||
|
LightDataUbo,
|
||||||
OverlayTexture,
|
OverlayTexture,
|
||||||
ViewerDataUbo,
|
ViewerDataUbo,
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -108,6 +108,7 @@ namespace Nz
|
||||||
|
|
||||||
std::size_t m_depthPassIndex;
|
std::size_t m_depthPassIndex;
|
||||||
std::size_t m_forwardPassIndex;
|
std::size_t m_forwardPassIndex;
|
||||||
|
std::shared_ptr<AbstractBuffer> m_lightDataBuffer;
|
||||||
std::unordered_map<AbstractViewer*, ViewerData> m_viewers;
|
std::unordered_map<AbstractViewer*, ViewerData> m_viewers;
|
||||||
std::unordered_map<MaterialPass*, MaterialData> m_materials;
|
std::unordered_map<MaterialPass*, MaterialData> m_materials;
|
||||||
std::unordered_map<WorldInstancePtr, std::unordered_map<const InstancedRenderable*, RenderableData>> m_renderables;
|
std::unordered_map<WorldInstancePtr, std::unordered_map<const InstancedRenderable*, RenderableData>> m_renderables;
|
||||||
|
|
|
||||||
|
|
@ -57,10 +57,6 @@ namespace Nz
|
||||||
std::array<std::shared_ptr<Texture>, ImageTypeCount> whiteTextures;
|
std::array<std::shared_ptr<Texture>, ImageTypeCount> whiteTextures;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void FillDrawDataPipelineLayout(RenderPipelineLayoutInfo& layoutInfo, UInt32 set);
|
|
||||||
static void FillViewerPipelineLayout(RenderPipelineLayoutInfo& layoutInfo, UInt32 set);
|
|
||||||
static void FillWorldPipelineLayout(RenderPipelineLayoutInfo& layoutInfo, UInt32 set);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void BuildBlitPipeline();
|
void BuildBlitPipeline();
|
||||||
void BuildDefaultTextures();
|
void BuildDefaultTextures();
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,7 @@ namespace Nz
|
||||||
inline const std::shared_ptr<Texture>& GetTexture(std::size_t textureIndex) const;
|
inline const std::shared_ptr<Texture>& GetTexture(std::size_t textureIndex) const;
|
||||||
inline const TextureSamplerInfo& GetTextureSampler(std::size_t textureIndex) const;
|
inline const TextureSamplerInfo& GetTextureSampler(std::size_t textureIndex) const;
|
||||||
inline const std::shared_ptr<AbstractBuffer>& GetUniformBuffer(std::size_t bufferIndex) const;
|
inline const std::shared_ptr<AbstractBuffer>& GetUniformBuffer(std::size_t bufferIndex) const;
|
||||||
inline const std::vector<UInt8>& GetUniformBufferConstData(std::size_t bufferIndex);
|
inline const std::vector<UInt8>& GetUniformBufferConstData(std::size_t bufferIndex) const;
|
||||||
inline std::vector<UInt8>& GetUniformBufferData(std::size_t bufferIndex);
|
inline std::vector<UInt8>& GetUniformBufferData(std::size_t bufferIndex);
|
||||||
|
|
||||||
inline bool HasTexture(std::size_t textureIndex) const;
|
inline bool HasTexture(std::size_t textureIndex) const;
|
||||||
|
|
|
||||||
|
|
@ -391,7 +391,7 @@ namespace Nz
|
||||||
return m_uniformBuffers[bufferIndex].buffer;
|
return m_uniformBuffers[bufferIndex].buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const std::vector<UInt8>& MaterialPass::GetUniformBufferConstData(std::size_t bufferIndex)
|
inline const std::vector<UInt8>& MaterialPass::GetUniformBufferConstData(std::size_t bufferIndex) const
|
||||||
{
|
{
|
||||||
NazaraAssert(bufferIndex < m_uniformBuffers.size(), "Invalid uniform buffer index");
|
NazaraAssert(bufferIndex < m_uniformBuffers.size(), "Invalid uniform buffer index");
|
||||||
return m_uniformBuffers[bufferIndex].data;
|
return m_uniformBuffers[bufferIndex].data;
|
||||||
|
|
|
||||||
|
|
@ -8,38 +8,31 @@
|
||||||
#define NAZARA_GRAPHICS_PHONGLIGHTINGMATERIAL_HPP
|
#define NAZARA_GRAPHICS_PHONGLIGHTINGMATERIAL_HPP
|
||||||
|
|
||||||
#include <Nazara/Prerequisites.hpp>
|
#include <Nazara/Prerequisites.hpp>
|
||||||
|
#include <Nazara/Graphics/BasicMaterial.hpp>
|
||||||
#include <Nazara/Graphics/MaterialPass.hpp>
|
#include <Nazara/Graphics/MaterialPass.hpp>
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
class NAZARA_GRAPHICS_API PhongLightingMaterial
|
class NAZARA_GRAPHICS_API PhongLightingMaterial : public BasicMaterial
|
||||||
{
|
{
|
||||||
friend class MaterialPipeline;
|
friend class MaterialPipeline;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PhongLightingMaterial(MaterialPass& material);
|
PhongLightingMaterial(MaterialPass& material);
|
||||||
|
|
||||||
inline const std::shared_ptr<Texture>& GetAlphaMap() const;
|
|
||||||
float GetAlphaThreshold() const;
|
|
||||||
Color GetAmbientColor() const;
|
Color GetAmbientColor() const;
|
||||||
Color GetDiffuseColor() const;
|
|
||||||
inline const std::shared_ptr<Texture>& GetDiffuseMap() const;
|
|
||||||
inline TextureSampler& GetDiffuseSampler();
|
|
||||||
inline const TextureSampler& GetDiffuseSampler() const;
|
|
||||||
inline const std::shared_ptr<Texture>& GetEmissiveMap() const;
|
inline const std::shared_ptr<Texture>& GetEmissiveMap() const;
|
||||||
|
inline const TextureSamplerInfo& GetEmissiveSampler() const;
|
||||||
inline const std::shared_ptr<Texture>& GetHeightMap() const;
|
inline const std::shared_ptr<Texture>& GetHeightMap() const;
|
||||||
|
inline const TextureSamplerInfo& GetHeightSampler() const;
|
||||||
inline const std::shared_ptr<Texture>& GetNormalMap() const;
|
inline const std::shared_ptr<Texture>& GetNormalMap() const;
|
||||||
|
inline const TextureSamplerInfo& GetNormalSampler() const;
|
||||||
float GetShininess() const;
|
float GetShininess() const;
|
||||||
Color GetSpecularColor() const;
|
Color GetSpecularColor() const;
|
||||||
inline const std::shared_ptr<Texture>& GetSpecularMap() const;
|
inline const std::shared_ptr<Texture>& GetSpecularMap() const;
|
||||||
inline TextureSampler& GetSpecularSampler();
|
inline const TextureSamplerInfo& GetSpecularSampler() const;
|
||||||
inline const TextureSampler& GetSpecularSampler() const;
|
|
||||||
|
|
||||||
inline bool HasAlphaMap() const;
|
|
||||||
inline bool HasAlphaThreshold() const;
|
|
||||||
inline bool HasAmbientColor() const;
|
inline bool HasAmbientColor() const;
|
||||||
inline bool HasDiffuseColor() const;
|
|
||||||
inline bool HasDiffuseMap() const;
|
|
||||||
inline bool HasEmissiveMap() const;
|
inline bool HasEmissiveMap() const;
|
||||||
inline bool HasHeightMap() const;
|
inline bool HasHeightMap() const;
|
||||||
inline bool HasNormalMap() const;
|
inline bool HasNormalMap() const;
|
||||||
|
|
@ -47,53 +40,68 @@ namespace Nz
|
||||||
inline bool HasSpecularColor() const;
|
inline bool HasSpecularColor() const;
|
||||||
inline bool HasSpecularMap() const;
|
inline bool HasSpecularMap() const;
|
||||||
|
|
||||||
inline void SetAlphaMap(std::shared_ptr<Texture> alphaMap);
|
|
||||||
void SetAlphaThreshold(float alphaThreshold);
|
|
||||||
void SetAmbientColor(const Color& ambient);
|
void SetAmbientColor(const Color& ambient);
|
||||||
void SetDiffuseColor(const Color& diffuse);
|
inline void SetEmissiveMap(std::shared_ptr<Texture> emissiveMap);
|
||||||
inline void SetDiffuseMap(std::shared_ptr<Texture> diffuseMap);
|
inline void SetEmissiveSampler(TextureSamplerInfo emissiveSampler);
|
||||||
inline void SetDiffuseSampler(const TextureSampler& sampler);
|
inline void SetHeightMap(std::shared_ptr<Texture> heightMap);
|
||||||
inline void SetEmissiveMap(std::shared_ptr<Texture> textureName);
|
inline void SetHeightSampler(TextureSamplerInfo heightSampler);
|
||||||
inline void SetHeightMap(std::shared_ptr<Texture> textureName);
|
inline void SetNormalMap(std::shared_ptr<Texture> normalMap);
|
||||||
inline void SetNormalMap(std::shared_ptr<Texture> textureName);
|
inline void SetNormalSampler(TextureSamplerInfo normalSampler);
|
||||||
void SetShininess(float shininess);
|
void SetShininess(float shininess);
|
||||||
void SetSpecularColor(const Color& specular);
|
void SetSpecularColor(const Color& specular);
|
||||||
inline void SetSpecularMap(std::shared_ptr<Texture> specularMap);
|
inline void SetSpecularMap(std::shared_ptr<Texture> specularMap);
|
||||||
inline void SetSpecularSampler(const TextureSampler& sampler);
|
inline void SetSpecularSampler(TextureSamplerInfo specularSampler);
|
||||||
|
|
||||||
static const std::shared_ptr<MaterialSettings>& GetSettings();
|
static const std::shared_ptr<MaterialSettings>& GetSettings();
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
|
struct PhongOptionIndexes
|
||||||
|
{
|
||||||
|
std::size_t hasEmissiveMap;
|
||||||
|
std::size_t hasHeightMap;
|
||||||
|
std::size_t hasNormalMap;
|
||||||
|
std::size_t hasSpecularMap;
|
||||||
|
};
|
||||||
|
|
||||||
struct PhongUniformOffsets
|
struct PhongUniformOffsets
|
||||||
{
|
{
|
||||||
std::size_t alphaThreshold;
|
|
||||||
std::size_t shininess;
|
|
||||||
std::size_t ambientColor;
|
std::size_t ambientColor;
|
||||||
std::size_t diffuseColor;
|
std::size_t shininess;
|
||||||
|
std::size_t totalSize;
|
||||||
std::size_t specularColor;
|
std::size_t specularColor;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TextureIndexes
|
struct PhongTextureIndexes
|
||||||
{
|
{
|
||||||
std::size_t alpha;
|
|
||||||
std::size_t diffuse;
|
|
||||||
std::size_t emissive;
|
std::size_t emissive;
|
||||||
std::size_t height;
|
std::size_t height;
|
||||||
std::size_t normal;
|
std::size_t normal;
|
||||||
std::size_t specular;
|
std::size_t specular;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct PhongBuildOptions : BasicBuildOptions
|
||||||
|
{
|
||||||
|
PhongUniformOffsets phongOffsets;
|
||||||
|
PhongOptionIndexes* phongOptionIndexes = nullptr;
|
||||||
|
PhongTextureIndexes* phongTextureIndexes = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
PhongOptionIndexes m_phongOptionIndexes;
|
||||||
|
PhongTextureIndexes m_phongTextureIndexes;
|
||||||
|
PhongUniformOffsets m_phongUniformOffsets;
|
||||||
|
|
||||||
|
static MaterialSettings::Builder Build(PhongBuildOptions& options);
|
||||||
|
static std::vector<std::shared_ptr<UberShader>> BuildShaders();
|
||||||
|
static std::pair<PhongUniformOffsets, FieldOffsets> BuildUniformOffsets();
|
||||||
|
|
||||||
|
private:
|
||||||
static bool Initialize();
|
static bool Initialize();
|
||||||
static void Uninitialize();
|
static void Uninitialize();
|
||||||
|
|
||||||
MaterialPass& m_material;
|
static std::shared_ptr<MaterialSettings> s_phongMaterialSettings;
|
||||||
std::size_t m_phongUniformIndex;
|
|
||||||
TextureIndexes m_textureIndexes;
|
|
||||||
PhongUniformOffsets m_phongUniformOffsets;
|
|
||||||
|
|
||||||
static std::shared_ptr<MaterialSettings> s_materialSettings;
|
|
||||||
static std::size_t s_phongUniformBlockIndex;
|
static std::size_t s_phongUniformBlockIndex;
|
||||||
static TextureIndexes s_textureIndexes;
|
static PhongOptionIndexes s_phongOptionIndexes;
|
||||||
|
static PhongTextureIndexes s_phongTextureIndexes;
|
||||||
static PhongUniformOffsets s_phongUniformOffsets;
|
static PhongUniformOffsets s_phongUniformOffsets;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,50 +9,52 @@
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
inline const std::shared_ptr<Texture>& PhongLightingMaterial::GetAlphaMap() const
|
|
||||||
{
|
|
||||||
NazaraAssert(HasAlphaMap(), "Material has no alpha map slot");
|
|
||||||
return m_material.GetTexture(m_textureIndexes.alpha);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const std::shared_ptr<Texture>& PhongLightingMaterial::GetDiffuseMap() const
|
|
||||||
{
|
|
||||||
NazaraAssert(HasDiffuseMap(), "Material has no alpha map slot");
|
|
||||||
return m_material.GetTexture(m_textureIndexes.diffuse);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const std::shared_ptr<Texture>& PhongLightingMaterial::GetEmissiveMap() const
|
inline const std::shared_ptr<Texture>& PhongLightingMaterial::GetEmissiveMap() const
|
||||||
{
|
{
|
||||||
NazaraAssert(HasEmissiveMap(), "Material has no alpha map slot");
|
NazaraAssert(HasEmissiveMap(), "Material has no emissive map slot");
|
||||||
return m_material.GetTexture(m_textureIndexes.emissive);
|
return GetMaterial().GetTexture(m_phongTextureIndexes.emissive);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const TextureSamplerInfo& PhongLightingMaterial::GetEmissiveSampler() const
|
||||||
|
{
|
||||||
|
NazaraAssert(HasSpecularMap(), "Material has no emissive map slot");
|
||||||
|
return GetMaterial().GetTextureSampler(m_phongTextureIndexes.emissive);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const std::shared_ptr<Texture>& PhongLightingMaterial::GetHeightMap() const
|
inline const std::shared_ptr<Texture>& PhongLightingMaterial::GetHeightMap() const
|
||||||
{
|
{
|
||||||
NazaraAssert(HasHeightMap(), "Material has no alpha map slot");
|
NazaraAssert(HasHeightMap(), "Material has no height map slot");
|
||||||
return m_material.GetTexture(m_textureIndexes.height);
|
return GetMaterial().GetTexture(m_phongTextureIndexes.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const TextureSamplerInfo& PhongLightingMaterial::GetHeightSampler() const
|
||||||
|
{
|
||||||
|
NazaraAssert(HasSpecularMap(), "Material has no height map slot");
|
||||||
|
return GetMaterial().GetTextureSampler(m_phongTextureIndexes.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const std::shared_ptr<Texture>& PhongLightingMaterial::GetNormalMap() const
|
inline const std::shared_ptr<Texture>& PhongLightingMaterial::GetNormalMap() const
|
||||||
{
|
{
|
||||||
NazaraAssert(HasNormalMap(), "Material has no alpha map slot");
|
NazaraAssert(HasNormalMap(), "Material has no normal map slot");
|
||||||
return m_material.GetTexture(m_textureIndexes.normal);
|
return GetMaterial().GetTexture(m_phongTextureIndexes.normal);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const TextureSamplerInfo& PhongLightingMaterial::GetNormalSampler() const
|
||||||
|
{
|
||||||
|
NazaraAssert(HasSpecularMap(), "Material has no normal map slot");
|
||||||
|
return GetMaterial().GetTextureSampler(m_phongTextureIndexes.normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const std::shared_ptr<Texture>& PhongLightingMaterial::GetSpecularMap() const
|
inline const std::shared_ptr<Texture>& PhongLightingMaterial::GetSpecularMap() const
|
||||||
{
|
{
|
||||||
NazaraAssert(HasSpecularMap(), "Material has no alpha map slot");
|
NazaraAssert(HasSpecularMap(), "Material has no specular map slot");
|
||||||
return m_material.GetTexture(m_textureIndexes.specular);
|
return GetMaterial().GetTexture(m_phongTextureIndexes.specular);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool PhongLightingMaterial::HasAlphaMap() const
|
inline const TextureSamplerInfo& PhongLightingMaterial::GetSpecularSampler() const
|
||||||
{
|
{
|
||||||
return m_textureIndexes.alpha != MaterialSettings::InvalidIndex;
|
NazaraAssert(HasSpecularMap(), "Material has no specular map slot");
|
||||||
}
|
return GetMaterial().GetTextureSampler(m_phongTextureIndexes.specular);
|
||||||
|
|
||||||
inline bool PhongLightingMaterial::HasAlphaThreshold() const
|
|
||||||
{
|
|
||||||
return m_phongUniformOffsets.alphaThreshold != MaterialSettings::InvalidIndex;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool PhongLightingMaterial::HasAmbientColor() const
|
inline bool PhongLightingMaterial::HasAmbientColor() const
|
||||||
|
|
@ -60,29 +62,19 @@ namespace Nz
|
||||||
return m_phongUniformOffsets.ambientColor != MaterialSettings::InvalidIndex;
|
return m_phongUniformOffsets.ambientColor != MaterialSettings::InvalidIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool PhongLightingMaterial::HasDiffuseColor() const
|
|
||||||
{
|
|
||||||
return m_phongUniformOffsets.diffuseColor != MaterialSettings::InvalidIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool PhongLightingMaterial::HasDiffuseMap() const
|
|
||||||
{
|
|
||||||
return m_textureIndexes.diffuse != MaterialSettings::InvalidIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool PhongLightingMaterial::HasEmissiveMap() const
|
inline bool PhongLightingMaterial::HasEmissiveMap() const
|
||||||
{
|
{
|
||||||
return m_textureIndexes.emissive != MaterialSettings::InvalidIndex;
|
return m_phongTextureIndexes.emissive != MaterialSettings::InvalidIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool PhongLightingMaterial::HasHeightMap() const
|
inline bool PhongLightingMaterial::HasHeightMap() const
|
||||||
{
|
{
|
||||||
return m_textureIndexes.height != MaterialSettings::InvalidIndex;
|
return m_phongTextureIndexes.height != MaterialSettings::InvalidIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool PhongLightingMaterial::HasNormalMap() const
|
inline bool PhongLightingMaterial::HasNormalMap() const
|
||||||
{
|
{
|
||||||
return m_textureIndexes.normal != MaterialSettings::InvalidIndex;
|
return m_phongTextureIndexes.normal != MaterialSettings::InvalidIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool PhongLightingMaterial::HasShininess() const
|
inline bool PhongLightingMaterial::HasShininess() const
|
||||||
|
|
@ -97,25 +89,71 @@ namespace Nz
|
||||||
|
|
||||||
inline bool PhongLightingMaterial::HasSpecularMap() const
|
inline bool PhongLightingMaterial::HasSpecularMap() const
|
||||||
{
|
{
|
||||||
return m_textureIndexes.specular != MaterialSettings::InvalidIndex;
|
return m_phongTextureIndexes.specular != MaterialSettings::InvalidIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void PhongLightingMaterial::SetAlphaMap(std::shared_ptr<Texture> alphaMap)
|
inline void PhongLightingMaterial::SetEmissiveMap(std::shared_ptr<Texture> emissiveMap)
|
||||||
{
|
{
|
||||||
NazaraAssert(HasAlphaMap(), "Material has no alpha map slot");
|
NazaraAssert(HasEmissiveMap(), "Material has no emissive map slot");
|
||||||
m_material.SetTexture(m_textureIndexes.alpha, std::move(alphaMap));
|
bool hasEmissiveMap = (emissiveMap != nullptr);
|
||||||
|
GetMaterial().SetTexture(m_phongTextureIndexes.emissive, std::move(emissiveMap));
|
||||||
|
|
||||||
|
if (m_phongOptionIndexes.hasEmissiveMap != MaterialSettings::InvalidIndex)
|
||||||
|
GetMaterial().SetOptionValue(m_phongOptionIndexes.hasEmissiveMap, hasEmissiveMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void PhongLightingMaterial::SetDiffuseMap(std::shared_ptr<Texture> diffuseMap)
|
inline void PhongLightingMaterial::SetEmissiveSampler(TextureSamplerInfo emissiveSampler)
|
||||||
{
|
{
|
||||||
NazaraAssert(HasDiffuseMap(), "Material has no diffuse map slot");
|
NazaraAssert(HasEmissiveMap(), "Material has no emissive map slot");
|
||||||
m_material.SetTexture(m_textureIndexes.diffuse, std::move(diffuseMap));
|
GetMaterial().SetTextureSampler(m_phongTextureIndexes.emissive, std::move(emissiveSampler));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void PhongLightingMaterial::SetHeightMap(std::shared_ptr<Texture> heightMap)
|
||||||
|
{
|
||||||
|
NazaraAssert(HasHeightMap(), "Material has no specular map slot");
|
||||||
|
bool hasHeightMap = (heightMap != nullptr);
|
||||||
|
GetMaterial().SetTexture(m_phongTextureIndexes.height, std::move(heightMap));
|
||||||
|
|
||||||
|
if (m_phongOptionIndexes.hasHeightMap != MaterialSettings::InvalidIndex)
|
||||||
|
GetMaterial().SetOptionValue(m_phongOptionIndexes.hasHeightMap, hasHeightMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void PhongLightingMaterial::SetHeightSampler(TextureSamplerInfo heightSampler)
|
||||||
|
{
|
||||||
|
NazaraAssert(HasHeightMap(), "Material has no height map slot");
|
||||||
|
GetMaterial().SetTextureSampler(m_phongTextureIndexes.height, std::move(heightSampler));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void PhongLightingMaterial::SetNormalMap(std::shared_ptr<Texture> normalMap)
|
inline void PhongLightingMaterial::SetNormalMap(std::shared_ptr<Texture> normalMap)
|
||||||
{
|
{
|
||||||
NazaraAssert(HasNormalMap(), "Material has no normal map slot");
|
NazaraAssert(HasNormalMap(), "Material has no normal map slot");
|
||||||
m_material.SetTexture(m_textureIndexes.normal, std::move(normalMap));
|
bool hasNormalMap = (normalMap != nullptr);
|
||||||
|
GetMaterial().SetTexture(m_phongTextureIndexes.normal, std::move(normalMap));
|
||||||
|
|
||||||
|
if (m_phongOptionIndexes.hasNormalMap != MaterialSettings::InvalidIndex)
|
||||||
|
GetMaterial().SetOptionValue(m_phongOptionIndexes.hasNormalMap, hasNormalMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void PhongLightingMaterial::SetNormalSampler(TextureSamplerInfo normalSampler)
|
||||||
|
{
|
||||||
|
NazaraAssert(HasNormalMap(), "Material has no normal map slot");
|
||||||
|
GetMaterial().SetTextureSampler(m_phongTextureIndexes.normal, std::move(normalSampler));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void PhongLightingMaterial::SetSpecularMap(std::shared_ptr<Texture> specularMap)
|
||||||
|
{
|
||||||
|
NazaraAssert(HasNormalMap(), "Material has no specular map slot");
|
||||||
|
bool hasSpecularMap = (specularMap != nullptr);
|
||||||
|
GetMaterial().SetTexture(m_phongTextureIndexes.specular, std::move(specularMap));
|
||||||
|
|
||||||
|
if (m_phongOptionIndexes.hasSpecularMap != MaterialSettings::InvalidIndex)
|
||||||
|
GetMaterial().SetOptionValue(m_phongOptionIndexes.hasSpecularMap, hasSpecularMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void PhongLightingMaterial::SetSpecularSampler(TextureSamplerInfo specularSampler)
|
||||||
|
{
|
||||||
|
NazaraAssert(HasSpecularMap(), "Material has no specular map slot");
|
||||||
|
GetMaterial().SetTextureSampler(m_phongTextureIndexes.specular, std::move(specularSampler));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ namespace Nz
|
||||||
{
|
{
|
||||||
struct NAZARA_GRAPHICS_API PredefinedLightData
|
struct NAZARA_GRAPHICS_API PredefinedLightData
|
||||||
{
|
{
|
||||||
struct InnerStruct
|
struct Light
|
||||||
{
|
{
|
||||||
std::size_t type;
|
std::size_t type;
|
||||||
std::size_t color;
|
std::size_t color;
|
||||||
|
|
@ -24,15 +24,18 @@ namespace Nz
|
||||||
std::size_t parameter2;
|
std::size_t parameter2;
|
||||||
std::size_t parameter3;
|
std::size_t parameter3;
|
||||||
std::size_t shadowMappingFlag;
|
std::size_t shadowMappingFlag;
|
||||||
std::size_t totalSize;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
InnerStruct innerOffsets;
|
std::size_t lightsOffset;
|
||||||
std::array<std::size_t, 3> lightArray;
|
std::size_t lightCountOffset;
|
||||||
std::size_t lightArraySize;
|
std::size_t lightSize;
|
||||||
|
std::size_t totalSize;
|
||||||
|
Light lightMemberOffsets;
|
||||||
|
|
||||||
|
static constexpr std::size_t MaxLightCount = 3;
|
||||||
|
|
||||||
static PredefinedLightData GetOffsets();
|
static PredefinedLightData GetOffsets();
|
||||||
static MaterialSettings::SharedUniformBlock GetUniformBlock();
|
static MaterialSettings::SharedUniformBlock GetUniformBlock(UInt32 bindingIndex, ShaderStageTypeFlags shaderStages);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NAZARA_GRAPHICS_API PredefinedInstanceData
|
struct NAZARA_GRAPHICS_API PredefinedInstanceData
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,7 @@ namespace Nz
|
||||||
|
|
||||||
inline void Sprite::UpdateVertices()
|
inline void Sprite::UpdateVertices()
|
||||||
{
|
{
|
||||||
Boxf aabb;
|
Boxf aabb = Boxf::Zero();
|
||||||
|
|
||||||
VertexStruct_XYZ_Color_UV* vertices = m_vertices.data();
|
VertexStruct_XYZ_Color_UV* vertices = m_vertices.data();
|
||||||
|
|
||||||
|
|
@ -105,7 +105,10 @@ namespace Nz
|
||||||
vertices->position = Vector3f(m_size * cornerExtent[UnderlyingCast(corner)], 0.f) - m_origin;
|
vertices->position = Vector3f(m_size * cornerExtent[UnderlyingCast(corner)], 0.f) - m_origin;
|
||||||
vertices->uv = m_textureCoords.GetCorner(corner);
|
vertices->uv = m_textureCoords.GetCorner(corner);
|
||||||
|
|
||||||
aabb.Set(vertices->position);
|
if (aabb.IsValid())
|
||||||
|
aabb.ExtendTo(vertices->position);
|
||||||
|
else
|
||||||
|
aabb.Set(vertices->position);
|
||||||
|
|
||||||
vertices++;
|
vertices++;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ namespace Nz
|
||||||
~SpriteChainRenderer() = default;
|
~SpriteChainRenderer() = default;
|
||||||
|
|
||||||
std::unique_ptr<ElementRendererData> InstanciateData() override;
|
std::unique_ptr<ElementRendererData> InstanciateData() override;
|
||||||
void Prepare(const ViewerInstance& viewerInstance, ElementRendererData& rendererData, RenderFrame& currentFrame, const Pointer<const RenderElement>* elements, std::size_t elementCount) override;
|
void Prepare(const ViewerInstance& viewerInstance, ElementRendererData& rendererData, RenderFrame& currentFrame, const RenderStates& renderStates, const Pointer<const RenderElement>* elements, std::size_t elementCount) override;
|
||||||
void Render(const ViewerInstance& viewerInstance, ElementRendererData& rendererData, CommandBufferBuilder& commandBuffer, const Pointer<const RenderElement>* elements, std::size_t elementCount) override;
|
void Render(const ViewerInstance& viewerInstance, ElementRendererData& rendererData, CommandBufferBuilder& commandBuffer, const Pointer<const RenderElement>* elements, std::size_t elementCount) override;
|
||||||
void Reset(ElementRendererData& rendererData, RenderFrame& currentFrame) override;
|
void Reset(ElementRendererData& rendererData, RenderFrame& currentFrame) override;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,13 +21,13 @@ namespace Nz
|
||||||
class NAZARA_GRAPHICS_API SubmeshRenderer : public ElementRenderer
|
class NAZARA_GRAPHICS_API SubmeshRenderer : public ElementRenderer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SubmeshRenderer();
|
SubmeshRenderer() = default;
|
||||||
~SubmeshRenderer() = default;
|
~SubmeshRenderer() = default;
|
||||||
|
|
||||||
std::unique_ptr<ElementRendererData> InstanciateData();
|
std::unique_ptr<ElementRendererData> InstanciateData() override;
|
||||||
void Prepare(const ViewerInstance& viewerInstance, ElementRendererData& rendererData, RenderFrame& currentFrame, const Pointer<const RenderElement>* elements, std::size_t elementCount);
|
void Prepare(const ViewerInstance& viewerInstance, ElementRendererData& rendererData, RenderFrame& currentFrame, const RenderStates& renderStates, const Pointer<const RenderElement>* elements, std::size_t elementCount) override;
|
||||||
void Render(const ViewerInstance& viewerInstance, ElementRendererData& rendererData, CommandBufferBuilder& commandBuffer, const Pointer<const RenderElement>* elements, std::size_t elementCount) override;
|
void Render(const ViewerInstance& viewerInstance, ElementRendererData& rendererData, CommandBufferBuilder& commandBuffer, const Pointer<const RenderElement>* elements, std::size_t elementCount) override;
|
||||||
void Reset(ElementRendererData& rendererData, RenderFrame& currentFrame);
|
void Reset(ElementRendererData& rendererData, RenderFrame& currentFrame) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<ShaderBinding::Binding> m_bindingCache;
|
std::vector<ShaderBinding::Binding> m_bindingCache;
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ namespace Nz
|
||||||
ViewerInstance(ViewerInstance&&) noexcept = default;
|
ViewerInstance(ViewerInstance&&) noexcept = default;
|
||||||
~ViewerInstance() = default;
|
~ViewerInstance() = default;
|
||||||
|
|
||||||
|
inline const Vector3f& GetEyePosition() const;
|
||||||
inline const Matrix4f& GetInvProjectionMatrix() const;
|
inline const Matrix4f& GetInvProjectionMatrix() const;
|
||||||
inline const Matrix4f& GetInvViewMatrix() const;
|
inline const Matrix4f& GetInvViewMatrix() const;
|
||||||
inline const Matrix4f& GetInvViewProjMatrix() const;
|
inline const Matrix4f& GetInvViewProjMatrix() const;
|
||||||
|
|
@ -39,6 +40,7 @@ namespace Nz
|
||||||
inline const std::shared_ptr<AbstractBuffer>& GetViewerBuffer() const;
|
inline const std::shared_ptr<AbstractBuffer>& GetViewerBuffer() const;
|
||||||
|
|
||||||
void UpdateBuffers(UploadPool& uploadPool, CommandBufferBuilder& builder);
|
void UpdateBuffers(UploadPool& uploadPool, CommandBufferBuilder& builder);
|
||||||
|
inline void UpdateEyePosition(const Vector3f& eyePosition);
|
||||||
inline void UpdateProjectionMatrix(const Matrix4f& projectionMatrix);
|
inline void UpdateProjectionMatrix(const Matrix4f& projectionMatrix);
|
||||||
inline void UpdateProjectionMatrix(const Matrix4f& projectionMatrix, const Matrix4f& invProjectionMatrix);
|
inline void UpdateProjectionMatrix(const Matrix4f& projectionMatrix, const Matrix4f& invProjectionMatrix);
|
||||||
inline void UpdateProjViewMatrices(const Matrix4f& projectionMatrix, const Matrix4f& viewMatrix);
|
inline void UpdateProjViewMatrices(const Matrix4f& projectionMatrix, const Matrix4f& viewMatrix);
|
||||||
|
|
@ -60,6 +62,7 @@ namespace Nz
|
||||||
Matrix4f m_viewProjMatrix;
|
Matrix4f m_viewProjMatrix;
|
||||||
Matrix4f m_viewMatrix;
|
Matrix4f m_viewMatrix;
|
||||||
Vector2f m_targetSize;
|
Vector2f m_targetSize;
|
||||||
|
Vector3f m_eyePosition;
|
||||||
bool m_dataInvalided;
|
bool m_dataInvalided;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,11 @@
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
|
inline const Vector3f& ViewerInstance::GetEyePosition() const
|
||||||
|
{
|
||||||
|
return m_eyePosition;
|
||||||
|
}
|
||||||
|
|
||||||
inline const Matrix4f& ViewerInstance::GetInvProjectionMatrix() const
|
inline const Matrix4f& ViewerInstance::GetInvProjectionMatrix() const
|
||||||
{
|
{
|
||||||
return m_invProjectionMatrix;
|
return m_invProjectionMatrix;
|
||||||
|
|
@ -53,6 +58,12 @@ namespace Nz
|
||||||
return m_viewerDataBuffer;
|
return m_viewerDataBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void ViewerInstance::UpdateEyePosition(const Vector3f& eyePosition)
|
||||||
|
{
|
||||||
|
m_eyePosition = eyePosition;
|
||||||
|
m_dataInvalided = true;
|
||||||
|
}
|
||||||
|
|
||||||
inline void ViewerInstance::UpdateProjectionMatrix(const Matrix4f& projectionMatrix)
|
inline void ViewerInstance::UpdateProjectionMatrix(const Matrix4f& projectionMatrix)
|
||||||
{
|
{
|
||||||
m_projectionMatrix = projectionMatrix;
|
m_projectionMatrix = projectionMatrix;
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,9 @@ namespace Nz
|
||||||
Length = 3,
|
Length = 3,
|
||||||
Max = 4,
|
Max = 4,
|
||||||
Min = 5,
|
Min = 5,
|
||||||
|
Normalize = 9,
|
||||||
Pow = 6,
|
Pow = 6,
|
||||||
|
Reflect = 8,
|
||||||
SampleTexture = 2,
|
SampleTexture = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ namespace Nz::ShaderAst
|
||||||
std::unordered_set<std::string> reservedIdentifiers;
|
std::unordered_set<std::string> reservedIdentifiers;
|
||||||
std::unordered_map<std::size_t, ConstantValue> optionValues;
|
std::unordered_map<std::size_t, ConstantValue> optionValues;
|
||||||
bool makeVariableNameUnique = false;
|
bool makeVariableNameUnique = false;
|
||||||
|
bool removeConstDeclaration = false;
|
||||||
bool reduceLoopsToWhile = false;
|
bool reduceLoopsToWhile = false;
|
||||||
bool removeCompoundAssignments = false;
|
bool removeCompoundAssignments = false;
|
||||||
bool removeOptionDeclaration = false;
|
bool removeOptionDeclaration = false;
|
||||||
|
|
|
||||||
|
|
@ -25,30 +25,37 @@ namespace Nz
|
||||||
}
|
}
|
||||||
|
|
||||||
BasicMaterial::BasicMaterial(MaterialPass& material) :
|
BasicMaterial::BasicMaterial(MaterialPass& material) :
|
||||||
m_material(material)
|
BasicMaterial(material, NoInit{})
|
||||||
{
|
{
|
||||||
// Most common case: don't fetch texture indexes as a little optimization
|
// Most common case: don't fetch texture indexes as a little optimization
|
||||||
const std::shared_ptr<const MaterialSettings>& materialSettings = material.GetSettings();
|
const std::shared_ptr<const MaterialSettings>& materialSettings = material.GetSettings();
|
||||||
if (materialSettings == s_materialSettings)
|
if (materialSettings == s_basicMaterialSettings)
|
||||||
{
|
{
|
||||||
m_optionIndexes = s_optionIndexes;
|
m_basicOptionIndexes = s_basicOptionIndexes;
|
||||||
m_textureIndexes = s_textureIndexes;
|
m_basicTextureIndexes = s_basicTextureIndexes;
|
||||||
m_uniformBlockIndex = s_uniformBlockIndex;
|
m_uniformBlockIndex = s_uniformBlockIndex;
|
||||||
m_uniformOffsets = s_uniformOffsets;
|
m_basicUniformOffsets = s_basicUniformOffsets;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_optionIndexes.alphaTest = materialSettings->GetOptionIndex("AlphaTest");
|
m_basicOptionIndexes.alphaTest = materialSettings->GetOptionIndex("AlphaTest");
|
||||||
m_optionIndexes.hasAlphaMap = materialSettings->GetOptionIndex("HasAlphaMap");
|
m_basicOptionIndexes.hasAlphaMap = materialSettings->GetOptionIndex("HasAlphaMap");
|
||||||
m_optionIndexes.hasDiffuseMap = materialSettings->GetOptionIndex("HasDiffuseMap");
|
m_basicOptionIndexes.hasDiffuseMap = materialSettings->GetOptionIndex("HasDiffuseMap");
|
||||||
|
|
||||||
m_textureIndexes.alpha = materialSettings->GetTextureIndex("Alpha");
|
m_basicTextureIndexes.alpha = materialSettings->GetTextureIndex("Alpha");
|
||||||
m_textureIndexes.diffuse = materialSettings->GetTextureIndex("Diffuse");
|
m_basicTextureIndexes.diffuse = materialSettings->GetTextureIndex("Diffuse");
|
||||||
|
|
||||||
m_uniformBlockIndex = materialSettings->GetUniformBlockIndex("BasicSettings");
|
m_uniformBlockIndex = materialSettings->GetUniformBlockIndex("MaterialSettings");
|
||||||
|
if (m_uniformBlockIndex != MaterialSettings::InvalidIndex)
|
||||||
m_uniformOffsets.alphaThreshold = materialSettings->GetUniformBlockVariableOffset(m_uniformBlockIndex, "AlphaThreshold");
|
{
|
||||||
m_uniformOffsets.diffuseColor = materialSettings->GetUniformBlockVariableOffset(m_uniformBlockIndex, "DiffuseColor");
|
m_basicUniformOffsets.alphaThreshold = materialSettings->GetUniformBlockVariableOffset(m_uniformBlockIndex, "AlphaThreshold");
|
||||||
|
m_basicUniformOffsets.diffuseColor = materialSettings->GetUniformBlockVariableOffset(m_uniformBlockIndex, "DiffuseColor");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_basicUniformOffsets.alphaThreshold = MaterialSettings::InvalidIndex;
|
||||||
|
m_basicUniformOffsets.diffuseColor = MaterialSettings::InvalidIndex;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -58,7 +65,7 @@ namespace Nz
|
||||||
|
|
||||||
const std::vector<UInt8>& bufferData = m_material.GetUniformBufferConstData(m_uniformBlockIndex);
|
const std::vector<UInt8>& bufferData = m_material.GetUniformBufferConstData(m_uniformBlockIndex);
|
||||||
|
|
||||||
return AccessByOffset<const float&>(bufferData.data(), m_uniformOffsets.alphaThreshold);
|
return AccessByOffset<const float&>(bufferData.data(), m_basicUniformOffsets.alphaThreshold);
|
||||||
}
|
}
|
||||||
|
|
||||||
Color BasicMaterial::GetDiffuseColor() const
|
Color BasicMaterial::GetDiffuseColor() const
|
||||||
|
|
@ -67,7 +74,7 @@ namespace Nz
|
||||||
|
|
||||||
const std::vector<UInt8>& bufferData = m_material.GetUniformBufferConstData(m_uniformBlockIndex);
|
const std::vector<UInt8>& bufferData = m_material.GetUniformBufferConstData(m_uniformBlockIndex);
|
||||||
|
|
||||||
const float* colorPtr = AccessByOffset<const float*>(bufferData.data(), m_uniformOffsets.diffuseColor);
|
const float* colorPtr = AccessByOffset<const float*>(bufferData.data(), m_basicUniformOffsets.diffuseColor);
|
||||||
return Color(colorPtr[0] * 255, colorPtr[1] * 255, colorPtr[2] * 255, colorPtr[3] * 255); //< TODO: Make color able to use float
|
return Color(colorPtr[0] * 255, colorPtr[1] * 255, colorPtr[2] * 255, colorPtr[3] * 255); //< TODO: Make color able to use float
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -76,7 +83,7 @@ namespace Nz
|
||||||
NazaraAssert(HasAlphaTestThreshold(), "Material has no alpha threshold uniform");
|
NazaraAssert(HasAlphaTestThreshold(), "Material has no alpha threshold uniform");
|
||||||
|
|
||||||
std::vector<UInt8>& bufferData = m_material.GetUniformBufferData(m_uniformBlockIndex);
|
std::vector<UInt8>& bufferData = m_material.GetUniformBufferData(m_uniformBlockIndex);
|
||||||
AccessByOffset<float&>(bufferData.data(), m_uniformOffsets.alphaThreshold) = alphaThreshold;
|
AccessByOffset<float&>(bufferData.data(), m_basicUniformOffsets.alphaThreshold) = alphaThreshold;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BasicMaterial::SetDiffuseColor(const Color& diffuse)
|
void BasicMaterial::SetDiffuseColor(const Color& diffuse)
|
||||||
|
|
@ -85,44 +92,45 @@ namespace Nz
|
||||||
|
|
||||||
std::vector<UInt8>& bufferData = m_material.GetUniformBufferData(m_uniformBlockIndex);
|
std::vector<UInt8>& bufferData = m_material.GetUniformBufferData(m_uniformBlockIndex);
|
||||||
|
|
||||||
float* colorPtr = AccessByOffset<float*>(bufferData.data(), m_uniformOffsets.diffuseColor);
|
float* colorPtr = AccessByOffset<float*>(bufferData.data(), m_basicUniformOffsets.diffuseColor);
|
||||||
colorPtr[0] = diffuse.r / 255.f;
|
colorPtr[0] = diffuse.r / 255.f;
|
||||||
colorPtr[1] = diffuse.g / 255.f;
|
colorPtr[1] = diffuse.g / 255.f;
|
||||||
colorPtr[2] = diffuse.b / 255.f;
|
colorPtr[2] = diffuse.b / 255.f;
|
||||||
colorPtr[3] = diffuse.a / 255.f;
|
colorPtr[3] = diffuse.a / 255.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialSettings::Builder BasicMaterial::Build(const UniformOffsets& offsets, std::vector<UInt8> defaultValues, std::vector<std::shared_ptr<UberShader>> uberShaders, std::size_t* uniformBlockIndex, OptionIndexes* optionIndexes, TextureIndexes* textureIndexes)
|
MaterialSettings::Builder BasicMaterial::Build(BasicBuildOptions& options)
|
||||||
{
|
{
|
||||||
MaterialSettings::Builder settings;
|
MaterialSettings::Builder settings;
|
||||||
|
|
||||||
std::vector<MaterialSettings::UniformVariable> variables;
|
std::vector<MaterialSettings::UniformVariable> variables;
|
||||||
if (offsets.alphaThreshold != std::numeric_limits<std::size_t>::max())
|
if (options.basicOffsets.alphaThreshold != std::numeric_limits<std::size_t>::max())
|
||||||
{
|
{
|
||||||
variables.push_back({
|
variables.push_back({
|
||||||
"AlphaThreshold",
|
"AlphaThreshold",
|
||||||
offsets.alphaThreshold
|
options.basicOffsets.alphaThreshold
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offsets.diffuseColor != std::numeric_limits<std::size_t>::max())
|
if (options.basicOffsets.diffuseColor != std::numeric_limits<std::size_t>::max())
|
||||||
{
|
{
|
||||||
variables.push_back({
|
variables.push_back({
|
||||||
"DiffuseColor",
|
"DiffuseColor",
|
||||||
offsets.diffuseColor
|
options.basicOffsets.diffuseColor
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offsets.alphaThreshold != std::numeric_limits<std::size_t>::max())
|
|
||||||
AccessByOffset<float&>(defaultValues.data(), offsets.alphaThreshold) = 0.2f;
|
|
||||||
|
|
||||||
static_assert(sizeof(Vector4f) == 4 * sizeof(float), "Vector4f is expected to be exactly 4 floats wide");
|
static_assert(sizeof(Vector4f) == 4 * sizeof(float), "Vector4f is expected to be exactly 4 floats wide");
|
||||||
if (offsets.diffuseColor != std::numeric_limits<std::size_t>::max())
|
|
||||||
AccessByOffset<Vector4f&>(defaultValues.data(), offsets.diffuseColor) = Vector4f(1.f, 1.f, 1.f, 1.f);
|
if (options.basicOffsets.alphaThreshold != std::numeric_limits<std::size_t>::max())
|
||||||
|
AccessByOffset<float&>(options.defaultValues.data(), options.basicOffsets.alphaThreshold) = 0.2f;
|
||||||
|
|
||||||
|
if (options.basicOffsets.diffuseColor != std::numeric_limits<std::size_t>::max())
|
||||||
|
AccessByOffset<Vector4f&>(options.defaultValues.data(), options.basicOffsets.diffuseColor) = Vector4f(1.f, 1.f, 1.f, 1.f);
|
||||||
|
|
||||||
// Textures
|
// Textures
|
||||||
if (textureIndexes)
|
if (options.basicTextureIndexes)
|
||||||
textureIndexes->alpha = settings.textures.size();
|
options.basicTextureIndexes->alpha = settings.textures.size();
|
||||||
|
|
||||||
settings.textures.push_back({
|
settings.textures.push_back({
|
||||||
2,
|
2,
|
||||||
|
|
@ -130,8 +138,8 @@ namespace Nz
|
||||||
ImageType::E2D
|
ImageType::E2D
|
||||||
});
|
});
|
||||||
|
|
||||||
if (textureIndexes)
|
if (options.basicTextureIndexes)
|
||||||
textureIndexes->diffuse = settings.textures.size();
|
options.basicTextureIndexes->diffuse = settings.textures.size();
|
||||||
|
|
||||||
settings.textures.push_back({
|
settings.textures.push_back({
|
||||||
1,
|
1,
|
||||||
|
|
@ -139,15 +147,15 @@ namespace Nz
|
||||||
ImageType::E2D
|
ImageType::E2D
|
||||||
});
|
});
|
||||||
|
|
||||||
if (uniformBlockIndex)
|
if (options.uniformBlockIndex)
|
||||||
*uniformBlockIndex = settings.uniformBlocks.size();
|
*options.uniformBlockIndex = settings.uniformBlocks.size();
|
||||||
|
|
||||||
settings.uniformBlocks.push_back({
|
settings.uniformBlocks.push_back({
|
||||||
0,
|
0,
|
||||||
"BasicSettings",
|
"MaterialSettings",
|
||||||
offsets.totalSize,
|
options.basicOffsets.totalSize,
|
||||||
std::move(variables),
|
std::move(variables),
|
||||||
std::move(defaultValues)
|
options.defaultValues
|
||||||
});
|
});
|
||||||
|
|
||||||
// Common data
|
// Common data
|
||||||
|
|
@ -164,7 +172,7 @@ namespace Nz
|
||||||
settings.predefinedBindings[UnderlyingCast(PredefinedShaderBinding::OverlayTexture)] = 3;
|
settings.predefinedBindings[UnderlyingCast(PredefinedShaderBinding::OverlayTexture)] = 3;
|
||||||
settings.predefinedBindings[UnderlyingCast(PredefinedShaderBinding::ViewerDataUbo)] = 5;
|
settings.predefinedBindings[UnderlyingCast(PredefinedShaderBinding::ViewerDataUbo)] = 5;
|
||||||
|
|
||||||
settings.shaders = std::move(uberShaders);
|
settings.shaders = options.shaders;
|
||||||
|
|
||||||
for (std::shared_ptr<UberShader> uberShader : settings.shaders)
|
for (std::shared_ptr<UberShader> uberShader : settings.shaders)
|
||||||
{
|
{
|
||||||
|
|
@ -230,20 +238,20 @@ namespace Nz
|
||||||
// Options
|
// Options
|
||||||
|
|
||||||
// HasDiffuseMap
|
// HasDiffuseMap
|
||||||
if (optionIndexes)
|
if (options.basicOptionIndexes)
|
||||||
optionIndexes->hasDiffuseMap = settings.options.size();
|
options.basicOptionIndexes->hasDiffuseMap = settings.options.size();
|
||||||
|
|
||||||
MaterialSettings::BuildOption(settings.options, settings.shaders, "HasDiffuseMap", "HasDiffuseTexture");
|
MaterialSettings::BuildOption(settings.options, settings.shaders, "HasDiffuseMap", "HasDiffuseTexture");
|
||||||
|
|
||||||
// HasAlphaMap
|
// HasAlphaMap
|
||||||
if (optionIndexes)
|
if (options.basicOptionIndexes)
|
||||||
optionIndexes->hasAlphaMap = settings.options.size();
|
options.basicOptionIndexes->hasAlphaMap = settings.options.size();
|
||||||
|
|
||||||
MaterialSettings::BuildOption(settings.options, settings.shaders, "HasAlphaMap", "HasAlphaTexture");
|
MaterialSettings::BuildOption(settings.options, settings.shaders, "HasAlphaMap", "HasAlphaTexture");
|
||||||
|
|
||||||
// AlphaTest
|
// AlphaTest
|
||||||
if (optionIndexes)
|
if (options.basicOptionIndexes)
|
||||||
optionIndexes->alphaTest = settings.options.size();
|
options.basicOptionIndexes->alphaTest = settings.options.size();
|
||||||
|
|
||||||
MaterialSettings::BuildOption(settings.options, settings.shaders, "AlphaTest", "AlphaTest");
|
MaterialSettings::BuildOption(settings.options, settings.shaders, "AlphaTest", "AlphaTest");
|
||||||
|
|
||||||
|
|
@ -258,36 +266,46 @@ namespace Nz
|
||||||
return { std::move(shader) };
|
return { std::move(shader) };
|
||||||
}
|
}
|
||||||
|
|
||||||
auto BasicMaterial::BuildUniformOffsets() -> std::pair<UniformOffsets, FieldOffsets>
|
auto BasicMaterial::BuildUniformOffsets() -> std::pair<BasicUniformOffsets, FieldOffsets>
|
||||||
{
|
{
|
||||||
FieldOffsets fieldOffsets(StructLayout::Std140);
|
FieldOffsets fieldOffsets(StructLayout::Std140);
|
||||||
|
|
||||||
UniformOffsets uniformOffsets;
|
BasicUniformOffsets uniformOffsets;
|
||||||
uniformOffsets.alphaThreshold = fieldOffsets.AddField(StructFieldType::Float1);
|
uniformOffsets.alphaThreshold = fieldOffsets.AddField(StructFieldType::Float1);
|
||||||
uniformOffsets.diffuseColor = fieldOffsets.AddField(StructFieldType::Float4);
|
uniformOffsets.diffuseColor = fieldOffsets.AddField(StructFieldType::Float4);
|
||||||
uniformOffsets.totalSize = fieldOffsets.GetSize();
|
uniformOffsets.totalSize = fieldOffsets.GetAlignedSize();
|
||||||
|
|
||||||
return std::make_pair(std::move(uniformOffsets), std::move(fieldOffsets));
|
return std::make_pair(std::move(uniformOffsets), std::move(fieldOffsets));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BasicMaterial::Initialize()
|
bool BasicMaterial::Initialize()
|
||||||
{
|
{
|
||||||
std::tie(s_uniformOffsets, std::ignore) = BuildUniformOffsets();
|
std::tie(s_basicUniformOffsets, std::ignore) = BuildUniformOffsets();
|
||||||
|
|
||||||
std::vector<UInt8> defaultValues(s_uniformOffsets.totalSize);
|
std::vector<UInt8> defaultValues(s_basicUniformOffsets.totalSize);
|
||||||
s_materialSettings = std::make_shared<MaterialSettings>(Build(s_uniformOffsets, std::move(defaultValues), BuildShaders(), &s_uniformBlockIndex, &s_optionIndexes, &s_textureIndexes));
|
|
||||||
|
BasicBuildOptions options;
|
||||||
|
options.defaultValues.resize(s_basicUniformOffsets.totalSize);
|
||||||
|
options.shaders = BuildShaders();
|
||||||
|
|
||||||
|
options.basicOffsets = s_basicUniformOffsets;
|
||||||
|
options.basicOptionIndexes = &s_basicOptionIndexes;
|
||||||
|
options.basicTextureIndexes = &s_basicTextureIndexes;
|
||||||
|
options.uniformBlockIndex = &s_uniformBlockIndex;
|
||||||
|
|
||||||
|
s_basicMaterialSettings = std::make_shared<MaterialSettings>(Build(options));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BasicMaterial::Uninitialize()
|
void BasicMaterial::Uninitialize()
|
||||||
{
|
{
|
||||||
s_materialSettings.reset();
|
s_basicMaterialSettings.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<MaterialSettings> BasicMaterial::s_materialSettings;
|
std::shared_ptr<MaterialSettings> BasicMaterial::s_basicMaterialSettings;
|
||||||
std::size_t BasicMaterial::s_uniformBlockIndex;
|
std::size_t BasicMaterial::s_uniformBlockIndex;
|
||||||
BasicMaterial::OptionIndexes BasicMaterial::s_optionIndexes;
|
BasicMaterial::BasicOptionIndexes BasicMaterial::s_basicOptionIndexes;
|
||||||
BasicMaterial::TextureIndexes BasicMaterial::s_textureIndexes;
|
BasicMaterial::BasicTextureIndexes BasicMaterial::s_basicTextureIndexes;
|
||||||
BasicMaterial::UniformOffsets BasicMaterial::s_uniformOffsets;
|
BasicMaterial::BasicUniformOffsets BasicMaterial::s_basicUniformOffsets;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,19 +26,26 @@ namespace Nz
|
||||||
|
|
||||||
bool DepthMaterial::Initialize()
|
bool DepthMaterial::Initialize()
|
||||||
{
|
{
|
||||||
UniformOffsets offsets;
|
BasicUniformOffsets offsets;
|
||||||
std::tie(offsets, std::ignore) = BuildUniformOffsets();
|
std::tie(offsets, std::ignore) = BuildUniformOffsets();
|
||||||
|
|
||||||
std::vector<UInt8> defaultValues(offsets.totalSize);
|
BasicBuildOptions options;
|
||||||
s_materialSettings = std::make_shared<MaterialSettings>(Build(offsets, std::move(defaultValues), BuildShaders()));
|
options.defaultValues.resize(offsets.totalSize);
|
||||||
|
options.shaders = BuildShaders();
|
||||||
|
|
||||||
|
options.basicOffsets = s_basicUniformOffsets;
|
||||||
|
options.basicOptionIndexes = &s_basicOptionIndexes;
|
||||||
|
options.basicTextureIndexes = &s_basicTextureIndexes;
|
||||||
|
|
||||||
|
s_basicMaterialSettings = std::make_shared<MaterialSettings>(Build(options));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DepthMaterial::Uninitialize()
|
void DepthMaterial::Uninitialize()
|
||||||
{
|
{
|
||||||
s_materialSettings.reset();
|
s_basicMaterialSettings.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<MaterialSettings> DepthMaterial::s_materialSettings;
|
std::shared_ptr<MaterialSettings> DepthMaterial::s_basicMaterialSettings;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ namespace Nz
|
||||||
{
|
{
|
||||||
ElementRenderer::~ElementRenderer() = default;
|
ElementRenderer::~ElementRenderer() = default;
|
||||||
|
|
||||||
void ElementRenderer::Prepare(const ViewerInstance& /*viewerInstance*/, ElementRendererData& /*rendererData*/, RenderFrame& /*currentFrame*/, const Pointer<const RenderElement>* /*elements*/, std::size_t /*elementCount*/)
|
void ElementRenderer::Prepare(const ViewerInstance& /*viewerInstance*/, ElementRendererData& /*rendererData*/, RenderFrame& /*currentFrame*/, const RenderStates& /*renderStates*/, const Pointer<const RenderElement>* /*elements*/, std::size_t /*elementCount*/)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
#include <Nazara/Graphics/InstancedRenderable.hpp>
|
#include <Nazara/Graphics/InstancedRenderable.hpp>
|
||||||
#include <Nazara/Graphics/Material.hpp>
|
#include <Nazara/Graphics/Material.hpp>
|
||||||
#include <Nazara/Graphics/RenderElement.hpp>
|
#include <Nazara/Graphics/RenderElement.hpp>
|
||||||
|
#include <Nazara/Graphics/PredefinedShaderStructs.hpp>
|
||||||
#include <Nazara/Graphics/SpriteChainRenderer.hpp>
|
#include <Nazara/Graphics/SpriteChainRenderer.hpp>
|
||||||
#include <Nazara/Graphics/SubmeshRenderer.hpp>
|
#include <Nazara/Graphics/SubmeshRenderer.hpp>
|
||||||
#include <Nazara/Graphics/ViewerInstance.hpp>
|
#include <Nazara/Graphics/ViewerInstance.hpp>
|
||||||
|
|
@ -35,6 +36,23 @@ namespace Nz
|
||||||
m_elementRenderers.resize(BasicRenderElementCount);
|
m_elementRenderers.resize(BasicRenderElementCount);
|
||||||
m_elementRenderers[UnderlyingCast(BasicRenderElement::SpriteChain)] = std::make_unique<SpriteChainRenderer>(*Graphics::Instance()->GetRenderDevice());
|
m_elementRenderers[UnderlyingCast(BasicRenderElement::SpriteChain)] = std::make_unique<SpriteChainRenderer>(*Graphics::Instance()->GetRenderDevice());
|
||||||
m_elementRenderers[UnderlyingCast(BasicRenderElement::Submesh)] = std::make_unique<SubmeshRenderer>();
|
m_elementRenderers[UnderlyingCast(BasicRenderElement::Submesh)] = std::make_unique<SubmeshRenderer>();
|
||||||
|
|
||||||
|
auto lightOffset = PredefinedLightData::GetOffsets();
|
||||||
|
|
||||||
|
m_lightDataBuffer = Graphics::Instance()->GetRenderDevice()->InstantiateBuffer(BufferType::Uniform);
|
||||||
|
if (!m_lightDataBuffer->Initialize(lightOffset.totalSize, BufferUsage::DeviceLocal))
|
||||||
|
throw std::runtime_error("failed to create light data buffer");
|
||||||
|
|
||||||
|
std::vector<UInt8> staticLightData(lightOffset.totalSize);
|
||||||
|
AccessByOffset<UInt32&>(staticLightData.data(), lightOffset.lightCountOffset) = 1;
|
||||||
|
AccessByOffset<UInt32&>(staticLightData.data(), lightOffset.lightsOffset + lightOffset.lightMemberOffsets.type) = 0;
|
||||||
|
AccessByOffset<Vector4f&>(staticLightData.data(), lightOffset.lightsOffset + lightOffset.lightMemberOffsets.color) = Vector4f(1.f, 1.f, 1.f, 1.f);
|
||||||
|
AccessByOffset<Vector2f&>(staticLightData.data(), lightOffset.lightsOffset + lightOffset.lightMemberOffsets.factor) = Vector2f(0.2f, 1.f);
|
||||||
|
AccessByOffset<Vector4f&>(staticLightData.data(), lightOffset.lightsOffset + lightOffset.lightMemberOffsets.parameter1) = Vector4f(0.f, 0.f, -1.f, 1.f);
|
||||||
|
AccessByOffset<UInt8&>(staticLightData.data(), lightOffset.lightsOffset + lightOffset.lightMemberOffsets.shadowMappingFlag) = 0;
|
||||||
|
|
||||||
|
if (!m_lightDataBuffer->Fill(staticLightData.data(), 0, staticLightData.size()))
|
||||||
|
throw std::runtime_error("failed to fill light data buffer");
|
||||||
}
|
}
|
||||||
|
|
||||||
void ForwardFramePipeline::InvalidateViewer(AbstractViewer* viewerInstance)
|
void ForwardFramePipeline::InvalidateViewer(AbstractViewer* viewerInstance)
|
||||||
|
|
@ -320,16 +338,19 @@ namespace Nz
|
||||||
|
|
||||||
const auto& viewerInstance = viewer->GetViewerInstance();
|
const auto& viewerInstance = viewer->GetViewerInstance();
|
||||||
|
|
||||||
|
ElementRenderer::RenderStates renderStates;
|
||||||
|
renderStates.lightData = m_lightDataBuffer;
|
||||||
|
|
||||||
ProcessRenderQueue(viewerData.depthPrepassRenderQueue, [&](std::size_t elementType, const Pointer<const RenderElement>* elements, std::size_t elementCount)
|
ProcessRenderQueue(viewerData.depthPrepassRenderQueue, [&](std::size_t elementType, const Pointer<const RenderElement>* elements, std::size_t elementCount)
|
||||||
{
|
{
|
||||||
ElementRenderer& elementRenderer = *m_elementRenderers[elementType];
|
ElementRenderer& elementRenderer = *m_elementRenderers[elementType];
|
||||||
elementRenderer.Prepare(viewerInstance, *rendererData[elementType], renderFrame, elements, elementCount);
|
elementRenderer.Prepare(viewerInstance, *rendererData[elementType], renderFrame, renderStates, elements, elementCount);
|
||||||
});
|
});
|
||||||
|
|
||||||
ProcessRenderQueue(viewerData.forwardRenderQueue, [&](std::size_t elementType, const Pointer<const RenderElement>* elements, std::size_t elementCount)
|
ProcessRenderQueue(viewerData.forwardRenderQueue, [&](std::size_t elementType, const Pointer<const RenderElement>* elements, std::size_t elementCount)
|
||||||
{
|
{
|
||||||
ElementRenderer& elementRenderer = *m_elementRenderers[elementType];
|
ElementRenderer& elementRenderer = *m_elementRenderers[elementType];
|
||||||
elementRenderer.Prepare(viewerInstance, *rendererData[elementType], renderFrame, elements, elementCount);
|
elementRenderer.Prepare(viewerInstance, *rendererData[elementType], renderFrame, renderStates, elements, elementCount);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -113,36 +113,6 @@ namespace Nz
|
||||||
m_defaultTextures.whiteTextures.fill(nullptr);
|
m_defaultTextures.whiteTextures.fill(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::FillDrawDataPipelineLayout(RenderPipelineLayoutInfo& layoutInfo, UInt32 set)
|
|
||||||
{
|
|
||||||
// TextureOverlay
|
|
||||||
layoutInfo.bindings.push_back({
|
|
||||||
set, 0,
|
|
||||||
ShaderBindingType::Texture,
|
|
||||||
ShaderStageType_All
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void Graphics::FillViewerPipelineLayout(RenderPipelineLayoutInfo& layoutInfo, UInt32 set)
|
|
||||||
{
|
|
||||||
// ViewerData
|
|
||||||
layoutInfo.bindings.push_back({
|
|
||||||
set, 0,
|
|
||||||
ShaderBindingType::UniformBuffer,
|
|
||||||
ShaderStageType_All
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void Graphics::FillWorldPipelineLayout(RenderPipelineLayoutInfo& layoutInfo, UInt32 set)
|
|
||||||
{
|
|
||||||
// InstanceData
|
|
||||||
layoutInfo.bindings.push_back({
|
|
||||||
set, 0,
|
|
||||||
ShaderBindingType::UniformBuffer,
|
|
||||||
ShaderStageType_All
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void Graphics::BuildBlitPipeline()
|
void Graphics::BuildBlitPipeline()
|
||||||
{
|
{
|
||||||
RenderPipelineLayoutInfo layoutInfo;
|
RenderPipelineLayoutInfo layoutInfo;
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
#include <Nazara/Core/ErrorFlags.hpp>
|
#include <Nazara/Core/ErrorFlags.hpp>
|
||||||
#include <Nazara/Graphics/PredefinedShaderStructs.hpp>
|
#include <Nazara/Graphics/PredefinedShaderStructs.hpp>
|
||||||
#include <Nazara/Renderer/Renderer.hpp>
|
#include <Nazara/Renderer/Renderer.hpp>
|
||||||
|
#include <Nazara/Shader/ShaderLangParser.hpp>
|
||||||
#include <Nazara/Utility/BufferMapper.hpp>
|
#include <Nazara/Utility/BufferMapper.hpp>
|
||||||
#include <Nazara/Utility/FieldOffsets.hpp>
|
#include <Nazara/Utility/FieldOffsets.hpp>
|
||||||
#include <Nazara/Utility/MaterialData.hpp>
|
#include <Nazara/Utility/MaterialData.hpp>
|
||||||
|
|
@ -15,69 +16,84 @@
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
const UInt8 r_shader[] = {
|
||||||
|
#include <Nazara/Graphics/Resources/Shaders/phong_material.nzsl.h>
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
PhongLightingMaterial::PhongLightingMaterial(MaterialPass& material) :
|
PhongLightingMaterial::PhongLightingMaterial(MaterialPass& material) :
|
||||||
m_material(material)
|
BasicMaterial(material, NoInit{})
|
||||||
{
|
{
|
||||||
// Most common case: don't fetch texture indexes as a little optimization
|
// Most common case: don't fetch texture indexes as a little optimization
|
||||||
const std::shared_ptr<const MaterialSettings>& materialSettings = m_material.GetSettings();
|
const std::shared_ptr<const MaterialSettings>& materialSettings = GetMaterial().GetSettings();
|
||||||
if (materialSettings == s_materialSettings)
|
if (materialSettings == s_phongMaterialSettings)
|
||||||
{
|
{
|
||||||
m_textureIndexes = s_textureIndexes;
|
m_basicUniformOffsets = s_basicUniformOffsets;
|
||||||
m_phongUniformIndex = s_phongUniformBlockIndex;
|
m_basicOptionIndexes = s_basicOptionIndexes;
|
||||||
|
m_basicTextureIndexes = s_basicTextureIndexes;
|
||||||
|
|
||||||
|
m_phongOptionIndexes = s_phongOptionIndexes;
|
||||||
|
m_phongTextureIndexes = s_phongTextureIndexes;
|
||||||
m_phongUniformOffsets = s_phongUniformOffsets;
|
m_phongUniformOffsets = s_phongUniformOffsets;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_textureIndexes.alpha = materialSettings->GetTextureIndex("Alpha");
|
m_basicOptionIndexes.alphaTest = materialSettings->GetOptionIndex("AlphaTest");
|
||||||
m_textureIndexes.diffuse = materialSettings->GetTextureIndex("Diffuse");
|
m_basicOptionIndexes.hasAlphaMap = materialSettings->GetOptionIndex("HasAlphaMap");
|
||||||
m_textureIndexes.emissive = materialSettings->GetTextureIndex("Emissive");
|
m_basicOptionIndexes.hasDiffuseMap = materialSettings->GetOptionIndex("HasDiffuseMap");
|
||||||
m_textureIndexes.height = materialSettings->GetTextureIndex("Height");
|
|
||||||
m_textureIndexes.normal = materialSettings->GetTextureIndex("Normal");
|
|
||||||
m_textureIndexes.specular = materialSettings->GetTextureIndex("Specular");
|
|
||||||
|
|
||||||
m_phongUniformIndex = materialSettings->GetUniformBlockIndex("PhongSettings");
|
m_phongOptionIndexes.hasEmissiveMap = materialSettings->GetOptionIndex("HasEmissiveMap");
|
||||||
|
m_phongOptionIndexes.hasHeightMap = materialSettings->GetOptionIndex("HasHeightMap");
|
||||||
|
m_phongOptionIndexes.hasNormalMap = materialSettings->GetOptionIndex("HasNormalMap");
|
||||||
|
m_phongOptionIndexes.hasSpecularMap = materialSettings->GetOptionIndex("HasSpecularMap");
|
||||||
|
|
||||||
m_phongUniformOffsets.alphaThreshold = materialSettings->GetUniformBlockVariableOffset(m_phongUniformIndex, "AlphaThreshold");
|
m_basicTextureIndexes.alpha = materialSettings->GetTextureIndex("Alpha");
|
||||||
m_phongUniformOffsets.ambientColor = materialSettings->GetUniformBlockVariableOffset(m_phongUniformIndex, "AmbientColor");
|
m_basicTextureIndexes.diffuse = materialSettings->GetTextureIndex("Diffuse");
|
||||||
m_phongUniformOffsets.diffuseColor = materialSettings->GetUniformBlockVariableOffset(m_phongUniformIndex, "DiffuseColor");
|
|
||||||
m_phongUniformOffsets.shininess = materialSettings->GetUniformBlockVariableOffset(m_phongUniformIndex, "Shininess");
|
m_phongTextureIndexes.emissive = materialSettings->GetTextureIndex("Emissive");
|
||||||
m_phongUniformOffsets.specularColor = materialSettings->GetUniformBlockVariableOffset(m_phongUniformIndex, "SpecularColor");
|
m_phongTextureIndexes.height = materialSettings->GetTextureIndex("Height");
|
||||||
|
m_phongTextureIndexes.normal = materialSettings->GetTextureIndex("Normal");
|
||||||
|
m_phongTextureIndexes.specular = materialSettings->GetTextureIndex("Specular");
|
||||||
|
|
||||||
|
m_uniformBlockIndex = materialSettings->GetUniformBlockIndex("MaterialSettings");
|
||||||
|
if (m_uniformBlockIndex != MaterialSettings::InvalidIndex)
|
||||||
|
{
|
||||||
|
m_basicUniformOffsets.alphaThreshold = materialSettings->GetUniformBlockVariableOffset(m_uniformBlockIndex, "AlphaThreshold");
|
||||||
|
m_basicUniformOffsets.diffuseColor = materialSettings->GetUniformBlockVariableOffset(m_uniformBlockIndex, "DiffuseColor");
|
||||||
|
|
||||||
|
m_phongUniformOffsets.ambientColor = materialSettings->GetUniformBlockVariableOffset(m_uniformBlockIndex, "AmbientColor");
|
||||||
|
m_phongUniformOffsets.shininess = materialSettings->GetUniformBlockVariableOffset(m_uniformBlockIndex, "Shininess");
|
||||||
|
m_phongUniformOffsets.specularColor = materialSettings->GetUniformBlockVariableOffset(m_uniformBlockIndex, "SpecularColor");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_basicUniformOffsets.alphaThreshold = MaterialSettings::InvalidIndex;
|
||||||
|
m_basicUniformOffsets.diffuseColor = MaterialSettings::InvalidIndex;
|
||||||
|
|
||||||
|
m_phongUniformOffsets.ambientColor = MaterialSettings::InvalidIndex;
|
||||||
|
m_phongUniformOffsets.shininess = MaterialSettings::InvalidIndex;
|
||||||
|
m_phongUniformOffsets.specularColor = MaterialSettings::InvalidIndex;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float PhongLightingMaterial::GetAlphaThreshold() const
|
|
||||||
{
|
|
||||||
NazaraAssert(HasAlphaThreshold(), "Material has no alpha threshold uniform");
|
|
||||||
|
|
||||||
const std::vector<UInt8>& bufferData = m_material.GetUniformBufferConstData(m_phongUniformIndex);
|
|
||||||
return AccessByOffset<const float&>(bufferData.data(), m_phongUniformOffsets.alphaThreshold);
|
|
||||||
}
|
|
||||||
|
|
||||||
Color PhongLightingMaterial::GetAmbientColor() const
|
Color PhongLightingMaterial::GetAmbientColor() const
|
||||||
{
|
{
|
||||||
NazaraAssert(HasAmbientColor(), "Material has no ambient color uniform");
|
NazaraAssert(HasAmbientColor(), "Material has no ambient color uniform");
|
||||||
|
|
||||||
const std::vector<UInt8>& bufferData = m_material.GetUniformBufferConstData(m_phongUniformIndex);
|
const std::vector<UInt8>& bufferData = GetMaterial().GetUniformBufferConstData(m_uniformBlockIndex);
|
||||||
|
|
||||||
const float* colorPtr = AccessByOffset<const float*>(bufferData.data(), m_phongUniformOffsets.ambientColor);
|
const float* colorPtr = AccessByOffset<const float*>(bufferData.data(), m_phongUniformOffsets.ambientColor);
|
||||||
return Color(colorPtr[0] * 255, colorPtr[1] * 255, colorPtr[2] * 255, colorPtr[3] * 255); //< TODO: Make color able to use float
|
return Color(colorPtr[0] * 255, colorPtr[1] * 255, colorPtr[2] * 255, colorPtr[3] * 255); //< TODO: Make color able to use float
|
||||||
}
|
}
|
||||||
|
|
||||||
Color PhongLightingMaterial::GetDiffuseColor() const
|
|
||||||
{
|
|
||||||
NazaraAssert(HasDiffuseColor(), "Material has no diffuse color uniform");
|
|
||||||
|
|
||||||
const std::vector<UInt8>& bufferData = m_material.GetUniformBufferConstData(m_phongUniformIndex);
|
|
||||||
|
|
||||||
const float* colorPtr = AccessByOffset<const float*>(bufferData.data(), m_phongUniformOffsets.diffuseColor);
|
|
||||||
return Color(colorPtr[0] * 255, colorPtr[1] * 255, colorPtr[2] * 255, colorPtr[3] * 255); //< TODO: Make color able to use float
|
|
||||||
}
|
|
||||||
|
|
||||||
float Nz::PhongLightingMaterial::GetShininess() const
|
float Nz::PhongLightingMaterial::GetShininess() const
|
||||||
{
|
{
|
||||||
NazaraAssert(HasShininess(), "Material has no shininess uniform");
|
NazaraAssert(HasShininess(), "Material has no shininess uniform");
|
||||||
|
|
||||||
const std::vector<UInt8>& bufferData = m_material.GetUniformBufferConstData(m_phongUniformIndex);
|
const std::vector<UInt8>& bufferData = GetMaterial().GetUniformBufferConstData(m_uniformBlockIndex);
|
||||||
return AccessByOffset<const float&>(bufferData.data(), m_phongUniformOffsets.shininess);
|
return AccessByOffset<const float&>(bufferData.data(), m_phongUniformOffsets.shininess);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -85,25 +101,17 @@ namespace Nz
|
||||||
{
|
{
|
||||||
NazaraAssert(HasSpecularColor(), "Material has no specular color uniform");
|
NazaraAssert(HasSpecularColor(), "Material has no specular color uniform");
|
||||||
|
|
||||||
const std::vector<UInt8>& bufferData = m_material.GetUniformBufferConstData(m_phongUniformIndex);
|
const std::vector<UInt8>& bufferData = GetMaterial().GetUniformBufferConstData(m_uniformBlockIndex);
|
||||||
|
|
||||||
const float* colorPtr = AccessByOffset<const float*>(bufferData.data(), m_phongUniformOffsets.specularColor);
|
const float* colorPtr = AccessByOffset<const float*>(bufferData.data(), m_phongUniformOffsets.specularColor);
|
||||||
return Color(colorPtr[0] * 255, colorPtr[1] * 255, colorPtr[2] * 255, colorPtr[3] * 255); //< TODO: Make color able to use float
|
return Color(colorPtr[0] * 255, colorPtr[1] * 255, colorPtr[2] * 255, colorPtr[3] * 255); //< TODO: Make color able to use float
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhongLightingMaterial::SetAlphaThreshold(float alphaThreshold)
|
|
||||||
{
|
|
||||||
NazaraAssert(HasAlphaThreshold(), "Material has no alpha threshold uniform");
|
|
||||||
|
|
||||||
std::vector<UInt8>& bufferData = m_material.GetUniformBufferData(m_phongUniformIndex);
|
|
||||||
AccessByOffset<float&>(bufferData.data(), m_phongUniformOffsets.alphaThreshold) = alphaThreshold;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PhongLightingMaterial::SetAmbientColor(const Color& ambient)
|
void PhongLightingMaterial::SetAmbientColor(const Color& ambient)
|
||||||
{
|
{
|
||||||
NazaraAssert(HasAmbientColor(), "Material has no ambient color uniform");
|
NazaraAssert(HasAmbientColor(), "Material has no ambient color uniform");
|
||||||
|
|
||||||
std::vector<UInt8>& bufferData = m_material.GetUniformBufferData(m_phongUniformIndex);
|
std::vector<UInt8>& bufferData = GetMaterial().GetUniformBufferData(m_uniformBlockIndex);
|
||||||
float* colorPtr = AccessByOffset<float*>(bufferData.data(), m_phongUniformOffsets.ambientColor);
|
float* colorPtr = AccessByOffset<float*>(bufferData.data(), m_phongUniformOffsets.ambientColor);
|
||||||
colorPtr[0] = ambient.r / 255.f;
|
colorPtr[0] = ambient.r / 255.f;
|
||||||
colorPtr[1] = ambient.g / 255.f;
|
colorPtr[1] = ambient.g / 255.f;
|
||||||
|
|
@ -111,23 +119,19 @@ namespace Nz
|
||||||
colorPtr[3] = ambient.a / 255.f;
|
colorPtr[3] = ambient.a / 255.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhongLightingMaterial::SetDiffuseColor(const Color& diffuse)
|
void PhongLightingMaterial::SetShininess(float shininess)
|
||||||
{
|
{
|
||||||
NazaraAssert(HasDiffuseColor(), "Material has no diffuse color uniform");
|
NazaraAssert(HasShininess(), "Material has no shininess uniform");
|
||||||
|
|
||||||
std::vector<UInt8>& bufferData = m_material.GetUniformBufferData(m_phongUniformIndex);
|
std::vector<UInt8>& bufferData = GetMaterial().GetUniformBufferData(m_uniformBlockIndex);
|
||||||
float* colorPtr = AccessByOffset<float*>(bufferData.data(), m_phongUniformOffsets.diffuseColor);
|
AccessByOffset<float&>(bufferData.data(), m_phongUniformOffsets.shininess) = shininess;
|
||||||
colorPtr[0] = diffuse.r / 255.f;
|
|
||||||
colorPtr[1] = diffuse.g / 255.f;
|
|
||||||
colorPtr[2] = diffuse.b / 255.f;
|
|
||||||
colorPtr[3] = diffuse.a / 255.f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhongLightingMaterial::SetSpecularColor(const Color& diffuse)
|
void PhongLightingMaterial::SetSpecularColor(const Color& diffuse)
|
||||||
{
|
{
|
||||||
NazaraAssert(HasSpecularColor(), "Material has no specular color uniform");
|
NazaraAssert(HasSpecularColor(), "Material has no specular color uniform");
|
||||||
|
|
||||||
std::vector<UInt8>& bufferData = m_material.GetUniformBufferData(m_phongUniformIndex);
|
std::vector<UInt8>& bufferData = GetMaterial().GetUniformBufferData(m_uniformBlockIndex);
|
||||||
float* colorPtr = AccessByOffset<float*>(bufferData.data(), m_phongUniformOffsets.specularColor);
|
float* colorPtr = AccessByOffset<float*>(bufferData.data(), m_phongUniformOffsets.specularColor);
|
||||||
colorPtr[0] = diffuse.r / 255.f;
|
colorPtr[0] = diffuse.r / 255.f;
|
||||||
colorPtr[1] = diffuse.g / 255.f;
|
colorPtr[1] = diffuse.g / 255.f;
|
||||||
|
|
@ -137,118 +141,256 @@ namespace Nz
|
||||||
|
|
||||||
const std::shared_ptr<MaterialSettings>& PhongLightingMaterial::GetSettings()
|
const std::shared_ptr<MaterialSettings>& PhongLightingMaterial::GetSettings()
|
||||||
{
|
{
|
||||||
return s_materialSettings;
|
return s_phongMaterialSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PhongLightingMaterial::Initialize()
|
MaterialSettings::Builder PhongLightingMaterial::Build(PhongBuildOptions& options)
|
||||||
{
|
{
|
||||||
// MaterialPhongSettings
|
MaterialSettings::Builder settings = BasicMaterial::Build(options);
|
||||||
FieldOffsets phongUniformStruct(StructLayout::Std140);
|
|
||||||
|
|
||||||
s_phongUniformOffsets.alphaThreshold = phongUniformStruct.AddField(StructFieldType::Float1);
|
assert(settings.uniformBlocks.size() == 1);
|
||||||
s_phongUniformOffsets.shininess = phongUniformStruct.AddField(StructFieldType::Float1);
|
std::vector<MaterialSettings::UniformVariable> variables = std::move(settings.uniformBlocks.front().uniforms);
|
||||||
s_phongUniformOffsets.ambientColor = phongUniformStruct.AddField(StructFieldType::Float4);
|
settings.uniformBlocks.clear();
|
||||||
s_phongUniformOffsets.diffuseColor = phongUniformStruct.AddField(StructFieldType::Float4);
|
|
||||||
s_phongUniformOffsets.specularColor = phongUniformStruct.AddField(StructFieldType::Float4);
|
|
||||||
|
|
||||||
MaterialSettings::Builder settings;
|
if (options.phongOffsets.ambientColor != std::numeric_limits<std::size_t>::max())
|
||||||
|
{
|
||||||
std::vector<MaterialSettings::UniformVariable> phongVariables;
|
variables.push_back({
|
||||||
phongVariables.assign({
|
|
||||||
{
|
|
||||||
"AlphaThreshold",
|
|
||||||
s_phongUniformOffsets.alphaThreshold
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Shininess",
|
|
||||||
s_phongUniformOffsets.shininess
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AmbientColor",
|
"AmbientColor",
|
||||||
s_phongUniformOffsets.ambientColor
|
options.phongOffsets.ambientColor
|
||||||
},
|
});
|
||||||
{
|
}
|
||||||
"DiffuseColor",
|
|
||||||
s_phongUniformOffsets.diffuseColor
|
if (options.phongOffsets.shininess != std::numeric_limits<std::size_t>::max())
|
||||||
},
|
{
|
||||||
{
|
variables.push_back({
|
||||||
|
"Shininess",
|
||||||
|
options.phongOffsets.shininess
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.phongOffsets.shininess != std::numeric_limits<std::size_t>::max())
|
||||||
|
{
|
||||||
|
variables.push_back({
|
||||||
"SpecularColor",
|
"SpecularColor",
|
||||||
s_phongUniformOffsets.specularColor
|
options.phongOffsets.specularColor
|
||||||
}
|
});
|
||||||
});
|
}
|
||||||
|
|
||||||
static_assert(sizeof(Vector4f) == 4 * sizeof(float), "Vector4f is expected to be exactly 4 floats wide");
|
static_assert(sizeof(Vector4f) == 4 * sizeof(float), "Vector4f is expected to be exactly 4 floats wide");
|
||||||
|
|
||||||
std::vector<UInt8> defaultValues(phongUniformStruct.GetSize());
|
if (options.phongOffsets.ambientColor != std::numeric_limits<std::size_t>::max())
|
||||||
AccessByOffset<Vector4f&>(defaultValues.data(), s_phongUniformOffsets.ambientColor) = Vector4f(0.5f, 0.5f, 0.5f, 1.f);
|
AccessByOffset<Vector4f&>(options.defaultValues.data(), options.phongOffsets.ambientColor) = Vector4f(0.f, 0.f, 0.f, 1.f);
|
||||||
AccessByOffset<Vector4f&>(defaultValues.data(), s_phongUniformOffsets.diffuseColor) = Vector4f(1.f, 1.f, 1.f, 1.f);
|
|
||||||
AccessByOffset<Vector4f&>(defaultValues.data(), s_phongUniformOffsets.specularColor) = Vector4f(1.f, 1.f, 1.f, 1.f);
|
|
||||||
AccessByOffset<float&>(defaultValues.data(), s_phongUniformOffsets.alphaThreshold) = 0.2f;
|
|
||||||
AccessByOffset<float&>(defaultValues.data(), s_phongUniformOffsets.shininess) = 50.f;
|
|
||||||
|
|
||||||
s_phongUniformBlockIndex = settings.uniformBlocks.size();
|
if (options.phongOffsets.specularColor != std::numeric_limits<std::size_t>::max())
|
||||||
settings.uniformBlocks.push_back({
|
AccessByOffset<Vector4f&>(options.defaultValues.data(), options.phongOffsets.specularColor) = Vector4f(1.f, 1.f, 1.f, 1.f);
|
||||||
0,
|
|
||||||
"PhongSettings",
|
|
||||||
phongUniformStruct.GetSize(),
|
|
||||||
std::move(phongVariables),
|
|
||||||
std::move(defaultValues)
|
|
||||||
});
|
|
||||||
|
|
||||||
s_textureIndexes.alpha = settings.textures.size();
|
if (options.phongOffsets.shininess != std::numeric_limits<std::size_t>::max())
|
||||||
settings.textures.push_back({
|
AccessByOffset<float&>(options.defaultValues.data(), options.phongOffsets.shininess) = 2.f;
|
||||||
2,
|
|
||||||
"Alpha",
|
// Textures
|
||||||
ImageType::E2D
|
if (options.phongTextureIndexes)
|
||||||
});
|
options.phongTextureIndexes->emissive = settings.textures.size();
|
||||||
|
|
||||||
s_textureIndexes.diffuse = settings.textures.size();
|
|
||||||
settings.textures.push_back({
|
|
||||||
1,
|
|
||||||
"Diffuse",
|
|
||||||
ImageType::E2D
|
|
||||||
});
|
|
||||||
|
|
||||||
s_textureIndexes.emissive = settings.textures.size();
|
|
||||||
settings.textures.push_back({
|
settings.textures.push_back({
|
||||||
3,
|
7,
|
||||||
"Emissive",
|
"Emissive",
|
||||||
ImageType::E2D
|
ImageType::E2D
|
||||||
});
|
});
|
||||||
|
|
||||||
s_textureIndexes.height = settings.textures.size();
|
if (options.phongTextureIndexes)
|
||||||
|
options.phongTextureIndexes->height = settings.textures.size();
|
||||||
|
|
||||||
settings.textures.push_back({
|
settings.textures.push_back({
|
||||||
4,
|
8,
|
||||||
"Height",
|
"Height",
|
||||||
ImageType::E2D
|
ImageType::E2D
|
||||||
});
|
});
|
||||||
|
|
||||||
s_textureIndexes.normal = settings.textures.size();
|
if (options.phongTextureIndexes)
|
||||||
|
options.phongTextureIndexes->normal = settings.textures.size();
|
||||||
|
|
||||||
settings.textures.push_back({
|
settings.textures.push_back({
|
||||||
5,
|
9,
|
||||||
"Normal",
|
"Normal",
|
||||||
ImageType::E2D
|
ImageType::E2D
|
||||||
});
|
});
|
||||||
|
|
||||||
s_textureIndexes.specular = settings.textures.size();
|
if (options.phongTextureIndexes)
|
||||||
|
options.phongTextureIndexes->specular = settings.textures.size();
|
||||||
|
|
||||||
settings.textures.push_back({
|
settings.textures.push_back({
|
||||||
6,
|
10,
|
||||||
"Specular",
|
"Specular",
|
||||||
ImageType::E2D
|
ImageType::E2D
|
||||||
});
|
});
|
||||||
|
|
||||||
s_materialSettings = std::make_shared<MaterialSettings>(std::move(settings));
|
if (options.uniformBlockIndex)
|
||||||
|
*options.uniformBlockIndex = settings.uniformBlocks.size();
|
||||||
|
|
||||||
|
settings.uniformBlocks.push_back({
|
||||||
|
0,
|
||||||
|
"MaterialSettings",
|
||||||
|
options.phongOffsets.totalSize,
|
||||||
|
std::move(variables),
|
||||||
|
options.defaultValues
|
||||||
|
});
|
||||||
|
|
||||||
|
settings.sharedUniformBlocks.push_back(PredefinedLightData::GetUniformBlock(6, ShaderStageType::Fragment));
|
||||||
|
settings.predefinedBindings[UnderlyingCast(PredefinedShaderBinding::LightDataUbo)] = 6;
|
||||||
|
|
||||||
|
settings.shaders = options.shaders;
|
||||||
|
|
||||||
|
for (std::shared_ptr<UberShader> uberShader : settings.shaders)
|
||||||
|
{
|
||||||
|
constexpr std::size_t InvalidOption = std::numeric_limits<std::size_t>::max();
|
||||||
|
|
||||||
|
auto FetchLocationOption = [&](const std::string& optionName)
|
||||||
|
{
|
||||||
|
const UberShader::Option* optionPtr;
|
||||||
|
if (!uberShader->HasOption(optionName, &optionPtr))
|
||||||
|
return InvalidOption;
|
||||||
|
|
||||||
|
if (optionPtr->type != ShaderAst::ExpressionType{ ShaderAst::PrimitiveType::Int32 })
|
||||||
|
throw std::runtime_error("Location options must be of type i32");
|
||||||
|
|
||||||
|
return optionPtr->index;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::size_t positionLocationIndex = FetchLocationOption("PosLocation");
|
||||||
|
std::size_t colorLocationIndex = FetchLocationOption("ColorLocation");
|
||||||
|
std::size_t normalLocationIndex = FetchLocationOption("NormalLocation");
|
||||||
|
std::size_t uvLocationIndex = FetchLocationOption("UvLocation");
|
||||||
|
|
||||||
|
uberShader->UpdateConfigCallback([=](UberShader::Config& config, const std::vector<RenderPipelineInfo::VertexBufferData>& vertexBuffers)
|
||||||
|
{
|
||||||
|
if (vertexBuffers.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
const VertexDeclaration& vertexDeclaration = *vertexBuffers.front().declaration;
|
||||||
|
const auto& components = vertexDeclaration.GetComponents();
|
||||||
|
|
||||||
|
std::size_t locationIndex = 0;
|
||||||
|
for (const auto& component : components)
|
||||||
|
{
|
||||||
|
switch (component.component)
|
||||||
|
{
|
||||||
|
case VertexComponent::Position:
|
||||||
|
if (positionLocationIndex != InvalidOption)
|
||||||
|
config.optionValues[positionLocationIndex] = static_cast<Int32>(locationIndex);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VertexComponent::Color:
|
||||||
|
if (colorLocationIndex != InvalidOption)
|
||||||
|
config.optionValues[colorLocationIndex] = static_cast<Int32>(locationIndex);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VertexComponent::Normal:
|
||||||
|
if (normalLocationIndex != InvalidOption)
|
||||||
|
config.optionValues[normalLocationIndex] = static_cast<Int32>(locationIndex);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VertexComponent::TexCoord:
|
||||||
|
if (uvLocationIndex != InvalidOption)
|
||||||
|
config.optionValues[uvLocationIndex] = static_cast<Int32>(locationIndex);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VertexComponent::Unused:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
++locationIndex;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Options
|
||||||
|
|
||||||
|
// HasEmissiveMap
|
||||||
|
if (options.phongOptionIndexes)
|
||||||
|
options.phongOptionIndexes->hasEmissiveMap = settings.options.size();
|
||||||
|
|
||||||
|
MaterialSettings::BuildOption(settings.options, settings.shaders, "HasEmissiveMap", "HasEmissiveTexture");
|
||||||
|
|
||||||
|
// HasHeightMap
|
||||||
|
if (options.phongOptionIndexes)
|
||||||
|
options.phongOptionIndexes->hasHeightMap = settings.options.size();
|
||||||
|
|
||||||
|
MaterialSettings::BuildOption(settings.options, settings.shaders, "HasHeightMap", "HasHeightTexture");
|
||||||
|
|
||||||
|
// HasNormalMap
|
||||||
|
if (options.phongOptionIndexes)
|
||||||
|
options.phongOptionIndexes->hasNormalMap = settings.options.size();
|
||||||
|
|
||||||
|
MaterialSettings::BuildOption(settings.options, settings.shaders, "HasNormalMap", "HasNormalTexture");
|
||||||
|
|
||||||
|
// HasSpecularMap
|
||||||
|
if (options.phongOptionIndexes)
|
||||||
|
options.phongOptionIndexes->hasSpecularMap = settings.options.size();
|
||||||
|
|
||||||
|
MaterialSettings::BuildOption(settings.options, settings.shaders, "HasSpecularMap", "HasSpecularTexture");
|
||||||
|
|
||||||
|
return settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::shared_ptr<UberShader>> PhongLightingMaterial::BuildShaders()
|
||||||
|
{
|
||||||
|
ShaderAst::StatementPtr shaderAst = ShaderLang::Parse(std::string_view(reinterpret_cast<const char*>(r_shader), sizeof(r_shader)));
|
||||||
|
auto shader = std::make_shared<UberShader>(ShaderStageType::Fragment | ShaderStageType::Vertex, shaderAst);
|
||||||
|
|
||||||
|
return { std::move(shader) };
|
||||||
|
}
|
||||||
|
|
||||||
|
auto PhongLightingMaterial::BuildUniformOffsets() -> std::pair<PhongUniformOffsets, FieldOffsets>
|
||||||
|
{
|
||||||
|
auto basicOffsets = BasicMaterial::BuildUniformOffsets();
|
||||||
|
FieldOffsets fieldOffsets = basicOffsets.second;
|
||||||
|
|
||||||
|
PhongUniformOffsets uniformOffsets;
|
||||||
|
uniformOffsets.ambientColor = fieldOffsets.AddField(StructFieldType::Float3);
|
||||||
|
uniformOffsets.specularColor = fieldOffsets.AddField(StructFieldType::Float3);
|
||||||
|
uniformOffsets.shininess = fieldOffsets.AddField(StructFieldType::Float1);
|
||||||
|
|
||||||
|
uniformOffsets.totalSize = fieldOffsets.GetAlignedSize();
|
||||||
|
|
||||||
|
return std::make_pair(std::move(uniformOffsets), std::move(fieldOffsets));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PhongLightingMaterial::Initialize()
|
||||||
|
{
|
||||||
|
std::tie(s_phongUniformOffsets, std::ignore) = BuildUniformOffsets();
|
||||||
|
|
||||||
|
std::vector<UInt8> defaultValues(s_phongUniformOffsets.totalSize);
|
||||||
|
|
||||||
|
PhongBuildOptions options;
|
||||||
|
options.defaultValues = std::move(defaultValues);
|
||||||
|
options.shaders = BuildShaders();
|
||||||
|
|
||||||
|
// Basic material
|
||||||
|
options.basicOffsets = s_basicUniformOffsets;
|
||||||
|
|
||||||
|
// Phong Material
|
||||||
|
options.phongOffsets = s_phongUniformOffsets;
|
||||||
|
options.phongOptionIndexes = &s_phongOptionIndexes;
|
||||||
|
options.phongTextureIndexes = &s_phongTextureIndexes;
|
||||||
|
|
||||||
|
s_phongMaterialSettings = std::make_shared<MaterialSettings>(Build(options));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhongLightingMaterial::Uninitialize()
|
void PhongLightingMaterial::Uninitialize()
|
||||||
{
|
{
|
||||||
s_materialSettings.reset();
|
s_phongMaterialSettings.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<MaterialSettings> PhongLightingMaterial::s_materialSettings;
|
std::shared_ptr<MaterialSettings> PhongLightingMaterial::s_phongMaterialSettings;
|
||||||
std::size_t PhongLightingMaterial::s_phongUniformBlockIndex;
|
std::size_t PhongLightingMaterial::s_phongUniformBlockIndex;
|
||||||
PhongLightingMaterial::TextureIndexes PhongLightingMaterial::s_textureIndexes;
|
PhongLightingMaterial::PhongOptionIndexes PhongLightingMaterial::s_phongOptionIndexes;
|
||||||
|
PhongLightingMaterial::PhongTextureIndexes PhongLightingMaterial::s_phongTextureIndexes;
|
||||||
PhongLightingMaterial::PhongUniformOffsets PhongLightingMaterial::s_phongUniformOffsets;
|
PhongLightingMaterial::PhongUniformOffsets PhongLightingMaterial::s_phongUniformOffsets;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,42 +13,40 @@ namespace Nz
|
||||||
PredefinedLightData lightData;
|
PredefinedLightData lightData;
|
||||||
|
|
||||||
FieldOffsets lightStruct(StructLayout::Std140);
|
FieldOffsets lightStruct(StructLayout::Std140);
|
||||||
lightData.innerOffsets.type = lightStruct.AddField(StructFieldType::Int1);
|
lightData.lightMemberOffsets.type = lightStruct.AddField(StructFieldType::Int1);
|
||||||
lightData.innerOffsets.color = lightStruct.AddField(StructFieldType::Float4);
|
lightData.lightMemberOffsets.color = lightStruct.AddField(StructFieldType::Float4);
|
||||||
lightData.innerOffsets.factor = lightStruct.AddField(StructFieldType::Float2);
|
lightData.lightMemberOffsets.factor = lightStruct.AddField(StructFieldType::Float2);
|
||||||
lightData.innerOffsets.parameter1 = lightStruct.AddField(StructFieldType::Float4);
|
lightData.lightMemberOffsets.parameter1 = lightStruct.AddField(StructFieldType::Float4);
|
||||||
lightData.innerOffsets.parameter2 = lightStruct.AddField(StructFieldType::Float4);
|
lightData.lightMemberOffsets.parameter2 = lightStruct.AddField(StructFieldType::Float4);
|
||||||
lightData.innerOffsets.parameter3 = lightStruct.AddField(StructFieldType::Float2);
|
lightData.lightMemberOffsets.parameter3 = lightStruct.AddField(StructFieldType::Float4);
|
||||||
lightData.innerOffsets.shadowMappingFlag = lightStruct.AddField(StructFieldType::Bool1);
|
lightData.lightMemberOffsets.shadowMappingFlag = lightStruct.AddField(StructFieldType::Bool1);
|
||||||
|
|
||||||
lightData.innerOffsets.totalSize = lightStruct.GetAlignedSize();
|
lightData.lightSize = lightStruct.GetAlignedSize();
|
||||||
|
|
||||||
FieldOffsets lightDataStruct(StructLayout::Std140);
|
FieldOffsets lightDataStruct(StructLayout::Std140);
|
||||||
for (std::size_t& lightOffset : lightData.lightArray)
|
lightData.lightsOffset = lightDataStruct.AddStructArray(lightStruct, MaxLightCount);
|
||||||
lightOffset = lightDataStruct.AddStruct(lightStruct);
|
lightData.lightCountOffset = lightDataStruct.AddField(StructFieldType::UInt1);
|
||||||
|
|
||||||
lightData.lightArraySize = lightDataStruct.GetAlignedSize();
|
lightData.totalSize = lightDataStruct.GetAlignedSize();
|
||||||
|
|
||||||
return lightData;
|
return lightData;
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialSettings::SharedUniformBlock PredefinedLightData::GetUniformBlock()
|
MaterialSettings::SharedUniformBlock PredefinedLightData::GetUniformBlock(UInt32 bindingIndex, ShaderStageTypeFlags shaderStages)
|
||||||
{
|
{
|
||||||
PredefinedLightData lightData = GetOffsets();
|
PredefinedLightData lightData = GetOffsets();
|
||||||
|
|
||||||
std::vector<MaterialSettings::UniformVariable> lightDataVariables;
|
std::vector<MaterialSettings::UniformVariable> variables = {
|
||||||
for (std::size_t i = 0; i < lightData.lightArray.size(); ++i)
|
{
|
||||||
{
|
{ "Lights", lightData.lightsOffset }
|
||||||
lightDataVariables.push_back({
|
}
|
||||||
"LightData[" + std::to_string(i) + "]",
|
};
|
||||||
lightData.lightArray[i]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
MaterialSettings::SharedUniformBlock uniformBlock = {
|
MaterialSettings::SharedUniformBlock uniformBlock = {
|
||||||
0, //< FIXME
|
bindingIndex,
|
||||||
"Light",
|
"LightData",
|
||||||
std::move(lightDataVariables)
|
std::move(variables),
|
||||||
|
shaderStages
|
||||||
};
|
};
|
||||||
|
|
||||||
return uniformBlock;
|
return uniformBlock;
|
||||||
|
|
|
||||||
|
|
@ -2,16 +2,23 @@ option HasDiffuseTexture: bool = false;
|
||||||
option HasAlphaTexture: bool = false;
|
option HasAlphaTexture: bool = false;
|
||||||
option AlphaTest: bool = false;
|
option AlphaTest: bool = false;
|
||||||
|
|
||||||
|
// Billboard related options
|
||||||
|
option Billboard: bool = false;
|
||||||
|
option BillboardCenterLocation: i32 = -1;
|
||||||
|
option BillboardColorLocation: i32 = -1;
|
||||||
|
option BillboardSizeRotLocation: i32 = -1;
|
||||||
|
|
||||||
// Vertex declaration related options
|
// Vertex declaration related options
|
||||||
option PosLocation: i32 = -1;
|
|
||||||
option ColorLocation: i32 = -1;
|
option ColorLocation: i32 = -1;
|
||||||
|
option PosLocation: i32 = -1;
|
||||||
option UvLocation: i32 = -1;
|
option UvLocation: i32 = -1;
|
||||||
|
|
||||||
const HasVertexColor = (ColorLocation >= 0);
|
const HasVertexColor = (ColorLocation >= 0);
|
||||||
|
const HasColor = (HasVertexColor || Billboard);
|
||||||
const HasUV = (UvLocation >= 0);
|
const HasUV = (UvLocation >= 0);
|
||||||
|
|
||||||
[layout(std140)]
|
[layout(std140)]
|
||||||
struct BasicSettings
|
struct MaterialSettings
|
||||||
{
|
{
|
||||||
AlphaThreshold: f32,
|
AlphaThreshold: f32,
|
||||||
DiffuseColor: vec4<f32>
|
DiffuseColor: vec4<f32>
|
||||||
|
|
@ -40,7 +47,7 @@ struct ViewerData
|
||||||
|
|
||||||
external
|
external
|
||||||
{
|
{
|
||||||
[binding(0)] settings: uniform<BasicSettings>,
|
[binding(0)] settings: uniform<MaterialSettings>,
|
||||||
[binding(1)] MaterialDiffuseMap: sampler2D<f32>,
|
[binding(1)] MaterialDiffuseMap: sampler2D<f32>,
|
||||||
[binding(2)] MaterialAlphaMap: sampler2D<f32>,
|
[binding(2)] MaterialAlphaMap: sampler2D<f32>,
|
||||||
[binding(3)] TextureOverlay: sampler2D<f32>,
|
[binding(3)] TextureOverlay: sampler2D<f32>,
|
||||||
|
|
@ -52,7 +59,7 @@ external
|
||||||
struct FragIn
|
struct FragIn
|
||||||
{
|
{
|
||||||
[location(0), cond(HasUV)] uv: vec2<f32>,
|
[location(0), cond(HasUV)] uv: vec2<f32>,
|
||||||
[location(1), cond(HasVertexColor)] color: vec4<f32>
|
[location(1), cond(HasColor)] color: vec4<f32>
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FragOut
|
struct FragOut
|
||||||
|
|
@ -68,7 +75,7 @@ fn main(input: FragIn) -> FragOut
|
||||||
const if (HasUV)
|
const if (HasUV)
|
||||||
diffuseColor *= TextureOverlay.Sample(input.uv);
|
diffuseColor *= TextureOverlay.Sample(input.uv);
|
||||||
|
|
||||||
const if (HasVertexColor)
|
const if (HasColor)
|
||||||
diffuseColor *= input.color;
|
diffuseColor *= input.color;
|
||||||
|
|
||||||
const if (HasDiffuseTexture)
|
const if (HasDiffuseTexture)
|
||||||
|
|
@ -91,25 +98,70 @@ fn main(input: FragIn) -> FragOut
|
||||||
// Vertex stage
|
// Vertex stage
|
||||||
struct VertIn
|
struct VertIn
|
||||||
{
|
{
|
||||||
[location(PosLocation)] pos: vec3<f32>,
|
[location(PosLocation)]
|
||||||
[location(ColorLocation), cond(HasVertexColor)] color: vec4<f32>,
|
pos: vec3<f32>,
|
||||||
[location(UvLocation), cond(HasUV)] uv: vec2<f32>
|
|
||||||
|
[cond(HasVertexColor), location(ColorLocation)]
|
||||||
|
color: vec4<f32>,
|
||||||
|
|
||||||
|
[cond(HasUV), location(UvLocation)]
|
||||||
|
uv: vec2<f32>,
|
||||||
|
|
||||||
|
[cond(Billboard), location(BillboardCenterLocation)]
|
||||||
|
billboardCenter: vec3<f32>,
|
||||||
|
|
||||||
|
[cond(Billboard), location(BillboardSizeRotLocation)]
|
||||||
|
billboardSizeRot: vec4<f32>, //< width,height,sin,cos
|
||||||
|
|
||||||
|
[cond(Billboard), location(BillboardColorLocation)]
|
||||||
|
billboardColor: vec4<f32>
|
||||||
}
|
}
|
||||||
|
|
||||||
struct VertOut
|
struct VertOut
|
||||||
{
|
{
|
||||||
[location(0), cond(HasUV)] uv: vec2<f32>,
|
[location(0), cond(HasUV)] uv: vec2<f32>,
|
||||||
[location(1), cond(HasVertexColor)] color: vec4<f32>,
|
[location(1), cond(HasColor)] color: vec4<f32>,
|
||||||
[builtin(position)] position: vec4<f32>
|
[builtin(position)] position: vec4<f32>
|
||||||
}
|
}
|
||||||
|
|
||||||
[entry(vert)]
|
[entry(vert), cond(Billboard)]
|
||||||
|
fn billboardMain(input: VertIn) -> VertOut
|
||||||
|
{
|
||||||
|
let size = input.billboardSizeRot.xy;
|
||||||
|
let sinCos = input.billboardSizeRot.zw;
|
||||||
|
|
||||||
|
let rotatedPosition = vec2<f32>(
|
||||||
|
input.pos.x * sinCos.y - input.pos.y * sinCos.x,
|
||||||
|
input.pos.y * sinCos.y + input.pos.x * sinCos.x
|
||||||
|
);
|
||||||
|
rotatedPosition *= size;
|
||||||
|
|
||||||
|
let cameraRight = vec3<f32>(viewerData.viewMatrix[0][0], viewerData.viewMatrix[1][0], viewerData.viewMatrix[2][0]);
|
||||||
|
let cameraUp = vec3<f32>(viewerData.viewMatrix[0][1], viewerData.viewMatrix[1][1], viewerData.viewMatrix[2][1]);
|
||||||
|
|
||||||
|
let vertexPos = input.billboardCenter;
|
||||||
|
vertexPos += cameraRight * rotatedPosition.x;
|
||||||
|
vertexPos += cameraUp * rotatedPosition.y;
|
||||||
|
|
||||||
|
let output: VertOut;
|
||||||
|
output.position = viewerData.viewProjMatrix * instanceData.worldMatrix * vec4<f32>(vertexPos, 1.0);
|
||||||
|
|
||||||
|
const if (HasColor)
|
||||||
|
output.color = input.billboardColor;
|
||||||
|
|
||||||
|
const if (HasUV)
|
||||||
|
output.uv = input.pos.xy + vec2<f32>(0.5, 0.5);
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
[entry(vert), cond(!Billboard)]
|
||||||
fn main(input: VertIn) -> VertOut
|
fn main(input: VertIn) -> VertOut
|
||||||
{
|
{
|
||||||
let output: VertOut;
|
let output: VertOut;
|
||||||
output.position = viewerData.viewProjMatrix * instanceData.worldMatrix * vec4<f32>(input.pos, 1.0);
|
output.position = viewerData.viewProjMatrix * instanceData.worldMatrix * vec4<f32>(input.pos, 1.0);
|
||||||
|
|
||||||
const if (HasVertexColor)
|
const if (HasColor)
|
||||||
output.color = input.color;
|
output.color = input.color;
|
||||||
|
|
||||||
const if (HasUV)
|
const if (HasUV)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,286 @@
|
||||||
|
// Basic material options
|
||||||
|
option HasDiffuseTexture: bool = false;
|
||||||
|
option HasAlphaTexture: bool = false;
|
||||||
|
option AlphaTest: bool = false;
|
||||||
|
|
||||||
|
// Phong material options
|
||||||
|
option HasEmissiveTexture: bool = false;
|
||||||
|
option HasHeightTexture: bool = false;
|
||||||
|
option HasNormalTexture: bool = false;
|
||||||
|
option HasSpecularTexture: bool = false;
|
||||||
|
|
||||||
|
option MaxLightCount: u32 = u32(3); //< FIXME: Fix integral value types
|
||||||
|
|
||||||
|
// Billboard related options
|
||||||
|
option Billboard: bool = false;
|
||||||
|
option BillboardCenterLocation: i32 = -1;
|
||||||
|
option BillboardColorLocation: i32 = -1;
|
||||||
|
option BillboardSizeRotLocation: i32 = -1;
|
||||||
|
|
||||||
|
// Vertex declaration related options
|
||||||
|
option ColorLocation: i32 = -1;
|
||||||
|
option NormalLocation: i32 = -1;
|
||||||
|
option PosLocation: i32 = -1;
|
||||||
|
option UvLocation: i32 = -1;
|
||||||
|
|
||||||
|
const HasNormal = (NormalLocation >= 0);
|
||||||
|
const HasVertexColor = (ColorLocation >= 0);
|
||||||
|
const HasColor = (HasVertexColor || Billboard);
|
||||||
|
const HasUV = (UvLocation >= 0);
|
||||||
|
|
||||||
|
[layout(std140)]
|
||||||
|
struct MaterialSettings
|
||||||
|
{
|
||||||
|
// BasicSettings
|
||||||
|
AlphaThreshold: f32,
|
||||||
|
DiffuseColor: vec4<f32>,
|
||||||
|
|
||||||
|
// PhongSettings
|
||||||
|
AmbientColor: vec3<f32>,
|
||||||
|
SpecularColor: vec3<f32>,
|
||||||
|
Shininess: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
[layout(std140)]
|
||||||
|
struct InstanceData
|
||||||
|
{
|
||||||
|
worldMatrix: mat4<f32>,
|
||||||
|
invWorldMatrix: mat4<f32>
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Add enums
|
||||||
|
const DirectionalLight = 0;
|
||||||
|
const PointLight = 1;
|
||||||
|
const SpotLight = 2;
|
||||||
|
|
||||||
|
[layout(std140)]
|
||||||
|
struct Light
|
||||||
|
{
|
||||||
|
type: i32,
|
||||||
|
color: vec4<f32>,
|
||||||
|
factor: vec2<f32>,
|
||||||
|
parameter1: vec4<f32>,
|
||||||
|
parameter2: vec4<f32>,
|
||||||
|
parameter3: vec4<f32>,
|
||||||
|
hasShadowMapping: bool
|
||||||
|
}
|
||||||
|
|
||||||
|
[layout(std140)]
|
||||||
|
struct LightData
|
||||||
|
{
|
||||||
|
lights: [Light; MaxLightCount],
|
||||||
|
lightCount: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
[layout(std140)]
|
||||||
|
struct ViewerData
|
||||||
|
{
|
||||||
|
projectionMatrix: mat4<f32>,
|
||||||
|
invProjectionMatrix: mat4<f32>,
|
||||||
|
viewMatrix: mat4<f32>,
|
||||||
|
invViewMatrix: mat4<f32>,
|
||||||
|
viewProjMatrix: mat4<f32>,
|
||||||
|
invViewProjMatrix: mat4<f32>,
|
||||||
|
renderTargetSize: vec2<f32>,
|
||||||
|
invRenderTargetSize: vec2<f32>,
|
||||||
|
eyePosition: vec3<f32>
|
||||||
|
}
|
||||||
|
|
||||||
|
external
|
||||||
|
{
|
||||||
|
[binding(0)] settings: uniform<MaterialSettings>,
|
||||||
|
[binding(1)] MaterialDiffuseMap: sampler2D<f32>,
|
||||||
|
[binding(2)] MaterialAlphaMap: sampler2D<f32>,
|
||||||
|
[binding(3)] TextureOverlay: sampler2D<f32>,
|
||||||
|
[binding(4)] instanceData: uniform<InstanceData>,
|
||||||
|
[binding(5)] viewerData: uniform<ViewerData>,
|
||||||
|
[binding(6)] lightData: uniform<LightData>,
|
||||||
|
[binding(7)] MaterialEmissiveMap: sampler2D<f32>,
|
||||||
|
[binding(8)] MaterialHeightMap: sampler2D<f32>,
|
||||||
|
[binding(9)] MaterialNormalMap: sampler2D<f32>,
|
||||||
|
[binding(10)] MaterialSpecularMap: sampler2D<f32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fragment stage
|
||||||
|
struct FragIn
|
||||||
|
{
|
||||||
|
[location(0)] worldPos: vec3<f32>,
|
||||||
|
[location(1), cond(HasUV)] uv: vec2<f32>,
|
||||||
|
[location(2), cond(HasColor)] color: vec4<f32>,
|
||||||
|
[location(3), cond(HasNormal)] normal: vec3<f32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct FragOut
|
||||||
|
{
|
||||||
|
[location(0)] RenderTarget0: vec4<f32>
|
||||||
|
}
|
||||||
|
|
||||||
|
[entry(frag)]
|
||||||
|
fn main(input: FragIn) -> FragOut
|
||||||
|
{
|
||||||
|
let diffuseColor = settings.DiffuseColor;
|
||||||
|
|
||||||
|
const if (HasUV)
|
||||||
|
diffuseColor *= TextureOverlay.Sample(input.uv);
|
||||||
|
|
||||||
|
const if (HasColor)
|
||||||
|
diffuseColor *= input.color;
|
||||||
|
|
||||||
|
const if (HasDiffuseTexture)
|
||||||
|
diffuseColor *= MaterialDiffuseMap.Sample(input.uv);
|
||||||
|
|
||||||
|
const if (HasAlphaTexture)
|
||||||
|
diffuseColor.w *= MaterialAlphaMap.Sample(input.uv).x;
|
||||||
|
|
||||||
|
const if (AlphaTest)
|
||||||
|
{
|
||||||
|
if (diffuseColor.w < settings.AlphaThreshold)
|
||||||
|
discard;
|
||||||
|
}
|
||||||
|
|
||||||
|
const if (HasNormal)
|
||||||
|
{
|
||||||
|
let lightAmbient = vec3<f32>(0.0, 0.0, 0.0);
|
||||||
|
let lightDiffuse = vec3<f32>(0.0, 0.0, 0.0);
|
||||||
|
let lightSpecular = vec3<f32>(0.0, 0.0, 0.0);
|
||||||
|
|
||||||
|
let eyeVec = normalize(viewerData.eyePosition - input.worldPos);
|
||||||
|
|
||||||
|
for i in 0 -> lightData.lightCount
|
||||||
|
{
|
||||||
|
let light = lightData.lights[i];
|
||||||
|
|
||||||
|
let lightAmbientFactor = light.factor.x;
|
||||||
|
let lightDiffuseFactor = light.factor.y;
|
||||||
|
|
||||||
|
// TODO: Add switch instruction
|
||||||
|
if (light.type == DirectionalLight)
|
||||||
|
{
|
||||||
|
let lightDir = -(light.parameter1.xyz); //< FIXME
|
||||||
|
|
||||||
|
lightAmbient += light.color.rgb * lightAmbientFactor * settings.AmbientColor;
|
||||||
|
|
||||||
|
let lambert = max(dot(input.normal, lightDir), 0.0);
|
||||||
|
|
||||||
|
lightDiffuse += lambert * light.color.rgb * lightDiffuseFactor;
|
||||||
|
|
||||||
|
let reflection = reflect(-lightDir, input.normal);
|
||||||
|
let specFactor = max(dot(reflection, eyeVec), 0.0);
|
||||||
|
specFactor = pow(specFactor, settings.Shininess);
|
||||||
|
|
||||||
|
lightSpecular += specFactor * light.color.rgb;
|
||||||
|
}
|
||||||
|
else if (light.type == PointLight)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (light.type == SpotLight)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lightSpecular *= settings.SpecularColor;
|
||||||
|
|
||||||
|
const if (HasSpecularTexture)
|
||||||
|
lightSpecular *= MaterialSpecularMap.Sample(input.uv).rgb;
|
||||||
|
|
||||||
|
let lightColor = lightAmbient + lightDiffuse + lightSpecular;
|
||||||
|
|
||||||
|
let output: FragOut;
|
||||||
|
output.RenderTarget0 = vec4<f32>(lightColor, 1.0) * diffuseColor;
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
let output: FragOut;
|
||||||
|
output.RenderTarget0 = diffuseColor.w;
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vertex stage
|
||||||
|
struct VertIn
|
||||||
|
{
|
||||||
|
[location(PosLocation)]
|
||||||
|
pos: vec3<f32>,
|
||||||
|
|
||||||
|
[cond(HasVertexColor), location(ColorLocation)]
|
||||||
|
color: vec4<f32>,
|
||||||
|
|
||||||
|
[cond(HasUV), location(UvLocation)]
|
||||||
|
uv: vec2<f32>,
|
||||||
|
|
||||||
|
[cond(HasNormal), location(NormalLocation)]
|
||||||
|
normal: vec3<f32>,
|
||||||
|
|
||||||
|
[cond(Billboard), location(BillboardCenterLocation)]
|
||||||
|
billboardCenter: vec3<f32>,
|
||||||
|
|
||||||
|
[cond(Billboard), location(BillboardSizeRotLocation)]
|
||||||
|
billboardSizeRot: vec4<f32>, //< width,height,sin,cos
|
||||||
|
|
||||||
|
[cond(Billboard), location(BillboardColorLocation)]
|
||||||
|
billboardColor: vec4<f32>
|
||||||
|
}
|
||||||
|
|
||||||
|
struct VertOut
|
||||||
|
{
|
||||||
|
[location(0)] worldPos: vec3<f32>,
|
||||||
|
[location(1), cond(HasUV)] uv: vec2<f32>,
|
||||||
|
[location(2), cond(HasColor)] color: vec4<f32>,
|
||||||
|
[location(3), cond(HasNormal)] normal: vec3<f32>,
|
||||||
|
[builtin(position)] position: vec4<f32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
[entry(vert), cond(Billboard)]
|
||||||
|
fn billboardMain(input: VertIn) -> VertOut
|
||||||
|
{
|
||||||
|
let size = input.billboardSizeRot.xy;
|
||||||
|
let sinCos = input.billboardSizeRot.zw;
|
||||||
|
|
||||||
|
let rotatedPosition = vec2<f32>(
|
||||||
|
input.pos.x * sinCos.y - input.pos.y * sinCos.x,
|
||||||
|
input.pos.y * sinCos.y + input.pos.x * sinCos.x
|
||||||
|
);
|
||||||
|
rotatedPosition *= size;
|
||||||
|
|
||||||
|
let cameraRight = vec3<f32>(viewerData.viewMatrix[0][0], viewerData.viewMatrix[1][0], viewerData.viewMatrix[2][0]);
|
||||||
|
let cameraUp = vec3<f32>(viewerData.viewMatrix[0][1], viewerData.viewMatrix[1][1], viewerData.viewMatrix[2][1]);
|
||||||
|
|
||||||
|
let vertexPos = input.billboardCenter;
|
||||||
|
vertexPos += cameraRight * rotatedPosition.x;
|
||||||
|
vertexPos += cameraUp * rotatedPosition.y;
|
||||||
|
|
||||||
|
let output: VertOut;
|
||||||
|
output.position = viewerData.viewProjMatrix * instanceData.worldMatrix * vec4<f32>(vertexPos, 1.0);
|
||||||
|
|
||||||
|
const if (HasColor)
|
||||||
|
output.color = input.billboardColor;
|
||||||
|
|
||||||
|
const if (HasUV)
|
||||||
|
output.uv = input.pos.xy + vec2<f32>(0.5, 0.5);
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
[entry(vert), cond(!Billboard)]
|
||||||
|
fn main(input: VertIn) -> VertOut
|
||||||
|
{
|
||||||
|
let worldPosition = instanceData.worldMatrix * vec4<f32>(input.pos, 1.0);
|
||||||
|
|
||||||
|
let output: VertOut;
|
||||||
|
output.worldPos = worldPosition.xyz;
|
||||||
|
output.position = viewerData.viewProjMatrix * worldPosition;
|
||||||
|
|
||||||
|
const if (HasColor)
|
||||||
|
output.color = input.color;
|
||||||
|
|
||||||
|
const if (HasNormal)
|
||||||
|
output.normal = input.normal;
|
||||||
|
|
||||||
|
const if (HasUV)
|
||||||
|
output.uv = input.uv;
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
@ -53,7 +53,7 @@ namespace Nz
|
||||||
return std::make_unique<SpriteChainRendererData>();
|
return std::make_unique<SpriteChainRendererData>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpriteChainRenderer::Prepare(const ViewerInstance& viewerInstance, ElementRendererData& rendererData, RenderFrame& currentFrame, const Pointer<const RenderElement>* elements, std::size_t elementCount)
|
void SpriteChainRenderer::Prepare(const ViewerInstance& viewerInstance, ElementRendererData& rendererData, RenderFrame& currentFrame, const RenderStates& renderStates, const Pointer<const RenderElement>* elements, std::size_t elementCount)
|
||||||
{
|
{
|
||||||
Graphics* graphics = Graphics::Instance();
|
Graphics* graphics = Graphics::Instance();
|
||||||
|
|
||||||
|
|
@ -210,6 +210,16 @@ namespace Nz
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (std::size_t bindingIndex = matSettings->GetPredefinedBinding(PredefinedShaderBinding::LightDataUbo); bindingIndex != MaterialSettings::InvalidIndex)
|
||||||
|
{
|
||||||
|
auto& bindingEntry = m_bindingCache.emplace_back();
|
||||||
|
bindingEntry.bindingIndex = bindingIndex;
|
||||||
|
bindingEntry.content = ShaderBinding::UniformBufferBinding{
|
||||||
|
renderStates.lightData.get(),
|
||||||
|
0, renderStates.lightData->GetSize()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
if (std::size_t bindingIndex = matSettings->GetPredefinedBinding(PredefinedShaderBinding::ViewerDataUbo); bindingIndex != MaterialSettings::InvalidIndex)
|
if (std::size_t bindingIndex = matSettings->GetPredefinedBinding(PredefinedShaderBinding::ViewerDataUbo); bindingIndex != MaterialSettings::InvalidIndex)
|
||||||
{
|
{
|
||||||
const auto& viewerBuffer = viewerInstance.GetViewerBuffer();
|
const auto& viewerBuffer = viewerInstance.GetViewerBuffer();
|
||||||
|
|
|
||||||
|
|
@ -12,16 +12,12 @@
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
SubmeshRenderer::SubmeshRenderer()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<ElementRendererData> SubmeshRenderer::InstanciateData()
|
std::unique_ptr<ElementRendererData> SubmeshRenderer::InstanciateData()
|
||||||
{
|
{
|
||||||
return std::make_unique<SubmeshRendererData>();
|
return std::make_unique<SubmeshRendererData>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SubmeshRenderer::Prepare(const ViewerInstance& viewerInstance, ElementRendererData& rendererData, RenderFrame& /*currentFrame*/, const Pointer<const RenderElement>* elements, std::size_t elementCount)
|
void SubmeshRenderer::Prepare(const ViewerInstance& viewerInstance, ElementRendererData& rendererData, RenderFrame& /*currentFrame*/, const RenderStates& renderStates, const Pointer<const RenderElement>* elements, std::size_t elementCount)
|
||||||
{
|
{
|
||||||
Graphics* graphics = Graphics::Instance();
|
Graphics* graphics = Graphics::Instance();
|
||||||
|
|
||||||
|
|
@ -118,6 +114,16 @@ namespace Nz
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (std::size_t bindingIndex = matSettings->GetPredefinedBinding(PredefinedShaderBinding::LightDataUbo); bindingIndex != MaterialSettings::InvalidIndex)
|
||||||
|
{
|
||||||
|
auto& bindingEntry = m_bindingCache.emplace_back();
|
||||||
|
bindingEntry.bindingIndex = bindingIndex;
|
||||||
|
bindingEntry.content = ShaderBinding::UniformBufferBinding{
|
||||||
|
renderStates.lightData.get(),
|
||||||
|
0, renderStates.lightData->GetSize()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
if (std::size_t bindingIndex = matSettings->GetPredefinedBinding(PredefinedShaderBinding::ViewerDataUbo); bindingIndex != MaterialSettings::InvalidIndex)
|
if (std::size_t bindingIndex = matSettings->GetPredefinedBinding(PredefinedShaderBinding::ViewerDataUbo); bindingIndex != MaterialSettings::InvalidIndex)
|
||||||
{
|
{
|
||||||
const auto& viewerBuffer = viewerInstance.GetViewerBuffer();
|
const auto& viewerBuffer = viewerInstance.GetViewerBuffer();
|
||||||
|
|
|
||||||
|
|
@ -156,8 +156,11 @@ namespace Nz
|
||||||
const NodeComponent& entityNode = registry.get<const NodeComponent>(entity);
|
const NodeComponent& entityNode = registry.get<const NodeComponent>(entity);
|
||||||
CameraComponent& entityCamera = registry.get<CameraComponent>(entity);
|
CameraComponent& entityCamera = registry.get<CameraComponent>(entity);
|
||||||
|
|
||||||
|
Vector3f cameraPosition = entityNode.GetPosition(CoordSys::Global);
|
||||||
|
|
||||||
ViewerInstance& viewerInstance = entityCamera.GetViewerInstance();
|
ViewerInstance& viewerInstance = entityCamera.GetViewerInstance();
|
||||||
viewerInstance.UpdateViewMatrix(Nz::Matrix4f::ViewMatrix(entityNode.GetPosition(CoordSys::Global), entityNode.GetRotation(CoordSys::Global)));
|
viewerInstance.UpdateEyePosition(cameraPosition);
|
||||||
|
viewerInstance.UpdateViewMatrix(Nz::Matrix4f::ViewMatrix(cameraPosition, entityNode.GetRotation(CoordSys::Global)));
|
||||||
|
|
||||||
m_pipeline->InvalidateViewer(&entityCamera);
|
m_pipeline->InvalidateViewer(&entityCamera);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,8 @@ namespace Nz
|
||||||
m_projectionMatrix(Matrix4f::Identity()),
|
m_projectionMatrix(Matrix4f::Identity()),
|
||||||
m_viewProjMatrix(Matrix4f::Identity()),
|
m_viewProjMatrix(Matrix4f::Identity()),
|
||||||
m_viewMatrix(Matrix4f::Identity()),
|
m_viewMatrix(Matrix4f::Identity()),
|
||||||
m_targetSize(Vector2f(0.f, 0.f)),
|
m_targetSize(Vector2f::Zero()),
|
||||||
|
m_eyePosition(Vector3f::Zero()),
|
||||||
m_dataInvalided(true)
|
m_dataInvalided(true)
|
||||||
{
|
{
|
||||||
PredefinedViewerData viewerUboOffsets = PredefinedViewerData::GetOffsets();
|
PredefinedViewerData viewerUboOffsets = PredefinedViewerData::GetOffsets();
|
||||||
|
|
@ -37,7 +38,7 @@ namespace Nz
|
||||||
PredefinedViewerData viewerDataOffsets = PredefinedViewerData::GetOffsets();
|
PredefinedViewerData viewerDataOffsets = PredefinedViewerData::GetOffsets();
|
||||||
|
|
||||||
auto& allocation = uploadPool.Allocate(viewerDataOffsets.totalSize);
|
auto& allocation = uploadPool.Allocate(viewerDataOffsets.totalSize);
|
||||||
AccessByOffset<Vector3f&>(allocation.mappedPtr, viewerDataOffsets.eyePositionOffset) = m_viewMatrix.GetTranslation();
|
AccessByOffset<Vector3f&>(allocation.mappedPtr, viewerDataOffsets.eyePositionOffset) = m_eyePosition;
|
||||||
AccessByOffset<Vector2f&>(allocation.mappedPtr, viewerDataOffsets.invTargetSizeOffset) = 1.f / m_targetSize;
|
AccessByOffset<Vector2f&>(allocation.mappedPtr, viewerDataOffsets.invTargetSizeOffset) = 1.f / m_targetSize;
|
||||||
AccessByOffset<Vector2f&>(allocation.mappedPtr, viewerDataOffsets.targetSizeOffset) = m_targetSize;
|
AccessByOffset<Vector2f&>(allocation.mappedPtr, viewerDataOffsets.targetSizeOffset) = m_targetSize;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,9 @@ namespace Nz::ShaderAst
|
||||||
RegisterIntrinsic("length", IntrinsicType::Length);
|
RegisterIntrinsic("length", IntrinsicType::Length);
|
||||||
RegisterIntrinsic("max", IntrinsicType::Max);
|
RegisterIntrinsic("max", IntrinsicType::Max);
|
||||||
RegisterIntrinsic("min", IntrinsicType::Min);
|
RegisterIntrinsic("min", IntrinsicType::Min);
|
||||||
|
RegisterIntrinsic("normalize", IntrinsicType::Normalize);
|
||||||
RegisterIntrinsic("pow", IntrinsicType::Pow);
|
RegisterIntrinsic("pow", IntrinsicType::Pow);
|
||||||
|
RegisterIntrinsic("reflect", IntrinsicType::Reflect);
|
||||||
|
|
||||||
// Collect function name and their types
|
// Collect function name and their types
|
||||||
if (statement.GetType() == NodeType::MultiStatement)
|
if (statement.GetType() == NodeType::MultiStatement)
|
||||||
|
|
@ -152,7 +154,7 @@ namespace Nz::ShaderAst
|
||||||
ExpressionPtr SanitizeVisitor::Clone(AccessIdentifierExpression& node)
|
ExpressionPtr SanitizeVisitor::Clone(AccessIdentifierExpression& node)
|
||||||
{
|
{
|
||||||
if (node.identifiers.empty())
|
if (node.identifiers.empty())
|
||||||
throw AstError{ "accessIdentifierExpression must have at least one identifier" };
|
throw AstError{ "AccessIdentifierExpression must have at least one identifier" };
|
||||||
|
|
||||||
ExpressionPtr indexedExpr = CloneExpression(MandatoryExpr(node.expr));
|
ExpressionPtr indexedExpr = CloneExpression(MandatoryExpr(node.expr));
|
||||||
for (const std::string& identifier : node.identifiers)
|
for (const std::string& identifier : node.identifiers)
|
||||||
|
|
@ -202,7 +204,7 @@ namespace Nz::ShaderAst
|
||||||
else
|
else
|
||||||
accessIdentifierPtr = static_cast<AccessIdentifierExpression*>(indexedExpr.get());
|
accessIdentifierPtr = static_cast<AccessIdentifierExpression*>(indexedExpr.get());
|
||||||
|
|
||||||
accessIdentifierPtr->identifiers.push_back(s->members[fieldIndex].name);
|
accessIdentifierPtr->identifiers.push_back(fieldPtr->name);
|
||||||
accessIdentifierPtr->cachedExpressionType = ResolveType(fieldPtr->type);
|
accessIdentifierPtr->cachedExpressionType = ResolveType(fieldPtr->type);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -602,6 +604,9 @@ namespace Nz::ShaderAst
|
||||||
|
|
||||||
clone->constIndex = RegisterConstant(clone->name, value);
|
clone->constIndex = RegisterConstant(clone->name, value);
|
||||||
|
|
||||||
|
if (m_context->options.removeConstDeclaration)
|
||||||
|
return ShaderBuilder::NoOp();
|
||||||
|
|
||||||
return clone;
|
return clone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1775,6 +1780,7 @@ namespace Nz::ShaderAst
|
||||||
case IntrinsicType::Max:
|
case IntrinsicType::Max:
|
||||||
case IntrinsicType::Min:
|
case IntrinsicType::Min:
|
||||||
case IntrinsicType::Pow:
|
case IntrinsicType::Pow:
|
||||||
|
case IntrinsicType::Reflect:
|
||||||
{
|
{
|
||||||
if (node.parameters.size() != 2)
|
if (node.parameters.size() != 2)
|
||||||
throw AstError { "Expected two parameters" };
|
throw AstError { "Expected two parameters" };
|
||||||
|
|
@ -1803,6 +1809,7 @@ namespace Nz::ShaderAst
|
||||||
}
|
}
|
||||||
|
|
||||||
case IntrinsicType::Length:
|
case IntrinsicType::Length:
|
||||||
|
case IntrinsicType::Normalize:
|
||||||
{
|
{
|
||||||
if (node.parameters.size() != 1)
|
if (node.parameters.size() != 1)
|
||||||
throw AstError{ "Expected only one parameters" };
|
throw AstError{ "Expected only one parameters" };
|
||||||
|
|
@ -1850,12 +1857,23 @@ namespace Nz::ShaderAst
|
||||||
{
|
{
|
||||||
const ExpressionType& type = GetExpressionType(*node.parameters.front());
|
const ExpressionType& type = GetExpressionType(*node.parameters.front());
|
||||||
if (!IsVectorType(type))
|
if (!IsVectorType(type))
|
||||||
throw AstError{ "DotProduct expects vector types" };
|
throw AstError{ "DotProduct expects vector types" }; //< FIXME
|
||||||
|
|
||||||
node.cachedExpressionType = std::get<VectorType>(type).type;
|
node.cachedExpressionType = std::get<VectorType>(type).type;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case IntrinsicType::Normalize:
|
||||||
|
case IntrinsicType::Reflect:
|
||||||
|
{
|
||||||
|
const ExpressionType& type = GetExpressionType(*node.parameters.front());
|
||||||
|
if (!IsVectorType(type))
|
||||||
|
throw AstError{ "DotProduct expects vector types" }; //< FIXME
|
||||||
|
|
||||||
|
node.cachedExpressionType = type;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case IntrinsicType::Max:
|
case IntrinsicType::Max:
|
||||||
case IntrinsicType::Min:
|
case IntrinsicType::Min:
|
||||||
{
|
{
|
||||||
|
|
@ -1998,17 +2016,18 @@ namespace Nz::ShaderAst
|
||||||
case BinaryType::CompGt:
|
case BinaryType::CompGt:
|
||||||
case BinaryType::CompLe:
|
case BinaryType::CompLe:
|
||||||
case BinaryType::CompLt:
|
case BinaryType::CompLt:
|
||||||
{
|
|
||||||
if (leftType == PrimitiveType::Boolean)
|
if (leftType == PrimitiveType::Boolean)
|
||||||
throw AstError{ "this operation is not supported for booleans" };
|
throw AstError{ "this operation is not supported for booleans" };
|
||||||
|
|
||||||
|
[[fallthrough]];
|
||||||
|
case BinaryType::CompEq:
|
||||||
|
case BinaryType::CompNe:
|
||||||
|
{
|
||||||
TypeMustMatch(leftExpr, rightExpr);
|
TypeMustMatch(leftExpr, rightExpr);
|
||||||
return PrimitiveType::Boolean;
|
return PrimitiveType::Boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
case BinaryType::Add:
|
case BinaryType::Add:
|
||||||
case BinaryType::CompEq:
|
|
||||||
case BinaryType::CompNe:
|
|
||||||
case BinaryType::Subtract:
|
case BinaryType::Subtract:
|
||||||
TypeMustMatch(leftExpr, rightExpr);
|
TypeMustMatch(leftExpr, rightExpr);
|
||||||
return leftExprType;
|
return leftExprType;
|
||||||
|
|
|
||||||
|
|
@ -209,6 +209,7 @@ namespace Nz
|
||||||
options.makeVariableNameUnique = true;
|
options.makeVariableNameUnique = true;
|
||||||
options.reduceLoopsToWhile = true;
|
options.reduceLoopsToWhile = true;
|
||||||
options.removeCompoundAssignments = false;
|
options.removeCompoundAssignments = false;
|
||||||
|
options.removeConstDeclaration = true;
|
||||||
options.removeOptionDeclaration = true;
|
options.removeOptionDeclaration = true;
|
||||||
options.removeScalarSwizzling = true;
|
options.removeScalarSwizzling = true;
|
||||||
options.reservedIdentifiers = {
|
options.reservedIdentifiers = {
|
||||||
|
|
@ -489,7 +490,10 @@ namespace Nz
|
||||||
bool first = true;
|
bool first = true;
|
||||||
for (const ShaderAst::StatementPtr& statement : statements)
|
for (const ShaderAst::StatementPtr& statement : statements)
|
||||||
{
|
{
|
||||||
if (!first && statement->GetType() != ShaderAst::NodeType::NoOpStatement)
|
if (statement->GetType() == ShaderAst::NodeType::NoOpStatement)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!first)
|
||||||
AppendLine();
|
AppendLine();
|
||||||
|
|
||||||
statement->Visit(*this);
|
statement->Visit(*this);
|
||||||
|
|
@ -863,10 +867,18 @@ namespace Nz
|
||||||
Append("min");
|
Append("min");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ShaderAst::IntrinsicType::Normalize:
|
||||||
|
Append("normalize");
|
||||||
|
break;
|
||||||
|
|
||||||
case ShaderAst::IntrinsicType::Pow:
|
case ShaderAst::IntrinsicType::Pow:
|
||||||
Append("pow");
|
Append("pow");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ShaderAst::IntrinsicType::Reflect:
|
||||||
|
Append("reflect");
|
||||||
|
break;
|
||||||
|
|
||||||
case ShaderAst::IntrinsicType::SampleTexture:
|
case ShaderAst::IntrinsicType::SampleTexture:
|
||||||
Append("texture");
|
Append("texture");
|
||||||
break;
|
break;
|
||||||
|
|
@ -1118,6 +1130,9 @@ namespace Nz
|
||||||
bool first = true;
|
bool first = true;
|
||||||
for (const auto& member : node.description.members)
|
for (const auto& member : node.description.members)
|
||||||
{
|
{
|
||||||
|
if (member.cond.HasValue() && !member.cond.GetResultingValue())
|
||||||
|
continue;
|
||||||
|
|
||||||
if (!first)
|
if (!first)
|
||||||
AppendLine();
|
AppendLine();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -945,10 +945,18 @@ namespace Nz
|
||||||
Append("min");
|
Append("min");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ShaderAst::IntrinsicType::Normalize:
|
||||||
|
Append("normalize");
|
||||||
|
break;
|
||||||
|
|
||||||
case ShaderAst::IntrinsicType::Pow:
|
case ShaderAst::IntrinsicType::Pow:
|
||||||
Append("pow");
|
Append("pow");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ShaderAst::IntrinsicType::Reflect:
|
||||||
|
Append("reflect");
|
||||||
|
break;
|
||||||
|
|
||||||
case ShaderAst::IntrinsicType::SampleTexture:
|
case ShaderAst::IntrinsicType::SampleTexture:
|
||||||
assert(!node.parameters.empty());
|
assert(!node.parameters.empty());
|
||||||
Visit(node.parameters.front(), true);
|
Visit(node.parameters.front(), true);
|
||||||
|
|
|
||||||
|
|
@ -801,6 +801,25 @@ namespace Nz
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case ShaderAst::IntrinsicType::Normalize:
|
||||||
|
{
|
||||||
|
UInt32 glslInstructionSet = m_writer.GetExtendedInstructionSet("GLSL.std.450");
|
||||||
|
|
||||||
|
const ShaderAst::ExpressionType& vecExprType = GetExpressionType(*node.parameters[0]);
|
||||||
|
assert(IsVectorType(vecExprType));
|
||||||
|
|
||||||
|
const ShaderAst::VectorType& vecType = std::get<ShaderAst::VectorType>(vecExprType);
|
||||||
|
UInt32 typeId = m_writer.GetTypeId(vecType);
|
||||||
|
|
||||||
|
UInt32 vec = EvaluateExpression(node.parameters[0]);
|
||||||
|
|
||||||
|
UInt32 resultId = m_writer.AllocateResultId();
|
||||||
|
|
||||||
|
m_currentBlock->Append(SpirvOp::OpExtInst, typeId, resultId, glslInstructionSet, GLSLstd450Normalize, vec);
|
||||||
|
PushResultId(resultId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case ShaderAst::IntrinsicType::Pow:
|
case ShaderAst::IntrinsicType::Pow:
|
||||||
{
|
{
|
||||||
UInt32 glslInstructionSet = m_writer.GetExtendedInstructionSet("GLSL.std.450");
|
UInt32 glslInstructionSet = m_writer.GetExtendedInstructionSet("GLSL.std.450");
|
||||||
|
|
@ -818,6 +837,23 @@ namespace Nz
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case ShaderAst::IntrinsicType::Reflect:
|
||||||
|
{
|
||||||
|
UInt32 glslInstructionSet = m_writer.GetExtendedInstructionSet("GLSL.std.450");
|
||||||
|
|
||||||
|
const ShaderAst::ExpressionType& parameterType = GetExpressionType(*node.parameters[0]);
|
||||||
|
assert(IsVectorType(parameterType));
|
||||||
|
UInt32 typeId = m_writer.GetTypeId(parameterType);
|
||||||
|
|
||||||
|
UInt32 firstParam = EvaluateExpression(node.parameters[0]);
|
||||||
|
UInt32 secondParam = EvaluateExpression(node.parameters[1]);
|
||||||
|
UInt32 resultId = m_writer.AllocateResultId();
|
||||||
|
|
||||||
|
m_currentBlock->Append(SpirvOp::OpExtInst, typeId, resultId, glslInstructionSet, GLSLstd450Reflect, firstParam, secondParam);
|
||||||
|
PushResultId(resultId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case ShaderAst::IntrinsicType::SampleTexture:
|
case ShaderAst::IntrinsicType::SampleTexture:
|
||||||
{
|
{
|
||||||
UInt32 typeId = m_writer.GetTypeId(ShaderAst::VectorType{4, ShaderAst::PrimitiveType::Float32});
|
UInt32 typeId = m_writer.GetTypeId(ShaderAst::VectorType{4, ShaderAst::PrimitiveType::Float32});
|
||||||
|
|
|
||||||
|
|
@ -356,7 +356,9 @@ namespace Nz
|
||||||
case ShaderAst::IntrinsicType::Length:
|
case ShaderAst::IntrinsicType::Length:
|
||||||
case ShaderAst::IntrinsicType::Max:
|
case ShaderAst::IntrinsicType::Max:
|
||||||
case ShaderAst::IntrinsicType::Min:
|
case ShaderAst::IntrinsicType::Min:
|
||||||
|
case ShaderAst::IntrinsicType::Normalize:
|
||||||
case ShaderAst::IntrinsicType::Pow:
|
case ShaderAst::IntrinsicType::Pow:
|
||||||
|
case ShaderAst::IntrinsicType::Reflect:
|
||||||
extInsts.emplace("GLSL.std.450");
|
extInsts.emplace("GLSL.std.450");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue