Merge branch 'master' into automatic-file-fix

This commit is contained in:
Jérôme Leclercq
2021-10-28 09:57:59 +02:00
committed by GitHub
55 changed files with 780 additions and 517 deletions

View File

@@ -152,6 +152,20 @@ namespace Nz
std::move(defaultValues)
});
// Common data
settings.textures.push_back({
3,
"TextureOverlay",
ImageType::E2D
});
settings.sharedUniformBlocks.push_back(PredefinedInstanceData::GetUniformBlock(4, ShaderStageType::Vertex));
settings.sharedUniformBlocks.push_back(PredefinedViewerData::GetUniformBlock(5, ShaderStageType_All));
settings.predefinedBindings[UnderlyingCast(PredefinedShaderBinding::InstanceDataUbo)] = 4;
settings.predefinedBindings[UnderlyingCast(PredefinedShaderBinding::OverlayTexture)] = 3;
settings.predefinedBindings[UnderlyingCast(PredefinedShaderBinding::ViewerDataUbo)] = 5;
settings.shaders = std::move(uberShaders);
for (std::shared_ptr<UberShader> uberShader : settings.shaders)

View File

@@ -9,7 +9,7 @@ namespace Nz
{
ElementRenderer::~ElementRenderer() = default;
void ElementRenderer::Prepare(ElementRendererData& /*rendererData*/, RenderFrame& /*currentFrame*/, const Pointer<const RenderElement>* /*elements*/, std::size_t /*elementCount*/)
void ElementRenderer::Prepare(const ViewerInstance& /*viewerInstance*/, ElementRendererData& /*rendererData*/, RenderFrame& /*currentFrame*/, const Pointer<const RenderElement>* /*elements*/, std::size_t /*elementCount*/)
{
}

View File

@@ -61,21 +61,21 @@ namespace Nz
{
if (newMaterial)
{
if (MaterialPass* pass = newMaterial->GetPass(m_depthPassIndex))
RegisterMaterialPass(pass);
if (const auto& pass = newMaterial->GetPass(m_depthPassIndex))
RegisterMaterialPass(pass.get());
if (MaterialPass* pass = newMaterial->GetPass(m_forwardPassIndex))
RegisterMaterialPass(pass);
if (const auto& pass = newMaterial->GetPass(m_forwardPassIndex))
RegisterMaterialPass(pass.get());
}
const auto& prevMaterial = instancedRenderable->GetMaterial(materialIndex);
if (prevMaterial)
{
if (MaterialPass* pass = prevMaterial->GetPass(m_depthPassIndex))
UnregisterMaterialPass(pass);
if (const auto& pass = prevMaterial->GetPass(m_depthPassIndex))
UnregisterMaterialPass(pass.get());
if (MaterialPass* pass = prevMaterial->GetPass(m_forwardPassIndex))
UnregisterMaterialPass(pass);
if (const auto& pass = prevMaterial->GetPass(m_forwardPassIndex))
UnregisterMaterialPass(pass.get());
}
for (auto&& [viewer, viewerData] : m_viewers)
@@ -90,11 +90,11 @@ namespace Nz
{
if (Material* mat = instancedRenderable->GetMaterial(i).get())
{
if (MaterialPass* pass = mat->GetPass(m_depthPassIndex))
RegisterMaterialPass(pass);
if (const auto& pass = mat->GetPass(m_depthPassIndex))
RegisterMaterialPass(pass.get());
if (MaterialPass* pass = mat->GetPass(m_forwardPassIndex))
RegisterMaterialPass(pass);
if (const auto& pass = mat->GetPass(m_forwardPassIndex))
RegisterMaterialPass(pass.get());
}
}
@@ -157,7 +157,7 @@ namespace Nz
{
viewerData.rebuildDepthPrepass = true;
viewerData.rebuildForwardPass = true;
prepare = true;
viewerData.prepare = true;
}
}
}
@@ -215,7 +215,7 @@ namespace Nz
{
viewerData.rebuildDepthPrepass = true;
viewerData.rebuildForwardPass = true;
prepare = true;
viewerData.prepare = true;
viewerData.visibilityHash = visibilityHash;
}
@@ -264,46 +264,42 @@ namespace Nz
});
}
if (prepare)
for (auto&& [viewer, viewerData] : m_viewers)
{
if (!viewerData.prepare)
continue;
for (std::size_t i = 0; i < m_elementRenderers.size(); ++i)
{
auto& elementRendererPtr = m_elementRenderers[i];
for (auto&& [_, viewerData] : m_viewers)
if (i >= viewerData.elementRendererData.size() || !viewerData.elementRendererData[i])
{
if (i >= viewerData.elementRendererData.size() || !viewerData.elementRendererData[i])
{
if (i >= viewerData.elementRendererData.size())
viewerData.elementRendererData.resize(i + 1);
if (i >= viewerData.elementRendererData.size())
viewerData.elementRendererData.resize(i + 1);
viewerData.elementRendererData[i] = elementRendererPtr->InstanciateData();
}
if (elementRendererPtr)
elementRendererPtr->Reset(*viewerData.elementRendererData[i], renderFrame);
viewerData.elementRendererData[i] = elementRendererPtr->InstanciateData();
}
if (elementRendererPtr)
elementRendererPtr->Reset(*viewerData.elementRendererData[i], renderFrame);
}
for (auto&& [_, viewerData] : m_viewers)
auto& rendererData = viewerData.elementRendererData;
const auto& viewerInstance = viewer->GetViewerInstance();
ProcessRenderQueue(viewerData.depthPrepassRenderQueue, [&](std::size_t elementType, const Pointer<const RenderElement>* elements, std::size_t elementCount)
{
auto& rendererData = viewerData.elementRendererData;
ElementRenderer& elementRenderer = *m_elementRenderers[elementType];
elementRenderer.Prepare(viewerInstance, *rendererData[elementType], renderFrame, elements, elementCount);
});
ProcessRenderQueue(viewerData.depthPrepassRenderQueue, [&](std::size_t elementType, const Pointer<const RenderElement>* elements, std::size_t elementCount)
{
ElementRenderer& elementRenderer = *m_elementRenderers[elementType];
elementRenderer.Prepare(*rendererData[elementType], renderFrame, elements, elementCount);
});
ProcessRenderQueue(viewerData.forwardRenderQueue, [&](std::size_t elementType, const Pointer<const RenderElement>* elements, std::size_t elementCount)
{
ElementRenderer& elementRenderer = *m_elementRenderers[elementType];
elementRenderer.Prepare(*rendererData[elementType], renderFrame, elements, elementCount);
});
viewerData.rebuildForwardPass = true;
viewerData.rebuildDepthPrepass = true;
}
ProcessRenderQueue(viewerData.forwardRenderQueue, [&](std::size_t elementType, const Pointer<const RenderElement>* elements, std::size_t elementCount)
{
ElementRenderer& elementRenderer = *m_elementRenderers[elementType];
elementRenderer.Prepare(viewerInstance, *rendererData[elementType], renderFrame, elements, elementCount);
});
}
if (m_bakedFrameGraph.Resize(renderFrame))
@@ -335,6 +331,7 @@ namespace Nz
{
viewerData.rebuildForwardPass = false;
viewerData.rebuildDepthPrepass = false;
viewerData.prepare = false;
const RenderTarget& renderTarget = viewer->GetRenderTarget();
Recti renderRegion(0, 0, frameSize.x, frameSize.y);
@@ -388,17 +385,17 @@ namespace Nz
else
{
m_removedWorldInstances.insert(worldInstance);
m_renderables.erase(instanceIt);;
m_renderables.erase(instanceIt);
}
std::size_t matCount = instancedRenderable->GetMaterialCount();
for (std::size_t i = 0; i < matCount; ++i)
{
if (MaterialPass* pass = instancedRenderable->GetMaterial(i)->GetPass(m_depthPassIndex))
UnregisterMaterialPass(pass);
if (const auto& pass = instancedRenderable->GetMaterial(i)->GetPass(m_depthPassIndex))
UnregisterMaterialPass(pass.get());
if (MaterialPass* pass = instancedRenderable->GetMaterial(i)->GetPass(m_forwardPassIndex))
UnregisterMaterialPass(pass);
if (const auto& pass = instancedRenderable->GetMaterial(i)->GetPass(m_forwardPassIndex))
UnregisterMaterialPass(pass.get());
}
for (auto&& [viewer, viewerData] : m_viewers)
@@ -454,12 +451,12 @@ namespace Nz
builder.SetScissor(viewport);
builder.SetViewport(viewport);
builder.BindShaderBinding(Graphics::ViewerBindingSet, viewer->GetViewerInstance().GetShaderBinding());
const auto& viewerInstance = viewer->GetViewerInstance();
ProcessRenderQueue(viewerData.depthPrepassRenderQueue, [&](std::size_t elementType, const Pointer<const RenderElement>* elements, std::size_t elementCount)
{
ElementRenderer& elementRenderer = *m_elementRenderers[elementType];
elementRenderer.Render(*viewerData.elementRendererData[elementType], builder, elements, elementCount);
elementRenderer.Render(viewerInstance, *viewerData.elementRendererData[elementType], builder, elements, elementCount);
});
});
@@ -486,12 +483,12 @@ namespace Nz
builder.SetScissor(viewport);
builder.SetViewport(viewport);
builder.BindShaderBinding(Graphics::ViewerBindingSet, viewer->GetViewerInstance().GetShaderBinding());
const auto& viewerInstance = viewer->GetViewerInstance();
ProcessRenderQueue(viewerData.forwardRenderQueue, [&](std::size_t elementType, const Pointer<const RenderElement>* elements, std::size_t elementCount)
{
ElementRenderer& elementRenderer = *m_elementRenderers[elementType];
elementRenderer.Render(*viewerData.elementRendererData[elementType], builder, elements, elementCount);
elementRenderer.Render(viewerInstance , *viewerData.elementRendererData[elementType], builder, elements, elementCount);
});
});
}

