Merge remote-tracking branch 'refs/remotes/origin/master' into reflection-mapping
This commit is contained in:
@@ -191,8 +191,8 @@ namespace Nz
|
||||
|
||||
void DeferredRenderQueue::AddMesh(int renderOrder, const Material* material, const MeshData& meshData, const Boxf& meshAABB, const Matrix4f& transformMatrix)
|
||||
{
|
||||
if (material->IsBlendingEnabled())
|
||||
// One transparent material ? I don't like it, go see if I'm in the forward queue
|
||||
if (material->IsBlendingEnabled() || material->IsDepthSortingEnabled()) //< Fixme: Deferred Shading should be able to handle depth sorting
|
||||
// Deferred Shading cannot handle blended objects, put them in the forward list
|
||||
m_forwardQueue->AddMesh(renderOrder, material, meshData, meshAABB, transformMatrix);
|
||||
else
|
||||
{
|
||||
@@ -254,7 +254,7 @@ namespace Nz
|
||||
* \param overlay Texture of the sprites
|
||||
*/
|
||||
|
||||
void DeferredRenderQueue::AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, unsigned int spriteCount, const Texture* overlay)
|
||||
void DeferredRenderQueue::AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, std::size_t spriteCount, const Texture* overlay)
|
||||
{
|
||||
m_forwardQueue->AddSprites(renderOrder, material, vertices, spriteCount, overlay);
|
||||
}
|
||||
|
||||
@@ -351,7 +351,7 @@ namespace Nz
|
||||
* \remark Produces a NazaraAssert if material is invalid
|
||||
*/
|
||||
|
||||
void DepthRenderQueue::AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, unsigned int spriteCount, const Texture* overlay)
|
||||
void DepthRenderQueue::AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, std::size_t spriteCount, const Texture* overlay)
|
||||
{
|
||||
NazaraAssert(material, "Invalid material");
|
||||
NazaraUnused(renderOrder);
|
||||
|
||||
@@ -95,7 +95,7 @@ namespace Nz
|
||||
if (!layer.opaqueModels.empty())
|
||||
DrawOpaqueModels(sceneData, layer);
|
||||
|
||||
if (!layer.basicSprites.empty())
|
||||
if (!layer.opaqueSprites.empty())
|
||||
DrawBasicSprites(sceneData, layer);
|
||||
|
||||
if (!layer.billboards.empty())
|
||||
@@ -219,7 +219,7 @@ namespace Nz
|
||||
Renderer::SetMatrix(MatrixType_World, Matrix4f::Identity());
|
||||
Renderer::SetVertexBuffer(&m_spriteBuffer);
|
||||
|
||||
for (auto& pipelinePair : layer.basicSprites)
|
||||
for (auto& pipelinePair : layer.opaqueSprites)
|
||||
{
|
||||
const MaterialPipeline* pipeline = pipelinePair.first;
|
||||
auto& pipelineEntry = pipelinePair.second;
|
||||
|
||||
@@ -376,23 +376,23 @@ namespace Nz
|
||||
{
|
||||
NazaraAssert(material, "Invalid material");
|
||||
|
||||
if (material->IsBlendingEnabled())
|
||||
if (material->IsDepthSortingEnabled())
|
||||
{
|
||||
Layer& currentLayer = GetLayer(renderOrder);
|
||||
auto& transparentModels = currentLayer.transparentModels;
|
||||
auto& transparentModelData = currentLayer.transparentModelData;
|
||||
auto& transparentMeshes = currentLayer.depthSortedMeshes;
|
||||
auto& transparentData = currentLayer.depthSortedMeshData;
|
||||
|
||||
// The material is transparent, we must draw this mesh using another way (after the rendering of opages objects while sorting them)
|
||||
std::size_t index = transparentModelData.size();
|
||||
transparentModelData.resize(index+1);
|
||||
// The material is marked for depth sorting, we must draw this mesh using another way (after the rendering of opaques objects while sorting them)
|
||||
std::size_t index = transparentData.size();
|
||||
transparentData.resize(index+1);
|
||||
|
||||
TransparentModelData& data = transparentModelData.back();
|
||||
UnbatchedModelData& data = transparentData.back();
|
||||
data.material = material;
|
||||
data.meshData = meshData;
|
||||
data.squaredBoundingSphere = Spheref(transformMatrix.GetTranslation() + meshAABB.GetCenter(), meshAABB.GetSquaredRadius());
|
||||
data.obbSphere = Spheref(transformMatrix.GetTranslation() + meshAABB.GetCenter(), meshAABB.GetSquaredRadius());
|
||||
data.transformMatrix = transformMatrix;
|
||||
|
||||
transparentModels.push_back(index);
|
||||
transparentMeshes.push_back(index);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -457,53 +457,74 @@ namespace Nz
|
||||
*
|
||||
* \remark Produces a NazaraAssert if material is invalid
|
||||
*/
|
||||
void ForwardRenderQueue::AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, unsigned int spriteCount, const Texture* overlay)
|
||||
void ForwardRenderQueue::AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, std::size_t spriteCount, const Texture* overlay)
|
||||
{
|
||||
NazaraAssert(material, "Invalid material");
|
||||
|
||||
Layer& currentLayer = GetLayer(renderOrder);
|
||||
SpritePipelineBatches& basicSprites = currentLayer.basicSprites;
|
||||
|
||||
const MaterialPipeline* materialPipeline = material->GetPipeline();
|
||||
|
||||
auto pipelineIt = basicSprites.find(materialPipeline);
|
||||
if (pipelineIt == basicSprites.end())
|
||||
if (material->IsDepthSortingEnabled())
|
||||
{
|
||||
BatchedSpritePipelineEntry materialEntry;
|
||||
pipelineIt = basicSprites.insert(SpritePipelineBatches::value_type(materialPipeline, std::move(materialEntry))).first;
|
||||
auto& transparentSprites = currentLayer.depthSortedSprites;
|
||||
auto& transparentData = currentLayer.depthSortedSpriteData;
|
||||
|
||||
// The material is marked for depth sorting, we must draw this mesh using another way (after the rendering of opaques objects while sorting them)
|
||||
std::size_t index = transparentData.size();
|
||||
transparentData.resize(index + 1);
|
||||
|
||||
UnbatchedSpriteData& data = transparentData.back();
|
||||
data.material = material;
|
||||
data.overlay = overlay;
|
||||
data.spriteCount = spriteCount;
|
||||
data.vertices = vertices;
|
||||
|
||||
transparentSprites.push_back(index);
|
||||
}
|
||||
|
||||
BatchedSpritePipelineEntry& pipelineEntry = pipelineIt->second;
|
||||
pipelineEntry.enabled = true;
|
||||
|
||||
SpriteMaterialBatches& materialMap = pipelineEntry.materialMap;
|
||||
|
||||
auto matIt = materialMap.find(material);
|
||||
if (matIt == materialMap.end())
|
||||
else
|
||||
{
|
||||
BatchedBasicSpriteEntry entry;
|
||||
entry.materialReleaseSlot.Connect(material->OnMaterialRelease, this, &ForwardRenderQueue::OnMaterialInvalidation);
|
||||
SpritePipelineBatches& sprites = currentLayer.opaqueSprites;
|
||||
|
||||
matIt = materialMap.insert(SpriteMaterialBatches::value_type(material, std::move(entry))).first;
|
||||
const MaterialPipeline* materialPipeline = material->GetPipeline();
|
||||
|
||||
auto pipelineIt = sprites.find(materialPipeline);
|
||||
if (pipelineIt == sprites.end())
|
||||
{
|
||||
BatchedSpritePipelineEntry materialEntry;
|
||||
pipelineIt = sprites.insert(SpritePipelineBatches::value_type(materialPipeline, std::move(materialEntry))).first;
|
||||
}
|
||||
|
||||
BatchedSpritePipelineEntry& pipelineEntry = pipelineIt->second;
|
||||
pipelineEntry.enabled = true;
|
||||
|
||||
SpriteMaterialBatches& materialMap = pipelineEntry.materialMap;
|
||||
|
||||
auto matIt = materialMap.find(material);
|
||||
if (matIt == materialMap.end())
|
||||
{
|
||||
BatchedBasicSpriteEntry entry;
|
||||
entry.materialReleaseSlot.Connect(material->OnMaterialRelease, this, &ForwardRenderQueue::OnMaterialInvalidation);
|
||||
|
||||
matIt = materialMap.insert(SpriteMaterialBatches::value_type(material, std::move(entry))).first;
|
||||
}
|
||||
|
||||
BatchedBasicSpriteEntry& entry = matIt->second;
|
||||
entry.enabled = true;
|
||||
|
||||
auto& overlayMap = entry.overlayMap;
|
||||
|
||||
auto overlayIt = overlayMap.find(overlay);
|
||||
if (overlayIt == overlayMap.end())
|
||||
{
|
||||
BatchedSpriteEntry overlayEntry;
|
||||
if (overlay)
|
||||
overlayEntry.textureReleaseSlot.Connect(overlay->OnTextureRelease, this, &ForwardRenderQueue::OnTextureInvalidation);
|
||||
|
||||
overlayIt = overlayMap.insert(std::make_pair(overlay, std::move(overlayEntry))).first;
|
||||
}
|
||||
|
||||
auto& spriteVector = overlayIt->second.spriteChains;
|
||||
spriteVector.push_back(SpriteChain_XYZ_Color_UV({vertices, spriteCount}));
|
||||
}
|
||||
|
||||
BatchedBasicSpriteEntry& entry = matIt->second;
|
||||
entry.enabled = true;
|
||||
|
||||
auto& overlayMap = entry.overlayMap;
|
||||
|
||||
auto overlayIt = overlayMap.find(overlay);
|
||||
if (overlayIt == overlayMap.end())
|
||||
{
|
||||
BatchedSpriteEntry overlayEntry;
|
||||
if (overlay)
|
||||
overlayEntry.textureReleaseSlot.Connect(overlay->OnTextureRelease, this, &ForwardRenderQueue::OnTextureInvalidation);
|
||||
|
||||
overlayIt = overlayMap.insert(std::make_pair(overlay, std::move(overlayEntry))).first;
|
||||
}
|
||||
|
||||
auto& spriteVector = overlayIt->second.spriteChains;
|
||||
spriteVector.push_back(SpriteChain_XYZ_Color_UV({vertices, spriteCount}));
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -545,7 +566,7 @@ namespace Nz
|
||||
pipelineEntry.enabled = false;
|
||||
}
|
||||
|
||||
for (auto& pipelinePair : layer.basicSprites)
|
||||
for (auto& pipelinePair : layer.opaqueSprites)
|
||||
{
|
||||
auto& pipelineEntry = pipelinePair.second;
|
||||
|
||||
@@ -596,9 +617,11 @@ namespace Nz
|
||||
}
|
||||
}
|
||||
|
||||
layer.depthSortedMeshes.clear();
|
||||
layer.depthSortedMeshData.clear();
|
||||
layer.depthSortedSpriteData.clear();
|
||||
layer.depthSortedSprites.clear();
|
||||
layer.otherDrawables.clear();
|
||||
layer.transparentModels.clear();
|
||||
layer.transparentModelData.clear();
|
||||
++it;
|
||||
}
|
||||
}
|
||||
@@ -613,44 +636,10 @@ namespace Nz
|
||||
|
||||
void ForwardRenderQueue::Sort(const AbstractViewer* viewer)
|
||||
{
|
||||
Planef nearPlane = viewer->GetFrustum().GetPlane(FrustumPlane_Near);
|
||||
Vector3f viewerPos = viewer->GetEyePosition();
|
||||
Vector3f viewerNormal = viewer->GetForward();
|
||||
|
||||
for (auto& pair : layers)
|
||||
{
|
||||
Layer& layer = pair.second;
|
||||
|
||||
std::sort(layer.transparentModels.begin(), layer.transparentModels.end(), [&layer, &nearPlane, &viewerNormal] (std::size_t index1, std::size_t index2)
|
||||
{
|
||||
const Spheref& sphere1 = layer.transparentModelData[index1].squaredBoundingSphere;
|
||||
const Spheref& sphere2 = layer.transparentModelData[index2].squaredBoundingSphere;
|
||||
|
||||
Vector3f position1 = sphere1.GetNegativeVertex(viewerNormal);
|
||||
Vector3f position2 = sphere2.GetNegativeVertex(viewerNormal);
|
||||
|
||||
return nearPlane.Distance(position1) > nearPlane.Distance(position2);
|
||||
});
|
||||
|
||||
for (auto& pipelinePair : layer.billboards)
|
||||
{
|
||||
for (auto& matPair : pipelinePair.second.materialMap)
|
||||
{
|
||||
const Material* mat = matPair.first;
|
||||
|
||||
if (mat->IsDepthSortingEnabled())
|
||||
{
|
||||
BatchedBillboardEntry& entry = matPair.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);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (viewer->GetProjectionType() == ProjectionType_Orthogonal)
|
||||
SortForOrthographic(viewer);
|
||||
else
|
||||
SortForPerspective(viewer);
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -715,12 +704,91 @@ namespace Nz
|
||||
return layer;
|
||||
}
|
||||
|
||||
void ForwardRenderQueue::SortBillboards(Layer& layer, const Planef& nearPlane)
|
||||
{
|
||||
for (auto& pipelinePair : layer.billboards)
|
||||
{
|
||||
for (auto& matPair : pipelinePair.second.materialMap)
|
||||
{
|
||||
const Material* mat = matPair.first;
|
||||
|
||||
if (mat->IsDepthSortingEnabled())
|
||||
{
|
||||
BatchedBillboardEntry& entry = matPair.second;
|
||||
auto& billboardVector = entry.billboards;
|
||||
|
||||
std::sort(billboardVector.begin(), billboardVector.end(), [&nearPlane] (const BillboardData& data1, const BillboardData& data2)
|
||||
{
|
||||
return nearPlane.Distance(data1.center) > nearPlane.Distance(data2.center);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ForwardRenderQueue::SortForOrthographic(const AbstractViewer * viewer)
|
||||
{
|
||||
Planef nearPlane = viewer->GetFrustum().GetPlane(FrustumPlane_Near);
|
||||
Vector3f viewerPos = viewer->GetEyePosition();
|
||||
|
||||
for (auto& pair : layers)
|
||||
{
|
||||
Layer& layer = pair.second;
|
||||
|
||||
std::sort(layer.depthSortedMeshes.begin(), layer.depthSortedMeshes.end(), [&layer, &nearPlane] (std::size_t index1, std::size_t index2)
|
||||
{
|
||||
const Spheref& sphere1 = layer.depthSortedMeshData[index1].obbSphere;
|
||||
const Spheref& sphere2 = layer.depthSortedMeshData[index2].obbSphere;
|
||||
|
||||
return nearPlane.Distance(sphere1.GetPosition()) < nearPlane.Distance(sphere2.GetPosition());
|
||||
});
|
||||
|
||||
std::sort(layer.depthSortedSprites.begin(), layer.depthSortedSprites.end(), [&layer, &nearPlane] (std::size_t index1, std::size_t index2)
|
||||
{
|
||||
const Vector3f& pos1 = layer.depthSortedSpriteData[index1].vertices[0].position;
|
||||
const Vector3f& pos2 = layer.depthSortedSpriteData[index2].vertices[0].position;
|
||||
|
||||
return nearPlane.Distance(pos1) < nearPlane.Distance(pos2);
|
||||
});
|
||||
|
||||
SortBillboards(layer, nearPlane);
|
||||
}
|
||||
}
|
||||
|
||||
void ForwardRenderQueue::SortForPerspective(const AbstractViewer* viewer)
|
||||
{
|
||||
Planef nearPlane = viewer->GetFrustum().GetPlane(FrustumPlane_Near);
|
||||
Vector3f viewerPos = viewer->GetEyePosition();
|
||||
|
||||
for (auto& pair : layers)
|
||||
{
|
||||
Layer& layer = pair.second;
|
||||
|
||||
std::sort(layer.depthSortedMeshes.begin(), layer.depthSortedMeshes.end(), [&layer, &viewerPos] (std::size_t index1, std::size_t index2)
|
||||
{
|
||||
const Spheref& sphere1 = layer.depthSortedMeshData[index1].obbSphere;
|
||||
const Spheref& sphere2 = layer.depthSortedMeshData[index2].obbSphere;
|
||||
|
||||
return viewerPos.SquaredDistance(sphere1.GetPosition()) > viewerPos.SquaredDistance(sphere2.GetPosition());
|
||||
});
|
||||
|
||||
std::sort(layer.depthSortedSprites.begin(), layer.depthSortedSprites.end(), [&layer, &viewerPos] (std::size_t index1, std::size_t index2)
|
||||
{
|
||||
const Vector3f& pos1 = layer.depthSortedSpriteData[index1].vertices[0].position;
|
||||
const Vector3f& pos2 = layer.depthSortedSpriteData[index2].vertices[0].position;
|
||||
|
||||
return viewerPos.SquaredDistance(pos1) > viewerPos.SquaredDistance(pos2);
|
||||
});
|
||||
|
||||
SortBillboards(layer, nearPlane);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Handle the invalidation of an index buffer
|
||||
*
|
||||
* \param indexBuffer Index buffer being invalidated
|
||||
*/
|
||||
|
||||
void ForwardRenderQueue::OnIndexBufferInvalidation(const IndexBuffer* indexBuffer)
|
||||
{
|
||||
for (auto& pair : layers)
|
||||
@@ -757,7 +825,7 @@ namespace Nz
|
||||
{
|
||||
Layer& layer = pair.second;
|
||||
|
||||
for (auto& pipelineEntry : layer.basicSprites)
|
||||
for (auto& pipelineEntry : layer.opaqueSprites)
|
||||
pipelineEntry.second.materialMap.erase(material);
|
||||
|
||||
for (auto& pipelineEntry : layer.billboards)
|
||||
@@ -779,7 +847,7 @@ namespace Nz
|
||||
for (auto& pair : layers)
|
||||
{
|
||||
Layer& layer = pair.second;
|
||||
for (auto& pipelineEntry : layer.basicSprites)
|
||||
for (auto& pipelineEntry : layer.opaqueSprites)
|
||||
{
|
||||
for (auto& materialEntry : pipelineEntry.second.materialMap)
|
||||
materialEntry.second.overlayMap.erase(texture);
|
||||
|
||||
@@ -33,8 +33,8 @@ namespace Nz
|
||||
Vector2f uv;
|
||||
};
|
||||
|
||||
std::size_t s_maxQuads = std::numeric_limits<UInt16>::max() / 6;
|
||||
std::size_t s_vertexBufferSize = 4 * 1024 * 1024; // 4 MiB
|
||||
UInt32 s_maxQuads = std::numeric_limits<UInt16>::max() / 6;
|
||||
UInt32 s_vertexBufferSize = 4 * 1024 * 1024; // 4 MiB
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -101,12 +101,15 @@ namespace Nz
|
||||
if (!layer.opaqueModels.empty())
|
||||
DrawOpaqueModels(sceneData, layer);
|
||||
|
||||
if (!layer.transparentModels.empty())
|
||||
if (!layer.depthSortedMeshes.empty())
|
||||
DrawTransparentModels(sceneData, layer);
|
||||
|
||||
if (!layer.basicSprites.empty())
|
||||
if (!layer.opaqueSprites.empty())
|
||||
DrawBasicSprites(sceneData, layer);
|
||||
|
||||
if (!layer.depthSortedSprites.empty())
|
||||
DrawOrderedSprites(sceneData, layer);
|
||||
|
||||
if (!layer.billboards.empty())
|
||||
DrawBillboards(sceneData, layer);
|
||||
|
||||
@@ -309,7 +312,10 @@ namespace Nz
|
||||
Renderer::SetMatrix(MatrixType_World, Matrix4f::Identity());
|
||||
Renderer::SetVertexBuffer(&m_spriteBuffer);
|
||||
|
||||
for (auto& pipelinePair : layer.basicSprites)
|
||||
const unsigned int overlayTextureUnit = Material::GetTextureUnit(TextureMap_Overlay);
|
||||
const std::size_t maxSpriteCount = std::min<std::size_t>(s_maxQuads, m_spriteBuffer.GetVertexCount() / 4);
|
||||
|
||||
for (auto& pipelinePair : layer.opaqueSprites)
|
||||
{
|
||||
const MaterialPipeline* pipeline = pipelinePair.first;
|
||||
auto& pipelineEntry = pipelinePair.second;
|
||||
@@ -331,6 +337,9 @@ namespace Nz
|
||||
// Position of the camera
|
||||
shader->SendVector(shaderUniforms->eyePosition, sceneData.viewer->GetEyePosition());
|
||||
|
||||
// Overlay texture unit
|
||||
shader->SendInteger(shaderUniforms->textureOverlay, overlayTextureUnit);
|
||||
|
||||
lastShader = shader;
|
||||
}
|
||||
|
||||
@@ -343,10 +352,6 @@ namespace Nz
|
||||
{
|
||||
material->Apply(pipelineInstance);
|
||||
|
||||
unsigned int overlayTextureUnit = Material::GetTextureUnit(TextureMap_Overlay);
|
||||
|
||||
shader->SendInteger(shaderUniforms->textureOverlay, overlayTextureUnit);
|
||||
|
||||
Renderer::SetTextureSampler(overlayTextureUnit, material->GetDiffuseSampler());
|
||||
|
||||
auto& overlayMap = matEntry.overlayMap;
|
||||
@@ -370,7 +375,6 @@ namespace Nz
|
||||
VertexStruct_XYZ_Color_UV* vertices = static_cast<VertexStruct_XYZ_Color_UV*>(vertexMapper.GetPointer());
|
||||
|
||||
std::size_t spriteCount = 0;
|
||||
std::size_t maxSpriteCount = std::min<std::size_t>(s_maxQuads, m_spriteBuffer.GetVertexCount() / 4);
|
||||
|
||||
do
|
||||
{
|
||||
@@ -797,6 +801,142 @@ namespace Nz
|
||||
}
|
||||
}
|
||||
|
||||
void ForwardRenderTechnique::DrawOrderedSprites(const SceneData & sceneData, ForwardRenderQueue::Layer & layer) const
|
||||
{
|
||||
NazaraAssert(sceneData.viewer, "Invalid viewer");
|
||||
|
||||
Renderer::SetIndexBuffer(&s_quadIndexBuffer);
|
||||
Renderer::SetMatrix(MatrixType_World, Matrix4f::Identity());
|
||||
Renderer::SetVertexBuffer(&m_spriteBuffer);
|
||||
|
||||
const Material* lastMaterial = nullptr;
|
||||
const MaterialPipeline* lastPipeline = nullptr;
|
||||
const Shader* lastShader = nullptr;
|
||||
const Texture* lastOverlay = nullptr;
|
||||
const MaterialPipeline::Instance* pipelineInstance = nullptr;
|
||||
|
||||
const unsigned int overlayTextureUnit = Material::GetTextureUnit(TextureMap_Overlay);
|
||||
|
||||
bool updateVertexBuffer = true;
|
||||
const std::size_t maxSpriteCount = std::min<std::size_t>(s_maxQuads, m_spriteBuffer.GetVertexCount() / 4);
|
||||
|
||||
std::size_t alreadyDrawnCount = 0;
|
||||
std::size_t spriteIndex = 0;
|
||||
std::size_t spriteChainOffset = 0;
|
||||
auto splitChainIt = layer.depthSortedSprites.end();
|
||||
|
||||
for (auto it = layer.depthSortedSprites.begin(); it != layer.depthSortedSprites.end();)
|
||||
{
|
||||
if (updateVertexBuffer)
|
||||
{
|
||||
// We open the buffer in writing mode
|
||||
BufferMapper<VertexBuffer> vertexMapper(m_spriteBuffer, BufferAccess_DiscardAndWrite);
|
||||
VertexStruct_XYZ_Color_UV* vertices = static_cast<VertexStruct_XYZ_Color_UV*>(vertexMapper.GetPointer());
|
||||
|
||||
std::size_t availableSpriteSpace = maxSpriteCount;
|
||||
bool split = false;
|
||||
for (auto it2 = it; it2 != layer.depthSortedSprites.end(); ++it2)
|
||||
{
|
||||
const ForwardRenderQueue::UnbatchedSpriteData& spriteData = layer.depthSortedSpriteData[*it2];
|
||||
|
||||
std::size_t count = std::min(availableSpriteSpace, spriteData.spriteCount - spriteChainOffset);
|
||||
|
||||
std::memcpy(vertices, spriteData.vertices + spriteChainOffset * 4, 4 * count * sizeof(VertexStruct_XYZ_Color_UV));
|
||||
vertices += count * 4;
|
||||
|
||||
availableSpriteSpace -= count;
|
||||
|
||||
// Have we treated the entire chain ?
|
||||
if (count != spriteData.spriteCount)
|
||||
{
|
||||
// Oops, not enough space to store current chain
|
||||
spriteChainOffset += count;
|
||||
splitChainIt = it2;
|
||||
split = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// Switch to next sprite chain, if any
|
||||
spriteChainOffset = 0;
|
||||
}
|
||||
|
||||
spriteIndex = 0;
|
||||
updateVertexBuffer = false;
|
||||
|
||||
if (!split)
|
||||
splitChainIt = layer.depthSortedSprites.end();
|
||||
}
|
||||
|
||||
std::size_t index = *it;
|
||||
|
||||
const ForwardRenderQueue::UnbatchedSpriteData& spriteData = layer.depthSortedSpriteData[index];
|
||||
|
||||
const Material* material = spriteData.material;
|
||||
if (material != lastMaterial)
|
||||
{
|
||||
const MaterialPipeline* pipeline = material->GetPipeline();
|
||||
if (pipeline != lastPipeline)
|
||||
{
|
||||
pipelineInstance = &pipeline->Apply(ShaderFlags_TextureOverlay | ShaderFlags_VertexColor);
|
||||
|
||||
const Shader* shader = pipelineInstance->uberInstance->GetShader();
|
||||
|
||||
// Uniforms are conserved in our program, there's no point to send them back until they change
|
||||
if (shader != lastShader)
|
||||
{
|
||||
// Index of uniforms in the shader
|
||||
const ShaderUniforms* shaderUniforms = GetShaderUniforms(shader);
|
||||
|
||||
// Ambient color of the scene
|
||||
shader->SendColor(shaderUniforms->sceneAmbient, sceneData.ambientColor);
|
||||
// Position of the camera
|
||||
shader->SendVector(shaderUniforms->eyePosition, sceneData.viewer->GetEyePosition());
|
||||
// Overlay texture unit
|
||||
shader->SendInteger(shaderUniforms->textureOverlay, overlayTextureUnit);
|
||||
|
||||
lastShader = shader;
|
||||
}
|
||||
|
||||
lastPipeline = pipeline;
|
||||
}
|
||||
|
||||
material->Apply(*pipelineInstance);
|
||||
|
||||
Renderer::SetTextureSampler(overlayTextureUnit, material->GetDiffuseSampler());
|
||||
|
||||
lastMaterial = material;
|
||||
}
|
||||
|
||||
const Texture* overlay = (spriteData.overlay) ? spriteData.overlay : &m_whiteTexture;
|
||||
if (overlay != lastOverlay)
|
||||
{
|
||||
Renderer::SetTexture(overlayTextureUnit, overlay);
|
||||
lastOverlay = overlay;
|
||||
}
|
||||
|
||||
std::size_t spriteCount;
|
||||
if (it != splitChainIt)
|
||||
{
|
||||
spriteCount = spriteData.spriteCount - alreadyDrawnCount;
|
||||
alreadyDrawnCount = 0;
|
||||
|
||||
++it;
|
||||
}
|
||||
else
|
||||
{
|
||||
spriteCount = spriteChainOffset;
|
||||
|
||||
alreadyDrawnCount = spriteCount;
|
||||
updateVertexBuffer = true;
|
||||
|
||||
// Restart at current iterator next time
|
||||
}
|
||||
|
||||
Renderer::DrawIndexedPrimitives(PrimitiveMode_TriangleList, spriteIndex * 6, spriteCount * 6);
|
||||
spriteIndex += spriteCount;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Draws transparent models
|
||||
*
|
||||
@@ -816,9 +956,9 @@ namespace Nz
|
||||
const ShaderUniforms* shaderUniforms = nullptr;
|
||||
unsigned int lightCount = 0;
|
||||
|
||||
for (unsigned int index : layer.transparentModels)
|
||||
for (std::size_t index : layer.depthSortedMeshes)
|
||||
{
|
||||
const ForwardRenderQueue::TransparentModelData& modelData = layer.transparentModelData[index];
|
||||
const ForwardRenderQueue::UnbatchedModelData& modelData = layer.depthSortedMeshData[index];
|
||||
|
||||
// Material
|
||||
const Material* material = modelData.material;
|
||||
@@ -885,8 +1025,8 @@ namespace Nz
|
||||
if (shaderUniforms->hasLightUniforms && lightCount < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS)
|
||||
{
|
||||
// Compute the closest lights
|
||||
Vector3f position = matrix.GetTranslation() + modelData.squaredBoundingSphere.GetPosition();
|
||||
float radius = modelData.squaredBoundingSphere.radius;
|
||||
Vector3f position = matrix.GetTranslation() + modelData.obbSphere.GetPosition();
|
||||
float radius = modelData.obbSphere.radius;
|
||||
ChooseLights(Spheref(position, radius), false);
|
||||
|
||||
for (std::size_t i = lightCount; i < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS; ++i)
|
||||
|
||||
@@ -198,6 +198,7 @@ namespace Nz
|
||||
pipelineInfo.blending = true;
|
||||
pipelineInfo.depthWrite = false;
|
||||
pipelineInfo.faceCulling = false;
|
||||
pipelineInfo.depthSorting = true;
|
||||
pipelineInfo.dstBlend = BlendFunc_InvSrcAlpha;
|
||||
pipelineInfo.srcBlend = BlendFunc_SrcAlpha;
|
||||
|
||||
@@ -208,6 +209,7 @@ namespace Nz
|
||||
pipelineInfo.depthBuffer = true;
|
||||
pipelineInfo.depthWrite = false;
|
||||
pipelineInfo.faceCulling = false;
|
||||
pipelineInfo.depthSorting = true;
|
||||
pipelineInfo.dstBlend = BlendFunc_InvSrcAlpha;
|
||||
pipelineInfo.srcBlend = BlendFunc_SrcAlpha;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user