Added mouse picking
This commit is contained in:
@@ -9,6 +9,8 @@
|
||||
#include "Nuake/Rendering/Vulkan/SceneViewport.h"
|
||||
#include "Nuake/Rendering/Vulkan/DebugCmd.h"
|
||||
|
||||
#include "Nuake/Rendering/Vulkan/SceneRenderPipeline.h"
|
||||
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
#include <Nuake/Scene/Components/AudioEmitterComponent.h>
|
||||
#include <Nuake/Scene/Components/ParticleEmitterComponent.h>
|
||||
@@ -85,7 +87,9 @@ void ViewportWidget::Draw()
|
||||
ImGui::Image(textureDesc, regionAvail, { 0, 1 }, { 1, 0 });
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
const Vector2& mousePos = Input::GetMousePosition();
|
||||
float title_bar_height = ImGui::GetFontSize() + ImGui::GetStyle().FramePadding.y * 2;
|
||||
Vector2 mousePos = Input::GetMousePosition();
|
||||
mousePos.y -= title_bar_height;
|
||||
|
||||
const ImVec2& windowPos = ImGui::GetWindowPos();
|
||||
const auto windowPosNuake = Vector2(windowPos.x, windowPos.y);
|
||||
@@ -93,6 +97,8 @@ void ViewportWidget::Draw()
|
||||
const bool isInsideWidth = mousePos.x > windowPos.x && mousePos.x < windowPos.x + windowSize.x;
|
||||
const bool isInsideHeight = mousePos.y > windowPos.y && mousePos.y < windowPos.y + windowSize.y;
|
||||
this->isHoveringViewport = isInsideWidth && isInsideHeight;
|
||||
auto pixelPos = (mousePos - windowPosNuake) * Engine::GetProject()->Settings.ResolutionScale;
|
||||
|
||||
|
||||
// TODO(antopilo) drag n drop
|
||||
ImGuizmo::SetDrawlist();
|
||||
@@ -187,6 +193,28 @@ void ViewportWidget::Draw()
|
||||
}
|
||||
}
|
||||
|
||||
if (!Engine::IsPlayMode() && !ImGuizmo::IsUsing() && ImGui::IsMouseClicked(ImGuiMouseButton_Left) && ImGui::GetIO().WantCaptureMouse && isHoveringViewport)
|
||||
{
|
||||
auto& sceneRenderer = VkRenderer::Get().SceneRenderers[sceneViewport->GetID()];
|
||||
sceneRenderer->sceneRenderPipeline->MousePick(pixelPos, [&](uint32_t picked)
|
||||
{
|
||||
Logger::Log("Mouse Picked: " + std::to_string(picked));
|
||||
|
||||
constexpr uint32_t INVALID_PICK_ID = 4187593120;
|
||||
if (picked != INVALID_PICK_ID)
|
||||
{
|
||||
Nuake::Entity entity = Nuake::Entity((entt::entity)picked, editorContext.GetScene().get());
|
||||
if (entity.IsValid())
|
||||
{
|
||||
editorContext.SetSelection(entity);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
editorContext.SetSelection(EditorSelection());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "Cmd.h"
|
||||
#include "VulkanAllocatedBuffer.h"
|
||||
|
||||
using namespace Nuake;
|
||||
|
||||
@@ -153,6 +154,31 @@ void Cmd::CopyImageToImage(Ref<VulkanImage> src, Ref<VulkanImage> dst) const
|
||||
vkCmdBlitImage2(CmdBuffer, &blitInfo);
|
||||
}
|
||||
|
||||
void Cmd::CopyImageToBuffer(Ref<VulkanImage> src, Ref<AllocatedBuffer> dst, const Vector2& offset, const Vector3& extent) const
|
||||
{
|
||||
VkBufferImageCopy copyRegion{};
|
||||
copyRegion.bufferOffset = 0;
|
||||
copyRegion.bufferRowLength = 0; // tightly packed
|
||||
copyRegion.bufferImageHeight = 0;
|
||||
|
||||
copyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
copyRegion.imageSubresource.mipLevel = 0;
|
||||
copyRegion.imageSubresource.baseArrayLayer = 0;
|
||||
copyRegion.imageSubresource.layerCount = 1;
|
||||
|
||||
copyRegion.imageOffset = { (int)offset.x, (int)offset.y, 0 }; // pixel offset (e.g. { mouseX, mouseY, 0 })
|
||||
copyRegion.imageExtent = { (uint32_t)extent.x, (uint32_t)extent.y, 1 }; // pixel size (e.g. { 1, 1, 1 } for one pixel)
|
||||
|
||||
vkCmdCopyImageToBuffer(
|
||||
CmdBuffer,
|
||||
src->GetImage(),
|
||||
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
dst->GetBuffer(),
|
||||
1,
|
||||
©Region
|
||||
);
|
||||
}
|
||||
|
||||
void Cmd::SetLineRasterizationMode(VkLineRasterizationMode mode) const
|
||||
{
|
||||
vkCmdSetLineRasterizationModeEXT(CmdBuffer, mode);
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
class AllocatedBuffer;
|
||||
|
||||
class Cmd
|
||||
{
|
||||
private:
|
||||
@@ -32,6 +34,7 @@ namespace Nuake
|
||||
void DrawIndexed(uint32_t count) const;
|
||||
void PushConstants(VkPipelineLayout pipeline, size_t size, void* data ) const;
|
||||
void CopyBuffer(VkBuffer src, VkBuffer dst, size_t size) const;
|
||||
void CopyImageToBuffer(Ref<VulkanImage> src, Ref<AllocatedBuffer> dst, const Vector2& offset, const Vector3& extent = {1, 1, 1}) const;
|
||||
void TransitionImageLayout(Ref<VulkanImage> img, VkImageLayout layout) const;
|
||||
void CopyImageToImage(Ref<VulkanImage> src, Ref<VulkanImage> dst) const;
|
||||
|
||||
|
||||
@@ -327,43 +327,6 @@ bool RenderPipeline::Build()
|
||||
for (auto& pass : RenderPasses)
|
||||
{
|
||||
pass.Build();
|
||||
|
||||
//for (auto& input : pass.GetInputs())
|
||||
//{
|
||||
// bool alreadyFoundAttachment = false;
|
||||
// if (attachments.find(input) == attachments.end())
|
||||
// {
|
||||
// if (pass.GetDepthAttachment().Image && pass.GetDepthAttachment().Name == input)
|
||||
// {
|
||||
// pass.SetInput(input, pass.GetDepthAttachment());
|
||||
// alreadyFoundAttachment = true;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// Logger::Log("Failed to build RenderPipeline. input " + input + " not found in previous passes.", "vulkan", CRITICAL);
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (!alreadyFoundAttachment)
|
||||
// {
|
||||
// pass.SetInput(input, attachments[input]);
|
||||
// }
|
||||
//}
|
||||
|
||||
//for (auto& attachment : pass.GetAttachments())
|
||||
//{
|
||||
// attachments[attachment.Name] = attachment;
|
||||
//}
|
||||
//
|
||||
//if (pass.GetDepthAttachment().Image)
|
||||
//{
|
||||
// attachments[pass.GetDepthAttachment().Name] = pass.GetDepthAttachment();
|
||||
//}
|
||||
}
|
||||
|
||||
for (auto& pass : RenderPasses)
|
||||
{
|
||||
}
|
||||
|
||||
Built = true;
|
||||
|
||||
@@ -196,7 +196,7 @@ SceneRenderPipeline::SceneRenderPipeline()
|
||||
TonemappedOutput = CreateRef<VulkanImage>(ImageFormat::RGBA8, defaultSize);
|
||||
TonemappedOutput->SetDebugName("TonemappedOutput");
|
||||
|
||||
GBufferEntityID = CreateRef<VulkanImage>(ImageFormat::RGBA16F, defaultSize);
|
||||
GBufferEntityID = CreateRef<VulkanImage>(ImageFormat::RGBA32F, defaultSize);
|
||||
GBufferEntityID->SetDebugName("GBufferEntityID");
|
||||
|
||||
OutlineOutput = CreateRef<VulkanImage>(ImageFormat::RGBA8, defaultSize);
|
||||
@@ -268,11 +268,41 @@ void SceneRenderPipeline::Render(PassRenderContext& ctx)
|
||||
{ GizmoOutput, GBufferEntityID, GBufferDepth }, // Reusing depth from gBuffer
|
||||
{ GizmoCombineOutput },
|
||||
{ OutlineOutput },
|
||||
{ LineCombineOutput },
|
||||
{ LineOutput, GBufferDepth },
|
||||
{ LineCombineOutput },
|
||||
};
|
||||
|
||||
GBufferPipeline.Execute(ctx, pipelineInputs);
|
||||
|
||||
// Mouse Picking requests
|
||||
if (!mousePickingRequests.empty())
|
||||
{
|
||||
for (auto& request : mousePickingRequests)
|
||||
{
|
||||
size_t bufferSize = sizeof(Vector4);
|
||||
Ref<AllocatedBuffer> stagingBuffer = CreateRef<AllocatedBuffer>(bufferSize, BufferUsage::TRANSFER_DST, MemoryUsage::GPU_TO_CPU);
|
||||
|
||||
assert(request.mousePosition.x < GBufferEntityID->GetSize().x && request.mousePosition.y < GBufferEntityID->GetSize().y && "Mouse coord out of bounds");
|
||||
request.mousePosition.y = GBufferEntityID->GetSize().y - request.mousePosition.y;
|
||||
|
||||
VkRenderer::Get().ImmediateSubmit([&](VkCommandBuffer cmd)
|
||||
{
|
||||
Cmd command(cmd);
|
||||
command.TransitionImageLayout(GBufferEntityID, VkImageLayout::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
||||
command.CopyImageToBuffer(GBufferEntityID, stagingBuffer, request.mousePosition);
|
||||
command.TransitionImageLayout(GBufferEntityID, VkImageLayout::VK_IMAGE_LAYOUT_GENERAL);
|
||||
});
|
||||
|
||||
void* mappedData;
|
||||
vmaMapMemory(VulkanAllocator::Get().GetAllocator(), stagingBuffer->GetAllocation(), &mappedData);
|
||||
Vector4 entityID = *reinterpret_cast<Vector4*>(mappedData);
|
||||
vmaUnmapMemory(VulkanAllocator::Get().GetAllocator(), stagingBuffer->GetAllocation());
|
||||
|
||||
request.callback(static_cast<int>(entityID.r));
|
||||
}
|
||||
|
||||
mousePickingRequests.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void SceneRenderPipeline::RecreatePipeline()
|
||||
@@ -709,10 +739,11 @@ void SceneRenderPipeline::RecreatePipeline()
|
||||
GBufferPipeline.Build();
|
||||
}
|
||||
|
||||
int SceneRenderPipeline::MousePick(const Vector2& coord)
|
||||
void SceneRenderPipeline::MousePick(const Vector2& coord, MousePickingCb mousePickingCb)
|
||||
{
|
||||
GBufferEntityID->GetImage();
|
||||
return 0;
|
||||
assert(coord.x > 0 && coord.y > 0 && "Mouse coords out of bounds");
|
||||
|
||||
mousePickingRequests.push_back({ coord, std::move(mousePickingCb) });
|
||||
}
|
||||
|
||||
Ref<VulkanImage> SceneRenderPipeline::ResizeImage(PassRenderContext& ctx, Ref<VulkanImage> image, const Vector2& size)
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#include "Nuake/Core/MulticastDelegate.h"
|
||||
#include "Constant/LineConstant.h"
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
struct GBufferConstant
|
||||
@@ -118,6 +120,14 @@ namespace Nuake
|
||||
class DebugCmd;
|
||||
class DebugLineCmd;
|
||||
|
||||
using MousePickingCb = std::function<void(int result)>;
|
||||
|
||||
struct MousePickingRequest
|
||||
{
|
||||
Vector2 mousePosition;
|
||||
MousePickingCb callback;
|
||||
};
|
||||
|
||||
// This class handles all the rendering of the scene
|
||||
class SceneRenderPipeline
|
||||
{
|
||||
@@ -127,6 +137,8 @@ namespace Nuake
|
||||
static std::vector<Vector3> ssaoKernelSamples;
|
||||
static Ref<VulkanImage> ssaoNoiseTexture;
|
||||
|
||||
std::vector<MousePickingRequest> mousePickingRequests;
|
||||
|
||||
// Attachments GBuffer
|
||||
Ref<VulkanImage> GBufferAlbedo;
|
||||
Ref<VulkanImage> GBufferDepth;
|
||||
@@ -184,14 +196,14 @@ namespace Nuake
|
||||
|
||||
void SetCamera(UUID camera);
|
||||
void Render(PassRenderContext& ctx);
|
||||
Ref<VulkanImage> GetOutput() { return OutlineOutput; }
|
||||
Ref<VulkanImage> GetOutput() { return LineCombineOutput; }
|
||||
|
||||
MulticastDelegate<DebugCmd&>& OnDebugDraw() { return DebugDrawDelegate; }
|
||||
MulticastDelegate<DebugLineCmd&>& OnLineDraw() { return DebugLineDrawDelegate; }
|
||||
|
||||
void RecreatePipeline();
|
||||
|
||||
int MousePick(const Vector2& coord);
|
||||
void MousePick(const Vector2& coord, MousePickingCb mousePickingCb);
|
||||
private:
|
||||
Ref<VulkanImage> ResizeImage(PassRenderContext& ctx, Ref<VulkanImage> image, const Vector2& size);
|
||||
};
|
||||
|
||||
@@ -18,8 +18,6 @@ Viewport::Viewport(UUID inViewId, const Vector2& inViewportSize) :
|
||||
|
||||
int Viewport::MousePick(const Vector2& mouseCoord)
|
||||
{
|
||||
auto& sceneRenderer = VkRenderer::Get().SceneRenderers[id];
|
||||
int result = sceneRenderer->sceneRenderPipeline->MousePick(mouseCoord);
|
||||
|
||||
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user