View File

@@ -67,13 +67,6 @@ namespace Nz
MaterialPipeline::Initialize();
RenderPipelineLayoutInfo referenceLayoutInfo;
FillDrawDataPipelineLayout(referenceLayoutInfo);
FillViewerPipelineLayout(referenceLayoutInfo);
FillWorldPipelineLayout(referenceLayoutInfo);
m_referencePipelineLayout = m_renderDevice->InstantiateRenderPipelineLayout(std::move(referenceLayoutInfo));
BuildDefaultTextures();
BuildFullscreenVertexBuffer();
BuildBlitPipeline();
@@ -117,7 +110,7 @@ namespace Nz
m_fullscreenVertexDeclaration.reset();
m_blitPipeline.reset();
m_blitPipelineLayout.reset();
m_defaultTextures.whiteTexture2d.reset();
m_defaultTextures.whiteTextures.fill(nullptr);
}
void Graphics::FillDrawDataPipelineLayout(RenderPipelineLayoutInfo& layoutInfo, UInt32 set)
@@ -191,10 +184,15 @@ namespace Nz
texInfo.pixelFormat = PixelFormat::L8;
texInfo.type = ImageType::E2D;
std::array<UInt8, 4> texData = { 0xFF, 0xFF, 0xFF, 0xFF };
std::array<UInt8, 6> whitePixels = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
m_defaultTextures.whiteTexture2d = m_renderDevice->InstantiateTexture(texInfo);
m_defaultTextures.whiteTexture2d->Update(texData.data());
for (std::size_t i = 0; i < ImageTypeCount; ++i)
{
texInfo.type = static_cast<ImageType>(i);
m_defaultTextures.whiteTextures[i] = m_renderDevice->InstantiateTexture(texInfo);
m_defaultTextures.whiteTextures[i]->Update(whitePixels.data());
}
}
}

View File

@@ -29,8 +29,7 @@ namespace Nz
MaterialPass::MaterialPass(std::shared_ptr<const MaterialSettings> settings) :
m_settings(std::move(settings)),
m_forceCommandBufferRegeneration(false),
m_pipelineUpdated(false),
m_shaderBindingUpdated(false)
m_pipelineUpdated(false)
{
m_pipelineInfo.settings = m_settings;
@@ -44,14 +43,14 @@ namespace Nz
const auto& textureSettings = m_settings->GetTextures();
const auto& uboSettings = m_settings->GetUniformBlocks();
m_textures.resize(m_settings->GetTextures().size());
m_textures.resize(textureSettings.size());
m_uniformBuffers.reserve(m_settings->GetUniformBlocks().size());
for (const auto& uniformBufferInfo : m_settings->GetUniformBlocks())
m_uniformBuffers.reserve(uboSettings.size());
for (const auto& uniformBufferInfo : uboSettings)
{
auto& uniformBuffer = m_uniformBuffers.emplace_back();
uniformBuffer.buffer = Graphics::Instance()->GetRenderDevice()->InstantiateBuffer(Nz::BufferType::Uniform);
uniformBuffer.buffer = Graphics::Instance()->GetRenderDevice()->InstantiateBuffer(BufferType::Uniform);
if (!uniformBuffer.buffer->Initialize(uniformBufferInfo.blockSize, BufferUsage::Dynamic))
throw std::runtime_error("failed to initialize UBO memory");
@@ -60,20 +59,60 @@ namespace Nz
uniformBuffer.data.resize(uniformBufferInfo.blockSize);
std::memcpy(uniformBuffer.data.data(), uniformBufferInfo.defaultValues.data(), uniformBufferInfo.defaultValues.size());
}
}
UpdateShaderBinding();
void MaterialPass::FillShaderBinding(std::vector<ShaderBinding::Binding>& bindings) const
{
const auto& textureSettings = m_settings->GetTextures();
const auto& uboSettings = m_settings->GetUniformBlocks();
// Textures
for (std::size_t i = 0; i < m_textures.size(); ++i)
{
const auto& textureSetting = textureSettings[i];
const auto& textureSlot = m_textures[i];
if (!textureSlot.sampler)
{
TextureSamplerCache& samplerCache = Graphics::Instance()->GetSamplerCache();
textureSlot.sampler = samplerCache.Get(textureSlot.samplerInfo);
}
//TODO: Use "missing" texture
Texture* texture = textureSlot.texture.get();
if (!texture)
{
const auto& defaultTextures = Graphics::Instance()->GetDefaultTextures();
texture = defaultTextures.whiteTextures[UnderlyingCast(textureSetting.type)].get();
}
bindings.push_back({
textureSetting.bindingIndex,
ShaderBinding::TextureBinding {
texture, textureSlot.sampler.get()
}
});
}
// Shared UBO (TODO)
// Owned UBO
for (std::size_t i = 0; i < m_uniformBuffers.size(); ++i)
{
const auto& uboSetting = uboSettings[i];
const auto& uboSlot = m_uniformBuffers[i];
bindings.push_back({
uboSetting.bindingIndex,
ShaderBinding::UniformBufferBinding {
uboSlot.buffer.get(), 0, uboSlot.buffer->GetSize()
}
});
}
}
bool MaterialPass::Update(RenderFrame& renderFrame, CommandBufferBuilder& builder)
{
if (!m_shaderBindingUpdated)
{
renderFrame.PushForRelease(std::move(m_shaderBinding));
m_shaderBinding.reset();
UpdateShaderBinding();
}
UploadPool& uploadPool = renderFrame.GetUploadPool();
for (auto& ubo : m_uniformBuffers)
@@ -118,60 +157,4 @@ namespace Nz
m_pipeline = MaterialPipeline::Get(m_pipelineInfo);
m_pipelineUpdated = true;
}
void MaterialPass::UpdateShaderBinding()
{
assert(!m_shaderBinding);
const auto& textureSettings = m_settings->GetTextures();
const auto& uboSettings = m_settings->GetUniformBlocks();
// TODO: Use StackVector
std::vector<ShaderBinding::Binding> bindings;
// Textures
for (std::size_t i = 0; i < m_textures.size(); ++i)
{
const auto& textureSetting = textureSettings[i];
const auto& textureSlot = m_textures[i];
if (!textureSlot.sampler)
{
TextureSamplerCache& samplerCache = Graphics::Instance()->GetSamplerCache();
textureSlot.sampler = samplerCache.Get(textureSlot.samplerInfo);
}
//TODO: Use "missing" texture
if (textureSlot.texture)
{
bindings.push_back({
textureSetting.bindingIndex,
ShaderBinding::TextureBinding {
textureSlot.texture.get(), textureSlot.sampler.get()
}
});
}
}
// Shared UBO (TODO)
// Owned UBO
for (std::size_t i = 0; i < m_uniformBuffers.size(); ++i)
{
const auto& uboSetting = uboSettings[i];
const auto& uboSlot = m_uniformBuffers[i];
bindings.push_back({
uboSetting.bindingIndex,
ShaderBinding::UniformBufferBinding {
uboSlot.buffer.get(), 0, uboSlot.buffer->GetSize()
}
});
}
m_shaderBinding = m_settings->GetRenderPipelineLayout()->AllocateShaderBinding(Graphics::MaterialBindingSet);
m_shaderBinding->Update(bindings.data(), bindings.size());
m_shaderBindingUpdated = true;
}
}

