diff --git a/Include/FlashlightEngine/EngineApplication.hpp b/Include/FlashlightEngine/EngineApplication.hpp index 66753a7..09f8957 100644 --- a/Include/FlashlightEngine/EngineApplication.hpp +++ b/Include/FlashlightEngine/EngineApplication.hpp @@ -35,7 +35,8 @@ namespace FlashlightEngine { private: ShaderCollection m_MainShaderCollection; - std::unique_ptr m_TriangleVertexBuffer; + std::unique_ptr m_CubeVertexBuffer; + std::unique_ptr m_CubeIndexBuffer; std::shared_ptr m_LinearSampler; std::unique_ptr m_FrogTexture; diff --git a/Include/FlashlightEngine/Renderer/Enums.hpp b/Include/FlashlightEngine/Renderer/Enums.hpp index 8b363e1..c1d2107 100644 --- a/Include/FlashlightEngine/Renderer/Enums.hpp +++ b/Include/FlashlightEngine/Renderer/Enums.hpp @@ -33,6 +33,11 @@ namespace FlashlightEngine { HullShader, DomainShader }; + + enum class IndexType { + UInt16, + UInt32 + }; } #endif // FL_RENDERER_ENUMS_HPP diff --git a/Include/FlashlightEngine/Renderer/Renderer.hpp b/Include/FlashlightEngine/Renderer/Renderer.hpp index d97b147..8adaa95 100644 --- a/Include/FlashlightEngine/Renderer/Renderer.hpp +++ b/Include/FlashlightEngine/Renderer/Renderer.hpp @@ -39,11 +39,13 @@ namespace FlashlightEngine { VertexType vertexType, const std::vector& offsets, UInt32 startSlot = 0) const; + void BindIndexBuffer(ID3D11Buffer* buffer, IndexType indexType) const; void BindConstantBuffers(const std::vector& buffers, PipelineBindPoint bindPoint, UInt32 startSlot = 0) const; void SetPrimitiveTopology(PrimitiveTopology topology) const; void Draw(UInt32 vertexCount, UInt32 firstVertex = 0) const; + void DrawIndexed(UInt32 indexCount, UInt32 firstIndex = 0, UInt32 baseVertex = 0) const; [[nodiscard]] ShaderCollection CreateShaderCollection(VertexType vertexType, const std::filesystem::path& vertexShaderPath, @@ -82,7 +84,12 @@ namespace FlashlightEngine { std::shared_ptr m_Device; std::shared_ptr m_Swapchain; + ComPtr m_DepthStencilState; + ComPtr m_RasterizerState; + Float32 m_ClearColor[4] = {0.1f, 0.1f, 0.1f, 0.1f}; + + void CreateDepthStencilState(); }; } diff --git a/Include/FlashlightEngine/Renderer/Swapchain.hpp b/Include/FlashlightEngine/Renderer/Swapchain.hpp index c731aaf..79b94aa 100644 --- a/Include/FlashlightEngine/Renderer/Swapchain.hpp +++ b/Include/FlashlightEngine/Renderer/Swapchain.hpp @@ -26,6 +26,7 @@ namespace FlashlightEngine { [[nodiscard]] inline ComPtr GetSwapchain() const; [[nodiscard]] inline ComPtr GetRTV() const; + [[nodiscard]] inline ComPtr GetDSV() const; void OnResize(UInt32 width, UInt32 height); @@ -35,6 +36,7 @@ namespace FlashlightEngine { private: ComPtr m_Swapchain{nullptr}; ComPtr m_RenderTargetView{nullptr}; + ComPtr m_DepthStencilView{nullptr}; std::shared_ptr m_Window{nullptr}; std::shared_ptr m_Device{nullptr}; diff --git a/Include/FlashlightEngine/Renderer/Swapchain.inl b/Include/FlashlightEngine/Renderer/Swapchain.inl index ca43edf..953d0c0 100644 --- a/Include/FlashlightEngine/Renderer/Swapchain.inl +++ b/Include/FlashlightEngine/Renderer/Swapchain.inl @@ -12,4 +12,8 @@ namespace FlashlightEngine { inline ComPtr Swapchain::GetRTV() const { return m_RenderTargetView; } + + inline ComPtr Swapchain::GetDSV() const { + return m_DepthStencilView; + } } diff --git a/Resources/Shaders/Main.ps.hlsl b/Resources/Shaders/Main.ps.hlsl index 8b3a243..2fd9b5d 100644 --- a/Resources/Shaders/Main.ps.hlsl +++ b/Resources/Shaders/Main.ps.hlsl @@ -5,12 +5,11 @@ struct VSOutput float2 Uv: TEXCOORD0; }; -sampler Sampler : register(s0); +SamplerState Sampler : register(s0); Texture2D Texture : register(t0); float4 Main(VSOutput input): SV_Target { - float4 texel = Texture.Sample(Sampler, input.Uv); - return float4(input.Color, 0.50f) * texel; + return input.Color.xyzz; } \ No newline at end of file diff --git a/Source/FlashlightEngine/EngineApplication.cpp b/Source/FlashlightEngine/EngineApplication.cpp index 4fc45dc..28e58c1 100644 --- a/Source/FlashlightEngine/EngineApplication.cpp +++ b/Source/FlashlightEngine/EngineApplication.cpp @@ -20,20 +20,52 @@ namespace FlashlightEngine { ); constexpr VertexPositionColorUv vertices[] = { - {Position{0.0f, 0.5f, 0.0f}, Color{0.25f, 0.39f, 0.19f}, Uv{0.5f, 0.0f}}, - {Position{0.5f, -0.5f, 0.0f}, Color{0.44f, 0.75f, 0.35f}, Uv{1.0f, 1.0f}}, - {Position{-0.5f, -0.5f, 0.0f}, Color{0.38f, 0.55f, 0.20f}, Uv{0.0f, 1.0f}}, + //Front + {Position{-0.5f, -0.5f, 0.5f}, Color{1.0f, 0.0f, 0.0f}, Uv{0.0f, 1.0f}}, + {Position{0.5f, -0.5f, 0.5f}, Color{0.0f, 1.0f, 0.0f}, Uv{1.0f, 1.0f}}, + {Position{-0.5f, 0.5f, 0.5f}, Color{0.0f, 0.0f, 1.0f}, Uv{0.0f, 0.0f}}, + {Position{0.5f, 0.5f, 0.5f}, Color{1.0f, 1.0f, 0.0f}, Uv{1.0f, 0.0f}}, + + //Back + {Position{-0.5f, -0.5f, -0.5f}, Color{0.0f, 1.0f, 1.0f}, Uv{0.0f, 1.0f}}, + {Position{0.5f, -0.5f, -0.5f}, Color{1.0f, 0.0f, 1.0f}, Uv{1.0f, 1.0f}}, + {Position{-0.5f, 0.5f, -0.5f}, Color{0.0f, 0.0f, 0.0f}, Uv{0.0f, 0.0f}}, + {Position{0.5f, 0.5f, -0.5f}, Color{1.0f, 1.0f, 1.0f}, Uv{1.0f, 0.0f}}, }; - // RGB triangle - //constexpr VertexPositionColorUv vertices[] = { - // {Position{0.0f, 0.5f, 0.0f}, Color{1.0f, 0.0f, 0.0f}, Uv{0.5f, 0.0f}}, - // {Position{0.5f, -0.5f, 0.0f}, Color{0.0f, 1.0f, 0.0f}, Uv{1.0f, 1.0f}}, - // {Position{-0.5f, -0.5f, 0.0f}, Color{0.0f, 0.0f, 1.0f}, Uv{0.0f, 1.0f}}, - //}; + constexpr uint32_t indices[] = + { + //Top + 7, 6, 2, + 2, 3, 7, + + //Bottom + 0, 4, 5, + 5, 1, 0, + + //Left + 0, 2, 6, + 6, 4, 0, + + //Right + 7, 3, 1, + 1, 5, 7, + + //Front + 3, 2, 0, + 0, 1, 3, + + //Back + 4, 6, 7, + 7, 5, 4 + }; + + m_CubeVertexBuffer = m_Renderer->CreateBuffer(vertices, sizeof(vertices), D3D11_USAGE_IMMUTABLE, + D3D11_BIND_VERTEX_BUFFER, "Cube Vertex Buffer"); + + m_CubeIndexBuffer = m_Renderer->CreateBuffer(indices, sizeof(indices), D3D11_USAGE_IMMUTABLE, + D3D11_BIND_INDEX_BUFFER, "Cube Index Buffer"); - m_TriangleVertexBuffer = m_Renderer->CreateBuffer(vertices, sizeof(vertices), D3D11_USAGE_IMMUTABLE, - D3D11_BIND_VERTEX_BUFFER, "Triangle Vertex Buffer"); m_PerFrameConstantBuffer = m_Renderer->CreateEmptyBuffer(sizeof(PerFrameConstantBuffer), D3D11_USAGE_DYNAMIC, @@ -111,7 +143,8 @@ namespace FlashlightEngine { m_Renderer->UseShaderCollection(m_MainShaderCollection); - m_Renderer->BindVertexBuffers({m_TriangleVertexBuffer->GetBuffer().Get()}, VertexType::PositionColorUv, {0}); + m_Renderer->BindVertexBuffers({m_CubeVertexBuffer->GetBuffer().Get()}, VertexType::PositionColorUv, {0}); + m_Renderer->BindIndexBuffer(m_CubeIndexBuffer->GetBuffer().Get(), IndexType::UInt32); m_Renderer->BindConstantBuffers({ m_PerFrameConstantBuffer->GetBuffer().Get(), m_PerObjectConstantBuffer->GetBuffer().Get() @@ -126,7 +159,7 @@ namespace FlashlightEngine { m_FallbackTexture->UseTexture(0, PipelineBindPoint::PixelShader); } - m_Renderer->Draw(3); + m_Renderer->DrawIndexed(36); m_Renderer->EndFrame(); } diff --git a/Source/FlashlightEngine/Renderer/Renderer.cpp b/Source/FlashlightEngine/Renderer/Renderer.cpp index 4656be3..85cd650 100644 --- a/Source/FlashlightEngine/Renderer/Renderer.cpp +++ b/Source/FlashlightEngine/Renderer/Renderer.cpp @@ -14,6 +14,26 @@ namespace FlashlightEngine { // Set the default primitive topology to be a triangle list. SetPrimitiveTopology(PrimitiveTopology::TriangleList); + + D3D11_RASTERIZER_DESC rasterizerDesc{}; + rasterizerDesc.CullMode = D3D11_CULL_NONE; + rasterizerDesc.FillMode = D3D11_FILL_SOLID; + + HRESULT hr = m_Device->GetDevice()->CreateRasterizerState(&rasterizerDesc, m_RasterizerState.GetAddressOf()); + if (FAILED(hr)) { + spdlog::error("[DirectX] Failed to create rasterizer state. Error: {}", HResultToString(hr)); + } + +#if defined(FL_DEBUG) || defined(FL_FORCE_DX_DEBUG_INTERFACE) + hr = m_RasterizerState->SetPrivateData(WKPDID_D3DDebugObjectName, sizeof("Rasterizer State") - 1, + "Rasterizer State"); + + if (FAILED(hr)) { + spdlog::error("[DirectX] Failed to set name for rasterizer state. Error: {}", HResultToString(hr)); + } +#endif + + CreateDepthStencilState(); } void Renderer::OnResize(const UInt32 width, const UInt32 height) const { @@ -34,8 +54,12 @@ namespace FlashlightEngine { viewport.MaxDepth = 1.0f; deviceContext->ClearRenderTargetView(m_Swapchain->GetRTV().Get(), m_ClearColor); + deviceContext->ClearDepthStencilView(m_Swapchain->GetDSV().Get(), D3D11_CLEAR_DEPTH, 1.0f, 0); + deviceContext->RSSetViewports(1, &viewport); - deviceContext->OMSetRenderTargets(1, m_Swapchain->GetRTV().GetAddressOf(), nullptr); + deviceContext->OMSetRenderTargets(1, m_Swapchain->GetRTV().GetAddressOf(), m_Swapchain->GetDSV().Get()); + deviceContext->OMSetDepthStencilState(m_DepthStencilState.Get(), 0); + deviceContext->RSSetState(m_RasterizerState.Get()); } void Renderer::EndFrame() const { @@ -61,6 +85,21 @@ namespace FlashlightEngine { &stride, offsets.data()); } + void Renderer::BindIndexBuffer(ID3D11Buffer* buffer, const IndexType indexType) const { + DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN; + switch (indexType) { + case IndexType::UInt16: + format = DXGI_FORMAT_R16_UINT; + break; + case IndexType::UInt32: + format = DXGI_FORMAT_R32_UINT; + break; + } + + m_Device->GetDeviceContext()->IASetIndexBuffer(buffer, format, 0); + } + + void Renderer::BindConstantBuffers(const std::vector& buffers, const PipelineBindPoint bindPoint, const UInt32 startSlot) const { @@ -93,6 +132,10 @@ namespace FlashlightEngine { m_Device->GetDeviceContext()->Draw(vertexCount, firstVertex); } + void Renderer::DrawIndexed(const UInt32 indexCount, const UInt32 firstIndex, const UInt32 baseVertex) const { + m_Device->GetDeviceContext()->DrawIndexed(indexCount, firstIndex, baseVertex); + } + ShaderCollection Renderer::CreateShaderCollection(const VertexType vertexType, const std::filesystem::path& vertexShaderPath, const std::filesystem::path& pixelShaderPath, @@ -141,4 +184,24 @@ namespace FlashlightEngine { const std::string_view name) const { return std::make_unique(path, name, m_Device); } + + void Renderer::CreateDepthStencilState() { + + D3D11_DEPTH_STENCIL_DESC depthStencilDesc{}; + depthStencilDesc.DepthEnable = true; + depthStencilDesc.DepthFunc = D3D11_COMPARISON_LESS; + depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; + HRESULT hr = m_Device->GetDevice()->CreateDepthStencilState(&depthStencilDesc, m_DepthStencilState.GetAddressOf()); + if (FAILED(hr)) { + spdlog::error("[DirectX] Failed to create depth stencil state. Error: {}", HResultToString(hr)); + } + +#if defined(FL_DEBUG) || defined(FL_FORCE_DX_DEBUG_INTERFACE) + hr = m_DepthStencilState->SetPrivateData(WKPDID_D3DDebugObjectName, sizeof("Depth Stencil State") - 1, + "Depth Stencil State"); + if (FAILED(hr)) { + spdlog::error("[DirectX] Failed to set name for depth stencil state. Error: {}", HResultToString(hr)); + } +#endif + } } diff --git a/Source/FlashlightEngine/Renderer/Swapchain.cpp b/Source/FlashlightEngine/Renderer/Swapchain.cpp index afcc35a..202a0c3 100644 --- a/Source/FlashlightEngine/Renderer/Swapchain.cpp +++ b/Source/FlashlightEngine/Renderer/Swapchain.cpp @@ -116,6 +116,30 @@ namespace FlashlightEngine { return false; } + D3D11_TEXTURE2D_DESC texDesc{}; + texDesc.Width = m_Window->GetWidth(); + texDesc.Height = m_Window->GetHeight(); + texDesc.MipLevels = 1; + texDesc.ArraySize = 1; + texDesc.SampleDesc.Count = 1; + texDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; + texDesc.Format = DXGI_FORMAT_R32_TYPELESS; + + ID3D11Texture2D* depthTexture = nullptr; + hr = m_Device->GetDevice()->CreateTexture2D(&texDesc, nullptr, &depthTexture); + if (FAILED(hr)) { + spdlog::error("[DirectX] Failed to create depth buffer texture. Error: {}", HResultToString(hr)); + } + + D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc{}; + dsvDesc.Format = DXGI_FORMAT_D32_FLOAT; + dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; + + hr = m_Device->GetDevice()->CreateDepthStencilView(depthTexture, &dsvDesc, m_DepthStencilView.GetAddressOf()); + if (FAILED(hr)) { + spdlog::error("[DirectX] Failed to create depth stencil view. Error: {}", HResultToString(hr)); + } + #if defined(FL_DEBUG) || defined(FL_FORCE_DX_DEBUG_INTERFACE) hr = backBuffer->SetPrivateData(WKPDID_D3DDebugObjectName, sizeof("Swapchain backbuffer"), "Swapchain backbuffer"); @@ -128,6 +152,18 @@ namespace FlashlightEngine { if (FAILED(hr)) { spdlog::error("[DirectX] Failed to set RTV name. Error: {}", HResultToString(hr)); } + + hr = depthTexture->SetPrivateData(WKPDID_D3DDebugObjectName, sizeof("Depth Buffer Texture") - 1, + "Depth Buffer Texture"); + if (FAILED(hr)) { + spdlog::error("[DirectX] Failed to set name for depth buffer texture. Error: {}", HResultToString(hr)); + } + + hr = m_DepthStencilView->SetPrivateData(WKPDID_D3DDebugObjectName, sizeof("Depth Stencil View") - 1, + "Depth Stencil View"); + if (FAILED(hr)) { + spdlog::error("[DirectX] Failed to set name for depth stencil view. Error: {}", HResultToString(hr)); + } #endif spdlog::info("[DirectX] Render target created."); @@ -137,5 +173,6 @@ namespace FlashlightEngine { void Swapchain::DestroySwapchainResources() { m_RenderTargetView.Reset(); + m_DepthStencilView.Reset(); } } diff --git a/xmake.lua b/xmake.lua index eaaa6b7..622d42c 100644 --- a/xmake.lua +++ b/xmake.lua @@ -7,7 +7,7 @@ set_project(ProjectName) add_rules("mode.debug", "mode.release") option("override_runtime", {description = "Override VS runtime to MD in release and MDd in debug.", default = true}) -option("force_validation", {description = "Force Vulkan validation layers to be enabled.", default = false}) +option("force_validation", {description = "Force DirectX debug interface to be enabled.", default = false}) option("profiler", {description = "Enable the Tracy profiler.", default = false}) add_includedirs("Include")