Documentation for module: Graphics
Former-commit-id: 5e3ee3c61779fbdd1a083117f537a45e1bad820b
This commit is contained in:
parent
6400ba2e28
commit
96b958d655
|
|
@ -7,6 +7,10 @@
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \brief Constructs a Billboard object by default
|
||||
*/
|
||||
|
||||
inline Billboard::Billboard()
|
||||
{
|
||||
SetColor(Color::White);
|
||||
|
|
@ -15,6 +19,12 @@ namespace Nz
|
|||
SetSize(64.f, 64.f);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Constructs a Billboard object with a reference to a material
|
||||
*
|
||||
* \param material Reference to a material
|
||||
*/
|
||||
|
||||
inline Billboard::Billboard(MaterialRef material)
|
||||
{
|
||||
SetColor(Color::White);
|
||||
|
|
@ -23,6 +33,12 @@ namespace Nz
|
|||
SetSize(64.f, 64.f);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Constructs a Billboard object with a pointer to a texture
|
||||
*
|
||||
* \param texture Pointer to a texture
|
||||
*/
|
||||
|
||||
inline Billboard::Billboard(Texture* texture)
|
||||
{
|
||||
SetColor(Color::White);
|
||||
|
|
@ -31,6 +47,12 @@ namespace Nz
|
|||
SetTexture(texture, true);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Constructs a Billboard object by assignation
|
||||
*
|
||||
* \param billboard Billboard to copy into this
|
||||
*/
|
||||
|
||||
inline Billboard::Billboard(const Billboard& billboard) :
|
||||
InstancedRenderable(billboard),
|
||||
m_color(billboard.m_color),
|
||||
|
|
@ -41,31 +63,61 @@ namespace Nz
|
|||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the color of the billboard
|
||||
* \return Current color
|
||||
*/
|
||||
|
||||
inline const Color& Billboard::GetColor() const
|
||||
{
|
||||
return m_color;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the material of the billboard
|
||||
* \return Current material
|
||||
*/
|
||||
|
||||
inline const MaterialRef& Billboard::GetMaterial() const
|
||||
{
|
||||
return m_material;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the rotation of the billboard
|
||||
* \return Current rotation
|
||||
*/
|
||||
|
||||
inline float Billboard::GetRotation() const
|
||||
{
|
||||
return m_rotation;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the size of the billboard
|
||||
* \return Current size
|
||||
*/
|
||||
|
||||
inline const Vector2f& Billboard::GetSize() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the color of the billboard
|
||||
*
|
||||
* \param color Color for the billboard
|
||||
*/
|
||||
|
||||
inline void Billboard::SetColor(const Color& color)
|
||||
{
|
||||
m_color = color;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the default material of the billboard (just default material)
|
||||
*/
|
||||
|
||||
inline void Billboard::SetDefaultMaterial()
|
||||
{
|
||||
MaterialRef material = Material::New();
|
||||
|
|
@ -75,6 +127,13 @@ namespace Nz
|
|||
SetMaterial(std::move(material));
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the material of the billboard
|
||||
*
|
||||
* \param material Material for the billboard
|
||||
* \param resizeBillboard Should billboard be resized to the material size (diffuse map)
|
||||
*/
|
||||
|
||||
inline void Billboard::SetMaterial(MaterialRef material, bool resizeBillboard)
|
||||
{
|
||||
m_material = std::move(material);
|
||||
|
|
@ -86,25 +145,51 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the rotation of the billboard
|
||||
*
|
||||
* \param rotation Rotation for the billboard
|
||||
*/
|
||||
|
||||
inline void Billboard::SetRotation(float rotation)
|
||||
{
|
||||
m_rotation = rotation;
|
||||
m_sinCos.Set(std::sin(m_rotation), std::cos(m_rotation));
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the size of the billboard
|
||||
*
|
||||
* \param size Size for the billboard
|
||||
*/
|
||||
|
||||
inline void Billboard::SetSize(const Vector2f& size)
|
||||
{
|
||||
m_size = size;
|
||||
|
||||
// On invalide la bounding box
|
||||
// We invalidate the bounding volume
|
||||
InvalidateBoundingVolume();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the size of the billboard
|
||||
*
|
||||
* \param sizeX Size in X for the billboard
|
||||
* \param sizeY Size in Y for the billboard
|
||||
*/
|
||||
|
||||
inline void Billboard::SetSize(float sizeX, float sizeY)
|
||||
{
|
||||
SetSize(Vector2f(sizeX, sizeY));
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the texture of the billboard
|
||||
*
|
||||
* \param texture Texture for the billboard
|
||||
* \param resizeBillboard Should billboard be resized to the texture size
|
||||
*/
|
||||
|
||||
inline void Billboard::SetTexture(TextureRef texture, bool resizeBillboard)
|
||||
{
|
||||
if (!m_material)
|
||||
|
|
@ -118,6 +203,13 @@ namespace Nz
|
|||
m_material->SetDiffuseMap(std::move(texture));
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the current billboard with the content of the other one
|
||||
* \return A reference to this
|
||||
*
|
||||
* \param billboard The other Billboard
|
||||
*/
|
||||
|
||||
inline Billboard& Billboard::operator=(const Billboard& billboard)
|
||||
{
|
||||
InstancedRenderable::operator=(billboard);
|
||||
|
|
@ -131,6 +223,13 @@ namespace Nz
|
|||
return *this;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Creates a new billboard from the arguments
|
||||
* \return A reference to the newly created billboard
|
||||
*
|
||||
* \param args Arguments for the billboard
|
||||
*/
|
||||
|
||||
template<typename... Args>
|
||||
BillboardRef Billboard::New(Args&&... args)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -7,6 +7,13 @@
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \brief Creates a new color background from the arguments
|
||||
* \return A reference to the newly created color background
|
||||
*
|
||||
* \param args Arguments for the color background
|
||||
*/
|
||||
|
||||
template<typename... Args>
|
||||
ColorBackgroundRef ColorBackground::New(Args&&... args)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -27,23 +27,28 @@
|
|||
#ifndef NAZARA_CONFIG_GRAPHICS_HPP
|
||||
#define NAZARA_CONFIG_GRAPHICS_HPP
|
||||
|
||||
/// Chaque modification d'un paramètre du module nécessite une recompilation de celui-ci
|
||||
/*!
|
||||
* \defgroup graphics (NazaraGraphics) Graphics module
|
||||
* Graphics/System module including classes to handle graphical elements...
|
||||
*/
|
||||
|
||||
// À partir de combien d'instances d'un même mesh/matériau l'instancing doit-il être utilisé ?
|
||||
/// Each modification of a paramater of the module needs a recompilation of the unit
|
||||
|
||||
// How much instances are need of a same mesh/material to enable instancing ?
|
||||
#define NAZARA_GRAPHICS_INSTANCING_MIN_INSTANCES_COUNT 10
|
||||
|
||||
// Utilise un manager de mémoire pour gérer les allocations dynamiques (détecte les leaks au prix d'allocations/libérations dynamiques plus lentes)
|
||||
// Use the MemoryManager to manage dynamic allocations (can detect memory leak but allocations/frees are slower)
|
||||
#define NAZARA_GRAPHICS_MANAGE_MEMORY 0
|
||||
|
||||
// Active les tests de sécurité basés sur le code (Conseillé pour le développement)
|
||||
// Activate the security tests based on the code (Advised for development)
|
||||
#define NAZARA_GRAPHICS_SAFE 1
|
||||
|
||||
/// Chaque modification d'un paramètre ci-dessous implique une modification (souvent mineure) du code
|
||||
/// Each modification of a parameter following implies a modification (often minor) of the code
|
||||
|
||||
// Le nombre maximum de lumières qu'un shader standard supportera
|
||||
// The maximum number of lights in a standard shader
|
||||
#define NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS 3
|
||||
|
||||
/// Vérification des valeurs et types de certaines constantes
|
||||
/// Checking the values and types of certain constants
|
||||
#include <Nazara/Graphics/ConfigCheck.hpp>
|
||||
|
||||
#if defined(NAZARA_STATIC)
|
||||
|
|
|
|||
|
|
@ -7,12 +7,12 @@
|
|||
#ifndef NAZARA_CONFIG_CHECK_GRAPHICS_HPP
|
||||
#define NAZARA_CONFIG_CHECK_GRAPHICS_HPP
|
||||
|
||||
/// Ce fichier sert à vérifier la valeur des constantes du fichier Config.hpp
|
||||
/// This file is used to check the constant values defined in Config.hpp
|
||||
|
||||
#include <type_traits>
|
||||
#define NazaraCheckTypeAndVal(name, type, op, val, err) static_assert(std::is_ ##type <decltype(name)>::value && name op val, #type err)
|
||||
|
||||
// On force la valeur de MANAGE_MEMORY en mode debug
|
||||
// We fore the value of MANAGE_MEMORY in debug
|
||||
#if defined(NAZARA_DEBUG) && !NAZARA_GRAPHICS_MANAGE_MEMORY
|
||||
#undef NAZARA_GRAPHICS_MANAGE_MEMORY
|
||||
#define NAZARA_GRAPHICS_MANAGE_MEMORY 0
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
// This file is part of the "Nazara Engine - Graphics module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
// On suppose que Debug.hpp a déjà été inclus, tout comme Config.hpp
|
||||
// We suppose that Debug.hpp is already included, same goes for Config.hpp
|
||||
#if NAZARA_GRAPHICS_MANAGE_MEMORY
|
||||
#undef delete
|
||||
#undef new
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ namespace Nz
|
|||
float GetBrightThreshold() const;
|
||||
Texture* GetTexture(unsigned int i) const;
|
||||
|
||||
bool Process(const SceneData& sceneData, unsigned int firstWorkTexture, unsigned secondWorkTexture) const;
|
||||
bool Process(const SceneData& sceneData, unsigned int firstWorkTexture, unsigned int secondWorkTexture) const;
|
||||
bool Resize(const Vector2ui& dimensions);
|
||||
|
||||
void SetBlurPassCount(unsigned int passCount);
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ namespace Nz
|
|||
DeferredDOFPass();
|
||||
virtual ~DeferredDOFPass();
|
||||
|
||||
bool Process(const SceneData& sceneData, unsigned int firstWorkTexture, unsigned secondWorkTexture) const;
|
||||
bool Process(const SceneData& sceneData, unsigned int firstWorkTexture, unsigned int secondWorkTexture) const;
|
||||
bool Resize(const Vector2ui& dimensions);
|
||||
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ namespace Nz
|
|||
DeferredFXAAPass();
|
||||
virtual ~DeferredFXAAPass();
|
||||
|
||||
bool Process(const SceneData& sceneData, unsigned int firstWorkTexture, unsigned secondWorkTexture) const;
|
||||
bool Process(const SceneData& sceneData, unsigned int firstWorkTexture, unsigned int secondWorkTexture) const;
|
||||
|
||||
protected:
|
||||
RenderStates m_states;
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ namespace Nz
|
|||
DeferredFinalPass();
|
||||
virtual ~DeferredFinalPass();
|
||||
|
||||
bool Process(const SceneData& sceneData, unsigned int firstWorkTexture, unsigned secondWorkTexture) const;
|
||||
bool Process(const SceneData& sceneData, unsigned int firstWorkTexture, unsigned int secondWorkTexture) const;
|
||||
|
||||
protected:
|
||||
RenderStates m_states;
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ namespace Nz
|
|||
DeferredFogPass();
|
||||
virtual ~DeferredFogPass();
|
||||
|
||||
bool Process(const SceneData& sceneData, unsigned int firstWorkTexture, unsigned secondWorkTexture) const;
|
||||
bool Process(const SceneData& sceneData, unsigned int firstWorkTexture, unsigned int secondWorkTexture) const;
|
||||
|
||||
protected:
|
||||
RenderStates m_states;
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ namespace Nz
|
|||
virtual ~DeferredForwardPass();
|
||||
|
||||
void Initialize(DeferredRenderTechnique* technique);
|
||||
bool Process(const SceneData& sceneData, unsigned int workTexture, unsigned sceneTexture) const;
|
||||
bool Process(const SceneData& sceneData, unsigned int workTexture, unsigned int sceneTexture) const;
|
||||
|
||||
protected:
|
||||
const ForwardRenderTechnique* m_forwardTechnique;
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ namespace Nz
|
|||
DeferredGeometryPass();
|
||||
virtual ~DeferredGeometryPass();
|
||||
|
||||
bool Process(const SceneData& sceneData, unsigned int firstWorkTexture, unsigned secondWorkTexture) const;
|
||||
bool Process(const SceneData& sceneData, unsigned int firstWorkTexture, unsigned int secondWorkTexture) const;
|
||||
bool Resize(const Vector2ui& dimensions);
|
||||
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ namespace Nz
|
|||
|
||||
bool IsLightMeshesDrawingEnabled() const;
|
||||
|
||||
bool Process(const SceneData& sceneData, unsigned int firstWorkTexture, unsigned secondWorkTexture) const;
|
||||
bool Process(const SceneData& sceneData, unsigned int firstWorkTexture, unsigned int secondWorkTexture) const;
|
||||
|
||||
protected:
|
||||
LightUniforms m_directionalLightUniforms;
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ namespace Nz
|
|||
|
||||
bool IsEnabled() const;
|
||||
|
||||
virtual bool Process(const SceneData& sceneData, unsigned int workTexture, unsigned sceneTexture) const = 0;
|
||||
virtual bool Process(const SceneData& sceneData, unsigned int workTexture, unsigned int sceneTexture) const = 0;
|
||||
virtual bool Resize(const Vector2ui& GBufferSize);
|
||||
|
||||
DeferredRenderPass& operator=(const DeferredRenderPass&) = delete;
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ namespace Nz
|
|||
};
|
||||
|
||||
std::map<RenderPassType, std::map<int, std::unique_ptr<DeferredRenderPass>>, RenderPassComparator> m_passes;
|
||||
ForwardRenderTechnique m_forwardTechnique; // Doit être initialisé avant la RenderQueue
|
||||
ForwardRenderTechnique m_forwardTechnique; // Must be initialized before the RenderQueue
|
||||
DeferredRenderQueue m_renderQueue;
|
||||
mutable RenderBufferRef m_depthStencilBuffer;
|
||||
mutable RenderTexture m_GBufferRTT;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,14 @@
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
|
||||
/*!
|
||||
* \brief Checks whether the material is suitable to fit in the render queue
|
||||
* \return true If it is the case
|
||||
*
|
||||
* \param material Material to verify
|
||||
*/
|
||||
|
||||
bool DepthRenderQueue::IsMaterialSuitable(const Material* material) const
|
||||
{
|
||||
NazaraAssert(material, "Invalid material");
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@ namespace Nz
|
|||
SceneNodeType_Max = SceneNodeType_User
|
||||
};
|
||||
|
||||
// Ces paramètres sont indépendants du matériau: ils peuvent être demandés à tout moment
|
||||
// These parameters are independant of the material: they can not be asked for the moment
|
||||
enum ShaderFlags
|
||||
{
|
||||
ShaderFlags_None = 0,
|
||||
|
|
@ -139,7 +139,7 @@ namespace Nz
|
|||
ShaderFlags_TextureOverlay = 0x08,
|
||||
ShaderFlags_VertexColor = 0x10,
|
||||
|
||||
ShaderFlags_Max = ShaderFlags_VertexColor*2-1
|
||||
ShaderFlags_Max = ShaderFlags_VertexColor * 2 - 1
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -159,6 +159,7 @@ namespace Nz
|
|||
std::map<int, Layer> layers;
|
||||
|
||||
private:
|
||||
BillboardData* GetBillboardData(int renderOrder, const Material* material, unsigned int count);
|
||||
Layer& GetLayer(int i); ///TODO: Inline
|
||||
|
||||
void OnIndexBufferInvalidation(const IndexBuffer* indexBuffer);
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ namespace Nz
|
|||
AbstractRenderQueue* GetRenderQueue() override;
|
||||
RenderTechniqueType GetType() const override;
|
||||
|
||||
void SetMaxLightPassPerObject(unsigned int passCount);
|
||||
void SetMaxLightPassPerObject(unsigned int maxLightPassPerObject);
|
||||
|
||||
static bool Initialize();
|
||||
static void Uninitialize();
|
||||
|
|
@ -70,11 +70,11 @@ namespace Nz
|
|||
LightUniforms lightUniforms;
|
||||
bool hasLightUniforms;
|
||||
|
||||
/// Moins coûteux en mémoire que de stocker un LightUniforms par index de lumière,
|
||||
/// à voir si ça fonctionne chez tout le monde
|
||||
int lightOffset; // "Distance" entre Lights[0].type et Lights[1].type
|
||||
/// Less costly in memory than storing a LightUniforms by index of light,
|
||||
/// this may not work everywhere
|
||||
int lightOffset; // "Distance" between Lights[0].type and Lights[1].type
|
||||
|
||||
// Autre uniformes
|
||||
// Other uniforms
|
||||
int eyePosition;
|
||||
int sceneAmbient;
|
||||
int textureOverlay;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,16 @@
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \brief Sens the uniforms for light
|
||||
*
|
||||
* \param shader Shader to send uniforms to
|
||||
* \param uniforms Uniforms to send
|
||||
* \param index Index of the light
|
||||
* \param uniformOffset Offset for the uniform
|
||||
* \param availableTextureUnit Unit texture available
|
||||
*/
|
||||
|
||||
inline void ForwardRenderTechnique::SendLightUniforms(const Shader* shader, const LightUniforms& uniforms, unsigned int index, unsigned int uniformOffset, UInt8 availableTextureUnit) const
|
||||
{
|
||||
// If anyone got a better idea..
|
||||
|
|
@ -104,6 +114,14 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Computes the score for directional light
|
||||
* \return 0.f
|
||||
*
|
||||
* \param object Sphere symbolising the object
|
||||
* \param light Light to compute
|
||||
*/
|
||||
|
||||
inline float ForwardRenderTechnique::ComputeDirectionalLightScore(const Spheref& object, const AbstractRenderQueue::DirectionalLight& light)
|
||||
{
|
||||
NazaraUnused(object);
|
||||
|
|
@ -113,18 +131,42 @@ namespace Nz
|
|||
return 0.f;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Computes the score for point light
|
||||
* \return Distance to the light
|
||||
*
|
||||
* \param object Sphere symbolising the object
|
||||
* \param light Light to compute
|
||||
*/
|
||||
|
||||
inline float ForwardRenderTechnique::ComputePointLightScore(const Spheref& object, const AbstractRenderQueue::PointLight& light)
|
||||
{
|
||||
///TODO: Compute a score depending on the light luminosity
|
||||
return object.SquaredDistance(light.position);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Computes the score for spot light
|
||||
* \return Distance to the light
|
||||
*
|
||||
* \param object Sphere symbolising the object
|
||||
* \param light Light to compute
|
||||
*/
|
||||
|
||||
inline float ForwardRenderTechnique::ComputeSpotLightScore(const Spheref& object, const AbstractRenderQueue::SpotLight& light)
|
||||
{
|
||||
///TODO: Compute a score depending on the light luminosity and spot direction
|
||||
return object.SquaredDistance(light.position);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether the directional light is suitable for the computations
|
||||
* \return true if light is enoughly close
|
||||
*
|
||||
* \param object Sphere symbolising the object
|
||||
* \param light Light to compute
|
||||
*/
|
||||
|
||||
inline bool ForwardRenderTechnique::IsDirectionalLightSuitable(const Spheref& object, const AbstractRenderQueue::DirectionalLight& light)
|
||||
{
|
||||
NazaraUnused(object);
|
||||
|
|
@ -134,12 +176,28 @@ namespace Nz
|
|||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether the point light is suitable for the computations
|
||||
* \return true if light is enoughly close
|
||||
*
|
||||
* \param object Sphere symbolising the object
|
||||
* \param light Light to compute
|
||||
*/
|
||||
|
||||
inline bool ForwardRenderTechnique::IsPointLightSuitable(const Spheref& object, const AbstractRenderQueue::PointLight& light)
|
||||
{
|
||||
// If the object is too far away from this point light, there is not way it could light it
|
||||
return object.SquaredDistance(light.position) <= light.radius * light.radius;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether the spot light is suitable for the computations
|
||||
* \return true if light is enoughly close
|
||||
*
|
||||
* \param object Sphere symbolising the object
|
||||
* \param light Light to compute
|
||||
*/
|
||||
|
||||
inline bool ForwardRenderTechnique::IsSpotLightSuitable(const Spheref& object, const AbstractRenderQueue::SpotLight& light)
|
||||
{
|
||||
///TODO: Exclude spot lights based on their direction and outer angle?
|
||||
|
|
|
|||
|
|
@ -4,6 +4,12 @@
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \brief Constructs a InstancedRenderable object by assignation
|
||||
*
|
||||
* \param renderable InstancedRenderable to copy into this
|
||||
*/
|
||||
|
||||
inline InstancedRenderable::InstancedRenderable(const InstancedRenderable& renderable) :
|
||||
RefCounted(),
|
||||
m_boundingVolume(renderable.m_boundingVolume),
|
||||
|
|
@ -11,22 +17,43 @@ namespace Nz
|
|||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Ensures that the bounding volume is up to date
|
||||
*/
|
||||
|
||||
inline void InstancedRenderable::EnsureBoundingVolumeUpdated() const
|
||||
{
|
||||
if (!m_boundingVolumeUpdated)
|
||||
UpdateBoundingVolume();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Invalidates the bounding volume
|
||||
*/
|
||||
|
||||
inline void InstancedRenderable::InvalidateBoundingVolume()
|
||||
{
|
||||
m_boundingVolumeUpdated = false;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Invalidates the instance data based on flags
|
||||
*
|
||||
* \param flags Flags to invalidate
|
||||
*/
|
||||
|
||||
inline void InstancedRenderable::InvalidateInstanceData(UInt32 flags)
|
||||
{
|
||||
OnInstancedRenderableInvalidateData(this, flags);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the current instanced renderable with the content of the other one
|
||||
* \return A reference to this
|
||||
*
|
||||
* \param renderable The other InstancedRenderable
|
||||
*/
|
||||
|
||||
inline InstancedRenderable& InstancedRenderable::operator=(const InstancedRenderable& renderable)
|
||||
{
|
||||
m_boundingVolume = renderable.m_boundingVolume;
|
||||
|
|
@ -35,6 +62,10 @@ namespace Nz
|
|||
return *this;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Updates the bounding volume
|
||||
*/
|
||||
|
||||
inline void InstancedRenderable::UpdateBoundingVolume() const
|
||||
{
|
||||
MakeBoundingVolume();
|
||||
|
|
|
|||
|
|
@ -7,6 +7,10 @@
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \brief Constructs a Light object by default
|
||||
*/
|
||||
|
||||
inline Light::Light(const Light& light) :
|
||||
Renderable(light),
|
||||
m_color(light.m_color),
|
||||
|
|
@ -28,6 +32,12 @@ namespace Nz
|
|||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Enables shadow casting
|
||||
*
|
||||
* \param castShadows Should shadows be cast
|
||||
*/
|
||||
|
||||
inline void Light::EnableShadowCasting(bool castShadows)
|
||||
{
|
||||
if (m_shadowCastingEnabled != castShadows)
|
||||
|
|
@ -37,72 +47,141 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Ensures that the shadow map is up to date
|
||||
*/
|
||||
|
||||
inline void Light::EnsureShadowMapUpdate() const
|
||||
{
|
||||
if (!m_shadowMapUpdated)
|
||||
UpdateShadowMap();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the ambient factor
|
||||
* \return Current ambient factor
|
||||
*/
|
||||
|
||||
inline float Light::GetAmbientFactor() const
|
||||
{
|
||||
return m_ambientFactor;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the light attenuation (in 1 / R^2)
|
||||
* \return Attenuation
|
||||
*/
|
||||
|
||||
inline float Light::GetAttenuation() const
|
||||
{
|
||||
return m_attenuation;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the color of the light
|
||||
* \return Light color
|
||||
*/
|
||||
|
||||
inline Color Light::GetColor() const
|
||||
{
|
||||
return m_color;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the diffuse factor
|
||||
* \return Current diffuse factor
|
||||
*/
|
||||
|
||||
inline float Light::GetDiffuseFactor() const
|
||||
{
|
||||
return m_diffuseFactor;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the inner angle in spot light
|
||||
* \return Inner angle
|
||||
*/
|
||||
|
||||
inline float Light::GetInnerAngle() const
|
||||
{
|
||||
return m_innerAngle;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the cosine inner angle in spot light
|
||||
* \return Cosine inner angle
|
||||
*/
|
||||
|
||||
inline float Light::GetInnerAngleCosine() const
|
||||
{
|
||||
return m_innerAngleCosine;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the inverse of the radius
|
||||
* \return Inverse of the radius
|
||||
*/
|
||||
|
||||
inline float Light::GetInvRadius() const
|
||||
{
|
||||
return m_invRadius;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the type of the light
|
||||
* \return Light type
|
||||
*/
|
||||
|
||||
inline LightType Light::GetLightType() const
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the outer angle in spot light
|
||||
* \return Outer angle
|
||||
*/
|
||||
|
||||
inline float Light::GetOuterAngle() const
|
||||
{
|
||||
return m_outerAngle;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the cosine outer angle in spot light
|
||||
* \return Cosine outer angle
|
||||
*/
|
||||
|
||||
inline float Light::GetOuterAngleCosine() const
|
||||
{
|
||||
return m_outerAngleCosine;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the tangent outer angle in spot light
|
||||
* \return Tangent outer angle
|
||||
*/
|
||||
|
||||
inline float Light::GetOuterAngleTangent() const
|
||||
{
|
||||
return m_outerAngleTangent;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the radius of the light
|
||||
* \return Light radius
|
||||
*/
|
||||
|
||||
inline float Light::GetRadius() const
|
||||
{
|
||||
return m_radius;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the shadow map
|
||||
* \return Reference to the shadow map texture
|
||||
*/
|
||||
|
||||
inline TextureRef Light::GetShadowMap() const
|
||||
{
|
||||
EnsureShadowMapUpdate();
|
||||
|
|
@ -110,47 +189,97 @@ namespace Nz
|
|||
return m_shadowMap;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the format of the shadow map
|
||||
* \return Shadow map format
|
||||
*/
|
||||
|
||||
inline PixelFormatType Light::GetShadowMapFormat() const
|
||||
{
|
||||
return m_shadowMapFormat;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the size of the shadow map
|
||||
* \return Shadow map size
|
||||
*/
|
||||
|
||||
inline const Vector2ui& Light::GetShadowMapSize() const
|
||||
{
|
||||
return m_shadowMapSize;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether the shadow casting is enabled
|
||||
* \return true If it is the case
|
||||
*/
|
||||
|
||||
inline bool Light::IsShadowCastingEnabled() const
|
||||
{
|
||||
return m_shadowCastingEnabled;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the ambient factor
|
||||
*
|
||||
* \param factor Ambient factor
|
||||
*/
|
||||
|
||||
inline void Light::SetAmbientFactor(float factor)
|
||||
{
|
||||
m_ambientFactor = factor;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the light attenuation (in 1 / R^2)
|
||||
*
|
||||
* \param attenuation Light attenuation
|
||||
*/
|
||||
|
||||
inline void Light::SetAttenuation(float attenuation)
|
||||
{
|
||||
m_attenuation = attenuation;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the color of the light
|
||||
*
|
||||
* \param color Light color
|
||||
*/
|
||||
|
||||
inline void Light::SetColor(const Color& color)
|
||||
{
|
||||
m_color = color;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the diffuse factor
|
||||
*
|
||||
* \param factor Diffuse factor
|
||||
*/
|
||||
|
||||
inline void Light::SetDiffuseFactor(float factor)
|
||||
{
|
||||
m_diffuseFactor = factor;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the inner angle in spot light
|
||||
* \return innerAngle Inner angle
|
||||
*/
|
||||
|
||||
inline void Light::SetInnerAngle(float innerAngle)
|
||||
{
|
||||
m_innerAngle = innerAngle;
|
||||
m_innerAngleCosine = std::cos(DegreeToRadian(m_innerAngle));
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the type of light
|
||||
*
|
||||
* \param type Light type
|
||||
*/
|
||||
|
||||
inline void Light::SetLightType(LightType type)
|
||||
{
|
||||
m_type = type;
|
||||
|
|
@ -158,6 +287,13 @@ namespace Nz
|
|||
InvalidateShadowMap();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the outer angle in spot light
|
||||
* \return outerAngle Outer angle
|
||||
*
|
||||
* \remark Invalidates the bounding volume
|
||||
*/
|
||||
|
||||
inline void Light::SetOuterAngle(float outerAngle)
|
||||
{
|
||||
m_outerAngle = outerAngle;
|
||||
|
|
@ -167,6 +303,13 @@ namespace Nz
|
|||
InvalidateBoundingVolume();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the radius of the light
|
||||
* \return radius Light radius
|
||||
*
|
||||
* \remark Invalidates the bounding volume
|
||||
*/
|
||||
|
||||
inline void Light::SetRadius(float radius)
|
||||
{
|
||||
m_radius = radius;
|
||||
|
|
@ -176,6 +319,15 @@ namespace Nz
|
|||
InvalidateBoundingVolume();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the shadow map format
|
||||
*
|
||||
* \param shadowFormat Shadow map format
|
||||
*
|
||||
* \remark Invalidates the shadow map
|
||||
* \remark Produces a NazaraAssert if format is not a depth type
|
||||
*/
|
||||
|
||||
inline void Light::SetShadowMapFormat(PixelFormatType shadowFormat)
|
||||
{
|
||||
NazaraAssert(PixelFormat::GetContent(shadowFormat) == PixelFormatContent_DepthStencil, "Shadow format type is not a depth format");
|
||||
|
|
@ -185,6 +337,15 @@ namespace Nz
|
|||
InvalidateShadowMap();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the size of the shadow map
|
||||
*
|
||||
* \param size Shadow map size
|
||||
*
|
||||
* \remark Invalidates the shadow map
|
||||
* \remark Produces a NazaraAssert if size is zero
|
||||
*/
|
||||
|
||||
inline void Light::SetShadowMapSize(const Vector2ui& size)
|
||||
{
|
||||
NazaraAssert(size.x > 0 && size.y > 0, "Shadow map size must have a positive size");
|
||||
|
|
@ -194,6 +355,15 @@ namespace Nz
|
|||
InvalidateShadowMap();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the current light with the content of the other one
|
||||
* \return A reference to this
|
||||
*
|
||||
* \param light The other Light
|
||||
*
|
||||
* \remark Invalidates the shadow map
|
||||
*/
|
||||
|
||||
inline Light& Light::operator=(const Light& light)
|
||||
{
|
||||
Renderable::operator=(light);
|
||||
|
|
@ -218,6 +388,10 @@ namespace Nz
|
|||
return *this;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Invalidates the shadow map
|
||||
*/
|
||||
|
||||
inline void Light::InvalidateShadowMap()
|
||||
{
|
||||
m_shadowMapUpdated = false;
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@ namespace Nz
|
|||
|
||||
inline Material& operator=(const Material& material);
|
||||
|
||||
static MaterialRef GetDefault();
|
||||
inline static MaterialRef GetDefault();
|
||||
template<typename... Args> static MaterialRef New(Args&&... args);
|
||||
|
||||
// Signals:
|
||||
|
|
@ -163,7 +163,7 @@ namespace Nz
|
|||
{
|
||||
const Shader* shader;
|
||||
UberShaderInstance* uberInstance = nullptr;
|
||||
int uniforms[MaterialUniform_Max+1];
|
||||
int uniforms[MaterialUniform_Max + 1];
|
||||
};
|
||||
|
||||
void Copy(const Material& material);
|
||||
|
|
@ -187,7 +187,7 @@ namespace Nz
|
|||
TextureRef m_normalMap;
|
||||
TextureRef m_specularMap;
|
||||
UberShaderConstRef m_uberShader;
|
||||
mutable ShaderInstance m_shaders[ShaderFlags_Max+1];
|
||||
mutable ShaderInstance m_shaders[ShaderFlags_Max + 1];
|
||||
bool m_alphaTestEnabled;
|
||||
bool m_depthSortingEnabled;
|
||||
bool m_lightingEnabled;
|
||||
|
|
|
|||
|
|
@ -7,11 +7,21 @@
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \brief Constructs a Material object by default
|
||||
*/
|
||||
|
||||
inline Material::Material()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Constructs a Material object by assignation
|
||||
*
|
||||
* \param material Material to copy into this
|
||||
*/
|
||||
|
||||
inline Material::Material(const Material& material) :
|
||||
RefCounted(),
|
||||
Resource(material)
|
||||
|
|
@ -19,11 +29,26 @@ namespace Nz
|
|||
Copy(material);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Destructs the object and calls OnMaterialRelease
|
||||
*
|
||||
* \see OnMaterialRelease
|
||||
*/
|
||||
|
||||
inline Material::~Material()
|
||||
{
|
||||
OnMaterialRelease(this);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Enables a renderer parameter
|
||||
*
|
||||
* \param renderParameter Parameter for the rendering
|
||||
* \param enable Should the parameter be enabled
|
||||
*
|
||||
* \remark Produces a NazaraAssert if enumeration is invalid
|
||||
*/
|
||||
|
||||
inline void Material::Enable(RendererParameter renderParameter, bool enable)
|
||||
{
|
||||
NazaraAssert(renderParameter <= RendererParameter_Max, "Renderer parameter out of enum");
|
||||
|
|
@ -31,6 +56,14 @@ namespace Nz
|
|||
m_states.parameters[renderParameter] = enable;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Enables the alpha test
|
||||
*
|
||||
* \param alphaTest Should the parameter be enabled
|
||||
*
|
||||
* \remark Invalidates the shaders
|
||||
*/
|
||||
|
||||
inline void Material::EnableAlphaTest(bool alphaTest)
|
||||
{
|
||||
m_alphaTestEnabled = alphaTest;
|
||||
|
|
@ -38,12 +71,26 @@ namespace Nz
|
|||
InvalidateShaders();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Enables the depth sorting
|
||||
*
|
||||
* \param depthSorting Should the parameter be enabled
|
||||
*/
|
||||
|
||||
inline void Material::EnableDepthSorting(bool depthSorting)
|
||||
{
|
||||
// Has no influence on shaders
|
||||
m_depthSortingEnabled = depthSorting;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Enables the lighting
|
||||
*
|
||||
* \param lighting Should the parameter be enabled
|
||||
*
|
||||
* \remark Invalidates the shaders
|
||||
*/
|
||||
|
||||
inline void Material::EnableLighting(bool lighting)
|
||||
{
|
||||
m_lightingEnabled = lighting;
|
||||
|
|
@ -51,12 +98,26 @@ namespace Nz
|
|||
InvalidateShaders();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Enables the shadow casting
|
||||
*
|
||||
* \param castShadows Should shadow casting be enabled
|
||||
*/
|
||||
|
||||
inline void Material::EnableShadowCasting(bool castShadows)
|
||||
{
|
||||
// Has no influence on shaders
|
||||
m_shadowCastingEnabled = castShadows;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Enables the shadow on receiving object
|
||||
*
|
||||
* \param receiveShadow Should receiving object have shadows enabled
|
||||
*
|
||||
* \remark Invalidates the shaders
|
||||
*/
|
||||
|
||||
inline void Material::EnableShadowReceive(bool receiveShadows)
|
||||
{
|
||||
m_shadowReceiveEnabled = receiveShadows;
|
||||
|
|
@ -64,6 +125,14 @@ namespace Nz
|
|||
InvalidateShaders();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Enables the transformation
|
||||
*
|
||||
* \param transform Should the parameter be enabled
|
||||
*
|
||||
* \remark Invalidates the shaders
|
||||
*/
|
||||
|
||||
inline void Material::EnableTransform(bool transform)
|
||||
{
|
||||
m_transformEnabled = transform;
|
||||
|
|
@ -71,91 +140,183 @@ namespace Nz
|
|||
InvalidateShaders();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the alpha map
|
||||
* \return Constant reference to the current texture
|
||||
*/
|
||||
|
||||
inline const TextureRef& Material::GetAlphaMap() const
|
||||
{
|
||||
return m_alphaMap;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the alpha threshold
|
||||
* \return The threshold value for the alpha
|
||||
*/
|
||||
|
||||
inline float Material::GetAlphaThreshold() const
|
||||
{
|
||||
return m_alphaThreshold;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the ambient color
|
||||
* \return Ambient color
|
||||
*/
|
||||
|
||||
inline Color Material::GetAmbientColor() const
|
||||
{
|
||||
return m_ambientColor;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the function to compare depth
|
||||
* \return Function comparing the depth of two materials
|
||||
*/
|
||||
|
||||
inline RendererComparison Material::GetDepthFunc() const
|
||||
{
|
||||
return m_states.depthFunc;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the depth material
|
||||
* \return Constant reference to the depth material
|
||||
*/
|
||||
|
||||
inline const MaterialRef& Material::GetDepthMaterial() const
|
||||
{
|
||||
return m_depthMaterial;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the diffuse color
|
||||
* \return Diffuse color
|
||||
*/
|
||||
|
||||
inline Color Material::GetDiffuseColor() const
|
||||
{
|
||||
return m_diffuseColor;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the diffuse sampler
|
||||
* \return Reference to the current texture sampler for the diffuse
|
||||
*/
|
||||
|
||||
inline TextureSampler& Material::GetDiffuseSampler()
|
||||
{
|
||||
return m_diffuseSampler;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the diffuse sampler
|
||||
* \return Constant reference to the current texture sampler for the diffuse
|
||||
*/
|
||||
|
||||
inline const TextureSampler& Material::GetDiffuseSampler() const
|
||||
{
|
||||
return m_diffuseSampler;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the diffuse map
|
||||
* \return Constant reference to the texture
|
||||
*/
|
||||
|
||||
const TextureRef& Material::GetDiffuseMap() const
|
||||
{
|
||||
return m_diffuseMap;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the dst in blend
|
||||
* \return Function for dst blending
|
||||
*/
|
||||
|
||||
inline BlendFunc Material::GetDstBlend() const
|
||||
{
|
||||
return m_states.dstBlend;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the emissive map
|
||||
* \return Constant reference to the texture
|
||||
*/
|
||||
|
||||
inline const TextureRef& Material::GetEmissiveMap() const
|
||||
{
|
||||
return m_emissiveMap;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the face culling
|
||||
* \return Current face culling side
|
||||
*/
|
||||
|
||||
inline FaceSide Material::GetFaceCulling() const
|
||||
{
|
||||
return m_states.faceCulling;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the face filling
|
||||
* \return Current face filling
|
||||
*/
|
||||
|
||||
inline FaceFilling Material::GetFaceFilling() const
|
||||
{
|
||||
return m_states.faceFilling;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the height map
|
||||
* \return Constant reference to the texture
|
||||
*/
|
||||
|
||||
inline const TextureRef& Material::GetHeightMap() const
|
||||
{
|
||||
return m_heightMap;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the normal map
|
||||
* \return Constant reference to the texture
|
||||
*/
|
||||
|
||||
inline const TextureRef& Material::GetNormalMap() const
|
||||
{
|
||||
return m_normalMap;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the render states
|
||||
* \return Constant reference to the render states
|
||||
*/
|
||||
|
||||
inline const RenderStates& Material::GetRenderStates() const
|
||||
{
|
||||
return m_states;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the shader of this material
|
||||
* \return Constant pointer to the ubershader used
|
||||
*/
|
||||
|
||||
inline const UberShader* Material::GetShader() const
|
||||
{
|
||||
return m_uberShader;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the shader instance based on the flag
|
||||
* \return Constant pointer to the ubershader instance
|
||||
*
|
||||
* \param flags Flag of the shader
|
||||
*/
|
||||
|
||||
inline const UberShaderInstance* Material::GetShaderInstance(UInt32 flags) const
|
||||
{
|
||||
const ShaderInstance& instance = m_shaders[flags];
|
||||
|
|
@ -165,81 +326,165 @@ namespace Nz
|
|||
return instance.uberInstance;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the shininess
|
||||
* \return Current shininess
|
||||
*/
|
||||
|
||||
inline float Material::GetShininess() const
|
||||
{
|
||||
return m_shininess;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the specular color
|
||||
* \return Specular color
|
||||
*/
|
||||
|
||||
inline Color Material::GetSpecularColor() const
|
||||
{
|
||||
return m_specularColor;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the specular map
|
||||
* \return Constant reference to the texture
|
||||
*/
|
||||
|
||||
inline const TextureRef& Material::GetSpecularMap() const
|
||||
{
|
||||
return m_specularMap;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the specular sampler
|
||||
* \return Reference to the current texture sampler for the specular
|
||||
*/
|
||||
|
||||
inline TextureSampler& Material::GetSpecularSampler()
|
||||
{
|
||||
return m_specularSampler;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the specular sampler
|
||||
* \return Constant reference to the current texture sampler for the specular
|
||||
*/
|
||||
|
||||
inline const TextureSampler& Material::GetSpecularSampler() const
|
||||
{
|
||||
return m_specularSampler;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the src in blend
|
||||
* \return Function for src blending
|
||||
*/
|
||||
|
||||
inline BlendFunc Material::GetSrcBlend() const
|
||||
{
|
||||
return m_states.srcBlend;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether this material has an alpha map
|
||||
* \return true If it is the case
|
||||
*/
|
||||
|
||||
inline bool Material::HasAlphaMap() const
|
||||
{
|
||||
return m_alphaMap.IsValid();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether this material has a depth material
|
||||
* \return true If it is the case
|
||||
*/
|
||||
|
||||
inline bool Material::HasDepthMaterial() const
|
||||
{
|
||||
return m_depthMaterial.IsValid();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether this material has a diffuse map
|
||||
* \return true If it is the case
|
||||
*/
|
||||
|
||||
inline bool Material::HasDiffuseMap() const
|
||||
{
|
||||
return m_diffuseMap.IsValid();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether this material has a emissive map
|
||||
* \return true If it is the case
|
||||
*/
|
||||
|
||||
inline bool Material::HasEmissiveMap() const
|
||||
{
|
||||
return m_emissiveMap.IsValid();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether this material has a height map
|
||||
* \return true If it is the case
|
||||
*/
|
||||
|
||||
inline bool Material::HasHeightMap() const
|
||||
{
|
||||
return m_heightMap.IsValid();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether this material has a normal map
|
||||
* \return true If it is the case
|
||||
*/
|
||||
|
||||
inline bool Material::HasNormalMap() const
|
||||
{
|
||||
return m_normalMap.IsValid();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether this material has a specular map
|
||||
* \return true If it is the case
|
||||
*/
|
||||
|
||||
inline bool Material::HasSpecularMap() const
|
||||
{
|
||||
return m_specularMap.IsValid();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether this material has alpha test enabled
|
||||
* \return true If it is the case
|
||||
*/
|
||||
|
||||
inline bool Material::IsAlphaTestEnabled() const
|
||||
{
|
||||
return m_alphaTestEnabled;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether this material has depth sorting enabled
|
||||
* \return true If it is the case
|
||||
*/
|
||||
|
||||
inline bool Material::IsDepthSortingEnabled() const
|
||||
{
|
||||
return m_depthSortingEnabled;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether this material has the render parameter enabled
|
||||
* \return true If it is the case
|
||||
*
|
||||
* \param parameter Parameter for the rendering
|
||||
*
|
||||
* \remark Produces a NazaraAssert if enumeration is invalid
|
||||
*/
|
||||
|
||||
inline bool Material::IsEnabled(RendererParameter parameter) const
|
||||
{
|
||||
NazaraAssert(parameter <= RendererParameter_Max, "Renderer parameter out of enum");
|
||||
|
|
@ -247,41 +492,93 @@ namespace Nz
|
|||
return m_states.parameters[parameter];
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether this material has lightning enabled
|
||||
* \return true If it is the case
|
||||
*/
|
||||
|
||||
inline bool Material::IsLightingEnabled() const
|
||||
{
|
||||
return m_lightingEnabled;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \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_shadowReceiveEnabled;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether this material has transformation enabled
|
||||
* \return true If it is the case
|
||||
*/
|
||||
|
||||
inline bool Material::IsTransformEnabled() const
|
||||
{
|
||||
return m_transformEnabled;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \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 bool Material::LoadFromFile(const String& filePath, const MaterialParams& params)
|
||||
{
|
||||
return MaterialLoader::LoadFromFile(this, 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 bool Material::LoadFromMemory(const void* data, std::size_t size, const MaterialParams& params)
|
||||
{
|
||||
return MaterialLoader::LoadFromMemory(this, 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 bool Material::LoadFromStream(Stream& stream, const MaterialParams& params)
|
||||
{
|
||||
return MaterialLoader::LoadFromStream(this, stream, params);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the alpha map by name
|
||||
* \return true If successful
|
||||
*
|
||||
* \param textureName Named texture
|
||||
*/
|
||||
|
||||
inline bool Material::SetAlphaMap(const String& textureName)
|
||||
{
|
||||
TextureRef texture = TextureLibrary::Query(textureName);
|
||||
|
|
@ -296,6 +593,15 @@ namespace Nz
|
|||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the alpha map with a reference to a texture
|
||||
* \return true If successful
|
||||
*
|
||||
* \param alphaMap Texture
|
||||
*
|
||||
* \remark Invalidates the shaders
|
||||
*/
|
||||
|
||||
inline void Material::SetAlphaMap(TextureRef alphaMap)
|
||||
{
|
||||
m_alphaMap = std::move(alphaMap);
|
||||
|
|
@ -303,31 +609,69 @@ namespace Nz
|
|||
InvalidateShaders();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the alpha threshold
|
||||
*
|
||||
* \param alphaThreshold Threshold for the alpha
|
||||
*/
|
||||
|
||||
inline void Material::SetAlphaThreshold(float alphaThreshold)
|
||||
{
|
||||
m_alphaThreshold = alphaThreshold;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the color for ambient
|
||||
*
|
||||
* \param ambient Color for ambient
|
||||
*/
|
||||
|
||||
inline void Material::SetAmbientColor(const Color& ambient)
|
||||
{
|
||||
m_ambientColor = ambient;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the depth functor
|
||||
*
|
||||
* \param depthFunc
|
||||
*/
|
||||
|
||||
inline void Material::SetDepthFunc(RendererComparison depthFunc)
|
||||
{
|
||||
m_states.depthFunc = depthFunc;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \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 color for diffuse
|
||||
*
|
||||
* \param diffuse Color for diffuse
|
||||
*/
|
||||
|
||||
inline void Material::SetDiffuseColor(const Color& diffuse)
|
||||
{
|
||||
m_diffuseColor = diffuse;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the diffuse map by name
|
||||
* \return true If successful
|
||||
*
|
||||
* \param textureName Named texture
|
||||
*/
|
||||
|
||||
inline bool Material::SetDiffuseMap(const String& textureName)
|
||||
{
|
||||
TextureRef texture = TextureLibrary::Query(textureName);
|
||||
|
|
@ -342,6 +686,15 @@ namespace Nz
|
|||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the diffuse map with a reference to a texture
|
||||
* \return true If successful
|
||||
*
|
||||
* \param diffuseMap Texture
|
||||
*
|
||||
* \remark Invalidates the shaders
|
||||
*/
|
||||
|
||||
inline void Material::SetDiffuseMap(TextureRef diffuseMap)
|
||||
{
|
||||
m_diffuseMap = std::move(diffuseMap);
|
||||
|
|
@ -349,16 +702,35 @@ namespace Nz
|
|||
InvalidateShaders();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the diffuse sampler
|
||||
*
|
||||
* \param sampler Diffuse sample
|
||||
*/
|
||||
|
||||
inline void Material::SetDiffuseSampler(const TextureSampler& sampler)
|
||||
{
|
||||
m_diffuseSampler = sampler;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the dst in blend
|
||||
*
|
||||
* \param func Function for dst blending
|
||||
*/
|
||||
|
||||
inline void Material::SetDstBlend(BlendFunc func)
|
||||
{
|
||||
m_states.dstBlend = func;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the emissive map by name
|
||||
* \return true If successful
|
||||
*
|
||||
* \param textureName Named texture
|
||||
*/
|
||||
|
||||
inline bool Material::SetEmissiveMap(const String& textureName)
|
||||
{
|
||||
TextureRef texture = TextureLibrary::Query(textureName);
|
||||
|
|
@ -373,6 +745,15 @@ namespace Nz
|
|||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the emissive map with a reference to a texture
|
||||
* \return true If successful
|
||||
*
|
||||
* \param emissiveMap Texture
|
||||
*
|
||||
* \remark Invalidates the shaders
|
||||
*/
|
||||
|
||||
inline void Material::SetEmissiveMap(TextureRef emissiveMap)
|
||||
{
|
||||
m_emissiveMap = std::move(emissiveMap);
|
||||
|
|
@ -380,16 +761,35 @@ namespace Nz
|
|||
InvalidateShaders();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the face culling
|
||||
*
|
||||
* \param faceSide Face to cull
|
||||
*/
|
||||
|
||||
inline void Material::SetFaceCulling(FaceSide faceSide)
|
||||
{
|
||||
m_states.faceCulling = faceSide;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the face filling
|
||||
*
|
||||
* \param filling Face to fill
|
||||
*/
|
||||
|
||||
inline void Material::SetFaceFilling(FaceFilling filling)
|
||||
{
|
||||
m_states.faceFilling = filling;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the height map by name
|
||||
* \return true If successful
|
||||
*
|
||||
* \param textureName Named texture
|
||||
*/
|
||||
|
||||
inline bool Material::SetHeightMap(const String& textureName)
|
||||
{
|
||||
TextureRef texture = TextureLibrary::Query(textureName);
|
||||
|
|
@ -404,6 +804,15 @@ namespace Nz
|
|||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the height map with a reference to a texture
|
||||
* \return true If successful
|
||||
*
|
||||
* \param heightMap Texture
|
||||
*
|
||||
* \remark Invalidates the shaders
|
||||
*/
|
||||
|
||||
inline void Material::SetHeightMap(TextureRef heightMap)
|
||||
{
|
||||
m_heightMap = std::move(heightMap);
|
||||
|
|
@ -411,6 +820,13 @@ namespace Nz
|
|||
InvalidateShaders();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the normal map by name
|
||||
* \return true If successful
|
||||
*
|
||||
* \param textureName Named texture
|
||||
*/
|
||||
|
||||
inline bool Material::SetNormalMap(const String& textureName)
|
||||
{
|
||||
TextureRef texture = TextureLibrary::Query(textureName);
|
||||
|
|
@ -425,6 +841,15 @@ namespace Nz
|
|||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the normal map with a reference to a texture
|
||||
* \return true If successful
|
||||
*
|
||||
* \param normalMap Texture
|
||||
*
|
||||
* \remark Invalidates the shaders
|
||||
*/
|
||||
|
||||
inline void Material::SetNormalMap(TextureRef normalMap)
|
||||
{
|
||||
m_normalMap = std::move(normalMap);
|
||||
|
|
@ -432,11 +857,25 @@ namespace Nz
|
|||
InvalidateShaders();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the render states
|
||||
*
|
||||
* \param states States for the rendering
|
||||
*/
|
||||
|
||||
inline void Material::SetRenderStates(const RenderStates& states)
|
||||
{
|
||||
m_states = states;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the shader with a constant reference to a ubershader
|
||||
*
|
||||
* \param uberShader Uber shader to apply
|
||||
*
|
||||
* \remark Invalidates the shaders
|
||||
*/
|
||||
|
||||
inline void Material::SetShader(UberShaderConstRef uberShader)
|
||||
{
|
||||
m_uberShader = std::move(uberShader);
|
||||
|
|
@ -444,6 +883,13 @@ namespace Nz
|
|||
InvalidateShaders();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \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);
|
||||
|
|
@ -454,16 +900,35 @@ namespace Nz
|
|||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the shininess of the material
|
||||
*
|
||||
* \param shininess Value of the shininess
|
||||
*/
|
||||
|
||||
inline void Material::SetShininess(float shininess)
|
||||
{
|
||||
m_shininess = shininess;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the color for specular
|
||||
*
|
||||
* \param specular Color
|
||||
*/
|
||||
|
||||
inline void Material::SetSpecularColor(const Color& specular)
|
||||
{
|
||||
m_specularColor = specular;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the specular map by name
|
||||
* \return true If successful
|
||||
*
|
||||
* \param textureName Named texture
|
||||
*/
|
||||
|
||||
inline bool Material::SetSpecularMap(const String& textureName)
|
||||
{
|
||||
TextureRef texture = TextureLibrary::Query(textureName);
|
||||
|
|
@ -478,6 +943,15 @@ namespace Nz
|
|||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the specular map with a reference to a texture
|
||||
* \return true If successful
|
||||
*
|
||||
* \param specularMap Texture
|
||||
*
|
||||
* \remark Invalidates the shaders
|
||||
*/
|
||||
|
||||
inline void Material::SetSpecularMap(TextureRef specularMap)
|
||||
{
|
||||
m_specularMap = std::move(specularMap);
|
||||
|
|
@ -485,16 +959,35 @@ namespace Nz
|
|||
InvalidateShaders();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the specular sampler
|
||||
*
|
||||
* \param sampler Specular sample
|
||||
*/
|
||||
|
||||
inline void Material::SetSpecularSampler(const TextureSampler& sampler)
|
||||
{
|
||||
m_specularSampler = sampler;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the src in blend
|
||||
*
|
||||
* \param func Function for src blending
|
||||
*/
|
||||
|
||||
inline void Material::SetSrcBlend(BlendFunc func)
|
||||
{
|
||||
m_states.srcBlend = func;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \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);
|
||||
|
|
@ -503,17 +996,33 @@ namespace Nz
|
|||
return *this;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the default material
|
||||
* \return Reference to the default material
|
||||
*/
|
||||
|
||||
inline MaterialRef Material::GetDefault()
|
||||
{
|
||||
return s_defaultMaterial;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Invalidates the shaders
|
||||
*/
|
||||
|
||||
inline void Material::InvalidateShaders()
|
||||
{
|
||||
for (ShaderInstance& instance : m_shaders)
|
||||
instance.uberInstance = nullptr;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -68,8 +68,6 @@ namespace Nz
|
|||
bool SetMaterial(unsigned int skinIndex, const String& subMeshName, Material* material);
|
||||
void SetMaterial(unsigned int skinIndex, unsigned int matIndex, Material* material);
|
||||
virtual void SetMesh(Mesh* mesh);
|
||||
bool SetSequence(const String& sequenceName);
|
||||
void SetSequence(unsigned int sequenceIndex);
|
||||
void SetSkin(unsigned int skin);
|
||||
void SetSkinCount(unsigned int skinCount);
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,13 @@
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \brief Creates a new Model from the arguments
|
||||
* \return A reference to the newly created model
|
||||
*
|
||||
* \param args Arguments for the model
|
||||
*/
|
||||
|
||||
template<typename... Args>
|
||||
ModelRef Model::New(Args&&... args)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -62,16 +62,16 @@ namespace Nz
|
|||
|
||||
/*
|
||||
** -Lynix:
|
||||
** Il serait aussi possible de préciser le stride de façon indépendante, ce que je ne permets pas
|
||||
** pour décomplexifier l'interface en enlevant quelque chose que je juge inutile.
|
||||
** Si vous pensez que ça peut être utile, n'hésitez pas à me le faire savoir !
|
||||
** It would be also possible to precise the stride by an independant way, what I don't allow
|
||||
** to decomplexify the interface of something I consider useless.
|
||||
** If you think that could be useful, don't hesitate to make me aware !
|
||||
*/
|
||||
};
|
||||
|
||||
Component m_components[ParticleComponent_Max+1];
|
||||
Component m_components[ParticleComponent_Max + 1];
|
||||
unsigned int m_stride;
|
||||
|
||||
static ParticleDeclaration s_declarations[ParticleLayout_Max+1];
|
||||
static ParticleDeclaration s_declarations[ParticleLayout_Max + 1];
|
||||
static ParticleDeclarationLibrary::LibraryMap s_library;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,10 +7,20 @@
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \brief Gets a pointer to iterate through same components
|
||||
* \return SparsePtr pointing to same components
|
||||
*
|
||||
* \param component Component to get in the declaration
|
||||
*
|
||||
* \remark The same components are not continguous but separated by sizeof(ParticleSize)
|
||||
* \remark Produces a NazaraError if component is disabled
|
||||
*/
|
||||
|
||||
template <typename T>
|
||||
SparsePtr<T> ParticleMapper::GetComponentPtr(ParticleComponent component)
|
||||
{
|
||||
// Ensuite le composant qui nous intéresse
|
||||
// Then the component that are interesting
|
||||
bool enabled;
|
||||
ComponentType type;
|
||||
unsigned int offset;
|
||||
|
|
@ -18,7 +28,7 @@ namespace Nz
|
|||
|
||||
if (enabled)
|
||||
{
|
||||
///TODO: Vérifier le rapport entre le type de l'attribut et le type template ?
|
||||
///TODO: Check the ratio between the type of the attribute and the template type ?
|
||||
return SparsePtr<T>(m_ptr + offset, m_declaration->GetStride());
|
||||
}
|
||||
else
|
||||
|
|
@ -28,10 +38,20 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets a pointer to iterate through same components
|
||||
* \return SparsePtr pointing to same components
|
||||
*
|
||||
* \param component Component to get in the declaration
|
||||
*
|
||||
* \remark The same components are not continguous but separated by sizeof(ParticleSize)
|
||||
* \remark Produces a NazaraError if component is disabled
|
||||
*/
|
||||
|
||||
template <typename T>
|
||||
SparsePtr<const T> ParticleMapper::GetComponentPtr(ParticleComponent component) const
|
||||
{
|
||||
// Ensuite le composant qui nous intéresse
|
||||
// Then the component that are interesting
|
||||
bool enabled;
|
||||
ComponentType type;
|
||||
unsigned int offset;
|
||||
|
|
@ -39,7 +59,7 @@ namespace Nz
|
|||
|
||||
if (enabled)
|
||||
{
|
||||
///TODO: Vérifier le rapport entre le type de l'attribut et le type template ?
|
||||
///TODO: Check the ratio between the type of the attribute and the template type ?
|
||||
return SparsePtr<const T>(m_ptr + offset, m_declaration->GetStride());
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -4,17 +4,31 @@
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \brief Ensures that the bounding volume is up to date
|
||||
*/
|
||||
|
||||
inline void Renderable::EnsureBoundingVolumeUpdated() const
|
||||
{
|
||||
if (!m_boundingVolumeUpdated)
|
||||
UpdateBoundingVolume();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Invalidates the bounding volume
|
||||
*/
|
||||
|
||||
inline void Renderable::InvalidateBoundingVolume()
|
||||
{
|
||||
m_boundingVolumeUpdated = false;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Updates the bounding volume by a matrix
|
||||
*
|
||||
* \param transformMatrix Matrix transformation for our bounding volume
|
||||
*/
|
||||
|
||||
inline void Renderable::UpdateBoundingVolume() const
|
||||
{
|
||||
MakeBoundingVolume();
|
||||
|
|
|
|||
|
|
@ -7,31 +7,62 @@
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \brief Gets the movement offset
|
||||
* \return Offset of the movement
|
||||
*/
|
||||
|
||||
inline const Vector3f& Nz::SkyboxBackground::GetMovementOffset() const
|
||||
{
|
||||
return m_movementOffset;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the movement scale
|
||||
* \return Scale of the movement
|
||||
*/
|
||||
|
||||
inline float SkyboxBackground::GetMovementScale() const
|
||||
{
|
||||
return m_movementScale;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the texture of the background
|
||||
* \return Texture of the background
|
||||
*/
|
||||
|
||||
inline const TextureRef& SkyboxBackground::GetTexture() const
|
||||
{
|
||||
return m_texture;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the texture sampler of the background
|
||||
* \return A reference to the texture sampler of the background
|
||||
*/
|
||||
|
||||
inline TextureSampler& SkyboxBackground::GetTextureSampler()
|
||||
{
|
||||
return m_sampler;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the texture sampler of the background
|
||||
* \return A constant reference to the texture sampler of the background
|
||||
*/
|
||||
|
||||
inline const TextureSampler& SkyboxBackground::GetTextureSampler() const
|
||||
{
|
||||
return m_sampler;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the movement offset
|
||||
*
|
||||
* \param offset Offset of the movement
|
||||
*/
|
||||
|
||||
inline void SkyboxBackground::SetMovementOffset(const Vector3f& offset)
|
||||
{
|
||||
NazaraAssert(std::isfinite(offset.x) && std::isfinite(offset.y) && std::isfinite(offset.z), "Offset must be a finite vector");
|
||||
|
|
@ -39,6 +70,12 @@ namespace Nz
|
|||
m_movementOffset = offset;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the movement scale
|
||||
*
|
||||
* \param scale Scale of the movement
|
||||
*/
|
||||
|
||||
inline void SkyboxBackground::SetMovementScale(float scale)
|
||||
{
|
||||
NazaraAssert(std::isfinite(scale), "Scale must be a finite value");
|
||||
|
|
@ -46,6 +83,12 @@ namespace Nz
|
|||
m_movementScale = scale;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the texture of the background
|
||||
*
|
||||
* \param cubemapTexture Texture of the background
|
||||
*/
|
||||
|
||||
inline void SkyboxBackground::SetTexture(TextureRef cubemapTexture)
|
||||
{
|
||||
NazaraAssert(!cubemapTexture || cubemapTexture->IsValid(), "Invalid texture");
|
||||
|
|
@ -54,11 +97,24 @@ namespace Nz
|
|||
m_texture = std::move(cubemapTexture);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the texture sampler of the background
|
||||
*
|
||||
* \param sampler Texture sampler of the background
|
||||
*/
|
||||
|
||||
void SkyboxBackground::SetTextureSampler(const TextureSampler& sampler)
|
||||
{
|
||||
m_sampler = sampler;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Creates a new skybox background from the arguments
|
||||
* \return A reference to the newly created skybox background
|
||||
*
|
||||
* \param args Arguments for the skybox background
|
||||
*/
|
||||
|
||||
template<typename... Args>
|
||||
SkyboxBackgroundRef SkyboxBackground::New(Args&&... args)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -8,6 +8,10 @@
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \brief Constructs a Sprite object by default
|
||||
*/
|
||||
|
||||
inline Sprite::Sprite() :
|
||||
m_color(Color::White),
|
||||
m_textureCoords(0.f, 0.f, 1.f, 1.f),
|
||||
|
|
@ -16,6 +20,12 @@ namespace Nz
|
|||
SetDefaultMaterial();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Constructs a Sprite object with a reference to a material
|
||||
*
|
||||
* \param material Reference to a material
|
||||
*/
|
||||
|
||||
inline Sprite::Sprite(MaterialRef material) :
|
||||
m_color(Color::White),
|
||||
m_textureCoords(0.f, 0.f, 1.f, 1.f),
|
||||
|
|
@ -24,6 +34,12 @@ namespace Nz
|
|||
SetMaterial(std::move(material), true);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Constructs a Sprite object with a pointer to a texture
|
||||
*
|
||||
* \param texture Pointer to a texture
|
||||
*/
|
||||
|
||||
inline Sprite::Sprite(Texture* texture) :
|
||||
m_color(Color::White),
|
||||
m_textureCoords(0.f, 0.f, 1.f, 1.f),
|
||||
|
|
@ -32,6 +48,12 @@ namespace Nz
|
|||
SetTexture(texture, true);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Constructs a Sprite object by assignation
|
||||
*
|
||||
* \param sprite Sprite to copy into this
|
||||
*/
|
||||
|
||||
inline Sprite::Sprite(const Sprite& sprite) :
|
||||
InstancedRenderable(sprite),
|
||||
m_color(sprite.m_color),
|
||||
|
|
@ -41,26 +63,52 @@ namespace Nz
|
|||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the color of the sprite
|
||||
* \return Current color
|
||||
*/
|
||||
|
||||
inline const Color& Sprite::GetColor() const
|
||||
{
|
||||
return m_color;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the material of the sprite
|
||||
* \return Current material
|
||||
*/
|
||||
|
||||
inline const MaterialRef& Sprite::GetMaterial() const
|
||||
{
|
||||
return m_material;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the size of the sprite
|
||||
* \return Current size
|
||||
*/
|
||||
|
||||
inline const Vector2f& Sprite::GetSize() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the texture coordinates of the sprite
|
||||
* \return Current texture coordinates
|
||||
*/
|
||||
|
||||
inline const Rectf& Sprite::GetTextureCoords() const
|
||||
{
|
||||
return m_textureCoords;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the color of the billboard
|
||||
*
|
||||
* \param color Color for the billboard
|
||||
*/
|
||||
|
||||
inline void Sprite::SetColor(const Color& color)
|
||||
{
|
||||
m_color = color;
|
||||
|
|
@ -68,6 +116,10 @@ namespace Nz
|
|||
InvalidateVertices();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the default material of the sprite (just default material)
|
||||
*/
|
||||
|
||||
inline void Sprite::SetDefaultMaterial()
|
||||
{
|
||||
MaterialRef material = Material::New();
|
||||
|
|
@ -77,6 +129,13 @@ namespace Nz
|
|||
SetMaterial(std::move(material));
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the material of the sprite
|
||||
*
|
||||
* \param material Material for the sprite
|
||||
* \param resizeSprite Should sprite be resized to the material size (diffuse map)
|
||||
*/
|
||||
|
||||
inline void Sprite::SetMaterial(MaterialRef material, bool resizeSprite)
|
||||
{
|
||||
m_material = std::move(material);
|
||||
|
|
@ -88,6 +147,12 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the size of the sprite
|
||||
*
|
||||
* \param size Size for the sprite
|
||||
*/
|
||||
|
||||
inline void Sprite::SetSize(const Vector2f& size)
|
||||
{
|
||||
m_size = size;
|
||||
|
|
@ -97,11 +162,25 @@ namespace Nz
|
|||
InvalidateVertices();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the size of the sprite
|
||||
*
|
||||
* \param sizeX Size in X for the sprite
|
||||
* \param sizeY Size in Y for the sprite
|
||||
*/
|
||||
|
||||
inline void Sprite::SetSize(float sizeX, float sizeY)
|
||||
{
|
||||
SetSize(Vector2f(sizeX, sizeY));
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the texture of the sprite
|
||||
*
|
||||
* \param texture Texture for the sprite
|
||||
* \param resizeSprite Should sprite be resized to the texture size
|
||||
*/
|
||||
|
||||
inline void Sprite::SetTexture(TextureRef texture, bool resizeSprite)
|
||||
{
|
||||
if (!m_material)
|
||||
|
|
@ -115,12 +194,27 @@ namespace Nz
|
|||
m_material->SetDiffuseMap(std::move(texture));
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the texture coordinates of the sprite
|
||||
*
|
||||
* \param coords Texture coordinates
|
||||
*/
|
||||
|
||||
inline void Sprite::SetTextureCoords(const Rectf& coords)
|
||||
{
|
||||
m_textureCoords = coords;
|
||||
InvalidateVertices();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the texture rectangle of the sprite
|
||||
*
|
||||
* \param rect Rectangles symbolizing the size of the texture
|
||||
*
|
||||
* \remark Produces a NazaraAssert if material is invalid
|
||||
* \remark Produces a NazaraAssert if material has no diffuse map
|
||||
*/
|
||||
|
||||
inline void Sprite::SetTextureRect(const Rectui& rect)
|
||||
{
|
||||
NazaraAssert(m_material, "Sprite has no material");
|
||||
|
|
@ -128,12 +222,19 @@ namespace Nz
|
|||
|
||||
Texture* diffuseMap = m_material->GetDiffuseMap();
|
||||
|
||||
float invWidth = 1.f/diffuseMap->GetWidth();
|
||||
float invHeight = 1.f/diffuseMap->GetHeight();
|
||||
float invWidth = 1.f / diffuseMap->GetWidth();
|
||||
float invHeight = 1.f / diffuseMap->GetHeight();
|
||||
|
||||
SetTextureCoords(Rectf(invWidth*rect.x, invHeight*rect.y, invWidth*rect.width, invHeight*rect.height));
|
||||
SetTextureCoords(Rectf(invWidth * rect.x, invHeight * rect.y, invWidth * rect.width, invHeight * rect.height));
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the current sprite with the content of the other one
|
||||
* \return A reference to this
|
||||
*
|
||||
* \param sprite The other Sprite
|
||||
*/
|
||||
|
||||
inline Sprite& Sprite::operator=(const Sprite& sprite)
|
||||
{
|
||||
InstancedRenderable::operator=(sprite);
|
||||
|
|
@ -143,18 +244,29 @@ namespace Nz
|
|||
m_textureCoords = sprite.m_textureCoords;
|
||||
m_size = sprite.m_size;
|
||||
|
||||
// On ne copie pas les sommets finaux car il est très probable que nos paramètres soient modifiés et qu'ils doivent être régénérés de toute façon
|
||||
// We do not copy final vertices because it's highly probable that our parameters are modified and they must be regenerated
|
||||
InvalidateBoundingVolume();
|
||||
InvalidateVertices();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Invalidates the vertices
|
||||
*/
|
||||
|
||||
inline void Sprite::InvalidateVertices()
|
||||
{
|
||||
InvalidateInstanceData(0);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Creates a new sprite from the arguments
|
||||
* \return A reference to the newly created sprite
|
||||
*
|
||||
* \param args Arguments for the sprite
|
||||
*/
|
||||
|
||||
template<typename... Args>
|
||||
SpriteRef Sprite::New(Args&&... args)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -7,6 +7,10 @@
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \brief Constructs a TextSprite object by default
|
||||
*/
|
||||
|
||||
inline TextSprite::TextSprite() :
|
||||
m_color(Color::White),
|
||||
m_scale(1.f)
|
||||
|
|
@ -14,12 +18,24 @@ namespace Nz
|
|||
SetDefaultMaterial();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Constructs a TextSprite object with a drawer
|
||||
*
|
||||
* \param drawer Drawer used to compose text on the sprite
|
||||
*/
|
||||
|
||||
inline TextSprite::TextSprite(const AbstractTextDrawer& drawer) :
|
||||
TextSprite()
|
||||
{
|
||||
Update(drawer);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Constructs a TextSprite object by assignation
|
||||
*
|
||||
* \param sprite TextSprite to copy into this
|
||||
*/
|
||||
|
||||
inline TextSprite::TextSprite(const TextSprite& sprite) :
|
||||
InstancedRenderable(sprite),
|
||||
m_renderInfos(sprite.m_renderInfos),
|
||||
|
|
@ -40,6 +56,10 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Clears the data
|
||||
*/
|
||||
|
||||
inline void TextSprite::Clear()
|
||||
{
|
||||
m_atlases.clear();
|
||||
|
|
@ -48,21 +68,42 @@ namespace Nz
|
|||
m_renderInfos.clear();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the color of the text sprite
|
||||
* \return Current color
|
||||
*/
|
||||
|
||||
inline const Color& TextSprite::GetColor() const
|
||||
{
|
||||
return m_color;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the material of the text sprite
|
||||
* \return Current material
|
||||
*/
|
||||
|
||||
inline const MaterialRef& TextSprite::GetMaterial() const
|
||||
{
|
||||
return m_material;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the current scale of the text sprite
|
||||
* \return Current scale
|
||||
*/
|
||||
|
||||
inline float TextSprite::GetScale() const
|
||||
{
|
||||
return m_scale;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the color of the text sprite
|
||||
*
|
||||
* \param color Color for the text sprite
|
||||
*/
|
||||
|
||||
inline void TextSprite::SetColor(const Color& color)
|
||||
{
|
||||
m_color = color;
|
||||
|
|
@ -70,6 +111,11 @@ namespace Nz
|
|||
InvalidateVertices();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the default material of the text sprite (just default material)
|
||||
*/
|
||||
|
||||
|
||||
inline void TextSprite::SetDefaultMaterial()
|
||||
{
|
||||
MaterialRef material = Material::New();
|
||||
|
|
@ -83,11 +129,23 @@ namespace Nz
|
|||
SetMaterial(material);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the material of the text sprite
|
||||
*
|
||||
* \param material Material for the text sprite
|
||||
*/
|
||||
|
||||
inline void TextSprite::SetMaterial(MaterialRef material)
|
||||
{
|
||||
m_material = std::move(material);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the current scale of the text sprite
|
||||
*
|
||||
* \param scale Scale of the text sprite
|
||||
*/
|
||||
|
||||
inline void TextSprite::SetScale(float scale)
|
||||
{
|
||||
m_scale = scale;
|
||||
|
|
@ -95,10 +153,12 @@ namespace Nz
|
|||
InvalidateVertices();
|
||||
}
|
||||
|
||||
inline void TextSprite::InvalidateVertices()
|
||||
{
|
||||
InvalidateInstanceData(0);
|
||||
}
|
||||
/*!
|
||||
* \brief Sets the current text sprite with the content of the other one
|
||||
* \return A reference to this
|
||||
*
|
||||
* \param text sprite The other TextSprite
|
||||
*/
|
||||
|
||||
inline TextSprite& TextSprite::operator=(const TextSprite& text)
|
||||
{
|
||||
|
|
@ -130,6 +190,22 @@ namespace Nz
|
|||
return *this;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Invalidates the vertices
|
||||
*/
|
||||
|
||||
inline void TextSprite::InvalidateVertices()
|
||||
{
|
||||
InvalidateInstanceData(0);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Creates a new text sprite from the arguments
|
||||
* \return A reference to the newly created text sprite
|
||||
*
|
||||
* \param args Arguments for the text sprite
|
||||
*/
|
||||
|
||||
template<typename... Args>
|
||||
TextSpriteRef TextSprite::New(Args&&... args)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -7,11 +7,22 @@
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \brief Gets the texture of the background
|
||||
* \return Texture of the background
|
||||
*/
|
||||
|
||||
inline const TextureRef& TextureBackground::GetTexture() const
|
||||
{
|
||||
return m_texture;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the texture of the background
|
||||
*
|
||||
* \param texture Texture of the background
|
||||
*/
|
||||
|
||||
inline void TextureBackground::SetTexture(TextureRef texture)
|
||||
{
|
||||
NazaraAssert(!texture || texture->IsValid(), "Invalid texture");
|
||||
|
|
@ -19,6 +30,13 @@ namespace Nz
|
|||
m_texture = std::move(texture);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Creates a new texture background from the arguments
|
||||
* \return A reference to the newly created texture background
|
||||
*
|
||||
* \param args Arguments for the texture background
|
||||
*/
|
||||
|
||||
template<typename... Args>
|
||||
TextureBackgroundRef TextureBackground::New(Args&&... args)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -491,8 +491,8 @@ namespace Nz
|
|||
*
|
||||
* \remark If volume is infinite, IntersectionSide_Intersecting is returned
|
||||
* \remark If volume is null, IntersectionSide_Outside is returned
|
||||
* \remark If enumeration of the volume is not defined in Extend, a NazaraError is thrown and false is returned
|
||||
* \remark If enumeration of the intersection is not defined in IntersectionSide, a NazaraError is thrown and false is returned. This should not never happen for a user of the library
|
||||
* \remark If enumeration of the volume is not defined in Extend, a NazaraError is thrown and IntersectionSide_Outside is returned
|
||||
* \remark If enumeration of the intersection is not defined in IntersectionSide, a NazaraError is thrown and IntersectionSide_Outside is returned. This should not never happen for a user of the library
|
||||
*/
|
||||
|
||||
template<typename T>
|
||||
|
|
|
|||
|
|
@ -485,7 +485,7 @@ namespace Nz
|
|||
template<typename T>
|
||||
T Sphere<T>::SquaredDistance(const Vector3<T>& point) const
|
||||
{
|
||||
return Vector3f::Distance(point, GetPosition()) - radius * radius;
|
||||
return Vector3f::SquaredDistance(point, GetPosition() + (point - GetPosition()).Normalize() * radius);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
|
|||
|
|
@ -7,6 +7,14 @@
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \ingroup graphics
|
||||
* \class Nz::AbstractBackground
|
||||
* \brief Graphics class that represents the background for our scene
|
||||
*
|
||||
* \remark This class is abstract
|
||||
*/
|
||||
|
||||
AbstractBackground::~AbstractBackground() = default;
|
||||
|
||||
BackgroundLibrary::LibraryMap AbstractBackground::s_library;
|
||||
|
|
|
|||
|
|
@ -7,23 +7,55 @@
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \ingroup graphics
|
||||
* \class Nz::AbstractRenderQueue
|
||||
* \brief Graphics class that represents the rendering queue for our scene
|
||||
*
|
||||
* \remark This class is abstract
|
||||
*/
|
||||
|
||||
AbstractRenderQueue::~AbstractRenderQueue() = default;
|
||||
|
||||
/*!
|
||||
* \brief Adds a directional light to the rendering queue
|
||||
*
|
||||
* \param light Directional light
|
||||
*/
|
||||
|
||||
void AbstractRenderQueue::AddDirectionalLight(const DirectionalLight& light)
|
||||
{
|
||||
directionalLights.push_back(light);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds a point light to the rendering queue
|
||||
*
|
||||
* \param light Point light
|
||||
*/
|
||||
|
||||
void AbstractRenderQueue::AddPointLight(const PointLight& light)
|
||||
{
|
||||
pointLights.push_back(light);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds a spot light to the rendering queue
|
||||
*
|
||||
* \param light Spot light
|
||||
*/
|
||||
|
||||
void AbstractRenderQueue::AddSpotLight(const SpotLight& light)
|
||||
{
|
||||
spotLights.push_back(light);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Clears the rendering queue
|
||||
*
|
||||
* \param fully Should everything be cleared ?
|
||||
*/
|
||||
|
||||
void AbstractRenderQueue::Clear(bool fully)
|
||||
{
|
||||
NazaraUnused(fully);
|
||||
|
|
|
|||
|
|
@ -10,6 +10,18 @@
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \ingroup graphics
|
||||
* \class Nz::AbstractRenderTechnique
|
||||
* \brief Graphics class that represents the rendering technique for our scene
|
||||
*
|
||||
* \remark This class is abstract
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Constructs a AbstractRenderTechnique object
|
||||
*/
|
||||
|
||||
AbstractRenderTechnique::AbstractRenderTechnique() :
|
||||
m_instancingEnabled(true)
|
||||
{
|
||||
|
|
@ -17,16 +29,34 @@ namespace Nz
|
|||
|
||||
AbstractRenderTechnique::~AbstractRenderTechnique() = default;
|
||||
|
||||
/*!
|
||||
* \brief Enables the instancing
|
||||
*
|
||||
* \param instancing Should instancing be enabled
|
||||
*
|
||||
* \remark This may improve performances
|
||||
*/
|
||||
|
||||
void AbstractRenderTechnique::EnableInstancing(bool instancing)
|
||||
{
|
||||
m_instancingEnabled = instancing;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the name of the actual technique
|
||||
* \return Name of the technique being used
|
||||
*/
|
||||
|
||||
String AbstractRenderTechnique::GetName() const
|
||||
{
|
||||
return RenderTechniques::ToString(GetType());
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether the instancing is enabled
|
||||
* \return true If it is the case
|
||||
*/
|
||||
|
||||
bool AbstractRenderTechnique::IsInstancingEnabled() const
|
||||
{
|
||||
return m_instancingEnabled;
|
||||
|
|
|
|||
|
|
@ -7,5 +7,13 @@
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \ingroup graphics
|
||||
* \class Nz::AbstractViewer
|
||||
* \brief Graphics class that represents the viewer for our scene
|
||||
*
|
||||
* \remark This class is abstract
|
||||
*/
|
||||
|
||||
AbstractViewer::~AbstractViewer() = default;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,19 @@
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \ingroup graphics
|
||||
* \class Nz::Billboard
|
||||
* \brief Graphics class that represents a billboard, a 2D surface which simulates a 3D object
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Adds this billboard to the render queue
|
||||
*
|
||||
* \param renderQueue Queue to be added
|
||||
* \param instanceData Data used for instance
|
||||
*/
|
||||
|
||||
void Billboard::AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData) const
|
||||
{
|
||||
if (!m_material)
|
||||
|
|
@ -20,11 +33,15 @@ namespace Nz
|
|||
renderQueue->AddBillboard(instanceData.renderOrder, m_material, instanceData.transformMatrix.GetTranslation(), m_size, m_sinCos, m_color);
|
||||
}
|
||||
|
||||
/*
|
||||
* \brief Makes the bounding volume of this billboard
|
||||
*/
|
||||
|
||||
void Billboard::MakeBoundingVolume() const
|
||||
{
|
||||
constexpr float sqrt2 = float(M_SQRT2);
|
||||
|
||||
m_boundingVolume.Set(Vector3f(0.f), sqrt2*m_size.x*Vector3f::Right() + sqrt2*m_size.y*Vector3f::Down());
|
||||
m_boundingVolume.Set(Vector3f(0.f), sqrt2 * m_size.x * Vector3f::Right() + sqrt2 * m_size.y * Vector3f::Down());
|
||||
}
|
||||
|
||||
BillboardLibrary::LibraryMap Billboard::s_library;
|
||||
|
|
|
|||
|
|
@ -11,6 +11,11 @@ namespace Nz
|
|||
{
|
||||
namespace
|
||||
{
|
||||
/*!
|
||||
* \brief Defines render states
|
||||
* \return RenderStates for the color background
|
||||
*/
|
||||
|
||||
RenderStates BuildRenderStates()
|
||||
{
|
||||
RenderStates states;
|
||||
|
|
@ -24,6 +29,18 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \ingroup graphics
|
||||
* \class Nz::ColorBackground
|
||||
* \brief Graphics class that represents a background with uniform color
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Constructs a ColorBackground object with a color
|
||||
*
|
||||
* \param color Uniform color (by default Black)
|
||||
*/
|
||||
|
||||
ColorBackground::ColorBackground(const Color& color) :
|
||||
m_color(color)
|
||||
{
|
||||
|
|
@ -38,6 +55,12 @@ namespace Nz
|
|||
m_vertexDepthUniform = shader->GetUniformLocation("VertexDepth");
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Draws this relatively to the viewer
|
||||
*
|
||||
* \param viewer Viewer for the background
|
||||
*/
|
||||
|
||||
void ColorBackground::Draw(const AbstractViewer* viewer) const
|
||||
{
|
||||
NazaraUnused(viewer);
|
||||
|
|
@ -55,16 +78,32 @@ namespace Nz
|
|||
Renderer::DrawFullscreenQuad();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the background type
|
||||
* \return Type of background
|
||||
*/
|
||||
|
||||
BackgroundType ColorBackground::GetBackgroundType() const
|
||||
{
|
||||
return BackgroundType_Color;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the color of the background
|
||||
* \return Background color
|
||||
*/
|
||||
|
||||
Color ColorBackground::GetColor() const
|
||||
{
|
||||
return m_color;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the color of the background
|
||||
*
|
||||
* \param color Background color
|
||||
*/
|
||||
|
||||
void ColorBackground::SetColor(const Color& color)
|
||||
{
|
||||
m_color = color;
|
||||
|
|
|
|||
|
|
@ -9,6 +9,16 @@
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \ingroup graphics
|
||||
* \class Nz::DeferredBloomPass
|
||||
* \brief Graphics class that represents the pass for bloom in deferred rendering
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Constructs a DeferredBloomPass object by default
|
||||
*/
|
||||
|
||||
DeferredBloomPass::DeferredBloomPass() :
|
||||
m_uniformUpdated(false),
|
||||
m_brightLuminance(0.8f),
|
||||
|
|
@ -32,26 +42,55 @@ namespace Nz
|
|||
|
||||
DeferredBloomPass::~DeferredBloomPass() = default;
|
||||
|
||||
/*!
|
||||
* \brief Gets the number of pass for blur
|
||||
* \return Number of pass for blur
|
||||
*/
|
||||
|
||||
unsigned int DeferredBloomPass::GetBlurPassCount() const
|
||||
{
|
||||
return m_blurPassCount;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the coefficiant for luminosity
|
||||
* \return Luminosity of bright elements
|
||||
*/
|
||||
|
||||
float DeferredBloomPass::GetBrightLuminance() const
|
||||
{
|
||||
return m_brightLuminance;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the coefficiant for the middle grey
|
||||
* \return Luminosity of grey elements
|
||||
*/
|
||||
|
||||
float DeferredBloomPass::GetBrightMiddleGrey() const
|
||||
{
|
||||
return m_brightMiddleGrey;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the coefficiant for things to be bright
|
||||
* \return Threshold for bright elements
|
||||
*/
|
||||
|
||||
float DeferredBloomPass::GetBrightThreshold() const
|
||||
{
|
||||
return m_brightThreshold;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the ith texture
|
||||
* \return Texture computed
|
||||
*
|
||||
* \param i Index of the texture
|
||||
*
|
||||
* \remark Produces a NazaraError with NAZARA_GRAPHICS_SAFE defined if index is invalid
|
||||
*/
|
||||
|
||||
Texture* DeferredBloomPass::GetTexture(unsigned int i) const
|
||||
{
|
||||
#if NAZARA_GRAPHICS_SAFE
|
||||
|
|
@ -65,7 +104,16 @@ namespace Nz
|
|||
return m_bloomTextures[i];
|
||||
}
|
||||
|
||||
bool DeferredBloomPass::Process(const SceneData& sceneData, unsigned int firstWorkTexture, unsigned secondWorkTexture) const
|
||||
/*!
|
||||
* \brief Processes the work on the data while working with textures
|
||||
* \return true
|
||||
*
|
||||
* \param sceneData Data for the scene
|
||||
* \param firstWorkTexture Index of the first texture to work with
|
||||
* \param firstWorkTexture Index of the second texture to work with
|
||||
*/
|
||||
|
||||
bool DeferredBloomPass::Process(const SceneData& sceneData, unsigned int firstWorkTexture, unsigned int secondWorkTexture) const
|
||||
{
|
||||
NazaraUnused(sceneData);
|
||||
|
||||
|
|
@ -91,7 +139,7 @@ namespace Nz
|
|||
Renderer::DrawFullscreenQuad();
|
||||
|
||||
Renderer::SetTarget(&m_bloomRTT);
|
||||
Renderer::SetViewport(Recti(0, 0, m_dimensions.x/8, m_dimensions.y/8));
|
||||
Renderer::SetViewport(Recti(0, 0, m_dimensions.x / 8, m_dimensions.y / 8));
|
||||
|
||||
Renderer::SetShader(m_gaussianBlurShader);
|
||||
|
||||
|
|
@ -124,6 +172,13 @@ namespace Nz
|
|||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Resizes the texture sizes
|
||||
* \return true If successful
|
||||
*
|
||||
* \param dimensions Dimensions for the compute texture
|
||||
*/
|
||||
|
||||
bool DeferredBloomPass::Resize(const Vector2ui& dimensions)
|
||||
{
|
||||
DeferredRenderPass::Resize(dimensions);
|
||||
|
|
@ -131,7 +186,7 @@ namespace Nz
|
|||
m_bloomRTT.Create(true);
|
||||
for (unsigned int i = 0; i < 2; ++i)
|
||||
{
|
||||
m_bloomTextures[i]->Create(ImageType_2D, PixelFormatType_RGBA8, dimensions.x/8, dimensions.y/8);
|
||||
m_bloomTextures[i]->Create(ImageType_2D, PixelFormatType_RGBA8, dimensions.x / 8, dimensions.y / 8);
|
||||
m_bloomRTT.AttachTexture(AttachmentPoint_Color, i, m_bloomTextures[i]);
|
||||
}
|
||||
m_bloomRTT.Unlock();
|
||||
|
|
@ -145,23 +200,47 @@ namespace Nz
|
|||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the number of pass for blur
|
||||
*
|
||||
* \param passCount Number of pass for blur
|
||||
*/
|
||||
|
||||
void DeferredBloomPass::SetBlurPassCount(unsigned int passCount)
|
||||
{
|
||||
m_blurPassCount = passCount; // N'est pas une uniforme
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the coefficiant for luminosity
|
||||
*
|
||||
* \param luminance Luminosity of bright elements
|
||||
*/
|
||||
|
||||
void DeferredBloomPass::SetBrightLuminance(float luminance)
|
||||
{
|
||||
m_brightLuminance = luminance;
|
||||
m_uniformUpdated = false;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the coefficiant for the middle grey
|
||||
*
|
||||
* \param middleGrey Luminosity of grey elements
|
||||
*/
|
||||
|
||||
void DeferredBloomPass::SetBrightMiddleGrey(float middleGrey)
|
||||
{
|
||||
m_brightMiddleGrey = middleGrey;
|
||||
m_uniformUpdated = false;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the coefficiant for things to be bright
|
||||
*
|
||||
* \param threshold Threshold for bright elements
|
||||
*/
|
||||
|
||||
void DeferredBloomPass::SetBrightThreshold(float threshold)
|
||||
{
|
||||
m_brightThreshold = threshold;
|
||||
|
|
|
|||
|
|
@ -13,6 +13,10 @@ namespace Nz
|
|||
{
|
||||
namespace
|
||||
{
|
||||
/*!
|
||||
* \brief Builds the shader for the depth of field
|
||||
* \return Reference to the shader newly created
|
||||
*/
|
||||
// http://digitalerr0r.wordpress.com/2009/05/16/xna-shader-programming-tutorial-20-depth-of-field/
|
||||
ShaderRef BuildDepthOfFieldShader()
|
||||
{
|
||||
|
|
@ -92,6 +96,16 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \ingroup graphics
|
||||
* \class Nz::DeferredDOFPass
|
||||
* \brief Graphics class that represents the pass for depth of field in deferred rendering
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Constructs a DeferredDOFPass object by default
|
||||
*/
|
||||
|
||||
DeferredDOFPass::DeferredDOFPass()
|
||||
{
|
||||
m_dofShader = BuildDepthOfFieldShader();
|
||||
|
|
@ -118,7 +132,16 @@ namespace Nz
|
|||
|
||||
DeferredDOFPass::~DeferredDOFPass() = default;
|
||||
|
||||
bool DeferredDOFPass::Process(const SceneData& sceneData, unsigned int firstWorkTexture, unsigned secondWorkTexture) const
|
||||
/*!
|
||||
* \brief Processes the work on the data while working with textures
|
||||
* \return true
|
||||
*
|
||||
* \param sceneData Data for the scene
|
||||
* \param firstWorkTexture Index of the first texture to work with
|
||||
* \param firstWorkTexture Index of the second texture to work with
|
||||
*/
|
||||
|
||||
bool DeferredDOFPass::Process(const SceneData& sceneData, unsigned int firstWorkTexture, unsigned int secondWorkTexture) const
|
||||
{
|
||||
NazaraUnused(sceneData);
|
||||
|
||||
|
|
@ -162,6 +185,13 @@ namespace Nz
|
|||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Resizes the texture sizes
|
||||
* \return true If successful
|
||||
*
|
||||
* \param dimensions Dimensions for the compute texture
|
||||
*/
|
||||
|
||||
bool DeferredDOFPass::Resize(const Vector2ui& dimensions)
|
||||
{
|
||||
DeferredRenderPass::Resize(dimensions);
|
||||
|
|
@ -181,5 +211,5 @@ namespace Nz
|
|||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,16 @@
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \ingroup graphics
|
||||
* \class Nz::DeferredFXAAPass
|
||||
* \brief Graphics class that represents the pass for FXAA in deferred rendering
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Constructs a DeferredFXAAPass object by default
|
||||
*/
|
||||
|
||||
DeferredFXAAPass::DeferredFXAAPass()
|
||||
{
|
||||
m_fxaaShader = ShaderLibrary::Get("DeferredFXAA");
|
||||
|
|
@ -23,7 +33,16 @@ namespace Nz
|
|||
|
||||
DeferredFXAAPass::~DeferredFXAAPass() = default;
|
||||
|
||||
bool DeferredFXAAPass::Process(const SceneData& sceneData, unsigned int firstWorkTexture, unsigned secondWorkTexture) const
|
||||
/*!
|
||||
* \brief Processes the work on the data while working with textures
|
||||
* \return true
|
||||
*
|
||||
* \param sceneData Data for the scene
|
||||
* \param firstWorkTexture Index of the first texture to work with
|
||||
* \param firstWorkTexture Index of the second texture to work with
|
||||
*/
|
||||
|
||||
bool DeferredFXAAPass::Process(const SceneData& sceneData, unsigned int firstWorkTexture, unsigned int secondWorkTexture) const
|
||||
{
|
||||
NazaraUnused(sceneData);
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,16 @@
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \ingroup graphics
|
||||
* \class Nz::DeferredFinalPass
|
||||
* \brief Graphics class that represents the final pass in deferred rendering
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Constructs a DeferredFinalPass object by default
|
||||
*/
|
||||
|
||||
DeferredFinalPass::DeferredFinalPass()
|
||||
{
|
||||
m_pointSampler.SetAnisotropyLevel(1);
|
||||
|
|
@ -34,7 +44,16 @@ namespace Nz
|
|||
|
||||
DeferredFinalPass::~DeferredFinalPass() = default;
|
||||
|
||||
bool DeferredFinalPass::Process(const SceneData& sceneData, unsigned int firstWorkTexture, unsigned secondWorkTexture) const
|
||||
/*!
|
||||
* \brief Processes the work on the data while working with textures
|
||||
* \return true
|
||||
*
|
||||
* \param sceneData Data for the scene
|
||||
* \param firstWorkTexture Index of the first texture to work with
|
||||
* \param firstWorkTexture Index of the second texture to work with
|
||||
*/
|
||||
|
||||
bool DeferredFinalPass::Process(const SceneData& sceneData, unsigned int firstWorkTexture, unsigned int secondWorkTexture) const
|
||||
{
|
||||
NazaraAssert(sceneData.viewer, "Invalid viewer");
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,11 @@ namespace Nz
|
|||
{
|
||||
namespace
|
||||
{
|
||||
/*!
|
||||
* \brief Builds the shader for the fog
|
||||
* \return Reference to the shader newly created
|
||||
*/
|
||||
|
||||
ShaderRef BuildFogShader()
|
||||
{
|
||||
/*const UInt8 fragmentSource[] = {
|
||||
|
|
@ -117,6 +122,16 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \ingroup graphics
|
||||
* \class Nz::DeferredFogPass
|
||||
* \brief Graphics class that represents the pass for fog in deferred rendering
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Constructs a DeferredFogPass object by default
|
||||
*/
|
||||
|
||||
DeferredFogPass::DeferredFogPass()
|
||||
{
|
||||
m_pointSampler.SetAnisotropyLevel(1);
|
||||
|
|
@ -131,7 +146,16 @@ namespace Nz
|
|||
|
||||
DeferredFogPass::~DeferredFogPass() = default;
|
||||
|
||||
bool DeferredFogPass::Process( const SceneData& sceneData, unsigned int firstWorkTexture, unsigned secondWorkTexture) const
|
||||
/*!
|
||||
* \brief Processes the work on the data while working with textures
|
||||
* \return true
|
||||
*
|
||||
* \param sceneData Data for the scene
|
||||
* \param firstWorkTexture Index of the first texture to work with
|
||||
* \param firstWorkTexture Index of the second texture to work with
|
||||
*/
|
||||
|
||||
bool DeferredFogPass::Process( const SceneData& sceneData, unsigned int firstWorkTexture, unsigned int secondWorkTexture) const
|
||||
{
|
||||
NazaraAssert(sceneData.viewer, "Invalid viewer");
|
||||
|
||||
|
|
|
|||
|
|
@ -13,9 +13,21 @@
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \ingroup graphics
|
||||
* \class Nz::DeferredForwardPass
|
||||
* \brief Graphics class that represents the forward pass in deferred rendering
|
||||
*/
|
||||
|
||||
DeferredForwardPass::DeferredForwardPass() = default;
|
||||
DeferredForwardPass::~DeferredForwardPass() = default;
|
||||
|
||||
/*!
|
||||
* \brief Initializes the deferred forward pass which needs the forward technique
|
||||
*
|
||||
* \param technique Rendering technique
|
||||
*/
|
||||
|
||||
void DeferredForwardPass::Initialize(DeferredRenderTechnique* technique)
|
||||
{
|
||||
DeferredRenderPass::Initialize(technique);
|
||||
|
|
@ -23,7 +35,16 @@ namespace Nz
|
|||
m_forwardTechnique = technique->GetForwardTechnique();
|
||||
}
|
||||
|
||||
bool DeferredForwardPass::Process(const SceneData& sceneData, unsigned int workTexture, unsigned sceneTexture) const
|
||||
/*!
|
||||
* \brief Processes the work on the data while working with textures
|
||||
* \return true
|
||||
*
|
||||
* \param sceneData Data for the scene
|
||||
* \param firstWorkTexture Index of the first texture to work with
|
||||
* \param firstWorkTexture Index of the second texture to work with
|
||||
*/
|
||||
|
||||
bool DeferredForwardPass::Process(const SceneData& sceneData, unsigned int workTexture, unsigned int sceneTexture) const
|
||||
{
|
||||
NazaraAssert(sceneData.viewer, "Invalid viewer");
|
||||
NazaraUnused(workTexture);
|
||||
|
|
|
|||
|
|
@ -18,6 +18,16 @@
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \ingroup graphics
|
||||
* \class Nz::DeferredGeometryPass
|
||||
* \brief Graphics class that represents the pass for geometries in deferred rendering
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Constructs a DeferredGeometryPass object by default
|
||||
*/
|
||||
|
||||
DeferredGeometryPass::DeferredGeometryPass()
|
||||
{
|
||||
m_clearShader = ShaderLibrary::Get("DeferredGBufferClear");
|
||||
|
|
@ -31,7 +41,16 @@ namespace Nz
|
|||
|
||||
DeferredGeometryPass::~DeferredGeometryPass() = default;
|
||||
|
||||
bool DeferredGeometryPass::Process(const SceneData& sceneData, unsigned int firstWorkTexture, unsigned secondWorkTexture) const
|
||||
/*!
|
||||
* \brief Processes the work on the data while working with textures
|
||||
* \return false
|
||||
*
|
||||
* \param sceneData Data for the scene
|
||||
* \param firstWorkTexture Index of the first texture to work with
|
||||
* \param firstWorkTexture Index of the second texture to work with
|
||||
*/
|
||||
|
||||
bool DeferredGeometryPass::Process(const SceneData& sceneData, unsigned int firstWorkTexture, unsigned int secondWorkTexture) const
|
||||
{
|
||||
NazaraAssert(sceneData.viewer, "Invalid viewer");
|
||||
NazaraUnused(firstWorkTexture);
|
||||
|
|
@ -72,22 +91,22 @@ namespace Nz
|
|||
|
||||
bool useInstancing = instancingEnabled && matEntry.instancingEnabled;
|
||||
|
||||
// On commence par récupérer le programme du matériau
|
||||
// We begin by getting the program for materials
|
||||
UInt32 flags = ShaderFlags_Deferred;
|
||||
if (useInstancing)
|
||||
flags |= ShaderFlags_Instancing;
|
||||
|
||||
const Shader* shader = material->Apply(flags);
|
||||
|
||||
// Les uniformes sont conservées au sein d'un programme, inutile de les renvoyer tant qu'il ne change pas
|
||||
// The uniforms are conserved in our program, there's no point to send them back if they don't change
|
||||
if (shader != lastShader)
|
||||
{
|
||||
// Index des uniformes dans le shader
|
||||
// Index of uniforms in the shader
|
||||
shaderUniforms = GetShaderUniforms(shader);
|
||||
|
||||
// Couleur ambiante de la scène
|
||||
// Ambient color for the scene
|
||||
shader->SendColor(shaderUniforms->sceneAmbient, sceneData.ambientColor);
|
||||
// Position de la caméra
|
||||
// Position of the camera
|
||||
shader->SendVector(shaderUniforms->eyePosition, sceneData.viewer->GetEyePosition());
|
||||
|
||||
lastShader = shader;
|
||||
|
|
@ -105,7 +124,7 @@ namespace Nz
|
|||
const IndexBuffer* indexBuffer = meshData.indexBuffer;
|
||||
const VertexBuffer* vertexBuffer = meshData.vertexBuffer;
|
||||
|
||||
// Gestion du draw call avant la boucle de rendu
|
||||
// Handle draw call before rendering loop
|
||||
Renderer::DrawCall drawFunc;
|
||||
Renderer::DrawCallInstanced instancedDrawFunc;
|
||||
unsigned int indexCount;
|
||||
|
|
@ -128,33 +147,33 @@ namespace Nz
|
|||
|
||||
if (useInstancing)
|
||||
{
|
||||
// On récupère le buffer d'instancing du Renderer et on le configure pour fonctionner avec des matrices
|
||||
// We get the buffer for instance of Renderer and we configure it to work with matrices
|
||||
VertexBuffer* instanceBuffer = Renderer::GetInstanceBuffer();
|
||||
instanceBuffer->SetVertexDeclaration(VertexDeclaration::Get(VertexLayout_Matrix4));
|
||||
|
||||
const Matrix4f* instanceMatrices = &instances[0];
|
||||
unsigned int instanceCount = instances.size();
|
||||
unsigned int maxInstanceCount = instanceBuffer->GetVertexCount(); // Le nombre de matrices que peut contenir le buffer
|
||||
unsigned int maxInstanceCount = instanceBuffer->GetVertexCount(); // The number of matrices that can be hold in the buffer
|
||||
|
||||
while (instanceCount > 0)
|
||||
{
|
||||
// On calcule le nombre d'instances que l'on pourra afficher cette fois-ci (Selon la taille du buffer d'instancing)
|
||||
// We compute the number of instances that we will be able to show this time (Depending on the instance buffer size)
|
||||
unsigned int renderedInstanceCount = std::min(instanceCount, maxInstanceCount);
|
||||
instanceCount -= renderedInstanceCount;
|
||||
|
||||
// On remplit l'instancing buffer avec nos matrices world
|
||||
// We fill the instancing buffer with our world matrices
|
||||
instanceBuffer->Fill(instanceMatrices, 0, renderedInstanceCount, true);
|
||||
instanceMatrices += renderedInstanceCount;
|
||||
|
||||
// Et on affiche
|
||||
// And we show
|
||||
instancedDrawFunc(renderedInstanceCount, meshData.primitiveMode, 0, indexCount);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Sans instancing, on doit effectuer un draw call pour chaque instance
|
||||
// Cela reste néanmoins plus rapide que l'instancing en dessous d'un certain nombre d'instances
|
||||
// À cause du temps de modification du buffer d'instancing
|
||||
// Without instancing, we must do one draw call for each instance
|
||||
// This may be faster than instancing under a threshold
|
||||
// Due to the time to modify the instancing buffer
|
||||
for (const Matrix4f& matrix : instances)
|
||||
{
|
||||
Renderer::SetMatrix(MatrixType_World, matrix);
|
||||
|
|
@ -167,16 +186,23 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
// Et on remet à zéro les données
|
||||
// Abd we set it back data to zero
|
||||
matEntry.enabled = false;
|
||||
matEntry.instancingEnabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false; // On ne fait que remplir le G-Buffer, les work texture ne sont pas affectées
|
||||
return false; // We only fill the G-Buffer, the work texture are unchanged
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Resizes the texture sizes
|
||||
* \return true If successful
|
||||
*
|
||||
* \param dimensions Dimensions for the compute texture
|
||||
*/
|
||||
|
||||
bool DeferredGeometryPass::Resize(const Vector2ui& dimensions)
|
||||
{
|
||||
DeferredRenderPass::Resize(dimensions);
|
||||
|
|
@ -241,6 +267,13 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the uniforms of a shader
|
||||
* \return Uniforms of the shader
|
||||
*
|
||||
* \param shader Shader to get uniforms from
|
||||
*/
|
||||
|
||||
const DeferredGeometryPass::ShaderUniforms* DeferredGeometryPass::GetShaderUniforms(const Shader* shader) const
|
||||
{
|
||||
auto it = m_shaderUniforms.find(shader);
|
||||
|
|
@ -260,6 +293,12 @@ namespace Nz
|
|||
return &it->second;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Handle the invalidation of a shader
|
||||
*
|
||||
* \param shader Shader being invalidated
|
||||
*/
|
||||
|
||||
void DeferredGeometryPass::OnShaderInvalidated(const Shader* shader) const
|
||||
{
|
||||
m_shaderUniforms.erase(shader);
|
||||
|
|
|
|||
|
|
@ -13,6 +13,16 @@
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \ingroup graphics
|
||||
* \class Nz::DeferredPhongLightingPass
|
||||
* \brief Graphics class that represents the pass for phong lighting in deferred rendering
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Constructs a DeferredPhongLightingPass object by default
|
||||
*/
|
||||
|
||||
DeferredPhongLightingPass::DeferredPhongLightingPass() :
|
||||
m_lightMeshesDrawing(false)
|
||||
{
|
||||
|
|
@ -21,7 +31,7 @@ namespace Nz
|
|||
m_directionalLightShaderSceneAmbientLocation = m_directionalLightShader->GetUniformLocation("SceneAmbient");
|
||||
|
||||
m_directionalLightUniforms.ubo = false;
|
||||
m_directionalLightUniforms.locations.type = -1; // Type déjà connu
|
||||
m_directionalLightUniforms.locations.type = -1; // Type already known
|
||||
m_directionalLightUniforms.locations.color = m_directionalLightShader->GetUniformLocation("LightColor");
|
||||
m_directionalLightUniforms.locations.factors = m_directionalLightShader->GetUniformLocation("LightFactors");
|
||||
m_directionalLightUniforms.locations.parameters1 = m_directionalLightShader->GetUniformLocation("LightDirection");
|
||||
|
|
@ -56,16 +66,36 @@ namespace Nz
|
|||
|
||||
DeferredPhongLightingPass::~DeferredPhongLightingPass() = default;
|
||||
|
||||
/*!
|
||||
* \brief Enables the drawing of meshes with light
|
||||
*
|
||||
* \param enable Should meshes with light parameter be drawed
|
||||
*/
|
||||
|
||||
void DeferredPhongLightingPass::EnableLightMeshesDrawing(bool enable)
|
||||
{
|
||||
m_lightMeshesDrawing = enable;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether the drawing of meshes with light is enabled
|
||||
* \return true If it is the case
|
||||
*/
|
||||
|
||||
bool DeferredPhongLightingPass::IsLightMeshesDrawingEnabled() const
|
||||
{
|
||||
return m_lightMeshesDrawing;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Processes the work on the data while working with textures
|
||||
* \return true
|
||||
*
|
||||
* \param sceneData Data for the scene
|
||||
* \param firstWorkTexture Index of the first texture to work with
|
||||
* \param firstWorkTexture Index of the second texture to work with
|
||||
*/
|
||||
|
||||
bool DeferredPhongLightingPass::Process(const SceneData& sceneData, unsigned int firstWorkTexture, unsigned secondWorkTexture) const
|
||||
{
|
||||
NazaraAssert(sceneData.viewer, "Invalid viewer");
|
||||
|
|
@ -151,12 +181,12 @@ namespace Nz
|
|||
m_pointSpotLightShader->SendVector(m_pointSpotLightUniforms.locations.parameters1, Vector4f(light.position, light.attenuation));
|
||||
m_pointSpotLightShader->SendVector(m_pointSpotLightUniforms.locations.parameters2, Vector4f(0.f, 0.f, 0.f, light.invRadius));
|
||||
|
||||
lightMatrix.SetScale(Vector3f(light.radius * 1.1f)); // Pour corriger les imperfections liées à la sphère
|
||||
lightMatrix.SetScale(Vector3f(light.radius * 1.1f)); // To correct imperfections due to the sphere
|
||||
lightMatrix.SetTranslation(light.position);
|
||||
|
||||
Renderer::SetMatrix(MatrixType_World, lightMatrix);
|
||||
|
||||
// Rendu de la sphère dans le stencil buffer
|
||||
// Sphere rendering in the stencil buffer
|
||||
Renderer::Enable(RendererParameter_ColorWrite, false);
|
||||
Renderer::Enable(RendererParameter_DepthBuffer, true);
|
||||
Renderer::Enable(RendererParameter_FaceCulling, false);
|
||||
|
|
@ -166,7 +196,7 @@ namespace Nz
|
|||
|
||||
Renderer::DrawIndexedPrimitives(PrimitiveMode_TriangleList, 0, indexBuffer->GetIndexCount());
|
||||
|
||||
// Rendu de la sphère comme zone d'effet
|
||||
// Sphere rendering as effect zone
|
||||
Renderer::Enable(RendererParameter_ColorWrite, true);
|
||||
Renderer::Enable(RendererParameter_DepthBuffer, false);
|
||||
Renderer::Enable(RendererParameter_FaceCulling, true);
|
||||
|
|
@ -192,7 +222,7 @@ namespace Nz
|
|||
Renderer::SetShader(shader);
|
||||
for (const auto& light : m_renderQueue->pointLights)
|
||||
{
|
||||
lightMatrix.SetScale(Vector3f(light.radius * 1.1f)); // Pour corriger les imperfections liées à la sphère
|
||||
lightMatrix.SetScale(Vector3f(light.radius * 1.1f)); // To correct imperfections due to the sphere
|
||||
lightMatrix.SetTranslation(light.position);
|
||||
|
||||
Renderer::SetMatrix(MatrixType_World, lightMatrix);
|
||||
|
|
@ -230,7 +260,7 @@ namespace Nz
|
|||
|
||||
Renderer::SetMatrix(MatrixType_World, lightMatrix);
|
||||
|
||||
// Rendu de la sphère dans le stencil buffer
|
||||
// Sphere rendering in the stencil buffer
|
||||
Renderer::Enable(RendererParameter_ColorWrite, false);
|
||||
Renderer::Enable(RendererParameter_DepthBuffer, true);
|
||||
Renderer::Enable(RendererParameter_FaceCulling, false);
|
||||
|
|
@ -240,7 +270,7 @@ namespace Nz
|
|||
|
||||
Renderer::DrawIndexedPrimitives(PrimitiveMode_TriangleList, 0, indexBuffer->GetIndexCount());
|
||||
|
||||
// Rendu de la sphère comme zone d'effet
|
||||
// Sphere rendering as effect zone
|
||||
Renderer::Enable(RendererParameter_ColorWrite, true);
|
||||
Renderer::Enable(RendererParameter_DepthBuffer, false);
|
||||
Renderer::Enable(RendererParameter_FaceCulling, true);
|
||||
|
|
|
|||
|
|
@ -9,6 +9,16 @@
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \ingroup graphics
|
||||
* \class Nz::DeferredRenderPass
|
||||
* \brief Graphics class that represents the pass for rendering in deferred rendering
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Constructs a DeferredRenderPass object by default
|
||||
*/
|
||||
|
||||
DeferredRenderPass::DeferredRenderPass() :
|
||||
m_enabled(true)
|
||||
{
|
||||
|
|
@ -16,11 +26,23 @@ namespace Nz
|
|||
|
||||
DeferredRenderPass::~DeferredRenderPass() = default;
|
||||
|
||||
/*!
|
||||
* \brief Enables the deferred rendering
|
||||
*
|
||||
* \param enable Should deferred rendering be activated
|
||||
*/
|
||||
|
||||
void DeferredRenderPass::Enable(bool enable)
|
||||
{
|
||||
m_enabled = enable;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Initializes the deferred forward pass which needs the deferred technique
|
||||
*
|
||||
* \param technique Rendering technique
|
||||
*/
|
||||
|
||||
void DeferredRenderPass::Initialize(DeferredRenderTechnique* technique)
|
||||
{
|
||||
m_deferredTechnique = technique;
|
||||
|
|
@ -37,11 +59,23 @@ namespace Nz
|
|||
m_workTextures[i] = technique->GetWorkTexture(i);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether the deferred rendering is enabled
|
||||
* \return true If it the case
|
||||
*/
|
||||
|
||||
bool DeferredRenderPass::IsEnabled() const
|
||||
{
|
||||
return m_enabled;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Resizes the texture sizes
|
||||
* \return true If successful
|
||||
*
|
||||
* \param dimensions Dimensions for the compute texture
|
||||
*/
|
||||
|
||||
bool DeferredRenderPass::Resize(const Vector2ui& dimensions)
|
||||
{
|
||||
m_dimensions = dimensions;
|
||||
|
|
|
|||
|
|
@ -8,69 +8,207 @@
|
|||
#include <Nazara/Graphics/Light.hpp>
|
||||
#include <Nazara/Graphics/Debug.hpp>
|
||||
|
||||
///TODO: Rendre les billboards via Deferred Shading si possible
|
||||
///TODO: Render billboards using Deferred Shading if possible
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \ingroup graphics
|
||||
* \class Nz::DeferredRenderQueue
|
||||
* \brief Graphics class that represents the rendering queue for deferred rendering
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Constructs a DeferredRenderQueue object with the rendering queue of forward rendering
|
||||
*
|
||||
* \param forwardQueue Queue of data to render
|
||||
*/
|
||||
|
||||
DeferredRenderQueue::DeferredRenderQueue(ForwardRenderQueue* forwardQueue) :
|
||||
m_forwardQueue(forwardQueue)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds billboard to the queue
|
||||
*
|
||||
* \param renderOrder Order of rendering
|
||||
* \param material Material of the billboard
|
||||
* \param position Position of the billboard
|
||||
* \param size Sizes of the billboard
|
||||
* \param sinCos Rotation of the billboard
|
||||
* \param color Color of the billboard
|
||||
*/
|
||||
|
||||
void DeferredRenderQueue::AddBillboard(int renderOrder, const Material* material, const Vector3f& position, const Vector2f& size, const Vector2f& sinCos, const Color& color)
|
||||
{
|
||||
m_forwardQueue->AddBillboard(renderOrder, material, position, size, sinCos, color);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds multiple billboards to the queue
|
||||
*
|
||||
* \param renderOrder Order of rendering
|
||||
* \param material Material of the billboards
|
||||
* \param count Number of billboards
|
||||
* \param positionPtr Position of the billboards
|
||||
* \param sizePtr Sizes of the billboards
|
||||
* \param sinCosPtr Rotation of the billboards if null, Vector2f(0.f, 1.f) is used
|
||||
* \param colorPtr Color of the billboards if null, Color::White is used
|
||||
*/
|
||||
|
||||
void DeferredRenderQueue::AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const Color> colorPtr)
|
||||
{
|
||||
m_forwardQueue->AddBillboards(renderOrder, material, count, positionPtr, sizePtr, sinCosPtr, colorPtr);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds multiple billboards to the queue
|
||||
*
|
||||
* \param renderOrder Order of rendering
|
||||
* \param material Material of the billboards
|
||||
* \param count Number of billboards
|
||||
* \param positionPtr Position of the billboards
|
||||
* \param sizePtr Sizes of the billboards
|
||||
* \param sinCosPtr Rotation of the billboards if null, Vector2f(0.f, 1.f) is used
|
||||
* \param alphaPtr Alpha parameters of the billboards if null, 1.f is used
|
||||
*/
|
||||
|
||||
void DeferredRenderQueue::AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const float> alphaPtr)
|
||||
{
|
||||
m_forwardQueue->AddBillboards(renderOrder, material, count, positionPtr, sizePtr, sinCosPtr, alphaPtr);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds multiple billboards to the queue
|
||||
*
|
||||
* \param renderOrder Order of rendering
|
||||
* \param material Material of the billboards
|
||||
* \param count Number of billboards
|
||||
* \param positionPtr Position of the billboards
|
||||
* \param sizePtr Sizes of the billboards
|
||||
* \param anglePtr Rotation of the billboards if null, 0.f is used
|
||||
* \param colorPtr Color of the billboards if null, Color::White is used
|
||||
*/
|
||||
|
||||
void DeferredRenderQueue::AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const Color> colorPtr)
|
||||
{
|
||||
m_forwardQueue->AddBillboards(renderOrder, material, count, positionPtr, sizePtr, anglePtr, colorPtr);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds multiple billboards to the queue
|
||||
*
|
||||
* \param renderOrder Order of rendering
|
||||
* \param material Material of the billboards
|
||||
* \param count Number of billboards
|
||||
* \param positionPtr Position of the billboards
|
||||
* \param sizePtr Sizes of the billboards
|
||||
* \param anglePtr Rotation of the billboards if null, 0.f is used
|
||||
* \param alphaPtr Alpha parameters of the billboards if null, 1.f is used
|
||||
*/
|
||||
|
||||
void DeferredRenderQueue::AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr)
|
||||
{
|
||||
m_forwardQueue->AddBillboards(renderOrder, material, count, positionPtr, sizePtr, anglePtr, alphaPtr);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds multiple billboards to the queue
|
||||
*
|
||||
* \param renderOrder Order of rendering
|
||||
* \param material Material of the billboards
|
||||
* \param count Number of billboards
|
||||
* \param positionPtr Position of the billboards
|
||||
* \param sizePtr Size of the billboards
|
||||
* \param sinCosPtr Rotation of the billboards if null, Vector2f(0.f, 1.f) is used
|
||||
* \param colorPtr Color of the billboards if null, Color::White is used
|
||||
*/
|
||||
|
||||
void DeferredRenderQueue::AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const Color> colorPtr)
|
||||
{
|
||||
m_forwardQueue->AddBillboards(renderOrder, material, count, positionPtr, sizePtr, sinCosPtr, colorPtr);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds multiple billboards to the queue
|
||||
*
|
||||
* \param renderOrder Order of rendering
|
||||
* \param material Material of the billboards
|
||||
* \param count Number of billboards
|
||||
* \param positionPtr Position of the billboards
|
||||
* \param sizePtr Size of the billboards
|
||||
* \param sinCosPtr Rotation of the billboards if null, Vector2f(0.f, 1.f) is used
|
||||
* \param alphaPtr Alpha parameters of the billboards if null, 1.f is used
|
||||
*/
|
||||
|
||||
void DeferredRenderQueue::AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const float> alphaPtr)
|
||||
{
|
||||
m_forwardQueue->AddBillboards(renderOrder, material, count, positionPtr, sizePtr, sinCosPtr, alphaPtr);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds multiple billboards to the queue
|
||||
*
|
||||
* \param renderOrder Order of rendering
|
||||
* \param material Material of the billboards
|
||||
* \param count Number of billboards
|
||||
* \param positionPtr Position of the billboards
|
||||
* \param sizePtr Size of the billboards
|
||||
* \param anglePtr Rotation of the billboards if null, 0.f is used
|
||||
* \param colorPtr Color of the billboards if null, Color::White is used
|
||||
*/
|
||||
|
||||
void DeferredRenderQueue::AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const Color> colorPtr)
|
||||
{
|
||||
m_forwardQueue->AddBillboards(renderOrder, material, count, positionPtr, sizePtr, anglePtr, colorPtr);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds multiple billboards to the queue
|
||||
*
|
||||
* \param renderOrder Order of rendering
|
||||
* \param material Material of the billboards
|
||||
* \param count Number of billboards
|
||||
* \param positionPtr Position of the billboards
|
||||
* \param sizePtr Size of the billboards
|
||||
* \param anglePtr Rotation of the billboards if null, 0.f is used
|
||||
* \param alphaPtr Alpha parameters of the billboards if null, 1.f is used
|
||||
*/
|
||||
|
||||
void DeferredRenderQueue::AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr)
|
||||
{
|
||||
m_forwardQueue->AddBillboards(renderOrder, material, count, positionPtr, sizePtr, anglePtr, alphaPtr);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds drawable to the queue
|
||||
*
|
||||
* \param renderOrder Order of rendering
|
||||
* \param drawable Drawable user defined
|
||||
*
|
||||
* \remark Produces a NazaraError if drawable is invalid
|
||||
*/
|
||||
|
||||
void DeferredRenderQueue::AddDrawable(int renderOrder, const Drawable* drawable)
|
||||
{
|
||||
m_forwardQueue->AddDrawable(renderOrder, drawable);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds mesh to the queue
|
||||
*
|
||||
* \param renderOrder Order of rendering
|
||||
* \param material Material of the mesh
|
||||
* \param meshData Data of the mesh
|
||||
* \param meshAABB Box of the mesh
|
||||
* \param transformMatrix Matrix of the mesh
|
||||
*/
|
||||
|
||||
void DeferredRenderQueue::AddMesh(int renderOrder, const Material* material, const MeshData& meshData, const Boxf& meshAABB, const Matrix4f& transformMatrix)
|
||||
{
|
||||
if (material->IsEnabled(RendererParameter_Blend))
|
||||
// Un matériau transparent ? J'aime pas, va voir dans la forward queue si j'y suis
|
||||
// One transparent material ? I don't like it, go see if I'm in the forward queue
|
||||
m_forwardQueue->AddMesh(renderOrder, material, meshData, meshAABB, transformMatrix);
|
||||
else
|
||||
{
|
||||
|
|
@ -103,21 +241,37 @@ namespace Nz
|
|||
it2 = meshMap.insert(std::make_pair(meshData, std::move(instanceEntry))).first;
|
||||
}
|
||||
|
||||
// On ajoute la matrice à la liste des instances de cet objet
|
||||
// We add matrices to the list of instances of this object
|
||||
std::vector<Matrix4f>& instances = it2->second.instances;
|
||||
instances.push_back(transformMatrix);
|
||||
|
||||
// Avons-nous suffisamment d'instances pour que le coût d'utilisation de l'instancing soit payé ?
|
||||
// Do we have enough instances to perform instancing ?
|
||||
if (instances.size() >= NAZARA_GRAPHICS_INSTANCING_MIN_INSTANCES_COUNT)
|
||||
entry.instancingEnabled = true; // Apparemment oui, activons l'instancing avec ce matériau
|
||||
entry.instancingEnabled = true; // Thus we can activate it
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds sprites to the queue
|
||||
*
|
||||
* \param renderOrder Order of rendering
|
||||
* \param material Material of the sprites
|
||||
* \param vertices Buffer of data for the sprites
|
||||
* \param spriteCount Number of sprites
|
||||
* \param overlay Texture of the sprites
|
||||
*/
|
||||
|
||||
void DeferredRenderQueue::AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, unsigned int spriteCount, const Texture* overlay)
|
||||
{
|
||||
m_forwardQueue->AddSprites(renderOrder, material, vertices, spriteCount, overlay);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Clears the queue
|
||||
*
|
||||
* \param fully Should everything be cleared or we can keep layers
|
||||
*/
|
||||
|
||||
void DeferredRenderQueue::Clear(bool fully)
|
||||
{
|
||||
AbstractRenderQueue::Clear(fully);
|
||||
|
|
@ -137,6 +291,13 @@ namespace Nz
|
|||
m_forwardQueue->Clear(fully);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the ith layer
|
||||
* \return Reference to the ith layer for the queue
|
||||
*
|
||||
* \param i Index of the layer
|
||||
*/
|
||||
|
||||
DeferredRenderQueue::Layer& DeferredRenderQueue::GetLayer(unsigned int i)
|
||||
{
|
||||
auto it = layers.find(i);
|
||||
|
|
@ -149,6 +310,12 @@ namespace Nz
|
|||
return layer;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Handle the invalidation of an index buffer
|
||||
*
|
||||
* \param indexBuffer Index buffer being invalidated
|
||||
*/
|
||||
|
||||
void DeferredRenderQueue::OnIndexBufferInvalidation(const IndexBuffer* indexBuffer)
|
||||
{
|
||||
for (auto& pair : layers)
|
||||
|
|
@ -170,6 +337,12 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Handle the invalidation of a material
|
||||
*
|
||||
* \param material Material being invalidated
|
||||
*/
|
||||
|
||||
void DeferredRenderQueue::OnMaterialInvalidation(const Material* material)
|
||||
{
|
||||
for (auto& pair : layers)
|
||||
|
|
@ -180,6 +353,12 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Handle the invalidation of a vertex buffer
|
||||
*
|
||||
* \param vertexBuffer Vertex buffer being invalidated
|
||||
*/
|
||||
|
||||
void DeferredRenderQueue::OnVertexBufferInvalidation(const VertexBuffer* vertexBuffer)
|
||||
{
|
||||
for (auto& pair : layers)
|
||||
|
|
@ -201,6 +380,14 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Functor to compare two batched model with material
|
||||
* \return true If first material is "smaller" than the second one
|
||||
*
|
||||
* \param mat1 First material to compare
|
||||
* \param mat2 Second material to compare
|
||||
*/
|
||||
|
||||
bool DeferredRenderQueue::BatchedModelMaterialComparator::operator()(const Material* mat1, const Material* mat2) const
|
||||
{
|
||||
const UberShader* uberShader1 = mat1->GetShader();
|
||||
|
|
@ -221,6 +408,14 @@ namespace Nz
|
|||
return mat1 < mat2;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Functor to compare two mesh data
|
||||
* \return true If first mesh is "smaller" than the second one
|
||||
*
|
||||
* \param data1 First mesh to compare
|
||||
* \param data2 Second mesh to compare
|
||||
*/
|
||||
|
||||
bool DeferredRenderQueue::MeshDataComparator::operator()(const MeshData& data1, const MeshData& data2) const
|
||||
{
|
||||
const Buffer* buffer1;
|
||||
|
|
|
|||
|
|
@ -77,7 +77,18 @@ namespace Nz
|
|||
3, // RenderPassType_SSAO
|
||||
};
|
||||
|
||||
static_assert(sizeof(RenderPassPriority)/sizeof(unsigned int) == RenderPassType_Max+1, "Render pass priority array is incomplete");
|
||||
static_assert(sizeof(RenderPassPriority) / sizeof(unsigned int) == RenderPassType_Max + 1, "Render pass priority array is incomplete");
|
||||
|
||||
/*!
|
||||
* \brief Registers the deferred shader
|
||||
* \return Reference to the newly created shader
|
||||
*
|
||||
* \param name Name of the shader
|
||||
* \param fragmentSource Raw data to fragment shader
|
||||
* \param fragmentSourceLength Size of the fragment source
|
||||
* \param vertexStage Stage of the shader
|
||||
* \param err Pointer to string to contain error message
|
||||
*/
|
||||
|
||||
inline ShaderRef RegisterDeferredShader(const String& name, const UInt8* fragmentSource, unsigned int fragmentSourceLength, const ShaderStage& vertexStage, String* err)
|
||||
{
|
||||
|
|
@ -109,6 +120,18 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \ingroup graphics
|
||||
* \class Nz::DeferredRenderTechnique
|
||||
* \brief Graphics class that represents the technique used in deferred rendering
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Constructs a DeferredRenderTechnique object by default
|
||||
*
|
||||
* \remark Produces a NazaraError if one pass could not be created
|
||||
*/
|
||||
|
||||
DeferredRenderTechnique::DeferredRenderTechnique() :
|
||||
m_renderQueue(static_cast<ForwardRenderQueue*>(m_forwardTechnique.GetRenderQueue())),
|
||||
m_GBufferSize(0U)
|
||||
|
|
@ -204,11 +227,27 @@ namespace Nz
|
|||
|
||||
DeferredRenderTechnique::~DeferredRenderTechnique() = default;
|
||||
|
||||
/*!
|
||||
* \brief Clears the data
|
||||
*
|
||||
* \param sceneData Data of the scene
|
||||
*/
|
||||
|
||||
void DeferredRenderTechnique::Clear(const SceneData& sceneData) const
|
||||
{
|
||||
NazaraUnused(sceneData);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Draws the data of the scene
|
||||
* \return true If successful
|
||||
*
|
||||
* \param sceneData Data of the scene
|
||||
*
|
||||
* \remark Produces a NazaraAssert if viewer of the scene is invalid
|
||||
* \remark Produces a NazaraError if updating viewport dimensions failed
|
||||
*/
|
||||
|
||||
bool DeferredRenderTechnique::Draw(const SceneData& sceneData) const
|
||||
{
|
||||
NazaraAssert(sceneData.viewer, "Invalid viewer");
|
||||
|
|
@ -242,6 +281,14 @@ namespace Nz
|
|||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Enables a pass
|
||||
*
|
||||
* \param renderPass Enumeration for the pass
|
||||
* \param position Position of the pass
|
||||
* \param enable Should the pass be enabled
|
||||
*/
|
||||
|
||||
void DeferredRenderTechnique::EnablePass(RenderPassType renderPass, int position, bool enable)
|
||||
{
|
||||
auto it = m_passes.find(renderPass);
|
||||
|
|
@ -253,11 +300,25 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the stencil buffer
|
||||
* \return Pointer to the rendering buffer
|
||||
*/
|
||||
|
||||
RenderBuffer* DeferredRenderTechnique::GetDepthStencilBuffer() const
|
||||
{
|
||||
return m_depthStencilBuffer;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the G-buffer
|
||||
* \return Pointer to the ith texture
|
||||
*
|
||||
* \param i Index of the G-buffer
|
||||
*
|
||||
* \remark Produces a NazaraError with NAZARA_GRAPHICS_SAFE defined if index is invalid
|
||||
*/
|
||||
|
||||
Texture* DeferredRenderTechnique::GetGBuffer(unsigned int i) const
|
||||
{
|
||||
#if NAZARA_GRAPHICS_SAFE
|
||||
|
|
@ -271,16 +332,34 @@ namespace Nz
|
|||
return m_GBuffer[i];
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the rendering texture of the G-buffer
|
||||
* \return Pointer to the rendering buffer
|
||||
*/
|
||||
|
||||
RenderTexture* DeferredRenderTechnique::GetGBufferRTT() const
|
||||
{
|
||||
return &m_GBufferRTT;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the forward technique
|
||||
* \return Constant pointer to the forward technique
|
||||
*/
|
||||
|
||||
const ForwardRenderTechnique* DeferredRenderTechnique::GetForwardTechnique() const
|
||||
{
|
||||
return &m_forwardTechnique;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the pass
|
||||
* \return Pointer to the deferred render pass
|
||||
*
|
||||
* \param renderPass Enumeration for the pass
|
||||
* \param position Position of the pass
|
||||
*/
|
||||
|
||||
DeferredRenderPass* DeferredRenderTechnique::GetPass(RenderPassType renderPass, int position)
|
||||
{
|
||||
auto it = m_passes.find(renderPass);
|
||||
|
|
@ -294,21 +373,45 @@ namespace Nz
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the render queue
|
||||
* \return Pointer to the render queue
|
||||
*/
|
||||
|
||||
AbstractRenderQueue* DeferredRenderTechnique::GetRenderQueue()
|
||||
{
|
||||
return &m_renderQueue;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the type of the current technique
|
||||
* \return Type of the render technique
|
||||
*/
|
||||
|
||||
RenderTechniqueType DeferredRenderTechnique::GetType() const
|
||||
{
|
||||
return RenderTechniqueType_DeferredShading;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the render texture used to work
|
||||
* \return Pointer to the rendering texture
|
||||
*/
|
||||
|
||||
RenderTexture* DeferredRenderTechnique::GetWorkRTT() const
|
||||
{
|
||||
return &m_workRTT;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the ith texture to work
|
||||
* \return Pointer to the texture
|
||||
*
|
||||
* \param i Index of the texture used to work
|
||||
*
|
||||
* \remark Produces a NazaraError with NAZARA_GRAPHICS_SAFE defined if index is invalid
|
||||
*/
|
||||
|
||||
Texture* DeferredRenderTechnique::GetWorkTexture(unsigned int i) const
|
||||
{
|
||||
#if NAZARA_GRAPHICS_SAFE
|
||||
|
|
@ -322,6 +425,14 @@ namespace Nz
|
|||
return m_workTextures[i];
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether the pass is enable
|
||||
* \return true If it is the case
|
||||
*
|
||||
* \param renderPass Enumeration for the pass
|
||||
* \param position Position of the pass
|
||||
*/
|
||||
|
||||
bool DeferredRenderTechnique::IsPassEnabled(RenderPassType renderPass, int position)
|
||||
{
|
||||
auto it = m_passes.find(renderPass);
|
||||
|
|
@ -335,9 +446,17 @@ namespace Nz
|
|||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Resets the pass
|
||||
* \return Pointer to the new deferred render pass
|
||||
*
|
||||
* \param renderPass Enumeration for the pass
|
||||
* \param position Position of the pass
|
||||
*/
|
||||
|
||||
DeferredRenderPass* DeferredRenderTechnique::ResetPass(RenderPassType renderPass, int position)
|
||||
{
|
||||
std::unique_ptr<DeferredRenderPass> smartPtr; // Nous évite un leak en cas d'exception
|
||||
std::unique_ptr<DeferredRenderPass> smartPtr; // We avoid to leak in case of exception
|
||||
|
||||
switch (renderPass)
|
||||
{
|
||||
|
|
@ -386,6 +505,14 @@ namespace Nz
|
|||
return smartPtr.release();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the pass
|
||||
*
|
||||
* \param relativeTo Enumeration for the pass
|
||||
* \param position Position of the pass
|
||||
* \param pass Render pass to set
|
||||
*/
|
||||
|
||||
void DeferredRenderTechnique::SetPass(RenderPassType relativeTo, int position, DeferredRenderPass* pass)
|
||||
{
|
||||
if (pass)
|
||||
|
|
@ -400,12 +527,26 @@ namespace Nz
|
|||
m_passes[relativeTo].erase(position);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether the technique is supported
|
||||
* \return true if it is the case
|
||||
*/
|
||||
|
||||
bool DeferredRenderTechnique::IsSupported()
|
||||
{
|
||||
// Depuis qu'OpenGL 3.3 est la version minimale, le Renderer supporte ce qu'il faut, mais par acquis de conscience...
|
||||
// Since OpenGL 3.3 is the minimal version, the Renderer supports what it needs, but we are never sure...
|
||||
return Renderer::GetMaxColorAttachments() >= 4 && Renderer::GetMaxRenderTargets() >= 4;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Resizes the texture sizes used for the render technique
|
||||
* \return true If successful
|
||||
*
|
||||
* \param dimensions Dimensions for the render technique
|
||||
*
|
||||
* \param Produces a NazaraError if one pass could not be resized
|
||||
*/
|
||||
|
||||
bool DeferredRenderTechnique::Resize(const Vector2ui& dimensions) const
|
||||
{
|
||||
try
|
||||
|
|
@ -427,6 +568,13 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Initializes the deferred render technique
|
||||
* \return true If successful
|
||||
*
|
||||
* \remark Produces a NazaraError if one shader creation failed
|
||||
*/
|
||||
|
||||
bool DeferredRenderTechnique::Initialize()
|
||||
{
|
||||
const char vertexSource_Basic[] =
|
||||
|
|
@ -560,6 +708,10 @@ namespace Nz
|
|||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Uninitializes the deferred render technique
|
||||
*/
|
||||
|
||||
void DeferredRenderTechnique::Uninitialize()
|
||||
{
|
||||
ShaderLibrary::Unregister("DeferredGBufferClear");
|
||||
|
|
@ -571,6 +723,14 @@ namespace Nz
|
|||
ShaderLibrary::Unregister("DeferredGaussianBlur");
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Functor to compare two render pass
|
||||
* \return true If first render pass is "smaller" than the second one
|
||||
*
|
||||
* \param pass1 First render pass to compare
|
||||
* \param pass2 Second render pass to compare
|
||||
*/
|
||||
|
||||
bool DeferredRenderTechnique::RenderPassComparator::operator()(RenderPassType pass1, RenderPassType pass2) const
|
||||
{
|
||||
return RenderPassPriority[pass1] < RenderPassPriority[pass2];
|
||||
|
|
|
|||
|
|
@ -9,6 +9,16 @@
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \ingroup graphics
|
||||
* \class Nz::DepthRenderQueue
|
||||
* \brief Graphics class that represents the rendering queue for depth rendering
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Constructs a DepthRenderTechnique object by default
|
||||
*/
|
||||
|
||||
DepthRenderQueue::DepthRenderQueue()
|
||||
{
|
||||
// Material
|
||||
|
|
@ -18,6 +28,19 @@ namespace Nz
|
|||
//m_baseMaterial->SetFaceCulling(FaceSide_Front);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds billboard to the queue
|
||||
*
|
||||
* \param renderOrder Order of rendering
|
||||
* \param material Material of the billboard
|
||||
* \param position Position of the billboard
|
||||
* \param size Sizes of the billboard
|
||||
* \param sinCos Rotation of the billboard
|
||||
* \param color Color of the billboard
|
||||
*
|
||||
* \remark Produces a NazaraAssert if material is invalid
|
||||
*/
|
||||
|
||||
void DepthRenderQueue::AddBillboard(int renderOrder, const Material* material, const Vector3f& position, const Vector2f& size, const Vector2f& sinCos, const Color& color)
|
||||
{
|
||||
NazaraAssert(material, "Invalid material");
|
||||
|
|
@ -34,6 +57,20 @@ namespace Nz
|
|||
ForwardRenderQueue::AddBillboard(0, material, position, size, sinCos, color);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds multiple billboards to the queue
|
||||
*
|
||||
* \param renderOrder Order of rendering
|
||||
* \param material Material of the billboards
|
||||
* \param count Number of billboards
|
||||
* \param positionPtr Position of the billboards
|
||||
* \param sizePtr Sizes of the billboards
|
||||
* \param sinCosPtr Rotation of the billboards if null, Vector2f(0.f, 1.f) is used
|
||||
* \param colorPtr Color of the billboards if null, Color::White is used
|
||||
*
|
||||
* \remark Produces a NazaraAssert if material is invalid
|
||||
*/
|
||||
|
||||
void DepthRenderQueue::AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const Color> colorPtr)
|
||||
{
|
||||
NazaraAssert(material, "Invalid material");
|
||||
|
|
@ -50,6 +87,20 @@ namespace Nz
|
|||
ForwardRenderQueue::AddBillboards(0, material, count, positionPtr, sizePtr, sinCosPtr, colorPtr);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds multiple billboards to the queue
|
||||
*
|
||||
* \param renderOrder Order of rendering
|
||||
* \param material Material of the billboards
|
||||
* \param count Number of billboards
|
||||
* \param positionPtr Position of the billboards
|
||||
* \param sizePtr Sizes of the billboards
|
||||
* \param sinCosPtr Rotation of the billboards if null, Vector2f(0.f, 1.f) is used
|
||||
* \param alphaPtr Alpha parameters of the billboards if null, 1.f is used
|
||||
*
|
||||
* \remark Produces a NazaraAssert if material is invalid
|
||||
*/
|
||||
|
||||
void DepthRenderQueue::AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const float> alphaPtr)
|
||||
{
|
||||
NazaraAssert(material, "Invalid material");
|
||||
|
|
@ -66,6 +117,20 @@ namespace Nz
|
|||
ForwardRenderQueue::AddBillboards(0, material, count, positionPtr, sizePtr, sinCosPtr, alphaPtr);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds multiple billboards to the queue
|
||||
*
|
||||
* \param renderOrder Order of rendering
|
||||
* \param material Material of the billboards
|
||||
* \param count Number of billboards
|
||||
* \param positionPtr Position of the billboards
|
||||
* \param sizePtr Sizes of the billboards
|
||||
* \param anglePtr Rotation of the billboards if null, 0.f is used
|
||||
* \param colorPtr Color of the billboards if null, Color::White is used
|
||||
*
|
||||
* \remark Produces a NazaraAssert if material is invalid
|
||||
*/
|
||||
|
||||
void DepthRenderQueue::AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const Color> colorPtr)
|
||||
{
|
||||
NazaraAssert(material, "Invalid material");
|
||||
|
|
@ -82,6 +147,20 @@ namespace Nz
|
|||
ForwardRenderQueue::AddBillboards(0, material, count, positionPtr, sizePtr, anglePtr, colorPtr);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds multiple billboards to the queue
|
||||
*
|
||||
* \param renderOrder Order of rendering
|
||||
* \param material Material of the billboards
|
||||
* \param count Number of billboards
|
||||
* \param positionPtr Position of the billboards
|
||||
* \param sizePtr Sizes of the billboards
|
||||
* \param anglePtr Rotation of the billboards if null, 0.f is used
|
||||
* \param alphaPtr Alpha parameters of the billboards if null, 1.f is used
|
||||
*
|
||||
* \remark Produces a NazaraAssert if material is invalid
|
||||
*/
|
||||
|
||||
void DepthRenderQueue::AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr)
|
||||
{
|
||||
NazaraAssert(material, "Invalid material");
|
||||
|
|
@ -98,6 +177,20 @@ namespace Nz
|
|||
ForwardRenderQueue::AddBillboards(0, material, count, positionPtr, sizePtr, anglePtr, alphaPtr);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds multiple billboards to the queue
|
||||
*
|
||||
* \param renderOrder Order of rendering
|
||||
* \param material Material of the billboards
|
||||
* \param count Number of billboards
|
||||
* \param positionPtr Position of the billboards
|
||||
* \param sizePtr Size of the billboards
|
||||
* \param sinCosPtr Rotation of the billboards if null, Vector2f(0.f, 1.f) is used
|
||||
* \param colorPtr Color of the billboards if null, Color::White is used
|
||||
*
|
||||
* \remark Produces a NazaraAssert if material is invalid
|
||||
*/
|
||||
|
||||
void DepthRenderQueue::AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const Color> colorPtr)
|
||||
{
|
||||
NazaraAssert(material, "Invalid material");
|
||||
|
|
@ -114,6 +207,20 @@ namespace Nz
|
|||
ForwardRenderQueue::AddBillboards(0, material, count, positionPtr, sizePtr, sinCosPtr, colorPtr);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds multiple billboards to the queue
|
||||
*
|
||||
* \param renderOrder Order of rendering
|
||||
* \param material Material of the billboards
|
||||
* \param count Number of billboards
|
||||
* \param positionPtr Position of the billboards
|
||||
* \param sizePtr Size of the billboards
|
||||
* \param sinCosPtr Rotation of the billboards if null, Vector2f(0.f, 1.f) is used
|
||||
* \param alphaPtr Alpha parameters of the billboards if null, 1.f is used
|
||||
*
|
||||
* \remark Produces a NazaraAssert if material is invalid
|
||||
*/
|
||||
|
||||
void DepthRenderQueue::AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const float> alphaPtr)
|
||||
{
|
||||
NazaraAssert(material, "Invalid material");
|
||||
|
|
@ -130,6 +237,20 @@ namespace Nz
|
|||
ForwardRenderQueue::AddBillboards(0, material, count, positionPtr, sizePtr, sinCosPtr, alphaPtr);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds multiple billboards to the queue
|
||||
*
|
||||
* \param renderOrder Order of rendering
|
||||
* \param material Material of the billboards
|
||||
* \param count Number of billboards
|
||||
* \param positionPtr Position of the billboards
|
||||
* \param sizePtr Size of the billboards
|
||||
* \param anglePtr Rotation of the billboards if null, 0.f is used
|
||||
* \param colorPtr Color of the billboards if null, Color::White is used
|
||||
*
|
||||
* \remark Produces a NazaraAssert if material is invalid
|
||||
*/
|
||||
|
||||
void DepthRenderQueue::AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const Color> colorPtr)
|
||||
{
|
||||
NazaraAssert(material, "Invalid material");
|
||||
|
|
@ -146,6 +267,20 @@ namespace Nz
|
|||
ForwardRenderQueue::AddBillboards(0, material, count, positionPtr, sizePtr, anglePtr, colorPtr);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds multiple billboards to the queue
|
||||
*
|
||||
* \param renderOrder Order of rendering
|
||||
* \param material Material of the billboards
|
||||
* \param count Number of billboards
|
||||
* \param positionPtr Position of the billboards
|
||||
* \param sizePtr Size of the billboards
|
||||
* \param anglePtr Rotation of the billboards if null, 0.f is used
|
||||
* \param alphaPtr Alpha parameters of the billboards if null, 1.f is used
|
||||
*
|
||||
* \remark Produces a NazaraAssert if material is invalid
|
||||
*/
|
||||
|
||||
void DepthRenderQueue::AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr)
|
||||
{
|
||||
NazaraAssert(material, "Invalid material");
|
||||
|
|
@ -162,12 +297,32 @@ namespace Nz
|
|||
ForwardRenderQueue::AddBillboards(0, material, count, positionPtr, sizePtr, anglePtr, alphaPtr);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds a direcitonal light to the queue
|
||||
*
|
||||
* \param light Light to add
|
||||
*
|
||||
* \remark Produces a NazaraAssert
|
||||
*/
|
||||
|
||||
void DepthRenderQueue::AddDirectionalLight(const DirectionalLight& light)
|
||||
{
|
||||
NazaraAssert(false, "Depth render queue doesn't handle lights");
|
||||
NazaraUnused(light);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds mesh to the queue
|
||||
*
|
||||
* \param renderOrder Order of rendering
|
||||
* \param material Material of the mesh
|
||||
* \param meshData Data of the mesh
|
||||
* \param meshAABB Box of the mesh
|
||||
* \param transformMatrix Matrix of the mesh
|
||||
*
|
||||
* \remark Produces a NazaraAssert if material is invalid
|
||||
*/
|
||||
|
||||
void DepthRenderQueue::AddMesh(int renderOrder, const Material* material, const MeshData& meshData, const Boxf& meshAABB, const Matrix4f& transformMatrix)
|
||||
{
|
||||
NazaraAssert(material, "Invalid material");
|
||||
|
|
@ -185,18 +340,46 @@ namespace Nz
|
|||
ForwardRenderQueue::AddMesh(0, material, meshData, meshAABB, transformMatrix);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds a point light to the queue
|
||||
*
|
||||
* \param light Light to add
|
||||
*
|
||||
* \remark Produces a NazaraAssert
|
||||
*/
|
||||
|
||||
void DepthRenderQueue::AddPointLight(const PointLight& light)
|
||||
{
|
||||
NazaraAssert(false, "Depth render queue doesn't handle lights");
|
||||
NazaraUnused(light);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds a spot light to the queue
|
||||
*
|
||||
* \param light Light to add
|
||||
*
|
||||
* \remark Produces a NazaraAssert
|
||||
*/
|
||||
|
||||
void DepthRenderQueue::AddSpotLight(const SpotLight& light)
|
||||
{
|
||||
NazaraAssert(false, "Depth render queue doesn't handle lights");
|
||||
NazaraUnused(light);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds sprites to the queue
|
||||
*
|
||||
* \param renderOrder Order of rendering
|
||||
* \param material Material of the sprites
|
||||
* \param vertices Buffer of data for the sprites
|
||||
* \param spriteCount Number of sprites
|
||||
* \param overlay Texture of the sprites
|
||||
*
|
||||
* \remark Produces a NazaraAssert if material is invalid
|
||||
*/
|
||||
|
||||
void DepthRenderQueue::AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, unsigned int spriteCount, const Texture* overlay)
|
||||
{
|
||||
NazaraAssert(material, "Invalid material");
|
||||
|
|
|
|||
|
|
@ -37,6 +37,16 @@ namespace Nz
|
|||
unsigned int s_vertexBufferSize = 4 * 1024 * 1024; // 4 MiB
|
||||
}
|
||||
|
||||
/*!
|
||||
* \ingroup graphics
|
||||
* \class Nz::DepthRenderTechnique
|
||||
* \brief Graphics class that represents the technique used in depth rendering
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Constructs a DepthRenderTechnique object by default
|
||||
*/
|
||||
|
||||
DepthRenderTechnique::DepthRenderTechnique() :
|
||||
m_vertexBuffer(BufferType_Vertex)
|
||||
{
|
||||
|
|
@ -48,6 +58,12 @@ namespace Nz
|
|||
m_spriteBuffer.Reset(VertexDeclaration::Get(VertexLayout_XYZ_Color_UV), &m_vertexBuffer);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Clears the data
|
||||
*
|
||||
* \param sceneData Data of the scene
|
||||
*/
|
||||
|
||||
void DepthRenderTechnique::Clear(const SceneData& sceneData) const
|
||||
{
|
||||
Renderer::Enable(RendererParameter_DepthBuffer, true);
|
||||
|
|
@ -59,6 +75,13 @@ namespace Nz
|
|||
// sceneData.background->Draw(sceneData.viewer);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Draws the data of the scene
|
||||
* \return true If successful
|
||||
*
|
||||
* \param sceneData Data of the scene
|
||||
*/
|
||||
|
||||
bool DepthRenderTechnique::Draw(const SceneData& sceneData) const
|
||||
{
|
||||
for (auto& pair : m_renderQueue.layers)
|
||||
|
|
@ -81,16 +104,33 @@ namespace Nz
|
|||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the render queue
|
||||
* \return Pointer to the render queue
|
||||
*/
|
||||
|
||||
AbstractRenderQueue* DepthRenderTechnique::GetRenderQueue()
|
||||
{
|
||||
return &m_renderQueue;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the type of the current technique
|
||||
* \return Type of the render technique
|
||||
*/
|
||||
|
||||
RenderTechniqueType DepthRenderTechnique::GetType() const
|
||||
{
|
||||
return RenderTechniqueType_Depth;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Initializes the depth render technique
|
||||
* \return true If successful
|
||||
*
|
||||
* \remark Produces a NazaraError if one shader creation failed
|
||||
*/
|
||||
|
||||
bool DepthRenderTechnique::Initialize()
|
||||
{
|
||||
try
|
||||
|
|
@ -149,12 +189,23 @@ namespace Nz
|
|||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Uninitializes the depth render technique
|
||||
*/
|
||||
|
||||
void DepthRenderTechnique::Uninitialize()
|
||||
{
|
||||
s_quadIndexBuffer.Reset();
|
||||
s_quadVertexBuffer.Reset();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Draws basic sprites
|
||||
*
|
||||
* \param sceneData Data of the scene
|
||||
* \param layer Layer of the rendering
|
||||
*/
|
||||
|
||||
void DepthRenderTechnique::DrawBasicSprites(const SceneData& sceneData, ForwardRenderQueue::Layer& layer) const
|
||||
{
|
||||
const Shader* lastShader = nullptr;
|
||||
|
|
@ -180,7 +231,7 @@ namespace Nz
|
|||
unsigned int spriteChainCount = spriteChainVector.size();
|
||||
if (spriteChainCount > 0)
|
||||
{
|
||||
// On commence par appliquer du matériau (et récupérer le shader ainsi activé)
|
||||
// We begin to apply the material (and get the shader activated doing so)
|
||||
UInt32 flags = 0;
|
||||
if (overlay)
|
||||
flags |= ShaderFlags_TextureOverlay;
|
||||
|
|
@ -195,26 +246,26 @@ namespace Nz
|
|||
Renderer::SetTextureSampler(overlayUnit, material->GetDiffuseSampler());
|
||||
}
|
||||
|
||||
// Les uniformes sont conservées au sein d'un programme, inutile de les renvoyer tant qu'il ne change pas
|
||||
// Uniforms are conserved in our program, there's no point to send them back until they change
|
||||
if (shader != lastShader)
|
||||
{
|
||||
// Index des uniformes dans le shader
|
||||
// Index of uniforms in the shader
|
||||
shaderUniforms = GetShaderUniforms(shader);
|
||||
|
||||
// Overlay
|
||||
shader->SendInteger(shaderUniforms->textureOverlay, overlayUnit);
|
||||
// Position de la caméra
|
||||
// Position of the camera
|
||||
shader->SendVector(shaderUniforms->eyePosition, Renderer::GetMatrix(MatrixType_ViewProj).GetTranslation());
|
||||
|
||||
lastShader = shader;
|
||||
}
|
||||
|
||||
unsigned int spriteChain = 0; // Quelle chaîne de sprite traitons-nous
|
||||
unsigned int spriteChainOffset = 0; // À quel offset dans la dernière chaîne nous sommes-nous arrêtés
|
||||
unsigned int spriteChain = 0; // Which chain of sprites are we treating
|
||||
unsigned int spriteChainOffset = 0; // Where was the last offset where we stopped in the last chain
|
||||
|
||||
do
|
||||
{
|
||||
// On ouvre le buffer en écriture
|
||||
// We open the buffer in writing mode
|
||||
BufferMapper<VertexBuffer> vertexMapper(m_spriteBuffer, BufferAccess_DiscardAndWrite);
|
||||
VertexStruct_XYZ_Color_UV* vertices = reinterpret_cast<VertexStruct_XYZ_Color_UV*>(vertexMapper.GetPointer());
|
||||
|
||||
|
|
@ -232,7 +283,7 @@ namespace Nz
|
|||
spriteCount += count;
|
||||
spriteChainOffset += count;
|
||||
|
||||
// Avons-nous traité la chaîne entière ?
|
||||
// Have we treated the entire chain ?
|
||||
if (spriteChainOffset == currentChain.spriteCount)
|
||||
{
|
||||
spriteChain++;
|
||||
|
|
@ -257,6 +308,13 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Draws billboards
|
||||
*
|
||||
* \param sceneData Data of the scene
|
||||
* \param layer Layer of the rendering
|
||||
*/
|
||||
|
||||
void DepthRenderTechnique::DrawBillboards(const SceneData& sceneData, ForwardRenderQueue::Layer& layer) const
|
||||
{
|
||||
const Shader* lastShader = nullptr;
|
||||
|
|
@ -278,16 +336,16 @@ namespace Nz
|
|||
unsigned int billboardCount = billboardVector.size();
|
||||
if (billboardCount > 0)
|
||||
{
|
||||
// On commence par appliquer du matériau (et récupérer le shader ainsi activé)
|
||||
// We begin to apply the material (and get the shader activated doing so)
|
||||
const Shader* shader = material->Apply(ShaderFlags_Billboard | ShaderFlags_Instancing | ShaderFlags_VertexColor);
|
||||
|
||||
// Les uniformes sont conservées au sein d'un programme, inutile de les renvoyer tant qu'il ne change pas
|
||||
// Uniforms are conserved in our program, there's no point to send them back until they change
|
||||
if (shader != lastShader)
|
||||
{
|
||||
// Index des uniformes dans le shader
|
||||
// Index of uniforms in the shader
|
||||
shaderUniforms = GetShaderUniforms(shader);
|
||||
|
||||
// Position de la caméra
|
||||
// Position of the camera
|
||||
shader->SendVector(shaderUniforms->eyePosition, Renderer::GetMatrix(MatrixType_ViewProj).GetTranslation());
|
||||
|
||||
lastShader = shader;
|
||||
|
|
@ -325,16 +383,16 @@ namespace Nz
|
|||
unsigned int billboardCount = billboardVector.size();
|
||||
if (billboardCount > 0)
|
||||
{
|
||||
// On commence par appliquer du matériau (et récupérer le shader ainsi activé)
|
||||
// We begin to apply the material (and get the shader activated doing so)
|
||||
const Shader* shader = material->Apply(ShaderFlags_Billboard | ShaderFlags_VertexColor);
|
||||
|
||||
// Les uniformes sont conservées au sein d'un programme, inutile de les renvoyer tant qu'il ne change pas
|
||||
// Uniforms are conserved in our program, there's no point to send them back until they change
|
||||
if (shader != lastShader)
|
||||
{
|
||||
// Index des uniformes dans le shader
|
||||
// Index of uniforms in the shader
|
||||
shaderUniforms = GetShaderUniforms(shader);
|
||||
|
||||
// Position de la caméra
|
||||
// Position of the camera
|
||||
shader->SendVector(shaderUniforms->eyePosition, Renderer::GetMatrix(MatrixType_ViewProj).GetTranslation());
|
||||
|
||||
lastShader = shader;
|
||||
|
|
@ -396,6 +454,13 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Draws opaques models
|
||||
*
|
||||
* \param sceneData Data of the scene
|
||||
* \param layer Layer of the rendering
|
||||
*/
|
||||
|
||||
void DepthRenderTechnique::DrawOpaqueModels(const SceneData& sceneData, ForwardRenderQueue::Layer& layer) const
|
||||
{
|
||||
const Shader* lastShader = nullptr;
|
||||
|
|
@ -415,14 +480,14 @@ namespace Nz
|
|||
|
||||
bool instancing = m_instancingEnabled && matEntry.instancingEnabled;
|
||||
|
||||
// On commence par appliquer du matériau (et récupérer le shader ainsi activé)
|
||||
// We begin to apply the material (and get the shader activated doing so)
|
||||
UInt8 freeTextureUnit;
|
||||
const Shader* shader = material->Apply((instancing) ? ShaderFlags_Instancing : 0, 0, &freeTextureUnit);
|
||||
|
||||
// Les uniformes sont conservées au sein d'un programme, inutile de les renvoyer tant qu'il ne change pas
|
||||
// Uniforms are conserved in our program, there's no point to send them back until they change
|
||||
if (shader != lastShader)
|
||||
{
|
||||
// Index des uniformes dans le shader
|
||||
// Index of uniforms in the shader
|
||||
shaderUniforms = GetShaderUniforms(shader);
|
||||
lastShader = shader;
|
||||
}
|
||||
|
|
@ -441,7 +506,7 @@ namespace Nz
|
|||
const IndexBuffer* indexBuffer = meshData.indexBuffer;
|
||||
const VertexBuffer* vertexBuffer = meshData.vertexBuffer;
|
||||
|
||||
// Gestion du draw call avant la boucle de rendu
|
||||
// Handle draw call before rendering loop
|
||||
Renderer::DrawCall drawFunc;
|
||||
Renderer::DrawCallInstanced instancedDrawFunc;
|
||||
unsigned int indexCount;
|
||||
|
|
@ -464,33 +529,33 @@ namespace Nz
|
|||
|
||||
if (instancing)
|
||||
{
|
||||
// On calcule le nombre d'instances que l'on pourra afficher cette fois-ci (Selon la taille du buffer d'instancing)
|
||||
// We compute the number of instances that we will be able to draw this time (depending on the instancing buffer size)
|
||||
VertexBuffer* instanceBuffer = Renderer::GetInstanceBuffer();
|
||||
instanceBuffer->SetVertexDeclaration(VertexDeclaration::Get(VertexLayout_Matrix4));
|
||||
|
||||
const Matrix4f* instanceMatrices = &instances[0];
|
||||
unsigned int instanceCount = instances.size();
|
||||
unsigned int maxInstanceCount = instanceBuffer->GetVertexCount(); // Le nombre maximum d'instances en une fois
|
||||
unsigned int maxInstanceCount = instanceBuffer->GetVertexCount(); // The maximum number of instances in one batch
|
||||
|
||||
while (instanceCount > 0)
|
||||
{
|
||||
// On calcule le nombre d'instances que l'on pourra afficher cette fois-ci (Selon la taille du buffer d'instancing)
|
||||
// We compute the number of instances that we will be able to draw this time (depending on the instancing buffer size)
|
||||
unsigned int renderedInstanceCount = std::min(instanceCount, maxInstanceCount);
|
||||
instanceCount -= renderedInstanceCount;
|
||||
|
||||
// On remplit l'instancing buffer avec nos matrices world
|
||||
// We fill the instancing buffer with our world matrices
|
||||
instanceBuffer->Fill(instanceMatrices, 0, renderedInstanceCount, true);
|
||||
instanceMatrices += renderedInstanceCount;
|
||||
|
||||
// Et on affiche
|
||||
// And we draw
|
||||
instancedDrawFunc(renderedInstanceCount, meshData.primitiveMode, 0, indexCount);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Sans instancing, on doit effectuer un draw call pour chaque instance
|
||||
// Cela reste néanmoins plus rapide que l'instancing en dessous d'un certain nombre d'instances
|
||||
// À cause du temps de modification du buffer d'instancing
|
||||
// Without instancing, we must do a draw call for each instance
|
||||
// This may be faster than instancing under a certain number
|
||||
// Due to the time to modify the instancing buffer
|
||||
for (const Matrix4f& matrix : instances)
|
||||
{
|
||||
Renderer::SetMatrix(MatrixType_World, matrix);
|
||||
|
|
@ -502,13 +567,20 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
// Et on remet à zéro les données
|
||||
// And we set the data back to zero
|
||||
matEntry.enabled = false;
|
||||
matEntry.instancingEnabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the shader uniforms
|
||||
* \return Uniforms of the shader
|
||||
*
|
||||
* \param shader Shader to get uniforms from
|
||||
*/
|
||||
|
||||
const DepthRenderTechnique::ShaderUniforms* DepthRenderTechnique::GetShaderUniforms(const Shader* shader) const
|
||||
{
|
||||
auto it = m_shaderUniforms.find(shader);
|
||||
|
|
@ -527,6 +599,12 @@ namespace Nz
|
|||
return &it->second;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Handle the invalidation of a shader
|
||||
*
|
||||
* \param shader Shader being invalidated
|
||||
*/
|
||||
|
||||
void DepthRenderTechnique::OnShaderInvalidated(const Shader* shader) const
|
||||
{
|
||||
m_shaderUniforms.erase(shader);
|
||||
|
|
|
|||
|
|
@ -7,5 +7,13 @@
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \ingroup graphics
|
||||
* \class Nz::Drawable
|
||||
* \brief Graphics class that represents something drawable for our scene
|
||||
*
|
||||
* \remark This class is abstract
|
||||
*/
|
||||
|
||||
Drawable::~Drawable() = default;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,10 +7,29 @@
|
|||
#include <Nazara/Graphics/Light.hpp>
|
||||
#include <Nazara/Graphics/Debug.hpp>
|
||||
|
||||
///TODO: Remplacer les sinus/cosinus par une lookup table (va booster les perfs d'un bon x10)
|
||||
///TODO: Replace sinus/cosinus by a lookup table (which will lead to a speed up about 10x)
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \ingroup graphics
|
||||
* \class Nz::ForwardRenderQueue
|
||||
* \brief Graphics class that represents the rendering queue for forward rendering
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Adds billboard to the queue
|
||||
*
|
||||
* \param renderOrder Order of rendering
|
||||
* \param material Material of the billboard
|
||||
* \param position Position of the billboard
|
||||
* \param size Sizes of the billboard
|
||||
* \param sinCos Rotation of the billboard
|
||||
* \param color Color of the billboard
|
||||
*
|
||||
* \remark Produces a NazaraAssert if material is invalid
|
||||
*/
|
||||
|
||||
void ForwardRenderQueue::AddBillboard(int renderOrder, const Material* material, const Vector3f& position, const Vector2f& size, const Vector2f& sinCos, const Color& color)
|
||||
{
|
||||
NazaraAssert(material, "Invalid material");
|
||||
|
|
@ -32,37 +51,33 @@ namespace Nz
|
|||
billboardVector.push_back(BillboardData{color, position, size, sinCos});
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds multiple billboards to the queue
|
||||
*
|
||||
* \param renderOrder Order of rendering
|
||||
* \param material Material of the billboards
|
||||
* \param count Number of billboards
|
||||
* \param positionPtr Position of the billboards
|
||||
* \param sizePtr Sizes of the billboards
|
||||
* \param sinCosPtr Rotation of the billboards if null, Vector2f(0.f, 1.f) is used
|
||||
* \param colorPtr Color of the billboards if null, Color::White is used
|
||||
*
|
||||
* \remark Produces a NazaraAssert if material is invalid
|
||||
*/
|
||||
|
||||
void ForwardRenderQueue::AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const Color> colorPtr)
|
||||
{
|
||||
NazaraAssert(material, "Invalid material");
|
||||
|
||||
///DOC: sinCosPtr et colorPtr peuvent être nuls, ils seont remplacés respectivement par Vector2f(0.f, 1.f) et Color::White
|
||||
Vector2f defaultSinCos(0.f, 1.f); // sin(0) = 0, cos(0) = 1
|
||||
|
||||
if (!sinCosPtr)
|
||||
sinCosPtr.Reset(&defaultSinCos, 0); // L'astuce ici est de mettre le stride sur zéro, rendant le pointeur immobile
|
||||
sinCosPtr.Reset(&defaultSinCos, 0); // The trick here is to put the stride to zero, which leads the pointer to be immobile
|
||||
|
||||
if (!colorPtr)
|
||||
colorPtr.Reset(&Color::White, 0); // Pareil
|
||||
colorPtr.Reset(&Color::White, 0); // Same
|
||||
|
||||
auto& billboards = GetLayer(renderOrder).billboards;
|
||||
|
||||
auto it = billboards.find(material);
|
||||
if (it == billboards.end())
|
||||
{
|
||||
BatchedBillboardEntry entry;
|
||||
entry.materialReleaseSlot.Connect(material->OnMaterialRelease, this, &ForwardRenderQueue::OnMaterialInvalidation);
|
||||
|
||||
it = billboards.insert(std::make_pair(material, std::move(entry))).first;
|
||||
}
|
||||
|
||||
BatchedBillboardEntry& entry = it->second;
|
||||
|
||||
auto& billboardVector = entry.billboards;
|
||||
unsigned int prevSize = billboardVector.size();
|
||||
billboardVector.resize(prevSize + count);
|
||||
|
||||
BillboardData* billboardData = &billboardVector[prevSize];
|
||||
BillboardData* billboardData = GetBillboardData(renderOrder, material, count);
|
||||
for (unsigned int i = 0; i < count; ++i)
|
||||
{
|
||||
billboardData->center = *positionPtr++;
|
||||
|
|
@ -73,39 +88,35 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds multiple billboards to the queue
|
||||
*
|
||||
* \param renderOrder Order of rendering
|
||||
* \param material Material of the billboards
|
||||
* \param count Number of billboards
|
||||
* \param positionPtr Position of the billboards
|
||||
* \param sizePtr Sizes of the billboards
|
||||
* \param sinCosPtr Rotation of the billboards if null, Vector2f(0.f, 1.f) is used
|
||||
* \param alphaPtr Alpha parameters of the billboards if null, 1.f is used
|
||||
*
|
||||
* \remark Produces a NazaraAssert if material is invalid
|
||||
*/
|
||||
|
||||
void ForwardRenderQueue::AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const float> alphaPtr)
|
||||
{
|
||||
NazaraAssert(material, "Invalid material");
|
||||
|
||||
///DOC: sinCosPtr et alphaPtr peuvent être nuls, ils seront remplacés respectivement par Vector2f(0.f, 1.f) et Color::White
|
||||
Vector2f defaultSinCos(0.f, 1.f); // sin(0) = 0, cos(0) = 1
|
||||
|
||||
if (!sinCosPtr)
|
||||
sinCosPtr.Reset(&defaultSinCos, 0); // L'astuce ici est de mettre le stride sur zéro, rendant le pointeur immobile
|
||||
sinCosPtr.Reset(&defaultSinCos, 0); // The trick here is to put the stride to zero, which leads the pointer to be immobile
|
||||
|
||||
float defaultAlpha = 1.f;
|
||||
|
||||
if (!alphaPtr)
|
||||
alphaPtr.Reset(&defaultAlpha, 0); // Pareil
|
||||
alphaPtr.Reset(&defaultAlpha, 0); // Same
|
||||
|
||||
auto& billboards = GetLayer(renderOrder).billboards;
|
||||
|
||||
auto it = billboards.find(material);
|
||||
if (it == billboards.end())
|
||||
{
|
||||
BatchedBillboardEntry entry;
|
||||
entry.materialReleaseSlot.Connect(material->OnMaterialRelease, this, &ForwardRenderQueue::OnMaterialInvalidation);
|
||||
|
||||
it = billboards.insert(std::make_pair(material, std::move(entry))).first;
|
||||
}
|
||||
|
||||
BatchedBillboardEntry& entry = it->second;
|
||||
|
||||
auto& billboardVector = entry.billboards;
|
||||
unsigned int prevSize = billboardVector.size();
|
||||
billboardVector.resize(prevSize + count);
|
||||
|
||||
BillboardData* billboardData = &billboardVector[prevSize];
|
||||
BillboardData* billboardData = GetBillboardData(renderOrder, material, count);
|
||||
for (unsigned int i = 0; i < count; ++i)
|
||||
{
|
||||
billboardData->center = *positionPtr++;
|
||||
|
|
@ -116,37 +127,33 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds multiple billboards to the queue
|
||||
*
|
||||
* \param renderOrder Order of rendering
|
||||
* \param material Material of the billboards
|
||||
* \param count Number of billboards
|
||||
* \param positionPtr Position of the billboards
|
||||
* \param sizePtr Sizes of the billboards
|
||||
* \param anglePtr Rotation of the billboards if null, 0.f is used
|
||||
* \param colorPtr Color of the billboards if null, Color::White is used
|
||||
*
|
||||
* \remark Produces a NazaraAssert if material is invalid
|
||||
*/
|
||||
|
||||
void ForwardRenderQueue::AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const Color> colorPtr)
|
||||
{
|
||||
NazaraAssert(material, "Invalid material");
|
||||
|
||||
///DOC: sinCosPtr et colorPtr peuvent être nuls, ils seront remplacés respectivement par Vector2f(0.f, 1.f) et Color::White
|
||||
float defaultRotation = 0.f;
|
||||
|
||||
if (!anglePtr)
|
||||
anglePtr.Reset(&defaultRotation, 0); // L'astuce ici est de mettre le stride sur zéro, rendant le pointeur immobile
|
||||
anglePtr.Reset(&defaultRotation, 0); // The trick here is to put the stride to zero, which leads the pointer to be immobile
|
||||
|
||||
if (!colorPtr)
|
||||
colorPtr.Reset(&Color::White, 0); // Pareil
|
||||
colorPtr.Reset(&Color::White, 0); // Same
|
||||
|
||||
auto& billboards = GetLayer(renderOrder).billboards;
|
||||
|
||||
auto it = billboards.find(material);
|
||||
if (it == billboards.end())
|
||||
{
|
||||
BatchedBillboardEntry entry;
|
||||
entry.materialReleaseSlot.Connect(material->OnMaterialRelease, this, &ForwardRenderQueue::OnMaterialInvalidation);
|
||||
|
||||
it = billboards.insert(std::make_pair(material, std::move(entry))).first;
|
||||
}
|
||||
|
||||
BatchedBillboardEntry& entry = it->second;
|
||||
|
||||
auto& billboardVector = entry.billboards;
|
||||
unsigned int prevSize = billboardVector.size();
|
||||
billboardVector.resize(prevSize + count);
|
||||
|
||||
BillboardData* billboardData = &billboardVector[prevSize];
|
||||
BillboardData* billboardData = GetBillboardData(renderOrder, material, count);
|
||||
for (unsigned int i = 0; i < count; ++i)
|
||||
{
|
||||
float sin = std::sin(ToRadians(*anglePtr));
|
||||
|
|
@ -161,39 +168,35 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds multiple billboards to the queue
|
||||
*
|
||||
* \param renderOrder Order of rendering
|
||||
* \param material Material of the billboards
|
||||
* \param count Number of billboards
|
||||
* \param positionPtr Position of the billboards
|
||||
* \param sizePtr Sizes of the billboards
|
||||
* \param anglePtr Rotation of the billboards if null, 0.f is used
|
||||
* \param alphaPtr Alpha parameters of the billboards if null, 1.f is used
|
||||
*
|
||||
* \remark Produces a NazaraAssert if material is invalid
|
||||
*/
|
||||
|
||||
void ForwardRenderQueue::AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr)
|
||||
{
|
||||
NazaraAssert(material, "Invalid material");
|
||||
|
||||
///DOC: sinCosPtr et alphaPtr peuvent être nuls, ils seront remplacés respectivement par Vector2f(0.f, 1.f) et Color::White
|
||||
float defaultRotation = 0.f;
|
||||
|
||||
if (!anglePtr)
|
||||
anglePtr.Reset(&defaultRotation, 0); // L'astuce ici est de mettre le stride sur zéro, rendant le pointeur immobile
|
||||
anglePtr.Reset(&defaultRotation, 0); // The trick here is to put the stride to zero, which leads the pointer to be immobile
|
||||
|
||||
float defaultAlpha = 1.f;
|
||||
|
||||
if (!alphaPtr)
|
||||
alphaPtr.Reset(&defaultAlpha, 0); // Pareil
|
||||
alphaPtr.Reset(&defaultAlpha, 0); // Same
|
||||
|
||||
auto& billboards = GetLayer(renderOrder).billboards;
|
||||
|
||||
auto it = billboards.find(material);
|
||||
if (it == billboards.end())
|
||||
{
|
||||
BatchedBillboardEntry entry;
|
||||
entry.materialReleaseSlot.Connect(material->OnMaterialRelease, this, &ForwardRenderQueue::OnMaterialInvalidation);
|
||||
|
||||
it = billboards.insert(std::make_pair(material, std::move(entry))).first;
|
||||
}
|
||||
|
||||
BatchedBillboardEntry& entry = it->second;
|
||||
|
||||
auto& billboardVector = entry.billboards;
|
||||
unsigned int prevSize = billboardVector.size();
|
||||
billboardVector.resize(prevSize + count);
|
||||
|
||||
BillboardData* billboardData = &billboardVector[prevSize];
|
||||
BillboardData* billboardData = GetBillboardData(renderOrder, material, count);
|
||||
for (unsigned int i = 0; i < count; ++i)
|
||||
{
|
||||
float sin = std::sin(ToRadians(*anglePtr));
|
||||
|
|
@ -208,37 +211,33 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds multiple billboards to the queue
|
||||
*
|
||||
* \param renderOrder Order of rendering
|
||||
* \param material Material of the billboards
|
||||
* \param count Number of billboards
|
||||
* \param positionPtr Position of the billboards
|
||||
* \param sizePtr Size of the billboards
|
||||
* \param sinCosPtr Rotation of the billboards if null, Vector2f(0.f, 1.f) is used
|
||||
* \param colorPtr Color of the billboards if null, Color::White is used
|
||||
*
|
||||
* \remark Produces a NazaraAssert if material is invalid
|
||||
*/
|
||||
|
||||
void ForwardRenderQueue::AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const Color> colorPtr)
|
||||
{
|
||||
NazaraAssert(material, "Invalid material");
|
||||
|
||||
///DOC: sinCosPtr et colorPtr peuvent être nuls, ils seront remplacés respectivement par Vector2f(0.f, 1.f) et Color::White
|
||||
Vector2f defaultSinCos(0.f, 1.f); // sin(0) = 0, cos(0) = 1
|
||||
|
||||
if (!sinCosPtr)
|
||||
sinCosPtr.Reset(&defaultSinCos, 0); // L'astuce ici est de mettre le stride sur zéro, rendant le pointeur immobile
|
||||
sinCosPtr.Reset(&defaultSinCos, 0); // The trick here is to put the stride to zero, which leads the pointer to be immobile
|
||||
|
||||
if (!colorPtr)
|
||||
colorPtr.Reset(&Color::White, 0); // Pareil
|
||||
colorPtr.Reset(&Color::White, 0); // Same
|
||||
|
||||
auto& billboards = GetLayer(renderOrder).billboards;
|
||||
|
||||
auto it = billboards.find(material);
|
||||
if (it == billboards.end())
|
||||
{
|
||||
BatchedBillboardEntry entry;
|
||||
entry.materialReleaseSlot.Connect(material->OnMaterialRelease, this, &ForwardRenderQueue::OnMaterialInvalidation);
|
||||
|
||||
it = billboards.insert(std::make_pair(material, std::move(entry))).first;
|
||||
}
|
||||
|
||||
BatchedBillboardEntry& entry = it->second;
|
||||
|
||||
auto& billboardVector = entry.billboards;
|
||||
unsigned int prevSize = billboardVector.size();
|
||||
billboardVector.resize(prevSize + count);
|
||||
|
||||
BillboardData* billboardData = &billboardVector[prevSize];
|
||||
BillboardData* billboardData = GetBillboardData(renderOrder, material, count);
|
||||
for (unsigned int i = 0; i < count; ++i)
|
||||
{
|
||||
billboardData->center = *positionPtr++;
|
||||
|
|
@ -249,39 +248,35 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds multiple billboards to the queue
|
||||
*
|
||||
* \param renderOrder Order of rendering
|
||||
* \param material Material of the billboards
|
||||
* \param count Number of billboards
|
||||
* \param positionPtr Position of the billboards
|
||||
* \param sizePtr Size of the billboards
|
||||
* \param sinCosPtr Rotation of the billboards if null, Vector2f(0.f, 1.f) is used
|
||||
* \param alphaPtr Alpha parameters of the billboards if null, 1.f is used
|
||||
*
|
||||
* \remark Produces a NazaraAssert if material is invalid
|
||||
*/
|
||||
|
||||
void ForwardRenderQueue::AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const float> alphaPtr)
|
||||
{
|
||||
NazaraAssert(material, "Invalid material");
|
||||
|
||||
///DOC: sinCosPtr et alphaPtr peuvent être nuls, ils seront remplacés respectivement par Vector2f(0.f, 1.f) et Color::White
|
||||
Vector2f defaultSinCos(0.f, 1.f); // sin(0) = 0, cos(0) = 1
|
||||
|
||||
if (!sinCosPtr)
|
||||
sinCosPtr.Reset(&defaultSinCos, 0); // L'astuce ici est de mettre le stride sur zéro, rendant le pointeur immobile
|
||||
sinCosPtr.Reset(&defaultSinCos, 0); // The trick here is to put the stride to zero, which leads the pointer to be immobile
|
||||
|
||||
float defaultAlpha = 1.f;
|
||||
|
||||
if (!alphaPtr)
|
||||
alphaPtr.Reset(&defaultAlpha, 0); // Pareil
|
||||
alphaPtr.Reset(&defaultAlpha, 0); // Same
|
||||
|
||||
auto& billboards = GetLayer(renderOrder).billboards;
|
||||
|
||||
auto it = billboards.find(material);
|
||||
if (it == billboards.end())
|
||||
{
|
||||
BatchedBillboardEntry entry;
|
||||
entry.materialReleaseSlot.Connect(material->OnMaterialRelease, this, &ForwardRenderQueue::OnMaterialInvalidation);
|
||||
|
||||
it = billboards.insert(std::make_pair(material, std::move(entry))).first;
|
||||
}
|
||||
|
||||
BatchedBillboardEntry& entry = it->second;
|
||||
|
||||
auto& billboardVector = entry.billboards;
|
||||
unsigned int prevSize = billboardVector.size();
|
||||
billboardVector.resize(prevSize + count);
|
||||
|
||||
BillboardData* billboardData = &billboardVector[prevSize];
|
||||
BillboardData* billboardData = GetBillboardData(renderOrder, material, count);
|
||||
for (unsigned int i = 0; i < count; ++i)
|
||||
{
|
||||
billboardData->center = *positionPtr++;
|
||||
|
|
@ -292,37 +287,33 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds multiple billboards to the queue
|
||||
*
|
||||
* \param renderOrder Order of rendering
|
||||
* \param material Material of the billboards
|
||||
* \param count Number of billboards
|
||||
* \param positionPtr Position of the billboards
|
||||
* \param sizePtr Size of the billboards
|
||||
* \param anglePtr Rotation of the billboards if null, 0.f is used
|
||||
* \param colorPtr Color of the billboards if null, Color::White is used
|
||||
*
|
||||
* \remark Produces a NazaraAssert if material is invalid
|
||||
*/
|
||||
|
||||
void ForwardRenderQueue::AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const Color> colorPtr)
|
||||
{
|
||||
NazaraAssert(material, "Invalid material");
|
||||
|
||||
///DOC: sinCosPtr et colorPtr peuvent être nuls, ils seront remplacés respectivement par Vector2f(0.f, 1.f) et Color::White
|
||||
float defaultRotation = 0.f;
|
||||
|
||||
if (!anglePtr)
|
||||
anglePtr.Reset(&defaultRotation, 0); // L'astuce ici est de mettre le stride sur zéro, rendant le pointeur immobile
|
||||
anglePtr.Reset(&defaultRotation, 0); // The trick here is to put the stride to zero, which leads the pointer to be immobile
|
||||
|
||||
if (!colorPtr)
|
||||
colorPtr.Reset(&Color::White, 0); // Pareil
|
||||
colorPtr.Reset(&Color::White, 0); // Same
|
||||
|
||||
auto& billboards = GetLayer(renderOrder).billboards;
|
||||
|
||||
auto it = billboards.find(material);
|
||||
if (it == billboards.end())
|
||||
{
|
||||
BatchedBillboardEntry entry;
|
||||
entry.materialReleaseSlot.Connect(material->OnMaterialRelease, this, &ForwardRenderQueue::OnMaterialInvalidation);
|
||||
|
||||
it = billboards.insert(std::make_pair(material, std::move(entry))).first;
|
||||
}
|
||||
|
||||
BatchedBillboardEntry& entry = it->second;
|
||||
|
||||
auto& billboardVector = entry.billboards;
|
||||
unsigned int prevSize = billboardVector.size();
|
||||
billboardVector.resize(prevSize + count);
|
||||
|
||||
BillboardData* billboardData = &billboardVector[prevSize];
|
||||
BillboardData* billboardData = GetBillboardData(renderOrder, material, count);
|
||||
for (unsigned int i = 0; i < count; ++i)
|
||||
{
|
||||
float sin = std::sin(ToRadians(*anglePtr));
|
||||
|
|
@ -337,39 +328,35 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds multiple billboards to the queue
|
||||
*
|
||||
* \param renderOrder Order of rendering
|
||||
* \param material Material of the billboards
|
||||
* \param count Number of billboards
|
||||
* \param positionPtr Position of the billboards
|
||||
* \param sizePtr Size of the billboards
|
||||
* \param anglePtr Rotation of the billboards if null, 0.f is used
|
||||
* \param alphaPtr Alpha parameters of the billboards if null, 1.f is used
|
||||
*
|
||||
* \remark Produces a NazaraAssert if material is invalid
|
||||
*/
|
||||
|
||||
void ForwardRenderQueue::AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr)
|
||||
{
|
||||
NazaraAssert(material, "Invalid material");
|
||||
|
||||
///DOC: sinCosPtr et alphaPtr peuvent être nuls, ils seront remplacés respectivement par Vector2f(0.f, 1.f) et Color::White
|
||||
float defaultRotation = 0.f;
|
||||
|
||||
if (!anglePtr)
|
||||
anglePtr.Reset(&defaultRotation, 0); // L'astuce ici est de mettre le stride sur zéro, rendant le pointeur immobile
|
||||
anglePtr.Reset(&defaultRotation, 0); // The trick here is to put the stride to zero, which leads the pointer to be immobile
|
||||
|
||||
float defaultAlpha = 1.f;
|
||||
|
||||
if (!alphaPtr)
|
||||
alphaPtr.Reset(&defaultAlpha, 0); // Pareil
|
||||
alphaPtr.Reset(&defaultAlpha, 0); // Same
|
||||
|
||||
auto& billboards = GetLayer(renderOrder).billboards;
|
||||
|
||||
auto it = billboards.find(material);
|
||||
if (it == billboards.end())
|
||||
{
|
||||
BatchedBillboardEntry entry;
|
||||
entry.materialReleaseSlot.Connect(material->OnMaterialRelease, this, &ForwardRenderQueue::OnMaterialInvalidation);
|
||||
|
||||
it = billboards.insert(std::make_pair(material, std::move(entry))).first;
|
||||
}
|
||||
|
||||
BatchedBillboardEntry& entry = it->second;
|
||||
|
||||
auto& billboardVector = entry.billboards;
|
||||
unsigned int prevSize = billboardVector.size();
|
||||
billboardVector.resize(prevSize + count);
|
||||
|
||||
BillboardData* billboardData = &billboardVector[prevSize];
|
||||
BillboardData* billboardData = GetBillboardData(renderOrder, material, count);
|
||||
for (unsigned int i = 0; i < count; ++i)
|
||||
{
|
||||
float sin = std::sin(ToRadians(*anglePtr));
|
||||
|
|
@ -384,6 +371,15 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds drawable to the queue
|
||||
*
|
||||
* \param renderOrder Order of rendering
|
||||
* \param drawable Drawable user defined
|
||||
*
|
||||
* \remark Produces a NazaraError if drawable is invalid
|
||||
*/
|
||||
|
||||
void ForwardRenderQueue::AddDrawable(int renderOrder, const Drawable* drawable)
|
||||
{
|
||||
#if NAZARA_GRAPHICS_SAFE
|
||||
|
|
@ -399,15 +395,29 @@ namespace Nz
|
|||
otherDrawables.push_back(drawable);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds mesh to the queue
|
||||
*
|
||||
* \param renderOrder Order of rendering
|
||||
* \param material Material of the mesh
|
||||
* \param meshData Data of the mesh
|
||||
* \param meshAABB Box of the mesh
|
||||
* \param transformMatrix Matrix of the mesh
|
||||
*
|
||||
* \remark Produces a NazaraAssert if material is invalid
|
||||
*/
|
||||
|
||||
void ForwardRenderQueue::AddMesh(int renderOrder, const Material* material, const MeshData& meshData, const Boxf& meshAABB, const Matrix4f& transformMatrix)
|
||||
{
|
||||
NazaraAssert(material, "Invalid material");
|
||||
|
||||
if (material->IsEnabled(RendererParameter_Blend))
|
||||
{
|
||||
Layer& currentLayer = GetLayer(renderOrder);
|
||||
auto& transparentModels = currentLayer.transparentModels;
|
||||
auto& transparentModelData = currentLayer.transparentModelData;
|
||||
|
||||
// Le matériau est transparent, nous devons rendre ce mesh d'une autre façon (après le rendu des objets opaques et en les triant)
|
||||
// The material is transparent, we must draw this mesh using another way (after the rendering of opages objects while sorting them)
|
||||
unsigned int index = transparentModelData.size();
|
||||
transparentModelData.resize(index+1);
|
||||
|
||||
|
|
@ -455,14 +465,28 @@ namespace Nz
|
|||
std::vector<Matrix4f>& instances = it2->second.instances;
|
||||
instances.push_back(transformMatrix);
|
||||
|
||||
// Avons-nous suffisamment d'instances pour que le coût d'utilisation de l'instancing soit payé ?
|
||||
// Do we have enough instances to perform instancing ?
|
||||
if (instances.size() >= NAZARA_GRAPHICS_INSTANCING_MIN_INSTANCES_COUNT)
|
||||
entry.instancingEnabled = true; // Apparemment oui, activons l'instancing avec ce matériau
|
||||
entry.instancingEnabled = true; // Thus we can activate it
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds sprites to the queue
|
||||
*
|
||||
* \param renderOrder Order of rendering
|
||||
* \param material Material of the sprites
|
||||
* \param vertices Buffer of data for the sprites
|
||||
* \param spriteCount Number of sprites
|
||||
* \param overlay Texture of the sprites
|
||||
*
|
||||
* \remark Produces a NazaraAssert if material is invalid
|
||||
*/
|
||||
|
||||
void ForwardRenderQueue::AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, unsigned int spriteCount, const Texture* overlay)
|
||||
{
|
||||
NazaraAssert(material, "Invalid material");
|
||||
|
||||
Layer& currentLayer = GetLayer(renderOrder);
|
||||
auto& basicSprites = currentLayer.basicSprites;
|
||||
|
||||
|
|
@ -494,6 +518,12 @@ namespace Nz
|
|||
spriteVector.push_back(SpriteChain_XYZ_Color_UV({vertices, spriteCount}));
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Clears the queue
|
||||
*
|
||||
* \param fully Should everything be cleared or we can keep layers
|
||||
*/
|
||||
|
||||
void ForwardRenderQueue::Clear(bool fully)
|
||||
{
|
||||
AbstractRenderQueue::Clear(fully);
|
||||
|
|
@ -518,15 +548,21 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sorts the object according to the viewer position, furthest to nearest
|
||||
*
|
||||
* \param viewer Viewer of the scene
|
||||
*/
|
||||
|
||||
void ForwardRenderQueue::Sort(const AbstractViewer* viewer)
|
||||
{
|
||||
Planef nearPlane = viewer->GetFrustum().GetPlane(FrustumPlane_Near);
|
||||
Vector3f viewerPos = viewer->GetEyePosition();
|
||||
Vector3f viewerNormal = viewer->GetForward();
|
||||
|
||||
for (auto& layerPair : layers)
|
||||
for (auto& pair : layers)
|
||||
{
|
||||
Layer& layer = layerPair.second;
|
||||
Layer& layer = pair.second;
|
||||
|
||||
std::sort(layer.transparentModels.begin(), layer.transparentModels.end(), [&layer, &nearPlane, &viewerNormal] (unsigned int index1, unsigned int index2)
|
||||
{
|
||||
|
|
@ -557,6 +593,43 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the billboard data
|
||||
* \return Pointer to the data of the billboards
|
||||
*
|
||||
* \param renderOrder Order of rendering
|
||||
* \param material Material of the billboard
|
||||
*/
|
||||
|
||||
ForwardRenderQueue::BillboardData* ForwardRenderQueue::GetBillboardData(int renderOrder, const Material* material, unsigned int count)
|
||||
{
|
||||
auto& billboards = GetLayer(renderOrder).billboards;
|
||||
|
||||
auto it = billboards.find(material);
|
||||
if (it == billboards.end())
|
||||
{
|
||||
BatchedBillboardEntry entry;
|
||||
entry.materialReleaseSlot.Connect(material->OnMaterialRelease, this, &ForwardRenderQueue::OnMaterialInvalidation);
|
||||
|
||||
it = billboards.insert(std::make_pair(material, std::move(entry))).first;
|
||||
}
|
||||
|
||||
BatchedBillboardEntry& entry = it->second;
|
||||
|
||||
auto& billboardVector = entry.billboards;
|
||||
unsigned int prevSize = billboardVector.size();
|
||||
billboardVector.resize(prevSize + count);
|
||||
|
||||
return &billboardVector[prevSize];
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the ith layer
|
||||
* \return Reference to the ith layer for the queue
|
||||
*
|
||||
* \param i Index of the layer
|
||||
*/
|
||||
|
||||
ForwardRenderQueue::Layer& ForwardRenderQueue::GetLayer(int i)
|
||||
{
|
||||
auto it = layers.find(i);
|
||||
|
|
@ -569,6 +642,12 @@ namespace Nz
|
|||
return layer;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Handle the invalidation of an index buffer
|
||||
*
|
||||
* \param indexBuffer Index buffer being invalidated
|
||||
*/
|
||||
|
||||
void ForwardRenderQueue::OnIndexBufferInvalidation(const IndexBuffer* indexBuffer)
|
||||
{
|
||||
for (auto& pair : layers)
|
||||
|
|
@ -590,6 +669,12 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Handle the invalidation of a material
|
||||
*
|
||||
* \param material Material being invalidated
|
||||
*/
|
||||
|
||||
void ForwardRenderQueue::OnMaterialInvalidation(const Material* material)
|
||||
{
|
||||
for (auto& pair : layers)
|
||||
|
|
@ -602,6 +687,12 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Handle the invalidation of a texture
|
||||
*
|
||||
* \param texture Texture being invalidated
|
||||
*/
|
||||
|
||||
void ForwardRenderQueue::OnTextureInvalidation(const Texture* texture)
|
||||
{
|
||||
for (auto& pair : layers)
|
||||
|
|
@ -615,6 +706,12 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Handle the invalidation of a vertex buffer
|
||||
*
|
||||
* \param vertexBuffer Vertex buffer being invalidated
|
||||
*/
|
||||
|
||||
void ForwardRenderQueue::OnVertexBufferInvalidation(const VertexBuffer* vertexBuffer)
|
||||
{
|
||||
for (auto& pair : layers)
|
||||
|
|
@ -635,6 +732,14 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Functor to compare two batched billboard with material
|
||||
* \return true If first material is "smaller" than the second one
|
||||
*
|
||||
* \param mat1 First material to compare
|
||||
* \param mat2 Second material to compare
|
||||
*/
|
||||
|
||||
bool ForwardRenderQueue::BatchedBillboardComparator::operator()(const Material* mat1, const Material* mat2) const
|
||||
{
|
||||
const UberShader* uberShader1 = mat1->GetShader();
|
||||
|
|
@ -655,6 +760,14 @@ namespace Nz
|
|||
return mat1 < mat2;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Functor to compare two batched model with material
|
||||
* \return true If first material is "smaller" than the second one
|
||||
*
|
||||
* \param mat1 First material to compare
|
||||
* \param mat2 Second material to compare
|
||||
*/
|
||||
|
||||
bool ForwardRenderQueue::BatchedModelMaterialComparator::operator()(const Material* mat1, const Material* mat2) const
|
||||
{
|
||||
const UberShader* uberShader1 = mat1->GetShader();
|
||||
|
|
@ -675,6 +788,14 @@ namespace Nz
|
|||
return mat1 < mat2;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Functor to compare two batched sprites with material
|
||||
* \return true If first material is "smaller" than the second one
|
||||
*
|
||||
* \param mat1 First material to compare
|
||||
* \param mat2 Second material to compare
|
||||
*/
|
||||
|
||||
bool ForwardRenderQueue::BatchedSpriteMaterialComparator::operator()(const Material* mat1, const Material* mat2)
|
||||
{
|
||||
const UberShader* uberShader1 = mat1->GetShader();
|
||||
|
|
@ -695,6 +816,14 @@ namespace Nz
|
|||
return mat1 < mat2;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Functor to compare two mesh data
|
||||
* \return true If first mesh is "smaller" than the second one
|
||||
*
|
||||
* \param data1 First mesh to compare
|
||||
* \param data2 Second mesh to compare
|
||||
*/
|
||||
|
||||
bool ForwardRenderQueue::MeshDataComparator::operator()(const MeshData& data1, const MeshData& data2) const
|
||||
{
|
||||
const Buffer* buffer1;
|
||||
|
|
|
|||
|
|
@ -33,10 +33,20 @@ namespace Nz
|
|||
Vector2f uv;
|
||||
};
|
||||
|
||||
unsigned int s_maxQuads = std::numeric_limits<UInt16>::max()/6;
|
||||
unsigned int s_vertexBufferSize = 4*1024*1024; // 4 MiB
|
||||
unsigned int s_maxQuads = std::numeric_limits<UInt16>::max() / 6;
|
||||
unsigned int s_vertexBufferSize = 4 * 1024 * 1024; // 4 MiB
|
||||
}
|
||||
|
||||
/*!
|
||||
* \ingroup graphics
|
||||
* \class Nz::ForwardRenderTechnique
|
||||
* \brief Graphics class that represents the technique used in forward rendering
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Constructs a ForwardRenderTechnique object by default
|
||||
*/
|
||||
|
||||
ForwardRenderTechnique::ForwardRenderTechnique() :
|
||||
m_vertexBuffer(BufferType_Vertex),
|
||||
m_maxLightPassPerObject(3)
|
||||
|
|
@ -49,6 +59,12 @@ namespace Nz
|
|||
m_spriteBuffer.Reset(VertexDeclaration::Get(VertexLayout_XYZ_Color_UV), &m_vertexBuffer);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Clears the data
|
||||
*
|
||||
* \param sceneData Data of the scene
|
||||
*/
|
||||
|
||||
void ForwardRenderTechnique::Clear(const SceneData& sceneData) const
|
||||
{
|
||||
Renderer::Enable(RendererParameter_DepthBuffer, true);
|
||||
|
|
@ -59,6 +75,15 @@ namespace Nz
|
|||
sceneData.background->Draw(sceneData.viewer);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Draws the data of the scene
|
||||
* \return true If successful
|
||||
*
|
||||
* \param sceneData Data of the scene
|
||||
*
|
||||
* \remark Produces a NazaraAssert if viewer of the scene is invalid
|
||||
*/
|
||||
|
||||
bool ForwardRenderTechnique::Draw(const SceneData& sceneData) const
|
||||
{
|
||||
NazaraAssert(sceneData.viewer, "Invalid viewer");
|
||||
|
|
@ -88,55 +113,83 @@ namespace Nz
|
|||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the maximum number of lights available per pass per object
|
||||
* \return Maximum number of light simulatenously per object
|
||||
*/
|
||||
|
||||
unsigned int ForwardRenderTechnique::GetMaxLightPassPerObject() const
|
||||
{
|
||||
return m_maxLightPassPerObject;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the render queue
|
||||
* \return Pointer to the render queue
|
||||
*/
|
||||
|
||||
AbstractRenderQueue* ForwardRenderTechnique::GetRenderQueue()
|
||||
{
|
||||
return &m_renderQueue;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the type of the current technique
|
||||
* \return Type of the render technique
|
||||
*/
|
||||
|
||||
RenderTechniqueType ForwardRenderTechnique::GetType() const
|
||||
{
|
||||
return RenderTechniqueType_BasicForward;
|
||||
}
|
||||
|
||||
void ForwardRenderTechnique::SetMaxLightPassPerObject(unsigned int passCount)
|
||||
/*!
|
||||
* \brief Sets the maximum number of lights available per pass per object
|
||||
*
|
||||
* \param passCount Maximum number of light simulatenously per object
|
||||
*/
|
||||
|
||||
void ForwardRenderTechnique::SetMaxLightPassPerObject(unsigned int maxLightPassPerObject)
|
||||
{
|
||||
m_maxLightPassPerObject = passCount;
|
||||
m_maxLightPassPerObject = maxLightPassPerObject;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Initializes the forward render technique
|
||||
* \return true If successful
|
||||
*
|
||||
* \remark Produces a NazaraError if one shader creation failed
|
||||
*/
|
||||
|
||||
bool ForwardRenderTechnique::Initialize()
|
||||
{
|
||||
try
|
||||
{
|
||||
ErrorFlags flags(ErrorFlag_ThrowException, true);
|
||||
|
||||
s_quadIndexBuffer.Reset(false, s_maxQuads*6, DataStorage_Hardware, BufferUsage_Static);
|
||||
s_quadIndexBuffer.Reset(false, s_maxQuads * 6, DataStorage_Hardware, BufferUsage_Static);
|
||||
|
||||
BufferMapper<IndexBuffer> mapper(s_quadIndexBuffer, BufferAccess_WriteOnly);
|
||||
UInt16* indices = static_cast<UInt16*>(mapper.GetPointer());
|
||||
|
||||
for (unsigned int i = 0; i < s_maxQuads; ++i)
|
||||
{
|
||||
*indices++ = i*4 + 0;
|
||||
*indices++ = i*4 + 2;
|
||||
*indices++ = i*4 + 1;
|
||||
*indices++ = i * 4 + 0;
|
||||
*indices++ = i * 4 + 2;
|
||||
*indices++ = i * 4 + 1;
|
||||
|
||||
*indices++ = i*4 + 2;
|
||||
*indices++ = i*4 + 3;
|
||||
*indices++ = i*4 + 1;
|
||||
*indices++ = i * 4 + 2;
|
||||
*indices++ = i * 4 + 3;
|
||||
*indices++ = i * 4 + 1;
|
||||
}
|
||||
|
||||
mapper.Unmap(); // Inutile de garder le buffer ouvert plus longtemps
|
||||
mapper.Unmap(); // No point to keep the buffer open any longer
|
||||
|
||||
// Quad buffer (utilisé pour l'instancing de billboard et de sprites)
|
||||
//Note: Les UV sont calculés dans le shader
|
||||
// Quad buffer (used for instancing of billboards and sprites)
|
||||
//Note: UV are computed in the shader
|
||||
s_quadVertexBuffer.Reset(VertexDeclaration::Get(VertexLayout_XY), 4, DataStorage_Hardware, BufferUsage_Static);
|
||||
|
||||
float vertices[2*4] = {
|
||||
float vertices[2 * 4] = {
|
||||
-0.5f, -0.5f,
|
||||
0.5f, -0.5f,
|
||||
-0.5f, 0.5f,
|
||||
|
|
@ -145,14 +198,14 @@ namespace Nz
|
|||
|
||||
s_quadVertexBuffer.FillRaw(vertices, 0, sizeof(vertices));
|
||||
|
||||
// Déclaration lors du rendu des billboards par sommet
|
||||
// Declaration used when rendering the vertex billboards
|
||||
s_billboardVertexDeclaration.EnableComponent(VertexComponent_Color, ComponentType_Color, NazaraOffsetOf(BillboardPoint, color));
|
||||
s_billboardVertexDeclaration.EnableComponent(VertexComponent_Position, ComponentType_Float3, NazaraOffsetOf(BillboardPoint, position));
|
||||
s_billboardVertexDeclaration.EnableComponent(VertexComponent_TexCoord, ComponentType_Float2, NazaraOffsetOf(BillboardPoint, uv));
|
||||
s_billboardVertexDeclaration.EnableComponent(VertexComponent_Userdata0, ComponentType_Float4, NazaraOffsetOf(BillboardPoint, size)); // Englobe sincos
|
||||
s_billboardVertexDeclaration.EnableComponent(VertexComponent_Userdata0, ComponentType_Float4, NazaraOffsetOf(BillboardPoint, size)); // Includes sincos
|
||||
|
||||
// Declaration utilisée lors du rendu des billboards par instancing
|
||||
// L'avantage ici est la copie directe (std::memcpy) des données de la RenderQueue vers le buffer GPU
|
||||
// Declaration used when rendering the billboards with intancing
|
||||
// The main advantage is the direct copy (std::memcpy) of data in the RenderQueue to the GPU buffer
|
||||
s_billboardInstanceDeclaration.EnableComponent(VertexComponent_InstanceData0, ComponentType_Float3, NazaraOffsetOf(ForwardRenderQueue::BillboardData, center));
|
||||
s_billboardInstanceDeclaration.EnableComponent(VertexComponent_InstanceData1, ComponentType_Float4, NazaraOffsetOf(ForwardRenderQueue::BillboardData, size)); // Englobe sincos
|
||||
s_billboardInstanceDeclaration.EnableComponent(VertexComponent_InstanceData2, ComponentType_Color, NazaraOffsetOf(ForwardRenderQueue::BillboardData, color));
|
||||
|
|
@ -169,12 +222,23 @@ namespace Nz
|
|||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Uninitializes the forward render technique
|
||||
*/
|
||||
|
||||
void ForwardRenderTechnique::Uninitialize()
|
||||
{
|
||||
s_quadIndexBuffer.Reset();
|
||||
s_quadVertexBuffer.Reset();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Chooses the nearest lights for one object
|
||||
*
|
||||
* \param object Sphere symbolising the object
|
||||
* \param includeDirectionalLights Should directional lights be included in the computation
|
||||
*/
|
||||
|
||||
void ForwardRenderTechnique::ChooseLights(const Spheref& object, bool includeDirectionalLights) const
|
||||
{
|
||||
m_lights.clear();
|
||||
|
|
@ -213,6 +277,15 @@ namespace Nz
|
|||
});
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Draws basic sprites
|
||||
*
|
||||
* \param sceneData Data of the scene
|
||||
* \param layer Layer of the rendering
|
||||
*
|
||||
* \remark Produces a NazaraAssert is viewer is invalid
|
||||
*/
|
||||
|
||||
void ForwardRenderTechnique::DrawBasicSprites(const SceneData& sceneData, ForwardRenderQueue::Layer& layer) const
|
||||
{
|
||||
NazaraAssert(sceneData.viewer, "Invalid viewer");
|
||||
|
|
@ -240,7 +313,7 @@ namespace Nz
|
|||
unsigned int spriteChainCount = spriteChainVector.size();
|
||||
if (spriteChainCount > 0)
|
||||
{
|
||||
// On commence par appliquer du matériau (et récupérer le shader ainsi activé)
|
||||
// We begin to apply the material (and get the shader activated doing so)
|
||||
UInt32 flags = ShaderFlags_VertexColor;
|
||||
if (overlay)
|
||||
flags |= ShaderFlags_TextureOverlay;
|
||||
|
|
@ -255,46 +328,46 @@ namespace Nz
|
|||
Renderer::SetTextureSampler(overlayUnit, material->GetDiffuseSampler());
|
||||
}
|
||||
|
||||
// Les uniformes sont conservées au sein d'un programme, inutile de les renvoyer tant qu'il ne change pas
|
||||
// Uniforms are conserved in our program, there's no point to send them back until they change
|
||||
if (shader != lastShader)
|
||||
{
|
||||
// Index des uniformes dans le shader
|
||||
// Index of uniforms in the shader
|
||||
shaderUniforms = GetShaderUniforms(shader);
|
||||
|
||||
// Couleur ambiante de la scène
|
||||
// Ambiant color of the scene
|
||||
shader->SendColor(shaderUniforms->sceneAmbient, sceneData.ambientColor);
|
||||
// Overlay
|
||||
shader->SendInteger(shaderUniforms->textureOverlay, overlayUnit);
|
||||
// Position de la caméra
|
||||
// Position of the camera
|
||||
shader->SendVector(shaderUniforms->eyePosition, sceneData.viewer->GetEyePosition());
|
||||
|
||||
lastShader = shader;
|
||||
}
|
||||
|
||||
unsigned int spriteChain = 0; // Quelle chaîne de sprite traitons-nous
|
||||
unsigned int spriteChainOffset = 0; // À quel offset dans la dernière chaîne nous sommes-nous arrêtés
|
||||
unsigned int spriteChain = 0; // Which chain of sprites are we treating
|
||||
unsigned int spriteChainOffset = 0; // Where was the last offset where we stopped in the last chain
|
||||
|
||||
do
|
||||
{
|
||||
// On ouvre le buffer en écriture
|
||||
// We open the buffer in writing mode
|
||||
BufferMapper<VertexBuffer> vertexMapper(m_spriteBuffer, BufferAccess_DiscardAndWrite);
|
||||
VertexStruct_XYZ_Color_UV* vertices = static_cast<VertexStruct_XYZ_Color_UV*>(vertexMapper.GetPointer());
|
||||
|
||||
unsigned int spriteCount = 0;
|
||||
unsigned int maxSpriteCount = std::min(s_maxQuads, m_spriteBuffer.GetVertexCount()/4);
|
||||
unsigned int maxSpriteCount = std::min(s_maxQuads, m_spriteBuffer.GetVertexCount() / 4);
|
||||
|
||||
do
|
||||
{
|
||||
ForwardRenderQueue::SpriteChain_XYZ_Color_UV& currentChain = spriteChainVector[spriteChain];
|
||||
unsigned int count = std::min(maxSpriteCount - spriteCount, currentChain.spriteCount - spriteChainOffset);
|
||||
|
||||
std::memcpy(vertices, currentChain.vertices + spriteChainOffset*4, 4*count*sizeof(VertexStruct_XYZ_Color_UV));
|
||||
vertices += count*4;
|
||||
std::memcpy(vertices, currentChain.vertices + spriteChainOffset * 4, 4 * count * sizeof(VertexStruct_XYZ_Color_UV));
|
||||
vertices += count * 4;
|
||||
|
||||
spriteCount += count;
|
||||
spriteChainOffset += count;
|
||||
|
||||
// Avons-nous traité la chaîne entière ?
|
||||
// Have we treated the entire chain ?
|
||||
if (spriteChainOffset == currentChain.spriteCount)
|
||||
{
|
||||
spriteChain++;
|
||||
|
|
@ -305,7 +378,7 @@ namespace Nz
|
|||
|
||||
vertexMapper.Unmap();
|
||||
|
||||
Renderer::DrawIndexedPrimitives(PrimitiveMode_TriangleList, 0, spriteCount*6);
|
||||
Renderer::DrawIndexedPrimitives(PrimitiveMode_TriangleList, 0, spriteCount * 6);
|
||||
}
|
||||
while (spriteChain < spriteChainCount);
|
||||
|
||||
|
|
@ -313,12 +386,21 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
// On remet à zéro
|
||||
// We set it back to zero
|
||||
matEntry.enabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Draws billboards
|
||||
*
|
||||
* \param sceneData Data of the scene
|
||||
* \param layer Layer of the rendering
|
||||
*
|
||||
* \remark Produces a NazaraAssert is viewer is invalid
|
||||
*/
|
||||
|
||||
void ForwardRenderTechnique::DrawBillboards(const SceneData& sceneData, ForwardRenderQueue::Layer& layer) const
|
||||
{
|
||||
NazaraAssert(sceneData.viewer, "Invalid viewer");
|
||||
|
|
@ -342,18 +424,18 @@ namespace Nz
|
|||
unsigned int billboardCount = billboardVector.size();
|
||||
if (billboardCount > 0)
|
||||
{
|
||||
// On commence par appliquer du matériau (et récupérer le shader ainsi activé)
|
||||
// We begin to apply the material (and get the shader activated doing so)
|
||||
const Shader* shader = material->Apply(ShaderFlags_Billboard | ShaderFlags_Instancing | ShaderFlags_VertexColor);
|
||||
|
||||
// Les uniformes sont conservées au sein d'un programme, inutile de les renvoyer tant qu'il ne change pas
|
||||
// Uniforms are conserved in our program, there's no point to send them back until they change
|
||||
if (shader != lastShader)
|
||||
{
|
||||
// Index des uniformes dans le shader
|
||||
// Index of uniforms in the shader
|
||||
shaderUniforms = GetShaderUniforms(shader);
|
||||
|
||||
// Couleur ambiante de la scène
|
||||
// Ambiant color of the scene
|
||||
shader->SendColor(shaderUniforms->sceneAmbient, sceneData.ambientColor);
|
||||
// Position de la caméra
|
||||
// Position of the camera
|
||||
shader->SendVector(shaderUniforms->eyePosition, sceneData.viewer->GetEyePosition());
|
||||
|
||||
lastShader = shader;
|
||||
|
|
@ -391,32 +473,32 @@ namespace Nz
|
|||
unsigned int billboardCount = billboardVector.size();
|
||||
if (billboardCount > 0)
|
||||
{
|
||||
// On commence par appliquer du matériau (et récupérer le shader ainsi activé)
|
||||
// We begin to apply the material (and get the shader activated doing so)
|
||||
const Shader* shader = material->Apply(ShaderFlags_Billboard | ShaderFlags_VertexColor);
|
||||
|
||||
// Les uniformes sont conservées au sein d'un programme, inutile de les renvoyer tant qu'il ne change pas
|
||||
// Uniforms are conserved in our program, there's no point to send them back until they change
|
||||
if (shader != lastShader)
|
||||
{
|
||||
// Index des uniformes dans le shader
|
||||
// Index of uniforms in the shader
|
||||
shaderUniforms = GetShaderUniforms(shader);
|
||||
|
||||
// Couleur ambiante de la scène
|
||||
// Ambiant color of the scene
|
||||
shader->SendColor(shaderUniforms->sceneAmbient, sceneData.ambientColor);
|
||||
// Position de la caméra
|
||||
// Position of the camera
|
||||
shader->SendVector(shaderUniforms->eyePosition, sceneData.viewer->GetEyePosition());
|
||||
|
||||
lastShader = shader;
|
||||
}
|
||||
|
||||
const ForwardRenderQueue::BillboardData* data = &billboardVector[0];
|
||||
unsigned int maxBillboardPerDraw = std::min(s_maxQuads, m_billboardPointBuffer.GetVertexCount()/4);
|
||||
unsigned int maxBillboardPerDraw = std::min(s_maxQuads, m_billboardPointBuffer.GetVertexCount() / 4);
|
||||
|
||||
do
|
||||
{
|
||||
unsigned int renderedBillboardCount = std::min(billboardCount, maxBillboardPerDraw);
|
||||
billboardCount -= renderedBillboardCount;
|
||||
|
||||
BufferMapper<VertexBuffer> vertexMapper(m_billboardPointBuffer, BufferAccess_DiscardAndWrite, 0, renderedBillboardCount*4);
|
||||
BufferMapper<VertexBuffer> vertexMapper(m_billboardPointBuffer, BufferAccess_DiscardAndWrite, 0, renderedBillboardCount * 4);
|
||||
BillboardPoint* vertices = static_cast<BillboardPoint*>(vertexMapper.GetPointer());
|
||||
|
||||
for (unsigned int i = 0; i < renderedBillboardCount; ++i)
|
||||
|
|
@ -454,7 +536,7 @@ namespace Nz
|
|||
|
||||
vertexMapper.Unmap();
|
||||
|
||||
Renderer::DrawIndexedPrimitives(PrimitiveMode_TriangleList, 0, renderedBillboardCount*6);
|
||||
Renderer::DrawIndexedPrimitives(PrimitiveMode_TriangleList, 0, renderedBillboardCount * 6);
|
||||
}
|
||||
while (billboardCount > 0);
|
||||
|
||||
|
|
@ -464,6 +546,15 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Draws opaques models
|
||||
*
|
||||
* \param sceneData Data of the scene
|
||||
* \param layer Layer of the rendering
|
||||
*
|
||||
* \remark Produces a NazaraAssert is viewer is invalid
|
||||
*/
|
||||
|
||||
void ForwardRenderTechnique::DrawOpaqueModels(const SceneData& sceneData, ForwardRenderQueue::Layer& layer) const
|
||||
{
|
||||
NazaraAssert(sceneData.viewer, "Invalid viewer");
|
||||
|
|
@ -483,25 +574,25 @@ namespace Nz
|
|||
{
|
||||
const Material* material = matIt.first;
|
||||
|
||||
// Nous utilisons de l'instancing que lorsqu'aucune lumière (autre que directionnelle) n'est active
|
||||
// Ceci car l'instancing n'est pas compatible avec la recherche des lumières les plus proches
|
||||
// (Le deferred shading n'a pas ce problème)
|
||||
// We only use instancing when no light (other than directional) is active
|
||||
// This is because instancing is not compatible with the search of nearest lights
|
||||
// Deferred shading does not have this problem
|
||||
bool noPointSpotLight = m_renderQueue.pointLights.empty() && m_renderQueue.spotLights.empty();
|
||||
bool instancing = m_instancingEnabled && (!material->IsLightingEnabled() || noPointSpotLight) && matEntry.instancingEnabled;
|
||||
|
||||
// On commence par appliquer du matériau (et récupérer le shader ainsi activé)
|
||||
// We begin to apply the material (and get the shader activated doing so)
|
||||
UInt8 freeTextureUnit;
|
||||
const Shader* shader = material->Apply((instancing) ? ShaderFlags_Instancing : 0, 0, &freeTextureUnit);
|
||||
|
||||
// Les uniformes sont conservées au sein d'un programme, inutile de les renvoyer tant qu'il ne change pas
|
||||
// Uniforms are conserved in our program, there's no point to send them back until they change
|
||||
if (shader != lastShader)
|
||||
{
|
||||
// Index des uniformes dans le shader
|
||||
// Index of uniforms in the shader
|
||||
shaderUniforms = GetShaderUniforms(shader);
|
||||
|
||||
// Couleur ambiante de la scène
|
||||
// Ambiant color of the scene
|
||||
shader->SendColor(shaderUniforms->sceneAmbient, sceneData.ambientColor);
|
||||
// Position de la caméra
|
||||
// Position of the camera
|
||||
shader->SendVector(shaderUniforms->eyePosition, sceneData.viewer->GetEyePosition());
|
||||
|
||||
lastShader = shader;
|
||||
|
|
@ -521,7 +612,7 @@ namespace Nz
|
|||
const IndexBuffer* indexBuffer = meshData.indexBuffer;
|
||||
const VertexBuffer* vertexBuffer = meshData.vertexBuffer;
|
||||
|
||||
// Gestion du draw call avant la boucle de rendu
|
||||
// Handle draw call before rendering loop
|
||||
Renderer::DrawCall drawFunc;
|
||||
Renderer::DrawCallInstanced instancedDrawFunc;
|
||||
unsigned int indexCount;
|
||||
|
|
@ -544,17 +635,17 @@ namespace Nz
|
|||
|
||||
if (instancing)
|
||||
{
|
||||
// On calcule le nombre d'instances que l'on pourra afficher cette fois-ci (Selon la taille du buffer d'instancing)
|
||||
// We compute the number of instances that we will be able to draw this time (depending on the instancing buffer size)
|
||||
VertexBuffer* instanceBuffer = Renderer::GetInstanceBuffer();
|
||||
instanceBuffer->SetVertexDeclaration(VertexDeclaration::Get(VertexLayout_Matrix4));
|
||||
|
||||
// Avec l'instancing, impossible de sélectionner les lumières pour chaque objet
|
||||
// Du coup, il n'est activé que pour les lumières directionnelles
|
||||
// With instancing, impossible to select the lights for each object
|
||||
// So, it's only activated for directional lights
|
||||
unsigned int lightCount = m_renderQueue.directionalLights.size();
|
||||
unsigned int lightIndex = 0;
|
||||
RendererComparison oldDepthFunc = Renderer::GetDepthFunc();
|
||||
|
||||
unsigned int passCount = (lightCount == 0) ? 1 : (lightCount-1)/NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS + 1;
|
||||
unsigned int passCount = (lightCount == 0) ? 1 : (lightCount - 1) / NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS + 1;
|
||||
for (unsigned int pass = 0; pass < passCount; ++pass)
|
||||
{
|
||||
if (shaderUniforms->hasLightUniforms)
|
||||
|
|
@ -564,10 +655,10 @@ namespace Nz
|
|||
|
||||
if (pass == 1)
|
||||
{
|
||||
// Pour additionner le résultat des calculs de lumière
|
||||
// Aucune chance d'interférer avec les paramètres du matériau car nous ne rendons que les objets opaques
|
||||
// (Autrement dit, sans blending)
|
||||
// Quant à la fonction de profondeur, elle ne doit être appliquée que la première fois
|
||||
// To add the result of light computations
|
||||
// We won't interfeer with materials parameters because we only render opaques objects
|
||||
// (A.K.A., without blending)
|
||||
// About the depth function, it must be applied only the first time
|
||||
Renderer::Enable(RendererParameter_Blend, true);
|
||||
Renderer::SetBlendFunc(BlendFunc_One, BlendFunc_One);
|
||||
Renderer::SetDepthFunc(RendererComparison_Equal);
|
||||
|
|
@ -575,32 +666,32 @@ namespace Nz
|
|||
|
||||
// Sends the uniforms
|
||||
for (unsigned int i = 0; i < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS; ++i)
|
||||
SendLightUniforms(shader, shaderUniforms->lightUniforms, lightIndex++, shaderUniforms->lightOffset*i, freeTextureUnit + i);
|
||||
SendLightUniforms(shader, shaderUniforms->lightUniforms, lightIndex++, shaderUniforms->lightOffset * i, freeTextureUnit + i);
|
||||
|
||||
// Et on passe à l'affichage
|
||||
// And we give them to draw
|
||||
drawFunc(meshData.primitiveMode, 0, indexCount);
|
||||
}
|
||||
|
||||
const Matrix4f* instanceMatrices = &instances[0];
|
||||
unsigned int instanceCount = instances.size();
|
||||
unsigned int maxInstanceCount = instanceBuffer->GetVertexCount(); // Le nombre maximum d'instances en une fois
|
||||
unsigned int maxInstanceCount = instanceBuffer->GetVertexCount(); // Maximum number of instance in one batch
|
||||
|
||||
while (instanceCount > 0)
|
||||
{
|
||||
// On calcule le nombre d'instances que l'on pourra afficher cette fois-ci (Selon la taille du buffer d'instancing)
|
||||
// We compute the number of instances that we will be able to draw this time (depending on the instancing buffer size)
|
||||
unsigned int renderedInstanceCount = std::min(instanceCount, maxInstanceCount);
|
||||
instanceCount -= renderedInstanceCount;
|
||||
|
||||
// On remplit l'instancing buffer avec nos matrices world
|
||||
// We fill the instancing buffer with our world matrices
|
||||
instanceBuffer->Fill(instanceMatrices, 0, renderedInstanceCount, true);
|
||||
instanceMatrices += renderedInstanceCount;
|
||||
|
||||
// Et on affiche
|
||||
// And we draw
|
||||
instancedDrawFunc(renderedInstanceCount, meshData.primitiveMode, 0, indexCount);
|
||||
}
|
||||
}
|
||||
|
||||
// On n'oublie pas de désactiver le blending pour ne pas interférer sur le reste du rendu
|
||||
// We don't forget to disable the blending to avoid to interfeer with the rest of the rendering
|
||||
Renderer::Enable(RendererParameter_Blend, false);
|
||||
Renderer::SetDepthFunc(oldDepthFunc);
|
||||
}
|
||||
|
|
@ -617,19 +708,19 @@ namespace Nz
|
|||
|
||||
Renderer::SetMatrix(MatrixType_World, matrix);
|
||||
unsigned int lightIndex = 0;
|
||||
RendererComparison oldDepthFunc = Renderer::GetDepthFunc(); // Dans le cas où nous aurions à le changer
|
||||
RendererComparison oldDepthFunc = Renderer::GetDepthFunc(); // In the case where we have to change it
|
||||
|
||||
unsigned int passCount = (lightCount == 0) ? 1 : (lightCount-1)/NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS + 1;
|
||||
unsigned int passCount = (lightCount == 0) ? 1 : (lightCount - 1) / NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS + 1;
|
||||
for (unsigned int pass = 0; pass < passCount; ++pass)
|
||||
{
|
||||
lightCount -= std::min(lightCount, NazaraSuffixMacro(NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS, U));
|
||||
|
||||
if (pass == 1)
|
||||
{
|
||||
// Pour additionner le résultat des calculs de lumière
|
||||
// Aucune chance d'interférer avec les paramètres du matériau car nous ne rendons que les objets opaques
|
||||
// (Autrement dit, sans blending)
|
||||
// Quant à la fonction de profondeur, elle ne doit être appliquée que la première fois
|
||||
// To add the result of light computations
|
||||
// We won't interfeer with materials parameters because we only render opaques objects
|
||||
// (A.K.A., without blending)
|
||||
// About the depth function, it must be applied only the first time
|
||||
Renderer::Enable(RendererParameter_Blend, true);
|
||||
Renderer::SetBlendFunc(BlendFunc_One, BlendFunc_One);
|
||||
Renderer::SetDepthFunc(RendererComparison_Equal);
|
||||
|
|
@ -639,7 +730,7 @@ namespace Nz
|
|||
for (unsigned int i = 0; i < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS; ++i)
|
||||
SendLightUniforms(shader, shaderUniforms->lightUniforms, lightIndex++, shaderUniforms->lightOffset*i, freeTextureUnit + i);
|
||||
|
||||
// Et on passe à l'affichage
|
||||
// And we draw
|
||||
drawFunc(meshData.primitiveMode, 0, indexCount);
|
||||
}
|
||||
|
||||
|
|
@ -649,9 +740,9 @@ namespace Nz
|
|||
}
|
||||
else
|
||||
{
|
||||
// Sans instancing, on doit effectuer un draw call pour chaque instance
|
||||
// Cela reste néanmoins plus rapide que l'instancing en dessous d'un certain nombre d'instances
|
||||
// À cause du temps de modification du buffer d'instancing
|
||||
// Without instancing, we must do a draw call for each instance
|
||||
// This may be faster than instancing under a certain number
|
||||
// Due to the time to modify the instancing buffer
|
||||
for (const Matrix4f& matrix : instances)
|
||||
{
|
||||
Renderer::SetMatrix(MatrixType_World, matrix);
|
||||
|
|
@ -664,13 +755,22 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
// Et on remet à zéro les données
|
||||
// And we set the data back to zero
|
||||
matEntry.enabled = false;
|
||||
matEntry.instancingEnabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Draws transparent models
|
||||
*
|
||||
* \param sceneData Data of the scene
|
||||
* \param layer Layer of the rendering
|
||||
*
|
||||
* \remark Produces a NazaraAssert is viewer is invalid
|
||||
*/
|
||||
|
||||
void ForwardRenderTechnique::DrawTransparentModels(const SceneData& sceneData, ForwardRenderQueue::Layer& layer) const
|
||||
{
|
||||
NazaraAssert(sceneData.viewer, "Invalid viewer");
|
||||
|
|
@ -683,25 +783,25 @@ namespace Nz
|
|||
{
|
||||
const ForwardRenderQueue::TransparentModelData& modelData = layer.transparentModelData[index];
|
||||
|
||||
// Matériau
|
||||
// Material
|
||||
const Material* material = modelData.material;
|
||||
|
||||
// On commence par appliquer du matériau (et récupérer le shader ainsi activé)
|
||||
// We begin to apply the material (and get the shader activated doing so)
|
||||
UInt8 freeTextureUnit;
|
||||
const Shader* shader = material->Apply(0, 0, &freeTextureUnit);
|
||||
|
||||
// Les uniformes sont conservées au sein d'un programme, inutile de les renvoyer tant qu'il ne change pas
|
||||
// Uniforms are conserved in our program, there's no point to send them back until they change
|
||||
if (shader != lastShader)
|
||||
{
|
||||
// Index des uniformes dans le shader
|
||||
// Index of uniforms in the shader
|
||||
shaderUniforms = GetShaderUniforms(shader);
|
||||
|
||||
// Couleur ambiante de la scène
|
||||
// Ambiant color of the scene
|
||||
shader->SendColor(shaderUniforms->sceneAmbient, sceneData.ambientColor);
|
||||
// Position de la caméra
|
||||
// Position of the camera
|
||||
shader->SendVector(shaderUniforms->eyePosition, sceneData.viewer->GetEyePosition());
|
||||
|
||||
// On envoie les lumières directionnelles s'il y a (Les mêmes pour tous)
|
||||
// We send the directional lights if there is one (same for all)
|
||||
if (shaderUniforms->hasLightUniforms)
|
||||
{
|
||||
lightCount = std::min(m_renderQueue.directionalLights.size(), static_cast<decltype(m_renderQueue.directionalLights.size())>(NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS));
|
||||
|
|
@ -720,7 +820,7 @@ namespace Nz
|
|||
const IndexBuffer* indexBuffer = meshData.indexBuffer;
|
||||
const VertexBuffer* vertexBuffer = meshData.vertexBuffer;
|
||||
|
||||
// Gestion du draw call avant la boucle de rendu
|
||||
// Handle draw call before the rendering loop
|
||||
Renderer::DrawCall drawFunc;
|
||||
unsigned int indexCount;
|
||||
|
||||
|
|
@ -754,6 +854,13 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the shader uniforms
|
||||
* \return Uniforms of the shader
|
||||
*
|
||||
* \param shader Shader to get uniforms from
|
||||
*/
|
||||
|
||||
const ForwardRenderTechnique::ShaderUniforms* ForwardRenderTechnique::GetShaderUniforms(const Shader* shader) const
|
||||
{
|
||||
auto it = m_shaderUniforms.find(shader);
|
||||
|
|
@ -795,6 +902,12 @@ namespace Nz
|
|||
return &it->second;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Handle the invalidation of a shader
|
||||
*
|
||||
* \param shader Shader being invalidated
|
||||
*/
|
||||
|
||||
void ForwardRenderTechnique::OnShaderInvalidated(const Shader* shader) const
|
||||
{
|
||||
m_shaderUniforms.erase(shader);
|
||||
|
|
|
|||
|
|
@ -28,15 +28,29 @@
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \ingroup graphics
|
||||
* \class Nz::Graphics
|
||||
* \brief Graphics class that represents the module initializer of Graphics
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Initializes the Graphics module
|
||||
* \return true if initialization is successful
|
||||
*
|
||||
* \remark Produces a NazaraNotice
|
||||
* \remark Produces a NazaraError if one submodule failed
|
||||
*/
|
||||
|
||||
bool Graphics::Initialize()
|
||||
{
|
||||
if (s_moduleReferenceCounter > 0)
|
||||
if (IsInitialized())
|
||||
{
|
||||
s_moduleReferenceCounter++;
|
||||
return true; // Déjà initialisé
|
||||
return true; // Already initialized
|
||||
}
|
||||
|
||||
// Initialisation des dépendances
|
||||
// Initialisation of dependances
|
||||
if (!Renderer::Initialize())
|
||||
{
|
||||
NazaraError("Failed to initialize Renderer module");
|
||||
|
|
@ -45,7 +59,7 @@ namespace Nz
|
|||
|
||||
s_moduleReferenceCounter++;
|
||||
|
||||
// Initialisation du module
|
||||
// Initialisation of the module
|
||||
CallOnExit onExit(Graphics::Uninitialize);
|
||||
|
||||
if (!Material::Initialize())
|
||||
|
|
@ -96,7 +110,7 @@ namespace Nz
|
|||
return false;
|
||||
}
|
||||
|
||||
// Loaders génériques
|
||||
// Generic loaders
|
||||
Loaders::RegisterMesh();
|
||||
Loaders::RegisterTexture();
|
||||
|
||||
|
|
@ -133,43 +147,54 @@ namespace Nz
|
|||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether the module is initialized
|
||||
* \return true if module is initialized
|
||||
*/
|
||||
|
||||
bool Graphics::IsInitialized()
|
||||
{
|
||||
return s_moduleReferenceCounter != 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Uninitializes the Core module
|
||||
*
|
||||
* \remark Produces a NazaraNotice
|
||||
*/
|
||||
|
||||
void Graphics::Uninitialize()
|
||||
{
|
||||
if (s_moduleReferenceCounter != 1)
|
||||
{
|
||||
// Le module est soit encore utilisé, soit pas initialisé
|
||||
// The module is still in use, or can not be uninitialized
|
||||
if (s_moduleReferenceCounter > 1)
|
||||
s_moduleReferenceCounter--;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Libération du module
|
||||
// Free of module
|
||||
s_moduleReferenceCounter = 0;
|
||||
|
||||
// Libération de l'atlas s'il vient de nous
|
||||
// Free of atlas if it is ours
|
||||
std::shared_ptr<AbstractAtlas> defaultAtlas = Font::GetDefaultAtlas();
|
||||
if (defaultAtlas && defaultAtlas->GetStorage() & DataStorage_Hardware)
|
||||
{
|
||||
Font::SetDefaultAtlas(nullptr);
|
||||
|
||||
// La police par défaut peut faire vivre un atlas hardware après la libération du module (ce qui va être problématique)
|
||||
// du coup, si la police par défaut utilise un atlas hardware, on lui enlève.
|
||||
// Je n'aime pas cette solution mais je n'en ai pas de meilleure sous la main pour l'instant
|
||||
// The default police can make live one hardware atlas after the free of a module (which could be problematic)
|
||||
// So, if the default police use a hardware atlas, we stole it.
|
||||
// I don't like this solution, but I don't have any better
|
||||
if (!defaultAtlas.unique())
|
||||
{
|
||||
// Encore au moins une police utilise l'atlas
|
||||
// Still at least one police use the atlas
|
||||
Font* defaultFont = Font::GetDefault();
|
||||
defaultFont->SetAtlas(nullptr);
|
||||
|
||||
if (!defaultAtlas.unique())
|
||||
{
|
||||
// Toujours pas seuls propriétaires ? Ah ben zut.
|
||||
// Still not the only one to own it ? Then crap.
|
||||
NazaraWarning("Default font atlas uses hardware storage and is still used");
|
||||
}
|
||||
}
|
||||
|
|
@ -195,7 +220,7 @@ namespace Nz
|
|||
|
||||
NazaraNotice("Uninitialized: Graphics module");
|
||||
|
||||
// Libération des dépendances
|
||||
// Free of dependances
|
||||
Renderer::Uninitialize();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,11 +9,32 @@
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \ingroup graphics
|
||||
* \class Nz::GuillotineTextureAtlas
|
||||
* \brief Graphics class that represents an atlas texture for guillotine
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Gets the underlying data storage
|
||||
* \return Value of the enumeration of the underlying data storage
|
||||
*/
|
||||
|
||||
UInt32 GuillotineTextureAtlas::GetStorage() const
|
||||
{
|
||||
return DataStorage_Hardware;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Resizes the image
|
||||
* \return Updated texture
|
||||
*
|
||||
* \param oldImage Old image to resize
|
||||
* \param size New image size
|
||||
*
|
||||
* \remark Produces a NazaraError if resize failed
|
||||
*/
|
||||
|
||||
AbstractImage* GuillotineTextureAtlas::ResizeImage(AbstractImage* oldImage, const Vector2ui& size) const
|
||||
{
|
||||
std::unique_ptr<Texture> newTexture(new Texture);
|
||||
|
|
@ -23,8 +44,8 @@ namespace Nz
|
|||
{
|
||||
Texture* oldTexture = static_cast<Texture*>(oldImage);
|
||||
|
||||
// Copie des anciennes données
|
||||
///TODO: Copie de texture à texture
|
||||
// Copy of old data
|
||||
///TODO: Copy from texture to texture
|
||||
Image image;
|
||||
if (!oldTexture->Download(&image))
|
||||
{
|
||||
|
|
@ -43,8 +64,7 @@ namespace Nz
|
|||
}
|
||||
else
|
||||
{
|
||||
// Si on arrive ici c'est que la taille demandée est trop grande pour la carte graphique
|
||||
// ou que nous manquons de mémoire
|
||||
// If we are here, it is that the size is too big for the graphic card or we don't have enough
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,16 +7,43 @@
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \ingroup graphics
|
||||
* \class Nz::InstancedRenderable
|
||||
* \brief Graphics class that represents an instancer renderable
|
||||
*
|
||||
* \remark This class is abstract
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Destructs the object and calls OnInstancedRenderableRelease
|
||||
*
|
||||
* \see OnInstancedRenderableRelease
|
||||
*/
|
||||
|
||||
InstancedRenderable::~InstancedRenderable()
|
||||
{
|
||||
OnInstancedRenderableRelease(this);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Culls the instanced if not in the frustum
|
||||
* \return true If instanced is in the frustum
|
||||
*
|
||||
* \param frustum Symbolizing the field of view
|
||||
* \param transformMatrix Matrix transformation for our object
|
||||
*/
|
||||
|
||||
bool InstancedRenderable::Cull(const Frustumf& frustum, const InstanceData& instanceData) const
|
||||
{
|
||||
return frustum.Contains(instanceData.volume);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the bounding volume
|
||||
* \return Bounding volume of the instanced
|
||||
*/
|
||||
|
||||
const BoundingVolumef& InstancedRenderable::GetBoundingVolume() const
|
||||
{
|
||||
EnsureBoundingVolumeUpdated();
|
||||
|
|
@ -24,11 +51,30 @@ namespace Nz
|
|||
return m_boundingVolume;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Invalidates data for instanced
|
||||
*
|
||||
* \param instanceData Pointer to data of instances
|
||||
* \param flags Flags for the instances
|
||||
*
|
||||
* \remark Produces a NazaraAssert if instanceData is invalid
|
||||
*/
|
||||
|
||||
void InstancedRenderable::InvalidateData(InstanceData* instanceData, UInt32 flags) const
|
||||
{
|
||||
NazaraAssert(instanceData, "Invalid instance data");
|
||||
|
||||
instanceData->flags |= flags;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Updates the bounding volume
|
||||
*
|
||||
* \param instanceData Pointer to data of instances
|
||||
*
|
||||
* \remark Produces a NazaraAssert if instanceData is invalid
|
||||
*/
|
||||
|
||||
void InstancedRenderable::UpdateBoundingVolume(InstanceData* instanceData) const
|
||||
{
|
||||
NazaraAssert(instanceData, "Invalid instance data");
|
||||
|
|
@ -37,6 +83,14 @@ namespace Nz
|
|||
instanceData->volume.Update(instanceData->transformMatrix);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Updates the instance data
|
||||
*
|
||||
* \param instanceData Pointer to data of instances
|
||||
*
|
||||
* \remark Produces a NazaraAssert if instanceData is invalid
|
||||
*/
|
||||
|
||||
void InstancedRenderable::UpdateData(InstanceData* instanceData) const
|
||||
{
|
||||
NazaraAssert(instanceData, "Invalid instance data");
|
||||
|
|
|
|||
|
|
@ -13,11 +13,23 @@
|
|||
#include <cstring>
|
||||
#include <Nazara/Graphics/Debug.hpp>
|
||||
|
||||
///TODO: Utilisation des UBOs
|
||||
///TODO: Use of UBOs
|
||||
///TODO: Scale ?
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \ingroup graphics
|
||||
* \class Nz::Light
|
||||
* \brief Graphics class that represents a light
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Constructs a Light object with a type
|
||||
*
|
||||
* \param type Type of the light
|
||||
*/
|
||||
|
||||
Light::Light(LightType type) :
|
||||
m_type(type),
|
||||
m_shadowMapFormat(PixelFormatType_Depth16),
|
||||
|
|
@ -34,6 +46,15 @@ namespace Nz
|
|||
SetRadius(5.f);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds this light to the render queue
|
||||
*
|
||||
* \param renderQueue Queue to be added
|
||||
* \param transformMatrix Matrix transformation for this light
|
||||
*
|
||||
* \remark Produces a NazaraError if type is invalid
|
||||
*/
|
||||
|
||||
void Light::AddToRenderQueue(AbstractRenderQueue* renderQueue, const Matrix4f& transformMatrix) const
|
||||
{
|
||||
static Matrix4f biasMatrix(0.5f, 0.f, 0.f, 0.f,
|
||||
|
|
@ -100,16 +121,36 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Clones this light
|
||||
* \return Pointer to newly allocated Light
|
||||
*/
|
||||
|
||||
Light* Light::Clone() const
|
||||
{
|
||||
return new Light(*this);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Creates a default light
|
||||
* \return Pointer to newly allocated light
|
||||
*/
|
||||
|
||||
Light* Light::Create() const
|
||||
{
|
||||
return new Light;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Culls the light if not in the frustum
|
||||
* \return true If light is in the frustum
|
||||
*
|
||||
* \param frustum Symbolizing the field of view
|
||||
* \param transformMatrix Matrix transformation for our object
|
||||
*
|
||||
* \remark Produces a NazaraError if type is invalid
|
||||
*/
|
||||
|
||||
bool Light::Cull(const Frustumf& frustum, const Matrix4f& transformMatrix) const
|
||||
{
|
||||
switch (m_type)
|
||||
|
|
@ -128,6 +169,14 @@ namespace Nz
|
|||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Updates the bounding volume by a matrix
|
||||
*
|
||||
* \param transformMatrix Matrix transformation for our bounding volume
|
||||
*
|
||||
* \remark Produces a NazaraError if type is invalid
|
||||
*/
|
||||
|
||||
void Light::UpdateBoundingVolume(const Matrix4f& transformMatrix)
|
||||
{
|
||||
switch (m_type)
|
||||
|
|
@ -149,6 +198,12 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* \brief Makes the bounding volume of this light
|
||||
*
|
||||
* \remark Produces a NazaraError if type is invalid
|
||||
*/
|
||||
|
||||
void Light::MakeBoundingVolume() const
|
||||
{
|
||||
switch (m_type)
|
||||
|
|
@ -166,19 +221,19 @@ namespace Nz
|
|||
|
||||
case LightType_Spot:
|
||||
{
|
||||
// On forme une boite sur l'origine
|
||||
// We make a box center in the origin
|
||||
Boxf box(Vector3f::Zero());
|
||||
|
||||
// On calcule le reste des points
|
||||
Vector3f base(Vector3f::Forward()*m_radius);
|
||||
// We compute the other points
|
||||
Vector3f base(Vector3f::Forward() * m_radius);
|
||||
|
||||
// Il nous faut maintenant le rayon du cercle projeté à cette distance
|
||||
// Tangente = Opposé/Adjaçent <=> Opposé = Adjaçent*Tangente
|
||||
// Now we need the radius of the projected circle depending on the distance
|
||||
// Tangent = Opposite/Adjacent <=> Opposite = Adjacent * Tangent
|
||||
float radius = m_radius * m_outerAngleTangent;
|
||||
Vector3f lExtend = Vector3f::Left()*radius;
|
||||
Vector3f uExtend = Vector3f::Up()*radius;
|
||||
Vector3f lExtend = Vector3f::Left() * radius;
|
||||
Vector3f uExtend = Vector3f::Up() * radius;
|
||||
|
||||
// Et on ajoute ensuite les quatres extrémités de la pyramide
|
||||
// And we add the four extremities of our pyramid
|
||||
box.ExtendTo(base + lExtend + uExtend);
|
||||
box.ExtendTo(base + lExtend - uExtend);
|
||||
box.ExtendTo(base - lExtend + uExtend);
|
||||
|
|
@ -194,6 +249,10 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Updates the shadow map
|
||||
*/
|
||||
|
||||
void Light::UpdateShadowMap() const
|
||||
{
|
||||
if (m_shadowCastingEnabled)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#ifndef NAZARA_RENDERER_OPENGL
|
||||
#define NAZARA_RENDERER_OPENGL // Nécessaire pour inclure les headers OpenGL
|
||||
#define NAZARA_RENDERER_OPENGL // Mandatory to include the OpenGL headers
|
||||
#endif
|
||||
|
||||
#include <Nazara/Graphics/Material.hpp>
|
||||
|
|
@ -36,6 +36,17 @@ namespace Nz
|
|||
};
|
||||
}
|
||||
|
||||
/*!
|
||||
* \ingroup graphics
|
||||
* \class Nz::Material
|
||||
* \brief Graphics class that represents a material
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Checks whether the parameters for the material are correct
|
||||
* \return true If parameters are valid
|
||||
*/
|
||||
|
||||
bool MaterialParams::IsValid() const
|
||||
{
|
||||
if (!UberShaderLibrary::Has(shaderName))
|
||||
|
|
@ -44,6 +55,15 @@ namespace Nz
|
|||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Applies shader to the material
|
||||
* \return Constant pointer to the shader
|
||||
*
|
||||
* \param shaderFlags Flags for the shader
|
||||
* \param textureUnit Unit for the texture GL_TEXTURE"i"
|
||||
* \param lastUsedUnit Optional argument to get the last texture unit
|
||||
*/
|
||||
|
||||
const Shader* Material::Apply(UInt32 shaderFlags, UInt8 textureUnit, UInt8* lastUsedUnit) const
|
||||
{
|
||||
const ShaderInstance& instance = m_shaders[shaderFlags];
|
||||
|
|
@ -123,6 +143,13 @@ namespace Nz
|
|||
return instance.shader;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Builds the material from parameters
|
||||
*
|
||||
* \param matData Data information for the material
|
||||
* \param matParams Parameters for the material
|
||||
*/
|
||||
|
||||
void Material::BuildFromParameters(const ParameterList& matData, const MaterialParams& matParams)
|
||||
{
|
||||
Color color;
|
||||
|
|
@ -283,6 +310,10 @@ namespace Nz
|
|||
SetShader(matParams.shaderName);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Resets the material, cleans everything
|
||||
*/
|
||||
|
||||
void Material::Reset()
|
||||
{
|
||||
OnMaterialReset(this);
|
||||
|
|
@ -319,9 +350,15 @@ namespace Nz
|
|||
SetShader("Basic");
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Copies the other material
|
||||
*
|
||||
* \param material Material to copy into this
|
||||
*/
|
||||
|
||||
void Material::Copy(const Material& material)
|
||||
{
|
||||
// Copie des états de base
|
||||
// Copy of base states
|
||||
m_alphaTestEnabled = material.m_alphaTestEnabled;
|
||||
m_alphaThreshold = material.m_alphaThreshold;
|
||||
m_ambientColor = material.m_ambientColor;
|
||||
|
|
@ -337,7 +374,7 @@ namespace Nz
|
|||
m_states = material.m_states;
|
||||
m_transformEnabled = material.m_transformEnabled;
|
||||
|
||||
// Copie des références de texture
|
||||
// Copy of reference to the textures
|
||||
m_alphaMap = material.m_alphaMap;
|
||||
m_depthMaterial = material.m_depthMaterial;
|
||||
m_diffuseMap = material.m_diffuseMap;
|
||||
|
|
@ -347,10 +384,16 @@ namespace Nz
|
|||
m_specularMap = material.m_specularMap;
|
||||
m_uberShader = material.m_uberShader;
|
||||
|
||||
// On copie les instances de shader par la même occasion
|
||||
std::memcpy(&m_shaders[0], &material.m_shaders[0], (ShaderFlags_Max+1)*sizeof(ShaderInstance));
|
||||
// We copy the instances of the shader too
|
||||
std::memcpy(&m_shaders[0], &material.m_shaders[0], (ShaderFlags_Max + 1) * sizeof(ShaderInstance));
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Generates the shader based on flag
|
||||
*
|
||||
* \param flags Flag for the shaer
|
||||
*/
|
||||
|
||||
void Material::GenerateShader(UInt32 flags) const
|
||||
{
|
||||
ParameterList list;
|
||||
|
|
@ -396,6 +439,13 @@ namespace Nz
|
|||
#undef CacheUniform
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Initializes the material librairies
|
||||
* \return true If successful
|
||||
*
|
||||
* \remark Produces a NazaraError if the material library failed to be initialized
|
||||
*/
|
||||
|
||||
bool Material::Initialize()
|
||||
{
|
||||
if (!MaterialLibrary::Initialize())
|
||||
|
|
@ -462,6 +512,10 @@ namespace Nz
|
|||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Uninitializes the material librairies
|
||||
*/
|
||||
|
||||
void Material::Uninitialize()
|
||||
{
|
||||
s_defaultMaterial.Reset();
|
||||
|
|
|
|||
|
|
@ -12,11 +12,26 @@
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \ingroup graphics
|
||||
* \class Nz::Model
|
||||
* \brief Graphics class that represents a model
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Constructs a ModelParameters object by default
|
||||
*/
|
||||
|
||||
ModelParameters::ModelParameters()
|
||||
{
|
||||
material.shaderName = "PhongLighting";
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether the parameters for the model are correct
|
||||
* \return true If parameters are valid
|
||||
*/
|
||||
|
||||
bool ModelParameters::IsValid() const
|
||||
{
|
||||
if (loadMaterials && !material.IsValid())
|
||||
|
|
@ -25,6 +40,10 @@ namespace Nz
|
|||
return mesh.IsValid();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Constructs a Model object by default
|
||||
*/
|
||||
|
||||
Model::Model() :
|
||||
m_matCount(0),
|
||||
m_skin(0),
|
||||
|
|
@ -32,11 +51,24 @@ namespace Nz
|
|||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Destructs the object and calls Reset
|
||||
*
|
||||
* \see Reset
|
||||
*/
|
||||
|
||||
Model::~Model()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds this model to the render queue
|
||||
*
|
||||
* \param renderQueue Queue to be added
|
||||
* \param instanceData Data used for this instance
|
||||
*/
|
||||
|
||||
void Model::AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData) const
|
||||
{
|
||||
unsigned int submeshCount = m_mesh->GetSubMeshCount();
|
||||
|
|
@ -54,6 +86,17 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the material of the named submesh
|
||||
* \return Pointer to the current material
|
||||
*
|
||||
* \param subMeshName Name of the subMesh
|
||||
*
|
||||
* \remark Produces a NazaraError with NAZARA_GRAPHICS_SAFE if there is no mesh
|
||||
* \remark Produces a NazaraError if there is no subMesh with that name
|
||||
* \remark Produces a NazaraError if material is invalid
|
||||
*/
|
||||
|
||||
Material* Model::GetMaterial(const String& subMeshName) const
|
||||
{
|
||||
#if NAZARA_GRAPHICS_SAFE
|
||||
|
|
@ -78,9 +121,18 @@ namespace Nz
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
return m_materials[m_skin*m_matCount + matIndex];
|
||||
return m_materials[m_skin * m_matCount + matIndex];
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the material by index
|
||||
* \return Pointer to the current material
|
||||
*
|
||||
* \param matIndex Index of the material
|
||||
*
|
||||
* \remark Produces a NazaraError if index is invalid
|
||||
*/
|
||||
|
||||
Material* Model::GetMaterial(unsigned int matIndex) const
|
||||
{
|
||||
#if NAZARA_GRAPHICS_SAFE
|
||||
|
|
@ -91,9 +143,21 @@ namespace Nz
|
|||
}
|
||||
#endif
|
||||
|
||||
return m_materials[m_skin*m_matCount + matIndex];
|
||||
return m_materials[m_skin * m_matCount + matIndex];
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the material by index of the named submesh
|
||||
* \return Pointer to the current material
|
||||
*
|
||||
* \param skinIndex Index of the skin
|
||||
* \param subMeshName Name of the subMesh
|
||||
*
|
||||
* \remark Produces a NazaraError with NAZARA_GRAPHICS_SAFE defined if skinIndex is invalid
|
||||
* \remark Produces a NazaraError if there is no subMesh with that name
|
||||
* \remark Produces a NazaraError if material index is invalid
|
||||
*/
|
||||
|
||||
Material* Model::GetMaterial(unsigned int skinIndex, const String& subMeshName) const
|
||||
{
|
||||
#if NAZARA_GRAPHICS_SAFE
|
||||
|
|
@ -118,9 +182,20 @@ namespace Nz
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
return m_materials[skinIndex*m_matCount + matIndex];
|
||||
return m_materials[skinIndex * m_matCount + matIndex];
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the material by index with skin
|
||||
* \return Pointer to the current material
|
||||
*
|
||||
* \param skinIndex Index of the skin
|
||||
* \param matIndex Index of the material
|
||||
*
|
||||
* \remark Produces a NazaraError with NAZARA_GRAPHICS_SAFE defined if skinIndex is invalid
|
||||
* \remark Produces a NazaraError with NAZARA_GRAPHICS_SAFE defined if matIndex is invalid
|
||||
*/
|
||||
|
||||
Material* Model::GetMaterial(unsigned int skinIndex, unsigned int matIndex) const
|
||||
{
|
||||
#if NAZARA_GRAPHICS_SAFE
|
||||
|
|
@ -137,49 +212,103 @@ namespace Nz
|
|||
}
|
||||
#endif
|
||||
|
||||
return m_materials[skinIndex*m_matCount + matIndex];
|
||||
return m_materials[skinIndex * m_matCount + matIndex];
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the number of materials
|
||||
* \return Current number of materials
|
||||
*/
|
||||
|
||||
unsigned int Model::GetMaterialCount() const
|
||||
{
|
||||
return m_matCount;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the mesh
|
||||
* \return Current mesh
|
||||
*/
|
||||
|
||||
Mesh* Model::GetMesh() const
|
||||
{
|
||||
return m_mesh;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the skin
|
||||
* \return Current skin
|
||||
*/
|
||||
|
||||
unsigned int Model::GetSkin() const
|
||||
{
|
||||
return m_skin;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the number of skins
|
||||
* \return Current number of skins
|
||||
*/
|
||||
|
||||
unsigned int Model::GetSkinCount() const
|
||||
{
|
||||
return m_skinCount;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether the model is animated
|
||||
* \return false
|
||||
*/
|
||||
|
||||
bool Model::IsAnimated() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Loads the model from file
|
||||
* \return true if loading is successful
|
||||
*
|
||||
* \param filePath Path to the file
|
||||
* \param params Parameters for the model
|
||||
*/
|
||||
|
||||
bool Model::LoadFromFile(const String& filePath, const ModelParameters& params)
|
||||
{
|
||||
return ModelLoader::LoadFromFile(this, filePath, params);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Loads the model from memory
|
||||
* \return true if loading is successful
|
||||
*
|
||||
* \param data Raw memory
|
||||
* \param size Size of the memory
|
||||
* \param params Parameters for the model
|
||||
*/
|
||||
|
||||
bool Model::LoadFromMemory(const void* data, std::size_t size, const ModelParameters& params)
|
||||
{
|
||||
return ModelLoader::LoadFromMemory(this, data, size, params);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Loads the model from stream
|
||||
* \return true if loading is successful
|
||||
*
|
||||
* \param stream Stream to the model
|
||||
* \param params Parameters for the model
|
||||
*/
|
||||
|
||||
bool Model::LoadFromStream(Stream& stream, const ModelParameters& params)
|
||||
{
|
||||
return ModelLoader::LoadFromStream(this, stream, params);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Resets the model, cleans everything
|
||||
*/
|
||||
|
||||
void Model::Reset()
|
||||
{
|
||||
m_matCount = 0;
|
||||
|
|
@ -192,6 +321,17 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the material of the named submesh
|
||||
* \return true If successful
|
||||
*
|
||||
* \param subMeshName Name of the subMesh
|
||||
* \param material Pointer to the material
|
||||
*
|
||||
* \remark Produces a NazaraError if there is no subMesh with that name
|
||||
* \remark Produces a NazaraError if material index is invalid
|
||||
*/
|
||||
|
||||
bool Model::SetMaterial(const String& subMeshName, Material* material)
|
||||
{
|
||||
SubMesh* subMesh = m_mesh->GetSubMesh(subMeshName);
|
||||
|
|
@ -208,7 +348,7 @@ namespace Nz
|
|||
return false;
|
||||
}
|
||||
|
||||
unsigned int index = m_skin*m_matCount + matIndex;
|
||||
unsigned int index = m_skin * m_matCount + matIndex;
|
||||
|
||||
if (material)
|
||||
m_materials[index] = material;
|
||||
|
|
@ -218,6 +358,16 @@ namespace Nz
|
|||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the material by index
|
||||
* \return true If successful
|
||||
*
|
||||
* \param matIndex Index of the material
|
||||
* \param material Pointer to the material
|
||||
*
|
||||
* \remark Produces a NazaraError with if NAZARA_GRAPHICS_SAFE defined index is invalid
|
||||
*/
|
||||
|
||||
void Model::SetMaterial(unsigned int matIndex, Material* material)
|
||||
{
|
||||
#if NAZARA_GRAPHICS_SAFE
|
||||
|
|
@ -228,7 +378,7 @@ namespace Nz
|
|||
}
|
||||
#endif
|
||||
|
||||
unsigned int index = m_skin*m_matCount + matIndex;
|
||||
unsigned int index = m_skin * m_matCount + matIndex;
|
||||
|
||||
if (material)
|
||||
m_materials[index] = material;
|
||||
|
|
@ -236,6 +386,19 @@ namespace Nz
|
|||
m_materials[index] = Material::GetDefault();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the material by index of the named submesh
|
||||
* \return true If successful
|
||||
*
|
||||
* \param skinIndex Index of the skin
|
||||
* \param subMeshName Name of the subMesh
|
||||
* \param material Pointer to the material
|
||||
*
|
||||
* \remark Produces a NazaraError with NAZARA_GRAPHICS_SAFE defined if skinIndex is invalid
|
||||
* \remark Produces a NazaraError if there is no subMesh with that name
|
||||
* \remark Produces a NazaraError if material index is invalid
|
||||
*/
|
||||
|
||||
bool Model::SetMaterial(unsigned int skinIndex, const String& subMeshName, Material* material)
|
||||
{
|
||||
#if NAZARA_GRAPHICS_SAFE
|
||||
|
|
@ -260,7 +423,7 @@ namespace Nz
|
|||
return false;
|
||||
}
|
||||
|
||||
unsigned int index = skinIndex*m_matCount + matIndex;
|
||||
unsigned int index = skinIndex * m_matCount + matIndex;
|
||||
|
||||
if (material)
|
||||
m_materials[index] = material;
|
||||
|
|
@ -270,6 +433,18 @@ namespace Nz
|
|||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the material by index with skin
|
||||
* \return true If successful
|
||||
*
|
||||
* \param skinIndex Index of the skin
|
||||
* \param matIndex Index of the material
|
||||
* \param material Pointer to the material
|
||||
*
|
||||
* \remark Produces a NazaraError with NAZARA_GRAPHICS_SAFE defined if skinIndex is invalid
|
||||
* \remark Produces a NazaraError with NAZARA_GRAPHICS_SAFE defined if matIndex is invalid
|
||||
*/
|
||||
|
||||
void Model::SetMaterial(unsigned int skinIndex, unsigned int matIndex, Material* material)
|
||||
{
|
||||
#if NAZARA_GRAPHICS_SAFE
|
||||
|
|
@ -286,7 +461,7 @@ namespace Nz
|
|||
}
|
||||
#endif
|
||||
|
||||
unsigned int index = skinIndex*m_matCount + matIndex;
|
||||
unsigned int index = skinIndex * m_matCount + matIndex;
|
||||
|
||||
if (material)
|
||||
m_materials[index] = material;
|
||||
|
|
@ -294,6 +469,14 @@ namespace Nz
|
|||
m_materials[index] = Material::GetDefault();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the mesh
|
||||
*
|
||||
* \param pointer to the mesh
|
||||
*
|
||||
* \remark Produces a NazaraError with NAZARA_GRAPHICS_SAFE defined if mesh is invalid
|
||||
*/
|
||||
|
||||
void Model::SetMesh(Mesh* mesh)
|
||||
{
|
||||
#if NAZARA_GRAPHICS_SAFE
|
||||
|
|
@ -323,6 +506,14 @@ namespace Nz
|
|||
InvalidateBoundingVolume();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the skin
|
||||
*
|
||||
* \param skin Skin to use
|
||||
*
|
||||
* \remark Produces a NazaraError if skin is invalid
|
||||
*/
|
||||
|
||||
void Model::SetSkin(unsigned int skin)
|
||||
{
|
||||
#if NAZARA_GRAPHICS_SAFE
|
||||
|
|
@ -336,6 +527,14 @@ namespace Nz
|
|||
m_skin = skin;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the number of skins
|
||||
*
|
||||
* \param skinCount Number of skins
|
||||
*
|
||||
* \remark Produces a NazaraError if skinCount equals zero
|
||||
*/
|
||||
|
||||
void Model::SetSkinCount(unsigned int skinCount)
|
||||
{
|
||||
#if NAZARA_GRAPHICS_SAFE
|
||||
|
|
@ -350,6 +549,10 @@ namespace Nz
|
|||
m_skinCount = skinCount;
|
||||
}
|
||||
|
||||
/*
|
||||
* \brief Makes the bounding volume of this billboard
|
||||
*/
|
||||
|
||||
void Model::MakeBoundingVolume() const
|
||||
{
|
||||
if (m_mesh)
|
||||
|
|
|
|||
|
|
@ -7,17 +7,44 @@
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \ingroup graphics
|
||||
* \class Nz::ParticleController
|
||||
* \brief Graphics class which controls a flow of particles
|
||||
*
|
||||
* \remark This class is abstract
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Constructs a ParticleController object by assignation
|
||||
*
|
||||
* \param controller ParticleController to copy into this
|
||||
*/
|
||||
|
||||
ParticleController::ParticleController(const ParticleController& controller) :
|
||||
RefCounted()
|
||||
{
|
||||
NazaraUnused(controller);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Destructs the object and calls OnParticleControllerRelease
|
||||
*
|
||||
* \see OnParticleControllerRelease
|
||||
*/
|
||||
|
||||
ParticleController::~ParticleController()
|
||||
{
|
||||
OnParticleControllerRelease(this);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Initializes the particle controller librairies
|
||||
* \return true If successful
|
||||
*
|
||||
* \remark Produces a NazaraError if the particle controller library failed to be initialized
|
||||
*/
|
||||
|
||||
bool ParticleController::Initialize()
|
||||
{
|
||||
if (!ParticleControllerLibrary::Initialize())
|
||||
|
|
@ -29,6 +56,10 @@ namespace Nz
|
|||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Uninitializes the particle controller librairies
|
||||
*/
|
||||
|
||||
void ParticleController::Uninitialize()
|
||||
{
|
||||
ParticleControllerLibrary::Uninitialize();
|
||||
|
|
|
|||
|
|
@ -15,23 +15,54 @@
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \ingroup graphics
|
||||
* \class Nz::ParticleDeclaration
|
||||
* \brief Graphics class that represents the declaration of the particle, works like an ECS
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Constructs a ParticleDeclaration object by default
|
||||
*/
|
||||
|
||||
ParticleDeclaration::ParticleDeclaration() :
|
||||
m_stride(0)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Constructs a ParticleDeclaration object by assignation
|
||||
*
|
||||
* \param declaration ParticleDeclaration to copy into this
|
||||
*/
|
||||
|
||||
ParticleDeclaration::ParticleDeclaration(const ParticleDeclaration& declaration) :
|
||||
RefCounted(),
|
||||
m_stride(declaration.m_stride)
|
||||
{
|
||||
std::memcpy(m_components, declaration.m_components, sizeof(Component)*(ParticleComponent_Max+1));
|
||||
std::memcpy(m_components, declaration.m_components, sizeof(Component) * (ParticleComponent_Max + 1));
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Destructs the object and calls OnParticleDeclarationRelease
|
||||
*
|
||||
* \see OnParticleDeclarationRelease
|
||||
*/
|
||||
|
||||
ParticleDeclaration::~ParticleDeclaration()
|
||||
{
|
||||
OnParticleDeclarationRelease(this);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Disables a component
|
||||
*
|
||||
* \param component Component to disable in the declaration
|
||||
*
|
||||
* \remark Produces a NazaraError with NAZARA_DEBUG defined if enumeration is invalid
|
||||
* \remark Produces a NazaraError with NAZARA_GRAPHICS_SAFE defined if enumeration is equal to ParticleComponent_Unused
|
||||
*/
|
||||
|
||||
void ParticleDeclaration::DisableComponent(ParticleComponent component)
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
|
|
@ -58,6 +89,17 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Enables a component
|
||||
*
|
||||
* \param component Component to enable in the declaration
|
||||
* \param type Type of this component
|
||||
* \param offset Offset in the declaration
|
||||
*
|
||||
* \remark Produces a NazaraError with NAZARA_DEBUG defined if enumeration is invalid
|
||||
* \remark Produces a NazaraError with NAZARA_GRAPHICS_SAFE defined if type is not supported
|
||||
*/
|
||||
|
||||
void ParticleDeclaration::EnableComponent(ParticleComponent component, ComponentType type, unsigned int offset)
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
|
|
@ -91,6 +133,18 @@ namespace Nz
|
|||
m_stride += Utility::ComponentStride[type];
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets a component
|
||||
*
|
||||
* \param component Component in the declaration
|
||||
* \param enabled Optional argument to get if this component is enabled
|
||||
* \param type Optional argument to get if the type of the component
|
||||
* \param offset Optional argument to get if the offset in the declaration
|
||||
*
|
||||
* \remark Produces a NazaraError with NAZARA_DEBUG defined if enumeration is invalid
|
||||
* \remark Produces a NazaraError with NAZARA_GRAPHICS_SAFE defined if enumeration is equal to ParticleComponent_Unused
|
||||
*/
|
||||
|
||||
void ParticleDeclaration::GetComponent(ParticleComponent component, bool* enabled, ComponentType* type, unsigned int* offset) const
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
|
|
@ -121,24 +175,51 @@ namespace Nz
|
|||
*offset = particleComponent.offset;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the stride of the declaration
|
||||
* \return Stride of the declaration
|
||||
*/
|
||||
|
||||
unsigned int ParticleDeclaration::GetStride() const
|
||||
{
|
||||
return m_stride;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the stride of the declaration
|
||||
*
|
||||
* \param stride Stride of the declaration
|
||||
*/
|
||||
|
||||
void ParticleDeclaration::SetStride(unsigned int stride)
|
||||
{
|
||||
m_stride = stride;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the current particle declaration with the content of the other one
|
||||
* \return A reference to this
|
||||
*
|
||||
* \param declaration The other ParticleDeclaration
|
||||
*/
|
||||
|
||||
ParticleDeclaration& ParticleDeclaration::operator=(const ParticleDeclaration& declaration)
|
||||
{
|
||||
std::memcpy(m_components, declaration.m_components, sizeof(Component)*(ParticleComponent_Max+1));
|
||||
std::memcpy(m_components, declaration.m_components, sizeof(Component) * (ParticleComponent_Max + 1));
|
||||
m_stride = declaration.m_stride;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the particle declaration based on the layout
|
||||
* \return Pointer to the declaration
|
||||
*
|
||||
* \param layout Layout of the particle declaration
|
||||
*
|
||||
* \remark Produces a NazaraError with NAZARA_DEBUG if enumeration is invalid
|
||||
*/
|
||||
|
||||
ParticleDeclaration* ParticleDeclaration::Get(ParticleLayout layout)
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
|
|
@ -152,6 +233,15 @@ namespace Nz
|
|||
return &s_declarations[layout];
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether the type is supported
|
||||
* \return true If it is the case
|
||||
*
|
||||
* \param type Type of the component
|
||||
*
|
||||
* \remark Produces a NazaraError if enumeration is invalid
|
||||
*/
|
||||
|
||||
bool ParticleDeclaration::IsTypeSupported(ComponentType type)
|
||||
{
|
||||
switch (type)
|
||||
|
|
@ -177,6 +267,14 @@ namespace Nz
|
|||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Initializes the particle declaration librairies
|
||||
* \return true If successful
|
||||
*
|
||||
* \remark Produces a NazaraError if the particle declaration library failed to be initialized
|
||||
* \remark Produces a NazaraAssert if memory layout of declaration does not match the corresponding structure
|
||||
*/
|
||||
|
||||
bool ParticleDeclaration::Initialize()
|
||||
{
|
||||
if (!ParticleDeclarationLibrary::Initialize())
|
||||
|
|
@ -231,11 +329,15 @@ namespace Nz
|
|||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Uninitializes the particle declaration librairies
|
||||
*/
|
||||
|
||||
void ParticleDeclaration::Uninitialize()
|
||||
{
|
||||
ParticleDeclarationLibrary::Uninitialize();
|
||||
}
|
||||
|
||||
ParticleDeclaration ParticleDeclaration::s_declarations[ParticleLayout_Max+1];
|
||||
ParticleDeclaration ParticleDeclaration::s_declarations[ParticleLayout_Max + 1];
|
||||
ParticleDeclarationLibrary::LibraryMap ParticleDeclaration::s_library;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,16 @@
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \ingroup graphics
|
||||
* \class Nz::ParticleEmitter
|
||||
* \brief Graphics class that represents an emitter of particles
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Constructs a ParticleEmitter object by default
|
||||
*/
|
||||
|
||||
ParticleEmitter::ParticleEmitter() :
|
||||
m_lagCompensationEnabled(false),
|
||||
m_emissionAccumulator(0.f),
|
||||
|
|
@ -24,28 +34,35 @@ namespace Nz
|
|||
|
||||
ParticleEmitter::~ParticleEmitter() = default;
|
||||
|
||||
/*!
|
||||
* \brief Emits particles according to the delta time between the previous frame
|
||||
*
|
||||
* \param system Particle system to work on
|
||||
* \param elapsedTime Delta time between the previous frame
|
||||
*/
|
||||
|
||||
void ParticleEmitter::Emit(ParticleSystem& system, float elapsedTime) const
|
||||
{
|
||||
if (m_emissionRate > 0.f)
|
||||
{
|
||||
// On accumule la partie réelle (pour éviter qu'un taux d'update élevé empêche des particules de se former)
|
||||
m_emissionAccumulator += elapsedTime*m_emissionRate;
|
||||
// We accumulate the real part (to avoid that a high emission rate prevents particles to form)
|
||||
m_emissionAccumulator += elapsedTime * m_emissionRate;
|
||||
|
||||
float emissionCount = std::floor(m_emissionAccumulator); // Le nombre d'émissions de cette mise à jour
|
||||
m_emissionAccumulator -= emissionCount; // On enlève la partie entière
|
||||
float emissionCount = std::floor(m_emissionAccumulator); // The number of emissions in this update
|
||||
m_emissionAccumulator -= emissionCount; // We get rid off the integer part
|
||||
|
||||
if (emissionCount >= 1.f)
|
||||
{
|
||||
// On calcule le nombre maximum de particules pouvant être émises cette fois-ci
|
||||
// We compute the maximum number of particles which can be emitted
|
||||
unsigned int emissionCountInt = static_cast<unsigned int>(emissionCount);
|
||||
unsigned int maxParticleCount = emissionCountInt*m_emissionCount;
|
||||
unsigned int maxParticleCount = emissionCountInt * m_emissionCount;
|
||||
|
||||
// On récupère le nombre de particules qu'il est possible de créer selon l'espace libre
|
||||
// We get the number of particles that we are able to create (depending on the free space)
|
||||
unsigned int particleCount = std::min(maxParticleCount, system.GetMaxParticleCount() - system.GetParticleCount());
|
||||
if (particleCount == 0)
|
||||
return;
|
||||
|
||||
// Et on émet nos particules
|
||||
// And we emit our particles
|
||||
void* particles = system.GenerateParticles(particleCount);
|
||||
ParticleMapper mapper(particles, system.GetDeclaration());
|
||||
|
||||
|
|
@ -53,40 +70,73 @@ namespace Nz
|
|||
|
||||
if (m_lagCompensationEnabled)
|
||||
{
|
||||
// On va maintenant appliquer les contrôleurs
|
||||
float invEmissionRate = 1.f/m_emissionRate;
|
||||
// We will now apply our controllers
|
||||
float invEmissionRate = 1.f / m_emissionRate;
|
||||
for (unsigned int i = 1; i <= emissionCountInt; ++i)
|
||||
system.ApplyControllers(mapper, std::min(m_emissionCount*i, particleCount), invEmissionRate);
|
||||
system.ApplyControllers(mapper, std::min(m_emissionCount * i, particleCount), invEmissionRate);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Enables the lag compensation
|
||||
*
|
||||
* \param enable Should lag compensation be enabled
|
||||
*/
|
||||
|
||||
void ParticleEmitter::EnableLagCompensation(bool enable)
|
||||
{
|
||||
m_lagCompensationEnabled = enable;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the emission count
|
||||
* \return Current emission count
|
||||
*/
|
||||
|
||||
unsigned int ParticleEmitter::GetEmissionCount() const
|
||||
{
|
||||
return m_emissionCount;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the emission rate
|
||||
* \return Current emission rate
|
||||
*/
|
||||
|
||||
float ParticleEmitter::GetEmissionRate() const
|
||||
{
|
||||
return m_emissionRate;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether the lag compensation is enabled
|
||||
* \return true If it is the case
|
||||
*/
|
||||
|
||||
bool ParticleEmitter::IsLagCompensationEnabled() const
|
||||
{
|
||||
return m_lagCompensationEnabled;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the emission count
|
||||
*
|
||||
* \param count Emission count
|
||||
*/
|
||||
|
||||
void ParticleEmitter::SetEmissionCount(unsigned int count)
|
||||
{
|
||||
m_emissionCount = count;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the emission rate
|
||||
*
|
||||
* \param rate Emission rate
|
||||
*/
|
||||
|
||||
void ParticleEmitter::SetEmissionRate(float rate)
|
||||
{
|
||||
m_emissionRate = rate;
|
||||
|
|
|
|||
|
|
@ -7,17 +7,44 @@
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \ingroup graphics
|
||||
* \class Nz::ParticleGenerator
|
||||
* \brief Graphics class which generates particles
|
||||
*
|
||||
* \remark This class is abstract
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Constructs a ParticleGenerator object by assignation
|
||||
*
|
||||
* \param generator ParticleGenerator to copy into this
|
||||
*/
|
||||
|
||||
ParticleGenerator::ParticleGenerator(const ParticleGenerator& generator) :
|
||||
RefCounted()
|
||||
{
|
||||
NazaraUnused(generator);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Destructs the object and calls OnParticleGeneratorRelease
|
||||
*
|
||||
* \see OnParticleGeneratorRelease
|
||||
*/
|
||||
|
||||
ParticleGenerator::~ParticleGenerator()
|
||||
{
|
||||
OnParticleGeneratorRelease(this);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Initializes the particle generator librairies
|
||||
* \return true If successful
|
||||
*
|
||||
* \remark Produces a NazaraError if the particle generator library failed to be initialized
|
||||
*/
|
||||
|
||||
bool ParticleGenerator::Initialize()
|
||||
{
|
||||
if (!ParticleGeneratorLibrary::Initialize())
|
||||
|
|
@ -29,6 +56,10 @@ namespace Nz
|
|||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Uninitializes the particle generator librairies
|
||||
*/
|
||||
|
||||
void ParticleGenerator::Uninitialize()
|
||||
{
|
||||
ParticleGeneratorLibrary::Uninitialize();
|
||||
|
|
|
|||
|
|
@ -8,6 +8,19 @@
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \ingroup graphics
|
||||
* \class Nz::ParticleMapper
|
||||
* \brief Graphics class that represents the mapping between the internal buffer and the particle declaration
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Constructs a ParticleMapper object with a raw buffer and a particle declaration
|
||||
*
|
||||
* \param buffer Raw buffer to store particles data
|
||||
* \param declaration Declaration of the particle
|
||||
*/
|
||||
|
||||
ParticleMapper::ParticleMapper(void* buffer, const ParticleDeclaration* declaration) :
|
||||
m_declaration(declaration),
|
||||
m_ptr(static_cast<UInt8*>(buffer))
|
||||
|
|
|
|||
|
|
@ -7,17 +7,42 @@
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \ingroup graphics
|
||||
* \class Nz::ParticleRenderer
|
||||
* \brief Graphics class that represents the rendering of the particle
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Constructs a ParticleRenderer object by assignation
|
||||
*
|
||||
* \param renderer ParticleRenderer to copy into this
|
||||
*/
|
||||
|
||||
ParticleRenderer::ParticleRenderer(const ParticleRenderer& renderer) :
|
||||
RefCounted()
|
||||
{
|
||||
NazaraUnused(renderer);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Destructs the object and calls OnParticleRendererRelease
|
||||
*
|
||||
* \see OnParticleRendererRelease
|
||||
*/
|
||||
|
||||
ParticleRenderer::~ParticleRenderer()
|
||||
{
|
||||
OnParticleRendererRelease(this);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Initializes the particle renderer librairies
|
||||
* \return true If successful
|
||||
*
|
||||
* \remark Produces a NazaraError if the particle renderer library failed to be initialized
|
||||
*/
|
||||
|
||||
bool ParticleRenderer::Initialize()
|
||||
{
|
||||
if (!ParticleRendererLibrary::Initialize())
|
||||
|
|
@ -29,6 +54,10 @@ namespace Nz
|
|||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Uninitializes the particle renderer librairies
|
||||
*/
|
||||
|
||||
void ParticleRenderer::Uninitialize()
|
||||
{
|
||||
ParticleRendererLibrary::Uninitialize();
|
||||
|
|
|
|||
|
|
@ -13,25 +13,51 @@
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \ingroup graphics
|
||||
* \class Nz::ParticleSystem
|
||||
* \brief Graphics class that represents the system to handle particles
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Constructs a ParticleSystem object with a maximal number of particles and a layout
|
||||
*
|
||||
* \param maxParticleCount Maximum number of particles to generate
|
||||
* \param layout Enumeration for the layout of data information for the particles
|
||||
*/
|
||||
|
||||
ParticleSystem::ParticleSystem(unsigned int maxParticleCount, ParticleLayout layout) :
|
||||
ParticleSystem(maxParticleCount, ParticleDeclaration::Get(layout))
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Constructs a ParticleSystem object with a maximal number of particles and a particle declaration
|
||||
*
|
||||
* \param maxParticleCount Maximum number of particles to generate
|
||||
* \param declaration Data information for the particles
|
||||
*/
|
||||
|
||||
ParticleSystem::ParticleSystem(unsigned int maxParticleCount, ParticleDeclarationConstRef declaration) :
|
||||
m_declaration(std::move(declaration)),
|
||||
m_processing(false),
|
||||
m_maxParticleCount(maxParticleCount),
|
||||
m_particleCount(0)
|
||||
{
|
||||
// En cas d'erreur, un constructeur ne peut que lancer une exception
|
||||
// In case of error, the constructor can only throw an exception
|
||||
ErrorFlags flags(ErrorFlag_ThrowException, true);
|
||||
|
||||
m_particleSize = m_declaration->GetStride(); // La taille de chaque particule
|
||||
m_particleSize = m_declaration->GetStride(); // The size of each particle
|
||||
|
||||
ResizeBuffer();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Constructs a ParticleSystem object by assignation
|
||||
*
|
||||
* \param system ParticleSystem to copy into this
|
||||
*/
|
||||
|
||||
ParticleSystem::ParticleSystem(const ParticleSystem& system) :
|
||||
Renderable(system),
|
||||
m_controllers(system.m_controllers),
|
||||
|
|
@ -47,12 +73,20 @@ namespace Nz
|
|||
|
||||
ResizeBuffer();
|
||||
|
||||
// On ne copie que les particules vivantes
|
||||
// We only copy alive particles
|
||||
std::memcpy(m_buffer.data(), system.m_buffer.data(), system.m_particleCount*m_particleSize);
|
||||
}
|
||||
|
||||
ParticleSystem::~ParticleSystem() = default;
|
||||
|
||||
/*!
|
||||
* \brief Adds a controller to the particles
|
||||
*
|
||||
* \param controller Controller for the particles
|
||||
*
|
||||
* \remark Produces a NazaraAssert if controller is invalid
|
||||
*/
|
||||
|
||||
void ParticleSystem::AddController(ParticleControllerRef controller)
|
||||
{
|
||||
NazaraAssert(controller, "Invalid particle controller");
|
||||
|
|
@ -60,6 +94,14 @@ namespace Nz
|
|||
m_controllers.emplace_back(std::move(controller));
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds an emitter to the particles
|
||||
*
|
||||
* \param emitter Emitter for the particles
|
||||
*
|
||||
* \remark Produces a NazaraAssert if emitter is invalid
|
||||
*/
|
||||
|
||||
void ParticleSystem::AddEmitter(ParticleEmitter* emitter)
|
||||
{
|
||||
NazaraAssert(emitter, "Invalid particle emitter");
|
||||
|
|
@ -67,6 +109,14 @@ namespace Nz
|
|||
m_emitters.emplace_back(emitter);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds a generator to the particles
|
||||
*
|
||||
* \param generator Generator for the particles
|
||||
*
|
||||
* \remark Produces a NazaraAssert if generator is invalid
|
||||
*/
|
||||
|
||||
void ParticleSystem::AddGenerator(ParticleGeneratorRef generator)
|
||||
{
|
||||
NazaraAssert(generator, "Invalid particle generator");
|
||||
|
|
@ -74,6 +124,16 @@ namespace Nz
|
|||
m_generators.emplace_back(std::move(generator));
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds the particle system to the rendering queue
|
||||
*
|
||||
* \param renderQueue Queue to be added
|
||||
* \param transformMatrix Transformation matrix for the system
|
||||
*
|
||||
* \remark Produces a NazaraAssert if inner renderer is invalid
|
||||
* \remark Produces a NazaraAssert if renderQueue is invalid
|
||||
*/
|
||||
|
||||
void ParticleSystem::AddToRenderQueue(AbstractRenderQueue* renderQueue, const Matrix4f& transformMatrix) const
|
||||
{
|
||||
NazaraAssert(m_renderer, "Invalid particle renderer");
|
||||
|
|
@ -83,45 +143,63 @@ namespace Nz
|
|||
if (m_particleCount > 0)
|
||||
{
|
||||
ParticleMapper mapper(m_buffer.data(), m_declaration);
|
||||
m_renderer->Render(*this, mapper, 0, m_particleCount-1, renderQueue);
|
||||
m_renderer->Render(*this, mapper, 0, m_particleCount - 1, renderQueue);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Applies the controllers
|
||||
*
|
||||
* \param mapper Mapper containing layout information of each particle
|
||||
* \param particleCount Number of particles
|
||||
* \param elapsedTime Delta time between the previous frame
|
||||
*/
|
||||
|
||||
void ParticleSystem::ApplyControllers(ParticleMapper& mapper, unsigned int particleCount, float elapsedTime)
|
||||
{
|
||||
m_processing = true;
|
||||
|
||||
// Pour éviter un verrouillage en cas d'exception
|
||||
// To avoid a lock in case of exception
|
||||
CallOnExit onExit([this]()
|
||||
{
|
||||
m_processing = false;
|
||||
});
|
||||
|
||||
for (ParticleController* controller : m_controllers)
|
||||
controller->Apply(*this, mapper, 0, particleCount-1, elapsedTime);
|
||||
controller->Apply(*this, mapper, 0, particleCount - 1, elapsedTime);
|
||||
|
||||
onExit.CallAndReset();
|
||||
|
||||
// On tue maintenant les particules mortes durant la mise à jour
|
||||
// We only kill now the dead particles during the update
|
||||
if (m_dyingParticles.size() < m_particleCount)
|
||||
{
|
||||
// On tue les particules depuis la dernière vers la première (en terme de place), le std::set étant trié via std::greater
|
||||
// La raison est simple, étant donné que la mort d'une particule signifie le déplacement de la dernière particule du buffer,
|
||||
// sans cette solution certaines particules pourraient échapper à la mort
|
||||
// We kill them in reverse order, std::set sorting them via std::greater
|
||||
// The reason is simple, as the death of a particle means the move of the last particle in the buffer,
|
||||
// without this solution, certain particles could avoid the death
|
||||
for (unsigned int index : m_dyingParticles)
|
||||
KillParticle(index);
|
||||
}
|
||||
else
|
||||
KillParticles(); // Toutes les particules sont mortes, ceci est beaucoup plus rapide
|
||||
KillParticles(); // Every particles are dead, this is way faster
|
||||
|
||||
m_dyingParticles.clear();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Creates one particle
|
||||
* \return Pointer to the particle memory buffer
|
||||
*/
|
||||
|
||||
void* ParticleSystem::CreateParticle()
|
||||
{
|
||||
return CreateParticles(1);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Creates multiple particles
|
||||
* \return Pointer to the first particle memory buffer
|
||||
*/
|
||||
|
||||
void* ParticleSystem::CreateParticles(unsigned int count)
|
||||
{
|
||||
if (count == 0)
|
||||
|
|
@ -133,14 +211,24 @@ namespace Nz
|
|||
unsigned int particlesIndex = m_particleCount;
|
||||
m_particleCount += count;
|
||||
|
||||
return &m_buffer[particlesIndex*m_particleSize];
|
||||
return &m_buffer[particlesIndex * m_particleSize];
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Generates one particle
|
||||
* \return Pointer to the particle memory buffer
|
||||
*/
|
||||
|
||||
void* ParticleSystem::GenerateParticle()
|
||||
{
|
||||
return GenerateParticles(1);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Generates multiple particles
|
||||
* \return Pointer to the first particle memory buffer
|
||||
*/
|
||||
|
||||
void* ParticleSystem::GenerateParticles(unsigned int count)
|
||||
{
|
||||
void* ptr = CreateParticles(count);
|
||||
|
|
@ -149,57 +237,108 @@ namespace Nz
|
|||
|
||||
ParticleMapper mapper(ptr, m_declaration);
|
||||
for (ParticleGenerator* generator : m_generators)
|
||||
generator->Generate(*this, mapper, 0, count-1);
|
||||
generator->Generate(*this, mapper, 0, count - 1);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the particle declaration
|
||||
* \return Particle declaration
|
||||
*/
|
||||
|
||||
const ParticleDeclarationConstRef& ParticleSystem::GetDeclaration() const
|
||||
{
|
||||
return m_declaration;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the fixed step size
|
||||
* \return Current fixed step size
|
||||
*/
|
||||
|
||||
float ParticleSystem::GetFixedStepSize() const
|
||||
{
|
||||
return m_stepSize;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the maximum number of particles
|
||||
* \return Current maximum number
|
||||
*/
|
||||
|
||||
unsigned int ParticleSystem::GetMaxParticleCount() const
|
||||
{
|
||||
return m_maxParticleCount;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the number of particles
|
||||
* \return Current number
|
||||
*/
|
||||
|
||||
unsigned int ParticleSystem::GetParticleCount() const
|
||||
{
|
||||
return m_particleCount;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the size of particles
|
||||
* \return Current size
|
||||
*/
|
||||
|
||||
unsigned int ParticleSystem::GetParticleSize() const
|
||||
{
|
||||
return m_particleSize;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether the fixed step is enabled
|
||||
* \return true If it is the case
|
||||
*/
|
||||
|
||||
bool ParticleSystem::IsFixedStepEnabled() const
|
||||
{
|
||||
return m_fixedStepEnabled;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Kills one particle
|
||||
*
|
||||
* \param index Index of the particle
|
||||
*/
|
||||
|
||||
void ParticleSystem::KillParticle(unsigned int index)
|
||||
{
|
||||
///FIXME: Vérifier index
|
||||
///FIXME: Verify the index
|
||||
|
||||
if (m_processing)
|
||||
{
|
||||
// Le buffer est en train d'être modifié, nous ne pouvons pas réduire sa taille, on place alors la particule dans une liste d'attente
|
||||
// The buffer is being modified, we can not reduce its size, we put the particle in the waiting list
|
||||
m_dyingParticles.insert(index);
|
||||
return;
|
||||
}
|
||||
|
||||
// On déplace la dernière particule vivante à la place de celle-ci
|
||||
// We move the last alive particle to the place of this one
|
||||
if (--m_particleCount > 0)
|
||||
std::memcpy(&m_buffer[index*m_particleSize], &m_buffer[m_particleCount*m_particleSize], m_particleSize);
|
||||
std::memcpy(&m_buffer[index * m_particleSize], &m_buffer[m_particleCount * m_particleSize], m_particleSize);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Kills every particles
|
||||
*/
|
||||
|
||||
void ParticleSystem::KillParticles()
|
||||
{
|
||||
m_particleCount = 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Removes a controller to the particles
|
||||
*
|
||||
* \param controller Controller for the particles to remove
|
||||
*/
|
||||
|
||||
void ParticleSystem::RemoveController(ParticleController* controller)
|
||||
{
|
||||
auto it = std::find(m_controllers.begin(), m_controllers.end(), controller);
|
||||
|
|
@ -207,6 +346,12 @@ namespace Nz
|
|||
m_controllers.erase(it);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Removes an emitter to the particles
|
||||
*
|
||||
* \param emitter Emitter for the particles to remove
|
||||
*/
|
||||
|
||||
void ParticleSystem::RemoveEmitter(ParticleEmitter* emitter)
|
||||
{
|
||||
auto it = std::find(m_emitters.begin(), m_emitters.end(), emitter);
|
||||
|
|
@ -214,6 +359,12 @@ namespace Nz
|
|||
m_emitters.erase(it);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Removes a generator to the particles
|
||||
*
|
||||
* \param generator Generator for the particles to remove
|
||||
*/
|
||||
|
||||
void ParticleSystem::RemoveGenerator(ParticleGenerator* generator)
|
||||
{
|
||||
auto it = std::find(m_generators.begin(), m_generators.end(), generator);
|
||||
|
|
@ -221,31 +372,55 @@ namespace Nz
|
|||
m_generators.erase(it);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the fixed step size
|
||||
*
|
||||
* \param stepSize Fixed step size
|
||||
*/
|
||||
|
||||
void ParticleSystem::SetFixedStepSize(float stepSize)
|
||||
{
|
||||
m_stepSize = stepSize;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the renderer of the particles
|
||||
*
|
||||
* \param renderer Renderer for the particles
|
||||
*/
|
||||
|
||||
void ParticleSystem::SetRenderer(ParticleRenderer* renderer)
|
||||
{
|
||||
m_renderer = renderer;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Updates the system
|
||||
*
|
||||
* \param elapsedTime Delta time between the previous frame
|
||||
*/
|
||||
|
||||
void ParticleSystem::Update(float elapsedTime)
|
||||
{
|
||||
// Émission
|
||||
// Emission
|
||||
for (ParticleEmitter* emitter : m_emitters)
|
||||
emitter->Emit(*this, elapsedTime);
|
||||
|
||||
// Mise à jour
|
||||
// Update
|
||||
if (m_particleCount > 0)
|
||||
{
|
||||
///TODO: Mettre à jour en utilisant des threads
|
||||
///TODO: Update using threads
|
||||
ParticleMapper mapper(m_buffer.data(), m_declaration);
|
||||
ApplyControllers(mapper, m_particleCount, elapsedTime);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Updates the bounding volume by a matrix
|
||||
*
|
||||
* \param transformMatrix Matrix transformation for our bounding volume
|
||||
*/
|
||||
|
||||
void ParticleSystem::UpdateBoundingVolume(const Matrix4f& transformMatrix)
|
||||
{
|
||||
NazaraUnused(transformMatrix);
|
||||
|
|
@ -253,6 +428,13 @@ namespace Nz
|
|||
// Nothing to do here (our bounding volume is global)
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the current particle system with the content of the other one
|
||||
* \return A reference to this
|
||||
*
|
||||
* \param system The other ParticleSystem
|
||||
*/
|
||||
|
||||
ParticleSystem& ParticleSystem::operator=(const ParticleSystem& system)
|
||||
{
|
||||
ErrorFlags flags(ErrorFlag_ThrowException, true);
|
||||
|
|
@ -268,29 +450,39 @@ namespace Nz
|
|||
m_renderer = system.m_renderer;
|
||||
m_stepSize = system.m_stepSize;
|
||||
|
||||
// La copie ne peut pas (ou plutôt ne devrait pas) avoir lieu pendant une mise à jour, inutile de copier
|
||||
// The copy can not (or should not) happen during the update, there is no use to copy
|
||||
m_dyingParticles.clear();
|
||||
m_processing = false;
|
||||
m_stepAccumulator = 0.f;
|
||||
|
||||
m_buffer.clear(); // Pour éviter une recopie lors du resize() qui ne servira pas à grand chose
|
||||
m_buffer.clear(); // To avoid a copy due to resize() which will be pointless
|
||||
ResizeBuffer();
|
||||
|
||||
// On ne copie que les particules vivantes
|
||||
std::memcpy(m_buffer.data(), system.m_buffer.data(), system.m_particleCount*m_particleSize);
|
||||
// We only copy alive particles
|
||||
std::memcpy(m_buffer.data(), system.m_buffer.data(), system.m_particleCount * m_particleSize);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Makes the bounding volume of this text
|
||||
*/
|
||||
|
||||
void ParticleSystem::MakeBoundingVolume() const
|
||||
{
|
||||
///TODO: Calculer l'AABB (prendre la taille des particules en compte s'il y a)
|
||||
///TODO: Compute the AABB (taking into account the size of particles)
|
||||
m_boundingVolume.MakeInfinite();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Resizes the internal buffer
|
||||
*
|
||||
* \remark Produces a NazaraError if resize did not work
|
||||
*/
|
||||
|
||||
void ParticleSystem::ResizeBuffer()
|
||||
{
|
||||
// Histoire de décrire un peu mieux l'erreur en cas d'échec
|
||||
// Just to have a better description of our problem in case of error
|
||||
try
|
||||
{
|
||||
m_buffer.resize(m_maxParticleCount*m_particleSize);
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ namespace Nz
|
|||
"User"
|
||||
};
|
||||
|
||||
static_assert(sizeof(techniquesName)/sizeof(const char*) == RenderTechniqueType_Max+1, "Render technique type name array is incomplete");
|
||||
static_assert(sizeof(techniquesName) / sizeof(const char*) == RenderTechniqueType_Max + 1, "Render technique type name array is incomplete");
|
||||
|
||||
struct RenderTechnique
|
||||
{
|
||||
|
|
@ -34,6 +34,22 @@ namespace Nz
|
|||
std::unordered_map<String, RenderTechnique> s_renderTechniques;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \ingroup graphics
|
||||
* \class Nz::RenderTechniques
|
||||
* \brief Graphics class that represents the techniques used in rendering
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Gets the technique by enumeration
|
||||
* \return A reference to the newly created technique
|
||||
*
|
||||
* \param renderTechnique Enumeration of the technique
|
||||
* \param techniqueRanking Ranking for the technique
|
||||
*
|
||||
* \remark Produces a NazaraError if renderTechnique does not exist
|
||||
*/
|
||||
|
||||
AbstractRenderTechnique* RenderTechniques::GetByEnum(RenderTechniqueType renderTechnique, int* techniqueRanking)
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
|
|
@ -47,6 +63,16 @@ namespace Nz
|
|||
return GetByName(techniquesName[renderTechnique], techniqueRanking);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the technique by index
|
||||
* \return A reference to the newly created technique
|
||||
*
|
||||
* \param index Index of the technique
|
||||
* \param techniqueRanking Ranking for the technique
|
||||
*
|
||||
* \remark Produces a NazaraError if index is out or range
|
||||
*/
|
||||
|
||||
AbstractRenderTechnique* RenderTechniques::GetByIndex(unsigned int index, int* techniqueRanking)
|
||||
{
|
||||
#if NAZARA_GRAPHICS_SAFE
|
||||
|
|
@ -66,6 +92,16 @@ namespace Nz
|
|||
return it->second.factory();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the technique by name
|
||||
* \return A reference to the newly created technique
|
||||
*
|
||||
* \param name Name of the technique
|
||||
* \param techniqueRanking Ranking for the technique
|
||||
*
|
||||
* \remark Produces a NazaraError if name does not exist or is invalid
|
||||
*/
|
||||
|
||||
AbstractRenderTechnique* RenderTechniques::GetByName(const String& name, int* techniqueRanking)
|
||||
{
|
||||
#if NAZARA_GRAPHICS_SAFE
|
||||
|
|
@ -89,6 +125,16 @@ namespace Nz
|
|||
return it->second.factory();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the technique by ranking
|
||||
* \return A reference to the newly created technique
|
||||
*
|
||||
* \param maxRanking Ranking maximum of the technique
|
||||
* \param techniqueRanking Ranking for the technique
|
||||
*
|
||||
* \remark Produces a NazaraError if name does not exist or is invalid
|
||||
*/
|
||||
|
||||
AbstractRenderTechnique* RenderTechniques::GetByRanking(int maxRanking, int* techniqueRanking)
|
||||
{
|
||||
if (maxRanking < 0)
|
||||
|
|
@ -119,11 +165,28 @@ namespace Nz
|
|||
return technique->factory();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the number of techniques available
|
||||
* \return Number of techniques
|
||||
*/
|
||||
|
||||
unsigned int RenderTechniques::GetCount()
|
||||
{
|
||||
return s_renderTechniques.size();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Registers a technique
|
||||
*
|
||||
* \param name Name of the technique
|
||||
* \param ranking Ranking of the technique
|
||||
* \param factory Factory to create the technique
|
||||
*
|
||||
* \remark Produces a NazaraError with NAZARA_GRAPHICS_SAFE defined if name is empty
|
||||
* \remark Produces a NazaraError with NAZARA_GRAPHICS_SAFE defined if ranking is negative
|
||||
* \remark Produces a NazaraError with NAZARA_GRAPHICS_SAFE defined if factory is invalid is invalid
|
||||
*/
|
||||
|
||||
void RenderTechniques::Register(const String& name, int ranking, RenderTechniqueFactory factory)
|
||||
{
|
||||
#if NAZARA_GRAPHICS_SAFE
|
||||
|
|
@ -149,6 +212,15 @@ namespace Nz
|
|||
s_renderTechniques[name] = {factory, ranking};
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Converts the enumeration to string
|
||||
* \return String symbolizing the technique
|
||||
*
|
||||
* \param renderTechnique Enumeration of the technique
|
||||
*
|
||||
* \remark Produces a NazaraError if renderTechnique does not exist and returns "Error"
|
||||
*/
|
||||
|
||||
String RenderTechniques::ToString(RenderTechniqueType renderTechnique)
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
|
|
@ -162,6 +234,12 @@ namespace Nz
|
|||
return techniquesName[renderTechnique];
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Unregisters a technique
|
||||
*
|
||||
* \param name Name of the technique
|
||||
*/
|
||||
|
||||
void RenderTechniques::Unregister(const String& name)
|
||||
{
|
||||
s_renderTechniques.erase(name);
|
||||
|
|
|
|||
|
|
@ -7,8 +7,24 @@
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \ingroup graphics
|
||||
* \class Nz::Renderable
|
||||
* \brief Graphics class that represents a renderable element for our scene
|
||||
*
|
||||
* \remark This class is abstract
|
||||
*/
|
||||
|
||||
Renderable::~Renderable() = default;
|
||||
|
||||
/*!
|
||||
* \brief Culls the model if not in the frustum
|
||||
* \return true If renderable is in the frustum
|
||||
*
|
||||
* \param frustum Symbolizing the field of view
|
||||
* \param transformMatrix Matrix transformation for our object
|
||||
*/
|
||||
|
||||
bool Renderable::Cull(const Frustumf& frustum, const Matrix4f& transformMatrix) const
|
||||
{
|
||||
NazaraUnused(transformMatrix);
|
||||
|
|
@ -16,6 +32,11 @@ namespace Nz
|
|||
return frustum.Contains(m_boundingVolume);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the bounding volume
|
||||
* \return Bounding volume of the renderable element
|
||||
*/
|
||||
|
||||
const BoundingVolumef& Renderable::GetBoundingVolume() const
|
||||
{
|
||||
EnsureBoundingVolumeUpdated();
|
||||
|
|
@ -23,6 +44,12 @@ namespace Nz
|
|||
return m_boundingVolume;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Updates the bounding volume by a matrix
|
||||
*
|
||||
* \param transformMatrix Matrix transformation for our bounding volume
|
||||
*/
|
||||
|
||||
void Renderable::UpdateBoundingVolume(const Matrix4f& transformMatrix)
|
||||
{
|
||||
m_boundingVolume.Update(transformMatrix);
|
||||
|
|
|
|||
|
|
@ -14,6 +14,17 @@
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \ingroup graphics
|
||||
* \class Nz::SkeletalModel
|
||||
* \brief Graphics class that represents a model with a skeleton
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Checks whether the parameters for the skeletal mesh are correct
|
||||
* \return true If parameters are valid
|
||||
*/
|
||||
|
||||
bool SkeletalModelParameters::IsValid() const
|
||||
{
|
||||
if (!ModelParameters::IsValid())
|
||||
|
|
@ -25,12 +36,23 @@ namespace Nz
|
|||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Constructs a SkeletalModel object by default
|
||||
*/
|
||||
|
||||
SkeletalModel::SkeletalModel() :
|
||||
m_currentSequence(nullptr),
|
||||
m_animationEnabled(true)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds the skeletal mesh to the rendering queue
|
||||
*
|
||||
* \param renderQueue Queue to be added
|
||||
* \param instanceData Data for the instance
|
||||
*/
|
||||
|
||||
void SkeletalModel::AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData) const
|
||||
{
|
||||
if (!m_mesh)
|
||||
|
|
@ -51,6 +73,14 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Updates the animation of the mesh
|
||||
*
|
||||
* \param elapsedTime Delta time between two frames
|
||||
*
|
||||
* \remark Produces a NazaraError with NAZARA_GRAPHICS_SAFE defined if there is no animation
|
||||
*/
|
||||
|
||||
void SkeletalModel::AdvanceAnimation(float elapsedTime)
|
||||
{
|
||||
#if NAZARA_GRAPHICS_SAFE
|
||||
|
|
@ -67,7 +97,7 @@ namespace Nz
|
|||
m_interpolation -= 1.f;
|
||||
|
||||
unsigned lastFrame = m_currentSequence->firstFrame + m_currentSequence->frameCount - 1;
|
||||
if (m_nextFrame+1 > lastFrame)
|
||||
if (m_nextFrame + 1 > lastFrame)
|
||||
{
|
||||
if (m_animation->IsLoopPointInterpolationEnabled())
|
||||
{
|
||||
|
|
@ -77,7 +107,7 @@ namespace Nz
|
|||
else
|
||||
{
|
||||
m_currentFrame = m_currentSequence->firstFrame;
|
||||
m_nextFrame = m_currentFrame+1;
|
||||
m_nextFrame = m_currentFrame + 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -92,26 +122,52 @@ namespace Nz
|
|||
InvalidateBoundingVolume();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Clones this skeletal model
|
||||
* \return Pointer to newly allocated SkeletalModel
|
||||
*/
|
||||
|
||||
SkeletalModel* SkeletalModel::Clone() const
|
||||
{
|
||||
return new SkeletalModel(*this);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Creates a default skeletal model
|
||||
* \return Pointer to newly allocated SkeletalModel
|
||||
*/
|
||||
|
||||
SkeletalModel* SkeletalModel::Create() const
|
||||
{
|
||||
return new SkeletalModel;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Enables the animation of the model
|
||||
*
|
||||
* \param animation Should the model be animated
|
||||
*/
|
||||
|
||||
void SkeletalModel::EnableAnimation(bool animation)
|
||||
{
|
||||
m_animationEnabled = animation;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the animation of the model
|
||||
* \return Pointer to the animation
|
||||
*/
|
||||
|
||||
Animation* SkeletalModel::GetAnimation() const
|
||||
{
|
||||
return m_animation;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the skeleton of the model
|
||||
* \return Pointer to the skeleton
|
||||
*/
|
||||
|
||||
Skeleton* SkeletalModel::GetSkeleton()
|
||||
{
|
||||
InvalidateBoundingVolume();
|
||||
|
|
@ -119,41 +175,96 @@ namespace Nz
|
|||
return &m_skeleton;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the skeleton of the model
|
||||
* \return Constant pointer to the skeleton
|
||||
*/
|
||||
|
||||
const Skeleton* SkeletalModel::GetSkeleton() const
|
||||
{
|
||||
return &m_skeleton;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether the skeleton has an animation
|
||||
* \return true If it is the case
|
||||
*
|
||||
* \see IsAnimated, IsAnimationEnabled
|
||||
*/
|
||||
|
||||
bool SkeletalModel::HasAnimation() const
|
||||
{
|
||||
return m_animation != nullptr;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether the skeleton is animated
|
||||
* \return true
|
||||
*
|
||||
* \see HasAnimation, IsAnimationEnabled
|
||||
*/
|
||||
|
||||
bool SkeletalModel::IsAnimated() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether the skeleton is currently animated
|
||||
* \return true If it is the case
|
||||
*
|
||||
* \see HasAnimation, IsAnimated
|
||||
*/
|
||||
|
||||
bool SkeletalModel::IsAnimationEnabled() const
|
||||
{
|
||||
return m_animationEnabled;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Loads the skeleton model from file
|
||||
* \return true if loading is successful
|
||||
*
|
||||
* \param filePath Path to the file
|
||||
* \param params Parameters for the skeleton model
|
||||
*/
|
||||
|
||||
bool SkeletalModel::LoadFromFile(const String& filePath, const SkeletalModelParameters& params)
|
||||
{
|
||||
return SkeletalModelLoader::LoadFromFile(this, filePath, params);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Loads the skeleton model from memory
|
||||
* \return true if loading is successful
|
||||
*
|
||||
* \param data Raw memory
|
||||
* \param size Size of the memory
|
||||
* \param params Parameters for the skeleton model
|
||||
*/
|
||||
|
||||
bool SkeletalModel::LoadFromMemory(const void* data, std::size_t size, const SkeletalModelParameters& params)
|
||||
{
|
||||
return SkeletalModelLoader::LoadFromMemory(this, data, size, params);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Loads the skeleton model from stream
|
||||
* \return true if loading is successful
|
||||
*
|
||||
* \param stream Stream to the skeleton model
|
||||
* \param params Parameters for the skeleton model
|
||||
*/
|
||||
|
||||
bool SkeletalModel::LoadFromStream(Stream& stream, const SkeletalModelParameters& params)
|
||||
{
|
||||
return SkeletalModelLoader::LoadFromStream(this, stream, params);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Resets the model
|
||||
*/
|
||||
|
||||
void SkeletalModel::Reset()
|
||||
{
|
||||
Model::Reset();
|
||||
|
|
@ -161,6 +272,16 @@ namespace Nz
|
|||
m_skeleton.Destroy();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the animation for the model
|
||||
* \return true If successful
|
||||
*
|
||||
* \param animation Animation for the model
|
||||
*
|
||||
* \remark Produces a NazaraError with NAZARA_GRAPHICS_SAFE if there is no mesh
|
||||
* \remark Produces a NazaraError with NAZARA_GRAPHICS_SAFE if animation is invalid
|
||||
*/
|
||||
|
||||
bool SkeletalModel::SetAnimation(Animation* animation)
|
||||
{
|
||||
#if NAZARA_GRAPHICS_SAFE
|
||||
|
|
@ -204,6 +325,14 @@ namespace Nz
|
|||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the mesh for the model
|
||||
*
|
||||
* \param mesh Mesh for the model
|
||||
*
|
||||
* \remark Produces a NazaraError with NAZARA_GRAPHICS_SAFE if there is no mesh or if invalid
|
||||
*/
|
||||
|
||||
void SkeletalModel::SetMesh(Mesh* mesh)
|
||||
{
|
||||
#if NAZARA_GRAPHICS_SAFE
|
||||
|
|
@ -224,13 +353,23 @@ namespace Nz
|
|||
SetAnimation(nullptr);
|
||||
}
|
||||
|
||||
m_skeleton = *m_mesh->GetSkeleton(); // Copie du squelette template
|
||||
m_skeleton = *m_mesh->GetSkeleton(); // Copy of skeleton template
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the sequence for the model
|
||||
* \return true If successful
|
||||
*
|
||||
* \param sequenceName Name for the sequence animation
|
||||
*
|
||||
* \remark Produces a NazaraError with NAZARA_GRAPHICS_SAFE if there is no animation
|
||||
* \remark Produces a NazaraError with NAZARA_GRAPHICS_SAFE if sequence name does not exist for the current animation
|
||||
*/
|
||||
|
||||
bool SkeletalModel::SetSequence(const String& sequenceName)
|
||||
{
|
||||
///TODO: Rendre cette erreur "safe" avec le nouveau système de gestions d'erreur (No-log)
|
||||
///TODO: Make this error "safe" with the new system of error handling (No-log)
|
||||
#if NAZARA_GRAPHICS_SAFE
|
||||
if (!m_animation)
|
||||
{
|
||||
|
|
@ -240,11 +379,13 @@ namespace Nz
|
|||
#endif
|
||||
|
||||
const Sequence* currentSequence = m_animation->GetSequence(sequenceName);
|
||||
#if NAZARA_GRAPHICS_SAFE
|
||||
if (!currentSequence)
|
||||
{
|
||||
NazaraError("Sequence not found");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
m_currentSequence = currentSequence;
|
||||
m_nextFrame = m_currentSequence->firstFrame;
|
||||
|
|
@ -252,6 +393,15 @@ namespace Nz
|
|||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the sequence for the model
|
||||
*
|
||||
* \param sequenceIndex Index for the sequence animation
|
||||
*
|
||||
* \remark Produces a NazaraError with NAZARA_GRAPHICS_SAFE if there is no animation
|
||||
* \remark Produces a NazaraError with NAZARA_GRAPHICS_SAFE if sequence name does not exist for the current animation
|
||||
*/
|
||||
|
||||
void SkeletalModel::SetSequence(unsigned int sequenceIndex)
|
||||
{
|
||||
#if NAZARA_GRAPHICS_SAFE
|
||||
|
|
@ -275,13 +425,22 @@ namespace Nz
|
|||
m_nextFrame = m_currentSequence->firstFrame;
|
||||
}
|
||||
|
||||
/*
|
||||
* \brief Makes the bounding volume of this text
|
||||
*/
|
||||
|
||||
void SkeletalModel::MakeBoundingVolume() const
|
||||
{
|
||||
m_boundingVolume.Set(m_skeleton.GetAABB());
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Updates the model
|
||||
*/
|
||||
|
||||
void SkeletalModel::Update()
|
||||
{
|
||||
///TODO
|
||||
/*if (m_animationEnabled && m_animation)
|
||||
AdvanceAnimation(m_scene->GetUpdateTime());*/
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,6 +46,13 @@ namespace Nz
|
|||
SkeletonMap s_cache;
|
||||
std::vector<QueueData> s_skinningQueue;
|
||||
|
||||
/*!
|
||||
* \brief Skins the mesh for a single thread context
|
||||
*
|
||||
* \param mesh Skeletal mesh to get vertex buffer from
|
||||
* \param skeleton Skeleton to consider for getting data
|
||||
* \param buffer Vertex buffer symbolizing the transition
|
||||
*/
|
||||
|
||||
void Skin_MonoCPU(const SkeletalMesh* mesh, const Skeleton* skeleton, VertexBuffer* buffer)
|
||||
{
|
||||
|
|
@ -60,6 +67,14 @@ namespace Nz
|
|||
SkinPositionNormalTangent(skinningData, 0, mesh->GetVertexCount());
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Skins the mesh for a multi-threaded context
|
||||
*
|
||||
* \param mesh Skeletal mesh to get vertex buffer from
|
||||
* \param skeleton Skeleton to consider for getting data
|
||||
* \param buffer Vertex buffer symbolizing the transition
|
||||
*/
|
||||
|
||||
void Skin_MultiCPU(const SkeletalMesh* mesh, const Skeleton* skeleton, VertexBuffer* buffer)
|
||||
{
|
||||
BufferMapper<VertexBuffer> inputMapper(mesh->GetVertexBuffer(), BufferAccess_ReadOnly);
|
||||
|
|
@ -70,8 +85,8 @@ namespace Nz
|
|||
skinningData.outputVertex = static_cast<MeshVertex*>(outputMapper.GetPointer());
|
||||
skinningData.joints = skeleton->GetJoints();
|
||||
|
||||
// Afin d'empêcher les différents threads de vouloir mettre à jour la même matrice en même temps,
|
||||
// on se charge de la mettre à jour avant de les lancer
|
||||
// To avoid different threads to update the same matrix at the same time
|
||||
// We try to update them before launching the tasks
|
||||
unsigned int jointCount = skeleton->GetJointCount();
|
||||
for (unsigned int i = 0; i < jointCount; ++i)
|
||||
skinningData.joints[i].EnsureSkinningMatrixUpdate();
|
||||
|
|
@ -87,6 +102,23 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \ingroup graphics
|
||||
* \class Nz::SkinningManager
|
||||
* \brief Graphics class that represents the management of skinning
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Gets the vertex buffer from a skeletal mesh with its skeleton
|
||||
* \return A pointer to the vertex buffer newly created
|
||||
*
|
||||
* \param mesh Skeletal mesh to get vertex buffer from
|
||||
* \param skeleton Skeleton to consider for getting data
|
||||
*
|
||||
* \remark Produces a NazaraError with NAZARA_GRAPHICS_SAFE defined if mesh is invalid
|
||||
* \remark Produces a NazaraError with NAZARA_GRAPHICS_SAFE defined if skeleton is invalid
|
||||
*/
|
||||
|
||||
VertexBuffer* SkinningManager::GetBuffer(const SkeletalMesh* mesh, const Skeleton* skeleton)
|
||||
{
|
||||
#if NAZARA_GRAPHICS_SAFE
|
||||
|
|
@ -149,6 +181,10 @@ namespace Nz
|
|||
return buffer;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Skins the skeletal mesh
|
||||
*/
|
||||
|
||||
void SkinningManager::Skin()
|
||||
{
|
||||
for (QueueData& data : s_skinningQueue)
|
||||
|
|
@ -157,6 +193,11 @@ namespace Nz
|
|||
s_skinningQueue.clear();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Initializes the skinning librairies
|
||||
* \return true
|
||||
*/
|
||||
|
||||
bool SkinningManager::Initialize()
|
||||
{
|
||||
///TODO: GPU Skinning
|
||||
|
|
@ -165,9 +206,15 @@ namespace Nz
|
|||
else
|
||||
s_skinFunc = Skin_MonoCPU;
|
||||
|
||||
return true; // Rien de particulier à faire
|
||||
return true; // Nothing particular to do
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Handle the destruction of a skeletal mesh
|
||||
*
|
||||
* \param mesh SkeletalMesh being destroyed
|
||||
*/
|
||||
|
||||
void SkinningManager::OnSkeletalMeshDestroy(const SkeletalMesh* mesh)
|
||||
{
|
||||
for (auto& pair : s_cache)
|
||||
|
|
@ -177,17 +224,33 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Handle the invalidation of a skeletal mesh
|
||||
*
|
||||
* \param mesh SkeletalMesh being invalidated
|
||||
*/
|
||||
|
||||
void SkinningManager::OnSkeletonInvalidated(const Skeleton* skeleton)
|
||||
{
|
||||
for (auto& pair : s_cache.at(skeleton).meshMap)
|
||||
pair.second.updated = false;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Handle the release of a skeletal mesh
|
||||
*
|
||||
* \param skeleton SkeletalMesh being released
|
||||
*/
|
||||
|
||||
void SkinningManager::OnSkeletonRelease(const Skeleton* skeleton)
|
||||
{
|
||||
s_cache.erase(skeleton);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Uninitializes the skinning librairies
|
||||
*/
|
||||
|
||||
void SkinningManager::Uninitialize()
|
||||
{
|
||||
s_cache.clear();
|
||||
|
|
|
|||
|
|
@ -22,6 +22,18 @@ namespace Nz
|
|||
static VertexBufferRef s_vertexBuffer;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \ingroup graphics
|
||||
* \class Nz::SkyboxBackground
|
||||
* \brief Graphics class that represents a background with a cubemap texture
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Constructs a SkyboxBackground object with a cubemap texture
|
||||
*
|
||||
* \param cubemapTexture Cubemap texture
|
||||
*/
|
||||
|
||||
SkyboxBackground::SkyboxBackground(TextureRef cubemapTexture) :
|
||||
m_movementOffset(Vector3f::Zero()),
|
||||
m_movementScale(0.f)
|
||||
|
|
@ -31,6 +43,12 @@ namespace Nz
|
|||
SetTexture(std::move(cubemapTexture));
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Draws this relatively to the viewer
|
||||
*
|
||||
* \param viewer Viewer for the background
|
||||
*/
|
||||
|
||||
void SkyboxBackground::Draw(const AbstractViewer* viewer) const
|
||||
{
|
||||
Matrix4f skyboxMatrix(viewer->GetViewMatrix());
|
||||
|
|
@ -65,14 +83,26 @@ namespace Nz
|
|||
Renderer::SetMatrix(MatrixType_View, viewer->GetViewMatrix());
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the background type
|
||||
* \return Type of background
|
||||
*/
|
||||
|
||||
BackgroundType SkyboxBackground::GetBackgroundType() const
|
||||
{
|
||||
return BackgroundType_Skybox;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Initializes the skybox
|
||||
* \return true If successful
|
||||
*
|
||||
* \remark Produces a NazaraError if initialization failed
|
||||
*/
|
||||
|
||||
bool SkyboxBackground::Initialize()
|
||||
{
|
||||
const UInt16 indices[6*6] =
|
||||
const UInt16 indices[6 * 6] =
|
||||
{
|
||||
0, 1, 2, 0, 2, 3,
|
||||
3, 2, 6, 3, 6, 7,
|
||||
|
|
@ -170,6 +200,10 @@ namespace Nz
|
|||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Uninitializes the skybox
|
||||
*/
|
||||
|
||||
void SkyboxBackground::Uninitialize()
|
||||
{
|
||||
s_indexBuffer.Reset();
|
||||
|
|
|
|||
|
|
@ -11,6 +11,19 @@
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \ingroup graphics
|
||||
* \class Nz::Sprite
|
||||
* \brief Graphics class that represents the rendering of a sprite
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Adds the sprite to the rendering queue
|
||||
*
|
||||
* \param renderQueue Queue to be added
|
||||
* \param instanceData Data for the instance
|
||||
*/
|
||||
|
||||
void Sprite::AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData) const
|
||||
{
|
||||
if (!m_material)
|
||||
|
|
@ -20,11 +33,21 @@ namespace Nz
|
|||
renderQueue->AddSprites(instanceData.renderOrder, m_material, vertices, 1);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Makes the bounding volume of this text
|
||||
*/
|
||||
|
||||
void Sprite::MakeBoundingVolume() const
|
||||
{
|
||||
m_boundingVolume.Set(Vector3f(0.f), m_size.x*Vector3f::Right() + m_size.y*Vector3f::Down());
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Updates the data of the sprite
|
||||
*
|
||||
* \param instanceData Data of the instance
|
||||
*/
|
||||
|
||||
void Sprite::UpdateData(InstanceData* instanceData) const
|
||||
{
|
||||
instanceData->data.resize(4 * sizeof(VertexStruct_XYZ_Color_UV));
|
||||
|
|
@ -51,6 +74,13 @@ namespace Nz
|
|||
*texCoordPtr++ = m_textureCoords.GetCorner(RectCorner_RightBottom);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Initializes the sprite librairies
|
||||
* \return true If successful
|
||||
*
|
||||
* \remark Produces a NazaraError if the sprite library failed to be initialized
|
||||
*/
|
||||
|
||||
bool Sprite::Initialize()
|
||||
{
|
||||
if (!SpriteLibrary::Initialize())
|
||||
|
|
@ -62,6 +92,10 @@ namespace Nz
|
|||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Uninitializes the sprite librairies
|
||||
*/
|
||||
|
||||
void Sprite::Uninitialize()
|
||||
{
|
||||
SpriteLibrary::Uninitialize();
|
||||
|
|
|
|||
|
|
@ -13,6 +13,19 @@
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \ingroup graphics
|
||||
* \class Nz::TextSprite
|
||||
* \brief Graphics class that represents the rendering of a sprite containing text
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Adds the text to the rendering queue
|
||||
*
|
||||
* \param renderQueue Queue to be added
|
||||
* \param instanceData Data for the instance
|
||||
*/
|
||||
|
||||
void TextSprite::AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData) const
|
||||
{
|
||||
if (!m_material)
|
||||
|
|
@ -26,11 +39,19 @@ namespace Nz
|
|||
if (indices.count > 0)
|
||||
{
|
||||
const VertexStruct_XYZ_Color_UV* vertices = reinterpret_cast<const VertexStruct_XYZ_Color_UV*>(instanceData.data.data());
|
||||
renderQueue->AddSprites(instanceData.renderOrder, m_material, &vertices[indices.first*4], indices.count, overlay);
|
||||
renderQueue->AddSprites(instanceData.renderOrder, m_material, &vertices[indices.first * 4], indices.count, overlay);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Updates the text
|
||||
*
|
||||
* \param drawer Drawer used to compose the text
|
||||
*
|
||||
* \remark Produces a NazaraAssert if atlas does not use a hardware storage
|
||||
*/
|
||||
|
||||
void TextSprite::Update(const AbstractTextDrawer& drawer)
|
||||
{
|
||||
CallOnExit clearOnFail([this]()
|
||||
|
|
@ -138,8 +159,8 @@ namespace Nz
|
|||
|
||||
// First, compute the uv coordinates from our atlas rect
|
||||
Vector2ui size(texture->GetSize());
|
||||
float invWidth = 1.f/size.x;
|
||||
float invHeight = 1.f/size.y;
|
||||
float invWidth = 1.f / size.x;
|
||||
float invHeight = 1.f / size.y;
|
||||
|
||||
Rectf uvRect(glyph.atlasRect);
|
||||
uvRect.x *= invWidth;
|
||||
|
|
@ -155,9 +176,9 @@ namespace Nz
|
|||
for (unsigned int j = 0; j < 4; ++j)
|
||||
{
|
||||
// Remember that indices->count is a counter here, not a count value
|
||||
m_localVertices[indices->count*4 + j].color = glyph.color;
|
||||
m_localVertices[indices->count*4 + j].position.Set(glyph.corners[j]);
|
||||
m_localVertices[indices->count*4 + j].uv.Set(uvRect.GetCorner((glyph.flipped) ? flippedCorners[j] : normalCorners[j]));
|
||||
m_localVertices[indices->count * 4 + j].color = glyph.color;
|
||||
m_localVertices[indices->count * 4 + j].position.Set(glyph.corners[j]);
|
||||
m_localVertices[indices->count * 4 + j].uv.Set(uvRect.GetCorner((glyph.flipped) ? flippedCorners[j] : normalCorners[j]));
|
||||
}
|
||||
|
||||
// Increment the counter, go to next glyph
|
||||
|
|
@ -172,15 +193,25 @@ namespace Nz
|
|||
clearOnFail.Reset();
|
||||
}
|
||||
|
||||
/*
|
||||
* \brief Makes the bounding volume of this text
|
||||
*/
|
||||
|
||||
void TextSprite::MakeBoundingVolume() const
|
||||
{
|
||||
Rectf bounds(m_localBounds);
|
||||
Vector2f max = bounds.GetMaximum();
|
||||
Vector2f min = bounds.GetMinimum();
|
||||
|
||||
m_boundingVolume.Set(min.x*Vector3f::Right() + min.y*Vector3f::Down(), max.x*Vector3f::Right() + max.y*Vector3f::Down());
|
||||
m_boundingVolume.Set(min.x * Vector3f::Right() + min.y * Vector3f::Down(), max.x * Vector3f::Right() + max.y * Vector3f::Down());
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Handle the invalidation of an atlas
|
||||
*
|
||||
* \param atlas Atlas being invalidated
|
||||
*/
|
||||
|
||||
void TextSprite::OnAtlasInvalidated(const AbstractAtlas* atlas)
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
|
|
@ -195,6 +226,14 @@ namespace Nz
|
|||
Clear();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Handle the invalidation of an atlas layer
|
||||
*
|
||||
* \param atlas Atlas being invalidated
|
||||
* \param oldLayer Pointer to the previous layer
|
||||
* \param newLayer Pointer to the new layer
|
||||
*/
|
||||
|
||||
void TextSprite::OnAtlasLayerChange(const AbstractAtlas* atlas, AbstractImage* oldLayer, AbstractImage* newLayer)
|
||||
{
|
||||
NazaraUnused(atlas);
|
||||
|
|
@ -207,23 +246,23 @@ namespace Nz
|
|||
}
|
||||
#endif
|
||||
|
||||
// La texture d'un atlas vient d'être recréée (changement de taille)
|
||||
// nous devons ajuster les coordonnées de textures et la texture du rendu
|
||||
// The texture of an atlas have just been recreated (size change)
|
||||
// we have to adjust the coordinates of the texture and the rendering texture
|
||||
Texture* oldTexture = static_cast<Texture*>(oldLayer);
|
||||
Texture* newTexture = static_cast<Texture*>(newLayer);
|
||||
|
||||
// Il est possible que nous n'utilisions pas la texture en question (l'atlas nous prévenant pour chacun de ses layers)
|
||||
// It is possible that we don't use the texture (the atlas warning us for each of its layers)
|
||||
auto it = m_renderInfos.find(oldTexture);
|
||||
if (it != m_renderInfos.end())
|
||||
{
|
||||
// Nous utilisons bien cette texture, nous devons mettre à jour les coordonnées de texture
|
||||
// We indeed use this texture, we have to update its coordinates
|
||||
RenderIndices indices = std::move(it->second);
|
||||
|
||||
Vector2ui oldSize(oldTexture->GetSize());
|
||||
Vector2ui newSize(newTexture->GetSize());
|
||||
Vector2f scale = Vector2f(oldSize)/Vector2f(newSize); // ratio ancienne et nouvelle taille
|
||||
Vector2f scale = Vector2f(oldSize) / Vector2f(newSize); // ratio of the old one to the new one
|
||||
|
||||
// On va maintenant parcourir toutes les coordonnées de texture concernées pour les multiplier par ce ratio
|
||||
// Now we will iterate through each coordinates of the concerned texture to multiply them by the ratio
|
||||
SparsePtr<Vector2f> texCoordPtr(&m_localVertices[indices.first].uv, sizeof(VertexStruct_XYZ_Color_UV));
|
||||
for (unsigned int i = 0; i < indices.count; ++i)
|
||||
{
|
||||
|
|
@ -231,12 +270,18 @@ namespace Nz
|
|||
m_localVertices[i*4 + j].uv *= scale;
|
||||
}
|
||||
|
||||
// Nous enlevons l'ancienne texture et rajoutons la nouvelle à sa place (pour les mêmes indices)
|
||||
// We get rid off the old texture and we set the new one at the place (same for indices)
|
||||
m_renderInfos.erase(it);
|
||||
m_renderInfos.insert(std::make_pair(newTexture, std::move(indices)));
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Updates the data of the sprite
|
||||
*
|
||||
* \param instanceData Data of the instance
|
||||
*/
|
||||
|
||||
void TextSprite::UpdateData(InstanceData* instanceData) const
|
||||
{
|
||||
instanceData->data.resize(m_localVertices.size() * sizeof(VertexStruct_XYZ_Color_UV));
|
||||
|
|
@ -246,18 +291,18 @@ namespace Nz
|
|||
SparsePtr<Vector3f> posPtr(&vertices[0].position, sizeof(VertexStruct_XYZ_Color_UV));
|
||||
SparsePtr<Vector2f> texCoordPtr(&vertices[0].uv, sizeof(VertexStruct_XYZ_Color_UV));
|
||||
|
||||
// Nous allons maintenant initialiser les sommets finaux (ceux envoyés à la RenderQueue)
|
||||
// à l'aide du repère, de la matrice et de notre attribut de couleur
|
||||
// We will not initialize the final vertices (those send to the RenderQueue)
|
||||
// With the help of the coordinates axis, the matrix and our color attribute
|
||||
for (auto& pair : m_renderInfos)
|
||||
{
|
||||
RenderIndices& indices = pair.second;
|
||||
if (indices.count == 0)
|
||||
continue; //< Ignore empty render indices
|
||||
|
||||
SparsePtr<Color> color = colorPtr + indices.first*4;
|
||||
SparsePtr<Vector3f> pos = posPtr + indices.first*4;
|
||||
SparsePtr<Vector2f> uv = texCoordPtr + indices.first*4;
|
||||
VertexStruct_XY_Color_UV* localVertex = &m_localVertices[indices.first*4];
|
||||
SparsePtr<Color> color = colorPtr + indices.first * 4;
|
||||
SparsePtr<Vector3f> pos = posPtr + indices.first * 4;
|
||||
SparsePtr<Vector2f> uv = texCoordPtr + indices.first * 4;
|
||||
VertexStruct_XY_Color_UV* localVertex = &m_localVertices[indices.first * 4];
|
||||
for (unsigned int i = 0; i < indices.count; ++i)
|
||||
{
|
||||
for (unsigned int j = 0; j < 4; ++j)
|
||||
|
|
|
|||
|
|
@ -11,6 +11,11 @@ namespace Nz
|
|||
{
|
||||
namespace
|
||||
{
|
||||
/*!
|
||||
* \brief Defines render states
|
||||
* \return RenderStates for the color background
|
||||
*/
|
||||
|
||||
RenderStates BuildRenderStates()
|
||||
{
|
||||
RenderStates states;
|
||||
|
|
@ -24,6 +29,18 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \ingroup graphics
|
||||
* \class Nz::TextureBackground
|
||||
* \brief Graphics class that represents a background with a texture
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Constructs a TextureBackground object with a texture
|
||||
*
|
||||
* \param texture Texture
|
||||
*/
|
||||
|
||||
TextureBackground::TextureBackground(TextureRef texture)
|
||||
{
|
||||
m_uberShader = UberShaderLibrary::Get("Basic");
|
||||
|
|
@ -43,6 +60,12 @@ namespace Nz
|
|||
SetTexture(std::move(texture));
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Draws this relatively to the viewer
|
||||
*
|
||||
* \param viewer Viewer for the background
|
||||
*/
|
||||
|
||||
void TextureBackground::Draw(const AbstractViewer* viewer) const
|
||||
{
|
||||
NazaraUnused(viewer);
|
||||
|
|
@ -62,6 +85,11 @@ namespace Nz
|
|||
Renderer::DrawFullscreenQuad();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the background type
|
||||
* \return Type of background
|
||||
*/
|
||||
|
||||
BackgroundType TextureBackground::GetBackgroundType() const
|
||||
{
|
||||
return BackgroundType_Texture;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
#include <Nazara/Graphics/Billboard.hpp>
|
||||
#include <Catch/catch.hpp>
|
||||
|
||||
SCENARIO("Billboard", "[GRAPHICS][BILLBOARD]")
|
||||
{
|
||||
GIVEN("A default billboard")
|
||||
{
|
||||
Nz::Billboard billboard;
|
||||
|
||||
WHEN("We assign it to another")
|
||||
{
|
||||
Nz::MaterialRef materialRef = Nz::Material::New();
|
||||
materialRef->LoadFromFile("resources/Engine/Graphics/Nazara.png");
|
||||
Nz::Color materialColor = materialRef->GetDiffuseColor();
|
||||
Nz::BillboardRef otherBillboard = Nz::Billboard::New(materialRef);
|
||||
|
||||
billboard = *otherBillboard;
|
||||
|
||||
THEN("The old one has the same properties than the new one")
|
||||
{
|
||||
REQUIRE(billboard.GetColor() == materialColor);
|
||||
REQUIRE(billboard.GetMaterial().Get() == materialRef.Get());
|
||||
REQUIRE(billboard.GetRotation() == Approx(0.f));
|
||||
REQUIRE(billboard.GetSize() == Nz::Vector2f(64.f, 64.f)); // Default sizes
|
||||
}
|
||||
|
||||
THEN("We set it with our new material and ask for its real size")
|
||||
{
|
||||
billboard.SetMaterial(materialRef, true);
|
||||
REQUIRE(billboard.GetSize() == Nz::Vector2f(765.f, 212.f)); // Nazara.png sizes
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
#include <Nazara/Graphics/ColorBackground.hpp>
|
||||
#include <Catch/catch.hpp>
|
||||
|
||||
SCENARIO("ColorBackground", "[GRAPHICS][COLORBACKGROUND]")
|
||||
{
|
||||
GIVEN("A default color background")
|
||||
{
|
||||
Nz::ColorBackground colorBackground;
|
||||
|
||||
WHEN("We assign it a color")
|
||||
{
|
||||
colorBackground.SetColor(Nz::Color::Red);
|
||||
|
||||
THEN("We can get it")
|
||||
{
|
||||
REQUIRE(colorBackground.GetColor() == Nz::Color::Red);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
#include <Nazara/Graphics/DeferredRenderTechnique.hpp>
|
||||
#include <Catch/catch.hpp>
|
||||
|
||||
SCENARIO("DeferredRenderTechnique", "[GRAPHICS][DEFERREDRENDERTECHNIQUE]")
|
||||
{
|
||||
GIVEN("A default deferred render technique")
|
||||
{
|
||||
Nz::DeferredRenderTechnique deferredRenderTechnique;
|
||||
|
||||
WHEN("We can disable a pass")
|
||||
{
|
||||
REQUIRE(deferredRenderTechnique.IsPassEnabled(Nz::RenderPassType::RenderPassType_AA, 0));
|
||||
deferredRenderTechnique.EnablePass(Nz::RenderPassType::RenderPassType_AA, 0, false);
|
||||
|
||||
THEN("It is disabled")
|
||||
{
|
||||
REQUIRE(!deferredRenderTechnique.IsPassEnabled(Nz::RenderPassType::RenderPassType_AA, 0));
|
||||
}
|
||||
|
||||
AND_THEN("We reset it, it is disabled and not the same as the old one")
|
||||
{
|
||||
Nz::DeferredRenderPass* oldPass = deferredRenderTechnique.GetPass(Nz::RenderPassType::RenderPassType_AA, 0);
|
||||
deferredRenderTechnique.ResetPass(Nz::RenderPassType::RenderPassType_AA, 0);
|
||||
REQUIRE(!deferredRenderTechnique.IsPassEnabled(Nz::RenderPassType::RenderPassType_AA, 0));
|
||||
REQUIRE(deferredRenderTechnique.GetPass(Nz::RenderPassType::RenderPassType_AA, 0) != oldPass);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
#include <Nazara/Graphics/Light.hpp>
|
||||
#include <Catch/catch.hpp>
|
||||
|
||||
SCENARIO("Light", "[GRAPHICS][LIGHT]")
|
||||
{
|
||||
GIVEN("Different light")
|
||||
{
|
||||
Nz::Light directionalLight(Nz::LightType_Directional);
|
||||
Nz::Light pointLight(Nz::LightType_Point);
|
||||
Nz::Light spotLight(Nz::LightType_Spot);
|
||||
|
||||
WHEN("We try to cull")
|
||||
{
|
||||
Nz::Frustumf frustum;
|
||||
frustum.Build(90.f, 16.f / 9.f, 1.f, 1000.f, Nz::Vector3f::Zero(), Nz::Vector3f::UnitX());
|
||||
Nz::Matrix4f Unit3InX = Nz::Matrix4f::Translate(Nz::Vector3f::UnitX() * 3.f);
|
||||
Nz::Matrix4f rotationTowardsY = Unit3InX * Nz::Matrix4f::Rotate(Nz::EulerAnglesf(Nz::FromDegrees(90.f), 0.f, 0.f).ToQuaternion());
|
||||
|
||||
THEN("These results are expected")
|
||||
{
|
||||
REQUIRE(directionalLight.Cull(frustum, Unit3InX));
|
||||
REQUIRE(pointLight.Cull(frustum, Unit3InX));
|
||||
REQUIRE(!spotLight.Cull(frustum, Unit3InX));
|
||||
|
||||
REQUIRE(directionalLight.Cull(frustum, rotationTowardsY));
|
||||
REQUIRE(pointLight.Cull(frustum, rotationTowardsY));
|
||||
REQUIRE(!spotLight.Cull(frustum, rotationTowardsY));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
#include <Nazara/Graphics/Model.hpp>
|
||||
#include <Catch/catch.hpp>
|
||||
|
||||
SCENARIO("Model", "[GRAPHICS][MODEL]")
|
||||
{
|
||||
GIVEN("The standford dragon model")
|
||||
{
|
||||
WHEN("We get general informations")
|
||||
{
|
||||
THEN("These results are expected")
|
||||
{
|
||||
Nz::ModelRef model = Nz::Model::New();
|
||||
REQUIRE(model->LoadFromFile("resources/Engine/Graphics/dragon_recon/dragon_vrip_res4.obj"));
|
||||
|
||||
REQUIRE(model->GetMaterialCount() == 2);
|
||||
REQUIRE(model->GetSkin() == 0);
|
||||
REQUIRE(model->GetSkinCount() == 1);
|
||||
|
||||
Nz::Material* material = model->GetMaterial(0);
|
||||
REQUIRE(material->GetAmbientColor() == Nz::Color(128));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
#include <Nazara/Graphics/ParticleDeclaration.hpp>
|
||||
#include <Catch/catch.hpp>
|
||||
|
||||
SCENARIO("ParticleDeclaration", "[GRAPHICS][PARTICLEDECLARATION]")
|
||||
{
|
||||
GIVEN("A particle declaration of a model")
|
||||
{
|
||||
Nz::ParticleDeclaration* particleDeclaration = Nz::ParticleDeclaration::Get(Nz::ParticleLayout_Model);
|
||||
|
||||
WHEN("We disable a component")
|
||||
{
|
||||
bool enabled;
|
||||
Nz::ComponentType type;
|
||||
unsigned int offset;
|
||||
particleDeclaration->GetComponent(Nz::ParticleComponent_Position, &enabled, &type, &offset);
|
||||
REQUIRE(enabled);
|
||||
unsigned int oldStride = particleDeclaration->GetStride();
|
||||
|
||||
particleDeclaration->DisableComponent(Nz::ParticleComponent_Position);
|
||||
REQUIRE(oldStride != particleDeclaration->GetStride());
|
||||
|
||||
THEN("We can enable it and the stride is back")
|
||||
{
|
||||
particleDeclaration->EnableComponent(Nz::ParticleComponent_Position, type, offset);
|
||||
REQUIRE(oldStride == particleDeclaration->GetStride());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
#include <Nazara/Graphics/ParticleSystem.hpp>
|
||||
#include <Catch/catch.hpp>
|
||||
|
||||
#include <Nazara/Core/SparsePtr.hpp>
|
||||
#include <Nazara/Graphics/ParticleMapper.hpp>
|
||||
|
||||
class TestParticleController : public Nz::ParticleController
|
||||
{
|
||||
public:
|
||||
// Be aware that the interval is [startId, endId] and NOT [startId, endId)
|
||||
void Apply(Nz::ParticleSystem& system, Nz::ParticleMapper& mapper, unsigned int startId, unsigned int endId, float elapsedTime) override
|
||||
{
|
||||
Nz::SparsePtr<Nz::Vector3f> positionPtr = mapper.GetComponentPtr<Nz::Vector3f>(Nz::ParticleComponent_Position);
|
||||
Nz::SparsePtr<Nz::Vector3f> velocityPtr = mapper.GetComponentPtr<Nz::Vector3f>(Nz::ParticleComponent_Velocity);
|
||||
Nz::SparsePtr<float> lifePtr = mapper.GetComponentPtr<float>(Nz::ParticleComponent_Life);
|
||||
|
||||
for (unsigned int i = startId; i <= endId; ++i)
|
||||
{
|
||||
Nz::Vector3f& particlePosition = positionPtr[i];
|
||||
Nz::Vector3f& particleVelocity = velocityPtr[i];
|
||||
float& particleLife = lifePtr[i];
|
||||
|
||||
particleLife -= elapsedTime;
|
||||
if (particleLife <= 0.f)
|
||||
system.KillParticle(i);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class TestParticleEmitter : public Nz::ParticleEmitter
|
||||
{
|
||||
public:
|
||||
~TestParticleEmitter() override = default;
|
||||
|
||||
void Emit(Nz::ParticleSystem& system, float elapsedTime) const override
|
||||
{
|
||||
system.GenerateParticles(GetEmissionCount());
|
||||
}
|
||||
|
||||
private:
|
||||
void SetupParticles(Nz::ParticleMapper& mapper, unsigned int count) const override
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class TestParticleGenerator : public Nz::ParticleGenerator
|
||||
{
|
||||
public:
|
||||
~TestParticleGenerator() override = default;
|
||||
|
||||
// Be aware that the interval is [startId, endId] and NOT [startId, endId)
|
||||
void Generate(Nz::ParticleSystem& system, Nz::ParticleMapper& mapper, unsigned int startId, unsigned int endId) override
|
||||
{
|
||||
Nz::SparsePtr<Nz::Vector3f> positionPtr = mapper.GetComponentPtr<Nz::Vector3f>(Nz::ParticleComponent_Position);
|
||||
Nz::SparsePtr<Nz::Vector3f> velocityPtr = mapper.GetComponentPtr<Nz::Vector3f>(Nz::ParticleComponent_Velocity);
|
||||
Nz::SparsePtr<float> lifePtr = mapper.GetComponentPtr<float>(Nz::ParticleComponent_Life);
|
||||
|
||||
for (unsigned int i = startId; i <= endId; ++i)
|
||||
{
|
||||
Nz::Vector3f& particlePosition = positionPtr[i];
|
||||
Nz::Vector3f& particleVelocity = velocityPtr[i];
|
||||
float& particleLife = lifePtr[i];
|
||||
|
||||
particlePosition = Nz::Vector3f::Zero();
|
||||
particleVelocity = Nz::Vector3f::UnitX();
|
||||
particleLife = 1.3f;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
SCENARIO("ParticleSystem", "[GRAPHICS][PARTICLESYSTEM]")
|
||||
{
|
||||
GIVEN("A particle system of maximum 10 billboards with its generators")
|
||||
{
|
||||
// These need to be alive longer than the particle system
|
||||
TestParticleController particleController;
|
||||
TestParticleGenerator particleGenerator;
|
||||
Nz::ParticleSystem particleSystem(10, Nz::ParticleLayout_Billboard);
|
||||
|
||||
particleSystem.AddController(&particleController);
|
||||
TestParticleEmitter particleEmitter;
|
||||
particleEmitter.SetEmissionCount(10);
|
||||
particleSystem.AddEmitter(&particleEmitter);
|
||||
|
||||
particleSystem.AddGenerator(&particleGenerator);
|
||||
|
||||
WHEN("We update to generate 10 particles")
|
||||
{
|
||||
particleSystem.Update(1.f);
|
||||
|
||||
THEN("There must be 10 particles")
|
||||
{
|
||||
REQUIRE(particleSystem.GetParticleCount() == 10);
|
||||
}
|
||||
|
||||
AND_THEN("We update to make them die")
|
||||
{
|
||||
particleSystem.Update(2.f);
|
||||
REQUIRE(particleSystem.GetParticleCount() == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
#include <Nazara/Graphics/RenderTechniques.hpp>
|
||||
#include <Catch/catch.hpp>
|
||||
|
||||
#include <Nazara/Graphics/AbstractRenderTechnique.hpp>
|
||||
#include <Nazara/Graphics/ForwardRenderTechnique.hpp>
|
||||
|
||||
SCENARIO("RenderTechniques", "[GRAPHICS][RENDERTECHNIQUES]")
|
||||
{
|
||||
GIVEN("Nothing")
|
||||
{
|
||||
WHEN("We try to get a technique")
|
||||
{
|
||||
THEN("We should get it")
|
||||
{
|
||||
std::unique_ptr<Nz::AbstractRenderTechnique> forwardByEnum(Nz::RenderTechniques::GetByEnum(Nz::RenderTechniqueType_BasicForward));
|
||||
REQUIRE(forwardByEnum->GetType() == Nz::RenderTechniqueType_BasicForward);
|
||||
|
||||
std::unique_ptr<Nz::AbstractRenderTechnique> forwardByIndex(Nz::RenderTechniques::GetByIndex(1));
|
||||
REQUIRE(forwardByIndex->GetType() == Nz::RenderTechniqueType_BasicForward);
|
||||
|
||||
std::unique_ptr<Nz::AbstractRenderTechnique> forwardByName(Nz::RenderTechniques::GetByName(Nz::RenderTechniques::ToString(Nz::RenderTechniqueType_BasicForward)));
|
||||
REQUIRE(forwardByName->GetType() == Nz::RenderTechniqueType_BasicForward);
|
||||
}
|
||||
|
||||
THEN("We can register a render technique")
|
||||
{
|
||||
unsigned int previousCount = Nz::RenderTechniques::GetCount();
|
||||
|
||||
Nz::RenderTechniques::Register("test", 23, []() -> Nz::AbstractRenderTechnique* {
|
||||
return new Nz::ForwardRenderTechnique;
|
||||
});
|
||||
|
||||
REQUIRE(previousCount < Nz::RenderTechniques::GetCount());
|
||||
|
||||
std::unique_ptr<Nz::AbstractRenderTechnique> forwardByRanking(Nz::RenderTechniques::GetByRanking(23));
|
||||
REQUIRE(forwardByRanking->GetType() == Nz::RenderTechniqueType_BasicForward);
|
||||
|
||||
std::unique_ptr<Nz::AbstractRenderTechnique> forwardByName(Nz::RenderTechniques::GetByName("test"));
|
||||
REQUIRE(forwardByName->GetType() == Nz::RenderTechniqueType_BasicForward);
|
||||
|
||||
Nz::RenderTechniques::Unregister("test");
|
||||
|
||||
REQUIRE(previousCount == Nz::RenderTechniques::GetCount());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
#include <Nazara/Graphics/SkeletalModel.hpp>
|
||||
#include <Catch/catch.hpp>
|
||||
|
||||
SCENARIO("SkeletalModel", "[GRAPHICS][SKELETALMODEL]")
|
||||
{
|
||||
GIVEN("A default skeletal model")
|
||||
{
|
||||
Nz::SkeletalModel skeletalModel;
|
||||
Nz::AnimationRef animation = Nz::Animation::New();
|
||||
|
||||
WHEN("We can load the bob lamp")
|
||||
{
|
||||
REQUIRE(skeletalModel.LoadFromFile("resources/Engine/Graphics/Bob lamp/bob_lamp_update.md5mesh"));
|
||||
REQUIRE(animation->LoadFromFile("resources/Engine/Graphics/Bob lamp/bob_lamp_update.md5anim"));
|
||||
skeletalModel.SetAnimation(animation);
|
||||
|
||||
THEN("We can enable its animation")
|
||||
{
|
||||
REQUIRE(skeletalModel.HasAnimation());
|
||||
skeletalModel.EnableAnimation(true);
|
||||
skeletalModel.AdvanceAnimation(0.10f);
|
||||
REQUIRE(skeletalModel.IsAnimationEnabled());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
#include <Nazara/Graphics/SkyboxBackground.hpp>
|
||||
#include <Catch/catch.hpp>
|
||||
|
||||
SCENARIO("SkyboxBackground", "[GRAPHICS][SKYBOXBACKGROUND]")
|
||||
{
|
||||
GIVEN("A skybox background with a loaded image")
|
||||
{
|
||||
Nz::TextureRef textureRef = Nz::Texture::New();
|
||||
textureRef->LoadCubemapFromFile("resources/Engine/Graphics/skybox.png");
|
||||
Nz::SkyboxBackgroundRef skyboxBackgroundRef = Nz::SkyboxBackground::New(textureRef);
|
||||
|
||||
WHEN("We assign it parameters")
|
||||
{
|
||||
skyboxBackgroundRef->SetMovementOffset(Nz::Vector3f::Unit());
|
||||
skyboxBackgroundRef->SetMovementScale(1.f);
|
||||
|
||||
THEN("We can get it")
|
||||
{
|
||||
REQUIRE(skyboxBackgroundRef->GetMovementOffset() == Nz::Vector3f::Unit());
|
||||
REQUIRE(skyboxBackgroundRef->GetMovementScale() == Approx(1.f));
|
||||
REQUIRE(skyboxBackgroundRef->GetTexture().Get() == textureRef.Get());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
#include <Nazara/Graphics/TextureBackground.hpp>
|
||||
#include <Catch/catch.hpp>
|
||||
|
||||
SCENARIO("TextureBackground", "[GRAPHICS][TEXTUREBACKGROUND]")
|
||||
{
|
||||
GIVEN("A default texture background")
|
||||
{
|
||||
Nz::TextureRef textureRef = Nz::Texture::New();
|
||||
textureRef->LoadFromFile("resources/Engine/Graphics/skybox.png");
|
||||
Nz::TextureBackgroundRef textureBackgroundRef = Nz::TextureBackground::New(textureRef);
|
||||
|
||||
WHEN("We assign it parameters")
|
||||
{
|
||||
THEN("We can get it")
|
||||
{
|
||||
REQUIRE(textureBackgroundRef->GetTexture().Get() == textureRef.Get());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -39,14 +39,14 @@ SCENARIO("Sphere", "[MATH][SPHERE]")
|
|||
|
||||
WHEN("We ask for distance")
|
||||
{
|
||||
THEN("These results are expected")
|
||||
THEN("These results are expected because we don't take into account the border")
|
||||
{
|
||||
REQUIRE(firstCenterAndUnit.Distance(Nz::Vector3f::UnitX()) == Approx(1.f));
|
||||
REQUIRE(firstCenterAndUnit.SquaredDistance(Nz::Vector3f::UnitX()) == Approx(1.f));
|
||||
REQUIRE(firstCenterAndUnit.Distance(Nz::Vector3f::UnitX() * 2.f) == Approx(1.f));
|
||||
REQUIRE(firstCenterAndUnit.SquaredDistance(Nz::Vector3f::UnitX() * 2.f) == Approx(1.f));
|
||||
|
||||
Nz::Spheref tmp(Nz::Vector3f::UnitX(), 1.f);
|
||||
REQUIRE(tmp.Distance(Nz::Vector3f::UnitX() * 4.f) == Approx(3.f));
|
||||
REQUIRE(tmp.SquaredDistance(Nz::Vector3f::UnitX() * 4.f) == Approx(9.f));
|
||||
REQUIRE(tmp.Distance(Nz::Vector3f::UnitX() * 4.f) == Approx(2.f));
|
||||
REQUIRE(tmp.SquaredDistance(Nz::Vector3f::UnitX() * 4.f) == Approx(4.f));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -84,7 +84,7 @@ SCENARIO("Sphere", "[MATH][SPHERE]")
|
|||
THEN("Sphere must contain it and distance should be good")
|
||||
{
|
||||
CHECK(firstCenterAndUnit.Contains(point));
|
||||
REQUIRE(firstCenterAndUnit.Distance(point) == 2.f);
|
||||
REQUIRE(firstCenterAndUnit.Distance(point) == 1.f);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,2 +1,16 @@
|
|||
#define CATCH_CONFIG_MAIN
|
||||
#define CATCH_CONFIG_RUNNER
|
||||
#include <Catch/catch.hpp>
|
||||
|
||||
#include <Nazara/Audio/Audio.hpp>
|
||||
#include <Nazara/Core/Core.hpp>
|
||||
#include <Nazara/Graphics/Graphics.hpp>
|
||||
#include <Nazara/Network/Network.hpp>
|
||||
|
||||
int main(int argc, char* const argv[])
|
||||
{
|
||||
Nz::Initializer<Nz::Audio, Nz::Core, Nz::Graphics, Nz::Network> modules;
|
||||
|
||||
int result = Catch::Session().run(argc, argv);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
#############################
|
||||
MD5 sample mesh and animation
|
||||
#############################
|
||||
|
||||
INFORMATION & USAGE
|
||||
===================
|
||||
File includes *.blend source files and TGA format textures for MD5 animated mesh testing.
|
||||
For extensive information and usage instructions visit http://www.katsbits.com/smforum/index.php?topic=178.0
|
||||
|
||||
- bob_lamp_update.blend contain mesh and armature as would be prior to preparation for export.
|
||||
- bob_lamp_update_export contains triangulated mesh ready for export.
|
||||
|
||||
NOTES
|
||||
=====
|
||||
Included files are for use in **Blender 2.69** or above; opening files in older versions may result in errors dues to internal differences between Blender versions.
|
||||
Files and media are provided "as is" without any warranties of functionality.
|
||||
|
||||
COPYRIGHT & DISTRIBUTION
|
||||
========================
|
||||
Copyright © 2014 KatsBits. All Rights Reserved.
|
||||
For more information visit http://www.katsbits.com/ or email info@katsbits.com
|
||||
|
||||
For NON-COMMERCIAL USE ONLY. This file and/or its contents and/or associated materials may not be reproduced, duplicated, distributed or otherwise 'monetised' without prior consent.
|
||||
Contact info@katsbits.com or visit http://copyright.katsbits.com/ for further details regarding this material and/or distribution/copyright.
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
skybox.png
|
||||
|
||||
https://commons.wikimedia.org/wiki/File:Skybox_example.png
|
||||
|
||||
Original file:
|
||||
Skybox example.ogg (Ogg Vorbis sound file, length 1 min 3 s, 378 kbps)
|
||||
|
||||
Summary:
|
||||
|
||||
Description: English: An example of a skybox and how the faces can be aligned
|
||||
Date: 8 June 2011
|
||||
Source: Own work
|
||||
Author: Creator:Arieee
|
||||
|
||||
Description: The Belgian national anthem (instrumental version) performed by the United States Navy Band. Direct link is at http://www.navyband.navy.mil/anthems/ANTHEMS/Belgium.mp3.
|
||||
Date: 19 October 2004
|
||||
Source: http://www.navyband.navy.mil/anthems/national_anthems.htm
|
||||
Author: United States Navy Band (rendition), uploaded to Wikimedia by Keith Lehwald
|
||||
|
||||
Licencing:
|
||||
|
||||
This file is licensed under the Creative Commons Attribution-Share Alike 3.0 Unported license.
|
||||
|
||||
You are free:
|
||||
|
||||
to share – to copy, distribute and transmit the work
|
||||
to remix – to adapt the work
|
||||
|
||||
Under the following conditions:
|
||||
|
||||
attribution – You must attribute the work in the manner specified by the author or licensor (but not in any way that suggests that they endorse you or your use of the work).
|
||||
share alike – If you alter, transform, or build upon this work, you may distribute the resulting work only under the same or similar license to this one.
|
||||
|
||||
-------------------------------------------------------------------------------------------------
|
||||
|
||||
Bob lamp
|
||||
|
||||
http://www.katsbits.com/download/models/md5-example.php
|
||||
|
||||
Original file:
|
||||
bob_lamp_update.zip (Animated MD5 sample file)
|
||||
|
||||
Summary:
|
||||
|
||||
Description: Updated version of "Bob", a low-poly character mesh for general export and testing of MD5 mesh and animation - "*.md5mesh" and "*.md5anim". File and it's contents should be opened in Blender 2.69 or above to avoid compatibility issues with older versions of Blender and/or resulting MD5 exports (md5mesh & md5anim).
|
||||
|
||||
File includes two versions of the source file, one 'working' - mesh is intact with surfaces in 'quad' form; and one 'prepped' (exported) - mesh has been tessilated (triangulated) for export.
|
||||
Date: Januari 2014
|
||||
Source: http://www.katsbits.com/download/models/md5-example.php
|
||||
Author: KatsBits
|
||||
|
||||
Licencing:
|
||||
|
||||
Please, refer to "Bob lamp/Readme.txt" file.
|
||||
|
||||
-------------------------------------------------------------------------------------------------
|
||||
|
||||
Standford dragon
|
||||
|
||||
http://graphics.stanford.edu/data/3Dscanrep/
|
||||
|
||||
Original file:
|
||||
dragon_recon.tar.gz (PLY files)
|
||||
|
||||
Summary:
|
||||
|
||||
Dragon
|
||||
Source: Stanford University Computer Graphics Laboratory
|
||||
Scanner: Cyberware 3030 MS + spacetime analysis
|
||||
Number of scans: ~70
|
||||
Total size of scans: 2,748,318 points (about 5,500,000 triangles)
|
||||
Reconstruction: vrip (conservatively decimated)
|
||||
Size of reconstruction: 566,098 vertices, 1,132,830 triangles
|
||||
Comments: contains numerous small holes
|
||||
Date: 1996
|
||||
Source: http://graphics.stanford.edu/data/3Dscanrep/
|
||||
Author: Stanford University Computer Graphics Laboratory
|
||||
|
||||
Licencing:
|
||||
|
||||
Please be sure to acknowledge the source of the data and models you take from this repository. In each of the listings below, we have cited the source of the range data and reconstructed models. You are welcome to use the data and models for research purposes. You are also welcome to mirror or redistribute them for free. Finally, you may publish images made using these models, or the images on this web site, in a scholarly article or book - as long as credit is given to the Stanford Computer Graphics Laboratory. However, such models or images are not to be used for commercial purposes, nor should they appear in a product for sale (with the exception of scholarly journals or books), without our permission.
|
||||
Please, refer to "dragon_recon/README" file.
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
Surface Reconstructions
|
||||
|
||||
Stanford Range Repository
|
||||
Computer Graphics Laboratory
|
||||
Stanford University
|
||||
|
||||
August 4, 1996
|
||||
|
||||
|
||||
These files are the result of reconstructing a set of range images
|
||||
using the "vrip" program. The first file is the high resolution
|
||||
result, while the "_res*" files are decimated versions. Note that
|
||||
these decimations were performed using a crude algorithm that does not
|
||||
necessarily preserve mesh topology. While they are not beautiful,
|
||||
they are suitable for interactive rendering.
|
||||
|
||||
Note that this model is a decimated version of the original which was
|
||||
constructed at the voxel resolution of 0.35 mm. The original model
|
||||
has no holes in it, however, the decimated model has some holes that
|
||||
we detected with software, but not by inspection. Apparently, the
|
||||
decimation software introduced these holes.
|
||||
|
||||
For more information, consult the web pages of the Stanford Graphics
|
||||
Laboratory:
|
||||
|
||||
http://www-graphics.stanford.edu
|
||||
|
||||
Loading…
Reference in New Issue