Merge remote-tracking branch 'origin/Particle-Update'

Conflicts:
	include/Nazara/Graphics/Enums.hpp
	include/Nazara/Graphics/ForwardRenderQueue.hpp
	include/Nazara/Graphics/ForwardRenderTechnique.hpp
	include/Nazara/Graphics/Sprite.hpp
	src/Nazara/Graphics/DeferredRenderQueue.cpp
	src/Nazara/Graphics/ForwardRenderQueue.cpp
	src/Nazara/Graphics/ForwardRenderTechnique.cpp
	src/Nazara/Graphics/Material.cpp
	src/Nazara/Graphics/Resources/Shaders/Basic/core.frag.h
	src/Nazara/Graphics/Resources/Shaders/Basic/core.vert
	src/Nazara/Graphics/Resources/Shaders/Basic/core.vert.h
	src/Nazara/Graphics/Resources/Shaders/PhongLighting/core.frag
	src/Nazara/Graphics/Resources/Shaders/PhongLighting/core.frag.h
	src/Nazara/Graphics/Resources/Shaders/PhongLighting/core.vert
	src/Nazara/Graphics/Resources/Shaders/PhongLighting/core.vert.h
	src/Nazara/Graphics/Sprite.cpp

Former-commit-id: 73139ce47d7721635d87c74b2ca1183c2f67c090
This commit is contained in:
Lynix 2015-01-19 02:20:28 +01:00
commit ead44173ba
41 changed files with 1958 additions and 146 deletions

View File

@ -8,7 +8,9 @@
#define NAZARA_ABSTRACTRENDERQUEUE_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/Color.hpp>
#include <Nazara/Core/NonCopyable.hpp>
#include <Nazara/Core/SparsePtr.hpp>
#include <Nazara/Math/Box.hpp>
#include <Nazara/Math/Matrix4.hpp>
#include <Nazara/Utility/Enums.hpp>
@ -27,6 +29,8 @@ class NAZARA_API NzAbstractRenderQueue : NzNonCopyable
NzAbstractRenderQueue() = default;
virtual ~NzAbstractRenderQueue();
virtual void AddBillboard(const NzMaterial* material, const NzVector3f& position, const NzVector2f& size, const NzVector2f& sinCos = NzVector2f(0.f, 1.f), const NzColor& color = NzColor::White) = 0;
virtual void AddBillboards(const NzMaterial* material, unsigned int count, NzSparsePtr<const NzVector3f> positionPtr, NzSparsePtr<const NzVector2f> sizePtr, NzSparsePtr<const NzVector2f> sinCosPtr = nullptr, NzSparsePtr<const NzColor> colorPtr = nullptr) = 0;
virtual void AddDrawable(const NzDrawable* drawable) = 0;
virtual void AddLight(const NzLight* light) = 0;
virtual void AddMesh(const NzMaterial* material, const NzMeshData& meshData, const NzBoxf& meshAABB, const NzMatrix4f& transformMatrix) = 0;

View File

