Added spotlight gizmo + yellow gizmo when selected

This commit is contained in:
antopilo
2025-04-14 10:38:53 -04:00
parent 1f219ba8bc
commit f4fd6e78f3
11 changed files with 154 additions and 45 deletions

View File

@@ -91,6 +91,7 @@ struct PSOutput {
struct DebugConstant
{
float4 Color;
float4x4 Transform;
int TextureID;
};
@@ -117,7 +118,7 @@ PSOutput main(PSInput input)
discard;
}
output.oColor0 = textureSample;
output.oColor0 = textureSample * pushConstants.Color;
}
return output;

View File

@@ -82,6 +82,7 @@ StructuredBuffer<CameraView> cameras;
struct DebugConstant
{
float4 Color;
float4x4 Transform;
int TextureID;
};

View File

@@ -322,7 +322,7 @@ PSOutput main(PSInput input)
float theta = dot(L, normalize(-light.direction));
float epsilon = light.innerConeAngle - light.outerConeAngle;
float intensity = clamp((theta - light.outerConeAngle) / epsilon, 0.0, 1.0);
radiance = light.color * intensity;
radiance = light.color * intensity * attenuation;
}
float3 H = normalize(V + L);

View File

@@ -234,7 +234,7 @@ float GetGizmoScale(const Vector3& camPosition, const Nuake::Vector3& position)
}
template<typename T>
void DrawIconGizmo(DebugCmd& debugCmd, const std::string& icon)
void DrawIconGizmo(DebugCmd& debugCmd, const std::string& icon, const EditorContext& context)
{
auto scene = debugCmd.GetScene();
auto cam = scene->GetCurrentCamera();
@@ -247,12 +247,15 @@ void DrawIconGizmo(DebugCmd& debugCmd, const std::string& icon)
{
auto [transform, cam] = scene->m_Registry.get<TransformComponent, T>(e);
auto selection = context.GetSelection();
bool isSelected = selection.Type == EditorSelectionType::Entity && selection.Entity.GetHandle() == (int)e;
Matrix4 initialTransform = transform.GetGlobalTransform();
Matrix4 gizmoTransform = initialTransform;
gizmoTransform = glm::inverse(scene->GetCurrentCamera()->GetTransform());
gizmoTransform[3] = initialTransform[3];
gizmoTransform = glm::scale(gizmoTransform, gizmoSize * GetGizmoScale(cameraPosition, initialTransform[3]));
debugCmd.DrawTexturedQuad(proj * view * gizmoTransform, TextureManager::Get()->GetTexture2(icon));
debugCmd.DrawTexturedQuad(proj * view * gizmoTransform, TextureManager::Get()->GetTexture2(icon), isSelected ? Color(1, 1, 0, 1) : Color(1, 1, 1, 1));
}
}
@@ -284,6 +287,57 @@ void ViewportWidget::OnLineDraw(DebugLineCmd& lineCmd)
lineCmd.DrawBox(proj * boxTransform, Color(1, 0, 0, 1.0f), 1.5f, false);
}
auto lightView = scene->m_Registry.view<TransformComponent, LightComponent>();
for (auto e : lightView)
{
auto [transformComp, lightComp] = scene->m_Registry.get<TransformComponent, LightComponent>(e);
const int32_t type = lightComp.Type;
const Quat& rotationOffset = QuatFromEuler(-90.0f, 0, 0);
const Quat& globalRotation = glm::normalize(transformComp.GetGlobalRotation()) * rotationOffset;
const Matrix4& rotationMatrix = glm::mat4_cast(globalRotation);
Matrix4 transform = Matrix4(1.0f);
transform = glm::translate(view, Vector3(transformComp.GetGlobalTransform()[3]));
transform = transform * rotationMatrix;
transform = glm::translate(transform, { 0, -1.0, 0.0 });
if (type == LightType::Spot)
{
const Quat& rotationOffset = QuatFromEuler(90.0f, 0, 0);
const Quat& globalRotation = glm::normalize(transformComp.GetGlobalRotation()) * rotationOffset;
const Matrix4& rotationMatrix = glm::mat4_cast(globalRotation);
Matrix4 transform = Matrix4(1.0f);
transform = glm::translate(view, Vector3(transformComp.GetGlobalTransform()[3]));
transform = transform * rotationMatrix;
float length = 1.0f;
float scaleDistance = glm::sqrt(lightComp.Strength);
length *= scaleDistance;
transform = glm::translate(transform, { 0, -length, 0.0 });
float radiusScale = (length) * glm::tan(Rad(lightComp.OuterCutoff)) / 0.25f;
Vector3 coneScale = Vector3(radiusScale, length, radiusScale);
transform = glm::scale(transform, coneScale);
lineCmd.DrawCone(proj * transform, Color{ lightComp.Color, 1.0f }, 1.5f, false);
}
else if (type == LightType::Directional)
{
const Quat& rotationOffset = QuatFromEuler(-90.0f, 0, 0);
const Quat& globalRotation = glm::normalize(transformComp.GetGlobalRotation()) * rotationOffset;
const Matrix4& rotationMatrix = glm::mat4_cast(globalRotation);
Matrix4 transform = Matrix4(1.0f);
transform = glm::translate(view, Vector3(transformComp.GetGlobalTransform()[3]));
transform = transform * rotationMatrix;
transform = glm::translate(transform, { 0, -1.0, 0.0 });
lineCmd.DrawCylinder(proj * transform, Color { lightComp.Color, 1.0f }, 1.5f, false);
}
}
auto boxColliderView = scene->m_Registry.view<TransformComponent, BoxColliderComponent>();
for (auto e : boxColliderView)
{
@@ -344,14 +398,14 @@ void ViewportWidget::OnDebugDraw(DebugCmd& debugCmd)
auto view = cam->GetTransform();
auto proj = cam->GetPerspective();
static auto drawGizmoIcon = [&](TransformComponent& transform, const std::string& icon)
static auto drawGizmoIcon = [&](TransformComponent& transform, const std::string& icon, const Color& color)
{
Matrix4 initialTransform = transform.GetGlobalTransform();
Matrix4 gizmoTransform = initialTransform;
gizmoTransform = glm::inverse(scene->GetCurrentCamera()->GetTransform());
gizmoTransform[3] = initialTransform[3];
gizmoTransform = glm::scale(gizmoTransform, gizmoSize * GetGizmoScale(cameraPosition, initialTransform[3]));
debugCmd.DrawTexturedQuad(proj * view * gizmoTransform, TextureManager::Get()->GetTexture2(icon));
debugCmd.DrawTexturedQuad(proj * view * gizmoTransform, TextureManager::Get()->GetTexture2(icon), color);
};
debugCmd.DrawQuad(proj * view * glm::translate(Matrix4(1.0f), { 0, 4, 0 }));
@@ -361,6 +415,9 @@ void ViewportWidget::OnDebugDraw(DebugCmd& debugCmd)
{
auto [transform, light] = scene->m_Registry.get<TransformComponent, LightComponent>(e);
auto selection = editorContext.GetSelection();
bool isSelected = selection.Type == EditorSelectionType::Entity && selection.Entity.GetHandle() == (int)e;
std::string texturePath = "Resources/Gizmos/";
switch (light.Type)
{
@@ -378,15 +435,15 @@ void ViewportWidget::OnDebugDraw(DebugCmd& debugCmd)
}
// Billboard + scaling logic
drawGizmoIcon(transform, texturePath);
drawGizmoIcon(transform, texturePath, isSelected ? Color(1, 1, 0, 1) : Color(1, 1, 1, 1));
}
DrawIconGizmo<CameraComponent>(debugCmd, "Resources/Gizmos/Camera.png");
DrawIconGizmo<CharacterControllerComponent>(debugCmd, "Resources/Gizmos/player.png");
DrawIconGizmo<BoneComponent>(debugCmd, "Resources/Gizmos/bone.png");
DrawIconGizmo<AudioEmitterComponent>(debugCmd, "Resources/Gizmos/sound_emitter.png");
DrawIconGizmo<RigidBodyComponent>(debugCmd, "Resources/Gizmos/rigidbody.png");
DrawIconGizmo<ParticleEmitterComponent>(debugCmd, "Resources/Gizmos/particles.png");
DrawIconGizmo<CameraComponent>(debugCmd, "Resources/Gizmos/Camera.png", editorContext);
DrawIconGizmo<CharacterControllerComponent>(debugCmd, "Resources/Gizmos/player.png", editorContext);
DrawIconGizmo<BoneComponent>(debugCmd, "Resources/Gizmos/bone.png", editorContext);
DrawIconGizmo<AudioEmitterComponent>(debugCmd, "Resources/Gizmos/sound_emitter.png", editorContext);
DrawIconGizmo<RigidBodyComponent>(debugCmd, "Resources/Gizmos/rigidbody.png", editorContext);
DrawIconGizmo<ParticleEmitterComponent>(debugCmd, "Resources/Gizmos/particles.png", editorContext);
}

