This commit is contained in:
Dmitry 2019-12-01 02:09:41 +03:00
parent a692b08930
commit 75be504c1f
112 changed files with 7346 additions and 570 deletions

View File

@ -15,7 +15,7 @@
<ProjectGuid>{53923514-84B2-4B78-889A-8709C6BFA3A5}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>RendererDirect3D12</RootNamespace>
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

View File

@ -34,12 +34,12 @@ CD3DX12_GPU_DESCRIPTOR_HANDLE DescriptorHeap::AtGPU(INT index) const
// DynamicDescriptorHeap:
void DynamicDescriptorHeap::Create(ID3D12Device* pDevice, D3D12_DESCRIPTOR_HEAP_TYPE type, UINT num, bool shaderVisible)
void DynamicDescriptorHeap::Create(ID3D12Device* pDevice, D3D12_DESCRIPTOR_HEAP_TYPE type, UINT num, UINT numStatic, bool shaderVisible)
{
VERUS_CT_ASSERT(sizeof(*this) == 56);
_capacity = num;
_offset = 0;
DescriptorHeap::Create(pDevice, type, _capacity * BaseRenderer::s_ringBufferSize, shaderVisible);
DescriptorHeap::Create(pDevice, type, _capacity * BaseRenderer::s_ringBufferSize + numStatic, shaderVisible);
}
HandlePair DynamicDescriptorHeap::GetNextHandlePair(int num)
@ -63,3 +63,9 @@ HandlePair DynamicDescriptorHeap::GetNextHandlePair(int num)
VERUS_RT_FAIL("DynamicDescriptorHeap is full.");
return HandlePair();
}
HandlePair DynamicDescriptorHeap::GetStaticHandlePair(int index)
{
const INT indexAt = _capacity * BaseRenderer::s_ringBufferSize + index;
return HandlePair(AtCPU(indexAt), AtGPU(indexAt));
}

View File

@ -43,9 +43,10 @@ namespace verus
UINT64 _peakLoad = 0;
public:
void Create(ID3D12Device* pDevice, D3D12_DESCRIPTOR_HEAP_TYPE type, UINT num, bool shaderVisible = false);
void Create(ID3D12Device* pDevice, D3D12_DESCRIPTOR_HEAP_TYPE type, UINT num, UINT numStatic = 0, bool shaderVisible = false);
HandlePair GetNextHandlePair(int num = 1);
HandlePair GetStaticHandlePair(int index);
UINT GetCapacity() const { return _capacity; }
UINT GetOffset() const { return _offset; }

View File

@ -17,8 +17,8 @@ void GeometryD3D12::Init(RcGeometryDesc desc)
{
VERUS_INIT();
_dynBindingsMask = desc._dynBindingsMask;
_32BitIndices = desc._32BitIndices;
_dynamic = desc._dynamic;
_vInputElementDesc.reserve(GetNumInputElementDesc(desc._pInputElementDesc));
int i = 0;
@ -30,7 +30,7 @@ void GeometryD3D12::Init(RcGeometryDesc desc)
if (binding < 0)
{
binding = -binding;
_bindingInstMask |= (1 << binding);
_instBindingsMask |= (1 << binding);
inputClassification = D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA;
instanceDataStepRate = 1;
}
@ -91,7 +91,7 @@ void GeometryD3D12::CreateVertexBuffer(int num, int binding)
const int elementSize = _vStrides[binding];
vb._bufferSize = num * elementSize;
if (((_bindingInstMask >> binding) & 0x1) || _dynamic)
if (((_instBindingsMask | _dynBindingsMask) >> binding) & 0x1)
{
D3D12MA::ALLOCATION_DESC allocDesc = {};
allocDesc.HeapType = D3D12_HEAP_TYPE_UPLOAD;
@ -136,7 +136,7 @@ void GeometryD3D12::UpdateVertexBuffer(const void* p, int binding, BaseCommandBu
VERUS_QREF_RENDERER_D3D12;
HRESULT hr = 0;
if (((_bindingInstMask >> binding) & 0x1) || _dynamic)
if (((_instBindingsMask | _dynBindingsMask) >> binding) & 0x1)
{
auto& vb = _vVertexBuffers[binding];
CD3DX12_RANGE readRange(0, 0);
@ -289,7 +289,7 @@ D3D12_INPUT_LAYOUT_DESC GeometryD3D12::GetD3DInputLayoutDesc(UINT32 bindingsFilt
const D3D12_VERTEX_BUFFER_VIEW* GeometryD3D12::GetD3DVertexBufferView(int binding) const
{
if ((_bindingInstMask >> binding) & 0x1)
if (((_instBindingsMask | _dynBindingsMask) >> binding) & 0x1)
{
VERUS_QREF_RENDERER_D3D12;
return &_vVertexBuffers[binding]._bufferView[pRendererD3D12->GetRingBufferIndex()];

View File

@ -141,7 +141,7 @@ void PipelineD3D12::Init(RcPipelineDesc desc)
gpsDesc.RasterizerState.SlopeScaledDepthBias = desc._rasterizationState._depthBiasSlopeFactor;
gpsDesc.RasterizerState.DepthClipEnable = desc._rasterizationState._depthClampEnable;
gpsDesc.RasterizerState.MultisampleEnable = FALSE;
gpsDesc.RasterizerState.AntialiasedLineEnable = FALSE;
gpsDesc.RasterizerState.AntialiasedLineEnable = TRUE;
gpsDesc.RasterizerState.ForcedSampleCount = 0;
gpsDesc.RasterizerState.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF;

View File

@ -31,6 +31,15 @@ void RendererD3D12::Init()
void RendererD3D12::Done()
{
WaitIdle();
if (ImGui::GetCurrentContext())
{
ImGui_ImplDX12_Shutdown();
ImGui_ImplSDL2_Shutdown();
ImGui::DestroyContext();
Renderer::I().ImGuiSetCurrentContext(nullptr);
}
DeleteFramebuffer(-1);
DeleteRenderPass(-1);
@ -190,8 +199,8 @@ void RendererD3D12::InitD3D()
_pFence = CreateFence();
_hFence = CreateEvent(nullptr, FALSE, FALSE, nullptr);
_dhCbvSrvUav.Create(_pDevice.Get(), D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, settings.GetLimits()._d3d12_dhCbvSrvUavCapacity, true);
_dhSamplers.Create(_pDevice.Get(), D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, settings.GetLimits()._d3d12_dhSamplersCapacity, true);
_dhCbvSrvUav.Create(_pDevice.Get(), D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, settings.GetLimits()._d3d12_dhCbvSrvUavCapacity, 16, true);
_dhSamplers.Create(_pDevice.Get(), D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, settings.GetLimits()._d3d12_dhSamplersCapacity, 0, true);
CreateSamplers();
}
@ -350,10 +359,63 @@ D3D12_STATIC_SAMPLER_DESC RendererD3D12::GetStaticSamplerDesc(Sampler s) const
void RendererD3D12::ImGuiInit(int renderPassID)
{
VERUS_QREF_RENDERER;
VERUS_QREF_CONST_SETTINGS;
IMGUI_CHECKVERSION();
ImGuiContext* pContext = ImGui::CreateContext();
renderer.ImGuiSetCurrentContext(pContext);
ImGuiIO& io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
io.ConfigWindowsMoveFromTitleBarOnly = true;
if (!settings._imguiFont.empty())
{
Vector<BYTE> vData;
IO::FileSystem::LoadResource(_C(settings._imguiFont), vData);
void* pFontData = IM_ALLOC(vData.size());
memcpy(pFontData, vData.data(), vData.size());
io.Fonts->AddFontFromMemoryTTF(pFontData, Utils::Cast32(vData.size()), 15);
}
ImGui::StyleColorsDark();
ImGui_ImplSDL2_InitForD3D(renderer.GetMainWindow()->GetSDL());
auto hp = _dhCbvSrvUav.GetStaticHandlePair(0);
ImGui_ImplDX12_Init(
_pDevice.Get(),
s_ringBufferSize,
DXGI_FORMAT_B8G8R8A8_UNORM_SRGB,
_dhCbvSrvUav.GetD3DDescriptorHeap(),
hp._hCPU,
hp._hGPU);
}
void RendererD3D12::ImGuiRenderDrawData()
{
VERUS_QREF_RENDERER;
ImGui::Render();
auto pCmdList = static_cast<CommandBufferD3D12*>(&(*renderer.GetCommandBuffer()))->GetD3DGraphicsCommandList();
if (ImGui::GetDrawData())
ImGui_ImplDX12_RenderDrawData(ImGui::GetDrawData(), pCmdList);
}
void RendererD3D12::ResizeSwapChain()
{
VERUS_QREF_RENDERER;
_dhSwapChainBuffersRTVs.Reset();
_vSwapChainBuffers.clear();
_pSwapChain->ResizeBuffers(
_swapChainDesc.BufferCount,
renderer.GetSwapChainWidth(),
renderer.GetSwapChainHeight(),
_swapChainDesc.Format,
_swapChainDesc.Flags);
_swapChainBufferIndex = _pSwapChain->GetCurrentBackBufferIndex();
CreateSwapChainBuffersRTVs();
}
void RendererD3D12::BeginFrame(bool present)
@ -361,6 +423,10 @@ void RendererD3D12::BeginFrame(bool present)
VERUS_QREF_RENDERER;
HRESULT hr = 0;
ImGui_ImplDX12_NewFrame();
ImGui_ImplSDL2_NewFrame(renderer.GetMainWindow()->GetSDL());
ImGui::NewFrame();
WaitForFenceValue(_fenceValues[_ringBufferIndex]);
if (present)
@ -391,6 +457,8 @@ void RendererD3D12::EndFrame(bool present)
_fenceValues[_ringBufferIndex] = QueueSignal();
_ringBufferIndex = (_ringBufferIndex + 1) % s_ringBufferSize;
}
ImGui::EndFrame();
}
void RendererD3D12::Present()
@ -495,7 +563,7 @@ int RendererD3D12::CreateRenderPass(std::initializer_list<RP::Attachment> ilA, s
return index;
index++;
}
throw VERUS_RECOVERABLE << "CreateRenderPass(), Attachment not found";
throw VERUS_RECOVERABLE << "CreateRenderPass(), attachment not found";
};
renderPass._vSubpasses.reserve(ilS.size());

View File

@ -67,6 +67,8 @@ namespace verus
virtual void ImGuiInit(int renderPassID) override;
virtual void ImGuiRenderDrawData() override;
virtual void ResizeSwapChain() override;
// Which graphics API?
virtual Gapi GetGapi() override { return Gapi::direct3D12; }
@ -74,7 +76,6 @@ namespace verus
virtual void BeginFrame(bool present) override;
virtual void EndFrame(bool present) override;
virtual void Present() override;
virtual void WaitIdle() override;
// Resources:

View File

@ -436,6 +436,16 @@ int ShaderD3D12::BindDescriptorSetTextures(int setNumber, std::initializer_list<
return complexSetID;
}
void ShaderD3D12::FreeDescriptorSet(int complexSetID)
{
if (complexSetID >= 0 && complexSetID < _vComplexSets.size())
{
_vComplexSets[complexSetID]._vTextures.clear();
_vComplexSets[complexSetID]._dhSrvUav.Reset();
_vComplexSets[complexSetID]._dhSamplers.Reset();
}
}
void ShaderD3D12::BeginBindDescriptors()
{
VERUS_QREF_RENDERER;

View File

@ -70,6 +70,7 @@ namespace verus
virtual void CreateDescriptorSet(int setNumber, const void* pSrc, int size, int capacity, std::initializer_list<Sampler> il, ShaderStageFlags stageFlags) override;
virtual void CreatePipelineLayout() override;
virtual int BindDescriptorSetTextures(int setNumber, std::initializer_list<TexturePtr> il, const int* pMips) override;
virtual void FreeDescriptorSet(int complexSetID) override;
virtual void BeginBindDescriptors() override;
virtual void EndBindDescriptors() override;

View File

@ -24,7 +24,7 @@ extern "C"
if (VERUS_SDK_VERSION != version)
{
VERUS_RT_FAIL("VerusCreateRenderer(), Wrong version");
VERUS_RT_FAIL("VerusCreateRenderer(), Wrong version.");
return nullptr;
}

View File

@ -15,7 +15,7 @@
<ProjectGuid>{C9195A1C-9224-4B40-BBBC-AA90EF3BE3E0}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>RendererVulkan</RootNamespace>
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

View File

@ -31,7 +31,8 @@ void CommandBufferVulkan::Begin()
VkResult res = VK_SUCCESS;
VkCommandBufferBeginInfo vkcbbi = {};
vkcbbi.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
vkcbbi.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
if (_oneTimeSubmit)
vkcbbi.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
if (VK_SUCCESS != (res = vkBeginCommandBuffer(GetVkCommandBuffer(), &vkcbbi)))
throw VERUS_RUNTIME_ERROR << "vkBeginCommandBuffer(), res=" << res;
}
@ -324,10 +325,11 @@ VkCommandBuffer CommandBufferVulkan::GetVkCommandBuffer() const
return _commandBuffers[renderer->GetRingBufferIndex()];
}
void CommandBufferVulkan::InitSingleTimeCommands()
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)
@ -335,7 +337,7 @@ void CommandBufferVulkan::InitSingleTimeCommands()
Begin();
}
void CommandBufferVulkan::DoneSingleTimeCommands()
void CommandBufferVulkan::DoneOneTimeSubmit()
{
VERUS_QREF_RENDERER;
VERUS_QREF_RENDERER_VULKAN;
@ -348,4 +350,5 @@ void CommandBufferVulkan::DoneSingleTimeCommands()
vkQueueWaitIdle(pRendererVulkan->GetVkGraphicsQueue());
auto commandPool = pRendererVulkan->GetVkCommandPool(renderer->GetRingBufferIndex());
vkFreeCommandBuffers(pRendererVulkan->GetVkDevice(), commandPool, 1, _commandBuffers);
_oneTimeSubmit = false;
}

View File

@ -7,6 +7,7 @@ namespace verus
class CommandBufferVulkan : public BaseCommandBuffer
{
VkCommandBuffer _commandBuffers[BaseRenderer::s_ringBufferSize] = {};
bool _oneTimeSubmit = false;
public:
CommandBufferVulkan();
@ -46,8 +47,8 @@ namespace verus
VkCommandBuffer GetVkCommandBuffer() const;
void InitSingleTimeCommands();
void DoneSingleTimeCommands();
void InitOneTimeSubmit();
void DoneOneTimeSubmit();
};
VERUS_TYPEDEFS(CommandBufferVulkan);
}

View File

