Graphics: Add support for draw call data (texture overlay)
This commit is contained in:
@@ -66,11 +66,13 @@ namespace Nz
|
||||
MaterialPipeline::Initialize();
|
||||
|
||||
RenderPipelineLayoutInfo referenceLayoutInfo;
|
||||
FillDrawDataPipelineLayout(referenceLayoutInfo);
|
||||
FillViewerPipelineLayout(referenceLayoutInfo);
|
||||
FillWorldPipelineLayout(referenceLayoutInfo);
|
||||
|
||||
m_referencePipelineLayout = m_renderDevice->InstantiateRenderPipelineLayout(std::move(referenceLayoutInfo));
|
||||
|
||||
BuildDefaultTextures();
|
||||
BuildFullscreenVertexBuffer();
|
||||
BuildBlitPipeline();
|
||||
RegisterMaterialPasses();
|
||||
@@ -86,10 +88,22 @@ namespace Nz
|
||||
m_fullscreenVertexDeclaration.reset();
|
||||
m_blitPipeline.reset();
|
||||
m_blitPipelineLayout.reset();
|
||||
m_defaultTextures.whiteTexture2d.reset();
|
||||
}
|
||||
|
||||
void Graphics::FillDrawDataPipelineLayout(RenderPipelineLayoutInfo& layoutInfo, UInt32 set)
|
||||
{
|
||||
// TextureOverlay
|
||||
layoutInfo.bindings.push_back({
|
||||
set, 0,
|
||||
ShaderBindingType::Texture,
|
||||
ShaderStageType_All
|
||||
});
|
||||
}
|
||||
|
||||
void Graphics::FillViewerPipelineLayout(RenderPipelineLayoutInfo& layoutInfo, UInt32 set)
|
||||
{
|
||||
// ViewerData
|
||||
layoutInfo.bindings.push_back({
|
||||
set, 0,
|
||||
ShaderBindingType::UniformBuffer,
|
||||
@@ -99,6 +113,7 @@ namespace Nz
|
||||
|
||||
void Graphics::FillWorldPipelineLayout(RenderPipelineLayoutInfo& layoutInfo, UInt32 set)
|
||||
{
|
||||
// InstanceData
|
||||
layoutInfo.bindings.push_back({
|
||||
set, 0,
|
||||
ShaderBindingType::UniformBuffer,
|
||||
@@ -138,6 +153,22 @@ namespace Nz
|
||||
m_blitPipeline = m_renderDevice->InstantiateRenderPipeline(std::move(pipelineInfo));
|
||||
}
|
||||
|
||||
void Graphics::BuildDefaultTextures()
|
||||
{
|
||||
// White texture 2D
|
||||
{
|
||||
Nz::TextureInfo texInfo;
|
||||
texInfo.width = texInfo.height = texInfo.depth = texInfo.mipmapLevel = 1;
|
||||
texInfo.pixelFormat = PixelFormat::BGRA8;
|
||||
texInfo.type = ImageType::E2D;
|
||||
|
||||
std::array<UInt8, 4> texData = { 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
|
||||
m_defaultTextures.whiteTexture2d = m_renderDevice->InstantiateTexture(texInfo);
|
||||
m_defaultTextures.whiteTexture2d->Update(texData.data());
|
||||
}
|
||||
}
|
||||
|
||||
void Graphics::BuildFullscreenVertexBuffer()
|
||||
{
|
||||
m_fullscreenVertexDeclaration = VertexDeclaration::Get(VertexLayout::XY_UV);
|
||||
|
||||
@@ -8,7 +8,7 @@ option ColorLocation: i32 = -1;
|
||||
option UvLocation: i32 = -1;
|
||||
|
||||
const HasVertexColor = (ColorLocation >= 0);
|
||||
const HasUV = (UvLocation >= 0) && (HasDiffuseTexture || HasAlphaTexture);
|
||||
const HasUV = (UvLocation >= 0);
|
||||
|
||||
[layout(std140)]
|
||||
struct BasicSettings
|
||||
@@ -42,9 +42,10 @@ external
|
||||
{
|
||||
[set(0), binding(0)] viewerData: uniform<ViewerData>,
|
||||
[set(1), binding(0)] instanceData: uniform<InstanceData>,
|
||||
[set(2), binding(0)] settings: uniform<BasicSettings>,
|
||||
[set(2), binding(2)] MaterialAlphaMap: sampler2D<f32>,
|
||||
[set(2), binding(1)] MaterialDiffuseMap: sampler2D<f32>
|
||||
[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>
|
||||
}
|
||||
|
||||
// Fragment stage
|
||||
@@ -64,6 +65,10 @@ fn main(input: FragIn) -> FragOut
|
||||
{
|
||||
let diffuseColor = settings.DiffuseColor;
|
||||
|
||||
const if (HasUV)
|
||||
//TODO: diffuseColor *= TextureOverlay.Sample(input.uv);
|
||||
diffuseColor = diffuseColor * TextureOverlay.Sample(input.uv);
|
||||
|
||||
const if (HasVertexColor)
|
||||
//TODO: diffuseColor *= input.color;
|
||||
diffuseColor = diffuseColor * input.color;
|
||||
|
||||
@@ -36,9 +36,10 @@ external
|
||||
{
|
||||
[set(0), binding(0)] viewerData: uniform<ViewerData>,
|
||||
[set(1), binding(0)] instanceData: uniform<InstanceData>,
|
||||
[set(2), binding(0)] settings: uniform<BasicSettings>,
|
||||
[set(2), binding(2)] MaterialAlphaMap: sampler2D<f32>,
|
||||
[set(2), binding(1)] MaterialDiffuseMap: sampler2D<f32>
|
||||
[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>
|
||||
}
|
||||
|
||||
// Fragment stage
|
||||
@@ -51,6 +52,11 @@ struct FragIn
|
||||
fn main(input: FragIn)
|
||||
{
|
||||
let alpha = settings.DiffuseColor.a;
|
||||
|
||||
const if (HasUV)
|
||||
//TODO: diffuseColor *= TextureOverlay.Sample(input.uv);
|
||||
alpha = alpha * TextureOverlay.Sample(input.uv).a;
|
||||
|
||||
const if (HasDiffuseTexture)
|
||||
// TODO: alpha *= MaterialDiffuseMap.Sample(input.uv).a;
|
||||
alpha = alpha * MaterialDiffuseMap.Sample(input.uv).a;
|
||||
|
||||
@@ -38,7 +38,9 @@ namespace Nz
|
||||
};
|
||||
const auto& renderPipeline = materialPass->GetPipeline()->GetRenderPipeline(vertexBufferData);
|
||||
|
||||
elements.emplace_back(std::make_unique<RenderSpriteChain>(0, renderPipeline, vertexDeclaration, 1, m_vertices.data(), materialPass->GetShaderBinding(), worldInstance.GetShaderBinding()));
|
||||
const auto& whiteTexture = Graphics::Instance()->GetDefaultTextures().whiteTexture2d;
|
||||
|
||||
elements.emplace_back(std::make_unique<RenderSpriteChain>(0, renderPipeline, vertexDeclaration, whiteTexture, 1, m_vertices.data(), materialPass->GetShaderBinding(), worldInstance.GetShaderBinding()));
|
||||
}
|
||||
|
||||
const std::shared_ptr<Material>& Sprite::GetMaterial(std::size_t i) const
|
||||
|
||||
@@ -52,6 +52,8 @@ namespace Nz
|
||||
|
||||
void SpriteChainRenderer::Prepare(ElementRendererData& rendererData, RenderFrame& currentFrame, const Pointer<const RenderElement>* elements, std::size_t elementCount)
|
||||
{
|
||||
Graphics* graphics = Graphics::Instance();
|
||||
|
||||
auto& data = static_cast<SpriteChainRendererData&>(rendererData);
|
||||
|
||||
std::size_t firstQuadIndex = 0;
|
||||
@@ -61,14 +63,23 @@ 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 Texture* currentTextureOverlay = nullptr;
|
||||
|
||||
auto FlushDrawCall = [&]()
|
||||
{
|
||||
currentDrawCall = nullptr;
|
||||
};
|
||||
|
||||
auto FlushDrawData = [&]()
|
||||
{
|
||||
FlushDrawCall();
|
||||
|
||||
currentDrawDataBinding = nullptr;
|
||||
};
|
||||
|
||||
auto Flush = [&]()
|
||||
{
|
||||
// changing vertex buffer always mean we have to switch draw calls
|
||||
@@ -85,6 +96,7 @@ namespace Nz
|
||||
};
|
||||
|
||||
std::size_t oldDrawCallCount = data.drawCalls.size();
|
||||
const auto& defaultSampler = graphics->GetSamplerCache().Get({});
|
||||
|
||||
for (std::size_t i = 0; i < elementCount; ++i)
|
||||
{
|
||||
@@ -122,6 +134,12 @@ namespace Nz
|
||||
currentInstanceBinding = &spriteChain.GetInstanceBinding();
|
||||
}
|
||||
|
||||
if (currentTextureOverlay != spriteChain.GetTextureOverlay())
|
||||
{
|
||||
FlushDrawData();
|
||||
currentTextureOverlay = spriteChain.GetTextureOverlay();
|
||||
}
|
||||
|
||||
std::size_t remainingQuads = spriteChain.GetSpriteCount();
|
||||
while (remainingQuads > 0)
|
||||
{
|
||||
@@ -149,11 +167,29 @@ namespace Nz
|
||||
data.vertexBuffers.emplace_back(std::move(vertexBuffer));
|
||||
}
|
||||
|
||||
if (!currentDrawDataBinding)
|
||||
{
|
||||
ShaderBindingPtr drawDataBinding = Graphics::Instance()->GetReferencePipelineLayout()->AllocateShaderBinding(Graphics::DrawDataBindingSet);
|
||||
drawDataBinding->Update({
|
||||
{
|
||||
0,
|
||||
ShaderBinding::TextureBinding {
|
||||
currentTextureOverlay, defaultSampler.get()
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
currentDrawDataBinding = drawDataBinding.get();
|
||||
|
||||
data.shaderBindings.emplace_back(std::move(drawDataBinding));
|
||||
}
|
||||
|
||||
if (!currentDrawCall)
|
||||
{
|
||||
data.drawCalls.push_back(SpriteChainRendererData::DrawCall{
|
||||
currentVertexBuffer,
|
||||
currentPipeline,
|
||||
currentDrawDataBinding,
|
||||
currentInstanceBinding,
|
||||
currentMaterialBinding,
|
||||
6 * firstQuadIndex,
|
||||
@@ -216,6 +252,7 @@ namespace Nz
|
||||
|
||||
const AbstractBuffer* currentVertexBuffer = nullptr;
|
||||
const RenderPipeline* currentPipeline = nullptr;
|
||||
const ShaderBinding* currentDrawDataBinding = nullptr;
|
||||
const ShaderBinding* currentInstanceBinding = nullptr;
|
||||
const ShaderBinding* currentMaterialBinding = nullptr;
|
||||
|
||||
@@ -241,6 +278,12 @@ namespace Nz
|
||||
currentPipeline = drawCall.renderPipeline;
|
||||
}
|
||||
|
||||
if (currentDrawDataBinding != drawCall.drawDataBinding)
|
||||
{
|
||||
commandBuffer.BindShaderBinding(Graphics::DrawDataBindingSet, *drawCall.drawDataBinding);
|
||||
currentDrawDataBinding = drawCall.drawDataBinding;
|
||||
}
|
||||
|
||||
if (currentMaterialBinding != drawCall.materialBinding)
|
||||
{
|
||||
commandBuffer.BindShaderBinding(Graphics::MaterialBindingSet, *drawCall.materialBinding);
|
||||
@@ -270,6 +313,10 @@ namespace Nz
|
||||
}
|
||||
data.vertexBuffers.clear();
|
||||
|
||||
for (auto& shaderBinding : data.shaderBindings)
|
||||
currentFrame.PushForRelease(std::move(shaderBinding));
|
||||
data.shaderBindings.clear();
|
||||
|
||||
data.drawCalls.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,23 @@
|
||||
|
||||
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 {};
|
||||
@@ -22,6 +39,8 @@ namespace Nz
|
||||
const RenderPipeline* currentPipeline = nullptr;
|
||||
const ShaderBinding* currentMaterialBinding = nullptr;
|
||||
|
||||
commandBuffer.BindShaderBinding(Graphics::DrawDataBindingSet, *m_renderDataBinding);
|
||||
|
||||
for (std::size_t i = 0; i < elementCount; ++i)
|
||||
{
|
||||
assert(elements[i]->GetElementType() == UnderlyingCast(BasicRenderElement::Submesh));
|
||||
|
||||
@@ -68,11 +68,11 @@ namespace Nz
|
||||
{
|
||||
auto& textureDescriptor = m_owner.GetTextureDescriptor(m_poolIndex, m_bindingIndex, binding.bindingIndex);
|
||||
|
||||
if (OpenGLTexture* glTexture = static_cast<OpenGLTexture*>(arg.texture))
|
||||
if (const OpenGLTexture* glTexture = static_cast<const OpenGLTexture*>(arg.texture))
|
||||
{
|
||||
textureDescriptor.texture = glTexture->GetTexture().GetObjectId();
|
||||
|
||||
if (OpenGLTextureSampler* glSampler = static_cast<OpenGLTextureSampler*>(arg.sampler))
|
||||
if (const OpenGLTextureSampler* glSampler = static_cast<const OpenGLTextureSampler*>(arg.sampler))
|
||||
textureDescriptor.sampler = glSampler->GetSampler(glTexture->GetLevelCount() > 1).GetObjectId();
|
||||
else
|
||||
textureDescriptor.sampler = 0;
|
||||
|
||||
@@ -34,8 +34,8 @@ namespace Nz
|
||||
|
||||
if constexpr (std::is_same_v<T, TextureBinding>)
|
||||
{
|
||||
VulkanTexture* vkTexture = static_cast<VulkanTexture*>(arg.texture);
|
||||
VulkanTextureSampler* vkSampler = static_cast<VulkanTextureSampler*>(arg.sampler);
|
||||
const VulkanTexture* vkTexture = static_cast<const VulkanTexture*>(arg.texture);
|
||||
const VulkanTextureSampler* vkSampler = static_cast<const VulkanTextureSampler*>(arg.sampler);
|
||||
|
||||
VkDescriptorImageInfo& imageInfo = imageBinding.emplace_back();
|
||||
imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
|
||||
Reference in New Issue
Block a user