View File

@@ -37,7 +37,7 @@ namespace Nz
{
const auto& submeshData = m_submeshes[i];
MaterialPass* materialPass = submeshData.material->GetPass(passIndex);
const auto& materialPass = submeshData.material->GetPass(passIndex);
if (!materialPass)
continue;
@@ -45,7 +45,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>(0, renderPipeline, m_graphicalMesh->GetIndexCount(i), indexBuffer, vertexBuffer, worldInstance, materialPass->GetShaderBinding(), materialPass->GetFlags()));
elements.emplace_back(std::make_unique<RenderSubmesh>(0, materialPass, renderPipeline, worldInstance, m_graphicalMesh->GetIndexCount(i), indexBuffer, vertexBuffer));
}
}

View File

@@ -8,7 +8,7 @@
namespace Nz
{
PredefinedLightData PredefinedLightData::GetOffset()
PredefinedLightData PredefinedLightData::GetOffsets()
{
PredefinedLightData lightData;
@@ -34,7 +34,7 @@ namespace Nz
MaterialSettings::SharedUniformBlock PredefinedLightData::GetUniformBlock()
{
PredefinedLightData lightData = GetOffset();
PredefinedLightData lightData = GetOffsets();
std::vector<MaterialSettings::UniformVariable> lightDataVariables;
for (std::size_t i = 0; i < lightData.lightArray.size(); ++i)
@@ -67,6 +67,27 @@ namespace Nz
return instanceData;
}
MaterialSettings::SharedUniformBlock PredefinedInstanceData::GetUniformBlock(UInt32 bindingIndex, ShaderStageTypeFlags shaderStages)
{
PredefinedInstanceData instanceData = GetOffsets();
std::vector<MaterialSettings::UniformVariable> variables = {
{
{ "WorldMatrix", instanceData.worldMatrixOffset },
{ "InvWorldMatrix", instanceData.invWorldMatrixOffset }
}
};
MaterialSettings::SharedUniformBlock uniformBlock = {
bindingIndex,
"InstanceData",
std::move(variables),
shaderStages
};
return uniformBlock;
}
PredefinedViewerData PredefinedViewerData::GetOffsets()
{
FieldOffsets viewerStruct(StructLayout::Std140);
@@ -86,4 +107,33 @@ namespace Nz
return viewerData;
}
MaterialSettings::SharedUniformBlock PredefinedViewerData::GetUniformBlock(UInt32 bindingIndex, ShaderStageTypeFlags shaderStages)
{
PredefinedViewerData viewerData = GetOffsets();
std::vector<MaterialSettings::UniformVariable> variables = {
{
{ "EyePosition", viewerData.eyePositionOffset },
{ "InvProjMatrix", viewerData.invProjMatrixOffset },
{ "InvTargetSize", viewerData.invTargetSizeOffset },
{ "InvViewMatrix", viewerData.invViewMatrixOffset },
{ "InvViewProjMatrix", viewerData.invViewProjMatrixOffset },
{ "ProjMatrix", viewerData.projMatrixOffset },
{ "TargetSize", viewerData.targetSizeOffset },
{ "ViewMatrix", viewerData.viewMatrixOffset },
{ "ViewProjMatrix", viewerData.viewProjMatrixOffset }
}
};
MaterialSettings::SharedUniformBlock uniformBlock = {
bindingIndex,
"ViewerData",
std::move(variables),
shaderStages
};
return uniformBlock;
}
}

View File

@@ -40,12 +40,12 @@ struct ViewerData
external
{
[set(0), binding(0)] viewerData: uniform<ViewerData>,
[set(1), binding(0)] instanceData: uniform<InstanceData>,
[set(2), binding(0)] TextureOverlay: sampler2D<f32>,
[set(3), binding(0)] settings: uniform<BasicSettings>,
[set(3), binding(2)] MaterialAlphaMap: sampler2D<f32>,
[set(3), binding(1)] MaterialDiffuseMap: sampler2D<f32>
[binding(0)] settings: uniform<BasicSettings>,
[binding(1)] MaterialDiffuseMap: sampler2D<f32>,
[binding(2)] MaterialAlphaMap: sampler2D<f32>,
[binding(3)] TextureOverlay: sampler2D<f32>,
[binding(4)] instanceData: uniform<InstanceData>,
[binding(5)] viewerData: uniform<ViewerData>,
}
// Fragment stage

View File

@@ -34,12 +34,12 @@ struct ViewerData
external
{
[set(0), binding(0)] viewerData: uniform<ViewerData>,
[set(1), binding(0)] instanceData: uniform<InstanceData>,
[set(2), binding(0)] TextureOverlay: sampler2D<f32>,
[set(3), binding(0)] settings: uniform<BasicSettings>,
[set(3), binding(2)] MaterialAlphaMap: sampler2D<f32>,
[set(3), binding(1)] MaterialDiffuseMap: sampler2D<f32>
[binding(0)] settings: uniform<BasicSettings>,
[binding(1)] MaterialDiffuseMap: sampler2D<f32>,
[binding(2)] MaterialAlphaMap: sampler2D<f32>,
[binding(3)] TextureOverlay: sampler2D<f32>,
[binding(4)] instanceData: uniform<InstanceData>,
[binding(5)] viewerData: uniform<ViewerData>,
}
// Fragment stage

View File

@@ -24,7 +24,7 @@ namespace Nz
void Sprite::BuildElement(std::size_t passIndex, const WorldInstance& worldInstance, std::vector<std::unique_ptr<RenderElement>>& elements) const
{
MaterialPass* materialPass = m_material->GetPass(passIndex);
const auto& materialPass = m_material->GetPass(passIndex);
if (!materialPass)
return;
@@ -40,9 +40,9 @@ namespace Nz
};
const auto& renderPipeline = materialPass->GetPipeline()->GetRenderPipeline(vertexBufferData);
const auto& whiteTexture = Graphics::Instance()->GetDefaultTextures().whiteTexture2d;
const auto& whiteTexture = Graphics::Instance()->GetDefaultTextures().whiteTextures[UnderlyingCast(ImageType::E2D)];
elements.emplace_back(std::make_unique<RenderSpriteChain>(0, renderPipeline, vertexDeclaration, whiteTexture, 1, m_vertices.data(), materialPass->GetShaderBinding(), worldInstance, materialPass->GetFlags()));
elements.emplace_back(std::make_unique<RenderSpriteChain>(0, materialPass, renderPipeline, worldInstance, vertexDeclaration, whiteTexture, 1, m_vertices.data()));
}
inline const Color& Sprite::GetColor() const