@ -16,8 +16,8 @@ void GeometryVulkan::Init(RcGeometryDesc desc)
{
VERUS_INIT();
_dynBindingsMask = desc._dynBindingsMask;
_32BitIndices = desc._32BitIndices;
_dynamic = desc._dynamic;
const int numBindings = GetNumBindings(desc._pInputElementDesc);
_vVertexInputBindingDesc.reserve(numBindings);
@ -30,7 +30,7 @@ void GeometryVulkan::Init(RcGeometryDesc desc)
if (binding < 0)
{
binding = -binding;
_bindingInstMask |= (1 << binding);
_instBindingsMask |= (1 << binding);
inputRate = VK_VERTEX_INPUT_RATE_INSTANCE;
}
@ -97,7 +97,7 @@ void GeometryVulkan::CreateVertexBuffer(int num, int binding)
const int elementSize = _vStrides[binding];
vb._bufferSize = num * elementSize;
if (((_bindingInstMask >> binding) & 0x1) || _dynamic)
if (((_instBindingsMask | _dynBindingsMask) >> binding) & 0x1)
{
pRendererVulkan->CreateBuffer(vb._bufferSize * BaseRenderer::s_ringBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VMA_MEMORY_USAGE_CPU_TO_GPU,
vb._buffer, vb._vmaAllocation);
@ -114,7 +114,7 @@ void GeometryVulkan::UpdateVertexBuffer(const void* p, int binding, BaseCommandB
VERUS_QREF_RENDERER_VULKAN;
VkResult res = VK_SUCCESS;
if (((_bindingInstMask >> binding) & 0x1) || _dynamic)
if (((_instBindingsMask | _dynBindingsMask) >> binding) & 0x1)
{
auto& vb = _vVertexBuffers[binding];
void* pData = nullptr;
@ -240,7 +240,7 @@ VkPipelineVertexInputStateCreateInfo GeometryVulkan::GetVkPipelineVertexInputSta
VkDeviceSize GeometryVulkan::GetVkVertexBufferOffset(int binding) const
{
if ((_bindingInstMask >> binding) & 0x1)
if (((_instBindingsMask | _dynBindingsMask) >> binding) & 0x1)
{
VERUS_QREF_RENDERER_VULKAN;
auto& vb = _vVertexBuffers[binding];

View File

@ -75,8 +75,12 @@ void PipelineVulkan::Init(RcPipelineDesc desc)
viewportState.viewportCount = desc._multiViewport;
viewportState.scissorCount = desc._multiViewport;
VkPipelineRasterizationLineStateCreateInfoEXT rasterizationLineState = {};
rasterizationLineState.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT;
rasterizationLineState.lineRasterizationMode = VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT;
VkPipelineRasterizationStateCreateInfo rasterizationState = {};
rasterizationState.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rasterizationState.pNext = &rasterizationLineState;
rasterizationState.depthClampEnable = desc._rasterizationState._depthClampEnable;
rasterizationState.rasterizerDiscardEnable = desc._rasterizationState._rasterizerDiscardEnable;
rasterizationState.polygonMode = ToNativePolygonMode(desc._rasterizationState._polygonMode);
@ -86,7 +90,7 @@ void PipelineVulkan::Init(RcPipelineDesc desc)
rasterizationState.depthBiasConstantFactor = desc._rasterizationState._depthBiasConstantFactor * 0.5f; // Magic value to match D3D12.
rasterizationState.depthBiasClamp = desc._rasterizationState._depthBiasClamp;
rasterizationState.depthBiasSlopeFactor = desc._rasterizationState._depthBiasSlopeFactor;
rasterizationState.lineWidth = desc._rasterizationState._lineWidth;
rasterizationState.lineWidth = 1;
VkPipelineMultisampleStateCreateInfo multisampleState = {};
multisampleState.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;

View File

@ -91,12 +91,22 @@ void RendererVulkan::Init()
void RendererVulkan::Done()
{
WaitIdle();
if (ImGui::GetCurrentContext())
{
ImGui_ImplVulkan_Shutdown();
ImGui_ImplSDL2_Shutdown();
ImGui::DestroyContext();
Renderer::I().ImGuiSetCurrentContext(nullptr);
}
DeleteFramebuffer(-1);
DeleteRenderPass(-1);
for (auto sampler : _vSamplers)
VERUS_VULKAN_DESTROY(sampler, vkDestroySampler(_device, sampler, GetAllocator()));
_vSamplers.clear();
VERUS_VULKAN_DESTROY(_descriptorPoolImGui, vkDestroyDescriptorPool(_device, _descriptorPoolImGui, GetAllocator()));
VERUS_FOR(i, s_ringBufferSize)
{
VERUS_VULKAN_DESTROY(_acquireNextImageSemaphores[i], vkDestroySemaphore(_device, _acquireNextImageSemaphores[i], GetAllocator()));
@ -378,6 +388,10 @@ void RendererVulkan::CreateDevice()
{
VkResult res = VK_SUCCESS;
VkPhysicalDeviceLineRasterizationFeaturesEXT lineRasterizationFeatures = {};
lineRasterizationFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT;
lineRasterizationFeatures.smoothLines = VK_TRUE;
_queueFamilyIndices = FindQueueFamilyIndices(_physicalDevice);
VERUS_RT_ASSERT(_queueFamilyIndices.IsComplete());
Set<int> setUniqueQueueFamilies = { _queueFamilyIndices._graphicsFamilyIndex, _queueFamilyIndices._presentFamilyIndex };
@ -400,6 +414,7 @@ void RendererVulkan::CreateDevice()
physicalDeviceFeatures.shaderImageGatherExtended = VK_TRUE;
VkDeviceCreateInfo vkdci = {};
vkdci.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
vkdci.pNext = &lineRasterizationFeatures;
vkdci.queueCreateInfoCount = Utils::Cast32(vDeviceQueueCreateInfos.size());
vkdci.pQueueCreateInfos = vDeviceQueueCreateInfos.data();
#if defined(_DEBUG) || defined(VERUS_DEBUG)
@ -441,8 +456,9 @@ RendererVulkan::SwapChainInfo RendererVulkan::GetSwapChainInfo(VkPhysicalDevice
return swapChainInfo;
}
void RendererVulkan::CreateSwapChain()
void RendererVulkan::CreateSwapChain(VkSwapchainKHR oldSwapchain)
{
VERUS_QREF_RENDERER;
VERUS_QREF_CONST_SETTINGS;
VkResult res = VK_SUCCESS;
@ -457,15 +473,15 @@ void RendererVulkan::CreateSwapChain()
vksci.minImageCount = _numSwapChainBuffers;
vksci.imageFormat = VK_FORMAT_B8G8R8A8_SRGB;
vksci.imageColorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
vksci.imageExtent.width = settings._screenSizeWidth;
vksci.imageExtent.height = settings._screenSizeHeight;
vksci.imageExtent.width = renderer.GetSwapChainWidth();
vksci.imageExtent.height = renderer.GetSwapChainHeight();
vksci.imageArrayLayers = 1;
vksci.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
vksci.preTransform = swapChainInfo._surfaceCapabilities.currentTransform;
vksci.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
vksci.presentMode = settings._screenVSync ? VK_PRESENT_MODE_MAILBOX_KHR : VK_PRESENT_MODE_FIFO_KHR;
vksci.clipped = VK_TRUE;
vksci.oldSwapchain = VK_NULL_HANDLE;
vksci.oldSwapchain = oldSwapchain;
const uint32_t queueFamilyIndicesArray[] =
{
static_cast<uint32_t>(_queueFamilyIndices._graphicsFamilyIndex),
@ -662,44 +678,45 @@ const VkSampler* RendererVulkan::GetImmutableSampler(Sampler s) const
return &_vSamplers[+s];
}
void RendererVulkan::ImGuiCheckVkResultFn(VkResult res)
{
if (VK_SUCCESS != res)
throw VERUS_RUNTIME_ERROR << "ImGuiCheckVkResultFn(), res=" << res;
}
void RendererVulkan::ImGuiInit(int renderPassID)
{
VkResult res = VK_SUCCESS;
VkDescriptorPool descriptorPool = VK_NULL_HANDLE;
{
VkDescriptorPoolSize pool_sizes[] =
{
{ VK_DESCRIPTOR_TYPE_SAMPLER, 1000 },
{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1000 },
{ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1000 },
{ VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1000 },
{ VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1000 },
{ VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1000 },
{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1000 },
{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1000 },
{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1000 },
{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, 1000 },
{ VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1000 }
};
VkDescriptorPoolCreateInfo pool_info = {};
pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
pool_info.maxSets = 1000 * IM_ARRAYSIZE(pool_sizes);
pool_info.poolSizeCount = (uint32_t)IM_ARRAYSIZE(pool_sizes);
pool_info.pPoolSizes = pool_sizes;
res = vkCreateDescriptorPool(_device, &pool_info, GetAllocator(), &descriptorPool);
}
VkDescriptorPoolSize vkdps = { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1 };
VkDescriptorPoolCreateInfo vkdpci = {};
vkdpci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
vkdpci.maxSets = 1;
vkdpci.poolSizeCount = 1;
vkdpci.pPoolSizes = &vkdps;
if (VK_SUCCESS != (res = vkCreateDescriptorPool(_device, &vkdpci, GetAllocator(), &_descriptorPoolImGui)))
throw VERUS_RUNTIME_ERROR << "vkCreateDescriptorPool(), res=" << res;
VERUS_QREF_RENDERER;
SDL_Window* pWnd = renderer.GetMainWindow()->GetSDL();
VERUS_QREF_CONST_SETTINGS;
IMGUI_CHECKVERSION();
ImGuiContext* pContext = ImGui::CreateContext();
renderer.ImGuiSetCurrentContext(pContext);
ImGuiIO& io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
io.ConfigWindowsMoveFromTitleBarOnly = true;
if (!settings._imguiFont.empty())
{
Vector<BYTE> vData;
IO::FileSystem::LoadResource(_C(settings._imguiFont), vData);
void* pFontData = IM_ALLOC(vData.size());
memcpy(pFontData, vData.data(), vData.size());
io.Fonts->AddFontFromMemoryTTF(pFontData, Utils::Cast32(vData.size()), 15);
}
ImGui::StyleColorsDark();
ImGui_ImplSDL2_InitForVulkan(pWnd);
ImGui_ImplSDL2_InitForVulkan(renderer.GetMainWindow()->GetSDL());
ImGui_ImplVulkan_InitInfo info = {};
info.Instance = _instance;
info.PhysicalDevice = _physicalDevice;
@ -707,49 +724,40 @@ void RendererVulkan::ImGuiInit(int renderPassID)
info.QueueFamily = _queueFamilyIndices._graphicsFamilyIndex;
info.Queue = _graphicsQueue;
info.PipelineCache = nullptr;
info.DescriptorPool = descriptorPool;
info.DescriptorPool = _descriptorPoolImGui;
info.Allocator = GetAllocator();
info.MinImageCount = 2;
info.ImageCount = 2;
info.CheckVkResultFn = nullptr;
info.MinImageCount = settings._screenVSync ? 3 : 2;;
info.ImageCount = s_ringBufferSize;
info.CheckVkResultFn = ImGuiCheckVkResultFn;
ImGui_ImplVulkan_Init(&info, _vRenderPasses[renderPassID]);
{
// Use any command queue
VkCommandPool command_pool = _commandPools[_ringBufferIndex];
VkCommandBuffer command_buffer = static_cast<CommandBufferVulkan*>(&(*renderer.GetCommandBuffer()))->GetVkCommandBuffer();
res = vkResetCommandPool(_device, command_pool, 0);
VkCommandBufferBeginInfo begin_info = {};
begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
begin_info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
res = vkBeginCommandBuffer(command_buffer, &begin_info);
ImGui_ImplVulkan_CreateFontsTexture(command_buffer);
VkSubmitInfo end_info = {};
end_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
end_info.commandBufferCount = 1;
end_info.pCommandBuffers = &command_buffer;
res = vkEndCommandBuffer(command_buffer);
res = vkQueueSubmit(_graphicsQueue, 1, &end_info, VK_NULL_HANDLE);
res = vkDeviceWaitIdle(_device);
ImGui_ImplVulkan_DestroyFontUploadObjects();
}
CommandBufferVulkan commandBuffer;
commandBuffer.InitOneTimeSubmit();
ImGui_ImplVulkan_CreateFontsTexture(commandBuffer.GetVkCommandBuffer());
commandBuffer.DoneOneTimeSubmit();
ImGui_ImplVulkan_DestroyFontUploadObjects();
}
void RendererVulkan::ImGuiRenderDrawData()
{
VERUS_QREF_RENDERER;
VkCommandBuffer command_buffer = static_cast<CommandBufferVulkan*>(&(*renderer.GetCommandBuffer()))->GetVkCommandBuffer();
ImGui::Render();
VkCommandBuffer commandBuffer = static_cast<CommandBufferVulkan*>(&(*renderer.GetCommandBuffer()))->GetVkCommandBuffer();
if (ImGui::GetDrawData())
ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), command_buffer);
ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), commandBuffer);
}
void RendererVulkan::ResizeSwapChain()
{
for (auto swapChainImageViews : _vSwapChainImageViews)
vkDestroyImageView(_device, swapChainImageViews, GetAllocator());
_vSwapChainImageViews.clear();
_vSwapChainImages.clear();
VkSwapchainKHR oldSwapchain = _swapChain;
CreateSwapChain(oldSwapchain);
CreateImageViews();
VERUS_VULKAN_DESTROY(oldSwapchain, vkDestroySwapchainKHR(_device, oldSwapchain, GetAllocator()));
}
void RendererVulkan::BeginFrame(bool present)
@ -944,7 +952,7 @@ int RendererVulkan::CreateRenderPass(std::initializer_list<RP::Attachment> ilA,
return index;
index++;
}
throw VERUS_RECOVERABLE << "CreateRenderPass(), Attachment not found";
throw VERUS_RECOVERABLE << "CreateRenderPass(), attachment not found";
};
struct SubpassMetadata
@ -1014,7 +1022,7 @@ int RendererVulkan::CreateRenderPass(std::initializer_list<RP::Attachment> ilA,
// vAttachmentRef is ready, convert indices to actual pointers:
if (vAttachmentRef.empty())
throw VERUS_RECOVERABLE << "CreateRenderPass(), No attachment references";
throw VERUS_RECOVERABLE << "CreateRenderPass(), no attachment references";
int index = 0;
for (auto& sd : vSubpassDesc)
{
@ -1041,7 +1049,7 @@ int RendererVulkan::CreateRenderPass(std::initializer_list<RP::Attachment> ilA,
return index;
index++;
}
throw VERUS_RECOVERABLE << "CreateRenderPass(), Subpass not found";
throw VERUS_RECOVERABLE << "CreateRenderPass(), subpass not found";
};
Vector<VkSubpassDependency> vSubpassDependency;

View File

@ -74,6 +74,7 @@ namespace verus
VkSemaphore _queueSubmitSemaphore = VK_NULL_HANDLE;
VkFence _queueSubmitFences[s_ringBufferSize] = {};
QueueFamilyIndices _queueFamilyIndices;
VkDescriptorPool _descriptorPoolImGui = VK_NULL_HANDLE;
Vector<VkSampler> _vSamplers;
Vector<VkRenderPass> _vRenderPasses;
Vector<Framebuffer> _vFramebuffers;
@ -109,7 +110,7 @@ namespace verus
void PickPhysicalDevice();
void CreateDevice();
SwapChainInfo GetSwapChainInfo(VkPhysicalDevice device);
void CreateSwapChain();
void CreateSwapChain(VkSwapchainKHR oldSwapchain = VK_NULL_HANDLE);
void CreateImageViews();
void CreateCommandPools();
void CreateSyncObjects();
@ -125,9 +126,12 @@ namespace verus
VkCommandPool GetVkCommandPool(int ringBufferIndex) const { return _commandPools[ringBufferIndex]; }
const VkSampler* GetImmutableSampler(Sampler s) const;
static void ImGuiCheckVkResultFn(VkResult res);
virtual void ImGuiInit(int renderPassID) override;
virtual void ImGuiRenderDrawData() override;
virtual void ResizeSwapChain() override;
// Which graphics API?
virtual Gapi GetGapi() override { return Gapi::vulkan; }
@ -135,7 +139,6 @@ namespace verus
virtual void BeginFrame(bool present) override;
virtual void EndFrame(bool present) override;
virtual void Present() override;
virtual void WaitIdle() override;
// Resources:

View File

@ -451,6 +451,19 @@ int ShaderVulkan::BindDescriptorSetTextures(int setNumber, std::initializer_list
return complexSetID;
}
void ShaderVulkan::FreeDescriptorSet(int complexSetID)
{
VERUS_QREF_RENDERER_VULKAN;
VkResult res = VK_SUCCESS;
if (complexSetID >= 0 && complexSetID < _vComplexDescriptorSets.size() && _vComplexDescriptorSets[complexSetID] != VK_NULL_HANDLE)
{
if (VK_SUCCESS != (res = vkFreeDescriptorSets(pRendererVulkan->GetVkDevice(), _descriptorPool, 1, &_vComplexDescriptorSets[complexSetID])))
throw VERUS_RUNTIME_ERROR << "vkFreeDescriptorSets(), res=" << res;
_vComplexDescriptorSets[complexSetID] = VK_NULL_HANDLE;
}
}
void ShaderVulkan::BeginBindDescriptors()
{
VERUS_QREF_RENDERER;
@ -496,32 +509,26 @@ void ShaderVulkan::CreateDescriptorPool()
VkDescriptorPoolCreateInfo vkdpci = {};
vkdpci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
vkdpci.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
vkdpci.poolSizeCount = 1;
VkDescriptorPoolSize vkdps[4] = {};
vkdps[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
vkdps[0].descriptorCount = _poolComplexUniformBuffers + Utils::Cast32(_vDescriptorSetLayouts.size());
vkdps[0] = { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, _poolComplexUniformBuffers + Utils::Cast32(_vDescriptorSetLayouts.size()) };
vkdpci.maxSets = vkdps[0].descriptorCount;
int index = 1;
if (_poolComplexImageSamplers > 0)
{
vkdps[index].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
vkdps[index].descriptorCount = _poolComplexImageSamplers;
vkdps[index++] = { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, _poolComplexImageSamplers };
vkdpci.poolSizeCount++;
index++;
}
if (_poolComplexStorageImages > 0)
{
vkdps[index].type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
vkdps[index].descriptorCount = _poolComplexStorageImages;
vkdps[index++] = { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, _poolComplexStorageImages };
vkdpci.poolSizeCount++;
index++;
}
if (_poolComplexInputAttachments > 0)
{
vkdps[index].type = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
vkdps[index].descriptorCount = _poolComplexInputAttachments;
vkdps[index++] = { VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, _poolComplexInputAttachments };
vkdpci.poolSizeCount++;
index++;
}
vkdpci.pPoolSizes = vkdps;
if (VK_SUCCESS != (res = vkCreateDescriptorPool(pRendererVulkan->GetVkDevice(), &vkdpci, pRendererVulkan->GetAllocator(), &_descriptorPool)))

View File

@ -37,10 +37,10 @@ namespace verus
VkDescriptorPool _descriptorPool = VK_NULL_HANDLE;
VkPipelineLayout _pipelineLayout = VK_NULL_HANDLE;
UINT64 _currentFrame = UINT64_MAX;
int _poolComplexUniformBuffers = 0;
int _poolComplexImageSamplers = 0;
int _poolComplexStorageImages = 0;
int _poolComplexInputAttachments = 0;
uint32_t _poolComplexUniformBuffers = 0;
uint32_t _poolComplexImageSamplers = 0;
uint32_t _poolComplexStorageImages = 0;
uint32_t _poolComplexInputAttachments = 0;
bool _compute = false;
public:
@ -53,6 +53,7 @@ namespace verus
virtual void CreateDescriptorSet(int setNumber, const void* pSrc, int size, int capacity, std::initializer_list<Sampler> il, ShaderStageFlags stageFlags) override;
virtual void CreatePipelineLayout() override;
virtual int BindDescriptorSetTextures(int setNumber, std::initializer_list<TexturePtr> il, const int* pMips) override;
virtual void FreeDescriptorSet(int complexSetID) override;
virtual void BeginBindDescriptors() override;
virtual void EndBindDescriptors() override;

View File

@ -101,9 +101,9 @@ void TextureVulkan::Init(RcTextureDesc desc)
if (renderTarget)
{
CommandBufferVulkan commandBuffer;
commandBuffer.InitSingleTimeCommands();
commandBuffer.InitOneTimeSubmit();
commandBuffer.PipelineImageMemoryBarrier(TexturePtr::From(this), ImageLayout::undefined, ImageLayout::fsReadOnly, 0, 0);
commandBuffer.DoneSingleTimeCommands();
commandBuffer.DoneOneTimeSubmit();
}
if (depthFormat)
{
@ -111,9 +111,9 @@ void TextureVulkan::Init(RcTextureDesc desc)
ImageLayout::depthStencilReadOnly :
ImageLayout::depthStencilAttachment;
CommandBufferVulkan commandBuffer;
commandBuffer.InitSingleTimeCommands();
commandBuffer.InitOneTimeSubmit();
commandBuffer.PipelineImageMemoryBarrier(TexturePtr::From(this), ImageLayout::undefined, layout, 0, 0);
commandBuffer.DoneSingleTimeCommands();
commandBuffer.DoneOneTimeSubmit();
}
_vStagingBuffers.reserve(_desc._mipLevels * _desc._arrayLayers);
@ -328,7 +328,7 @@ void TextureVulkan::CreateSampler()
}
}
vksci.mipLodBias = _desc._pSamplerDesc->_mipLodBias;
vksci.maxAnisotropy = settings._gpuAnisotropyLevel;
vksci.maxAnisotropy = static_cast<float>(settings._gpuAnisotropyLevel);
vksci.minLod = _desc._pSamplerDesc->_minLod;
vksci.maxLod = _desc._pSamplerDesc->_maxLod;
if (_desc._pSamplerDesc->_borderColor.getX() < 0.5f)

View File

@ -24,7 +24,7 @@ extern "C"
if (VERUS_SDK_VERSION != version)
{
VERUS_RT_FAIL("VerusCreateRenderer(), Wrong version");
VERUS_RT_FAIL("VerusCreateRenderer(), Wrong version.");
return nullptr;
}

View File

@ -3,8 +3,8 @@
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<IncludePath>C:\Home\Projects\Verus\verus\Verus\src;C:\Home\Middleware\bullet3-2.88\src;C:\Home\Middleware\bullet3-2.88\Extras;C:\Home\Middleware\libogg-1.3.3\include;C:\Home\Middleware\libvorbis-1.3.6\include;C:\Home\Middleware\SDL2-2.0.9\include;C:\Program Files %28x86%29\OpenAL 1.1 SDK\include;C:\VulkanSDK\1.1.126.0\Include;C:\VulkanSDK\1.1.126.0\glslang;$(IncludePath)</IncludePath>
<LibraryPath>C:\Home\Middleware\bullet3-2.88\bin;C:\Home\Middleware\libogg-1.3.3\lib;C:\Home\Middleware\libvorbis-1.3.6\lib2;C:\Home\Middleware\SDL2-2.0.9\lib\x64;C:\Program Files %28x86%29\OpenAL 1.1 SDK\libs\Win64;C:\VulkanSDK\1.1.126.0\Lib;$(LibraryPath)</LibraryPath>
<IncludePath>C:\Home\Projects\Verus\verus\Verus\src;C:\Home\Middleware\AMD Tootle 2.3\include;C:\Home\Middleware\bullet3-2.88\src;C:\Home\Middleware\bullet3-2.88\Extras;C:\Home\Middleware\libogg-1.3.4\include;C:\Home\Middleware\libvorbis-1.3.6\include;C:\Home\Middleware\SDL2-2.0.10\include;C:\Program Files %28x86%29\OpenAL 1.1 SDK\include;C:\VulkanSDK\1.1.126.0\Include;C:\VulkanSDK\1.1.126.0\glslang;$(IncludePath)</IncludePath>
<LibraryPath>C:\Home\Middleware\bullet3-2.88\bin;C:\Home\Middleware\AMD Tootle 2.3\lib;C:\Home\Middleware\libogg-1.3.4\lib;C:\Home\Middleware\libvorbis-1.3.6\lib2;C:\Home\Middleware\SDL2-2.0.10\lib\x64;C:\Program Files %28x86%29\OpenAL 1.1 SDK\libs\Win64;C:\VulkanSDK\1.1.126.0\Lib;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup />
<ItemGroup />

View File

@ -15,7 +15,7 @@
<ProjectGuid>{B154D670-E4B1-4D8A-885C-69546A5BD833}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>Verus</RootNamespace>
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
@ -126,6 +126,8 @@
<ClInclude Include="src\D\Log.h" />
<ClInclude Include="src\D\Recoverable.h" />
<ClInclude Include="src\D\RuntimeError.h" />
<ClInclude Include="src\Extra\Extra.h" />
<ClInclude Include="src\Extra\FileParser.h" />
<ClInclude Include="src\Game\BaseGame.h" />
<ClInclude Include="src\Game\Spirit.h" />
<ClInclude Include="src\Game\Game.h" />
@ -153,6 +155,7 @@
<ClInclude Include="src\Global\Utils.h" />
<ClInclude Include="src\Input\Input.h" />
<ClInclude Include="src\Input\KeyMapper.h" />
<ClInclude Include="src\Input\DragController.h" />
<ClInclude Include="src\IO\Async.h" />
<ClInclude Include="src\IO\DDSHeader.h" />
<ClInclude Include="src\IO\File.h" />
@ -186,12 +189,16 @@
<ClInclude Include="src\Net\Net.h" />
<ClInclude Include="src\Net\Socket.h" />
<ClInclude Include="src\Physics\Bullet.h" />
<ClInclude Include="src\Physics\BulletDebugDraw.h" />
<ClInclude Include="src\Physics\CharacterController.h" />
<ClInclude Include="src\Physics\Groups.h" />
<ClInclude Include="src\Physics\KinematicCharacterController.h" />
<ClInclude Include="src\Physics\Physics.h" />
<ClInclude Include="src\Physics\UserPtr.h" />
<ClInclude Include="src\Scene\Atmosphere.h" />
<ClInclude Include="src\Scene\BaseMesh.h" />
<ClInclude Include="src\Scene\Camera.h" />
<ClInclude Include="src\Scene\CameraOrbit.h" />
<ClInclude Include="src\Scene\EditorTerrain.h" />
<ClInclude Include="src\Scene\Helpers.h" />
<ClInclude Include="src\Scene\MaterialManager.h" />
@ -213,6 +220,7 @@
<ClInclude Include="src\ThirdParty\libb64\cdecode.h" />
<ClInclude Include="src\ThirdParty\libb64\cencode.h" />
<ClInclude Include="src\ThirdParty\md5.h" />
<ClInclude Include="src\ThirdParty\nativefiledialog\nfd.h" />
<ClInclude Include="src\ThirdParty\pugixml-1.10\pugiconfig.hpp" />
<ClInclude Include="src\ThirdParty\pugixml-1.10\pugixml.hpp" />
<ClInclude Include="src\ThirdParty\ThirdParty.h" />
@ -263,6 +271,8 @@
<ClCompile Include="src\CGI\RendererParser.cpp" />
<ClCompile Include="src\CGI\RenderPass.cpp" />
<ClCompile Include="src\D\Log.cpp" />
<ClCompile Include="src\Extra\Extra.cpp" />
<ClCompile Include="src\Extra\FileParser.cpp" />
<ClCompile Include="src\Game\BaseGame.cpp" />
<ClCompile Include="src\Game\Spirit.cpp" />
<ClCompile Include="src\Game\State.cpp" />
@ -279,6 +289,7 @@
<ClCompile Include="src\Global\Utils.cpp" />
<ClCompile Include="src\Input\Input.cpp" />
<ClCompile Include="src\Input\KeyMapper.cpp" />
<ClCompile Include="src\Input\DragController.cpp" />
<ClCompile Include="src\IO\Async.cpp" />
<ClCompile Include="src\IO\DDSHeader.cpp" />
<ClCompile Include="src\IO\File.cpp" />
@ -304,10 +315,17 @@
<ClCompile Include="src\Net\Net.cpp" />
<ClCompile Include="src\Net\Socket.cpp" />
<ClCompile Include="src\Physics\Bullet.cpp" />
<ClCompile Include="src\Physics\BulletDebugDraw.cpp" />
<ClCompile Include="src\Physics\CharacterController.cpp" />
<ClCompile Include="src\Physics\KinematicCharacterController.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="src\Physics\Physics.cpp" />
<ClCompile Include="src\Scene\Atmosphere.cpp" />
<ClCompile Include="src\Scene\BaseMesh.cpp" />
<ClCompile Include="src\Scene\Camera.cpp" />
<ClCompile Include="src\Scene\CameraOrbit.cpp" />
<ClCompile Include="src\Scene\EditorTerrain.cpp" />
<ClCompile Include="src\Scene\Helpers.cpp" />
<ClCompile Include="src\Scene\MaterialManager.cpp" />
@ -316,6 +334,10 @@
<ClCompile Include="src\Scene\SceneManager.cpp" />
<ClCompile Include="src\Scene\ShadowMap.cpp" />
<ClCompile Include="src\Scene\Terrain.cpp" />
<ClCompile Include="src\ThirdParty\fast_atof.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="src\ThirdParty\imgui\imgui.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
@ -356,6 +378,14 @@
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<ClCompile Include="src\ThirdParty\nativefiledialog\nfd_common.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="src\ThirdParty\nativefiledialog\nfd_win.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="src\ThirdParty\pugixml-1.10\pugixml.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>

View File

@ -82,6 +82,12 @@
<Filter Include="src\ThirdParty\imgui">
<UniqueIdentifier>{3ee2005e-b456-4f4f-95cd-ad3ac11aaccb}</UniqueIdentifier>
</Filter>
<Filter Include="src\ThirdParty\nativefiledialog">
<UniqueIdentifier>{91530a5d-5ad0-4b0a-b2af-b48fa807a91d}</UniqueIdentifier>
</Filter>
<Filter Include="src\Extra">
<UniqueIdentifier>{a3579964-dc6d-460a-82fb-b3b35746fcf1}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\CGI\BaseGeometry.h">
@ -516,6 +522,30 @@
<ClInclude Include="src\ThirdParty\imgui\imgui_impl_sdl.h">
<Filter>src\ThirdParty\imgui</Filter>
</ClInclude>
<ClInclude Include="src\Physics\BulletDebugDraw.h">
<Filter>src\Physics</Filter>
</ClInclude>
<ClInclude Include="src\Physics\CharacterController.h">
<Filter>src\Physics</Filter>
</ClInclude>
<ClInclude Include="src\Physics\KinematicCharacterController.h">
<Filter>src\Physics</Filter>
</ClInclude>
<ClInclude Include="src\Scene\CameraOrbit.h">
<Filter>src\Scene</Filter>
</ClInclude>
<ClInclude Include="src\Input\DragController.h">
<Filter>src\Input</Filter>
</ClInclude>
<ClInclude Include="src\ThirdParty\nativefiledialog\nfd.h">
<Filter>src\ThirdParty\nativefiledialog</Filter>
</ClInclude>
<ClInclude Include="src\Extra\Extra.h">
<Filter>src\Extra</Filter>
</ClInclude>
<ClInclude Include="src\Extra\FileParser.h">
<Filter>src\Extra</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\CGI\BaseGeometry.cpp">
@ -839,6 +869,36 @@
<ClCompile Include="src\ThirdParty\imgui\imgui_impl_sdl.cpp">
<Filter>src\ThirdParty\imgui</Filter>
</ClCompile>
<ClCompile Include="src\Physics\BulletDebugDraw.cpp">
<Filter>src\Physics</Filter>
</ClCompile>
<ClCompile Include="src\Physics\CharacterController.cpp">
<Filter>src\Physics</Filter>
</ClCompile>
<ClCompile Include="src\Physics\KinematicCharacterController.cpp">
<Filter>src\Physics</Filter>
</ClCompile>
<ClCompile Include="src\Scene\CameraOrbit.cpp">
<Filter>src\Scene</Filter>
</ClCompile>
<ClCompile Include="src\Input\DragController.cpp">
<Filter>src\Input</Filter>
</ClCompile>
<ClCompile Include="src\ThirdParty\nativefiledialog\nfd_win.cpp">
<Filter>src\ThirdParty\nativefiledialog</Filter>
</ClCompile>
<ClCompile Include="src\ThirdParty\nativefiledialog\nfd_common.c">
<Filter>src\ThirdParty\nativefiledialog</Filter>
</ClCompile>
<ClCompile Include="src\Extra\Extra.cpp">
<Filter>src\Extra</Filter>
</ClCompile>
<ClCompile Include="src\Extra\FileParser.cpp">
<Filter>src\Extra</Filter>
</ClCompile>
<ClCompile Include="src\ThirdParty\fast_atof.c">
<Filter>src\ThirdParty</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="src\Shaders\Lib.hlsl">

View File

@ -716,26 +716,26 @@ void Motion::Deserialize(IO::RStream stream)
UINT32 magic = 0;
stream >> magic;
if ('2NAX' != magic)
throw VERUS_RECOVERABLE << "Deserialize(), Invalid XAN format";
throw VERUS_RECOVERABLE << "Deserialize(), invalid XAN format";
UINT16 version = 0;
stream >> version;
if (s_xanVersion != version)
throw VERUS_RECOVERABLE << "Deserialize(), Invalid XAN version";
throw VERUS_RECOVERABLE << "Deserialize(), invalid XAN version";
stream >> _numFrames;
stream >> _fps;
if (_numFrames < 0 || _numFrames > s_maxNumFrames)
throw VERUS_RECOVERABLE << "Deserialize(), Invalid number of frames in XAN";
throw VERUS_RECOVERABLE << "Deserialize(), invalid number of frames in XAN";
if (_fps <= 0 || _fps > s_maxFps)
throw VERUS_RECOVERABLE << "Deserialize(), Invalid FPS in XAN";
throw VERUS_RECOVERABLE << "Deserialize(), invalid FPS in XAN";
SetFps(_fps);
int numBones = 0;
stream >> numBones;
if (numBones < 0 || numBones > s_maxNumBones)
throw VERUS_RECOVERABLE << "Deserialize(), Invalid number of bones in XAN";
throw VERUS_RECOVERABLE << "Deserialize(), invalid number of bones in XAN";
char buffer[IO::Stream::s_bufferSize] = {};
VERUS_FOR(i, numBones)

View File

@ -295,20 +295,6 @@ void Skeleton::RecursiveBoneUpdate()
pCurrentBone->_ready = true;
}
void Skeleton::VisitBones(std::function<Continue(RBone)> fn)
{
for (auto& kv : _mapBones)
if (Continue::yes != fn(kv.second))
return;
}
void Skeleton::VisitBones(std::function<Continue(RcBone)> fn) const
{
for (const auto& kv : _mapBones)
if (Continue::yes != fn(kv.second))
return;
}
void Skeleton::InsertBonesIntoMotion(RMotion motion) const
{
for (const auto& kv : _mapBones)

View File

@ -111,8 +111,20 @@ namespace verus
int GetNumBones() const { return _numPrimaryBones ? _numPrimaryBones : Utils::Cast32(_mapBones.size()); }
void VisitBones(std::function<Continue(RBone)> fn);
void VisitBones(std::function<Continue(RcBone)> fn) const;
template<typename F>
void VisitBones(const F& fn)
{
for (auto& kv : _mapBones)
if (Continue::yes != fn(kv.second))
return;
}
template<typename F>
void VisitBones(const F& fn) const
{
for (const auto& kv : _mapBones)
if (Continue::yes != fn(kv.second))
return;
}
//! Adds skeleton's bones to motion object (Motion).
void InsertBonesIntoMotion(RMotion motion) const;

View File

@ -82,6 +82,7 @@ namespace verus
String _uiLang = "EN";
CommandLine _commandLine;
Limits _limits;
String _imguiFont;
Settings();
~Settings();

View File

@ -33,9 +33,11 @@ void Window::Init(RcDesc descConst)
if (desc._useSettings)
desc.ApplySettings();
Uint32 flags = 0;
Uint32 flags = desc._flags;
if (desc._fullscreen)
flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
if (desc._resizable)
flags |= SDL_WINDOW_RESIZABLE;
if (0 == settings._gapi)
flags |= SDL_WINDOW_VULKAN;

View File

@ -11,11 +11,13 @@ namespace verus
public:
struct Desc
{
CSZ _title = nullptr;
int _width = 0;
int _height = 0;
bool _fullscreen = false;
bool _useSettings = true;
CSZ _title = nullptr;
int _width = 0;
int _height = 0;
Uint32 _flags = 0;
bool _fullscreen = false;
bool _resizable = false;
bool _useSettings = true;
void ApplySettings();
};
@ -27,7 +29,7 @@ namespace verus
void Init(RcDesc desc = Desc());
void Done();
SDL_Window* GetSDL() { return _pWnd; }
SDL_Window* GetSDL() const { return _pWnd; }
};
VERUS_TYPEDEFS(Window);
}

View File

@ -274,7 +274,7 @@ void StreamPlayer::ThreadProc()
}
catch (D::RcRuntimeError e)
{
//Utils::CLog::Error(e.what(), e.GetThreadID(), e.GetFile(), e.GetLine());
D::Log::I().Write(e.what(), e.GetThreadID(), e.GetFile(), e.GetLine(), D::Log::Severity::error);
}
catch (const std::exception & e)
{

View File

@ -10,17 +10,17 @@ namespace verus
{
PcInputElementDesc _pInputElementDesc;
const int* _pStrides = nullptr;
UINT32 _dynBindingsMask = 0;
bool _32BitIndices = false;
bool _dynamic = false;
};
VERUS_TYPEDEFS(GeometryDesc);
class BaseGeometry : public Object
{
protected:
int _bindingInstMask = 0;
bool _32BitIndices = false;
bool _dynamic = false;
UINT32 _instBindingsMask = 0;
UINT32 _dynBindingsMask = 0;
bool _32BitIndices = false;
BaseGeometry() = default;
virtual ~BaseGeometry() = default;

View File

@ -25,6 +25,7 @@ namespace verus
bool _primitiveRestartEnable = false; // Special index value is 0xFFFFFFFF for 32-bit and 0xFFFF for 16-bit indices.
bool _compute = false; // Compute pipeline, use PipelineDesc(ShaderPtr, CSZ) to set this to true.
// What to draw (geo)? How to draw (shader)? Where to draw (render pass)?
PipelineDesc(GeometryPtr geo, ShaderPtr shader, CSZ branch, int renderPassID, int subpass = 0) :
_geometry(geo), _shader(shader), _shaderBranch(branch), _renderPassID(renderPassID), _subpass(subpass)
{

View File

@ -67,7 +67,7 @@ void BaseRenderer::SetAlphaBlendHelper(
{
case 0: break;
case 1: colorBlendOp = BLENDOP_REVSUBTRACT; break;
default: VERUS_RT_FAIL("FAIL: color s/d not found.");
default: VERUS_RT_FAIL("Color s/d not found.");
}
srcColorBlendFactor = RendererParser::ExpectBlendOp(p);
p += VERUS_LITERAL_LENGTH(")");
@ -77,7 +77,7 @@ void BaseRenderer::SetAlphaBlendHelper(
case 0: if (-1 == colorBlendOp) colorBlendOp = BLENDOP_ADD; break;
case 1: if (-1 == colorBlendOp) colorBlendOp = BLENDOP_SUBTRACT; break;
case 2: break;
default: VERUS_RT_FAIL("FAIL: invalid color op.");
default: VERUS_RT_FAIL("Invalid color op.");
}
p += VERUS_LITERAL_LENGTH("d*(");
dstColorBlendFactor = RendererParser::ExpectBlendOp(p);
@ -99,7 +99,7 @@ void BaseRenderer::SetAlphaBlendHelper(
{
case 0: break;
case 1: alphaBlendOp = BLENDOP_REVSUBTRACT; break;
default: VERUS_RT_FAIL("FAIL: alpha s/d not found.");
default: VERUS_RT_FAIL("Alpha s/d not found.");
}
srcAlphaBlendFactor = RendererParser::ExpectBlendOp(p);
p += VERUS_LITERAL_LENGTH(")");
@ -108,7 +108,7 @@ void BaseRenderer::SetAlphaBlendHelper(
case 0: if (-1 == alphaBlendOp) alphaBlendOp = BLENDOP_ADD; break;
case 1: if (-1 == alphaBlendOp) alphaBlendOp = BLENDOP_SUBTRACT; break;
case 2: break;
default: VERUS_RT_FAIL("FAIL: invalid alpha op.");
default: VERUS_RT_FAIL("Invalid alpha op.");
}
p += VERUS_LITERAL_LENGTH("d*(");
dstAlphaBlendFactor = RendererParser::ExpectBlendOp(p);

View File

@ -25,10 +25,10 @@ namespace verus
class BaseRenderer : public Object
{
protected:
BaseRendererDesc _desc;
UINT32 _numSwapChainBuffers = 0;
UINT32 _swapChainBufferIndex = 0;
UINT32 _ringBufferIndex = 0;
BaseRendererDesc _desc;
UINT32 _numSwapChainBuffers = 0;
UINT32 _swapChainBufferIndex = 0;
UINT32 _ringBufferIndex = 0;
BaseRenderer();
virtual ~BaseRenderer();
@ -37,7 +37,6 @@ namespace verus
static const int s_ringBufferSize = 3;
static BaseRenderer* Load(CSZ dll, RBaseRendererDesc desc);
virtual void ReleaseMe() = 0;
void SetDesc(RBaseRendererDesc desc) { _desc = desc; }
@ -49,6 +48,8 @@ namespace verus
virtual void ImGuiInit(int renderPassID) = 0;
virtual void ImGuiRenderDrawData() = 0;
virtual void ResizeSwapChain() = 0;
// Which graphics API?
virtual Gapi GetGapi() = 0;
@ -56,7 +57,6 @@ namespace verus
virtual void BeginFrame(bool present = true) = 0;
virtual void EndFrame(bool present = true) = 0;
virtual void Present() = 0;
virtual void WaitIdle() = 0;
// Resources:

View File

@ -62,6 +62,7 @@ namespace verus
int capacity = 1, std::initializer_list<Sampler> il = {}, ShaderStageFlags stageFlags = ShaderStageFlags::vs_fs) = 0;
virtual void CreatePipelineLayout() = 0;
virtual int BindDescriptorSetTextures(int setNumber, std::initializer_list<TexturePtr> il, const int* pMips = nullptr) = 0;
virtual void FreeDescriptorSet(int complexSetID) = 0;
virtual void BeginBindDescriptors() = 0;
virtual void EndBindDescriptors() = 0;

View File

@ -34,7 +34,7 @@ void DebugDraw::Init()
geoDesc._pInputElementDesc = ied;
const int strides[] = { sizeof(Vertex), 0 };
geoDesc._pStrides = strides;
geoDesc._dynamic = true;
geoDesc._dynBindingsMask = 0x1;
_geo.Init(geoDesc);
_geo->CreateVertexBuffer(_maxNumVert, 0);
@ -44,7 +44,7 @@ void DebugDraw::Init()
{
PipelineDesc pipeDesc(_geo, _shader, "#", renderer.GetRenderPass_SwapChainDepth());
pipeDesc._rasterizationState._polygonMode = PolygonMode::line;
pipeDesc._colorAttachBlendEqs[0] = VERUS_COLOR_BLEND_ALPHA;
pipeDesc._topology = PrimitiveTopology::pointList;
_pipe[PIPE_POINTS].Init(pipeDesc);
pipeDesc._depthTestEnable = false;
@ -52,7 +52,7 @@ void DebugDraw::Init()
}
{
PipelineDesc pipeDesc(_geo, _shader, "#", renderer.GetRenderPass_SwapChainDepth());
pipeDesc._rasterizationState._polygonMode = PolygonMode::line;
pipeDesc._colorAttachBlendEqs[0] = VERUS_COLOR_BLEND_ALPHA;
pipeDesc._topology = PrimitiveTopology::lineList;
_pipe[PIPE_LINES].Init(pipeDesc);
pipeDesc._depthTestEnable = false;
@ -60,6 +60,7 @@ void DebugDraw::Init()
}
{
PipelineDesc pipeDesc(_geo, _shader, "#", renderer.GetRenderPass_SwapChainDepth());
pipeDesc._colorAttachBlendEqs[0] = VERUS_COLOR_BLEND_ALPHA;
pipeDesc._rasterizationState._polygonMode = PolygonMode::line;
pipeDesc._topology = PrimitiveTopology::triangleList;
_pipe[PIPE_POLY].Init(pipeDesc);
@ -114,11 +115,13 @@ void DebugDraw::Begin(Type type, PcTransform3 pMat, bool zEnable)
void DebugDraw::End()
{
if (!_numVert)
return;
VERUS_QREF_RENDERER;
_geo->UpdateVertexBuffer(_vDynamicBuffer.data(), 0);
renderer.GetCommandBuffer()->Draw(_numVert, 1, _offset);
_offset = _numVert;
_offset += _numVert;
_numVert = 0;
}

View File

@ -41,7 +41,7 @@ namespace verus
PipelinePwns<PIPE_MAX> _pipe;
Vector<Vertex> _vDynamicBuffer;
UINT64 _currentFrame = UINT64_MAX;
const int _maxNumVert = 4096;
const int _maxNumVert = 0x10000;
int _numVert = 0;
int _offset = 0;
int _peakLoad = 0;

View File

@ -103,100 +103,59 @@ void DeferredShading::Init()
_pipe[PIPE_QUAD].Init(pipeDesc);
}
InitGBuffers(settings._screenSizeWidth, settings._screenSizeHeight);
TextureDesc texDesc;
// Light accumulation buffers:
texDesc._format = Format::unormR10G10B10A2;
texDesc._width = settings._screenSizeWidth;
texDesc._height = settings._screenSizeHeight;
texDesc._flags = TextureDesc::Flags::colorAttachment;
_tex[TEX_LIGHT_ACC_DIFF].Init(texDesc);
texDesc._format = Format::unormR10G10B10A2;
texDesc._width = settings._screenSizeWidth;
texDesc._height = settings._screenSizeHeight;
texDesc._flags = TextureDesc::Flags::colorAttachment;
_tex[TEX_LIGHT_ACC_SPEC].Init(texDesc);
_fb = renderer->CreateFramebuffer(_rp,
{
_tex[TEX_GBUFFER_0],
_tex[TEX_GBUFFER_1],
_tex[TEX_GBUFFER_2],
_tex[TEX_GBUFFER_3],
_tex[TEX_LIGHT_ACC_DIFF],
_tex[TEX_LIGHT_ACC_SPEC],
renderer.GetTexDepthStencil()
},
settings._screenSizeWidth,
settings._screenSizeHeight);
_csidCompose = _shader[S_COMPOSE]->BindDescriptorSetTextures(1,
{
_tex[TEX_GBUFFER_0],
_tex[TEX_GBUFFER_1],
_tex[TEX_GBUFFER_2],
_tex[TEX_GBUFFER_3],
_tex[TEX_LIGHT_ACC_DIFF],
_tex[TEX_LIGHT_ACC_SPEC]
});
VERUS_FOR(i, VERUS_ARRAY_LENGTH(_csidQuad))
_csidQuad[i] = renderer.GetShaderQuad()->BindDescriptorSetTextures(1, { _tex[TEX_GBUFFER_0 + i] });
OnSwapChainResized(true, false);
VERUS_LOG_INFO("</DeferredShadingInit>");
}
void DeferredShading::InitGBuffers(int w, int h)
{
_width = w;
_height = h;
TextureDesc texDesc;
// GB0:
texDesc._clearValue = Vector4(0, 0, 0, 1);
texDesc._format = Format::srgbR8G8B8A8;
texDesc._width = _width;
texDesc._height = _height;
texDesc._width = w;
texDesc._height = h;
texDesc._flags = TextureDesc::Flags::colorAttachment | TextureDesc::Flags::inputAttachment;
_tex[TEX_GBUFFER_0].Init(texDesc);
// GB1:
texDesc._clearValue = Vector4(1);
texDesc._format = Format::floatR32;
texDesc._width = _width;
texDesc._height = _height;
texDesc._width = w;
texDesc._height = h;
texDesc._flags = TextureDesc::Flags::colorAttachment | TextureDesc::Flags::inputAttachment;
_tex[TEX_GBUFFER_1].Init(texDesc);
// GB2:
texDesc._clearValue = Vector4(0.5f, 0.5f, 0.5f, 0.5f);
texDesc._clearValue = Vector4(0.5f, 0.5f, 0.25f, 0.5f);
texDesc._format = Format::unormR10G10B10A2;
texDesc._width = _width;
texDesc._height = _height;
texDesc._width = w;
texDesc._height = h;
texDesc._flags = TextureDesc::Flags::colorAttachment | TextureDesc::Flags::inputAttachment;
_tex[TEX_GBUFFER_2].Init(texDesc);
// GB3:
texDesc._clearValue = Vector4(1, 1, 1, 1);
texDesc._format = Format::unormR8G8B8A8;
texDesc._width = _width;
texDesc._height = _height;
texDesc._width = w;
texDesc._height = h;
texDesc._flags = TextureDesc::Flags::colorAttachment | TextureDesc::Flags::inputAttachment;
_tex[TEX_GBUFFER_3].Init(texDesc);
}
void DeferredShading::InitByAtmosphere(TexturePtr texShadow)
{
_texShadowAtmo = texShadow;
_csidLight = _shader[S_LIGHT]->BindDescriptorSetTextures(1,
{
_tex[TEX_GBUFFER_0],
_tex[TEX_GBUFFER_1],
_tex[TEX_GBUFFER_2],
_tex[TEX_GBUFFER_3],
texShadow,
texShadow
_texShadowAtmo,
_texShadowAtmo
});
}
@ -205,6 +164,76 @@ void DeferredShading::Done()
VERUS_DONE(DeferredShading);
}
void DeferredShading::OnSwapChainResized(bool init, bool done)
{
VERUS_QREF_RENDERER;
if (done)
{
_shader[S_LIGHT]->FreeDescriptorSet(_csidLight);
VERUS_FOR(i, VERUS_ARRAY_LENGTH(_csidQuad))
renderer.GetShaderQuad()->FreeDescriptorSet(_csidQuad[i]);
_shader[S_COMPOSE]->FreeDescriptorSet(_csidCompose);
renderer->DeleteFramebuffer(_fb);
_tex[TEX_LIGHT_ACC_SPEC].Done();
_tex[TEX_LIGHT_ACC_DIFF].Done();
_tex[TEX_GBUFFER_3].Done();
_tex[TEX_GBUFFER_2].Done();
_tex[TEX_GBUFFER_1].Done();
_tex[TEX_GBUFFER_0].Done();
}
if (init)
{
InitGBuffers(renderer.GetSwapChainWidth(), renderer.GetSwapChainHeight());
TextureDesc texDesc;
// Light accumulation buffers:
texDesc._format = Format::unormR10G10B10A2;
texDesc._width = renderer.GetSwapChainWidth();
texDesc._height = renderer.GetSwapChainHeight();
texDesc._flags = TextureDesc::Flags::colorAttachment;
_tex[TEX_LIGHT_ACC_DIFF].Init(texDesc);
texDesc._format = Format::unormR10G10B10A2;
texDesc._width = renderer.GetSwapChainWidth();
texDesc._height = renderer.GetSwapChainHeight();
texDesc._flags = TextureDesc::Flags::colorAttachment;
_tex[TEX_LIGHT_ACC_SPEC].Init(texDesc);
_fb = renderer->CreateFramebuffer(_rp,
{
_tex[TEX_GBUFFER_0],
_tex[TEX_GBUFFER_1],
_tex[TEX_GBUFFER_2],
_tex[TEX_GBUFFER_3],
_tex[TEX_LIGHT_ACC_DIFF],
_tex[TEX_LIGHT_ACC_SPEC],
renderer.GetTexDepthStencil()
},
renderer.GetSwapChainWidth(),
renderer.GetSwapChainHeight());
_csidCompose = _shader[S_COMPOSE]->BindDescriptorSetTextures(1,
{
_tex[TEX_GBUFFER_0],
_tex[TEX_GBUFFER_1],
_tex[TEX_GBUFFER_2],
_tex[TEX_GBUFFER_3],
_tex[TEX_LIGHT_ACC_DIFF],
_tex[TEX_LIGHT_ACC_SPEC]
});
VERUS_FOR(i, VERUS_ARRAY_LENGTH(_csidQuad))
_csidQuad[i] = renderer.GetShaderQuad()->BindDescriptorSetTextures(1, { _tex[TEX_GBUFFER_0 + i] });
if (_texShadowAtmo)
InitByAtmosphere(_texShadowAtmo);
}
}
bool DeferredShading::IsLoaded()
{
VERUS_QREF_HELPERS;
@ -308,6 +337,14 @@ void DeferredShading::EndGeometryPass(bool resetRT)
bool DeferredShading::BeginLightingPass()
{
VERUS_QREF_RENDERER;
VERUS_RT_ASSERT(renderer.GetNumFrames() == _frame);
VERUS_RT_ASSERT(!_activeGeometryPass && !_activeLightingPass);
_activeLightingPass = true;
renderer.GetCommandBuffer()->NextSubpass();
_shader[S_LIGHT]->BeginBindDescriptors();
if (!IsLoaded())
return false;
@ -348,15 +385,6 @@ bool DeferredShading::BeginLightingPass()
}
}
VERUS_QREF_RENDERER;
VERUS_RT_ASSERT(renderer.GetNumFrames() == _frame);
VERUS_RT_ASSERT(!_activeGeometryPass && !_activeLightingPass);
_activeLightingPass = true;
renderer.GetCommandBuffer()->NextSubpass();
_shader[S_LIGHT]->BeginBindDescriptors();
return true;
}
@ -371,7 +399,7 @@ void DeferredShading::EndLightingPass()
renderer.GetCommandBuffer()->EndRenderPass();
}
void DeferredShading::Compose()
void DeferredShading::Compose(RcVector4 bgColor)
{
VERUS_QREF_RENDERER;
VERUS_QREF_SM;
@ -383,6 +411,7 @@ void DeferredShading::Compose()
s_ubComposeVS._matV = Math::ToUVMatrix().UniformBufferFormat();
s_ubComposeFS._matInvV = sm.GetCamera()->GetMatrixVi().UniformBufferFormat();
s_ubComposeFS._colorAmbient = Vector4(0.1f, 0.1f, 0.2f, 1).GLM();
s_ubComposeFS._colorBackground = bgColor.GLM();
s_ubComposeFS._fogColor = Vector4(0.5f, 0.5f, 0.5f, 0.002f).GLM();
s_ubComposeFS._zNearFarEx = sm.GetCamera()->GetZNearFarEx().GLM();
renderer.GetCommandBuffer()->BindDescriptors(_shader[S_COMPOSE], 0);
@ -432,13 +461,12 @@ void DeferredShading::OnNewLightType(LightType type, bool wireframe)
renderer.GetCommandBuffer()->BindDescriptors(_shader[S_LIGHT], 1, _csidLight);
// Shadow:
if (atmo.GetSunShadowTexture())
s_ubShadowFS._shadowTexSize = atmo.GetSunShadowTexture()->GetSize().GLM();
s_ubShadowFS._matSunShadow = atmo.GetSunShadowMatrixDS(0).UniformBufferFormat();
s_ubShadowFS._matSunShadowCSM1 = atmo.GetSunShadowMatrixDS(1).UniformBufferFormat();
s_ubShadowFS._matSunShadowCSM2 = atmo.GetSunShadowMatrixDS(2).UniformBufferFormat();
s_ubShadowFS._matSunShadowCSM3 = atmo.GetSunShadowMatrixDS(3).UniformBufferFormat();
s_ubShadowFS._splitRanges = atmo.GetSunShadowSplitRanges().GLM();
s_ubShadowFS._matSunShadow = atmo.GetShadowMap().GetShadowMatrixDS(0).UniformBufferFormat();
s_ubShadowFS._matSunShadowCSM1 = atmo.GetShadowMap().GetShadowMatrixDS(1).UniformBufferFormat();
s_ubShadowFS._matSunShadowCSM2 = atmo.GetShadowMap().GetShadowMatrixDS(2).UniformBufferFormat();
s_ubShadowFS._matSunShadowCSM3 = atmo.GetShadowMap().GetShadowMatrixDS(3).UniformBufferFormat();
s_ubShadowFS._shadowConfig = atmo.GetShadowMap().GetConfig().GLM();
s_ubShadowFS._splitRanges = atmo.GetShadowMap().GetSplitRanges().GLM();
renderer.GetCommandBuffer()->BindDescriptors(_shader[S_LIGHT], 3);
}

View File

@ -56,9 +56,8 @@ namespace verus
ShaderPwns<S_MAX> _shader;
PipelinePwns<PIPE_MAX> _pipe;
TexturePwns<TEX_MAX> _tex;
TexturePtr _texShadowAtmo;
UINT64 _frame = 0;
int _width = 0;
int _height = 0;
int _rp = -1;
int _fb = -1;
int _csidLight = -1;
@ -77,13 +76,12 @@ namespace verus
void InitByAtmosphere(TexturePtr texShadow);
void Done();
void OnSwapChainResized(bool init, bool done);
static bool IsLoaded();
void Draw(int gbuffer);
int GetWidth() const { return _width; }
int GetHeight() const { return _height; }
bool IsActiveGeometryPass() const { return _activeGeometryPass; }
bool IsActiveLightingPass() const { return _activeLightingPass; }
@ -93,7 +91,7 @@ namespace verus
void EndGeometryPass(bool resetRT = false);
bool BeginLightingPass();
void EndLightingPass();
void Compose();
void Compose(RcVector4 bgColor = Vector4(0));
void AntiAliasing();
static bool IsLightUrl(CSZ url);

View File

@ -28,6 +28,9 @@ void Renderer::Init(PRendererDelegate pDelegate)
VERUS_INIT();
VERUS_QREF_CONST_SETTINGS;
_swapChainWidth = settings._screenSizeWidth;
_swapChainHeight = settings._screenSizeHeight;
_pRendererDelegate = pDelegate;
CSZ dll = "RendererVulkan.dll";
@ -73,13 +76,6 @@ void Renderer::Init(PRendererDelegate pDelegate)
PipelineDesc pipeDesc(_shader[S_GENERATE_MIPS], "#");
_pipeGenerateMips.Init(pipeDesc);
TextureDesc texDesc;
texDesc._clearValue = Vector4(1);
texDesc._format = Format::unormD24uintS8;
texDesc._width = settings._screenSizeWidth;
texDesc._height = settings._screenSizeHeight;
_texDepthStencil.Init(texDesc);
_rpSwapChain = _pBaseRenderer->CreateRenderPass(
{ RP::Attachment("Color", Format::srgbB8G8R8A8).LoadOpClear().Layout(ImageLayout::undefined, ImageLayout::presentSrc) },
{ RP::Subpass("Sp0").Color({RP::Ref("Color", ImageLayout::colorAttachment)}) },
@ -96,14 +92,11 @@ void Renderer::Init(PRendererDelegate pDelegate)
}).DepthStencil(RP::Ref("Depth", ImageLayout::depthStencilAttachment)),
},
{});
_fbSwapChain.resize(_pBaseRenderer->GetNumSwapChainBuffers());
VERUS_FOR(i, _fbSwapChain.size())
_fbSwapChain[i] = _pBaseRenderer->CreateFramebuffer(_rpSwapChain, {}, settings._screenSizeWidth, settings._screenSizeHeight, i);
_fbSwapChainDepth.resize(_pBaseRenderer->GetNumSwapChainBuffers());
VERUS_FOR(i, _fbSwapChainDepth.size())
_fbSwapChainDepth[i] = _pBaseRenderer->CreateFramebuffer(_rpSwapChainDepth, { _texDepthStencil }, settings._screenSizeWidth, settings._screenSizeHeight, i);
OnSwapChainResized(true, false);
_pBaseRenderer->ImGuiInit(_rpSwapChainDepth);
ImGuiUpdateStyle();
_ds.Init();
}
@ -161,6 +154,48 @@ void Renderer::Present()
_fps = _fps * 0.75f + timer.GetDeltaTimeInv() * 0.25f;
}
void Renderer::OnWindowResized(int w, int h)
{
_pBaseRenderer->WaitIdle();
_swapChainWidth = w;
_swapChainHeight = h;
_pBaseRenderer->ResizeSwapChain();
OnSwapChainResized(true, true);
_ds.OnSwapChainResized(true, true);
}
void Renderer::OnSwapChainResized(bool init, bool done)
{
if (done)
{
VERUS_FOR(i, _fbSwapChainDepth.size())
_pBaseRenderer->DeleteFramebuffer(_fbSwapChainDepth[i]);
VERUS_FOR(i, _fbSwapChain.size())
_pBaseRenderer->DeleteFramebuffer(_fbSwapChain[i]);
_texDepthStencil.Done();
}
if (init)
{
TextureDesc texDesc;
texDesc._clearValue = Vector4(1);
texDesc._format = Format::unormD24uintS8;
texDesc._width = _swapChainWidth;
texDesc._height = _swapChainHeight;
_texDepthStencil.Init(texDesc);
_fbSwapChain.resize(_pBaseRenderer->GetNumSwapChainBuffers());
VERUS_FOR(i, _fbSwapChain.size())
_fbSwapChain[i] = _pBaseRenderer->CreateFramebuffer(_rpSwapChain, {}, _swapChainWidth, _swapChainHeight, i);
_fbSwapChainDepth.resize(_pBaseRenderer->GetNumSwapChainBuffers());
VERUS_FOR(i, _fbSwapChainDepth.size())
_fbSwapChainDepth[i] = _pBaseRenderer->CreateFramebuffer(_rpSwapChainDepth, { _texDepthStencil }, _swapChainWidth, _swapChainHeight, i);
}
}
void Renderer::DrawQuad(PBaseCommandBuffer pCB)
{
if (!pCB)
@ -182,10 +217,79 @@ void Renderer::OnShaderWarning(CSZ s)
float Renderer::GetWindowAspectRatio() const
{
VERUS_QREF_CONST_SETTINGS;
return static_cast<float>(settings._screenSizeWidth) / static_cast<float>(settings._screenSizeHeight);
return static_cast<float>(_swapChainWidth) / static_cast<float>(_swapChainHeight);
}
void Renderer::ImGuiSetCurrentContext(ImGuiContext* pContext)
{
ImGui::SetCurrentContext(pContext);
}
void Renderer::ImGuiUpdateStyle()
{
ImGuiStyle& style = ImGui::GetStyle();
style.WindowRounding = 4;
style.WindowTitleAlign.x = 0.5f;
style.ChildRounding = 2;
style.PopupRounding = 2;
style.FramePadding.y = 4;
style.FrameRounding = 2;
style.FrameBorderSize = 1;
style.ScrollbarSize = 16;
style.ScrollbarRounding = 2;
style.GrabMinSize = 12;
style.GrabRounding = 2;
style.TabRounding = 0;
style.TabBorderSize = 1;
ImVec4* colors = style.Colors;
colors[ImGuiCol_Text] = ImVec4(0.82f, 0.82f, 0.82f, 1.00f);
colors[ImGuiCol_TextDisabled] = ImVec4(0.39f, 0.39f, 0.39f, 1.00f);
colors[ImGuiCol_WindowBg] = ImVec4(0.02f, 0.02f, 0.02f, 0.99f);
colors[ImGuiCol_ChildBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.50f);
colors[ImGuiCol_PopupBg] = ImVec4(0.02f, 0.02f, 0.02f, 0.99f);
colors[ImGuiCol_Border] = ImVec4(0.05f, 0.05f, 0.05f, 1.00f);
colors[ImGuiCol_BorderShadow] = ImVec4(0.05f, 0.05f, 0.05f, 0.08f);
colors[ImGuiCol_FrameBg] = ImVec4(0.01f, 0.01f, 0.01f, 1.00f);
colors[ImGuiCol_FrameBgHovered] = ImVec4(0.02f, 0.02f, 0.02f, 1.00f);
colors[ImGuiCol_FrameBgActive] = ImVec4(0.05f, 0.05f, 0.05f, 1.00f);
colors[ImGuiCol_TitleBg] = ImVec4(0.01f, 0.01f, 0.01f, 1.00f);
colors[ImGuiCol_TitleBgActive] = ImVec4(0.19f, 0.03f, 0.00f, 1.00f);
colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.01f, 0.01f, 0.01f, 1.00f);
colors[ImGuiCol_MenuBarBg] = ImVec4(0.01f, 0.01f, 0.01f, 1.00f);
colors[ImGuiCol_ScrollbarBg] = ImVec4(0.02f, 0.02f, 0.02f, 1.00f);
colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.05f, 0.05f, 0.05f, 1.00f);
colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.09f, 0.09f, 0.09f, 1.00f);
colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.92f, 0.43f, 0.02f, 1.00f);
colors[ImGuiCol_CheckMark] = ImVec4(0.92f, 0.43f, 0.02f, 1.00f);
colors[ImGuiCol_SliderGrab] = ImVec4(0.09f, 0.09f, 0.09f, 1.00f);
colors[ImGuiCol_SliderGrabActive] = ImVec4(0.92f, 0.43f, 0.02f, 1.00f);
colors[ImGuiCol_Button] = ImVec4(0.05f, 0.05f, 0.05f, 1.00f);
colors[ImGuiCol_ButtonHovered] = ImVec4(1.00f, 1.00f, 1.00f, 0.13f);
colors[ImGuiCol_ButtonActive] = ImVec4(1.00f, 1.00f, 1.00f, 0.25f);
colors[ImGuiCol_Header] = ImVec4(0.05f, 0.05f, 0.05f, 1.00f);
colors[ImGuiCol_HeaderHovered] = ImVec4(0.09f, 0.09f, 0.09f, 1.00f);
colors[ImGuiCol_HeaderActive] = ImVec4(0.19f, 0.19f, 0.19f, 1.00f);
colors[ImGuiCol_Separator] = ImVec4(0.05f, 0.05f, 0.05f, 1.00f);
colors[ImGuiCol_SeparatorHovered] = ImVec4(0.09f, 0.09f, 0.09f, 1.00f);
colors[ImGuiCol_SeparatorActive] = ImVec4(0.89f, 0.13f, 0.00f, 1.00f);
colors[ImGuiCol_ResizeGrip] = ImVec4(0.05f, 0.05f, 0.05f, 1.00f);
colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.09f, 0.09f, 0.09f, 1.00f);
colors[ImGuiCol_ResizeGripActive] = ImVec4(0.89f, 0.13f, 0.00f, 1.00f);
colors[ImGuiCol_Tab] = ImVec4(0.02f, 0.02f, 0.02f, 1.00f);
colors[ImGuiCol_TabHovered] = ImVec4(0.89f, 0.13f, 0.00f, 1.00f);
colors[ImGuiCol_TabActive] = ImVec4(0.19f, 0.03f, 0.00f, 1.00f);
colors[ImGuiCol_TabUnfocused] = ImVec4(0.01f, 0.01f, 0.01f, 1.00f);
colors[ImGuiCol_TabUnfocusedActive] = ImVec4(0.05f, 0.05f, 0.05f, 1.00f);
colors[ImGuiCol_PlotLines] = ImVec4(0.39f, 0.39f, 0.39f, 1.00f);
colors[ImGuiCol_PlotLinesHovered] = ImVec4(0.89f, 0.13f, 0.00f, 1.00f);
colors[ImGuiCol_PlotHistogram] = ImVec4(0.39f, 0.39f, 0.39f, 1.00f);
colors[ImGuiCol_PlotHistogramHovered] = ImVec4(0.89f, 0.13f, 0.00f, 1.00f);
colors[ImGuiCol_TextSelectedBg] = ImVec4(1.00f, 1.00f, 1.00f, 0.06f);
colors[ImGuiCol_DragDropTarget] = ImVec4(0.89f, 0.13f, 0.00f, 1.00f);
colors[ImGuiCol_NavHighlight] = ImVec4(0.89f, 0.13f, 0.00f, 1.00f);
colors[ImGuiCol_NavWindowingHighlight] = ImVec4(0.89f, 0.13f, 0.00f, 1.00f);
colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.50f);
colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.50f);
}

