2020.8
This commit is contained in:
parent
4fac1e6d28
commit
d6d07e7883
111 changed files with 4347 additions and 1114 deletions
|
@ -33,11 +33,39 @@ void CommandBufferD3D12::Done()
|
||||||
VERUS_DONE(CommandBufferD3D12);
|
VERUS_DONE(CommandBufferD3D12);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CommandBufferD3D12::InitOneTimeSubmit()
|
||||||
|
{
|
||||||
|
VERUS_QREF_RENDERER;
|
||||||
|
VERUS_QREF_RENDERER_D3D12;
|
||||||
|
_pOneTimeCommandAllocator = pRendererD3D12->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT);
|
||||||
|
auto pCmdList = pRendererD3D12->CreateCommandList(D3D12_COMMAND_LIST_TYPE_DIRECT, _pOneTimeCommandAllocator);
|
||||||
|
VERUS_FOR(i, BaseRenderer::s_ringBufferSize)
|
||||||
|
_pCommandLists[i] = pCmdList;
|
||||||
|
_pOneTimeCommandAllocator->Reset();
|
||||||
|
Begin();
|
||||||
|
pRendererD3D12->SetDescriptorHeaps(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommandBufferD3D12::DoneOneTimeSubmit()
|
||||||
|
{
|
||||||
|
VERUS_QREF_RENDERER;
|
||||||
|
VERUS_QREF_RENDERER_D3D12;
|
||||||
|
End();
|
||||||
|
ID3D12CommandList* ppCommandLists[] = { _pCommandLists[0].Get() };
|
||||||
|
pRendererD3D12->GetCommandQueue()->ExecuteCommandLists(VERUS_COUNT_OF(ppCommandLists), ppCommandLists);
|
||||||
|
pRendererD3D12->QueueWaitIdle();
|
||||||
|
_pOneTimeCommandAllocator.Reset();
|
||||||
|
VERUS_FOR(i, BaseRenderer::s_ringBufferSize)
|
||||||
|
_pCommandLists[i].Reset();
|
||||||
|
}
|
||||||
|
|
||||||
void CommandBufferD3D12::Begin()
|
void CommandBufferD3D12::Begin()
|
||||||
{
|
{
|
||||||
VERUS_QREF_RENDERER_D3D12;
|
VERUS_QREF_RENDERER_D3D12;
|
||||||
HRESULT hr = 0;
|
HRESULT hr = 0;
|
||||||
if (FAILED(hr = GetD3DGraphicsCommandList()->Reset(pRendererD3D12->GetD3DCommandAllocator(pRendererD3D12->GetRingBufferIndex()), nullptr)))
|
if (FAILED(hr = GetD3DGraphicsCommandList()->Reset(
|
||||||
|
_pOneTimeCommandAllocator ? _pOneTimeCommandAllocator.Get() : pRendererD3D12->GetD3DCommandAllocator(pRendererD3D12->GetRingBufferIndex()),
|
||||||
|
nullptr)))
|
||||||
throw VERUS_RUNTIME_ERROR << "Reset(), hr=" << VERUS_HR(hr);
|
throw VERUS_RUNTIME_ERROR << "Reset(), hr=" << VERUS_HR(hr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ namespace verus
|
||||||
{
|
{
|
||||||
class CommandBufferD3D12 : public BaseCommandBuffer
|
class CommandBufferD3D12 : public BaseCommandBuffer
|
||||||
{
|
{
|
||||||
|
ComPtr<ID3D12CommandAllocator> _pOneTimeCommandAllocator;
|
||||||
ComPtr<ID3D12GraphicsCommandList3> _pCommandLists[BaseRenderer::s_ringBufferSize];
|
ComPtr<ID3D12GraphicsCommandList3> _pCommandLists[BaseRenderer::s_ringBufferSize];
|
||||||
RP::PcD3DRenderPass _pRenderPass = nullptr;
|
RP::PcD3DRenderPass _pRenderPass = nullptr;
|
||||||
RP::PcD3DFramebuffer _pFramebuffer = nullptr;
|
RP::PcD3DFramebuffer _pFramebuffer = nullptr;
|
||||||
|
@ -20,6 +21,9 @@ namespace verus
|
||||||
virtual void Init() override;
|
virtual void Init() override;
|
||||||
virtual void Done() override;
|
virtual void Done() override;
|
||||||
|
|
||||||
|
virtual void InitOneTimeSubmit() override;
|
||||||
|
virtual void DoneOneTimeSubmit() override;
|
||||||
|
|
||||||
virtual void Begin() override;
|
virtual void Begin() override;
|
||||||
virtual void End() override;
|
virtual void End() override;
|
||||||
|
|
||||||
|
|
|
@ -170,7 +170,7 @@ void GeometryD3D12::UpdateVertexBuffer(const void* p, int binding, PBaseCommandB
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pCB)
|
if (!pCB)
|
||||||
pCB = &(*renderer.GetCommandBuffer());
|
pCB = renderer.GetCommandBuffer().Get();
|
||||||
auto pCmdList = static_cast<PCommandBufferD3D12>(pCB)->GetD3DGraphicsCommandList();
|
auto pCmdList = static_cast<PCommandBufferD3D12>(pCB)->GetD3DGraphicsCommandList();
|
||||||
if (revertState)
|
if (revertState)
|
||||||
{
|
{
|
||||||
|
@ -241,7 +241,7 @@ void GeometryD3D12::UpdateIndexBuffer(const void* p, PBaseCommandBuffer pCB)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pCB)
|
if (!pCB)
|
||||||
pCB = &(*renderer.GetCommandBuffer());
|
pCB = renderer.GetCommandBuffer().Get();
|
||||||
auto pCmdList = static_cast<PCommandBufferD3D12>(pCB)->GetD3DGraphicsCommandList();
|
auto pCmdList = static_cast<PCommandBufferD3D12>(pCB)->GetD3DGraphicsCommandList();
|
||||||
if (revertState)
|
if (revertState)
|
||||||
{
|
{
|
||||||
|
|
|
@ -418,7 +418,7 @@ void RendererD3D12::ImGuiRenderDrawData()
|
||||||
{
|
{
|
||||||
VERUS_QREF_RENDERER;
|
VERUS_QREF_RENDERER;
|
||||||
ImGui::Render();
|
ImGui::Render();
|
||||||
auto pCmdList = static_cast<CommandBufferD3D12*>(&(*renderer.GetCommandBuffer()))->GetD3DGraphicsCommandList();
|
auto pCmdList = static_cast<CommandBufferD3D12*>(renderer.GetCommandBuffer().Get())->GetD3DGraphicsCommandList();
|
||||||
if (ImGui::GetDrawData())
|
if (ImGui::GetDrawData())
|
||||||
ImGui_ImplDX12_RenderDrawData(ImGui::GetDrawData(), pCmdList);
|
ImGui_ImplDX12_RenderDrawData(ImGui::GetDrawData(), pCmdList);
|
||||||
}
|
}
|
||||||
|
@ -460,10 +460,9 @@ void RendererD3D12::BeginFrame(bool present)
|
||||||
if (FAILED(hr = pCommandAllocator->Reset()))
|
if (FAILED(hr = pCommandAllocator->Reset()))
|
||||||
throw VERUS_RUNTIME_ERROR << "Reset(), hr=" << VERUS_HR(hr);
|
throw VERUS_RUNTIME_ERROR << "Reset(), hr=" << VERUS_HR(hr);
|
||||||
|
|
||||||
renderer.GetCommandBuffer()->Begin();
|
auto cb = renderer.GetCommandBuffer();
|
||||||
|
cb->Begin();
|
||||||
ID3D12DescriptorHeap* ppHeaps[] = { _dhViews.GetD3DDescriptorHeap(), _dhSamplers.GetD3DDescriptorHeap() };
|
SetDescriptorHeaps(cb.Get());
|
||||||
static_cast<CommandBufferD3D12*>(&(*renderer.GetCommandBuffer()))->GetD3DGraphicsCommandList()->SetDescriptorHeaps(2, ppHeaps);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererD3D12::EndFrame(bool present)
|
void RendererD3D12::EndFrame(bool present)
|
||||||
|
@ -473,7 +472,7 @@ void RendererD3D12::EndFrame(bool present)
|
||||||
|
|
||||||
renderer.GetCommandBuffer()->End();
|
renderer.GetCommandBuffer()->End();
|
||||||
|
|
||||||
ID3D12CommandList* ppCommandLists[] = { static_cast<CommandBufferD3D12*>(&(*renderer.GetCommandBuffer()))->GetD3DGraphicsCommandList() };
|
ID3D12CommandList* ppCommandLists[] = { static_cast<CommandBufferD3D12*>(renderer.GetCommandBuffer().Get())->GetD3DGraphicsCommandList() };
|
||||||
_pCommandQueue->ExecuteCommandLists(VERUS_COUNT_OF(ppCommandLists), ppCommandLists);
|
_pCommandQueue->ExecuteCommandLists(VERUS_COUNT_OF(ppCommandLists), ppCommandLists);
|
||||||
|
|
||||||
if (!present)
|
if (!present)
|
||||||
|
@ -814,3 +813,9 @@ RP::RcD3DFramebuffer RendererD3D12::GetFramebuffer(FBHandle handle) const
|
||||||
{
|
{
|
||||||
return _vFramebuffers[handle.Get()];
|
return _vFramebuffers[handle.Get()];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RendererD3D12::SetDescriptorHeaps(PBaseCommandBuffer p)
|
||||||
|
{
|
||||||
|
ID3D12DescriptorHeap* ppHeaps[] = { _dhViews.GetD3DDescriptorHeap(), _dhSamplers.GetD3DDescriptorHeap() };
|
||||||
|
static_cast<CommandBufferD3D12*>(p)->GetD3DGraphicsCommandList()->SetDescriptorHeaps(2, ppHeaps);
|
||||||
|
}
|
||||||
|
|
|
@ -60,6 +60,7 @@ namespace verus
|
||||||
void CreateSamplers();
|
void CreateSamplers();
|
||||||
|
|
||||||
ID3D12Device3* GetD3DDevice() const { return _pDevice.Get(); }
|
ID3D12Device3* GetD3DDevice() const { return _pDevice.Get(); }
|
||||||
|
ID3D12CommandQueue* GetCommandQueue() const { return _pCommandQueue.Get(); }
|
||||||
D3D12MA::Allocator* GetMaAllocator() const { return _pMaAllocator; }
|
D3D12MA::Allocator* GetMaAllocator() const { return _pMaAllocator; }
|
||||||
ID3D12CommandAllocator* GetD3DCommandAllocator(int ringBufferIndex) const { return _mapCommandAllocators[ringBufferIndex].at(std::this_thread::get_id()).Get(); }
|
ID3D12CommandAllocator* GetD3DCommandAllocator(int ringBufferIndex) const { return _mapCommandAllocators[ringBufferIndex].at(std::this_thread::get_id()).Get(); }
|
||||||
D3D12_STATIC_SAMPLER_DESC GetStaticSamplerDesc(Sampler s) const;
|
D3D12_STATIC_SAMPLER_DESC GetStaticSamplerDesc(Sampler s) const;
|
||||||
|
@ -102,6 +103,7 @@ namespace verus
|
||||||
|
|
||||||
RDynamicDescriptorHeap GetViewHeap() { return _dhViews; }
|
RDynamicDescriptorHeap GetViewHeap() { return _dhViews; }
|
||||||
RDynamicDescriptorHeap GetSamplerHeap() { return _dhSamplers; }
|
RDynamicDescriptorHeap GetSamplerHeap() { return _dhSamplers; }
|
||||||
|
void SetDescriptorHeaps(PBaseCommandBuffer p);
|
||||||
};
|
};
|
||||||
VERUS_TYPEDEFS(RendererD3D12);
|
VERUS_TYPEDEFS(RendererD3D12);
|
||||||
}
|
}
|
||||||
|
|
|
@ -228,7 +228,7 @@ void TextureD3D12::UpdateSubresource(const void* p, int mipLevel, int arrayLayer
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pCB)
|
if (!pCB)
|
||||||
pCB = &(*renderer.GetCommandBuffer());
|
pCB = renderer.GetCommandBuffer().Get();
|
||||||
auto pCmdList = static_cast<PCommandBufferD3D12>(pCB)->GetD3DGraphicsCommandList();
|
auto pCmdList = static_cast<PCommandBufferD3D12>(pCB)->GetD3DGraphicsCommandList();
|
||||||
pCB->PipelineImageMemoryBarrier(TexturePtr::From(this), _mainLayout, ImageLayout::transferDst, mipLevel, arrayLayer);
|
pCB->PipelineImageMemoryBarrier(TexturePtr::From(this), _mainLayout, ImageLayout::transferDst, mipLevel, arrayLayer);
|
||||||
D3D12_SUBRESOURCE_DATA sd = {};
|
D3D12_SUBRESOURCE_DATA sd = {};
|
||||||
|
@ -257,7 +257,7 @@ void TextureD3D12::UpdateSubresource(const void* p, int mipLevel, int arrayLayer
|
||||||
Schedule();
|
Schedule();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TextureD3D12::ReadbackSubresource(void* p, PBaseCommandBuffer pCB)
|
bool TextureD3D12::ReadbackSubresource(void* p, bool recordCopyCommand, PBaseCommandBuffer pCB)
|
||||||
{
|
{
|
||||||
VERUS_QREF_RENDERER;
|
VERUS_QREF_RENDERER;
|
||||||
HRESULT hr = 0;
|
HRESULT hr = 0;
|
||||||
|
@ -268,9 +268,10 @@ bool TextureD3D12::ReadbackSubresource(void* p, PBaseCommandBuffer pCB)
|
||||||
|
|
||||||
auto& rb = _vReadbackBuffers[renderer->GetRingBufferIndex()];
|
auto& rb = _vReadbackBuffers[renderer->GetRingBufferIndex()];
|
||||||
|
|
||||||
// Schedule copying to readback buffer:
|
if (recordCopyCommand)
|
||||||
|
{
|
||||||
if (!pCB)
|
if (!pCB)
|
||||||
pCB = &(*renderer.GetCommandBuffer());
|
pCB = renderer.GetCommandBuffer().Get();
|
||||||
auto pCmdList = static_cast<PCommandBufferD3D12>(pCB)->GetD3DGraphicsCommandList();
|
auto pCmdList = static_cast<PCommandBufferD3D12>(pCB)->GetD3DGraphicsCommandList();
|
||||||
pCB->PipelineImageMemoryBarrier(TexturePtr::From(this), _mainLayout, ImageLayout::transferSrc, _desc._readbackMip, 0);
|
pCB->PipelineImageMemoryBarrier(TexturePtr::From(this), _mainLayout, ImageLayout::transferSrc, _desc._readbackMip, 0);
|
||||||
D3D12_PLACED_SUBRESOURCE_FOOTPRINT footprint = {};
|
D3D12_PLACED_SUBRESOURCE_FOOTPRINT footprint = {};
|
||||||
|
@ -286,14 +287,25 @@ bool TextureD3D12::ReadbackSubresource(void* p, PBaseCommandBuffer pCB)
|
||||||
&CD3DX12_TEXTURE_COPY_LOCATION(_resource._pResource.Get(), subresource),
|
&CD3DX12_TEXTURE_COPY_LOCATION(_resource._pResource.Get(), subresource),
|
||||||
nullptr);
|
nullptr);
|
||||||
pCB->PipelineImageMemoryBarrier(TexturePtr::From(this), ImageLayout::transferSrc, _mainLayout, _desc._readbackMip, 0);
|
pCB->PipelineImageMemoryBarrier(TexturePtr::From(this), ImageLayout::transferSrc, _mainLayout, _desc._readbackMip, 0);
|
||||||
|
}
|
||||||
|
|
||||||
// Read current data from readback buffer:
|
if (p) // Read current data from readback buffer:
|
||||||
|
{
|
||||||
CD3DX12_RANGE readRange(0, 0);
|
CD3DX12_RANGE readRange(0, 0);
|
||||||
void* pData = nullptr;
|
void* pData = nullptr;
|
||||||
if (FAILED(hr = rb._pResource->Map(0, &readRange, &pData)))
|
if (FAILED(hr = rb._pResource->Map(0, &readRange, &pData)))
|
||||||
throw VERUS_RUNTIME_ERROR << "Map(), hr=" << VERUS_HR(hr);
|
throw VERUS_RUNTIME_ERROR << "Map(), hr=" << VERUS_HR(hr);
|
||||||
memcpy(p, pData, _bytesPerPixel * w);
|
BYTE* pDst = static_cast<BYTE*>(p);
|
||||||
|
BYTE* pSrc = static_cast<BYTE*>(pData);
|
||||||
|
VERUS_FOR(i, h)
|
||||||
|
{
|
||||||
|
memcpy(
|
||||||
|
pDst + i * _bytesPerPixel * w,
|
||||||
|
pSrc + i * rowPitch,
|
||||||
|
_bytesPerPixel * w);
|
||||||
|
}
|
||||||
rb._pResource->Unmap(0, nullptr);
|
rb._pResource->Unmap(0, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
return _initAtFrame + BaseRenderer::s_ringBufferSize < renderer.GetFrameCount();
|
return _initAtFrame + BaseRenderer::s_ringBufferSize < renderer.GetFrameCount();
|
||||||
}
|
}
|
||||||
|
@ -304,8 +316,10 @@ void TextureD3D12::GenerateMips(PBaseCommandBuffer pCB)
|
||||||
VERUS_QREF_RENDERER;
|
VERUS_QREF_RENDERER;
|
||||||
|
|
||||||
if (!pCB)
|
if (!pCB)
|
||||||
pCB = &(*renderer.GetCommandBuffer());
|
pCB = renderer.GetCommandBuffer().Get();
|
||||||
auto pCmdList = static_cast<PCommandBufferD3D12>(pCB)->GetD3DGraphicsCommandList();
|
auto pCmdList = static_cast<PCommandBufferD3D12>(pCB)->GetD3DGraphicsCommandList();
|
||||||
|
auto shader = renderer.GetShaderGenerateMips();
|
||||||
|
auto& ub = renderer.GetUbGenerateMips();
|
||||||
auto tex = TexturePtr::From(this);
|
auto tex = TexturePtr::From(this);
|
||||||
|
|
||||||
// Transition state for sampling in compute shader:
|
// Transition state for sampling in compute shader:
|
||||||
|
@ -314,10 +328,7 @@ void TextureD3D12::GenerateMips(PBaseCommandBuffer pCB)
|
||||||
|
|
||||||
pCB->BindPipeline(renderer.GetPipelineGenerateMips(!!(_desc._flags & TextureDesc::Flags::exposureMips)));
|
pCB->BindPipeline(renderer.GetPipelineGenerateMips(!!(_desc._flags & TextureDesc::Flags::exposureMips)));
|
||||||
|
|
||||||
auto shader = renderer.GetShaderGenerateMips();
|
|
||||||
shader->BeginBindDescriptors();
|
shader->BeginBindDescriptors();
|
||||||
auto& ub = renderer.GetUbGenerateMips();
|
|
||||||
|
|
||||||
const bool createComplexSets = _vCshGenerateMips.empty();
|
const bool createComplexSets = _vCshGenerateMips.empty();
|
||||||
int dispatchIndex = 0;
|
int dispatchIndex = 0;
|
||||||
for (int srcMip = 0; srcMip < _desc._mipLevels - 1;)
|
for (int srcMip = 0; srcMip < _desc._mipLevels - 1;)
|
||||||
|
@ -399,7 +410,6 @@ void TextureD3D12::GenerateMips(PBaseCommandBuffer pCB)
|
||||||
srcMip += dispatchMipCount;
|
srcMip += dispatchMipCount;
|
||||||
dispatchIndex++;
|
dispatchIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
shader->EndBindDescriptors();
|
shader->EndBindDescriptors();
|
||||||
|
|
||||||
// Revert to main state:
|
// Revert to main state:
|
||||||
|
|
|
@ -31,7 +31,7 @@ namespace verus
|
||||||
virtual void Done() override;
|
virtual void Done() override;
|
||||||
|
|
||||||
virtual void UpdateSubresource(const void* p, int mipLevel, int arrayLayer, PBaseCommandBuffer pCB) override;
|
virtual void UpdateSubresource(const void* p, int mipLevel, int arrayLayer, PBaseCommandBuffer pCB) override;
|
||||||
virtual bool ReadbackSubresource(void* p, PBaseCommandBuffer pCB) override;
|
virtual bool ReadbackSubresource(void* p, bool recordCopyCommand, PBaseCommandBuffer pCB) override;
|
||||||
|
|
||||||
virtual void GenerateMips(PBaseCommandBuffer pCB) override;
|
virtual void GenerateMips(PBaseCommandBuffer pCB) override;
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,34 @@ void CommandBufferVulkan::Done()
|
||||||
VERUS_DONE(CommandBufferVulkan);
|
VERUS_DONE(CommandBufferVulkan);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CommandBufferVulkan::InitOneTimeSubmit()
|
||||||
|
{
|
||||||
|
VERUS_QREF_RENDERER;
|
||||||
|
VERUS_QREF_RENDERER_VULKAN;
|
||||||
|
_oneTimeSubmit = true;
|
||||||
|
auto commandPool = pRendererVulkan->GetVkCommandPool(renderer->GetRingBufferIndex());
|
||||||
|
auto commandBuffer = pRendererVulkan->CreateCommandBuffer(commandPool);
|
||||||
|
VERUS_FOR(i, BaseRenderer::s_ringBufferSize)
|
||||||
|
_commandBuffers[i] = commandBuffer;
|
||||||
|
Begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommandBufferVulkan::DoneOneTimeSubmit()
|
||||||
|
{
|
||||||
|
VERUS_QREF_RENDERER;
|
||||||
|
VERUS_QREF_RENDERER_VULKAN;
|
||||||
|
End();
|
||||||
|
VkSubmitInfo submitInfo = {};
|
||||||
|
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||||
|
submitInfo.commandBufferCount = 1;
|
||||||
|
submitInfo.pCommandBuffers = _commandBuffers;
|
||||||
|
vkQueueSubmit(pRendererVulkan->GetVkGraphicsQueue(), 1, &submitInfo, VK_NULL_HANDLE);
|
||||||
|
vkQueueWaitIdle(pRendererVulkan->GetVkGraphicsQueue());
|
||||||
|
auto commandPool = pRendererVulkan->GetVkCommandPool(renderer->GetRingBufferIndex());
|
||||||
|
vkFreeCommandBuffers(pRendererVulkan->GetVkDevice(), commandPool, 1, _commandBuffers);
|
||||||
|
_oneTimeSubmit = false;
|
||||||
|
}
|
||||||
|
|
||||||
void CommandBufferVulkan::Begin()
|
void CommandBufferVulkan::Begin()
|
||||||
{
|
{
|
||||||
VkResult res = VK_SUCCESS;
|
VkResult res = VK_SUCCESS;
|
||||||
|
@ -217,121 +245,87 @@ void CommandBufferVulkan::PipelineImageMemoryBarrier(TexturePtr tex, ImageLayout
|
||||||
vkimb[index].subresourceRange.layerCount = 1;
|
vkimb[index].subresourceRange.layerCount = 1;
|
||||||
|
|
||||||
// See: https://github.com/KhronosGroup/Vulkan-Docs/wiki/Synchronization-Examples
|
// See: https://github.com/KhronosGroup/Vulkan-Docs/wiki/Synchronization-Examples
|
||||||
if (vkimb[index].oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && vkimb[index].newLayout == VK_IMAGE_LAYOUT_GENERAL)
|
|
||||||
{
|
|
||||||
// Storage image (UAV) initialization.
|
|
||||||
srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
|
||||||
vkimb[index].srcAccessMask = 0;
|
|
||||||
dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
|
||||||
vkimb[index].dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
|
||||||
}
|
|
||||||
else if (vkimb[index].oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && vkimb[index].newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)
|
|
||||||
{
|
|
||||||
// Depth texture initialization.
|
|
||||||
srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
|
||||||
vkimb[index].srcAccessMask = 0;
|
|
||||||
dstStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
|
|
||||||
vkimb[index].dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
|
||||||
|
|
||||||
vkimb[index].subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
|
auto UseDefaultsForOldLayout = [&vkimb, index, &srcStageMask]()
|
||||||
if (Format::unormD24uintS8 == tex->GetFormat())
|
|
||||||
vkimb[index].subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
|
|
||||||
}
|
|
||||||
else if (vkimb[index].oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && vkimb[index].newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL)
|
|
||||||
{
|
{
|
||||||
// Shadow map initialization.
|
|
||||||
srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
|
||||||
vkimb[index].srcAccessMask = 0;
|
vkimb[index].srcAccessMask = 0;
|
||||||
dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
switch (vkimb[index].oldLayout)
|
||||||
vkimb[index].dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
|
||||||
|
|
||||||
vkimb[index].subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
|
|
||||||
if (Format::unormD24uintS8 == tex->GetFormat())
|
|
||||||
vkimb[index].subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
|
|
||||||
}
|
|
||||||
else if (vkimb[index].oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && vkimb[index].newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
|
|
||||||
{
|
{
|
||||||
// Render target initialization.
|
case VK_IMAGE_LAYOUT_UNDEFINED:
|
||||||
|
case VK_IMAGE_LAYOUT_GENERAL:
|
||||||
srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
||||||
vkimb[index].srcAccessMask = 0;
|
break;
|
||||||
dstStageMask = (ImageLayout::xsReadOnly == newLayout) ? dstStageMaskXS : VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
|
||||||
vkimb[index].dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
srcStageMask = VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
|
||||||
}
|
break;
|
||||||
else if (vkimb[index].oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && vkimb[index].newLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL)
|
case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
|
||||||
{
|
case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
|
||||||
// Reading to readback buffer.
|
|
||||||
srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
|
||||||
vkimb[index].srcAccessMask = 0;
|
|
||||||
dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
|
||||||
vkimb[index].dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
|
||||||
}
|
|
||||||
else if (vkimb[index].oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && vkimb[index].newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
|
|
||||||
{
|
|
||||||
// Regular texture's first and only update (before transfer).
|
|
||||||
srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
|
||||||
vkimb[index].srcAccessMask = 0;
|
|
||||||
dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
|
||||||
vkimb[index].dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
|
||||||
}
|
|
||||||
else if (vkimb[index].oldLayout == VK_IMAGE_LAYOUT_GENERAL && vkimb[index].newLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL)
|
|
||||||
{
|
|
||||||
// To transfer data from storage image during mipmap generation.
|
|
||||||
srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
|
||||||
vkimb[index].srcAccessMask = 0;
|
|
||||||
dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
|
||||||
vkimb[index].dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
|
||||||
}
|
|
||||||
else if (vkimb[index].oldLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL && vkimb[index].newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
|
|
||||||
{
|
|
||||||
// To support vertex texture fetch.
|
|
||||||
srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
||||||
vkimb[index].srcAccessMask = 0;
|
break;
|
||||||
dstStageMask = (ImageLayout::xsReadOnly == newLayout) ? dstStageMaskXS : VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
|
||||||
vkimb[index].dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
|
||||||
}
|
|
||||||
else if (vkimb[index].oldLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL && vkimb[index].newLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL)
|
|
||||||
{
|
|
||||||
// Reading to readback buffer.
|
|
||||||
srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
|
||||||
vkimb[index].srcAccessMask = 0;
|
|
||||||
dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
|
||||||
vkimb[index].dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
|
||||||
}
|
|
||||||
else if (vkimb[index].oldLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL && vkimb[index].newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
|
|
||||||
{
|
|
||||||
// To update regular texture during mipmap generation.
|
|
||||||
srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
|
||||||
vkimb[index].srcAccessMask = 0;
|
|
||||||
dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
|
||||||
vkimb[index].dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
|
||||||
}
|
|
||||||
else if (vkimb[index].oldLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL && vkimb[index].newLayout == VK_IMAGE_LAYOUT_GENERAL)
|
|
||||||
{
|
|
||||||
// To restore storage image after transfer during mipmap generation.
|
|
||||||
srcStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
srcStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||||
vkimb[index].srcAccessMask = 0;
|
break;
|
||||||
dstStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
|
case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
|
||||||
vkimb[index].dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
|
||||||
}
|
|
||||||
else if (vkimb[index].oldLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL && vkimb[index].newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
|
|
||||||
{
|
|
||||||
// To restore image after transfer to readback buffer.
|
|
||||||
srcStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
|
||||||
vkimb[index].srcAccessMask = 0;
|
|
||||||
dstStageMask = (ImageLayout::xsReadOnly == newLayout) ? dstStageMaskXS : VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
|
||||||
vkimb[index].dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
|
||||||
}
|
|
||||||
else if (vkimb[index].oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && vkimb[index].newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
|
|
||||||
{
|
|
||||||
// To sample regular texture after update.
|
|
||||||
srcStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
srcStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||||
vkimb[index].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
vkimb[index].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
VERUS_RT_FAIL("Unknown oldLayout");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
auto UseDefaultsForNewLayout = [&vkimb, index, &dstStageMask, dstStageMaskXS, newLayout, tex]()
|
||||||
|
{
|
||||||
|
switch (vkimb[index].newLayout)
|
||||||
|
{
|
||||||
|
case VK_IMAGE_LAYOUT_UNDEFINED:
|
||||||
|
case VK_IMAGE_LAYOUT_GENERAL:
|
||||||
|
dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||||
|
vkimb[index].dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||||
|
break;
|
||||||
|
case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
|
||||||
|
dstStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
|
||||||
|
vkimb[index].dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
||||||
|
break;
|
||||||
|
case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
|
||||||
|
dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
||||||
|
vkimb[index].dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
||||||
|
break;
|
||||||
|
case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
|
||||||
dstStageMask = (ImageLayout::xsReadOnly == newLayout) ? dstStageMaskXS : VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
dstStageMask = (ImageLayout::xsReadOnly == newLayout) ? dstStageMaskXS : VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
||||||
vkimb[index].dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
vkimb[index].dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
||||||
|
break;
|
||||||
|
case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
|
||||||
|
dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||||
|
vkimb[index].dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
||||||
|
break;
|
||||||
|
case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
|
||||||
|
dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||||
|
vkimb[index].dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
VERUS_RT_FAIL("Unknown newLayout");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vkimb[index].newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL ||
|
||||||
|
vkimb[index].newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL)
|
||||||
|
{
|
||||||
|
vkimb[index].subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||||
|
if (Format::unormD24uintS8 == tex->GetFormat())
|
||||||
|
vkimb[index].subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (vkimb[index].oldLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL && vkimb[index].newLayout == VK_IMAGE_LAYOUT_GENERAL)
|
||||||
|
{
|
||||||
|
UseDefaultsForOldLayout();
|
||||||
|
dstStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
|
||||||
|
vkimb[index].dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
VERUS_RT_FAIL("");
|
UseDefaultsForOldLayout();
|
||||||
|
UseDefaultsForNewLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
index++;
|
index++;
|
||||||
|
@ -362,31 +356,3 @@ VkCommandBuffer CommandBufferVulkan::GetVkCommandBuffer() const
|
||||||
VERUS_QREF_RENDERER;
|
VERUS_QREF_RENDERER;
|
||||||
return _commandBuffers[renderer->GetRingBufferIndex()];
|
return _commandBuffers[renderer->GetRingBufferIndex()];
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandBufferVulkan::InitOneTimeSubmit()
|
|
||||||
{
|
|
||||||
VERUS_QREF_RENDERER;
|
|
||||||
VERUS_QREF_RENDERER_VULKAN;
|
|
||||||
_oneTimeSubmit = true;
|
|
||||||
auto commandPool = pRendererVulkan->GetVkCommandPool(renderer->GetRingBufferIndex());
|
|
||||||
auto commandBuffer = pRendererVulkan->CreateCommandBuffer(commandPool);
|
|
||||||
VERUS_FOR(i, BaseRenderer::s_ringBufferSize)
|
|
||||||
_commandBuffers[i] = commandBuffer;
|
|
||||||
Begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CommandBufferVulkan::DoneOneTimeSubmit()
|
|
||||||
{
|
|
||||||
VERUS_QREF_RENDERER;
|
|
||||||
VERUS_QREF_RENDERER_VULKAN;
|
|
||||||
End();
|
|
||||||
VkSubmitInfo submitInfo = {};
|
|
||||||
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
|
||||||
submitInfo.commandBufferCount = 1;
|
|
||||||
submitInfo.pCommandBuffers = _commandBuffers;
|
|
||||||
vkQueueSubmit(pRendererVulkan->GetVkGraphicsQueue(), 1, &submitInfo, VK_NULL_HANDLE);
|
|
||||||
vkQueueWaitIdle(pRendererVulkan->GetVkGraphicsQueue());
|
|
||||||
auto commandPool = pRendererVulkan->GetVkCommandPool(renderer->GetRingBufferIndex());
|
|
||||||
vkFreeCommandBuffers(pRendererVulkan->GetVkDevice(), commandPool, 1, _commandBuffers);
|
|
||||||
_oneTimeSubmit = false;
|
|
||||||
}
|
|
||||||
|
|
|
@ -16,6 +16,9 @@ namespace verus
|
||||||
virtual void Init() override;
|
virtual void Init() override;
|
||||||
virtual void Done() override;
|
virtual void Done() override;
|
||||||
|
|
||||||
|
virtual void InitOneTimeSubmit();
|
||||||
|
virtual void DoneOneTimeSubmit();
|
||||||
|
|
||||||
virtual void Begin() override;
|
virtual void Begin() override;
|
||||||
virtual void End() override;
|
virtual void End() override;
|
||||||
|
|
||||||
|
@ -46,9 +49,6 @@ namespace verus
|
||||||
//
|
//
|
||||||
|
|
||||||
VkCommandBuffer GetVkCommandBuffer() const;
|
VkCommandBuffer GetVkCommandBuffer() const;
|
||||||
|
|
||||||
void InitOneTimeSubmit();
|
|
||||||
void DoneOneTimeSubmit();
|
|
||||||
};
|
};
|
||||||
VERUS_TYPEDEFS(CommandBufferVulkan);
|
VERUS_TYPEDEFS(CommandBufferVulkan);
|
||||||
}
|
}
|
||||||
|
|
|
@ -768,7 +768,7 @@ void RendererVulkan::ImGuiRenderDrawData()
|
||||||
{
|
{
|
||||||
VERUS_QREF_RENDERER;
|
VERUS_QREF_RENDERER;
|
||||||
ImGui::Render();
|
ImGui::Render();
|
||||||
VkCommandBuffer commandBuffer = static_cast<CommandBufferVulkan*>(&(*renderer.GetCommandBuffer()))->GetVkCommandBuffer();
|
VkCommandBuffer commandBuffer = static_cast<CommandBufferVulkan*>(renderer.GetCommandBuffer().Get())->GetVkCommandBuffer();
|
||||||
if (ImGui::GetDrawData())
|
if (ImGui::GetDrawData())
|
||||||
ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), commandBuffer);
|
ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), commandBuffer);
|
||||||
}
|
}
|
||||||
|
@ -825,7 +825,7 @@ void RendererVulkan::EndFrame(bool present)
|
||||||
_acquireNextImageSemaphore = _acquireNextImageSemaphores[_ringBufferIndex];
|
_acquireNextImageSemaphore = _acquireNextImageSemaphores[_ringBufferIndex];
|
||||||
_queueSubmitSemaphore = _queueSubmitSemaphores[_ringBufferIndex];
|
_queueSubmitSemaphore = _queueSubmitSemaphores[_ringBufferIndex];
|
||||||
|
|
||||||
VkCommandBuffer commandBuffer = static_cast<CommandBufferVulkan*>(&(*renderer.GetCommandBuffer()))->GetVkCommandBuffer();
|
VkCommandBuffer commandBuffer = static_cast<CommandBufferVulkan*>(renderer.GetCommandBuffer().Get())->GetVkCommandBuffer();
|
||||||
VkSubmitInfo vksi = {};
|
VkSubmitInfo vksi = {};
|
||||||
vksi.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
vksi.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||||
if (present)
|
if (present)
|
||||||
|
@ -1260,7 +1260,7 @@ void RendererVulkan::CopyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDevice
|
||||||
VERUS_QREF_RENDERER;
|
VERUS_QREF_RENDERER;
|
||||||
|
|
||||||
if (!pCB)
|
if (!pCB)
|
||||||
pCB = &(*renderer.GetCommandBuffer());
|
pCB = renderer.GetCommandBuffer().Get();
|
||||||
auto commandBuffer = static_cast<PCommandBufferVulkan>(pCB)->GetVkCommandBuffer();
|
auto commandBuffer = static_cast<PCommandBufferVulkan>(pCB)->GetVkCommandBuffer();
|
||||||
|
|
||||||
VkBufferCopy region = {};
|
VkBufferCopy region = {};
|
||||||
|
@ -1287,7 +1287,7 @@ void RendererVulkan::CopyImage(
|
||||||
VERUS_QREF_RENDERER;
|
VERUS_QREF_RENDERER;
|
||||||
|
|
||||||
if (!pCB)
|
if (!pCB)
|
||||||
pCB = &(*renderer.GetCommandBuffer());
|
pCB = renderer.GetCommandBuffer().Get();
|
||||||
auto commandBuffer = static_cast<PCommandBufferVulkan>(pCB)->GetVkCommandBuffer();
|
auto commandBuffer = static_cast<PCommandBufferVulkan>(pCB)->GetVkCommandBuffer();
|
||||||
|
|
||||||
VkImageCopy region = {};
|
VkImageCopy region = {};
|
||||||
|
@ -1313,7 +1313,7 @@ void RendererVulkan::CopyBufferToImage(
|
||||||
VERUS_QREF_RENDERER;
|
VERUS_QREF_RENDERER;
|
||||||
|
|
||||||
if (!pCB)
|
if (!pCB)
|
||||||
pCB = &(*renderer.GetCommandBuffer());
|
pCB = renderer.GetCommandBuffer().Get();
|
||||||
auto commandBuffer = static_cast<PCommandBufferVulkan>(pCB)->GetVkCommandBuffer();
|
auto commandBuffer = static_cast<PCommandBufferVulkan>(pCB)->GetVkCommandBuffer();
|
||||||
|
|
||||||
VkBufferImageCopy region = {};
|
VkBufferImageCopy region = {};
|
||||||
|
@ -1339,7 +1339,7 @@ void RendererVulkan::CopyImageToBuffer(
|
||||||
VERUS_QREF_RENDERER;
|
VERUS_QREF_RENDERER;
|
||||||
|
|
||||||
if (!pCB)
|
if (!pCB)
|
||||||
pCB = &(*renderer.GetCommandBuffer());
|
pCB = renderer.GetCommandBuffer().Get();
|
||||||
auto commandBuffer = static_cast<PCommandBufferVulkan>(pCB)->GetVkCommandBuffer();
|
auto commandBuffer = static_cast<PCommandBufferVulkan>(pCB)->GetVkCommandBuffer();
|
||||||
|
|
||||||
VkBufferImageCopy region = {};
|
VkBufferImageCopy region = {};
|
||||||
|
|
|
@ -210,7 +210,7 @@ void TextureVulkan::UpdateSubresource(const void* p, int mipLevel, int arrayLaye
|
||||||
vmaUnmapMemory(pRendererVulkan->GetVmaAllocator(), sb._vmaAllocation);
|
vmaUnmapMemory(pRendererVulkan->GetVmaAllocator(), sb._vmaAllocation);
|
||||||
|
|
||||||
if (!pCB)
|
if (!pCB)
|
||||||
pCB = &(*renderer.GetCommandBuffer());
|
pCB = renderer.GetCommandBuffer().Get();
|
||||||
pCB->PipelineImageMemoryBarrier(TexturePtr::From(this), GetSubresourceMainLayout(mipLevel, arrayLayer), ImageLayout::transferDst, mipLevel, arrayLayer);
|
pCB->PipelineImageMemoryBarrier(TexturePtr::From(this), GetSubresourceMainLayout(mipLevel, arrayLayer), ImageLayout::transferDst, mipLevel, arrayLayer);
|
||||||
pRendererVulkan->CopyBufferToImage(
|
pRendererVulkan->CopyBufferToImage(
|
||||||
sb._buffer,
|
sb._buffer,
|
||||||
|
@ -223,7 +223,7 @@ void TextureVulkan::UpdateSubresource(const void* p, int mipLevel, int arrayLaye
|
||||||
Schedule();
|
Schedule();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TextureVulkan::ReadbackSubresource(void* p, PBaseCommandBuffer pCB)
|
bool TextureVulkan::ReadbackSubresource(void* p, bool recordCopyCommand, PBaseCommandBuffer pCB)
|
||||||
{
|
{
|
||||||
VERUS_QREF_RENDERER;
|
VERUS_QREF_RENDERER;
|
||||||
VERUS_QREF_RENDERER_VULKAN;
|
VERUS_QREF_RENDERER_VULKAN;
|
||||||
|
@ -235,9 +235,10 @@ bool TextureVulkan::ReadbackSubresource(void* p, PBaseCommandBuffer pCB)
|
||||||
|
|
||||||
auto& rb = _vReadbackBuffers[renderer->GetRingBufferIndex()];
|
auto& rb = _vReadbackBuffers[renderer->GetRingBufferIndex()];
|
||||||
|
|
||||||
// Schedule copying to readback buffer:
|
if (recordCopyCommand)
|
||||||
|
{
|
||||||
if (!pCB)
|
if (!pCB)
|
||||||
pCB = &(*renderer.GetCommandBuffer());
|
pCB = renderer.GetCommandBuffer().Get();
|
||||||
pCB->PipelineImageMemoryBarrier(TexturePtr::From(this), GetSubresourceMainLayout(_desc._readbackMip, 0), ImageLayout::transferSrc, _desc._readbackMip, 0);
|
pCB->PipelineImageMemoryBarrier(TexturePtr::From(this), GetSubresourceMainLayout(_desc._readbackMip, 0), ImageLayout::transferSrc, _desc._readbackMip, 0);
|
||||||
pRendererVulkan->CopyImageToBuffer(
|
pRendererVulkan->CopyImageToBuffer(
|
||||||
_image, _desc._readbackMip, 0,
|
_image, _desc._readbackMip, 0,
|
||||||
|
@ -245,13 +246,16 @@ bool TextureVulkan::ReadbackSubresource(void* p, PBaseCommandBuffer pCB)
|
||||||
rb._buffer,
|
rb._buffer,
|
||||||
pCB);
|
pCB);
|
||||||
pCB->PipelineImageMemoryBarrier(TexturePtr::From(this), ImageLayout::transferSrc, _mainLayout, _desc._readbackMip, 0);
|
pCB->PipelineImageMemoryBarrier(TexturePtr::From(this), ImageLayout::transferSrc, _mainLayout, _desc._readbackMip, 0);
|
||||||
|
}
|
||||||
|
|
||||||
// Read current data from readback buffer:
|
if (p) // Read current data from readback buffer:
|
||||||
|
{
|
||||||
void* pData = nullptr;
|
void* pData = nullptr;
|
||||||
if (VK_SUCCESS != (res = vmaMapMemory(pRendererVulkan->GetVmaAllocator(), rb._vmaAllocation, &pData)))
|
if (VK_SUCCESS != (res = vmaMapMemory(pRendererVulkan->GetVmaAllocator(), rb._vmaAllocation, &pData)))
|
||||||
throw VERUS_RECOVERABLE << "vmaMapMemory(), res=" << res;
|
throw VERUS_RECOVERABLE << "vmaMapMemory(), res=" << res;
|
||||||
memcpy(p, pData, bufferSize);
|
memcpy(p, pData, bufferSize);
|
||||||
vmaUnmapMemory(pRendererVulkan->GetVmaAllocator(), rb._vmaAllocation);
|
vmaUnmapMemory(pRendererVulkan->GetVmaAllocator(), rb._vmaAllocation);
|
||||||
|
}
|
||||||
|
|
||||||
return _initAtFrame + BaseRenderer::s_ringBufferSize < renderer.GetFrameCount();
|
return _initAtFrame + BaseRenderer::s_ringBufferSize < renderer.GetFrameCount();
|
||||||
}
|
}
|
||||||
|
@ -263,7 +267,9 @@ void TextureVulkan::GenerateMips(PBaseCommandBuffer pCB)
|
||||||
VERUS_QREF_RENDERER_VULKAN;
|
VERUS_QREF_RENDERER_VULKAN;
|
||||||
|
|
||||||
if (!pCB)
|
if (!pCB)
|
||||||
pCB = &(*renderer.GetCommandBuffer());
|
pCB = renderer.GetCommandBuffer().Get();
|
||||||
|
auto shader = renderer.GetShaderGenerateMips();
|
||||||
|
auto& ub = renderer.GetUbGenerateMips();
|
||||||
auto tex = TexturePtr::From(this);
|
auto tex = TexturePtr::From(this);
|
||||||
|
|
||||||
if (!_definedStorage)
|
if (!_definedStorage)
|
||||||
|
@ -286,10 +292,7 @@ void TextureVulkan::GenerateMips(PBaseCommandBuffer pCB)
|
||||||
|
|
||||||
pCB->BindPipeline(renderer.GetPipelineGenerateMips(!!(_desc._flags & TextureDesc::Flags::exposureMips)));
|
pCB->BindPipeline(renderer.GetPipelineGenerateMips(!!(_desc._flags & TextureDesc::Flags::exposureMips)));
|
||||||
|
|
||||||
auto shader = renderer.GetShaderGenerateMips();
|
|
||||||
shader->BeginBindDescriptors();
|
shader->BeginBindDescriptors();
|
||||||
auto& ub = renderer.GetUbGenerateMips();
|
|
||||||
|
|
||||||
const bool createComplexSets = _vCshGenerateMips.empty();
|
const bool createComplexSets = _vCshGenerateMips.empty();
|
||||||
int dispatchIndex = 0;
|
int dispatchIndex = 0;
|
||||||
for (int srcMip = 0; srcMip < _desc._mipLevels - 1;)
|
for (int srcMip = 0; srcMip < _desc._mipLevels - 1;)
|
||||||
|
@ -357,7 +360,6 @@ void TextureVulkan::GenerateMips(PBaseCommandBuffer pCB)
|
||||||
srcMip += dispatchMipCount;
|
srcMip += dispatchMipCount;
|
||||||
dispatchIndex++;
|
dispatchIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
shader->EndBindDescriptors();
|
shader->EndBindDescriptors();
|
||||||
|
|
||||||
// Revert to main layout:
|
// Revert to main layout:
|
||||||
|
|
|
@ -34,7 +34,7 @@ namespace verus
|
||||||
virtual void Done() override;
|
virtual void Done() override;
|
||||||
|
|
||||||
virtual void UpdateSubresource(const void* p, int mipLevel, int arrayLayer, PBaseCommandBuffer pCB) override;
|
virtual void UpdateSubresource(const void* p, int mipLevel, int arrayLayer, PBaseCommandBuffer pCB) override;
|
||||||
virtual bool ReadbackSubresource(void* p, PBaseCommandBuffer pCB) override;
|
virtual bool ReadbackSubresource(void* p, bool recordCopyCommand, PBaseCommandBuffer pCB) override;
|
||||||
|
|
||||||
virtual void GenerateMips(PBaseCommandBuffer pCB) override;
|
virtual void GenerateMips(PBaseCommandBuffer pCB) override;
|
||||||
|
|
||||||
|
|
12
Scripts/CompressForest.py
Normal file
12
Scripts/CompressForest.py
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import glob, os
|
||||||
|
|
||||||
|
exe = "C:\\Home\\Projects\\Verus\\verus\\Bin\\TextureTool.exe"
|
||||||
|
|
||||||
|
for file in glob.glob("*.GB0.psd"):
|
||||||
|
os.system("\"" + exe + "\" " + file)
|
||||||
|
|
||||||
|
for file in glob.glob("*.GB1.FX.psd"):
|
||||||
|
os.system("\"" + exe + "\" --non-color-data " + file)
|
||||||
|
|
||||||
|
for file in glob.glob("*.GB2.FX.psd"):
|
||||||
|
os.system("\"" + exe + "\" --non-color-data " + file)
|
|
@ -3,8 +3,8 @@
|
||||||
<ImportGroup Label="PropertySheets" />
|
<ImportGroup Label="PropertySheets" />
|
||||||
<PropertyGroup Label="UserMacros" />
|
<PropertyGroup Label="UserMacros" />
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<IncludePath>C:\Compressonator_3.2.4691\include;C:\Home\Projects\Verus\verus\Verus\src;C:\Home\Middleware\AMD Tootle 2.3\include;C:\Home\Middleware\bullet3-2.89\src;C:\Home\Middleware\bullet3-2.89\Extras;C:\Home\Middleware\DevIL-Windows-SDK-1.8.0\include;C:\Home\Middleware\libogg-1.3.4\include;C:\Home\Middleware\libvorbis-1.3.6\include;C:\Home\Middleware\openal-soft-1.20.1-bin\include;C:\Home\Middleware\SDL2-2.0.12\include;C:\VulkanSDK\1.2.141.2\Include;$(IncludePath)</IncludePath>
|
<IncludePath>C:\Compressonator_3.2.4691\include;C:\Home\Projects\Verus\verus\Verus\src;C:\Home\Middleware\AMD Tootle 2.3\include;C:\Home\Middleware\bullet3-2.89\src;C:\Home\Middleware\bullet3-2.89\Extras;C:\Home\Middleware\DevIL-Windows-SDK-1.8.0\include;C:\Home\Middleware\libogg-1.3.4\include;C:\Home\Middleware\libvorbis-1.3.6\include;C:\Home\Middleware\openal-soft-1.20.1-bin\include;C:\Home\Middleware\SDL2-2.0.12\include;C:\VulkanSDK\1.2.148.1\Include;$(IncludePath)</IncludePath>
|
||||||
<LibraryPath>C:\Compressonator_3.2.4691\lib\VS2017\x64;C:\Home\Middleware\bullet3-2.89\bin;C:\Home\Middleware\AMD Tootle 2.3\lib;C:\Home\Middleware\DevIL-Windows-SDK-1.8.0\lib\x64\Release;C:\Home\Middleware\libogg-1.3.4\lib;C:\Home\Middleware\libvorbis-1.3.6\lib2;C:\Home\Middleware\openal-soft-1.20.1-bin\libs\Win64;C:\Home\Middleware\SDL2-2.0.12\lib\x64;C:\VulkanSDK\1.2.141.2\Lib;$(LibraryPath)</LibraryPath>
|
<LibraryPath>C:\Compressonator_3.2.4691\lib\VS2017\x64;C:\Home\Middleware\bullet3-2.89\bin;C:\Home\Middleware\AMD Tootle 2.3\lib;C:\Home\Middleware\DevIL-Windows-SDK-1.8.0\lib\x64\Release;C:\Home\Middleware\libogg-1.3.4\lib;C:\Home\Middleware\libvorbis-1.3.6\lib2;C:\Home\Middleware\openal-soft-1.20.1-bin\libs\Win64;C:\Home\Middleware\SDL2-2.0.12\lib\x64;C:\VulkanSDK\1.2.148.1\Lib;$(LibraryPath)</LibraryPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemDefinitionGroup />
|
<ItemDefinitionGroup />
|
||||||
<ItemGroup />
|
<ItemGroup />
|
||||||
|
|
|
@ -235,6 +235,13 @@
|
||||||
<ClInclude Include="src\Scene\Scatter.h" />
|
<ClInclude Include="src\Scene\Scatter.h" />
|
||||||
<ClInclude Include="src\Scene\Scene.h" />
|
<ClInclude Include="src\Scene\Scene.h" />
|
||||||
<ClInclude Include="src\Scene\SceneManager.h" />
|
<ClInclude Include="src\Scene\SceneManager.h" />
|
||||||
|
<ClInclude Include="src\Scene\SceneNodes\Block.h" />
|
||||||
|
<ClInclude Include="src\Scene\SceneNodes\Light.h" />
|
||||||
|
<ClInclude Include="src\Scene\SceneNodes\Model.h" />
|
||||||
|
<ClInclude Include="src\Scene\SceneNodes\SceneNode.h" />
|
||||||
|
<ClInclude Include="src\Scene\SceneNodes\SceneNodes.h" />
|
||||||
|
<ClInclude Include="src\Scene\SceneNodes\TransformGizmo.h" />
|
||||||
|
<ClInclude Include="src\Scene\SceneNodes\Types.h" />
|
||||||
<ClInclude Include="src\Scene\ShadowMap.h" />
|
<ClInclude Include="src\Scene\ShadowMap.h" />
|
||||||
<ClInclude Include="src\Scene\Terrain.h" />
|
<ClInclude Include="src\Scene\Terrain.h" />
|
||||||
<ClInclude Include="src\Scene\Water.h" />
|
<ClInclude Include="src\Scene\Water.h" />
|
||||||
|
@ -394,6 +401,12 @@
|
||||||
<ClCompile Include="src\Scene\Scatter.cpp" />
|
<ClCompile Include="src\Scene\Scatter.cpp" />
|
||||||
<ClCompile Include="src\Scene\Scene.cpp" />
|
<ClCompile Include="src\Scene\Scene.cpp" />
|
||||||
<ClCompile Include="src\Scene\SceneManager.cpp" />
|
<ClCompile Include="src\Scene\SceneManager.cpp" />
|
||||||
|
<ClCompile Include="src\Scene\SceneNodes\Block.cpp" />
|
||||||
|
<ClCompile Include="src\Scene\SceneNodes\Light.cpp" />
|
||||||
|
<ClCompile Include="src\Scene\SceneNodes\Model.cpp" />
|
||||||
|
<ClCompile Include="src\Scene\SceneNodes\SceneNode.cpp" />
|
||||||
|
<ClCompile Include="src\Scene\SceneNodes\SceneNodes.cpp" />
|
||||||
|
<ClCompile Include="src\Scene\SceneNodes\TransformGizmo.cpp" />
|
||||||
<ClCompile Include="src\Scene\ShadowMap.cpp" />
|
<ClCompile Include="src\Scene\ShadowMap.cpp" />
|
||||||
<ClCompile Include="src\Scene\Terrain.cpp" />
|
<ClCompile Include="src\Scene\Terrain.cpp" />
|
||||||
<ClCompile Include="src\Scene\Water.cpp" />
|
<ClCompile Include="src\Scene\Water.cpp" />
|
||||||
|
@ -727,6 +740,30 @@
|
||||||
<FileType>Document</FileType>
|
<FileType>Document</FileType>
|
||||||
</None>
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="src\Shaders\DS_AO.hlsl">
|
||||||
|
<FileType>Document</FileType>
|
||||||
|
</None>
|
||||||
|
<None Include="src\Shaders\DS_AO.inc.hlsl">
|
||||||
|
<FileType>Document</FileType>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="src\Shaders\DS_BakeSprites.hlsl">
|
||||||
|
<FileType>Document</FileType>
|
||||||
|
</None>
|
||||||
|
<None Include="src\Shaders\DS_BakeSprites.inc.hlsl">
|
||||||
|
<FileType>Document</FileType>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="src\Shaders\DS_Forest.hlsl">
|
||||||
|
<FileType>Document</FileType>
|
||||||
|
</None>
|
||||||
|
<None Include="src\Shaders\DS_Forest.inc.hlsl">
|
||||||
|
<FileType>Document</FileType>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
|
|
|
@ -94,6 +94,9 @@
|
||||||
<Filter Include="src\Effects">
|
<Filter Include="src\Effects">
|
||||||
<UniqueIdentifier>{5ea015f8-8b97-4159-ad67-d71abdba3c91}</UniqueIdentifier>
|
<UniqueIdentifier>{5ea015f8-8b97-4159-ad67-d71abdba3c91}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
<Filter Include="src\Scene\SceneNodes">
|
||||||
|
<UniqueIdentifier>{07af1a9e-5cdc-4264-811b-d958ec70a709}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="src\CGI\BaseGeometry.h">
|
<ClInclude Include="src\CGI\BaseGeometry.h">
|
||||||
|
@ -645,6 +648,27 @@
|
||||||
<ClInclude Include="src\Scene\Scatter.h">
|
<ClInclude Include="src\Scene\Scatter.h">
|
||||||
<Filter>src\Scene</Filter>
|
<Filter>src\Scene</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Scene\SceneNodes\Block.h">
|
||||||
|
<Filter>src\Scene\SceneNodes</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Scene\SceneNodes\Light.h">
|
||||||
|
<Filter>src\Scene\SceneNodes</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Scene\SceneNodes\Model.h">
|
||||||
|
<Filter>src\Scene\SceneNodes</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Scene\SceneNodes\SceneNode.h">
|
||||||
|
<Filter>src\Scene\SceneNodes</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Scene\SceneNodes\SceneNodes.h">
|
||||||
|
<Filter>src\Scene\SceneNodes</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Scene\SceneNodes\TransformGizmo.h">
|
||||||
|
<Filter>src\Scene\SceneNodes</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Scene\SceneNodes\Types.h">
|
||||||
|
<Filter>src\Scene\SceneNodes</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="src\CGI\BaseGeometry.cpp">
|
<ClCompile Include="src\CGI\BaseGeometry.cpp">
|
||||||
|
@ -1094,6 +1118,24 @@
|
||||||
<ClCompile Include="src\Scene\Scatter.cpp">
|
<ClCompile Include="src\Scene\Scatter.cpp">
|
||||||
<Filter>src\Scene</Filter>
|
<Filter>src\Scene</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Scene\SceneNodes\Block.cpp">
|
||||||
|
<Filter>src\Scene\SceneNodes</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Scene\SceneNodes\Light.cpp">
|
||||||
|
<Filter>src\Scene\SceneNodes</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Scene\SceneNodes\Model.cpp">
|
||||||
|
<Filter>src\Scene\SceneNodes</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Scene\SceneNodes\SceneNode.cpp">
|
||||||
|
<Filter>src\Scene\SceneNodes</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Scene\SceneNodes\SceneNodes.cpp">
|
||||||
|
<Filter>src\Scene\SceneNodes</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Scene\SceneNodes\TransformGizmo.cpp">
|
||||||
|
<Filter>src\Scene\SceneNodes</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="src\Shaders\Lib.hlsl">
|
<None Include="src\Shaders\Lib.hlsl">
|
||||||
|
@ -1222,6 +1264,18 @@
|
||||||
<None Include="src\Shaders\Bloom.inc.hlsl">
|
<None Include="src\Shaders\Bloom.inc.hlsl">
|
||||||
<Filter>src\Shaders</Filter>
|
<Filter>src\Shaders</Filter>
|
||||||
</None>
|
</None>
|
||||||
|
<None Include="src\Shaders\DS_AO.hlsl">
|
||||||
|
<Filter>src\Shaders</Filter>
|
||||||
|
</None>
|
||||||
|
<None Include="src\Shaders\DS_AO.inc.hlsl">
|
||||||
|
<Filter>src\Shaders</Filter>
|
||||||
|
</None>
|
||||||
|
<None Include="src\Shaders\DS_BakeSprites.hlsl">
|
||||||
|
<Filter>src\Shaders</Filter>
|
||||||
|
</None>
|
||||||
|
<None Include="src\Shaders\DS_BakeSprites.inc.hlsl">
|
||||||
|
<Filter>src\Shaders</Filter>
|
||||||
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Natvis Include="src\ThirdParty\pugixml-1.10\pugixml.natvis">
|
<Natvis Include="src\ThirdParty\pugixml-1.10\pugixml.natvis">
|
||||||
|
@ -1234,4 +1288,12 @@
|
||||||
<Filter>src\ThirdParty\imgui</Filter>
|
<Filter>src\ThirdParty\imgui</Filter>
|
||||||
</Natvis>
|
</Natvis>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<FxCompile Include="src\Shaders\DS_Forest.hlsl">
|
||||||
|
<Filter>src\Shaders</Filter>
|
||||||
|
</FxCompile>
|
||||||
|
<FxCompile Include="src\Shaders\DS_Forest.inc.hlsl">
|
||||||
|
<Filter>src\Shaders</Filter>
|
||||||
|
</FxCompile>
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
|
@ -4,15 +4,19 @@ namespace verus
|
||||||
{
|
{
|
||||||
namespace App
|
namespace App
|
||||||
{
|
{
|
||||||
|
// Capacity is per frame. 3 frames are buffered.
|
||||||
class Limits
|
class Limits
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
int _d3d12_dhViewsCapacity = 10000;
|
int _d3d12_dhViewsCapacity = 10000; // D3D limit is one million.
|
||||||
int _d3d12_dhSamplersCapacity = 500;
|
int _d3d12_dhSamplersCapacity = 500; // D3D limit is 2048.
|
||||||
|
int _generateMips_ubCapacity = 100;
|
||||||
int _mesh_ubPerFrameCapacity = 100;
|
int _mesh_ubPerFrameCapacity = 100;
|
||||||
int _mesh_ubPerMaterialFSCapacity = 1000;
|
int _mesh_ubPerMaterialFSCapacity = 1000;
|
||||||
int _mesh_ubPerMeshVSCapacity = 10000;
|
int _mesh_ubPerMeshVSCapacity = 10000;
|
||||||
int _mesh_ubSkinningVSCapacity = 5000;
|
int _mesh_ubSkinningVSCapacity = 5000;
|
||||||
|
int _quad_ubVSCapacity = 100;
|
||||||
|
int _quad_ubFSCapacity = 100;
|
||||||
int _terrain_ubDrawDepthCapacity = 100;
|
int _terrain_ubDrawDepthCapacity = 100;
|
||||||
};
|
};
|
||||||
VERUS_TYPEDEFS(Limits);
|
VERUS_TYPEDEFS(Limits);
|
||||||
|
|
|
@ -13,6 +13,14 @@ void CommandBufferPtr::Init()
|
||||||
_p->Init();
|
_p->Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CommandBufferPtr::InitOneTimeSubmit()
|
||||||
|
{
|
||||||
|
VERUS_QREF_RENDERER;
|
||||||
|
VERUS_RT_ASSERT(!_p);
|
||||||
|
_p = renderer->InsertCommandBuffer();
|
||||||
|
_p->InitOneTimeSubmit();
|
||||||
|
}
|
||||||
|
|
||||||
void CommandBufferPwn::Done()
|
void CommandBufferPwn::Done()
|
||||||
{
|
{
|
||||||
if (_p)
|
if (_p)
|
||||||
|
|
|
@ -16,6 +16,9 @@ namespace verus
|
||||||
virtual void Init() = 0;
|
virtual void Init() = 0;
|
||||||
virtual void Done() = 0;
|
virtual void Done() = 0;
|
||||||
|
|
||||||
|
virtual void InitOneTimeSubmit() = 0;
|
||||||
|
virtual void DoneOneTimeSubmit() = 0;
|
||||||
|
|
||||||
virtual void Begin() = 0;
|
virtual void Begin() = 0;
|
||||||
virtual void End() = 0;
|
virtual void End() = 0;
|
||||||
|
|
||||||
|
@ -50,6 +53,7 @@ namespace verus
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void Init();
|
void Init();
|
||||||
|
void InitOneTimeSubmit();
|
||||||
};
|
};
|
||||||
VERUS_TYPEDEFS(CommandBufferPtr);
|
VERUS_TYPEDEFS(CommandBufferPtr);
|
||||||
|
|
||||||
|
|
|
@ -161,8 +161,8 @@ void BaseRenderer::SetAlphaBlendHelper(
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
alphaBlendOp = colorBlendOp;
|
alphaBlendOp = 0;
|
||||||
srcAlphaBlendFactor = srcColorBlendFactor;
|
srcAlphaBlendFactor = 1;
|
||||||
dstAlphaBlendFactor = dstColorBlendFactor;
|
dstAlphaBlendFactor = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,7 +112,7 @@ namespace verus
|
||||||
virtual void Async_Run(CSZ url, RcBlob blob) override;
|
virtual void Async_Run(CSZ url, RcBlob blob) override;
|
||||||
|
|
||||||
virtual void UpdateSubresource(const void* p, int mipLevel = 0, int arrayLayer = 0, BaseCommandBuffer* pCB = nullptr) = 0;
|
virtual void UpdateSubresource(const void* p, int mipLevel = 0, int arrayLayer = 0, BaseCommandBuffer* pCB = nullptr) = 0;
|
||||||
virtual bool ReadbackSubresource(void* p, BaseCommandBuffer* pCB = nullptr) = 0;
|
virtual bool ReadbackSubresource(void* p, bool recordCopyCommand = true, BaseCommandBuffer* pCB = nullptr) = 0;
|
||||||
|
|
||||||
virtual void GenerateMips(BaseCommandBuffer* pCB = nullptr) = 0;
|
virtual void GenerateMips(BaseCommandBuffer* pCB = nullptr) = 0;
|
||||||
|
|
||||||
|
|
|
@ -79,6 +79,8 @@ void DebugDraw::Begin(Type type, PcTransform3 pMat, bool zEnable)
|
||||||
VERUS_QREF_SM;
|
VERUS_QREF_SM;
|
||||||
VERUS_QREF_RENDERER;
|
VERUS_QREF_RENDERER;
|
||||||
|
|
||||||
|
auto cb = renderer.GetCommandBuffer();
|
||||||
|
|
||||||
_type = type;
|
_type = type;
|
||||||
_vertCount = 0;
|
_vertCount = 0;
|
||||||
if (_currentFrame != renderer.GetFrameCount())
|
if (_currentFrame != renderer.GetFrameCount())
|
||||||
|
@ -104,10 +106,8 @@ void DebugDraw::Begin(Type type, PcTransform3 pMat, bool zEnable)
|
||||||
if (!zEnable)
|
if (!zEnable)
|
||||||
pipe = static_cast<PIPE>(pipe + 1);
|
pipe = static_cast<PIPE>(pipe + 1);
|
||||||
|
|
||||||
auto cb = renderer.GetCommandBuffer();
|
|
||||||
|
|
||||||
cb->BindVertexBuffers(_geo);
|
|
||||||
cb->BindPipeline(_pipe[pipe]);
|
cb->BindPipeline(_pipe[pipe]);
|
||||||
|
cb->BindVertexBuffers(_geo);
|
||||||
_shader->BeginBindDescriptors();
|
_shader->BeginBindDescriptors();
|
||||||
cb->BindDescriptors(_shader, 0);
|
cb->BindDescriptors(_shader, 0);
|
||||||
_shader->EndBindDescriptors();
|
_shader->EndBindDescriptors();
|
||||||
|
|
|
@ -10,6 +10,12 @@ DeferredShading::UB_ShadowFS DeferredShading::s_ubShadowFS;
|
||||||
DeferredShading::UB_PerObject DeferredShading::s_ubPerObject;
|
DeferredShading::UB_PerObject DeferredShading::s_ubPerObject;
|
||||||
DeferredShading::UB_ComposeVS DeferredShading::s_ubComposeVS;
|
DeferredShading::UB_ComposeVS DeferredShading::s_ubComposeVS;
|
||||||
DeferredShading::UB_ComposeFS DeferredShading::s_ubComposeFS;
|
DeferredShading::UB_ComposeFS DeferredShading::s_ubComposeFS;
|
||||||
|
DeferredShading::UB_AOPerFrame DeferredShading::s_ubAOPerFrame;
|
||||||
|
DeferredShading::UB_AOTexturesFS DeferredShading::s_ubAOTexturesFS;
|
||||||
|
DeferredShading::UB_AOPerMeshVS DeferredShading::s_ubAOPerMeshVS;
|
||||||
|
DeferredShading::UB_AOPerObject DeferredShading::s_ubAOPerObject;
|
||||||
|
DeferredShading::UB_BakeSpritesVS DeferredShading::s_ubBakeSpritesVS;
|
||||||
|
DeferredShading::UB_BakeSpritesFS DeferredShading::s_ubBakeSpritesFS;
|
||||||
|
|
||||||
DeferredShading::DeferredShading()
|
DeferredShading::DeferredShading()
|
||||||
{
|
{
|
||||||
|
@ -58,6 +64,16 @@ void DeferredShading::Init()
|
||||||
{
|
{
|
||||||
RP::Dependency("Sp0", "Sp1").Mode(1)
|
RP::Dependency("Sp0", "Sp1").Mode(1)
|
||||||
});
|
});
|
||||||
|
_rphAO = renderer->CreateRenderPass(
|
||||||
|
{
|
||||||
|
RP::Attachment("Attach", Format::unormR8).Layout(ImageLayout::fsReadOnly),
|
||||||
|
RP::Attachment("Depth", Format::unormD24uintS8).Layout(ImageLayout::depthStencilReadOnly)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
RP::Subpass("Sp0").Color(
|
||||||
|
{RP::Ref("Attach", ImageLayout::colorAttachment)}).DepthStencil(RP::Ref("Depth", ImageLayout::depthStencilReadOnly))
|
||||||
|
},
|
||||||
|
{});
|
||||||
_rphCompose = renderer->CreateRenderPass(
|
_rphCompose = renderer->CreateRenderPass(
|
||||||
{
|
{
|
||||||
RP::Attachment("ComposedA", Format::floatR11G11B10).LoadOpDontCare().Layout(ImageLayout::fsReadOnly),
|
RP::Attachment("ComposedA", Format::floatR11G11B10).LoadOpDontCare().Layout(ImageLayout::fsReadOnly),
|
||||||
|
@ -95,14 +111,14 @@ void DeferredShading::Init()
|
||||||
Sampler::input,
|
Sampler::input,
|
||||||
Sampler::shadow,
|
Sampler::shadow,
|
||||||
Sampler::nearestClampMipN
|
Sampler::nearestClampMipN
|
||||||
}, CGI::ShaderStageFlags::fs);
|
}, ShaderStageFlags::fs);
|
||||||
_shader[SHADER_LIGHT]->CreateDescriptorSet(2, &s_ubPerMeshVS, sizeof(s_ubPerMeshVS), 1000, {}, CGI::ShaderStageFlags::vs);
|
_shader[SHADER_LIGHT]->CreateDescriptorSet(2, &s_ubPerMeshVS, sizeof(s_ubPerMeshVS), 1000, {}, ShaderStageFlags::vs);
|
||||||
_shader[SHADER_LIGHT]->CreateDescriptorSet(3, &s_ubShadowFS, sizeof(s_ubShadowFS), 1000, {}, CGI::ShaderStageFlags::fs);
|
_shader[SHADER_LIGHT]->CreateDescriptorSet(3, &s_ubShadowFS, sizeof(s_ubShadowFS), 1000, {}, ShaderStageFlags::fs);
|
||||||
_shader[SHADER_LIGHT]->CreateDescriptorSet(4, &s_ubPerObject, sizeof(s_ubPerObject), 0);
|
_shader[SHADER_LIGHT]->CreateDescriptorSet(4, &s_ubPerObject, sizeof(s_ubPerObject), 0);
|
||||||
_shader[SHADER_LIGHT]->CreatePipelineLayout();
|
_shader[SHADER_LIGHT]->CreatePipelineLayout();
|
||||||
|
|
||||||
_shader[SHADER_COMPOSE].Init("[Shaders]:DS_Compose.hlsl");
|
_shader[SHADER_COMPOSE].Init("[Shaders]:DS_Compose.hlsl");
|
||||||
_shader[SHADER_COMPOSE]->CreateDescriptorSet(0, &s_ubComposeVS, sizeof(s_ubComposeVS), 2, {}, CGI::ShaderStageFlags::vs);
|
_shader[SHADER_COMPOSE]->CreateDescriptorSet(0, &s_ubComposeVS, sizeof(s_ubComposeVS), 2, {}, ShaderStageFlags::vs);
|
||||||
_shader[SHADER_COMPOSE]->CreateDescriptorSet(1, &s_ubComposeFS, sizeof(s_ubComposeFS), 2,
|
_shader[SHADER_COMPOSE]->CreateDescriptorSet(1, &s_ubComposeFS, sizeof(s_ubComposeFS), 2,
|
||||||
{
|
{
|
||||||
Sampler::nearestClampMipN,
|
Sampler::nearestClampMipN,
|
||||||
|
@ -111,9 +127,30 @@ void DeferredShading::Init()
|
||||||
Sampler::nearestClampMipN,
|
Sampler::nearestClampMipN,
|
||||||
Sampler::nearestClampMipN,
|
Sampler::nearestClampMipN,
|
||||||
Sampler::nearestClampMipN
|
Sampler::nearestClampMipN
|
||||||
}, CGI::ShaderStageFlags::fs);
|
}, ShaderStageFlags::fs);
|
||||||
_shader[SHADER_COMPOSE]->CreatePipelineLayout();
|
_shader[SHADER_COMPOSE]->CreatePipelineLayout();
|
||||||
|
|
||||||
|
_shader[SHADER_AO].Init("[Shaders]:DS_AO.hlsl");
|
||||||
|
_shader[SHADER_AO]->CreateDescriptorSet(0, &s_ubAOPerFrame, sizeof(s_ubAOPerFrame));
|
||||||
|
_shader[SHADER_AO]->CreateDescriptorSet(1, &s_ubAOTexturesFS, sizeof(s_ubAOTexturesFS), 1,
|
||||||
|
{
|
||||||
|
Sampler::nearestClampMipN,
|
||||||
|
Sampler::nearestClampMipN
|
||||||
|
}, ShaderStageFlags::fs);
|
||||||
|
_shader[SHADER_AO]->CreateDescriptorSet(2, &s_ubAOPerMeshVS, sizeof(s_ubAOPerMeshVS), 1000, {}, ShaderStageFlags::vs);
|
||||||
|
_shader[SHADER_AO]->CreateDescriptorSet(3, &s_ubAOPerObject, sizeof(s_ubAOPerObject), 0);
|
||||||
|
_shader[SHADER_AO]->CreatePipelineLayout();
|
||||||
|
|
||||||
|
_shader[SHADER_BAKE_SPRITES].Init("[Shaders]:DS_BakeSprites.hlsl");
|
||||||
|
_shader[SHADER_BAKE_SPRITES]->CreateDescriptorSet(0, &s_ubBakeSpritesVS, sizeof(s_ubBakeSpritesVS), 1000);
|
||||||
|
_shader[SHADER_BAKE_SPRITES]->CreateDescriptorSet(1, &s_ubBakeSpritesFS, sizeof(s_ubBakeSpritesFS), 1000,
|
||||||
|
{
|
||||||
|
Sampler::nearestClampMipN,
|
||||||
|
Sampler::nearestClampMipN,
|
||||||
|
Sampler::nearestClampMipN
|
||||||
|
}, ShaderStageFlags::fs);
|
||||||
|
_shader[SHADER_BAKE_SPRITES]->CreatePipelineLayout();
|
||||||
|
|
||||||
{
|
{
|
||||||
PipelineDesc pipeDesc(renderer.GetGeoQuad(), _shader[SHADER_COMPOSE], "#Compose", _rphCompose);
|
PipelineDesc pipeDesc(renderer.GetGeoQuad(), _shader[SHADER_COMPOSE], "#Compose", _rphCompose);
|
||||||
pipeDesc._colorAttachBlendEqs[0] = VERUS_COLOR_BLEND_OFF;
|
pipeDesc._colorAttachBlendEqs[0] = VERUS_COLOR_BLEND_OFF;
|
||||||
|
@ -207,7 +244,24 @@ void DeferredShading::InitBySsao(TexturePtr tex)
|
||||||
{
|
{
|
||||||
VERUS_QREF_RENDERER;
|
VERUS_QREF_RENDERER;
|
||||||
|
|
||||||
|
_texAO = tex;
|
||||||
|
|
||||||
|
_fbhAO = renderer->CreateFramebuffer(_rphAO,
|
||||||
|
{
|
||||||
|
tex,
|
||||||
|
renderer.GetTexDepthStencil(),
|
||||||
|
},
|
||||||
|
renderer.GetSwapChainWidth(),
|
||||||
|
renderer.GetSwapChainHeight());
|
||||||
|
|
||||||
_shader[SHADER_COMPOSE]->FreeDescriptorSet(_cshCompose);
|
_shader[SHADER_COMPOSE]->FreeDescriptorSet(_cshCompose);
|
||||||
|
_shader[SHADER_AO]->FreeDescriptorSet(_cshAO);
|
||||||
|
|
||||||
|
_cshAO = _shader[SHADER_AO]->BindDescriptorSetTextures(1,
|
||||||
|
{
|
||||||
|
_tex[TEX_GBUFFER_1],
|
||||||
|
renderer.GetTexDepthStencil(),
|
||||||
|
});
|
||||||
_cshCompose = _shader[SHADER_COMPOSE]->BindDescriptorSetTextures(1,
|
_cshCompose = _shader[SHADER_COMPOSE]->BindDescriptorSetTextures(1,
|
||||||
{
|
{
|
||||||
_tex[TEX_GBUFFER_0],
|
_tex[TEX_GBUFFER_0],
|
||||||
|
@ -236,7 +290,9 @@ void DeferredShading::OnSwapChainResized(bool init, bool done)
|
||||||
_shader[SHADER_COMPOSE]->FreeDescriptorSet(_cshToneMapping);
|
_shader[SHADER_COMPOSE]->FreeDescriptorSet(_cshToneMapping);
|
||||||
_shader[SHADER_COMPOSE]->FreeDescriptorSet(_cshCompose);
|
_shader[SHADER_COMPOSE]->FreeDescriptorSet(_cshCompose);
|
||||||
|
|
||||||
|
renderer->DeleteFramebuffer(_fbhExtraCompose);
|
||||||
renderer->DeleteFramebuffer(_fbhCompose);
|
renderer->DeleteFramebuffer(_fbhCompose);
|
||||||
|
renderer->DeleteFramebuffer(_fbhAO);
|
||||||
renderer->DeleteFramebuffer(_fbh);
|
renderer->DeleteFramebuffer(_fbh);
|
||||||
|
|
||||||
_tex[TEX_COMPOSED_B].Done();
|
_tex[TEX_COMPOSED_B].Done();
|
||||||
|
@ -324,9 +380,18 @@ bool DeferredShading::IsLoaded()
|
||||||
VERUS_QREF_HELPERS;
|
VERUS_QREF_HELPERS;
|
||||||
Scene::RDeferredLights dl = helpers.GetDeferredLights();
|
Scene::RDeferredLights dl = helpers.GetDeferredLights();
|
||||||
return
|
return
|
||||||
dl.Get(CGI::LightType::dir).IsLoaded() &&
|
dl.Get(LightType::dir).IsLoaded() &&
|
||||||
dl.Get(CGI::LightType::omni).IsLoaded() &&
|
dl.Get(LightType::omni).IsLoaded() &&
|
||||||
dl.Get(CGI::LightType::spot).IsLoaded();
|
dl.Get(LightType::spot).IsLoaded();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeferredShading::ResetInstanceCount()
|
||||||
|
{
|
||||||
|
VERUS_QREF_HELPERS;
|
||||||
|
Scene::RDeferredLights dl = helpers.GetDeferredLights();
|
||||||
|
dl.Get(LightType::dir).ResetInstanceCount();
|
||||||
|
dl.Get(LightType::omni).ResetInstanceCount();
|
||||||
|
dl.Get(LightType::spot).ResetInstanceCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeferredShading::Draw(int gbuffer)
|
void DeferredShading::Draw(int gbuffer)
|
||||||
|
@ -336,12 +401,12 @@ void DeferredShading::Draw(int gbuffer)
|
||||||
const float w = static_cast<float>(renderer.GetSwapChainWidth() / 2);
|
const float w = static_cast<float>(renderer.GetSwapChainWidth() / 2);
|
||||||
const float h = static_cast<float>(renderer.GetSwapChainHeight() / 2);
|
const float h = static_cast<float>(renderer.GetSwapChainHeight() / 2);
|
||||||
|
|
||||||
renderer.GetUbQuadVS()._matW = Math::QuadMatrix().UniformBufferFormat();
|
|
||||||
renderer.GetUbQuadVS()._matV = Math::ToUVMatrix().UniformBufferFormat();
|
|
||||||
|
|
||||||
auto cb = renderer.GetCommandBuffer();
|
auto cb = renderer.GetCommandBuffer();
|
||||||
auto shader = renderer.GetShaderQuad();
|
auto shader = renderer.GetShaderQuad();
|
||||||
|
|
||||||
|
renderer.GetUbQuadVS()._matW = Math::QuadMatrix().UniformBufferFormat();
|
||||||
|
renderer.GetUbQuadVS()._matV = Math::ToUVMatrix().UniformBufferFormat();
|
||||||
|
|
||||||
cb->BindPipeline(_pipe[PIPE_QUAD]);
|
cb->BindPipeline(_pipe[PIPE_QUAD]);
|
||||||
|
|
||||||
shader->BeginBindDescriptors();
|
shader->BeginBindDescriptors();
|
||||||
|
@ -350,15 +415,15 @@ void DeferredShading::Draw(int gbuffer)
|
||||||
{
|
{
|
||||||
cb->SetViewport({ Vector4(0, 0, w, h) });
|
cb->SetViewport({ Vector4(0, 0, w, h) });
|
||||||
cb->BindDescriptors(shader, 1, _cshQuad[0]);
|
cb->BindDescriptors(shader, 1, _cshQuad[0]);
|
||||||
renderer.DrawQuad(&(*cb));
|
renderer.DrawQuad(cb.Get());
|
||||||
|
|
||||||
cb->SetViewport({ Vector4(w, 0, w, h) });
|
cb->SetViewport({ Vector4(w, 0, w, h) });
|
||||||
cb->BindDescriptors(shader, 1, _cshQuad[1]);
|
cb->BindDescriptors(shader, 1, _cshQuad[1]);
|
||||||
renderer.DrawQuad(&(*cb));
|
renderer.DrawQuad(cb.Get());
|
||||||
|
|
||||||
cb->SetViewport({ Vector4(0, h, w, h) });
|
cb->SetViewport({ Vector4(0, h, w, h) });
|
||||||
cb->BindDescriptors(shader, 1, _cshQuad[2]);
|
cb->BindDescriptors(shader, 1, _cshQuad[2]);
|
||||||
renderer.DrawQuad(&(*cb));
|
renderer.DrawQuad(cb.Get());
|
||||||
|
|
||||||
cb->SetViewport({ Vector4(0, 0, static_cast<float>(renderer.GetSwapChainWidth()), static_cast<float>(renderer.GetSwapChainHeight())) });
|
cb->SetViewport({ Vector4(0, 0, static_cast<float>(renderer.GetSwapChainWidth()), static_cast<float>(renderer.GetSwapChainHeight())) });
|
||||||
}
|
}
|
||||||
|
@ -366,18 +431,18 @@ void DeferredShading::Draw(int gbuffer)
|
||||||
{
|
{
|
||||||
cb->SetViewport({ Vector4(0, 0, w, h) });
|
cb->SetViewport({ Vector4(0, 0, w, h) });
|
||||||
cb->BindDescriptors(shader, 1, _cshQuad[3]);
|
cb->BindDescriptors(shader, 1, _cshQuad[3]);
|
||||||
renderer.DrawQuad(&(*cb));
|
renderer.DrawQuad(cb.Get());
|
||||||
|
|
||||||
cb->SetViewport({ Vector4(w, 0, w, h) });
|
cb->SetViewport({ Vector4(w, 0, w, h) });
|
||||||
cb->BindDescriptors(shader, 1, _cshQuad[4]);
|
cb->BindDescriptors(shader, 1, _cshQuad[4]);
|
||||||
renderer.DrawQuad(&(*cb));
|
renderer.DrawQuad(cb.Get());
|
||||||
|
|
||||||
cb->SetViewport({ Vector4(0, 0, static_cast<float>(renderer.GetSwapChainWidth()), static_cast<float>(renderer.GetSwapChainHeight())) });
|
cb->SetViewport({ Vector4(0, 0, static_cast<float>(renderer.GetSwapChainWidth()), static_cast<float>(renderer.GetSwapChainHeight())) });
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cb->BindDescriptors(shader, 1, _cshQuad[gbuffer]);
|
cb->BindDescriptors(shader, 1, _cshQuad[gbuffer]);
|
||||||
renderer.DrawQuad(&(*cb));
|
renderer.DrawQuad(cb.Get());
|
||||||
}
|
}
|
||||||
shader->EndBindDescriptors();
|
shader->EndBindDescriptors();
|
||||||
}
|
}
|
||||||
|
@ -437,7 +502,7 @@ bool DeferredShading::BeginLightingPass()
|
||||||
Scene::RDeferredLights dl = helpers.GetDeferredLights();
|
Scene::RDeferredLights dl = helpers.GetDeferredLights();
|
||||||
|
|
||||||
{
|
{
|
||||||
PipelineDesc pipeDesc(dl.Get(CGI::LightType::dir).GetGeometry(), _shader[SHADER_LIGHT], "#InstancedDir", _rph, 1);
|
PipelineDesc pipeDesc(dl.Get(LightType::dir).GetGeometry(), _shader[SHADER_LIGHT], "#InstancedDir", _rph, 1);
|
||||||
pipeDesc._colorAttachBlendEqs[0] = VERUS_COLOR_BLEND_ADD;
|
pipeDesc._colorAttachBlendEqs[0] = VERUS_COLOR_BLEND_ADD;
|
||||||
pipeDesc._colorAttachBlendEqs[1] = VERUS_COLOR_BLEND_ADD;
|
pipeDesc._colorAttachBlendEqs[1] = VERUS_COLOR_BLEND_ADD;
|
||||||
pipeDesc._vertexInputBindingsFilter = (1 << 0) | (1 << 4);
|
pipeDesc._vertexInputBindingsFilter = (1 << 0) | (1 << 4);
|
||||||
|
@ -445,7 +510,7 @@ bool DeferredShading::BeginLightingPass()
|
||||||
_pipe[PIPE_INSTANCED_DIR].Init(pipeDesc);
|
_pipe[PIPE_INSTANCED_DIR].Init(pipeDesc);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
PipelineDesc pipeDesc(dl.Get(CGI::LightType::omni).GetGeometry(), _shader[SHADER_LIGHT], "#InstancedOmni", _rph, 1);
|
PipelineDesc pipeDesc(dl.Get(LightType::omni).GetGeometry(), _shader[SHADER_LIGHT], "#InstancedOmni", _rph, 1);
|
||||||
pipeDesc._colorAttachBlendEqs[0] = VERUS_COLOR_BLEND_ADD;
|
pipeDesc._colorAttachBlendEqs[0] = VERUS_COLOR_BLEND_ADD;
|
||||||
pipeDesc._colorAttachBlendEqs[1] = VERUS_COLOR_BLEND_ADD;
|
pipeDesc._colorAttachBlendEqs[1] = VERUS_COLOR_BLEND_ADD;
|
||||||
pipeDesc._rasterizationState._cullMode = CullMode::front;
|
pipeDesc._rasterizationState._cullMode = CullMode::front;
|
||||||
|
@ -455,7 +520,7 @@ bool DeferredShading::BeginLightingPass()
|
||||||
_pipe[PIPE_INSTANCED_OMNI].Init(pipeDesc);
|
_pipe[PIPE_INSTANCED_OMNI].Init(pipeDesc);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
PipelineDesc pipeDesc(dl.Get(CGI::LightType::spot).GetGeometry(), _shader[SHADER_LIGHT], "#InstancedSpot", _rph, 1);
|
PipelineDesc pipeDesc(dl.Get(LightType::spot).GetGeometry(), _shader[SHADER_LIGHT], "#InstancedSpot", _rph, 1);
|
||||||
pipeDesc._colorAttachBlendEqs[0] = VERUS_COLOR_BLEND_ADD;
|
pipeDesc._colorAttachBlendEqs[0] = VERUS_COLOR_BLEND_ADD;
|
||||||
pipeDesc._colorAttachBlendEqs[1] = VERUS_COLOR_BLEND_ADD;
|
pipeDesc._colorAttachBlendEqs[1] = VERUS_COLOR_BLEND_ADD;
|
||||||
pipeDesc._rasterizationState._cullMode = CullMode::front;
|
pipeDesc._rasterizationState._cullMode = CullMode::front;
|
||||||
|
@ -464,6 +529,15 @@ bool DeferredShading::BeginLightingPass()
|
||||||
pipeDesc._depthWriteEnable = false;
|
pipeDesc._depthWriteEnable = false;
|
||||||
_pipe[PIPE_INSTANCED_SPOT].Init(pipeDesc);
|
_pipe[PIPE_INSTANCED_SPOT].Init(pipeDesc);
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
PipelineDesc pipeDesc(dl.Get(LightType::omni).GetGeometry(), _shader[SHADER_AO], "#InstancedOmni", _rphAO);
|
||||||
|
pipeDesc._colorAttachBlendEqs[0] = VERUS_COLOR_BLEND_MUL;
|
||||||
|
pipeDesc._rasterizationState._cullMode = CullMode::front;
|
||||||
|
pipeDesc._vertexInputBindingsFilter = (1 << 0) | (1 << 4);
|
||||||
|
pipeDesc._depthCompareOp = CompareOp::greater;
|
||||||
|
pipeDesc._depthWriteEnable = false;
|
||||||
|
_pipe[PIPE_INSTANCED_AO].Init(pipeDesc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -480,6 +554,29 @@ void DeferredShading::EndLightingPass()
|
||||||
renderer.GetCommandBuffer()->EndRenderPass();
|
renderer.GetCommandBuffer()->EndRenderPass();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DeferredShading::BeginAmbientOcclusion()
|
||||||
|
{
|
||||||
|
VERUS_QREF_RENDERER;
|
||||||
|
|
||||||
|
auto cb = renderer.GetCommandBuffer();
|
||||||
|
|
||||||
|
// Add more dark regions to SSAO buffer:
|
||||||
|
cb->BeginRenderPass(_rphAO, _fbhAO,
|
||||||
|
{
|
||||||
|
_texAO->GetClearValue(),
|
||||||
|
renderer.GetTexDepthStencil()->GetClearValue()
|
||||||
|
});
|
||||||
|
_shader[SHADER_AO]->BeginBindDescriptors();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeferredShading::EndAmbientOcclusion()
|
||||||
|
{
|
||||||
|
VERUS_QREF_RENDERER;
|
||||||
|
|
||||||
|
_shader[SHADER_AO]->EndBindDescriptors();
|
||||||
|
renderer.GetCommandBuffer()->EndRenderPass();
|
||||||
|
}
|
||||||
|
|
||||||
void DeferredShading::BeginCompose()
|
void DeferredShading::BeginCompose()
|
||||||
{
|
{
|
||||||
VERUS_QREF_RENDERER;
|
VERUS_QREF_RENDERER;
|
||||||
|
@ -489,6 +586,8 @@ void DeferredShading::BeginCompose()
|
||||||
|
|
||||||
const Matrix4 matInvVP = VMath::inverse(sm.GetCamera()->GetMatrixVP());
|
const Matrix4 matInvVP = VMath::inverse(sm.GetCamera()->GetMatrixVP());
|
||||||
|
|
||||||
|
auto cb = renderer.GetCommandBuffer();
|
||||||
|
|
||||||
s_ubComposeVS._matW = Math::QuadMatrix().UniformBufferFormat();
|
s_ubComposeVS._matW = Math::QuadMatrix().UniformBufferFormat();
|
||||||
s_ubComposeVS._matV = Math::ToUVMatrix().UniformBufferFormat();
|
s_ubComposeVS._matV = Math::ToUVMatrix().UniformBufferFormat();
|
||||||
s_ubComposeFS._matInvV = sm.GetCamera()->GetMatrixVi().UniformBufferFormat();
|
s_ubComposeFS._matInvV = sm.GetCamera()->GetMatrixVi().UniformBufferFormat();
|
||||||
|
@ -499,8 +598,7 @@ void DeferredShading::BeginCompose()
|
||||||
s_ubComposeFS._waterDiffColorShallow = float4(water.GetDiffuseColorShallow().GLM(), water.GetFogDensity());
|
s_ubComposeFS._waterDiffColorShallow = float4(water.GetDiffuseColorShallow().GLM(), water.GetFogDensity());
|
||||||
s_ubComposeFS._waterDiffColorDeep = float4(water.GetDiffuseColorDeep().GLM(), water.IsUnderwater() ? 1.f : 0.f);
|
s_ubComposeFS._waterDiffColorDeep = float4(water.GetDiffuseColorDeep().GLM(), water.IsUnderwater() ? 1.f : 0.f);
|
||||||
|
|
||||||
auto cb = renderer.GetCommandBuffer();
|
// Compose buffers, that is perform "final color = albedo * diffuse + specular" computation. Result is still HDR:
|
||||||
|
|
||||||
cb->BeginRenderPass(_rphCompose, _fbhCompose,
|
cb->BeginRenderPass(_rphCompose, _fbhCompose,
|
||||||
{
|
{
|
||||||
_tex[TEX_COMPOSED_A]->GetClearValue(),
|
_tex[TEX_COMPOSED_A]->GetClearValue(),
|
||||||
|
@ -509,16 +607,15 @@ void DeferredShading::BeginCompose()
|
||||||
});
|
});
|
||||||
|
|
||||||
cb->BindPipeline(_pipe[PIPE_COMPOSE]);
|
cb->BindPipeline(_pipe[PIPE_COMPOSE]);
|
||||||
|
|
||||||
_shader[SHADER_COMPOSE]->BeginBindDescriptors();
|
_shader[SHADER_COMPOSE]->BeginBindDescriptors();
|
||||||
cb->BindDescriptors(_shader[SHADER_COMPOSE], 0);
|
cb->BindDescriptors(_shader[SHADER_COMPOSE], 0);
|
||||||
cb->BindDescriptors(_shader[SHADER_COMPOSE], 1, _cshCompose);
|
cb->BindDescriptors(_shader[SHADER_COMPOSE], 1, _cshCompose);
|
||||||
_shader[SHADER_COMPOSE]->EndBindDescriptors();
|
_shader[SHADER_COMPOSE]->EndBindDescriptors();
|
||||||
|
renderer.DrawQuad(cb.Get());
|
||||||
renderer.DrawQuad(&(*cb));
|
|
||||||
|
|
||||||
cb->EndRenderPass();
|
cb->EndRenderPass();
|
||||||
|
|
||||||
|
// Begin drawing extra stuff, which is not using deferred shading, for example water (updates depth buffer) and sky:
|
||||||
cb->BeginRenderPass(_rphExtraCompose, _fbhExtraCompose,
|
cb->BeginRenderPass(_rphExtraCompose, _fbhExtraCompose,
|
||||||
{
|
{
|
||||||
_tex[TEX_COMPOSED_A]->GetClearValue(),
|
_tex[TEX_COMPOSED_A]->GetClearValue(),
|
||||||
|
@ -539,6 +636,8 @@ void DeferredShading::ToneMapping(RcVector4 bgColor)
|
||||||
VERUS_QREF_SM;
|
VERUS_QREF_SM;
|
||||||
VERUS_QREF_ATMO;
|
VERUS_QREF_ATMO;
|
||||||
|
|
||||||
|
auto cb = renderer.GetCommandBuffer();
|
||||||
|
|
||||||
s_ubComposeVS._matW = Math::QuadMatrix().UniformBufferFormat();
|
s_ubComposeVS._matW = Math::QuadMatrix().UniformBufferFormat();
|
||||||
s_ubComposeVS._matV = Math::ToUVMatrix().UniformBufferFormat();
|
s_ubComposeVS._matV = Math::ToUVMatrix().UniformBufferFormat();
|
||||||
s_ubComposeFS._matInvV = sm.GetCamera()->GetMatrixVi().UniformBufferFormat();
|
s_ubComposeFS._matInvV = sm.GetCamera()->GetMatrixVi().UniformBufferFormat();
|
||||||
|
@ -547,20 +646,13 @@ void DeferredShading::ToneMapping(RcVector4 bgColor)
|
||||||
s_ubComposeFS._fogColor = Vector4(0.5f, 0.5f, 0.5f, 0.002f).GLM();
|
s_ubComposeFS._fogColor = Vector4(0.5f, 0.5f, 0.5f, 0.002f).GLM();
|
||||||
s_ubComposeFS._zNearFarEx = sm.GetCamera()->GetZNearFarEx().GLM();
|
s_ubComposeFS._zNearFarEx = sm.GetCamera()->GetZNearFarEx().GLM();
|
||||||
|
|
||||||
auto cb = renderer.GetCommandBuffer();
|
// Convert HDR image to SDR. First multiply by exposure, then apply tone mapping curve:
|
||||||
|
|
||||||
cb->BindPipeline(_pipe[PIPE_TONE_MAPPING]);
|
cb->BindPipeline(_pipe[PIPE_TONE_MAPPING]);
|
||||||
|
|
||||||
_shader[SHADER_COMPOSE]->BeginBindDescriptors();
|
_shader[SHADER_COMPOSE]->BeginBindDescriptors();
|
||||||
cb->BindDescriptors(_shader[SHADER_COMPOSE], 0);
|
cb->BindDescriptors(_shader[SHADER_COMPOSE], 0);
|
||||||
cb->BindDescriptors(_shader[SHADER_COMPOSE], 1, _cshToneMapping);
|
cb->BindDescriptors(_shader[SHADER_COMPOSE], 1, _cshToneMapping);
|
||||||
_shader[SHADER_COMPOSE]->EndBindDescriptors();
|
_shader[SHADER_COMPOSE]->EndBindDescriptors();
|
||||||
|
renderer.DrawQuad(cb.Get());
|
||||||
renderer.DrawQuad(&(*cb));
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeferredShading::AntiAliasing()
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DeferredShading::IsLightUrl(CSZ url)
|
bool DeferredShading::IsLightUrl(CSZ url)
|
||||||
|
@ -571,26 +663,31 @@ bool DeferredShading::IsLightUrl(CSZ url)
|
||||||
!strcmp(url, "SPOT");
|
!strcmp(url, "SPOT");
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeferredShading::OnNewLightType(LightType type, bool wireframe)
|
void DeferredShading::OnNewLightType(CommandBufferPtr cb, LightType type, bool wireframe)
|
||||||
{
|
{
|
||||||
VERUS_QREF_RENDERER;
|
|
||||||
VERUS_QREF_ATMO;
|
VERUS_QREF_ATMO;
|
||||||
|
VERUS_QREF_SM;
|
||||||
|
|
||||||
auto cb = renderer.GetCommandBuffer();
|
s_ubPerFrame._matQuad = Math::QuadMatrix().UniformBufferFormat();
|
||||||
|
s_ubPerFrame._matToUV = Math::ToUVMatrix().UniformBufferFormat();
|
||||||
|
s_ubPerFrame._matV = sm.GetCamera()->GetMatrixV().UniformBufferFormat();
|
||||||
|
s_ubPerFrame._matVP = sm.GetCamera()->GetMatrixVP().UniformBufferFormat();
|
||||||
|
s_ubPerFrame._matInvP = Matrix4(VMath::inverse(sm.GetCamera()->GetMatrixP())).UniformBufferFormat();
|
||||||
|
s_ubPerFrame._toUV = float4(0, 0, 0, 0);
|
||||||
|
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case CGI::LightType::dir:
|
case LightType::dir:
|
||||||
{
|
{
|
||||||
cb->BindPipeline(_pipe[PIPE_INSTANCED_DIR]);
|
cb->BindPipeline(_pipe[PIPE_INSTANCED_DIR]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CGI::LightType::omni:
|
case LightType::omni:
|
||||||
{
|
{
|
||||||
cb->BindPipeline(_pipe[PIPE_INSTANCED_OMNI]);
|
cb->BindPipeline(_pipe[PIPE_INSTANCED_OMNI]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CGI::LightType::spot:
|
case LightType::spot:
|
||||||
{
|
{
|
||||||
cb->BindPipeline(_pipe[PIPE_INSTANCED_SPOT]);
|
cb->BindPipeline(_pipe[PIPE_INSTANCED_SPOT]);
|
||||||
}
|
}
|
||||||
|
@ -610,24 +707,36 @@ void DeferredShading::OnNewLightType(LightType type, bool wireframe)
|
||||||
cb->BindDescriptors(_shader[SHADER_LIGHT], 3);
|
cb->BindDescriptors(_shader[SHADER_LIGHT], 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeferredShading::UpdateUniformBufferPerFrame()
|
void DeferredShading::BindDescriptorsPerMeshVS(CommandBufferPtr cb)
|
||||||
|
{
|
||||||
|
cb->BindDescriptors(_shader[SHADER_LIGHT], 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeferredShading::OnNewAOType(CommandBufferPtr cb, LightType type)
|
||||||
{
|
{
|
||||||
VERUS_QREF_SM;
|
VERUS_QREF_SM;
|
||||||
|
|
||||||
// Standard quad:
|
s_ubAOPerFrame._matToUV = Math::ToUVMatrix().UniformBufferFormat();
|
||||||
s_ubPerFrame._matQuad = Math::QuadMatrix().UniformBufferFormat();
|
s_ubAOPerFrame._matV = sm.GetCamera()->GetMatrixV().UniformBufferFormat();
|
||||||
s_ubPerFrame._matToUV = Math::ToUVMatrix().UniformBufferFormat();
|
s_ubAOPerFrame._matVP = sm.GetCamera()->GetMatrixVP().UniformBufferFormat();
|
||||||
|
s_ubAOPerFrame._matInvP = Matrix4(VMath::inverse(sm.GetCamera()->GetMatrixP())).UniformBufferFormat();
|
||||||
|
|
||||||
s_ubPerFrame._matV = sm.GetCamera()->GetMatrixV().UniformBufferFormat();
|
switch (type)
|
||||||
s_ubPerFrame._matVP = sm.GetCamera()->GetMatrixVP().UniformBufferFormat();
|
{
|
||||||
s_ubPerFrame._matInvP = Matrix4(VMath::inverse(sm.GetCamera()->GetMatrixP())).UniformBufferFormat();
|
case LightType::omni:
|
||||||
s_ubPerFrame._toUV = float4(0, 0, 0, 0);
|
{
|
||||||
|
cb->BindPipeline(_pipe[PIPE_INSTANCED_AO]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
cb->BindDescriptors(_shader[SHADER_AO], 0);
|
||||||
|
cb->BindDescriptors(_shader[SHADER_AO], 1, _cshAO);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeferredShading::BindDescriptorsPerMeshVS()
|
void DeferredShading::BindDescriptorsAOPerMeshVS(CommandBufferPtr cb)
|
||||||
{
|
{
|
||||||
VERUS_QREF_RENDERER;
|
cb->BindDescriptors(_shader[SHADER_AO], 2);
|
||||||
renderer.GetCommandBuffer()->BindDescriptors(_shader[SHADER_LIGHT], 2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeferredShading::Load()
|
void DeferredShading::Load()
|
||||||
|
@ -636,16 +745,16 @@ void DeferredShading::Load()
|
||||||
Scene::RDeferredLights dl = helpers.GetDeferredLights();
|
Scene::RDeferredLights dl = helpers.GetDeferredLights();
|
||||||
|
|
||||||
Scene::Mesh::Desc meshDesc;
|
Scene::Mesh::Desc meshDesc;
|
||||||
meshDesc._instanceCapacity = 1000;
|
meshDesc._instanceCapacity = 10000;
|
||||||
|
|
||||||
meshDesc._url = "[Models]:DS/Dir.x3d";
|
meshDesc._url = "[Models]:DS/Dir.x3d";
|
||||||
dl.Get(CGI::LightType::dir).Init(meshDesc);
|
dl.Get(LightType::dir).Init(meshDesc);
|
||||||
|
|
||||||
meshDesc._url = "[Models]:DS/Omni.x3d";
|
meshDesc._url = "[Models]:DS/Omni.x3d";
|
||||||
dl.Get(CGI::LightType::omni).Init(meshDesc);
|
dl.Get(LightType::omni).Init(meshDesc);
|
||||||
|
|
||||||
meshDesc._url = "[Models]:DS/Spot.x3d";
|
meshDesc._url = "[Models]:DS/Spot.x3d";
|
||||||
dl.Get(CGI::LightType::spot).Init(meshDesc);
|
dl.Get(LightType::spot).Init(meshDesc);
|
||||||
}
|
}
|
||||||
|
|
||||||
TexturePtr DeferredShading::GetGBuffer(int index)
|
TexturePtr DeferredShading::GetGBuffer(int index)
|
||||||
|
@ -662,3 +771,100 @@ TexturePtr DeferredShading::GetComposedTextureB()
|
||||||
{
|
{
|
||||||
return _tex[TEX_COMPOSED_B];
|
return _tex[TEX_COMPOSED_B];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector4 DeferredShading::GetClearValueForGBuffer0()
|
||||||
|
{
|
||||||
|
return Vector4(0.5f, 0.5f, 0.5f, 0.25f);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector4 DeferredShading::GetClearValueForGBuffer1()
|
||||||
|
{
|
||||||
|
return Vector4(0.5f, 0.5f, 0.25f);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector4 DeferredShading::GetClearValueForGBuffer2()
|
||||||
|
{
|
||||||
|
return Vector4(0.125f, 0.5f, 0.5f, 0.125f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeferredShading::BakeSprites(TexturePtr texGBufferIn[3], TexturePtr texGBufferOut[3], PBaseCommandBuffer pCB)
|
||||||
|
{
|
||||||
|
VERUS_QREF_RENDERER;
|
||||||
|
|
||||||
|
if (!pCB)
|
||||||
|
pCB = renderer.GetCommandBuffer().Get();
|
||||||
|
|
||||||
|
RcVector4 size = texGBufferOut[0]->GetSize();
|
||||||
|
const int w = static_cast<int>(size.getX());
|
||||||
|
const int h = static_cast<int>(size.getY());
|
||||||
|
|
||||||
|
_rphBakeSprites = renderer->CreateRenderPass(
|
||||||
|
{
|
||||||
|
RP::Attachment("GBuffer0", Format::srgbR8G8B8A8).LoadOpClear().Layout(ImageLayout::fsReadOnly),
|
||||||
|
RP::Attachment("GBuffer1", Format::unormR8G8B8A8).LoadOpClear().Layout(ImageLayout::fsReadOnly),
|
||||||
|
RP::Attachment("GBuffer2", Format::unormR8G8B8A8).LoadOpClear().Layout(ImageLayout::fsReadOnly),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
RP::Subpass("Sp0").Color(
|
||||||
|
{
|
||||||
|
RP::Ref("GBuffer0", ImageLayout::colorAttachment),
|
||||||
|
RP::Ref("GBuffer1", ImageLayout::colorAttachment),
|
||||||
|
RP::Ref("GBuffer2", ImageLayout::colorAttachment)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
{});
|
||||||
|
|
||||||
|
_fbhBakeSprites = renderer->CreateFramebuffer(_rphBakeSprites,
|
||||||
|
{
|
||||||
|
texGBufferOut[0],
|
||||||
|
texGBufferOut[1],
|
||||||
|
texGBufferOut[2]
|
||||||
|
},
|
||||||
|
w, h);
|
||||||
|
|
||||||
|
_cshBakeSprites = _shader[SHADER_BAKE_SPRITES]->BindDescriptorSetTextures(1,
|
||||||
|
{
|
||||||
|
texGBufferIn[0],
|
||||||
|
texGBufferIn[1],
|
||||||
|
texGBufferIn[2]
|
||||||
|
});
|
||||||
|
|
||||||
|
{
|
||||||
|
PipelineDesc pipeDesc(renderer.GetGeoQuad(), _shader[SHADER_BAKE_SPRITES], "#", _rphBakeSprites);
|
||||||
|
pipeDesc._colorAttachBlendEqs[0] = VERUS_COLOR_BLEND_OFF;
|
||||||
|
pipeDesc._colorAttachBlendEqs[1] = VERUS_COLOR_BLEND_OFF;
|
||||||
|
pipeDesc._colorAttachBlendEqs[2] = VERUS_COLOR_BLEND_OFF;
|
||||||
|
pipeDesc._topology = PrimitiveTopology::triangleStrip;
|
||||||
|
pipeDesc.DisableDepthTest();
|
||||||
|
_pipe[PIPE_BAKE_SPRITES].Init(pipeDesc);
|
||||||
|
}
|
||||||
|
|
||||||
|
s_ubBakeSpritesVS._matW = Math::QuadMatrix().UniformBufferFormat();
|
||||||
|
s_ubBakeSpritesVS._matV = Math::ToUVMatrix().UniformBufferFormat();
|
||||||
|
|
||||||
|
pCB->BeginRenderPass(_rphBakeSprites, _fbhBakeSprites,
|
||||||
|
{
|
||||||
|
texGBufferOut[0]->GetClearValue(),
|
||||||
|
texGBufferOut[1]->GetClearValue(),
|
||||||
|
texGBufferOut[2]->GetClearValue()
|
||||||
|
});
|
||||||
|
|
||||||
|
pCB->BindPipeline(_pipe[PIPE_BAKE_SPRITES]);
|
||||||
|
_shader[SHADER_BAKE_SPRITES]->BeginBindDescriptors();
|
||||||
|
pCB->BindDescriptors(_shader[SHADER_BAKE_SPRITES], 0);
|
||||||
|
pCB->BindDescriptors(_shader[SHADER_BAKE_SPRITES], 1, _cshBakeSprites);
|
||||||
|
_shader[SHADER_BAKE_SPRITES]->EndBindDescriptors();
|
||||||
|
renderer.DrawQuad(pCB);
|
||||||
|
|
||||||
|
pCB->EndRenderPass();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeferredShading::BakeSpritesCleanup()
|
||||||
|
{
|
||||||
|
VERUS_QREF_RENDERER;
|
||||||
|
|
||||||
|
_pipe[PIPE_BAKE_SPRITES].Done();
|
||||||
|
_shader[SHADER_BAKE_SPRITES]->FreeDescriptorSet(_cshBakeSprites);
|
||||||
|
renderer->DeleteFramebuffer(_fbhBakeSprites);
|
||||||
|
renderer->DeleteRenderPass(_rphBakeSprites);
|
||||||
|
}
|
||||||
|
|
|
@ -16,11 +16,15 @@ namespace verus
|
||||||
{
|
{
|
||||||
#include "../Shaders/DS.inc.hlsl"
|
#include "../Shaders/DS.inc.hlsl"
|
||||||
#include "../Shaders/DS_Compose.inc.hlsl"
|
#include "../Shaders/DS_Compose.inc.hlsl"
|
||||||
|
#include "../Shaders/DS_AO.inc.hlsl"
|
||||||
|
#include "../Shaders/DS_BakeSprites.inc.hlsl"
|
||||||
|
|
||||||
enum SHADER
|
enum SHADER
|
||||||
{
|
{
|
||||||
SHADER_LIGHT,
|
SHADER_LIGHT,
|
||||||
SHADER_COMPOSE,
|
SHADER_COMPOSE,
|
||||||
|
SHADER_AO,
|
||||||
|
SHADER_BAKE_SPRITES,
|
||||||
SHADER_COUNT
|
SHADER_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -32,6 +36,8 @@ namespace verus
|
||||||
PIPE_COMPOSE,
|
PIPE_COMPOSE,
|
||||||
PIPE_TONE_MAPPING,
|
PIPE_TONE_MAPPING,
|
||||||
PIPE_QUAD,
|
PIPE_QUAD,
|
||||||
|
PIPE_INSTANCED_AO,
|
||||||
|
PIPE_BAKE_SPRITES,
|
||||||
PIPE_COUNT
|
PIPE_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -54,22 +60,35 @@ namespace verus
|
||||||
static UB_PerObject s_ubPerObject;
|
static UB_PerObject s_ubPerObject;
|
||||||
static UB_ComposeVS s_ubComposeVS;
|
static UB_ComposeVS s_ubComposeVS;
|
||||||
static UB_ComposeFS s_ubComposeFS;
|
static UB_ComposeFS s_ubComposeFS;
|
||||||
|
static UB_AOPerFrame s_ubAOPerFrame;
|
||||||
|
static UB_AOTexturesFS s_ubAOTexturesFS;
|
||||||
|
static UB_AOPerMeshVS s_ubAOPerMeshVS;
|
||||||
|
static UB_AOPerObject s_ubAOPerObject;
|
||||||
|
static UB_BakeSpritesVS s_ubBakeSpritesVS;
|
||||||
|
static UB_BakeSpritesFS s_ubBakeSpritesFS;
|
||||||
|
|
||||||
ShaderPwns<SHADER_COUNT> _shader;
|
ShaderPwns<SHADER_COUNT> _shader;
|
||||||
PipelinePwns<PIPE_COUNT> _pipe;
|
PipelinePwns<PIPE_COUNT> _pipe;
|
||||||
TexturePwns<TEX_COUNT> _tex;
|
TexturePwns<TEX_COUNT> _tex;
|
||||||
TexturePtr _texShadowAtmo;
|
TexturePtr _texShadowAtmo;
|
||||||
|
TexturePtr _texAO;
|
||||||
UINT64 _frame = 0;
|
UINT64 _frame = 0;
|
||||||
RPHandle _rph;
|
RPHandle _rph;
|
||||||
|
RPHandle _rphAO;
|
||||||
RPHandle _rphCompose;
|
RPHandle _rphCompose;
|
||||||
RPHandle _rphExtraCompose;
|
RPHandle _rphExtraCompose;
|
||||||
|
RPHandle _rphBakeSprites;
|
||||||
FBHandle _fbh;
|
FBHandle _fbh;
|
||||||
|
FBHandle _fbhAO;
|
||||||
FBHandle _fbhCompose;
|
FBHandle _fbhCompose;
|
||||||
FBHandle _fbhExtraCompose;
|
FBHandle _fbhExtraCompose;
|
||||||
|
FBHandle _fbhBakeSprites;
|
||||||
CSHandle _cshLight;
|
CSHandle _cshLight;
|
||||||
|
CSHandle _cshAO;
|
||||||
CSHandle _cshCompose;
|
CSHandle _cshCompose;
|
||||||
CSHandle _cshToneMapping;
|
CSHandle _cshToneMapping;
|
||||||
CSHandle _cshQuad[5];
|
CSHandle _cshQuad[5];
|
||||||
|
CSHandle _cshBakeSprites;
|
||||||
bool _activeGeometryPass = false;
|
bool _activeGeometryPass = false;
|
||||||
bool _activeLightingPass = false;
|
bool _activeLightingPass = false;
|
||||||
bool _async_initPipe = false;
|
bool _async_initPipe = false;
|
||||||
|
@ -89,6 +108,7 @@ namespace verus
|
||||||
|
|
||||||
static bool IsLoaded();
|
static bool IsLoaded();
|
||||||
|
|
||||||
|
void ResetInstanceCount();
|
||||||
void Draw(int gbuffer);
|
void Draw(int gbuffer);
|
||||||
|
|
||||||
bool IsActiveGeometryPass() const { return _activeGeometryPass; }
|
bool IsActiveGeometryPass() const { return _activeGeometryPass; }
|
||||||
|
@ -101,16 +121,20 @@ namespace verus
|
||||||
void EndGeometryPass(bool resetRT = false);
|
void EndGeometryPass(bool resetRT = false);
|
||||||
bool BeginLightingPass();
|
bool BeginLightingPass();
|
||||||
void EndLightingPass();
|
void EndLightingPass();
|
||||||
|
void BeginAmbientOcclusion();
|
||||||
|
void EndAmbientOcclusion();
|
||||||
void BeginCompose();
|
void BeginCompose();
|
||||||
void EndCompose();
|
void EndCompose();
|
||||||
void ToneMapping(RcVector4 bgColor = Vector4(0));
|
void ToneMapping(RcVector4 bgColor = Vector4(0));
|
||||||
void AntiAliasing();
|
|
||||||
|
|
||||||
static bool IsLightUrl(CSZ url);
|
static bool IsLightUrl(CSZ url);
|
||||||
|
void OnNewLightType(CommandBufferPtr cb, LightType type, bool wireframe = false);
|
||||||
|
void BindDescriptorsPerMeshVS(CommandBufferPtr cb);
|
||||||
static UB_PerMeshVS& GetUbPerMeshVS() { return s_ubPerMeshVS; }
|
static UB_PerMeshVS& GetUbPerMeshVS() { return s_ubPerMeshVS; }
|
||||||
void OnNewLightType(LightType type, bool wireframe = false);
|
|
||||||
void UpdateUniformBufferPerFrame();
|
void OnNewAOType(CommandBufferPtr cb, LightType type);
|
||||||
void BindDescriptorsPerMeshVS();
|
void BindDescriptorsAOPerMeshVS(CommandBufferPtr cb);
|
||||||
|
static UB_AOPerMeshVS& GetUbAOPerMeshVS() { return s_ubAOPerMeshVS; }
|
||||||
|
|
||||||
void Load();
|
void Load();
|
||||||
|
|
||||||
|
@ -118,6 +142,13 @@ namespace verus
|
||||||
|
|
||||||
TexturePtr GetComposedTextureA();
|
TexturePtr GetComposedTextureA();
|
||||||
TexturePtr GetComposedTextureB();
|
TexturePtr GetComposedTextureB();
|
||||||
|
|
||||||
|
static Vector4 GetClearValueForGBuffer0();
|
||||||
|
static Vector4 GetClearValueForGBuffer1();
|
||||||
|
static Vector4 GetClearValueForGBuffer2();
|
||||||
|
|
||||||
|
void BakeSprites(TexturePtr texGBufferIn[3], TexturePtr texGBufferOut[3], PBaseCommandBuffer pCB = nullptr);
|
||||||
|
void BakeSpritesCleanup();
|
||||||
};
|
};
|
||||||
VERUS_TYPEDEFS(DeferredShading);
|
VERUS_TYPEDEFS(DeferredShading);
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,7 +108,7 @@ void Renderer::Init(PRendererDelegate pDelegate)
|
||||||
_geoQuad.Init(geoDesc);
|
_geoQuad.Init(geoDesc);
|
||||||
|
|
||||||
_shader[SHADER_GENERATE_MIPS].Init("[Shaders]:GenerateMips.hlsl");
|
_shader[SHADER_GENERATE_MIPS].Init("[Shaders]:GenerateMips.hlsl");
|
||||||
_shader[SHADER_GENERATE_MIPS]->CreateDescriptorSet(0, &_ubGenerateMips, sizeof(_ubGenerateMips), 100,
|
_shader[SHADER_GENERATE_MIPS]->CreateDescriptorSet(0, &_ubGenerateMips, sizeof(_ubGenerateMips), settings.GetLimits()._generateMips_ubCapacity,
|
||||||
{
|
{
|
||||||
Sampler::linearClampMipN,
|
Sampler::linearClampMipN,
|
||||||
Sampler::storage,
|
Sampler::storage,
|
||||||
|
@ -120,8 +120,8 @@ void Renderer::Init(PRendererDelegate pDelegate)
|
||||||
_shader[SHADER_GENERATE_MIPS]->CreatePipelineLayout();
|
_shader[SHADER_GENERATE_MIPS]->CreatePipelineLayout();
|
||||||
|
|
||||||
_shader[SHADER_QUAD].Init("[Shaders]:Quad.hlsl");
|
_shader[SHADER_QUAD].Init("[Shaders]:Quad.hlsl");
|
||||||
_shader[SHADER_QUAD]->CreateDescriptorSet(0, &_ubQuadVS, sizeof(_ubQuadVS), 100, {}, ShaderStageFlags::vs);
|
_shader[SHADER_QUAD]->CreateDescriptorSet(0, &_ubQuadVS, sizeof(_ubQuadVS), settings.GetLimits()._quad_ubVSCapacity, {}, ShaderStageFlags::vs);
|
||||||
_shader[SHADER_QUAD]->CreateDescriptorSet(1, &_ubQuadFS, sizeof(_ubQuadFS), 100, { Sampler::linearClampMipN }, ShaderStageFlags::fs);
|
_shader[SHADER_QUAD]->CreateDescriptorSet(1, &_ubQuadFS, sizeof(_ubQuadFS), settings.GetLimits()._quad_ubFSCapacity, { Sampler::linearClampMipN }, ShaderStageFlags::fs);
|
||||||
_shader[SHADER_QUAD]->CreatePipelineLayout();
|
_shader[SHADER_QUAD]->CreatePipelineLayout();
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -175,6 +175,7 @@ void Renderer::Done()
|
||||||
_geoQuad.Done();
|
_geoQuad.Done();
|
||||||
_commandBuffer.Done();
|
_commandBuffer.Done();
|
||||||
|
|
||||||
|
Scene::Forest::DoneStatic();
|
||||||
Scene::Grass::DoneStatic();
|
Scene::Grass::DoneStatic();
|
||||||
Scene::Terrain::DoneStatic();
|
Scene::Terrain::DoneStatic();
|
||||||
Scene::Mesh::DoneStatic();
|
Scene::Mesh::DoneStatic();
|
||||||
|
@ -205,10 +206,10 @@ void Renderer::Update()
|
||||||
const float alpha = Math::Max(0.001f, floatColor[3]);
|
const float alpha = Math::Max(0.001f, floatColor[3]);
|
||||||
const float actual = gray.r;
|
const float actual = gray.r;
|
||||||
const float expScale = Math::Clamp(_exposure[1] * (1 / 15.f), 0.f, 1.f);
|
const float expScale = Math::Clamp(_exposure[1] * (1 / 15.f), 0.f, 1.f);
|
||||||
const float target = -0.4f + 0.75f * expScale * expScale; // Dark scene exposure compensation.
|
const float target = -0.3f + 0.6f * expScale * expScale; // Dark scene exposure compensation.
|
||||||
const float important = (actual - 0.5f * (1 - alpha)) / alpha;
|
const float important = (actual - 0.5f * (1 - alpha)) / alpha;
|
||||||
const float delta = abs(target - important);
|
const float delta = abs(target - important);
|
||||||
const float speed = delta * sqrt(delta) * 43;
|
const float speed = delta * sqrt(delta) * 30;
|
||||||
|
|
||||||
if (important < target * 0.95f)
|
if (important < target * 0.95f)
|
||||||
_exposure[1] -= speed * dt;
|
_exposure[1] -= speed * dt;
|
||||||
|
@ -312,7 +313,7 @@ void Renderer::OnSwapChainResized(bool init, bool done)
|
||||||
void Renderer::DrawQuad(PBaseCommandBuffer pCB)
|
void Renderer::DrawQuad(PBaseCommandBuffer pCB)
|
||||||
{
|
{
|
||||||
if (!pCB)
|
if (!pCB)
|
||||||
pCB = &(*_commandBuffer);
|
pCB = _commandBuffer.Get();
|
||||||
pCB->BindVertexBuffers(_geoQuad);
|
pCB->BindVertexBuffers(_geoQuad);
|
||||||
pCB->Draw(4, 1);
|
pCB->Draw(4, 1);
|
||||||
}
|
}
|
||||||
|
@ -323,7 +324,7 @@ void Renderer::DrawOffscreenColor(PBaseCommandBuffer pCB, bool endRenderPass)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!pCB)
|
if (!pCB)
|
||||||
pCB = &(*_commandBuffer);
|
pCB = _commandBuffer.Get();
|
||||||
|
|
||||||
_tex[TEX_OFFSCREEN_COLOR]->GenerateMips();
|
_tex[TEX_OFFSCREEN_COLOR]->GenerateMips();
|
||||||
|
|
||||||
|
@ -332,8 +333,8 @@ void Renderer::DrawOffscreenColor(PBaseCommandBuffer pCB, bool endRenderPass)
|
||||||
|
|
||||||
pCB->BeginRenderPass(_rphSwapChainWithDepth, _fbhSwapChainWithDepth[_pBaseRenderer->GetSwapChainBufferIndex()], { Vector4(0), Vector4(1) });
|
pCB->BeginRenderPass(_rphSwapChainWithDepth, _fbhSwapChainWithDepth[_pBaseRenderer->GetSwapChainBufferIndex()], { Vector4(0), Vector4(1) });
|
||||||
|
|
||||||
pCB->BindVertexBuffers(_geoQuad);
|
|
||||||
pCB->BindPipeline(_pipe[PIPE_OFFSCREEN_COLOR]);
|
pCB->BindPipeline(_pipe[PIPE_OFFSCREEN_COLOR]);
|
||||||
|
pCB->BindVertexBuffers(_geoQuad);
|
||||||
_shader[SHADER_QUAD]->BeginBindDescriptors();
|
_shader[SHADER_QUAD]->BeginBindDescriptors();
|
||||||
pCB->BindDescriptors(_shader[SHADER_QUAD], 0);
|
pCB->BindDescriptors(_shader[SHADER_QUAD], 0);
|
||||||
pCB->BindDescriptors(_shader[SHADER_QUAD], 1, _cshOffscreenColor);
|
pCB->BindDescriptors(_shader[SHADER_QUAD], 1, _cshOffscreenColor);
|
||||||
|
@ -350,7 +351,7 @@ void Renderer::DrawOffscreenColorSwitchRenderPass(PBaseCommandBuffer pCB)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!pCB)
|
if (!pCB)
|
||||||
pCB = &(*_commandBuffer);
|
pCB = _commandBuffer.Get();
|
||||||
|
|
||||||
pCB->EndRenderPass();
|
pCB->EndRenderPass();
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ void TextureRAM::UpdateSubresource(const void* p, int mipLevel, int arrayLayer,
|
||||||
memcpy(_vBuffer.data(), p, _vBuffer.size());
|
memcpy(_vBuffer.data(), p, _vBuffer.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TextureRAM::ReadbackSubresource(void* p, PBaseCommandBuffer pCB)
|
bool TextureRAM::ReadbackSubresource(void* p, bool recordCopyCommand, PBaseCommandBuffer pCB)
|
||||||
{
|
{
|
||||||
VERUS_RT_ASSERT(IsLoaded());
|
VERUS_RT_ASSERT(IsLoaded());
|
||||||
memcpy(p, _vBuffer.data(), _vBuffer.size());
|
memcpy(p, _vBuffer.data(), _vBuffer.size());
|
||||||
|
|
|
@ -16,7 +16,7 @@ namespace verus
|
||||||
virtual void Done() override;
|
virtual void Done() override;
|
||||||
|
|
||||||
virtual void UpdateSubresource(const void* p, int mipLevel, int arrayLayer, PBaseCommandBuffer pCB) override;
|
virtual void UpdateSubresource(const void* p, int mipLevel, int arrayLayer, PBaseCommandBuffer pCB) override;
|
||||||
virtual bool ReadbackSubresource(void* p, PBaseCommandBuffer pCB) override;
|
virtual bool ReadbackSubresource(void* p, bool recordCopyCommand, PBaseCommandBuffer pCB) override;
|
||||||
|
|
||||||
virtual void GenerateMips(PBaseCommandBuffer pCB) override;
|
virtual void GenerateMips(PBaseCommandBuffer pCB) override;
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ using namespace verus::Effects;
|
||||||
|
|
||||||
Bloom::UB_BloomVS Bloom::s_ubBloomVS;
|
Bloom::UB_BloomVS Bloom::s_ubBloomVS;
|
||||||
Bloom::UB_BloomFS Bloom::s_ubBloomFS;
|
Bloom::UB_BloomFS Bloom::s_ubBloomFS;
|
||||||
|
Bloom::UB_BloomGodRaysFS Bloom::s_ubBloomGodRaysFS;
|
||||||
|
|
||||||
Bloom::Bloom()
|
Bloom::Bloom()
|
||||||
{
|
{
|
||||||
|
@ -26,12 +27,17 @@ void Bloom::Init()
|
||||||
_shader->CreateDescriptorSet(0, &s_ubBloomVS, sizeof(s_ubBloomVS), 100, {}, CGI::ShaderStageFlags::vs);
|
_shader->CreateDescriptorSet(0, &s_ubBloomVS, sizeof(s_ubBloomVS), 100, {}, CGI::ShaderStageFlags::vs);
|
||||||
_shader->CreateDescriptorSet(1, &s_ubBloomFS, sizeof(s_ubBloomFS), 100,
|
_shader->CreateDescriptorSet(1, &s_ubBloomFS, sizeof(s_ubBloomFS), 100,
|
||||||
{
|
{
|
||||||
CGI::Sampler::nearestMipN
|
CGI::Sampler::linearClampMipN
|
||||||
|
}, CGI::ShaderStageFlags::fs);
|
||||||
|
_shader->CreateDescriptorSet(2, &s_ubBloomGodRaysFS, sizeof(s_ubBloomGodRaysFS), 100,
|
||||||
|
{
|
||||||
|
CGI::Sampler::linearClampMipN,
|
||||||
|
CGI::Sampler::shadow
|
||||||
}, CGI::ShaderStageFlags::fs);
|
}, CGI::ShaderStageFlags::fs);
|
||||||
_shader->CreatePipelineLayout();
|
_shader->CreatePipelineLayout();
|
||||||
|
|
||||||
{
|
{
|
||||||
CGI::PipelineDesc pipeDesc(renderer.GetGeoQuad(), _shader, "#", _rph);
|
CGI::PipelineDesc pipeDesc(renderer.GetGeoQuad(), _shader, "#GodRays", _rph);
|
||||||
pipeDesc._topology = CGI::PrimitiveTopology::triangleStrip;
|
pipeDesc._topology = CGI::PrimitiveTopology::triangleStrip;
|
||||||
pipeDesc.DisableDepthTest();
|
pipeDesc.DisableDepthTest();
|
||||||
_pipe.Init(pipeDesc);
|
_pipe.Init(pipeDesc);
|
||||||
|
@ -40,15 +46,30 @@ void Bloom::Init()
|
||||||
OnSwapChainResized();
|
OnSwapChainResized();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Bloom::InitByAtmosphere(CGI::TexturePtr texShadow)
|
||||||
|
{
|
||||||
|
VERUS_QREF_RENDERER;
|
||||||
|
|
||||||
|
_texAtmoShadow = texShadow;
|
||||||
|
|
||||||
|
_cshGodRays = _shader->BindDescriptorSetTextures(2, { renderer.GetTexDepthStencil(), _texAtmoShadow });
|
||||||
|
}
|
||||||
|
|
||||||
void Bloom::Done()
|
void Bloom::Done()
|
||||||
{
|
{
|
||||||
|
VERUS_QREF_RENDERER;
|
||||||
|
_shader->FreeDescriptorSet(_cshGodRays);
|
||||||
|
_shader->FreeDescriptorSet(_csh);
|
||||||
|
renderer->DeleteFramebuffer(_fbh);
|
||||||
VERUS_DONE(Bloom);
|
VERUS_DONE(Bloom);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bloom::OnSwapChainResized()
|
void Bloom::OnSwapChainResized()
|
||||||
{
|
{
|
||||||
VERUS_QREF_RENDERER;
|
VERUS_QREF_RENDERER;
|
||||||
|
VERUS_QREF_ATMO;
|
||||||
{
|
{
|
||||||
|
_shader->FreeDescriptorSet(_cshGodRays);
|
||||||
_shader->FreeDescriptorSet(_csh);
|
_shader->FreeDescriptorSet(_csh);
|
||||||
renderer->DeleteFramebuffer(_fbh);
|
renderer->DeleteFramebuffer(_fbh);
|
||||||
_tex.Done();
|
_tex.Done();
|
||||||
|
@ -65,6 +86,9 @@ void Bloom::OnSwapChainResized()
|
||||||
_tex[TEX_PONG].Init(texDesc);
|
_tex[TEX_PONG].Init(texDesc);
|
||||||
_fbh = renderer->CreateFramebuffer(_rph, { _tex[TEX_PING] }, w, h);
|
_fbh = renderer->CreateFramebuffer(_rph, { _tex[TEX_PING] }, w, h);
|
||||||
_csh = _shader->BindDescriptorSetTextures(1, { renderer.GetDS().GetComposedTextureA() });
|
_csh = _shader->BindDescriptorSetTextures(1, { renderer.GetDS().GetComposedTextureA() });
|
||||||
|
|
||||||
|
if (_texAtmoShadow)
|
||||||
|
InitByAtmosphere(_texAtmoShadow);
|
||||||
}
|
}
|
||||||
renderer.GetDS().InitByBloom(_tex[TEX_PING]);
|
renderer.GetDS().InitByBloom(_tex[TEX_PING]);
|
||||||
}
|
}
|
||||||
|
@ -72,25 +96,38 @@ void Bloom::OnSwapChainResized()
|
||||||
void Bloom::Generate()
|
void Bloom::Generate()
|
||||||
{
|
{
|
||||||
VERUS_QREF_RENDERER;
|
VERUS_QREF_RENDERER;
|
||||||
|
VERUS_QREF_ATMO;
|
||||||
|
VERUS_QREF_SM;
|
||||||
|
|
||||||
|
auto cb = renderer.GetCommandBuffer();
|
||||||
|
|
||||||
s_ubBloomVS._matW = Math::QuadMatrix().UniformBufferFormat();
|
s_ubBloomVS._matW = Math::QuadMatrix().UniformBufferFormat();
|
||||||
s_ubBloomVS._matV = Math::ToUVMatrix().UniformBufferFormat();
|
s_ubBloomVS._matV = Math::ToUVMatrix().UniformBufferFormat();
|
||||||
s_ubBloomFS._exposure.x = renderer.GetExposure();
|
s_ubBloomFS._exposure.x = renderer.GetExposure();
|
||||||
|
s_ubBloomGodRaysFS._matInvVP = Matrix4(VMath::inverse(sm.GetMainCamera()->GetMatrixVP())).UniformBufferFormat();
|
||||||
|
s_ubBloomGodRaysFS._matSunShadow = atmo.GetShadowMap().GetShadowMatrix(0).UniformBufferFormat();
|
||||||
|
s_ubBloomGodRaysFS._matSunShadowCSM1 = atmo.GetShadowMap().GetShadowMatrix(1).UniformBufferFormat();
|
||||||
|
s_ubBloomGodRaysFS._matSunShadowCSM2 = atmo.GetShadowMap().GetShadowMatrix(2).UniformBufferFormat();
|
||||||
|
s_ubBloomGodRaysFS._matSunShadowCSM3 = atmo.GetShadowMap().GetShadowMatrix(3).UniformBufferFormat();
|
||||||
|
memcpy(&s_ubBloomGodRaysFS._shadowConfig, &atmo.GetShadowMap().GetConfig(), sizeof(s_ubBloomGodRaysFS._shadowConfig));
|
||||||
|
s_ubBloomGodRaysFS._splitRanges = atmo.GetShadowMap().GetSplitRanges().GLM();
|
||||||
|
s_ubBloomGodRaysFS._dirToSun = float4(atmo.GetDirToSun().GLM(), 0);
|
||||||
|
s_ubBloomGodRaysFS._sunColor = float4(atmo.GetSunColor().GLM(), 0);
|
||||||
|
s_ubBloomGodRaysFS._eyePos = float4(atmo.GetEyePosition().GLM(), 0);
|
||||||
|
|
||||||
auto cb = renderer.GetCommandBuffer();
|
cb->PipelineImageMemoryBarrier(renderer.GetTexDepthStencil(), CGI::ImageLayout::depthStencilAttachment, CGI::ImageLayout::depthStencilReadOnly, 0);
|
||||||
|
|
||||||
cb->BeginRenderPass(_rph, _fbh, { _tex[TEX_PING]->GetClearValue() });
|
cb->BeginRenderPass(_rph, _fbh, { _tex[TEX_PING]->GetClearValue() });
|
||||||
|
|
||||||
cb->BindPipeline(_pipe);
|
cb->BindPipeline(_pipe);
|
||||||
|
|
||||||
_shader->BeginBindDescriptors();
|
_shader->BeginBindDescriptors();
|
||||||
cb->BindDescriptors(_shader, 0);
|
cb->BindDescriptors(_shader, 0);
|
||||||
cb->BindDescriptors(_shader, 1, _csh);
|
cb->BindDescriptors(_shader, 1, _csh);
|
||||||
|
cb->BindDescriptors(_shader, 2, _cshGodRays);
|
||||||
_shader->EndBindDescriptors();
|
_shader->EndBindDescriptors();
|
||||||
|
renderer.DrawQuad(cb.Get());
|
||||||
renderer.DrawQuad(&(*cb));
|
|
||||||
|
|
||||||
cb->EndRenderPass();
|
cb->EndRenderPass();
|
||||||
|
cb->PipelineImageMemoryBarrier(renderer.GetTexDepthStencil(), CGI::ImageLayout::depthStencilReadOnly, CGI::ImageLayout::depthStencilAttachment, 0);
|
||||||
|
|
||||||
Blur::I().GenerateForBloom();
|
Blur::I().GenerateForBloom();
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,19 +17,23 @@ namespace verus
|
||||||
|
|
||||||
static UB_BloomVS s_ubBloomVS;
|
static UB_BloomVS s_ubBloomVS;
|
||||||
static UB_BloomFS s_ubBloomFS;
|
static UB_BloomFS s_ubBloomFS;
|
||||||
|
static UB_BloomGodRaysFS s_ubBloomGodRaysFS;
|
||||||
|
|
||||||
CGI::ShaderPwn _shader;
|
CGI::ShaderPwn _shader;
|
||||||
CGI::PipelinePwn _pipe;
|
CGI::PipelinePwn _pipe;
|
||||||
CGI::TexturePwns<TEX_COUNT> _tex;
|
CGI::TexturePwns<TEX_COUNT> _tex;
|
||||||
|
CGI::TexturePtr _texAtmoShadow;
|
||||||
CGI::RPHandle _rph;
|
CGI::RPHandle _rph;
|
||||||
CGI::FBHandle _fbh;
|
CGI::FBHandle _fbh;
|
||||||
CGI::CSHandle _csh;
|
CGI::CSHandle _csh;
|
||||||
|
CGI::CSHandle _cshGodRays;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Bloom();
|
Bloom();
|
||||||
~Bloom();
|
~Bloom();
|
||||||
|
|
||||||
void Init();
|
void Init();
|
||||||
|
void InitByAtmosphere(CGI::TexturePtr texShadow);
|
||||||
void Done();
|
void Done();
|
||||||
|
|
||||||
void OnSwapChainResized();
|
void OnSwapChainResized();
|
||||||
|
|
|
@ -5,6 +5,7 @@ using namespace verus::Effects;
|
||||||
|
|
||||||
Blur::UB_BlurVS Blur::s_ubBlurVS;
|
Blur::UB_BlurVS Blur::s_ubBlurVS;
|
||||||
Blur::UB_BlurFS Blur::s_ubBlurFS;
|
Blur::UB_BlurFS Blur::s_ubBlurFS;
|
||||||
|
Blur::UB_ExtraBlurFS Blur::s_ubExtraBlurFS;
|
||||||
|
|
||||||
// Blur::Handles:
|
// Blur::Handles:
|
||||||
|
|
||||||
|
@ -41,6 +42,8 @@ void Blur::Init()
|
||||||
_bloomHandles._rphV = renderer->CreateSimpleRenderPass(CGI::Format::srgbR8G8B8A8);
|
_bloomHandles._rphV = renderer->CreateSimpleRenderPass(CGI::Format::srgbR8G8B8A8);
|
||||||
_ssaoHandles._rphH = renderer->CreateSimpleRenderPass(CGI::Format::srgbR8G8B8A8);
|
_ssaoHandles._rphH = renderer->CreateSimpleRenderPass(CGI::Format::srgbR8G8B8A8);
|
||||||
_ssaoHandles._rphV = renderer->CreateSimpleRenderPass(CGI::Format::unormR8);
|
_ssaoHandles._rphV = renderer->CreateSimpleRenderPass(CGI::Format::unormR8);
|
||||||
|
_rphAntiAliasing = renderer->CreateSimpleRenderPass(CGI::Format::floatR11G11B10);
|
||||||
|
_rphMotionBlur = renderer->CreateSimpleRenderPass(CGI::Format::floatR11G11B10);
|
||||||
|
|
||||||
_shader.Init("[Shaders]:Blur.hlsl");
|
_shader.Init("[Shaders]:Blur.hlsl");
|
||||||
_shader->CreateDescriptorSet(0, &s_ubBlurVS, sizeof(s_ubBlurVS), 100, {}, CGI::ShaderStageFlags::vs);
|
_shader->CreateDescriptorSet(0, &s_ubBlurVS, sizeof(s_ubBlurVS), 100, {}, CGI::ShaderStageFlags::vs);
|
||||||
|
@ -48,6 +51,11 @@ void Blur::Init()
|
||||||
{
|
{
|
||||||
CGI::Sampler::linearClampMipN
|
CGI::Sampler::linearClampMipN
|
||||||
}, CGI::ShaderStageFlags::fs);
|
}, CGI::ShaderStageFlags::fs);
|
||||||
|
_shader->CreateDescriptorSet(2, &s_ubExtraBlurFS, sizeof(s_ubExtraBlurFS), 100,
|
||||||
|
{
|
||||||
|
CGI::Sampler::linearClampMipN,
|
||||||
|
CGI::Sampler::linearClampMipN
|
||||||
|
}, CGI::ShaderStageFlags::fs);
|
||||||
_shader->CreatePipelineLayout();
|
_shader->CreatePipelineLayout();
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -76,12 +84,28 @@ void Blur::Init()
|
||||||
pipeDesc._renderPassHandle = _ssaoHandles._rphV;
|
pipeDesc._renderPassHandle = _ssaoHandles._rphV;
|
||||||
_pipe[PIPE_SSAO_V].Init(pipeDesc);
|
_pipe[PIPE_SSAO_V].Init(pipeDesc);
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
CGI::PipelineDesc pipeDesc(renderer.GetGeoQuad(), _shader, "#AntiAliasing", _rphAntiAliasing);
|
||||||
|
pipeDesc._topology = CGI::PrimitiveTopology::triangleStrip;
|
||||||
|
pipeDesc.DisableDepthTest();
|
||||||
|
_pipe[PIPE_AA].Init(pipeDesc);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
CGI::PipelineDesc pipeDesc(renderer.GetGeoQuad(), _shader, "#Motion", _rphMotionBlur);
|
||||||
|
pipeDesc._topology = CGI::PrimitiveTopology::triangleStrip;
|
||||||
|
pipeDesc.DisableDepthTest();
|
||||||
|
_pipe[PIPE_MOTION_BLUR].Init(pipeDesc);
|
||||||
|
}
|
||||||
|
|
||||||
OnSwapChainResized();
|
OnSwapChainResized();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Blur::Done()
|
void Blur::Done()
|
||||||
{
|
{
|
||||||
|
_shader->FreeDescriptorSet(_cshMotionBlurExtra);
|
||||||
|
_shader->FreeDescriptorSet(_cshMotionBlur);
|
||||||
|
_shader->FreeDescriptorSet(_cshAntiAliasingExtra);
|
||||||
|
_shader->FreeDescriptorSet(_cshAntiAliasing);
|
||||||
_ssaoHandles.FreeDescriptorSets(_shader);
|
_ssaoHandles.FreeDescriptorSets(_shader);
|
||||||
_bloomHandles.FreeDescriptorSets(_shader);
|
_bloomHandles.FreeDescriptorSets(_shader);
|
||||||
VERUS_DONE(Blur);
|
VERUS_DONE(Blur);
|
||||||
|
@ -93,6 +117,12 @@ void Blur::OnSwapChainResized()
|
||||||
VERUS_QREF_BLOOM;
|
VERUS_QREF_BLOOM;
|
||||||
VERUS_QREF_SSAO;
|
VERUS_QREF_SSAO;
|
||||||
{
|
{
|
||||||
|
_shader->FreeDescriptorSet(_cshMotionBlurExtra);
|
||||||
|
_shader->FreeDescriptorSet(_cshMotionBlur);
|
||||||
|
renderer->DeleteFramebuffer(_fbhMotionBlur);
|
||||||
|
_shader->FreeDescriptorSet(_cshAntiAliasingExtra);
|
||||||
|
_shader->FreeDescriptorSet(_cshAntiAliasing);
|
||||||
|
renderer->DeleteFramebuffer(_fbhAntiAliasing);
|
||||||
_ssaoHandles.FreeDescriptorSets(_shader);
|
_ssaoHandles.FreeDescriptorSets(_shader);
|
||||||
_ssaoHandles.DeleteFramebuffers();
|
_ssaoHandles.DeleteFramebuffers();
|
||||||
_bloomHandles.FreeDescriptorSets(_shader);
|
_bloomHandles.FreeDescriptorSets(_shader);
|
||||||
|
@ -100,24 +130,35 @@ void Blur::OnSwapChainResized()
|
||||||
_tex.Done();
|
_tex.Done();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
const int swapChainWidth = renderer.GetSwapChainWidth();
|
||||||
|
const int swapChainHeight = renderer.GetSwapChainHeight();
|
||||||
|
const int swapChainHalfWidth = renderer.GetSwapChainWidth() / 2;
|
||||||
|
const int swapChainHalfHeight = renderer.GetSwapChainHeight() / 2;
|
||||||
|
|
||||||
CGI::TextureDesc texDesc;
|
CGI::TextureDesc texDesc;
|
||||||
texDesc._format = CGI::Format::srgbR8G8B8A8;
|
texDesc._format = CGI::Format::srgbR8G8B8A8;
|
||||||
texDesc._width = renderer.GetSwapChainWidth();
|
texDesc._width = swapChainWidth;
|
||||||
texDesc._height = renderer.GetSwapChainHeight();
|
texDesc._height = swapChainHeight;
|
||||||
texDesc._flags = CGI::TextureDesc::Flags::colorAttachment;
|
texDesc._flags = CGI::TextureDesc::Flags::colorAttachment;
|
||||||
_tex.Init(texDesc);
|
_tex.Init(texDesc);
|
||||||
|
|
||||||
const int halfW = renderer.GetSwapChainWidth() / 2;
|
_bloomHandles._fbhH = renderer->CreateFramebuffer(_bloomHandles._rphH, { bloom.GetPongTexture() }, swapChainHalfWidth, swapChainHalfHeight);
|
||||||
const int halfH = renderer.GetSwapChainHeight() / 2;
|
_bloomHandles._fbhV = renderer->CreateFramebuffer(_bloomHandles._rphV, { bloom.GetTexture() }, swapChainHalfWidth, swapChainHalfHeight);
|
||||||
_bloomHandles._fbhH = renderer->CreateFramebuffer(_bloomHandles._rphH, { bloom.GetPongTexture() }, halfW, halfH);
|
|
||||||
_bloomHandles._fbhV = renderer->CreateFramebuffer(_bloomHandles._rphV, { bloom.GetTexture() }, halfW, halfH);
|
|
||||||
_bloomHandles._cshH = _shader->BindDescriptorSetTextures(1, { bloom.GetTexture() });
|
_bloomHandles._cshH = _shader->BindDescriptorSetTextures(1, { bloom.GetTexture() });
|
||||||
_bloomHandles._cshV = _shader->BindDescriptorSetTextures(1, { bloom.GetPongTexture() });
|
_bloomHandles._cshV = _shader->BindDescriptorSetTextures(1, { bloom.GetPongTexture() });
|
||||||
|
|
||||||
_ssaoHandles._fbhH = renderer->CreateFramebuffer(_ssaoHandles._rphH, { _tex }, renderer.GetSwapChainWidth(), renderer.GetSwapChainHeight());
|
_ssaoHandles._fbhH = renderer->CreateFramebuffer(_ssaoHandles._rphH, { _tex }, swapChainWidth, swapChainHeight);
|
||||||
_ssaoHandles._fbhV = renderer->CreateFramebuffer(_ssaoHandles._rphV, { ssao.GetTexture() }, renderer.GetSwapChainWidth(), renderer.GetSwapChainHeight());
|
_ssaoHandles._fbhV = renderer->CreateFramebuffer(_ssaoHandles._rphV, { ssao.GetTexture() }, swapChainWidth, swapChainHeight);
|
||||||
_ssaoHandles._cshH = _shader->BindDescriptorSetTextures(1, { ssao.GetTexture() });
|
_ssaoHandles._cshH = _shader->BindDescriptorSetTextures(1, { ssao.GetTexture() });
|
||||||
_ssaoHandles._cshV = _shader->BindDescriptorSetTextures(1, { _tex });
|
_ssaoHandles._cshV = _shader->BindDescriptorSetTextures(1, { _tex });
|
||||||
|
|
||||||
|
_fbhAntiAliasing = renderer->CreateFramebuffer(_rphAntiAliasing, { renderer.GetDS().GetComposedTextureB() }, swapChainWidth, swapChainHeight);
|
||||||
|
_cshAntiAliasing = _shader->BindDescriptorSetTextures(1, { renderer.GetDS().GetComposedTextureA() });
|
||||||
|
_cshAntiAliasingExtra = _shader->BindDescriptorSetTextures(2, { renderer.GetDS().GetGBuffer(1), renderer.GetTexDepthStencil() });
|
||||||
|
|
||||||
|
_fbhMotionBlur = renderer->CreateFramebuffer(_rphMotionBlur, { renderer.GetDS().GetComposedTextureA() }, swapChainWidth, swapChainHeight);
|
||||||
|
_cshMotionBlur = _shader->BindDescriptorSetTextures(1, { renderer.GetDS().GetComposedTextureB() });
|
||||||
|
_cshMotionBlurExtra = _shader->BindDescriptorSetTextures(2, { renderer.GetDS().GetGBuffer(1), renderer.GetTexDepthStencil() });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,21 +171,19 @@ void Blur::GenerateForBloom()
|
||||||
VERUS_QREF_RENDERER;
|
VERUS_QREF_RENDERER;
|
||||||
VERUS_QREF_BLOOM;
|
VERUS_QREF_BLOOM;
|
||||||
|
|
||||||
|
auto cb = renderer.GetCommandBuffer();
|
||||||
|
|
||||||
s_ubBlurVS._matW = Math::QuadMatrix().UniformBufferFormat();
|
s_ubBlurVS._matW = Math::QuadMatrix().UniformBufferFormat();
|
||||||
s_ubBlurVS._matV = Math::ToUVMatrix(0, bloom.GetTexture()->GetSize(), nullptr, 0.5f, 0).UniformBufferFormat();
|
s_ubBlurVS._matV = Math::ToUVMatrix(0, bloom.GetTexture()->GetSize(), nullptr, 0.5f, 0).UniformBufferFormat();
|
||||||
|
|
||||||
auto cb = renderer.GetCommandBuffer();
|
|
||||||
|
|
||||||
_shader->BeginBindDescriptors();
|
_shader->BeginBindDescriptors();
|
||||||
{
|
{
|
||||||
cb->BeginRenderPass(_bloomHandles._rphH, _bloomHandles._fbhH, { bloom.GetPongTexture()->GetClearValue() });
|
cb->BeginRenderPass(_bloomHandles._rphH, _bloomHandles._fbhH, { bloom.GetPongTexture()->GetClearValue() });
|
||||||
|
|
||||||
cb->BindPipeline(_pipe[PIPE_BLOOM_H]);
|
cb->BindPipeline(_pipe[PIPE_BLOOM_H]);
|
||||||
|
|
||||||
cb->BindDescriptors(_shader, 0);
|
cb->BindDescriptors(_shader, 0);
|
||||||
cb->BindDescriptors(_shader, 1, _bloomHandles._cshH);
|
cb->BindDescriptors(_shader, 1, _bloomHandles._cshH);
|
||||||
|
renderer.DrawQuad(cb.Get());
|
||||||
renderer.DrawQuad(&(*cb));
|
|
||||||
|
|
||||||
cb->EndRenderPass();
|
cb->EndRenderPass();
|
||||||
}
|
}
|
||||||
|
@ -153,11 +192,9 @@ void Blur::GenerateForBloom()
|
||||||
cb->BeginRenderPass(_bloomHandles._rphV, _bloomHandles._fbhV, { bloom.GetTexture()->GetClearValue() });
|
cb->BeginRenderPass(_bloomHandles._rphV, _bloomHandles._fbhV, { bloom.GetTexture()->GetClearValue() });
|
||||||
|
|
||||||
cb->BindPipeline(_pipe[PIPE_BLOOM_V]);
|
cb->BindPipeline(_pipe[PIPE_BLOOM_V]);
|
||||||
|
|
||||||
cb->BindDescriptors(_shader, 0);
|
cb->BindDescriptors(_shader, 0);
|
||||||
cb->BindDescriptors(_shader, 1, _bloomHandles._cshV);
|
cb->BindDescriptors(_shader, 1, _bloomHandles._cshV);
|
||||||
|
renderer.DrawQuad(cb.Get());
|
||||||
renderer.DrawQuad(&(*cb));
|
|
||||||
|
|
||||||
cb->EndRenderPass();
|
cb->EndRenderPass();
|
||||||
}
|
}
|
||||||
|
@ -169,21 +206,19 @@ void Blur::GenerateForSsao()
|
||||||
VERUS_QREF_RENDERER;
|
VERUS_QREF_RENDERER;
|
||||||
VERUS_QREF_SSAO;
|
VERUS_QREF_SSAO;
|
||||||
|
|
||||||
|
auto cb = renderer.GetCommandBuffer();
|
||||||
|
|
||||||
s_ubBlurVS._matW = Math::QuadMatrix().UniformBufferFormat();
|
s_ubBlurVS._matW = Math::QuadMatrix().UniformBufferFormat();
|
||||||
s_ubBlurVS._matV = Math::ToUVMatrix(0, _tex->GetSize(), nullptr, 0.5f, 0).UniformBufferFormat();
|
s_ubBlurVS._matV = Math::ToUVMatrix(0, _tex->GetSize(), nullptr, 0.5f, 0).UniformBufferFormat();
|
||||||
|
|
||||||
auto cb = renderer.GetCommandBuffer();
|
|
||||||
|
|
||||||
_shader->BeginBindDescriptors();
|
_shader->BeginBindDescriptors();
|
||||||
{
|
{
|
||||||
cb->BeginRenderPass(_ssaoHandles._rphH, _ssaoHandles._fbhH, { _tex->GetClearValue() });
|
cb->BeginRenderPass(_ssaoHandles._rphH, _ssaoHandles._fbhH, { _tex->GetClearValue() });
|
||||||
|
|
||||||
cb->BindPipeline(_pipe[PIPE_SSAO_H]);
|
cb->BindPipeline(_pipe[PIPE_SSAO_H]);
|
||||||
|
|
||||||
cb->BindDescriptors(_shader, 0);
|
cb->BindDescriptors(_shader, 0);
|
||||||
cb->BindDescriptors(_shader, 1, _ssaoHandles._cshH);
|
cb->BindDescriptors(_shader, 1, _ssaoHandles._cshH);
|
||||||
|
renderer.DrawQuad(cb.Get());
|
||||||
renderer.DrawQuad(&(*cb));
|
|
||||||
|
|
||||||
cb->EndRenderPass();
|
cb->EndRenderPass();
|
||||||
}
|
}
|
||||||
|
@ -192,21 +227,66 @@ void Blur::GenerateForSsao()
|
||||||
cb->BeginRenderPass(_ssaoHandles._rphV, _ssaoHandles._fbhV, { ssao.GetTexture()->GetClearValue() });
|
cb->BeginRenderPass(_ssaoHandles._rphV, _ssaoHandles._fbhV, { ssao.GetTexture()->GetClearValue() });
|
||||||
|
|
||||||
cb->BindPipeline(_pipe[PIPE_SSAO_V]);
|
cb->BindPipeline(_pipe[PIPE_SSAO_V]);
|
||||||
|
|
||||||
cb->BindDescriptors(_shader, 0);
|
cb->BindDescriptors(_shader, 0);
|
||||||
cb->BindDescriptors(_shader, 1, _ssaoHandles._cshV);
|
cb->BindDescriptors(_shader, 1, _ssaoHandles._cshV);
|
||||||
|
renderer.DrawQuad(cb.Get());
|
||||||
renderer.DrawQuad(&(*cb));
|
|
||||||
|
|
||||||
cb->EndRenderPass();
|
cb->EndRenderPass();
|
||||||
}
|
}
|
||||||
_shader->EndBindDescriptors();
|
_shader->EndBindDescriptors();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Blur::GenerateForDepthOfField()
|
void Blur::GenerateForAntiAliasing()
|
||||||
{
|
{
|
||||||
|
VERUS_QREF_RENDERER;
|
||||||
|
VERUS_QREF_SM;
|
||||||
|
|
||||||
|
auto cb = renderer.GetCommandBuffer();
|
||||||
|
|
||||||
|
s_ubBlurVS._matW = Math::QuadMatrix().UniformBufferFormat();
|
||||||
|
s_ubBlurVS._matV = Math::ToUVMatrix().UniformBufferFormat();
|
||||||
|
s_ubExtraBlurFS._zNearFarEx = sm.GetMainCamera()->GetZNearFarEx().GLM();
|
||||||
|
s_ubExtraBlurFS._textureSize = renderer.GetDS().GetComposedTextureA()->GetSize().GLM();
|
||||||
|
|
||||||
|
cb->PipelineImageMemoryBarrier(renderer.GetTexDepthStencil(), CGI::ImageLayout::depthStencilAttachment, CGI::ImageLayout::depthStencilReadOnly, 0);
|
||||||
|
cb->BeginRenderPass(_rphAntiAliasing, _fbhAntiAliasing, { renderer.GetDS().GetComposedTextureB()->GetClearValue() });
|
||||||
|
|
||||||
|
cb->BindPipeline(_pipe[PIPE_AA]);
|
||||||
|
_shader->BeginBindDescriptors();
|
||||||
|
cb->BindDescriptors(_shader, 0);
|
||||||
|
cb->BindDescriptors(_shader, 1, _cshAntiAliasing);
|
||||||
|
cb->BindDescriptors(_shader, 2, _cshAntiAliasingExtra);
|
||||||
|
_shader->EndBindDescriptors();
|
||||||
|
renderer.DrawQuad(cb.Get());
|
||||||
|
|
||||||
|
cb->EndRenderPass();
|
||||||
|
cb->PipelineImageMemoryBarrier(renderer.GetTexDepthStencil(), CGI::ImageLayout::depthStencilReadOnly, CGI::ImageLayout::depthStencilAttachment, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Blur::GenerateForMotionBlur()
|
void Blur::GenerateForMotionBlur()
|
||||||
{
|
{
|
||||||
|
VERUS_QREF_RENDERER;
|
||||||
|
VERUS_QREF_SM;
|
||||||
|
|
||||||
|
auto cb = renderer.GetCommandBuffer();
|
||||||
|
|
||||||
|
s_ubBlurVS._matW = Math::QuadMatrix().UniformBufferFormat();
|
||||||
|
s_ubBlurVS._matV = Math::ToUVMatrix().UniformBufferFormat();
|
||||||
|
s_ubExtraBlurFS._matInvVP = Matrix4(VMath::inverse(sm.GetMainCamera()->GetMatrixVP())).UniformBufferFormat();
|
||||||
|
s_ubExtraBlurFS._matPrevVP = sm.GetMainCamera()->GetMatrixPrevVP().UniformBufferFormat();
|
||||||
|
s_ubExtraBlurFS._zNearFarEx = sm.GetMainCamera()->GetZNearFarEx().GLM();
|
||||||
|
|
||||||
|
cb->PipelineImageMemoryBarrier(renderer.GetTexDepthStencil(), CGI::ImageLayout::depthStencilAttachment, CGI::ImageLayout::depthStencilReadOnly, 0);
|
||||||
|
cb->BeginRenderPass(_rphMotionBlur, _fbhMotionBlur, { renderer.GetDS().GetComposedTextureB()->GetClearValue() });
|
||||||
|
|
||||||
|
cb->BindPipeline(_pipe[PIPE_MOTION_BLUR]);
|
||||||
|
_shader->BeginBindDescriptors();
|
||||||
|
cb->BindDescriptors(_shader, 0);
|
||||||
|
cb->BindDescriptors(_shader, 1, _cshMotionBlur);
|
||||||
|
cb->BindDescriptors(_shader, 2, _cshMotionBlurExtra);
|
||||||
|
_shader->EndBindDescriptors();
|
||||||
|
renderer.DrawQuad(cb.Get());
|
||||||
|
|
||||||
|
cb->EndRenderPass();
|
||||||
|
cb->PipelineImageMemoryBarrier(renderer.GetTexDepthStencil(), CGI::ImageLayout::depthStencilReadOnly, CGI::ImageLayout::depthStencilAttachment, 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,8 @@ namespace verus
|
||||||
PIPE_BLOOM_V,
|
PIPE_BLOOM_V,
|
||||||
PIPE_SSAO_H,
|
PIPE_SSAO_H,
|
||||||
PIPE_SSAO_V,
|
PIPE_SSAO_V,
|
||||||
|
PIPE_AA,
|
||||||
|
PIPE_MOTION_BLUR,
|
||||||
PIPE_COUNT
|
PIPE_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -34,12 +36,21 @@ namespace verus
|
||||||
|
|
||||||
static UB_BlurVS s_ubBlurVS;
|
static UB_BlurVS s_ubBlurVS;
|
||||||
static UB_BlurFS s_ubBlurFS;
|
static UB_BlurFS s_ubBlurFS;
|
||||||
|
static UB_ExtraBlurFS s_ubExtraBlurFS;
|
||||||
|
|
||||||
CGI::ShaderPwn _shader;
|
CGI::ShaderPwn _shader;
|
||||||
CGI::PipelinePwns<PIPE_COUNT> _pipe;
|
CGI::PipelinePwns<PIPE_COUNT> _pipe;
|
||||||
CGI::TexturePwn _tex;
|
CGI::TexturePwn _tex;
|
||||||
Handles _bloomHandles;
|
Handles _bloomHandles;
|
||||||
Handles _ssaoHandles;
|
Handles _ssaoHandles;
|
||||||
|
CGI::RPHandle _rphAntiAliasing;
|
||||||
|
CGI::FBHandle _fbhAntiAliasing;
|
||||||
|
CGI::CSHandle _cshAntiAliasing;
|
||||||
|
CGI::CSHandle _cshAntiAliasingExtra;
|
||||||
|
CGI::RPHandle _rphMotionBlur;
|
||||||
|
CGI::FBHandle _fbhMotionBlur;
|
||||||
|
CGI::CSHandle _cshMotionBlur;
|
||||||
|
CGI::CSHandle _cshMotionBlurExtra;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Blur();
|
Blur();
|
||||||
|
@ -53,7 +64,7 @@ namespace verus
|
||||||
void Generate();
|
void Generate();
|
||||||
void GenerateForBloom();
|
void GenerateForBloom();
|
||||||
void GenerateForSsao();
|
void GenerateForSsao();
|
||||||
void GenerateForDepthOfField();
|
void GenerateForAntiAliasing();
|
||||||
void GenerateForMotionBlur();
|
void GenerateForMotionBlur();
|
||||||
};
|
};
|
||||||
VERUS_TYPEDEFS(Blur);
|
VERUS_TYPEDEFS(Blur);
|
||||||
|
|
|
@ -86,6 +86,8 @@ void Ssao::Generate()
|
||||||
|
|
||||||
Scene::RCamera cam = *sm.GetCamera();
|
Scene::RCamera cam = *sm.GetCamera();
|
||||||
|
|
||||||
|
auto cb = renderer.GetCommandBuffer();
|
||||||
|
|
||||||
s_ubSsaoVS._matW = Math::QuadMatrix().UniformBufferFormat();
|
s_ubSsaoVS._matW = Math::QuadMatrix().UniformBufferFormat();
|
||||||
s_ubSsaoVS._matV = Math::ToUVMatrix().UniformBufferFormat();
|
s_ubSsaoVS._matV = Math::ToUVMatrix().UniformBufferFormat();
|
||||||
s_ubSsaoVS._matP = Math::ToUVMatrix(0, _tex[TEX_GEN_AO]->GetSize(), &_tex[TEX_RAND_NORMALS]->GetSize()).UniformBufferFormat();
|
s_ubSsaoVS._matP = Math::ToUVMatrix(0, _tex[TEX_GEN_AO]->GetSize(), &_tex[TEX_RAND_NORMALS]->GetSize()).UniformBufferFormat();
|
||||||
|
@ -93,18 +95,14 @@ void Ssao::Generate()
|
||||||
s_ubSsaoFS._camScale.x = cam.GetFovScale() / cam.GetAspectRatio();
|
s_ubSsaoFS._camScale.x = cam.GetFovScale() / cam.GetAspectRatio();
|
||||||
s_ubSsaoFS._camScale.y = -cam.GetFovScale();
|
s_ubSsaoFS._camScale.y = -cam.GetFovScale();
|
||||||
|
|
||||||
auto cb = renderer.GetCommandBuffer();
|
|
||||||
|
|
||||||
cb->BeginRenderPass(_rph, _fbh, { _tex[TEX_GEN_AO]->GetClearValue() });
|
cb->BeginRenderPass(_rph, _fbh, { _tex[TEX_GEN_AO]->GetClearValue() });
|
||||||
|
|
||||||
cb->BindPipeline(_pipe);
|
cb->BindPipeline(_pipe);
|
||||||
|
|
||||||
_shader->BeginBindDescriptors();
|
_shader->BeginBindDescriptors();
|
||||||
cb->BindDescriptors(_shader, 0);
|
cb->BindDescriptors(_shader, 0);
|
||||||
cb->BindDescriptors(_shader, 1, _csh);
|
cb->BindDescriptors(_shader, 1, _csh);
|
||||||
_shader->EndBindDescriptors();
|
_shader->EndBindDescriptors();
|
||||||
|
renderer.DrawQuad(cb.Get());
|
||||||
renderer.DrawQuad(&(*cb));
|
|
||||||
|
|
||||||
cb->EndRenderPass();
|
cb->EndRenderPass();
|
||||||
|
|
||||||
|
|
|
@ -133,7 +133,7 @@ PWidget Container::GetWidgetById(CSZ id)
|
||||||
|
|
||||||
int Container::GetWidgetIndex(PWidget p)
|
int Container::GetWidgetIndex(PWidget p)
|
||||||
{
|
{
|
||||||
const int size = _vWidgets.size();
|
const int size = Utils::Cast32(_vWidgets.size());
|
||||||
VERUS_FOR(i, size)
|
VERUS_FOR(i, size)
|
||||||
{
|
{
|
||||||
if (_vWidgets[i] == p)
|
if (_vWidgets[i] == p)
|
||||||
|
|
|
@ -31,7 +31,7 @@ namespace verus
|
||||||
|
|
||||||
PWidget GetHovered(float x, float y);
|
PWidget GetHovered(float x, float y);
|
||||||
PWidget GetWidgetById(CSZ id);
|
PWidget GetWidgetById(CSZ id);
|
||||||
int GetWidgetCount() const { return _vWidgets.size(); }
|
int GetWidgetCount() const { return Utils::Cast32(_vWidgets.size()); }
|
||||||
int GetWidgetIndex(PWidget p);
|
int GetWidgetIndex(PWidget p);
|
||||||
};
|
};
|
||||||
VERUS_TYPEDEFS(Container);
|
VERUS_TYPEDEFS(Container);
|
||||||
|
|
|
@ -156,8 +156,8 @@ void Font::Draw(RcDrawDesc dd)
|
||||||
|
|
||||||
auto cb = renderer.GetCommandBuffer();
|
auto cb = renderer.GetCommandBuffer();
|
||||||
|
|
||||||
cb->BindVertexBuffers(_dynBuffer);
|
|
||||||
cb->BindPipeline(_pipe);
|
cb->BindPipeline(_pipe);
|
||||||
|
cb->BindVertexBuffers(_dynBuffer);
|
||||||
|
|
||||||
s_shader->BeginBindDescriptors();
|
s_shader->BeginBindDescriptors();
|
||||||
cb->BindDescriptors(s_shader, 0, _csh);
|
cb->BindDescriptors(s_shader, 0, _csh);
|
||||||
|
@ -168,7 +168,7 @@ void Font::Draw(RcDrawDesc dd)
|
||||||
{
|
{
|
||||||
const float spaceLeft = (dd._x + dd._w) - xoffset;
|
const float spaceLeft = (dd._x + dd._w) - xoffset;
|
||||||
|
|
||||||
int wordLen = wcscspn(text, wrapChars); // First occurrence of wrap chars.
|
int wordLen = static_cast<int>(wcscspn(text, wrapChars)); // First occurrence of wrap chars.
|
||||||
|
|
||||||
if (!wordLen && L'-' == *text)
|
if (!wordLen && L'-' == *text)
|
||||||
wordLen = 1; // Don't throw away hyphen.
|
wordLen = 1; // Don't throw away hyphen.
|
||||||
|
@ -296,7 +296,7 @@ float Font::DrawWord(CWSZ word, int wordLen, float xoffset, float yoffset, bool
|
||||||
|
|
||||||
int Font::GetTextWidth(CWSZ text, int textLen)
|
int Font::GetTextWidth(CWSZ text, int textLen)
|
||||||
{
|
{
|
||||||
const int len = (textLen >= 0) ? textLen : wcslen(text);
|
const int len = (textLen >= 0) ? textLen : static_cast<int>(wcslen(text));
|
||||||
int width = 0;
|
int width = 0;
|
||||||
VERUS_FOR(i, len)
|
VERUS_FOR(i, len)
|
||||||
{
|
{
|
||||||
|
|
|
@ -101,7 +101,6 @@ void Image::Draw()
|
||||||
cb->BindDescriptors(shader, 0);
|
cb->BindDescriptors(shader, 0);
|
||||||
cb->BindDescriptors(shader, 1, _solidColor ? CGI::CSHandle() : _csh);
|
cb->BindDescriptors(shader, 1, _solidColor ? CGI::CSHandle() : _csh);
|
||||||
shader->EndBindDescriptors();
|
shader->EndBindDescriptors();
|
||||||
|
|
||||||
renderer.DrawQuad();
|
renderer.DrawQuad();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,19 +57,17 @@ void Table::Draw()
|
||||||
{
|
{
|
||||||
if (row == _selectedRow)
|
if (row == _selectedRow)
|
||||||
{
|
{
|
||||||
vm.GetUbGui()._matW = Math::QuadMatrix(x, yOffset, w, _rowHeight).UniformBufferFormat();
|
|
||||||
vm.GetUbGuiFS()._color = Vector4(1, 1, 1, 0.25f).GLM();
|
|
||||||
|
|
||||||
auto cb = renderer.GetCommandBuffer();
|
auto cb = renderer.GetCommandBuffer();
|
||||||
auto shader = vm.GetShader();
|
auto shader = vm.GetShader();
|
||||||
|
|
||||||
vm.BindPipeline(ViewManager::PIPE_SOLID_COLOR, cb);
|
vm.GetUbGui()._matW = Math::QuadMatrix(x, yOffset, w, _rowHeight).UniformBufferFormat();
|
||||||
|
vm.GetUbGuiFS()._color = Vector4(1, 1, 1, 0.25f).GLM();
|
||||||
|
|
||||||
|
vm.BindPipeline(ViewManager::PIPE_SOLID_COLOR, cb);
|
||||||
shader->BeginBindDescriptors();
|
shader->BeginBindDescriptors();
|
||||||
cb->BindDescriptors(shader, 0);
|
cb->BindDescriptors(shader, 0);
|
||||||
cb->BindDescriptors(shader, 1);
|
cb->BindDescriptors(shader, 1);
|
||||||
shader->EndBindDescriptors();
|
shader->EndBindDescriptors();
|
||||||
|
|
||||||
renderer.DrawQuad();
|
renderer.DrawQuad();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,7 +176,7 @@ void Table::UpdateRow(int index, int col, CSZ txt, UINT32 color, const void* pUs
|
||||||
|
|
||||||
int Table::AppendRow()
|
int Table::AppendRow()
|
||||||
{
|
{
|
||||||
const int size = _vRows.size();
|
const int size = Utils::Cast32(_vRows.size());
|
||||||
_vRows.resize(size + 1);
|
_vRows.resize(size + 1);
|
||||||
_vRows[size]._vCells.resize(_cols);
|
_vRows[size]._vCells.resize(_cols);
|
||||||
return size;
|
return size;
|
||||||
|
|
|
@ -42,7 +42,7 @@ namespace verus
|
||||||
virtual void InputFocus_Key(int scancode) override;
|
virtual void InputFocus_Key(int scancode) override;
|
||||||
|
|
||||||
void Clear();
|
void Clear();
|
||||||
int GetRowCount() const { return _vRows.size(); }
|
int GetRowCount() const { return Utils::Cast32(_vRows.size()); }
|
||||||
int GetSelectedRow() const { return _selectedRow; }
|
int GetSelectedRow() const { return _selectedRow; }
|
||||||
void SelectRow(int row) { _selectedRow = row; }
|
void SelectRow(int row) { _selectedRow = row; }
|
||||||
void SelectNextRow();
|
void SelectNextRow();
|
||||||
|
|
|
@ -44,20 +44,18 @@ void TextBox::Draw()
|
||||||
PFont pFont = vm.FindFont(GetFont());
|
PFont pFont = vm.FindFont(GetFont());
|
||||||
const float caretX = Font::ToFloatX(pFont->GetTextWidth(_C(GetText())), GetFontScale());
|
const float caretX = Font::ToFloatX(pFont->GetTextWidth(_C(GetText())), GetFontScale());
|
||||||
|
|
||||||
|
auto cb = renderer.GetCommandBuffer();
|
||||||
|
auto shader = vm.GetShader();
|
||||||
|
|
||||||
vm.GetUbGui()._matW = Math::QuadMatrix(x + caretX, y, 0.0015f, GetH()).UniformBufferFormat();
|
vm.GetUbGui()._matW = Math::QuadMatrix(x + caretX, y, 0.0015f, GetH()).UniformBufferFormat();
|
||||||
vm.GetUbGui()._matV = Math::ToUVMatrix(0, 0).UniformBufferFormat();
|
vm.GetUbGui()._matV = Math::ToUVMatrix(0, 0).UniformBufferFormat();
|
||||||
vm.GetUbGuiFS()._color = Vector4(1, 1, 1, 1).GLM();
|
vm.GetUbGuiFS()._color = Vector4(1, 1, 1, 1).GLM();
|
||||||
|
|
||||||
auto cb = renderer.GetCommandBuffer();
|
|
||||||
auto shader = vm.GetShader();
|
|
||||||
|
|
||||||
vm.BindPipeline(ViewManager::PIPE_SOLID_COLOR, cb);
|
vm.BindPipeline(ViewManager::PIPE_SOLID_COLOR, cb);
|
||||||
|
|
||||||
shader->BeginBindDescriptors();
|
shader->BeginBindDescriptors();
|
||||||
cb->BindDescriptors(shader, 0);
|
cb->BindDescriptors(shader, 0);
|
||||||
cb->BindDescriptors(shader, 1);
|
cb->BindDescriptors(shader, 1);
|
||||||
shader->EndBindDescriptors();
|
shader->EndBindDescriptors();
|
||||||
|
|
||||||
renderer.DrawQuad();
|
renderer.DrawQuad();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,7 +65,7 @@ void TextBox::Parse(pugi::xml_node node)
|
||||||
Label::Parse(node);
|
Label::Parse(node);
|
||||||
|
|
||||||
_fullText = _C(GetText());
|
_fullText = _C(GetText());
|
||||||
_cursor = GetText().Length();
|
_cursor = Utils::Cast32(GetText().Length());
|
||||||
|
|
||||||
_maxLength = node.attribute("maxLength").as_int(_maxLength);
|
_maxLength = node.attribute("maxLength").as_int(_maxLength);
|
||||||
|
|
||||||
|
@ -176,7 +174,7 @@ void TextBox::SetText(CWSZ txt)
|
||||||
if (!txt)
|
if (!txt)
|
||||||
return;
|
return;
|
||||||
_fullText = txt;
|
_fullText = txt;
|
||||||
_cursor = _fullText.length();
|
_cursor = Utils::Cast32(_fullText.length());
|
||||||
UpdateLabelText();
|
UpdateLabelText();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,6 +183,6 @@ void TextBox::SetText(CSZ txt)
|
||||||
if (!txt)
|
if (!txt)
|
||||||
return;
|
return;
|
||||||
_fullText = Str::Utf8ToWide(txt);
|
_fullText = Str::Utf8ToWide(txt);
|
||||||
_cursor = _fullText.length();
|
_cursor = Utils::Cast32(_fullText.length());
|
||||||
UpdateLabelText();
|
UpdateLabelText();
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,13 +94,11 @@ void View::Draw()
|
||||||
ubGuiFS._color = Vector4::Replicate(1).GLM();
|
ubGuiFS._color = Vector4::Replicate(1).GLM();
|
||||||
|
|
||||||
vm.BindPipeline(ViewManager::PIPE_MAIN, cb);
|
vm.BindPipeline(ViewManager::PIPE_MAIN, cb);
|
||||||
|
|
||||||
shader->BeginBindDescriptors();
|
shader->BeginBindDescriptors();
|
||||||
cb->BindDescriptors(shader, 0);
|
cb->BindDescriptors(shader, 0);
|
||||||
cb->BindDescriptors(shader, 1, _csh);
|
cb->BindDescriptors(shader, 1, _csh);
|
||||||
shader->EndBindDescriptors();
|
shader->EndBindDescriptors();
|
||||||
|
renderer.DrawQuad(cb.Get());
|
||||||
renderer.DrawQuad(&(*cb));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!GetColor().IsZero())
|
else if (!GetColor().IsZero())
|
||||||
|
@ -112,13 +110,11 @@ void View::Draw()
|
||||||
ubGuiFS._color = GetColor().GLM();
|
ubGuiFS._color = GetColor().GLM();
|
||||||
|
|
||||||
vm.BindPipeline(ViewManager::PIPE_SOLID_COLOR, cb);
|
vm.BindPipeline(ViewManager::PIPE_SOLID_COLOR, cb);
|
||||||
|
|
||||||
shader->BeginBindDescriptors();
|
shader->BeginBindDescriptors();
|
||||||
cb->BindDescriptors(shader, 0);
|
cb->BindDescriptors(shader, 0);
|
||||||
cb->BindDescriptors(shader, 1, vm.GetDefaultComplexSetHandle());
|
cb->BindDescriptors(shader, 1, vm.GetDefaultComplexSetHandle());
|
||||||
shader->EndBindDescriptors();
|
shader->EndBindDescriptors();
|
||||||
|
renderer.DrawQuad(cb.Get());
|
||||||
renderer.DrawQuad(&(*cb));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawWidgets();
|
DrawWidgets();
|
||||||
|
@ -128,17 +124,12 @@ void View::Draw()
|
||||||
vm.GetUbGui()._matW = Transform3::UniformBufferFormatIdentity();
|
vm.GetUbGui()._matW = Transform3::UniformBufferFormatIdentity();
|
||||||
vm.GetUbGuiFS()._color = Vector4(0, 0, 0, _fade.GetValue()).GLM();
|
vm.GetUbGuiFS()._color = Vector4(0, 0, 0, _fade.GetValue()).GLM();
|
||||||
|
|
||||||
auto cb = renderer.GetCommandBuffer();
|
|
||||||
auto shader = vm.GetShader();
|
|
||||||
|
|
||||||
vm.BindPipeline(ViewManager::PIPE_SOLID_COLOR, cb);
|
vm.BindPipeline(ViewManager::PIPE_SOLID_COLOR, cb);
|
||||||
|
|
||||||
shader->BeginBindDescriptors();
|
shader->BeginBindDescriptors();
|
||||||
cb->BindDescriptors(shader, 0);
|
cb->BindDescriptors(shader, 0);
|
||||||
cb->BindDescriptors(shader, 1, vm.GetDefaultComplexSetHandle());
|
cb->BindDescriptors(shader, 1, vm.GetDefaultComplexSetHandle());
|
||||||
shader->EndBindDescriptors();
|
shader->EndBindDescriptors();
|
||||||
|
renderer.DrawQuad(cb.Get());
|
||||||
renderer.DrawQuad(&(*cb));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ WideStr Widget::GetText() const
|
||||||
void Widget::SetText(CWSZ text)
|
void Widget::SetText(CWSZ text)
|
||||||
{
|
{
|
||||||
if (_fixedTextLength)
|
if (_fixedTextLength)
|
||||||
wcsncpy(_vFixedText.data(), text, Math::Min<int>(wcslen(text), _fixedTextLength - 1));
|
wcsncpy(_vFixedText.data(), text, Math::Min<int>(Utils::Cast32(wcslen(text)), _fixedTextLength - 1));
|
||||||
else
|
else
|
||||||
_text = text;
|
_text = text;
|
||||||
}
|
}
|
||||||
|
@ -65,19 +65,17 @@ void Widget::DrawInputStyle()
|
||||||
float x, y;
|
float x, y;
|
||||||
GetAbsolutePosition(x, y);
|
GetAbsolutePosition(x, y);
|
||||||
|
|
||||||
vm.GetUbGui()._matW = Math::QuadMatrix(x, y, GetW(), GetH()).UniformBufferFormat();
|
|
||||||
vm.GetUbGuiFS()._color = Vector4(0, 0, 0, 0.75f * GetColor().getW()).GLM();
|
|
||||||
|
|
||||||
auto cb = renderer.GetCommandBuffer();
|
auto cb = renderer.GetCommandBuffer();
|
||||||
auto shader = vm.GetShader();
|
auto shader = vm.GetShader();
|
||||||
|
|
||||||
vm.BindPipeline(ViewManager::PIPE_SOLID_COLOR, cb);
|
vm.GetUbGui()._matW = Math::QuadMatrix(x, y, GetW(), GetH()).UniformBufferFormat();
|
||||||
|
vm.GetUbGuiFS()._color = Vector4(0, 0, 0, 0.75f * GetColor().getW()).GLM();
|
||||||
|
|
||||||
|
vm.BindPipeline(ViewManager::PIPE_SOLID_COLOR, cb);
|
||||||
shader->BeginBindDescriptors();
|
shader->BeginBindDescriptors();
|
||||||
cb->BindDescriptors(shader, 0);
|
cb->BindDescriptors(shader, 0);
|
||||||
cb->BindDescriptors(shader, 1);
|
cb->BindDescriptors(shader, 1);
|
||||||
shader->EndBindDescriptors();
|
shader->EndBindDescriptors();
|
||||||
|
|
||||||
renderer.DrawQuad();
|
renderer.DrawQuad();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -290,13 +290,14 @@ void BaseCharacter::ComputeThirdPersonCameraArgs(RcVector3 offset, RPoint3 eye,
|
||||||
Point3 point;
|
Point3 point;
|
||||||
Vector3 norm;
|
Vector3 norm;
|
||||||
|
|
||||||
|
const RcVector3 offsetW = GetYawMatrix() * offset;
|
||||||
const Point3 pos = _smoothPosition;
|
const Point3 pos = _smoothPosition;
|
||||||
const float startAt = _cc.GetRadius() + _cc.GetHeight() * 0.5f; // Inside capsule.
|
const float startAt = _cc.GetRadius() + _cc.GetHeight() * 0.5f; // Inside capsule.
|
||||||
const Point3 origin = pos + Vector3(0, startAt, 0);
|
const Point3 origin = pos + Vector3(0, startAt, 0);
|
||||||
at = pos + GetYawMatrix() * offset;
|
at = pos + offsetW;
|
||||||
if (sm.RayCastingTest(origin, at, nullptr, &point, &norm, &r))
|
if (sm.RayCastingTest(origin, at, nullptr, &point, &norm, &r))
|
||||||
at = point + norm * r;
|
at = point + norm * r;
|
||||||
eye = at - GetFrontDirection() * _cameraRadius.GetValue();
|
eye = at - GetFrontDirection() * _cameraRadius.GetValue() + offsetW * 0.05f;
|
||||||
}
|
}
|
||||||
|
|
||||||
float BaseCharacter::ComputeThirdPersonCamera(Scene::RCamera camera, Anim::RcOrbit orbit, RcVector3 offset)
|
float BaseCharacter::ComputeThirdPersonCamera(Scene::RCamera camera, Anim::RcOrbit orbit, RcVector3 offset)
|
||||||
|
|
|
@ -87,7 +87,7 @@ void EngineInit::Init(Input::PKeyMapperDelegate pKeyMapperDelegate, CGI::Rendere
|
||||||
Scene::Mesh::InitStatic();
|
Scene::Mesh::InitStatic();
|
||||||
Scene::Terrain::InitStatic();
|
Scene::Terrain::InitStatic();
|
||||||
Scene::Grass::InitStatic();
|
Scene::Grass::InitStatic();
|
||||||
//Scene::CForest::InitStatic();
|
Scene::Forest::InitStatic();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helpers:
|
// Helpers:
|
||||||
|
|
|
@ -8,13 +8,10 @@
|
||||||
#define VERUS_QREF_BULLET Physics::RBullet bullet = Physics::Bullet::I()
|
#define VERUS_QREF_BULLET Physics::RBullet bullet = Physics::Bullet::I()
|
||||||
#define VERUS_QREF_CONST_SETTINGS App::RcSettings settings = App::Settings::IConst()
|
#define VERUS_QREF_CONST_SETTINGS App::RcSettings settings = App::Settings::IConst()
|
||||||
#define VERUS_QREF_DD CGI::RDebugDraw dd = CGI::DebugDraw::I()
|
#define VERUS_QREF_DD CGI::RDebugDraw dd = CGI::DebugDraw::I()
|
||||||
#define VERUS_QREF_DEPTH Effects::RDepth depth = Effects::Depth::I()
|
|
||||||
#define VERUS_QREF_FSYS IO::RFileSystem fsys = IO::FileSystem::I()
|
#define VERUS_QREF_FSYS IO::RFileSystem fsys = IO::FileSystem::I()
|
||||||
#define VERUS_QREF_GAME Game::RGame game = Game::Game::I()
|
|
||||||
#define VERUS_QREF_GRASS Scene::RGrass grass = Scene::Grass::I()
|
#define VERUS_QREF_GRASS Scene::RGrass grass = Scene::Grass::I()
|
||||||
#define VERUS_QREF_HELPERS Scene::RHelpers helpers = Scene::Helpers::I()
|
#define VERUS_QREF_HELPERS Scene::RHelpers helpers = Scene::Helpers::I()
|
||||||
#define VERUS_QREF_KM Input::RKeyMapper km = Input::KeyMapper::I()
|
#define VERUS_QREF_KM Input::RKeyMapper km = Input::KeyMapper::I()
|
||||||
#define VERUS_QREF_LS Scene::RLandscape ls = Scene::Landscape::I()
|
|
||||||
#define VERUS_QREF_MM Scene::RMaterialManager mm = Scene::MaterialManager::I()
|
#define VERUS_QREF_MM Scene::RMaterialManager mm = Scene::MaterialManager::I()
|
||||||
#define VERUS_QREF_MP Net::RMultiplayer mp = Net::Multiplayer::I()
|
#define VERUS_QREF_MP Net::RMultiplayer mp = Net::Multiplayer::I()
|
||||||
#define VERUS_QREF_PHYSICS Physics::RPhysics physics = Physics::Physics::I()
|
#define VERUS_QREF_PHYSICS Physics::RPhysics physics = Physics::Physics::I()
|
||||||
|
|
|
@ -185,18 +185,25 @@ namespace verus
|
||||||
bool operator==(const Ptr<T>& that) const { return _p == that._p; }
|
bool operator==(const Ptr<T>& that) const { return _p == that._p; }
|
||||||
bool operator!=(const Ptr<T>& that) const { return _p != that._p; }
|
bool operator!=(const Ptr<T>& that) const { return _p != that._p; }
|
||||||
bool operator<(const Ptr<T>& that) const { return _p < that._p; }
|
bool operator<(const Ptr<T>& that) const { return _p < that._p; }
|
||||||
|
|
||||||
T* Attach(T* ptr)
|
T* Attach(T* ptr)
|
||||||
{
|
{
|
||||||
T* p = _p;
|
T* p = _p;
|
||||||
_p = ptr;
|
_p = ptr;
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
T* Detach()
|
T* Detach()
|
||||||
{
|
{
|
||||||
T* p = _p;
|
T* p = _p;
|
||||||
_p = nullptr;
|
_p = nullptr;
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
T* Get() const
|
||||||
|
{
|
||||||
|
return _p;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T, int COUNT>
|
template<typename T, int COUNT>
|
||||||
|
|
|
@ -146,6 +146,21 @@ String Str::GetFilename(CSZ pathname)
|
||||||
return pathname;
|
return pathname;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String Str::ToPakFriendlyUrl(CSZ url)
|
||||||
|
{
|
||||||
|
if (!url || !url[0] || url[0] != '[')
|
||||||
|
return url;
|
||||||
|
String ret(url + 1);
|
||||||
|
const size_t pos = ret.find("]:");
|
||||||
|
if (pos != String::npos)
|
||||||
|
{
|
||||||
|
ret.replace(pos, 2, "-");
|
||||||
|
ReplaceAll(ret, "/", ".");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
String Str::FromInt(int n)
|
String Str::FromInt(int n)
|
||||||
{
|
{
|
||||||
StringStream ss;
|
StringStream ss;
|
||||||
|
|
|
@ -39,6 +39,7 @@ namespace verus
|
||||||
static void ReplaceFilename(RString pathname, CSZ filename);
|
static void ReplaceFilename(RString pathname, CSZ filename);
|
||||||
static String GetPath(CSZ pathname);
|
static String GetPath(CSZ pathname);
|
||||||
static String GetFilename(CSZ pathname);
|
static String GetFilename(CSZ pathname);
|
||||||
|
static String ToPakFriendlyUrl(CSZ url);
|
||||||
static String FromInt(int n);
|
static String FromInt(int n);
|
||||||
static void Explode(CSZ s, CSZ delimiter, Vector<String>& pieces);
|
static void Explode(CSZ s, CSZ delimiter, Vector<String>& pieces);
|
||||||
static void Trim(RString s);
|
static void Trim(RString s);
|
||||||
|
|
|
@ -389,25 +389,24 @@ String FileSystem::ConvertFilenameToPassword(CSZ fileEntry)
|
||||||
|
|
||||||
bool FileSystem::FileExist(CSZ url)
|
bool FileSystem::FileExist(CSZ url)
|
||||||
{
|
{
|
||||||
String path(url), pak, projectPathname;
|
String pathname(url), pakPathname, projectPathname;
|
||||||
const size_t pakPos = FindPosForPAK(url);
|
const size_t pakPos = FindPosForPAK(url);
|
||||||
if (pakPos != String::npos)
|
if (pakPos != String::npos)
|
||||||
{
|
{
|
||||||
StringStream ssPak;
|
const String dataFolder(s_dataFolder);
|
||||||
ssPak << _C(Utils::I().GetModulePath()) << s_dataFolder << path.substr(0, pakPos) << ".pak";
|
const String pakFilename = pathname.substr(1, pakPos - 1);
|
||||||
pak = ssPak.str();
|
|
||||||
|
|
||||||
path.replace(pakPos, 1, "/");
|
pakPathname = _C(Utils::I().GetModulePath()) + dataFolder + pakFilename + ".pak";
|
||||||
projectPathname = String(_C(Utils::I().GetProjectPath())) + "/" + path;
|
|
||||||
|
|
||||||
StringStream ss;
|
pathname = pakFilename + '/' + pathname.substr(pakPos + 2);
|
||||||
ss << _C(Utils::I().GetModulePath()) << s_dataFolder << path;
|
projectPathname = _C(Utils::I().GetProjectPath()) + dataFolder + pathname;
|
||||||
path = ss.str();
|
|
||||||
|
pathname = _C(Utils::I().GetModulePath()) + dataFolder + pathname;
|
||||||
}
|
}
|
||||||
File file;
|
File file;
|
||||||
if (file.Open(_C(path))) // Normal filename:
|
if (file.Open(_C(pathname))) // Normal filename:
|
||||||
return true;
|
return true;
|
||||||
if (file.Open(_C(pak))) // PAK filename:
|
if (file.Open(_C(pakPathname))) // PAK filename:
|
||||||
return true;
|
return true;
|
||||||
if (file.Open(_C(projectPathname))) // File in another project dir:
|
if (file.Open(_C(projectPathname))) // File in another project dir:
|
||||||
return true;
|
return true;
|
||||||
|
@ -430,7 +429,7 @@ String FileSystem::ConvertAbsolutePathToRelative(RcString path)
|
||||||
const size_t data = path.rfind("\\Data\\");
|
const size_t data = path.rfind("\\Data\\");
|
||||||
if (data != String::npos)
|
if (data != String::npos)
|
||||||
{
|
{
|
||||||
s = "[" + path.substr(data + 6);
|
s = '[' + path.substr(data + 6);
|
||||||
const size_t colon = s.find('\\');
|
const size_t colon = s.find('\\');
|
||||||
if (colon != String::npos)
|
if (colon != String::npos)
|
||||||
s.replace(colon, 1, "]:");
|
s.replace(colon, 1, "]:");
|
||||||
|
@ -442,14 +441,15 @@ String FileSystem::ConvertAbsolutePathToRelative(RcString path)
|
||||||
String FileSystem::ConvertRelativePathToAbsolute(RcString path, bool useProjectDir)
|
String FileSystem::ConvertRelativePathToAbsolute(RcString path, bool useProjectDir)
|
||||||
{
|
{
|
||||||
VERUS_QREF_UTILS;
|
VERUS_QREF_UTILS;
|
||||||
String systemPath = path;
|
const String dataFolder(s_dataFolder);
|
||||||
|
String systemPath = path.substr(1);
|
||||||
const size_t colon = systemPath.find(':');
|
const size_t colon = systemPath.find(':');
|
||||||
if (colon != String::npos)
|
if (colon != String::npos && colon > 0)
|
||||||
systemPath[colon] = '/';
|
systemPath = systemPath.substr(0, colon - 1) + '/' + systemPath.substr(colon + 1);
|
||||||
if (useProjectDir && *_C(utils.GetProjectPath()))
|
if (useProjectDir && !utils.GetProjectPath().IsEmpty())
|
||||||
systemPath = String(_C(utils.GetProjectPath())) + "/" + systemPath;
|
systemPath = _C(utils.GetProjectPath()) + dataFolder + systemPath;
|
||||||
else
|
else
|
||||||
systemPath = String(_C(utils.GetModulePath())) + s_dataFolder + systemPath;
|
systemPath = _C(utils.GetModulePath()) + dataFolder + systemPath;
|
||||||
return systemPath;
|
return systemPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -472,7 +472,6 @@ String FileSystem::ReplaceFilename(CSZ pathname, CSZ filename)
|
||||||
return filename;
|
return filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
void FileSystem::SaveImage(CSZ pathname, const UINT32* p, int w, int h, bool upsideDown, ILenum type)
|
void FileSystem::SaveImage(CSZ pathname, const UINT32* p, int w, int h, bool upsideDown, ILenum type)
|
||||||
{
|
{
|
||||||
struct RAII
|
struct RAII
|
||||||
|
@ -511,7 +510,6 @@ void FileSystem::SaveImage(CSZ pathname, const UINT32* p, int w, int h, bool ups
|
||||||
else
|
else
|
||||||
throw VERUS_RUNTIME_ERROR << "SaveImage(), Open()";
|
throw VERUS_RUNTIME_ERROR << "SaveImage(), Open()";
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
void FileSystem::SaveDDS(CSZ pathname, const UINT32* p, int w, int h, int d)
|
void FileSystem::SaveDDS(CSZ pathname, const UINT32* p, int w, int h, int d)
|
||||||
{
|
{
|
||||||
|
|
|
@ -57,9 +57,9 @@ namespace verus
|
||||||
static String ReplaceFilename(CSZ pathname, CSZ filename);
|
static String ReplaceFilename(CSZ pathname, CSZ filename);
|
||||||
|
|
||||||
// Save data:
|
// Save data:
|
||||||
//static void SaveImage /**/(CSZ pathname, const UINT32* p, int w, int h, bool upsideDown = false, ILenum type = IL_PSD);
|
static void SaveImage /**/(CSZ pathname, const UINT32* p, int w, int h, bool upsideDown = false, ILenum type = IL_PSD);
|
||||||
static void SaveDDS /**/(CSZ pathname, const UINT32* p, int w, int h, int d = 0);
|
static void SaveDDS /**/(CSZ pathname, const UINT32* p, int w, int h, int d = 0);
|
||||||
static void SaveString /**/(CSZ pathname, CSZ s);
|
static void SaveString/**/(CSZ pathname, CSZ s);
|
||||||
};
|
};
|
||||||
VERUS_TYPEDEFS(FileSystem);
|
VERUS_TYPEDEFS(FileSystem);
|
||||||
|
|
||||||
|
|
|
@ -23,29 +23,29 @@ bool Octree::Node::HasChildren(int currentNode, int nodeCount)
|
||||||
return GetChildIndex(currentNode, 7) < nodeCount;
|
return GetChildIndex(currentNode, 7) < nodeCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Octree::Node::BindEntity(RcEntity entity)
|
void Octree::Node::BindClient(RcClient client)
|
||||||
{
|
{
|
||||||
_vEntities.push_back(entity);
|
_vClients.push_back(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Octree::Node::UnbindEntity(void* pToken)
|
void Octree::Node::UnbindClient(void* pToken)
|
||||||
{
|
{
|
||||||
VERUS_WHILE(Vector<Entity>, _vEntities, it)
|
VERUS_WHILE(Vector<Client>, _vClients, it)
|
||||||
{
|
{
|
||||||
if (pToken == (*it)._pToken)
|
if (pToken == (*it)._pToken)
|
||||||
it = _vEntities.erase(it);
|
it = _vClients.erase(it);
|
||||||
else
|
else
|
||||||
it++;
|
it++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Octree::Node::UpdateDynamicEntity(RcEntity entity)
|
void Octree::Node::UpdateDynamicClient(RcClient client)
|
||||||
{
|
{
|
||||||
for (auto& o : _vEntities)
|
for (auto& o : _vClients)
|
||||||
{
|
{
|
||||||
if (o._pToken == entity._pToken)
|
if (o._pToken == client._pToken)
|
||||||
{
|
{
|
||||||
o = entity;
|
o = client;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -135,25 +135,25 @@ void Octree::Build(int currentNode, int depth)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Octree::BindEntity(RcEntity entity, bool forceRoot, int currentNode)
|
bool Octree::BindClient(RcClient client, bool forceRoot, int currentNode)
|
||||||
{
|
{
|
||||||
if (!currentNode)
|
if (!currentNode)
|
||||||
{
|
{
|
||||||
if (_vNodes.empty())
|
if (_vNodes.empty())
|
||||||
return false; // Octree is not ready.
|
return false; // Octree is not ready.
|
||||||
UnbindEntity(entity._pToken);
|
UnbindClient(client._pToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
Entity entityEx = entity;
|
Client clientEx = client;
|
||||||
if (forceRoot)
|
if (forceRoot)
|
||||||
{
|
{
|
||||||
entityEx._bounds = _vNodes[currentNode].GetBounds();
|
clientEx._bounds = _vNodes[currentNode].GetBounds();
|
||||||
entityEx._sphere = entityEx._bounds.GetSphere();
|
clientEx._sphere = clientEx._bounds.GetSphere();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MustBind(currentNode, entityEx._bounds))
|
if (MustBind(currentNode, clientEx._bounds))
|
||||||
{
|
{
|
||||||
_vNodes[currentNode].BindEntity(entityEx);
|
_vNodes[currentNode].BindClient(clientEx);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (Node::HasChildren(currentNode, Utils::Cast32(_vNodes.size())))
|
else if (Node::HasChildren(currentNode, Utils::Cast32(_vNodes.size())))
|
||||||
|
@ -161,25 +161,25 @@ bool Octree::BindEntity(RcEntity entity, bool forceRoot, int currentNode)
|
||||||
VERUS_FOR(i, 8)
|
VERUS_FOR(i, 8)
|
||||||
{
|
{
|
||||||
const int childIndex = Node::GetChildIndex(currentNode, i);
|
const int childIndex = Node::GetChildIndex(currentNode, i);
|
||||||
if (BindEntity(entity, false, childIndex))
|
if (BindClient(client, false, childIndex))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Octree::UnbindEntity(void* pToken)
|
void Octree::UnbindClient(void* pToken)
|
||||||
{
|
{
|
||||||
for (auto& node : _vNodes)
|
for (auto& node : _vNodes)
|
||||||
node.UnbindEntity(pToken);
|
node.UnbindClient(pToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Octree::UpdateDynamicBounds(RcEntity entity)
|
void Octree::UpdateDynamicBounds(RcClient client)
|
||||||
{
|
{
|
||||||
if (_vNodes.empty())
|
if (_vNodes.empty())
|
||||||
return; // Octree is not ready.
|
return; // Octree is not ready.
|
||||||
|
|
||||||
_vNodes[0].UpdateDynamicEntity(entity);
|
_vNodes[0].UpdateDynamicClient(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Octree::MustBind(int currentNode, RcBounds bounds) const
|
bool Octree::MustBind(int currentNode, RcBounds bounds) const
|
||||||
|
@ -200,13 +200,16 @@ bool Octree::MustBind(int currentNode, RcBounds bounds) const
|
||||||
return _vNodes[currentNode].GetBounds().IsOverlappingWith(bounds);
|
return _vNodes[currentNode].GetBounds().IsOverlappingWith(bounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
Continue Octree::TraverseProper(RcFrustum frustum, PResult pResult, int currentNode, void* pUser)
|
Continue Octree::TraverseVisible(RcFrustum frustum, PResult pResult, int currentNode, void* pUser)
|
||||||
{
|
{
|
||||||
if (_vNodes.empty())
|
if (_vNodes.empty())
|
||||||
return Continue::no;
|
return Continue::no;
|
||||||
|
|
||||||
if (!currentNode)
|
if (!currentNode)
|
||||||
{
|
{
|
||||||
|
_defaultResult = Result();
|
||||||
|
if (!pResult)
|
||||||
|
pResult = &_defaultResult;
|
||||||
pResult->_testCount = 0;
|
pResult->_testCount = 0;
|
||||||
pResult->_passedTestCount = 0;
|
pResult->_passedTestCount = 0;
|
||||||
pResult->_pLastFoundToken = nullptr;
|
pResult->_pLastFoundToken = nullptr;
|
||||||
|
@ -225,22 +228,22 @@ Continue Octree::TraverseProper(RcFrustum frustum, PResult pResult, int currentN
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
RcNode node = _vNodes[currentNode];
|
RcNode node = _vNodes[currentNode];
|
||||||
const int count = node.GetEntityCount();
|
const int count = node.GetClientCount();
|
||||||
VERUS_FOR(i, count)
|
VERUS_FOR(i, count)
|
||||||
{
|
{
|
||||||
RcEntity entity = node.GetEntityAt(i);
|
RcClient client = node.GetClientAt(i);
|
||||||
|
|
||||||
pResult->_testCount++;
|
pResult->_testCount++;
|
||||||
const float onePixel = Math::ComputeOnePixelDistance(
|
const float onePixel = Math::ComputeOnePixelDistance(
|
||||||
entity._sphere.GetRadius());
|
client._sphere.GetRadius());
|
||||||
const bool notTooSmall = pResult->_depth || VMath::distSqr(
|
const bool notTooSmall = pResult->_depth || VMath::distSqr(
|
||||||
frustum.GetEyePosition(), entity._sphere.GetCenter()) < onePixel * onePixel;
|
frustum.GetEyePosition(), client._sphere.GetCenter()) < onePixel * onePixel;
|
||||||
|
|
||||||
if (notTooSmall &&
|
if (notTooSmall &&
|
||||||
Relation::outside != frustum.ContainsSphere(entity._sphere) &&
|
Relation::outside != frustum.ContainsSphere(client._sphere) &&
|
||||||
Relation::outside != frustum.ContainsAabb(entity._bounds))
|
Relation::outside != frustum.ContainsAabb(client._bounds))
|
||||||
{
|
{
|
||||||
pResult->_pLastFoundToken = entity._pToken;
|
pResult->_pLastFoundToken = client._pToken;
|
||||||
pResult->_passedTestCount++;
|
pResult->_passedTestCount++;
|
||||||
if (Continue::no == _pDelegate->Octree_ProcessNode(pResult->_pLastFoundToken, pUser))
|
if (Continue::no == _pDelegate->Octree_ProcessNode(pResult->_pLastFoundToken, pUser))
|
||||||
return Continue::no;
|
return Continue::no;
|
||||||
|
@ -253,7 +256,7 @@ Continue Octree::TraverseProper(RcFrustum frustum, PResult pResult, int currentN
|
||||||
VERUS_FOR(i, 8)
|
VERUS_FOR(i, 8)
|
||||||
{
|
{
|
||||||
const int childIndex = Node::GetChildIndex(currentNode, i);
|
const int childIndex = Node::GetChildIndex(currentNode, i);
|
||||||
if (Continue::no == TraverseProper(frustum, pResult, childIndex, pUser))
|
if (Continue::no == TraverseVisible(frustum, pResult, childIndex, pUser))
|
||||||
return Continue::no;
|
return Continue::no;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -261,13 +264,16 @@ Continue Octree::TraverseProper(RcFrustum frustum, PResult pResult, int currentN
|
||||||
return Continue::yes;
|
return Continue::yes;
|
||||||
}
|
}
|
||||||
|
|
||||||
Continue Octree::TraverseProper(RcPoint3 point, PResult pResult, int currentNode, void* pUser)
|
Continue Octree::TraverseVisible(RcPoint3 point, PResult pResult, int currentNode, void* pUser)
|
||||||
{
|
{
|
||||||
if (_vNodes.empty())
|
if (_vNodes.empty())
|
||||||
return Continue::no;
|
return Continue::no;
|
||||||
|
|
||||||
if (!currentNode)
|
if (!currentNode)
|
||||||
{
|
{
|
||||||
|
_defaultResult = Result();
|
||||||
|
if (!pResult)
|
||||||
|
pResult = &_defaultResult;
|
||||||
pResult->_testCount = 0;
|
pResult->_testCount = 0;
|
||||||
pResult->_passedTestCount = 0;
|
pResult->_passedTestCount = 0;
|
||||||
pResult->_pLastFoundToken = nullptr;
|
pResult->_pLastFoundToken = nullptr;
|
||||||
|
@ -278,14 +284,14 @@ Continue Octree::TraverseProper(RcPoint3 point, PResult pResult, int currentNode
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
RcNode node = _vNodes[currentNode];
|
RcNode node = _vNodes[currentNode];
|
||||||
const int count = node.GetEntityCount();
|
const int count = node.GetClientCount();
|
||||||
VERUS_FOR(i, count)
|
VERUS_FOR(i, count)
|
||||||
{
|
{
|
||||||
RcEntity entity = node.GetEntityAt(i);
|
RcClient client = node.GetClientAt(i);
|
||||||
pResult->_testCount++;
|
pResult->_testCount++;
|
||||||
if (entity._bounds.IsInside(point))
|
if (client._bounds.IsInside(point))
|
||||||
{
|
{
|
||||||
pResult->_pLastFoundToken = entity._pToken;
|
pResult->_pLastFoundToken = client._pToken;
|
||||||
pResult->_passedTestCount++;
|
pResult->_passedTestCount++;
|
||||||
if (Continue::no == _pDelegate->Octree_ProcessNode(pResult->_pLastFoundToken, pUser))
|
if (Continue::no == _pDelegate->Octree_ProcessNode(pResult->_pLastFoundToken, pUser))
|
||||||
return Continue::no;
|
return Continue::no;
|
||||||
|
@ -300,7 +306,7 @@ Continue Octree::TraverseProper(RcPoint3 point, PResult pResult, int currentNode
|
||||||
VERUS_FOR(i, 8)
|
VERUS_FOR(i, 8)
|
||||||
{
|
{
|
||||||
const int childIndex = Node::GetChildIndex(currentNode, remapped[i]);
|
const int childIndex = Node::GetChildIndex(currentNode, remapped[i]);
|
||||||
if (Continue::no == TraverseProper(point, pResult, childIndex, pUser))
|
if (Continue::no == TraverseVisible(point, pResult, childIndex, pUser))
|
||||||
return Continue::no;
|
return Continue::no;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,28 +14,38 @@ namespace verus
|
||||||
class Octree : public Object
|
class Octree : public Object
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
class Entity
|
class Client
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Bounds _bounds;
|
Bounds _bounds;
|
||||||
Sphere _sphere;
|
Sphere _sphere;
|
||||||
void* _pToken = nullptr;
|
void* _pToken = nullptr;
|
||||||
|
|
||||||
Entity() {}
|
Client() {}
|
||||||
Entity(RcBounds bounds, void* pToken) :
|
Client(RcBounds bounds, void* pToken) :
|
||||||
_bounds(bounds), _pToken(pToken)
|
_bounds(bounds), _pToken(pToken)
|
||||||
{
|
{
|
||||||
_sphere = _bounds.GetSphere();
|
_sphere = _bounds.GetSphere();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
VERUS_TYPEDEFS(Entity);
|
VERUS_TYPEDEFS(Client);
|
||||||
|
|
||||||
|
class Result
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void* _pLastFoundToken = nullptr;
|
||||||
|
int _testCount = 0;
|
||||||
|
int _passedTestCount = 0;
|
||||||
|
bool _depth = false;
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(Result);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class Node : public AllocatorAware
|
class Node : public AllocatorAware
|
||||||
{
|
{
|
||||||
Bounds _bounds;
|
Bounds _bounds;
|
||||||
Sphere _sphere;
|
Sphere _sphere;
|
||||||
Vector<Entity> _vEntities;
|
Vector<Client> _vClients;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Node();
|
Node();
|
||||||
|
@ -48,12 +58,12 @@ namespace verus
|
||||||
RcBounds GetBounds() const { return _bounds; }
|
RcBounds GetBounds() const { return _bounds; }
|
||||||
void SetBounds(RcBounds b) { _bounds = b; _sphere = b.GetSphere(); }
|
void SetBounds(RcBounds b) { _bounds = b; _sphere = b.GetSphere(); }
|
||||||
|
|
||||||
void BindEntity(RcEntity entity);
|
void BindClient(RcClient client);
|
||||||
void UnbindEntity(void* pToken);
|
void UnbindClient(void* pToken);
|
||||||
void UpdateDynamicEntity(RcEntity entity);
|
void UpdateDynamicClient(RcClient client);
|
||||||
|
|
||||||
int GetEntityCount() const { return Utils::Cast32(_vEntities.size()); }
|
int GetClientCount() const { return Utils::Cast32(_vClients.size()); }
|
||||||
RcEntity GetEntityAt(int i) const { return _vEntities[i]; }
|
RcClient GetClientAt(int i) const { return _vClients[i]; }
|
||||||
};
|
};
|
||||||
VERUS_TYPEDEFS(Node);
|
VERUS_TYPEDEFS(Node);
|
||||||
|
|
||||||
|
@ -61,18 +71,9 @@ namespace verus
|
||||||
Vector3 _limit = Vector3(0);
|
Vector3 _limit = Vector3(0);
|
||||||
Vector<Node> _vNodes;
|
Vector<Node> _vNodes;
|
||||||
POctreeDelegate _pDelegate = nullptr;
|
POctreeDelegate _pDelegate = nullptr;
|
||||||
|
Result _defaultResult;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
class Result
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void* _pLastFoundToken = nullptr;
|
|
||||||
int _testCount = 0;
|
|
||||||
int _passedTestCount = 0;
|
|
||||||
bool _depth = false;
|
|
||||||
};
|
|
||||||
VERUS_TYPEDEFS(Result);
|
|
||||||
|
|
||||||
Octree();
|
Octree();
|
||||||
~Octree();
|
~Octree();
|
||||||
|
|
||||||
|
@ -83,13 +84,13 @@ namespace verus
|
||||||
|
|
||||||
VERUS_P(void Build(int currentNode = 0, int depth = 0));
|
VERUS_P(void Build(int currentNode = 0, int depth = 0));
|
||||||
|
|
||||||
bool BindEntity(RcEntity entity, bool forceRoot = false, int currentNode = 0);
|
bool BindClient(RcClient client, bool forceRoot = false, int currentNode = 0);
|
||||||
void UnbindEntity(void* pToken);
|
void UnbindClient(void* pToken);
|
||||||
void UpdateDynamicBounds(RcEntity entity);
|
void UpdateDynamicBounds(RcClient client);
|
||||||
VERUS_P(bool MustBind(int currentNode, RcBounds bounds) const);
|
VERUS_P(bool MustBind(int currentNode, RcBounds bounds) const);
|
||||||
|
|
||||||
Continue TraverseProper(RcFrustum frustum, PResult pResult = nullptr, int currentNode = 0, void* pUser = nullptr);
|
Continue TraverseVisible(RcFrustum frustum, PResult pResult = nullptr, int currentNode = 0, void* pUser = nullptr);
|
||||||
Continue TraverseProper(RcPoint3 point, PResult pResult = nullptr, int currentNode = 0, void* pUser = nullptr);
|
Continue TraverseVisible(RcPoint3 point, PResult pResult = nullptr, int currentNode = 0, void* pUser = nullptr);
|
||||||
|
|
||||||
VERUS_P(static void RemapChildIndices(RcPoint3 point, RcPoint3 center, BYTE childIndices[8]));
|
VERUS_P(static void RemapChildIndices(RcPoint3 point, RcPoint3 center, BYTE childIndices[8]));
|
||||||
|
|
||||||
|
|
|
@ -15,17 +15,17 @@ Quadtree::Node::~Node()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void Quadtree::Node::BindEntity(RcEntity entity)
|
void Quadtree::Node::BindClient(RcClient client)
|
||||||
{
|
{
|
||||||
_vEntities.push_back(entity);
|
_vClients.push_back(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Quadtree::Node::UnbindEntity(int index)
|
void Quadtree::Node::UnbindClient(int index)
|
||||||
{
|
{
|
||||||
VERUS_WHILE(Vector<Entity>, _vEntities, it)
|
VERUS_WHILE(Vector<Client>, _vClients, it)
|
||||||
{
|
{
|
||||||
if (index == (*it)._userIndex)
|
if (index == (*it)._userIndex)
|
||||||
it = _vEntities.erase(it);
|
it = _vClients.erase(it);
|
||||||
else
|
else
|
||||||
it++;
|
it++;
|
||||||
}
|
}
|
||||||
|
@ -110,22 +110,22 @@ void Quadtree::Build(int currentNode, int level)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Quadtree::BindEntity(RcEntity entity, bool forceRoot, int currentNode)
|
bool Quadtree::BindClient(RcClient client, bool forceRoot, int currentNode)
|
||||||
{
|
{
|
||||||
if (!currentNode)
|
if (!currentNode)
|
||||||
{
|
{
|
||||||
if (_vNodes.empty())
|
if (_vNodes.empty())
|
||||||
return false; // Quadtree is not ready.
|
return false; // Quadtree is not ready.
|
||||||
UnbindEntity(entity._userIndex);
|
UnbindClient(client._userIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
Entity entityEx = entity;
|
Client clientEx = client;
|
||||||
if (forceRoot)
|
if (forceRoot)
|
||||||
entityEx._bounds = _vNodes[currentNode].GetBounds();
|
clientEx._bounds = _vNodes[currentNode].GetBounds();
|
||||||
|
|
||||||
if (MustBind(currentNode, entityEx._bounds))
|
if (MustBind(currentNode, clientEx._bounds))
|
||||||
{
|
{
|
||||||
_vNodes[currentNode].BindEntity(entityEx);
|
_vNodes[currentNode].BindClient(clientEx);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -135,7 +135,7 @@ bool Quadtree::BindEntity(RcEntity entity, bool forceRoot, int currentNode)
|
||||||
const int index = _vNodes[currentNode].GetChildIndex(i);
|
const int index = _vNodes[currentNode].GetChildIndex(i);
|
||||||
if (index >= 0)
|
if (index >= 0)
|
||||||
{
|
{
|
||||||
if (BindEntity(entity, false, index))
|
if (BindClient(client, false, index))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -143,10 +143,10 @@ bool Quadtree::BindEntity(RcEntity entity, bool forceRoot, int currentNode)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Quadtree::UnbindEntity(int index)
|
void Quadtree::UnbindClient(int index)
|
||||||
{
|
{
|
||||||
VERUS_FOREACH(Vector<Node>, _vNodes, it)
|
VERUS_FOREACH(Vector<Node>, _vNodes, it)
|
||||||
(*it).UnbindEntity(index);
|
(*it).UnbindClient(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Quadtree::MustBind(int currentNode, RcBounds bounds) const
|
bool Quadtree::MustBind(int currentNode, RcBounds bounds) const
|
||||||
|
@ -168,7 +168,7 @@ bool Quadtree::MustBind(int currentNode, RcBounds bounds) const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Continue Quadtree::TraverseProper(RcPoint3 point, PResult pResult, int currentNode, void* pUser) const
|
Continue Quadtree::TraverseVisible(RcPoint3 point, PResult pResult, int currentNode, void* pUser) const
|
||||||
{
|
{
|
||||||
if (_vNodes.empty())
|
if (_vNodes.empty())
|
||||||
return Continue::no;
|
return Continue::no;
|
||||||
|
@ -186,14 +186,14 @@ Continue Quadtree::TraverseProper(RcPoint3 point, PResult pResult, int currentNo
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
RcNode node = _vNodes[currentNode];
|
RcNode node = _vNodes[currentNode];
|
||||||
const int count = node.GetEntityCount();
|
const int count = node.GetClientCount();
|
||||||
VERUS_FOR(i, count)
|
VERUS_FOR(i, count)
|
||||||
{
|
{
|
||||||
RcEntity entity = node.GetEntityAt(i);
|
RcClient client = node.GetClientAt(i);
|
||||||
pResult->_testCount++;
|
pResult->_testCount++;
|
||||||
if (entity._bounds.IsInside2D(point))
|
if (client._bounds.IsInside2D(point))
|
||||||
{
|
{
|
||||||
pResult->_lastFoundIndex = entity._userIndex;
|
pResult->_lastFoundIndex = client._userIndex;
|
||||||
pResult->_passedTestCount++;
|
pResult->_passedTestCount++;
|
||||||
if (Continue::no == _pDelegate->Quadtree_ProcessNode(pResult->_lastFoundIndex, pUser))
|
if (Continue::no == _pDelegate->Quadtree_ProcessNode(pResult->_lastFoundIndex, pUser))
|
||||||
return Continue::no;
|
return Continue::no;
|
||||||
|
@ -208,7 +208,7 @@ Continue Quadtree::TraverseProper(RcPoint3 point, PResult pResult, int currentNo
|
||||||
const int index = _vNodes[currentNode].GetChildIndex(childIndices[i]);
|
const int index = _vNodes[currentNode].GetChildIndex(childIndices[i]);
|
||||||
if (index >= 0)
|
if (index >= 0)
|
||||||
{
|
{
|
||||||
if (Continue::no == TraverseProper(point, pResult, index, pUser))
|
if (Continue::no == TraverseVisible(point, pResult, index, pUser))
|
||||||
return Continue::no;
|
return Continue::no;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,23 +14,23 @@ namespace verus
|
||||||
class Quadtree : public Object
|
class Quadtree : public Object
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
class Entity
|
class Client
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Bounds _bounds;
|
Bounds _bounds;
|
||||||
int _userIndex;
|
int _userIndex;
|
||||||
|
|
||||||
Entity() {}
|
Client() {}
|
||||||
Entity(RcBounds bounds, int index) :
|
Client(RcBounds bounds, int index) :
|
||||||
_bounds(bounds), _userIndex(index) {}
|
_bounds(bounds), _userIndex(index) {}
|
||||||
};
|
};
|
||||||
VERUS_TYPEDEFS(Entity);
|
VERUS_TYPEDEFS(Client);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class Node : public AllocatorAware
|
class Node : public AllocatorAware
|
||||||
{
|
{
|
||||||
Bounds _bounds;
|
Bounds _bounds;
|
||||||
Vector<Entity> _vEntities;
|
Vector<Client> _vClients;
|
||||||
int _children[4];
|
int _children[4];
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -43,11 +43,11 @@ namespace verus
|
||||||
int GetChildIndex(int child) const { return _children[child]; }
|
int GetChildIndex(int child) const { return _children[child]; }
|
||||||
void SetChildIndex(int child, int index) { _children[child] = index; }
|
void SetChildIndex(int child, int index) { _children[child] = index; }
|
||||||
|
|
||||||
void BindEntity(RcEntity entity);
|
void BindClient(RcClient client);
|
||||||
void UnbindEntity(int index);
|
void UnbindClient(int index);
|
||||||
|
|
||||||
int GetEntityCount() const { return Utils::Cast32(_vEntities.size()); }
|
int GetClientCount() const { return Utils::Cast32(_vClients.size()); }
|
||||||
RcEntity GetEntityAt(int i) const { return _vEntities[i]; }
|
RcClient GetClientAt(int i) const { return _vClients[i]; }
|
||||||
};
|
};
|
||||||
VERUS_TYPEDEFS(Node);
|
VERUS_TYPEDEFS(Node);
|
||||||
|
|
||||||
|
@ -77,11 +77,11 @@ namespace verus
|
||||||
|
|
||||||
VERUS_P(void Build(int currentNode = 0, int level = 0));
|
VERUS_P(void Build(int currentNode = 0, int level = 0));
|
||||||
|
|
||||||
bool BindEntity(RcEntity entity, bool forceRoot = false, int currentNode = 0);
|
bool BindClient(RcClient client, bool forceRoot = false, int currentNode = 0);
|
||||||
void UnbindEntity(int index);
|
void UnbindClient(int index);
|
||||||
VERUS_P(bool MustBind(int currentNode, RcBounds bounds) const);
|
VERUS_P(bool MustBind(int currentNode, RcBounds bounds) const);
|
||||||
|
|
||||||
Continue TraverseProper(RcPoint3 point, PResult pResult = nullptr, int currentNode = 0, void* pUser = nullptr) const;
|
Continue TraverseVisible(RcPoint3 point, PResult pResult = nullptr, int currentNode = 0, void* pUser = nullptr) const;
|
||||||
|
|
||||||
VERUS_P(static void ChildIndices(RcPoint3 point, RcPoint3 center, BYTE childIndices[4]));
|
VERUS_P(static void ChildIndices(RcPoint3 point, RcPoint3 center, BYTE childIndices[4]));
|
||||||
|
|
||||||
|
|
|
@ -46,41 +46,12 @@ void Bullet::Done()
|
||||||
{
|
{
|
||||||
DeleteAllCollisionObjects();
|
DeleteAllCollisionObjects();
|
||||||
|
|
||||||
if (_pStaticPlaneShape)
|
VERUS_SMART_DELETE(_pStaticPlaneShape);
|
||||||
{
|
VERUS_SMART_DELETE(_pDiscreteDynamicsWorld);
|
||||||
delete _pStaticPlaneShape;
|
VERUS_SMART_DELETE(_pConstraintSolver);
|
||||||
_pStaticPlaneShape = nullptr;
|
VERUS_SMART_DELETE(_pBroadphaseInterface);
|
||||||
}
|
VERUS_SMART_DELETE(_pDispatcher);
|
||||||
|
VERUS_SMART_DELETE(_pCollisionConfiguration);
|
||||||
if (_pDiscreteDynamicsWorld)
|
|
||||||
{
|
|
||||||
delete _pDiscreteDynamicsWorld;
|
|
||||||
_pDiscreteDynamicsWorld = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_pConstraintSolver)
|
|
||||||
{
|
|
||||||
delete _pConstraintSolver;
|
|
||||||
_pConstraintSolver = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_pBroadphaseInterface)
|
|
||||||
{
|
|
||||||
delete _pBroadphaseInterface;
|
|
||||||
_pBroadphaseInterface = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_pDispatcher)
|
|
||||||
{
|
|
||||||
delete _pDispatcher;
|
|
||||||
_pDispatcher = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_pCollisionConfiguration)
|
|
||||||
{
|
|
||||||
delete _pCollisionConfiguration;
|
|
||||||
_pCollisionConfiguration = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
VERUS_DONE(Bullet);
|
VERUS_DONE(Bullet);
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,7 @@ void Atmosphere::Init()
|
||||||
_shadowMap.Init(4096);
|
_shadowMap.Init(4096);
|
||||||
|
|
||||||
renderer.GetDS().InitByAtmosphere(_shadowMap.GetTexture());
|
renderer.GetDS().InitByAtmosphere(_shadowMap.GetTexture());
|
||||||
|
Effects::Bloom::I().InitByAtmosphere(_shadowMap.GetTexture());
|
||||||
|
|
||||||
CreateCelestialBodyMesh();
|
CreateCelestialBodyMesh();
|
||||||
|
|
||||||
|
@ -79,7 +80,7 @@ void Atmosphere::Init()
|
||||||
_clouds._phaseB.setX(utils.GetRandom().NextFloat());
|
_clouds._phaseB.setX(utils.GetRandom().NextFloat());
|
||||||
_clouds._phaseB.setY(utils.GetRandom().NextFloat());
|
_clouds._phaseB.setY(utils.GetRandom().NextFloat());
|
||||||
|
|
||||||
_fog._density[0] = _fog._density[1] = 0.0006f;
|
_fog._density[0] = _fog._density[1] = 0.001f;
|
||||||
|
|
||||||
_sun._matTilt = Matrix3::rotationX(_sun._latitude);
|
_sun._matTilt = Matrix3::rotationX(_sun._latitude);
|
||||||
UpdateSun(_time);
|
UpdateSun(_time);
|
||||||
|
@ -215,9 +216,9 @@ void Atmosphere::Update()
|
||||||
const float cloudScaleFog = 1 - 0.9f * _clouds._cloudiness * cloudinessSq;
|
const float cloudScaleFog = 1 - 0.9f * _clouds._cloudiness * cloudinessSq;
|
||||||
const float cloudScaleSun = 1 - 0.999f * _clouds._cloudiness * cloudinessSq;
|
const float cloudScaleSun = 1 - 0.999f * _clouds._cloudiness * cloudinessSq;
|
||||||
float color[3];
|
float color[3];
|
||||||
GetColor(208, color, 1); _ambientColor = Vector3::MakeFromPointer(color) * (GetMagnitude(68000, 45000, 10) * cloudScaleAmb);
|
GetColor(208, color, 1); _ambientColor = Vector3::MakeFromPointer(color) * (GetMagnitude(60000, 40000, 10) * cloudScaleAmb);
|
||||||
GetColor(110, color, 1); _fog._color = Vector3::MakeFromPointer(color) * (GetMagnitude(75000, 8000, 1) * cloudScaleFog);
|
GetColor(100, color, 1); _fog._color = Vector3::MakeFromPointer(color) * (GetMagnitude(30000, 2000, 1) * cloudScaleFog);
|
||||||
GetColor(240, color, 1); _sun._color = Vector3::MakeFromPointer(color) * (GetMagnitude(85000, 30000, 1) * cloudScaleSun);
|
GetColor(240, color, 1); _sun._color = Vector3::MakeFromPointer(color) * (GetMagnitude(85000, 20000, 1) * cloudScaleSun);
|
||||||
|
|
||||||
glm::vec3 ambientColor = _ambientColor.GLM();
|
glm::vec3 ambientColor = _ambientColor.GLM();
|
||||||
glm::vec3 fogColor = _fog._color.GLM();
|
glm::vec3 fogColor = _fog._color.GLM();
|
||||||
|
@ -231,7 +232,7 @@ void Atmosphere::Update()
|
||||||
const glm::vec3 grayAmbient = glm::saturation(0.f, _ambientColor.GLM());
|
const glm::vec3 grayAmbient = glm::saturation(0.f, _ambientColor.GLM());
|
||||||
const glm::vec3 grayFog = glm::saturation(0.f, _fog._color.GLM());
|
const glm::vec3 grayFog = glm::saturation(0.f, _fog._color.GLM());
|
||||||
const glm::vec3 graySun = glm::saturation(0.f, _sun._color.GLM());
|
const glm::vec3 graySun = glm::saturation(0.f, _sun._color.GLM());
|
||||||
VERUS_RT_ASSERT(glm::epsilonEqual(grayAmbient.x, 6400.f, 640.f));
|
VERUS_RT_ASSERT(glm::epsilonEqual(grayAmbient.x, 6000.f, 640.f));
|
||||||
VERUS_RT_ASSERT(glm::epsilonEqual(graySun.x, 32000.f, 3200.f));
|
VERUS_RT_ASSERT(glm::epsilonEqual(graySun.x, 32000.f, 3200.f));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -255,12 +256,12 @@ void Atmosphere::DrawSky(bool reflection)
|
||||||
if (water.IsUnderwater())
|
if (water.IsUnderwater())
|
||||||
reflection = false;
|
reflection = false;
|
||||||
|
|
||||||
auto cb = renderer.GetCommandBuffer();
|
|
||||||
|
|
||||||
RcCamera cam = *sm.GetCamera();
|
RcCamera cam = *sm.GetCamera();
|
||||||
Matrix3 matS = Matrix3::scale(Vector3(4, 1, 4)); // Stretch sky dome.
|
Matrix3 matS = Matrix3::scale(Vector3(4, 1, 4)); // Stretch sky dome.
|
||||||
const Matrix4 matSkyDome = cam.GetMatrixVP() * Transform3(matS, Vector3(cam.GetEyePosition()));
|
const Matrix4 matSkyDome = cam.GetMatrixVP() * Transform3(matS, Vector3(cam.GetEyePosition()));
|
||||||
|
|
||||||
|
auto cb = renderer.GetCommandBuffer();
|
||||||
|
|
||||||
s_ubPerFrame._time_cloudiness.x = _time;
|
s_ubPerFrame._time_cloudiness.x = _time;
|
||||||
s_ubPerFrame._time_cloudiness.y = _clouds._cloudiness;
|
s_ubPerFrame._time_cloudiness.y = _clouds._cloudiness;
|
||||||
s_ubPerFrame._ambientColor = float4(_ambientColor.GLM(), 0);
|
s_ubPerFrame._ambientColor = float4(_ambientColor.GLM(), 0);
|
||||||
|
@ -278,16 +279,14 @@ void Atmosphere::DrawSky(bool reflection)
|
||||||
|
|
||||||
// <Sky>
|
// <Sky>
|
||||||
s_ubPerObject._matWVP = matSkyDome.UniformBufferFormat();
|
s_ubPerObject._matWVP = matSkyDome.UniformBufferFormat();
|
||||||
_skyDome.BindGeo(cb);
|
|
||||||
cb->BindPipeline(_pipe[reflection ? PIPE_SKY_REFLECTION : PIPE_SKY]);
|
cb->BindPipeline(_pipe[reflection ? PIPE_SKY_REFLECTION : PIPE_SKY]);
|
||||||
|
_skyDome.BindGeo(cb);
|
||||||
_shader->BeginBindDescriptors();
|
_shader->BeginBindDescriptors();
|
||||||
cb->BindDescriptors(_shader, 0);
|
cb->BindDescriptors(_shader, 0);
|
||||||
cb->BindDescriptors(_shader, 1, _cshSkyFS);
|
cb->BindDescriptors(_shader, 1, _cshSkyFS);
|
||||||
cb->BindDescriptors(_shader, 2);
|
cb->BindDescriptors(_shader, 2);
|
||||||
cb->BindDescriptors(_shader, 3);
|
cb->BindDescriptors(_shader, 3);
|
||||||
_shader->EndBindDescriptors();
|
_shader->EndBindDescriptors();
|
||||||
|
|
||||||
cb->DrawIndexed(_skyDome.GetIndexCount());
|
cb->DrawIndexed(_skyDome.GetIndexCount());
|
||||||
// </Sky>
|
// </Sky>
|
||||||
|
|
||||||
|
@ -301,16 +300,14 @@ void Atmosphere::DrawSky(bool reflection)
|
||||||
s_ubPerObject._matW = matW.UniformBufferFormat();
|
s_ubPerObject._matW = matW.UniformBufferFormat();
|
||||||
s_ubPerObject._matWVP = Matrix4(cam.GetMatrixVP() * matW).UniformBufferFormat();
|
s_ubPerObject._matWVP = Matrix4(cam.GetMatrixVP() * matW).UniformBufferFormat();
|
||||||
|
|
||||||
cb->BindVertexBuffers(_geo);
|
|
||||||
cb->BindPipeline(_pipe[PIPE_SUN]);
|
cb->BindPipeline(_pipe[PIPE_SUN]);
|
||||||
|
cb->BindVertexBuffers(_geo);
|
||||||
_shader->BeginBindDescriptors();
|
_shader->BeginBindDescriptors();
|
||||||
cb->BindDescriptors(_shader, 0);
|
cb->BindDescriptors(_shader, 0);
|
||||||
cb->BindDescriptors(_shader, 1, _cshSunFS);
|
cb->BindDescriptors(_shader, 1, _cshSunFS);
|
||||||
cb->BindDescriptors(_shader, 2);
|
cb->BindDescriptors(_shader, 2);
|
||||||
cb->BindDescriptors(_shader, 3);
|
cb->BindDescriptors(_shader, 3);
|
||||||
_shader->EndBindDescriptors();
|
_shader->EndBindDescriptors();
|
||||||
|
|
||||||
cb->Draw(4, 1);
|
cb->Draw(4, 1);
|
||||||
}
|
}
|
||||||
// </Sun>
|
// </Sun>
|
||||||
|
@ -322,32 +319,28 @@ void Atmosphere::DrawSky(bool reflection)
|
||||||
s_ubPerObject._matW = matW.UniformBufferFormat();
|
s_ubPerObject._matW = matW.UniformBufferFormat();
|
||||||
s_ubPerObject._matWVP = Matrix4(cam.GetMatrixVP() * matW).UniformBufferFormat();
|
s_ubPerObject._matWVP = Matrix4(cam.GetMatrixVP() * matW).UniformBufferFormat();
|
||||||
|
|
||||||
cb->BindVertexBuffers(_geo);
|
|
||||||
cb->BindPipeline(_pipe[PIPE_MOON]);
|
cb->BindPipeline(_pipe[PIPE_MOON]);
|
||||||
|
cb->BindVertexBuffers(_geo);
|
||||||
_shader->BeginBindDescriptors();
|
_shader->BeginBindDescriptors();
|
||||||
cb->BindDescriptors(_shader, 0);
|
cb->BindDescriptors(_shader, 0);
|
||||||
cb->BindDescriptors(_shader, 1, _cshMoonFS);
|
cb->BindDescriptors(_shader, 1, _cshMoonFS);
|
||||||
cb->BindDescriptors(_shader, 2);
|
cb->BindDescriptors(_shader, 2);
|
||||||
cb->BindDescriptors(_shader, 3);
|
cb->BindDescriptors(_shader, 3);
|
||||||
_shader->EndBindDescriptors();
|
_shader->EndBindDescriptors();
|
||||||
|
|
||||||
cb->Draw(4, 1);
|
cb->Draw(4, 1);
|
||||||
}
|
}
|
||||||
// </Moon>
|
// </Moon>
|
||||||
|
|
||||||
// <Clouds>
|
// <Clouds>
|
||||||
s_ubPerObject._matWVP = matSkyDome.UniformBufferFormat();
|
s_ubPerObject._matWVP = matSkyDome.UniformBufferFormat();
|
||||||
_skyDome.BindGeo(cb);
|
|
||||||
cb->BindPipeline(_pipe[reflection ? PIPE_CLOUDS_REFLECTION : PIPE_CLOUDS]);
|
cb->BindPipeline(_pipe[reflection ? PIPE_CLOUDS_REFLECTION : PIPE_CLOUDS]);
|
||||||
|
_skyDome.BindGeo(cb);
|
||||||
_shader->BeginBindDescriptors();
|
_shader->BeginBindDescriptors();
|
||||||
cb->BindDescriptors(_shader, 0);
|
cb->BindDescriptors(_shader, 0);
|
||||||
cb->BindDescriptors(_shader, 1, _cshSkyFS);
|
cb->BindDescriptors(_shader, 1, _cshSkyFS);
|
||||||
cb->BindDescriptors(_shader, 2);
|
cb->BindDescriptors(_shader, 2);
|
||||||
cb->BindDescriptors(_shader, 3);
|
cb->BindDescriptors(_shader, 3);
|
||||||
_shader->EndBindDescriptors();
|
_shader->EndBindDescriptors();
|
||||||
|
|
||||||
cb->DrawIndexed(_skyDome.GetIndexCount());
|
cb->DrawIndexed(_skyDome.GetIndexCount());
|
||||||
// </Clouds>
|
// </Clouds>
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ void BaseMesh::Init(CSZ url)
|
||||||
void BaseMesh::Done()
|
void BaseMesh::Done()
|
||||||
{
|
{
|
||||||
IO::Async::Cancel(this);
|
IO::Async::Cancel(this);
|
||||||
|
DoneShape();
|
||||||
VERUS_DONE(BaseMesh);
|
VERUS_DONE(BaseMesh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -303,6 +304,9 @@ void BaseMesh::LoadX3D3(RcBlob blob)
|
||||||
ComputeTangentSpace();
|
ComputeTangentSpace();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_initShape)
|
||||||
|
InitShape(Transform3::identity());
|
||||||
|
|
||||||
CreateDeviceBuffers();
|
CreateDeviceBuffers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -477,6 +481,83 @@ void BaseMesh::ComputeTangentSpace()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
btBvhTriangleMeshShape* BaseMesh::InitShape(RcTransform3 tr, CSZ url)
|
||||||
|
{
|
||||||
|
if (!_vertCount)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
DoneShape();
|
||||||
|
|
||||||
|
String finalUrl = url ? url : _url;
|
||||||
|
String cacheFilename;
|
||||||
|
if (!finalUrl.empty())
|
||||||
|
{
|
||||||
|
String filename = Str::ToPakFriendlyUrl(_C(finalUrl));
|
||||||
|
if (url)
|
||||||
|
filename += ".INST";
|
||||||
|
filename = "[Models]:PhyCache/" + filename + ".bullet";
|
||||||
|
cacheFilename = IO::FileSystem::ConvertRelativePathToAbsolute(filename, true);
|
||||||
|
if (IO::FileSystem::FileExist(_C(filename)))
|
||||||
|
{
|
||||||
|
Vector<BYTE> vMesh;
|
||||||
|
IO::FileSystem::LoadResource(_C(filename), vMesh);
|
||||||
|
|
||||||
|
btBulletWorldImporter bwi(0);
|
||||||
|
if (!vMesh.empty() && bwi.loadFileFromMemory(reinterpret_cast<char*>(vMesh.data()), Utils::Cast32(vMesh.size())))
|
||||||
|
{
|
||||||
|
const int count = bwi.getNumCollisionShapes();
|
||||||
|
if (count)
|
||||||
|
_pShape = static_cast<btBvhTriangleMeshShape*>(bwi.getCollisionShapeByIndex(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
return _pShape;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
btTriangleMesh* pTriangleMesh = new btTriangleMesh(_vIndices.empty());
|
||||||
|
pTriangleMesh->preallocateVertices(_vertCount);
|
||||||
|
pTriangleMesh->preallocateIndices(_indexCount);
|
||||||
|
VERUS_FOR(i, _vertCount)
|
||||||
|
{
|
||||||
|
Point3 pos;
|
||||||
|
DequantizeUsingDeq3D(_vBinding0[i]._pos, _posDeq, pos);
|
||||||
|
pos = tr * pos;
|
||||||
|
pTriangleMesh->findOrAddVertex(pos.Bullet(), false);
|
||||||
|
}
|
||||||
|
VERUS_FOR(i, _faceCount)
|
||||||
|
{
|
||||||
|
const int i0 = _vIndices.empty() ? _vIndices32[i * 3 + 0] : _vIndices[i * 3 + 0];
|
||||||
|
const int i1 = _vIndices.empty() ? _vIndices32[i * 3 + 1] : _vIndices[i * 3 + 1];
|
||||||
|
const int i2 = _vIndices.empty() ? _vIndices32[i * 3 + 2] : _vIndices[i * 3 + 2];
|
||||||
|
pTriangleMesh->addTriangleIndices(i0, i1, i2);
|
||||||
|
}
|
||||||
|
|
||||||
|
_pShape = new btBvhTriangleMeshShape(pTriangleMesh, true);
|
||||||
|
|
||||||
|
if (!cacheFilename.empty())
|
||||||
|
{
|
||||||
|
btDefaultSerializer s;
|
||||||
|
s.startSerialization();
|
||||||
|
_pShape->serializeSingleShape(&s);
|
||||||
|
s.finishSerialization();
|
||||||
|
IO::File file;
|
||||||
|
if (file.Open(_C(cacheFilename), "wb"))
|
||||||
|
file.Write(s.getBufferPointer(), s.getCurrentBufferSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
return _pShape;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseMesh::DoneShape()
|
||||||
|
{
|
||||||
|
if (_pShape)
|
||||||
|
{
|
||||||
|
delete _pShape->getMeshInterface();
|
||||||
|
delete _pShape;
|
||||||
|
_pShape = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void BaseMesh::GetBounds(RPoint3 mn, RPoint3 mx) const
|
void BaseMesh::GetBounds(RPoint3 mn, RPoint3 mx) const
|
||||||
{
|
{
|
||||||
const short smin[] = { -SHRT_MAX, -SHRT_MAX, -SHRT_MAX };
|
const short smin[] = { -SHRT_MAX, -SHRT_MAX, -SHRT_MAX };
|
||||||
|
|
|
@ -42,6 +42,7 @@ namespace verus
|
||||||
Anim::Warp _warp;
|
Anim::Warp _warp;
|
||||||
String _warpUrl;
|
String _warpUrl;
|
||||||
String _url;
|
String _url;
|
||||||
|
btBvhTriangleMeshShape* _pShape = nullptr;
|
||||||
int _vertCount = 0;
|
int _vertCount = 0;
|
||||||
int _faceCount = 0;
|
int _faceCount = 0;
|
||||||
int _indexCount = 0;
|
int _indexCount = 0;
|
||||||
|
@ -51,6 +52,7 @@ namespace verus
|
||||||
float _tc1Deq[4];
|
float _tc1Deq[4];
|
||||||
bool _loadOnly = false;
|
bool _loadOnly = false;
|
||||||
bool _rigidSkeleton = false;
|
bool _rigidSkeleton = false;
|
||||||
|
bool _initShape = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BaseMesh();
|
BaseMesh();
|
||||||
|
@ -98,6 +100,11 @@ namespace verus
|
||||||
virtual void CreateDeviceBuffers() {}
|
virtual void CreateDeviceBuffers() {}
|
||||||
virtual void UpdateVertexBuffer(const void* p, int binding) {}
|
virtual void UpdateVertexBuffer(const void* p, int binding) {}
|
||||||
|
|
||||||
|
// Physics:
|
||||||
|
btBvhTriangleMeshShape* GetShape() const { return _pShape; }
|
||||||
|
btBvhTriangleMeshShape* InitShape(RcTransform3 tr, CSZ url = nullptr);
|
||||||
|
void DoneShape();
|
||||||
|
|
||||||
// Bounds:
|
// Bounds:
|
||||||
void GetBounds(RPoint3 mn, RPoint3 mx) const;
|
void GetBounds(RPoint3 mn, RPoint3 mx) const;
|
||||||
Math::Bounds GetBounds() const;
|
Math::Bounds GetBounds() const;
|
||||||
|
|
|
@ -4,8 +4,8 @@ using namespace verus;
|
||||||
using namespace verus::Scene;
|
using namespace verus::Scene;
|
||||||
|
|
||||||
CGI::ShaderPwn Forest::s_shader;
|
CGI::ShaderPwn Forest::s_shader;
|
||||||
//CGI::CStateBlockPwns<Forest::SB_MAX> Forest::ms_sb;
|
Forest::UB_ForestVS Forest::s_ubForestVS;
|
||||||
//Forest::CB_PerFrame Forest::ms_cbPerFrame;
|
Forest::UB_ForestFS Forest::s_ubForestFS;
|
||||||
|
|
||||||
// Forest::Plant:
|
// Forest::Plant:
|
||||||
|
|
||||||
|
@ -28,38 +28,20 @@ Forest::~Forest()
|
||||||
|
|
||||||
void Forest::InitStatic()
|
void Forest::InitStatic()
|
||||||
{
|
{
|
||||||
//VERUS_OUTPUT_DEBUG_STRING(__FUNCTION__);
|
s_shader.Init("[Shaders]:DS_Forest.hlsl");
|
||||||
//
|
s_shader->CreateDescriptorSet(0, &s_ubForestVS, sizeof(s_ubForestVS), 100, {}, CGI::ShaderStageFlags::vs_hs_ds_fs);
|
||||||
//CGI::CShaderDesc sd;
|
s_shader->CreateDescriptorSet(1, &s_ubForestFS, sizeof(s_ubForestFS), 100,
|
||||||
//sd._url = "Shaders:DS_Forest.cg";
|
{
|
||||||
//s_shader.Init(sd);
|
CGI::Sampler::aniso,
|
||||||
//s_shader->BindBufferSource(&ms_cbPerFrame, sizeof(ms_cbPerFrame), 0, "PerFrame");
|
CGI::Sampler::aniso,
|
||||||
//
|
CGI::Sampler::aniso
|
||||||
//CGI::CStateBlockDesc sbd;
|
}, CGI::ShaderStageFlags::fs);
|
||||||
//sbd.B();
|
s_shader->CreatePipelineLayout();
|
||||||
//sbd.R();
|
|
||||||
//sbd.Z().depthEnable = true;
|
|
||||||
//sbd.Z().depthWriteEnable = true;
|
|
||||||
//sbd.S(0).Set("a", "ww");
|
|
||||||
//sbd.S(1).Set("a", "ww");
|
|
||||||
//sbd.S(2).Set("a", "ww");
|
|
||||||
//ms_sb[SB_MASTER].Init(sbd);
|
|
||||||
//
|
|
||||||
//sbd.Reset();
|
|
||||||
//sbd.B().rtWriteMasks[0] = CShadowMap::GetWriteMask();
|
|
||||||
//sbd.R().depthBias = CShadowMap::GetDepthBias() * 48;
|
|
||||||
//sbd.R().slopeScaledDepthBias = CShadowMap::GetSlopeScaledDepthBias();
|
|
||||||
//sbd.Z().depthEnable = true;
|
|
||||||
//sbd.Z().depthWriteEnable = true;
|
|
||||||
//sbd.S(0).Set("a", "ww");
|
|
||||||
//ms_sb[SB_DEPTH].Init(sbd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Forest::DoneStatic()
|
void Forest::DoneStatic()
|
||||||
{
|
{
|
||||||
//VERUS_OUTPUT_DEBUG_STRING(__FUNCTION__);
|
s_shader.Done();
|
||||||
//ms_sb.Done();
|
|
||||||
//s_shader.Done();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Forest::Init(PTerrain pTerrain)
|
void Forest::Init(PTerrain pTerrain)
|
||||||
|
@ -92,6 +74,7 @@ void Forest::Init(PTerrain pTerrain)
|
||||||
_scatter.SetDelegate(this);
|
_scatter.SetDelegate(this);
|
||||||
|
|
||||||
_vPlants.reserve(16);
|
_vPlants.reserve(16);
|
||||||
|
_vLayerPlants.reserve(16);
|
||||||
_vDrawPlants.resize(_capacity);
|
_vDrawPlants.resize(_capacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,6 +103,7 @@ void Forest::Update()
|
||||||
Mesh::Desc meshDesc;
|
Mesh::Desc meshDesc;
|
||||||
meshDesc._url = _C(plant._url);
|
meshDesc._url = _C(plant._url);
|
||||||
meshDesc._instanceCapacity = _capacity;
|
meshDesc._instanceCapacity = _capacity;
|
||||||
|
meshDesc._initShape = true;
|
||||||
plant._mesh.Init(meshDesc);
|
plant._mesh.Init(meshDesc);
|
||||||
|
|
||||||
Material::Desc matDesc;
|
Material::Desc matDesc;
|
||||||
|
@ -132,6 +116,7 @@ void Forest::Update()
|
||||||
for (auto& plant : _vPlants)
|
for (auto& plant : _vPlants)
|
||||||
{
|
{
|
||||||
plant._material->IncludePart(0);
|
plant._material->IncludePart(0);
|
||||||
|
|
||||||
if (!plant._maxSize && plant._mesh.IsLoaded())
|
if (!plant._maxSize && plant._mesh.IsLoaded())
|
||||||
{
|
{
|
||||||
// Time to get the size of this mesh.
|
// Time to get the size of this mesh.
|
||||||
|
@ -142,10 +127,29 @@ void Forest::Update()
|
||||||
_maxSizeAll = plant._maxSize;
|
_maxSizeAll = plant._maxSize;
|
||||||
_pTerrain->FattenQuadtreeNodesBy(_maxSizeAll);
|
_pTerrain->FattenQuadtreeNodesBy(_maxSizeAll);
|
||||||
}
|
}
|
||||||
|
plant._aoSize = plant._mesh.GetBounds().GetAverageSize() * 1.7f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!plant._tex[0] && plant._mesh.IsLoaded() && plant._material->IsLoaded())
|
||||||
|
LoadSprite(plant);
|
||||||
|
|
||||||
|
if (!plant._csh.IsSet())
|
||||||
|
{
|
||||||
|
if (plant._tex[Plant::TEX_GBUFFER_0] && plant._tex[Plant::TEX_GBUFFER_0]->IsLoaded() &&
|
||||||
|
plant._tex[Plant::TEX_GBUFFER_1] && plant._tex[Plant::TEX_GBUFFER_1]->IsLoaded() &&
|
||||||
|
plant._tex[Plant::TEX_GBUFFER_2] && plant._tex[Plant::TEX_GBUFFER_2]->IsLoaded())
|
||||||
|
{
|
||||||
|
plant._csh = s_shader->BindDescriptorSetTextures(1,
|
||||||
|
{
|
||||||
|
plant._tex[Plant::TEX_GBUFFER_0],
|
||||||
|
plant._tex[Plant::TEX_GBUFFER_1],
|
||||||
|
plant._tex[Plant::TEX_GBUFFER_2]
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (false && !_geo)
|
if (!_geo)
|
||||||
{
|
{
|
||||||
bool allLoaded = !_vPlants.empty();
|
bool allLoaded = !_vPlants.empty();
|
||||||
for (auto& plant : _vPlants)
|
for (auto& plant : _vPlants)
|
||||||
|
@ -164,7 +168,7 @@ void Forest::Update()
|
||||||
for (auto& bc : plant._vBakedChunks)
|
for (auto& bc : plant._vBakedChunks)
|
||||||
{
|
{
|
||||||
bc._vbOffset = vertCount;
|
bc._vbOffset = vertCount;
|
||||||
vertCount += bc._vSprites.size();
|
vertCount += Utils::Cast32(bc._vSprites.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Vector<Vertex> vVB;
|
Vector<Vertex> vVB;
|
||||||
|
@ -178,26 +182,45 @@ void Forest::Update()
|
||||||
for (auto& s : bc._vSprites)
|
for (auto& s : bc._vSprites)
|
||||||
bounds.Include(s._pos);
|
bounds.Include(s._pos);
|
||||||
bounds.FattenBy(plant.GetSize());
|
bounds.FattenBy(plant.GetSize());
|
||||||
_octree.BindEntity(Math::Octree::Entity(bounds, &bc));
|
_octree.BindClient(Math::Octree::Client(bounds, &bc));
|
||||||
|
|
||||||
if (!bc._vSprites.empty())
|
if (!bc._vSprites.empty())
|
||||||
memcpy(&vVB[vertCount], bc._vSprites.data(), bc._vSprites.size() * sizeof(Vertex));
|
memcpy(&vVB[vertCount], bc._vSprites.data(), bc._vSprites.size() * sizeof(Vertex));
|
||||||
vertCount += bc._vSprites.size();
|
vertCount += Utils::Cast32(bc._vSprites.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//CGI::CVertexElement ve[] =
|
CGI::GeometryDesc geoDesc;
|
||||||
//{
|
const CGI::VertexInputAttrDesc viaDesc[] =
|
||||||
// {0, offsetof(Vertex, _pos), /**/CGI::VeType::_float, 3, CGI::VeUsage::position, 0},
|
{
|
||||||
// {0, offsetof(Vertex, _tc), /**/CGI::VeType::_short, 2, CGI::VeUsage::texCoord, 0},
|
{0, offsetof(Vertex, _pos), CGI::ViaType::floats, 3, CGI::ViaUsage::position, 0},
|
||||||
// VERUS_END_DECL
|
{0, offsetof(Vertex, _tc), CGI::ViaType::shorts, 2, CGI::ViaUsage::texCoord, 0},
|
||||||
//};
|
CGI::VertexInputAttrDesc::End()
|
||||||
//CGI::GeometryDesc gd;
|
};
|
||||||
//gd._pVertDecl = ve;
|
geoDesc._pVertexInputAttrDesc = viaDesc;
|
||||||
//gd._pShader = &(*s_shader);
|
const int strides[] = { sizeof(Vertex), 0 };
|
||||||
//_geo.Init(gd);
|
geoDesc._pStrides = strides;
|
||||||
//_geo->DefineVertexStream(0, sizeof(Vertex), vertCount * sizeof(Vertex));
|
_geo.Init(geoDesc);
|
||||||
//_geo->BufferDataVB(vVB.data());
|
_geo->CreateVertexBuffer(vertCount, 0);
|
||||||
|
_geo->UpdateVertexBuffer(vVB.data(), 0);
|
||||||
|
|
||||||
|
VERUS_QREF_RENDERER;
|
||||||
|
VERUS_QREF_ATMO;
|
||||||
|
|
||||||
|
{
|
||||||
|
CGI::PipelineDesc pipeDesc(_geo, s_shader, "#", renderer.GetDS().GetRenderPassHandle());
|
||||||
|
pipeDesc._colorAttachBlendEqs[0] = VERUS_COLOR_BLEND_OFF;
|
||||||
|
pipeDesc._colorAttachBlendEqs[1] = VERUS_COLOR_BLEND_OFF;
|
||||||
|
pipeDesc._colorAttachBlendEqs[2] = VERUS_COLOR_BLEND_OFF;
|
||||||
|
pipeDesc._topology = CGI::PrimitiveTopology::pointList;
|
||||||
|
_pipe[PIPE_MAIN].Init(pipeDesc);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
CGI::PipelineDesc pipeDesc(_geo, s_shader, "#Depth", atmo.GetShadowMap().GetRenderPassHandle());
|
||||||
|
pipeDesc._colorAttachBlendEqs[0] = "";
|
||||||
|
pipeDesc._topology = CGI::PrimitiveTopology::pointList;
|
||||||
|
_pipe[PIPE_DEPTH].Init(pipeDesc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -215,8 +238,11 @@ void Forest::Layout()
|
||||||
for (auto& bc : plant._vBakedChunks)
|
for (auto& bc : plant._vBakedChunks)
|
||||||
bc._visible = false;
|
bc._visible = false;
|
||||||
|
|
||||||
|
{
|
||||||
const float zFarWas = sm.GetCamera()->GetZFar();
|
const float zFarWas = sm.GetCamera()->GetZFar();
|
||||||
if (Atmosphere::I().GetShadowMap().IsRendering())
|
|
||||||
|
const bool drawingDepth = Scene::SceneManager::IsDrawingDepth(DrawDepth::automatic);
|
||||||
|
if (drawingDepth)
|
||||||
{
|
{
|
||||||
const int csmSplit = Atmosphere::I().GetShadowMap().GetCurrentSplit();
|
const int csmSplit = Atmosphere::I().GetShadowMap().GetCurrentSplit();
|
||||||
if (!csmSplit)
|
if (!csmSplit)
|
||||||
|
@ -229,106 +255,123 @@ void Forest::Layout()
|
||||||
qt.SetDelegate(&_scatter);
|
qt.SetDelegate(&_scatter);
|
||||||
qt.TraverseVisible();
|
qt.TraverseVisible();
|
||||||
qt.SetDelegate(_pTerrain);
|
qt.SetDelegate(_pTerrain);
|
||||||
sm.GetCamera()->SetFrustumFar(zFarWas);
|
|
||||||
|
|
||||||
const Point3 eyePos = sm.GetCamera()->GetEyePosition();
|
if (drawingDepth)
|
||||||
std::sort(_vDrawPlants.begin(), _vDrawPlants.begin() + _visibleCount, [&eyePos](RcDrawPlant plantA, RcDrawPlant plantB)
|
_octree.TraverseVisible(sm.GetCamera()->GetFrustum());
|
||||||
|
sm.GetCamera()->SetFrustumFar(_maxDist * 8);
|
||||||
|
if (!drawingDepth)
|
||||||
|
_octree.TraverseVisible(sm.GetCamera()->GetFrustum());
|
||||||
|
|
||||||
|
sm.GetCamera()->SetFrustumFar(zFarWas);
|
||||||
|
}
|
||||||
|
|
||||||
|
const float tessDistSq = _tessDist * _tessDist;
|
||||||
|
std::sort(_vDrawPlants.begin(), _vDrawPlants.begin() + _visibleCount, [tessDistSq](RDrawPlant plantA, RDrawPlant plantB)
|
||||||
{
|
{
|
||||||
|
const bool tessA = plantA._distToEyeSq < tessDistSq;
|
||||||
|
const bool tessB = plantB._distToEyeSq < tessDistSq;
|
||||||
|
if (tessA != tessB)
|
||||||
|
return tessA;
|
||||||
if (plantA._plantIndex != plantB._plantIndex)
|
if (plantA._plantIndex != plantB._plantIndex)
|
||||||
return plantA._plantIndex < plantB._plantIndex;
|
return plantA._plantIndex < plantB._plantIndex;
|
||||||
const float distA = VMath::distSqr(eyePos, plantA._pos);
|
return plantA._distToEyeSq < plantB._distToEyeSq;
|
||||||
const float distB = VMath::distSqr(eyePos, plantB._pos);
|
|
||||||
return distA < distB;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Forest::Draw()
|
void Forest::Draw(bool allowTess)
|
||||||
{
|
{
|
||||||
if (!IsInitialized())
|
if (!IsInitialized())
|
||||||
return;
|
return;
|
||||||
VERUS_UPDATE_ONCE_CHECK_DRAW;
|
VERUS_UPDATE_ONCE_CHECK_DRAW;
|
||||||
|
|
||||||
//for (auto& plant : _vPlants)
|
DrawModels(allowTess);
|
||||||
//{
|
|
||||||
// if (!plant._tex[0] && plant._mesh.IsLoaded() && plant._material->IsLoaded())
|
|
||||||
// {
|
|
||||||
// if (!LoadSprite(plant))
|
|
||||||
// BakeSprite(plant);
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
DrawModels();
|
|
||||||
DrawSprites();
|
DrawSprites();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Forest::DrawModels()
|
void Forest::DrawModels(bool allowTess)
|
||||||
{
|
{
|
||||||
if (!_visibleCount)
|
if (!_visibleCount)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
VERUS_QREF_RENDERER;
|
VERUS_QREF_RENDERER;
|
||||||
|
VERUS_QREF_CONST_SETTINGS;
|
||||||
|
|
||||||
PMesh pMesh = nullptr;
|
PMesh pMesh = nullptr;
|
||||||
MaterialPtr material;
|
MaterialPtr material;
|
||||||
bool bindPipeline = true;
|
int bindPipelineStage = -1;
|
||||||
|
bool tess = true;
|
||||||
|
const float tessDistSq = _tessDist * _tessDist;
|
||||||
|
|
||||||
auto cb = renderer.GetCommandBuffer();
|
auto cb = renderer.GetCommandBuffer();
|
||||||
auto shader = Scene::Mesh::GetShader();
|
auto shader = Scene::Mesh::GetShader();
|
||||||
|
|
||||||
// Draw all visible assets:
|
auto DrawMesh = [cb](PMesh pMesh)
|
||||||
|
{
|
||||||
|
if (pMesh && !pMesh->IsInstanceBufferEmpty(true))
|
||||||
|
{
|
||||||
|
pMesh->UpdateInstanceBuffer();
|
||||||
|
cb->DrawIndexed(pMesh->GetIndexCount(), pMesh->GetInstanceCount(true), 0, 0, pMesh->GetFirstInstance());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
shader->BeginBindDescriptors();
|
shader->BeginBindDescriptors();
|
||||||
for (int i = 0; i <= _visibleCount; ++i)
|
for (int i = 0; i <= _visibleCount; ++i)
|
||||||
{
|
{
|
||||||
if (i == _visibleCount) // The end?
|
if (i == _visibleCount) // The end?
|
||||||
{
|
{
|
||||||
if (pMesh && !pMesh->IsInstanceBufferEmpty(true))
|
DrawMesh(pMesh);
|
||||||
{
|
|
||||||
pMesh->UpdateInstanceBuffer();
|
|
||||||
cb->DrawIndexed(pMesh->GetIndexCount(), pMesh->GetInstanceCount(true), 0, 0, pMesh->GetFirstInstance());
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
RcDrawPlant drawPlant = _vDrawPlants[i];
|
RcDrawPlant drawPlant = _vDrawPlants[i];
|
||||||
RPlant plant = _vPlants[drawPlant._plantIndex];
|
RPlant plant = _vPlants[drawPlant._plantIndex];
|
||||||
PMesh pNewMesh = &plant._mesh;
|
PMesh pNextMesh = &plant._mesh;
|
||||||
MaterialPtr newMaterial = plant._material;
|
MaterialPtr nextMaterial = plant._material;
|
||||||
|
const bool nextTess = drawPlant._distToEyeSq < tessDistSq;
|
||||||
|
|
||||||
if (!pNewMesh->IsLoaded() || !newMaterial->IsLoaded())
|
if (!pNextMesh->IsLoaded() || !nextMaterial->IsLoaded())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (pNewMesh != pMesh) // New pMesh?
|
if (pNextMesh != pMesh || nextTess != tess)
|
||||||
{
|
{
|
||||||
if (pMesh && !pMesh->IsInstanceBufferEmpty(true))
|
DrawMesh(pMesh);
|
||||||
{
|
|
||||||
pMesh->UpdateInstanceBuffer();
|
|
||||||
cb->DrawIndexed(pMesh->GetIndexCount(), pMesh->GetInstanceCount(true), 0, 0, pMesh->GetFirstInstance());
|
|
||||||
}
|
|
||||||
pMesh = pNewMesh;
|
|
||||||
pMesh->MarkFirstInstance();
|
|
||||||
if (bindPipeline)
|
|
||||||
{
|
|
||||||
bindPipeline = false;
|
|
||||||
pMesh->BindPipelineInstanced(cb, false);
|
|
||||||
}
|
|
||||||
pMesh->BindGeo(cb);
|
|
||||||
|
|
||||||
|
pMesh = pNextMesh;
|
||||||
|
pMesh->MarkFirstInstance();
|
||||||
|
if (bindPipelineStage)
|
||||||
|
{
|
||||||
|
if (-1 == bindPipelineStage)
|
||||||
|
{
|
||||||
|
bindPipelineStage = (nextTess && allowTess && settings._gpuTessellation) ? 1 : 0;
|
||||||
|
pMesh->BindPipelineInstanced(cb, 1 == bindPipelineStage, true);
|
||||||
|
pMesh->UpdateUniformBufferPerFrame(1 / (_tessDist - 10));
|
||||||
|
cb->BindDescriptors(shader, 0);
|
||||||
|
}
|
||||||
|
else if (1 == bindPipelineStage && !nextTess)
|
||||||
|
{
|
||||||
|
bindPipelineStage = 0;
|
||||||
|
pMesh->BindPipelineInstanced(cb, false, true);
|
||||||
pMesh->UpdateUniformBufferPerFrame();
|
pMesh->UpdateUniformBufferPerFrame();
|
||||||
cb->BindDescriptors(shader, 0);
|
cb->BindDescriptors(shader, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tess = nextTess;
|
||||||
|
pMesh->BindGeo(cb);
|
||||||
pMesh->UpdateUniformBufferPerMeshVS();
|
pMesh->UpdateUniformBufferPerMeshVS();
|
||||||
cb->BindDescriptors(shader, 2);
|
cb->BindDescriptors(shader, 2);
|
||||||
}
|
}
|
||||||
if (newMaterial != material) // Switch material?
|
if (nextMaterial != material)
|
||||||
{
|
{
|
||||||
material = newMaterial;
|
material = nextMaterial;
|
||||||
material->UpdateMeshUniformBuffer();
|
material->UpdateMeshUniformBuffer();
|
||||||
cb->BindDescriptors(shader, 1, material->GetComplexSetHandle());
|
cb->BindDescriptors(shader, 1, material->GetComplexSetHandle());
|
||||||
}
|
}
|
||||||
if (pMesh) // Draw this pMesh:
|
|
||||||
|
if (pMesh)
|
||||||
{
|
{
|
||||||
const Transform3 matW = VMath::appendScale(Transform3(drawPlant._basis * Matrix3::rotationY(drawPlant._angle),
|
const Transform3 matW = VMath::appendScale(Transform3(drawPlant._basis * Matrix3::rotationY(drawPlant._angle),
|
||||||
Vector3(drawPlant._pos + drawPlant._pushBack)), Vector3::Replicate(drawPlant._scale));
|
Vector3(drawPlant._pos + drawPlant._pushBack)), Vector3::Replicate(drawPlant._scale));
|
||||||
pMesh->PushInstance(matW, Vector4::Replicate(1));
|
pMesh->PushInstance(matW, Vector4(Vector3(drawPlant._pos), 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
shader->EndBindDescriptors();
|
shader->EndBindDescriptors();
|
||||||
|
@ -336,51 +379,104 @@ void Forest::DrawModels()
|
||||||
|
|
||||||
void Forest::DrawSprites()
|
void Forest::DrawSprites()
|
||||||
{
|
{
|
||||||
//if (!_geo)
|
if (!_geo)
|
||||||
// return;
|
return;
|
||||||
//
|
|
||||||
//VERUS_QREF_RENDER;
|
VERUS_QREF_RENDERER;
|
||||||
//VERUS_QREF_SM;
|
VERUS_QREF_SM;
|
||||||
//
|
VERUS_QREF_ATMO;
|
||||||
//const bool depth = Utils::IsDrawingDepth(DrawDepth::automatic);
|
|
||||||
//
|
const bool drawingDepth = Scene::SceneManager::IsDrawingDepth(DrawDepth::automatic);
|
||||||
//if (depth)
|
|
||||||
// ms_sb[SB_DEPTH]->Apply();
|
auto cb = renderer.GetCommandBuffer();
|
||||||
//else
|
|
||||||
// ms_sb[SB_MASTER]->Apply();
|
s_ubForestVS._matP = sm.GetCamera()->GetMatrixP().UniformBufferFormat();
|
||||||
//
|
s_ubForestVS._matWVP = sm.GetCamera()->GetMatrixVP().UniformBufferFormat();
|
||||||
//ms_cbPerFrame.matP = sm.GetCamera()->GetMatrixP().ConstBufferFormat();
|
s_ubForestVS._viewportSize = renderer.GetCommandBuffer()->GetViewportSize().GLM();
|
||||||
//ms_cbPerFrame.matWVP = sm.GetCamera()->GetMatrixVP().ConstBufferFormat();
|
s_ubForestVS._eyePos = float4(sm.GetCamera()->GetEyePosition().GLM(), 0);
|
||||||
//ms_cbPerFrame.viewportSize = render.GetViewportSize();
|
s_ubForestVS._eyePosScreen = float4(atmo.GetEyePosition().GLM(), 0);
|
||||||
//ms_cbPerFrame.eyePos = sm.GetCamera()->GetPositionEye();
|
|
||||||
//ms_cbPerFrame.posEyeScreen = Atmosphere::I().GetEyePosition();
|
cb->BindPipeline(_pipe[drawingDepth ? PIPE_DEPTH : PIPE_MAIN]);
|
||||||
//
|
cb->BindVertexBuffers(_geo);
|
||||||
//s_shader->Bind(depth ? "TDepth" : "T");
|
s_shader->BeginBindDescriptors();
|
||||||
//s_shader->UpdateBuffer(0);
|
cb->BindDescriptors(s_shader, 0);
|
||||||
//
|
for (auto& plant : _vPlants)
|
||||||
//_geo->BeginDraw(0x1);
|
{
|
||||||
//for (auto& plant : _vPlants)
|
if (!plant._csh.IsSet())
|
||||||
//{
|
continue;
|
||||||
// if (depth)
|
cb->BindDescriptors(s_shader, 1, plant._csh);
|
||||||
// {
|
for (auto& bc : plant._vBakedChunks)
|
||||||
// render->SetTextures({ plant._tex[Plant::TEX_GBUFFER_0] });
|
{
|
||||||
// }
|
if (bc._visible)
|
||||||
// else
|
cb->Draw(bc._vSprites.size(), 1, bc._vbOffset);
|
||||||
// {
|
}
|
||||||
// render->SetTextures(
|
}
|
||||||
// {
|
s_shader->EndBindDescriptors();
|
||||||
// plant._tex[Plant::TEX_GBUFFER_0],
|
}
|
||||||
// plant._tex[Plant::TEX_GBUFFER_2],
|
|
||||||
// plant._tex[Plant::TEX_GBUFFER_3]
|
void Forest::DrawAO()
|
||||||
// });
|
{
|
||||||
// }
|
if (!_visibleCount)
|
||||||
// for (auto& bc : plant._vBakedChunks)
|
return;
|
||||||
// {
|
|
||||||
// if (bc._visible)
|
VERUS_QREF_RENDERER;
|
||||||
// render->DrawPrimitive(CGI::PT_POINTLIST, bc._vbOffset, bc._vSprites.size());
|
VERUS_QREF_HELPERS;
|
||||||
// }
|
|
||||||
//}
|
CGI::LightType type = CGI::LightType::none;
|
||||||
//_geo->EndDraw(0x1);
|
PMesh pMesh = nullptr;
|
||||||
|
|
||||||
|
auto& ds = renderer.GetDS();
|
||||||
|
auto cb = renderer.GetCommandBuffer();
|
||||||
|
|
||||||
|
auto DrawMesh = [cb](PMesh pMesh)
|
||||||
|
{
|
||||||
|
if (pMesh && !pMesh->IsInstanceBufferEmpty(true))
|
||||||
|
{
|
||||||
|
pMesh->UpdateInstanceBuffer();
|
||||||
|
cb->DrawIndexed(pMesh->GetIndexCount(), pMesh->GetInstanceCount(true), 0, 0, pMesh->GetFirstInstance());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int i = 0; i <= _visibleCount; ++i)
|
||||||
|
{
|
||||||
|
if (i == _visibleCount) // The end?
|
||||||
|
{
|
||||||
|
DrawMesh(pMesh);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
RcDrawPlant drawPlant = _vDrawPlants[i];
|
||||||
|
RPlant plant = _vPlants[drawPlant._plantIndex];
|
||||||
|
|
||||||
|
const CGI::LightType nextType = CGI::LightType::omni;
|
||||||
|
|
||||||
|
if (nextType != type)
|
||||||
|
{
|
||||||
|
DrawMesh(pMesh);
|
||||||
|
|
||||||
|
type = nextType;
|
||||||
|
ds.OnNewAOType(cb, type);
|
||||||
|
|
||||||
|
pMesh = (type != CGI::LightType::none) ? &helpers.GetDeferredLights().Get(type) : nullptr;
|
||||||
|
|
||||||
|
if (pMesh)
|
||||||
|
{
|
||||||
|
pMesh->MarkFirstInstance();
|
||||||
|
pMesh->BindGeo(cb, (1 << 0) | (1 << 4));
|
||||||
|
pMesh->CopyPosDeqScale(&ds.GetUbAOPerMeshVS()._posDeqScale.x);
|
||||||
|
pMesh->CopyPosDeqBias(&ds.GetUbAOPerMeshVS()._posDeqBias.x);
|
||||||
|
ds.BindDescriptorsAOPerMeshVS(cb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pMesh)
|
||||||
|
{
|
||||||
|
const float size = drawPlant._scale * plant._aoSize;
|
||||||
|
const Transform3 matW = VMath::appendScale(Transform3(Matrix3::identity(),
|
||||||
|
Vector3(drawPlant._pos + drawPlant._pushBack + Vector3(0, size * 0.25f, 0))), Vector3::Replicate(size));
|
||||||
|
pMesh->PushInstance(matW, Vector4::Replicate(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Forest::SetLayer(int layer, RcLayerDesc desc)
|
void Forest::SetLayer(int layer, RcLayerDesc desc)
|
||||||
|
@ -402,18 +498,19 @@ void Forest::SetLayer(int layer, RcLayerDesc desc)
|
||||||
}
|
}
|
||||||
else // Add new plant?
|
else // Add new plant?
|
||||||
{
|
{
|
||||||
_vLayerPlants[layer]._plants[type] = _vPlants.size();
|
_vLayerPlants[layer]._plants[type] = Utils::Cast32(_vPlants.size());
|
||||||
_vPlants.resize(_vPlants.size() + 1);
|
_vPlants.resize(_vPlants.size() + 1);
|
||||||
RPlant plant = _vPlants[_vPlants.size() - 1];
|
RPlant plant = _vPlants[_vPlants.size() - 1];
|
||||||
plant._url = plantDesc._url;
|
plant._url = plantDesc._url;
|
||||||
plant._normal = plantDesc._normal;
|
plant._alignToNormal = plantDesc._alignToNormal;
|
||||||
|
plant._maxScale = plantDesc._maxScale;
|
||||||
|
plant._allowedNormal = plantDesc._allowedNormal;
|
||||||
const float ds = plantDesc._maxScale - plantDesc._minScale;
|
const float ds = plantDesc._maxScale - plantDesc._minScale;
|
||||||
const int count = 64;
|
const int count = 64;
|
||||||
plant._vScales.resize(count);
|
plant._vScales.resize(count);
|
||||||
VERUS_FOR(i, count)
|
VERUS_FOR(i, count)
|
||||||
plant._vScales[i] = plantDesc._minScale + ds * (i * i * i) / (count * count * count);
|
plant._vScales[i] = plantDesc._minScale + ds * (i * i * i) / (count * count * count);
|
||||||
std::shuffle(plant._vScales.begin(), plant._vScales.end(), random.GetGenerator());
|
std::shuffle(plant._vScales.begin(), plant._vScales.end(), random.GetGenerator());
|
||||||
plant._maxScale = plantDesc._maxScale;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -450,7 +547,7 @@ void Forest::BakeChunks(RPlant plant)
|
||||||
if (layer >= _vLayerPlants.size())
|
if (layer >= _vLayerPlants.size())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (_pTerrain->GetNormalAt(ij)[1] < plant._normal)
|
if (_pTerrain->GetNormalAt(ij)[1] < plant._allowedNormal)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
VERUS_FOR(type, SCATTER_TYPE_COUNT)
|
VERUS_FOR(type, SCATTER_TYPE_COUNT)
|
||||||
|
@ -480,8 +577,8 @@ void Forest::BakeChunks(RPlant plant)
|
||||||
xOffset - half + instance._x,
|
xOffset - half + instance._x,
|
||||||
hMin - psize * 0.05f,
|
hMin - psize * 0.05f,
|
||||||
zOffset - half + instance._z);
|
zOffset - half + instance._z);
|
||||||
v._tc[0] = Math::Clamp<int>(psize * 500, 0, SHRT_MAX);
|
v._tc[0] = Math::Clamp<int>(static_cast<int>(psize * 500), 0, SHRT_MAX);
|
||||||
v._tc[1] = Math::Clamp<int>(instance._angle * SHRT_MAX / VERUS_2PI, 0, SHRT_MAX);
|
v._tc[1] = Math::Clamp<int>(static_cast<int>(instance._angle * SHRT_MAX / VERUS_2PI), 0, SHRT_MAX);
|
||||||
v._pos.y += psize * 0.5f / _margin;
|
v._pos.y += psize * 0.5f / _margin;
|
||||||
if (!bc._vSprites.capacity())
|
if (!bc._vSprites.capacity())
|
||||||
bc._vSprites.reserve(256);
|
bc._vSprites.reserve(256);
|
||||||
|
@ -506,119 +603,216 @@ void Forest::BakeChunks(RPlant plant)
|
||||||
bool Forest::LoadSprite(RPlant plant)
|
bool Forest::LoadSprite(RPlant plant)
|
||||||
{
|
{
|
||||||
int count = 0;
|
int count = 0;
|
||||||
const CSZ ext2[] = { "", ".NM", ".FX" };
|
const CSZ ext[] = { "", ".FX", ".FX" };
|
||||||
VERUS_FOR(gb, 3)
|
VERUS_FOR(i, 3)
|
||||||
{
|
{
|
||||||
const int gbIndices[3] = { 0, 2, 3 };
|
String pathname = _C(plant._mesh.GetUrl());
|
||||||
const int gbIndex = gbIndices[gb];
|
char filename[20];
|
||||||
|
sprintf_s(filename, "GB%d%s.dds", i, ext[i]);
|
||||||
|
Str::ReplaceFilename(pathname, filename);
|
||||||
|
pathname = Str::ToPakFriendlyUrl(_C(pathname));
|
||||||
|
pathname = "[Textures]:Forest/" + pathname;
|
||||||
|
|
||||||
String path = _C(plant._mesh.GetUrl());
|
if (IO::FileSystem::FileExist(_C(pathname)))
|
||||||
char name[20];
|
|
||||||
sprintf_s(name, "GB%d%s.dds", gbIndex, ext2[gb]);
|
|
||||||
Str::ReplaceFilename(path, name);
|
|
||||||
Str::ReplaceAll(path, ":", "-");
|
|
||||||
Str::ReplaceAll(path, "/", ".");
|
|
||||||
|
|
||||||
const String url = "Textures:Forest/" + path;
|
|
||||||
|
|
||||||
if (IO::FileSystem::FileExist(_C(url)))
|
|
||||||
{
|
{
|
||||||
count++;
|
count++;
|
||||||
CGI::TextureDesc td;
|
plant._tex[i].Init(_C(pathname));
|
||||||
td._url = _C(url);
|
|
||||||
plant._tex[gb].Init(td);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 3 == count;
|
return 3 == count;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Forest::BakeSprite(RPlant plant)
|
void Forest::BakeSprite(RPlant plant, CSZ url)
|
||||||
{
|
{
|
||||||
//#ifdef _DEBUG
|
const bool drawingDepth = Scene::SceneManager::IsDrawingDepth(DrawDepth::automatic);
|
||||||
// const bool depth = Utils::IsDrawingDepth(DrawDepth::automatic);
|
if (drawingDepth)
|
||||||
// if (depth)
|
return;
|
||||||
// return;
|
|
||||||
//
|
VERUS_QREF_RENDERER;
|
||||||
// VERUS_QREF_RENDER;
|
VERUS_QREF_SM;
|
||||||
// VERUS_QREF_SM;
|
|
||||||
// VERUS_RT_ASSERT(render.GetDS().IsActiveGeometryPass());
|
CGI::CommandBufferPtr cb;
|
||||||
//
|
cb.InitOneTimeSubmit();
|
||||||
// const int frameSide = 512;
|
|
||||||
// const int framePad = 16;
|
const int frameSide = 512;
|
||||||
// const int numFramesH = 8;
|
const int framePad = 16;
|
||||||
// const int numFramesV = 4;
|
const int frameCountH = 16;
|
||||||
// const int texW = numFramesH * frameSide;
|
const int frameCountV = 16;
|
||||||
// const int texH = numFramesV * frameSide;
|
const int texWidth = frameCountH * frameSide;
|
||||||
// const float stepH = VERUS_2PI / numFramesH;
|
const int texHeight = frameCountV * frameSide;
|
||||||
// const float stepV = VERUS_PI / 2 / numFramesV;
|
const float stepH = VERUS_2PI / frameCountH;
|
||||||
//
|
const float stepV = VERUS_PI / 2 / frameCountV;
|
||||||
// CGI::DeferredShading ds;
|
|
||||||
// ds.InitGBuffers(texW, texH, true, true);
|
CGI::RPHandle rph = renderer->CreateRenderPass(
|
||||||
//
|
{
|
||||||
// ds.BeginGeometryPass(false, true);
|
CGI::RP::Attachment("GBuffer0", CGI::Format::srgbR8G8B8A8).LoadOpClear().Layout(CGI::ImageLayout::fsReadOnly),
|
||||||
// VERUS_FOR(i, numFramesV)
|
CGI::RP::Attachment("GBuffer1", CGI::Format::unormR10G10B10A2).LoadOpClear().Layout(CGI::ImageLayout::fsReadOnly),
|
||||||
// {
|
CGI::RP::Attachment("GBuffer2", CGI::Format::unormR8G8B8A8).LoadOpClear().Layout(CGI::ImageLayout::fsReadOnly),
|
||||||
// const Matrix3 matV = Matrix3::rotationX(-stepV * i);
|
CGI::RP::Attachment("Depth", CGI::Format::unormD24uintS8).LoadOpClear().Layout(CGI::ImageLayout::depthStencilAttachment, CGI::ImageLayout::depthStencilReadOnly),
|
||||||
// VERUS_FOR(j, numFramesH)
|
},
|
||||||
// {
|
{
|
||||||
// int vp[4] =
|
CGI::RP::Subpass("Sp0").Color(
|
||||||
// {
|
{
|
||||||
// j * frameSide + framePad,
|
CGI::RP::Ref("GBuffer0", CGI::ImageLayout::colorAttachment),
|
||||||
// i * frameSide + framePad,
|
CGI::RP::Ref("GBuffer1", CGI::ImageLayout::colorAttachment),
|
||||||
// frameSide - framePad * 2,
|
CGI::RP::Ref("GBuffer2", CGI::ImageLayout::colorAttachment)
|
||||||
// frameSide - framePad * 2,
|
}).DepthStencil(CGI::RP::Ref("Depth", CGI::ImageLayout::depthStencilAttachment))
|
||||||
// };
|
},
|
||||||
// render->SetViewport(vp);
|
{});
|
||||||
//
|
|
||||||
// const float size = plant.GetSize();
|
CGI::TexturePwn texGB[3], texDepth;
|
||||||
// const Matrix3 matH = Matrix3::rotationY(stepH * j);
|
CGI::TextureDesc texDesc;
|
||||||
// const Matrix3 matR = matH * matV;
|
texDesc._width = texWidth;
|
||||||
// const Vector3 offset = matR * Vector3(0, 0, size);
|
texDesc._height = texHeight;
|
||||||
//
|
texDesc._flags = CGI::TextureDesc::Flags::colorAttachment;
|
||||||
// Camera cam;
|
|
||||||
// cam.MoveAtTo(Vector3(0, size * 0.5f / m_margin, 0));
|
texDesc._clearValue = CGI::DeferredShading::GetClearValueForGBuffer0();
|
||||||
// cam.MoveEyeTo(Vector3(0, size * 0.5f / m_margin, 0) + offset);
|
texDesc._format = CGI::Format::srgbR8G8B8A8;
|
||||||
// cam.SetFOV(0);
|
texGB[0].Init(texDesc);
|
||||||
// cam.SetWidth(size * m_margin);
|
texDesc._clearValue = CGI::DeferredShading::GetClearValueForGBuffer1();
|
||||||
// cam.SetHeight(size * m_margin);
|
texDesc._format = CGI::Format::unormR10G10B10A2;
|
||||||
// cam.SetAspectRatio(1);
|
texGB[1].Init(texDesc);
|
||||||
// cam.SetZNear(0);
|
texDesc._clearValue = CGI::DeferredShading::GetClearValueForGBuffer2();
|
||||||
// cam.SetZFar(size * 2);
|
texDesc._format = CGI::Format::unormR8G8B8A8;
|
||||||
// cam.Update();
|
texGB[2].Init(texDesc);
|
||||||
// PCamera pPrevCamera = sm.SetCamera(&cam);
|
texDesc.Reset();
|
||||||
//
|
texDesc._clearValue = Vector4(1);
|
||||||
// Mesh::CDrawDesc dd;
|
texDesc._format = CGI::Format::unormD24uintS8;
|
||||||
// dd._material = plant._material;
|
texDesc._width = texWidth;
|
||||||
// dd._spriteBaking = true;
|
texDesc._height = texHeight;
|
||||||
// plant._mesh.Draw(dd);
|
texDepth.Init(texDesc);
|
||||||
//
|
|
||||||
// sm.SetCamera(pPrevCamera);
|
CGI::FBHandle fbh = renderer->CreateFramebuffer(rph,
|
||||||
// }
|
{
|
||||||
// }
|
texGB[0],
|
||||||
// ds.EndGeometryPass();
|
texGB[1],
|
||||||
//
|
texGB[2],
|
||||||
// Vector<UINT32> vData;
|
texDepth
|
||||||
// vData.resize(texW * texH);
|
},
|
||||||
// VERUS_FOR(gb, 3)
|
texWidth,
|
||||||
// {
|
texHeight);
|
||||||
// const int gbIndices[3] = { 0, 2, 3 };
|
|
||||||
// const int gbIndex = gbIndices[gb];
|
cb->BeginRenderPass(rph, fbh,
|
||||||
//
|
{
|
||||||
// ds.GetGBuffer(gbIndex)->GetTexImage(reinterpret_cast<BYTE*>(vData.data()));
|
texGB[0]->GetClearValue(),
|
||||||
//
|
texGB[1]->GetClearValue(),
|
||||||
// String path = _C(plant._mesh.GetUrl());
|
texGB[2]->GetClearValue(),
|
||||||
// char name[20];
|
texDepth->GetClearValue()
|
||||||
// sprintf_s(name, "GB%d.psd", gbIndex);
|
});
|
||||||
// Str::ReplaceFilename(path, name);
|
|
||||||
// Str::ReplaceAll(path, ":", "-");
|
plant._mesh.BindPipeline(cb, false);
|
||||||
// Str::ReplaceAll(path, "/", ".");
|
plant._mesh.BindGeo(cb);
|
||||||
// path = "D:\\Stuff\\Gulman\\Data\\Textures\\Forest/" + path;
|
Mesh::GetShader()->BeginBindDescriptors();
|
||||||
// IO::FileSystem::SaveImage(_C(path), vData.data(), texW, texH);
|
plant._material->UpdateMeshUniformBuffer();
|
||||||
// }
|
cb->BindDescriptors(Scene::Mesh::GetShader(), 1, plant._material->GetComplexSetHandle());
|
||||||
//
|
plant._mesh.UpdateUniformBufferPerMeshVS();
|
||||||
// render.GetDS().BeginGeometryPass(true);
|
cb->BindDescriptors(Scene::Mesh::GetShader(), 2);
|
||||||
// VERUS_RT_ASSERT(false);
|
plant._mesh.UpdateUniformBufferSkeletonVS();
|
||||||
//#endif
|
cb->BindDescriptors(Scene::Mesh::GetShader(), 3);
|
||||||
|
plant._mesh.UpdateUniformBufferPerObject(Transform3::identity());
|
||||||
|
cb->BindDescriptors(Scene::Mesh::GetShader(), 4);
|
||||||
|
VERUS_FOR(i, frameCountV)
|
||||||
|
{
|
||||||
|
const Matrix3 matV = Matrix3::rotationX(-stepV * i);
|
||||||
|
VERUS_FOR(j, frameCountH)
|
||||||
|
{
|
||||||
|
const Vector4 vp(
|
||||||
|
static_cast<float>(j * frameSide + framePad),
|
||||||
|
static_cast<float>(i * frameSide + framePad),
|
||||||
|
static_cast<float>(frameSide - framePad * 2),
|
||||||
|
static_cast<float>(frameSide - framePad * 2));
|
||||||
|
cb->SetViewport({ vp });
|
||||||
|
|
||||||
|
const float size = plant.GetSize();
|
||||||
|
const Matrix3 matH = Matrix3::rotationY(stepH * j);
|
||||||
|
const Matrix3 matR = matH * matV;
|
||||||
|
const Vector3 offset = matR * Vector3(0, 0, size);
|
||||||
|
|
||||||
|
Camera cam;
|
||||||
|
cam.MoveAtTo(Vector3(0, size * 0.5f / _margin, 0));
|
||||||
|
cam.MoveEyeTo(Vector3(0, size * 0.5f / _margin, 0) + offset);
|
||||||
|
cam.SetFovY(0);
|
||||||
|
cam.SetWidth(size * _margin);
|
||||||
|
cam.SetHeight(size * _margin);
|
||||||
|
cam.SetAspectRatio(1);
|
||||||
|
cam.SetZNear(0);
|
||||||
|
cam.SetZFar(size * 2);
|
||||||
|
cam.Update();
|
||||||
|
PCamera pPrevCamera = sm.SetCamera(&cam);
|
||||||
|
|
||||||
|
plant._mesh.UpdateUniformBufferPerFrame();
|
||||||
|
cb->BindDescriptors(Scene::Mesh::GetShader(), 0);
|
||||||
|
cb->DrawIndexed(plant._mesh.GetIndexCount());
|
||||||
|
|
||||||
|
sm.SetCamera(pPrevCamera);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Mesh::GetShader()->EndBindDescriptors();
|
||||||
|
|
||||||
|
cb->EndRenderPass();
|
||||||
|
|
||||||
|
CGI::TexturePwn texFinalGB[3];
|
||||||
|
texDesc.Reset();
|
||||||
|
texDesc._width = texWidth;
|
||||||
|
texDesc._height = texHeight;
|
||||||
|
texDesc._mipLevels = 0;
|
||||||
|
texDesc._flags = CGI::TextureDesc::Flags::colorAttachment | CGI::TextureDesc::Flags::generateMips;
|
||||||
|
texDesc._readbackMip = 2;
|
||||||
|
|
||||||
|
texDesc._clearValue = CGI::DeferredShading::GetClearValueForGBuffer0();
|
||||||
|
texDesc._format = CGI::Format::srgbR8G8B8A8;
|
||||||
|
texFinalGB[0].Init(texDesc);
|
||||||
|
texDesc._clearValue = CGI::DeferredShading::GetClearValueForGBuffer1();
|
||||||
|
texDesc._format = CGI::Format::unormR8G8B8A8;
|
||||||
|
texFinalGB[1].Init(texDesc);
|
||||||
|
texDesc._clearValue = CGI::DeferredShading::GetClearValueForGBuffer2();
|
||||||
|
texDesc._format = CGI::Format::unormR8G8B8A8;
|
||||||
|
texFinalGB[2].Init(texDesc);
|
||||||
|
|
||||||
|
renderer.GetDS().BakeSprites(texGB, texFinalGB, cb.Get());
|
||||||
|
|
||||||
|
VERUS_FOR(i, 3)
|
||||||
|
{
|
||||||
|
texFinalGB[i]->GenerateMips(cb.Get());
|
||||||
|
texFinalGB[i]->ReadbackSubresource(nullptr, true, cb.Get());
|
||||||
|
}
|
||||||
|
|
||||||
|
cb->DoneOneTimeSubmit();
|
||||||
|
|
||||||
|
const int mipWidth = texWidth / 4;
|
||||||
|
const int mipHeight = texHeight / 4;
|
||||||
|
Vector<UINT32> vData;
|
||||||
|
vData.resize(mipWidth * mipHeight);
|
||||||
|
const CSZ ext[] = { "", ".FX", ".FX" };
|
||||||
|
VERUS_FOR(i, 3)
|
||||||
|
{
|
||||||
|
texFinalGB[i]->ReadbackSubresource(vData.data(), false);
|
||||||
|
|
||||||
|
String pathname = _C(plant._mesh.GetUrl());
|
||||||
|
char filename[20];
|
||||||
|
sprintf_s(filename, "GB%d%s.psd", i, ext[i]);
|
||||||
|
Str::ReplaceFilename(pathname, filename);
|
||||||
|
pathname = Str::ToPakFriendlyUrl(_C(pathname));
|
||||||
|
pathname = String(url) + '/' + pathname;
|
||||||
|
IO::FileSystem::SaveImage(_C(pathname), vData.data(), mipWidth, mipHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer.GetDS().BakeSpritesCleanup();
|
||||||
|
renderer->DeleteFramebuffer(fbh);
|
||||||
|
renderer->DeleteRenderPass(rph);
|
||||||
|
renderer->DeleteCommandBuffer(cb.Detach());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Forest::BakeSprites(CSZ url)
|
||||||
|
{
|
||||||
|
for (auto& plant : _vPlants)
|
||||||
|
{
|
||||||
|
if (plant._mesh.IsLoaded() && plant._material->IsLoaded())
|
||||||
|
BakeSprite(plant, url);
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Forest::Scatter_AddInstance(const int ij[2], int type, float x, float z, float scale, float angle, UINT32 r)
|
void Forest::Scatter_AddInstance(const int ij[2], int type, float x, float z, float scale, float angle, UINT32 r)
|
||||||
|
@ -626,6 +820,8 @@ void Forest::Scatter_AddInstance(const int ij[2], int type, float x, float z, fl
|
||||||
if (_visibleCount == _vDrawPlants.size())
|
if (_visibleCount == _vDrawPlants.size())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
VERUS_QREF_ATMO;
|
||||||
|
|
||||||
const int layer = _pTerrain->GetMainLayerAt(ij);
|
const int layer = _pTerrain->GetMainLayerAt(ij);
|
||||||
if (layer >= _vLayerPlants.size())
|
if (layer >= _vLayerPlants.size())
|
||||||
return;
|
return;
|
||||||
|
@ -635,14 +831,15 @@ void Forest::Scatter_AddInstance(const int ij[2], int type, float x, float z, fl
|
||||||
|
|
||||||
const float h = _pTerrain->GetHeightAt(ij);
|
const float h = _pTerrain->GetHeightAt(ij);
|
||||||
Point3 pos(x, h, z);
|
Point3 pos(x, h, z);
|
||||||
RcPoint3 eyePos = Atmosphere::I().GetEyePosition();
|
RcPoint3 eyePos = atmo.GetEyePosition();
|
||||||
const float distSq = VMath::distSqr(eyePos, pos);
|
const float distSq = VMath::distSqr(eyePos, pos);
|
||||||
if (distSq >= _maxDist * _maxDist)
|
const float maxDistSq = _maxDist * _maxDist;
|
||||||
|
if (distSq >= maxDistSq)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
RPlant plant = _vPlants[plantIndex];
|
RPlant plant = _vPlants[plantIndex];
|
||||||
|
|
||||||
if (_pTerrain->GetNormalAt(ij)[1] < plant._normal)
|
if (_pTerrain->GetNormalAt(ij)[1] < plant._allowedNormal)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int ij4[2] = { ij[0], ij[1] };
|
int ij4[2] = { ij[0], ij[1] };
|
||||||
|
@ -652,26 +849,32 @@ void Forest::Scatter_AddInstance(const int ij[2], int type, float x, float z, fl
|
||||||
ij4[1]++; h4[2] = _pTerrain->GetHeightAt(ij4);
|
ij4[1]++; h4[2] = _pTerrain->GetHeightAt(ij4);
|
||||||
ij4[0]--; h4[3] = _pTerrain->GetHeightAt(ij4);
|
ij4[0]--; h4[3] = _pTerrain->GetHeightAt(ij4);
|
||||||
pos.setY(*std::min_element(h4 + 0, h4 + 4));
|
pos.setY(*std::min_element(h4 + 0, h4 + 4));
|
||||||
const float ratio = 1 - sqrt(distSq) / _maxDist;
|
|
||||||
const float t = Math::Clamp<float>((ratio - 0.1f) / 0.8f, 0, 1);
|
const float distFractionSq = distSq / maxDistSq;
|
||||||
|
const float alignToNormal = (1 - distFractionSq) * plant._alignToNormal;
|
||||||
|
const float t = Math::Clamp<float>((alignToNormal - 0.1f) / 0.8f, 0, 1);
|
||||||
|
|
||||||
Vector3 pushBack(0);
|
Vector3 pushBack(0);
|
||||||
Matrix3 matScale = Matrix3::identity();
|
Matrix3 matScale = Matrix3::identity();
|
||||||
if (ratio < 0.25f)
|
if (Scene::SceneManager::IsDrawingDepth(DrawDepth::automatic))
|
||||||
{
|
{
|
||||||
const float a = ratio * 4;
|
const float strength = Math::Clamp<float>((1 - distFractionSq) * 1.25f, 0, 1);
|
||||||
//if (Utils::IsDrawingDepth(DrawDepth::automatic))
|
matScale = Matrix3::scale(Vector3(strength, 0.5f + 0.5f * strength, strength));
|
||||||
//{
|
|
||||||
// const float b = Math::Clamp<float>((a - 0.5f) * 2, 0, 1);
|
|
||||||
// matScale = Matrix3::scale(Vector3(b, 1, b));
|
|
||||||
//}
|
|
||||||
pushBack = VMath::normalizeApprox(pos - eyePos) * plant._maxSize * (1 - a) * 0.4f;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const float strength = Math::Clamp<float>((distFractionSq - 0.5f) * 2, 0, 1);
|
||||||
|
const Point3 center = pos + Vector3(0, plant._maxSize * 0.5f, 0);
|
||||||
|
pushBack = VMath::normalizeApprox(center - eyePos) * plant._maxSize * strength;
|
||||||
|
}
|
||||||
|
|
||||||
DrawPlant drawPlant;
|
DrawPlant drawPlant;
|
||||||
drawPlant._basis = Matrix3::Lerp(Matrix3::identity(), _pTerrain->GetBasisAt(ij), t) * matScale;
|
drawPlant._basis = Matrix3::Lerp(Matrix3::identity(), _pTerrain->GetBasisAt(ij), t) * matScale;
|
||||||
drawPlant._pos = pos;
|
drawPlant._pos = pos;
|
||||||
drawPlant._pushBack = pushBack;
|
drawPlant._pushBack = pushBack;
|
||||||
drawPlant._scale = plant._vScales[r % plant._vScales.size()];
|
drawPlant._scale = plant._vScales[r % plant._vScales.size()];
|
||||||
drawPlant._angle = angle;
|
drawPlant._angle = angle;
|
||||||
|
drawPlant._distToEyeSq = distSq;
|
||||||
drawPlant._plantIndex = plantIndex;
|
drawPlant._plantIndex = plantIndex;
|
||||||
_vDrawPlants[_visibleCount++] = drawPlant;
|
_vDrawPlants[_visibleCount++] = drawPlant;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,14 @@ namespace verus
|
||||||
{
|
{
|
||||||
class Forest : public Object, public ScatterDelegate, public Math::OctreeDelegate
|
class Forest : public Object, public ScatterDelegate, public Math::OctreeDelegate
|
||||||
{
|
{
|
||||||
//#include "../Cg/DS_Forest.inc.cg"
|
#include "../Shaders/DS_Forest.inc.hlsl"
|
||||||
|
|
||||||
|
enum PIPE
|
||||||
|
{
|
||||||
|
PIPE_MAIN,
|
||||||
|
PIPE_DEPTH,
|
||||||
|
PIPE_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum SCATTER_TYPE
|
enum SCATTER_TYPE
|
||||||
|
@ -45,8 +52,8 @@ namespace verus
|
||||||
enum TEX
|
enum TEX
|
||||||
{
|
{
|
||||||
TEX_GBUFFER_0,
|
TEX_GBUFFER_0,
|
||||||
|
TEX_GBUFFER_1,
|
||||||
TEX_GBUFFER_2,
|
TEX_GBUFFER_2,
|
||||||
TEX_GBUFFER_3,
|
|
||||||
TEX_COUNT
|
TEX_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -54,11 +61,14 @@ namespace verus
|
||||||
Mesh _mesh;
|
Mesh _mesh;
|
||||||
MaterialPwn _material;
|
MaterialPwn _material;
|
||||||
CGI::TexturePwns<TEX_COUNT> _tex;
|
CGI::TexturePwns<TEX_COUNT> _tex;
|
||||||
|
CGI::CSHandle _csh;
|
||||||
Vector<BakedChunk> _vBakedChunks;
|
Vector<BakedChunk> _vBakedChunks;
|
||||||
Vector<float> _vScales;
|
Vector<float> _vScales;
|
||||||
|
float _alignToNormal = 1;
|
||||||
float _maxScale = 0;
|
float _maxScale = 0;
|
||||||
float _maxSize = 0;
|
float _maxSize = 0;
|
||||||
char _normal = 116;
|
float _aoSize = 1;
|
||||||
|
char _allowedNormal = 116;
|
||||||
|
|
||||||
float GetSize() const;
|
float GetSize() const;
|
||||||
};
|
};
|
||||||
|
@ -84,15 +94,18 @@ namespace verus
|
||||||
Vector3 _pushBack = Vector3(0);
|
Vector3 _pushBack = Vector3(0);
|
||||||
float _scale = 1;
|
float _scale = 1;
|
||||||
float _angle = 0;
|
float _angle = 0;
|
||||||
|
float _distToEyeSq = 0;
|
||||||
int _plantIndex = 0;
|
int _plantIndex = 0;
|
||||||
};
|
};
|
||||||
VERUS_TYPEDEFS(DrawPlant);
|
VERUS_TYPEDEFS(DrawPlant);
|
||||||
|
|
||||||
static CGI::ShaderPwn s_shader;
|
static CGI::ShaderPwn s_shader;
|
||||||
//static CGI::CStateBlockPwns<SB_MAX> ms_sb;
|
static UB_ForestVS s_ubForestVS;
|
||||||
|
static UB_ForestFS s_ubForestFS;
|
||||||
|
|
||||||
PTerrain _pTerrain = nullptr;
|
PTerrain _pTerrain = nullptr;
|
||||||
CGI::GeometryPwn _geo;
|
CGI::GeometryPwn _geo;
|
||||||
|
CGI::PipelinePwns<PIPE_COUNT> _pipe;
|
||||||
Math::Octree _octree;
|
Math::Octree _octree;
|
||||||
Scatter _scatter;
|
Scatter _scatter;
|
||||||
Vector<Plant> _vPlants;
|
Vector<Plant> _vPlants;
|
||||||
|
@ -100,6 +113,7 @@ namespace verus
|
||||||
Vector<DrawPlant> _vDrawPlants;
|
Vector<DrawPlant> _vDrawPlants;
|
||||||
const float _margin = 1.1f;
|
const float _margin = 1.1f;
|
||||||
float _maxDist = 100;
|
float _maxDist = 100;
|
||||||
|
float _tessDist = 50;
|
||||||
float _maxSizeAll = 0;
|
float _maxSizeAll = 0;
|
||||||
int _capacity = 4000;
|
int _capacity = 4000;
|
||||||
int _visibleCount = 0;
|
int _visibleCount = 0;
|
||||||
|
@ -110,16 +124,18 @@ namespace verus
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CSZ _url = nullptr;
|
CSZ _url = nullptr;
|
||||||
|
float _alignToNormal = 1;
|
||||||
float _minScale = 0.5f;
|
float _minScale = 0.5f;
|
||||||
float _maxScale = 1.5f;
|
float _maxScale = 1.5f;
|
||||||
char _normal = 116;
|
char _allowedNormal = 116;
|
||||||
|
|
||||||
void Set(CSZ url, float minScale = 0.5f, float maxScale = 1.5f, char normal = 116)
|
void Set(CSZ url, float alignToNormal = 1, float minScale = 0.5f, float maxScale = 1.5f, char allowedNormal = 116)
|
||||||
{
|
{
|
||||||
_url = url;
|
_url = url;
|
||||||
|
_alignToNormal = alignToNormal;
|
||||||
_minScale = minScale;
|
_minScale = minScale;
|
||||||
_maxScale = maxScale;
|
_maxScale = maxScale;
|
||||||
_normal = normal;
|
_allowedNormal = allowedNormal;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
VERUS_TYPEDEFS(PlantDesc);
|
VERUS_TYPEDEFS(PlantDesc);
|
||||||
|
@ -143,12 +159,12 @@ namespace verus
|
||||||
void Done();
|
void Done();
|
||||||
|
|
||||||
void ResetInstanceCount();
|
void ResetInstanceCount();
|
||||||
|
|
||||||
void Update();
|
void Update();
|
||||||
void Layout();
|
void Layout();
|
||||||
void Draw();
|
void Draw(bool allowTess = true);
|
||||||
VERUS_P(void DrawModels());
|
VERUS_P(void DrawModels(bool allowTess));
|
||||||
VERUS_P(void DrawSprites());
|
VERUS_P(void DrawSprites());
|
||||||
|
void DrawAO();
|
||||||
|
|
||||||
PTerrain SetTerrain(PTerrain p) { return Utils::Swap(_pTerrain, p); }
|
PTerrain SetTerrain(PTerrain p) { return Utils::Swap(_pTerrain, p); }
|
||||||
|
|
||||||
|
@ -156,7 +172,8 @@ namespace verus
|
||||||
VERUS_P(int FindPlant(CSZ url) const);
|
VERUS_P(int FindPlant(CSZ url) const);
|
||||||
VERUS_P(void BakeChunks(RPlant plant));
|
VERUS_P(void BakeChunks(RPlant plant));
|
||||||
bool LoadSprite(RPlant plant);
|
bool LoadSprite(RPlant plant);
|
||||||
void BakeSprite(RPlant plant);
|
void BakeSprite(RPlant plant, CSZ url);
|
||||||
|
bool BakeSprites(CSZ url);
|
||||||
|
|
||||||
virtual void Scatter_AddInstance(const int ij[2], int type, float x, float z,
|
virtual void Scatter_AddInstance(const int ij[2], int type, float x, float z,
|
||||||
float scale, float angle, UINT32 r) override;
|
float scale, float angle, UINT32 r) override;
|
||||||
|
|
|
@ -157,6 +157,11 @@ void Grass::Done()
|
||||||
VERUS_DONE(Grass);
|
VERUS_DONE(Grass);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Grass::ResetInstanceCount()
|
||||||
|
{
|
||||||
|
_instanceCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
void Grass::Update()
|
void Grass::Update()
|
||||||
{
|
{
|
||||||
VERUS_UPDATE_ONCE_CHECK;
|
VERUS_UPDATE_ONCE_CHECK;
|
||||||
|
@ -209,13 +214,13 @@ void Grass::Draw()
|
||||||
VERUS_QREF_SM;
|
VERUS_QREF_SM;
|
||||||
VERUS_RT_ASSERT(_pTerrain->GetMapSide() == _mapSide);
|
VERUS_RT_ASSERT(_pTerrain->GetMapSide() == _mapSide);
|
||||||
|
|
||||||
auto cb = renderer.GetCommandBuffer();
|
|
||||||
|
|
||||||
const bool drawingDepth = Scene::SceneManager::IsDrawingDepth(Scene::DrawDepth::automatic);
|
const bool drawingDepth = Scene::SceneManager::IsDrawingDepth(Scene::DrawDepth::automatic);
|
||||||
|
|
||||||
const UINT32 bushMask = _bushMask & 0xFF; // Use only first 8 bushes, next 8 are reserved.
|
const UINT32 bushMask = _bushMask & 0xFF; // Use only first 8 bushes, next 8 are reserved.
|
||||||
const int half = _mapSide >> 1;
|
const int half = _mapSide >> 1;
|
||||||
|
|
||||||
|
auto cb = renderer.GetCommandBuffer();
|
||||||
|
|
||||||
s_ubGrassVS._matW = Transform3::UniformBufferFormatIdentity();
|
s_ubGrassVS._matW = Transform3::UniformBufferFormatIdentity();
|
||||||
s_ubGrassVS._matWV = sm.GetCamera()->GetMatrixV().UniformBufferFormat();
|
s_ubGrassVS._matWV = sm.GetCamera()->GetMatrixV().UniformBufferFormat();
|
||||||
s_ubGrassVS._matVP = sm.GetCamera()->GetMatrixVP().UniformBufferFormat();
|
s_ubGrassVS._matVP = sm.GetCamera()->GetMatrixVP().UniformBufferFormat();
|
||||||
|
@ -277,11 +282,6 @@ void Grass::Draw()
|
||||||
_geo->UpdateVertexBuffer(_vInstanceBuffer.data(), 1);
|
_geo->UpdateVertexBuffer(_vInstanceBuffer.data(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Grass::ResetInstanceCount()
|
|
||||||
{
|
|
||||||
_instanceCount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Grass::QuadtreeIntegral_ProcessVisibleNode(const short ij[2], RcPoint3 center)
|
void Grass::QuadtreeIntegral_ProcessVisibleNode(const short ij[2], RcPoint3 center)
|
||||||
{
|
{
|
||||||
VERUS_QREF_ATMO;
|
VERUS_QREF_ATMO;
|
||||||
|
|
|
@ -92,12 +92,11 @@ namespace verus
|
||||||
void Init(RTerrain terrain);
|
void Init(RTerrain terrain);
|
||||||
void Done();
|
void Done();
|
||||||
|
|
||||||
|
void ResetInstanceCount();
|
||||||
void Update();
|
void Update();
|
||||||
void Layout();
|
void Layout();
|
||||||
void Draw();
|
void Draw();
|
||||||
|
|
||||||
void ResetInstanceCount();
|
|
||||||
|
|
||||||
virtual void QuadtreeIntegral_ProcessVisibleNode(const short ij[2], RcPoint3 center) override;
|
virtual void QuadtreeIntegral_ProcessVisibleNode(const short ij[2], RcPoint3 center) override;
|
||||||
virtual void QuadtreeIntegral_GetHeights(const short ij[2], float height[2]) override;
|
virtual void QuadtreeIntegral_GetHeights(const short ij[2], float height[2]) override;
|
||||||
|
|
||||||
|
|
|
@ -335,8 +335,8 @@ String Material::ToString(bool cleanDict)
|
||||||
|
|
||||||
CSZ empty = "";
|
CSZ empty = "";
|
||||||
|
|
||||||
CGI::PBaseTexture pTexAlbedo = &(*_texAlbedo->GetTex());
|
CGI::PBaseTexture pTexAlbedo = _texAlbedo->GetTex().Get();
|
||||||
CGI::PBaseTexture pTexNormal = &(*_texNormal->GetTex());
|
CGI::PBaseTexture pTexNormal = _texNormal->GetTex().Get();
|
||||||
|
|
||||||
_dict.Insert("alphaSwitch", /**/_C(Str::ToString(_alphaSwitch)));
|
_dict.Insert("alphaSwitch", /**/_C(Str::ToString(_alphaSwitch)));
|
||||||
_dict.Insert("anisoSpecDir", /**/_C(Str::ToString(_anisoSpecDir)));
|
_dict.Insert("anisoSpecDir", /**/_C(Str::ToString(_anisoSpecDir)));
|
||||||
|
|
|
@ -59,6 +59,7 @@ void Mesh::Init(RcDesc desc)
|
||||||
}
|
}
|
||||||
|
|
||||||
_instanceCapacity = desc._instanceCapacity;
|
_instanceCapacity = desc._instanceCapacity;
|
||||||
|
_initShape = desc._initShape;
|
||||||
|
|
||||||
BaseMesh::Init(desc._url);
|
BaseMesh::Init(desc._url);
|
||||||
}
|
}
|
||||||
|
@ -70,19 +71,19 @@ void Mesh::Done()
|
||||||
|
|
||||||
void Mesh::Draw(RcDrawDesc dd, CGI::CommandBufferPtr cb)
|
void Mesh::Draw(RcDrawDesc dd, CGI::CommandBufferPtr cb)
|
||||||
{
|
{
|
||||||
BindGeo(cb);
|
|
||||||
BindPipeline(cb, dd._allowTess);
|
BindPipeline(cb, dd._allowTess);
|
||||||
|
BindGeo(cb);
|
||||||
|
|
||||||
UpdateUniformBufferPerFrame();
|
UpdateUniformBufferPerFrame();
|
||||||
cb->BindDescriptors(Scene::Mesh::GetShader(), 0);
|
cb->BindDescriptors(GetShader(), 0);
|
||||||
UpdateUniformBufferPerMaterialFS();
|
// Material buffer should already be updated. For example call Material::UpdateMeshUniformBuffer.
|
||||||
cb->BindDescriptors(Scene::Mesh::GetShader(), 1, dd._cshMaterial);
|
cb->BindDescriptors(GetShader(), 1, dd._cshMaterial);
|
||||||
UpdateUniformBufferPerMeshVS();
|
UpdateUniformBufferPerMeshVS();
|
||||||
cb->BindDescriptors(Scene::Mesh::GetShader(), 2);
|
cb->BindDescriptors(GetShader(), 2);
|
||||||
UpdateUniformBufferSkeletonVS();
|
UpdateUniformBufferSkeletonVS();
|
||||||
cb->BindDescriptors(Scene::Mesh::GetShader(), 3);
|
cb->BindDescriptors(GetShader(), 3);
|
||||||
UpdateUniformBufferPerObject(dd._matW);
|
UpdateUniformBufferPerObject(dd._matW);
|
||||||
cb->BindDescriptors(Scene::Mesh::GetShader(), 4);
|
cb->BindDescriptors(GetShader(), 4);
|
||||||
|
|
||||||
cb->DrawIndexed(GetIndexCount());
|
cb->DrawIndexed(GetIndexCount());
|
||||||
}
|
}
|
||||||
|
@ -98,8 +99,16 @@ void Mesh::BindPipeline(PIPE pipe, CGI::CommandBufferPtr cb)
|
||||||
switch (pipe)
|
switch (pipe)
|
||||||
{
|
{
|
||||||
case PIPE_TESS: pipe = PIPE_MAIN; break;
|
case PIPE_TESS: pipe = PIPE_MAIN; break;
|
||||||
|
case PIPE_TESS_INSTANCED: pipe = PIPE_INSTANCED; break;
|
||||||
|
case PIPE_TESS_PLANT: pipe = PIPE_PLANT; break;
|
||||||
case PIPE_TESS_ROBOTIC: pipe = PIPE_ROBOTIC; break;
|
case PIPE_TESS_ROBOTIC: pipe = PIPE_ROBOTIC; break;
|
||||||
case PIPE_TESS_SKINNED: pipe = PIPE_SKINNED; break;
|
case PIPE_TESS_SKINNED: pipe = PIPE_SKINNED; break;
|
||||||
|
|
||||||
|
case PIPE_DEPTH_TESS: pipe = PIPE_DEPTH; break;
|
||||||
|
case PIPE_DEPTH_TESS_INSTANCED: pipe = PIPE_DEPTH_INSTANCED; break;
|
||||||
|
case PIPE_DEPTH_TESS_PLANT: pipe = PIPE_DEPTH_PLANT; break;
|
||||||
|
case PIPE_DEPTH_TESS_ROBOTIC: pipe = PIPE_DEPTH_ROBOTIC; break;
|
||||||
|
case PIPE_DEPTH_TESS_SKINNED: pipe = PIPE_DEPTH_SKINNED; break;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,18 +118,27 @@ void Mesh::BindPipeline(PIPE pipe, CGI::CommandBufferPtr cb)
|
||||||
{
|
{
|
||||||
"#",
|
"#",
|
||||||
"#Instanced",
|
"#Instanced",
|
||||||
|
"#Plant",
|
||||||
"#Robotic",
|
"#Robotic",
|
||||||
"#Skinned",
|
"#Skinned",
|
||||||
|
|
||||||
|
"#Tess",
|
||||||
|
"#TessInstanced",
|
||||||
|
"#TessPlant",
|
||||||
|
"#TessRobotic",
|
||||||
|
"#TessSkinned",
|
||||||
|
|
||||||
"#Depth",
|
"#Depth",
|
||||||
"#DepthInstanced",
|
"#DepthInstanced",
|
||||||
|
"#DepthPlant",
|
||||||
"#DepthRobotic",
|
"#DepthRobotic",
|
||||||
"#DepthSkinned",
|
"#DepthSkinned",
|
||||||
|
|
||||||
"#Tess",
|
"#DepthTess",
|
||||||
"#TessInstanced",
|
"#DepthTessInstanced",
|
||||||
"#TessRobotic",
|
"#DepthTessPlant",
|
||||||
"#TessSkinned",
|
"#DepthTessRobotic",
|
||||||
|
"#DepthTessSkinned",
|
||||||
|
|
||||||
"#SolidColor",
|
"#SolidColor",
|
||||||
"#SolidColorInstanced",
|
"#SolidColorInstanced",
|
||||||
|
@ -141,14 +159,27 @@ void Mesh::BindPipeline(PIPE pipe, CGI::CommandBufferPtr cb)
|
||||||
{
|
{
|
||||||
case PIPE_MAIN:
|
case PIPE_MAIN:
|
||||||
case PIPE_INSTANCED:
|
case PIPE_INSTANCED:
|
||||||
|
case PIPE_PLANT:
|
||||||
case PIPE_ROBOTIC:
|
case PIPE_ROBOTIC:
|
||||||
case PIPE_SKINNED:
|
case PIPE_SKINNED:
|
||||||
{
|
{
|
||||||
SetBlendEqsForDS();
|
SetBlendEqsForDS();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case PIPE_TESS:
|
||||||
|
case PIPE_TESS_INSTANCED:
|
||||||
|
case PIPE_TESS_PLANT:
|
||||||
|
case PIPE_TESS_ROBOTIC:
|
||||||
|
case PIPE_TESS_SKINNED:
|
||||||
|
{
|
||||||
|
SetBlendEqsForDS();
|
||||||
|
if (settings._gpuTessellation)
|
||||||
|
pipeDesc._topology = CGI::PrimitiveTopology::patchList3;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case PIPE_DEPTH:
|
case PIPE_DEPTH:
|
||||||
case PIPE_DEPTH_INSTANCED:
|
case PIPE_DEPTH_INSTANCED:
|
||||||
|
case PIPE_DEPTH_PLANT:
|
||||||
case PIPE_DEPTH_ROBOTIC:
|
case PIPE_DEPTH_ROBOTIC:
|
||||||
case PIPE_DEPTH_SKINNED:
|
case PIPE_DEPTH_SKINNED:
|
||||||
{
|
{
|
||||||
|
@ -156,12 +187,14 @@ void Mesh::BindPipeline(PIPE pipe, CGI::CommandBufferPtr cb)
|
||||||
pipeDesc._renderPassHandle = atmo.GetShadowMap().GetRenderPassHandle();
|
pipeDesc._renderPassHandle = atmo.GetShadowMap().GetRenderPassHandle();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PIPE_TESS:
|
case PIPE_DEPTH_TESS:
|
||||||
case PIPE_TESS_INSTANCED:
|
case PIPE_DEPTH_TESS_INSTANCED:
|
||||||
case PIPE_TESS_ROBOTIC:
|
case PIPE_DEPTH_TESS_PLANT:
|
||||||
case PIPE_TESS_SKINNED:
|
case PIPE_DEPTH_TESS_ROBOTIC:
|
||||||
|
case PIPE_DEPTH_TESS_SKINNED:
|
||||||
{
|
{
|
||||||
SetBlendEqsForDS();
|
pipeDesc._colorAttachBlendEqs[0] = "";
|
||||||
|
pipeDesc._renderPassHandle = atmo.GetShadowMap().GetRenderPassHandle();
|
||||||
if (settings._gpuTessellation)
|
if (settings._gpuTessellation)
|
||||||
pipeDesc._topology = CGI::PrimitiveTopology::patchList3;
|
pipeDesc._topology = CGI::PrimitiveTopology::patchList3;
|
||||||
}
|
}
|
||||||
|
@ -195,32 +228,56 @@ void Mesh::BindPipeline(CGI::CommandBufferPtr cb, bool allowTess)
|
||||||
if (_skeleton.IsInitialized())
|
if (_skeleton.IsInitialized())
|
||||||
{
|
{
|
||||||
if (atmo.GetShadowMap().IsRendering())
|
if (atmo.GetShadowMap().IsRendering())
|
||||||
BindPipeline(Scene::Mesh::PIPE_DEPTH_SKINNED, cb);
|
{
|
||||||
else if (allowTess)
|
if (allowTess)
|
||||||
BindPipeline(Scene::Mesh::PIPE_TESS_SKINNED, cb);
|
BindPipeline(PIPE_DEPTH_TESS_SKINNED, cb);
|
||||||
else
|
else
|
||||||
BindPipeline(Scene::Mesh::PIPE_SKINNED, cb);
|
BindPipeline(PIPE_DEPTH_SKINNED, cb);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (allowTess)
|
||||||
|
BindPipeline(PIPE_TESS_SKINNED, cb);
|
||||||
|
else
|
||||||
|
BindPipeline(PIPE_SKINNED, cb);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (atmo.GetShadowMap().IsRendering())
|
if (atmo.GetShadowMap().IsRendering())
|
||||||
BindPipeline(Scene::Mesh::PIPE_DEPTH, cb);
|
{
|
||||||
else if (allowTess)
|
if (allowTess)
|
||||||
BindPipeline(Scene::Mesh::PIPE_TESS, cb);
|
BindPipeline(PIPE_DEPTH_TESS, cb);
|
||||||
else
|
else
|
||||||
BindPipeline(Scene::Mesh::PIPE_MAIN, cb);
|
BindPipeline(PIPE_DEPTH, cb);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (allowTess)
|
||||||
|
BindPipeline(PIPE_TESS, cb);
|
||||||
|
else
|
||||||
|
BindPipeline(PIPE_MAIN, cb);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mesh::BindPipelineInstanced(CGI::CommandBufferPtr cb, bool allowTess)
|
void Mesh::BindPipelineInstanced(CGI::CommandBufferPtr cb, bool allowTess, bool plant)
|
||||||
{
|
{
|
||||||
VERUS_QREF_ATMO;
|
VERUS_QREF_ATMO;
|
||||||
if (atmo.GetShadowMap().IsRendering())
|
if (atmo.GetShadowMap().IsRendering())
|
||||||
BindPipeline(Scene::Mesh::PIPE_DEPTH_INSTANCED, cb);
|
{
|
||||||
else if (allowTess)
|
if (allowTess)
|
||||||
BindPipeline(Scene::Mesh::PIPE_TESS_INSTANCED, cb);
|
BindPipeline(plant ? PIPE_DEPTH_TESS_PLANT : PIPE_DEPTH_TESS_INSTANCED, cb);
|
||||||
else
|
else
|
||||||
BindPipeline(Scene::Mesh::PIPE_INSTANCED, cb);
|
BindPipeline(plant ? PIPE_DEPTH_PLANT : PIPE_DEPTH_INSTANCED, cb);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (allowTess)
|
||||||
|
BindPipeline(plant ? PIPE_TESS_PLANT : PIPE_TESS_INSTANCED, cb);
|
||||||
|
else
|
||||||
|
BindPipeline(plant ? PIPE_PLANT : PIPE_INSTANCED, cb);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mesh::BindGeo(CGI::CommandBufferPtr cb)
|
void Mesh::BindGeo(CGI::CommandBufferPtr cb)
|
||||||
|
@ -234,18 +291,20 @@ void Mesh::BindGeo(CGI::CommandBufferPtr cb, UINT32 bindingsFilter)
|
||||||
cb->BindIndexBuffer(_geo);
|
cb->BindIndexBuffer(_geo);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mesh::UpdateUniformBufferPerFrame()
|
void Mesh::UpdateUniformBufferPerFrame(float invTessDist)
|
||||||
{
|
{
|
||||||
VERUS_QREF_RENDERER;
|
VERUS_QREF_RENDERER;
|
||||||
VERUS_QREF_SM;
|
VERUS_QREF_SM;
|
||||||
|
VERUS_QREF_ATMO;
|
||||||
|
|
||||||
|
RcPoint3 eyePos = atmo.GetEyePosition();
|
||||||
|
Point3 eyePosWV = sm.GetCamera()->GetMatrixV() * eyePos;
|
||||||
|
|
||||||
s_ubPerFrame._matV = sm.GetCamera()->GetMatrixV().UniformBufferFormat();
|
s_ubPerFrame._matV = sm.GetCamera()->GetMatrixV().UniformBufferFormat();
|
||||||
s_ubPerFrame._matVP = sm.GetCamera()->GetMatrixVP().UniformBufferFormat();
|
s_ubPerFrame._matVP = sm.GetCamera()->GetMatrixVP().UniformBufferFormat();
|
||||||
s_ubPerFrame._matP = sm.GetCamera()->GetMatrixP().UniformBufferFormat();
|
s_ubPerFrame._matP = sm.GetCamera()->GetMatrixP().UniformBufferFormat();
|
||||||
s_ubPerFrame._viewportSize = renderer.GetCommandBuffer()->GetViewportSize().GLM();
|
s_ubPerFrame._viewportSize = renderer.GetCommandBuffer()->GetViewportSize().GLM();
|
||||||
}
|
s_ubPerFrame._eyePosWV_invTessDistSq = float4(eyePosWV.GLM(), invTessDist * invTessDist);
|
||||||
|
|
||||||
void Mesh::UpdateUniformBufferPerMaterialFS()
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mesh::UpdateUniformBufferPerMeshVS()
|
void Mesh::UpdateUniformBufferPerMeshVS()
|
||||||
|
@ -354,7 +413,7 @@ void Mesh::CreateDeviceBuffers()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Instance buffer:
|
// Instance buffer:
|
||||||
if (_instanceCapacity > 1)
|
if (_instanceCapacity > 0)
|
||||||
{
|
{
|
||||||
_vInstanceBuffer.resize(_instanceCapacity);
|
_vInstanceBuffer.resize(_instanceCapacity);
|
||||||
_bindingsMask |= (1 << 4);
|
_bindingsMask |= (1 << 4);
|
||||||
|
@ -367,8 +426,15 @@ void Mesh::UpdateVertexBuffer(const void* p, int binding)
|
||||||
_geo->UpdateVertexBuffer(p, binding);
|
_geo->UpdateVertexBuffer(p, binding);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Mesh::ResetInstanceCount()
|
||||||
|
{
|
||||||
|
_instanceCount = 0;
|
||||||
|
_firstInstance = 0;
|
||||||
|
}
|
||||||
|
|
||||||
void Mesh::PushInstance(RcTransform3 matW, RcVector4 instData)
|
void Mesh::PushInstance(RcTransform3 matW, RcVector4 instData)
|
||||||
{
|
{
|
||||||
|
VERUS_RT_ASSERT(!_vInstanceBuffer.empty());
|
||||||
if (!_vertCount)
|
if (!_vertCount)
|
||||||
return;
|
return;
|
||||||
if (IsInstanceBufferFull())
|
if (IsInstanceBufferFull())
|
||||||
|
@ -380,6 +446,7 @@ void Mesh::PushInstance(RcTransform3 matW, RcVector4 instData)
|
||||||
|
|
||||||
bool Mesh::IsInstanceBufferFull()
|
bool Mesh::IsInstanceBufferFull()
|
||||||
{
|
{
|
||||||
|
VERUS_RT_ASSERT(!_vInstanceBuffer.empty());
|
||||||
if (!_vertCount)
|
if (!_vertCount)
|
||||||
return false;
|
return false;
|
||||||
return _instanceCount >= _instanceCapacity;
|
return _instanceCount >= _instanceCapacity;
|
||||||
|
@ -387,18 +454,14 @@ bool Mesh::IsInstanceBufferFull()
|
||||||
|
|
||||||
bool Mesh::IsInstanceBufferEmpty(bool fromFirstInstance)
|
bool Mesh::IsInstanceBufferEmpty(bool fromFirstInstance)
|
||||||
{
|
{
|
||||||
|
VERUS_RT_ASSERT(!_vInstanceBuffer.empty());
|
||||||
if (!_vertCount)
|
if (!_vertCount)
|
||||||
return true;
|
return true;
|
||||||
return GetInstanceCount(fromFirstInstance) <= 0;
|
return GetInstanceCount(fromFirstInstance) <= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mesh::ResetInstanceCount()
|
|
||||||
{
|
|
||||||
_instanceCount = 0;
|
|
||||||
_firstInstance = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mesh::UpdateInstanceBuffer()
|
void Mesh::UpdateInstanceBuffer()
|
||||||
{
|
{
|
||||||
|
VERUS_RT_ASSERT(!_vInstanceBuffer.empty());
|
||||||
_geo->UpdateVertexBuffer(_vInstanceBuffer.data(), 4);
|
_geo->UpdateVertexBuffer(_vInstanceBuffer.data(), 4);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,18 +13,27 @@ namespace verus
|
||||||
{
|
{
|
||||||
PIPE_MAIN,
|
PIPE_MAIN,
|
||||||
PIPE_INSTANCED,
|
PIPE_INSTANCED,
|
||||||
|
PIPE_PLANT,
|
||||||
PIPE_ROBOTIC,
|
PIPE_ROBOTIC,
|
||||||
PIPE_SKINNED,
|
PIPE_SKINNED,
|
||||||
|
|
||||||
|
PIPE_TESS,
|
||||||
|
PIPE_TESS_INSTANCED,
|
||||||
|
PIPE_TESS_PLANT,
|
||||||
|
PIPE_TESS_ROBOTIC,
|
||||||
|
PIPE_TESS_SKINNED,
|
||||||
|
|
||||||
PIPE_DEPTH,
|
PIPE_DEPTH,
|
||||||
PIPE_DEPTH_INSTANCED,
|
PIPE_DEPTH_INSTANCED,
|
||||||
|
PIPE_DEPTH_PLANT,
|
||||||
PIPE_DEPTH_ROBOTIC,
|
PIPE_DEPTH_ROBOTIC,
|
||||||
PIPE_DEPTH_SKINNED,
|
PIPE_DEPTH_SKINNED,
|
||||||
|
|
||||||
PIPE_TESS,
|
PIPE_DEPTH_TESS,
|
||||||
PIPE_TESS_INSTANCED,
|
PIPE_DEPTH_TESS_INSTANCED,
|
||||||
PIPE_TESS_ROBOTIC,
|
PIPE_DEPTH_TESS_PLANT,
|
||||||
PIPE_TESS_SKINNED,
|
PIPE_DEPTH_TESS_ROBOTIC,
|
||||||
|
PIPE_DEPTH_TESS_SKINNED,
|
||||||
|
|
||||||
PIPE_WIREFRAME,
|
PIPE_WIREFRAME,
|
||||||
PIPE_WIREFRAME_INSTANCED,
|
PIPE_WIREFRAME_INSTANCED,
|
||||||
|
@ -63,7 +72,8 @@ namespace verus
|
||||||
{
|
{
|
||||||
CSZ _url = nullptr;
|
CSZ _url = nullptr;
|
||||||
CSZ _warpUrl = nullptr;
|
CSZ _warpUrl = nullptr;
|
||||||
int _instanceCapacity = 1;
|
int _instanceCapacity = 0;
|
||||||
|
bool _initShape = false;
|
||||||
|
|
||||||
Desc(CSZ url = nullptr) : _url(url) {}
|
Desc(CSZ url = nullptr) : _url(url) {}
|
||||||
};
|
};
|
||||||
|
@ -90,14 +100,13 @@ namespace verus
|
||||||
|
|
||||||
void BindPipeline(PIPE pipe, CGI::CommandBufferPtr cb);
|
void BindPipeline(PIPE pipe, CGI::CommandBufferPtr cb);
|
||||||
void BindPipeline(CGI::CommandBufferPtr cb, bool allowTess = true);
|
void BindPipeline(CGI::CommandBufferPtr cb, bool allowTess = true);
|
||||||
void BindPipelineInstanced(CGI::CommandBufferPtr cb, bool allowTess = true);
|
void BindPipelineInstanced(CGI::CommandBufferPtr cb, bool allowTess = true, bool plant = false);
|
||||||
void BindGeo(CGI::CommandBufferPtr cb);
|
void BindGeo(CGI::CommandBufferPtr cb);
|
||||||
void BindGeo(CGI::CommandBufferPtr cb, UINT32 bindingsFilter);
|
void BindGeo(CGI::CommandBufferPtr cb, UINT32 bindingsFilter);
|
||||||
|
|
||||||
static CGI::ShaderPtr GetShader() { return s_shader; }
|
static CGI::ShaderPtr GetShader() { return s_shader; }
|
||||||
static UB_PerMaterialFS& GetUbPerMaterialFS() { return s_ubPerMaterialFS; }
|
static UB_PerMaterialFS& GetUbPerMaterialFS() { return s_ubPerMaterialFS; }
|
||||||
void UpdateUniformBufferPerFrame();
|
void UpdateUniformBufferPerFrame(float invTessDist = 0);
|
||||||
void UpdateUniformBufferPerMaterialFS();
|
|
||||||
void UpdateUniformBufferPerMeshVS();
|
void UpdateUniformBufferPerMeshVS();
|
||||||
void UpdateUniformBufferSkeletonVS();
|
void UpdateUniformBufferSkeletonVS();
|
||||||
void UpdateUniformBufferPerObject(RcTransform3 tr, RcVector4 color = Vector4(0.5f, 0.5f, 0.5f, 1));
|
void UpdateUniformBufferPerObject(RcTransform3 tr, RcVector4 color = Vector4(0.5f, 0.5f, 0.5f, 1));
|
||||||
|
@ -108,11 +117,12 @@ namespace verus
|
||||||
virtual void UpdateVertexBuffer(const void* p, int binding) override;
|
virtual void UpdateVertexBuffer(const void* p, int binding) override;
|
||||||
|
|
||||||
// Instancing:
|
// Instancing:
|
||||||
|
void ResetInstanceCount();
|
||||||
|
void MarkFirstInstance() { _firstInstance = _instanceCount; }
|
||||||
void PushInstance(RcTransform3 matW, RcVector4 instData);
|
void PushInstance(RcTransform3 matW, RcVector4 instData);
|
||||||
bool IsInstanceBufferFull();
|
bool IsInstanceBufferFull();
|
||||||
bool IsInstanceBufferEmpty(bool fromFirstInstance = false);
|
bool IsInstanceBufferEmpty(bool fromFirstInstance = false);
|
||||||
void ResetInstanceCount();
|
|
||||||
void MarkFirstInstance() { _firstInstance = _instanceCount; }
|
|
||||||
void UpdateInstanceBuffer();
|
void UpdateInstanceBuffer();
|
||||||
int GetInstanceCount(bool fromFirstInstance = false) const { return fromFirstInstance ? _instanceCount - _firstInstance : _instanceCount; }
|
int GetInstanceCount(bool fromFirstInstance = false) const { return fromFirstInstance ? _instanceCount - _firstInstance : _instanceCount; }
|
||||||
int GetInstanceCapacity() const { return _instanceCapacity; }
|
int GetInstanceCapacity() const { return _instanceCapacity; }
|
||||||
|
|
|
@ -24,7 +24,7 @@ void Scatter::Init(int side, int typeCount, PcTypeDesc pTypes, int seed)
|
||||||
|
|
||||||
// Fill 2D array of instances:
|
// Fill 2D array of instances:
|
||||||
_vInstances.resize(_side * _side);
|
_vInstances.resize(_side * _side);
|
||||||
const int instanceCount = _vInstances.size();
|
const int instanceCount = Utils::Cast32(_vInstances.size());
|
||||||
int type = 0;
|
int type = 0;
|
||||||
int maxPermille = (typeCount >= 1) ? pTypes[0]._permille : 1000;
|
int maxPermille = (typeCount >= 1) ? pTypes[0]._permille : 1000;
|
||||||
VERUS_FOR(i, instanceCount)
|
VERUS_FOR(i, instanceCount)
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include "Atmosphere.h"
|
#include "Atmosphere.h"
|
||||||
#include "Water.h"
|
#include "Water.h"
|
||||||
#include "MaterialManager.h"
|
#include "MaterialManager.h"
|
||||||
|
#include "SceneNodes/SceneNodes.h"
|
||||||
#include "SceneManager.h"
|
#include "SceneManager.h"
|
||||||
#include "Helpers.h"
|
#include "Helpers.h"
|
||||||
#include "Scatter.h"
|
#include "Scatter.h"
|
||||||
|
|
|
@ -5,6 +5,7 @@ using namespace verus::Scene;
|
||||||
|
|
||||||
SceneManager::SceneManager()
|
SceneManager::SceneManager()
|
||||||
{
|
{
|
||||||
|
VERUS_ZERO_MEM(_visibleCountPerType);
|
||||||
}
|
}
|
||||||
|
|
||||||
SceneManager::~SceneManager()
|
SceneManager::~SceneManager()
|
||||||
|
@ -12,18 +13,290 @@ SceneManager::~SceneManager()
|
||||||
Done();
|
Done();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneManager::Init()
|
void SceneManager::Init(RcDesc desc)
|
||||||
{
|
{
|
||||||
VERUS_INIT();
|
VERUS_INIT();
|
||||||
|
|
||||||
|
SetCamera(desc._pMainCamera);
|
||||||
|
|
||||||
|
const float hf = desc._mapSide * 0.5f;
|
||||||
|
Math::Bounds bounds;
|
||||||
|
bounds.Set(
|
||||||
|
Vector3(-hf, -hf, -hf),
|
||||||
|
Vector3(+hf, +hf, +hf));
|
||||||
|
const Vector3 limit(hf / 14, hf / 14, hf / 14);
|
||||||
|
_octree.Done();
|
||||||
|
_octree.Init(bounds, limit);
|
||||||
|
_octree.SetDelegate(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneManager::Done()
|
void SceneManager::Done()
|
||||||
{
|
{
|
||||||
|
{ // PBLE:
|
||||||
|
//DeleteAllPrefabs();
|
||||||
|
DeleteAllBlocks();
|
||||||
|
DeleteAllLights();
|
||||||
|
//DeleteAllEmitters();
|
||||||
|
}
|
||||||
|
DeleteAllModels();
|
||||||
VERUS_DONE(SceneManager);
|
VERUS_DONE(SceneManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SceneManager::ResetInstanceCount()
|
||||||
|
{
|
||||||
|
for (auto& x : TStoreModels::_map)
|
||||||
|
x.second.GetMesh().ResetInstanceCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneManager::Update()
|
||||||
|
{
|
||||||
|
VERUS_UPDATE_ONCE_CHECK;
|
||||||
|
//for (auto& x : TStoreSites::_map)
|
||||||
|
// x.second.Update();
|
||||||
|
{ // PBLE:
|
||||||
|
//for (auto& x : TStorePrefabs::_list)
|
||||||
|
// x.Update();
|
||||||
|
for (auto& x : TStoreBlocks::_list)
|
||||||
|
x.Update();
|
||||||
|
for (auto& x : TStoreLights::_list)
|
||||||
|
x.Update();
|
||||||
|
//for (auto& x : TStoreEmitters::_list)
|
||||||
|
// x.Update();
|
||||||
|
}
|
||||||
|
//for (auto& x : TStoreSceneParticles::_map)
|
||||||
|
// x.second.Update();
|
||||||
|
}
|
||||||
|
|
||||||
void SceneManager::UpdateParts()
|
void SceneManager::UpdateParts()
|
||||||
{
|
{
|
||||||
|
const RcPoint3 eyePos = _pMainCamera->GetEyePosition();
|
||||||
|
for (auto& block : TStoreBlocks::_list)
|
||||||
|
{
|
||||||
|
const float distSq = VMath::distSqr(block.GetPosition(), eyePos);
|
||||||
|
const float part = MaterialManager::ComputePart(distSq, block.GetBounds().GetAverageSize() * 0.5f);
|
||||||
|
block.GetMaterial()->IncludePart(part);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneManager::Layout()
|
||||||
|
{
|
||||||
|
VERUS_QREF_CONST_SETTINGS;
|
||||||
|
VERUS_QREF_ATMO;
|
||||||
|
VERUS_QREF_SM;
|
||||||
|
|
||||||
|
// Allocate enough space:
|
||||||
|
int countAll = 0;
|
||||||
|
//countAll += TStorePrefabs::_list.size();
|
||||||
|
countAll += TStoreBlocks::_list.size();
|
||||||
|
countAll += TStoreLights::_list.size();
|
||||||
|
//countAll += TStoreSites::_map.size();
|
||||||
|
if (_vVisibleNodes.size() != countAll)
|
||||||
|
_vVisibleNodes.resize(countAll);
|
||||||
|
|
||||||
|
_visibleCount = 0;
|
||||||
|
VERUS_ZERO_MEM(_visibleCountPerType);
|
||||||
|
|
||||||
|
PCamera pPrevCamera = nullptr;
|
||||||
|
// For CSM we need to create geometry beyond the view frustum (1st slice):
|
||||||
|
if (settings._sceneShadowQuality >= App::Settings::ShadowQuality::cascaded && atmo.GetShadowMap().IsRendering())
|
||||||
|
{
|
||||||
|
PCamera pCameraCSM = atmo.GetShadowMap().GetCameraCSM();
|
||||||
|
if (pCameraCSM)
|
||||||
|
pPrevCamera = sm.SetCamera(pCameraCSM);
|
||||||
|
}
|
||||||
|
_octree.TraverseVisible(_pCamera->GetFrustum());
|
||||||
|
// Back to original camera:
|
||||||
|
if (pPrevCamera)
|
||||||
|
SetCamera(pPrevCamera);
|
||||||
|
|
||||||
|
VERUS_RT_ASSERT(!_visibleCountPerType[+NodeType::unknown]);
|
||||||
|
std::sort(_vVisibleNodes.begin(), _vVisibleNodes.begin() + _visibleCount, [](PSceneNode pA, PSceneNode pB)
|
||||||
|
{
|
||||||
|
// Sort by node type?
|
||||||
|
const NodeType typeA = pA->GetType();
|
||||||
|
const NodeType typeB = pB->GetType();
|
||||||
|
if (typeA != typeB)
|
||||||
|
return typeA < typeB;
|
||||||
|
|
||||||
|
// Both are blocks?
|
||||||
|
if (NodeType::block == typeA)
|
||||||
|
{
|
||||||
|
PBlock pBlockA = static_cast<PBlock>(pA);
|
||||||
|
PBlock pBlockB = static_cast<PBlock>(pB);
|
||||||
|
MaterialPtr materialA = pBlockA->GetMaterial();
|
||||||
|
MaterialPtr materialB = pBlockB->GetMaterial();
|
||||||
|
|
||||||
|
if (materialA && materialB) // A and B have materials, compare them.
|
||||||
|
{
|
||||||
|
const bool ab = *materialA < *materialB;
|
||||||
|
const bool ba = *materialB < *materialA;
|
||||||
|
if (ab || ba)
|
||||||
|
return ab;
|
||||||
|
}
|
||||||
|
else if (materialA) // A is with material, B is without, so A goes first.
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (materialB) // A is without material, B is with, so B goes first.
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Equal materials or none have any material, compare models used:
|
||||||
|
ModelPtr modelA = pBlockA->GetModel();
|
||||||
|
ModelPtr modelB = pBlockB->GetModel();
|
||||||
|
if (modelA != modelB)
|
||||||
|
return modelA < modelB;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Both are lights?
|
||||||
|
if (NodeType::light == typeA)
|
||||||
|
{
|
||||||
|
PLight pLightA = static_cast<PLight>(pA);
|
||||||
|
PLight pLightB = static_cast<PLight>(pB);
|
||||||
|
const CGI::LightType lightTypeA = pLightA->GetLightType();
|
||||||
|
const CGI::LightType lightTypeB = pLightB->GetLightType();
|
||||||
|
if (lightTypeA != lightTypeB)
|
||||||
|
return lightTypeA < lightTypeB;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw same node types front-to-back:
|
||||||
|
return pA->GetDistToEyeSq() < pB->GetDistToEyeSq();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneManager::Draw()
|
||||||
|
{
|
||||||
|
if (!_visibleCountPerType[+NodeType::block])
|
||||||
|
return;
|
||||||
|
|
||||||
|
VERUS_QREF_RENDERER;
|
||||||
|
|
||||||
|
ModelPtr model;
|
||||||
|
MaterialPtr material;
|
||||||
|
bool bindPipeline = true;
|
||||||
|
|
||||||
|
auto cb = renderer.GetCommandBuffer();
|
||||||
|
auto shader = Scene::Mesh::GetShader();
|
||||||
|
|
||||||
|
const int begin = 0;
|
||||||
|
const int end = _visibleCountPerType[+NodeType::block];
|
||||||
|
shader->BeginBindDescriptors();
|
||||||
|
for (int i = begin; i <= end; ++i)
|
||||||
|
{
|
||||||
|
if (i == end)
|
||||||
|
{
|
||||||
|
if (model)
|
||||||
|
model->Draw(cb);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
PSceneNode pSN = _vVisibleNodes[i];
|
||||||
|
PBlock pBlock = static_cast<PBlock>(pSN);
|
||||||
|
ModelPtr nextModel = pBlock->GetModel();
|
||||||
|
MaterialPtr nextMaterial = pBlock->GetMaterial();
|
||||||
|
|
||||||
|
if (!nextModel->IsLoaded() || !nextMaterial->IsLoaded())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (nextModel != model)
|
||||||
|
{
|
||||||
|
if (model)
|
||||||
|
model->Draw(cb);
|
||||||
|
|
||||||
|
model = nextModel;
|
||||||
|
model->MarkFirstInstance();
|
||||||
|
if (bindPipeline)
|
||||||
|
{
|
||||||
|
bindPipeline = false;
|
||||||
|
model->BindPipeline(cb);
|
||||||
|
cb->BindDescriptors(shader, 0);
|
||||||
|
}
|
||||||
|
model->BindGeo(cb);
|
||||||
|
cb->BindDescriptors(shader, 2);
|
||||||
|
}
|
||||||
|
if (nextMaterial != material)
|
||||||
|
{
|
||||||
|
material = nextMaterial;
|
||||||
|
material->UpdateMeshUniformBuffer();
|
||||||
|
cb->BindDescriptors(shader, 1, material->GetComplexSetHandle());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (model)
|
||||||
|
model->PushInstance(pBlock->GetTransform(), pBlock->GetColor());
|
||||||
|
}
|
||||||
|
shader->EndBindDescriptors();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneManager::DrawLights()
|
||||||
|
{
|
||||||
|
if (!_visibleCountPerType[+NodeType::light])
|
||||||
|
return;
|
||||||
|
|
||||||
|
VERUS_QREF_RENDERER;
|
||||||
|
VERUS_QREF_HELPERS;
|
||||||
|
|
||||||
|
CGI::LightType type = CGI::LightType::none;
|
||||||
|
PMesh pMesh = nullptr;
|
||||||
|
bool bindPipeline = true;
|
||||||
|
|
||||||
|
auto& ds = renderer.GetDS();
|
||||||
|
auto cb = renderer.GetCommandBuffer();
|
||||||
|
|
||||||
|
auto DrawMesh = [cb](PMesh pMesh)
|
||||||
|
{
|
||||||
|
if (pMesh && !pMesh->IsInstanceBufferEmpty(true))
|
||||||
|
{
|
||||||
|
pMesh->UpdateInstanceBuffer();
|
||||||
|
cb->DrawIndexed(pMesh->GetIndexCount(), pMesh->GetInstanceCount(true), 0, 0, pMesh->GetFirstInstance());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const int begin = _visibleCountPerType[+NodeType::block];
|
||||||
|
const int end = _visibleCountPerType[+NodeType::block] + _visibleCountPerType[+NodeType::light];
|
||||||
|
for (int i = begin; i <= end; ++i)
|
||||||
|
{
|
||||||
|
if (i == end)
|
||||||
|
{
|
||||||
|
DrawMesh(pMesh);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
PSceneNode pSN = _vVisibleNodes[i];
|
||||||
|
PLight pLight = static_cast<PLight>(pSN);
|
||||||
|
const CGI::LightType nextType = pLight->GetLightType();
|
||||||
|
|
||||||
|
if (nextType != type)
|
||||||
|
{
|
||||||
|
DrawMesh(pMesh);
|
||||||
|
|
||||||
|
type = nextType;
|
||||||
|
ds.OnNewLightType(cb, type);
|
||||||
|
|
||||||
|
pMesh = (type != CGI::LightType::none) ? &helpers.GetDeferredLights().Get(type) : nullptr;
|
||||||
|
|
||||||
|
if (pMesh)
|
||||||
|
{
|
||||||
|
pMesh->MarkFirstInstance();
|
||||||
|
pMesh->BindGeo(cb, (1 << 0) | (1 << 4));
|
||||||
|
pMesh->CopyPosDeqScale(&ds.GetUbPerMeshVS()._posDeqScale.x);
|
||||||
|
pMesh->CopyPosDeqBias(&ds.GetUbPerMeshVS()._posDeqBias.x);
|
||||||
|
ds.BindDescriptorsPerMeshVS(cb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef VERUS_RELEASE_DEBUG
|
||||||
|
if (CGI::LightType::dir == type) // Must not be scaled!
|
||||||
|
{
|
||||||
|
RcTransform3 matW = pLight->GetTransform();
|
||||||
|
const Vector3 s = matW.GetScale();
|
||||||
|
VERUS_RT_ASSERT(glm::all(glm::epsilonEqual(s.GLM(), glm::vec3(1), glm::vec3(VERUS_FLOAT_THRESHOLD))));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (pMesh)
|
||||||
|
pMesh->PushInstance(pLight->GetTransform(), pLight->GetInstData());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SceneManager::IsDrawingDepth(DrawDepth dd)
|
bool SceneManager::IsDrawingDepth(DrawDepth dd)
|
||||||
|
@ -37,10 +310,95 @@ bool SceneManager::IsDrawingDepth(DrawDepth dd)
|
||||||
return DrawDepth::yes == dd;
|
return DrawDepth::yes == dd;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SceneManager::RayCastingTest(RcPoint3 pointA, RcPoint3 pointB, void* pBlock,
|
String SceneManager::EnsureUniqueName(CSZ name)
|
||||||
|
{
|
||||||
|
// Compact name:
|
||||||
|
const char* s = strrchr(name, ':');
|
||||||
|
s = s ? s + 1 : name;
|
||||||
|
const char* e = strrchr(name, '.');
|
||||||
|
if (!e)
|
||||||
|
e = name + strlen(name);
|
||||||
|
|
||||||
|
// Unique name:
|
||||||
|
int id = -1;
|
||||||
|
String test;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
test = (id < 0) ? String(s, e) : String(s, e) + "_" + std::to_string(id);
|
||||||
|
//for (auto& it : TStorePrefabs::_list) if (it.GetName() == _C(test)) test.clear();
|
||||||
|
for (auto& it : TStoreBlocks::_list) if (it.GetName() == _C(test)) test.clear();
|
||||||
|
for (auto& it : TStoreLights::_list) if (it.GetName() == _C(test)) test.clear();
|
||||||
|
//for (auto& it : TStoreEmitters::_list) if (it.GetName() == _C(test)) test.clear();
|
||||||
|
id++;
|
||||||
|
} while (test.empty());
|
||||||
|
|
||||||
|
return test;
|
||||||
|
}
|
||||||
|
|
||||||
|
PModel SceneManager::InsertModel(CSZ url)
|
||||||
|
{
|
||||||
|
return TStoreModels::Insert(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
PModel SceneManager::FindModel(CSZ url)
|
||||||
|
{
|
||||||
|
return TStoreModels::Find(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneManager::DeleteModel(CSZ url)
|
||||||
|
{
|
||||||
|
TStoreModels::Delete(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneManager::DeleteAllModels()
|
||||||
|
{
|
||||||
|
TStoreModels::DeleteAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
PBlock SceneManager::InsertBlock()
|
||||||
|
{
|
||||||
|
return TStoreBlocks::Insert();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneManager::DeleteBlock(PBlock p)
|
||||||
|
{
|
||||||
|
TStoreBlocks::Delete(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneManager::DeleteAllBlocks()
|
||||||
|
{
|
||||||
|
TStoreBlocks::DeleteAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
PLight SceneManager::InsertLight()
|
||||||
|
{
|
||||||
|
return TStoreLights::Insert();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneManager::DeleteLight(PLight p)
|
||||||
|
{
|
||||||
|
TStoreLights::Delete(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneManager::DeleteAllLights()
|
||||||
|
{
|
||||||
|
TStoreLights::DeleteAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
Continue SceneManager::Octree_ProcessNode(void* pToken, void* pUser)
|
||||||
|
{
|
||||||
|
PSceneNode pSN = static_cast<PSceneNode>(pToken);
|
||||||
|
if (pSN->IsHidden())
|
||||||
|
return Continue::yes;
|
||||||
|
_vVisibleNodes[_visibleCount++] = pSN;
|
||||||
|
_visibleCountPerType[+pSN->GetType()]++;
|
||||||
|
return Continue::yes;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SceneManager::RayCastingTest(RcPoint3 pointA, RcPoint3 pointB, PBlockPtr pBlock,
|
||||||
PPoint3 pPoint, PVector3 pNormal, const float* pRadius, Physics::Group mask)
|
PPoint3 pPoint, PVector3 pNormal, const float* pRadius, Physics::Group mask)
|
||||||
{
|
{
|
||||||
//VERUS_RT_ASSERT(!pBlock || *pBlock);
|
VERUS_RT_ASSERT(!pBlock || *pBlock);
|
||||||
VERUS_QREF_BULLET;
|
VERUS_QREF_BULLET;
|
||||||
btVector3 from(pointA.Bullet()), to(pointB.Bullet());
|
btVector3 from(pointA.Bullet()), to(pointB.Bullet());
|
||||||
if (pPoint || pNormal)
|
if (pPoint || pNormal)
|
||||||
|
@ -59,8 +417,8 @@ bool SceneManager::RayCastingTest(RcPoint3 pointA, RcPoint3 pointB, void* pBlock
|
||||||
if (ccrc.hasHit())
|
if (ccrc.hasHit())
|
||||||
{
|
{
|
||||||
Physics::PUserPtr p = static_cast<Physics::PUserPtr>(ccrc.m_hitCollisionObject->getUserPointer());
|
Physics::PUserPtr p = static_cast<Physics::PUserPtr>(ccrc.m_hitCollisionObject->getUserPointer());
|
||||||
//if (pBlock && p->UserPtr_GetType() == +NodeType::block)
|
if (pBlock && p->UserPtr_GetType() == +NodeType::block)
|
||||||
// pBlock->Attach(static_cast<PBlock>(p));
|
pBlock->Attach(static_cast<PBlock>(p));
|
||||||
if (pPoint)
|
if (pPoint)
|
||||||
*pPoint = ccrc.m_hitPointWorld;
|
*pPoint = ccrc.m_hitPointWorld;
|
||||||
if (pNormal)
|
if (pNormal)
|
||||||
|
@ -78,8 +436,8 @@ bool SceneManager::RayCastingTest(RcPoint3 pointA, RcPoint3 pointB, void* pBlock
|
||||||
if (crrc.hasHit())
|
if (crrc.hasHit())
|
||||||
{
|
{
|
||||||
Physics::PUserPtr p = static_cast<Physics::PUserPtr>(crrc.m_collisionObject->getUserPointer());
|
Physics::PUserPtr p = static_cast<Physics::PUserPtr>(crrc.m_collisionObject->getUserPointer());
|
||||||
//if (pBlock && p->UserPtr_GetType() == +NodeType::block)
|
if (pBlock && p->UserPtr_GetType() == +NodeType::block)
|
||||||
// pBlock->Attach(static_cast<PBlock>(p));
|
pBlock->Attach(static_cast<PBlock>(p));
|
||||||
if (pPoint)
|
if (pPoint)
|
||||||
*pPoint = crrc.m_hitPointWorld;
|
*pPoint = crrc.m_hitPointWorld;
|
||||||
if (pNormal)
|
if (pNormal)
|
||||||
|
@ -106,8 +464,8 @@ bool SceneManager::RayCastingTest(RcPoint3 pointA, RcPoint3 pointB, void* pBlock
|
||||||
if (arrc.hasHit())
|
if (arrc.hasHit())
|
||||||
{
|
{
|
||||||
Physics::PUserPtr p = static_cast<Physics::PUserPtr>(arrc.m_collisionObject->getUserPointer());
|
Physics::PUserPtr p = static_cast<Physics::PUserPtr>(arrc.m_collisionObject->getUserPointer());
|
||||||
//if (pBlock && p->UserPtr_GetType() == +NodeType::block)
|
if (pBlock && p->UserPtr_GetType() == +NodeType::block)
|
||||||
// pBlock->Attach(static_cast<PBlock>(p));
|
pBlock->Attach(static_cast<PBlock>(p));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -11,20 +11,52 @@ namespace verus
|
||||||
automatic
|
automatic
|
||||||
};
|
};
|
||||||
|
|
||||||
class SceneManager : public Singleton<SceneManager>, public Object
|
typedef StoreUnique<String, Model> TStoreModels;
|
||||||
|
typedef Store<Block> TStoreBlocks;
|
||||||
|
typedef Store<Light> TStoreLights;
|
||||||
|
class SceneManager : public Singleton<SceneManager>, public Object, public Math::OctreeDelegate,
|
||||||
|
private TStoreModels, private TStoreBlocks, private TStoreLights
|
||||||
{
|
{
|
||||||
Math::Octree _octree;
|
Math::Octree _octree;
|
||||||
PCamera _pCamera = nullptr;
|
PCamera _pCamera = nullptr;
|
||||||
PMainCamera _pMainCamera = nullptr;
|
PMainCamera _pMainCamera = nullptr;
|
||||||
|
Vector<PSceneNode> _vVisibleNodes;
|
||||||
|
int _visibleCount = 0;
|
||||||
|
int _visibleCountPerType[+NodeType::count];
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
struct Desc
|
||||||
|
{
|
||||||
|
PMainCamera _pMainCamera = nullptr;
|
||||||
|
int _mapSide = 256;
|
||||||
|
|
||||||
|
Desc() {}
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(Desc);
|
||||||
|
|
||||||
|
struct Query
|
||||||
|
{
|
||||||
|
CSZ _name = nullptr;
|
||||||
|
CSZ _blockMesh = nullptr;
|
||||||
|
CSZ _blockMaterial = nullptr;
|
||||||
|
NodeType _type = NodeType::unknown;
|
||||||
|
|
||||||
|
void Reset() { *this = Query(); }
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(Query);
|
||||||
|
|
||||||
SceneManager();
|
SceneManager();
|
||||||
virtual ~SceneManager();
|
virtual ~SceneManager();
|
||||||
|
|
||||||
void Init();
|
void Init(RcDesc desc = Desc());
|
||||||
void Done();
|
void Done();
|
||||||
|
|
||||||
|
void ResetInstanceCount();
|
||||||
|
void Update();
|
||||||
void UpdateParts();
|
void UpdateParts();
|
||||||
|
void Layout();
|
||||||
|
void Draw();
|
||||||
|
void DrawLights();
|
||||||
|
|
||||||
// Camera:
|
// Camera:
|
||||||
PCamera GetCamera() const { return _pCamera; }
|
PCamera GetCamera() const { return _pCamera; }
|
||||||
|
@ -34,7 +66,89 @@ namespace verus
|
||||||
|
|
||||||
static bool IsDrawingDepth(DrawDepth dd);
|
static bool IsDrawingDepth(DrawDepth dd);
|
||||||
|
|
||||||
bool RayCastingTest(RcPoint3 pointA, RcPoint3 pointB, void* pBlock = nullptr,
|
String EnsureUniqueName(CSZ name);
|
||||||
|
|
||||||
|
// Models:
|
||||||
|
PModel InsertModel(CSZ url);
|
||||||
|
PModel FindModel(CSZ url);
|
||||||
|
void DeleteModel(CSZ url);
|
||||||
|
void DeleteAllModels();
|
||||||
|
|
||||||
|
// Blocks:
|
||||||
|
PBlock InsertBlock();
|
||||||
|
void DeleteBlock(PBlock p);
|
||||||
|
void DeleteAllBlocks();
|
||||||
|
|
||||||
|
// Lights (and Shadows):
|
||||||
|
PLight InsertLight();
|
||||||
|
void DeleteLight(PLight p);
|
||||||
|
void DeleteAllLights();
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void ForEachNode(RcQuery query, const T& fn)
|
||||||
|
{
|
||||||
|
// Visit PBLE:
|
||||||
|
//if (NodeType::unknown == query._type || NodeType::prefab == query._type)
|
||||||
|
//{
|
||||||
|
// VERUS_FOREACH_X(TStorePrefabs::TList, TStorePrefabs::_list, it)
|
||||||
|
// {
|
||||||
|
// auto& prefab = *it++;
|
||||||
|
// if (!query._name || prefab.GetName() == query._name)
|
||||||
|
// if (Continue::yes != fn(prefab))
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
if (NodeType::unknown == query._type || NodeType::block == query._type)
|
||||||
|
{
|
||||||
|
VERUS_FOREACH_X(TStoreBlocks::TList, TStoreBlocks::_list, it)
|
||||||
|
{
|
||||||
|
auto& block = *it++;
|
||||||
|
if (
|
||||||
|
(!query._name || block.GetName() == query._name) &&
|
||||||
|
(!query._blockMesh || block.GetModel()->GetMesh().GetUrl() == query._blockMesh) &&
|
||||||
|
(!query._blockMaterial || block.GetMaterial()->_name == query._blockMaterial))
|
||||||
|
if (Continue::yes != fn(block))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (NodeType::unknown == query._type || NodeType::light == query._type)
|
||||||
|
{
|
||||||
|
VERUS_FOREACH_X(TStoreLights::TList, TStoreLights::_list, it)
|
||||||
|
{
|
||||||
|
auto& light = *it++;
|
||||||
|
if (!query._name || light.GetName() == query._name)
|
||||||
|
if (Continue::yes != fn(light))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//if (NodeType::unknown == query._type || NodeType::emitter == query._type)
|
||||||
|
//{
|
||||||
|
// VERUS_FOREACH_X(TStoreEmitters::TList, TStoreEmitters::_list, it)
|
||||||
|
// {
|
||||||
|
// auto& emitter = *it++;
|
||||||
|
// if (!query._name || emitter.GetName() == query._name)
|
||||||
|
// if (Continue::yes != fn(emitter))
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void ForEachModel(const T& fn)
|
||||||
|
{
|
||||||
|
VERUS_FOREACH_X(TStoreModels::TMap, TStoreModels::_map, it)
|
||||||
|
{
|
||||||
|
auto& model = *it++;
|
||||||
|
if (Continue::yes != fn(model.second))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Octree (Acceleration Structure):
|
||||||
|
Math::ROctree GetOctree() { return _octree; }
|
||||||
|
virtual Continue Octree_ProcessNode(void* pToken, void* pUser) override;
|
||||||
|
|
||||||
|
bool RayCastingTest(RcPoint3 pointA, RcPoint3 pointB, PBlockPtr pBlock = nullptr,
|
||||||
PPoint3 pPoint = nullptr, PVector3 pNormal = nullptr, const float* pRadius = nullptr,
|
PPoint3 pPoint = nullptr, PVector3 pNormal = nullptr, const float* pRadius = nullptr,
|
||||||
Physics::Group mask = Physics::Group::immovable | Physics::Group::terrain);
|
Physics::Group mask = Physics::Group::immovable | Physics::Group::terrain);
|
||||||
};
|
};
|
||||||
|
|
222
Verus/src/Scene/SceneNodes/Block.cpp
Normal file
222
Verus/src/Scene/SceneNodes/Block.cpp
Normal file
|
@ -0,0 +1,222 @@
|
||||||
|
#include "verus.h"
|
||||||
|
|
||||||
|
using namespace verus;
|
||||||
|
using namespace verus::Scene;
|
||||||
|
|
||||||
|
// Block:
|
||||||
|
|
||||||
|
Block::Block()
|
||||||
|
{
|
||||||
|
_type = NodeType::block;
|
||||||
|
}
|
||||||
|
|
||||||
|
Block::~Block()
|
||||||
|
{
|
||||||
|
Done();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Block::Init(RcDesc desc)
|
||||||
|
{
|
||||||
|
VERUS_QREF_SM;
|
||||||
|
_name = sm.EnsureUniqueName(desc._name ? desc._name : desc._model);
|
||||||
|
_matIndex = desc._matIndex;
|
||||||
|
_collide = desc._collide;
|
||||||
|
|
||||||
|
Model::Desc modelDesc;
|
||||||
|
modelDesc._url = desc._model;
|
||||||
|
modelDesc._mat = desc._modelMat;
|
||||||
|
_model.Init(modelDesc);
|
||||||
|
|
||||||
|
if (desc._blockMat)
|
||||||
|
{
|
||||||
|
Material::Desc matDesc;
|
||||||
|
matDesc._name = desc._blockMat;
|
||||||
|
matDesc._load = true;
|
||||||
|
_material.Init(matDesc);
|
||||||
|
}
|
||||||
|
|
||||||
|
String url = desc._model;
|
||||||
|
Str::ReplaceExtension(url, ".Extra.xml");
|
||||||
|
Vector<BYTE> vData;
|
||||||
|
IO::FileSystem::I().LoadResourceFromCache(_C(url), vData, false);
|
||||||
|
if (vData.size() > 1)
|
||||||
|
LoadExtra(reinterpret_cast<CSZ>(vData.data()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Block::Done()
|
||||||
|
{
|
||||||
|
RemoveRigidBody();
|
||||||
|
_material.Done();
|
||||||
|
_model.Done();
|
||||||
|
SceneManager::I().GetOctree().UnbindClient(this);
|
||||||
|
_vLights.clear();
|
||||||
|
_vEmitters.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Block::LoadExtra(CSZ xml)
|
||||||
|
{
|
||||||
|
//tinyxml2::XMLDocument doc;
|
||||||
|
//doc.Parse(xml);
|
||||||
|
//if (doc.Error())
|
||||||
|
// return;
|
||||||
|
//tinyxml2::XMLElement* pRoot = doc.FirstChildElement();
|
||||||
|
//if (!pRoot)
|
||||||
|
// return;
|
||||||
|
//
|
||||||
|
//int numLights = 0;
|
||||||
|
//for (pugi::xml_node node = pRoot->FirstChildElement("light"); pElem; pElem = pElem->NextSiblingElement("light"))
|
||||||
|
//{
|
||||||
|
// CSZ mat = pElem->Attribute("mat");
|
||||||
|
// if (!mat || atoi(mat) == _matIndex)
|
||||||
|
// numLights++;
|
||||||
|
//}
|
||||||
|
//int numEmitters = 0;
|
||||||
|
//for (pugi::xml_node node = pRoot->FirstChildElement("emit"); pElem; pElem = pElem->NextSiblingElement("emit"))
|
||||||
|
// numEmitters++;
|
||||||
|
//
|
||||||
|
//_vLights.resize(numLights);
|
||||||
|
//_vEmitters.resize(numEmitters);
|
||||||
|
//
|
||||||
|
//int i = 0;
|
||||||
|
//for (pugi::xml_node node = pRoot->FirstChildElement("light"); pElem; pElem = pElem->NextSiblingElement("light"))
|
||||||
|
//{
|
||||||
|
// CSZ mat = pElem->Attribute("mat");
|
||||||
|
// if (!mat || atoi(mat) == _matIndex)
|
||||||
|
// {
|
||||||
|
// RLightPwn light = _vLights[i]._light;
|
||||||
|
//
|
||||||
|
// Light::Desc descLight;
|
||||||
|
// descLight._pLoadXML = pElem;
|
||||||
|
// light.Init(descLight);
|
||||||
|
// _vLights[i]._tr = light->GetTransform();
|
||||||
|
// light->SetTransform(GetTransform() * _vLights[i]._tr);
|
||||||
|
//
|
||||||
|
// i++;
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
//i = 0;
|
||||||
|
//for (pugi::xml_node node = pRoot->FirstChildElement("emit"); pElem; pElem = pElem->NextSiblingElement("emit"))
|
||||||
|
//{
|
||||||
|
// REmitterPwn emitter = _vEmitters[i]._emitter;
|
||||||
|
//
|
||||||
|
// CEmitter::Desc descEmitter;
|
||||||
|
// descEmitter._pLoadXML = pElem;
|
||||||
|
// emitter.Init(descEmitter);
|
||||||
|
// _vEmitters[i]._tr = emitter->GetTransform();
|
||||||
|
// emitter->SetTransform(GetTransform() * _vEmitters[i]._tr);
|
||||||
|
//
|
||||||
|
// i++;
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Block::Update()
|
||||||
|
{
|
||||||
|
if (!_async_loadedModel && _model->IsLoaded())
|
||||||
|
{
|
||||||
|
_async_loadedModel = true;
|
||||||
|
if (!_dynamic)
|
||||||
|
{
|
||||||
|
VERUS_QREF_BULLET;
|
||||||
|
const btTransform tr = GetTransform().Bullet();
|
||||||
|
_pBody = bullet.AddNewRigidBody(0, tr, _model->GetMesh().GetShape(), +Physics::Group::immovable);
|
||||||
|
_pBody->setFriction(Physics::Bullet::GetFriction(Physics::Material::stone));
|
||||||
|
_pBody->setRestitution(Physics::Bullet::GetRestitution(Physics::Material::stone));
|
||||||
|
_pBody->setUserPointer(this);
|
||||||
|
SetCollisionGroup(_collide ? Physics::Group::immovable : Physics::Group::general);
|
||||||
|
}
|
||||||
|
UpdateBounds();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Block::Draw()
|
||||||
|
{
|
||||||
|
//_model->Draw(&_tr, _material);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Block::SetDynamic(bool mode)
|
||||||
|
{
|
||||||
|
SceneNode::SetDynamic(mode);
|
||||||
|
_octreeBindOnce = false;
|
||||||
|
_async_loadedModel = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialPtr Block::GetMaterial(bool orModelMat)
|
||||||
|
{
|
||||||
|
if (!_material && orModelMat)
|
||||||
|
return _model->GetMaterial();
|
||||||
|
return _material;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Block::UpdateBounds()
|
||||||
|
{
|
||||||
|
if (_model->IsLoaded())
|
||||||
|
{
|
||||||
|
if (!_octreeBindOnce)
|
||||||
|
{
|
||||||
|
_bounds = Math::Bounds::MakeFromOrientedBox(_model->GetMesh().GetBounds(), _tr);
|
||||||
|
SceneManager::I().GetOctree().BindClient(Math::Octree::Client(_bounds, this), _dynamic);
|
||||||
|
_octreeBindOnce = _dynamic;
|
||||||
|
}
|
||||||
|
if (_dynamic)
|
||||||
|
{
|
||||||
|
_bounds = Math::Bounds::MakeFromOrientedBox(_model->GetMesh().GetBounds(), _tr);
|
||||||
|
SceneManager::I().GetOctree().UpdateDynamicBounds(Math::Octree::Client(_bounds, this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& x : _vLights)
|
||||||
|
x._light->SetTransform(GetTransform() * x._tr);
|
||||||
|
//for (auto& x : _vEmitters)
|
||||||
|
// x._emitter->SetTransform(GetTransform() * x._tr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Block::SaveXML(pugi::xml_node node)
|
||||||
|
{
|
||||||
|
SceneNode::SaveXML(node);
|
||||||
|
|
||||||
|
node.append_attribute("url") = _C(GetUrl());
|
||||||
|
if (_material)
|
||||||
|
node.append_attribute("mat") = _C(_material->_name);
|
||||||
|
if (!_userColor.IsZero())
|
||||||
|
node.append_attribute("color") = _C(_userColor.ToColorString());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Block::LoadXML(pugi::xml_node node)
|
||||||
|
{
|
||||||
|
SceneNode::LoadXML(node);
|
||||||
|
_name.clear();
|
||||||
|
|
||||||
|
_userColor = Vector4(0);
|
||||||
|
if (auto attr = node.attribute("color"))
|
||||||
|
_userColor.FromColorString(attr.value());
|
||||||
|
|
||||||
|
Desc desc;
|
||||||
|
desc._name = node.attribute("name").value();
|
||||||
|
desc._model = node.attribute("url").value();
|
||||||
|
desc._blockMat = node.attribute("mat").value();
|
||||||
|
if (desc._blockMat)
|
||||||
|
desc._matIndex = atoi(strrchr(desc._blockMat, '.') - 1);
|
||||||
|
Init(desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
// BlockPtr:
|
||||||
|
|
||||||
|
void BlockPtr::Init(Block::RcDesc desc)
|
||||||
|
{
|
||||||
|
VERUS_QREF_SM;
|
||||||
|
VERUS_RT_ASSERT(!_p);
|
||||||
|
_p = sm.InsertBlock();
|
||||||
|
if (desc._node)
|
||||||
|
_p->LoadXML(desc._node);
|
||||||
|
else
|
||||||
|
_p->Init(desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BlockPwn::Done()
|
||||||
|
{
|
||||||
|
if (_p)
|
||||||
|
{
|
||||||
|
SceneManager::I().DeleteBlock(_p);
|
||||||
|
_p = nullptr;
|
||||||
|
}
|
||||||
|
}
|
95
Verus/src/Scene/SceneNodes/Block.h
Normal file
95
Verus/src/Scene/SceneNodes/Block.h
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
namespace Scene
|
||||||
|
{
|
||||||
|
class BlockLight
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Transform3 _tr = Transform3::identity();
|
||||||
|
LightPwn _light;
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(BlockLight);
|
||||||
|
|
||||||
|
class BlockEmitter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Transform3 _tr = Transform3::identity();
|
||||||
|
//CEmitterPwn _emitter;
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(BlockEmitter);
|
||||||
|
|
||||||
|
//! Block is a scene node which has a model and material info.
|
||||||
|
//! Most blocks form the scene's so called static or immovable geometry.
|
||||||
|
class Block : public SceneNode
|
||||||
|
{
|
||||||
|
Vector4 _userColor = Vector4(0);
|
||||||
|
Vector<BlockLight> _vLights;
|
||||||
|
Vector<BlockEmitter> _vEmitters;
|
||||||
|
ModelPwn _model;
|
||||||
|
MaterialPwn _material;
|
||||||
|
int _matIndex = 0;
|
||||||
|
bool _collide = true;
|
||||||
|
bool _async_loadedModel = false;
|
||||||
|
|
||||||
|
public:
|
||||||
|
struct Desc
|
||||||
|
{
|
||||||
|
pugi::xml_node _node;
|
||||||
|
CSZ _name = nullptr;
|
||||||
|
CSZ _model = nullptr;
|
||||||
|
CSZ _modelMat = nullptr;
|
||||||
|
CSZ _blockMat = nullptr;
|
||||||
|
int _matIndex = 0;
|
||||||
|
bool _collide = true;
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(Desc);
|
||||||
|
|
||||||
|
Block();
|
||||||
|
~Block();
|
||||||
|
|
||||||
|
void Init(RcDesc desc);
|
||||||
|
void Done();
|
||||||
|
|
||||||
|
VERUS_P(void LoadExtra(CSZ xml));
|
||||||
|
|
||||||
|
virtual void Update() override;
|
||||||
|
virtual void Draw() override;
|
||||||
|
|
||||||
|
virtual String GetUrl() override { return _C(_model->GetMesh().GetUrl()); }
|
||||||
|
|
||||||
|
bool IsLoadedModel() const { return _model->IsLoaded(); }
|
||||||
|
|
||||||
|
virtual void SetDynamic(bool mode) override;
|
||||||
|
|
||||||
|
virtual void SetColor(RcVector4 color) override { _userColor = color; }
|
||||||
|
virtual Vector4 GetColor() override { return _userColor; }
|
||||||
|
ModelPtr GetModel() { return _model; }
|
||||||
|
MaterialPtr GetMaterial(bool orModelMat = true);
|
||||||
|
int GetMaterialIndex() const { return _matIndex; }
|
||||||
|
|
||||||
|
virtual void UpdateBounds() override;
|
||||||
|
|
||||||
|
// Serialization:
|
||||||
|
virtual void SaveXML(pugi::xml_node node) override;
|
||||||
|
virtual void LoadXML(pugi::xml_node node) override;
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(Block);
|
||||||
|
|
||||||
|
class BlockPtr : public Ptr<Block>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void Init(Block::RcDesc desc);
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(BlockPtr);
|
||||||
|
|
||||||
|
class BlockPwn : public BlockPtr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
~BlockPwn() { Done(); }
|
||||||
|
void Done();
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(BlockPwn);
|
||||||
|
}
|
||||||
|
}
|
283
Verus/src/Scene/SceneNodes/Light.cpp
Normal file
283
Verus/src/Scene/SceneNodes/Light.cpp
Normal file
|
@ -0,0 +1,283 @@
|
||||||
|
#include "verus.h"
|
||||||
|
|
||||||
|
using namespace verus;
|
||||||
|
using namespace verus::Scene;
|
||||||
|
|
||||||
|
// Light:
|
||||||
|
|
||||||
|
Light::Light()
|
||||||
|
{
|
||||||
|
_type = NodeType::light;
|
||||||
|
}
|
||||||
|
|
||||||
|
Light::~Light()
|
||||||
|
{
|
||||||
|
Done();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Light::Init(RcDesc desc)
|
||||||
|
{
|
||||||
|
_data = desc._data;
|
||||||
|
//if (desc._urlIntShaker)
|
||||||
|
//{
|
||||||
|
// _shaker.Load(desc._urlIntShaker);
|
||||||
|
// _shaker.Randomize();
|
||||||
|
// _shaker.SetScaleBias(0.5f * desc._intShakerScale, 1 - 0.5f * desc._intShakerScale);
|
||||||
|
// _intMax = GetIntensity();
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Light::Done()
|
||||||
|
{
|
||||||
|
SceneManager::I().GetOctree().UnbindClient(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Light::Update()
|
||||||
|
{
|
||||||
|
if (!_async_loadedMesh)
|
||||||
|
{
|
||||||
|
VERUS_QREF_HELPERS;
|
||||||
|
RMesh mesh = helpers.GetDeferredLights().Get(_data._lightType);
|
||||||
|
if (mesh.IsLoaded())
|
||||||
|
{
|
||||||
|
_async_loadedMesh = true;
|
||||||
|
UpdateBounds();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//if (_shaker.IsLoaded())
|
||||||
|
//{
|
||||||
|
// _shaker.Update();
|
||||||
|
// SetIntensity(_shaker.Get() * _intMax);
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Light::Draw()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Light::SetLightType(CGI::LightType type)
|
||||||
|
{
|
||||||
|
_data._lightType = type;
|
||||||
|
ComputeTransform();
|
||||||
|
}
|
||||||
|
|
||||||
|
CGI::LightType Light::GetLightType() const
|
||||||
|
{
|
||||||
|
return _data._lightType;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Light::SetColor(RcVector4 color)
|
||||||
|
{
|
||||||
|
_data._color = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector4 Light::GetColor()
|
||||||
|
{
|
||||||
|
return _data._color;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Light::SetIntensity(float i)
|
||||||
|
{
|
||||||
|
_data._color.setW(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
float Light::GetIntensity() const
|
||||||
|
{
|
||||||
|
return _data._color.getW();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Light::SetDirection(RcVector3 dir)
|
||||||
|
{
|
||||||
|
_data._dir = dir;
|
||||||
|
ComputeTransform();
|
||||||
|
}
|
||||||
|
|
||||||
|
RcVector3 Light::GetDirection() const
|
||||||
|
{
|
||||||
|
return _data._dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Light::SetRadius(float r)
|
||||||
|
{
|
||||||
|
_data._radius = r;
|
||||||
|
ComputeTransform();
|
||||||
|
}
|
||||||
|
|
||||||
|
float Light::GetRadius() const
|
||||||
|
{
|
||||||
|
return _data._radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Light::SetCone(float coneIn, float coneOut)
|
||||||
|
{
|
||||||
|
if (coneIn)
|
||||||
|
_data._coneIn = coneIn;
|
||||||
|
if (coneOut)
|
||||||
|
_data._coneOut = coneOut;
|
||||||
|
VERUS_RT_ASSERT(_data._coneIn >= _data._coneOut);
|
||||||
|
ComputeTransform();
|
||||||
|
}
|
||||||
|
|
||||||
|
float Light::GetConeIn() const
|
||||||
|
{
|
||||||
|
return _data._coneIn;
|
||||||
|
}
|
||||||
|
|
||||||
|
float Light::GetConeOut() const
|
||||||
|
{
|
||||||
|
return _data._coneOut;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector4 Light::GetInstData() const
|
||||||
|
{
|
||||||
|
return Vector4(_data._color.getXYZ() * _data._color.getW(), _data._coneIn);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Light::DirFromPoint(RcPoint3 point, float radiusScale)
|
||||||
|
{
|
||||||
|
const Vector3 to = point - GetPosition();
|
||||||
|
const float len = VMath::length(to);
|
||||||
|
if (len > VERUS_FLOAT_THRESHOLD)
|
||||||
|
{
|
||||||
|
_data._dir = to / len;
|
||||||
|
if (radiusScale > 0)
|
||||||
|
_data._radius = len * radiusScale;
|
||||||
|
}
|
||||||
|
ComputeTransform();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Light::ConeFromPoint(RcPoint3 point, bool coneIn)
|
||||||
|
{
|
||||||
|
const Vector3 to = point - GetPosition();
|
||||||
|
const Vector3 dir = VMath::normalize(to);
|
||||||
|
const float d = VMath::dot(dir, _data._dir);
|
||||||
|
if (coneIn)
|
||||||
|
_data._coneIn = d;
|
||||||
|
else
|
||||||
|
_data._coneIn = _data._coneOut = Math::Clamp<float>(d, cos(Math::ToRadians(80)), cos(Math::ToRadians(10)));
|
||||||
|
const float angle = acos(_data._coneOut);
|
||||||
|
const float minIn = cos(angle - Math::ToRadians(10));
|
||||||
|
_data._coneIn = Math::Clamp<float>(_data._coneIn, minIn, 1);
|
||||||
|
SetCone(_data._coneIn, _data._coneOut);
|
||||||
|
}
|
||||||
|
|
||||||
|
Transform3 Light::GetTransformNoScale() const
|
||||||
|
{
|
||||||
|
const Matrix3 matR = Matrix3::MakeAimZ(_data._dir);
|
||||||
|
return Transform3(matR, Vector3(GetPosition()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Light::SetTransform(RcTransform3 mat)
|
||||||
|
{
|
||||||
|
_data._dir = VMath::normalize(mat.getCol2());
|
||||||
|
const Transform3 tr = VMath::appendScale(mat, ComputeScale());
|
||||||
|
SceneNode::SetTransform(tr);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3 Light::ComputeScale()
|
||||||
|
{
|
||||||
|
switch (_data._lightType)
|
||||||
|
{
|
||||||
|
case CGI::LightType::dir:
|
||||||
|
return Vector3::Replicate(1);
|
||||||
|
case CGI::LightType::omni:
|
||||||
|
return Vector3::Replicate(_data._radius);
|
||||||
|
case CGI::LightType::spot:
|
||||||
|
const float angle = acos(_data._coneOut);
|
||||||
|
const float scaleXY = tan(angle);
|
||||||
|
return Vector3(_data._radius * scaleXY, _data._radius * scaleXY, _data._radius);
|
||||||
|
}
|
||||||
|
return Vector3::Replicate(_data._radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Light::ComputeTransform()
|
||||||
|
{
|
||||||
|
const Matrix3 matR = Matrix3::MakeAimZ(_data._dir);
|
||||||
|
const Transform3 tr = VMath::appendScale(Transform3(matR, Vector3(GetPosition())), ComputeScale());
|
||||||
|
SceneNode::SetTransform(tr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Light::UpdateBounds()
|
||||||
|
{
|
||||||
|
const bool dir = (CGI::LightType::dir == _data._lightType);
|
||||||
|
const bool octreeRoot = (_dynamic || dir);
|
||||||
|
|
||||||
|
VERUS_QREF_HELPERS;
|
||||||
|
RMesh mesh = helpers.GetDeferredLights().Get(_data._lightType);
|
||||||
|
if (mesh.IsLoaded())
|
||||||
|
{
|
||||||
|
if (!_octreeBindOnce)
|
||||||
|
{
|
||||||
|
_bounds = Math::Bounds::MakeFromOrientedBox(mesh.GetBounds(), _tr);
|
||||||
|
SceneManager::I().GetOctree().BindClient(Math::Octree::Client(_bounds, this), octreeRoot);
|
||||||
|
_octreeBindOnce = octreeRoot;
|
||||||
|
}
|
||||||
|
if (_dynamic)
|
||||||
|
{
|
||||||
|
_bounds = Math::Bounds::MakeFromOrientedBox(mesh.GetBounds(), _tr);
|
||||||
|
SceneManager::I().GetOctree().UpdateDynamicBounds(Math::Octree::Client(_bounds, this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Light::SaveXML(pugi::xml_node node)
|
||||||
|
{
|
||||||
|
SceneNode::SaveXML(node);
|
||||||
|
|
||||||
|
switch (_data._lightType)
|
||||||
|
{
|
||||||
|
case CGI::LightType::dir: node.append_attribute("url") = "DIR"; break;
|
||||||
|
case CGI::LightType::omni: node.append_attribute("url") = "OMNI"; break;
|
||||||
|
case CGI::LightType::spot: node.append_attribute("url") = "SPOT"; break;
|
||||||
|
}
|
||||||
|
node.append_attribute("type") = +_data._lightType;
|
||||||
|
node.append_attribute("color") = _C(_data._color.ToString(true));
|
||||||
|
node.append_attribute("dir") = _C(_data._dir.ToString(true));
|
||||||
|
node.append_attribute("radius") = _data._radius;
|
||||||
|
node.append_attribute("coneIn") = _data._coneIn;
|
||||||
|
node.append_attribute("coneOut") = _data._coneOut;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Light::LoadXML(pugi::xml_node node)
|
||||||
|
{
|
||||||
|
SceneNode::LoadXML(node);
|
||||||
|
_name.clear();
|
||||||
|
|
||||||
|
Desc desc;
|
||||||
|
const int type = node.attribute("type").as_int(+CGI::LightType::omni);
|
||||||
|
desc._data._lightType = static_cast<CGI::LightType>(type);
|
||||||
|
if (auto attr = node.attribute("color"))
|
||||||
|
desc._data._color.FromString(attr.value());
|
||||||
|
if (auto attr = node.attribute("dir"))
|
||||||
|
desc._data._dir.FromString(attr.value());
|
||||||
|
desc._data._radius = node.attribute("radius").as_float(desc._data._radius);
|
||||||
|
desc._data._coneIn = node.attribute("coneIn").as_float(desc._data._coneIn);
|
||||||
|
desc._data._coneOut = node.attribute("coneOut").as_float(desc._data._coneOut);
|
||||||
|
Init(desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
// LightPtr:
|
||||||
|
|
||||||
|
void LightPtr::Init(Light::RcDesc desc)
|
||||||
|
{
|
||||||
|
VERUS_QREF_SM;
|
||||||
|
VERUS_RT_ASSERT(!_p);
|
||||||
|
_p = sm.InsertLight();
|
||||||
|
if (desc._node)
|
||||||
|
_p->LoadXML(desc._node);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_p->Init(desc);
|
||||||
|
_p->SetLightType(desc._data._lightType); // Call ComputeTransform().
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LightPwn::Done()
|
||||||
|
{
|
||||||
|
if (_p)
|
||||||
|
{
|
||||||
|
SceneManager::I().DeleteLight(_p);
|
||||||
|
_p = nullptr;
|
||||||
|
}
|
||||||
|
}
|
92
Verus/src/Scene/SceneNodes/Light.h
Normal file
92
Verus/src/Scene/SceneNodes/Light.h
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
namespace Scene
|
||||||
|
{
|
||||||
|
class LightData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Vector4 _color = Vector4::Replicate(1);
|
||||||
|
Vector3 _dir = Vector3(0, 0, 1);
|
||||||
|
CGI::LightType _lightType = CGI::LightType::omni;
|
||||||
|
float _radius = 10;
|
||||||
|
float _coneIn = cos(Math::ToRadians(35)); // [0, coneOut-10] angle cosine.
|
||||||
|
float _coneOut = cos(Math::ToRadians(45)); // [10, 80] angle cosine.
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(LightData);
|
||||||
|
|
||||||
|
//! Light is a scene node with light's info.
|
||||||
|
class Light : public SceneNode
|
||||||
|
{
|
||||||
|
LightData _data;
|
||||||
|
//Anim::CShaker _shaker;
|
||||||
|
float _intMax = 1;
|
||||||
|
bool _async_loadedMesh = false;
|
||||||
|
|
||||||
|
public:
|
||||||
|
struct Desc
|
||||||
|
{
|
||||||
|
pugi::xml_node _node;
|
||||||
|
CSZ _urlIntShaker = nullptr;
|
||||||
|
float _intShakerScale = 0.25f;
|
||||||
|
LightData _data;
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(Desc);
|
||||||
|
|
||||||
|
Light();
|
||||||
|
~Light();
|
||||||
|
|
||||||
|
void Init(RcDesc desc);
|
||||||
|
void Done();
|
||||||
|
|
||||||
|
virtual void Update() override;
|
||||||
|
virtual void Draw() override;
|
||||||
|
|
||||||
|
void SetLightType(CGI::LightType type);
|
||||||
|
CGI::LightType GetLightType() const;
|
||||||
|
virtual void SetColor(RcVector4 color) override;
|
||||||
|
virtual Vector4 GetColor() override;
|
||||||
|
void SetIntensity(float i);
|
||||||
|
float GetIntensity() const;
|
||||||
|
void SetDirection(RcVector3 dir);
|
||||||
|
RcVector3 GetDirection() const;
|
||||||
|
void SetRadius(float r);
|
||||||
|
float GetRadius() const;
|
||||||
|
void SetCone(float coneIn = 0, float coneOut = 0);
|
||||||
|
float GetConeIn() const;
|
||||||
|
float GetConeOut() const;
|
||||||
|
Vector4 GetInstData() const;
|
||||||
|
|
||||||
|
void DirFromPoint(RcPoint3 point, float radiusScale = 0);
|
||||||
|
void ConeFromPoint(RcPoint3 point, bool coneIn = false);
|
||||||
|
|
||||||
|
Transform3 GetTransformNoScale() const;
|
||||||
|
virtual void SetTransform(RcTransform3 mat) override;
|
||||||
|
VERUS_P(Vector3 ComputeScale());
|
||||||
|
VERUS_P(void ComputeTransform());
|
||||||
|
|
||||||
|
virtual void UpdateBounds() override;
|
||||||
|
|
||||||
|
// Serialization:
|
||||||
|
virtual void SaveXML(pugi::xml_node node) override;
|
||||||
|
virtual void LoadXML(pugi::xml_node node) override;
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(Light);
|
||||||
|
|
||||||
|
class LightPtr : public Ptr<Light>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void Init(Light::RcDesc desc);
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(LightPtr);
|
||||||
|
|
||||||
|
class LightPwn : public LightPtr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
~LightPwn() { Done(); }
|
||||||
|
void Done();
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(LightPwn);
|
||||||
|
}
|
||||||
|
}
|
96
Verus/src/Scene/SceneNodes/Model.cpp
Normal file
96
Verus/src/Scene/SceneNodes/Model.cpp
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
#include "verus.h"
|
||||||
|
|
||||||
|
using namespace verus;
|
||||||
|
using namespace verus::Scene;
|
||||||
|
|
||||||
|
// Model:
|
||||||
|
|
||||||
|
Model::Model()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Model::~Model()
|
||||||
|
{
|
||||||
|
Done();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Model::Init(RcDesc desc)
|
||||||
|
{
|
||||||
|
if (_refCount)
|
||||||
|
return;
|
||||||
|
|
||||||
|
VERUS_INIT();
|
||||||
|
_refCount = 1;
|
||||||
|
|
||||||
|
Mesh::Desc meshDesc;
|
||||||
|
meshDesc._url = desc._url;
|
||||||
|
meshDesc._instanceCapacity = 1000;
|
||||||
|
meshDesc._initShape = true;
|
||||||
|
_mesh.Init(meshDesc);
|
||||||
|
|
||||||
|
Material::Desc matDesc;
|
||||||
|
matDesc._name = desc._mat ? desc._mat : desc._url;
|
||||||
|
matDesc._load = true;
|
||||||
|
_material.Init(matDesc);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Model::Done()
|
||||||
|
{
|
||||||
|
_refCount--;
|
||||||
|
if (_refCount <= 0)
|
||||||
|
{
|
||||||
|
VERUS_DONE(Model);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Model::MarkFirstInstance()
|
||||||
|
{
|
||||||
|
_mesh.MarkFirstInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Model::Draw(CGI::CommandBufferPtr cb)
|
||||||
|
{
|
||||||
|
if (!_mesh.IsInstanceBufferEmpty(true))
|
||||||
|
{
|
||||||
|
_mesh.UpdateInstanceBuffer();
|
||||||
|
cb->DrawIndexed(_mesh.GetIndexCount(), _mesh.GetInstanceCount(true), 0, 0, _mesh.GetFirstInstance());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Model::BindPipeline(CGI::CommandBufferPtr cb)
|
||||||
|
{
|
||||||
|
_mesh.BindPipelineInstanced(cb, false);
|
||||||
|
_mesh.UpdateUniformBufferPerFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Model::BindGeo(CGI::CommandBufferPtr cb)
|
||||||
|
{
|
||||||
|
_mesh.BindGeo(cb);
|
||||||
|
_mesh.UpdateUniformBufferPerMeshVS();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Model::PushInstance(RcTransform3 matW, RcVector4 instData)
|
||||||
|
{
|
||||||
|
_mesh.PushInstance(matW, instData);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ModelPtr:
|
||||||
|
|
||||||
|
void ModelPtr::Init(Model::RcDesc desc)
|
||||||
|
{
|
||||||
|
VERUS_QREF_SM;
|
||||||
|
VERUS_RT_ASSERT(!_p);
|
||||||
|
_p = sm.InsertModel(desc._url);
|
||||||
|
_p->Init(desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModelPwn::Done()
|
||||||
|
{
|
||||||
|
if (_p)
|
||||||
|
{
|
||||||
|
SceneManager::I().DeleteModel(_C(_p->GetMesh().GetUrl()));
|
||||||
|
_p = nullptr;
|
||||||
|
}
|
||||||
|
}
|
62
Verus/src/Scene/SceneNodes/Model.h
Normal file
62
Verus/src/Scene/SceneNodes/Model.h
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
namespace Scene
|
||||||
|
{
|
||||||
|
//! Model is an element of the scene manager container
|
||||||
|
//! * has a mesh
|
||||||
|
//! * has a material
|
||||||
|
//! * has generic parameters
|
||||||
|
class Model : public Object
|
||||||
|
{
|
||||||
|
Mesh _mesh;
|
||||||
|
MaterialPwn _material;
|
||||||
|
IO::Dictionary _dict;
|
||||||
|
int _refCount = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
struct Desc
|
||||||
|
{
|
||||||
|
CSZ _url = nullptr;
|
||||||
|
CSZ _mat = nullptr;
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(Desc);
|
||||||
|
|
||||||
|
Model();
|
||||||
|
~Model();
|
||||||
|
|
||||||
|
void Init(RcDesc desc);
|
||||||
|
bool Done();
|
||||||
|
|
||||||
|
bool IsLoaded() const { return _mesh.IsLoaded(); }
|
||||||
|
|
||||||
|
void AddRef() { _refCount++; }
|
||||||
|
|
||||||
|
void MarkFirstInstance();
|
||||||
|
void Draw(CGI::CommandBufferPtr cb);
|
||||||
|
void BindPipeline(CGI::CommandBufferPtr cb);
|
||||||
|
void BindGeo(CGI::CommandBufferPtr cb);
|
||||||
|
void PushInstance(RcTransform3 matW, RcVector4 instData);
|
||||||
|
|
||||||
|
RMesh GetMesh() { return _mesh; }
|
||||||
|
MaterialPtr GetMaterial() { return _material; }
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(Model);
|
||||||
|
|
||||||
|
class ModelPtr : public Ptr<Model>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void Init(Model::RcDesc desc);
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(ModelPtr);
|
||||||
|
|
||||||
|
class ModelPwn : public ModelPtr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
~ModelPwn() { Done(); }
|
||||||
|
void Done();
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(ModelPwn);
|
||||||
|
}
|
||||||
|
}
|
137
Verus/src/Scene/SceneNodes/SceneNode.cpp
Normal file
137
Verus/src/Scene/SceneNodes/SceneNode.cpp
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
#include "verus.h"
|
||||||
|
|
||||||
|
using namespace verus;
|
||||||
|
using namespace verus::Scene;
|
||||||
|
|
||||||
|
// SceneNode:
|
||||||
|
|
||||||
|
SceneNode::SceneNode()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SceneNode::~SceneNode()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int SceneNode::UserPtr_GetType()
|
||||||
|
{
|
||||||
|
return +_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneNode::DrawBounds()
|
||||||
|
{
|
||||||
|
if (!_bounds.IsNull())
|
||||||
|
{
|
||||||
|
VERUS_QREF_HELPERS;
|
||||||
|
helpers.DrawBox(&_bounds.GetDrawTransform());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneNode::SetTransform(RcTransform3 tr)
|
||||||
|
{
|
||||||
|
_tr = tr;
|
||||||
|
// Also update the UI values and bounds:
|
||||||
|
const Quat q(_tr.getUpper3x3());
|
||||||
|
_uiRotation.EulerFromQuaternion(q);
|
||||||
|
_uiScale = _tr.GetScale();
|
||||||
|
UpdateBounds();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneNode::ComputeTransform()
|
||||||
|
{
|
||||||
|
Quat q;
|
||||||
|
_uiRotation.EulerToQuaternion(q);
|
||||||
|
_tr = VMath::appendScale(Transform3(q, _tr.getTranslation()), _uiScale);
|
||||||
|
}
|
||||||
|
|
||||||
|
Point3 SceneNode::GetPosition() const
|
||||||
|
{
|
||||||
|
return _tr.getTranslation();
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3 SceneNode::GetRotation() const
|
||||||
|
{
|
||||||
|
return _uiRotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3 SceneNode::GetScale() const
|
||||||
|
{
|
||||||
|
return _uiScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneNode::MoveTo(RcPoint3 pos)
|
||||||
|
{
|
||||||
|
_tr.setTranslation(Vector3(pos));
|
||||||
|
UpdateBounds();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneNode::RotateTo(RcVector3 v)
|
||||||
|
{
|
||||||
|
_uiRotation = v;
|
||||||
|
ComputeTransform();
|
||||||
|
UpdateBounds();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneNode::ScaleTo(RcVector3 v)
|
||||||
|
{
|
||||||
|
_uiScale = v;
|
||||||
|
ComputeTransform();
|
||||||
|
UpdateBounds();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneNode::RemoveRigidBody()
|
||||||
|
{
|
||||||
|
if (_pBody)
|
||||||
|
{
|
||||||
|
VERUS_QREF_BULLET;
|
||||||
|
bullet.GetWorld()->removeRigidBody(_pBody);
|
||||||
|
delete _pBody->getMotionState();
|
||||||
|
delete _pBody;
|
||||||
|
_pBody = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneNode::SetCollisionGroup(Physics::Group g)
|
||||||
|
{
|
||||||
|
if (_pBody && _pBody->getBroadphaseHandle()->m_collisionFilterGroup != +g)
|
||||||
|
{
|
||||||
|
// http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=7538
|
||||||
|
VERUS_QREF_BULLET;
|
||||||
|
bullet.GetWorld()->removeRigidBody(_pBody);
|
||||||
|
bullet.GetWorld()->addRigidBody(_pBody, +g, -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneNode::MoveRigidBody()
|
||||||
|
{
|
||||||
|
if (_pBody)
|
||||||
|
{
|
||||||
|
// http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=6729
|
||||||
|
VERUS_QREF_BULLET;
|
||||||
|
_pBody->setWorldTransform(_tr.Bullet());
|
||||||
|
bullet.GetWorld()->updateSingleAabb(_pBody);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneNode::SaveXML(pugi::xml_node node)
|
||||||
|
{
|
||||||
|
node.append_attribute("name") = _C(_name);
|
||||||
|
node.append_attribute("uiR") = _C(_uiRotation.ToString(true));
|
||||||
|
node.append_attribute("uiS") = _C(_uiScale.ToString(true));
|
||||||
|
node.append_attribute("m") = _C(_tr.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneNode::LoadXML(pugi::xml_node node)
|
||||||
|
{
|
||||||
|
if (auto attr = node.attribute("name"))
|
||||||
|
_name = attr.value();
|
||||||
|
_uiRotation.FromString(node.attribute("uiR").value());
|
||||||
|
_uiScale.FromString(node.attribute("uiS").value());
|
||||||
|
_tr.FromString(node.attribute("m").value());
|
||||||
|
}
|
||||||
|
|
||||||
|
float SceneNode::GetDistToEyeSq() const
|
||||||
|
{
|
||||||
|
VERUS_QREF_SM;
|
||||||
|
return VMath::distSqr(sm.GetCamera()->GetEyePosition(), GetPosition());
|
||||||
|
}
|
82
Verus/src/Scene/SceneNodes/SceneNode.h
Normal file
82
Verus/src/Scene/SceneNodes/SceneNode.h
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
namespace Scene
|
||||||
|
{
|
||||||
|
//! SceneNode is an element of the scene manager container.
|
||||||
|
//! * has a name
|
||||||
|
//! * can be parent or child
|
||||||
|
//! * has generic parameters
|
||||||
|
//! * has bounds
|
||||||
|
//! * can be transformed using the gizmo
|
||||||
|
class SceneNode : public AllocatorAware, public Physics::UserPtr
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
Transform3 _tr = Transform3::identity(); //!< Main transformation matrix.
|
||||||
|
Vector3 _uiRotation = Vector3(0); //!< User-friendly rotation used in editor's UI.
|
||||||
|
Vector3 _uiScale = Vector3(1, 1, 1); //!< User-friendly scale used in editor's UI.
|
||||||
|
Math::Bounds _bounds;
|
||||||
|
IO::Dictionary _dict;
|
||||||
|
String _name;
|
||||||
|
String _parent;
|
||||||
|
btRigidBody* _pBody = nullptr;
|
||||||
|
NodeType _type = NodeType::unknown;
|
||||||
|
bool _hidden = false;
|
||||||
|
bool _dynamic = false;
|
||||||
|
bool _octreeBindOnce = false; //!< Don't rebind this node after every bounds change.
|
||||||
|
|
||||||
|
public:
|
||||||
|
SceneNode();
|
||||||
|
virtual ~SceneNode();
|
||||||
|
|
||||||
|
virtual int UserPtr_GetType() override;
|
||||||
|
|
||||||
|
virtual void Update() {}
|
||||||
|
virtual void Draw() {}
|
||||||
|
virtual void DrawImmediate() {}
|
||||||
|
void DrawBounds();
|
||||||
|
|
||||||
|
Str GetName() const { return _C(_name); }
|
||||||
|
NodeType GetType() const { return _type; }
|
||||||
|
virtual String GetUrl() { return ""; }
|
||||||
|
IO::RDictionary GetDictionary() { return _dict; }
|
||||||
|
|
||||||
|
void Hide(bool hide = true) { _hidden = hide; }
|
||||||
|
bool IsHidden() const { return _hidden; }
|
||||||
|
|
||||||
|
virtual void SetDynamic(bool mode) { _dynamic = mode; }
|
||||||
|
bool IsDynamic() const { return _dynamic; }
|
||||||
|
|
||||||
|
virtual Vector4 GetColor() { return Vector4(0); }
|
||||||
|
virtual void SetColor(RcVector4 color) {}
|
||||||
|
|
||||||
|
RcTransform3 GetTransform() const { return _tr; }
|
||||||
|
virtual void SetTransform(RcTransform3 tr);
|
||||||
|
VERUS_P(void ComputeTransform());
|
||||||
|
|
||||||
|
Point3 GetPosition() const; //!< Gets the position from the main transformation matrix.
|
||||||
|
Vector3 GetRotation() const; //!< Gets the user-friendly rotation.
|
||||||
|
Vector3 GetScale() const; //!< Gets the user-friendly scale.
|
||||||
|
virtual void MoveTo(RcPoint3 pos);
|
||||||
|
virtual void RotateTo(RcVector3 v);
|
||||||
|
virtual void ScaleTo(RcVector3 v);
|
||||||
|
|
||||||
|
// Bounds:
|
||||||
|
Math::RcBounds GetBounds() const { return _bounds; }
|
||||||
|
virtual void UpdateBounds() {}
|
||||||
|
|
||||||
|
// Physics engine:
|
||||||
|
void RemoveRigidBody();
|
||||||
|
virtual void SetCollisionGroup(Physics::Group g = Physics::Group::immovable);
|
||||||
|
virtual void MoveRigidBody();
|
||||||
|
|
||||||
|
// Serialization:
|
||||||
|
virtual void SaveXML(pugi::xml_node node);
|
||||||
|
virtual void LoadXML(pugi::xml_node node);
|
||||||
|
|
||||||
|
float GetDistToEyeSq() const;
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(SceneNode);
|
||||||
|
}
|
||||||
|
}
|
1
Verus/src/Scene/SceneNodes/SceneNodes.cpp
Normal file
1
Verus/src/Scene/SceneNodes/SceneNodes.cpp
Normal file
|
@ -0,0 +1 @@
|
||||||
|
#include "verus.h"
|
12
Verus/src/Scene/SceneNodes/SceneNodes.h
Normal file
12
Verus/src/Scene/SceneNodes/SceneNodes.h
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Model.h"
|
||||||
|
//#include "SceneParticles.h"
|
||||||
|
#include "Types.h"
|
||||||
|
#include "SceneNode.h"
|
||||||
|
#include "TransformGizmo.h"
|
||||||
|
#include "Light.h"
|
||||||
|
//#include "Emitter.h"
|
||||||
|
#include "Block.h"
|
||||||
|
//#include "Prefab.h"
|
||||||
|
//#include "Site.h"
|
54
Verus/src/Scene/SceneNodes/TransformGizmo.cpp
Normal file
54
Verus/src/Scene/SceneNodes/TransformGizmo.cpp
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
#include "verus.h"
|
||||||
|
|
||||||
|
using namespace verus;
|
||||||
|
using namespace verus::Scene;
|
||||||
|
|
||||||
|
TransformGizmo::TransformGizmo()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
TransformGizmo::~TransformGizmo()
|
||||||
|
{
|
||||||
|
Done();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransformGizmo::Init()
|
||||||
|
{
|
||||||
|
VERUS_INIT();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransformGizmo::Done()
|
||||||
|
{
|
||||||
|
VERUS_DONE(TransformGizmo);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransformGizmo::Draw()
|
||||||
|
{
|
||||||
|
VERUS_QREF_HELPERS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransformGizmo::DragController_GetParams(float& x, float& y)
|
||||||
|
{
|
||||||
|
x = y = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransformGizmo::DragController_SetParams(float x, float y)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransformGizmo::DragController_GetRatio(float& x, float& y)
|
||||||
|
{
|
||||||
|
x = y = 0.001f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransformGizmo::DragController_Begin()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransformGizmo::DragController_End()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransformGizmo::DragController_SetScale(float s)
|
||||||
|
{
|
||||||
|
}
|
27
Verus/src/Scene/SceneNodes/TransformGizmo.h
Normal file
27
Verus/src/Scene/SceneNodes/TransformGizmo.h
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
namespace Scene
|
||||||
|
{
|
||||||
|
class TransformGizmo : public Object, public SceneNode, public Input::DragControllerDelegate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TransformGizmo();
|
||||||
|
~TransformGizmo();
|
||||||
|
|
||||||
|
void Init();
|
||||||
|
void Done();
|
||||||
|
|
||||||
|
void Draw();
|
||||||
|
|
||||||
|
virtual void DragController_GetParams(float& x, float& y) override;
|
||||||
|
virtual void DragController_SetParams(float x, float y) override;
|
||||||
|
virtual void DragController_GetRatio(float& x, float& y) override;
|
||||||
|
virtual void DragController_Begin() override;
|
||||||
|
virtual void DragController_End() override;
|
||||||
|
virtual void DragController_SetScale(float s) override;
|
||||||
|
};
|
||||||
|
VERUS_TYPEDEFS(TransformGizmo);
|
||||||
|
}
|
||||||
|
}
|
23
Verus/src/Scene/SceneNodes/Types.h
Normal file
23
Verus/src/Scene/SceneNodes/Types.h
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace verus
|
||||||
|
{
|
||||||
|
namespace Scene
|
||||||
|
{
|
||||||
|
//! SceneManager will sort nodes using their type.
|
||||||
|
enum class NodeType : int
|
||||||
|
{
|
||||||
|
unknown,
|
||||||
|
block,
|
||||||
|
light,
|
||||||
|
prefab,
|
||||||
|
emitter,
|
||||||
|
site,
|
||||||
|
terrain,
|
||||||
|
character,
|
||||||
|
vehicle,
|
||||||
|
transformGizmo,
|
||||||
|
count
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -54,20 +54,20 @@ void ShadowMap::Begin(RcVector3 dirToSun, float zNear, float zFar)
|
||||||
|
|
||||||
const Vector3 up(0, 1, 0);
|
const Vector3 up(0, 1, 0);
|
||||||
Point3 eye, at;
|
Point3 eye, at;
|
||||||
const float size = 4096 * 0.005f;
|
const float texSizeInMeters = 4096 * 0.005f;
|
||||||
if (0 == zFar)
|
if (0 == zFar)
|
||||||
zFar = 1001;
|
zFar = 1001;
|
||||||
|
|
||||||
at = sm.GetCamera()->GetEyePosition() + sm.GetCamera()->GetFrontDirection() * (size * (1 / 3.f));
|
at = sm.GetCamera()->GetEyePosition() + sm.GetCamera()->GetFrontDirection() * (texSizeInMeters * (1 / 3.f));
|
||||||
if (_snapToTexels)
|
if (_snapToTexels)
|
||||||
{
|
{
|
||||||
const Matrix4 matToShadowSpace = Matrix4::lookAt(Point3(dirToSun), Point3(0), up);
|
const Matrix4 matToShadowSpace = Matrix4::lookAt(Point3(dirToSun), Point3(0), up);
|
||||||
const Matrix4 matFromShadowSpace = VMath::orthoInverse(matToShadowSpace);
|
const Matrix4 matFromShadowSpace = VMath::orthoInverse(matToShadowSpace);
|
||||||
const Point3 atPosShadowSpace = (matToShadowSpace * at).getXYZ();
|
const Point3 atPosShadowSpace = (matToShadowSpace * at).getXYZ();
|
||||||
const float texelSize = size / _side;
|
const float texelSizeInMeters = texSizeInMeters / _side;
|
||||||
Point3 atPosShadowSpaceSnapped(atPosShadowSpace);
|
Point3 atPosShadowSpaceSnapped(atPosShadowSpace);
|
||||||
atPosShadowSpaceSnapped.setX(atPosShadowSpaceSnapped.getX() - fmod(static_cast<float>(atPosShadowSpaceSnapped.getX()), texelSize));
|
atPosShadowSpaceSnapped.setX(atPosShadowSpaceSnapped.getX() - fmod(atPosShadowSpaceSnapped.getX(), texelSizeInMeters));
|
||||||
atPosShadowSpaceSnapped.setY(atPosShadowSpaceSnapped.getY() - fmod(static_cast<float>(atPosShadowSpaceSnapped.getY()), texelSize));
|
atPosShadowSpaceSnapped.setY(atPosShadowSpaceSnapped.getY() - fmod(atPosShadowSpaceSnapped.getY(), texelSizeInMeters));
|
||||||
at = (matFromShadowSpace * atPosShadowSpaceSnapped).getXYZ();
|
at = (matFromShadowSpace * atPosShadowSpaceSnapped).getXYZ();
|
||||||
}
|
}
|
||||||
eye = at + dirToSun * ((zFar - zNear) * 0.5f);
|
eye = at + dirToSun * ((zFar - zNear) * 0.5f);
|
||||||
|
@ -79,8 +79,8 @@ void ShadowMap::Begin(RcVector3 dirToSun, float zNear, float zFar)
|
||||||
_camera.SetFovY(0);
|
_camera.SetFovY(0);
|
||||||
_camera.SetZNear(zNear);
|
_camera.SetZNear(zNear);
|
||||||
_camera.SetZFar(zFar);
|
_camera.SetZFar(zFar);
|
||||||
_camera.SetWidth(size);
|
_camera.SetWidth(texSizeInMeters);
|
||||||
_camera.SetHeight(size);
|
_camera.SetHeight(texSizeInMeters);
|
||||||
_camera.Update();
|
_camera.Update();
|
||||||
_pSceneCamera = sm.SetCamera(&_camera);
|
_pSceneCamera = sm.SetCamera(&_camera);
|
||||||
|
|
||||||
|
@ -239,8 +239,7 @@ void CascadedShadowMap::Begin(RcVector3 dirToSun, float zNear, float zFar, int s
|
||||||
|
|
||||||
const Vector3 up(0, 1, 0);
|
const Vector3 up(0, 1, 0);
|
||||||
Point3 eye, at;
|
Point3 eye, at;
|
||||||
int sideW, sideH, side;
|
float texWidthInMeters, texHeightInMeters, texSizeInMeters;
|
||||||
float sizeW, sizeH;
|
|
||||||
|
|
||||||
float zNearFrustum, zFarFrustum;
|
float zNearFrustum, zFarFrustum;
|
||||||
const float closerToLight = 1500;
|
const float closerToLight = 1500;
|
||||||
|
@ -267,10 +266,9 @@ void CascadedShadowMap::Begin(RcVector3 dirToSun, float zNear, float zFar, int s
|
||||||
if (0 == zFar)
|
if (0 == zFar)
|
||||||
zFar = abs(zFarFrustum - zNearFrustum) + closerToLight;
|
zFar = abs(zFarFrustum - zNearFrustum) + closerToLight;
|
||||||
|
|
||||||
sideW = static_cast<int>(frustumBounds.getZ() - frustumBounds.getX() + 2.5f);
|
texWidthInMeters = ceil(frustumBounds.getZ() - frustumBounds.getX() + 2.5f);
|
||||||
sideH = static_cast<int>(frustumBounds.getW() - frustumBounds.getY() + 2.5f);
|
texHeightInMeters = ceil(frustumBounds.getW() - frustumBounds.getY() + 2.5f);
|
||||||
sizeW = static_cast<float>(sideW);
|
texSizeInMeters = Math::Max(texWidthInMeters, texHeightInMeters);
|
||||||
sizeH = static_cast<float>(sideH);
|
|
||||||
|
|
||||||
// Setup CSM light space camera for full range (used for terrain layout, etc.):
|
// Setup CSM light space camera for full range (used for terrain layout, etc.):
|
||||||
_cameraCSM.SetUpDirection(up);
|
_cameraCSM.SetUpDirection(up);
|
||||||
|
@ -279,8 +277,8 @@ void CascadedShadowMap::Begin(RcVector3 dirToSun, float zNear, float zFar, int s
|
||||||
_cameraCSM.SetFovY(0);
|
_cameraCSM.SetFovY(0);
|
||||||
_cameraCSM.SetZNear(zNear);
|
_cameraCSM.SetZNear(zNear);
|
||||||
_cameraCSM.SetZFar(zFar);
|
_cameraCSM.SetZFar(zFar);
|
||||||
_cameraCSM.SetWidth(sizeW);
|
_cameraCSM.SetWidth(texSizeInMeters);
|
||||||
_cameraCSM.SetHeight(sizeH);
|
_cameraCSM.SetHeight(texSizeInMeters);
|
||||||
_cameraCSM.Update();
|
_cameraCSM.Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -319,26 +317,16 @@ void CascadedShadowMap::Begin(RcVector3 dirToSun, float zNear, float zFar, int s
|
||||||
(frustumBounds.getY() + frustumBounds.getW()) * 0.5f,
|
(frustumBounds.getY() + frustumBounds.getW()) * 0.5f,
|
||||||
zNearFrustum);
|
zNearFrustum);
|
||||||
|
|
||||||
sideW = static_cast<int>(frustumBounds.getZ() - frustumBounds.getX() + 2.5f);
|
texWidthInMeters = ceil(frustumBounds.getZ() - frustumBounds.getX() + 2.5f);
|
||||||
sideH = static_cast<int>(frustumBounds.getW() - frustumBounds.getY() + 2.5f);
|
texHeightInMeters = ceil(frustumBounds.getW() - frustumBounds.getY() + 2.5f);
|
||||||
if (_currentSplit < 3)
|
texSizeInMeters = Math::Max(texWidthInMeters, texHeightInMeters);
|
||||||
{
|
|
||||||
side = (sideW < sideH) ? sideH : sideW;
|
|
||||||
side = Math::NextPowerOfTwo(side);
|
|
||||||
sizeW = static_cast<float>(side);
|
|
||||||
sizeH = static_cast<float>(side);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sizeW = static_cast<float>(sideW);
|
|
||||||
sizeH = static_cast<float>(sideH);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_snapToTexels)
|
if (_snapToTexels)
|
||||||
{
|
{
|
||||||
const float sideInv = 2.f / _side;
|
const float invSide = 2.f / _side;
|
||||||
pos.setX(pos.getX() - fmod(static_cast<float>(pos.getX()), sizeW * sideInv));
|
const float texelSizeInMeters = texSizeInMeters * invSide;
|
||||||
pos.setY(pos.getY() - fmod(static_cast<float>(pos.getY()), sizeH * sideInv));
|
pos.setX(pos.getX() - fmod(pos.getX(), texelSizeInMeters));
|
||||||
|
pos.setY(pos.getY() - fmod(pos.getY(), texelSizeInMeters));
|
||||||
}
|
}
|
||||||
pos = (VMath::orthoInverse(matToLightSpace) * pos).getXYZ(); // To world space.
|
pos = (VMath::orthoInverse(matToLightSpace) * pos).getXYZ(); // To world space.
|
||||||
|
|
||||||
|
@ -356,8 +344,8 @@ void CascadedShadowMap::Begin(RcVector3 dirToSun, float zNear, float zFar, int s
|
||||||
_camera.SetFovY(0);
|
_camera.SetFovY(0);
|
||||||
_camera.SetZNear(zNear);
|
_camera.SetZNear(zNear);
|
||||||
_camera.SetZFar(zFar);
|
_camera.SetZFar(zFar);
|
||||||
_camera.SetWidth(sizeW);
|
_camera.SetWidth(texSizeInMeters);
|
||||||
_camera.SetHeight(sizeH);
|
_camera.SetHeight(texSizeInMeters);
|
||||||
_camera.Update();
|
_camera.Update();
|
||||||
_pSceneCamera = sm.SetCamera(&_camera);
|
_pSceneCamera = sm.SetCamera(&_camera);
|
||||||
|
|
||||||
|
|
|
@ -422,6 +422,7 @@ void Terrain::Init(RcDesc desc)
|
||||||
VERUS_INIT();
|
VERUS_INIT();
|
||||||
VERUS_QREF_RENDERER;
|
VERUS_QREF_RENDERER;
|
||||||
VERUS_QREF_CONST_SETTINGS;
|
VERUS_QREF_CONST_SETTINGS;
|
||||||
|
VERUS_QREF_ATMO;
|
||||||
|
|
||||||
if (!Math::IsPowerOfTwo(desc._mapSide))
|
if (!Math::IsPowerOfTwo(desc._mapSide))
|
||||||
throw VERUS_RECOVERABLE << "Init(), mapSide must be power of two";
|
throw VERUS_RECOVERABLE << "Init(), mapSide must be power of two";
|
||||||
|
@ -543,8 +544,17 @@ void Terrain::Init(RcDesc desc)
|
||||||
pipeDesc._primitiveRestartEnable = true;
|
pipeDesc._primitiveRestartEnable = true;
|
||||||
_pipe[PIPE_STRIP].Init(pipeDesc);
|
_pipe[PIPE_STRIP].Init(pipeDesc);
|
||||||
}
|
}
|
||||||
|
if (settings._gpuTessellation)
|
||||||
|
{
|
||||||
|
CGI::PipelineDesc pipeDesc(_geo, s_shader[SHADER_MAIN], "#Tess", renderer.GetDS().GetRenderPassHandle());
|
||||||
|
pipeDesc._colorAttachBlendEqs[0] = VERUS_COLOR_BLEND_OFF;
|
||||||
|
pipeDesc._colorAttachBlendEqs[1] = VERUS_COLOR_BLEND_OFF;
|
||||||
|
pipeDesc._colorAttachBlendEqs[2] = VERUS_COLOR_BLEND_OFF;
|
||||||
|
pipeDesc._topology = CGI::PrimitiveTopology::patchList3;
|
||||||
|
_pipe[PIPE_TESS].Init(pipeDesc);
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
VERUS_QREF_ATMO;
|
|
||||||
CGI::PipelineDesc pipeDesc(_geo, s_shader[SHADER_MAIN], "#Depth", atmo.GetShadowMap().GetRenderPassHandle());
|
CGI::PipelineDesc pipeDesc(_geo, s_shader[SHADER_MAIN], "#Depth", atmo.GetShadowMap().GetRenderPassHandle());
|
||||||
pipeDesc._colorAttachBlendEqs[0] = "";
|
pipeDesc._colorAttachBlendEqs[0] = "";
|
||||||
_pipe[PIPE_DEPTH_LIST].Init(pipeDesc);
|
_pipe[PIPE_DEPTH_LIST].Init(pipeDesc);
|
||||||
|
@ -552,6 +562,14 @@ void Terrain::Init(RcDesc desc)
|
||||||
pipeDesc._primitiveRestartEnable = true;
|
pipeDesc._primitiveRestartEnable = true;
|
||||||
_pipe[PIPE_DEPTH_STRIP].Init(pipeDesc);
|
_pipe[PIPE_DEPTH_STRIP].Init(pipeDesc);
|
||||||
}
|
}
|
||||||
|
if (settings._gpuTessellation)
|
||||||
|
{
|
||||||
|
CGI::PipelineDesc pipeDesc(_geo, s_shader[SHADER_MAIN], "#DepthTess", atmo.GetShadowMap().GetRenderPassHandle());
|
||||||
|
pipeDesc._colorAttachBlendEqs[0] = "";
|
||||||
|
pipeDesc._topology = CGI::PrimitiveTopology::patchList3;
|
||||||
|
_pipe[PIPE_DEPTH_TESS].Init(pipeDesc);
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
CGI::PipelineDesc pipeDesc(_geo, s_shader[SHADER_MAIN], "#SolidColor", renderer.GetDS().GetRenderPassHandle());
|
CGI::PipelineDesc pipeDesc(_geo, s_shader[SHADER_MAIN], "#SolidColor", renderer.GetDS().GetRenderPassHandle());
|
||||||
pipeDesc._colorAttachBlendEqs[0] = VERUS_COLOR_BLEND_OFF;
|
pipeDesc._colorAttachBlendEqs[0] = VERUS_COLOR_BLEND_OFF;
|
||||||
|
@ -566,15 +584,6 @@ void Terrain::Init(RcDesc desc)
|
||||||
pipeDesc._primitiveRestartEnable = true;
|
pipeDesc._primitiveRestartEnable = true;
|
||||||
_pipe[PIPE_WIREFRAME_STRIP].Init(pipeDesc);
|
_pipe[PIPE_WIREFRAME_STRIP].Init(pipeDesc);
|
||||||
}
|
}
|
||||||
if (settings._gpuTessellation)
|
|
||||||
{
|
|
||||||
CGI::PipelineDesc pipeDesc(_geo, s_shader[SHADER_MAIN], "#Tess", renderer.GetDS().GetRenderPassHandle());
|
|
||||||
pipeDesc._colorAttachBlendEqs[0] = VERUS_COLOR_BLEND_OFF;
|
|
||||||
pipeDesc._colorAttachBlendEqs[1] = VERUS_COLOR_BLEND_OFF;
|
|
||||||
pipeDesc._colorAttachBlendEqs[2] = VERUS_COLOR_BLEND_OFF;
|
|
||||||
pipeDesc._topology = CGI::PrimitiveTopology::patchList3;
|
|
||||||
_pipe[PIPE_TESS].Init(pipeDesc);
|
|
||||||
}
|
|
||||||
|
|
||||||
CGI::TextureDesc texDesc;
|
CGI::TextureDesc texDesc;
|
||||||
texDesc._format = CGI::Format::floatR16;
|
texDesc._format = CGI::Format::floatR16;
|
||||||
|
@ -659,6 +668,11 @@ void Terrain::Done()
|
||||||
VERUS_DONE(Terrain);
|
VERUS_DONE(Terrain);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Terrain::ResetInstanceCount()
|
||||||
|
{
|
||||||
|
_instanceCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
void Terrain::Layout()
|
void Terrain::Layout()
|
||||||
{
|
{
|
||||||
VERUS_QREF_CONST_SETTINGS;
|
VERUS_QREF_CONST_SETTINGS;
|
||||||
|
@ -696,11 +710,12 @@ void Terrain::Draw(RcDrawDesc dd)
|
||||||
if (!_visiblePatchCount)
|
if (!_visiblePatchCount)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto cb = renderer.GetCommandBuffer();
|
|
||||||
|
|
||||||
const bool drawingDepth = Scene::SceneManager::IsDrawingDepth(Scene::DrawDepth::automatic);
|
const bool drawingDepth = Scene::SceneManager::IsDrawingDepth(Scene::DrawDepth::automatic);
|
||||||
|
|
||||||
const Transform3 matW = Transform3::identity();
|
const Transform3 matW = Transform3::identity();
|
||||||
|
|
||||||
|
auto cb = renderer.GetCommandBuffer();
|
||||||
|
|
||||||
s_ubTerrainVS._matW = matW.UniformBufferFormat();
|
s_ubTerrainVS._matW = matW.UniformBufferFormat();
|
||||||
s_ubTerrainVS._matWV = Transform3(sm.GetCamera()->GetMatrixV() * matW).UniformBufferFormat();
|
s_ubTerrainVS._matWV = Transform3(sm.GetCamera()->GetMatrixV() * matW).UniformBufferFormat();
|
||||||
s_ubTerrainVS._matV = sm.GetCamera()->GetMatrixV().UniformBufferFormat();
|
s_ubTerrainVS._matV = sm.GetCamera()->GetMatrixV().UniformBufferFormat();
|
||||||
|
@ -709,7 +724,6 @@ void Terrain::Draw(RcDrawDesc dd)
|
||||||
s_ubTerrainVS._eyePos_mapSideInv = float4(atmo.GetEyePosition().GLM(), 0);
|
s_ubTerrainVS._eyePos_mapSideInv = float4(atmo.GetEyePosition().GLM(), 0);
|
||||||
s_ubTerrainVS._eyePos_mapSideInv.w = 1.f / _mapSide;
|
s_ubTerrainVS._eyePos_mapSideInv.w = 1.f / _mapSide;
|
||||||
s_ubTerrainVS._viewportSize = cb->GetViewportSize().GLM();
|
s_ubTerrainVS._viewportSize = cb->GetViewportSize().GLM();
|
||||||
|
|
||||||
s_ubTerrainFS._matWV = s_ubTerrainVS._matWV;
|
s_ubTerrainFS._matWV = s_ubTerrainVS._matWV;
|
||||||
VERUS_FOR(i, VERUS_COUNT_OF(_layerData))
|
VERUS_FOR(i, VERUS_COUNT_OF(_layerData))
|
||||||
{
|
{
|
||||||
|
@ -738,14 +752,13 @@ void Terrain::Draw(RcDrawDesc dd)
|
||||||
|
|
||||||
if (!lod)
|
if (!lod)
|
||||||
{
|
{
|
||||||
|
const bool tess = dd._allowTess && settings._gpuTessellation;
|
||||||
if (dd._wireframe)
|
if (dd._wireframe)
|
||||||
cb->BindPipeline(_pipe[PIPE_WIREFRAME_LIST]);
|
cb->BindPipeline(_pipe[PIPE_WIREFRAME_LIST]);
|
||||||
else if (drawingDepth)
|
else if (drawingDepth)
|
||||||
cb->BindPipeline(_pipe[PIPE_DEPTH_LIST]);
|
cb->BindPipeline(_pipe[tess ? PIPE_DEPTH_TESS : PIPE_DEPTH_LIST]);
|
||||||
else if (dd._tess && settings._gpuTessellation)
|
|
||||||
cb->BindPipeline(_pipe[PIPE_TESS]);
|
|
||||||
else
|
else
|
||||||
cb->BindPipeline(_pipe[PIPE_LIST]);
|
cb->BindPipeline(_pipe[tess ? PIPE_TESS : PIPE_LIST]);
|
||||||
cb->BindDescriptors(s_shader[SHADER_MAIN], 0, _cshVS);
|
cb->BindDescriptors(s_shader[SHADER_MAIN], 0, _cshVS);
|
||||||
cb->BindDescriptors(s_shader[SHADER_MAIN], 1, _cshFS);
|
cb->BindDescriptors(s_shader[SHADER_MAIN], 1, _cshFS);
|
||||||
}
|
}
|
||||||
|
@ -812,15 +825,15 @@ void Terrain::DrawReflection()
|
||||||
if (!_visiblePatchCount)
|
if (!_visiblePatchCount)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
const Transform3 matW = Transform3::identity();
|
||||||
|
|
||||||
auto cb = renderer.GetCommandBuffer();
|
auto cb = renderer.GetCommandBuffer();
|
||||||
|
|
||||||
const Transform3 matW = Transform3::identity();
|
|
||||||
s_ubSimpleTerrainVS._matW = matW.UniformBufferFormat();
|
s_ubSimpleTerrainVS._matW = matW.UniformBufferFormat();
|
||||||
s_ubSimpleTerrainVS._matVP = sm.GetCamera()->GetMatrixVP().UniformBufferFormat();
|
s_ubSimpleTerrainVS._matVP = sm.GetCamera()->GetMatrixVP().UniformBufferFormat();
|
||||||
s_ubSimpleTerrainVS._eyePos = float4(atmo.GetEyePosition().GLM(), 0);
|
s_ubSimpleTerrainVS._eyePos = float4(atmo.GetEyePosition().GLM(), 0);
|
||||||
s_ubSimpleTerrainVS._mapSideInv_clipDistanceOffset.x = 1.f / _mapSide;
|
s_ubSimpleTerrainVS._mapSideInv_clipDistanceOffset.x = 1.f / _mapSide;
|
||||||
s_ubSimpleTerrainVS._mapSideInv_clipDistanceOffset.y = static_cast<float>(water.IsUnderwater() ? USHRT_MAX : 0);
|
s_ubSimpleTerrainVS._mapSideInv_clipDistanceOffset.y = static_cast<float>(water.IsUnderwater() ? USHRT_MAX : 0);
|
||||||
|
|
||||||
VERUS_FOR(i, VERUS_COUNT_OF(_layerData))
|
VERUS_FOR(i, VERUS_COUNT_OF(_layerData))
|
||||||
s_ubSimpleTerrainFS._vSpecStrength[i >> 2][i & 0x3] = _layerData[i]._specStrength;
|
s_ubSimpleTerrainFS._vSpecStrength[i >> 2][i & 0x3] = _layerData[i]._specStrength;
|
||||||
s_ubSimpleTerrainFS._lamScaleBias.x = _lamScale;
|
s_ubSimpleTerrainFS._lamScaleBias.x = _lamScale;
|
||||||
|
@ -899,11 +912,6 @@ void Terrain::DrawReflection()
|
||||||
_geo->UpdateVertexBuffer(_vInstanceBuffer.data(), 1);
|
_geo->UpdateVertexBuffer(_vInstanceBuffer.data(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Terrain::ResetInstanceCount()
|
|
||||||
{
|
|
||||||
_instanceCount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Terrain::SortVisiblePatches()
|
void Terrain::SortVisiblePatches()
|
||||||
{
|
{
|
||||||
std::sort(_vSortedPatchIndices.begin(), _vSortedPatchIndices.begin() + _visiblePatchCount, [this](int a, int b)
|
std::sort(_vSortedPatchIndices.begin(), _vSortedPatchIndices.begin() + _visiblePatchCount, [this](int a, int b)
|
||||||
|
|
|
@ -93,11 +93,14 @@ namespace verus
|
||||||
{
|
{
|
||||||
PIPE_LIST,
|
PIPE_LIST,
|
||||||
PIPE_STRIP,
|
PIPE_STRIP,
|
||||||
|
PIPE_TESS,
|
||||||
|
|
||||||
PIPE_DEPTH_LIST,
|
PIPE_DEPTH_LIST,
|
||||||
PIPE_DEPTH_STRIP,
|
PIPE_DEPTH_STRIP,
|
||||||
|
PIPE_DEPTH_TESS,
|
||||||
|
|
||||||
PIPE_WIREFRAME_LIST,
|
PIPE_WIREFRAME_LIST,
|
||||||
PIPE_WIREFRAME_STRIP,
|
PIPE_WIREFRAME_STRIP,
|
||||||
PIPE_TESS,
|
|
||||||
PIPE_REFLECTION_LIST,
|
PIPE_REFLECTION_LIST,
|
||||||
PIPE_REFLECTION_STRIP,
|
PIPE_REFLECTION_STRIP,
|
||||||
PIPE_UNDERWATER_LIST,
|
PIPE_UNDERWATER_LIST,
|
||||||
|
@ -183,7 +186,7 @@ namespace verus
|
||||||
|
|
||||||
struct DrawDesc
|
struct DrawDesc
|
||||||
{
|
{
|
||||||
bool _tess = false;
|
bool _allowTess = false;
|
||||||
bool _wireframe = false;
|
bool _wireframe = false;
|
||||||
|
|
||||||
void Reset()
|
void Reset()
|
||||||
|
@ -203,12 +206,11 @@ namespace verus
|
||||||
void InitByWater();
|
void InitByWater();
|
||||||
void Done();
|
void Done();
|
||||||
|
|
||||||
|
void ResetInstanceCount();
|
||||||
void Layout();
|
void Layout();
|
||||||
void Draw(RcDrawDesc dd = DrawDesc());
|
void Draw(RcDrawDesc dd = DrawDesc());
|
||||||
void DrawReflection();
|
void DrawReflection();
|
||||||
|
|
||||||
void ResetInstanceCount();
|
|
||||||
|
|
||||||
void SortVisiblePatches();
|
void SortVisiblePatches();
|
||||||
|
|
||||||
virtual int UserPtr_GetType() override;
|
virtual int UserPtr_GetType() override;
|
||||||
|
|
|
@ -210,8 +210,6 @@ void Water::Draw()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto cb = renderer.GetCommandBuffer();
|
|
||||||
|
|
||||||
RCamera cam = *sm.GetCamera();
|
RCamera cam = *sm.GetCamera();
|
||||||
|
|
||||||
Transform3 matW;
|
Transform3 matW;
|
||||||
|
@ -232,6 +230,8 @@ void Water::Draw()
|
||||||
const Matrix4 matWVP = cam.GetMatrixVP() * matW;
|
const Matrix4 matWVP = cam.GetMatrixVP() * matW;
|
||||||
const Matrix4 matScreen = Matrix4(Math::ToUVMatrix()) * matShift * cam.GetMatrixVP();
|
const Matrix4 matScreen = Matrix4(Math::ToUVMatrix()) * matShift * cam.GetMatrixVP();
|
||||||
|
|
||||||
|
auto cb = renderer.GetCommandBuffer();
|
||||||
|
|
||||||
s_ubWaterVS._matW = matW.UniformBufferFormat();
|
s_ubWaterVS._matW = matW.UniformBufferFormat();
|
||||||
s_ubWaterVS._matVP = cam.GetMatrixVP().UniformBufferFormat();
|
s_ubWaterVS._matVP = cam.GetMatrixVP().UniformBufferFormat();
|
||||||
s_ubWaterVS._matScreen = matScreen.UniformBufferFormat();
|
s_ubWaterVS._matScreen = matScreen.UniformBufferFormat();
|
||||||
|
@ -264,15 +264,14 @@ void Water::Draw()
|
||||||
memcpy(&s_ubWaterFS._shadowConfig, &atmo.GetShadowMap().GetConfig(), sizeof(s_ubWaterFS._shadowConfig));
|
memcpy(&s_ubWaterFS._shadowConfig, &atmo.GetShadowMap().GetConfig(), sizeof(s_ubWaterFS._shadowConfig));
|
||||||
s_ubWaterFS._splitRanges = atmo.GetShadowMap().GetSplitRanges().GLM();
|
s_ubWaterFS._splitRanges = atmo.GetShadowMap().GetSplitRanges().GLM();
|
||||||
|
|
||||||
|
cb->BindPipeline(_pipe[PIPE_MAIN]);
|
||||||
cb->BindVertexBuffers(_geo);
|
cb->BindVertexBuffers(_geo);
|
||||||
cb->BindIndexBuffer(_geo);
|
cb->BindIndexBuffer(_geo);
|
||||||
cb->BindPipeline(_pipe[PIPE_MAIN]);
|
|
||||||
|
|
||||||
_shader[SHADER_MAIN]->BeginBindDescriptors();
|
_shader[SHADER_MAIN]->BeginBindDescriptors();
|
||||||
cb->BindDescriptors(_shader[SHADER_MAIN], 0, _cshWaterVS);
|
cb->BindDescriptors(_shader[SHADER_MAIN], 0, _cshWaterVS);
|
||||||
cb->BindDescriptors(_shader[SHADER_MAIN], 1, _cshWaterFS);
|
cb->BindDescriptors(_shader[SHADER_MAIN], 1, _cshWaterFS);
|
||||||
cb->DrawIndexed(_indexCount);
|
|
||||||
_shader[SHADER_MAIN]->EndBindDescriptors();
|
_shader[SHADER_MAIN]->EndBindDescriptors();
|
||||||
|
cb->DrawIndexed(_indexCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Water::OnSwapChainResized()
|
void Water::OnSwapChainResized()
|
||||||
|
@ -305,7 +304,7 @@ void Water::BeginReflection(CGI::PBaseCommandBuffer pCB)
|
||||||
VERUS_QREF_SM;
|
VERUS_QREF_SM;
|
||||||
|
|
||||||
if (!pCB)
|
if (!pCB)
|
||||||
pCB = &(*renderer.GetCommandBuffer());
|
pCB = renderer.GetCommandBuffer().Get();
|
||||||
|
|
||||||
_camera = *sm.GetCamera();
|
_camera = *sm.GetCamera();
|
||||||
if (!IsUnderwater(_camera.GetEyePosition()))
|
if (!IsUnderwater(_camera.GetEyePosition()))
|
||||||
|
@ -325,7 +324,7 @@ void Water::EndReflection(CGI::PBaseCommandBuffer pCB)
|
||||||
VERUS_QREF_SM;
|
VERUS_QREF_SM;
|
||||||
|
|
||||||
if (!pCB)
|
if (!pCB)
|
||||||
pCB = &(*renderer.GetCommandBuffer());
|
pCB = renderer.GetCommandBuffer().Get();
|
||||||
|
|
||||||
pCB->EndRenderPass();
|
pCB->EndRenderPass();
|
||||||
|
|
||||||
|
@ -355,54 +354,50 @@ void Water::GenerateHeightmapTexture()
|
||||||
{
|
{
|
||||||
VERUS_QREF_RENDERER;
|
VERUS_QREF_RENDERER;
|
||||||
|
|
||||||
|
auto cb = renderer.GetCommandBuffer();
|
||||||
|
|
||||||
s_ubGen._matW = Math::QuadMatrix().UniformBufferFormat();
|
s_ubGen._matW = Math::QuadMatrix().UniformBufferFormat();
|
||||||
s_ubGen._matV = Math::ToUVMatrix().UniformBufferFormat();
|
s_ubGen._matV = Math::ToUVMatrix().UniformBufferFormat();
|
||||||
s_ubGenHeightmapFS._phase.x = _phase;
|
s_ubGenHeightmapFS._phase.x = _phase;
|
||||||
memcpy(&s_ubGenHeightmapFS._amplitudes, _amplitudes, sizeof(_amplitudes));
|
memcpy(&s_ubGenHeightmapFS._amplitudes, _amplitudes, sizeof(_amplitudes));
|
||||||
|
|
||||||
auto cb = renderer.GetCommandBuffer();
|
|
||||||
|
|
||||||
cb->BeginRenderPass(_rphGenHeightmap, _fbhGenHeightmap, { _tex[TEX_GEN_HEIGHTMAP]->GetClearValue(), });
|
cb->BeginRenderPass(_rphGenHeightmap, _fbhGenHeightmap, { _tex[TEX_GEN_HEIGHTMAP]->GetClearValue(), });
|
||||||
|
|
||||||
cb->BindPipeline(_pipe[PIPE_GEN_HEIGHTMAP]);
|
cb->BindPipeline(_pipe[PIPE_GEN_HEIGHTMAP]);
|
||||||
|
|
||||||
_shader[SHADER_GEN]->BeginBindDescriptors();
|
_shader[SHADER_GEN]->BeginBindDescriptors();
|
||||||
cb->BindDescriptors(_shader[SHADER_GEN], 0);
|
cb->BindDescriptors(_shader[SHADER_GEN], 0);
|
||||||
cb->BindDescriptors(_shader[SHADER_GEN], 1, _cshGenHeightmap);
|
cb->BindDescriptors(_shader[SHADER_GEN], 1, _cshGenHeightmap);
|
||||||
_shader[SHADER_GEN]->EndBindDescriptors();
|
_shader[SHADER_GEN]->EndBindDescriptors();
|
||||||
|
renderer.DrawQuad(cb.Get());
|
||||||
renderer.DrawQuad(&(*cb));
|
|
||||||
|
|
||||||
cb->EndRenderPass();
|
cb->EndRenderPass();
|
||||||
|
|
||||||
_tex[TEX_GEN_HEIGHTMAP]->GenerateMips(&(*cb));
|
_tex[TEX_GEN_HEIGHTMAP]->GenerateMips(cb.Get());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Water::GenerateNormalsTexture()
|
void Water::GenerateNormalsTexture()
|
||||||
{
|
{
|
||||||
VERUS_QREF_RENDERER;
|
VERUS_QREF_RENDERER;
|
||||||
|
|
||||||
|
auto cb = renderer.GetCommandBuffer();
|
||||||
|
|
||||||
s_ubGen._matW = Math::QuadMatrix().UniformBufferFormat();
|
s_ubGen._matW = Math::QuadMatrix().UniformBufferFormat();
|
||||||
s_ubGen._matV = Math::ToUVMatrix().UniformBufferFormat();
|
s_ubGen._matV = Math::ToUVMatrix().UniformBufferFormat();
|
||||||
s_ubGenNormalsFS._textureSize = _tex[TEX_GEN_HEIGHTMAP]->GetSize().GLM();
|
s_ubGenNormalsFS._textureSize = _tex[TEX_GEN_HEIGHTMAP]->GetSize().GLM();
|
||||||
s_ubGenNormalsFS._waterScale.x = 1 / _patchSide;
|
s_ubGenNormalsFS._waterScale.x = 1 / _patchSide;
|
||||||
|
|
||||||
auto cb = renderer.GetCommandBuffer();
|
|
||||||
|
|
||||||
cb->BeginRenderPass(_rphGenNormals, _fbhGenNormals, { _tex[TEX_GEN_NORMALS]->GetClearValue(), });
|
cb->BeginRenderPass(_rphGenNormals, _fbhGenNormals, { _tex[TEX_GEN_NORMALS]->GetClearValue(), });
|
||||||
|
|
||||||
cb->BindPipeline(_pipe[PIPE_GEN_NORMALS]);
|
cb->BindPipeline(_pipe[PIPE_GEN_NORMALS]);
|
||||||
|
|
||||||
_shader[SHADER_GEN]->BeginBindDescriptors();
|
_shader[SHADER_GEN]->BeginBindDescriptors();
|
||||||
cb->BindDescriptors(_shader[SHADER_GEN], 0);
|
cb->BindDescriptors(_shader[SHADER_GEN], 0);
|
||||||
cb->BindDescriptors(_shader[SHADER_GEN], 2, _cshGenNormals);
|
cb->BindDescriptors(_shader[SHADER_GEN], 2, _cshGenNormals);
|
||||||
_shader[SHADER_GEN]->EndBindDescriptors();
|
_shader[SHADER_GEN]->EndBindDescriptors();
|
||||||
|
renderer.DrawQuad(cb.Get());
|
||||||
renderer.DrawQuad(&(*cb));
|
|
||||||
|
|
||||||
cb->EndRenderPass();
|
cb->EndRenderPass();
|
||||||
|
|
||||||
_tex[TEX_GEN_NORMALS]->GenerateMips(&(*cb));
|
_tex[TEX_GEN_NORMALS]->GenerateMips(cb.Get());
|
||||||
}
|
}
|
||||||
|
|
||||||
CGI::TexturePtr Water::GetCausticsTexture() const
|
CGI::TexturePtr Water::GetCausticsTexture() const
|
||||||
|
|
|
@ -1,13 +1,20 @@
|
||||||
// Copyright (C) 2020, Dmitry Maluev (dmaluev@gmail.com)
|
// Copyright (C) 2020, Dmitry Maluev (dmaluev@gmail.com)
|
||||||
|
|
||||||
#include "Lib.hlsl"
|
#include "Lib.hlsl"
|
||||||
|
#include "LibDeferredShading.hlsl"
|
||||||
|
#include "LibDepth.hlsl"
|
||||||
#include "Bloom.inc.hlsl"
|
#include "Bloom.inc.hlsl"
|
||||||
|
|
||||||
ConstantBuffer<UB_BloomVS> g_ubBloomVS : register(b0, space0);
|
ConstantBuffer<UB_BloomVS> g_ubBloomVS : register(b0, space0);
|
||||||
ConstantBuffer<UB_BloomFS> g_ubBloomFS : register(b0, space1);
|
ConstantBuffer<UB_BloomFS> g_ubBloomFS : register(b0, space1);
|
||||||
|
ConstantBuffer<UB_BloomGodRaysFS> g_ubBloomGodRaysFS : register(b0, space2);
|
||||||
|
|
||||||
Texture2D g_tex : register(t1, space1);
|
Texture2D g_tex : register(t1, space1);
|
||||||
SamplerState g_sam : register(s1, space1);
|
SamplerState g_sam : register(s1, space1);
|
||||||
|
Texture2D g_texDepth : register(t1, space2);
|
||||||
|
SamplerState g_samDepth : register(s1, space2);
|
||||||
|
Texture2D g_texShadow : register(t2, space2);
|
||||||
|
SamplerComparisonState g_samShadow : register(s2, space2);
|
||||||
|
|
||||||
struct VSI
|
struct VSI
|
||||||
{
|
{
|
||||||
|
@ -45,7 +52,51 @@ FSO mainFS(VSO si)
|
||||||
|
|
||||||
const float4 rawColor = g_tex.SampleLevel(g_sam, si.tc0, 0.0);
|
const float4 rawColor = g_tex.SampleLevel(g_sam, si.tc0, 0.0);
|
||||||
const float3 color = rawColor.rgb * g_ubBloomFS._exposure.x;
|
const float3 color = rawColor.rgb * g_ubBloomFS._exposure.x;
|
||||||
so.color.rgb = (color - 1.0) * 0.4;
|
const float3 bloom = saturate((color - 1.0) * 0.4);
|
||||||
|
|
||||||
|
#ifdef DEF_GOD_RAYS
|
||||||
|
const float2 ndcPos = ToNdcPos(si.tc0);
|
||||||
|
const float rawDepth = g_texDepth.SampleLevel(g_samDepth, si.tc0, 0.0).r;
|
||||||
|
const float3 posW = DS_GetPosition(rawDepth, g_ubBloomGodRaysFS._matInvVP, ndcPos);
|
||||||
|
|
||||||
|
const float3 eyePos = g_ubBloomGodRaysFS._eyePos.xyz;
|
||||||
|
const float3 toPosW = posW - eyePos;
|
||||||
|
const float depth = length(toPosW);
|
||||||
|
const float3 pickingRayDir = toPosW / depth;
|
||||||
|
const float strength = pow(saturate(dot(g_ubBloomGodRaysFS._dirToSun.xyz, pickingRayDir)), 7.0) * 0.2;
|
||||||
|
|
||||||
|
float3 godRays = 0.0;
|
||||||
|
if (strength > 0.0)
|
||||||
|
{
|
||||||
|
const float3 rand = Rand(si.pos.xy);
|
||||||
|
const int sampleCount = 20;
|
||||||
|
float acc = 0.0;
|
||||||
|
[unroll] for (int i = 0; i < sampleCount; ++i)
|
||||||
|
{
|
||||||
|
const float pickingRayLen = rand.y + i;
|
||||||
|
const float3 pos = eyePos + pickingRayDir * pickingRayLen;
|
||||||
|
|
||||||
|
const float4 tcShadow = ShadowCoords(float4(pos, 1), g_ubBloomGodRaysFS._matSunShadow, pickingRayLen);
|
||||||
|
const float shadowMask = SimpleShadowMapCSM(
|
||||||
|
g_texShadow,
|
||||||
|
g_samShadow,
|
||||||
|
tcShadow,
|
||||||
|
g_ubBloomGodRaysFS._shadowConfig,
|
||||||
|
g_ubBloomGodRaysFS._splitRanges,
|
||||||
|
g_ubBloomGodRaysFS._matSunShadow,
|
||||||
|
g_ubBloomGodRaysFS._matSunShadowCSM1,
|
||||||
|
g_ubBloomGodRaysFS._matSunShadowCSM2,
|
||||||
|
g_ubBloomGodRaysFS._matSunShadowCSM3);
|
||||||
|
acc += shadowMask * step(pickingRayLen, depth);
|
||||||
|
}
|
||||||
|
godRays = acc * (1.0 / sampleCount) * g_ubBloomGodRaysFS._sunColor.rgb * g_ubBloomFS._exposure.x * strength;
|
||||||
|
}
|
||||||
|
|
||||||
|
so.color.rgb = bloom + godRays;
|
||||||
|
#else
|
||||||
|
so.color.rgb = bloom;
|
||||||
|
#endif
|
||||||
|
|
||||||
so.color.a = 1.0;
|
so.color.a = 1.0;
|
||||||
|
|
||||||
return so;
|
return so;
|
||||||
|
@ -53,3 +104,4 @@ FSO mainFS(VSO si)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//@main:#
|
//@main:#
|
||||||
|
//@main:#GodRays GOD_RAYS
|
||||||
|
|
|
@ -10,3 +10,17 @@ VERUS_UBUFFER UB_BloomFS
|
||||||
{
|
{
|
||||||
float4 _exposure;
|
float4 _exposure;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
VERUS_UBUFFER UB_BloomGodRaysFS
|
||||||
|
{
|
||||||
|
matrix _matInvVP;
|
||||||
|
matrix _matSunShadow;
|
||||||
|
matrix _matSunShadowCSM1;
|
||||||
|
matrix _matSunShadowCSM2;
|
||||||
|
matrix _matSunShadowCSM3;
|
||||||
|
float4 _shadowConfig;
|
||||||
|
float4 _splitRanges;
|
||||||
|
float4 _dirToSun;
|
||||||
|
float4 _sunColor;
|
||||||
|
float4 _eyePos;
|
||||||
|
};
|
||||||
|
|
|
@ -1,13 +1,20 @@
|
||||||
// Copyright (C) 2020, Dmitry Maluev (dmaluev@gmail.com)
|
// Copyright (C) 2020, Dmitry Maluev (dmaluev@gmail.com)
|
||||||
|
|
||||||
#include "Lib.hlsl"
|
#include "Lib.hlsl"
|
||||||
|
#include "LibDeferredShading.hlsl"
|
||||||
|
#include "LibDepth.hlsl"
|
||||||
#include "Blur.inc.hlsl"
|
#include "Blur.inc.hlsl"
|
||||||
|
|
||||||
ConstantBuffer<UB_BlurVS> g_ubBlurVS : register(b0, space0);
|
ConstantBuffer<UB_BlurVS> g_ubBlurVS : register(b0, space0);
|
||||||
ConstantBuffer<UB_BlurFS> g_ubBlurFS : register(b0, space1);
|
ConstantBuffer<UB_BlurFS> g_ubBlurFS : register(b0, space1);
|
||||||
|
ConstantBuffer<UB_ExtraBlurFS> g_ubExtraBlurFS : register(b0, space2);
|
||||||
|
|
||||||
Texture2D g_tex : register(t1, space1);
|
Texture2D g_tex : register(t1, space1);
|
||||||
SamplerState g_sam : register(s1, space1);
|
SamplerState g_sam : register(s1, space1);
|
||||||
|
Texture2D g_texGBuffer1 : register(t1, space2);
|
||||||
|
SamplerState g_samGBuffer1 : register(s1, space2);
|
||||||
|
Texture2D g_texDepth : register(t2, space2);
|
||||||
|
SamplerState g_samDepth : register(s2, space2);
|
||||||
|
|
||||||
struct VSI
|
struct VSI
|
||||||
{
|
{
|
||||||
|
@ -44,9 +51,9 @@ FSO mainFS(VSO si)
|
||||||
FSO so;
|
FSO so;
|
||||||
|
|
||||||
#if _ANISOTROPY_LEVEL > 4
|
#if _ANISOTROPY_LEVEL > 4
|
||||||
const int step = 2;
|
const int stride = 2;
|
||||||
#else
|
#else
|
||||||
const int step = 4;
|
const int stride = 4;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
float4 acc = 0.0;
|
float4 acc = 0.0;
|
||||||
|
@ -55,7 +62,7 @@ FSO mainFS(VSO si)
|
||||||
[unroll] for (int i = -1; i <= 1; i += 2)
|
[unroll] for (int i = -1; i <= 1; i += 2)
|
||||||
#else
|
#else
|
||||||
float weightSum = _SINGULARITY_FIX;
|
float weightSum = _SINGULARITY_FIX;
|
||||||
[unroll] for (int i = -8; i <= 7; i += step)
|
[unroll] for (int i = -8; i <= 7; i += stride)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
#ifdef DEF_VERTICAL
|
#ifdef DEF_VERTICAL
|
||||||
|
@ -67,7 +74,7 @@ FSO mainFS(VSO si)
|
||||||
#ifdef DEF_SSAO
|
#ifdef DEF_SSAO
|
||||||
const float weight = 1.0;
|
const float weight = 1.0;
|
||||||
#else
|
#else
|
||||||
const float weight = smoothstep(0.0, 1.0, (1.0 - abs(i) * (1.0 / 10.0)));
|
const float weight = smoothstep(0.0, 1.0, (1.0 - abs(i) * 0.1));
|
||||||
weightSum += weight;
|
weightSum += weight;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -88,7 +95,169 @@ FSO mainFS(VSO si)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef _VS
|
||||||
|
VSO mainAntiAliasingVS(VSI si)
|
||||||
|
{
|
||||||
|
VSO so;
|
||||||
|
|
||||||
|
// Standard quad:
|
||||||
|
so.pos = float4(mul(si.pos, g_ubBlurVS._matW), 1);
|
||||||
|
so.tc0 = mul(si.pos, g_ubBlurVS._matV).xy;
|
||||||
|
|
||||||
|
return so;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _FS
|
||||||
|
FSO mainAntiAliasingFS(VSO si)
|
||||||
|
{
|
||||||
|
FSO so;
|
||||||
|
|
||||||
|
const float4 rawGBuffer1 = g_texGBuffer1.SampleLevel(g_samGBuffer1, si.tc0, 0.0);
|
||||||
|
const float3 normalWV = DS_GetNormal(rawGBuffer1);
|
||||||
|
const float coarseAlpha = normalWV.b * normalWV.b * normalWV.b;
|
||||||
|
|
||||||
|
// <DepthBased>
|
||||||
|
float3 coarseNorm;
|
||||||
|
float originDeeper;
|
||||||
|
float depthBasedEdge;
|
||||||
|
{
|
||||||
|
const float rawOriginDepth = g_texDepth.SampleLevel(g_samDepth, si.tc0, 0.0).r;
|
||||||
|
const float originDepth = ToLinearDepth(rawOriginDepth, g_ubExtraBlurFS._zNearFarEx);
|
||||||
|
const float4 rawKernelDepths = float4(
|
||||||
|
g_texDepth.SampleLevel(g_samDepth, si.tc0, 0.0, int2(-2, +0)).r, // L
|
||||||
|
g_texDepth.SampleLevel(g_samDepth, si.tc0, 0.0, int2(+0, -2)).r, // T
|
||||||
|
g_texDepth.SampleLevel(g_samDepth, si.tc0, 0.0, int2(+2, +0)).r, // R
|
||||||
|
g_texDepth.SampleLevel(g_samDepth, si.tc0, 0.0, int2(+0, +2)).r); // B
|
||||||
|
const float4 kernelDepths = ToLinearDepth(rawKernelDepths, g_ubExtraBlurFS._zNearFarEx);
|
||||||
|
const float minDepth = min(min(kernelDepths[0], kernelDepths[1]), min(kernelDepths[2], kernelDepths[3]));
|
||||||
|
const float equalize = max(1.0 / originDepth, 0.05);
|
||||||
|
originDeeper = saturate((originDepth - minDepth) * equalize);
|
||||||
|
const float4 depthOffsets = abs((originDepth - kernelDepths) * equalize);
|
||||||
|
depthBasedEdge = saturate(dot(depthOffsets, 1.0));
|
||||||
|
|
||||||
|
const float3 v0 = float3(1, 0, kernelDepths[0] - kernelDepths[2]);
|
||||||
|
const float3 v1 = float3(0, 1, kernelDepths[3] - kernelDepths[1]);
|
||||||
|
coarseNorm = normalize(cross(v0, v1));
|
||||||
|
}
|
||||||
|
// </DepthBased>
|
||||||
|
|
||||||
|
// <NormalBased>
|
||||||
|
float normalBasedEdge;
|
||||||
|
{
|
||||||
|
const float4 rawNrmLT = float4(
|
||||||
|
g_texGBuffer1.SampleLevel(g_samGBuffer1, si.tc0, 0.0, int2(-2, +0)).rg,
|
||||||
|
g_texGBuffer1.SampleLevel(g_samGBuffer1, si.tc0, 0.0, int2(+0, -2)).rg);
|
||||||
|
const float4 rawNrmRB = float4(
|
||||||
|
g_texGBuffer1.SampleLevel(g_samGBuffer1, si.tc0, 0.0, int2(+2, +0)).rg,
|
||||||
|
g_texGBuffer1.SampleLevel(g_samGBuffer1, si.tc0, 0.0, int2(+0, +2)).rg);
|
||||||
|
const float4 diffA = rawNrmLT - rawNrmRB;
|
||||||
|
const float4 diffB = rawNrmLT - rawNrmRB.zwxy;
|
||||||
|
const float4 dots = float4(
|
||||||
|
dot(diffA.xy, diffA.xy),
|
||||||
|
dot(diffA.zw, diffA.zw),
|
||||||
|
dot(diffB.xy, diffB.xy),
|
||||||
|
dot(diffB.zw, diffB.zw));
|
||||||
|
const float maxDot = max(max(dots.x, dots.y), max(dots.z, dots.w));
|
||||||
|
normalBasedEdge = saturate(maxDot * maxDot * 10.0);
|
||||||
|
}
|
||||||
|
// </NormalBased>
|
||||||
|
|
||||||
|
// Directional blur:
|
||||||
|
const float3 normal = lerp(normalWV, coarseNorm, coarseAlpha * 0.5);
|
||||||
|
// {y, -x} is perpendicular vector. Also flip Y axis: normal XY to texture UV.
|
||||||
|
const float3 perp = normal.yxz;
|
||||||
|
const float omni = max(perp.z * perp.z * perp.z, originDeeper);
|
||||||
|
const float2 dirs[4] =
|
||||||
|
{
|
||||||
|
lerp(perp.xy * +4.0, float2(-0.6, -0.3), omni),
|
||||||
|
lerp(perp.xy * -2.0, float2(+0.3, -0.6), omni),
|
||||||
|
lerp(perp.xy * -4.0, float2(-0.3, +0.6), omni),
|
||||||
|
lerp(perp.xy * +2.0, float2(+0.6, +0.3), omni)
|
||||||
|
};
|
||||||
|
const float2 offsetScale = g_ubExtraBlurFS._textureSize.zw * max(normalBasedEdge, depthBasedEdge);
|
||||||
|
const float3 kernelColors[4] =
|
||||||
|
{
|
||||||
|
g_tex.SampleLevel(g_sam, si.tc0 + dirs[0] * offsetScale, 0.0).rgb,
|
||||||
|
g_tex.SampleLevel(g_sam, si.tc0 + dirs[1] * offsetScale, 0.0).rgb,
|
||||||
|
g_tex.SampleLevel(g_sam, si.tc0 + dirs[2] * offsetScale, 0.0).rgb,
|
||||||
|
g_tex.SampleLevel(g_sam, si.tc0 + dirs[3] * offsetScale, 0.0).rgb
|
||||||
|
};
|
||||||
|
so.color.rgb = (kernelColors[0] + kernelColors[1] + kernelColors[2] + kernelColors[3]) * 0.25;
|
||||||
|
so.color.a = 1.0;
|
||||||
|
|
||||||
|
return so;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _VS
|
||||||
|
VSO mainMotionVS(VSI si)
|
||||||
|
{
|
||||||
|
VSO so;
|
||||||
|
|
||||||
|
// Standard quad:
|
||||||
|
so.pos = float4(mul(si.pos, g_ubBlurVS._matW), 1);
|
||||||
|
so.tc0 = mul(si.pos, g_ubBlurVS._matV).xy;
|
||||||
|
|
||||||
|
return so;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _FS
|
||||||
|
FSO mainMotionFS(VSO si)
|
||||||
|
{
|
||||||
|
FSO so;
|
||||||
|
|
||||||
|
const float3 rand = Rand(si.pos.xy);
|
||||||
|
const float offsetScale = 0.5 + 0.3 * rand.x; // Blur 50% - 80% of frame time.
|
||||||
|
|
||||||
|
const int sampleCount = max(4, _ANISOTROPY_LEVEL);
|
||||||
|
|
||||||
|
const float4 rawGBuffer1 = g_texGBuffer1.SampleLevel(g_samGBuffer1, si.tc0, 0.0);
|
||||||
|
|
||||||
|
const float rawOriginDepth = g_texDepth.SampleLevel(g_samDepth, si.tc0, 0.0).r;
|
||||||
|
const float originDepth = ToLinearDepth(rawOriginDepth, g_ubExtraBlurFS._zNearFarEx);
|
||||||
|
|
||||||
|
float2 tcFrom;
|
||||||
|
{
|
||||||
|
const float2 ndcPos = ToNdcPos(si.tc0);
|
||||||
|
const float3 posW = DS_GetPosition(rawOriginDepth, g_ubExtraBlurFS._matInvVP, ndcPos);
|
||||||
|
const float4 prevClipSpacePos = mul(float4(posW, 1), g_ubExtraBlurFS._matPrevVP);
|
||||||
|
const float2 prevNdcPos = prevClipSpacePos.xy / prevClipSpacePos.w;
|
||||||
|
tcFrom = ToTexCoords(prevNdcPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
const float2 stride = (si.tc0 - tcFrom) * offsetScale / (sampleCount - 1);
|
||||||
|
const float2 tcOrigin = lerp(tcFrom, si.tc0, 0.7);
|
||||||
|
|
||||||
|
float4 acc = float4(g_tex.SampleLevel(g_sam, si.tc0, 0.0).rgb, 1);
|
||||||
|
[unroll] for (int i = 0; i < sampleCount; i++)
|
||||||
|
{
|
||||||
|
if (i == sampleCount / 2)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const float2 kernelCoords = tcOrigin + stride * i;
|
||||||
|
|
||||||
|
const float rawKernelDepth = g_texDepth.SampleLevel(g_samDepth, kernelCoords, 0.0).r;
|
||||||
|
const float kernelDepth = ToLinearDepth(rawKernelDepth, g_ubExtraBlurFS._zNearFarEx);
|
||||||
|
const float kernelDeeper = kernelDepth - originDepth;
|
||||||
|
const float allowed = saturate(kernelDeeper * 0.2 + 1.0) * rawGBuffer1.a;
|
||||||
|
const float weight = saturate(kernelDeeper * 0.2) + 1.0;
|
||||||
|
|
||||||
|
const float3 kernelColor = g_tex.SampleLevel(g_sam, kernelCoords, 0.0).rgb;
|
||||||
|
acc += lerp(0.0, float4(kernelColor * weight, weight), allowed);
|
||||||
|
}
|
||||||
|
acc /= acc.a;
|
||||||
|
|
||||||
|
so.color = float4(acc.rgb, 1);
|
||||||
|
|
||||||
|
return so;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//@main:#H
|
//@main:#H
|
||||||
//@main:#V VERTICAL
|
//@main:#V VERTICAL
|
||||||
//@main:#HSsao SSAO
|
//@main:#HSsao SSAO
|
||||||
//@main:#VSsao SSAO VERTICAL
|
//@main:#VSsao SSAO VERTICAL
|
||||||
|
//@mainAntiAliasing:#AntiAliasing AA
|
||||||
|
//@mainMotion:#Motion MOTION
|
||||||
|
|
|
@ -10,3 +10,11 @@ VERUS_UBUFFER UB_BlurFS
|
||||||
{
|
{
|
||||||
float4 _dummy;
|
float4 _dummy;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
VERUS_UBUFFER UB_ExtraBlurFS
|
||||||
|
{
|
||||||
|
matrix _matInvVP;
|
||||||
|
matrix _matPrevVP;
|
||||||
|
float4 _zNearFarEx;
|
||||||
|
float4 _textureSize;
|
||||||
|
};
|
||||||
|
|
|
@ -34,18 +34,18 @@ struct VSI
|
||||||
|
|
||||||
struct VSO
|
struct VSO
|
||||||
{
|
{
|
||||||
float4 pos /**/ : SV_Position;
|
float4 pos : SV_Position;
|
||||||
float4 clipSpacePos /**/ : TEXCOORD0;
|
float4 clipSpacePos : TEXCOORD0;
|
||||||
#if defined(DEF_OMNI) || defined(DEF_SPOT)
|
#if defined(DEF_OMNI) || defined(DEF_SPOT)
|
||||||
float3 radius_radiusSq_invRadiusSq /**/ : TEXCOORD1;
|
float3 radius_radiusSq_invRadiusSq : TEXCOORD1;
|
||||||
float3 lightPosWV /**/ : TEXCOORD2;
|
float3 lightPosWV : TEXCOORD2;
|
||||||
#endif
|
#endif
|
||||||
#if defined(DEF_DIR) || defined(DEF_SPOT)
|
#if defined(DEF_DIR) || defined(DEF_SPOT)
|
||||||
float4 lightDirWV_invConeDelta /**/ : TEXCOORD3;
|
float4 lightDirWV_invConeDelta : TEXCOORD3;
|
||||||
#endif
|
#endif
|
||||||
float4 color_coneOut /**/ : TEXCOORD4;
|
float4 color_coneOut : TEXCOORD4;
|
||||||
#ifdef DEF_DIR
|
#ifdef DEF_DIR
|
||||||
float3 dirZenithWV /**/ : TEXCOORD5;
|
float3 dirZenithWV : TEXCOORD5;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -166,7 +166,7 @@ DS_ACC_FSO mainFS(VSO si)
|
||||||
so.target1 = 0.0;
|
so.target1 = 0.0;
|
||||||
|
|
||||||
#if defined(DEF_OMNI) || defined(DEF_SPOT)
|
#if defined(DEF_OMNI) || defined(DEF_SPOT)
|
||||||
if (lightPosWV.z - posWV.z + radius >= 0.0) // Optimize finite volume lights.
|
if (posWV.z <= lightPosWV.z + radius)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
// Light's diffuse & specular color:
|
// Light's diffuse & specular color:
|
||||||
|
@ -228,10 +228,11 @@ DS_ACC_FSO mainFS(VSO si)
|
||||||
float shadowMask = 1.0;
|
float shadowMask = 1.0;
|
||||||
{
|
{
|
||||||
#ifdef DEF_DIR
|
#ifdef DEF_DIR
|
||||||
|
const float lightPassOffset = saturate((lamScaleBiasWithHair.y - 0.5) * 5.0) * 2.0;
|
||||||
float4 config = g_ubShadowFS._shadowConfig;
|
float4 config = g_ubShadowFS._shadowConfig;
|
||||||
const float lamBiasMask = saturate(lamScaleBiasWithHair.y * config.y);
|
const float lamBiasMask = saturate(lamScaleBiasWithHair.y * config.y);
|
||||||
config.y = 1.0 - lamBiasMask; // Keep penumbra blurry.
|
config.y = 1.0 - lamBiasMask; // Keep penumbra blurry.
|
||||||
const float3 posForShadow = AdjustPosForShadow(posWV, normalWV, dirToLightWV, -posWV.z);
|
const float3 posForShadow = AdjustPosForShadow(posWV, normalWV, dirToLightWV, -posWV.z, lightPassOffset);
|
||||||
const float4 tcShadow = ShadowCoords(float4(posForShadow, 1), g_ubShadowFS._matSunShadow, -posForShadow.z);
|
const float4 tcShadow = ShadowCoords(float4(posForShadow, 1), g_ubShadowFS._matSunShadow, -posForShadow.z);
|
||||||
shadowMask = ShadowMapCSM(
|
shadowMask = ShadowMapCSM(
|
||||||
g_texShadowCmp,
|
g_texShadowCmp,
|
||||||
|
@ -245,7 +246,6 @@ DS_ACC_FSO mainFS(VSO si)
|
||||||
g_ubShadowFS._matSunShadowCSM1,
|
g_ubShadowFS._matSunShadowCSM1,
|
||||||
g_ubShadowFS._matSunShadowCSM2,
|
g_ubShadowFS._matSunShadowCSM2,
|
||||||
g_ubShadowFS._matSunShadowCSM3);
|
g_ubShadowFS._matSunShadowCSM3);
|
||||||
shadowMask = saturate(shadowMask + saturate(lamScaleBiasWithHair.y - 1.7)); // Light pass effect.
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
// </Shadow>
|
// </Shadow>
|
||||||
|
|
132
Verus/src/Shaders/DS_AO.hlsl
Normal file
132
Verus/src/Shaders/DS_AO.hlsl
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
// Copyright (C) 2020, Dmitry Maluev (dmaluev@gmail.com)
|
||||||
|
|
||||||
|
#include "Lib.hlsl"
|
||||||
|
#include "LibColor.hlsl"
|
||||||
|
#include "LibDeferredShading.hlsl"
|
||||||
|
#include "LibDepth.hlsl"
|
||||||
|
#include "LibLighting.hlsl"
|
||||||
|
#include "LibVertex.hlsl"
|
||||||
|
#include "DS_AO.inc.hlsl"
|
||||||
|
|
||||||
|
ConstantBuffer<UB_AOPerFrame> g_ubAOPerFrame : register(b0, space0);
|
||||||
|
ConstantBuffer<UB_AOTexturesFS> g_ubAOTexturesFS : register(b0, space1);
|
||||||
|
ConstantBuffer<UB_AOPerMeshVS> g_ubAOPerMeshVS : register(b0, space2);
|
||||||
|
VK_PUSH_CONSTANT
|
||||||
|
ConstantBuffer<UB_AOPerObject> g_ubAOPerObject : register(b0, space3);
|
||||||
|
|
||||||
|
Texture2D g_texGBuffer1 : register(t1, space1);
|
||||||
|
SamplerState g_samGBuffer1 : register(s1, space1);
|
||||||
|
Texture2D g_texDepth : register(t2, space1);
|
||||||
|
SamplerState g_samDepth : register(s2, space1);
|
||||||
|
|
||||||
|
struct VSI
|
||||||
|
{
|
||||||
|
VK_LOCATION_POSITION int4 pos : POSITION;
|
||||||
|
VK_LOCATION_NORMAL float3 nrm : NORMAL;
|
||||||
|
VK_LOCATION(8) int4 tc0 : TEXCOORD0;
|
||||||
|
_PER_INSTANCE_DATA
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VSO
|
||||||
|
{
|
||||||
|
float4 pos : SV_Position;
|
||||||
|
float4 clipSpacePos : TEXCOORD0;
|
||||||
|
float3 radius_radiusSq_invRadiusSq : TEXCOORD1;
|
||||||
|
float3 lightPosWV : TEXCOORD2;
|
||||||
|
float4 color_coneOut : TEXCOORD3;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FSO
|
||||||
|
{
|
||||||
|
float4 color : SV_Target0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef _VS
|
||||||
|
VSO mainVS(VSI si)
|
||||||
|
{
|
||||||
|
VSO so;
|
||||||
|
|
||||||
|
// World matrix, instance data:
|
||||||
|
#ifdef DEF_INSTANCED
|
||||||
|
const mataff matW = GetInstMatrix(
|
||||||
|
si.matPart0,
|
||||||
|
si.matPart1,
|
||||||
|
si.matPart2);
|
||||||
|
const float3 color = si.instData.rgb;
|
||||||
|
const float coneIn = si.instData.a;
|
||||||
|
#else
|
||||||
|
const mataff matW = g_ubAOPerObject._matW;
|
||||||
|
const float3 color = g_ubAOPerObject.rgb;
|
||||||
|
const float coneIn = g_ubAOPerObject.a;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const matrix matWV = mul(ToFloat4x4(matW), ToFloat4x4(g_ubAOPerFrame._matV));
|
||||||
|
|
||||||
|
const float3x3 matW33 = (float3x3)matW;
|
||||||
|
const float3x3 matV33 = (float3x3)g_ubAOPerFrame._matV;
|
||||||
|
const float3x3 matWV33 = (float3x3)matWV;
|
||||||
|
|
||||||
|
const float3 intactPos = DequantizeUsingDeq3D(si.pos.xyz, g_ubAOPerMeshVS._posDeqScale.xyz, g_ubAOPerMeshVS._posDeqBias.xyz);
|
||||||
|
|
||||||
|
const float3 posW = mul(float4(intactPos, 1), matW);
|
||||||
|
so.pos = mul(float4(posW, 1), g_ubAOPerFrame._matVP);
|
||||||
|
so.clipSpacePos = so.pos;
|
||||||
|
|
||||||
|
// <MoreAOParams>
|
||||||
|
const float3 posUnit = mul(float3(0, 0, 1), matW33); // Need to know the scale.
|
||||||
|
so.radius_radiusSq_invRadiusSq.y = dot(posUnit, posUnit);
|
||||||
|
so.radius_radiusSq_invRadiusSq.x = sqrt(so.radius_radiusSq_invRadiusSq.y);
|
||||||
|
so.radius_radiusSq_invRadiusSq.z = 1.0 / so.radius_radiusSq_invRadiusSq.y;
|
||||||
|
const float4 posOrigin = float4(0, 0, 0, 1);
|
||||||
|
so.lightPosWV = mul(posOrigin, matWV).xyz;
|
||||||
|
so.color_coneOut = float4(color, 1.0);
|
||||||
|
// </MoreAOParams>
|
||||||
|
|
||||||
|
return so;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _FS
|
||||||
|
FSO mainFS(VSO si)
|
||||||
|
{
|
||||||
|
FSO so;
|
||||||
|
|
||||||
|
so.color = 1.0;
|
||||||
|
|
||||||
|
const float3 ndcPos = si.clipSpacePos.xyz / si.clipSpacePos.w;
|
||||||
|
|
||||||
|
const float2 tc0 = mul(float4(ndcPos.xy, 0, 1), g_ubAOPerFrame._matToUV).xy;
|
||||||
|
|
||||||
|
const float radius = si.radius_radiusSq_invRadiusSq.x;
|
||||||
|
const float radiusSq = si.radius_radiusSq_invRadiusSq.y;
|
||||||
|
const float invRadiusSq = si.radius_radiusSq_invRadiusSq.z;
|
||||||
|
const float3 lightPosWV = si.lightPosWV;
|
||||||
|
|
||||||
|
// GBuffer1:
|
||||||
|
const float depth = g_texDepth.SampleLevel(g_samDepth, tc0, 0.0).r;
|
||||||
|
const float3 posWV = DS_GetPosition(depth, g_ubAOPerFrame._matInvP, ndcPos.xy);
|
||||||
|
|
||||||
|
if (posWV.z <= lightPosWV.z + radius)
|
||||||
|
{
|
||||||
|
const float4 rawGBuffer1 = g_texGBuffer1.SampleLevel(g_samGBuffer1, tc0, 0.0);
|
||||||
|
const float3 normalWV = DS_GetNormal(rawGBuffer1);
|
||||||
|
|
||||||
|
const float3 toLightWV = lightPosWV - posWV;
|
||||||
|
const float3 dirToLightWV = normalize(toLightWV);
|
||||||
|
const float distToLightSq = dot(toLightWV, toLightWV);
|
||||||
|
const float lightFalloff = min(0.25, ComputePointLightIntensity(distToLightSq, radiusSq, invRadiusSq));
|
||||||
|
|
||||||
|
const float nDotL = saturate(0.1 + dot(normalWV, dirToLightWV));
|
||||||
|
|
||||||
|
so.color = 1.0 - nDotL * lightFalloff;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
clip(-1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return so;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//@main:#InstancedOmni INSTANCED OMNI
|
26
Verus/src/Shaders/DS_AO.inc.hlsl
Normal file
26
Verus/src/Shaders/DS_AO.inc.hlsl
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
// Copyright (C) 2020, Dmitry Maluev (dmaluev@gmail.com)
|
||||||
|
|
||||||
|
VERUS_UBUFFER UB_AOPerFrame
|
||||||
|
{
|
||||||
|
mataff _matToUV;
|
||||||
|
mataff _matV;
|
||||||
|
matrix _matVP;
|
||||||
|
matrix _matInvP;
|
||||||
|
};
|
||||||
|
|
||||||
|
VERUS_UBUFFER UB_AOTexturesFS
|
||||||
|
{
|
||||||
|
float4 _dummy;
|
||||||
|
};
|
||||||
|
|
||||||
|
VERUS_UBUFFER UB_AOPerMeshVS
|
||||||
|
{
|
||||||
|
float4 _posDeqScale;
|
||||||
|
float4 _posDeqBias;
|
||||||
|
};
|
||||||
|
|
||||||
|
VERUS_UBUFFER UB_AOPerObject
|
||||||
|
{
|
||||||
|
mataff _matW;
|
||||||
|
float4 _color;
|
||||||
|
};
|
87
Verus/src/Shaders/DS_BakeSprites.hlsl
Normal file
87
Verus/src/Shaders/DS_BakeSprites.hlsl
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
// Copyright (C) 2020, Dmitry Maluev (dmaluev@gmail.com)
|
||||||
|
|
||||||
|
#include "Lib.hlsl"
|
||||||
|
#include "LibDeferredShading.hlsl"
|
||||||
|
#include "DS_BakeSprites.inc.hlsl"
|
||||||
|
|
||||||
|
ConstantBuffer<UB_BakeSpritesVS> g_ubBakeSpritesVS : register(b0, space0);
|
||||||
|
ConstantBuffer<UB_BakeSpritesFS> g_ubBakeSpritesFS : register(b0, space1);
|
||||||
|
|
||||||
|
Texture2D g_texGBuffer0 : register(t1, space1);
|
||||||
|
SamplerState g_samGBuffer0 : register(s1, space1);
|
||||||
|
Texture2D g_texGBuffer1 : register(t2, space1);
|
||||||
|
SamplerState g_samGBuffer1 : register(s2, space1);
|
||||||
|
Texture2D g_texGBuffer2 : register(t3, space1);
|
||||||
|
SamplerState g_samGBuffer2 : register(s3, space1);
|
||||||
|
|
||||||
|
struct VSI
|
||||||
|
{
|
||||||
|
VK_LOCATION_POSITION float4 pos : POSITION;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VSO
|
||||||
|
{
|
||||||
|
float4 pos : SV_Position;
|
||||||
|
float2 tc0 : TEXCOORD0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef _VS
|
||||||
|
VSO mainVS(VSI si)
|
||||||
|
{
|
||||||
|
VSO so;
|
||||||
|
|
||||||
|
// Standard quad:
|
||||||
|
so.pos = float4(mul(si.pos, g_ubBakeSpritesVS._matW), 1);
|
||||||
|
so.tc0 = mul(si.pos, g_ubBakeSpritesVS._matV).xy;
|
||||||
|
|
||||||
|
return so;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _FS
|
||||||
|
DS_FSO mainFS(VSO si)
|
||||||
|
{
|
||||||
|
DS_FSO so;
|
||||||
|
|
||||||
|
const float4 rawGBuffer0 = g_texGBuffer0.SampleLevel(g_samGBuffer0, si.tc0, 0.0);
|
||||||
|
const float4 rawGBuffer1 = g_texGBuffer1.SampleLevel(g_samGBuffer1, si.tc0, 0.0);
|
||||||
|
const float4 rawGBuffer2 = g_texGBuffer2.SampleLevel(g_samGBuffer2, si.tc0, 0.0);
|
||||||
|
|
||||||
|
so.target0 = rawGBuffer0;
|
||||||
|
so.target1 = rawGBuffer1;
|
||||||
|
so.target2 = rawGBuffer2;
|
||||||
|
|
||||||
|
if (rawGBuffer1.a < 0.5)
|
||||||
|
{
|
||||||
|
// Defringe:
|
||||||
|
float minDist = 1000.0;
|
||||||
|
[unroll] for (int i = -7; i <= 7; ++i)
|
||||||
|
{
|
||||||
|
[unroll] for (int j = -7; j <= 7; ++j)
|
||||||
|
{
|
||||||
|
const float2 offset = float2(j, i);
|
||||||
|
const float dist = dot(offset, offset);
|
||||||
|
|
||||||
|
const float4 rawKernel1 = g_texGBuffer1.SampleLevel(g_samGBuffer1, si.tc0, 0.0, int2(j, i));
|
||||||
|
const float kernelAlpha = rawKernel1.a;
|
||||||
|
|
||||||
|
if (kernelAlpha >= 0.5 && dist < minDist)
|
||||||
|
{
|
||||||
|
minDist = dist;
|
||||||
|
|
||||||
|
const float4 rawKernel0 = g_texGBuffer0.SampleLevel(g_samGBuffer0, si.tc0, 0.0, int2(j, i));
|
||||||
|
const float4 rawKernel2 = g_texGBuffer2.SampleLevel(g_samGBuffer2, si.tc0, 0.0, int2(j, i));
|
||||||
|
|
||||||
|
so.target0 = rawKernel0;
|
||||||
|
so.target1.rgb = rawKernel1.rgb;
|
||||||
|
so.target2 = rawKernel2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return so;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//@main:#
|
12
Verus/src/Shaders/DS_BakeSprites.inc.hlsl
Normal file
12
Verus/src/Shaders/DS_BakeSprites.inc.hlsl
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
// Copyright (C) 2020, Dmitry Maluev (dmaluev@gmail.com)
|
||||||
|
|
||||||
|
VERUS_UBUFFER UB_BakeSpritesVS
|
||||||
|
{
|
||||||
|
mataff _matW;
|
||||||
|
mataff _matV;
|
||||||
|
};
|
||||||
|
|
||||||
|
VERUS_UBUFFER UB_BakeSpritesFS
|
||||||
|
{
|
||||||
|
float4 _dummy;
|
||||||
|
};
|
|
@ -69,13 +69,13 @@ FSO2 mainFS(VSO si)
|
||||||
|
|
||||||
const float2 ndcPos = si.clipSpacePos.xy;
|
const float2 ndcPos = si.clipSpacePos.xy;
|
||||||
|
|
||||||
const float4 rawGBuffer0 = g_texGBuffer0.Sample(g_samGBuffer0, si.tc0);
|
const float4 rawGBuffer0 = g_texGBuffer0.SampleLevel(g_samGBuffer0, si.tc0, 0.0);
|
||||||
const float4 rawGBuffer1 = g_texGBuffer1.Sample(g_samGBuffer1, si.tc0);
|
const float4 rawGBuffer1 = g_texGBuffer1.SampleLevel(g_samGBuffer1, si.tc0, 0.0);
|
||||||
const float4 rawGBuffer2 = g_texGBuffer2.Sample(g_samGBuffer2, si.tc0);
|
const float4 rawGBuffer2 = g_texGBuffer2.SampleLevel(g_samGBuffer2, si.tc0, 0.0);
|
||||||
const float1 rawDepth = g_texDepth.Sample(g_samDepth, si.tc0).r;
|
const float rawDepth = g_texDepth.SampleLevel(g_samDepth, si.tc0, 0.0).r;
|
||||||
|
|
||||||
const float4 rawAccDiff = g_texAccDiff.Sample(g_samAccDiff, si.tc0);
|
const float4 rawAccDiff = g_texAccDiff.SampleLevel(g_samAccDiff, si.tc0, 0.0);
|
||||||
const float4 rawAccSpec = g_texAccSpec.Sample(g_samAccSpec, si.tc0);
|
const float4 rawAccSpec = g_texAccSpec.SampleLevel(g_samAccSpec, si.tc0, 0.0);
|
||||||
const float4 accDiff = rawAccDiff;
|
const float4 accDiff = rawAccDiff;
|
||||||
const float4 accSpec = rawAccSpec;
|
const float4 accSpec = rawAccSpec;
|
||||||
|
|
||||||
|
@ -86,13 +86,13 @@ FSO2 mainFS(VSO si)
|
||||||
const float3 posW = DS_GetPosition(rawDepth, g_ubComposeFS._matInvVP, ndcPos);
|
const float3 posW = DS_GetPosition(rawDepth, g_ubComposeFS._matInvVP, ndcPos);
|
||||||
const float depth = ToLinearDepth(rawDepth, g_ubComposeFS._zNearFarEx);
|
const float depth = ToLinearDepth(rawDepth, g_ubComposeFS._zNearFarEx);
|
||||||
|
|
||||||
const float ssaoDiff = 0.8 + 0.2 * rawGBuffer2.r;
|
const float ssaoDiff = 0.5 + 0.5 * rawGBuffer2.r;
|
||||||
const float ssaoSpec = ssaoDiff;
|
const float ssaoSpec = ssaoDiff;
|
||||||
const float ssaoAmb = rawGBuffer2.r;
|
const float ssaoAmb = rawGBuffer2.r;
|
||||||
|
|
||||||
const float3 normalW = mul(normalWV, (float3x3)g_ubComposeFS._matInvV);
|
const float3 normalW = mul(normalWV, (float3x3)g_ubComposeFS._matInvV);
|
||||||
const float grayAmbient = Grayscale(ambientColor);
|
const float grayAmbient = Grayscale(ambientColor);
|
||||||
const float3 finalAmbientColor = lerp(grayAmbient * 0.5, ambientColor, normalW.y * 0.5 + 0.5);
|
const float3 finalAmbientColor = lerp(grayAmbient * 0.2, ambientColor, normalW.y * 0.5 + 0.5);
|
||||||
|
|
||||||
const float3 color =
|
const float3 color =
|
||||||
albedo * (accDiff.rgb * ssaoDiff + finalAmbientColor * ssaoAmb) +
|
albedo * (accDiff.rgb * ssaoDiff + finalAmbientColor * ssaoAmb) +
|
||||||
|
@ -125,7 +125,7 @@ FSO2 mainFS(VSO si)
|
||||||
}
|
}
|
||||||
// </Fog>
|
// </Fog>
|
||||||
|
|
||||||
so.target0.rgb = colorWithFog;
|
so.target0.rgb = lerp(colorWithFog, albedo, floor(rawDepth));
|
||||||
so.target0.a = 1.0;
|
so.target0.a = 1.0;
|
||||||
|
|
||||||
so.target1 = so.target0;
|
so.target1 = so.target0;
|
||||||
|
@ -138,10 +138,10 @@ FSO mainFS(VSO si)
|
||||||
{
|
{
|
||||||
FSO so;
|
FSO so;
|
||||||
|
|
||||||
const float4 rawGBuffer0 = g_texGBuffer0.Sample(g_samGBuffer0, si.tc0);
|
const float4 rawGBuffer0 = g_texGBuffer0.SampleLevel(g_samGBuffer0, si.tc0, 0.0);
|
||||||
const float4 rawGBuffer1 = g_texGBuffer1.Sample(g_samGBuffer1, si.tc0);
|
const float4 rawGBuffer1 = g_texGBuffer1.SampleLevel(g_samGBuffer1, si.tc0, 0.0);
|
||||||
const float4 rawGBuffer2 = g_texGBuffer2.Sample(g_samGBuffer2, si.tc0);
|
const float4 rawGBuffer2 = g_texGBuffer2.SampleLevel(g_samGBuffer2, si.tc0, 0.0);
|
||||||
const float4 rawComposed = g_texDepth.Sample(g_samDepth, si.tc0);
|
const float4 rawComposed = g_texDepth.SampleLevel(g_samDepth, si.tc0, 0.0);
|
||||||
|
|
||||||
const float3 exposedComposed = rawComposed.rgb * g_ubComposeFS._ambientColor_exposure.a;
|
const float3 exposedComposed = rawComposed.rgb * g_ubComposeFS._ambientColor_exposure.a;
|
||||||
so.color.rgb = VerusToneMapping(exposedComposed, 0.5);
|
so.color.rgb = VerusToneMapping(exposedComposed, 0.5);
|
||||||
|
|
137
Verus/src/Shaders/DS_Forest.hlsl
Normal file
137
Verus/src/Shaders/DS_Forest.hlsl
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
// Copyright (C) 2020, Dmitry Maluev (dmaluev@gmail.com)
|
||||||
|
|
||||||
|
#include "Lib.hlsl"
|
||||||
|
#include "LibDeferredShading.hlsl"
|
||||||
|
#include "DS_Forest.inc.hlsl"
|
||||||
|
|
||||||
|
ConstantBuffer<UB_ForestVS> g_ubForestVS : register(b0, space0);
|
||||||
|
ConstantBuffer<UB_ForestFS> g_ubForestFS : register(b0, space1);
|
||||||
|
|
||||||
|
Texture2D g_texGBuffer0 : register(t1, space1);
|
||||||
|
SamplerState g_samGBuffer0 : register(s1, space1);
|
||||||
|
Texture2D g_texGBuffer1 : register(t2, space1);
|
||||||
|
SamplerState g_samGBuffer1 : register(s2, space1);
|
||||||
|
Texture2D g_texGBuffer2 : register(t3, space1);
|
||||||
|
SamplerState g_samGBuffer2 : register(s3, space1);
|
||||||
|
|
||||||
|
struct VSI
|
||||||
|
{
|
||||||
|
VK_LOCATION_POSITION float4 pos : POSITION;
|
||||||
|
VK_LOCATION(8) int4 tc0 : TEXCOORD0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VSO
|
||||||
|
{
|
||||||
|
float4 pos : SV_Position;
|
||||||
|
float2 tc0 : TEXCOORD0;
|
||||||
|
float2 angles : TEXCOORD1;
|
||||||
|
float4 color : COLOR0;
|
||||||
|
float2 psize : PSIZE;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef _VS
|
||||||
|
VSO mainVS(VSI si)
|
||||||
|
{
|
||||||
|
VSO so;
|
||||||
|
|
||||||
|
const float pointSpriteSize = si.tc0.x / 500.0;
|
||||||
|
const float angle = si.tc0.y / 32767.0;
|
||||||
|
|
||||||
|
const float3 toEye = g_ubForestVS._eyePos.xyz - si.pos.xyz;
|
||||||
|
const float distToScreen = length(g_ubForestVS._eyePosScreen.xyz - si.pos.xyz);
|
||||||
|
|
||||||
|
so.pos = mul(si.pos, g_ubForestVS._matWVP);
|
||||||
|
so.tc0 = 0.0;
|
||||||
|
so.color.rgb = RandomColor(si.pos.xz, 0.3, 0.2);
|
||||||
|
so.color.a = saturate((distToScreen - 60.0) / 30.0);
|
||||||
|
so.psize = pointSpriteSize * (g_ubForestVS._viewportSize.yx * g_ubForestVS._viewportSize.z) * g_ubForestVS._matP._m11;
|
||||||
|
so.psize *= ceil(so.color.a); // Hide if too close.
|
||||||
|
|
||||||
|
float2 param0 = toEye.xy;
|
||||||
|
float2 param1 = toEye.zz;
|
||||||
|
param0.y = max(0.0, param0.y); // Only upper hemisphere.
|
||||||
|
param1.y = length(toEye.xz); // Distance in XZ-plane.
|
||||||
|
so.angles.xy = (atan2(param0, param1) + _PI) * (0.5 / _PI); // atan2(x, z) and atan2(max(0.0, y), length(toEye.xz)). From 0 to 1.
|
||||||
|
so.angles.y = (so.angles.y - 0.5) * 4.0; // Choose this quadrant.
|
||||||
|
so.angles.xy = saturate(so.angles.xy);
|
||||||
|
so.angles.x = frac(so.angles.x - angle + 0.5); // Turn.
|
||||||
|
|
||||||
|
return so;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _GS
|
||||||
|
[maxvertexcount(4)]
|
||||||
|
void mainGS(point VSO si[1], inout TriangleStream<VSO> stream)
|
||||||
|
{
|
||||||
|
VSO so;
|
||||||
|
|
||||||
|
so = si[0];
|
||||||
|
const float2 center = so.pos.xy;
|
||||||
|
for (int i = 0; i < 4; ++i)
|
||||||
|
{
|
||||||
|
so.pos.xy = center + _POINT_SPRITE_POS_OFFSETS[i] * so.psize;
|
||||||
|
so.tc0.xy = _POINT_SPRITE_TEX_COORDS[i];
|
||||||
|
stream.Append(so);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
float2 ComputeTexCoords(float2 tc, float2 angles)
|
||||||
|
{
|
||||||
|
const float marginBias = 16.0 / 512.0;
|
||||||
|
const float marginScale = 1.0 - marginBias * 2.0;
|
||||||
|
const float2 tcMargin = tc * marginScale + marginBias;
|
||||||
|
|
||||||
|
const float2 frameCount = float2(16, 16);
|
||||||
|
const float2 frameScale = 1.0 / frameCount;
|
||||||
|
const float2 frameBias = floor(min(angles * frameCount + 0.5, float2(256, frameCount.y - 0.5)));
|
||||||
|
return (tcMargin + frameBias) * frameScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
float ComputeMask(float2 tc, float alpha)
|
||||||
|
{
|
||||||
|
const float2 tcCenter = tc - 0.5;
|
||||||
|
const float rad = saturate(dot(tcCenter, tcCenter) * 4.0);
|
||||||
|
return saturate(rad + (alpha * 2.0 - 1.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _FS
|
||||||
|
#ifdef DEF_DEPTH
|
||||||
|
void mainFS(VSO si)
|
||||||
|
{
|
||||||
|
const float2 tc = ComputeTexCoords(si.tc0, si.angles);
|
||||||
|
const float mask = ComputeMask(si.tc0, si.color.a);
|
||||||
|
|
||||||
|
const float alpha = g_texGBuffer1.Sample(g_samGBuffer1, tc).a;
|
||||||
|
|
||||||
|
clip(alpha * mask - 0.5);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
DS_FSO mainFS(VSO si)
|
||||||
|
{
|
||||||
|
DS_FSO so;
|
||||||
|
|
||||||
|
const float2 tc = ComputeTexCoords(si.tc0, si.angles);
|
||||||
|
const float mask = ComputeMask(si.tc0, si.color.a);
|
||||||
|
|
||||||
|
const float4 rawGBuffer0 = g_texGBuffer0.Sample(g_samGBuffer0, tc);
|
||||||
|
const float4 rawGBuffer1 = g_texGBuffer1.Sample(g_samGBuffer1, tc);
|
||||||
|
const float4 rawGBuffer2 = g_texGBuffer2.Sample(g_samGBuffer2, tc);
|
||||||
|
|
||||||
|
so.target0 = rawGBuffer0;
|
||||||
|
so.target1 = rawGBuffer1;
|
||||||
|
so.target2 = rawGBuffer2;
|
||||||
|
|
||||||
|
so.target0.rgb *= si.color.rgb;
|
||||||
|
so.target2.g = lerp(so.target2.g, 0.25, si.tc0.y);
|
||||||
|
|
||||||
|
clip(rawGBuffer1.a * mask - 0.5);
|
||||||
|
|
||||||
|
return so;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//@main:# (VGF)
|
||||||
|
//@main:#Depth DEPTH (VGF)
|
15
Verus/src/Shaders/DS_Forest.inc.hlsl
Normal file
15
Verus/src/Shaders/DS_Forest.inc.hlsl
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
// Copyright (C) 2020, Dmitry Maluev (dmaluev@gmail.com)
|
||||||
|
|
||||||
|
VERUS_UBUFFER UB_ForestVS
|
||||||
|
{
|
||||||
|
matrix _matP;
|
||||||
|
matrix _matWVP;
|
||||||
|
float4 _viewportSize;
|
||||||
|
float4 _eyePos;
|
||||||
|
float4 _eyePosScreen;
|
||||||
|
};
|
||||||
|
|
||||||
|
VERUS_UBUFFER UB_ForestFS
|
||||||
|
{
|
||||||
|
float4 _dummy;
|
||||||
|
};
|
|
@ -57,7 +57,7 @@ VSO mainVS(VSI si)
|
||||||
float3 intactPos;
|
float3 intactPos;
|
||||||
float3 pos;
|
float3 pos;
|
||||||
float2 center;
|
float2 center;
|
||||||
float2 pointSpriteScale = 1.0;
|
float2 pointSpriteSize = 1.0;
|
||||||
float groundHeight;
|
float groundHeight;
|
||||||
float3 normal;
|
float3 normal;
|
||||||
float2 tc0;
|
float2 tc0;
|
||||||
|
@ -67,8 +67,8 @@ VSO mainVS(VSI si)
|
||||||
pos = intactPos + float3(si.patchPos.x, 0, si.patchPos.z);
|
pos = intactPos + float3(si.patchPos.x, 0, si.patchPos.z);
|
||||||
center = si.tc.zw * (1.0 / 1000.0) + si.patchPos.xz;
|
center = si.tc.zw * (1.0 / 1000.0) + si.patchPos.xz;
|
||||||
#ifdef DEF_BILLBOARDS
|
#ifdef DEF_BILLBOARDS
|
||||||
pointSpriteScale = intactPos.y;
|
pointSpriteSize = intactPos.y;
|
||||||
pos = float3(center.x, 0.45 * pointSpriteScale.y, center.y);
|
pos = float3(center.x, 0.45 * pointSpriteSize.y, center.y);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const float distToEye = distance(pos + float3(0, si.patchPos.y * 0.01, 0), g_ubGrassVS._posEye.xyz);
|
const float distToEye = distance(pos + float3(0, si.patchPos.y * 0.01, 0), g_ubGrassVS._posEye.xyz);
|
||||||
|
@ -146,7 +146,7 @@ VSO mainVS(VSI si)
|
||||||
hide = saturate(hide);
|
hide = saturate(hide);
|
||||||
|
|
||||||
#ifdef DEF_BILLBOARDS
|
#ifdef DEF_BILLBOARDS
|
||||||
pointSpriteScale = lerp(pointSpriteScale, float2(0.0, pointSpriteScale.y), hide);
|
pointSpriteSize = lerp(pointSpriteSize, float2(0.0, pointSpriteSize.y), hide);
|
||||||
#else
|
#else
|
||||||
posWarped = lerp(posWarped, float3(center.x, posWarped.y, center.y), hide); // Optimize by morphing to center point.
|
posWarped = lerp(posWarped, float3(center.x, posWarped.y, center.y), hide); // Optimize by morphing to center point.
|
||||||
#endif
|
#endif
|
||||||
|
@ -163,8 +163,7 @@ VSO mainVS(VSI si)
|
||||||
|
|
||||||
#ifdef DEF_BILLBOARDS
|
#ifdef DEF_BILLBOARDS
|
||||||
so.tcOffset_phaseShift.xy = tc0;
|
so.tcOffset_phaseShift.xy = tc0;
|
||||||
const float2 pointSize = g_ubGrassVS._viewportSize.yx * g_ubGrassVS._viewportSize.z * pointSpriteScale;
|
so.psize = pointSpriteSize * (g_ubGrassVS._viewportSize.yx * g_ubGrassVS._viewportSize.z) * g_ubGrassVS._matP._m11;
|
||||||
so.psize = pointSize * g_ubGrassVS._matP._m11;
|
|
||||||
#else
|
#else
|
||||||
so.normal_top.xyz += float3(0, 0, top * top * 0.25);
|
so.normal_top.xyz += float3(0, 0, top * top * 0.25);
|
||||||
#endif
|
#endif
|
||||||
|
@ -219,6 +218,7 @@ DS_FSO mainFS(VSO si)
|
||||||
|
|
||||||
DS_SetNormal(so, normal + NormalDither(rand));
|
DS_SetNormal(so, normal + NormalDither(rand));
|
||||||
DS_SetEmission(so, 0.0, 0.0);
|
DS_SetEmission(so, 0.0, 0.0);
|
||||||
|
DS_SetMotionBlur(so, 1.0);
|
||||||
|
|
||||||
DS_SetLamScaleBias(so, float2(1.2, -0.2), 0.0);
|
DS_SetLamScaleBias(so, float2(1.2, -0.2), 0.0);
|
||||||
DS_SetMetallicity(so, 0.05, 0.0);
|
DS_SetMetallicity(so, 0.05, 0.0);
|
||||||
|
|
|
@ -50,12 +50,12 @@ struct VSO
|
||||||
{
|
{
|
||||||
float4 pos : SV_Position;
|
float4 pos : SV_Position;
|
||||||
float2 tc0 : TEXCOORD0;
|
float2 tc0 : TEXCOORD0;
|
||||||
|
float4 matTBN2 : TEXCOORD1;
|
||||||
#if !defined(DEF_DEPTH)
|
#if !defined(DEF_DEPTH)
|
||||||
float4 color0 : COLOR0;
|
float4 color0 : COLOR0;
|
||||||
#if !defined(DEF_DEPTH) && !defined(DEF_SOLID_COLOR)
|
#if !defined(DEF_DEPTH) && !defined(DEF_SOLID_COLOR)
|
||||||
float4 matTBN0 : TEXCOORD1;
|
float4 matTBN0 : TEXCOORD2;
|
||||||
float4 matTBN1 : TEXCOORD2;
|
float4 matTBN1 : TEXCOORD3;
|
||||||
float4 matTBN2 : TEXCOORD3;
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
@ -148,12 +148,19 @@ VSO mainVS(VSI si)
|
||||||
|
|
||||||
so.pos = MulTessPos(float4(posW, 1), g_ubPerFrame._matV, g_ubPerFrame._matVP);
|
so.pos = MulTessPos(float4(posW, 1), g_ubPerFrame._matV, g_ubPerFrame._matVP);
|
||||||
so.tc0 = intactTc0;
|
so.tc0 = intactTc0;
|
||||||
|
so.matTBN2 = float4(nrmWV, posW.z);
|
||||||
|
#ifdef DEF_TESS
|
||||||
|
so.matTBN2.xyz = normalize(so.matTBN2.xyz);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !defined(DEF_DEPTH)
|
#if !defined(DEF_DEPTH)
|
||||||
so.color0 = userColor;
|
so.color0 = userColor;
|
||||||
|
#ifdef DEF_PLANT
|
||||||
|
so.color0.rgb = RandomColor(userColor.xz, 0.3, 0.2);
|
||||||
|
#endif
|
||||||
#if !defined(DEF_DEPTH) && !defined(DEF_SOLID_COLOR)
|
#if !defined(DEF_DEPTH) && !defined(DEF_SOLID_COLOR)
|
||||||
so.matTBN0 = float4(tanWV, posW.x);
|
so.matTBN0 = float4(tanWV, posW.x);
|
||||||
so.matTBN1 = float4(binWV, posW.y);
|
so.matTBN1 = float4(binWV, posW.y);
|
||||||
so.matTBN2 = float4(nrmWV, posW.z);
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -185,12 +192,12 @@ HSO mainHS(InputPatch<VSO, 3> inputPatch, uint id : SV_OutputControlPointID)
|
||||||
|
|
||||||
_HS_COPY(pos);
|
_HS_COPY(pos);
|
||||||
_HS_COPY(tc0);
|
_HS_COPY(tc0);
|
||||||
|
_HS_COPY(matTBN2);
|
||||||
#if !defined(DEF_DEPTH)
|
#if !defined(DEF_DEPTH)
|
||||||
_HS_COPY(color0);
|
_HS_COPY(color0);
|
||||||
#if !defined(DEF_DEPTH) && !defined(DEF_SOLID_COLOR)
|
#if !defined(DEF_DEPTH) && !defined(DEF_SOLID_COLOR)
|
||||||
_HS_COPY(matTBN0);
|
_HS_COPY(matTBN0);
|
||||||
_HS_COPY(matTBN1);
|
_HS_COPY(matTBN1);
|
||||||
_HS_COPY(matTBN2);
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -204,16 +211,21 @@ VSO mainDS(_IN_DS)
|
||||||
{
|
{
|
||||||
VSO so;
|
VSO so;
|
||||||
|
|
||||||
|
_DS_INIT_FLAT_POS;
|
||||||
_DS_INIT_SMOOTH_POS;
|
_DS_INIT_SMOOTH_POS;
|
||||||
|
|
||||||
so.pos = ApplyProjection(smoothPosWV, g_ubPerFrame._matP);
|
const float3 toEyeWV = g_ubPerFrame._eyePosWV_invTessDistSq.xyz - flatPosWV;
|
||||||
|
const float distToEyeSq = dot(toEyeWV, toEyeWV);
|
||||||
|
const float tessStrength = 1.0 - saturate(distToEyeSq * g_ubPerFrame._eyePosWV_invTessDistSq.w * 1.1 - 0.1);
|
||||||
|
const float3 posWV = lerp(flatPosWV, smoothPosWV, tessStrength);
|
||||||
|
so.pos = ApplyProjection(posWV, g_ubPerFrame._matP);
|
||||||
_DS_COPY(tc0);
|
_DS_COPY(tc0);
|
||||||
|
_DS_COPY(matTBN2);
|
||||||
#if !defined(DEF_DEPTH)
|
#if !defined(DEF_DEPTH)
|
||||||
_DS_COPY(color0);
|
_DS_COPY(color0);
|
||||||
#if !defined(DEF_DEPTH) && !defined(DEF_SOLID_COLOR)
|
#if !defined(DEF_DEPTH) && !defined(DEF_SOLID_COLOR)
|
||||||
_DS_COPY(matTBN0);
|
_DS_COPY(matTBN0);
|
||||||
_DS_COPY(matTBN1);
|
_DS_COPY(matTBN1);
|
||||||
_DS_COPY(matTBN2);
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -290,7 +302,11 @@ DS_FSO mainFS(VSO si)
|
||||||
const float skinAlpha = PickAlpha(rawAlbedo.rgb, mm_skinPick, 16.0);
|
const float skinAlpha = PickAlpha(rawAlbedo.rgb, mm_skinPick, 16.0);
|
||||||
const float userAlpha = PickAlphaHue(rawAlbedo.rgb, mm_userPick, 32.0);
|
const float userAlpha = PickAlphaHue(rawAlbedo.rgb, mm_userPick, 32.0);
|
||||||
|
|
||||||
|
#ifdef DEF_PLANT
|
||||||
|
rawAlbedo.rgb *= si.color0.rgb;
|
||||||
|
#else
|
||||||
rawAlbedo.rgb = lerp(rawAlbedo.rgb, Overlay(gray, si.color0.rgb), userAlpha * si.color0.a);
|
rawAlbedo.rgb = lerp(rawAlbedo.rgb, Overlay(gray, si.color0.rgb), userAlpha * si.color0.a);
|
||||||
|
#endif
|
||||||
const float3 hairAlbedo = Overlay(alpha_spec.y, Desaturate(rawAlbedo.rgb, hairAlpha * mm_hairDesat));
|
const float3 hairAlbedo = Overlay(alpha_spec.y, Desaturate(rawAlbedo.rgb, hairAlpha * mm_hairDesat));
|
||||||
|
|
||||||
// <Gloss>
|
// <Gloss>
|
||||||
|
@ -373,20 +389,29 @@ DS_FSO mainFS(VSO si)
|
||||||
|
|
||||||
//@main:#
|
//@main:#
|
||||||
//@main:#Instanced INSTANCED
|
//@main:#Instanced INSTANCED
|
||||||
|
//@main:#Plant PLANT INSTANCED
|
||||||
//@main:#Robotic ROBOTIC
|
//@main:#Robotic ROBOTIC
|
||||||
//@main:#Skinned SKINNED
|
//@main:#Skinned SKINNED
|
||||||
|
|
||||||
|
//@main:#Tess TESS (VHDF)
|
||||||
|
//@main:#TessInstanced TESS INSTANCED (VHDF)
|
||||||
|
//@main:#TessPlant TESS PLANT INSTANCED (VHDF)
|
||||||
|
//@main:#TessRobotic TESS ROBOTIC (VHDF)
|
||||||
|
//@main:#TessSkinned TESS SKINNED (VHDF)
|
||||||
|
|
||||||
//@main:#Depth DEPTH
|
//@main:#Depth DEPTH
|
||||||
//@main:#DepthInstanced DEPTH INSTANCED
|
//@main:#DepthInstanced DEPTH INSTANCED
|
||||||
|
//@main:#DepthPlant DEPTH PLANT INSTANCED
|
||||||
//@main:#DepthRobotic DEPTH ROBOTIC
|
//@main:#DepthRobotic DEPTH ROBOTIC
|
||||||
//@main:#DepthSkinned DEPTH SKINNED
|
//@main:#DepthSkinned DEPTH SKINNED
|
||||||
|
|
||||||
|
//@main:#DepthTess DEPTH TESS (VHDF)
|
||||||
|
//@main:#DepthTessInstanced DEPTH TESS INSTANCED (VHDF)
|
||||||
|
//@main:#DepthTessPlant DEPTH TESS PLANT INSTANCED (VHDF)
|
||||||
|
//@main:#DepthTessRobotic DEPTH TESS ROBOTIC (VHDF)
|
||||||
|
//@main:#DepthTessSkinned DEPTH TESS SKINNED (VHDF)
|
||||||
|
|
||||||
//@main:#SolidColor SOLID_COLOR
|
//@main:#SolidColor SOLID_COLOR
|
||||||
//@main:#SolidColorInstanced SOLID_COLOR INSTANCED
|
//@main:#SolidColorInstanced SOLID_COLOR INSTANCED
|
||||||
//@main:#SolidColorRobotic SOLID_COLOR ROBOTIC
|
//@main:#SolidColorRobotic SOLID_COLOR ROBOTIC
|
||||||
//@main:#SolidColorSkinned SOLID_COLOR SKINNED
|
//@main:#SolidColorSkinned SOLID_COLOR SKINNED
|
||||||
|
|
||||||
//@main:#Tess TESS (VHDF)
|
|
||||||
//@main:#TessInstanced TESS INSTANCED (VHDF)
|
|
||||||
//@main:#TessRobotic TESS ROBOTIC (VHDF)
|
|
||||||
//@main:#TessSkinned TESS SKINNED (VHDF)
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ VERUS_UBUFFER UB_PerFrame
|
||||||
matrix _matVP;
|
matrix _matVP;
|
||||||
matrix _matP;
|
matrix _matP;
|
||||||
float4 _viewportSize;
|
float4 _viewportSize;
|
||||||
|
float4 _eyePosWV_invTessDistSq;
|
||||||
};
|
};
|
||||||
|
|
||||||
VERUS_UBUFFER UB_PerMaterialFS
|
VERUS_UBUFFER UB_PerMaterialFS
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue