WIP
This commit is contained in:
72
include/Nazara/Graphics/BasicMaterial.hpp
Normal file
72
include/Nazara/Graphics/BasicMaterial.hpp
Normal file
@@ -0,0 +1,72 @@
|
||||
// Copyright (C) 2017 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Graphics module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_BASIC_MATERIAL_HPP
|
||||
#define NAZARA_BASIC_MATERIAL_HPP
|
||||
|
||||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <Nazara/Graphics/Material.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class NAZARA_GRAPHICS_API BasicMaterial
|
||||
{
|
||||
friend class MaterialPipeline;
|
||||
|
||||
public:
|
||||
BasicMaterial(Material* material);
|
||||
|
||||
inline const TextureRef& GetAlphaMap() const;
|
||||
float GetAlphaThreshold() const;
|
||||
Color GetDiffuseColor() const;
|
||||
inline const TextureRef& GetDiffuseMap() const;
|
||||
|
||||
inline bool HasAlphaMap() const;
|
||||
inline bool HasAlphaThreshold() const;
|
||||
inline bool HasDiffuseColor() const;
|
||||
inline bool HasDiffuseMap() const;
|
||||
|
||||
inline bool SetAlphaMap(const String& textureName);
|
||||
inline void SetAlphaMap(TextureRef alphaMap);
|
||||
void SetAlphaThreshold(float alphaThreshold);
|
||||
void SetDiffuseColor(const Color& diffuse);
|
||||
inline bool SetDiffuseMap(const String& textureName);
|
||||
inline void SetDiffuseMap(TextureRef diffuseMap);
|
||||
|
||||
static const std::shared_ptr<MaterialSettings>& GetSettings();
|
||||
|
||||
private:
|
||||
struct UniformOffsets
|
||||
{
|
||||
std::size_t alphaThreshold;
|
||||
std::size_t diffuseColor;
|
||||
};
|
||||
|
||||
struct TextureIndexes
|
||||
{
|
||||
std::size_t alpha;
|
||||
std::size_t diffuse;
|
||||
};
|
||||
|
||||
static bool Initialize();
|
||||
static void Uninitialize();
|
||||
|
||||
MaterialRef m_material;
|
||||
std::size_t m_uniformBlockIndex;
|
||||
TextureIndexes m_textureIndexes;
|
||||
UniformOffsets m_uniformOffsets;
|
||||
|
||||
static std::shared_ptr<MaterialSettings> s_materialSettings;
|
||||
static std::size_t s_uniformBlockIndex;
|
||||
static RenderPipelineLayoutRef s_renderPipelineLayout;
|
||||
static TextureIndexes s_textureIndexes;
|
||||
static UniformOffsets s_uniformOffsets;
|
||||
};
|
||||
}
|
||||
|
||||
#include <Nazara/Graphics/BasicMaterial.inl>
|
||||
|
||||
#endif // NAZARA_BASIC_MATERIAL_HPP
|
||||
91
include/Nazara/Graphics/BasicMaterial.inl
Normal file
91
include/Nazara/Graphics/BasicMaterial.inl
Normal file
@@ -0,0 +1,91 @@
|
||||
// Copyright (C) 2017 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Graphics module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Graphics/BasicMaterial.hpp>
|
||||
#include <Nazara/Core/ErrorFlags.hpp>
|
||||
#include <memory>
|
||||
#include <Nazara/Graphics/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
inline const TextureRef& BasicMaterial::GetAlphaMap() const
|
||||
{
|
||||
NazaraAssert(HasAlphaMap(), "Material has no alpha map slot");
|
||||
return m_material->GetTexture(m_textureIndexes.alpha);
|
||||
}
|
||||
|
||||
inline const TextureRef& BasicMaterial::GetDiffuseMap() const
|
||||
{
|
||||
NazaraAssert(HasDiffuseMap(), "Material has no alpha map slot");
|
||||
return m_material->GetTexture(m_textureIndexes.diffuse);
|
||||
}
|
||||
|
||||
inline bool BasicMaterial::HasAlphaMap() const
|
||||
{
|
||||
return m_textureIndexes.alpha != MaterialSettings::InvalidIndex;
|
||||
}
|
||||
|
||||
inline bool BasicMaterial::HasAlphaThreshold() const
|
||||
{
|
||||
return m_uniformOffsets.alphaThreshold != MaterialSettings::InvalidIndex;
|
||||
}
|
||||
|
||||
inline bool BasicMaterial::HasDiffuseColor() const
|
||||
{
|
||||
return m_uniformOffsets.diffuseColor != MaterialSettings::InvalidIndex;
|
||||
}
|
||||
|
||||
inline bool BasicMaterial::HasDiffuseMap() const
|
||||
{
|
||||
return m_textureIndexes.diffuse != MaterialSettings::InvalidIndex;
|
||||
}
|
||||
|
||||
inline bool BasicMaterial::SetAlphaMap(const String& textureName)
|
||||
{
|
||||
TextureRef texture = TextureLibrary::Query(textureName);
|
||||
if (!texture)
|
||||
{
|
||||
texture = TextureManager::Get(textureName);
|
||||
if (!texture)
|
||||
{
|
||||
NazaraError("Failed to get alpha map \"" + textureName + "\"");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
SetAlphaMap(std::move(texture));
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void BasicMaterial::SetAlphaMap(TextureRef alphaMap)
|
||||
{
|
||||
NazaraAssert(HasAlphaMap(), "Material has no alpha map slot");
|
||||
m_material->SetTexture(m_textureIndexes.alpha, std::move(alphaMap));
|
||||
}
|
||||
|
||||
inline bool BasicMaterial::SetDiffuseMap(const String& textureName)
|
||||
{
|
||||
TextureRef texture = TextureLibrary::Query(textureName);
|
||||
if (!texture)
|
||||
{
|
||||
texture = TextureManager::Get(textureName);
|
||||
if (!texture)
|
||||
{
|
||||
NazaraError("Failed to get diffuse map \"" + textureName + "\"");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
SetDiffuseMap(std::move(texture));
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void BasicMaterial::SetDiffuseMap(TextureRef diffuseMap)
|
||||
{
|
||||
NazaraAssert(HasDiffuseMap(), "Material has no diffuse map slot");
|
||||
m_material->SetTexture(m_textureIndexes.diffuse, std::move(diffuseMap));
|
||||
}
|
||||
}
|
||||
|
||||
#include <Nazara/Graphics/DebugOff.hpp>
|
||||
215
include/Nazara/Graphics/CullingList.hpp
Normal file
215
include/Nazara/Graphics/CullingList.hpp
Normal file
@@ -0,0 +1,215 @@
|
||||
// Copyright (C) 2017 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Graphics module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_CULLINGLIST_HPP
|
||||
#define NAZARA_CULLINGLIST_HPP
|
||||
|
||||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <Nazara/Core/Signal.hpp>
|
||||
#include <Nazara/Graphics/Config.hpp>
|
||||
#include <Nazara/Graphics/Enums.hpp>
|
||||
#include <Nazara/Math/BoundingVolume.hpp>
|
||||
#include <Nazara/Math/Frustum.hpp>
|
||||
#include <Nazara/Math/Sphere.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
template<typename T>
|
||||
class CullingList
|
||||
{
|
||||
public:
|
||||
template<CullTest> class Entry;
|
||||
class BoxEntry;
|
||||
class NoTestEntry;
|
||||
class SphereEntry;
|
||||
class VolumeEntry;
|
||||
|
||||
template<CullTest> friend class Entry;
|
||||
friend BoxEntry;
|
||||
friend NoTestEntry;
|
||||
friend SphereEntry;
|
||||
friend VolumeEntry;
|
||||
|
||||
using ResultContainer = std::vector<const T*>;
|
||||
|
||||
CullingList() = default;
|
||||
CullingList(const CullingList& renderable) = delete;
|
||||
CullingList(CullingList&& renderable) = delete;
|
||||
~CullingList();
|
||||
|
||||
std::size_t Cull(const Frustumf& frustum, bool* forceInvalidation = nullptr);
|
||||
|
||||
std::size_t FillWithAllEntries(bool* forceInvalidation = nullptr);
|
||||
|
||||
const ResultContainer& GetFullyVisibleResults() const;
|
||||
const ResultContainer& GetPartiallyVisibleResults() const;
|
||||
|
||||
BoxEntry RegisterBoxTest(const T* renderable);
|
||||
NoTestEntry RegisterNoTest(const T* renderable);
|
||||
SphereEntry RegisterSphereTest(const T* renderable);
|
||||
VolumeEntry RegisterVolumeTest(const T* renderable);
|
||||
|
||||
CullingList& operator=(const CullingList& renderable) = delete;
|
||||
CullingList& operator=(CullingList&& renderable) = delete;
|
||||
|
||||
NazaraSignal(OnCullingListRelease, CullingList* /*cullingList*/);
|
||||
|
||||
private:
|
||||
inline void NotifyBoxUpdate(std::size_t index, const Boxf& boundingVolume);
|
||||
inline void NotifyForceInvalidation(CullTest type, std::size_t index);
|
||||
inline void NotifyMovement(CullTest type, std::size_t index, void* oldPtr, void* newPtr);
|
||||
inline void NotifyRelease(CullTest type, std::size_t index);
|
||||
inline void NotifySphereUpdate(std::size_t index, const Spheref& sphere);
|
||||
inline void NotifyVolumeUpdate(std::size_t index, const BoundingVolumef& boundingVolume);
|
||||
|
||||
struct BoxVisibilityEntry
|
||||
{
|
||||
Boxf box;
|
||||
BoxEntry* entry;
|
||||
const T* renderable;
|
||||
bool forceInvalidation;
|
||||
};
|
||||
|
||||
struct NoTestVisibilityEntry
|
||||
{
|
||||
NoTestEntry* entry;
|
||||
const T* renderable;
|
||||
bool forceInvalidation;
|
||||
};
|
||||
|
||||
struct SphereVisibilityEntry
|
||||
{
|
||||
Spheref sphere;
|
||||
SphereEntry* entry;
|
||||
const T* renderable;
|
||||
bool forceInvalidation;
|
||||
};
|
||||
|
||||
struct VolumeVisibilityEntry
|
||||
{
|
||||
BoundingVolumef volume;
|
||||
VolumeEntry* entry;
|
||||
const T* renderable;
|
||||
bool forceInvalidation;
|
||||
};
|
||||
|
||||
std::vector<BoxVisibilityEntry> m_boxTestList;
|
||||
std::vector<NoTestVisibilityEntry> m_noTestList;
|
||||
std::vector<SphereVisibilityEntry> m_sphereTestList;
|
||||
std::vector<VolumeVisibilityEntry> m_volumeTestList;
|
||||
ResultContainer m_fullyVisibleResults;
|
||||
ResultContainer m_partiallyVisibleResults;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
template<CullTest Type>
|
||||
class CullingList<T>::Entry
|
||||
{
|
||||
public:
|
||||
Entry();
|
||||
Entry(const Entry&) = delete;
|
||||
Entry(Entry&& entry);
|
||||
~Entry();
|
||||
|
||||
void ForceInvalidation();
|
||||
|
||||
CullingList* GetParent() const;
|
||||
|
||||
void UpdateIndex(std::size_t index);
|
||||
|
||||
Entry& operator=(const Entry&) = delete;
|
||||
Entry& operator=(Entry&& entry);
|
||||
|
||||
protected:
|
||||
Entry(CullingList* parent, std::size_t index);
|
||||
|
||||
std::size_t m_index;
|
||||
CullingList* m_parent;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class CullingList<T>::BoxEntry : public CullingList<T>::template Entry<CullTest::Box>
|
||||
{
|
||||
friend CullingList;
|
||||
|
||||
using ParentType = Entry<CullTest::Box>;
|
||||
|
||||
public:
|
||||
BoxEntry();
|
||||
BoxEntry(BoxEntry&&) = default;
|
||||
~BoxEntry() = default;
|
||||
|
||||
void UpdateBox(const Boxf& box);
|
||||
|
||||
BoxEntry& operator=(BoxEntry&&) = default;
|
||||
|
||||
private:
|
||||
BoxEntry(CullingList* parent, std::size_t index);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class CullingList<T>::NoTestEntry : public CullingList<T>::template Entry<CullTest::NoTest>
|
||||
{
|
||||
friend CullingList;
|
||||
|
||||
using ParentType = Entry<CullTest::NoTest>;
|
||||
|
||||
public:
|
||||
NoTestEntry();
|
||||
NoTestEntry(NoTestEntry&&) = default;
|
||||
~NoTestEntry() = default;
|
||||
|
||||
NoTestEntry& operator=(NoTestEntry&&) = default;
|
||||
|
||||
private:
|
||||
NoTestEntry(CullingList* parent, std::size_t index);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class CullingList<T>::SphereEntry : public CullingList<T>::template Entry<CullTest::Sphere>
|
||||
{
|
||||
friend CullingList;
|
||||
|
||||
using ParentType = Entry<CullTest::Sphere>;
|
||||
|
||||
public:
|
||||
SphereEntry();
|
||||
SphereEntry(SphereEntry&&) = default;
|
||||
~SphereEntry() = default;
|
||||
|
||||
void UpdateSphere(const Spheref& sphere);
|
||||
|
||||
SphereEntry& operator=(SphereEntry&&) = default;
|
||||
|
||||
private:
|
||||
SphereEntry(CullingList* parent, std::size_t index);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class CullingList<T>::VolumeEntry : public CullingList<T>::template Entry<CullTest::Volume>
|
||||
{
|
||||
friend CullingList;
|
||||
|
||||
using ParentType = Entry<CullTest::Volume>;
|
||||
|
||||
public:
|
||||
VolumeEntry();
|
||||
VolumeEntry(VolumeEntry&&) = default;
|
||||
~VolumeEntry() = default;
|
||||
|
||||
void UpdateVolume(const BoundingVolumef& sphere);
|
||||
|
||||
VolumeEntry& operator=(VolumeEntry&&) = default;
|
||||
|
||||
private:
|
||||
VolumeEntry(CullingList* parent, std::size_t index);
|
||||
};
|
||||
}
|
||||
|
||||
#include <Nazara/Graphics/CullingList.inl>
|
||||
|
||||
#endif // NAZARA_CULLINGLIST_HPP
|
||||
498
include/Nazara/Graphics/CullingList.inl
Normal file
498
include/Nazara/Graphics/CullingList.inl
Normal file
@@ -0,0 +1,498 @@
|
||||
// Copyright (C) 2017 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Graphics module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Graphics/CullingList.hpp>
|
||||
#include <Nazara/Graphics/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
template<typename T>
|
||||
CullingList<T>::~CullingList()
|
||||
{
|
||||
OnCullingListRelease(this);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::size_t CullingList<T>::Cull(const Frustumf& frustum, bool* forceInvalidation)
|
||||
{
|
||||
m_fullyVisibleResults.clear();
|
||||
m_partiallyVisibleResults.clear();
|
||||
|
||||
bool forcedInvalidation = false;
|
||||
|
||||
std::size_t fullyVisibleHash = 5U;
|
||||
std::size_t partiallyVisibleHash = 5U;
|
||||
|
||||
auto CombineHash = [](std::size_t currentHash, std::size_t newHash)
|
||||
{
|
||||
return currentHash * 23 + newHash;
|
||||
};
|
||||
|
||||
for (BoxVisibilityEntry& entry : m_boxTestList)
|
||||
{
|
||||
switch (frustum.Intersect(entry.box))
|
||||
{
|
||||
case IntersectionSide_Inside:
|
||||
m_fullyVisibleResults.push_back(entry.renderable);
|
||||
fullyVisibleHash = CombineHash(fullyVisibleHash, std::hash<const T*>()(entry.renderable));
|
||||
|
||||
forcedInvalidation = forcedInvalidation | entry.forceInvalidation;
|
||||
entry.forceInvalidation = false;
|
||||
break;
|
||||
|
||||
case IntersectionSide_Intersecting:
|
||||
m_partiallyVisibleResults.push_back(entry.renderable);
|
||||
partiallyVisibleHash = CombineHash(partiallyVisibleHash, std::hash<const T*>()(entry.renderable));
|
||||
|
||||
forcedInvalidation = forcedInvalidation | entry.forceInvalidation;
|
||||
entry.forceInvalidation = false;
|
||||
break;
|
||||
|
||||
case IntersectionSide_Outside:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (NoTestVisibilityEntry& entry : m_noTestList)
|
||||
{
|
||||
m_fullyVisibleResults.push_back(entry.renderable);
|
||||
CombineHash(fullyVisibleHash, std::hash<const T*>()(entry.renderable));
|
||||
|
||||
if (entry.forceInvalidation)
|
||||
{
|
||||
forcedInvalidation = true;
|
||||
entry.forceInvalidation = false;
|
||||
}
|
||||
}
|
||||
|
||||
for (SphereVisibilityEntry& entry : m_sphereTestList)
|
||||
{
|
||||
switch (frustum.Intersect(entry.sphere))
|
||||
{
|
||||
case IntersectionSide_Inside:
|
||||
m_fullyVisibleResults.push_back(entry.renderable);
|
||||
fullyVisibleHash = CombineHash(fullyVisibleHash, std::hash<const T*>()(entry.renderable));
|
||||
|
||||
forcedInvalidation = forcedInvalidation | entry.forceInvalidation;
|
||||
entry.forceInvalidation = false;
|
||||
break;
|
||||
|
||||
case IntersectionSide_Intersecting:
|
||||
m_partiallyVisibleResults.push_back(entry.renderable);
|
||||
partiallyVisibleHash = CombineHash(partiallyVisibleHash, std::hash<const T*>()(entry.renderable));
|
||||
|
||||
forcedInvalidation = forcedInvalidation | entry.forceInvalidation;
|
||||
entry.forceInvalidation = false;
|
||||
break;
|
||||
|
||||
case IntersectionSide_Outside:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (VolumeVisibilityEntry& entry : m_volumeTestList)
|
||||
{
|
||||
switch (frustum.Intersect(entry.volume))
|
||||
{
|
||||
case IntersectionSide_Inside:
|
||||
m_fullyVisibleResults.push_back(entry.renderable);
|
||||
fullyVisibleHash = CombineHash(fullyVisibleHash, std::hash<const T*>()(entry.renderable));
|
||||
|
||||
forcedInvalidation = forcedInvalidation | entry.forceInvalidation;
|
||||
entry.forceInvalidation = false;
|
||||
break;
|
||||
|
||||
case IntersectionSide_Intersecting:
|
||||
m_partiallyVisibleResults.push_back(entry.renderable);
|
||||
partiallyVisibleHash = CombineHash(partiallyVisibleHash, std::hash<const T*>()(entry.renderable));
|
||||
|
||||
forcedInvalidation = forcedInvalidation | entry.forceInvalidation;
|
||||
entry.forceInvalidation = false;
|
||||
break;
|
||||
|
||||
case IntersectionSide_Outside:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (forceInvalidation)
|
||||
*forceInvalidation = forcedInvalidation;
|
||||
|
||||
return 5 + partiallyVisibleHash * 17 + fullyVisibleHash;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::size_t CullingList<T>::FillWithAllEntries(bool* forceInvalidation)
|
||||
{
|
||||
m_fullyVisibleResults.clear();
|
||||
m_partiallyVisibleResults.clear();
|
||||
|
||||
bool forcedInvalidation = false;
|
||||
|
||||
std::size_t visibleHash = 5U;
|
||||
|
||||
auto FillWithList = [&](auto& testList)
|
||||
{
|
||||
for (auto& entry : testList)
|
||||
{
|
||||
m_fullyVisibleResults.push_back(entry.renderable);
|
||||
visibleHash = visibleHash * 23 + std::hash<const T*>()(entry.renderable);
|
||||
|
||||
forcedInvalidation = forcedInvalidation | entry.forceInvalidation;
|
||||
entry.forceInvalidation = false;
|
||||
}
|
||||
};
|
||||
|
||||
FillWithList(m_boxTestList);
|
||||
FillWithList(m_noTestList);
|
||||
FillWithList(m_sphereTestList);
|
||||
FillWithList(m_volumeTestList);
|
||||
|
||||
if (forceInvalidation)
|
||||
*forceInvalidation = forcedInvalidation;
|
||||
|
||||
return visibleHash;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
auto CullingList<T>::GetFullyVisibleResults() const -> const ResultContainer&
|
||||
{
|
||||
return m_fullyVisibleResults;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
auto CullingList<T>::GetPartiallyVisibleResults() const -> const ResultContainer&
|
||||
{
|
||||
return m_partiallyVisibleResults;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
auto CullingList<T>::RegisterBoxTest(const T* renderable) -> BoxEntry
|
||||
{
|
||||
BoxEntry newEntry(this, m_boxTestList.size());
|
||||
m_boxTestList.emplace_back(BoxVisibilityEntry{ Nz::Boxf(), &newEntry, renderable, false }); //< Address of entry will be updated when moving
|
||||
|
||||
return newEntry;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
auto CullingList<T>::RegisterNoTest(const T* renderable) -> NoTestEntry
|
||||
{
|
||||
NoTestEntry newEntry(this, m_volumeTestList.size());
|
||||
m_noTestList.emplace_back(NoTestVisibilityEntry{&newEntry, renderable, false}); //< Address of entry will be updated when moving
|
||||
|
||||
return newEntry;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
auto CullingList<T>::RegisterSphereTest(const T* renderable) -> SphereEntry
|
||||
{
|
||||
SphereEntry newEntry(this, m_sphereTestList.size());
|
||||
m_sphereTestList.emplace_back(SphereVisibilityEntry{Nz::Spheref(), &newEntry, renderable, false}); //< Address of entry will be updated when moving
|
||||
|
||||
return newEntry;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
auto CullingList<T>::RegisterVolumeTest(const T* renderable) -> VolumeEntry
|
||||
{
|
||||
VolumeEntry newEntry(this, m_volumeTestList.size());
|
||||
m_volumeTestList.emplace_back(VolumeVisibilityEntry{Nz::BoundingVolumef(), &newEntry, renderable, false}); //< Address of entry will be updated when moving
|
||||
|
||||
return newEntry;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline void CullingList<T>::NotifyBoxUpdate(std::size_t index, const Boxf& box)
|
||||
{
|
||||
m_boxTestList[index].box = box;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void CullingList<T>::NotifyForceInvalidation(CullTest type, std::size_t index)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case CullTest::Box:
|
||||
{
|
||||
m_boxTestList[index].forceInvalidation = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case CullTest::NoTest:
|
||||
{
|
||||
m_noTestList[index].forceInvalidation = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case CullTest::Sphere:
|
||||
{
|
||||
m_sphereTestList[index].forceInvalidation = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case CullTest::Volume:
|
||||
{
|
||||
m_volumeTestList[index].forceInvalidation = true;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
NazaraInternalError("Unhandled culltype");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void CullingList<T>::NotifyMovement(CullTest type, std::size_t index, void* oldPtr, void* newPtr)
|
||||
{
|
||||
NazaraUnused(oldPtr);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case CullTest::Box:
|
||||
{
|
||||
BoxVisibilityEntry& entry = m_boxTestList[index];
|
||||
NazaraAssert(entry.entry == oldPtr, "Invalid box entry");
|
||||
|
||||
entry.entry = static_cast<BoxEntry*>(newPtr);
|
||||
break;
|
||||
}
|
||||
|
||||
case CullTest::NoTest:
|
||||
{
|
||||
NoTestVisibilityEntry& entry = m_noTestList[index];
|
||||
NazaraAssert(entry.entry == oldPtr, "Invalid entry");
|
||||
|
||||
entry.entry = static_cast<NoTestEntry*>(newPtr);
|
||||
break;
|
||||
}
|
||||
|
||||
case CullTest::Sphere:
|
||||
{
|
||||
SphereVisibilityEntry& entry = m_sphereTestList[index];
|
||||
NazaraAssert(entry.entry == oldPtr, "Invalid sphere entry");
|
||||
|
||||
entry.entry = static_cast<SphereEntry*>(newPtr);
|
||||
break;
|
||||
}
|
||||
|
||||
case CullTest::Volume:
|
||||
{
|
||||
VolumeVisibilityEntry& entry = m_volumeTestList[index];
|
||||
NazaraAssert(entry.entry == oldPtr, "Invalid volume entry");
|
||||
|
||||
entry.entry = static_cast<VolumeEntry*>(newPtr);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
NazaraInternalError("Unhandled culltype");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void CullingList<T>::NotifyRelease(CullTest type, std::size_t index)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case CullTest::Box:
|
||||
{
|
||||
m_boxTestList[index] = std::move(m_boxTestList.back());
|
||||
m_boxTestList[index].entry->UpdateIndex(index);
|
||||
m_boxTestList.pop_back();
|
||||
break;
|
||||
}
|
||||
|
||||
case CullTest::NoTest:
|
||||
{
|
||||
m_noTestList[index] = std::move(m_noTestList.back());
|
||||
m_noTestList[index].entry->UpdateIndex(index);
|
||||
m_noTestList.pop_back();
|
||||
break;
|
||||
}
|
||||
|
||||
case CullTest::Sphere:
|
||||
{
|
||||
m_sphereTestList[index] = std::move(m_sphereTestList.back());
|
||||
m_sphereTestList[index].entry->UpdateIndex(index);
|
||||
m_sphereTestList.pop_back();
|
||||
break;
|
||||
}
|
||||
|
||||
case CullTest::Volume:
|
||||
{
|
||||
m_volumeTestList[index] = std::move(m_volumeTestList.back());
|
||||
m_volumeTestList[index].entry->UpdateIndex(index);
|
||||
m_volumeTestList.pop_back();
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
NazaraInternalError("Unhandled culltype");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void CullingList<T>::NotifySphereUpdate(std::size_t index, const Spheref& sphere)
|
||||
{
|
||||
m_sphereTestList[index].sphere = sphere;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void CullingList<T>::NotifyVolumeUpdate(std::size_t index, const BoundingVolumef& boundingVolume)
|
||||
{
|
||||
m_volumeTestList[index].volume = boundingVolume;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename T>
|
||||
template<CullTest Type>
|
||||
CullingList<T>::Entry<Type>::Entry() :
|
||||
m_parent(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<CullTest Type>
|
||||
CullingList<T>::Entry<Type>::Entry(CullingList* parent, std::size_t index) :
|
||||
m_index(index),
|
||||
m_parent(parent)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<CullTest Type>
|
||||
CullingList<T>::Entry<Type>::Entry(Entry&& entry) :
|
||||
m_index(entry.m_index),
|
||||
m_parent(entry.m_parent)
|
||||
{
|
||||
if (m_parent)
|
||||
m_parent->NotifyMovement(Type, m_index, &entry, this);
|
||||
|
||||
entry.m_parent = nullptr;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<CullTest Type>
|
||||
CullingList<T>::Entry<Type>::~Entry()
|
||||
{
|
||||
if (m_parent)
|
||||
m_parent->NotifyRelease(Type, m_index);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<CullTest Type>
|
||||
void CullingList<T>::Entry<Type>::ForceInvalidation()
|
||||
{
|
||||
m_parent->NotifyForceInvalidation(Type, m_index);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<CullTest Type>
|
||||
CullingList<T>* CullingList<T>::Entry<Type>::GetParent() const
|
||||
{
|
||||
return m_parent;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<CullTest Type>
|
||||
void CullingList<T>::Entry<Type>::UpdateIndex(std::size_t index)
|
||||
{
|
||||
m_index = index;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<CullTest Type>
|
||||
typename CullingList<T>::template Entry<Type>& CullingList<T>::Entry<Type>::operator=(Entry&& entry)
|
||||
{
|
||||
m_index = entry.m_index;
|
||||
m_parent = entry.m_parent;
|
||||
if (m_parent)
|
||||
m_parent->NotifyMovement(Type, m_index, &entry, this);
|
||||
|
||||
entry.m_parent = nullptr;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename T>
|
||||
CullingList<T>::BoxEntry::BoxEntry() :
|
||||
ParentType()
|
||||
{
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
CullingList<T>::BoxEntry::BoxEntry(CullingList* parent, std::size_t index) :
|
||||
ParentType(parent, index)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void CullingList<T>::BoxEntry::UpdateBox(const Boxf& box)
|
||||
{
|
||||
this->m_parent->NotifyBoxUpdate(this->m_index, box);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename T>
|
||||
CullingList<T>::NoTestEntry::NoTestEntry() :
|
||||
ParentType()
|
||||
{
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
CullingList<T>::NoTestEntry::NoTestEntry(CullingList* parent, std::size_t index) :
|
||||
ParentType(parent, index)
|
||||
{
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename T>
|
||||
CullingList<T>::SphereEntry::SphereEntry() :
|
||||
ParentType()
|
||||
{
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
CullingList<T>::SphereEntry::SphereEntry(CullingList* parent, std::size_t index) :
|
||||
ParentType(parent, index)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void CullingList<T>::SphereEntry::UpdateSphere(const Spheref& sphere)
|
||||
{
|
||||
this->m_parent->NotifySphereUpdate(this->m_index, sphere);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename T>
|
||||
CullingList<T>::VolumeEntry::VolumeEntry() :
|
||||
ParentType()
|
||||
{
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
CullingList<T>::VolumeEntry::VolumeEntry(CullingList* parent, std::size_t index) :
|
||||
ParentType(parent, index)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void CullingList<T>::VolumeEntry::UpdateVolume(const BoundingVolumef& volume)
|
||||
{
|
||||
this->m_parent->NotifyVolumeUpdate(this->m_index, volume);
|
||||
}
|
||||
}
|
||||
|
||||
#include <Nazara/Graphics/DebugOff.hpp>
|
||||
@@ -9,6 +9,24 @@
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
enum class CullTest
|
||||
{
|
||||
Box,
|
||||
NoTest,
|
||||
Sphere,
|
||||
Volume
|
||||
};
|
||||
|
||||
enum PredefinedShaderBinding
|
||||
{
|
||||
PredefinedShaderBinding_TexOverlay,
|
||||
PredefinedShaderBinding_UboInstanceData,
|
||||
PredefinedShaderBinding_UboLighData,
|
||||
PredefinedShaderBinding_UboViewerData,
|
||||
|
||||
PredefinedShaderBinding_Max = PredefinedShaderBinding_UboViewerData
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // NAZARA_ENUMS_GRAPHICS_HPP
|
||||
|
||||
@@ -10,9 +10,12 @@
|
||||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <Nazara/Graphics/Config.hpp>
|
||||
#include <Nazara/Renderer/Renderer.hpp>
|
||||
#include <Nazara/Renderer/RenderDevice.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class RenderDevice;
|
||||
|
||||
class NAZARA_GRAPHICS_API Graphics : public ModuleBase<Graphics>
|
||||
{
|
||||
friend ModuleBase;
|
||||
@@ -20,14 +23,25 @@ namespace Nz
|
||||
public:
|
||||
using Dependencies = TypeList<Renderer>;
|
||||
|
||||
struct Config {};
|
||||
struct Config;
|
||||
|
||||
Graphics(Config /*config*/);
|
||||
~Graphics();
|
||||
Graphics(Config config);
|
||||
~Graphics() = default;
|
||||
|
||||
inline RenderDevice& GetRenderDevice();
|
||||
|
||||
struct Config
|
||||
{
|
||||
bool useDedicatedRenderDevice = true;
|
||||
};
|
||||
|
||||
private:
|
||||
std::shared_ptr<RenderDevice> m_renderDevice;
|
||||
|
||||
static Graphics* s_instance;
|
||||
};
|
||||
}
|
||||
|
||||
#include <Nazara/Graphics/Graphics.inl>
|
||||
|
||||
#endif
|
||||
|
||||
16
include/Nazara/Graphics/Graphics.inl
Normal file
16
include/Nazara/Graphics/Graphics.inl
Normal file
@@ -0,0 +1,16 @@
|
||||
// Copyright (C) 2017 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Graphics module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Graphics/Graphics.hpp>
|
||||
#include <Nazara/Graphics/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
inline RenderDevice& Graphics::GetRenderDevice()
|
||||
{
|
||||
return *m_renderDevice;
|
||||
}
|
||||
}
|
||||
|
||||
#include <Nazara/Graphics/DebugOff.hpp>
|
||||
150
include/Nazara/Graphics/Material.hpp
Normal file
150
include/Nazara/Graphics/Material.hpp
Normal file
@@ -0,0 +1,150 @@
|
||||
// Copyright (C) 2017 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Graphics module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_BASE_MATERIAL_HPP
|
||||
#define NAZARA_BASE_MATERIAL_HPP
|
||||
|
||||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <Nazara/Core/Color.hpp>
|
||||
#include <Nazara/Core/ObjectLibrary.hpp>
|
||||
#include <Nazara/Core/ObjectRef.hpp>
|
||||
#include <Nazara/Core/RefCounted.hpp>
|
||||
#include <Nazara/Core/Resource.hpp>
|
||||
#include <Nazara/Core/ResourceLoader.hpp>
|
||||
#include <Nazara/Core/ResourceManager.hpp>
|
||||
#include <Nazara/Core/ResourceParameters.hpp>
|
||||
#include <Nazara/Core/Signal.hpp>
|
||||
#include <Nazara/Graphics/Config.hpp>
|
||||
#include <Nazara/Graphics/Enums.hpp>
|
||||
#include <Nazara/Graphics/MaterialPipeline.hpp>
|
||||
#include <Nazara/Renderer/Texture.hpp>
|
||||
#include <Nazara/Renderer/TextureSampler.hpp>
|
||||
#include <Nazara/Utility/UniformBuffer.hpp>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
struct NAZARA_GRAPHICS_API MaterialParams : ResourceParameters
|
||||
{
|
||||
bool loadAlphaMap = true;
|
||||
bool loadDiffuseMap = true;
|
||||
bool loadEmissiveMap = true;
|
||||
bool loadHeightMap = true;
|
||||
bool loadNormalMap = true;
|
||||
bool loadSpecularMap = true;
|
||||
std::string shaderName = "Basic";
|
||||
|
||||
bool IsValid() const;
|
||||
};
|
||||
|
||||
class NAZARA_GRAPHICS_API Material : public RefCounted, public Resource
|
||||
{
|
||||
public:
|
||||
Material(std::shared_ptr<const MaterialSettings> settings);
|
||||
inline Material(const Material& material);
|
||||
inline ~Material();
|
||||
|
||||
void Apply(const MaterialPipeline::Instance& instance) const;
|
||||
|
||||
void BuildFromParameters(const ParameterList& matData, const MaterialParams& matParams = MaterialParams());
|
||||
|
||||
inline void Configure(const MaterialPipeline* pipeline);
|
||||
inline void Configure(const MaterialPipelineInfo& pipelineInfo);
|
||||
inline bool Configure(const String& pipelineName);
|
||||
|
||||
inline void EnableAlphaTest(bool alphaTest);
|
||||
inline void EnableBlending(bool blending);
|
||||
inline void EnableColorWrite(bool colorWrite);
|
||||
inline void EnableDepthBuffer(bool depthBuffer);
|
||||
inline void EnableDepthSorting(bool depthSorting);
|
||||
inline void EnableDepthWrite(bool depthWrite);
|
||||
inline void EnableFaceCulling(bool faceCulling);
|
||||
inline void EnableReflectionMapping(bool reflection);
|
||||
inline void EnableScissorTest(bool scissorTest);
|
||||
inline void EnableShadowCasting(bool castShadows);
|
||||
inline void EnableShadowReceive(bool receiveShadows);
|
||||
inline void EnableStencilTest(bool stencilTest);
|
||||
inline void EnableVertexColor(bool vertexColor);
|
||||
|
||||
inline void EnsurePipelineUpdate() const;
|
||||
|
||||
inline RendererComparison GetDepthFunc() const;
|
||||
inline BlendFunc GetDstBlend() const;
|
||||
inline FaceSide GetFaceCulling() const;
|
||||
inline FaceFilling GetFaceFilling() const;
|
||||
inline float GetLineWidth() const;
|
||||
inline const MaterialPipeline* GetPipeline() const;
|
||||
inline const MaterialPipelineInfo& GetPipelineInfo() const;
|
||||
inline float GetPointSize() const;
|
||||
inline const std::shared_ptr<const MaterialSettings>& GetSettings() const;
|
||||
inline const std::shared_ptr<Shader>& GetShader() const;
|
||||
inline BlendFunc GetSrcBlend() const;
|
||||
inline UniformBuffer* GetSharedUniformBuffer(std::size_t bufferIndex) const;
|
||||
inline const std::shared_ptr<Texture>& GetTexture(std::size_t textureIndex) const;
|
||||
inline const std::shared_ptr<TextureSampler>& GetTextureSampler(std::size_t textureIndex) const;
|
||||
inline UniformBufferRef& GetUniformBuffer(std::size_t bufferIndex);
|
||||
inline const UniformBufferRef& GetUniformBuffer(std::size_t bufferIndex) const;
|
||||
|
||||
inline bool HasDepthMaterial() const;
|
||||
inline bool HasTexture(std::size_t textureIndex) const;
|
||||
inline bool HasVertexColor() const;
|
||||
|
||||
inline bool IsAlphaTestEnabled() const;
|
||||
inline bool IsBlendingEnabled() const;
|
||||
inline bool IsColorWriteEnabled() const;
|
||||
inline bool IsDepthBufferEnabled() const;
|
||||
inline bool IsDepthSortingEnabled() const;
|
||||
inline bool IsDepthWriteEnabled() const;
|
||||
inline bool IsFaceCullingEnabled() const;
|
||||
inline bool IsReflectionMappingEnabled() const;
|
||||
inline bool IsScissorTestEnabled() const;
|
||||
inline bool IsStencilTestEnabled() const;
|
||||
inline bool IsShadowCastingEnabled() const;
|
||||
inline bool IsShadowReceiveEnabled() const;
|
||||
|
||||
void SaveToParameters(ParameterList* matData);
|
||||
|
||||
inline void SetDepthFunc(RendererComparison depthFunc);
|
||||
inline void SetDstBlend(BlendFunc func);
|
||||
inline void SetFaceCulling(FaceSide faceSide);
|
||||
inline void SetFaceFilling(FaceFilling filling);
|
||||
inline void SetLineWidth(float lineWidth);
|
||||
inline void SetPointSize(float pointSize);
|
||||
inline void SetShader(std::shared_ptr<Shader> shader);
|
||||
inline void SetUniformBuffer(std::size_t bufferIndex, UniformBuffer* uniformBuffer);
|
||||
inline void SetSrcBlend(BlendFunc func);
|
||||
inline void SetTexture(std::size_t textureIndex, Texture* texture);
|
||||
inline void SetTextureSampler(std::size_t textureIndex, const TextureSampler& sampler);
|
||||
|
||||
inline Material& operator=(const Material& material);
|
||||
|
||||
// Signals:
|
||||
NazaraSignal(OnMaterialRelease, const Material* /*material*/);
|
||||
|
||||
private:
|
||||
inline void InvalidatePipeline();
|
||||
inline void UpdatePipeline() const;
|
||||
|
||||
struct MaterialTexture
|
||||
{
|
||||
std::shared_ptr<TextureSampler> sampler;
|
||||
std::shared_ptr<Texture> texture;
|
||||
};
|
||||
|
||||
std::shared_ptr<const MaterialSettings> m_settings;
|
||||
std::vector<MaterialTexture> m_textures;
|
||||
std::vector<UniformBufferRef> m_uniformBuffers;
|
||||
mutable const MaterialPipeline* m_pipeline;
|
||||
MaterialPipelineInfo m_pipelineInfo;
|
||||
mutable bool m_pipelineUpdated;
|
||||
bool m_shadowCastingEnabled;
|
||||
};
|
||||
}
|
||||
|
||||
#include <Nazara/Graphics/Material.inl>
|
||||
|
||||
#endif // NAZARA_BASE_MATERIAL_HPP
|
||||
981
include/Nazara/Graphics/Material.inl
Normal file
981
include/Nazara/Graphics/Material.inl
Normal file
@@ -0,0 +1,981 @@
|
||||
// Copyright (C) 2017 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Graphics module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Graphics/Material.hpp>
|
||||
#include <Nazara/Core/ErrorFlags.hpp>
|
||||
#include <memory>
|
||||
#include <Nazara/Graphics/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \brief Constructs a Material object by assignation
|
||||
*
|
||||
* \param material Material to copy into this
|
||||
*/
|
||||
inline Material::Material(const Material& material) :
|
||||
RefCounted(),
|
||||
Resource(material)
|
||||
{
|
||||
operator=(material);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Destructs the object and calls OnMaterialRelease
|
||||
*
|
||||
* \see OnMaterialRelease
|
||||
*/
|
||||
inline Material::~Material()
|
||||
{
|
||||
OnMaterialRelease(this);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Reset material pipeline state
|
||||
*
|
||||
* Sets the material pipeline
|
||||
*
|
||||
* \remark pipeline must be valid
|
||||
*
|
||||
* \see Configure
|
||||
*/
|
||||
inline void Material::Configure(const MaterialPipeline* pipeline)
|
||||
{
|
||||
NazaraAssert(pipeline, "Invalid material pipeline");
|
||||
|
||||
m_pipeline = pipeline;
|
||||
m_pipelineInfo = m_pipeline->GetInfo();
|
||||
m_pipelineUpdated = true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Reset material pipeline state
|
||||
*
|
||||
* Sets the material pipeline using pipeline info
|
||||
*
|
||||
* \remark pipeline must be valid
|
||||
*
|
||||
* \see Configure
|
||||
*/
|
||||
inline void Material::Configure(const MaterialPipelineInfo& pipelineInfo)
|
||||
{
|
||||
m_pipelineInfo = pipelineInfo;
|
||||
|
||||
InvalidatePipeline();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Reset material pipeline state
|
||||
*
|
||||
* Sets the material pipeline using a name to lookup in the MaterialPipelineLibrary
|
||||
*
|
||||
* \return True if the material pipeline was found in the library
|
||||
*
|
||||
* \see Configure
|
||||
*/
|
||||
inline bool Material::Configure(const String& pipelineName)
|
||||
{
|
||||
MaterialPipelineRef pipeline = MaterialPipelineLibrary::Query(pipelineName);
|
||||
if (!pipeline)
|
||||
{
|
||||
NazaraError("Failed to get pipeline \"" + pipelineName + "\"");
|
||||
return false;
|
||||
}
|
||||
|
||||
Configure(std::move(pipeline));
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Enable/Disable alpha test for this material
|
||||
*
|
||||
* When enabled, all objects using this material will be rendered using alpha testing,
|
||||
* rejecting pixels if their alpha component is under a defined threshold.
|
||||
* This allows some kind of transparency with a much cheaper cost as it doesn't prevent any optimization (as deferred rendering or batching).
|
||||
*
|
||||
* \param alphaTest Defines if this material will use alpha testing
|
||||
*
|
||||
* \remark Invalidates the pipeline
|
||||
*
|
||||
* \see IsAlphaTestEnabled
|
||||
* \see SetAlphaThreshold
|
||||
*/
|
||||
inline void Material::EnableAlphaTest(bool alphaTest)
|
||||
{
|
||||
m_pipelineInfo.alphaTest = alphaTest;
|
||||
|
||||
InvalidatePipeline();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Enable/Disable blending for this material
|
||||
*
|
||||
* When enabled, all objects using this material will be rendered using blending, obeying the dstBlend and srcBlend parameters
|
||||
* This is useful with translucent objects, but will reduces performance as it prevents some optimizations (as deferred rendering)
|
||||
*
|
||||
* \param blending Defines if this material will use blending
|
||||
*
|
||||
* \remark Invalidates the pipeline
|
||||
*
|
||||
* \see IsBlendingEnabled
|
||||
* \see SetDstBlend
|
||||
* \see SetSrcBlend
|
||||
*/
|
||||
inline void Material::EnableBlending(bool blending)
|
||||
{
|
||||
m_pipelineInfo.blending = blending;
|
||||
|
||||
InvalidatePipeline();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Enable/Disable color writing for this material
|
||||
*
|
||||
* \param colorWrite Defines if this material will use color writing
|
||||
*
|
||||
* \remark Invalidates the pipeline
|
||||
*
|
||||
* \see IsColorWritingEnabled
|
||||
*/
|
||||
inline void Material::EnableColorWrite(bool colorWrite)
|
||||
{
|
||||
m_pipelineInfo.colorWrite = colorWrite;
|
||||
|
||||
InvalidatePipeline();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Enable/Disable depth buffer for this material
|
||||
*
|
||||
* When enabled, all objects using this material will be rendered using a depth buffer, if the RenderTarget has one.
|
||||
* This will enable Depth Test, preventing further fragments to render on top of closer ones.
|
||||
*
|
||||
* This parameter is required for depth writing.
|
||||
*
|
||||
* In order to enable depth writing without enabling depth test, set the depth comparison function to RendererComparison_Never
|
||||
*
|
||||
* \param depthBuffer Defines if this material will use depth buffer
|
||||
*
|
||||
* \remark Invalidates the pipeline
|
||||
*
|
||||
* \see EnableDepthWrite
|
||||
* \see IsDepthBufferEnabled
|
||||
* \see SetDepthFunc
|
||||
*/
|
||||
inline void Material::EnableDepthBuffer(bool depthBuffer)
|
||||
{
|
||||
m_pipelineInfo.depthBuffer = depthBuffer;
|
||||
|
||||
InvalidatePipeline();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Enable/Disable depth sorting for this material
|
||||
*
|
||||
* When enabled, all objects using this material will be rendered far from near
|
||||
* This is useful with translucent objects, but will reduces performance as it breaks batching
|
||||
*
|
||||
* \param depthSorting Defines if this material will use depth sorting
|
||||
*
|
||||
* \remark Depth sorting may not be perfect (may be object-sorting instead of triangle-sorting)
|
||||
* \remark Invalidates the pipeline
|
||||
*
|
||||
* \see IsDepthSortingEnabled
|
||||
*/
|
||||
inline void Material::EnableDepthSorting(bool depthSorting)
|
||||
{
|
||||
m_pipelineInfo.depthSorting = depthSorting;
|
||||
|
||||
InvalidatePipeline();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Enable/Disable depth writing for this material
|
||||
*
|
||||
* When enabled, and if depth buffer is enabled and present, all fragments generated with this material will write
|
||||
* to the depth buffer if they pass depth test.
|
||||
*
|
||||
* This is usually disabled with translucent objects, as depth test is wanted to prevent them from rendering on top of opaque objects but
|
||||
* not depth writing (which could make other translucent fragments to fail depth test)
|
||||
*
|
||||
* \param depthBuffer Defines if this material will use depth write
|
||||
*
|
||||
* \remark Invalidates the pipeline
|
||||
*
|
||||
* \see EnableDepthBuffer
|
||||
* \see IsDepthWriteEnabled
|
||||
*/
|
||||
inline void Material::EnableDepthWrite(bool depthWrite)
|
||||
{
|
||||
m_pipelineInfo.depthWrite = depthWrite;
|
||||
|
||||
InvalidatePipeline();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Enable/Disable face culling for this material
|
||||
*
|
||||
* When enabled, the material prevents front and/or back faces from rendering.
|
||||
* This is commonly used as an optimization to prevent processing of hidden faces by the rendering device.
|
||||
*
|
||||
* Use SetFaceCulling to control which side will be eliminated.
|
||||
*
|
||||
* \param faceCulling Defines if this material will use face culling
|
||||
*
|
||||
* \remark Invalidates the pipeline
|
||||
*
|
||||
* \see IsFaceCullingEnabled
|
||||
* \see SetFaceCulling
|
||||
*/
|
||||
inline void Material::EnableFaceCulling(bool faceCulling)
|
||||
{
|
||||
m_pipelineInfo.faceCulling = faceCulling;
|
||||
|
||||
InvalidatePipeline();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Enable/Disable reflection mapping for this material
|
||||
*
|
||||
* When enabled, the material will render reflections from the object environment according to the reflection mode.
|
||||
* Whether or not this is expensive depends of the reflection mode and size.
|
||||
*
|
||||
* Please note this is only a hint for the render technique, and reflections can be forcefully enabled or disabled depending on the material shader.
|
||||
*
|
||||
* Use SetReflectionMode and SetReflectionSize to control reflection quality.
|
||||
*
|
||||
* \param reflection Defines if this material should use reflection mapping
|
||||
*
|
||||
* \remark May invalidates the pipeline
|
||||
*
|
||||
* \see IsReflectionMappingEnabled
|
||||
* \see SetReflectionMode
|
||||
* \see SetReflectionSize
|
||||
*/
|
||||
inline void Material::EnableReflectionMapping(bool reflection)
|
||||
{
|
||||
m_pipelineInfo.reflectionMapping = reflection;
|
||||
|
||||
InvalidatePipeline();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Enable/Disable scissor test for this material
|
||||
*
|
||||
* When enabled, the material prevents fragments out of the scissor box to be rendered.
|
||||
* This can be useful with GUI, where widgets must not be rendered outside of their parent rendering area.
|
||||
*
|
||||
* \param scissorTest Defines if this material will use scissor test
|
||||
*
|
||||
* \remark Invalidates the pipeline
|
||||
*
|
||||
* \see IsScissorTestEnabled
|
||||
*/
|
||||
inline void Material::EnableScissorTest(bool scissorTest)
|
||||
{
|
||||
m_pipelineInfo.scissorTest = scissorTest;
|
||||
|
||||
InvalidatePipeline();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Enable/Disable shadow casting for this material
|
||||
*
|
||||
* When enabled, all objects using this material will be allowed to cast shadows upon any objects using a material with shadow receiving enabled.
|
||||
* The depth material replaces this one when rendering shadows.
|
||||
*
|
||||
* \param castShadows Defines if this material will be allowed to cast shadows
|
||||
*
|
||||
* \remark Does not invalidate the pipeline
|
||||
*
|
||||
* \see EnableShadowReceive
|
||||
* \see IsShadowCastingEnabled
|
||||
* \see SetDepthMaterial
|
||||
*/
|
||||
inline void Material::EnableShadowCasting(bool castShadows)
|
||||
{
|
||||
// Has no influence on pipeline
|
||||
m_shadowCastingEnabled = castShadows;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Enable/Disable shadow receiving for this material
|
||||
*
|
||||
* When enabled, all objects using this material will be allowed to be casted shadows upon themselves
|
||||
* Disabling this can be helpful to prevent some rendering artifacts (especially with translucent objects)
|
||||
*
|
||||
* \param receiveShadows Defines if this material will be able to receive shadows
|
||||
*
|
||||
* \remark Invalidates the pipeline
|
||||
*
|
||||
* \see IsShadowReceiveEnabled
|
||||
*/
|
||||
inline void Material::EnableShadowReceive(bool receiveShadows)
|
||||
{
|
||||
m_pipelineInfo.shadowReceive = receiveShadows;
|
||||
|
||||
InvalidatePipeline();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Enable/Disable stencil test for this material
|
||||
*
|
||||
* When enabled, all fragments must pass the stencil test to be rendered.
|
||||
*
|
||||
* \param scissorTest Defines if this material will use stencil test
|
||||
*
|
||||
* \remark Invalidates the pipeline
|
||||
*
|
||||
* \see IsStencilTestEnabled
|
||||
*/
|
||||
inline void Material::EnableStencilTest(bool stencilTest)
|
||||
{
|
||||
m_pipelineInfo.stencilTest = stencilTest;
|
||||
|
||||
InvalidatePipeline();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Enable/Disable vertex coloring on this material
|
||||
*
|
||||
* This is a temporary option, until the new material pipeline system is ready, allowing to enable vertex coloring.
|
||||
* This option only works with meshes using vertex colors.
|
||||
*
|
||||
* \param vertexColor Defines if this material will use vertex color or not
|
||||
*
|
||||
* \remark Invalidates the pipeline
|
||||
*
|
||||
* \see HasVertexColor
|
||||
*/
|
||||
inline void Material::EnableVertexColor(bool vertexColor)
|
||||
{
|
||||
m_pipelineInfo.hasVertexColor = vertexColor;
|
||||
|
||||
InvalidatePipeline();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Ensures the pipeline gets updated
|
||||
*
|
||||
* When the pipeline gets invalidated, it's not updated until required (per example by calling GetPipeline).
|
||||
* Using this function forces the pipeline update, making GetPipeline thread-safe as long as the pipeline does not get invalidated.
|
||||
*
|
||||
* \see GetPipeline
|
||||
*/
|
||||
inline void Material::EnsurePipelineUpdate() const
|
||||
{
|
||||
if (!m_pipelineUpdated)
|
||||
UpdatePipeline();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the function to compare depth
|
||||
*
|
||||
* \return Function comparing the depth of two materials
|
||||
*
|
||||
* \see EnableDepthTest
|
||||
* \see SetAmbientColor
|
||||
*/
|
||||
inline RendererComparison Material::GetDepthFunc() const
|
||||
{
|
||||
return m_pipelineInfo.depthCompare;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the depth material
|
||||
*
|
||||
* \return Constant reference to the depth material
|
||||
*
|
||||
* \see EnableShadowCasting
|
||||
*/
|
||||
inline const MaterialRef& Material::GetDepthMaterial() const
|
||||
{
|
||||
return m_depthMaterial;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the dst in blend
|
||||
*
|
||||
* \return Function for dst blending
|
||||
*
|
||||
* \see SetDstBlend
|
||||
*/
|
||||
inline BlendFunc Material::GetDstBlend() const
|
||||
{
|
||||
return m_pipelineInfo.dstBlend;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the face culling
|
||||
*
|
||||
* \return Current face culling side
|
||||
*
|
||||
* \see SetFaceCulling
|
||||
*/
|
||||
inline FaceSide Material::GetFaceCulling() const
|
||||
{
|
||||
return m_pipelineInfo.cullingSide;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the face filling
|
||||
* \return Current face filling
|
||||
*/
|
||||
inline FaceFilling Material::GetFaceFilling() const
|
||||
{
|
||||
return m_pipelineInfo.faceFilling;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the line width of this material
|
||||
* \return Line width
|
||||
*/
|
||||
inline float Material::GetLineWidth() const
|
||||
{
|
||||
return m_pipelineInfo.lineWidth;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the render states
|
||||
* \return Constant reference to the render states
|
||||
*/
|
||||
inline const MaterialPipeline* Material::GetPipeline() const
|
||||
{
|
||||
EnsurePipelineUpdate();
|
||||
|
||||
return m_pipeline;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the pipeline informations
|
||||
* \return Constant reference to the pipeline info
|
||||
*/
|
||||
inline const MaterialPipelineInfo& Material::GetPipelineInfo() const
|
||||
{
|
||||
return m_pipelineInfo;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the point size of this material
|
||||
* \return Point size
|
||||
*/
|
||||
inline float Material::GetPointSize() const
|
||||
{
|
||||
return m_pipelineInfo.pointSize;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the reflection mode of the material
|
||||
*
|
||||
* \return Current reflection mode
|
||||
*
|
||||
* \see SetReflectionMode
|
||||
*/
|
||||
inline ReflectionMode Material::GetReflectionMode() const
|
||||
{
|
||||
return m_reflectionMode;
|
||||
}
|
||||
|
||||
inline const std::shared_ptr<const MaterialSettings>& Material::GetSettings() const
|
||||
{
|
||||
return m_settings;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the über-shader used by this material
|
||||
* \return Constant pointer to the über-shader used
|
||||
*/
|
||||
inline const UberShader* Material::GetShader() const
|
||||
{
|
||||
return m_pipelineInfo.uberShader;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the src in blend
|
||||
* \return Function for src blending
|
||||
*/
|
||||
inline BlendFunc Material::GetSrcBlend() const
|
||||
{
|
||||
return m_pipelineInfo.srcBlend;
|
||||
}
|
||||
|
||||
inline const TextureRef& Material::GetTexture(std::size_t textureIndex) const
|
||||
{
|
||||
NazaraAssert(textureIndex < m_textures.size(), "Invalid texture index");
|
||||
return m_textures[textureIndex].texture;
|
||||
}
|
||||
|
||||
inline TextureSampler& Material::GetTextureSampler(std::size_t textureIndex)
|
||||
{
|
||||
NazaraAssert(textureIndex < m_textures.size(), "Invalid texture index");
|
||||
return m_textures[textureIndex].sampler;
|
||||
}
|
||||
|
||||
inline const TextureSampler& Material::GetTextureSampler(std::size_t textureIndex) const
|
||||
{
|
||||
NazaraAssert(textureIndex < m_textures.size(), "Invalid texture index");
|
||||
return m_textures[textureIndex].sampler;
|
||||
}
|
||||
|
||||
inline UniformBufferRef& Material::GetUniformBuffer(std::size_t bufferIndex)
|
||||
{
|
||||
NazaraAssert(bufferIndex < m_uniformBuffers.size(), "Invalid uniform buffer index");
|
||||
return m_uniformBuffers[bufferIndex];
|
||||
}
|
||||
|
||||
inline const UniformBufferRef& Material::GetUniformBuffer(std::size_t bufferIndex) const
|
||||
{
|
||||
NazaraAssert(bufferIndex < m_uniformBuffers.size(), "Invalid uniform buffer index");
|
||||
return m_uniformBuffers[bufferIndex];
|
||||
}
|
||||
|
||||
inline bool Material::HasDepthMaterial() const
|
||||
{
|
||||
return m_depthMaterial.IsValid();
|
||||
}
|
||||
|
||||
inline bool Material::HasTexture(std::size_t textureIndex) const
|
||||
{
|
||||
Texture* texture = GetTexture(textureIndex);
|
||||
return texture && texture->IsValid();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether this material uses vertex coloring
|
||||
* \return true If it is the case
|
||||
*/
|
||||
inline bool Material::HasVertexColor() const
|
||||
{
|
||||
return m_pipelineInfo.hasVertexColor;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether this material has alpha test enabled
|
||||
* \return true If it is the case
|
||||
*/
|
||||
inline bool Material::IsAlphaTestEnabled() const
|
||||
{
|
||||
return m_pipelineInfo.alphaTest;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether this material has blending enabled
|
||||
* \return true If it is the case
|
||||
*/
|
||||
inline bool Material::IsBlendingEnabled() const
|
||||
{
|
||||
return m_pipelineInfo.blending;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether this material has color write enabled
|
||||
* \return true If it is the case
|
||||
*/
|
||||
inline bool Material::IsColorWriteEnabled() const
|
||||
{
|
||||
return m_pipelineInfo.colorWrite;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether this material has depth buffer enabled
|
||||
* \return true If it is the case
|
||||
*/
|
||||
inline bool Material::IsDepthBufferEnabled() const
|
||||
{
|
||||
return m_pipelineInfo.depthBuffer;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether this material has depth sorting enabled
|
||||
* \return true If it is the case
|
||||
*/
|
||||
inline bool Material::IsDepthSortingEnabled() const
|
||||
{
|
||||
return m_pipelineInfo.depthSorting;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether this material has depth writing enabled
|
||||
* \return true If it is the case
|
||||
*/
|
||||
inline bool Material::IsDepthWriteEnabled() const
|
||||
{
|
||||
return m_pipelineInfo.depthWrite;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether this material has face culling enabled
|
||||
* \return true If it is the case
|
||||
*/
|
||||
inline bool Material::IsFaceCullingEnabled() const
|
||||
{
|
||||
return m_pipelineInfo.faceCulling;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether this material has reflection mapping enabled
|
||||
* \return true If it is the case
|
||||
*
|
||||
* \see EnableReflectionMapping
|
||||
*/
|
||||
inline bool Material::IsReflectionMappingEnabled() const
|
||||
{
|
||||
return m_pipelineInfo.reflectionMapping;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether this material has scissor test enabled
|
||||
* \return true If it is the case
|
||||
*/
|
||||
inline bool Material::IsScissorTestEnabled() const
|
||||
{
|
||||
return m_pipelineInfo.scissorTest;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether this material has stencil test enabled
|
||||
* \return true If it is the case
|
||||
*/
|
||||
inline bool Material::IsStencilTestEnabled() const
|
||||
{
|
||||
return m_pipelineInfo.stencilTest;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether this material cast shadow
|
||||
* \return true If it is the case
|
||||
*/
|
||||
inline bool Material::IsShadowCastingEnabled() const
|
||||
{
|
||||
return m_shadowCastingEnabled;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether this material receive shadow
|
||||
* \return true If it is the case
|
||||
*/
|
||||
inline bool Material::IsShadowReceiveEnabled() const
|
||||
{
|
||||
return m_pipelineInfo.shadowReceive;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the depth functor
|
||||
*
|
||||
* \param depthFunc
|
||||
*
|
||||
* \remark Invalidates the pipeline
|
||||
*/
|
||||
inline void Material::SetDepthFunc(RendererComparison depthFunc)
|
||||
{
|
||||
m_pipelineInfo.depthFunc = depthFunc;
|
||||
|
||||
InvalidatePipeline();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the depth material
|
||||
* \return true If successful
|
||||
*
|
||||
* \param depthMaterial Material for depth
|
||||
*/
|
||||
inline void Material::SetDepthMaterial(MaterialRef depthMaterial)
|
||||
{
|
||||
m_depthMaterial = std::move(depthMaterial);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the dst in blend
|
||||
*
|
||||
* \param func Function for dst blending
|
||||
*
|
||||
* \remark Invalidates the pipeline
|
||||
*/
|
||||
inline void Material::SetDstBlend(BlendFunc func)
|
||||
{
|
||||
m_pipelineInfo.dstBlend = func;
|
||||
|
||||
InvalidatePipeline();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the face culling
|
||||
*
|
||||
* \param faceSide Face to cull
|
||||
*
|
||||
* \remark Invalidates the pipeline
|
||||
*/
|
||||
inline void Material::SetFaceCulling(FaceSide faceSide)
|
||||
{
|
||||
m_pipelineInfo.cullingSide = faceSide;
|
||||
|
||||
InvalidatePipeline();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the face filling
|
||||
*
|
||||
* \param filling Face to fill
|
||||
*
|
||||
* \remark Invalidates the pipeline
|
||||
*/
|
||||
inline void Material::SetFaceFilling(FaceFilling filling)
|
||||
{
|
||||
m_pipelineInfo.faceFilling = filling;
|
||||
|
||||
InvalidatePipeline();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the line width for this material
|
||||
*
|
||||
* This parameter is used when rendering lines, to define the width (in pixels) the line will take on the framebuffer
|
||||
*
|
||||
* \param lineWidth Width of the line
|
||||
*
|
||||
* \remark Invalidates the pipeline
|
||||
*
|
||||
* \see GetLineWidth
|
||||
*/
|
||||
inline void Material::SetLineWidth(float lineWidth)
|
||||
{
|
||||
m_pipelineInfo.lineWidth = lineWidth;
|
||||
|
||||
InvalidatePipeline();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the point size for this material
|
||||
*
|
||||
* This parameter is used when rendering points, to define the size (in pixels) the point will take on the framebuffer
|
||||
*
|
||||
* \param pointSize Size of the point
|
||||
*
|
||||
* \remark Invalidates the pipeline
|
||||
*
|
||||
* \see GetPointSize
|
||||
*/
|
||||
inline void Material::SetPointSize(float pointSize)
|
||||
{
|
||||
m_pipelineInfo.pointSize = pointSize;
|
||||
|
||||
InvalidatePipeline();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Changes reflection mode of the material
|
||||
*
|
||||
* When reflections are enabled, the material will render reflections from the object environment according to the reflection mode.
|
||||
* This function does change the reflection mode used by the material.
|
||||
*
|
||||
* Skyboxes reflections are the cheapest but are static and thus can't reflect other objects.
|
||||
* Probes reflections are cheap, depending on probes reflection mode, but require regular probe finding from objects using it.
|
||||
* Real-time reflections are expensive but provide the most accurate reflection map (and can reflect other objects around).
|
||||
*
|
||||
* \param reflectionMode The new reflection mode this material should use
|
||||
*
|
||||
* \remark May invalidates the pipeline
|
||||
*
|
||||
* \see EnableReflectionMapping
|
||||
* \see IsReflectionMappingEnabled
|
||||
* \see SetReflectionSize
|
||||
*/
|
||||
inline void Material::SetReflectionMode(ReflectionMode reflectionMode)
|
||||
{
|
||||
if (m_reflectionMode != reflectionMode)
|
||||
{
|
||||
OnMaterialReflectionModeChange(this, reflectionMode);
|
||||
|
||||
m_reflectionMode = reflectionMode;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the shader with a constant reference to a ubershader
|
||||
*
|
||||
* \param uberShader Uber shader to apply
|
||||
*
|
||||
* \remark Invalidates the pipeline
|
||||
*
|
||||
* \see GetShader
|
||||
*/
|
||||
inline void Material::SetShader(UberShaderConstRef uberShader)
|
||||
{
|
||||
m_pipelineInfo.uberShader = std::move(uberShader);
|
||||
|
||||
InvalidatePipeline();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the shader by name
|
||||
* \return true If successful
|
||||
*
|
||||
* \param uberShaderName Named shader
|
||||
*/
|
||||
inline bool Material::SetShader(const String& uberShaderName)
|
||||
{
|
||||
UberShaderConstRef uberShader = UberShaderLibrary::Get(uberShaderName);
|
||||
if (!uberShader)
|
||||
return false;
|
||||
|
||||
SetShader(std::move(uberShader));
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void Material::SetUniformBuffer(std::size_t bufferIndex, UniformBuffer* uniformBuffer)
|
||||
{
|
||||
NazaraAssert(bufferIndex < m_uniformBuffers.size(), "Invalid shared uniform buffer index");
|
||||
m_uniformBuffers[bufferIndex] = uniformBuffer;
|
||||
}
|
||||
|
||||
inline void Material::SetTexture(std::size_t textureIndex, Texture* texture)
|
||||
{
|
||||
NazaraAssert(textureIndex < m_textures.size(), "Invalid texture index");
|
||||
m_textures[textureIndex].texture = texture;
|
||||
|
||||
if (texture)
|
||||
m_pipelineInfo.textures |= UInt64(1) << UInt64(textureIndex);
|
||||
else
|
||||
m_pipelineInfo.textures &= ~(UInt64(1) << UInt64(textureIndex));
|
||||
|
||||
InvalidatePipeline();
|
||||
}
|
||||
|
||||
inline void Material::SetTextureSampler(std::size_t textureIndex, const TextureSampler& sampler)
|
||||
{
|
||||
NazaraAssert(textureIndex < m_textures.size(), "Invalid texture index");
|
||||
m_textures[textureIndex].sampler = sampler;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the src in blend
|
||||
*
|
||||
* \param func Function for src blending
|
||||
*
|
||||
* \remark Invalidates the pipeline
|
||||
*
|
||||
* \see GetSrcBlend
|
||||
*/
|
||||
inline void Material::SetSrcBlend(BlendFunc func)
|
||||
{
|
||||
m_pipelineInfo.srcBlend = func;
|
||||
|
||||
InvalidatePipeline();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the current material with the content of the other one
|
||||
* \return A reference to this
|
||||
*
|
||||
* \param material The other Material
|
||||
*/
|
||||
inline Material& Material::operator=(const Material& material)
|
||||
{
|
||||
Resource::operator=(material);
|
||||
|
||||
m_settings = material.m_settings;
|
||||
m_textures = material.m_textures;
|
||||
m_depthMaterial = material.m_depthMaterial;
|
||||
m_pipeline = material.m_pipeline;
|
||||
m_pipelineInfo = material.m_pipelineInfo;
|
||||
m_pipelineUpdated = material.m_pipelineUpdated;
|
||||
m_shadowCastingEnabled = material.m_shadowCastingEnabled;
|
||||
m_reflectionSize = material.m_reflectionSize;
|
||||
|
||||
m_pipelineInfo.settings = m_settings;
|
||||
|
||||
for (std::size_t i = 0; i < m_uniformBuffers.size(); ++i)
|
||||
{
|
||||
const UniformBuffer* sourceBuffer = material.GetUniformBuffer(i);
|
||||
UniformBuffer* targetBuffer = m_uniformBuffers[i] = UniformBuffer::New(sourceBuffer->GetEndOffset() - sourceBuffer->GetStartOffset(), DataStorage_Hardware, BufferUsage_Dynamic);
|
||||
if (!targetBuffer->CopyContent(sourceBuffer))
|
||||
NazaraError("Failed to copy uniform buffer content");
|
||||
}
|
||||
|
||||
SetReflectionMode(material.GetReflectionMode());
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the default material
|
||||
*
|
||||
* \return Reference to the default material
|
||||
*
|
||||
* \remark This material should NOT be modified as it would affect all objects using it
|
||||
*/
|
||||
inline MaterialRef Material::GetDefault()
|
||||
{
|
||||
return s_defaultMaterial;
|
||||
}
|
||||
|
||||
inline int Material::GetTextureUnit(TextureMap textureMap)
|
||||
{
|
||||
return s_textureUnits[textureMap];
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Loads the material from file
|
||||
* \return true if loading is successful
|
||||
*
|
||||
* \param filePath Path to the file
|
||||
* \param params Parameters for the material
|
||||
*/
|
||||
inline MaterialRef Material::LoadFromFile(const String& filePath, const MaterialParams& params)
|
||||
{
|
||||
return MaterialLoader::LoadFromFile(filePath, params);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Loads the material from memory
|
||||
* \return true if loading is successful
|
||||
*
|
||||
* \param data Raw memory
|
||||
* \param size Size of the memory
|
||||
* \param params Parameters for the material
|
||||
*/
|
||||
inline MaterialRef Material::LoadFromMemory(const void* data, std::size_t size, const MaterialParams& params)
|
||||
{
|
||||
return MaterialLoader::LoadFromMemory(data, size, params);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Loads the material from stream
|
||||
* \return true if loading is successful
|
||||
*
|
||||
* \param stream Stream to the material
|
||||
* \param params Parameters for the material
|
||||
*/
|
||||
inline MaterialRef Material::LoadFromStream(Stream& stream, const MaterialParams& params)
|
||||
{
|
||||
return MaterialLoader::LoadFromStream(stream, params);
|
||||
}
|
||||
|
||||
inline void Material::InvalidatePipeline()
|
||||
{
|
||||
m_pipelineUpdated = false;
|
||||
}
|
||||
|
||||
inline void Material::UpdatePipeline() const
|
||||
{
|
||||
m_pipeline = MaterialPipeline::GetPipeline(m_pipelineInfo);
|
||||
m_pipelineUpdated = true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Creates a new material from the arguments
|
||||
* \return A reference to the newly created material
|
||||
*
|
||||
* \param args Arguments for the material
|
||||
*/
|
||||
template<typename... Args>
|
||||
MaterialRef Material::New(Args&&... args)
|
||||
{
|
||||
std::unique_ptr<Material> object(new Material(std::forward<Args>(args)...));
|
||||
object->SetPersistent(false);
|
||||
|
||||
return object.release();
|
||||
}
|
||||
}
|
||||
|
||||
#include <Nazara/Graphics/DebugOff.hpp>
|
||||
87
include/Nazara/Graphics/MaterialPipeline.hpp
Normal file
87
include/Nazara/Graphics/MaterialPipeline.hpp
Normal file
@@ -0,0 +1,87 @@
|
||||
// Copyright (C) 2017 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Graphics module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_MATERIALPIPELINE_HPP
|
||||
#define NAZARA_MATERIALPIPELINE_HPP
|
||||
|
||||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <Nazara/Graphics/Config.hpp>
|
||||
#include <Nazara/Graphics/Enums.hpp>
|
||||
#include <Nazara/Graphics/MaterialSettings.hpp>
|
||||
#include <Nazara/Renderer/RenderPipeline.hpp>
|
||||
#include <array>
|
||||
#include <memory>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class Shader;
|
||||
|
||||
struct MaterialPipelineInfo : RenderStates
|
||||
{
|
||||
bool alphaTest = false;
|
||||
bool depthSorting = false;
|
||||
bool hasVertexColor = false;
|
||||
bool reflectionMapping = false;
|
||||
bool shadowReceive = true;
|
||||
Nz::UInt64 textures = 0;
|
||||
|
||||
std::shared_ptr<RenderPipelineLayout> pipelineLayout;
|
||||
std::shared_ptr<const MaterialSettings> settings;
|
||||
std::shared_ptr<Shader> shader;
|
||||
};
|
||||
|
||||
inline bool operator==(const MaterialPipelineInfo& lhs, const MaterialPipelineInfo& rhs);
|
||||
inline bool operator!=(const MaterialPipelineInfo& lhs, const MaterialPipelineInfo& rhs);
|
||||
|
||||
|
||||
class NAZARA_GRAPHICS_API MaterialPipeline
|
||||
{
|
||||
public:
|
||||
struct Instance;
|
||||
|
||||
MaterialPipeline(const MaterialPipeline&) = delete;
|
||||
MaterialPipeline(MaterialPipeline&&) = delete;
|
||||
~MaterialPipeline() = default;
|
||||
|
||||
inline const Instance& Apply(UInt32 flags = ShaderFlags_None) const;
|
||||
|
||||
MaterialPipeline& operator=(const MaterialPipeline&) = delete;
|
||||
MaterialPipeline& operator=(MaterialPipeline&&) = delete;
|
||||
|
||||
inline const MaterialPipelineInfo& GetInfo() const;
|
||||
inline const Instance& GetInstance(UInt32 flags = ShaderFlags_None) const;
|
||||
|
||||
static MaterialPipelineRef GetPipeline(const MaterialPipelineInfo& pipelineInfo);
|
||||
|
||||
struct Instance
|
||||
{
|
||||
RenderPipeline renderPipeline;
|
||||
//Shader::LayoutBindings bindings;
|
||||
//UberShaderInstance* uberInstance = nullptr;
|
||||
};
|
||||
|
||||
private:
|
||||
inline MaterialPipeline(const MaterialPipelineInfo& pipelineInfo);
|
||||
|
||||
void GenerateRenderPipeline(UInt32 flags) const;
|
||||
|
||||
static bool Initialize();
|
||||
template<typename... Args> static MaterialPipelineRef New(Args&&... args);
|
||||
static void Uninitialize();
|
||||
|
||||
MaterialPipelineInfo m_pipelineInfo;
|
||||
mutable std::array<Instance, ShaderFlags_Max + 1> m_instances;
|
||||
|
||||
using PipelineCache = std::unordered_map<MaterialPipelineInfo, MaterialPipelineRef>;
|
||||
static PipelineCache s_pipelineCache;
|
||||
|
||||
static MaterialPipelineLibrary::LibraryMap s_library;
|
||||
};
|
||||
}
|
||||
|
||||
#include <Nazara/Graphics/MaterialPipeline.inl>
|
||||
|
||||
#endif // NAZARA_MATERIALPIPELINE_HPP
|
||||
138
include/Nazara/Graphics/MaterialPipeline.inl
Normal file
138
include/Nazara/Graphics/MaterialPipeline.inl
Normal file
@@ -0,0 +1,138 @@
|
||||
// Copyright (C) 2017 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Graphics module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Renderer/Renderer.hpp>
|
||||
#include <Nazara/Renderer/UberShaderInstance.hpp>
|
||||
#include <functional>
|
||||
#include <Nazara/Graphics/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
inline MaterialPipeline::MaterialPipeline(const MaterialPipelineInfo& pipelineInfo) :
|
||||
m_pipelineInfo(pipelineInfo)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Enable pipeline states for rendering
|
||||
*
|
||||
* \param flags Shader flags
|
||||
*/
|
||||
inline const MaterialPipeline::Instance& MaterialPipeline::Apply(UInt32 flags) const
|
||||
{
|
||||
const Instance& instance = GetInstance(flags);
|
||||
instance.uberInstance->Activate();
|
||||
|
||||
Renderer::SetRenderStates(m_pipelineInfo);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Retrieve a MaterialPipelineInfo object describing this pipeline
|
||||
*
|
||||
* \return Pipeline informations
|
||||
*/
|
||||
const MaterialPipelineInfo& MaterialPipeline::GetInfo() const
|
||||
{
|
||||
return m_pipelineInfo;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Retrieve (and generate if required) a pipeline instance using shader flags without applying it
|
||||
*
|
||||
* \param flags Shader flags
|
||||
*
|
||||
* \return Pipeline instance
|
||||
*/
|
||||
inline const MaterialPipeline::Instance& MaterialPipeline::GetInstance(UInt32 flags) const
|
||||
{
|
||||
const Instance& instance = m_instances[flags];
|
||||
if (!instance.uberInstance)
|
||||
GenerateRenderPipeline(flags);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
bool operator==(const MaterialPipelineInfo& lhs, const MaterialPipelineInfo& rhs)
|
||||
{
|
||||
if (!operator==(static_cast<const RenderStates&>(lhs), static_cast<const RenderStates&>(rhs)))
|
||||
return false;
|
||||
|
||||
#define NazaraPipelineMember(field) if (lhs.field != rhs.field) return false
|
||||
#define NazaraPipelineBoolMember NazaraPipelineMember
|
||||
|
||||
NazaraPipelineBoolMember(depthSorting);
|
||||
NazaraPipelineBoolMember(hasVertexColor);
|
||||
NazaraPipelineBoolMember(reflectionMapping);
|
||||
NazaraPipelineBoolMember(shadowReceive);
|
||||
|
||||
NazaraPipelineMember(pipelineLayout);
|
||||
NazaraPipelineMember(settings);
|
||||
NazaraPipelineMember(shader);
|
||||
|
||||
#undef NazaraPipelineMember
|
||||
#undef NazaraPipelineBoolMember
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operator!=(const MaterialPipelineInfo& lhs, const MaterialPipelineInfo& rhs)
|
||||
{
|
||||
return !operator==(lhs, rhs);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Creates a new MaterialPipeline from the arguments
|
||||
* \return A reference to the newly created material pipeline
|
||||
*
|
||||
* \param args Arguments for the material pipeline
|
||||
*/
|
||||
template<typename... Args>
|
||||
MaterialPipelineRef MaterialPipeline::New(Args&&... args)
|
||||
{
|
||||
std::unique_ptr<MaterialPipeline> object(new MaterialPipeline(std::forward<Args>(args)...));
|
||||
object->SetPersistent(false);
|
||||
return object.release();
|
||||
}
|
||||
}
|
||||
|
||||
namespace std
|
||||
{
|
||||
template<>
|
||||
struct hash<Nz::MaterialPipelineInfo>
|
||||
{
|
||||
size_t operator()(const Nz::MaterialPipelineInfo& pipelineInfo) const
|
||||
{
|
||||
hash<Nz::RenderStates> parentHash;
|
||||
|
||||
std::size_t seed = parentHash(pipelineInfo);
|
||||
|
||||
Nz::UInt16 parameterHash = 0;
|
||||
Nz::UInt16 parameterIndex = 0;
|
||||
|
||||
#define NazaraPipelineMember(member) Nz::HashCombine(seed, pipelineInfo.member)
|
||||
#define NazaraPipelineBoolMember(member) parameterHash |= ((pipelineInfo.member) ? 1U : 0U) << (parameterIndex++)
|
||||
|
||||
NazaraPipelineBoolMember(alphaTest);
|
||||
NazaraPipelineBoolMember(depthSorting);
|
||||
NazaraPipelineBoolMember(hasVertexColor);
|
||||
NazaraPipelineBoolMember(reflectionMapping);
|
||||
NazaraPipelineBoolMember(shadowReceive);
|
||||
|
||||
NazaraPipelineMember(pipelineLayout.get()); //< Hash pointer
|
||||
NazaraPipelineMember(settings.get()); //< Hash pointer
|
||||
NazaraPipelineMember(shader.get());
|
||||
|
||||
#undef NazaraPipelineMember
|
||||
#undef NazaraPipelineBoolMember
|
||||
|
||||
Nz::HashCombine(seed, parameterHash);
|
||||
|
||||
return seed;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#include <Nazara/Graphics/DebugOff.hpp>
|
||||
92
include/Nazara/Graphics/MaterialSettings.hpp
Normal file
92
include/Nazara/Graphics/MaterialSettings.hpp
Normal file
@@ -0,0 +1,92 @@
|
||||
// Copyright (C) 2017 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Graphics module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_MATERIALSETTINGS_HPP
|
||||
#define NAZARA_MATERIALSETTINGS_HPP
|
||||
|
||||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <Nazara/Graphics/Enums.hpp>
|
||||
#include <Nazara/Renderer/RenderPipelineLayout.hpp>
|
||||
#include <Nazara/Utility/Enums.hpp>
|
||||
#include <array>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class MaterialSettings
|
||||
{
|
||||
public:
|
||||
using PredefinedBinding = std::array<std::size_t, PredefinedShaderBinding_Max + 1>;
|
||||
|
||||
struct SharedUniformBlock;
|
||||
struct Texture;
|
||||
struct UniformBlock;
|
||||
|
||||
inline MaterialSettings();
|
||||
inline MaterialSettings(std::vector<Texture> textures, std::vector<UniformBlock> uniformBlocks, std::vector<SharedUniformBlock> sharedUniformBlocks, const PredefinedBinding& predefinedBinding);
|
||||
MaterialSettings(const MaterialSettings&) = default;
|
||||
MaterialSettings(MaterialSettings&&) = delete;
|
||||
~MaterialSettings() = default;
|
||||
|
||||
inline std::size_t GetPredefinedBindingIndex(PredefinedShaderBinding binding) const;
|
||||
inline const std::shared_ptr<RenderPipelineLayout>& GetRenderPipelineLayout() const;
|
||||
inline const std::vector<SharedUniformBlock>& GetSharedUniformBlocks() const;
|
||||
inline std::size_t GetSharedUniformBlockVariableOffset(std::size_t uniformBlockIndex, const std::string_view& name) const;
|
||||
inline std::size_t GetSharedUniformBlockIndex(const std::string_view& name) const;
|
||||
inline const std::vector<Texture>& GetTextures() const;
|
||||
inline std::size_t GetTextureIndex(const std::string_view& name) const;
|
||||
inline const std::vector<UniformBlock>& GetUniformBlocks() const;
|
||||
inline std::size_t GetUniformBlockIndex(const std::string_view& name) const;
|
||||
inline std::size_t GetUniformBlockVariableOffset(std::size_t uniformBlockIndex, const std::string_view& name) const;
|
||||
|
||||
MaterialSettings& operator=(const MaterialSettings&) = delete;
|
||||
MaterialSettings& operator=(MaterialSettings&&) = delete;
|
||||
|
||||
static constexpr std::size_t InvalidIndex = std::numeric_limits<std::size_t>::max();
|
||||
|
||||
struct UniformVariable
|
||||
{
|
||||
std::string name;
|
||||
std::size_t offset;
|
||||
};
|
||||
|
||||
struct SharedUniformBlock
|
||||
{
|
||||
std::string name;
|
||||
std::string bindingPoint;
|
||||
std::vector<UniformVariable> uniforms;
|
||||
};
|
||||
|
||||
struct Texture
|
||||
{
|
||||
std::string bindingPoint;
|
||||
std::string name;
|
||||
ImageType type;
|
||||
};
|
||||
|
||||
struct UniformBlock
|
||||
{
|
||||
std::size_t blockSize;
|
||||
std::string name;
|
||||
std::string bindingPoint;
|
||||
std::vector<UniformVariable> uniforms;
|
||||
std::vector<UInt8> defaultValues;
|
||||
};
|
||||
|
||||
private:
|
||||
std::shared_ptr<RenderPipelineLayout> m_pipelineLayout;
|
||||
std::vector<SharedUniformBlock> m_sharedUniformBlocks;
|
||||
std::vector<Texture> m_textures;
|
||||
std::vector<UniformBlock> m_uniformBlocks;
|
||||
PredefinedBinding m_predefinedBinding;
|
||||
};
|
||||
}
|
||||
|
||||
#include <Nazara/Graphics/MaterialSettings.inl>
|
||||
|
||||
#endif // NAZARA_MATERIALPIPELINESETTINGS_HPP
|
||||
147
include/Nazara/Graphics/MaterialSettings.inl
Normal file
147
include/Nazara/Graphics/MaterialSettings.inl
Normal file
@@ -0,0 +1,147 @@
|
||||
// Copyright (C) 2017 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Graphics module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Graphics/MaterialSettings.hpp>
|
||||
#include <Nazara/Graphics/Graphics.hpp>
|
||||
#include <cassert>
|
||||
#include <Nazara/Graphics/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
inline MaterialSettings::MaterialSettings() :
|
||||
MaterialSettings({}, {}, {}, { InvalidIndex })
|
||||
{
|
||||
}
|
||||
|
||||
inline MaterialSettings::MaterialSettings(std::vector<Texture> textures, std::vector<UniformBlock> uniformBlocks, std::vector<SharedUniformBlock> sharedUniformBlocks, const PredefinedBinding& predefinedBindings) :
|
||||
m_sharedUniformBlocks(std::move(sharedUniformBlocks)),
|
||||
m_textures(std::move(textures)),
|
||||
m_uniformBlocks(std::move(uniformBlocks)),
|
||||
m_predefinedBinding(predefinedBindings)
|
||||
{
|
||||
RenderPipelineLayoutInfo info;
|
||||
|
||||
unsigned int bindingIndex = 0;
|
||||
|
||||
for (const Texture& textureInfo : m_textures)
|
||||
{
|
||||
info.bindings.push_back({
|
||||
textureInfo.bindingPoint,
|
||||
ShaderBindingType::Texture,
|
||||
ShaderStageType_All,
|
||||
bindingIndex++
|
||||
});
|
||||
}
|
||||
|
||||
for (const UniformBlock& ubo : m_uniformBlocks)
|
||||
{
|
||||
info.bindings.push_back({
|
||||
ubo.bindingPoint,
|
||||
ShaderBindingType::UniformBuffer,
|
||||
ShaderStageType_All,
|
||||
bindingIndex++
|
||||
});
|
||||
}
|
||||
|
||||
for (const SharedUniformBlock& ubo : m_sharedUniformBlocks)
|
||||
{
|
||||
info.bindings.push_back({
|
||||
ubo.bindingPoint,
|
||||
ShaderBindingType::UniformBuffer,
|
||||
ShaderStageType_All,
|
||||
bindingIndex++
|
||||
});
|
||||
}
|
||||
|
||||
m_pipelineLayout = Graphics::Instance()->GetRenderDevice().InstantiateRenderPipelineLayout(std::move(info));
|
||||
}
|
||||
|
||||
inline std::size_t MaterialSettings::GetPredefinedBindingIndex(PredefinedShaderBinding binding) const
|
||||
{
|
||||
return m_predefinedBinding[static_cast<std::size_t>(binding)];
|
||||
}
|
||||
|
||||
inline const std::shared_ptr<RenderPipelineLayout>& MaterialSettings::GetRenderPipelineLayout() const
|
||||
{
|
||||
return m_pipelineLayout;
|
||||
}
|
||||
|
||||
inline auto MaterialSettings::GetSharedUniformBlocks() const -> const std::vector<SharedUniformBlock>&
|
||||
{
|
||||
return m_sharedUniformBlocks;
|
||||
}
|
||||
|
||||
inline std::size_t MaterialSettings::GetSharedUniformBlockIndex(const std::string_view& name) const
|
||||
{
|
||||
for (std::size_t i = 0; i < m_sharedUniformBlocks.size(); ++i)
|
||||
{
|
||||
if (m_sharedUniformBlocks[i].name == name)
|
||||
return i;
|
||||
}
|
||||
|
||||
return InvalidIndex;
|
||||
}
|
||||
|
||||
inline auto MaterialSettings::GetTextures() const -> const std::vector<Texture>&
|
||||
{
|
||||
return m_textures;
|
||||
}
|
||||
|
||||
inline std::size_t MaterialSettings::GetSharedUniformBlockVariableOffset(std::size_t uniformBlockIndex, const std::string_view& name) const
|
||||
{
|
||||
assert(uniformBlockIndex < m_sharedUniformBlocks.size());
|
||||
|
||||
const std::vector<UniformVariable>& variables = m_sharedUniformBlocks[uniformBlockIndex].uniforms;
|
||||
for (std::size_t i = 0; i < variables.size(); ++i)
|
||||
{
|
||||
if (variables[i].name == name)
|
||||
return i;
|
||||
}
|
||||
|
||||
return InvalidIndex;
|
||||
}
|
||||
|
||||
inline std::size_t MaterialSettings::GetTextureIndex(const std::string_view& name) const
|
||||
{
|
||||
for (std::size_t i = 0; i < m_textures.size(); ++i)
|
||||
{
|
||||
if (m_textures[i].name == name)
|
||||
return i;
|
||||
}
|
||||
|
||||
return InvalidIndex;
|
||||
}
|
||||
|
||||
inline auto MaterialSettings::GetUniformBlocks() const -> const std::vector<UniformBlock>&
|
||||
{
|
||||
return m_uniformBlocks;
|
||||
}
|
||||
|
||||
inline std::size_t MaterialSettings::GetUniformBlockIndex(const std::string_view& name) const
|
||||
{
|
||||
for (std::size_t i = 0; i < m_uniformBlocks.size(); ++i)
|
||||
{
|
||||
if (m_uniformBlocks[i].name == name)
|
||||
return i;
|
||||
}
|
||||
|
||||
return InvalidIndex;
|
||||
}
|
||||
|
||||
inline std::size_t MaterialSettings::GetUniformBlockVariableOffset(std::size_t uniformBlockIndex, const std::string_view& name) const
|
||||
{
|
||||
assert(uniformBlockIndex < m_uniformBlocks.size());
|
||||
|
||||
const std::vector<UniformVariable>& variables = m_uniformBlocks[uniformBlockIndex].uniforms;
|
||||
for (std::size_t i = 0; i < variables.size(); ++i)
|
||||
{
|
||||
if (variables[i].name == name)
|
||||
return i;
|
||||
}
|
||||
|
||||
return InvalidIndex;
|
||||
}
|
||||
}
|
||||
|
||||
#include <Nazara/Graphics/DebugOff.hpp>
|
||||
110
include/Nazara/Graphics/PhongLightingMaterial.hpp
Normal file
110
include/Nazara/Graphics/PhongLightingMaterial.hpp
Normal file
@@ -0,0 +1,110 @@
|
||||
// Copyright (C) 2017 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Graphics module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_PHONG_LIGHTING_MATERIAL_HPP
|
||||
#define NAZARA_PHONG_LIGHTING_MATERIAL_HPP
|
||||
|
||||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <Nazara/Graphics/Material.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class NAZARA_GRAPHICS_API PhongLightingMaterial
|
||||
{
|
||||
friend class MaterialPipeline;
|
||||
|
||||
public:
|
||||
PhongLightingMaterial(Material* material);
|
||||
|
||||
inline const TextureRef& GetAlphaMap() const;
|
||||
float GetAlphaThreshold() const;
|
||||
Color GetAmbientColor() const;
|
||||
Color GetDiffuseColor() const;
|
||||
inline const TextureRef& GetDiffuseMap() const;
|
||||
inline TextureSampler& GetDiffuseSampler();
|
||||
inline const TextureSampler& GetDiffuseSampler() const;
|
||||
inline const TextureRef& GetEmissiveMap() const;
|
||||
inline const TextureRef& GetHeightMap() const;
|
||||
inline const TextureRef& GetNormalMap() const;
|
||||
float GetShininess() const;
|
||||
Color GetSpecularColor() const;
|
||||
inline const TextureRef& GetSpecularMap() const;
|
||||
inline TextureSampler& GetSpecularSampler();
|
||||
inline const TextureSampler& GetSpecularSampler() const;
|
||||
|
||||
inline bool HasAlphaMap() const;
|
||||
inline bool HasAlphaThreshold() const;
|
||||
inline bool HasAmbientColor() const;
|
||||
inline bool HasDiffuseColor() const;
|
||||
inline bool HasDiffuseMap() const;
|
||||
inline bool HasEmissiveMap() const;
|
||||
inline bool HasHeightMap() const;
|
||||
inline bool HasNormalMap() const;
|
||||
inline bool HasShininess() const;
|
||||
inline bool HasSpecularColor() const;
|
||||
inline bool HasSpecularMap() const;
|
||||
|
||||
inline bool SetAlphaMap(const String& textureName);
|
||||
inline void SetAlphaMap(TextureRef alphaMap);
|
||||
void SetAlphaThreshold(float alphaThreshold);
|
||||
void SetAmbientColor(const Color& ambient);
|
||||
void SetDiffuseColor(const Color& diffuse);
|
||||
inline bool SetDiffuseMap(const String& textureName);
|
||||
inline void SetDiffuseMap(TextureRef diffuseMap);
|
||||
inline void SetDiffuseSampler(const TextureSampler& sampler);
|
||||
inline bool SetEmissiveMap(const String& textureName);
|
||||
inline void SetEmissiveMap(TextureRef textureName);
|
||||
inline bool SetHeightMap(const String& textureName);
|
||||
inline void SetHeightMap(TextureRef textureName);
|
||||
inline bool SetNormalMap(const String& textureName);
|
||||
inline void SetNormalMap(TextureRef textureName);
|
||||
void SetShininess(float shininess);
|
||||
void SetSpecularColor(const Color& specular);
|
||||
inline bool SetSpecularMap(const String& textureName);
|
||||
inline void SetSpecularMap(TextureRef specularMap);
|
||||
inline void SetSpecularSampler(const TextureSampler& sampler);
|
||||
|
||||
static const std::shared_ptr<MaterialSettings>& GetSettings();
|
||||
|
||||
private:
|
||||
struct PhongUniformOffsets
|
||||
{
|
||||
std::size_t alphaThreshold;
|
||||
std::size_t shininess;
|
||||
std::size_t ambientColor;
|
||||
std::size_t diffuseColor;
|
||||
std::size_t specularColor;
|
||||
};
|
||||
|
||||
struct TextureIndexes
|
||||
{
|
||||
std::size_t alpha;
|
||||
std::size_t diffuse;
|
||||
std::size_t emissive;
|
||||
std::size_t height;
|
||||
std::size_t normal;
|
||||
std::size_t specular;
|
||||
};
|
||||
|
||||
static bool Initialize();
|
||||
static void Uninitialize();
|
||||
|
||||
MaterialRef m_material;
|
||||
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 RenderPipelineLayoutRef s_renderPipelineLayout;
|
||||
static TextureIndexes s_textureIndexes;
|
||||
static PhongUniformOffsets s_phongUniformOffsets;
|
||||
};
|
||||
}
|
||||
|
||||
#include <Nazara/Graphics/PhongLightingMaterial.inl>
|
||||
|
||||
#endif // NAZARA_PHONG_LIGHTING_MATERIAL_HPP
|
||||
156
include/Nazara/Graphics/PhongLightingMaterial.inl
Normal file
156
include/Nazara/Graphics/PhongLightingMaterial.inl
Normal file
@@ -0,0 +1,156 @@
|
||||
// Copyright (C) 2017 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Graphics module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Graphics/PhongLightingMaterial.hpp>
|
||||
#include <Nazara/Core/ErrorFlags.hpp>
|
||||
#include <memory>
|
||||
#include <Nazara/Graphics/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
inline const TextureRef& PhongLightingMaterial::GetAlphaMap() const
|
||||
{
|
||||
NazaraAssert(HasAlphaMap(), "Material has no alpha map slot");
|
||||
return m_material->GetTexture(m_textureIndexes.alpha);
|
||||
}
|
||||
|
||||
inline const TextureRef& PhongLightingMaterial::GetDiffuseMap() const
|
||||
{
|
||||
NazaraAssert(HasDiffuseMap(), "Material has no alpha map slot");
|
||||
return m_material->GetTexture(m_textureIndexes.diffuse);
|
||||
}
|
||||
|
||||
inline const TextureRef& PhongLightingMaterial::GetEmissiveMap() const
|
||||
{
|
||||
NazaraAssert(HasEmissiveMap(), "Material has no alpha map slot");
|
||||
return m_material->GetTexture(m_textureIndexes.emissive);
|
||||
}
|
||||
|
||||
inline const TextureRef& PhongLightingMaterial::GetHeightMap() const
|
||||
{
|
||||
NazaraAssert(HasHeightMap(), "Material has no alpha map slot");
|
||||
return m_material->GetTexture(m_textureIndexes.height);
|
||||
}
|
||||
|
||||
inline const TextureRef& PhongLightingMaterial::GetNormalMap() const
|
||||
{
|
||||
NazaraAssert(HasNormalMap(), "Material has no alpha map slot");
|
||||
return m_material->GetTexture(m_textureIndexes.normal);
|
||||
}
|
||||
|
||||
inline const TextureRef& PhongLightingMaterial::GetSpecularMap() const
|
||||
{
|
||||
NazaraAssert(HasSpecularMap(), "Material has no alpha map slot");
|
||||
return m_material->GetTexture(m_textureIndexes.specular);
|
||||
}
|
||||
|
||||
inline bool PhongLightingMaterial::HasAlphaMap() const
|
||||
{
|
||||
return m_textureIndexes.alpha != MaterialSettings::InvalidIndex;
|
||||
}
|
||||
|
||||
inline bool PhongLightingMaterial::HasAlphaThreshold() const
|
||||
{
|
||||
return m_phongUniformOffsets.alphaThreshold != MaterialSettings::InvalidIndex;
|
||||
}
|
||||
|
||||
inline bool PhongLightingMaterial::HasAmbientColor() const
|
||||
{
|
||||
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
|
||||
{
|
||||
return m_textureIndexes.emissive != MaterialSettings::InvalidIndex;
|
||||
}
|
||||
|
||||
inline bool PhongLightingMaterial::HasHeightMap() const
|
||||
{
|
||||
return m_textureIndexes.height != MaterialSettings::InvalidIndex;
|
||||
}
|
||||
|
||||
inline bool PhongLightingMaterial::HasNormalMap() const
|
||||
{
|
||||
return m_textureIndexes.normal != MaterialSettings::InvalidIndex;
|
||||
}
|
||||
|
||||
inline bool PhongLightingMaterial::HasShininess() const
|
||||
{
|
||||
return m_phongUniformOffsets.shininess != MaterialSettings::InvalidIndex;
|
||||
}
|
||||
|
||||
inline bool PhongLightingMaterial::HasSpecularColor() const
|
||||
{
|
||||
return m_phongUniformOffsets.specularColor != MaterialSettings::InvalidIndex;
|
||||
}
|
||||
|
||||
inline bool PhongLightingMaterial::HasSpecularMap() const
|
||||
{
|
||||
return m_textureIndexes.specular != MaterialSettings::InvalidIndex;
|
||||
}
|
||||
|
||||
inline void PhongLightingMaterial::SetAlphaMap(TextureRef alphaMap)
|
||||
{
|
||||
NazaraAssert(HasAlphaMap(), "Material has no alpha map slot");
|
||||
m_material->SetTexture(m_textureIndexes.alpha, std::move(alphaMap));
|
||||
}
|
||||
|
||||
inline bool PhongLightingMaterial::SetDiffuseMap(const String& textureName)
|
||||
{
|
||||
TextureRef texture = TextureLibrary::Query(textureName);
|
||||
if (!texture)
|
||||
{
|
||||
texture = TextureManager::Get(textureName);
|
||||
if (!texture)
|
||||
{
|
||||
NazaraError("Failed to get diffuse map \"" + textureName + "\"");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
SetDiffuseMap(std::move(texture));
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void PhongLightingMaterial::SetDiffuseMap(TextureRef diffuseMap)
|
||||
{
|
||||
NazaraAssert(HasDiffuseMap(), "Material has no diffuse map slot");
|
||||
m_material->SetTexture(m_textureIndexes.diffuse, std::move(diffuseMap));
|
||||
}
|
||||
|
||||
inline bool PhongLightingMaterial::SetNormalMap(const String& textureName)
|
||||
{
|
||||
TextureRef texture = TextureLibrary::Query(textureName);
|
||||
if (!texture)
|
||||
{
|
||||
texture = TextureManager::Get(textureName);
|
||||
if (!texture)
|
||||
{
|
||||
NazaraError("Failed to get normal map \"" + textureName + "\"");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
SetNormalMap(std::move(texture));
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void PhongLightingMaterial::SetNormalMap(TextureRef normalMap)
|
||||
{
|
||||
NazaraAssert(HasNormalMap(), "Material has no normal map slot");
|
||||
m_material->SetTexture(m_textureIndexes.normal, std::move(normalMap));
|
||||
}
|
||||
}
|
||||
|
||||
#include <Nazara/Graphics/DebugOff.hpp>
|
||||
68
include/Nazara/Graphics/PredefinedShaderStructs.hpp
Normal file
68
include/Nazara/Graphics/PredefinedShaderStructs.hpp
Normal file
@@ -0,0 +1,68 @@
|
||||
// Copyright (C) 2017 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Graphics module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_PREDEFINEDSHADERSTRUCTS_HPP
|
||||
#define NAZARA_PREDEFINEDSHADERSTRUCTS_HPP
|
||||
|
||||
#include <Nazara/Graphics/Config.hpp>
|
||||
#include <Nazara/Graphics/MaterialSettings.hpp>
|
||||
#include <array>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
struct NAZARA_GRAPHICS_API PredefinedLightData
|
||||
{
|
||||
struct InnerStruct
|
||||
{
|
||||
std::size_t type;
|
||||
std::size_t color;
|
||||
std::size_t factor;
|
||||
std::size_t parameter1;
|
||||
std::size_t parameter2;
|
||||
std::size_t parameter3;
|
||||
std::size_t shadowMappingFlag;
|
||||
std::size_t totalSize;
|
||||
};
|
||||
|
||||
InnerStruct innerOffsets;
|
||||
std::array<std::size_t, 3> lightArray;
|
||||
std::size_t lightArraySize;
|
||||
|
||||
static PredefinedLightData GetOffset();
|
||||
static MaterialSettings::SharedUniformBlock GetUniformBlock();
|
||||
};
|
||||
|
||||
struct NAZARA_GRAPHICS_API PredefinedInstanceData
|
||||
{
|
||||
std::size_t invWorldMatrixOffset;
|
||||
std::size_t totalSize;
|
||||
std::size_t worldMatrixOffset;
|
||||
|
||||
static PredefinedInstanceData GetOffset();
|
||||
static MaterialSettings::SharedUniformBlock GetUniformBlock();
|
||||
};
|
||||
|
||||
struct NAZARA_GRAPHICS_API PredefinedViewerData
|
||||
{
|
||||
std::size_t eyePositionOffset;
|
||||
std::size_t invProjMatrixOffset;
|
||||
std::size_t invTargetSizeOffset;
|
||||
std::size_t invViewMatrixOffset;
|
||||
std::size_t invViewProjMatrixOffset;
|
||||
std::size_t projMatrixOffset;
|
||||
std::size_t targetSizeOffset;
|
||||
std::size_t totalSize;
|
||||
std::size_t viewMatrixOffset;
|
||||
std::size_t viewProjMatrixOffset;
|
||||
|
||||
static PredefinedViewerData GetOffset();
|
||||
static MaterialSettings::SharedUniformBlock GetUniformBlock();
|
||||
};
|
||||
}
|
||||
|
||||
#include <Nazara/Graphics/PredefinedShaderStructs.inl>
|
||||
|
||||
#endif // NAZARA_PREDEFINEDSHADERSTRUCTS_HPP
|
||||
9
include/Nazara/Graphics/PredefinedShaderStructs.inl
Normal file
9
include/Nazara/Graphics/PredefinedShaderStructs.inl
Normal file
@@ -0,0 +1,9 @@
|
||||
// Copyright (C) 2017 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Graphics module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Graphics/PredefinedShaderStructs.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
}
|
||||
101
include/Nazara/Graphics/RenderQueue.hpp
Normal file
101
include/Nazara/Graphics/RenderQueue.hpp
Normal file
@@ -0,0 +1,101 @@
|
||||
// Copyright (C) 2017 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Graphics module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_RENDERQUEUE_HPP
|
||||
#define NAZARA_RENDERQUEUE_HPP
|
||||
|
||||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class RenderQueueInternal
|
||||
{
|
||||
public:
|
||||
using Index = Nz::UInt64;
|
||||
|
||||
RenderQueueInternal() = default;
|
||||
RenderQueueInternal(const RenderQueueInternal&) = default;
|
||||
RenderQueueInternal(RenderQueueInternal&&) = default;
|
||||
~RenderQueueInternal() = default;
|
||||
|
||||
RenderQueueInternal& operator=(const RenderQueueInternal&) = default;
|
||||
RenderQueueInternal& operator=(RenderQueueInternal&&) = default;
|
||||
|
||||
protected:
|
||||
using RenderDataPair = std::pair<Index, std::size_t>;
|
||||
|
||||
void Sort();
|
||||
|
||||
std::vector<RenderDataPair> m_orderedRenderQueue;
|
||||
};
|
||||
|
||||
template<typename RenderData>
|
||||
class RenderQueue : public RenderQueueInternal
|
||||
{
|
||||
public:
|
||||
class const_iterator;
|
||||
friend const_iterator;
|
||||
using size_type = std::size_t;
|
||||
|
||||
RenderQueue() = default;
|
||||
RenderQueue(const RenderQueue&) = default;
|
||||
RenderQueue(RenderQueue&&) noexcept = default;
|
||||
~RenderQueue() = default;
|
||||
|
||||
void Clear();
|
||||
|
||||
void Insert(RenderData&& data);
|
||||
|
||||
template<typename IndexFunc> void Sort(IndexFunc&& func);
|
||||
|
||||
// STL API
|
||||
inline const_iterator begin() const;
|
||||
inline bool empty() const;
|
||||
inline const_iterator end() const;
|
||||
inline size_type size() const;
|
||||
|
||||
RenderQueue& operator=(const RenderQueue&) = default;
|
||||
RenderQueue& operator=(RenderQueue&&) noexcept = default;
|
||||
|
||||
private:
|
||||
const RenderData& GetData(std::size_t i) const;
|
||||
|
||||
std::vector<RenderData> m_data;
|
||||
};
|
||||
|
||||
template<typename RenderData>
|
||||
class RenderQueue<RenderData>::const_iterator : public std::iterator<std::forward_iterator_tag, const RenderData>
|
||||
{
|
||||
friend RenderQueue;
|
||||
|
||||
public:
|
||||
const_iterator(const const_iterator& it);
|
||||
|
||||
const RenderData& operator*() const;
|
||||
|
||||
const_iterator& operator=(const const_iterator& it);
|
||||
const_iterator& operator++();
|
||||
const_iterator operator++(int);
|
||||
|
||||
bool operator==(const const_iterator& rhs) const;
|
||||
bool operator!=(const const_iterator& rhs) const;
|
||||
|
||||
void swap(const_iterator& rhs);
|
||||
|
||||
private:
|
||||
const_iterator(const RenderQueue* queue, std::size_t nextId);
|
||||
|
||||
std::size_t m_nextDataId;
|
||||
const RenderQueue* m_queue;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#include <Nazara/Graphics/RenderQueue.inl>
|
||||
|
||||
#endif // NAZARA_RENDERQUEUE_HPP
|
||||
136
include/Nazara/Graphics/RenderQueue.inl
Normal file
136
include/Nazara/Graphics/RenderQueue.inl
Normal file
@@ -0,0 +1,136 @@
|
||||
// Copyright (C) 2017 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Graphics module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Graphics/RenderQueue.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
template<typename RenderData>
|
||||
void RenderQueue<RenderData>::Clear()
|
||||
{
|
||||
m_orderedRenderQueue.clear();
|
||||
m_data.clear();
|
||||
}
|
||||
|
||||
template<typename RenderData>
|
||||
void RenderQueue<RenderData>::Insert(RenderData&& data)
|
||||
{
|
||||
m_data.emplace_back(std::move(data));
|
||||
}
|
||||
|
||||
template<typename RenderData>
|
||||
template<typename IndexFunc>
|
||||
void RenderQueue<RenderData>::Sort(IndexFunc&& func)
|
||||
{
|
||||
m_orderedRenderQueue.clear();
|
||||
m_orderedRenderQueue.reserve(m_data.size());
|
||||
|
||||
std::size_t dataIndex = 0;
|
||||
for (const RenderData& renderData : m_data)
|
||||
m_orderedRenderQueue.emplace_back(func(renderData), dataIndex++);
|
||||
|
||||
RenderQueueInternal::Sort();
|
||||
}
|
||||
|
||||
template<typename RenderData>
|
||||
typename RenderQueue<RenderData>::const_iterator RenderQueue<RenderData>::begin() const
|
||||
{
|
||||
return const_iterator(this, 0);
|
||||
}
|
||||
|
||||
template<typename RenderData>
|
||||
bool RenderQueue<RenderData>::empty() const
|
||||
{
|
||||
return m_orderedRenderQueue.empty();
|
||||
}
|
||||
|
||||
template<typename RenderData>
|
||||
typename RenderQueue<RenderData>::const_iterator RenderQueue<RenderData>::end() const
|
||||
{
|
||||
return const_iterator(this, m_orderedRenderQueue.size());
|
||||
}
|
||||
|
||||
template<typename RenderData>
|
||||
typename RenderQueue<RenderData>::size_type RenderQueue<RenderData>::size() const
|
||||
{
|
||||
return m_orderedRenderQueue.size();
|
||||
}
|
||||
|
||||
template<typename RenderData>
|
||||
const RenderData& RenderQueue<RenderData>::GetData(std::size_t i) const
|
||||
{
|
||||
NazaraAssert(i < m_orderedRenderQueue.size(), "Cannot dereference post-end iterator");
|
||||
|
||||
return m_data[m_orderedRenderQueue[i].second];
|
||||
}
|
||||
|
||||
|
||||
template<typename RenderData>
|
||||
RenderQueue<RenderData>::const_iterator::const_iterator(const RenderQueue* queue, std::size_t nextId) :
|
||||
m_nextDataId(nextId),
|
||||
m_queue(queue)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename RenderData>
|
||||
RenderQueue<RenderData>::const_iterator::const_iterator(const const_iterator& it) :
|
||||
m_nextDataId(it.m_nextDataId),
|
||||
m_queue(it.m_queue)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename RenderData>
|
||||
const RenderData& RenderQueue<RenderData>::const_iterator::operator*() const
|
||||
{
|
||||
return m_queue->GetData(m_nextDataId);
|
||||
}
|
||||
|
||||
template<typename RenderData>
|
||||
typename RenderQueue<RenderData>::const_iterator& RenderQueue<RenderData>::const_iterator::operator=(const const_iterator& it)
|
||||
{
|
||||
m_nextDataId = it.m_nextDataId;
|
||||
m_queue = it.m_queue;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename RenderData>
|
||||
typename RenderQueue<RenderData>::const_iterator& RenderQueue<RenderData>::const_iterator::operator++()
|
||||
{
|
||||
++m_nextDataId;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename RenderData>
|
||||
typename RenderQueue<RenderData>::const_iterator RenderQueue<RenderData>::const_iterator::operator++(int)
|
||||
{
|
||||
return iterator(m_queue, m_nextDataId++);
|
||||
}
|
||||
|
||||
template<typename RenderData>
|
||||
bool RenderQueue<RenderData>::const_iterator::operator==(const typename RenderQueue<RenderData>::const_iterator& rhs) const
|
||||
{
|
||||
NazaraAssert(m_queue == rhs.m_queue, "Cannot compare iterator coming from different queues");
|
||||
|
||||
return m_nextDataId == rhs.m_nextDataId;
|
||||
}
|
||||
|
||||
template<typename RenderData>
|
||||
bool RenderQueue<RenderData>::const_iterator::operator!=(const typename RenderQueue<RenderData>::const_iterator& rhs) const
|
||||
{
|
||||
return !operator==(rhs);
|
||||
}
|
||||
|
||||
template<typename RenderData>
|
||||
void RenderQueue<RenderData>::const_iterator::swap(typename RenderQueue<RenderData>::const_iterator& rhs)
|
||||
{
|
||||
NazaraAssert(m_queue == rhs.m_queue, "Cannot swap iterator coming from different queues");
|
||||
|
||||
using std::swap;
|
||||
|
||||
swap(m_nextDataId, rhs.m_nextDataId);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user