View File

@@ -5,6 +5,7 @@
#include <Nazara/Graphics/SpriteChainRenderer.hpp>
#include <Nazara/Graphics/Graphics.hpp>
#include <Nazara/Graphics/RenderSpriteChain.hpp>
#include <Nazara/Graphics/ViewerInstance.hpp>
#include <Nazara/Renderer/CommandBufferBuilder.hpp>
#include <Nazara/Renderer/RenderFrame.hpp>
#include <Nazara/Renderer/UploadPool.hpp>
@@ -52,7 +53,7 @@ namespace Nz
return std::make_unique<SpriteChainRendererData>();
}
void SpriteChainRenderer::Prepare(ElementRendererData& rendererData, RenderFrame& currentFrame, const Pointer<const RenderElement>* elements, std::size_t elementCount)
void SpriteChainRenderer::Prepare(const ViewerInstance& viewerInstance, ElementRendererData& rendererData, RenderFrame& currentFrame, const Pointer<const RenderElement>* elements, std::size_t elementCount)
{
Graphics* graphics = Graphics::Instance();
@@ -65,10 +66,9 @@ namespace Nz
const VertexDeclaration* currentVertexDeclaration = nullptr;
AbstractBuffer* currentVertexBuffer = nullptr;
const RenderPipeline* currentPipeline = nullptr;
const ShaderBinding* currentDrawDataBinding = nullptr;
const ShaderBinding* currentInstanceBinding = nullptr;
const ShaderBinding* currentMaterialBinding = nullptr;
const ShaderBinding* currentShaderBinding = nullptr;
const Texture* currentTextureOverlay = nullptr;
const WorldInstance* currentWorldInstance = nullptr;
auto FlushDrawCall = [&]()
{
@@ -79,7 +79,7 @@ namespace Nz
{
FlushDrawCall();
currentDrawDataBinding = nullptr;
currentShaderBinding = nullptr;
};
auto Flush = [&]()
@@ -122,24 +122,18 @@ namespace Nz
currentVertexDeclaration = vertexDeclaration;
}
if (currentPipeline != spriteChain.GetRenderPipeline())
if (currentPipeline != &spriteChain.GetRenderPipeline())
{
FlushDrawCall();
currentPipeline = spriteChain.GetRenderPipeline();
currentPipeline = &spriteChain.GetRenderPipeline();
}
if (currentMaterialBinding != &spriteChain.GetMaterialBinding())
{
FlushDrawCall();
currentMaterialBinding = &spriteChain.GetMaterialBinding();
}
if (currentInstanceBinding != &spriteChain.GetInstanceBinding())
if (currentWorldInstance != &spriteChain.GetWorldInstance())
{
// TODO: Flushing draw calls on instance binding means we can have e.g. 1000 sprites rendered using a draw call for each one
// which is far from being efficient, using some bindless could help (or at least instancing?)
FlushDrawCall();
currentInstanceBinding = &spriteChain.GetInstanceBinding();
FlushDrawData();
currentWorldInstance = &spriteChain.GetWorldInstance();
}
if (currentTextureOverlay != spriteChain.GetTextureOverlay())
@@ -177,19 +171,52 @@ namespace Nz
data.vertexBuffers.emplace_back(std::move(vertexBuffer));
}
if (!currentDrawDataBinding)
if (!currentShaderBinding)
{
ShaderBindingPtr drawDataBinding = Graphics::Instance()->GetReferencePipelineLayout()->AllocateShaderBinding(Graphics::DrawDataBindingSet);
drawDataBinding->Update({
{
0,
ShaderBinding::TextureBinding {
currentTextureOverlay, defaultSampler.get()
}
}
});
m_bindingCache.clear();
currentDrawDataBinding = drawDataBinding.get();
const MaterialPass& materialPass = spriteChain.GetMaterialPass();
materialPass.FillShaderBinding(m_bindingCache);
// Predefined shader bindings
const auto& matSettings = materialPass.GetSettings();
if (std::size_t bindingIndex = matSettings->GetPredefinedBinding(PredefinedShaderBinding::InstanceDataUbo); bindingIndex != MaterialSettings::InvalidIndex)
{
const auto& instanceBuffer = currentWorldInstance->GetInstanceBuffer();
auto& bindingEntry = m_bindingCache.emplace_back();
bindingEntry.bindingIndex = bindingIndex;
bindingEntry.content = ShaderBinding::UniformBufferBinding{
instanceBuffer.get(),
0, instanceBuffer->GetSize()
};
}
if (std::size_t bindingIndex = matSettings->GetPredefinedBinding(PredefinedShaderBinding::ViewerDataUbo); bindingIndex != MaterialSettings::InvalidIndex)
{
const auto& viewerBuffer = viewerInstance.GetViewerBuffer();
auto& bindingEntry = m_bindingCache.emplace_back();
bindingEntry.bindingIndex = bindingIndex;
bindingEntry.content = ShaderBinding::UniformBufferBinding{
viewerBuffer.get(),
0, viewerBuffer->GetSize()
};
}
if (std::size_t bindingIndex = matSettings->GetPredefinedBinding(PredefinedShaderBinding::OverlayTexture); bindingIndex != MaterialSettings::InvalidIndex)
{
auto& bindingEntry = m_bindingCache.emplace_back();
bindingEntry.bindingIndex = bindingIndex;
bindingEntry.content = ShaderBinding::TextureBinding{
currentTextureOverlay, defaultSampler.get()
};
}
ShaderBindingPtr drawDataBinding = currentPipeline->GetPipelineInfo().pipelineLayout->AllocateShaderBinding(0);
drawDataBinding->Update(m_bindingCache.data(), m_bindingCache.size());
currentShaderBinding = drawDataBinding.get();
data.shaderBindings.emplace_back(std::move(drawDataBinding));
}
@@ -199,9 +226,7 @@ namespace Nz
data.drawCalls.push_back(SpriteChainRendererData::DrawCall{
currentVertexBuffer,
currentPipeline,
currentDrawDataBinding,
currentInstanceBinding,
currentMaterialBinding,
currentShaderBinding,
6 * firstQuadIndex,
0,
});
@@ -255,7 +280,7 @@ namespace Nz
}
}
void SpriteChainRenderer::Render(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);
@@ -263,9 +288,9 @@ namespace Nz
const AbstractBuffer* currentVertexBuffer = nullptr;
const RenderPipeline* currentPipeline = nullptr;
const ShaderBinding* currentDrawDataBinding = nullptr;
const ShaderBinding* currentInstanceBinding = nullptr;
const ShaderBinding* currentMaterialBinding = nullptr;
const ShaderBinding* currentShaderBinding = nullptr;
const ViewerInstance* currentViewerInstance = nullptr;
const WorldInstance* currentWorldInstance = nullptr;
const RenderSpriteChain* firstSpriteChain = static_cast<const RenderSpriteChain*>(elements[0]);
auto it = data.drawCallPerElement.find(firstSpriteChain);
@@ -289,22 +314,10 @@ namespace Nz
currentPipeline = drawCall.renderPipeline;
}
if (currentDrawDataBinding != drawCall.drawDataBinding)
if (currentShaderBinding != drawCall.shaderBinding)
{
commandBuffer.BindShaderBinding(Graphics::DrawDataBindingSet, *drawCall.drawDataBinding);
currentDrawDataBinding = drawCall.drawDataBinding;
}
if (currentMaterialBinding != drawCall.materialBinding)
{
commandBuffer.BindShaderBinding(Graphics::MaterialBindingSet, *drawCall.materialBinding);
currentMaterialBinding = drawCall.materialBinding;
}
if (currentInstanceBinding != drawCall.instanceBinding)
{
commandBuffer.BindShaderBinding(Graphics::WorldBindingSet, *drawCall.instanceBinding);
currentInstanceBinding = drawCall.instanceBinding;
commandBuffer.BindShaderBinding(0, *drawCall.shaderBinding);
currentShaderBinding = drawCall.shaderBinding;
}
commandBuffer.DrawIndexed(drawCall.quadCount * 6, 1U, drawCall.firstIndex);

View File

@@ -5,41 +5,48 @@
#include <Nazara/Graphics/SubmeshRenderer.hpp>
#include <Nazara/Graphics/Graphics.hpp>
#include <Nazara/Graphics/RenderSubmesh.hpp>
#include <Nazara/Graphics/ViewerInstance.hpp>
#include <Nazara/Renderer/CommandBufferBuilder.hpp>
#include <Nazara/Renderer/RenderFrame.hpp>
#include <Nazara/Graphics/Debug.hpp>
namespace Nz
{
SubmeshRenderer::SubmeshRenderer()
{
Graphics* graphics = Graphics::Instance();
const auto& whiteTexture = graphics->GetDefaultTextures().whiteTexture2d;
const auto& defaultSampler = graphics->GetSamplerCache().Get({});
m_renderDataBinding = graphics->GetReferencePipelineLayout()->AllocateShaderBinding(Graphics::DrawDataBindingSet);
m_renderDataBinding->Update({
{
0,
ShaderBinding::TextureBinding {
whiteTexture.get(), defaultSampler.get()
}
}
});
}
std::unique_ptr<ElementRendererData> SubmeshRenderer::InstanciateData()
{
return {};
return std::make_unique<SubmeshRendererData>();
}
void SubmeshRenderer::Render(ElementRendererData& /*rendererData*/, CommandBufferBuilder& commandBuffer, const Pointer<const RenderElement>* elements, std::size_t elementCount)
void SubmeshRenderer::Prepare(const ViewerInstance& viewerInstance, ElementRendererData& rendererData, RenderFrame& /*currentFrame*/, const Pointer<const RenderElement>* elements, std::size_t elementCount)
{
Graphics* graphics = Graphics::Instance();
auto& data = static_cast<SubmeshRendererData&>(rendererData);
const AbstractBuffer* currentIndexBuffer = nullptr;
const AbstractBuffer* currentVertexBuffer = nullptr;
const RenderPipeline* currentPipeline = nullptr;
const ShaderBinding* currentMaterialBinding = nullptr;
const ShaderBinding* currentShaderBinding = nullptr;
const WorldInstance* currentWorldInstance = nullptr;
commandBuffer.BindShaderBinding(Graphics::DrawDataBindingSet, *m_renderDataBinding);
auto FlushDrawCall = [&]()
{
// Does nothing for now (but will serve once instancing is implemented)
};
auto FlushDrawData = [&]()
{
FlushDrawCall();
currentShaderBinding = nullptr;
};
const auto& whiteTexture = Graphics::Instance()->GetDefaultTextures().whiteTextures[UnderlyingCast(ImageType::E2D)];
const auto& defaultSampler = graphics->GetSamplerCache().Get({});
for (std::size_t i = 0; i < elementCount; ++i)
{
@@ -48,34 +55,139 @@ namespace Nz
if (const RenderPipeline* pipeline = submesh.GetRenderPipeline(); currentPipeline != pipeline)
{
commandBuffer.BindPipeline(*pipeline);
FlushDrawCall();
currentPipeline = pipeline;
}
if (const ShaderBinding* materialBinding = &submesh.GetMaterialBinding(); currentMaterialBinding != materialBinding)
{
commandBuffer.BindShaderBinding(Graphics::MaterialBindingSet, *materialBinding);
currentMaterialBinding = materialBinding;
}
if (const AbstractBuffer* indexBuffer = submesh.GetIndexBuffer(); currentIndexBuffer != indexBuffer)
{
commandBuffer.BindIndexBuffer(*indexBuffer);
FlushDrawCall();
currentIndexBuffer = indexBuffer;
}
if (const AbstractBuffer* vertexBuffer = submesh.GetVertexBuffer(); currentVertexBuffer != vertexBuffer)
{
commandBuffer.BindVertexBuffer(0, *vertexBuffer);
FlushDrawCall();
currentVertexBuffer = vertexBuffer;
}
commandBuffer.BindShaderBinding(Graphics::WorldBindingSet, submesh.GetInstanceBinding());
if (currentWorldInstance != &submesh.GetWorldInstance())
{
// TODO: Flushing draw calls on instance binding means we can have e.g. 1000 sprites rendered using a draw call for each one
// which is far from being efficient, using some bindless could help (or at least instancing?)
FlushDrawData();
currentWorldInstance = &submesh.GetWorldInstance();
}
if (currentIndexBuffer)
commandBuffer.DrawIndexed(submesh.GetIndexCount());
else
commandBuffer.Draw(submesh.GetIndexCount());
if (!currentShaderBinding)
{
m_bindingCache.clear();
const MaterialPass& materialPass = submesh.GetMaterialPass();
materialPass.FillShaderBinding(m_bindingCache);
// Predefined shader bindings
const auto& matSettings = materialPass.GetSettings();
if (std::size_t bindingIndex = matSettings->GetPredefinedBinding(PredefinedShaderBinding::InstanceDataUbo); bindingIndex != MaterialSettings::InvalidIndex)
{
const auto& instanceBuffer = currentWorldInstance->GetInstanceBuffer();
auto& bindingEntry = m_bindingCache.emplace_back();
bindingEntry.bindingIndex = bindingIndex;
bindingEntry.content = ShaderBinding::UniformBufferBinding{
instanceBuffer.get(),
0, instanceBuffer->GetSize()
};
}
if (std::size_t bindingIndex = matSettings->GetPredefinedBinding(PredefinedShaderBinding::ViewerDataUbo); bindingIndex != MaterialSettings::InvalidIndex)
{
const auto& viewerBuffer = viewerInstance.GetViewerBuffer();
auto& bindingEntry = m_bindingCache.emplace_back();
bindingEntry.bindingIndex = bindingIndex;
bindingEntry.content = ShaderBinding::UniformBufferBinding{
viewerBuffer.get(),
0, viewerBuffer->GetSize()
};
}
if (std::size_t bindingIndex = matSettings->GetPredefinedBinding(PredefinedShaderBinding::OverlayTexture); bindingIndex != MaterialSettings::InvalidIndex)
{
auto& bindingEntry = m_bindingCache.emplace_back();
bindingEntry.bindingIndex = bindingIndex;
bindingEntry.content = ShaderBinding::TextureBinding{
whiteTexture.get(), defaultSampler.get()
};
}
ShaderBindingPtr drawDataBinding = currentPipeline->GetPipelineInfo().pipelineLayout->AllocateShaderBinding(0);
drawDataBinding->Update(m_bindingCache.data(), m_bindingCache.size());
currentShaderBinding = drawDataBinding.get();
data.shaderBindings.emplace_back(std::move(drawDataBinding));
}
auto& drawCall = data.drawCalls.emplace_back();
drawCall.indexBuffer = currentIndexBuffer;
drawCall.indexCount = submesh.GetIndexCount();
drawCall.renderPipeline = currentPipeline;
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*/)
{
auto& data = static_cast<SubmeshRendererData&>(rendererData);
const AbstractBuffer* currentIndexBuffer = nullptr;
const AbstractBuffer* currentVertexBuffer = nullptr;
const RenderPipeline* currentPipeline = nullptr;
const ShaderBinding* currentShaderBinding = nullptr;
for (const auto& drawData : data.drawCalls)
{
if (currentPipeline != drawData.renderPipeline)
{
commandBuffer.BindPipeline(*drawData.renderPipeline);
currentPipeline = drawData.renderPipeline;
}
if (currentShaderBinding != drawData.shaderBinding)
{
commandBuffer.BindShaderBinding(0, *drawData.shaderBinding);
currentShaderBinding = drawData.shaderBinding;
}
if (currentIndexBuffer != drawData.indexBuffer)
{
commandBuffer.BindIndexBuffer(*drawData.indexBuffer);
currentIndexBuffer = drawData.indexBuffer;
}
if (currentVertexBuffer != drawData.vertexBuffer)
{
commandBuffer.BindVertexBuffer(0, *drawData.vertexBuffer);
currentVertexBuffer = drawData.vertexBuffer;
}
if (currentIndexBuffer)
commandBuffer.DrawIndexed(drawData.indexCount);
else
commandBuffer.Draw(drawData.indexCount);
}
}
void SubmeshRenderer::Reset(ElementRendererData& rendererData, RenderFrame& currentFrame)
{
auto& data = static_cast<SubmeshRendererData&>(rendererData);
for (auto& shaderBinding : data.shaderBindings)
currentFrame.PushForRelease(std::move(shaderBinding));
data.shaderBindings.clear();
data.drawCalls.clear();
}
}

View File

@@ -20,7 +20,7 @@ namespace Nz
void TextSprite::BuildElement(std::size_t passIndex, const WorldInstance& worldInstance, std::vector<std::unique_ptr<RenderElement>>& elements) const
{
MaterialPass* materialPass = m_material->GetPass(passIndex);
const auto& materialPass = m_material->GetPass(passIndex);
if (!materialPass)
return;
@@ -42,7 +42,7 @@ namespace Nz
RenderIndices& indices = pair.second;
if (indices.count > 0)
elements.emplace_back(std::make_unique<RenderSpriteChain>(0, renderPipeline, vertexDeclaration, key.texture->shared_from_this(), indices.count, &m_vertices[indices.first * 4], materialPass->GetShaderBinding(), worldInstance, materialPass->GetFlags()));
elements.emplace_back(std::make_unique<RenderSpriteChain>(0, materialPass, renderPipeline, worldInstance, vertexDeclaration, key.texture->shared_from_this(), indices.count, &m_vertices[indices.first * 4]));
}
}

