Added mouse picking

This commit is contained in:
antopilo
2025-04-14 21:11:26 -04:00
parent b8bedd6cb2
commit 710d63ad98
7 changed files with 108 additions and 47 deletions

View File

@@ -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
{

View File

@@ -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,
&copyRegion
);
}
void Cmd::SetLineRasterizationMode(VkLineRasterizationMode mode) const
{
vkCmdSetLineRasterizationModeEXT(CmdBuffer, mode);

View File

@@ -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;

View File

@@ -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;

View File

@@ -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)

View File

@@ -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);
};

View File

@@ -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;