Graphics/Widgets: Add support for scissoring

This commit is contained in:
Jérôme Leclercq
2021-12-01 20:26:33 +01:00
parent a483e16e15
commit 61779d1cad
21 changed files with 137 additions and 35 deletions

View File

@@ -46,7 +46,7 @@ namespace Nz
const auto& vertexBuffer = m_graphicalMesh->GetVertexBuffer(i);
const auto& renderPipeline = materialPass->GetPipeline()->GetRenderPipeline(submeshData.vertexBufferData);
elements.emplace_back(std::make_unique<RenderSubmesh>(GetRenderLayer(), materialPass, renderPipeline, worldInstance, m_graphicalMesh->GetIndexCount(i), indexBuffer, vertexBuffer));
elements.emplace_back(std::make_unique<RenderSubmesh>(GetRenderLayer(), materialPass, renderPipeline, worldInstance, m_graphicalMesh->GetIndexCount(i), indexBuffer, vertexBuffer, GetScissorBox()));
}
}

View File

@@ -39,7 +39,7 @@ namespace Nz
const auto& whiteTexture = Graphics::Instance()->GetDefaultTextures().whiteTextures[UnderlyingCast(ImageType::E2D)];
elements.emplace_back(std::make_unique<RenderSpriteChain>(GetRenderLayer(), materialPass, renderPipeline, worldInstance, vertexDeclaration, whiteTexture, m_spriteCount, m_vertices.data()));
elements.emplace_back(std::make_unique<RenderSpriteChain>(GetRenderLayer(), materialPass, renderPipeline, worldInstance, vertexDeclaration, whiteTexture, m_spriteCount, m_vertices.data(), GetScissorBox()));
}
const std::shared_ptr<Material>& SlicedSprite::GetMaterial(std::size_t i) const

View File

@@ -42,7 +42,7 @@ namespace Nz
const auto& whiteTexture = Graphics::Instance()->GetDefaultTextures().whiteTextures[UnderlyingCast(ImageType::E2D)];
elements.emplace_back(std::make_unique<RenderSpriteChain>(GetRenderLayer(), materialPass, renderPipeline, worldInstance, vertexDeclaration, whiteTexture, 1, m_vertices.data()));
elements.emplace_back(std::make_unique<RenderSpriteChain>(GetRenderLayer(), materialPass, renderPipeline, worldInstance, vertexDeclaration, whiteTexture, 1, m_vertices.data(), GetScissorBox()));
}
const std::shared_ptr<Material>& Sprite::GetMaterial(std::size_t i) const

View File