View File

@@ -14,49 +14,39 @@
namespace Nz
{
ViewerInstance::ViewerInstance() :
m_invProjectionMatrix(Nz::Matrix4f::Identity()),
m_invViewProjMatrix(Nz::Matrix4f::Identity()),
m_invViewMatrix(Nz::Matrix4f::Identity()),
m_projectionMatrix(Nz::Matrix4f::Identity()),
m_viewProjMatrix(Nz::Matrix4f::Identity()),
m_viewMatrix(Nz::Matrix4f::Identity()),
m_targetSize(Nz::Vector2f(0.f, 0.f)),
m_invProjectionMatrix(Matrix4f::Identity()),
m_invViewProjMatrix(Matrix4f::Identity()),
m_invViewMatrix(Matrix4f::Identity()),
m_projectionMatrix(Matrix4f::Identity()),
m_viewProjMatrix(Matrix4f::Identity()),
m_viewMatrix(Matrix4f::Identity()),
m_targetSize(Vector2f(0.f, 0.f)),
m_dataInvalided(true)
{
Nz::PredefinedViewerData viewerUboOffsets = Nz::PredefinedViewerData::GetOffsets();
PredefinedViewerData viewerUboOffsets = PredefinedViewerData::GetOffsets();
m_viewerDataBuffer = Graphics::Instance()->GetRenderDevice()->InstantiateBuffer(BufferType::Uniform);
if (!m_viewerDataBuffer->Initialize(viewerUboOffsets.totalSize, Nz::BufferUsage::DeviceLocal | Nz::BufferUsage::Dynamic))
if (!m_viewerDataBuffer->Initialize(viewerUboOffsets.totalSize, BufferUsage::DeviceLocal | BufferUsage::Dynamic))
throw std::runtime_error("failed to initialize viewer data UBO");
m_shaderBinding = Graphics::Instance()->GetReferencePipelineLayout()->AllocateShaderBinding(Graphics::ViewerBindingSet);
m_shaderBinding->Update({
{
0,
ShaderBinding::UniformBufferBinding {
m_viewerDataBuffer.get(), 0, m_viewerDataBuffer->GetSize()
}
}
});
}
void ViewerInstance::UpdateBuffers(UploadPool& uploadPool, CommandBufferBuilder& builder)
{
if (m_dataInvalided)
{
Nz::PredefinedViewerData viewerDataOffsets = Nz::PredefinedViewerData::GetOffsets();
PredefinedViewerData viewerDataOffsets = PredefinedViewerData::GetOffsets();
auto& allocation = uploadPool.Allocate(viewerDataOffsets.totalSize);
Nz::AccessByOffset<Nz::Vector3f&>(allocation.mappedPtr, viewerDataOffsets.eyePositionOffset) = m_viewMatrix.GetTranslation();
Nz::AccessByOffset<Nz::Vector2f&>(allocation.mappedPtr, viewerDataOffsets.invTargetSizeOffset) = 1.f / m_targetSize;
Nz::AccessByOffset<Nz::Vector2f&>(allocation.mappedPtr, viewerDataOffsets.targetSizeOffset) = m_targetSize;
AccessByOffset<Vector3f&>(allocation.mappedPtr, viewerDataOffsets.eyePositionOffset) = m_viewMatrix.GetTranslation();
AccessByOffset<Vector2f&>(allocation.mappedPtr, viewerDataOffsets.invTargetSizeOffset) = 1.f / m_targetSize;
AccessByOffset<Vector2f&>(allocation.mappedPtr, viewerDataOffsets.targetSizeOffset) = m_targetSize;
Nz::AccessByOffset<Nz::Matrix4f&>(allocation.mappedPtr, viewerDataOffsets.invProjMatrixOffset) = m_invProjectionMatrix;
Nz::AccessByOffset<Nz::Matrix4f&>(allocation.mappedPtr, viewerDataOffsets.invViewMatrixOffset) = m_invViewMatrix;
Nz::AccessByOffset<Nz::Matrix4f&>(allocation.mappedPtr, viewerDataOffsets.invViewProjMatrixOffset) = m_invViewProjMatrix;
Nz::AccessByOffset<Nz::Matrix4f&>(allocation.mappedPtr, viewerDataOffsets.projMatrixOffset) = m_projectionMatrix;
Nz::AccessByOffset<Nz::Matrix4f&>(allocation.mappedPtr, viewerDataOffsets.viewProjMatrixOffset) = m_viewProjMatrix;
Nz::AccessByOffset<Nz::Matrix4f&>(allocation.mappedPtr, viewerDataOffsets.viewMatrixOffset) = m_viewMatrix;
AccessByOffset<Matrix4f&>(allocation.mappedPtr, viewerDataOffsets.invProjMatrixOffset) = m_invProjectionMatrix;
AccessByOffset<Matrix4f&>(allocation.mappedPtr, viewerDataOffsets.invViewMatrixOffset) = m_invViewMatrix;
AccessByOffset<Matrix4f&>(allocation.mappedPtr, viewerDataOffsets.invViewProjMatrixOffset) = m_invViewProjMatrix;
AccessByOffset<Matrix4f&>(allocation.mappedPtr, viewerDataOffsets.projMatrixOffset) = m_projectionMatrix;
AccessByOffset<Matrix4f&>(allocation.mappedPtr, viewerDataOffsets.viewProjMatrixOffset) = m_viewProjMatrix;
AccessByOffset<Matrix4f&>(allocation.mappedPtr, viewerDataOffsets.viewMatrixOffset) = m_viewMatrix;
builder.CopyBuffer(allocation, m_viewerDataBuffer.get());

View File

@@ -14,25 +14,15 @@
namespace Nz
{
WorldInstance::WorldInstance() :
m_invWorldMatrix(Nz::Matrix4f::Identity()),
m_worldMatrix(Nz::Matrix4f::Identity()),
m_invWorldMatrix(Matrix4f::Identity()),
m_worldMatrix(Matrix4f::Identity()),
m_dataInvalided(true)
{
PredefinedInstanceData instanceUboOffsets = PredefinedInstanceData::GetOffsets();
m_instanceDataBuffer = Graphics::Instance()->GetRenderDevice()->InstantiateBuffer(BufferType::Uniform);
if (!m_instanceDataBuffer->Initialize(instanceUboOffsets.totalSize, Nz::BufferUsage::DeviceLocal | Nz::BufferUsage::Dynamic))
if (!m_instanceDataBuffer->Initialize(instanceUboOffsets.totalSize, BufferUsage::DeviceLocal | BufferUsage::Dynamic))
throw std::runtime_error("failed to initialize viewer data UBO");
m_shaderBinding = Graphics::Instance()->GetReferencePipelineLayout()->AllocateShaderBinding(Graphics::WorldBindingSet);
m_shaderBinding->Update({
{
0,
ShaderBinding::UniformBufferBinding {
m_instanceDataBuffer.get(), 0, m_instanceDataBuffer->GetSize()
}
}
});
}
void WorldInstance::UpdateBuffers(UploadPool& uploadPool, CommandBufferBuilder& builder)

View File

@@ -26,9 +26,11 @@ namespace Nz
switch (params.type)
{
case ImageType::E1D:
m_texture.TexStorage2D(GL::TextureTarget::Target2D, params.mipmapLevel, format->internalFormat, params.width, 1);
break;
case ImageType::E1D_Array:
m_texture.TexStorage2D(GL::TextureTarget::Target2D, params.mipmapLevel, format->internalFormat, params.width, params.height);
break;
case ImageType::E2D:
@@ -36,17 +38,16 @@ namespace Nz
break;
case ImageType::E2D_Array:
m_texture.TexStorage3D(GL::TextureTarget::Target2D_Array, params.mipmapLevel, format->internalFormat, params.width, params.height, params.depth);
break;
case ImageType::E3D:
m_texture.TexStorage3D(GL::TextureTarget::Target3D, params.mipmapLevel, format->internalFormat, params.width, params.height, params.depth);
break;
case ImageType::Cubemap:
m_texture.TexStorage2D(GL::TextureTarget::Cubemap, params.mipmapLevel, format->internalFormat, params.width, params.height);
break;
default:
break;
}
if (!context.DidLastCallSucceed())

View File

@@ -71,7 +71,7 @@ namespace Nz
std::array<Vector2f, circleVerticesCount> vertices;
Vector2f origin = FromChipmunk(pos);
float r = static_cast<float>(radius);
float r = SafeCast<float>(radius);
RadianAnglef angleBetweenVertices = 2.f * Pi<float> / vertices.size();
for (std::size_t i = 0; i < vertices.size(); ++i)
@@ -91,7 +91,7 @@ namespace Nz
{
const auto& callback = *static_cast<const CallbackType*>(userdata);
static std::pair<float, float> sincos = Nz::DegreeAnglef(90.f).GetSinCos();
static std::pair<float, float> sincos = DegreeAnglef(90.f).GetSinCos();
Vector2f from = FromChipmunk(a);
Vector2f to = FromChipmunk(b);
@@ -100,7 +100,7 @@ namespace Nz
Vector2f thicknessNormal(sincos.second * normal.x - sincos.first * normal.y,
sincos.first * normal.x + sincos.second * normal.y);
float thickness = static_cast<float>(radius);
float thickness = SafeCast<float>(radius);
std::array<Vector2f, 4> vertices;
vertices[0] = from + thickness * thicknessNormal;
@@ -166,14 +166,14 @@ namespace Nz
{
}
Nz::Vector2f BoxCollider2D::ComputeCenterOfMass() const
Vector2f BoxCollider2D::ComputeCenterOfMass() const
{
return m_rect.GetCenter();
}
float BoxCollider2D::ComputeMomentOfInertia(float mass) const
{
return static_cast<float>(cpMomentForBox2(mass, cpBBNew(m_rect.x, m_rect.y, m_rect.x + m_rect.width, m_rect.y + m_rect.height)));
return SafeCast<float>(cpMomentForBox2(mass, cpBBNew(m_rect.x, m_rect.y, m_rect.x + m_rect.width, m_rect.y + m_rect.height)));
}
ColliderType2D BoxCollider2D::GetType() const
@@ -195,14 +195,14 @@ namespace Nz
{
}
Nz::Vector2f CircleCollider2D::ComputeCenterOfMass() const
Vector2f CircleCollider2D::ComputeCenterOfMass() const
{
return m_offset;
}
float CircleCollider2D::ComputeMomentOfInertia(float mass) const
{
return static_cast<float>(cpMomentForCircle(mass, 0.f, m_radius, cpv(m_offset.x, m_offset.y)));
return SafeCast<float>(cpMomentForCircle(mass, 0.f, m_radius, cpv(m_offset.x, m_offset.y)));
}
ColliderType2D CircleCollider2D::GetType() const
@@ -224,9 +224,9 @@ namespace Nz
{
}
Nz::Vector2f CompoundCollider2D::ComputeCenterOfMass() const
Vector2f CompoundCollider2D::ComputeCenterOfMass() const
{
Nz::Vector2f centerOfMass = Nz::Vector2f::Zero();
Vector2f centerOfMass = Vector2f::Zero();
for (const auto& geom : m_geoms)
centerOfMass += geom->ComputeCenterOfMass();
@@ -285,20 +285,20 @@ namespace Nz
m_vertices[i].Set(*vertices++);
}
Nz::Vector2f ConvexCollider2D::ComputeCenterOfMass() const
Vector2f ConvexCollider2D::ComputeCenterOfMass() const
{
static_assert(sizeof(cpVect) == sizeof(Vector2d), "Chipmunk vector is not equivalent to Vector2d");
cpVect center = cpCentroidForPoly(int(m_vertices.size()), reinterpret_cast<const cpVect*>(m_vertices.data()));
return Nz::Vector2f(float(center.x), float(center.y));
return Vector2f(float(center.x), float(center.y));
}
float ConvexCollider2D::ComputeMomentOfInertia(float mass) const
{
static_assert(sizeof(cpVect) == sizeof(Vector2d), "Chipmunk vector is not equivalent to Vector2d");
return static_cast<float>(cpMomentForPoly(mass, int(m_vertices.size()), reinterpret_cast<const cpVect*>(m_vertices.data()), cpv(0.0, 0.0), m_radius));
return SafeCast<float>(cpMomentForPoly(mass, int(m_vertices.size()), reinterpret_cast<const cpVect*>(m_vertices.data()), cpv(0.0, 0.0), m_radius));
}
ColliderType2D ConvexCollider2D::GetType() const
@@ -319,9 +319,9 @@ namespace Nz
return ColliderType2D::Null;
}
Nz::Vector2f NullCollider2D::ComputeCenterOfMass() const
Vector2f NullCollider2D::ComputeCenterOfMass() const
{
return Nz::Vector2f::Zero();
return Vector2f::Zero();
}
float NullCollider2D::ComputeMomentOfInertia(float mass) const
@@ -336,14 +336,14 @@ namespace Nz
/******************************** SegmentCollider2D *********************************/
Nz::Vector2f SegmentCollider2D::ComputeCenterOfMass() const
Vector2f SegmentCollider2D::ComputeCenterOfMass() const
{
return (m_first + m_second) / 2.f;
}
float SegmentCollider2D::ComputeMomentOfInertia(float mass) const
{
return static_cast<float>(cpMomentForSegment(mass, cpv(m_first.x, m_first.y), cpv(m_second.x, m_second.y), m_thickness));
return SafeCast<float>(cpMomentForSegment(mass, cpv(m_first.x, m_first.y), cpv(m_second.x, m_second.y), m_thickness));
}
ColliderType2D SegmentCollider2D::GetType() const

View File

@@ -145,38 +145,38 @@ namespace Nz
std::shared_ptr<StaticMesh> Collider3D::GenerateMesh() const
{
std::vector<Nz::Vector3f> colliderVertices;
std::vector<Nz::UInt16> colliderIndices;
std::vector<Vector3f> colliderVertices;
std::vector<UInt16> colliderIndices;
// Generate a line list
ForEachPolygon([&](const Nz::Vector3f* vertices, std::size_t vertexCount)
ForEachPolygon([&](const Vector3f* vertices, std::size_t vertexCount)
{
Nz::UInt16 firstIndex = colliderVertices.size();
UInt16 firstIndex = SafeCast<UInt16>(colliderVertices.size());
for (std::size_t i = 0; i < vertexCount; ++i)
colliderVertices.push_back(vertices[i]);
for (std::size_t i = 1; i < vertexCount; ++i)
{
colliderIndices.push_back(firstIndex + i - 1);
colliderIndices.push_back(firstIndex + i);
colliderIndices.push_back(SafeCast<UInt16>(firstIndex + i - 1));
colliderIndices.push_back(SafeCast<UInt16>(firstIndex + i));
}
if (vertexCount > 2)
{
colliderIndices.push_back(firstIndex + vertexCount - 1);
colliderIndices.push_back(firstIndex);
colliderIndices.push_back(SafeCast<UInt16>(firstIndex + vertexCount - 1));
colliderIndices.push_back(SafeCast<UInt16>(firstIndex));
}
});
std::shared_ptr<Nz::VertexBuffer> colliderVB = std::make_shared<Nz::VertexBuffer>(Nz::VertexDeclaration::Get(Nz::VertexLayout::XYZ), colliderVertices.size(), Nz::DataStorage::Software, 0);
std::shared_ptr<VertexBuffer> colliderVB = std::make_shared<VertexBuffer>(VertexDeclaration::Get(VertexLayout::XYZ), colliderVertices.size(), DataStorage::Software, 0);
colliderVB->Fill(colliderVertices.data(), 0, colliderVertices.size());
std::shared_ptr<Nz::IndexBuffer> colliderIB = std::make_shared<Nz::IndexBuffer>(false, colliderIndices.size(), Nz::DataStorage::Software, 0);
std::shared_ptr<IndexBuffer> colliderIB = std::make_shared<IndexBuffer>(false, colliderIndices.size(), DataStorage::Software, 0);
colliderIB->Fill(colliderIndices.data(), 0, colliderIndices.size());
std::shared_ptr<Nz::StaticMesh> colliderSubMesh = std::make_shared<Nz::StaticMesh>(std::move(colliderVB), std::move(colliderIB));
std::shared_ptr<StaticMesh> colliderSubMesh = std::make_shared<StaticMesh>(std::move(colliderVB), std::move(colliderIB));
colliderSubMesh->GenerateAABB();
colliderSubMesh->SetPrimitiveMode(Nz::PrimitiveMode::LineList);
colliderSubMesh->SetPrimitiveMode(PrimitiveMode::LineList);
return colliderSubMesh;
}

View File

@@ -325,18 +325,6 @@ namespace Nz
{
}
inline entt::registry& BaseWidget::GetRegistry()
{
assert(m_registry);
return *m_registry;
}
inline const entt::registry& BaseWidget::GetRegistry() const
{
assert(m_registry);
return *m_registry;
}
void BaseWidget::ShowChildren(bool show)
{
for (const auto& widgetPtr : m_children)

View File

@@ -528,7 +528,6 @@ Nz::ShaderAst::StatementPtr ShaderGraph::ToAst() const
statements.push_back(Nz::ShaderBuilder::DeclareStruct(std::move(structDesc)));
}
Nz::ShaderAst::ExpressionType returnType;
if (!m_outputs.empty())
{
Nz::ShaderAst::StructDescription structDesc;