@ -28,6 +28,8 @@ class NAZARA_API NzDeferredRenderQueue : public NzAbstractRenderQueue, NzResourc
NzDeferredRenderQueue(NzForwardRenderQueue* forwardQueue);
~NzDeferredRenderQueue() = default;
void AddBillboard(const NzMaterial* material, const NzVector3f& position, const NzVector2f& size, const NzVector2f& sinCos = NzVector2f(0.f, 1.f), const NzColor& color = NzColor::White) override;
void AddBillboards(const NzMaterial* material, unsigned int count, NzSparsePtr<const NzVector3f> positionPtr, NzSparsePtr<const NzVector2f> sizePtr, NzSparsePtr<const NzVector2f> sinCosPtr = nullptr, NzSparsePtr<const NzColor> colorPtr = nullptr) override;
void AddDrawable(const NzDrawable* drawable) override;
void AddLight(const NzLight* light) override;
void AddMesh(const NzMaterial* material, const NzMeshData& meshData, const NzBoxf& meshAABB, const NzMatrix4f& transformMatrix) override;
@ -42,7 +44,7 @@ class NAZARA_API NzDeferredRenderQueue : public NzAbstractRenderQueue, NzResourc
struct MeshInstanceEntry
{
MeshInstanceEntry(NzDeferredRenderQueue* listener, int indexBufferValue, int vertexBufferValue) :
MeshInstanceEntry(NzResourceListener* listener, int indexBufferValue, int vertexBufferValue) :
indexBufferListener(listener, indexBufferValue),
vertexBufferListener(listener, vertexBufferValue)
{
@ -62,7 +64,7 @@ class NAZARA_API NzDeferredRenderQueue : public NzAbstractRenderQueue, NzResourc
struct BatchedModelEntry
{
BatchedModelEntry(NzDeferredRenderQueue* listener, int materialValue) :
BatchedModelEntry(NzResourceListener* listener, int materialValue) :
materialListener(listener, materialValue)
{
}

View File

@ -43,6 +43,41 @@ enum nzMaterialUniform
nzMaterialUniform_Max = nzMaterialUniform_SpecularMap
};
enum nzParticleComponent
{
nzParticleComponent_Unused = -1,
nzParticleComponent_Color,
nzParticleComponent_Life,
nzParticleComponent_Mass,
nzParticleComponent_Normal,
nzParticleComponent_Position,
nzParticleComponent_Radius,
nzParticleComponent_Rotation,
nzParticleComponent_Size,
nzParticleComponent_Velocity,
nzParticleComponent_Userdata0,
nzParticleComponent_Userdata1,
nzParticleComponent_Userdata2,
nzParticleComponent_Userdata3,
nzParticleComponent_Userdata4,
nzParticleComponent_Userdata5,
nzParticleComponent_Userdata6,
nzParticleComponent_Userdata7,
nzParticleComponent_Userdata8,
nzParticleComponent_Max = nzParticleComponent_Userdata8
};
enum nzParticleLayout
{
nzParticleLayout_Billboard,
nzParticleLayout_Model,
nzParticleLayout_Sprite,
nzParticleLayout_Max = nzParticleLayout_Sprite
};
enum nzRenderPassType
{
nzRenderPassType_AA,
@ -71,11 +106,12 @@ enum nzRenderTechniqueType
enum nzSceneNodeType
{
nzSceneNodeType_Light, // NzLight
nzSceneNodeType_Model, // NzModel
nzSceneNodeType_Root, // NzSceneRoot
nzSceneNodeType_Sprite, // NzSprite
nzSceneNodeType_TextSprite, // NzTextSprite
nzSceneNodeType_Light, // NzLight
nzSceneNodeType_Model, // NzModel
nzSceneNodeType_ParticleEmitter, // NzParticleEmitter
nzSceneNodeType_Root, // NzSceneRoot
nzSceneNodeType_Sprite, // NzSprite
nzSceneNodeType_TextSprite, // NzTextSprite
nzSceneNodeType_User,
nzSceneNodeType_Max = nzSceneNodeType_User
@ -86,10 +122,11 @@ enum nzShaderFlags
{
nzShaderFlags_None = 0,
nzShaderFlags_Deferred = 0x1,
nzShaderFlags_Instancing = 0x2,
nzShaderFlags_TextureOverlay = 0x4,
nzShaderFlags_VertexColor = 0x8,
nzShaderFlags_Billboard = 0x01,
nzShaderFlags_Deferred = 0x02,
nzShaderFlags_Instancing = 0x04,
nzShaderFlags_TextureOverlay = 0x08,
nzShaderFlags_VertexColor = 0x10,
nzShaderFlags_Max = nzShaderFlags_VertexColor*2-1
};

View File

@ -30,6 +30,8 @@ class NAZARA_API NzForwardRenderQueue : public NzAbstractRenderQueue, NzResource
NzForwardRenderQueue() = default;
~NzForwardRenderQueue() = default;
void AddBillboard(const NzMaterial* material, const NzVector3f& position, const NzVector2f& size, const NzVector2f& sinCos = NzVector2f(0.f, 1.f), const NzColor& color = NzColor::White) override;
void AddBillboards(const NzMaterial* material, unsigned int count, NzSparsePtr<const NzVector3f> positionPtr, NzSparsePtr<const NzVector2f> sizePtr, NzSparsePtr<const NzVector2f> sinCosPtr = nullptr, NzSparsePtr<const NzColor> colorPtr = nullptr) override;
void AddDrawable(const NzDrawable* drawable) override;
void AddLight(const NzLight* light) override;
void AddMesh(const NzMaterial* material, const NzMeshData& meshData, const NzBoxf& meshAABB, const NzMatrix4f& transformMatrix) override;
@ -43,6 +45,34 @@ class NAZARA_API NzForwardRenderQueue : public NzAbstractRenderQueue, NzResource
bool OnResourceDestroy(const NzResource* resource, int index) override;
void OnResourceReleased(const NzResource* resource, int index) override;
/// Billboards
struct BillboardData
{
NzColor color;
NzVector3f center;
NzVector2f size;
NzVector2f sinCos;
};
struct BatchedBillboardComparator
{
bool operator()(const NzMaterial* mat1, const NzMaterial* mat2);
};
struct BatchedBillboardEntry
{
BatchedBillboardEntry(NzResourceListener* listener, int materialValue) :
materialListener(listener, materialValue)
{
}
NzMaterialConstListener materialListener;
std::vector<BillboardData> billboards;
};
typedef std::map<const NzMaterial*, BatchedBillboardEntry, BatchedBillboardComparator> BatchedBillboardContainer;
/// Sprites
struct SpriteChain_XYZ_Color_UV
{
const NzVertexStruct_XYZ_Color_UV* vertices;
@ -51,7 +81,7 @@ class NAZARA_API NzForwardRenderQueue : public NzAbstractRenderQueue, NzResource
struct BatchedSpriteEntry
{
BatchedSpriteEntry(NzForwardRenderQueue* listener, int textureValue) :
BatchedSpriteEntry(NzResourceListener* listener, int textureValue) :
textureListener(listener, textureValue)
{
}
@ -69,7 +99,7 @@ class NAZARA_API NzForwardRenderQueue : public NzAbstractRenderQueue, NzResource
struct BatchedBasicSpriteEntry
{
BatchedBasicSpriteEntry(NzForwardRenderQueue* listener, int materialValue) :
BatchedBasicSpriteEntry(NzResourceListener* listener, int materialValue) :
materialListener(listener, materialValue)
{
}
@ -81,6 +111,7 @@ class NAZARA_API NzForwardRenderQueue : public NzAbstractRenderQueue, NzResource
typedef std::map<const NzMaterial*, BatchedBasicSpriteEntry> BasicSpriteBatches;
/// Meshes
struct MeshDataComparator
{
bool operator()(const NzMeshData& data1, const NzMeshData& data2);
@ -88,7 +119,7 @@ class NAZARA_API NzForwardRenderQueue : public NzAbstractRenderQueue, NzResource
struct MeshInstanceEntry
{
MeshInstanceEntry(NzForwardRenderQueue* listener, int indexBufferValue, int vertexBufferValue) :
MeshInstanceEntry(NzResourceListener* listener, int indexBufferValue, int vertexBufferValue) :
indexBufferListener(listener, indexBufferValue),
vertexBufferListener(listener, vertexBufferValue)
{
@ -109,7 +140,7 @@ class NAZARA_API NzForwardRenderQueue : public NzAbstractRenderQueue, NzResource
struct BatchedModelEntry
{
BatchedModelEntry(NzForwardRenderQueue* listener, int materialValue) :
BatchedModelEntry(NzResourceListener* listener, int materialValue) :
materialListener(listener, materialValue)
{
}
@ -133,6 +164,7 @@ class NAZARA_API NzForwardRenderQueue : public NzAbstractRenderQueue, NzResource
typedef std::vector<const NzLight*> LightContainer;
typedef std::vector<unsigned int> TransparentModelContainer;
BatchedBillboardContainer billboards;
BasicSpriteBatches basicSprites;
ModelBatches opaqueModels;
TransparentModelContainer transparentModels;

View File

@ -20,7 +20,7 @@ class NAZARA_API NzForwardRenderTechnique : public NzAbstractRenderTechnique, Nz
{
public:
NzForwardRenderTechnique();
~NzForwardRenderTechnique();
~NzForwardRenderTechnique() = default;
void Clear(const NzScene* scene) const;
bool Draw(const NzScene* scene) const;
@ -31,10 +31,14 @@ class NAZARA_API NzForwardRenderTechnique : public NzAbstractRenderTechnique, Nz
void SetMaxLightPassPerObject(unsigned int passCount);
static bool Initialize();
static void Uninitialize();
private:
struct ShaderUniforms;
void DrawBasicSprites(const NzScene* scene) const;
void DrawBillboards(const NzScene* scene) const;
void DrawOpaqueModels(const NzScene* scene) const;
void DrawTransparentModels(const NzScene* scene) const;
const ShaderUniforms* GetShaderUniforms(const NzShader* shader) const;
@ -55,12 +59,18 @@ class NAZARA_API NzForwardRenderTechnique : public NzAbstractRenderTechnique, Nz
};
mutable std::unordered_map<const NzShader*, ShaderUniforms> m_shaderUniforms;
NzBuffer m_vertexBuffer;
mutable NzForwardRenderQueue m_renderQueue;
NzIndexBufferRef m_indexBuffer;
mutable NzLightManager m_directionalLights;
mutable NzLightManager m_lights;
NzVertexBuffer m_billboardPointBuffer;
NzVertexBuffer m_spriteBuffer;
unsigned int m_maxLightPassPerObject;
static NzIndexBuffer s_quadIndexBuffer;
static NzVertexBuffer s_quadVertexBuffer;
static NzVertexDeclaration s_billboardInstanceDeclaration;
static NzVertexDeclaration s_billboardVertexDeclaration;
};
#endif // NAZARA_FORWARDRENDERTECHNIQUE_HPP

View File

@ -0,0 +1,34 @@
// Copyright (C) 2014 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_PARTICLECONTROLLER_HPP
#define NAZARA_PARTICLECONTROLLER_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/Resource.hpp>
#include <Nazara/Core/ResourceListenerWrapper.hpp>
#include <Nazara/Core/ResourceRef.hpp>
class NzParticleController;
class NzParticleMapper;
class NzParticleSystem;
using NzParticleControllerConstListener = NzResourceListenerWrapper<const NzParticleController>;
using NzParticleControllerConstRef = NzResourceRef<const NzParticleController>;
using NzParticleControllerListener = NzResourceListenerWrapper<NzParticleController>;
using NzParticleControllerRef = NzResourceRef<NzParticleController>;
class NAZARA_API NzParticleController : public NzResource
{
public:
NzParticleController() = default;
NzParticleController(const NzParticleController& controller);
virtual ~NzParticleController();
virtual void Apply(NzParticleSystem& system, NzParticleMapper& mapper, unsigned int startId, unsigned int endId, float elapsedTime) = 0;
};
#endif // NAZARA_PARTICLECONTROLLER_HPP

View File

@ -0,0 +1,70 @@
// Copyright (C) 2014 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_PARTICLEDECLARATION_HPP
#define NAZARA_PARTICLEDECLARATION_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/Resource.hpp>
#include <Nazara/Core/ResourceListenerWrapper.hpp>
#include <Nazara/Core/ResourceRef.hpp>
#include <Nazara/Graphics/Enums.hpp>
#include <Nazara/Utility/Enums.hpp>
class NzParticleDeclaration;
using NzParticleDeclarationConstListener = NzResourceListenerWrapper<const NzParticleDeclaration>;
using NzParticleDeclarationConstRef = NzResourceRef<const NzParticleDeclaration>;
using NzParticleDeclarationListener = NzResourceListenerWrapper<NzParticleDeclaration>;
using NzParticleDeclarationRef = NzResourceRef<NzParticleDeclaration>;
class NAZARA_API NzParticleDeclaration : public NzResource
{
friend class NzGraphics;
public:
NzParticleDeclaration();
NzParticleDeclaration(const NzParticleDeclaration& declaration);
~NzParticleDeclaration();
void DisableComponent(nzParticleComponent component);
void EnableComponent(nzParticleComponent component, nzComponentType type, unsigned int offset);
void GetComponent(nzParticleComponent component, bool* enabled, nzComponentType* type, unsigned int* offset) const;
unsigned int GetStride() const;
void SetStride(unsigned int stride);
NzParticleDeclaration& operator=(const NzParticleDeclaration& declaration);
static NzParticleDeclaration* Get(nzParticleLayout layout);
static bool IsTypeSupported(nzComponentType type);
private:
static bool Initialize();
static void Uninitialize();
struct Component
{
nzComponentType type;
bool enabled = false;
unsigned int offset;
/*
** -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 !
*/
};
Component m_components[nzParticleComponent_Max+1];
unsigned int m_stride;
static NzParticleDeclaration s_declarations[nzParticleLayout_Max+1];
};
#endif // NAZARA_PARTICLEDECLARATION_HPP

View File

@ -0,0 +1,43 @@
// Copyright (C) 2014 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_PARTICLEEMITTER_HPP
#define NAZARA_PARTICLEEMITTER_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Utility/Node.hpp>
class NzParticleMapper;
class NzParticleSystem;
class NAZARA_API NzParticleEmitter : public NzNode
{
public:
NzParticleEmitter();
NzParticleEmitter(const NzParticleEmitter& emitter) = default;
NzParticleEmitter(NzParticleEmitter&& emitter) = default;
virtual ~NzParticleEmitter();
virtual void Emit(NzParticleSystem& system, float elapsedTime) const;
unsigned int GetEmissionCount() const;
float GetEmissionRate() const;
void SetEmissionCount(unsigned int count);
void SetEmissionRate(float rate);
NzParticleEmitter& operator=(const NzParticleEmitter& emitter) = default;
NzParticleEmitter& operator=(NzParticleEmitter&& emitter) = default;
private:
virtual void SetupParticles(NzParticleMapper& mapper, unsigned int count) const = 0;
mutable float m_emissionAccumulator;
float m_emissionRate;
unsigned int m_emissionCount;
};
#endif // NAZARA_PARTICLEEMITTER_HPP

View File

@ -0,0 +1,34 @@
// Copyright (C) 2014 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_PARTICLEGENERATOR_HPP
#define NAZARA_PARTICLEGENERATOR_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/Resource.hpp>
#include <Nazara/Core/ResourceListenerWrapper.hpp>
#include <Nazara/Core/ResourceRef.hpp>
class NzParticleGenerator;
class NzParticleMapper;
class NzParticleSystem;
using NzParticleGeneratorConstListener = NzResourceListenerWrapper<const NzParticleGenerator>;
using NzParticleGeneratorConstRef = NzResourceRef<const NzParticleGenerator>;
using NzParticleGeneratorListener = NzResourceListenerWrapper<NzParticleGenerator>;
using NzParticleGeneratorRef = NzResourceRef<NzParticleGenerator>;
class NAZARA_API NzParticleGenerator : public NzResource
{
public:
NzParticleGenerator() = default;
NzParticleGenerator(const NzParticleGenerator& generator);
virtual ~NzParticleGenerator();
virtual void Generate(NzParticleSystem& system, NzParticleMapper& mapper, unsigned int startId, unsigned int endId) = 0;
};
#endif // NAZARA_PARTICLEGENERATOR_HPP

View File

@ -0,0 +1,31 @@
// Copyright (C) 2014 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_PARTICLEMAPPER_HPP
#define NAZARA_PARTICLEMAPPER_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/SparsePtr.hpp>
#include <Nazara/Graphics/Enums.hpp>
#include <Nazara/Graphics/ParticleDeclaration.hpp>
class NAZARA_API NzParticleMapper
{
public:
NzParticleMapper(void* buffer, const NzParticleDeclaration* declaration);
~NzParticleMapper();
template<typename T> NzSparsePtr<T> GetComponentPtr(nzParticleComponent component);
template<typename T> NzSparsePtr<const T> GetComponentPtr(nzParticleComponent component) const;
private:
const NzParticleDeclaration* m_declaration;
nzUInt8* m_ptr;
};
#include <Nazara/Graphics/ParticleMapper.inl>
#endif // NAZARA_PARTICLEMAPPER_HPP

View File

@ -0,0 +1,50 @@
// Copyright (C) 2014 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/Error.hpp>
#include <Nazara/Graphics/Debug.hpp>
template <typename T>
NzSparsePtr<T> NzParticleMapper::GetComponentPtr(nzParticleComponent component)
{
// Ensuite le composant qui nous intéresse
bool enabled;
nzComponentType type;
unsigned int offset;
m_declaration->GetComponent(component, &enabled, &type, &offset);
if (enabled)
{
///TODO: Vérifier le rapport entre le type de l'attribut et le type template ?
return NzSparsePtr<T>(m_ptr + offset, m_declaration->GetStride());
}
else
{
NazaraError("Attribute 0x" + NzString::Number(component, 16) + " is not enabled");
return NzSparsePtr<T>();
}
}
template <typename T>
NzSparsePtr<const T> NzParticleMapper::GetComponentPtr(nzParticleComponent component) const
{
// Ensuite le composant qui nous intéresse
bool enabled;
nzComponentType type;
unsigned int offset;
m_declaration->GetComponent(component, &enabled, &type, &offset);
if (enabled)
{
///TODO: Vérifier le rapport entre le type de l'attribut et le type template ?
return NzSparsePtr<const T>(m_ptr + offset, m_declaration->GetStride());
}
else
{
NazaraError("Attribute 0x" + NzString::Number(component, 16) + " is not enabled");
return NzSparsePtr<const T>();
}
}
#include <Nazara/Graphics/DebugOff.hpp>

View File

@ -0,0 +1,35 @@
// Copyright (C) 2014 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_PARTICLERENDERER_HPP
#define NAZARA_PARTICLERENDERER_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/Resource.hpp>
#include <Nazara/Core/ResourceListenerWrapper.hpp>
#include <Nazara/Core/ResourceRef.hpp>
class NzAbstractRenderQueue;
class NzParticleMapper;
class NzParticleRenderer;
class NzParticleSystem;
using NzParticleRendererConstListener = NzResourceListenerWrapper<const NzParticleRenderer>;
using NzParticleRendererConstRef = NzResourceRef<const NzParticleRenderer>;
using NzParticleRendererListener = NzResourceListenerWrapper<NzParticleRenderer>;
using NzParticleRendererRef = NzResourceRef<NzParticleRenderer>;
class NAZARA_API NzParticleRenderer : public NzResource
{
public:
NzParticleRenderer() = default;
NzParticleRenderer(const NzParticleRenderer& renderer);
virtual ~NzParticleRenderer();
virtual void Render(const NzParticleSystem& system, const NzParticleMapper& mapper, unsigned int startId, unsigned int endId, NzAbstractRenderQueue* renderQueue) = 0;
};
#endif // NAZARA_PARTICLERENDERER_HPP

View File

@ -0,0 +1,42 @@
// Copyright (C) 2014 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_PARTICLESTRUCT_HPP
#define NAZARA_PARTICLESTRUCT_HPP
#include <Nazara/Core/Color.hpp>
#include <Nazara/Math/Quaternion.hpp>
#include <Nazara/Math/Vector2.hpp>
#include <Nazara/Math/Vector3.hpp>
struct NzParticleStruct_Billboard
{
NzColor color;
NzVector3f normal;
NzVector3f position;
NzVector3f velocity;
nzUInt32 life;
float rotation;
};
struct NzParticleStruct_Model
{
NzVector3f position;
NzVector3f velocity;
nzUInt32 life;
NzQuaternionf rotation;
};
struct NzParticleStruct_Sprite
{
NzColor color;
NzVector2f position;
NzVector2f velocity;
nzUInt32 life;
float rotation;
};
#endif // NAZARA_PARTICLESTRUCT_HPP

View File

@ -0,0 +1,93 @@
// Copyright (C) 2014 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_PARTICLESYSTEM_HPP
#define NAZARA_PARTICLESYSTEM_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/Updatable.hpp>
#include <Nazara/Graphics/ParticleController.hpp>
#include <Nazara/Graphics/ParticleDeclaration.hpp>
#include <Nazara/Graphics/ParticleEmitter.hpp>
#include <Nazara/Graphics/ParticleGenerator.hpp>
#include <Nazara/Graphics/ParticleRenderer.hpp>
#include <Nazara/Graphics/SceneNode.hpp>
#include <Nazara/Math/BoundingVolume.hpp>
#include <memory>
#include <set>
#include <vector>
class NAZARA_API NzParticleSystem : public NzSceneNode, NzUpdatable
{
public:
NzParticleSystem(unsigned int maxParticleCount, nzParticleLayout layout);
NzParticleSystem(unsigned int maxParticleCount, const NzParticleDeclaration* declaration);
NzParticleSystem(const NzParticleSystem& emitter);
~NzParticleSystem();
void AddController(NzParticleController* controller);
void AddEmitter(NzParticleEmitter* emitter);
void AddGenerator(NzParticleGenerator* generator);
void AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const;
void* CreateParticle();
void* CreateParticles(unsigned int count);
void EnableFixedStep(bool fixedStep);
void* GenerateParticle();
void* GenerateParticles(unsigned int count);
const NzBoundingVolumef& GetBoundingVolume() const override;
const NzParticleDeclaration* GetDeclaration() const;
float GetFixedStepSize() const;
unsigned int GetMaxParticleCount() const;
unsigned int GetParticleCount() const;
unsigned int GetParticleSize() const;
nzSceneNodeType GetSceneNodeType() const override;
bool IsDrawable() const;
bool IsFixedStepEnabled() const;
void KillParticle(unsigned int index);
void KillParticles();
void RemoveController(NzParticleController* controller);
void RemoveEmitter(NzParticleEmitter* emitter);
void RemoveGenerator(NzParticleGenerator* generator);
void SetFixedStepSize(float stepSize);
void SetRenderer(NzParticleRenderer* renderer);
NzParticleSystem& operator=(const NzParticleSystem& emitter);
private:
void GenerateAABB() const;
void Register() override;
void ResizeBuffer();
void Unregister() override;
void UpdateBoundingVolume() const;
void Update() override;
std::set<unsigned int, std::greater<unsigned int>> m_dyingParticles;
mutable std::vector<nzUInt8> m_buffer;
std::vector<NzParticleControllerRef> m_controllers;
std::vector<NzParticleEmitter*> m_emitters;
std::vector<NzParticleGeneratorRef> m_generators;
mutable NzBoundingVolumef m_boundingVolume;
NzParticleDeclarationConstRef m_declaration;
NzParticleRendererRef m_renderer;
mutable bool m_boundingVolumeUpdated;
bool m_fixedStepEnabled;
bool m_processing;
float m_stepAccumulator;
float m_stepSize;
unsigned int m_maxParticleCount;
unsigned int m_particleCount;
unsigned int m_particleSize;
};
#endif // NAZARA_PARTICLESYSTEM_HPP

View File

@ -23,6 +23,18 @@ m_forwardQueue(forwardQueue)
{
}
void NzDeferredRenderQueue::AddBillboard(const NzMaterial* material, const NzVector3f& position, const NzVector2f& size, const NzVector2f& sinCos, const NzColor& color)
{
///TODO: Rendre les billboards via Deferred Shading si possible
m_forwardQueue->AddBillboard(material, position, size, sinCos, color);
}
void NzDeferredRenderQueue::AddBillboards(const NzMaterial* material, unsigned int count, NzSparsePtr<const NzVector3f> positionPtr, NzSparsePtr<const NzVector2f> sizePtr, NzSparsePtr<const NzVector2f> sinCosPtr, NzSparsePtr<const NzColor> colorPtr)
{
///TODO: Rendre les billboards via Deferred Shading si possible
m_forwardQueue->AddBillboards(material, count, positionPtr, sizePtr, sinCosPtr, colorPtr);
}
void NzDeferredRenderQueue::AddDrawable(const NzDrawable* drawable)
{
m_forwardQueue->AddDrawable(drawable);
@ -90,6 +102,7 @@ void NzDeferredRenderQueue::AddMesh(const NzMaterial* material, const NzMeshData
it2 = meshMap.insert(std::make_pair(meshData, std::move(instanceEntry))).first;
}
// On ajoute la matrice à la liste des instances de cet objet
std::vector<NzMatrix4f>& instances = it2->second.instances;
instances.push_back(transformMatrix);

View File

@ -18,6 +18,60 @@ namespace
};
}
void NzForwardRenderQueue::AddBillboard(const NzMaterial* material, const NzVector3f& position, const NzVector2f& size, const NzVector2f& sinCos, const NzColor& color)
{
auto it = billboards.find(material);
if (it == billboards.end())
{
BatchedBillboardEntry entry(this, ResourceType_Material);
entry.materialListener = material;
it = billboards.insert(std::make_pair(material, std::move(entry))).first;
}
BatchedBillboardEntry& entry = it->second;
auto& billboardVector = entry.billboards;
billboardVector.push_back(BillboardData{color, position, size, sinCos});
}
void NzForwardRenderQueue::AddBillboards(const NzMaterial* material, unsigned int count, NzSparsePtr<const NzVector3f> positionPtr, NzSparsePtr<const NzVector2f> sizePtr, NzSparsePtr<const NzVector2f> sinCosPtr, NzSparsePtr<const NzColor> colorPtr)
{
///DOC: sinCosPtr et colorPtr peuvent être nuls, ils seont remplacés respectivement par Vector2f(0.f, 1.f) et Color::White
NzVector2f 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
if (!colorPtr)
colorPtr.Reset(&NzColor::White, 0); // Pareil
auto it = billboards.find(material);
if (it == billboards.end())
{
BatchedBillboardEntry entry(this, ResourceType_Material);
entry.materialListener = material;
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];
for (unsigned int i = 0; i < count; ++i)
{
billboardData->center = *positionPtr++;
billboardData->color = *colorPtr++;
billboardData->sinCos = *sinCosPtr++;
billboardData->size = *sizePtr++;
billboardData++;
}
}
void NzForwardRenderQueue::AddDrawable(const NzDrawable* drawable)
{
#if NAZARA_GRAPHICS_SAFE
@ -63,6 +117,7 @@ void NzForwardRenderQueue::AddMesh(const NzMaterial* material, const NzMeshData&
{
if (material->IsEnabled(nzRendererParameter_Blend))
{
// 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)
unsigned int index = transparentModelData.size();
transparentModelData.resize(index+1);
@ -76,7 +131,7 @@ void NzForwardRenderQueue::AddMesh(const NzMaterial* material, const NzMeshData&
}
else
{
ModelBatches::iterator it = opaqueModels.find(material);
auto it = opaqueModels.find(material);
if (it == opaqueModels.end())
{
BatchedModelEntry entry(this, ResourceType_Material);
@ -150,6 +205,7 @@ void NzForwardRenderQueue::Clear(bool fully)
if (fully)
{
basicSprites.clear();
billboards.clear();
opaqueModels.clear();
}
}
@ -157,6 +213,7 @@ void NzForwardRenderQueue::Clear(bool fully)
void NzForwardRenderQueue::Sort(const NzAbstractViewer* viewer)
{
NzPlanef nearPlane = viewer->GetFrustum().GetPlane(nzFrustumPlane_Near);
NzVector3f viewerPos = viewer->GetEyePosition();
NzVector3f viewerNormal = viewer->GetForward();
std::sort(transparentModels.begin(), transparentModels.end(), [this, &nearPlane, &viewerNormal](unsigned int index1, unsigned int index2)
@ -169,6 +226,22 @@ void NzForwardRenderQueue::Sort(const NzAbstractViewer* viewer)
return nearPlane.Distance(position1) > nearPlane.Distance(position2);
});
for (auto& pair : billboards)
{
const NzMaterial* mat = pair.first;
if (mat->IsEnabled(nzRendererParameter_Blend))
{
BatchedBillboardEntry& entry = pair.second;
auto& billboardVector = entry.billboards;
std::sort(billboardVector.begin(), billboardVector.end(), [&viewerPos](const BillboardData& data1, const BillboardData& data2)
{
return viewerPos.SquaredDistance(data1.center) > viewerPos.SquaredDistance(data2.center);
});
}
}
}
bool NzForwardRenderQueue::OnResourceDestroy(const NzResource* resource, int index)
@ -197,6 +270,7 @@ bool NzForwardRenderQueue::OnResourceDestroy(const NzResource* resource, int ind
const NzMaterial* material = static_cast<const NzMaterial*>(resource);
basicSprites.erase(material);
billboards.erase(material);
opaqueModels.erase(material);
break;
}
@ -257,6 +331,15 @@ void NzForwardRenderQueue::OnResourceReleased(const NzResource* resource, int in
}
}
for (auto it = billboards.begin(); it != billboards.end(); ++it)
{
if (it->first == resource)
{
billboards.erase(it);
break;
}
}
for (auto it = opaqueModels.begin(); it != opaqueModels.end(); ++it)
{
if (it->first == resource)
@ -306,6 +389,26 @@ void NzForwardRenderQueue::OnResourceReleased(const NzResource* resource, int in
}
}
bool NzForwardRenderQueue::BatchedBillboardComparator::operator()(const NzMaterial* mat1, const NzMaterial* mat2)
{
const NzUberShader* uberShader1 = mat1->GetShader();
const NzUberShader* uberShader2 = mat2->GetShader();
if (uberShader1 != uberShader2)
return uberShader1 < uberShader2;
const NzShader* shader1 = mat1->GetShaderInstance(nzShaderFlags_Billboard | nzShaderFlags_VertexColor)->GetShader();
const NzShader* shader2 = mat2->GetShaderInstance(nzShaderFlags_Billboard | nzShaderFlags_VertexColor)->GetShader();
if (shader1 != shader2)
return shader1 < shader2;
const NzTexture* diffuseMap1 = mat1->GetDiffuseMap();
const NzTexture* diffuseMap2 = mat2->GetDiffuseMap();
if (diffuseMap1 != diffuseMap2)
return diffuseMap1 < diffuseMap2;
return mat1 < mat2;
}
bool NzForwardRenderQueue::BatchedModelMaterialComparator::operator()(const NzMaterial* mat1, const NzMaterial* mat2)
{
const NzUberShader* uberShader1 = mat1->GetShader();

View File

@ -3,6 +3,8 @@
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Graphics/ForwardRenderTechnique.hpp>
#include <Nazara/Core/ErrorFlags.hpp>
#include <Nazara/Core/OffsetOf.hpp>
#include <Nazara/Graphics/AbstractBackground.hpp>
#include <Nazara/Graphics/Camera.hpp>
#include <Nazara/Graphics/Drawable.hpp>
@ -22,46 +24,29 @@
namespace
{
static NzIndexBuffer* s_indexBuffer = nullptr;
unsigned int s_maxSprites = 8192;
NzIndexBuffer* BuildIndexBuffer()
struct BillboardPoint
{
std::unique_ptr<NzIndexBuffer> indexBuffer(new NzIndexBuffer(false, s_maxSprites*6, nzDataStorage_Hardware, nzBufferUsage_Static));
indexBuffer->SetPersistent(false);
NzColor color;
NzVector3f position;
NzVector2f size;
NzVector2f sinCos; // doit suivre size
NzVector2f uv;
};
NzBufferMapper<NzIndexBuffer> mapper(indexBuffer.get(), nzBufferAccess_WriteOnly);
nzUInt16* indices = static_cast<nzUInt16*>(mapper.GetPointer());
for (unsigned int i = 0; i < s_maxSprites; ++i)
{
*indices++ = i*4 + 0;
*indices++ = i*4 + 2;
*indices++ = i*4 + 1;
*indices++ = i*4 + 2;
*indices++ = i*4 + 3;
*indices++ = i*4 + 1;
}
return indexBuffer.release();
}
unsigned int s_maxQuads = std::numeric_limits<nzUInt16>::max()/6;
unsigned int s_vertexBufferSize = 4*1024*1024; // 4 MiB
}
NzForwardRenderTechnique::NzForwardRenderTechnique() :
m_spriteBuffer(NzVertexDeclaration::Get(nzVertexLayout_XYZ_Color_UV), s_maxSprites*4, nzDataStorage_Hardware, nzBufferUsage_Dynamic),
m_vertexBuffer(nzBufferType_Vertex),
m_maxLightPassPerObject(3)
{
if (!s_indexBuffer)
s_indexBuffer = BuildIndexBuffer();
NzErrorFlags flags(nzErrorFlag_ThrowException, true);
m_indexBuffer = s_indexBuffer;
}
m_vertexBuffer.Create(s_vertexBufferSize, nzDataStorage_Hardware, nzBufferUsage_Dynamic);
NzForwardRenderTechnique::~NzForwardRenderTechnique()
{
if (m_indexBuffer.Reset())
s_indexBuffer = nullptr;
m_billboardPointBuffer.Reset(&s_billboardVertexDeclaration, &m_vertexBuffer);
m_spriteBuffer.Reset(NzVertexDeclaration::Get(nzVertexLayout_XYZ_Color_UV), &m_vertexBuffer);
}
void NzForwardRenderTechnique::Clear(const NzScene* scene) const
@ -90,6 +75,9 @@ bool NzForwardRenderTechnique::Draw(const NzScene* scene) const
if (!m_renderQueue.basicSprites.empty())
DrawBasicSprites(scene);
if (!m_renderQueue.billboards.empty())
DrawBillboards(scene);
// Les autres drawables (Exemple: Terrain)
for (const NzDrawable* drawable : m_renderQueue.otherDrawables)
drawable->Draw();
@ -168,7 +156,7 @@ void NzForwardRenderTechnique::DrawBasicSprites(const NzScene* scene) const
const NzShader* lastShader = nullptr;
const ShaderUniforms* shaderUniforms = nullptr;
NzRenderer::SetIndexBuffer(m_indexBuffer);
NzRenderer::SetIndexBuffer(&s_quadIndexBuffer);
NzRenderer::SetMatrix(nzMatrixType_World, NzMatrix4f::Identity());
NzRenderer::SetVertexBuffer(&m_spriteBuffer);
@ -229,11 +217,12 @@ void NzForwardRenderTechnique::DrawBasicSprites(const NzScene* scene) const
NzVertexStruct_XYZ_Color_UV* vertices = reinterpret_cast<NzVertexStruct_XYZ_Color_UV*>(vertexMapper.GetPointer());
unsigned int spriteCount = 0;
unsigned int maxSpriteCount = std::min(s_maxQuads, m_spriteBuffer.GetVertexCount()/4);
do
{
NzForwardRenderQueue::SpriteChain_XYZ_Color_UV& currentChain = spriteChainVector[spriteChain];
unsigned int count = std::min(s_maxSprites - spriteCount, currentChain.spriteCount - spriteChainOffset);
unsigned int count = std::min(maxSpriteCount - spriteCount, currentChain.spriteCount - spriteChainOffset);
std::memcpy(vertices, currentChain.vertices + spriteChainOffset*4, 4*count*sizeof(NzVertexStruct_XYZ_Color_UV));
vertices += count*4;
@ -248,7 +237,7 @@ void NzForwardRenderTechnique::DrawBasicSprites(const NzScene* scene) const
spriteChainOffset = 0;
}
}
while (spriteCount < s_maxSprites && spriteChain < spriteChainCount);
while (spriteCount < maxSpriteCount && spriteChain < spriteChainCount);
vertexMapper.Unmap();
@ -266,6 +255,211 @@ void NzForwardRenderTechnique::DrawBasicSprites(const NzScene* scene) const
}
}
bool NzForwardRenderTechnique::Initialize()
{
try
{
NzErrorFlags flags(nzErrorFlag_ThrowException, true);
s_quadIndexBuffer.Reset(false, s_maxQuads*6, nzDataStorage_Hardware, nzBufferUsage_Static);
NzBufferMapper<NzIndexBuffer> mapper(s_quadIndexBuffer, nzBufferAccess_WriteOnly);
nzUInt16* indices = static_cast<nzUInt16*>(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 + 2;
*indices++ = i*4 + 3;
*indices++ = i*4 + 1;
}
mapper.Unmap(); // Inutile de garder le buffer ouvert plus longtemps
// Quad buffer (utilisé pour l'instancing de billboard et de sprites)
//Note: Les UV sont calculés dans le shader
s_quadVertexBuffer.Reset(NzVertexDeclaration::Get(nzVertexLayout_XY), 4, nzDataStorage_Hardware, nzBufferUsage_Static);
float vertices[2*4] = {
-0.5f, -0.5f,
0.5f, -0.5f,
-0.5f, 0.5f,
0.5f, 0.5f,
};
s_quadVertexBuffer.FillRaw(vertices, 0, sizeof(vertices));
// Déclaration lors du rendu des billboards par sommet
s_billboardVertexDeclaration.EnableComponent(nzVertexComponent_Color, nzComponentType_Color, NzOffsetOf(BillboardPoint, color));
s_billboardVertexDeclaration.EnableComponent(nzVertexComponent_Position, nzComponentType_Float3, NzOffsetOf(BillboardPoint, position));
s_billboardVertexDeclaration.EnableComponent(nzVertexComponent_TexCoord, nzComponentType_Float2, NzOffsetOf(BillboardPoint, uv));
s_billboardVertexDeclaration.EnableComponent(nzVertexComponent_Userdata0, nzComponentType_Float4, NzOffsetOf(BillboardPoint, size)); // Englobe 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
s_billboardInstanceDeclaration.EnableComponent(nzVertexComponent_InstanceData0, nzComponentType_Float3, NzOffsetOf(NzForwardRenderQueue::BillboardData, center));
s_billboardInstanceDeclaration.EnableComponent(nzVertexComponent_InstanceData1, nzComponentType_Float4, NzOffsetOf(NzForwardRenderQueue::BillboardData, size)); // Englobe sincos
s_billboardInstanceDeclaration.EnableComponent(nzVertexComponent_InstanceData2, nzComponentType_Color, NzOffsetOf(NzForwardRenderQueue::BillboardData, color));
}
catch (const std::exception& e)
{
NazaraError("Failed to initialise: " + NzString(e.what()));
return false;
}
return true;
}
void NzForwardRenderTechnique::Uninitialize()
{
s_quadIndexBuffer.Reset();
s_quadVertexBuffer.Reset();
}
void NzForwardRenderTechnique::DrawBillboards(const NzScene* scene) const
{
NzAbstractViewer* viewer = scene->GetViewer();
const NzShader* lastShader = nullptr;
const ShaderUniforms* shaderUniforms = nullptr;
if (NzRenderer::HasCapability(nzRendererCap_Instancing))
{
NzVertexBuffer* instanceBuffer = NzRenderer::GetInstanceBuffer();
instanceBuffer->SetVertexDeclaration(&s_billboardInstanceDeclaration);
NzRenderer::SetVertexBuffer(&s_quadVertexBuffer);
for (auto& matIt : m_renderQueue.billboards)
{
const NzMaterial* material = matIt.first;
auto& entry = matIt.second;
auto& billboardVector = entry.billboards;
unsigned int billboardCount = billboardVector.size();
if (billboardCount > 0)
{
// On commence par appliquer du matériau (et récupérer le shader ainsi activé)
const NzShader* shader = material->Apply(nzShaderFlags_Billboard | nzShaderFlags_Instancing | nzShaderFlags_VertexColor);
// Les uniformes sont conservées au sein d'un programme, inutile de les renvoyer tant qu'il ne change pas
if (shader != lastShader)
{
// Index des uniformes dans le shader
shaderUniforms = GetShaderUniforms(shader);
// Couleur ambiante de la scène
shader->SendColor(shaderUniforms->sceneAmbient, scene->GetAmbientColor());
// Position de la caméra
shader->SendVector(shaderUniforms->eyePosition, viewer->GetEyePosition());
lastShader = shader;
}
const NzForwardRenderQueue::BillboardData* data = &billboardVector[0];
unsigned int maxBillboardPerDraw = instanceBuffer->GetVertexCount();
do
{
unsigned int renderedBillboardCount = std::min(billboardCount, maxBillboardPerDraw);
billboardCount -= renderedBillboardCount;
instanceBuffer->Fill(data, 0, renderedBillboardCount, true);
data += renderedBillboardCount;
NzRenderer::DrawPrimitivesInstanced(renderedBillboardCount, nzPrimitiveMode_TriangleStrip, 0, 4);
}
while (billboardCount > 0);
billboardVector.clear();
}
}
}
else
{
NzRenderer::SetIndexBuffer(&s_quadIndexBuffer);
NzRenderer::SetVertexBuffer(&m_billboardPointBuffer);
for (auto& matIt : m_renderQueue.billboards)
{
const NzMaterial* material = matIt.first;
auto& entry = matIt.second;
auto& billboardVector = entry.billboards;
unsigned int billboardCount = billboardVector.size();
if (billboardCount > 0)
{
// On commence par appliquer du matériau (et récupérer le shader ainsi activé)
const NzShader* shader = material->Apply(nzShaderFlags_Billboard | nzShaderFlags_VertexColor);
// Les uniformes sont conservées au sein d'un programme, inutile de les renvoyer tant qu'il ne change pas
if (shader != lastShader)
{
// Couleur ambiante de la scène
shader->SendColor(shaderUniforms->sceneAmbient, scene->GetAmbientColor());
// Position de la caméra
shader->SendVector(shaderUniforms->eyePosition, viewer->GetEyePosition());
lastShader = shader;
}
const NzForwardRenderQueue::BillboardData* data = &billboardVector[0];
unsigned int maxBillboardPerDraw = std::min(s_maxQuads, m_billboardPointBuffer.GetVertexCount()/4);
do
{
unsigned int renderedBillboardCount = std::min(billboardCount, maxBillboardPerDraw);
billboardCount -= renderedBillboardCount;
NzBufferMapper<NzVertexBuffer> vertexMapper(m_billboardPointBuffer, nzBufferAccess_DiscardAndWrite, 0, renderedBillboardCount*4);
BillboardPoint* vertices = reinterpret_cast<BillboardPoint*>(vertexMapper.GetPointer());
for (unsigned int i = 0; i < renderedBillboardCount; ++i)
{
const NzForwardRenderQueue::BillboardData& billboard = *data++;
vertices->color = billboard.color;
vertices->position = billboard.center;
vertices->sinCos = billboard.sinCos;
vertices->size = billboard.size;
vertices->uv.Set(0.f, 1.f);
vertices++;
vertices->color = billboard.color;
vertices->position = billboard.center;
vertices->sinCos = billboard.sinCos;
vertices->size = billboard.size;
vertices->uv.Set(1.f, 1.f);
vertices++;
vertices->color = billboard.color;
vertices->position = billboard.center;
vertices->sinCos = billboard.sinCos;
vertices->size = billboard.size;
vertices->uv.Set(0.f, 0.f);
vertices++;
vertices->color = billboard.color;
vertices->position = billboard.center;
vertices->sinCos = billboard.sinCos;
vertices->size = billboard.size;
vertices->uv.Set(1.f, 0.f);
vertices++;
}
vertexMapper.Unmap();
NzRenderer::DrawIndexedPrimitives(nzPrimitiveMode_TriangleList, 0, renderedBillboardCount*6);
}
while (billboardCount > 0);
billboardVector.clear();
}
}
}
}
void NzForwardRenderTechnique::DrawOpaqueModels(const NzScene* scene) const
{
NzAbstractViewer* viewer = scene->GetViewer();
@ -593,3 +787,8 @@ const NzForwardRenderTechnique::ShaderUniforms* NzForwardRenderTechnique::GetSha
return &it->second;
}
NzIndexBuffer NzForwardRenderTechnique::s_quadIndexBuffer;
NzVertexBuffer NzForwardRenderTechnique::s_quadVertexBuffer;
NzVertexDeclaration NzForwardRenderTechnique::s_billboardInstanceDeclaration;
NzVertexDeclaration NzForwardRenderTechnique::s_billboardVertexDeclaration;

View File

@ -11,6 +11,7 @@
#include <Nazara/Graphics/ForwardRenderTechnique.hpp>
#include <Nazara/Graphics/GuillotineTextureAtlas.hpp>
#include <Nazara/Graphics/Material.hpp>
#include <Nazara/Graphics/ParticleDeclaration.hpp>
#include <Nazara/Graphics/RenderTechniques.hpp>
#include <Nazara/Graphics/SkinningManager.hpp>
#include <Nazara/Graphics/Loaders/Mesh.hpp>
@ -46,6 +47,12 @@ bool NzGraphics::Initialize()
return false;
}
if (!NzParticleDeclaration::Initialize())
{
NazaraError("Failed to initialize particle declarations");
return false;
}
if (!NzSkinningManager::Initialize())
{
NazaraError("Failed to initialize skinning manager");
@ -60,12 +67,22 @@ bool NzGraphics::Initialize()
NzLoaders_Texture_Register();
// RenderTechniques
if (!NzForwardRenderTechnique::Initialize())
{
NazaraError("Failed to initialize Forward Rendering");
return false;
}
NzRenderTechniques::Register(NzRenderTechniques::ToString(nzRenderTechniqueType_BasicForward), 0, []() -> NzAbstractRenderTechnique* { return new NzForwardRenderTechnique; });
if (NzDeferredRenderTechnique::IsSupported())
{
NzDeferredRenderTechnique::Initialize();
NzRenderTechniques::Register(NzRenderTechniques::ToString(nzRenderTechniqueType_DeferredShading), 20, []() -> NzAbstractRenderTechnique* { return new NzDeferredRenderTechnique; });
if (NzDeferredRenderTechnique::Initialize())
NzRenderTechniques::Register(NzRenderTechniques::ToString(nzRenderTechniqueType_DeferredShading), 20, []() -> NzAbstractRenderTechnique* { return new NzDeferredRenderTechnique; });
else
{
NazaraWarning("Failed to initialize Deferred Rendering");
}
}
NzFont::SetDefaultAtlas(std::make_shared<NzGuillotineTextureAtlas>());
@ -126,7 +143,9 @@ void NzGraphics::Uninitialize()
NzLoaders_Texture_Unregister();
NzDeferredRenderTechnique::Uninitialize();
NzForwardRenderTechnique::Uninitialize();
NzMaterial::Uninitialize();
NzParticleDeclaration::Uninitialize();
NzSkinningManager::Uninitialize();
NazaraNotice("Uninitialized: Graphics module");

View File

@ -234,10 +234,11 @@ const NzUberShader* NzMaterial::GetShader() const
const NzUberShaderInstance* NzMaterial::GetShaderInstance(nzUInt32 flags) const
{
if (!m_shaders[flags].uberInstance)
const ShaderInstance& instance = m_shaders[flags];
if (!instance.uberInstance)
GenerateShader(flags);
return m_shaders[flags].uberInstance;
return instance.uberInstance;
}
float NzMaterial::GetShininess() const
@ -660,6 +661,7 @@ void NzMaterial::GenerateShader(nzUInt32 flags) const
flags & nzShaderFlags_TextureOverlay);
list.SetParameter("TRANSFORM", m_transformEnabled);
list.SetParameter("FLAG_BILLBOARD", static_cast<bool>(flags & nzShaderFlags_Billboard));
list.SetParameter("FLAG_DEFERRED", static_cast<bool>((flags & nzShaderFlags_Deferred) != 0));
list.SetParameter("FLAG_INSTANCING", static_cast<bool>((flags & nzShaderFlags_Instancing) != 0));
list.SetParameter("FLAG_TEXTUREOVERLAY", static_cast<bool>((flags & nzShaderFlags_TextureOverlay) != 0));
@ -731,7 +733,7 @@ bool NzMaterial::Initialize()
}
uberShader->SetShader(nzShaderStage_Fragment, fragmentShader, "FLAG_TEXTUREOVERLAY ALPHA_MAPPING ALPHA_TEST AUTO_TEXCOORDS DIFFUSE_MAPPING");
uberShader->SetShader(nzShaderStage_Vertex, vertexShader, "FLAG_INSTANCING FLAG_VERTEXCOLOR TEXTURE_MAPPING TRANSFORM UNIFORM_VERTEX_DEPTH");
uberShader->SetShader(nzShaderStage_Vertex, vertexShader, "FLAG_BILLBOARD FLAG_INSTANCING FLAG_VERTEXCOLOR TEXTURE_MAPPING TRANSFORM UNIFORM_VERTEX_DEPTH");
NzUberShaderLibrary::Register("Basic", uberShader.get());
uberShader.release();
@ -771,8 +773,8 @@ bool NzMaterial::Initialize()
vertexShader.Set(reinterpret_cast<const char*>(compatibilityVertexShader), sizeof(compatibilityVertexShader));
}
uberShader->SetShader(nzShaderStage_Fragment, fragmentShader, "FLAG_DEFERRED FLAG_TEXTUREOVERLAY ALPHA_MAPPING ALPHA_TEST DIFFUSE_MAPPING EMISSIVE_MAPPING LIGHTING NORMAL_MAPPING PARALLAX_MAPPING SPECULAR_MAPPING");
uberShader->SetShader(nzShaderStage_Vertex, vertexShader, "FLAG_DEFERRED FLAG_INSTANCING FLAG_VERTEXCOLOR COMPUTE_TBNMATRIX LIGHTING PARALLAX_MAPPING TEXTURE_MAPPING TRANSFORM UNIFORM_VERTEX_DEPTH");
uberShader->SetShader(nzShaderStage_Fragment, fragmentShader, "FLAG_DEFERRED FLAG_TEXTUREOVERLAY ALPHA_MAPPING ALPHA_TEST AUTO_TEXCOORDS DIFFUSE_MAPPING EMISSIVE_MAPPING LIGHTING NORMAL_MAPPING PARALLAX_MAPPING SPECULAR_MAPPING");
uberShader->SetShader(nzShaderStage_Vertex, vertexShader, "FLAG_BILLBOARD FLAG_DEFERRED FLAG_INSTANCING FLAG_VERTEXCOLOR COMPUTE_TBNMATRIX LIGHTING PARALLAX_MAPPING TEXTURE_MAPPING TRANSFORM UNIFORM_VERTEX_DEPTH");
NzUberShaderLibrary::Register("PhongLighting", uberShader.get());
uberShader.release();

View File

@ -0,0 +1,14 @@
// Copyright (C) 2014 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Graphics/ParticleController.hpp>
#include <Nazara/Graphics/Debug.hpp>
NzParticleController::NzParticleController(const NzParticleController& controller) :
NzResource()
{
NazaraUnused(controller);
}
NzParticleController::~NzParticleController() = default;

View File

@ -0,0 +1,231 @@
// Copyright (C) 2014 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Graphics/ParticleDeclaration.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/ErrorFlags.hpp>
#include <Nazara/Core/OffsetOf.hpp>
#include <Nazara/Graphics/Config.hpp>
#include <Nazara/Graphics/Enums.hpp>
#include <Nazara/Graphics/ParticleStruct.hpp>
#include <Nazara/Utility/Utility.hpp>
#include <cstring>
#include <Nazara/Graphics/Debug.hpp>
NzParticleDeclaration::NzParticleDeclaration() :
m_stride(0)
{
}
NzParticleDeclaration::NzParticleDeclaration(const NzParticleDeclaration& declaration) :
NzResource(),
m_stride(declaration.m_stride)
{
std::memcpy(m_components, declaration.m_components, sizeof(Component)*(nzParticleComponent_Max+1));
}
NzParticleDeclaration::~NzParticleDeclaration()
{
NotifyDestroy();
}
void NzParticleDeclaration::DisableComponent(nzParticleComponent component)
{
#ifdef NAZARA_DEBUG
if (component > nzParticleComponent_Max)
{
NazaraError("Vertex component out of enum");
return;
}
#endif
#if NAZARA_GRAPHICS_SAFE
if (component == nzParticleComponent_Unused)
{
NazaraError("Cannot disable \"unused\" component");
return;
}
#endif
Component& vertexComponent = m_components[component];
if (vertexComponent.enabled)
{
vertexComponent.enabled = false;
m_stride -= NzUtility::ComponentStride[vertexComponent.type];
}
}
void NzParticleDeclaration::EnableComponent(nzParticleComponent component, nzComponentType type, unsigned int offset)
{
#ifdef NAZARA_DEBUG
if (component > nzParticleComponent_Max)
{
NazaraError("Vertex component out of enum");
return;
}
#endif
#if NAZARA_GRAPHICS_SAFE
if (!IsTypeSupported(type))
{
NazaraError("Component type 0x" + NzString::Number(type, 16) + " is not supported by particle declarations");
return;
}
#endif
if (component != nzParticleComponent_Unused)
{
Component& particleComponent = m_components[component];
if (particleComponent.enabled)
m_stride -= NzUtility::ComponentStride[particleComponent.type];
else
particleComponent.enabled = true;
particleComponent.offset = offset;
particleComponent.type = type;
}
m_stride += NzUtility::ComponentStride[type];
}
void NzParticleDeclaration::GetComponent(nzParticleComponent component, bool* enabled, nzComponentType* type, unsigned int* offset) const
{
#ifdef NAZARA_DEBUG
if (component > nzParticleComponent_Max)
{
NazaraError("Particle component out of enum");
return;
}
#endif
#if NAZARA_GRAPHICS_SAFE
if (component == nzParticleComponent_Unused)
{
NazaraError("Cannot get \"unused\" component");
return;
}
#endif
const Component& particleComponent = m_components[component];
if (enabled)
*enabled = particleComponent.enabled;
if (type)
*type = particleComponent.type;
if (offset)
*offset = particleComponent.offset;
}
unsigned int NzParticleDeclaration::GetStride() const
{
return m_stride;
}
void NzParticleDeclaration::SetStride(unsigned int stride)
{
m_stride = stride;
}
NzParticleDeclaration& NzParticleDeclaration::operator=(const NzParticleDeclaration& declaration)
{
std::memcpy(m_components, declaration.m_components, sizeof(Component)*(nzParticleComponent_Max+1));
m_stride = declaration.m_stride;
return *this;
}
NzParticleDeclaration* NzParticleDeclaration::Get(nzParticleLayout layout)
{
#ifdef NAZARA_DEBUG
if (layout > nzParticleLayout_Max)
{
NazaraError("Particle layout out of enum");
return nullptr;
}
#endif
return &s_declarations[layout];
}
bool NzParticleDeclaration::IsTypeSupported(nzComponentType type)
{
switch (type)
{
case nzComponentType_Color:
case nzComponentType_Double1:
case nzComponentType_Double2:
case nzComponentType_Double3:
case nzComponentType_Double4:
case nzComponentType_Float1:
case nzComponentType_Float2:
case nzComponentType_Float3:
case nzComponentType_Float4:
case nzComponentType_Int1:
case nzComponentType_Int2:
case nzComponentType_Int3:
case nzComponentType_Int4:
case nzComponentType_Quaternion:
return true;
}
NazaraError("Component type not handled (0x" + NzString::Number(type, 16) + ')');
return false;
}
bool NzParticleDeclaration::Initialize()
{
try
{
NzErrorFlags flags(nzErrorFlag_Silent | nzErrorFlag_ThrowException);
// Layout : Type
NzParticleDeclaration* declaration;
// nzParticleLayout_Billboard : NzParticleStruct_Billboard
declaration = &s_declarations[nzParticleLayout_Billboard];
declaration->EnableComponent(nzParticleComponent_Color, nzComponentType_Color, NzOffsetOf(NzParticleStruct_Billboard, color));
declaration->EnableComponent(nzParticleComponent_Life, nzComponentType_Int1, NzOffsetOf(NzParticleStruct_Billboard, life));
declaration->EnableComponent(nzParticleComponent_Normal, nzComponentType_Float3, NzOffsetOf(NzParticleStruct_Billboard, normal));
declaration->EnableComponent(nzParticleComponent_Position, nzComponentType_Float3, NzOffsetOf(NzParticleStruct_Billboard, position));
declaration->EnableComponent(nzParticleComponent_Rotation, nzComponentType_Float1, NzOffsetOf(NzParticleStruct_Billboard, rotation));
declaration->EnableComponent(nzParticleComponent_Velocity, nzComponentType_Float3, NzOffsetOf(NzParticleStruct_Billboard, velocity));
NazaraAssert(declaration->GetStride() == sizeof(NzParticleStruct_Billboard), "Invalid stride for declaration nzParticleLayout_Billboard");
// nzParticleLayout_Model : NzParticleStruct_Model
declaration = &s_declarations[nzParticleLayout_Model];
declaration->EnableComponent(nzParticleComponent_Life, nzComponentType_Int1, NzOffsetOf(NzParticleStruct_Model, life));
declaration->EnableComponent(nzParticleComponent_Position, nzComponentType_Float3, NzOffsetOf(NzParticleStruct_Model, position));
declaration->EnableComponent(nzParticleComponent_Rotation, nzComponentType_Quaternion, NzOffsetOf(NzParticleStruct_Model, rotation));
declaration->EnableComponent(nzParticleComponent_Velocity, nzComponentType_Float3, NzOffsetOf(NzParticleStruct_Model, velocity));
NazaraAssert(declaration->GetStride() == sizeof(NzParticleStruct_Model), "Invalid stride for declaration nzParticleLayout_Model");
// nzParticleLayout_Sprite : NzParticleStruct_Sprite
declaration = &s_declarations[nzParticleLayout_Sprite];
declaration->EnableComponent(nzParticleComponent_Color, nzComponentType_Color, NzOffsetOf(NzParticleStruct_Sprite, color));
declaration->EnableComponent(nzParticleComponent_Life, nzComponentType_Int1, NzOffsetOf(NzParticleStruct_Sprite, life));
declaration->EnableComponent(nzParticleComponent_Position, nzComponentType_Float2, NzOffsetOf(NzParticleStruct_Sprite, position));
declaration->EnableComponent(nzParticleComponent_Rotation, nzComponentType_Float1, NzOffsetOf(NzParticleStruct_Sprite, rotation));
declaration->EnableComponent(nzParticleComponent_Velocity, nzComponentType_Float2, NzOffsetOf(NzParticleStruct_Sprite, velocity));
NazaraAssert(declaration->GetStride() == sizeof(NzParticleStruct_Sprite), "Invalid stride for declaration nzParticleLayout_Sprite");
}
catch (const std::exception& e)
{
NazaraError("Failed to initialize particle declarations: " + NzString(e.what()));
return false;
}
return true;
}
void NzParticleDeclaration::Uninitialize()
{
// Rien à faire
}
NzParticleDeclaration NzParticleDeclaration::s_declarations[nzParticleLayout_Max+1];

View File

@ -0,0 +1,69 @@
// Copyright (C) 2014 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Graphics/ParticleEmitter.hpp>
#include <Nazara/Core/CallOnExit.hpp>
#include <Nazara/Core/ErrorFlags.hpp>
#include <Nazara/Core/StringStream.hpp>
#include <Nazara/Graphics/ParticleMapper.hpp>
#include <Nazara/Graphics/ParticleSystem.hpp>
#include <cstdlib>
#include <memory>
#include <Nazara/Graphics/Debug.hpp>
NzParticleEmitter::NzParticleEmitter() :
m_emissionAccumulator(0.f),
m_emissionRate(0.f),
m_emissionCount(1)
{
}
NzParticleEmitter::~NzParticleEmitter() = default;
void NzParticleEmitter::Emit(NzParticleSystem& 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;
float emissionCount = std::floor(m_emissionAccumulator); // Le nombre d'émissions de cette mise à jour
m_emissionAccumulator -= emissionCount; // On enlève la partie entière
if (emissionCount >= 1.f)
{
// On calcule le nombre maximum de particules pouvant être émises cette fois-ci
unsigned int maxParticleCount = static_cast<unsigned int>(emissionCount)*m_emissionCount;
// On récupère le nombre de particules qu'il est possible de créer selon l'espace libre
unsigned int particleCount = std::min(maxParticleCount, system.GetMaxParticleCount() - system.GetParticleCount());
// Et on émet nos particules
void* particles = system.GenerateParticles(particleCount);
NzParticleMapper mapper(particles, system.GetDeclaration());
SetupParticles(mapper, particleCount);
}
}
}
unsigned int NzParticleEmitter::GetEmissionCount() const
{
return m_emissionCount;
}
float NzParticleEmitter::GetEmissionRate() const
{
return m_emissionRate;
}
void NzParticleEmitter::SetEmissionCount(unsigned int count)
{
m_emissionCount = count;
}
void NzParticleEmitter::SetEmissionRate(float rate)
{
m_emissionRate = rate;
}

View File

@ -0,0 +1,14 @@
// Copyright (C) 2014 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Graphics/ParticleGenerator.hpp>
#include <Nazara/Graphics/Debug.hpp>
NzParticleGenerator::NzParticleGenerator(const NzParticleGenerator& generator) :
NzResource()
{
NazaraUnused(generator);
}
NzParticleGenerator::~NzParticleGenerator() = default;

View File

@ -0,0 +1,15 @@
// Copyright (C) 2014 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Graphics/ParticleMapper.hpp>
#include <Nazara/Core/ErrorFlags.hpp>
#include <Nazara/Graphics/Debug.hpp>
NzParticleMapper::NzParticleMapper(void* buffer, const NzParticleDeclaration* declaration) :
m_declaration(declaration),
m_ptr(static_cast<nzUInt8*>(buffer))
{
}
NzParticleMapper::~NzParticleMapper() = default;

View File

@ -0,0 +1,14 @@
// Copyright (C) 2014 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Graphics/ParticleRenderer.hpp>
#include <Nazara/Graphics/Debug.hpp>
NzParticleRenderer::NzParticleRenderer(const NzParticleRenderer& renderer) :
NzResource()
{
NazaraUnused(renderer);
}
NzParticleRenderer::~NzParticleRenderer() = default;

View File

@ -0,0 +1,365 @@
// Copyright (C) 2014 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Graphics/ParticleSystem.hpp>
#include <Nazara/Core/CallOnExit.hpp>
#include <Nazara/Core/ErrorFlags.hpp>
#include <Nazara/Core/StringStream.hpp>
#include <Nazara/Graphics/ParticleMapper.hpp>
#include <cstdlib>
#include <memory>
#include <Nazara/Graphics/Debug.hpp>
NzParticleSystem::NzParticleSystem(unsigned int maxParticleCount, nzParticleLayout layout) :
NzParticleSystem(maxParticleCount, NzParticleDeclaration::Get(layout))
{
}
NzParticleSystem::NzParticleSystem(unsigned int maxParticleCount, const NzParticleDeclaration* declaration) :
m_declaration(declaration),
m_boundingVolumeUpdated(false),
m_fixedStepEnabled(false),
m_processing(false),
m_stepAccumulator(0.f),
m_stepSize(1.f/60.f),
m_maxParticleCount(maxParticleCount),
m_particleCount(0)
{
// En cas d'erreur, un constructeur ne peut que lancer une exception
NzErrorFlags flags(nzErrorFlag_ThrowException, true);
m_particleSize = m_declaration->GetStride(); // La taille de chaque particule
ResizeBuffer();
}
NzParticleSystem::NzParticleSystem(const NzParticleSystem& system) :
NzSceneNode(system),
m_controllers(system.m_controllers),
m_generators(system.m_generators),
m_boundingVolume(system.m_boundingVolume),
m_declaration(system.m_declaration),
m_renderer(system.m_renderer),
m_boundingVolumeUpdated(system.m_boundingVolumeUpdated),
m_fixedStepEnabled(system.m_fixedStepEnabled),
m_processing(false),
m_stepAccumulator(0.f),
m_stepSize(system.m_stepSize),
m_maxParticleCount(system.m_maxParticleCount),
m_particleCount(system.m_particleCount),
m_particleSize(system.m_particleSize)
{
NzErrorFlags flags(nzErrorFlag_ThrowException, true);
ResizeBuffer();
// On ne copie que les particules vivantes
std::memcpy(m_buffer.data(), system.m_buffer.data(), system.m_particleCount*m_particleSize);
}
NzParticleSystem::~NzParticleSystem() = default;
void NzParticleSystem::AddController(NzParticleController* controller)
{
m_controllers.emplace_back(controller);
}
void NzParticleSystem::AddEmitter(NzParticleEmitter* emitter)
{
m_emitters.emplace_back(emitter);
}
void NzParticleSystem::AddGenerator(NzParticleGenerator* generator)
{
m_generators.emplace_back(generator);
}
void NzParticleSystem::AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const
{
///FIXME: Vérifier le renderer
if (m_particleCount > 0)
{
NzParticleMapper mapper(m_buffer.data(), m_declaration);
m_renderer->Render(*this, mapper, 0, m_particleCount-1, renderQueue);
}
}
void* NzParticleSystem::CreateParticle()
{
return CreateParticles(1);
}
void* NzParticleSystem::CreateParticles(unsigned int count)
{
if (count == 0)
return nullptr;
if (m_particleCount+count > m_maxParticleCount)
return nullptr;
unsigned int particlesIndex = m_particleCount;
m_particleCount += count;
return &m_buffer[particlesIndex*m_particleSize];
}
void NzParticleSystem::EnableFixedStep(bool fixedStep)
{
// On teste pour empêcher que cette méthode ne remette systématiquement le step accumulator à zéro
if (m_fixedStepEnabled != fixedStep)
{
m_fixedStepEnabled = fixedStep;
m_stepAccumulator = 0.f;
}
}
void* NzParticleSystem::GenerateParticle()
{
return GenerateParticles(1);
}
void* NzParticleSystem::GenerateParticles(unsigned int count)
{
void* ptr = CreateParticles(count);
if (!ptr)
return nullptr;
NzParticleMapper mapper(ptr, m_declaration);
for (NzParticleGenerator* generator : m_generators)
generator->Generate(*this, mapper, 0, m_particleCount-1);
return ptr;
}
const NzBoundingVolumef& NzParticleSystem::GetBoundingVolume() const
{
if (!m_boundingVolumeUpdated)
UpdateBoundingVolume();
return m_boundingVolume;
}
const NzParticleDeclaration* NzParticleSystem::GetDeclaration() const
{
return m_declaration;
}
float NzParticleSystem::GetFixedStepSize() const
{
return m_stepSize;
}
unsigned int NzParticleSystem::GetMaxParticleCount() const
{
return m_maxParticleCount;
}
unsigned int NzParticleSystem::GetParticleCount() const
{
return m_particleCount;
}
unsigned int NzParticleSystem::GetParticleSize() const
{
return m_particleSize;
}
nzSceneNodeType NzParticleSystem::GetSceneNodeType() const
{
return nzSceneNodeType_ParticleEmitter;
}
bool NzParticleSystem::IsDrawable() const
{
return true;
}
bool NzParticleSystem::IsFixedStepEnabled() const
{
return m_fixedStepEnabled;
}
void NzParticleSystem::KillParticle(unsigned int index)
{
///FIXME: Vérifier 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 de secours
m_dyingParticles.insert(index);
return;
}
// On déplace la dernière particule vivante à la place de celle-ci
if (--m_particleCount > 0)
std::memcpy(&m_buffer[index*m_particleSize], &m_buffer[m_particleCount*m_particleSize], m_particleSize);
}
void NzParticleSystem::KillParticles()
{
m_particleCount = 0;
}
void NzParticleSystem::RemoveController(NzParticleController* controller)
{
auto it = std::find(m_controllers.begin(), m_controllers.end(), controller);
if (it != m_controllers.end())
m_controllers.erase(it);
}
void NzParticleSystem::RemoveEmitter(NzParticleEmitter* emitter)
{
auto it = std::find(m_emitters.begin(), m_emitters.end(), emitter);
if (it != m_emitters.end())
m_emitters.erase(it);
}
void NzParticleSystem::RemoveGenerator(NzParticleGenerator* generator)
{
auto it = std::find(m_generators.begin(), m_generators.end(), generator);
if (it != m_generators.end())
m_generators.erase(it);
}
void NzParticleSystem::SetFixedStepSize(float stepSize)
{
m_stepSize = stepSize;
}
void NzParticleSystem::SetRenderer(NzParticleRenderer* renderer)
{
m_renderer = renderer;
}
NzParticleSystem& NzParticleSystem::operator=(const NzParticleSystem& system)
{
NzErrorFlags flags(nzErrorFlag_ThrowException, true);
NzSceneNode::operator=(system);
m_boundingVolume = system.m_boundingVolume;
m_boundingVolumeUpdated = system.m_boundingVolumeUpdated;
m_controllers = system.m_controllers;
m_declaration = system.m_declaration;
m_fixedStepEnabled = system.m_fixedStepEnabled;
m_generators = system.m_generators;
m_maxParticleCount = system.m_maxParticleCount;
m_particleCount = system.m_particleCount;
m_particleSize = system.m_particleSize;
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
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
ResizeBuffer();
// On ne copie que les particules vivantes
std::memcpy(m_buffer.data(), system.m_buffer.data(), system.m_particleCount*m_particleSize);
return *this;
}
void NzParticleSystem::GenerateAABB() const
{
m_boundingVolume.MakeInfinite();
}
void NzParticleSystem::Register()
{
m_scene->RegisterForUpdate(this);
}
void NzParticleSystem::ResizeBuffer()
{
// Histoire de décrire un peu mieux l'erreur en cas d'échec
try
{
m_buffer.resize(m_maxParticleCount*m_particleSize);
}
catch (const std::exception& e)
{
NzStringStream stream;
stream << "Failed to allocate particle buffer (" << e.what() << ") for " << m_maxParticleCount << " particles of size " << m_particleSize;
NazaraError(stream.ToString());
}
}
void NzParticleSystem::Unregister()
{
m_scene->UnregisterForUpdate(this);
}
void NzParticleSystem::UpdateBoundingVolume() const
{
if (m_boundingVolume.IsNull())
GenerateAABB();
if (!m_transformMatrixUpdated)
UpdateTransformMatrix();
m_boundingVolume.Update(m_transformMatrix);
m_boundingVolumeUpdated = true;
}
void NzParticleSystem::Update()
{
float elapsedTime = m_scene->GetUpdateTime();
// Émission
for (NzParticleEmitter* emitter : m_emitters)
emitter->Emit(*this, elapsedTime);
// Mise à jour
if (m_particleCount > 0)
{
NzParticleMapper mapper(m_buffer.data(), m_declaration);
m_processing = true;
// Pour éviter un verrouillage en cas d'exception
NzCallOnExit onExit([this]()
{
m_processing = false;
});
if (m_fixedStepEnabled)
{
m_stepAccumulator += elapsedTime;
while (m_stepAccumulator >= m_stepSize)
{
for (NzParticleController* controller : m_controllers)
controller->Apply(*this, mapper, 0, m_particleCount-1, m_stepAccumulator);
m_stepAccumulator -= m_stepSize;
}
}
else
{
for (NzParticleController* controller : m_controllers)
controller->Apply(*this, mapper, 0, m_particleCount-1, elapsedTime);
}
m_processing = false;
onExit.Reset();
// On tue maintenant les particules mortes durant la mise à jour
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
for (unsigned int index : m_dyingParticles)
KillParticle(index);
}
else
KillParticles(); // Toutes les particules sont mortes, ceci est beaucoup plus rapide
m_dyingParticles.clear();
}
}

View File

@ -1,22 +1,31 @@
/********************Entrant********************/
varying vec2 vTexCoord;
varying vec4 vColor;
/********************Uniformes********************/
uniform sampler2D MaterialAlphaMap;
uniform float MaterialAlphaThreshold;
uniform vec4 MaterialDiffuse;
uniform sampler2D MaterialDiffuseMap;
uniform vec2 InvTargetSize;
/********************Fonctions********************/
void main()
{
vec4 fragmentColor = MaterialDiffuse;
vec4 fragmentColor = MaterialDiffuse; * vColor;
#if AUTO_TEXCOORDS
vec2 texCoord = gl_FragCoord.xy * InvTargetSize;
#else
vec2 texCoord = vTexCoord;
#endif
#if DIFFUSE_MAPPING
fragmentColor *= texture2D(MaterialDiffuseMap, vTexCoord);
fragmentColor *= texture2D(MaterialDiffuseMap, texCoord);
#endif
#if ALPHA_MAPPING
fragmentColor.a *= texture2D(MaterialAlphaMap, vTexCoord).r;
fragmentColor.a *= texture2D(MaterialAlphaMap, texCoord).r;
#endif
#if ALPHA_TEST

View File

@ -1 +1 @@
47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,69,110,116,114,97,110,116,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,118,97,114,121,105,110,103,32,118,101,99,50,32,118,84,101,120,67,111,111,114,100,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,85,110,105,102,111,114,109,101,115,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,77,97,116,101,114,105,97,108,65,108,112,104,97,77,97,112,59,13,10,117,110,105,102,111,114,109,32,102,108,111,97,116,32,77,97,116,101,114,105,97,108,65,108,112,104,97,84,104,114,101,115,104,111,108,100,59,13,10,117,110,105,102,111,114,109,32,118,101,99,52,32,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,59,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,77,97,112,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,70,111,110,99,116,105,111,110,115,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,118,111,105,100,32,109,97,105,110,40,41,13,10,123,13,10,9,118,101,99,52,32,102,114,97,103,109,101,110,116,67,111,108,111,114,32,61,32,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,59,13,10,35,105,102,32,68,73,70,70,85,83,69,95,77,65,80,80,73,78,71,13,10,9,102,114,97,103,109,101,110,116,67,111,108,111,114,32,42,61,32,116,101,120,116,117,114,101,50,68,40,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,77,97,112,44,32,118,84,101,120,67,111,111,114,100,41,59,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,65,76,80,72,65,95,77,65,80,80,73,78,71,13,10,9,102,114,97,103,109,101,110,116,67,111,108,111,114,46,97,32,42,61,32,116,101,120,116,117,114,101,50,68,40,77,97,116,101,114,105,97,108,65,108,112,104,97,77,97,112,44,32,118,84,101,120,67,111,111,114,100,41,46,114,59,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,65,76,80,72,65,95,84,69,83,84,13,10,9,105,102,32,40,102,114,97,103,109,101,110,116,67,111,108,111,114,46,97,32,60,32,77,97,116,101,114,105,97,108,65,108,112,104,97,84,104,114,101,115,104,111,108,100,41,13,10,9,9,100,105,115,99,97,114,100,59,13,10,35,101,110,100,105,102,13,10,13,10,9,103,108,95,70,114,97,103,67,111,108,111,114,32,61,32,102,114,97,103,109,101,110,116,67,111,108,111,114,59,13,10,125,
47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,69,110,116,114,97,110,116,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,118,97,114,121,105,110,103,32,118,101,99,50,32,118,84,101,120,67,111,111,114,100,59,13,10,118,97,114,121,105,110,103,32,118,101,99,52,32,118,67,111,108,111,114,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,85,110,105,102,111,114,109,101,115,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,77,97,116,101,114,105,97,108,65,108,112,104,97,77,97,112,59,13,10,117,110,105,102,111,114,109,32,102,108,111,97,116,32,77,97,116,101,114,105,97,108,65,108,112,104,97,84,104,114,101,115,104,111,108,100,59,13,10,117,110,105,102,111,114,109,32,118,101,99,52,32,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,59,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,77,97,112,59,13,10,117,110,105,102,111,114,109,32,118,101,99,50,32,73,110,118,84,97,114,103,101,116,83,105,122,101,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,70,111,110,99,116,105,111,110,115,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,118,111,105,100,32,109,97,105,110,40,41,13,10,123,13,10,9,118,101,99,52,32,102,114,97,103,109,101,110,116,67,111,108,111,114,32,61,32,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,59,32,42,32,118,67,111,108,111,114,59,13,10,13,10,35,105,102,32,65,85,84,79,95,84,69,88,67,79,79,82,68,83,13,10,9,118,101,99,50,32,116,101,120,67,111,111,114,100,32,61,32,103,108,95,70,114,97,103,67,111,111,114,100,46,120,121,32,42,32,73,110,118,84,97,114,103,101,116,83,105,122,101,59,13,10,35,101,108,115,101,13,10,9,118,101,99,50,32,116,101,120,67,111,111,114,100,32,61,32,118,84,101,120,67,111,111,114,100,59,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,68,73,70,70,85,83,69,95,77,65,80,80,73,78,71,13,10,9,102,114,97,103,109,101,110,116,67,111,108,111,114,32,42,61,32,116,101,120,116,117,114,101,50,68,40,77,97,116,101,114,105,97,108,68,105,102,102,117,115,101,77,97,112,44,32,116,101,120,67,111,111,114,100,41,59,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,65,76,80,72,65,95,77,65,80,80,73,78,71,13,10,9,102,114,97,103,109,101,110,116,67,111,108,111,114,46,97,32,42,61,32,116,101,120,116,117,114,101,50,68,40,77,97,116,101,114,105,97,108,65,108,112,104,97,77,97,112,44,32,116,101,120,67,111,111,114,100,41,46,114,59,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,32,65,76,80,72,65,95,84,69,83,84,13,10,9,105,102,32,40,102,114,97,103,109,101,110,116,67,111,108,111,114,46,97,32,60,32,77,97,116,101,114,105,97,108,65,108,112,104,97,84,104,114,101,115,104,111,108,100,41,13,10,9,9,100,105,115,99,97,114,100,59,13,10,35,101,110,100,105,102,13,10,13,10,9,103,108,95,70,114,97,103,67,111,108,111,114,32,61,32,102,114,97,103,109,101,110,116,67,111,108,111,114,59,13,10,125,

View File

@ -1,10 +1,19 @@
/********************Entrant********************/
#if FLAG_BILLBOARD
varying vec3 InstanceData0; // center
varying vec4 InstanceData1; // size | sin cos
varying vec4 InstanceData2; // color
#else
varying mat4 InstanceData0;
#endif
varying vec4 VertexColor;
varying vec3 VertexPosition;
varying vec2 VertexTexCoord;
/********************Sortant********************/
varying vec2 vTexCoord;
varying vec4 vColor;
/********************Uniformes********************/
uniform float VertexDepth;
@ -14,29 +23,77 @@ uniform mat4 WorldViewProjMatrix;
/********************Fonctions********************/
void main()
{
#if FLAG_INSTANCING
#if TRANSFORM
gl_Position = ViewProjMatrix * InstanceData0 * vec4(VertexPosition, 1.0);
#if FLAG_VERTEXCOLOR
vec4 color = VertexColor;
#else
vec4 color = vec4(1.0);
#endif
vec2 texCoords;
#if FLAG_BILLBOARD
#if FLAG_INSTANCING
vec3 billboardCenter = InstanceData0;
vec2 billboardSize = InstanceData1.xy;
vec2 billboardSinCos = InstanceData1.zw;
vec4 billboardColor = InstanceData2;
vec2 rotatedPosition;
rotatedPosition.x = VertexPosition.x*billboardSinCos.y - VertexPosition.y*billboardSinCos.x;
rotatedPosition.y = VertexPosition.y*billboardSinCos.y + VertexPosition.x*billboardSinCos.x;
rotatedPosition *= billboardSize;
vec3 cameraRight = vec3(ViewMatrix[0][0], ViewMatrix[1][0], ViewMatrix[2][0]);
vec3 cameraUp = vec3(ViewMatrix[0][1], ViewMatrix[1][1], ViewMatrix[2][1]);
vec3 vertexPos = billboardCenter + cameraRight*rotatedPosition.x + cameraUp*rotatedPosition.y;
gl_Position = ViewProjMatrix * vec4(vertexPos, 1.0);
color = billboardColor;
texCoords = VertexPosition.xy + vec2(0.5, 0.5);
#else
#if UNIFORM_VERTEX_DEPTH
gl_Position = InstanceData0 * vec4(VertexPosition.xy, VertexDepth, 1.0);
#else
gl_Position = InstanceData0 * vec4(VertexPosition, 1.0);
#endif
vec2 billboardCorner = VertexTexCoord - vec2(0.5, 0.5);
vec2 billboardSize = VertexUserdata0.xy;
vec2 billboardSinCos = VertexUserdata0.zw;
vec2 rotatedPosition;
rotatedPosition.x = billboardCorner.x*billboardSinCos.y - billboardCorner.y*billboardSinCos.x;
rotatedPosition.y = billboardCorner.y*billboardSinCos.y + billboardCorner.x*billboardSinCos.x;
rotatedPosition *= billboardSize;
vec3 cameraRight = vec3(ViewMatrix[0][0], ViewMatrix[1][0], ViewMatrix[2][0]);
vec3 cameraUp = vec3(ViewMatrix[0][1], ViewMatrix[1][1], ViewMatrix[2][1]);
vec3 vertexPos = VertexPosition + cameraRight*rotatedPosition.x + cameraUp*rotatedPosition.y;
gl_Position = ViewProjMatrix * vec4(vertexPos, 1.0);
texCoords = VertexTexCoord;
#endif
#else
#if TRANSFORM
gl_Position = WorldViewProjMatrix * vec4(VertexPosition, 1.0);
#else
#if UNIFORM_VERTEX_DEPTH
gl_Position = vec4(VertexPosition.xy, VertexDepth, 1.0);
#if FLAG_INSTANCING
#if TRANSFORM
gl_Position = ViewProjMatrix * InstanceData0 * vec4(VertexPosition, 1.0);
#else
gl_Position = vec4(VertexPosition, 1.0);
#if UNIFORM_VERTEX_DEPTH
gl_Position = InstanceData0 * vec4(VertexPosition.xy, VertexDepth, 1.0);
#else
gl_Position = InstanceData0 * vec4(VertexPosition, 1.0);
#endif
#endif
#else
#if TRANSFORM
gl_Position = WorldViewProjMatrix * vec4(VertexPosition, 1.0);
#else
#if UNIFORM_VERTEX_DEPTH
gl_Position = vec4(VertexPosition.xy, VertexDepth, 1.0);
#else
gl_Position = vec4(VertexPosition, 1.0);
#endif
#endif
#endif
texCoords = VertexTexCoord;
#endif
vColor = color;
#if TEXTURE_MAPPING
vTexCoord = vec2(VertexTexCoord);
vTexCoord = vec2(texCoords);
#endif
}

File diff suppressed because one or more lines are too long

View File

@ -1,8 +1,16 @@
/********************Entrant********************/
#if FLAG_BILLBOARD
in vec3 InstanceData0; // center
in vec4 InstanceData1; // size | sin cos
in vec4 InstanceData2; // color
#else
in mat4 InstanceData0;
#endif
in vec4 VertexColor;
in vec3 VertexPosition;
in vec2 VertexTexCoord;
in vec4 VertexUserdata0;
/********************Sortant********************/
out vec4 vColor;
@ -10,6 +18,7 @@ out vec2 vTexCoord;
/********************Uniformes********************/
uniform float VertexDepth;
uniform mat4 ViewMatrix;
uniform mat4 ViewProjMatrix;
uniform mat4 WorldViewProjMatrix;
@ -22,30 +31,72 @@ void main()
vec4 color = vec4(1.0);
#endif
#if FLAG_INSTANCING
#if TRANSFORM
gl_Position = ViewProjMatrix * InstanceData0 * vec4(VertexPosition, 1.0);
vec2 texCoords;
#if FLAG_BILLBOARD
#if FLAG_INSTANCING
vec3 billboardCenter = InstanceData0;
vec2 billboardSize = InstanceData1.xy;
vec2 billboardSinCos = InstanceData1.zw;
vec4 billboardColor = InstanceData2;
vec2 rotatedPosition;
rotatedPosition.x = VertexPosition.x*billboardSinCos.y - VertexPosition.y*billboardSinCos.x;
rotatedPosition.y = VertexPosition.y*billboardSinCos.y + VertexPosition.x*billboardSinCos.x;
rotatedPosition *= billboardSize;
vec3 cameraRight = vec3(ViewMatrix[0][0], ViewMatrix[1][0], ViewMatrix[2][0]);
vec3 cameraUp = vec3(ViewMatrix[0][1], ViewMatrix[1][1], ViewMatrix[2][1]);
vec3 vertexPos = billboardCenter + cameraRight*rotatedPosition.x + cameraUp*rotatedPosition.y;
gl_Position = ViewProjMatrix * vec4(vertexPos, 1.0);
color = billboardColor;
texCoords = VertexPosition.xy + 0.5;
#else
#if UNIFORM_VERTEX_DEPTH
gl_Position = InstanceData0 * vec4(VertexPosition.xy, VertexDepth, 1.0);
#else
gl_Position = InstanceData0 * vec4(VertexPosition, 1.0);
#endif
vec2 billboardCorner = VertexTexCoord - 0.5;
vec2 billboardSize = VertexUserdata0.xy;
vec2 billboardSinCos = VertexUserdata0.zw;
vec2 rotatedPosition;
rotatedPosition.x = billboardCorner.x*billboardSinCos.y - billboardCorner.y*billboardSinCos.x;
rotatedPosition.y = billboardCorner.y*billboardSinCos.y + billboardCorner.x*billboardSinCos.x;
rotatedPosition *= billboardSize;
vec3 cameraRight = vec3(ViewMatrix[0][0], ViewMatrix[1][0], ViewMatrix[2][0]);
vec3 cameraUp = vec3(ViewMatrix[0][1], ViewMatrix[1][1], ViewMatrix[2][1]);
vec3 vertexPos = VertexPosition + cameraRight*rotatedPosition.x + cameraUp*rotatedPosition.y;
gl_Position = ViewProjMatrix * vec4(vertexPos, 1.0);
texCoords = VertexTexCoord;
#endif
#else
#if TRANSFORM
gl_Position = WorldViewProjMatrix * vec4(VertexPosition, 1.0);
#else
#if UNIFORM_VERTEX_DEPTH
gl_Position = vec4(VertexPosition.xy, VertexDepth, 1.0);
#if FLAG_INSTANCING
#if TRANSFORM
gl_Position = ViewProjMatrix * InstanceData0 * vec4(VertexPosition, 1.0);
#else
gl_Position = vec4(VertexPosition, 1.0);
#if UNIFORM_VERTEX_DEPTH
gl_Position = InstanceData0 * vec4(VertexPosition.xy, VertexDepth, 1.0);
#else
gl_Position = InstanceData0 * vec4(VertexPosition, 1.0);
#endif
#endif
#else
#if TRANSFORM
gl_Position = WorldViewProjMatrix * vec4(VertexPosition, 1.0);
#else
#if UNIFORM_VERTEX_DEPTH
gl_Position = vec4(VertexPosition.xy, VertexDepth, 1.0);
#else
gl_Position = vec4(VertexPosition, 1.0);
#endif
#endif
#endif
texCoords = VertexTexCoord;
#endif
vColor = color;
#if TEXTURE_MAPPING
vTexCoord = vec2(VertexTexCoord);
vTexCoord = vec2(texCoords);
#endif
}

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,5 @@
#if FLAG_DEFERRED
#error Deferred Shading needs core profile
#error Deferred Shading is not supported by compatibility shaders
#endif
#define LIGHT_DIRECTIONAL 0
@ -11,6 +11,7 @@ varying mat3 vLightToWorld;
varying vec3 vNormal;
varying vec2 vTexCoord;
varying vec3 vWorldPos;
varying vec4 vColor;
/********************Uniformes********************/
struct Light
@ -24,9 +25,10 @@ struct Light
vec2 parameters3;
};
uniform vec3 EyePosition;
// Lumières
uniform Light Lights[3];
// Matériau
uniform sampler2D MaterialAlphaMap;
uniform float MaterialAlphaThreshold;
uniform vec4 MaterialAmbient;
@ -38,18 +40,27 @@ uniform float MaterialShininess;
uniform vec4 MaterialSpecular;
uniform sampler2D MaterialSpecularMap;
// Autres
uniform vec3 EyePosition;
uniform vec4 SceneAmbient;
/********************Fonctions********************/
void main()
{
vec4 diffuseColor = MaterialDiffuse;
vec4 diffuseColor = MaterialDiffuse * vColor;
#if AUTO_TEXCOORDS
vec2 texCoord = gl_FragCoord.xy * InvTargetSize;
#else
vec2 texCoord = vTexCoord;
#endif
#if DIFFUSE_MAPPING
diffuseColor *= texture(MaterialDiffuseMap, vTexCoord);
diffuseColor *= texture(MaterialDiffuseMap, texCoord);
#endif
#if ALPHA_MAPPING
diffuseColor.a *= texture(MaterialAlphaMap, vTexCoord).r;
diffuseColor.a *= texture(MaterialAlphaMap, texCoord).r;
#endif
#if ALPHA_TEST
@ -63,7 +74,7 @@ void main()
vec3 lightSpecular = vec3(0.0);
#if NORMAL_MAPPING
vec3 normal = normalize(vLightToWorld * (2.0 * vec3(texture(MaterialNormalMap, vTexCoord)) - 1.0));
vec3 normal = normalize(vLightToWorld * (2.0 * vec3(texture(MaterialNormalMap, texCoord)) - 1.0));
#else
vec3 normal = normalize(vNormal);
#endif
@ -206,7 +217,7 @@ void main()
lightSpecular *= MaterialSpecular.rgb;
#if SPECULAR_MAPPING
lightSpecular *= texture(MaterialSpecularMap, vTexCoord).rgb; // Utiliser l'alpha de MaterialSpecular n'aurait aucun sens
lightSpecular *= texture(MaterialSpecularMap, texCoord).rgb; // Utiliser l'alpha de MaterialSpecular n'aurait aucun sens
#endif
vec3 lightColor = (lightAmbient + lightDiffuse + lightSpecular);
@ -215,7 +226,7 @@ void main()
#if EMISSIVE_MAPPING
float lightIntensity = dot(lightColor, vec3(0.3, 0.59, 0.11));
vec3 emissionColor = MaterialDiffuse.rgb * texture(MaterialEmissiveMap, vTexCoord).rgb;
vec3 emissionColor = MaterialDiffuse.rgb * texture(MaterialEmissiveMap, texCoord).rgb;
RenderTarget0 = vec4(mix(fragmentColor.rgb, emissionColor, clamp(1.0 - 3.0*lightIntensity, 0.0, 1.0)), fragmentColor.a);
#else
RenderTarget0 = fragmentColor;

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,12 @@
/********************Entrant********************/
#if FLAG_BILLBOARD
varying vec3 InstanceData0; // center
varying vec4 InstanceData1; // size | sin cos
varying vec4 InstanceData2; // color
#else
varying mat4 InstanceData0;
#endif
varying vec3 VertexPosition;
varying vec3 VertexNormal;
varying vec3 VertexTangent;
@ -10,6 +17,7 @@ varying mat3 vLightToWorld;
varying vec3 vNormal;
varying vec2 vTexCoord;
varying vec3 vWorldPos;
varying vec4 vColor;
/********************Uniformes********************/
uniform float VertexDepth;
@ -20,28 +28,76 @@ uniform mat4 WorldViewProjMatrix;
/********************Fonctions********************/
void main()
{
#if FLAG_INSTANCING
#if TRANSFORM
gl_Position = ViewProjMatrix * InstanceData0 * vec4(VertexPosition, 1.0);
#if FLAG_VERTEXCOLOR
vec4 color = VertexColor;
#else
vec4 color = vec4(1.0);
#endif
vec2 texCoords;
#if FLAG_BILLBOARD
#if FLAG_INSTANCING
vec3 billboardCenter = InstanceData0;
vec2 billboardSize = InstanceData1.xy;
vec2 billboardSinCos = InstanceData1.zw;
vec4 billboardColor = InstanceData2;
vec2 rotatedPosition;
rotatedPosition.x = VertexPosition.x*billboardSinCos.y - VertexPosition.y*billboardSinCos.x;
rotatedPosition.y = VertexPosition.y*billboardSinCos.y + VertexPosition.x*billboardSinCos.x;
rotatedPosition *= billboardSize;
vec3 cameraRight = vec3(ViewMatrix[0][0], ViewMatrix[1][0], ViewMatrix[2][0]);
vec3 cameraUp = vec3(ViewMatrix[0][1], ViewMatrix[1][1], ViewMatrix[2][1]);
vec3 vertexPos = billboardCenter + cameraRight*rotatedPosition.x + cameraUp*rotatedPosition.y;
gl_Position = ViewProjMatrix * vec4(vertexPos, 1.0);
color = billboardColor;
texCoords = VertexPosition.xy + vec2(0.5, 0.5);
#else
#if UNIFORM_VERTEX_DEPTH
gl_Position = InstanceData0 * vec4(VertexPosition.xy, VertexDepth, 1.0);
#else
gl_Position = InstanceData0 * vec4(VertexPosition, 1.0);
#endif
vec2 billboardCorner = VertexTexCoord - vec2(0.5, 0.5);
vec2 billboardSize = VertexUserdata0.xy;
vec2 billboardSinCos = VertexUserdata0.zw;
vec2 rotatedPosition;
rotatedPosition.x = billboardCorner.x*billboardSinCos.y - billboardCorner.y*billboardSinCos.x;
rotatedPosition.y = billboardCorner.y*billboardSinCos.y + billboardCorner.x*billboardSinCos.x;
rotatedPosition *= billboardSize;
vec3 cameraRight = vec3(ViewMatrix[0][0], ViewMatrix[1][0], ViewMatrix[2][0]);
vec3 cameraUp = vec3(ViewMatrix[0][1], ViewMatrix[1][1], ViewMatrix[2][1]);
vec3 vertexPos = VertexPosition + cameraRight*rotatedPosition.x + cameraUp*rotatedPosition.y;
gl_Position = ViewProjMatrix * vec4(vertexPos, 1.0);
texCoords = VertexTexCoord;
#endif
#else
#if TRANSFORM
gl_Position = WorldViewProjMatrix * vec4(VertexPosition, 1.0);
#else
#if UNIFORM_VERTEX_DEPTH
gl_Position = vec4(VertexPosition.xy, VertexDepth, 1.0);
#if FLAG_INSTANCING
#if TRANSFORM
gl_Position = ViewProjMatrix * InstanceData0 * vec4(VertexPosition, 1.0);
#else
gl_Position = vec4(VertexPosition, 1.0);
#if UNIFORM_VERTEX_DEPTH
gl_Position = InstanceData0 * vec4(VertexPosition.xy, VertexDepth, 1.0);
#else
gl_Position = InstanceData0 * vec4(VertexPosition, 1.0);
#endif
#endif
#else
#if TRANSFORM
gl_Position = WorldViewProjMatrix * vec4(VertexPosition, 1.0);
#else
#if UNIFORM_VERTEX_DEPTH
gl_Position = vec4(VertexPosition.xy, VertexDepth, 1.0);
#else
gl_Position = vec4(VertexPosition, 1.0);
#endif
#endif
#endif
texCoords = VertexTexCoord;
#endif
vColor = color;
#if LIGHTING
#if FLAG_INSTANCING
@ -61,11 +117,7 @@ void main()
#endif
#if TEXTURE_MAPPING
#if FLAG_FLIP_UVS
vTexCoord = vec2(VertexTexCoord.x, 1.0 - VertexTexCoord.y);
#else
vTexCoord = VertexTexCoord;
#endif
vTexCoord = vec2(texCoords);
#endif
#if LIGHTING && PARALLAX_MAPPING

File diff suppressed because one or more lines are too long

View File

@ -31,9 +31,10 @@ struct Light
vec2 parameters3;
};
uniform vec3 EyePosition;
// Lumières
uniform Light Lights[3];
// Matériau
uniform sampler2D MaterialAlphaMap;
uniform float MaterialAlphaThreshold;
uniform vec4 MaterialAmbient;
@ -46,8 +47,11 @@ uniform float MaterialShininess;
uniform vec4 MaterialSpecular;
uniform sampler2D MaterialSpecularMap;
// Autres
uniform float ParallaxBias = -0.03;
uniform float ParallaxScale = 0.02;
uniform vec2 InvTargetSize;
uniform vec3 EyePosition;
uniform vec4 SceneAmbient;
uniform sampler2D TextureOverlay;
@ -80,7 +84,13 @@ vec4 EncodeNormal(in vec3 normal)
void main()
{
vec4 diffuseColor = MaterialDiffuse * vColor;
#if AUTO_TEXCOORDS
vec2 texCoord = gl_FragCoord.xy * InvTargetSize;
#else
vec2 texCoord = vTexCoord;
#endif
#if LIGHTING && PARALLAX_MAPPING
float height = texture(MaterialHeightMap, texCoord).r;
float v = height*ParallaxScale + ParallaxBias;
@ -99,7 +109,8 @@ void main()
#if FLAG_DEFERRED
#if ALPHA_TEST
#if ALPHA_MAPPING // Inutile de faire de l'alpha-mapping sans alpha-test en Deferred (l'alpha n'est pas sauvegardé)
// Inutile de faire de l'alpha-mapping sans alpha-test en Deferred (l'alpha n'est pas sauvegardé dans le G-Buffer)
#if ALPHA_MAPPING
diffuseColor.a *= texture(MaterialAlphaMap, texCoord).r;
#endif

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,12 @@
/********************Entrant********************/
#if FLAG_BILLBOARD
in vec3 InstanceData0; // center
in vec4 InstanceData1; // size | sin cos
in vec4 InstanceData2; // color
#else
in mat4 InstanceData0;
#endif
in vec4 VertexColor;
in vec3 VertexPosition;
in vec3 VertexNormal;
@ -30,26 +37,68 @@ void main()
vec4 color = vec4(1.0);
#endif
#if FLAG_INSTANCING
#if TRANSFORM
gl_Position = ViewProjMatrix * InstanceData0 * vec4(VertexPosition, 1.0);
vec2 texCoords;
#if FLAG_BILLBOARD
#if FLAG_INSTANCING
vec3 billboardCenter = InstanceData0;
vec2 billboardSize = InstanceData1.xy;
vec2 billboardSinCos = InstanceData1.zw;
vec4 billboardColor = InstanceData2;
vec2 rotatedPosition;
rotatedPosition.x = VertexPosition.x*billboardSinCos.y - VertexPosition.y*billboardSinCos.x;
rotatedPosition.y = VertexPosition.y*billboardSinCos.y + VertexPosition.x*billboardSinCos.x;
rotatedPosition *= billboardSize;
vec3 cameraRight = vec3(ViewMatrix[0][0], ViewMatrix[1][0], ViewMatrix[2][0]);
vec3 cameraUp = vec3(ViewMatrix[0][1], ViewMatrix[1][1], ViewMatrix[2][1]);
vec3 vertexPos = billboardCenter + cameraRight*rotatedPosition.x + cameraUp*rotatedPosition.y;
gl_Position = ViewProjMatrix * vec4(vertexPos, 1.0);
color = billboardColor;
texCoords = VertexPosition.xy + 0.5;
#else
#if UNIFORM_VERTEX_DEPTH
gl_Position = InstanceData0 * vec4(VertexPosition.xy, VertexDepth, 1.0);
#else
gl_Position = InstanceData0 * vec4(VertexPosition, 1.0);
#endif
vec2 billboardCorner = VertexTexCoord - 0.5;
vec2 billboardSize = VertexUserdata0.xy;
vec2 billboardSinCos = VertexUserdata0.zw;
vec2 rotatedPosition;
rotatedPosition.x = billboardCorner.x*billboardSinCos.y - billboardCorner.y*billboardSinCos.x;
rotatedPosition.y = billboardCorner.y*billboardSinCos.y + billboardCorner.x*billboardSinCos.x;
rotatedPosition *= billboardSize;
vec3 cameraRight = vec3(ViewMatrix[0][0], ViewMatrix[1][0], ViewMatrix[2][0]);
vec3 cameraUp = vec3(ViewMatrix[0][1], ViewMatrix[1][1], ViewMatrix[2][1]);
vec3 vertexPos = VertexPosition + cameraRight*rotatedPosition.x + cameraUp*rotatedPosition.y;
gl_Position = ViewProjMatrix * vec4(vertexPos, 1.0);
texCoords = VertexTexCoord;
#endif
#else
#if TRANSFORM
gl_Position = WorldViewProjMatrix * vec4(VertexPosition, 1.0);
#else
#if UNIFORM_VERTEX_DEPTH
gl_Position = vec4(VertexPosition.xy, VertexDepth, 1.0);
#if FLAG_INSTANCING
#if TRANSFORM
gl_Position = ViewProjMatrix * InstanceData0 * vec4(VertexPosition, 1.0);
#else
gl_Position = vec4(VertexPosition, 1.0);
#if UNIFORM_VERTEX_DEPTH
gl_Position = InstanceData0 * vec4(VertexPosition.xy, VertexDepth, 1.0);
#else
gl_Position = InstanceData0 * vec4(VertexPosition, 1.0);
#endif
#endif
#else
#if TRANSFORM
gl_Position = WorldViewProjMatrix * vec4(VertexPosition, 1.0);
#else
#if UNIFORM_VERTEX_DEPTH
gl_Position = vec4(VertexPosition.xy, VertexDepth, 1.0);
#else
gl_Position = vec4(VertexPosition, 1.0);
#endif
#endif
#endif
texCoords = VertexTexCoord;
#endif
vColor = color;
@ -72,11 +121,7 @@ void main()
#endif
#if TEXTURE_MAPPING
#if FLAG_FLIP_UVS
vTexCoord = vec2(VertexTexCoord.x, 1.0 - VertexTexCoord.y);
#else
vTexCoord = VertexTexCoord;
#endif
#endif
#if LIGHTING && PARALLAX_MAPPING

File diff suppressed because one or more lines are too long

View File

@ -33,6 +33,7 @@ m_verticesUpdated(false)
NzSprite::NzSprite(const NzSprite& sprite) :
NzSceneNode(sprite),
m_boundingVolume(sprite.m_boundingVolume),
m_color(sprite.m_color),
m_material(sprite.m_material),
m_textureCoords(sprite.m_textureCoords),
m_size(sprite.m_size),