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:
@@ -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);
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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();
|
||||
|
||||
14
src/Nazara/Graphics/ParticleController.cpp
Normal file
14
src/Nazara/Graphics/ParticleController.cpp
Normal 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;
|
||||
231
src/Nazara/Graphics/ParticleDeclaration.cpp
Normal file
231
src/Nazara/Graphics/ParticleDeclaration.cpp
Normal 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];
|
||||
69
src/Nazara/Graphics/ParticleEmitter.cpp
Normal file
69
src/Nazara/Graphics/ParticleEmitter.cpp
Normal 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;
|
||||
}
|
||||
14
src/Nazara/Graphics/ParticleGenerator.cpp
Normal file
14
src/Nazara/Graphics/ParticleGenerator.cpp
Normal 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;
|
||||
15
src/Nazara/Graphics/ParticleMapper.cpp
Normal file
15
src/Nazara/Graphics/ParticleMapper.cpp
Normal 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;
|
||||
14
src/Nazara/Graphics/ParticleRenderer.cpp
Normal file
14
src/Nazara/Graphics/ParticleRenderer.cpp
Normal 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;
|
||||
365
src/Nazara/Graphics/ParticleSystem.cpp
Normal file
365
src/Nazara/Graphics/ParticleSystem.cpp
Normal 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();
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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),
|
||||
|
||||
Reference in New Issue
Block a user