@@ -59,6 +59,8 @@ namespace Nz
auto& data = static_cast<SpriteChainRendererData&>(rendererData);
Recti invalidScissorBox(-1, -1, -1, -1);
std::size_t firstQuadIndex = 0;
SpriteChainRendererData::DrawCall* currentDrawCall = nullptr;
UploadPool::Allocation* currentAllocation = nullptr;
@@ -70,6 +72,7 @@ namespace Nz
const ShaderBinding* currentShaderBinding = nullptr;
const Texture* currentTextureOverlay = nullptr;
const WorldInstance* currentWorldInstance = nullptr;
Recti currentScissorBox = invalidScissorBox;
auto FlushDrawCall = [&]()
{
@@ -149,6 +152,14 @@ namespace Nz
currentTextureOverlay = textureOverlay;
}
const Recti& scissorBox = spriteChain.GetScissorBox();
const Recti& targetScissorBox = (scissorBox.width >= 0) ? scissorBox : invalidScissorBox;
if (currentScissorBox != targetScissorBox)
{
FlushDrawData();
currentScissorBox = targetScissorBox;
}
std::size_t remainingQuads = spriteChain.GetSpriteCount();
const UInt8* spriteData = static_cast<const UInt8*>(spriteChain.GetSpriteData());
@@ -236,6 +247,7 @@ namespace Nz
currentShaderBinding,
6 * firstQuadIndex,
0,
currentScissorBox
});
currentDrawCall = &data.drawCalls.back();
@@ -287,15 +299,19 @@ namespace Nz
}
}
void SpriteChainRenderer::Render(const ViewerInstance& /*viewerInstance*/, ElementRendererData& rendererData, CommandBufferBuilder& commandBuffer, const Pointer<const RenderElement>* elements, std::size_t /*elementCount*/)
void SpriteChainRenderer::Render(const ViewerInstance& viewerInstance, ElementRendererData& rendererData, CommandBufferBuilder& commandBuffer, const Pointer<const RenderElement>* elements, std::size_t /*elementCount*/)
{
auto& data = static_cast<SpriteChainRendererData&>(rendererData);
commandBuffer.BindIndexBuffer(*m_indexBuffer);
Vector2f targetSize = viewerInstance.GetTargetSize();
Recti fullscreenScissorBox(0, 0, SafeCast<int>(std::floor(targetSize.x)), SafeCast<int>(std::floor(targetSize.y)));
const AbstractBuffer* currentVertexBuffer = nullptr;
const RenderPipeline* currentPipeline = nullptr;
const ShaderBinding* currentShaderBinding = nullptr;
Recti currentScissorBox(-1, -1, -1, -1);
const RenderSpriteChain* firstSpriteChain = static_cast<const RenderSpriteChain*>(elements[0]);
auto it = data.drawCallPerElement.find(firstSpriteChain);
@@ -305,27 +321,34 @@ namespace Nz
for (std::size_t i = 0; i < indices.count; ++i)
{
const auto& drawCall = data.drawCalls[indices.start + i];
const auto& drawData = data.drawCalls[indices.start + i];
if (currentVertexBuffer != drawCall.vertexBuffer)
if (currentVertexBuffer != drawData.vertexBuffer)
{
commandBuffer.BindVertexBuffer(0, *drawCall.vertexBuffer);
currentVertexBuffer = drawCall.vertexBuffer;
commandBuffer.BindVertexBuffer(0, *drawData.vertexBuffer);
currentVertexBuffer = drawData.vertexBuffer;
}
if (currentPipeline != drawCall.renderPipeline)
if (currentPipeline != drawData.renderPipeline)
{
commandBuffer.BindPipeline(*drawCall.renderPipeline);
currentPipeline = drawCall.renderPipeline;
commandBuffer.BindPipeline(*drawData.renderPipeline);
currentPipeline = drawData.renderPipeline;
}
if (currentShaderBinding != drawCall.shaderBinding)
if (currentShaderBinding != drawData.shaderBinding)
{
commandBuffer.BindShaderBinding(0, *drawCall.shaderBinding);
currentShaderBinding = drawCall.shaderBinding;
commandBuffer.BindShaderBinding(0, *drawData.shaderBinding);
currentShaderBinding = drawData.shaderBinding;
}
commandBuffer.DrawIndexed(drawCall.quadCount * 6, 1U, drawCall.firstIndex);
const Recti& targetScissorBox = (drawData.scissorBox.width >= 0) ? drawData.scissorBox : fullscreenScissorBox;
if (currentScissorBox != targetScissorBox)
{
commandBuffer.SetScissor(targetScissorBox);
currentScissorBox = targetScissorBox;
}
commandBuffer.DrawIndexed(SafeCast<UInt32>(drawData.quadCount * 6), 1U, SafeCast<UInt32>(drawData.firstIndex));
}
}

View File