View File

@ -41,6 +41,8 @@ namespace verus
DeferredShading _ds;
UINT64 _numFrames = 0;
Gapi _gapi = Gapi::unknown;
int _swapChainWidth = 0;
int _swapChainHeight = 0;
float _fps = 30;
int _rpSwapChain = 0;
int _rpSwapChainDepth = 0;
@ -66,6 +68,11 @@ namespace verus
void Draw();
void Present();
void OnWindowResized(int w, int h);
VERUS_P(void OnSwapChainResized(bool init, bool done));
int GetSwapChainWidth() const { return _swapChainWidth; }
int GetSwapChainHeight() const { return _swapChainHeight; }
// Simple (fullscreen) quad:
void DrawQuad(PBaseCommandBuffer pCB = nullptr);
@ -82,6 +89,7 @@ namespace verus
float GetWindowAspectRatio() const;
virtual void ImGuiSetCurrentContext(ImGuiContext* pContext);
void ImGuiUpdateStyle();
// Frame rate:
float GetFps() const { return _fps; }

View File

@ -16,7 +16,7 @@ int RendererParser::Expect(CSZ& p, CSZ* ppOptions)
CSZ option = ppOptions[index];
while (option)
{
size_t len = strlen(option);
const size_t len = strlen(option);
if (!strncmp(p, option, len))
{
p += len;

View File

@ -47,7 +47,6 @@ namespace verus
float _depthBiasConstantFactor = 0;
float _depthBiasClamp = 0;
float _depthBiasSlopeFactor = 0;
float _lineWidth = 1;
bool _depthClampEnable = false;
bool _depthBiasEnable = false;
bool _rasterizerDiscardEnable = false;

View File

@ -1,5 +1,7 @@
#pragma once
#define VERUS_DEBUG
#include "AssertionRunTime.h"
#include "AssertionCompileTime.h"
#include "RuntimeError.h"

View File

@ -5,79 +5,14 @@ using namespace verus::D;
std::mutex D::Log::s_mutex;
void Log::Error(CSZ txt, std::thread::id tid, CSZ filename, UINT32 line)
{
std::lock_guard<std::mutex> lock(s_mutex);
const time_t t = time(0);
const tm* pTM = localtime(&t);
char timestamp[80];
strftime(timestamp, sizeof(timestamp), "%Y.%m.%d %H:%M:%S", pTM);
CSZ p = strrchr(filename, '/');
if (!p)
p = strrchr(filename, '\\');
filename = p ? p + 1 : filename;
String pathName;
//if (Global::IsValidSingleton())
//{
// pathName = Global::I().GetWritablePath() + "/Errors.txt";
//}
//else
{
String temp = getenv("TEMP");
pathName = temp + "/CorrErrors.txt";
}
IO::File file;
if (file.Open(_C(pathName), "a"))
{
if (file.GetSize() > 100 * 1024)
{
file.Close();
file.Open(_C(pathName), "w");
}
StringStream ss;
ss << timestamp << " " << tid << " " << filename << ":" << line << " ERROR: " << txt << "\n";
file.Write(_C(ss.str()), ss.str().length());
}
}
void Log::Session(CSZ txt)
{
/*
std::lock_guard<std::mutex> lock(s_mutex);
String pathName(Global::I().GetWritablePath());
pathName += "/SessionLog.txt";
IO::File file;
if (file.Create(_C(pathName), "a"))
{
StringStream ss;
ss.fill('0');
ss << '[';
ss.width(8);
ss << SDL_GetTicks() << "ms] " << txt << "\n";
file.Write(_C(ss.str()), ss.str().length());
}
*/
}
void Log::DebugString(CSZ txt)
{
/*
StringStream ss;
ss << verus::Global::GetNextCounterValue() << ": " << txt << "\n";
#ifdef _WIN32
OutputDebugStringA(_C(ss.str()));
#endif
*/
}
void Log::Write(CSZ txt, std::thread::id tid, CSZ filename, UINT32 line, Severity severity)
{
#ifdef _DEBUG
if (severity <= Severity::error)
{
SDL_TriggerBreakpoint();
}
#endif
char timestamp[40];
FormatTime(timestamp, sizeof(timestamp));
CSZ severityLetter = GetSeverityLetter(severity);

View File

@ -1,15 +1,5 @@
#pragma once
//#define VERUS_LOG_ERROR(txt) {verus::D::Log::Error(txt, std::this_thread::get_id(), __FILE__, __LINE__);}
//#define VERUS_LOG_ERROR_STREAM(txt) {StringStream ss; ss << txt; verus::D::Log::Error(_C(ss.str()), std::this_thread::get_id(), __FILE__, __LINE__);}
//#define VERUS_LOG_SESSION(txt) {verus::D::Log::Session(txt);}
//#define VERUS_LOG_SESSION_STREAM(txt) {StringStream ss; ss << txt; verus::D::Log::Session(_C(ss.str()));}
//#ifdef _DEBUG
//# define VERUS_LOG_DEBUG(x) {verus::D::Log::DebugString(x);}
//#else
//# define VERUS_LOG_DEBUG(x) {}
//#endif
#define VERUS_LOG_ERROR(txt) {StringStream ss; ss << txt; D::Log::I().Write(_C(ss.str()), std::this_thread::get_id(), __FILE__, __LINE__, D::Log::Severity::error);}
#define VERUS_LOG_WARN(txt) {StringStream ss; ss << txt; D::Log::I().Write(_C(ss.str()), std::this_thread::get_id(), __FILE__, __LINE__, D::Log::Severity::warning);}
#define VERUS_LOG_INFO(txt) {StringStream ss; ss << txt; D::Log::I().Write(_C(ss.str()), std::this_thread::get_id(), __FILE__, __LINE__, D::Log::Severity::info);}
@ -34,10 +24,6 @@ namespace verus
static std::mutex s_mutex;
public:
static void Error(CSZ txt, std::thread::id tid, CSZ filename, UINT32 line);
static void Session(CSZ txt);
static void DebugString(CSZ txt);
void Write(CSZ txt, std::thread::id tid, CSZ filename, UINT32 line, Severity severity);
static void FormatTime(char* buffer, size_t size);

13
Verus/src/Extra/Extra.cpp Normal file
View File

@ -0,0 +1,13 @@
#include "verus.h"
namespace verus
{
void Make_Extra()
{
Extra::FileParser::Make();
}
void Free_Extra()
{
Extra::FileParser::Free();
}
}

9
Verus/src/Extra/Extra.h Normal file
View File

@ -0,0 +1,9 @@
#pragma once
#include "FileParser.h"
namespace verus
{
void Make_Extra();
void Free_Extra();
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,332 @@
#pragma once
namespace verus
{
namespace Extra
{
struct FileParserDelegate;
class FileParser : public Singleton<FileParser>, public Object
{
public:
class Mesh
{
public:
enum class Found : int
{
null = 0,
faces = (1 << 0),
vertsAndUVs = (1 << 1),
normals = (1 << 2),
boneHierarchy = (1 << 3),
skinning = (1 << 4),
tangentSpace = (1 << 5),
texcoordExtra = (1 << 6)
};
struct UberVertex
{
glm::vec3 _pos;
glm::vec3 _nrm;
glm::vec2 _tc0;
glm::vec2 _tc1;
glm::vec3 _tan;
glm::vec3 _bin;
float _bw[4];
UINT32 _bi[4];
int _currentWeight = 0;
UberVertex();
bool operator==(const UberVertex& that) const;
void Add(float weight, UINT32 index);
void CompileBits(UINT32& ww, UINT32& ii) const;
UINT32 GetDominantIndex();
};
VERUS_TYPEDEFS(UberVertex);
struct Face
{
UINT16 _indices[3];
};
VERUS_TYPEDEFS(Face);
struct Bone
{
String _name;
String _parentName;
glm::mat4 _matOffset;
glm::mat4 _matFrame;
glm::mat4 _matFrameAcc;
};
VERUS_TYPEDEFS(Bone);
private:
struct Vec3Short
{
short _x;
short _y;
short _z;
};
struct Vec2Short
{
short _u;
short _v;
};
struct Vec3Char
{
char _x;
char _y;
char _z;
};
struct Aabb
{
glm::vec3 _mn = glm::vec3(+FLT_MAX);
glm::vec3 _mx = glm::vec3(-FLT_MAX);
void Reset();
void Include(const glm::vec3& point);
glm::vec3 GetExtents() const;
};
String _name;
String _copyOf;
Vector<UberVertex> _vUberVerts;
Vector<Face> _vFaces;
Vector<Vec3Short> _vZipPos;
Vector<Vec3Char> _vZipNormal;
Vector<Vec3Char> _vZipTan;
Vector<Vec3Char> _vZipBin;
Vector<Vec2Short> _vZipTc0;
Vector<Vec2Short> _vZipTc1;
Vector<Bone> _vBones;
int _numVerts = 0;
int _numFaces = 0;
int _numBones = 0;
glm::vec3 _posScale;
glm::vec3 _posBias;
glm::vec2 _tc0Scale;
glm::vec2 _tc0Bias;
glm::vec2 _tc1Scale;
glm::vec2 _tc1Bias;
glm::mat4 _matBoneAxis;
glm::mat4 _matCombined;
glm::mat4 _worldSpace;
Found _found = Found::null;
int _materialIndex = 0;
public:
Mesh();
~Mesh();
PBone FindBone(CSZ name);
VERUS_P(void Optimize());
VERUS_P(void ComputeTangentSpace());
VERUS_P(void Compress());
void SerializeX3D3(IO::RFile file);
RcString GetName() const { return _name; }
void SetName(CSZ name) { _name = name; }
const glm::mat4& GetBoneAxisMatrix() const { return _matBoneAxis; }
const glm::mat4& GetCombinedMatrix() const { return _matCombined; }
void SetCombinedMatrix(const glm::mat4& mat) { _matCombined = mat; }
const glm::mat4& GetWorldSpaceMatrix() const { return _worldSpace; }
void SetWorldSpaceMatrix(const glm::mat4& mat) { _worldSpace = mat; }
int GetNumVerts() const { return _numVerts; }
int GetNumFaces() const { return _numFaces; }
int GetNumBones() const { return _numBones; }
void SetNumVerts(int num) { _numVerts = num; }
void SetNumFaces(int num) { _numFaces = num; }
void SetNumBones(int num) { _numBones = num; }
void ResizeVertsArray(int size) { _vUberVerts.resize(size); }
void ResizeFacesArray(int size) { _vFaces.resize(size); }
RUberVertex GetSetVertexAt(int index) { return _vUberVerts[index]; }
RFace GetSetFaceAt(int index) { return _vFaces[index]; }
void AddFoundFlag(Found flag) { _found |= flag; }
int GetNextBoneIndex() const { return _vBones.size(); }
void AddBone(RcBone bone) { _vBones.push_back(bone); }
bool IsCopyOf(Mesh& that);
bool IsCopy() const { return !_copyOf.empty(); }
RcString GetCopyOfName() const { return _copyOf; }
int GetMaterialIndex() const { return _materialIndex; }
void SetMaterialIndex(int index) { _materialIndex = index; }
};
VERUS_TYPEDEFS(Mesh);
struct Desc
{
glm::vec3 _bias = glm::vec3(0);
float _scaleFactor = 1;
float _angle = 0;
float _areaBasedNormals = 0;
bool _useRigidBones = false;
bool _convertAsLevel = false;
bool _useDefaultMaterial = false;
bool _rightHanded = true;
};
VERUS_TYPEDEFS(Desc);
private:
struct Frame
{
String _name;
String _parent;
glm::mat4 _mat;
glm::mat4 _matAcc;
};
VERUS_TYPEDEFS(Frame);
struct SubKey
{
Quat _q;
bool _redundant = false;
};
struct AnimationKey
{
Vector<SubKey> _vFrame;
int _type = 0;
int _numLogicFrames = 0;
void DetectRedundantFrames(float threshold = 0.001f);
};
struct Animation
{
String _name;
Vector<AnimationKey> _vAnimKeys;
};
struct AnimationSet
{
String _name;
Vector<Animation> _vAnimations;
void CleanUp();
};
struct Material
{
String _name;
String _copyOf;
String _textureFilename;
glm::vec4 _faceColor;
glm::vec3 _specularColor;
glm::vec3 _emissiveColor;
float _power = 1;
bool IsCopyOf(const Material& that)
{
const float e = 0.01f;
return
_textureFilename == that._textureFilename &&
glm::all(glm::epsilonEqual(_faceColor, that._faceColor, e)) &&
glm::all(glm::epsilonEqual(_specularColor, that._specularColor, e)) &&
glm::all(glm::epsilonEqual(_emissiveColor, that._emissiveColor, e)) &&
glm::epsilonEqual(_power, that._power, e);
}
};
VERUS_TYPEDEFS(Material);
typedef Map<String, String> TMapBoneNames;
typedef Map<String, Frame> TMapFrames;
Transform3 _matRoot;
TMapBoneNames _mapBoneNames;
String _currentMesh;
String _pathName;
Vector<char> _vData;
const char* _pData;
const char* _pDataBegin;
Vector<PMesh> _vMesh;
std::unique_ptr<Mesh> _pCurrentMesh;
TMapFrames _mapFrames;
Vector<Frame> _stackFrames;
Vector<AnimationSet> _vAnimSets;
Vector<Material> _vMaterials;
FileParserDelegate* _pDelegate;
std::future<void> _future;
Desc _desc;
int _depth = 0;
StringStream _ssDebug;
public:
FileParser();
~FileParser();
void Init(FileParserDelegate* p, RcDesc desc);
void Done();
void LoadBoneNames(CSZ pathName);
void ParseData(CSZ pathName);
void SerializeAll(CSZ pathName);
void AsyncRun(CSZ pathName);
void AsyncJoin();
bool IsAsyncStarted() const;
bool IsAsyncFinished() const;
private:
void LoadFromFile(CSZ pathName);
void StreamReadUntil(SZ dest, int destSize, CSZ separator);
void StreamSkipWhitespace();
void StreamSkipUntil(char c);
void FixBones();
void ParseBlockRecursive(CSZ type, CSZ blockName);
void ParseBlockData_Mesh();
void ParseBlockData_MeshTextureCoords();
void ParseBlockData_MeshNormals();
void ParseBlockData_FVFData(bool declData);
void ParseBlockData_XSkinMeshHeader();
void ParseBlockData_SkinWeights();
void ParseBlockData_Frame(CSZ blockName);
void ParseBlockData_FrameTransformMatrix();
void ParseBlockData_AnimationSet(CSZ blockName);
void ParseBlockData_Animation(CSZ blockName);
void ParseBlockData_AnimationKey();
void ParseBlockData_Material();
void ParseBlockData_TextureFilename();
void ParseBlockData_MeshMaterialList();
PMesh AddMesh(PMesh pMesh);
PMesh FindMesh(CSZ name);
void DeleteAll();
void OnProgress(float percent);
void OnProgressText(CSZ txt);
void Debug(CSZ txt);
void DetectMaterialCopies();
String GetXmlMaterial(int i);
String RenameBone(CSZ name);
};
VERUS_TYPEDEFS(FileParser);
struct FileParserDelegate
{
virtual void FileParser_OnProgress(float percent) = 0;
virtual void FileParser_OnProgressText(CSZ txt) = 0;
virtual void FileParser_Optimize(
Vector<FileParser::Mesh::UberVertex>& vVb,
Vector<FileParser::Mesh::Face>& vIb) = 0;
virtual bool FileParser_CanOverwriteFile(CSZ filename) { return true; }
};
}
}

View File

@ -12,11 +12,6 @@ struct MyRendererDelegate : CGI::RendererDelegate
virtual void Renderer_OnDraw() override
{
//VERUS_QREF_RENDERER;
//VERUS_QREF_TIMER;
//const float x = fmod(timer.GetTime(), 1.f);
//renderer.SetClearColor(Vector4(x, 0.5f, 0.25f, 1.f));
//renderer->Clear(0);
_p->BaseGame_Draw();
}
@ -42,11 +37,12 @@ struct BaseGame::Pimpl : AllocatorAware
PBaseGame _p = nullptr;
Scene::MainCamera _camera;
Spirit _cameraSpirit;
bool _bulletDebugDrawEnabled = false;
bool _defaultCameraMovement = true;
bool _showFPS = true;
bool _debugBullet = false;
bool _escapeKeyExitGame = true;
bool _minimized = false;
bool _rawInputEvents = false;
bool _showFPS = true;
Pimpl(PBaseGame p) : _p(p)
{
@ -55,15 +51,6 @@ struct BaseGame::Pimpl : AllocatorAware
~Pimpl()
{
}
bool HandleUserEvents(SDL_Event* pEvent)
{
switch (pEvent->user.code)
{
case 0: return true; // Exit.
}
return false;
}
};
BaseGame::BaseGame()
@ -83,7 +70,7 @@ BaseGame::~BaseGame()
//CGL::CRender::DoneWin32();
}
void BaseGame::Initialize(VERUS_MAIN_DEFAULT_ARGS)
void BaseGame::Initialize(VERUS_MAIN_DEFAULT_ARGS, App::Window::RcDesc desc)
{
VERUS_SDL_CENTERED;
@ -91,6 +78,7 @@ void BaseGame::Initialize(VERUS_MAIN_DEFAULT_ARGS)
VERUS_QREF_SETTINGS;
settings.ParseCommandLineArgs(argc, argv);
//settings.LoadValidateSave();
BaseGame_UpdateSettings();
const int ret = SDL_Init(SDL_INIT_EVERYTHING);
if (ret)
@ -103,15 +91,16 @@ void BaseGame::Initialize(VERUS_MAIN_DEFAULT_ARGS)
//Utils::TestAll();
#endif
_window.Init();
_window.Init(desc);
CGI::Renderer::I().SetMainWindow(&_window);
_engineInit.Init(this, new MyRendererDelegate(this));
// Configure:
VERUS_QREF_RENDERER;
//VERUS_QREF_SM;
VERUS_QREF_SM;
_p->_camera.SetAspectRatio(renderer.GetWindowAspectRatio());
//sm.SetCamera(&_p->_camera);
_p->_camera.Update();
sm.SetCamera(&_p->_camera);
renderer->BeginFrame(false); // Begin recording a command buffer.
renderer.InitCmd();
@ -119,22 +108,23 @@ void BaseGame::Initialize(VERUS_MAIN_DEFAULT_ARGS)
renderer->EndFrame(false); // End recording a command buffer.
}
void BaseGame::Run()
void BaseGame::Run(bool relativeMouseMode)
{
VERUS_QREF_TIMER;
VERUS_QREF_KM;
VERUS_QREF_BULLET;
VERUS_QREF_RENDERER;
VERUS_QREF_ASYNC;
VERUS_QREF_ASYS;
VERUS_QREF_BULLET;
VERUS_QREF_KM;
VERUS_QREF_RENDERER;
VERUS_QREF_SM;
VERUS_QREF_TIMER;
SDL_SetRelativeMouseMode(SDL_TRUE);
if (relativeMouseMode)
SDL_SetRelativeMouseMode(SDL_TRUE);
timer.Update();
SDL_Event event;
bool done = false;
bool quit = false;
do // The Game Loop.
{
@ -144,37 +134,73 @@ void BaseGame::Run()
while (SDL_PollEvent(&event))
{
ImGui_ImplSDL2_ProcessEvent(&event);
if (_p->_rawInputEvents && !ImGui::GetIO().WantCaptureMouse)
{
switch (event.type)
{
case SDL_MOUSEMOTION:
{
BaseGame_SDL_OnMouseMotion(event.motion.xrel, event.motion.yrel);
}
break;
case SDL_MOUSEBUTTONDOWN:
{
if (1 == event.button.clicks)
BaseGame_SDL_OnMouseButtonDown(event.button.button);
else if (2 == event.button.clicks)
BaseGame_SDL_OnMouseDoubleClick(event.button.button);
}
break;
case SDL_MOUSEBUTTONUP:
{
if (1 == event.button.clicks)
BaseGame_SDL_OnMouseButtonUp(event.button.button);
}
break;
case SDL_MOUSEWHEEL:
{
BaseGame_SDL_OnMouseWheel(event.wheel.y);
}
break;
}
}
if (!km.HandleSdlEvent(event))
{
switch (event.type)
{
case SDL_QUIT:
{
done = true;
if (BaseGame_CanQuitEventLoop())
quit = true;
}
break;
case SDL_WINDOWEVENT:
{
switch (event.window.event)
{
case SDL_WINDOWEVENT_RESIZED:
{
renderer.OnWindowResized(event.window.data1, event.window.data2);
sm.GetCamera()->SetAspectRatio(renderer.GetWindowAspectRatio());
sm.GetCamera()->Update();
BaseGame_OnWindowResized();
}
break;
case SDL_WINDOWEVENT_MINIMIZED:
{
_p->_minimized = true;
BaseGame_OnDeactivated();
renderer->WaitIdle();
break;
}
break;
case SDL_WINDOWEVENT_RESTORED:
{
_p->_minimized = false;
BaseGame_OnActivated();
break;
}
}
break;
case SDL_USEREVENT:
{
if (_p->HandleUserEvents(&event))
{
SDL_Delay(100);
done = true;
break;
}
}
break;
@ -185,7 +211,7 @@ void BaseGame::Run()
if (_p->_minimized)
continue;
if (done)
if (quit)
break;
//
@ -227,8 +253,8 @@ void BaseGame::Run()
// _p->_camera.ExcludeWaterLine();
}
_p->_camera.Update();
sm.SetCamera(&_p->_camera);
}
sm.SetCamera(&_p->_camera);
BaseGame_Update();
@ -253,20 +279,24 @@ void BaseGame::Run()
sprintf_s(title, "[%s] - %.1f FPS", gapi, renderer.GetFps());
SDL_SetWindowTitle(renderer.GetMainWindow()->GetSDL(), title);
}
} while (!done); // The Game Loop.
} while (!quit); // The Game Loop.
BaseGame_UnloadContent();
SDL_SetRelativeMouseMode(SDL_FALSE);
if (relativeMouseMode)
SDL_SetRelativeMouseMode(SDL_FALSE);
}
void BaseGame::Exit()
{
Utils::ExitSdlLoop();
Utils::PushQuitEvent();
}
void BaseGame::KeyMapper_OnMouseMove(int x, int y)
{
if (!SDL_GetRelativeMouseMode())
return;
VERUS_QREF_CONST_SETTINGS;
const float rad = (VERUS_2PI / 360.f) / 3.f; // 3 pixels = 1 degree.
@ -303,22 +333,43 @@ RSpirit BaseGame::GetCameraSpirit()
return _p->_cameraSpirit;
}
void BaseGame::ActivateDefaultCameraMovement(bool b)
void BaseGame::EnableBulletDebugDraw(bool b)
{
_p->_bulletDebugDrawEnabled = b;
}
void BaseGame::EnableDefaultCameraMovement(bool b)
{
_p->_defaultCameraMovement = b;
}
void BaseGame::EnableEscapeKeyExitGame(bool b)
{
_p->_escapeKeyExitGame = b;
}
void BaseGame::EnableRawInputEvents(bool b)
{
_p->_rawInputEvents = b;
}
void BaseGame::ShowFPS(bool b)
{
_p->_showFPS = b;
}
void BaseGame::DebugBullet(bool b)
bool BaseGame::IsBulletDebugDrawEnabled() const
{
_p->_debugBullet = b;
return _p->_bulletDebugDrawEnabled;
}
bool BaseGame::IsDebugBulletMode() const
void BaseGame::BulletDebugDraw()
{
return _p->_debugBullet;
#ifdef VERUS_DEBUG
if (_p->_bulletDebugDrawEnabled)
{
VERUS_QREF_BULLET;
bullet.DebugDraw();
}
#endif
}

View File

@ -16,35 +16,53 @@ namespace verus
BaseGame();
~BaseGame();
void Initialize(VERUS_MAIN_DEFAULT_ARGS);
void Run();
void Initialize(VERUS_MAIN_DEFAULT_ARGS, App::Window::RcDesc desc = App::Window::Desc());
void Run(bool relativeMouseMode = true);
void Exit();
virtual void BaseGame_UpdateSettings() {};
virtual void BaseGame_LoadContent() = 0;
virtual void BaseGame_UnloadContent() = 0;
virtual void BaseGame_HandleInput() = 0;
virtual void BaseGame_Update() = 0;
virtual void BaseGame_Draw() = 0;
virtual void BaseGame_DrawOverlay() = 0;
virtual void BaseGame_OnWindowResized() {}
virtual void BaseGame_OnActivated() {}
virtual void BaseGame_OnDeactivated() {}
virtual void BaseGame_OnMouseMove(float x, float y) {}
virtual void BaseGame_OnKey(int scancode) {}
virtual void BaseGame_OnChar(wchar_t c) {}
virtual bool BaseGame_CanQuitEventLoop() { return true; }
// Raw SDL events, for editor:
virtual void BaseGame_SDL_OnMouseMotion(int x, int y) {}
virtual void BaseGame_SDL_OnMouseButtonDown(int button) {}
virtual void BaseGame_SDL_OnMouseDoubleClick(int button) {}
virtual void BaseGame_SDL_OnMouseButtonUp(int button) {}
virtual void BaseGame_SDL_OnMouseWheel(int delta) {}
virtual void KeyMapper_OnMouseMove(int x, int y) override;
virtual void KeyMapper_OnKey(int scancode) override;
virtual void KeyMapper_OnChar(wchar_t c) override;
// Internal objects:
REngineInit GetEngineInit() { return _engineInit; }
App::RcWindow GetWindow() const { return _window; }
// Camera:
Scene::RCamera GetCamera();
RSpirit GetCameraSpirit();
// Configurations:
void ActivateDefaultCameraMovement(bool b);
// Configuration:
void EnableBulletDebugDraw(bool b);
void EnableDefaultCameraMovement(bool b);
void EnableEscapeKeyExitGame(bool b);
void EnableRawInputEvents(bool b);
void ShowFPS(bool b);
void DebugBullet(bool b);
bool IsDebugBulletMode() const;
bool IsBulletDebugDrawEnabled() const;
void BulletDebugDraw();
};
VERUS_TYPEDEFS(BaseGame);
}

View File

@ -6,3 +6,49 @@
#include "QuickRefs.h"
#include "AllocatorAware.h"
#include "Singleton.h"
namespace verus
{
namespace Math
{
// Clamp:
template<typename T>
T Clamp(T x, T mn, T mx)
{
if (x <= mn)
return mn;
else if (x >= mx)
return mx;
return x;
}
// Minimum & maximum:
template<typename T>
T Min(T a, T b)
{
return a < b ? a : b;
}
template<typename T>
T Max(T a, T b)
{
return a > b ? a : b;
}
// Memory alignment:
template<typename T>
T AlignUp(T val, T align)
{
return (val + align - 1) / align * align;
}
template<typename T>
T AlignDown(T val, T align)
{
return val / align * align;
}
template<typename T>
T DivideByMultiple(T value, T alignment)
{
return (value + alignment - 1) / alignment;
}
}
}

View File

@ -20,8 +20,8 @@ void EngineInit::Make()
Make_Physics();
//if (_makeEffects)
// Make_Effects();
//if (_makeExtra)
// Make_Extra();
if (_makeExtra)
Make_Extra();
if (_makeScene)
Make_Scene();
//if (_makeGUI)
@ -34,8 +34,8 @@ void EngineInit::Free()
// Free_GUI();
if (_makeScene)
Free_Scene();
//if (_makeExtra)
// Free_Extra();
if (_makeExtra)
Free_Extra();
//if (_makeEffects)
// Free_Effects();
if (_makePhysics)

View File

@ -26,14 +26,14 @@ void Object::Done()
#ifdef VERUS_DEBUG
void Object::UpdateOnceCheck()
{
const UINT32 numFrames = CGL::CRender::I().GetNumFrames();
const UINT64 numFrames = CGI::Renderer::I().GetNumFrames();
VERUS_RT_ASSERT(_updateOnceFrame <= numFrames);
_updateOnceFrame = numFrames + 1;
}
void Object::UpdateOnceCheckDraw()
{
const UINT32 numFrames = CGL::CRender::I().GetNumFrames();
const UINT64 numFrames = CGI::Renderer::I().GetNumFrames();
VERUS_RT_ASSERT(_updateOnceFrame > numFrames);
}
#endif

View File

@ -8,14 +8,8 @@
# define VERUS_UPDATE_ONCE_CHECK_DRAW
#endif
#define VERUS_INIT()\
Object::Init();
#define VERUS_DONE(x)\
if(Object::IsInitialized()) {\
Object::Done();\
this->~x();\
new(this) x();}
#define VERUS_INIT() Object::Init();
#define VERUS_DONE(x) if (Object::IsInitialized()) { Object::Done(); this->~x(); new(this) x(); }
namespace verus
{
@ -32,7 +26,7 @@ namespace verus
{
std::atomic_uint _flags;
#ifdef VERUS_DEBUG
UINT32 _updateOnceFrame = 0;
UINT64 _updateOnceFrame = 0;
#endif
protected:

View File

@ -2,6 +2,12 @@
namespace verus
{
template<typename F, typename... Ts>
inline auto Async(F&& f, Ts&&... params)
{
return std::async(std::launch::async, std::forward<F>(f), std::forward<Ts>(params)...);
}
class Parallel
{
public:

View File

@ -51,7 +51,7 @@ namespace verus
int GetNumStored() const
{
return _list.size();
return static_cast<int>(_list.size());
}
};
@ -108,7 +108,7 @@ namespace verus
int GetNumStored() const
{
return _map.size();
return static_cast<int>(_map.size());
}
};

View File

@ -55,10 +55,10 @@ void Utils::InitPaths()
VERUS_LOG_INFO("Writable path: " << _writablePath);
}
void Utils::ExitSdlLoop()
void Utils::PushQuitEvent()
{
SDL_Event event = {};
event.type = SDL_USEREVENT;
event.type = SDL_QUIT;
SDL_PushEvent(&event);
}

View File

@ -8,6 +8,7 @@ namespace verus
String _modulePath;
String _shaderPath;
String _writablePath;
String _projectPath;
PBaseAllocator _pAllocator;
public:
@ -26,6 +27,8 @@ namespace verus
void SetShaderPath(CSZ path) { _shaderPath = path; }
Str GetWritablePath() const { return _C(_writablePath); }
void SetWritablePath(CSZ path) { _writablePath = path; }
Str GetProjectPath() const { return _C(_projectPath); }
void SetProjectPath(CSZ path) { _projectPath = path; }
RRandom GetRandom() { return _random; }
@ -33,7 +36,7 @@ namespace verus
PBaseAllocator GetAllocator() { return _pAllocator; }
void SetAllocator(PBaseAllocator p) { _pAllocator = p; }
static void ExitSdlLoop();
static void PushQuitEvent();
static INT32 Cast32(INT64 x);
static UINT32 Cast32(UINT64 x);

View File

@ -146,6 +146,7 @@ void FileSystem::LoadResourceFromFile(CSZ url, Vector<BYTE>& vData, RcLoadDesc d
if (shader)
{
strUrl.replace(0, strlen(s_shaderPAK), "/");
pathNameProject = String(_C(Utils::I().GetProjectPath())) + strUrl;
StringStream ss;
ss << _C(Utils::I().GetShaderPath()) << strUrl;
strUrl = ss.str();
@ -154,6 +155,7 @@ void FileSystem::LoadResourceFromFile(CSZ url, Vector<BYTE>& vData, RcLoadDesc d
{
String folder = strUrl.substr(1, pakPos - 1);
const String name = strUrl.substr(pakPos + 2);
pathNameProject = String(_C(Utils::I().GetProjectPath())) + s_dataFolder + folder + "/" + name;
StringStream ss;
ss << _C(Utils::I().GetModulePath()) << s_dataFolder << folder << "/" << name;
strUrl = ss.str();

View File

@ -0,0 +1,55 @@
#include "verus.h"
using namespace verus;
using namespace verus::Input;
void DragController::SetDelegate(PDragControllerDelegate p)
{
_pDelegate = p;
if (_pDelegate)
_pDelegate->DragController_GetRatio(_ratioX, _ratioY);
}
void DragController::Begin(int x, int y)
{
if (!_pDelegate)
return;
_active = true;
_originCoordX = x;
_originCoordY = y;
_pDelegate->DragController_Begin();
_pDelegate->DragController_GetParams(_originX, _originY);
}
bool DragController::DragTo(int x, int y)
{
if (!_pDelegate || !_active)
return false;
const float newX = _originX + (x - _originCoordX) * _ratioX;
const float newY = _originY + (y - _originCoordY) * _ratioY;
_pDelegate->DragController_SetParams(newX, newY);
return true;
}
bool DragController::DragBy(int x, int y)
{
if (!_pDelegate || !_active)
return false;
_originX += x * _ratioX;
_originY += y * _ratioY;
_pDelegate->DragController_SetParams(_originX, _originY);
return true;
}
void DragController::End()
{
if (_pDelegate)
_pDelegate->DragController_End();
_active = false;
}
void DragController::SetScale(float s)
{
if (_pDelegate)
_pDelegate->DragController_SetScale(s);
}

View File

@ -0,0 +1,41 @@
#pragma once
namespace verus
{
namespace Input
{
struct DragControllerDelegate
{
virtual void DragController_GetParams(float& x, float& y) = 0;
virtual void DragController_SetParams(float x, float y) = 0;
virtual void DragController_GetRatio(float& x, float& y) = 0;
virtual void DragController_Begin() {}
virtual void DragController_End() {}
virtual void DragController_SetScale(float s) {}
};
VERUS_TYPEDEFS(DragControllerDelegate);
class DragController
{
PDragControllerDelegate _pDelegate = nullptr;
float _originX = 0;
float _originY = 0;
int _originCoordX = 0;
int _originCoordY = 0;
float _ratioX = 1;
float _ratioY = 1;
bool _active = false;
public:
void SetDelegate(PDragControllerDelegate p);
void Begin(int x, int y);
bool DragTo(int x, int y);
bool DragBy(int x, int y);
void End();
void SetScale(float s);
};
VERUS_TYPEDEFS(DragController);
}
}

View File

@ -1,6 +1,7 @@
#pragma once
#include "KeyMapper.h"
#include "DragController.h"
namespace verus
{

View File

@ -58,21 +58,29 @@ bool KeyMapper::HandleSdlEvent(SDL_Event& event)
// Keyboard:
case SDL_KEYDOWN:
{
if (ImGui::GetIO().WantCaptureKeyboard)
return false;
#if defined(_DEBUG) || defined(VERUS_DEBUG)
if (settings._screenWindowed && SDL_SCANCODE_KP_ENTER == event.key.keysym.scancode)
{
const SDL_bool rel = SDL_GetRelativeMouseMode();
SDL_SetRelativeMouseMode(rel ? SDL_FALSE : SDL_TRUE);
}
#endif
OnKeyDown(event.key.keysym.scancode);
}
break;
case SDL_KEYUP:
{
if (ImGui::GetIO().WantCaptureKeyboard)
return false;
OnKeyUp(event.key.keysym.scancode);
}
break;
case SDL_TEXTINPUT:
{
if (ImGui::GetIO().WantCaptureKeyboard)
return false;
wchar_t wide[4];
Str::Utf8ToWide(event.text.text, wide, 4);
OnChar(wide[0]);
@ -90,6 +98,8 @@ bool KeyMapper::HandleSdlEvent(SDL_Event& event)
break;
case SDL_MOUSEBUTTONDOWN:
{
if (ImGui::GetIO().WantCaptureMouse)
return false;
if (1 == event.button.clicks)
{
if (event.button.button < VERUS_BUTTON_WHEELUP)
@ -104,6 +114,8 @@ bool KeyMapper::HandleSdlEvent(SDL_Event& event)
break;
case SDL_MOUSEBUTTONUP:
{
if (ImGui::GetIO().WantCaptureMouse)
return false;
if (1 == event.button.clicks)
{
if (event.button.button < VERUS_BUTTON_WHEELUP)
@ -113,6 +125,8 @@ bool KeyMapper::HandleSdlEvent(SDL_Event& event)
break;
case SDL_MOUSEWHEEL:
{
if (ImGui::GetIO().WantCaptureMouse)
return false;
if (event.wheel.y >= 0)
{
OnMouseDown(VERUS_BUTTON_WHEELUP);

View File

@ -81,45 +81,5 @@ namespace verus
// Matrices:
Transform3 QuadMatrix(float x = 0, float y = 0, float w = 1, float h = 1);
Transform3 ToUVMatrix(float zOffset = 0, RcVector4 texSize = Vector4(0), PcVector4 pTileSize = nullptr);
// Clamp:
template<typename T>
T Clamp(T x, T mn, T mx)
{
if (x <= mn)
return mn;
else if (x >= mx)
return mx;
return x;
}
// Minimum & maximum:
template<typename T>
T Min(T a, T b)
{
return a < b ? a : b;
}
template<typename T>
T Max(T a, T b)
{
return a > b ? a : b;
}
// Memory alignment:
template<typename T>
T AlignUp(T val, T align)
{
return (val + align - 1) / align * align;
}
template<typename T>
T AlignDown(T val, T align)
{
return val / align * align;
}
template<typename T>
T DivideByMultiple(T value, T alignment)
{
return (value + alignment - 1) / alignment;
}
};
}

View File

@ -21,7 +21,7 @@ void Bullet::Init()
_pBroadphaseInterface = new btDbvtBroadphase();
_pConstraintSolver = new btSequentialImpulseConstraintSolver();
//_pBroadphaseInterface->getOverlappingPairCache()->setInternalGhostPairCallback(&m_ghostPairCallback);
_pBroadphaseInterface->getOverlappingPairCache()->setInternalGhostPairCallback(&_ghostPairCallback);
_pDiscreteDynamicsWorld = new btDiscreteDynamicsWorld(
_pDispatcher,
@ -31,7 +31,7 @@ void Bullet::Init()
#ifdef VERUS_DEBUG
_pDiscreteDynamicsWorld->setDebugDrawer(&_debugDraw);
_pDiscreteDynamicsWorld->getDebugDrawer()->setDebugMode(btIDebugDraw::DBG_NoDebug);
EnableDebugDraw(true);
#endif
// See: http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=6773:
@ -131,13 +131,15 @@ void Bullet::Simulate()
void Bullet::DebugDraw()
{
#ifdef VERUS_DEBUG
if (!_pDiscreteDynamicsWorld)
return;
//VERUS_QREF_DR;
//dr.Begin(CGL::CDebugRender::T_LINES, nullptr, false);
//_pDiscreteDynamicsWorld->debugDrawWorld();
//dr.End();
VERUS_QREF_DD;
dd.Begin(CGI::DebugDraw::Type::lines, nullptr, false);
_pDiscreteDynamicsWorld->debugDrawWorld();
dd.End();
#endif
}
void Bullet::EnableDebugDraw(bool b)

View File

@ -26,6 +26,8 @@ namespace verus
btConstraintSolver* _pConstraintSolver = nullptr;
btCollisionConfiguration* _pCollisionConfiguration = nullptr;
btDiscreteDynamicsWorld* _pDiscreteDynamicsWorld = nullptr;
btGhostPairCallback _ghostPairCallback;
BulletDebugDraw _debugDraw;
public:
Bullet();

View File

@ -0,0 +1,71 @@
#include "verus.h"
using namespace verus;
using namespace verus::Physics;
void BulletDebugDraw::drawLine(const btVector3& from, const btVector3& to,
const btVector3& color)
{
VERUS_QREF_SM;
const float maxDistSq = s_maxDrawDist * s_maxDrawDist;
const Point3 posEye = sm.GetCamera()->GetPositionEye();
if (VMath::distSqr(posEye, Point3(from)) >= maxDistSq &&
VMath::distSqr(posEye, Point3(to)) >= maxDistSq)
return;
VERUS_QREF_DD;
dd.AddLine(from, to, Convert::ColorFloatToInt32(color) | VERUS_COLOR_BLACK);
}
void BulletDebugDraw::drawLine(const btVector3& from, const btVector3& to,
const btVector3& fromColor, const btVector3& toColor)
{
VERUS_QREF_SM;
const float maxDistSq = s_maxDrawDist * s_maxDrawDist;
const Point3 posEye = sm.GetCamera()->GetPositionEye();
if (VMath::distSqr(posEye, Point3(from)) >= maxDistSq &&
VMath::distSqr(posEye, Point3(to)) >= maxDistSq)
return;
VERUS_QREF_DD;
dd.AddLine(from, to, Convert::ColorFloatToInt32(fromColor) | VERUS_COLOR_BLACK);
}
void BulletDebugDraw::drawSphere(const btVector3& p, btScalar radius, const btVector3& color)
{
}
void BulletDebugDraw::drawBox(const btVector3& boxMin, const btVector3& boxMax,
const btVector3& color)
{
}
void BulletDebugDraw::drawTriangle(const btVector3& a, const btVector3& b, const btVector3& c,
const btVector3& color, btScalar alpha)
{
VERUS_QREF_DD;
Vector4 colorEx = color;
colorEx.setW(alpha);
const UINT32 color32 = Convert::ColorFloatToInt32(colorEx.ToPointer());
dd.AddLine(a, b, color32);
dd.AddLine(b, c, color32);
dd.AddLine(c, a, color32);
}
void BulletDebugDraw::drawContactPoint(const btVector3& pointOnB, const btVector3& normalOnB,
btScalar distance, int lifeTime, const btVector3& color)
{
}
void BulletDebugDraw::reportErrorWarning(const char* warningString)
{
}
void BulletDebugDraw::draw3dText(const btVector3& location, const char* textString)
{
}
void BulletDebugDraw::drawTransform(const btTransform& transform, btScalar orthoLen)
{
btIDebugDraw::drawTransform(transform, 0.1f);
}

View File

@ -0,0 +1,38 @@
#pragma once
namespace verus
{
namespace Physics
{
class BulletDebugDraw : public btIDebugDraw
{
static const int s_maxDrawDist = 30;
int _debugMode = 0;
public:
BulletDebugDraw() : _debugMode(btIDebugDraw::DBG_DrawWireframe) {}
~BulletDebugDraw() {}
virtual void drawLine(const btVector3& from, const btVector3& to, const btVector3& color) override;
virtual void drawLine(const btVector3& from, const btVector3& to, const btVector3& fromColor, const btVector3& toColor) override;
virtual void drawSphere(const btVector3& p, btScalar radius, const btVector3& color) override;
virtual void drawBox(const btVector3& boxMin, const btVector3& boxMax, const btVector3& color) override;
virtual void drawTriangle(const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& color, btScalar alpha) override;
virtual void drawContactPoint(const btVector3& pointOnB, const btVector3& normalOnB, btScalar distance, int lifeTime, const btVector3& color) override;
virtual void reportErrorWarning(const char* warningString) override;
virtual void draw3dText(const btVector3& location, const char* textString) override;
virtual void drawTransform(const btTransform& transform, btScalar orthoLen) override;
virtual void setDebugMode(int debugMode) override { _debugMode = debugMode; }
virtual int getDebugMode() const override { return _debugMode; }
};
VERUS_TYPEDEFS(BulletDebugDraw);
}
}

View File

@ -0,0 +1,135 @@
#include "verus.h"
using namespace verus;
using namespace verus::Physics;
CharacterController::CharacterController()
{
}
CharacterController::~CharacterController()
{
Done();
}
void CharacterController::Init(RcPoint3 pos, RcDesc desc)
{
VERUS_INIT();
VERUS_QREF_BULLET;
if (desc._radius >= 1e-4f)
_radius = desc._radius;
if (desc._height >= 1e-4f)
_height = desc._height;
float stepHeight = _radius;
if (desc._stepHeight >= 0)
stepHeight = desc._stepHeight;
_offset = _radius + _height * 0.5f;
btTransform t;
t.setIdentity();
t.setOrigin(pos.Bullet() + btVector3(0, _offset, 0));
_pCapsule = new btCapsuleShape(1, 1);
_pGhostObject = new btPairCachingGhostObject();
_pGhostObject->setWorldTransform(t);
_pGhostObject->setCollisionShape(_pCapsule);
_pGhostObject->setCollisionFlags(btCollisionObject::CF_CHARACTER_OBJECT);
_pGhostObject->setUserPointer(this);
_pKCC = new KinematicCharacterController(_pGhostObject, _pCapsule, stepHeight);
_pKCC->setGravity(-bullet.GetWorld()->getGravity().getY());
_pKCC->setMaxSlope(btRadians(48));
bullet.GetWorld()->addCollisionObject(_pGhostObject, +Group::character, -1);
bullet.GetWorld()->addAction(_pKCC);
UpdateScaling();
}
void CharacterController::Done()
{
VERUS_QREF_BULLET;
if (_pKCC)
{
bullet.GetWorld()->removeAction(_pKCC);
delete _pKCC;
_pKCC = nullptr;
}
if (_pGhostObject)
{
bullet.GetWorld()->removeCollisionObject(_pGhostObject);
delete _pGhostObject;
_pGhostObject = nullptr;
}
if (_pCapsule)
{
delete _pCapsule;
_pCapsule = nullptr;
}
VERUS_DONE(CharacterController);
}
int CharacterController::UserPtr_GetType()
{
return 0;
//return +Scene::NodeType::character;
}
void CharacterController::SetRadius(float r)
{
const bool update = (r != _radius);
_radius = r;
if (update)
UpdateScaling();
}
void CharacterController::SetHeight(float h)
{
const Point3 pos = GetPosition();
const bool update = (h != _height);
_height = h;
if (update)
{
UpdateScaling();
MoveTo(pos);
}
}
void CharacterController::UpdateScaling()
{
_offset = _radius + _height * 0.5f;
if (_pCapsule)
_pCapsule->setLocalScaling(btVector3(_radius, _height, _radius));
}
void CharacterController::Move(RcVector3 velocity)
{
VERUS_QREF_TIMER;
if (_pKCC)
_pKCC->setVelocityForTimeInterval(velocity.Bullet(), dt);
}
Point3 CharacterController::GetPosition()
{
if (_pGhostObject)
return _pGhostObject->getWorldTransform().getOrigin() - btVector3(0, _offset, 0);
return Point3(0);
}
void CharacterController::MoveTo(RcPoint3 pos)
{
if (_pKCC)
_pKCC->warp(pos.Bullet() + btVector3(0, _offset, 0));
}
void CharacterController::Visualize(bool b)
{
const int f = _pGhostObject->getCollisionFlags();
if (b)
_pGhostObject->setCollisionFlags(f & ~btCollisionObject::CF_DISABLE_VISUALIZE_OBJECT);
else
_pGhostObject->setCollisionFlags(f | btCollisionObject::CF_DISABLE_VISUALIZE_OBJECT);
}

View File

@ -0,0 +1,55 @@
#pragma once
namespace verus
{
namespace Physics
{
class CharacterController : public Object, public UserPtr
{
btCapsuleShape* _pCapsule = nullptr;
KinematicCharacterController* _pKCC = nullptr; // Action.
btPairCachingGhostObject* _pGhostObject = nullptr; // CollisionObject.
float _radius = 1;
float _height = 1;
float _offset = 0;
public:
class Desc
{
public:
float _radius = -1;
float _height = -1;
float _stepHeight = -1;
};
VERUS_TYPEDEFS(Desc);
CharacterController();
~CharacterController();
void Init(RcPoint3 pos, RcDesc desc);
void Done();
virtual int UserPtr_GetType() override;
float GetRadius() const { return _radius; }
float GetHeight() const { return _height; }
float GetOffset() const { return _offset; }
void SetRadius(float r);
void SetHeight(float h);
VERUS_P(void UpdateScaling());
KinematicCharacterController* GetKCC() { return _pKCC; }
const KinematicCharacterController* GetKCC() const { return _pKCC; }
void Move(RcVector3 velocity);
Point3 GetPosition();
void MoveTo(RcPoint3 pos);
void Visualize(bool b);
bool Is(const void* p) const { return p == this; }
};
VERUS_TYPEDEFS(CharacterController);
}
}

View File

@ -0,0 +1,791 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include <verus.h>
#include <LinearMath/btIDebugDraw.h>
#include <BulletCollision/CollisionDispatch/btGhostObject.h>
#include <BulletCollision/CollisionShapes/btMultiSphereShape.h>
#include <BulletCollision/BroadphaseCollision/btOverlappingPairCache.h>
#include <BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h>
#include <BulletCollision/CollisionDispatch/btCollisionWorld.h>
#include <LinearMath/btDefaultMotionState.h>
#include "KinematicCharacterController.h"
// static helper method
static btVector3
getNormalizedVector(const btVector3& v)
{
btVector3 n(0, 0, 0);
if (v.length() > SIMD_EPSILON) {
n = v.normalized();
}
return n;
}
///@todo Interact with dynamic objects,
///Ride kinematicly animated platforms properly
///More realistic (or maybe just a config option) falling
/// -> Should integrate falling velocity manually and use that in stepDown()
///Support jumping
///Support ducking
class btKinematicClosestNotMeRayResultCallback : public btCollisionWorld::ClosestRayResultCallback
{
public:
btKinematicClosestNotMeRayResultCallback(btCollisionObject* me) : btCollisionWorld::ClosestRayResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0))
{
m_me = me;
}
virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult, bool normalInWorldSpace)
{
if (rayResult.m_collisionObject == m_me)
return 1.0;
return ClosestRayResultCallback::addSingleResult(rayResult, normalInWorldSpace);
}
protected:
btCollisionObject* m_me;
};
class btKinematicClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback
{
public:
btKinematicClosestNotMeConvexResultCallback(btCollisionObject* me, const btVector3& up, btScalar minSlopeDot)
: btCollisionWorld::ClosestConvexResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0))
, m_me(me)
, m_up(up)
, m_minSlopeDot(minSlopeDot)
{
}
virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult, bool normalInWorldSpace)
{
if (convexResult.m_hitCollisionObject == m_me)
return btScalar(1.0);
if (!convexResult.m_hitCollisionObject->hasContactResponse())
return btScalar(1.0);
btVector3 hitNormalWorld;
if (normalInWorldSpace)
{
hitNormalWorld = convexResult.m_hitNormalLocal;
}
else
{
///need to transform normal into worldspace
hitNormalWorld = convexResult.m_hitCollisionObject->getWorldTransform().getBasis() * convexResult.m_hitNormalLocal;
}
btScalar dotUp = m_up.dot(hitNormalWorld);
if (dotUp < m_minSlopeDot) {
return btScalar(1.0);
}
return ClosestConvexResultCallback::addSingleResult(convexResult, normalInWorldSpace);
}
protected:
btCollisionObject* m_me;
const btVector3 m_up;
btScalar m_minSlopeDot;
};
/*
* Returns the reflection direction of a ray going 'direction' hitting a surface with normal 'normal'
*
* from: http://www-cs-students.stanford.edu/~adityagp/final/node3.html
*/
btVector3 KinematicCharacterController::computeReflectionDirection(const btVector3& direction, const btVector3& normal)
{
return direction - (btScalar(2.0) * direction.dot(normal)) * normal;
}
/*
* Returns the portion of 'direction' that is parallel to 'normal'
*/
btVector3 KinematicCharacterController::parallelComponent(const btVector3& direction, const btVector3& normal)
{
btScalar magnitude = direction.dot(normal);
return normal * magnitude;
}
/*
* Returns the portion of 'direction' that is perpindicular to 'normal'
*/
btVector3 KinematicCharacterController::perpindicularComponent(const btVector3& direction, const btVector3& normal)
{
return direction - parallelComponent(direction, normal);
}
KinematicCharacterController::KinematicCharacterController(btPairCachingGhostObject* ghostObject, btConvexShape* convexShape, btScalar stepHeight, int upAxis)
{
m_upAxis = upAxis;
m_addedMargin = 0.02f;
m_walkDirection.setValue(0, 0, 0);
m_useGhostObjectSweepTest = true;
m_ghostObject = ghostObject;
m_stepHeight = stepHeight;
m_turnAngle = btScalar(0.0);
m_convexShape = convexShape;
m_useWalkDirection = true; // use walk direction by default, legacy behavior
m_velocityTimeInterval = 0.0;
m_verticalVelocity = 0.0;
m_verticalOffset = 0.0;
m_gravity = 9.8f * 3; // 3G acceleration.
m_fallSpeed = 55.0; // Terminal velocity of a sky diver in m/s.
m_jumpSpeed = 10.0; // ?
m_wasOnGround = false;
m_wasJumping = false;
m_interpolateUp = true;
setMaxSlope(btRadians(45.0));
m_currentStepOffset = 0;
full_drop = false;
bounce_fix = false;
}
KinematicCharacterController::~KinematicCharacterController()
{
}
btPairCachingGhostObject* KinematicCharacterController::getGhostObject()
{
return m_ghostObject;
}
bool KinematicCharacterController::recoverFromPenetration(btCollisionWorld* collisionWorld)
{
// Here we must refresh the overlapping paircache as the penetrating movement itself or the
// previous recovery iteration might have used setWorldTransform and pushed us into an object
// that is not in the previous cache contents from the last timestep, as will happen if we
// are pushed into a new AABB overlap. Unhandled this means the next convex sweep gets stuck.
//
// Do this by calling the broadphase's setAabb with the moved AABB, this will update the broadphase
// paircache and the ghostobject's internal paircache at the same time. /BW
btVector3 minAabb, maxAabb;
m_convexShape->getAabb(m_ghostObject->getWorldTransform(), minAabb, maxAabb);
collisionWorld->getBroadphase()->setAabb(m_ghostObject->getBroadphaseHandle(),
minAabb,
maxAabb,
collisionWorld->getDispatcher());
bool penetration = false;
collisionWorld->getDispatcher()->dispatchAllCollisionPairs(m_ghostObject->getOverlappingPairCache(), collisionWorld->getDispatchInfo(), collisionWorld->getDispatcher());
m_currentPosition = m_ghostObject->getWorldTransform().getOrigin();
btScalar maxPen = btScalar(0.0);
for (int i = 0; i < m_ghostObject->getOverlappingPairCache()->getNumOverlappingPairs(); i++)
{
m_manifoldArray.resize(0);
btBroadphasePair* collisionPair = &m_ghostObject->getOverlappingPairCache()->getOverlappingPairArray()[i];
btCollisionObject* obj0 = static_cast<btCollisionObject*>(collisionPair->m_pProxy0->m_clientObject);
btCollisionObject* obj1 = static_cast<btCollisionObject*>(collisionPair->m_pProxy1->m_clientObject);
if ((obj0 && !obj0->hasContactResponse()) || (obj1 && !obj1->hasContactResponse()))
continue;
if (collisionPair->m_algorithm)
collisionPair->m_algorithm->getAllContactManifolds(m_manifoldArray);
for (int j = 0; j < m_manifoldArray.size(); j++)
{
btPersistentManifold* manifold = m_manifoldArray[j];
btScalar directionSign = manifold->getBody0() == m_ghostObject ? btScalar(-1.0) : btScalar(1.0);
for (int p = 0; p < manifold->getNumContacts(); p++)
{
const btManifoldPoint& pt = manifold->getContactPoint(p);
btScalar dist = pt.getDistance();
if (dist < 0.0)
{
if (dist < maxPen)
{
maxPen = dist;
m_touchingNormal = pt.m_normalWorldOnB * directionSign;//??
}
m_currentPosition += pt.m_normalWorldOnB * directionSign * dist * btScalar(0.2);
penetration = true;
}
else {
//printf("touching %f\n", dist);
}
}
//manifold->clearManifold();
}
}
btTransform newTrans = m_ghostObject->getWorldTransform();
newTrans.setOrigin(m_currentPosition);
m_ghostObject->setWorldTransform(newTrans);
// printf("m_touchingNormal = %f,%f,%f\n",m_touchingNormal[0],m_touchingNormal[1],m_touchingNormal[2]);
return penetration;
}
void KinematicCharacterController::stepUp(btCollisionWorld* world)
{
// phase 1: up
btTransform start, end;
m_targetPosition = m_currentPosition + getUpAxisDirections()[m_upAxis] * (m_stepHeight + (m_verticalOffset > 0.f ? m_verticalOffset : 0.f));
start.setIdentity();
end.setIdentity();
/* FIXME: Handle penetration properly */
start.setOrigin(m_currentPosition + getUpAxisDirections()[m_upAxis] * (m_convexShape->getMargin() + m_addedMargin));
end.setOrigin(m_targetPosition);
btKinematicClosestNotMeConvexResultCallback callback(m_ghostObject, -getUpAxisDirections()[m_upAxis], btScalar(0.7071));
callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask;
if (m_useGhostObjectSweepTest)
{
m_ghostObject->convexSweepTest(m_convexShape, start, end, callback, world->getDispatchInfo().m_allowedCcdPenetration);
}
else
{
world->convexSweepTest(m_convexShape, start, end, callback);
}
if (callback.hasHit())
{
// Only modify the position if the hit was a slope and not a wall or ceiling.
if (callback.m_hitNormalWorld.dot(getUpAxisDirections()[m_upAxis]) > 0.0)
{
// we moved up only a fraction of the step height
m_currentStepOffset = m_stepHeight * callback.m_closestHitFraction;
if (m_interpolateUp == true)
m_currentPosition.setInterpolate3(m_currentPosition, m_targetPosition, callback.m_closestHitFraction);
else
m_currentPosition = m_targetPosition;
}
m_verticalVelocity = 0.0;
m_verticalOffset = 0.0;
}
else {
m_currentStepOffset = m_stepHeight;
m_currentPosition = m_targetPosition;
}
}
void KinematicCharacterController::updateTargetPositionBasedOnCollision(const btVector3& hitNormal, btScalar tangentMag, btScalar normalMag)
{
btVector3 movementDirection = m_targetPosition - m_currentPosition;
btScalar movementLength = movementDirection.length();
if (movementLength > SIMD_EPSILON)
{
movementDirection.normalize();
btVector3 reflectDir = computeReflectionDirection(movementDirection, hitNormal);
reflectDir.normalize();
btVector3 parallelDir, perpindicularDir;
parallelDir = parallelComponent(reflectDir, hitNormal);
perpindicularDir = perpindicularComponent(reflectDir, hitNormal);
m_targetPosition = m_currentPosition;
if (0)//tangentMag != 0.0)
{
btVector3 parComponent = parallelDir * btScalar(tangentMag * movementLength);
// printf("parComponent=%f,%f,%f\n",parComponent[0],parComponent[1],parComponent[2]);
m_targetPosition += parComponent;
}
if (normalMag != 0.0)
{
btVector3 perpComponent = perpindicularDir * btScalar(normalMag * movementLength);
// printf("perpComponent=%f,%f,%f\n",perpComponent[0],perpComponent[1],perpComponent[2]);
m_targetPosition += perpComponent;
}
}
else
{
// printf("movementLength don't normalize a zero vector\n");
}
}
void KinematicCharacterController::stepForwardAndStrafe(btCollisionWorld* collisionWorld, const btVector3& walkMove)
{
// printf("m_normalizedDirection=%f,%f,%f\n",
// m_normalizedDirection[0],m_normalizedDirection[1],m_normalizedDirection[2]);
// phase 2: forward and strafe
btTransform start, end;
m_targetPosition = m_currentPosition + walkMove;
start.setIdentity();
end.setIdentity();
btScalar fraction = 1.0;
btScalar distance2 = (m_currentPosition - m_targetPosition).length2();
// printf("distance2=%f\n",distance2);
if (m_touchingContact)
{
if (m_normalizedDirection.dot(m_touchingNormal) > btScalar(0.0))
{
//interferes with step movement
//updateTargetPositionBasedOnCollision (m_touchingNormal);
}
}
int maxIter = 10;
while (fraction > btScalar(0.01) && maxIter-- > 0)
{
start.setOrigin(m_currentPosition);
end.setOrigin(m_targetPosition);
btVector3 sweepDirNegative(m_currentPosition - m_targetPosition);
btKinematicClosestNotMeConvexResultCallback callback(m_ghostObject, sweepDirNegative, btScalar(0.0));
callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask;
btScalar margin = m_convexShape->getMargin();
m_convexShape->setMargin(margin + m_addedMargin);
if (m_useGhostObjectSweepTest)
{
m_ghostObject->convexSweepTest(m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
}
else
{
collisionWorld->convexSweepTest(m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
}
m_convexShape->setMargin(margin);
fraction -= callback.m_closestHitFraction;
if (callback.hasHit())
{
// we moved only a fraction
//btScalar hitDistance;
//hitDistance = (callback.m_hitPointWorld - m_currentPosition).length();
// m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction);
updateTargetPositionBasedOnCollision(callback.m_hitNormalWorld);
btVector3 currentDir = m_targetPosition - m_currentPosition;
distance2 = currentDir.length2();
if (distance2 > SIMD_EPSILON)
{
currentDir.normalize();
/* See Quake2: "If velocity is against original velocity, stop ead to avoid tiny oscilations in sloping corners." */
if (currentDir.dot(m_normalizedDirection) <= btScalar(0.0))
{
break;
}
}
else
{
// printf("currentDir: don't normalize a zero vector\n");
break;
}
}
else {
// we moved whole way
m_currentPosition = m_targetPosition;
}
// if (callback.m_closestHitFraction == 0.f)
// break;
}
}
void KinematicCharacterController::stepDown(btCollisionWorld* collisionWorld, btScalar dt)
{
btTransform start, end, end_double;
bool runonce = false;
// phase 3: down
/*btScalar additionalDownStep = (m_wasOnGround && !onGround()) ? m_stepHeight : 0.0;
btVector3 step_drop = getUpAxisDirections()[m_upAxis] * (m_currentStepOffset + additionalDownStep);
btScalar downVelocity = (additionalDownStep == 0.0 && m_verticalVelocity<0.0?-m_verticalVelocity:0.0) * dt;
btVector3 gravity_drop = getUpAxisDirections()[m_upAxis] * downVelocity;
m_targetPosition -= (step_drop + gravity_drop);*/
btVector3 orig_position = m_targetPosition;
btScalar downVelocity = (m_verticalVelocity < 0.f ? -m_verticalVelocity : 0.f) * dt;
if (downVelocity > 0.0 && downVelocity > m_fallSpeed
&& (m_wasOnGround || !m_wasJumping))
downVelocity = m_fallSpeed;
btVector3 step_drop = getUpAxisDirections()[m_upAxis] * (m_currentStepOffset + downVelocity);
m_targetPosition -= step_drop;
btKinematicClosestNotMeConvexResultCallback callback(m_ghostObject, getUpAxisDirections()[m_upAxis], m_maxSlopeCosine);
callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask;
btKinematicClosestNotMeConvexResultCallback callback2(m_ghostObject, getUpAxisDirections()[m_upAxis], m_maxSlopeCosine);
callback2.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
callback2.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask;
while (1)
{
start.setIdentity();
end.setIdentity();
end_double.setIdentity();
start.setOrigin(m_currentPosition);
end.setOrigin(m_targetPosition);
//set double test for 2x the step drop, to check for a large drop vs small drop
end_double.setOrigin(m_targetPosition - step_drop);
if (m_useGhostObjectSweepTest)
{
m_ghostObject->convexSweepTest(m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
if (!callback.hasHit())
{
//test a double fall height, to see if the character should interpolate it's fall (full) or not (partial)
m_ghostObject->convexSweepTest(m_convexShape, start, end_double, callback2, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
}
}
else
{
collisionWorld->convexSweepTest(m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
if (!callback.hasHit())
{
//test a double fall height, to see if the character should interpolate it's fall (large) or not (small)
collisionWorld->convexSweepTest(m_convexShape, start, end_double, callback2, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
}
}
btScalar downVelocity2 = (m_verticalVelocity < 0.f ? -m_verticalVelocity : 0.f) * dt;
bool has_hit = false;
if (bounce_fix == true)
has_hit = callback.hasHit() || callback2.hasHit();
else
has_hit = callback2.hasHit();
if (downVelocity2 > 0.0 && downVelocity2 < m_stepHeight && has_hit == true && runonce == false
&& (m_wasOnGround || !m_wasJumping))
{
//redo the velocity calculation when falling a small amount, for fast stairs motion
//for larger falls, use the smoother/slower interpolated movement by not touching the target position
m_targetPosition = orig_position;
downVelocity = m_stepHeight;
btVector3 step_drop = getUpAxisDirections()[m_upAxis] * (m_currentStepOffset + downVelocity);
m_targetPosition -= step_drop;
runonce = true;
continue; //re-run previous tests
}
break;
}
if (callback.hasHit() || runonce == true)
{
// we dropped a fraction of the height -> hit floor
btScalar fraction = (m_currentPosition.getY() - callback.m_hitPointWorld.getY()) / 2;
//printf("hitpoint: %g - pos %g\n", callback.m_hitPointWorld.getY(), m_currentPosition.getY());
if (bounce_fix == true)
{
if (full_drop == true)
m_currentPosition.setInterpolate3(m_currentPosition, m_targetPosition, callback.m_closestHitFraction);
else
//due to errors in the closestHitFraction variable when used with large polygons, calculate the hit fraction manually
m_currentPosition.setInterpolate3(m_currentPosition, m_targetPosition, fraction);
}
else
m_currentPosition.setInterpolate3(m_currentPosition, m_targetPosition, callback.m_closestHitFraction);
full_drop = false;
m_verticalVelocity = 0.0;
m_verticalOffset = 0.0;
m_wasJumping = false;
}
else {
// we dropped the full height
full_drop = true;
if (bounce_fix == true)
{
downVelocity = (m_verticalVelocity < 0.f ? -m_verticalVelocity : 0.f) * dt;
if (downVelocity > m_fallSpeed && (m_wasOnGround || !m_wasJumping))
{
m_targetPosition += step_drop; //undo previous target change
downVelocity = m_fallSpeed;
step_drop = getUpAxisDirections()[m_upAxis] * (m_currentStepOffset + downVelocity);
m_targetPosition -= step_drop;
}
}
//printf("full drop - %g, %g\n", m_currentPosition.getY(), m_targetPosition.getY());
m_currentPosition = m_targetPosition;
}
}
void KinematicCharacterController::setWalkDirection
(
const btVector3& walkDirection
)
{
m_useWalkDirection = true;
m_walkDirection = walkDirection;
m_normalizedDirection = getNormalizedVector(m_walkDirection);
}
void KinematicCharacterController::setVelocityForTimeInterval
(
const btVector3& velocity,
btScalar timeInterval
)
{
// printf("setVelocity!\n");
// printf(" interval: %f\n", timeInterval);
// printf(" velocity: (%f, %f, %f)\n",
// velocity.x(), velocity.y(), velocity.z());
m_useWalkDirection = false;
m_walkDirection = velocity;
m_normalizedDirection = getNormalizedVector(m_walkDirection);
m_velocityTimeInterval += timeInterval;
}
void KinematicCharacterController::reset(btCollisionWorld* collisionWorld)
{
m_verticalVelocity = 0.0;
m_verticalOffset = 0.0;
m_wasOnGround = false;
m_wasJumping = false;
m_walkDirection.setValue(0, 0, 0);
m_velocityTimeInterval = 0.0;
//clear pair cache
btHashedOverlappingPairCache* cache = m_ghostObject->getOverlappingPairCache();
while (cache->getOverlappingPairArray().size() > 0)
{
cache->removeOverlappingPair(cache->getOverlappingPairArray()[0].m_pProxy0, cache->getOverlappingPairArray()[0].m_pProxy1, collisionWorld->getDispatcher());
}
}
void KinematicCharacterController::warp(const btVector3& origin)
{
btTransform xform;
xform.setIdentity();
xform.setOrigin(origin);
m_ghostObject->setWorldTransform(xform);
}
void KinematicCharacterController::preStep(btCollisionWorld* collisionWorld)
{
int numPenetrationLoops = 0;
m_touchingContact = false;
while (recoverFromPenetration(collisionWorld))
{
numPenetrationLoops++;
m_touchingContact = true;
if (numPenetrationLoops > 4)
{
//printf("character could not recover from penetration = %d\n", numPenetrationLoops);
break;
}
}
m_currentPosition = m_ghostObject->getWorldTransform().getOrigin();
m_targetPosition = m_currentPosition;
// printf("m_targetPosition=%f,%f,%f\n",m_targetPosition[0],m_targetPosition[1],m_targetPosition[2]);
}
#include <stdio.h>
void KinematicCharacterController::playerStep(btCollisionWorld* collisionWorld, btScalar dt)
{
// printf("playerStep(): ");
// printf(" dt = %f", dt);
// quick check...
if (!m_useWalkDirection && m_velocityTimeInterval <= 0.0) {
// printf("\n");
return; // no motion
}
m_wasOnGround = onGround();
// Update fall velocity.
m_verticalVelocity -= m_gravity * dt;
if (m_verticalVelocity > 0.0 && m_verticalVelocity > m_jumpSpeed)
{
m_verticalVelocity = m_jumpSpeed;
}
if (m_verticalVelocity < 0.0 && btFabs(m_verticalVelocity) > btFabs(m_fallSpeed))
{
m_verticalVelocity = -btFabs(m_fallSpeed);
}
m_verticalOffset = m_verticalVelocity * dt;
btTransform xform;
xform = m_ghostObject->getWorldTransform();
// printf("walkDirection(%f,%f,%f)\n",walkDirection[0],walkDirection[1],walkDirection[2]);
// printf("walkSpeed=%f\n",walkSpeed);
stepUp(collisionWorld);
if (m_useWalkDirection) {
stepForwardAndStrafe(collisionWorld, m_walkDirection);
}
else {
//printf(" time: %f", m_velocityTimeInterval);
// still have some time left for moving!
if (m_velocityTimeInterval >= dt)
{
m_velocityTimeInterval -= dt;
btVector3 move = m_walkDirection * dt;
stepForwardAndStrafe(collisionWorld, move);
}
#if 0
btScalar dtMoving =
(dt < m_velocityTimeInterval) ? dt : m_velocityTimeInterval;
m_velocityTimeInterval -= dt;
// how far will we move while we are moving?
btVector3 move = m_walkDirection * dtMoving;
//printf(" dtMoving: %f", dtMoving);
// okay, step
stepForwardAndStrafe(collisionWorld, move);
#endif
}
stepDown(collisionWorld, dt);
// printf("\n");
xform.setOrigin(m_currentPosition);
m_ghostObject->setWorldTransform(xform);
}
void KinematicCharacterController::setFallSpeed(btScalar fallSpeed)
{
m_fallSpeed = fallSpeed;
}
void KinematicCharacterController::setJumpSpeed(btScalar jumpSpeed)
{
m_jumpSpeed = jumpSpeed;
}
void KinematicCharacterController::setMaxJumpHeight(btScalar maxJumpHeight)
{
m_maxJumpHeight = maxJumpHeight;
}
bool KinematicCharacterController::canJump() const
{
//return onGround();
return true; // Can jump even in the air!
}
void KinematicCharacterController::jump(const btVector3& v)
{
if (!canJump())
return;
// Add jump impulse:
m_verticalVelocity += m_jumpSpeed;
m_wasJumping = true;
#if 0
currently no jumping.
btTransform xform;
m_rigidBody->getMotionState()->getWorldTransform(xform);
btVector3 up = xform.getBasis()[1];
up.normalize();
btScalar magnitude = (btScalar(1.0) / m_rigidBody->getInvMass()) * btScalar(8.0);
m_rigidBody->applyCentralImpulse(up * magnitude);
#endif
}
void KinematicCharacterController::setGravity(btScalar gravity)
{
m_gravity = gravity;
}
btScalar KinematicCharacterController::getGravity() const
{
return m_gravity;
}
void KinematicCharacterController::setMaxSlope(btScalar slopeRadians)
{
m_maxSlopeRadians = slopeRadians;
m_maxSlopeCosine = btCos(slopeRadians);
}
btScalar KinematicCharacterController::getMaxSlope() const
{
return m_maxSlopeRadians;
}
bool KinematicCharacterController::onGround() const
{
return m_verticalVelocity == 0.0 && m_verticalOffset == 0.0;
}
btVector3* KinematicCharacterController::getUpAxisDirections()
{
static btVector3 sUpAxisDirection[3] = { btVector3(1.0f, 0.0f, 0.0f), btVector3(0.0f, 1.0f, 0.0f), btVector3(0.0f, 0.0f, 1.0f) };
return sUpAxisDirection;
}
void KinematicCharacterController::debugDraw(btIDebugDraw* debugDrawer)
{
}
void KinematicCharacterController::setUpInterpolate(bool value)
{
m_interpolateUp = value;
}

View File

@ -0,0 +1,170 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef KINEMATIC_CHARACTER_CONTROLLER_H
#define KINEMATIC_CHARACTER_CONTROLLER_H
#include <LinearMath/btVector3.h>
#include <BulletDynamics/Character/btCharacterControllerInterface.h>
#include <BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h>
class btCollisionShape;
class btConvexShape;
class btRigidBody;
class btCollisionWorld;
class btCollisionDispatcher;
class btPairCachingGhostObject;
///btKinematicCharacterController is an object that supports a sliding motion in a world.
///It uses a ghost object and convex sweep test to test for upcoming collisions. This is combined with discrete collision detection to recover from penetrations.
///Interaction between btKinematicCharacterController and dynamic rigid bodies needs to be explicity implemented by the user.
ATTRIBUTE_ALIGNED16(class) KinematicCharacterController : public btCharacterControllerInterface
{
protected:
btScalar m_halfHeight;
btPairCachingGhostObject* m_ghostObject;
btConvexShape* m_convexShape;//is also in m_ghostObject, but it needs to be convex, so we store it here to avoid upcast
btScalar m_verticalVelocity;
btScalar m_verticalOffset;
btScalar m_fallSpeed;
btScalar m_jumpSpeed;
btScalar m_maxJumpHeight;
btScalar m_maxSlopeRadians; // Slope angle that is set (used for returning the exact value)
btScalar m_maxSlopeCosine; // Cosine equivalent of m_maxSlopeRadians (calculated once when set, for optimization)
btScalar m_gravity;
btScalar m_turnAngle;
btScalar m_stepHeight;
btScalar m_addedMargin;//@todo: remove this and fix the code
///this is the desired walk direction, set by the user
btVector3 m_walkDirection;
btVector3 m_normalizedDirection;
//some internal variables
btVector3 m_currentPosition;
btScalar m_currentStepOffset;
btVector3 m_targetPosition;
///keep track of the contact manifolds
btManifoldArray m_manifoldArray;
bool m_touchingContact;
btVector3 m_touchingNormal;
bool m_wasOnGround;
bool m_wasJumping;
bool m_useGhostObjectSweepTest;
bool m_useWalkDirection;
btScalar m_velocityTimeInterval;
int m_upAxis;
static btVector3* getUpAxisDirections();
bool m_interpolateUp;
bool full_drop;
bool bounce_fix;
btVector3 computeReflectionDirection(const btVector3& direction, const btVector3& normal);
btVector3 parallelComponent(const btVector3& direction, const btVector3& normal);
btVector3 perpindicularComponent(const btVector3& direction, const btVector3& normal);
bool recoverFromPenetration(btCollisionWorld* collisionWorld);
void stepUp(btCollisionWorld* collisionWorld);
void updateTargetPositionBasedOnCollision(const btVector3& hit_normal, btScalar tangentMag = btScalar(0.0), btScalar normalMag = btScalar(1.0));
void stepForwardAndStrafe(btCollisionWorld* collisionWorld, const btVector3& walkMove);
void stepDown(btCollisionWorld* collisionWorld, btScalar dt);
public:
BT_DECLARE_ALIGNED_ALLOCATOR();
KinematicCharacterController(btPairCachingGhostObject* ghostObject, btConvexShape* convexShape, btScalar stepHeight, int upAxis = 1);
~KinematicCharacterController();
///btActionInterface interface
virtual void updateAction(btCollisionWorld* collisionWorld, btScalar deltaTime)
{
preStep(collisionWorld);
playerStep(collisionWorld, deltaTime);
}
///btActionInterface interface
void debugDraw(btIDebugDraw* debugDrawer);
void setUpAxis(int axis)
{
if (axis < 0)
axis = 0;
if (axis > 2)
axis = 2;
m_upAxis = axis;
}
/// This should probably be called setPositionIncrementPerSimulatorStep.
/// This is neither a direction nor a velocity, but the amount to
/// increment the position each simulation iteration, regardless
/// of dt.
/// This call will reset any velocity set by setVelocityForTimeInterval().
virtual void setWalkDirection(const btVector3& walkDirection);
/// Caller provides a velocity with which the character should move for
/// the given time period. After the time period, velocity is reset
/// to zero.
/// This call will reset any walk direction set by setWalkDirection().
/// Negative time intervals will result in no motion.
virtual void setVelocityForTimeInterval(const btVector3& velocity,
btScalar timeInterval);
void reset(btCollisionWorld* collisionWorld);
void warp(const btVector3& origin);
void preStep(btCollisionWorld* collisionWorld);
void playerStep(btCollisionWorld* collisionWorld, btScalar dt);
void setFallSpeed(btScalar fallSpeed);
void setJumpSpeed(btScalar jumpSpeed);
void setMaxJumpHeight(btScalar maxJumpHeight);
bool canJump() const;
void jump(const btVector3& v = btVector3());
void setGravity(btScalar gravity);
btScalar getGravity() const;
/// The max slope determines the maximum angle that the controller can walk up.
/// The slope angle is measured in radians.
void setMaxSlope(btScalar slopeRadians);
btScalar getMaxSlope() const;
btPairCachingGhostObject* getGhostObject();
void setUseGhostSweepTest(bool useGhostObjectSweepTest)
{
m_useGhostObjectSweepTest = useGhostObjectSweepTest;
}
bool onGround() const;
void setUpInterpolate(bool value);
void reset() {}
};
#endif // BT_KINEMATIC_CHARACTER_CONTROLLER_H

View File

@ -2,7 +2,10 @@
#include "Groups.h"
#include "UserPtr.h"
#include "BulletDebugDraw.h"
#include "Bullet.h"
#include "KinematicCharacterController.h" // Improved btKinematicCharacterController.
#include "CharacterController.h"
namespace verus
{

View File

@ -53,14 +53,7 @@ namespace verus
// Shadow:
void BeginShadow(int split);
void EndShadow(int split);
RShadowMap GetShadowMap() { return _shadowMap; }
bool IsRenderingShadow() const { return _shadowMap.IsRendering(); }
int GetCurrentSplit() const { return _shadowMap.GetCurrentSplit(); }
PCamera GetSunCameraCSM() { return _shadowMap.GetCameraCSM(); }
RcVector4 GetSunShadowSplitRanges() const { return _shadowMap.GetSplitRanges(); }
RcMatrix4 GetSunShadowMatrix(int split) const { return _shadowMap.GetShadowMatrix(split); }
RcMatrix4 GetSunShadowMatrixDS(int split) const { return _shadowMap.GetShadowMatrixDS(split); }
CGI::TexturePtr GetSunShadowTexture() const { return _shadowMap.GetTexture(); }
RCascadedShadowMap GetShadowMap() { return _shadowMap; }
RcPoint3 GetEyePosition(PVector3 pDirFront = nullptr);
};

View File

@ -57,7 +57,7 @@ void BaseMesh::Load(RcBlob blob)
}
else
{
throw VERUS_RECOVERABLE << "Load(), Invalid magic number";
throw VERUS_RECOVERABLE << "Load(), invalid magic number";
}
}
VERUS_LOG_WARN("Load(), Old X3D version");
@ -90,6 +90,7 @@ void BaseMesh::LoadX3D3(RcBlob blob)
{
sp.ReadString(buffer);
_numFaces = atoi(buffer);
_indexCount = _numFaces * 3;
VERUS_RT_ASSERT(_vIndices.empty());
_vIndices.resize(_numFaces * 3);
UINT16* pIB = _vIndices.data();
@ -113,22 +114,18 @@ void BaseMesh::LoadX3D3(RcBlob blob)
vPolyCheck.push_back(tag);
}
std::sort(vPolyCheck.begin(), vPolyCheck.end());
if (std::adjacent_find(vPolyCheck.begin(), vPolyCheck.end()) != vPolyCheck.end())
VERUS_LOG_SESSION(_C("WARNING: Duplicate triangle in " + _url));
if (vPolyCheck.end() != std::adjacent_find(vPolyCheck.begin(), vPolyCheck.end()))
VERUS_LOG_WARN("Duplicate triangle in " << _url);
Vector<UINT16> vSorted;
vSorted.assign(_vIndices.begin(), _vIndices.end());
std::sort(vSorted.begin(), vSorted.end());
bool isolatedVertex = false;
std::adjacent_find(vSorted.begin(), vSorted.end(), [&isolatedVertex](const UINT16& a, const UINT16& b)
{
if (b - a > 1)
isolatedVertex = true;
return false;
});
if (vSorted.end() != std::adjacent_find(vSorted.begin(), vSorted.end(), [](const UINT16& a, const UINT16& b) {return b - a > 1; }))
isolatedVertex = true;
if (isolatedVertex)
VERUS_LOG_SESSION(_C("WARNING: Isolated vertex in " + _url));
VERUS_LOG_WARN("Isolated vertex in " << _url);
if (_numVerts <= vSorted.back())
VERUS_LOG_SESSION(_C("WARNING: Index out of bounds in " + _url));
VERUS_LOG_WARN("Index out of bounds in " << _url);
#endif
sp.Read(&_posDeq[0], 12);
sp.Read(&_posDeq[3], 12);
@ -142,8 +139,8 @@ void BaseMesh::LoadX3D3(RcBlob blob)
#ifdef VERUS_DEBUG
const short* pMin = std::min_element(pVB[i]._pos, pVB[i]._pos + 3);
const short* pMax = std::max_element(pVB[i]._pos, pVB[i]._pos + 3);
mn = CMath::Min(mn, *pMin);
mx = CMath::Max(mx, *pMax);
mn = Math::Min(mn, *pMin);
mx = Math::Max(mx, *pMax);
#endif
}
#ifdef VERUS_DEBUG
@ -210,8 +207,8 @@ void BaseMesh::LoadX3D3(RcBlob blob)
#ifdef VERUS_DEBUG
const short* pMin = std::min_element(pVB[i]._tc0, pVB[i]._tc0 + 2);
const short* pMax = std::max_element(pVB[i]._tc0, pVB[i]._tc0 + 2);
mn = CMath::Min(mn, *pMin);
mx = CMath::Max(mx, *pMax);
mn = Math::Min(mn, *pMin);
mx = Math::Max(mx, *pMax);
#endif
}
#ifdef VERUS_DEBUG

View File

@ -43,6 +43,7 @@ namespace verus
int _numVerts = 0;
int _numFaces = 0;
int _numBones = 0;
int _indexCount = 0;
float _posDeq[6];
float _tc0Deq[4];
float _tc1Deq[4];
@ -61,6 +62,7 @@ namespace verus
int GetNumVerts() const { return _numVerts; }
int GetNumFaces() const { return _numFaces; }
int GetNumBones() const { return _numBones; }
int GetIndexCount() const { return _indexCount; }
virtual void Async_Run(CSZ url, RcBlob blob) override;
@ -101,6 +103,7 @@ namespace verus
void VisitVertices(std::function<Continue(RcPoint3, int)> fn);
Anim::RSkeleton GetSkeleton() { return _skeleton; }
Anim::RcSkeleton GetSkeleton() const { return _skeleton; }
String ToXmlString() const;
String ToObjString() const;

View File

@ -0,0 +1,70 @@
#include "verus.h"
using namespace verus;
using namespace verus::Scene;
void CameraOrbit::Update()
{
const Vector3 toEye = Matrix3::rotationZYX(Vector3(_pitch, _yaw, 0)) * Vector3(0, 0, _radius);
MoveEyeTo(_posAt + toEye);
MainCamera::Update();
}
void CameraOrbit::DragController_GetParams(float& x, float& y)
{
x = _yaw;
y = _pitch;
}
void CameraOrbit::DragController_SetParams(float x, float y)
{
_yaw = fmod(x, VERUS_2PI);
_pitch = Math::Clamp(y, -VERUS_PI * 0.49f, VERUS_PI * 0.49f);
Update();
}
void CameraOrbit::DragController_GetRatio(float& x, float& y)
{
x = -VERUS_2PI / 1440.f;
y = -VERUS_2PI / 1440.f;
}
void CameraOrbit::MulRadiusBy(float a)
{
_radius *= a;
Update();
}
void CameraOrbit::SaveState(int slot)
{
StringStream ss;
ss << _C(Utils::I().GetWritablePath()) << "/CameraState.xml";
IO::Xml xml;
xml.SetFilename(_C(ss.str()));
xml.Load();
char txt[16];
sprintf_s(txt, "slot%d", slot);
char params[40];
sprintf_s(params, "|%f %f %f", _pitch, _yaw, _radius);
xml.Set(txt, _C(_posAt.ToString() + params));
}
void CameraOrbit::LoadState(int slot)
{
StringStream ss;
ss << _C(Utils::I().GetWritablePath()) << "/CameraState.xml";
IO::Xml xml;
xml.SetFilename(_C(ss.str()));
xml.Load();
char txt[16];
sprintf_s(txt, "slot%d", slot);
CSZ v = xml.GetS(txt);
if (v)
{
CSZ p = strchr(v, '|');
_posAt.FromString(v);
sscanf(p + 1, "%f %f %f", &_pitch, &_yaw, &_radius);
_update |= Update::v;
Update();
}
}

View File

@ -0,0 +1,33 @@
#pragma once
namespace verus
{
namespace Scene
{
class CameraOrbit : public MainCamera, public Input::DragControllerDelegate
{
float _pitch = 0;
float _yaw = 0;
float _radius = 10;
public:
virtual void Update() override;
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;
float GetRadius() const { return _radius; }
void MulRadiusBy(float a);
float GetPitch() const { return _pitch; }
float GetYaw() const { return _yaw; }
void SetPitch(float a) { _pitch = a; }
void SetYaw(float a) { _yaw = a; }
virtual void SaveState(int slot) override;
virtual void LoadState(int slot) override;
};
VERUS_TYPEDEFS(CameraOrbit);
}
}

View File

@ -20,8 +20,8 @@ void Helpers::Init()
// Grid:
_vGrid.reserve(92);
const UINT32 colorMain = VERUS_COLOR_RGBA(0, 0, 0, 255);
const UINT32 colorExtra = VERUS_COLOR_RGBA(80, 80, 80, 255);
const UINT32 colorMain = VERUS_COLOR_RGBA(32, 32, 32, 255);
const UINT32 colorExtra = VERUS_COLOR_RGBA(64, 64, 64, 255);
const int edgeMin = 5, edgeMax = 55;
for (int i = -edgeMin; i <= edgeMin; ++i)
{
@ -157,7 +157,7 @@ void Helpers::Done()
void Helpers::DrawGrid()
{
CGI::DebugDraw::I().Begin(CGI::DebugDraw::Type::lines);
const int numLines = _vGrid.size() >> 1;
const int numLines = Utils::Cast32(_vGrid.size() >> 1);
VERUS_FOR(i, numLines)
{
CGI::DebugDraw::I().AddLine(
@ -177,7 +177,7 @@ void Helpers::DrawBasis(PcTransform3 pMat, int axis, bool overlay)
axis = 2;
const UINT32 hover = VERUS_COLOR_RGBA(200, 200, 0, 255);
CGI::DebugDraw::I().Begin(CGI::DebugDraw::Type::lines, pMat, !overlay);
const int numLines = (int)_vBasis.size() >> 1;
const int numLines = Utils::Cast32(_vBasis.size() >> 1);
VERUS_FOR(i, numLines)
{
const bool isHover = (i / 5 == axis);
@ -192,7 +192,7 @@ void Helpers::DrawBasis(PcTransform3 pMat, int axis, bool overlay)
void Helpers::DrawCircle(RcPoint3 pos, float radius, UINT32 color, Scene::RTerrain terrain)
{
CGI::DebugDraw::I().Begin(CGI::DebugDraw::Type::lines, nullptr, false);
const int numLines = _vCircle.size() >> 1;
const int numLines = Utils::Cast32(_vCircle.size() >> 1);
Point3 a = VMath::scale(_vCircle[0]._pos, radius) + Vector3(pos);
float xz[2] = { a.getX(), a.getZ() };
a.setY(terrain.GetHeightAt(xz));
@ -211,7 +211,7 @@ void Helpers::DrawCircle(RcPoint3 pos, float radius, UINT32 color, Scene::RTerra
void Helpers::DrawBox(PcTransform3 pMat, UINT32 color)
{
CGI::DebugDraw::I().Begin(CGI::DebugDraw::Type::lines, pMat);
const int numLines = _vBox.size() >> 1;
const int numLines = Utils::Cast32(_vBox.size() >> 1);
VERUS_FOR(i, numLines)
{
CGI::DebugDraw::I().AddLine(
@ -226,7 +226,7 @@ void Helpers::DrawLight(RcPoint3 pos, UINT32 color, PcPoint3 pTarget)
{
Transform3 matW = Transform3::translation(Vector3(pos));
CGI::DebugDraw::I().Begin(CGI::DebugDraw::Type::lines, &matW);
const int numLines = _vLight.size() >> 1;
const int numLines = Utils::Cast32(_vLight.size() >> 1);
VERUS_FOR(i, numLines)
{
CGI::DebugDraw::I().AddLine(

View File

@ -3,8 +3,8 @@
using namespace verus;
using namespace verus::Scene;
CGI::ShaderPwn Mesh::s_shader;
CGI::PipelinePwns<1> Mesh::s_pipe;
CGI::ShaderPwn Mesh::s_shader;
CGI::PipelinePwns<Mesh::PIPE_MAX> Mesh::s_pipe;
Mesh::UB_PerFrame Mesh::s_ubPerFrame;
Mesh::UB_PerMaterialFS Mesh::s_ubPerMaterialFS;
@ -42,6 +42,7 @@ void Mesh::InitStatic()
void Mesh::DoneStatic()
{
s_pipe.Done();
s_shader.Done();
}
@ -56,10 +57,48 @@ void Mesh::Init(RcDesc desc)
void Mesh::Done()
{
BaseMesh::Done();
VERUS_DONE(Mesh);
}
void Mesh::Bind(CGI::CommandBufferPtr cb, UINT32 bindingsFilter)
void Mesh::BindPipeline(PIPE pipe, CGI::CommandBufferPtr cb)
{
VERUS_QREF_RENDERER;
if (!s_pipe[pipe])
{
static CSZ branches[] =
{
"#",
"#DepthRobotic",
"#DepthSkinned",
"#Instanced",
"#Robotic",
"#Skinned"
};
CGI::PipelineDesc pipeDesc(_geo, s_shader, branches[pipe], renderer.GetDS().GetRenderPassID());
switch (pipe)
{
case PIPE_DEPTH_ROBOTIC:
case PIPE_DEPTH_SKINNED:
pipeDesc._colorAttachBlendEqs[0] = "";
pipeDesc.DepthBiasEnable();
default:
pipeDesc._colorAttachBlendEqs[0] = VERUS_COLOR_BLEND_OFF;
pipeDesc._colorAttachBlendEqs[1] = VERUS_COLOR_BLEND_OFF;
pipeDesc._colorAttachBlendEqs[2] = VERUS_COLOR_BLEND_OFF;
pipeDesc._colorAttachBlendEqs[3] = VERUS_COLOR_BLEND_OFF;
}
pipeDesc._vertexInputBindingsFilter = _bindingsMask;
s_pipe[pipe].Init(pipeDesc);
}
cb->BindPipeline(s_pipe[pipe]);
}
void Mesh::BindGeo(CGI::CommandBufferPtr cb)
{
BindGeo(cb, _bindingsMask);
}
void Mesh::BindGeo(CGI::CommandBufferPtr cb, UINT32 bindingsFilter)
{
cb->BindVertexBuffers(_geo, bindingsFilter);
cb->BindIndexBuffer(_geo);
@ -90,6 +129,12 @@ void Mesh::UpdateUniformBufferSkeletonVS()
_skeleton.UpdateUniformBufferArray(s_ubSkeletonVS._vMatBones);
}
void Mesh::UpdateUniformBufferPerObject(RcTransform3 tr)
{
s_ubPerObject._matW = tr.UniformBufferFormat();
s_ubPerObject._userColor = Vector4(1, 0, 0, 1).GLM();
}
void Mesh::UpdateUniformBufferPerObject(Point3 pos)
{
const Transform3 matT = Transform3::translation(Vector3(pos));

View File

@ -9,6 +9,17 @@ namespace verus
public:
#include "../Shaders/DS_Mesh.inc.hlsl"
enum PIPE
{
PIPE_MAIN,
PIPE_DEPTH_ROBOTIC,
PIPE_DEPTH_SKINNED,
PIPE_INSTANCED,
PIPE_ROBOTIC,
PIPE_SKINNED,
PIPE_MAX
};
struct PerInstanceData
{
Vector4 _matPart0 = Vector4(0);
@ -18,13 +29,13 @@ namespace verus
};
private:
static CGI::ShaderPwn s_shader;
static CGI::PipelinePwns<1> s_pipe;
static UB_PerFrame s_ubPerFrame;
static UB_PerMaterialFS s_ubPerMaterialFS;
static UB_PerMeshVS s_ubPerMeshVS;
static UB_SkeletonVS s_ubSkeletonVS;
static UB_PerObject s_ubPerObject;
static CGI::ShaderPwn s_shader;
static CGI::PipelinePwns<PIPE_MAX> s_pipe;
static UB_PerFrame s_ubPerFrame;
static UB_PerMaterialFS s_ubPerMaterialFS;
static UB_PerMeshVS s_ubPerMeshVS;
static UB_SkeletonVS s_ubSkeletonVS;
static UB_PerObject s_ubPerObject;
CGI::GeometryPwn _geo;
Vector<PerInstanceData> _vInstanceBuffer;
@ -51,7 +62,9 @@ namespace verus
void Init(RcDesc desc = Desc());
void Done();
void Bind(CGI::CommandBufferPtr cb, UINT32 bindingsFilter);
void BindPipeline(PIPE pipe, CGI::CommandBufferPtr cb);
void BindGeo(CGI::CommandBufferPtr cb);
void BindGeo(CGI::CommandBufferPtr cb, UINT32 bindingsFilter);
static CGI::ShaderPtr GetShader() { return s_shader; }
static UB_PerMaterialFS& GetUbPerMaterialFS() { return s_ubPerMaterialFS; }
@ -59,6 +72,7 @@ namespace verus
void UpdateUniformBufferPerMaterialFS();
void UpdateUniformBufferPerMeshVS();
void UpdateUniformBufferSkeletonVS();
void UpdateUniformBufferPerObject(RcTransform3 tr);
void UpdateUniformBufferPerObject(Point3 pos);
CGI::GeometryPtr GetGeometry() const { return _geo; }

View File

@ -1,6 +1,7 @@
#pragma once
#include "Camera.h"
#include "CameraOrbit.h"
#include "BaseMesh.h"
#include "Mesh.h"
#include "Terrain.h"

View File

@ -27,7 +27,7 @@ bool SceneManager::IsDrawingDepth(DrawDepth dd)
if (DrawDepth::automatic == dd)
{
VERUS_QREF_ATMO;
return atmo.IsRenderingShadow();
return atmo.GetShadowMap().IsRendering();
}
else
return DrawDepth::yes == dd;

View File

@ -91,6 +91,8 @@ void ShadowMap::Begin(RcVector3 dirToSun, float zNear, float zFar)
_camera.Update();
_pSceneCamera = sm.SetCamera(&_camera);
_config.setX((zFar - zNear) * 2);
renderer.GetCommandBuffer()->BeginRenderPass(_rp, _fb,
{
_tex->GetClearValue()
@ -355,6 +357,8 @@ void CascadedShadowMap::Begin(RcVector3 dirToSun, float zNear, float zFar, int s
_camera.Update();
_pSceneCamera = sm.SetCamera(&_camera);
_config.setX((zFar - zNear) * 2);
if (0 == _currentSplit)
{
renderer.GetCommandBuffer()->BeginRenderPass(_rp, _fb,
@ -363,7 +367,7 @@ void CascadedShadowMap::Begin(RcVector3 dirToSun, float zNear, float zFar, int s
});
}
const int s = _side / 2;
const float s = static_cast<float>(_side / 2);
switch (_currentSplit)
{
case 0: renderer.GetCommandBuffer()->SetViewport({ Vector4(0, 0, s, s) }); break;

View File

@ -9,6 +9,7 @@ namespace verus
protected:
Matrix4 _matShadow;
Matrix4 _matShadowDS;
Vector4 _config = Vector4(0);
CGI::TexturePwn _tex;
Camera _camera;
PCamera _pSceneCamera = nullptr;
@ -37,6 +38,8 @@ namespace verus
RcMatrix4 GetShadowMatrix() const;
RcMatrix4 GetShadowMatrixDS() const;
RcVector4 GetConfig() { return _config; }
CGI::TexturePtr GetTexture() const;
PCamera GetSceneCamera() { return _pSceneCamera; }

View File

@ -43,8 +43,13 @@ void TerrainPhysics::Init(Physics::PUserPtr p, int w, int h, float heightScale)
pBody->setFriction(Physics::Bullet::GetFriction(Physics::Material::wood));
pBody->setRestitution(Physics::Bullet::GetRestitution(Physics::Material::wood));
pBody->setUserPointer(p);
const int f = pBody->getCollisionFlags();
pBody->setCollisionFlags(f | btCollisionObject::CF_DISABLE_VISUALIZE_OBJECT);
#ifndef _DEBUG
if (w >= 128 || h >= 128)
#endif
{
const int f = pBody->getCollisionFlags();
pBody->setCollisionFlags(f | btCollisionObject::CF_DISABLE_VISUALIZE_OBJECT);
}
}
void TerrainPhysics::Done()
@ -432,6 +437,7 @@ void Terrain::Init(RcDesc desc)
_csidVS = s_shader->BindDescriptorSetTextures(0, { _tex[TEX_HEIGHTMAP] });
OnHeightModified();
AddNewRigidBody();
_vLayerUrls.reserve(s_maxNumLayers);
}
@ -470,9 +476,9 @@ void Terrain::Layout()
PCamera pPrevCamera = nullptr;
Camera cam;
// For CSM we need to create geometry beyond the view frustum (1st slice):
if (settings._sceneShadowQuality >= App::Settings::ShadowQuality::cascaded && atmo.IsRenderingShadow())
if (settings._sceneShadowQuality >= App::Settings::ShadowQuality::cascaded && atmo.GetShadowMap().IsRendering())
{
PCamera pCameraCSM = atmo.GetSunCameraCSM();
PCamera pCameraCSM = atmo.GetShadowMap().GetCameraCSM();
if (pCameraCSM)
pPrevCamera = sm.SetCamera(pCameraCSM);
}
@ -905,16 +911,15 @@ void Terrain::OnHeightModified()
UpdateHeightmapTexture();
UpdateNormalsTexture();
//UpdateLandTexture();
//UpdateRigidBody();
UpdateRigidBodyData();
}
void Terrain::AddNewRigidBody()
{
UpdateRigidBody();
_physics.Init(this, _mapSide, _mapSide, ConvertHeight(static_cast<short>(1)));
}
void Terrain::UpdateRigidBody()
void Terrain::UpdateRigidBodyData()
{
auto& v = _physics.GetData();
v.resize(_mapSide * _mapSide);

View File

@ -208,7 +208,7 @@ namespace verus
// Physics:
void AddNewRigidBody();
void UpdateRigidBody();
void UpdateRigidBodyData();
};
VERUS_TYPEDEFS(Terrain);
}

View File

@ -236,6 +236,7 @@ DS_ACC_FSO mainFS(VSO si)
g_texShadow,
g_samShadow,
tcShadow,
g_ubShadowFS._shadowConfig,
g_ubShadowFS._splitRanges,
g_ubShadowFS._matSunShadow,
g_ubShadowFS._matSunShadowCSM1,
@ -277,10 +278,12 @@ DS_ACC_FSO mainFS(VSO si)
so.target0.rgb = maxDiff * litRet.y; // Lambert's cosine law.
so.target1.rgb = maxSpec * saturate(litRet.z * intensitySpec) + diffBoost;
#endif
so.target0.rgb = max(so.target0.rgb, emission.x * GetEmissionScale());
so.target1.rgb = min(so.target1.rgb, 1.0 - emission.x * GetEmissionScale());
so.target0.rgb = max(so.target0.rgb, emission.x);
so.target1.rgb = min(so.target1.rgb, 1.0 - emission.x);
so.target0.a = 1.0;
so.target1.a = 1.0;
so.target0 = HDRColorToSRGB(so.target0);
so.target1 = HDRColorToSRGB(so.target1);
}
#if defined(DEF_OMNI) || defined(DEF_SPOT)
else

View File

@ -21,11 +21,11 @@ VERUS_UBUFFER UB_PerMeshVS
VERUS_UBUFFER UB_ShadowFS
{
float4 _shadowTexSize;
matrix _matSunShadow;
matrix _matSunShadowCSM1;
matrix _matSunShadowCSM2;
matrix _matSunShadowCSM3;
float4 _shadowConfig;
float4 _splitRanges;
};

View File

@ -65,6 +65,8 @@ FSO mainFS(VSO si)
const float4 rawAccDiff = g_texAccDiff.Sample(g_samAccDiff, si.tc0);
const float4 rawAccSpec = g_texAccSpec.Sample(g_samAccSpec, si.tc0);
const float4 accDiff = HDRColorToLinear(rawAccDiff);
const float4 accSpec = HDRColorToLinear(rawAccSpec);
const float ssaoDiff = 1.0;
const float ssaoSpec = 1.0;
@ -79,12 +81,15 @@ FSO mainFS(VSO si)
const float gray = Grayscale(colorAmbient);
const float3 colorGround = lerp(colorAmbient, float3(1, 0.88, 0.47) * gray, saturate(gray * 14.0));
const float3 colorAmbientFinal = lerp(colorGround, colorAmbient, saturate(normalW.y * 2.0 + 0.5));
const float3 color = lerp(
ApplyEmission(albedo, emission.x) * saturate(rawAccDiff.rgb * ssaoDiff + colorAmbientFinal * ssaoAmb) + rawAccSpec.rgb * ssaoSpec,
g_ubComposeFS._fogColor.rgb,
fog);
so.color.rgb = color;
const float3 color =
albedo * saturate(accDiff.rgb * ssaoDiff + colorAmbientFinal * ssaoAmb) +
accSpec.rgb * ssaoSpec +
albedo * emission.x;
const float3 colorWithFog = lerp(color, g_ubComposeFS._fogColor.rgb, fog);
so.color.rgb = lerp(colorWithFog, g_ubComposeFS._colorBackground.rgb, floor(rawGBuffer1) * g_ubComposeFS._colorBackground.a);
so.color.a = 1.0;
return so;

View File

@ -8,6 +8,7 @@ VERUS_UBUFFER UB_ComposeFS
{
mataff _matInvV;
float4 _colorAmbient;
float4 _colorBackground;
float4 _fogColor;
float4 _zNearFarEx;
};

View File

@ -155,9 +155,9 @@ void mainFS(VSO si)
}
#endif
#else
_DS_FSO mainFS(VSO si)
DS_FSO mainFS(VSO si)
{
_DS_FSO so;
DS_FSO so;
#ifdef DEF_SOLID
DS_Reset(so);

View File

@ -1,4 +1,5 @@
#include "Lib.hlsl"
#include "LibColor.hlsl"
#include "LibDeferredShading.hlsl"
#include "DS_Terrain.inc.hlsl"

View File

@ -10,6 +10,27 @@ float4 ColorToSRGB(float4 x)
return float4(rgb, x.a);
}
// HDR from 0.0 to 12.0, where 1.0 - night, 10.0 - bright daylight, 11.0 - sky, 12.0 - ultra bright sun:
float4 HDRColorToLinear(float4 x)
{
return float4(x.rgb * x.rgb * 12.0, x.a);
}
float4 HDRColorToSRGB(float4 x)
{
return float4(sqrt(saturate(x.rgb * (1.0 / 12.0))), x.a);
}
// See: https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/
float3 ToneMappingACES(float3 x)
{
const float a = 2.51f;
const float b = 0.03f;
const float c = 2.43f;
const float d = 0.59f;
const float e = 0.14f;
return saturate((x * (a * x + b)) / (x * (c * x + d) + e));
}
// See: https://en.wikipedia.org/wiki/Grayscale
float Grayscale(float3 color)
{
@ -22,6 +43,12 @@ float3 Desaturate(float3 color, float alpha, float lum = 1.0)
return lerp(color, gray, alpha);
}
float3 DesaturateFilmic(float3 color)
{
const float gray = Grayscale(color);
return lerp(color, gray, saturate(gray * gray * gray));
}
// See: http://www.chilliant.com/rgb2hsv.html
float3 ConvertRGBtoHCV(float3 color)
{

View File

@ -5,15 +5,6 @@ struct DS_FSO
float4 target2 : SV_Target2; // {normal, emission, motion}
float4 target3 : SV_Target3; // {lam, metal, gloss}
};
struct DS_FSO_DEPTH
{
float4 color : SV_Target0;
};
#ifdef DEF_DEPTH
# define _DS_FSO DS_FSO_DEPTH
#else
# define _DS_FSO DS_FSO
#endif
struct DS_ACC_FSO
{
@ -37,16 +28,6 @@ float3 DecodeNormal(float2 enc)
return float3(fenc * g, f2.y);
}
float GetEmissionScale()
{
return 4.0;
}
float3 ApplyEmission(float3 color, float emission)
{
return color * (1.0 + emission * GetEmissionScale());
}
void DS_Reset(out DS_FSO so)
{
so.target0 = 0.0;
@ -59,7 +40,7 @@ void DS_Test(out DS_FSO so, float3 normal, float spec, float gloss)
{
so.target0 = float4(0.5, 0.5, 0.5, spec);
so.target1 = 0.0;
so.target2 = float4(EncodeNormal(normal), 0.5, 0.5);
so.target2 = float4(EncodeNormal(normal), 0.25, 0.5);
so.target3 = float4(1.0 / 8.0, 0.5, 0.5, gloss * (1.0 / 64.0));
}
@ -90,15 +71,14 @@ void DS_SetNormal(inout DS_FSO so, float3 normal)
float2 DS_GetEmission(float4 gbuffer)
{
const float x2 = gbuffer.b * 2.0;
return float2(
saturate(x2 - 1.0),
saturate(1.0 - x2));
const float2 em_skin = saturate((gbuffer.b - 0.25) * float2(1.0 / 0.75, -1.0 / 0.25));
return float2(HDRColorToLinear(em_skin.x).r, em_skin.y);
}
void DS_SetEmission(inout DS_FSO so, float emission, float skin)
{
so.target2.b = (emission - skin) * 0.5 + 0.5;
const float em = HDRColorToSRGB(emission).r;
so.target2.b = (3.0 * em - skin) * 0.25 + 0.25;
}
float2 DS_GetLamScaleBias(float4 gbuffer)

View File

@ -44,7 +44,8 @@ float PCF(
SamplerComparisonState samCmp,
Texture2D tex,
SamplerState sam,
float3 tc)
float3 tc,
float4 config)
{
#if _SHADOW_QUALITY <= 2
return texCmp.SampleCmpLevelZero(samCmp, tc.xy, tc.z).r;
@ -72,14 +73,10 @@ float PCF(
const float ret = sum * (1.0 / num);
if (dzBlockers_numBlockers.y > 0.0)
{
#if _SHADOW_QUALITY <= 3
const float scale = 655.36;
#else
const float scale = 20000.0;
#endif
const float penumbraScale = config.x;
const float dzBlockers = dzBlockers_numBlockers.x / dzBlockers_numBlockers.y;
const float penumbra = saturate(dzFrag - dzBlockers);
const float contrast = 1.0 + max(0.0, 3.0 - penumbra * scale);
const float contrast = 1.0 + max(0.0, 3.0 - penumbra * penumbraScale);
return saturate((ret - 0.5) * contrast + 0.5);
}
else
@ -94,12 +91,13 @@ float ShadowMap(
SamplerComparisonState samCmp,
Texture2D tex,
SamplerState sam,
float4 tc)
float4 tc,
float4 config)
{
#if _SHADOW_QUALITY <= 0
return 1.0;
#else
const float ret = PCF(texCmp, samCmp, tex, sam, tc.xyz);
const float ret = PCF(texCmp, samCmp, tex, sam, tc.xyz, config);
const float2 center = tc.xy * 2.0 - 1.0;
return max(ret, saturate(dot(center, center) * (9.0 / 4.0) - 1.0));
#endif
@ -111,6 +109,7 @@ float ShadowMapCSM(
Texture2D tex,
SamplerState sam,
float4 pos,
float4 config,
float4 ranges,
matrix mat0,
matrix mat1,
@ -130,28 +129,28 @@ float ShadowMapCSM(
contrast = contrastScale * contrastScale * contrastScale;
const float3 tc = mul(p, mat0).xyz;
ret = max(PCF(texCmp, samCmp, tex, sam, tc), fade);
ret = max(PCF(texCmp, samCmp, tex, sam, tc, config), fade);
}
else if (pos.w > ranges.y)
{
contrast = contrastScale * contrastScale;
const float3 tc = mul(p, mat1).xyz;
ret = PCF(texCmp, samCmp, tex, sam, tc);
ret = PCF(texCmp, samCmp, tex, sam, tc, config);
}
else if (pos.w > ranges.z)
{
contrast = contrastScale;
const float3 tc = mul(p, mat2).xyz;
ret = PCF(texCmp, samCmp, tex, sam, tc);
ret = PCF(texCmp, samCmp, tex, sam, tc, config);
}
else
{
const float3 tc = mul(p, mat3).xyz;
ret = PCF(texCmp, samCmp, tex, sam, tc);
ret = PCF(texCmp, samCmp, tex, sam, tc, config);
}
return saturate((ret - 0.5) * contrast + 0.5);
#else
return ShadowMap(texCmp, samCmp, tex, sam, pos);
return ShadowMap(texCmp, samCmp, tex, sam, pos, config);
#endif
}

View File

@ -12,8 +12,14 @@ extern "C"
# include "libb64/cdecode.h"
#endif
// fast_atof (http://www.leapsecond.com/tools/fast_atof.c)
extern "C"
{
double fast_atof(const char* p);
}
// GLM (https://github.com/g-truc/glm):
#define GLM_ENABLE_EXPERIMENTAL
#define GLM_FORCE_CTOR_INIT
#include "glm-0.9.9.6/glm/glm/glm.hpp"
#include "glm-0.9.9.6/glm/glm/gtc/packing.hpp"
#include "glm-0.9.9.6/glm/glm/gtc/quaternion.hpp"
@ -33,6 +39,9 @@ extern "C"
// MD5:
#include "md5.h"
// Native File Dialog (https://github.com/mlabbe/nativefiledialog):
#include "nativefiledialog/nfd.h"
// pugixml (https://pugixml.org/):
#include "pugixml-1.10/pugixml.hpp"

Some files were not shown because too many files have changed in this diff Show More