View File

@@ -5,6 +5,7 @@ namespace Nuake
{
struct DebugConstant
{
Vector4 Color = Vector4(1, 1, 1, 1);
Matrix4 Transform;
int TextureID;
};

View File

@@ -28,10 +28,11 @@ void DebugCmd::DrawQuad(const Matrix4& transform)
cmd.DrawIndexed(6);
}
void DebugCmd::DrawTexturedQuad(const Matrix4& transform, Ref<VulkanImage> texture)
void DebugCmd::DrawTexturedQuad(const Matrix4& transform, Ref<VulkanImage> texture, const Color& color)
{
debugConstant.Transform = transform;
debugConstant.TextureID = GPUResources::Get().GetBindlessTextureID(texture->GetID());
debugConstant.Color = color;
cmd.PushConstants(ctx.renderPass->PipelineLayout, sizeof(DebugConstant), &debugConstant);
@@ -41,8 +42,6 @@ void DebugCmd::DrawTexturedQuad(const Matrix4& transform, Ref<VulkanImage> textu
cmd.DrawIndexed(6);
}
DebugLineCmd::DebugLineCmd(Cmd& inCmd, PassRenderContext& inCtx) :
cmd(inCmd), ctx(inCtx), lineConstant({})
{
@@ -182,29 +181,6 @@ void DebugLineCmd::DrawArrow(const Vector3& from, const Vector3& to, const Matri
cmd.SetLineWidth(lineWidth);
// Shaft direction (normalized)
glm::vec3 dir = glm::normalize(to - from);
// Get camera position from inverse of view
glm::vec3 cameraPos = glm::vec3(glm::inverse(view)[3]);
glm::vec3 toCamera = glm::normalize(cameraPos - to);
// Billboard basis
glm::vec3 right = glm::normalize(glm::cross(dir, toCamera));
glm::vec3 up = glm::normalize(glm::cross(right, dir));
//// Build arrowhead transform
//glm::mat4 arrowTransform(1.0f);
//arrowTransform[0] = glm::vec4(right, 0.0f); // X axis
//arrowTransform[1] = glm::vec4(up, 0.0f); // Y axis
//arrowTransform[2] = glm::vec4(dir, 0.0f); // Z axis (forward)
//arrowTransform[3] = glm::vec4(to, 1.0f); // Position
// Optional: scale arrowhead size
//float arrowScale = 0.2f; // You can tweak this
//arrowTransform = arrowTransform * glm::scale(glm::mat4(1.0f), glm::vec3(arrowScale));
// Final matrix
lineConstant.Transform = proj * view;
lineConstant.LineColor = inColor;
@@ -215,3 +191,27 @@ void DebugLineCmd::DrawArrow(const Vector3& from, const Vector3& to, const Matri
cmd.BindIndexBuffer(sphereMesh->GetIndexBuffer()->GetBuffer());
cmd.DrawIndexed(sphereMesh->GetIndexBuffer()->GetSize() / sizeof(uint32_t));
}
void DebugLineCmd::DrawCone(const Matrix4& transform, const Color& inColor, float lineWidth, bool stippled)
{
cmd.SetPolygonMode(VK_POLYGON_MODE_LINE);
cmd.SetLineRasterizationMode(VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH);
cmd.SetPrimitiveTopology(VK_PRIMITIVE_TOPOLOGY_LINE_LIST);
cmd.SetLineStippleEnabled(stippled);
if (stippled)
{
cmd.SetLineStipple(2, 0b1111111100000000);
}
cmd.SetLineWidth(lineWidth);
lineConstant.LineColor = inColor;
lineConstant.Transform = transform;
cmd.PushConstants(ctx.renderPass->PipelineLayout, sizeof(LineConstant), &lineConstant);
auto& coneMesh = VkSceneRenderer::ConeMesh;
cmd.BindDescriptorSet(ctx.renderPass->PipelineLayout, coneMesh->GetDescriptorSet(), 1);
cmd.BindIndexBuffer(coneMesh->GetIndexBuffer()->GetBuffer());
cmd.DrawIndexed(coneMesh->GetIndexBuffer()->GetSize() / sizeof(uint32_t));
}

View File

@@ -26,7 +26,7 @@ namespace Nuake
Ref<Scene> GetScene() const;
void DrawQuad(const Matrix4& transform);
void DrawTexturedQuad(const Matrix4& transform, Ref<VulkanImage> texture);
void DrawTexturedQuad(const Matrix4& transform, Ref<VulkanImage> texture, const Color& color = Color(1, 1, 1 ,1));
void DrawSphere(const Vector2& position, float radius, const Color& color) const;
void DrawCube(const Vector3& position, const Vector3& size, const Color& color) const;
@@ -59,5 +59,6 @@ namespace Nuake
void DrawSphere(const Matrix4& transform, const Color& color, float lineWidth = 1.0f, bool stippled = false);
void DrawCylinder(const Matrix4& transform, const Color& color, float lineWidth = 1.0f, bool stippled = false);
void DrawArrow(const Vector3& from, const Vector3& to, const Matrix4& view, const Matrix4& proj, const Color& color, float lineWidth = 1.0f, bool stippled = false);
void DrawCone(const Matrix4& transform, const Color& color, float lineWidth = 1.0f, bool stippled = false);
};
}

View File

@@ -606,7 +606,7 @@ void SceneRenderPipeline::RecreatePipeline()
auto& gizmoPass = GBufferPipeline.AddPass("Gizmo");
gizmoPass.SetShaders(shaderMgr.GetShader("gizmo_vert"), shaderMgr.GetShader("gizmo_frag"));
gizmoPass.SetPushConstant(debugConstant);
gizmoPass.SetPushConstant<DebugConstant>(debugConstant);
gizmoPass.AddInput("Depth");
gizmoPass.AddAttachment("GizmoOutput", GizmoOutput->GetFormat());
gizmoPass.AddAttachment("GizmoDepth", GBufferDepth->GetFormat(), ImageUsage::Depth, false);

View File

@@ -28,6 +28,7 @@ Ref<VkMesh> VkSceneRenderer::CapsuleMesh;
Ref<VkMesh> VkSceneRenderer::SphereMesh;
Ref<VkMesh> VkSceneRenderer::CylinderMesh;
Ref<VkMesh> VkSceneRenderer::ArrowMesh;
Ref<VkMesh> VkSceneRenderer::ConeMesh;
void VkSceneRenderer::Init()
{
@@ -293,7 +294,7 @@ void VkSceneRenderer::Init()
std::vector<uint32_t> cylinderIndices;
const int segments = 16;
const float radius = 0.5f;
const float radius = 0.25f;
const float halfHeight = 1.0f;
// Vertex pairs: top and bottom
@@ -341,6 +342,52 @@ void VkSceneRenderer::Init()
CylinderMesh = CreateRef<VkMesh>(cylinderVertices, cylinderIndices);
}
{
std::vector<Vertex> coneVertices;
std::vector<uint32_t> coneIndices;
const int segments = 16;
const float radius = 0.5f;
const float height = 2.0f;
const float halfHeight = height * 0.5f;
// Tip vertex at the top center
Vector3 tipPosition = Vector3(0.0f, +halfHeight, 0.0f);
coneVertices.push_back({ tipPosition, 0.0f, Vector3(), 0.0f });
uint32_t tipIndex = 0;
// Base ring vertices
for (int i = 0; i < segments; ++i)
{
float angle = (2.0f * glm::pi<float>() * i) / segments;
float x = cos(angle) * radius;
float z = sin(angle) * radius;
Vector3 pos = Vector3(x, -halfHeight, z);
coneVertices.push_back({ pos, 0.0f, Vector3(), 0.0f });
}
// Circle outline on base
for (int i = 0; i < segments; ++i)
{
uint32_t currIdx = tipIndex + 1 + i;
uint32_t nextIdx = tipIndex + 1 + ((i + 1) % segments);
coneIndices.push_back(currIdx);
coneIndices.push_back(nextIdx);
}
// Lines from base to tip
for (int i = 0; i < segments; ++i)
{
uint32_t baseIdx = tipIndex + 1 + i;
coneIndices.push_back(tipIndex); // tip
coneIndices.push_back(baseIdx); // base
}
// Final creation of the cone outline mesh
ConeMesh = CreateRef<VkMesh>(coneVertices, coneIndices);
}
}
void VkSceneRenderer::LoadShaders()

View File

@@ -30,6 +30,7 @@ namespace Nuake
static Ref<VkMesh> SphereMesh;
static Ref<VkMesh> CylinderMesh;
static Ref<VkMesh> ArrowMesh;
static Ref<VkMesh> ConeMesh;
public:
//RenderContext Context;

View File

@@ -15,7 +15,7 @@
namespace Nuake
{
enum LightType
enum LightType : int32_t
{
Directional, Point, Spot
};