@@ -27,12 +27,15 @@ namespace Nz
auto& data = static_cast<SubmeshRendererData&>(rendererData);
Recti invalidScissorBox(-1, -1, -1, -1);
const AbstractBuffer* currentIndexBuffer = nullptr;
const AbstractBuffer* currentVertexBuffer = nullptr;
const MaterialPass* currentMaterialPass = nullptr;
const RenderPipeline* currentPipeline = nullptr;
const ShaderBinding* currentShaderBinding = nullptr;
const WorldInstance* currentWorldInstance = nullptr;
Recti currentScissorBox = invalidScissorBox;
auto FlushDrawCall = [&]()
{
@@ -86,6 +89,14 @@ namespace Nz
currentWorldInstance = worldInstance;
}
const Recti& scissorBox = submesh.GetScissorBox();
const Recti& targetScissorBox = (scissorBox.width >= 0) ? scissorBox : invalidScissorBox;
if (currentScissorBox != targetScissorBox)
{
FlushDrawData();
currentScissorBox = targetScissorBox;
}
if (!currentShaderBinding)
{
m_bindingCache.clear();
@@ -140,19 +151,24 @@ namespace Nz
drawCall.indexBuffer = currentIndexBuffer;
drawCall.indexCount = submesh.GetIndexCount();
drawCall.renderPipeline = currentPipeline;
drawCall.scissorBox = currentScissorBox;
drawCall.shaderBinding = currentShaderBinding;
drawCall.vertexBuffer = currentVertexBuffer;
}
}
void SubmeshRenderer::Render(const ViewerInstance& /*viewerInstance*/, ElementRendererData& rendererData, CommandBufferBuilder& commandBuffer, const Pointer<const RenderElement>* /*elements*/, std::size_t /*elementCount*/)
void SubmeshRenderer::Render(const ViewerInstance& viewerInstance, ElementRendererData& rendererData, CommandBufferBuilder& commandBuffer, const Pointer<const RenderElement>* /*elements*/, std::size_t /*elementCount*/)
{
auto& data = static_cast<SubmeshRendererData&>(rendererData);
Vector2f targetSize = viewerInstance.GetTargetSize();
Recti fullscreenScissorBox(0, 0, SafeCast<int>(std::floor(targetSize.x)), SafeCast<int>(std::floor(targetSize.y)));
const AbstractBuffer* currentIndexBuffer = nullptr;
const AbstractBuffer* currentVertexBuffer = nullptr;
const RenderPipeline* currentPipeline = nullptr;
const ShaderBinding* currentShaderBinding = nullptr;
Recti currentScissorBox(-1, -1, -1, -1);
for (const auto& drawData : data.drawCalls)
{
@@ -180,10 +196,17 @@ namespace Nz
currentVertexBuffer = drawData.vertexBuffer;
}
const Recti& targetScissorBox = (drawData.scissorBox.width >= 0) ? drawData.scissorBox : fullscreenScissorBox;
if (currentScissorBox != targetScissorBox)
{
commandBuffer.SetScissor(targetScissorBox);
currentScissorBox = targetScissorBox;
}
if (currentIndexBuffer)
commandBuffer.DrawIndexed(drawData.indexCount);
commandBuffer.DrawIndexed(SafeCast<UInt32>(drawData.indexCount));
else
commandBuffer.Draw(drawData.indexCount);
commandBuffer.Draw(SafeCast<UInt32>(drawData.indexCount));
}
}

View File

@@ -42,7 +42,7 @@ namespace Nz
RenderIndices& indices = pair.second;
if (indices.count > 0)
elements.emplace_back(std::make_unique<RenderSpriteChain>(GetRenderLayer(), materialPass, renderPipeline, worldInstance, vertexDeclaration, key.texture->shared_from_this(), indices.count, &m_vertices[indices.first * 4]));
elements.emplace_back(std::make_unique<RenderSpriteChain>(GetRenderLayer(), materialPass, renderPipeline, worldInstance, vertexDeclaration, key.texture->shared_from_this(), indices.count, &m_vertices[indices.first * 4], GetScissorBox()));
}
}

View File

@@ -382,12 +382,18 @@ namespace Nz
scissorRect = parentScissorRect;
}
/*Recti fullBounds(scissorRect);
scissorRect.y = GetCanvas()->GetSize().y - scissorRect.height - scissorRect.y; //< scissor rect is in screen coordinates
Recti fullBounds(scissorRect);
auto& registry = GetRegistry();
for (WidgetEntity& widgetEntity : m_entities)
{
const Ndk::EntityHandle& entity = widgetEntity.handle;
if (entity->HasComponent<GraphicsComponent>())
entity->GetComponent<GraphicsComponent>().SetScissorRect(fullBounds);
}*/
if (GraphicsComponent* gfx = registry.try_get<GraphicsComponent>(widgetEntity.handle))
{
for (const auto& renderable : gfx->GetRenderables())
renderable.renderable->UpdateScissorBox(fullBounds);
}
}
}
}

View File

@@ -19,6 +19,7 @@ namespace Nz
m_cursorController(cursorController)
{
m_canvas = this;
BaseWidget::m_registry = &m_registry;
m_widgetParent = nullptr;
SetBaseRenderLayer(initialRenderLayer);