Formalize editor skybox wiring and debug presets
This commit is contained in:
@@ -378,7 +378,7 @@ bool SceneViewportEditorOverlayPassRenderer::Render(
|
||||
const Rendering::RenderContext& renderContext,
|
||||
const Rendering::RenderSurface& surface,
|
||||
const SceneViewportOverlayFrameData& frameData) {
|
||||
if (!frameData.HasOverlayPrimitives() || !renderContext.IsValid() || renderContext.commandList == nullptr) {
|
||||
if (!frameData.HasRenderPassPrimitives() || !renderContext.IsValid() || renderContext.commandList == nullptr) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -411,33 +411,10 @@ bool SceneViewportEditorOverlayPassRenderer::Render(
|
||||
AppendScreenTriangleVertices(targetVertices, triangle);
|
||||
}
|
||||
|
||||
std::vector<const SceneViewportOverlaySpritePrimitive*> depthTestedSprites = {};
|
||||
std::vector<const SceneViewportOverlaySpritePrimitive*> alwaysOnTopSprites = {};
|
||||
depthTestedSprites.reserve(frameData.worldSprites.size());
|
||||
alwaysOnTopSprites.reserve(frameData.worldSprites.size());
|
||||
for (const SceneViewportOverlaySpritePrimitive& sprite : frameData.worldSprites) {
|
||||
if (sprite.sizePixels.x <= Math::EPSILON || sprite.sizePixels.y <= Math::EPSILON) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sprite.depthMode == SceneViewportOverlayDepthMode::DepthTested) {
|
||||
depthTestedSprites.push_back(&sprite);
|
||||
} else {
|
||||
alwaysOnTopSprites.push_back(&sprite);
|
||||
}
|
||||
}
|
||||
|
||||
const auto sortBackToFront =
|
||||
[](const SceneViewportOverlaySpritePrimitive* lhs, const SceneViewportOverlaySpritePrimitive* rhs) {
|
||||
return lhs->sortDepth > rhs->sortDepth;
|
||||
};
|
||||
std::sort(depthTestedSprites.begin(), depthTestedSprites.end(), sortBackToFront);
|
||||
std::sort(alwaysOnTopSprites.begin(), alwaysOnTopSprites.end(), sortBackToFront);
|
||||
|
||||
const size_t lineVertexCount = depthTestedLineVertices.size() + alwaysOnTopLineVertices.size();
|
||||
const size_t screenTriangleVertexCount =
|
||||
depthTestedScreenTriangleVertices.size() + alwaysOnTopScreenTriangleVertices.size();
|
||||
const size_t spriteVertexCount = (depthTestedSprites.size() + alwaysOnTopSprites.size()) * 6u;
|
||||
const size_t spriteVertexCount = 0u;
|
||||
if (lineVertexCount == 0u && screenTriangleVertexCount == 0u && spriteVertexCount == 0u) {
|
||||
return true;
|
||||
}
|
||||
@@ -471,35 +448,6 @@ bool SceneViewportEditorOverlayPassRenderer::Render(
|
||||
screenTriangleVertices.size() * sizeof(OverlayScreenTriangleVertex));
|
||||
}
|
||||
|
||||
std::vector<OverlaySpriteVertex> spriteVertices = {};
|
||||
std::array<OverlaySpriteBatchRange, kSceneViewportOverlaySpriteResourceCount> depthTestedSpriteBatches = {};
|
||||
std::array<OverlaySpriteBatchRange, kSceneViewportOverlaySpriteResourceCount> alwaysOnTopSpriteBatches = {};
|
||||
if (spriteVertexCount > 0u) {
|
||||
spriteVertices.reserve(spriteVertexCount);
|
||||
const auto appendSpriteBatches =
|
||||
[&spriteVertices](
|
||||
const std::vector<const SceneViewportOverlaySpritePrimitive*>& sprites,
|
||||
std::array<OverlaySpriteBatchRange, kSceneViewportOverlaySpriteResourceCount>& outBatches) {
|
||||
for (size_t textureIndex = 0; textureIndex < kSceneViewportOverlaySpriteResourceCount; ++textureIndex) {
|
||||
OverlaySpriteBatchRange range = {};
|
||||
range.firstVertex = static_cast<uint32_t>(spriteVertices.size());
|
||||
for (const SceneViewportOverlaySpritePrimitive* sprite : sprites) {
|
||||
if (sprite == nullptr ||
|
||||
GetSceneViewportOverlaySpriteResourceIndex(sprite->textureKind) != textureIndex) {
|
||||
continue;
|
||||
}
|
||||
|
||||
AppendSpriteVertices(spriteVertices, *sprite);
|
||||
}
|
||||
range.vertexCount = static_cast<uint32_t>(spriteVertices.size()) - range.firstVertex;
|
||||
outBatches[textureIndex] = range;
|
||||
}
|
||||
};
|
||||
appendSpriteBatches(depthTestedSprites, depthTestedSpriteBatches);
|
||||
appendSpriteBatches(alwaysOnTopSprites, alwaysOnTopSpriteBatches);
|
||||
m_spriteVertexBuffer->SetData(spriteVertices.data(), spriteVertices.size() * sizeof(OverlaySpriteVertex));
|
||||
}
|
||||
|
||||
OverlayConstants constants = {};
|
||||
constants.viewProjection = BuildSceneViewportViewProjectionMatrix(
|
||||
frameData.overlay,
|
||||
@@ -564,49 +512,6 @@ bool SceneViewportEditorOverlayPassRenderer::Render(
|
||||
}
|
||||
}
|
||||
|
||||
if (spriteVertexCount > 0u) {
|
||||
commandList->SetPrimitiveTopology(RHI::PrimitiveTopology::TriangleList);
|
||||
RHI::RHIResourceView* vertexBuffers[] = { m_spriteVertexBufferView };
|
||||
const uint64_t offsets[] = { 0u };
|
||||
const uint32_t strides[] = { static_cast<uint32_t>(sizeof(OverlaySpriteVertex)) };
|
||||
commandList->SetVertexBuffers(0, 1, vertexBuffers, offsets, strides);
|
||||
|
||||
const auto drawSpriteBatchGroup =
|
||||
[this, commandList](
|
||||
RHI::RHIPipelineState* pipelineState,
|
||||
const std::array<OverlaySpriteBatchRange, kSceneViewportOverlaySpriteResourceCount>& batches) {
|
||||
if (pipelineState == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
commandList->SetPipelineState(pipelineState);
|
||||
for (size_t textureIndex = 0; textureIndex < kSceneViewportOverlaySpriteResourceCount; ++textureIndex) {
|
||||
const OverlaySpriteBatchRange& batch = batches[textureIndex];
|
||||
if (!batch.HasVertices()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
RHI::RHIDescriptorSet* const textureSet =
|
||||
m_overlaySpriteResources.GetTextureSet(
|
||||
GetSceneViewportOverlaySpriteTextureKindByIndex(textureIndex));
|
||||
if (textureSet == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
RHI::RHIDescriptorSet* descriptorSets[] = {
|
||||
m_constantSet,
|
||||
textureSet,
|
||||
m_samplerSet
|
||||
};
|
||||
commandList->SetGraphicsDescriptorSets(0, 3, descriptorSets, m_spritePipelineLayout);
|
||||
commandList->Draw(batch.vertexCount, 1, batch.firstVertex, 0);
|
||||
}
|
||||
};
|
||||
|
||||
drawSpriteBatchGroup(m_depthTestedSpritePipelineState, depthTestedSpriteBatches);
|
||||
drawSpriteBatchGroup(m_alwaysOnTopSpritePipelineState, alwaysOnTopSpriteBatches);
|
||||
}
|
||||
|
||||
if (screenTriangleVertexCount > 0u) {
|
||||
commandList->SetPrimitiveTopology(RHI::PrimitiveTopology::TriangleList);
|
||||
RHI::RHIResourceView* vertexBuffers[] = { m_screenTriangleVertexBufferView };
|
||||
|
||||
@@ -110,6 +110,10 @@ struct SceneViewportOverlayFrameData {
|
||||
return overlay.valid && (!worldLines.empty() || !worldSprites.empty() || !screenTriangles.empty());
|
||||
}
|
||||
|
||||
bool HasRenderPassPrimitives() const {
|
||||
return overlay.valid && (!worldLines.empty() || !screenTriangles.empty());
|
||||
}
|
||||
|
||||
bool HasWorldOverlay() const {
|
||||
return HasOverlayPrimitives();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
#include "SceneViewportHudOverlay.h"
|
||||
|
||||
#include "SceneViewportOrientationGizmo.h"
|
||||
#include "SceneViewportMath.h"
|
||||
|
||||
#include "UI/BuiltInIcons.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Editor {
|
||||
@@ -11,6 +17,97 @@ bool IsViewportRectValid(const ImVec2& viewportMin, const ImVec2& viewportMax) {
|
||||
viewportMax.y - viewportMin.y > 1.0f;
|
||||
}
|
||||
|
||||
bool DrawSceneViewportSpriteIcon(
|
||||
ImDrawList* drawList,
|
||||
const ImVec2& min,
|
||||
const ImVec2& max,
|
||||
SceneViewportOverlaySpriteTextureKind textureKind) {
|
||||
switch (textureKind) {
|
||||
case SceneViewportOverlaySpriteTextureKind::Camera:
|
||||
return UI::DrawEditorTextureIcon(
|
||||
drawList,
|
||||
min,
|
||||
max,
|
||||
UI::EditorTextureIconKind::CameraGizmo);
|
||||
case SceneViewportOverlaySpriteTextureKind::Light:
|
||||
return UI::DrawEditorTextureIcon(
|
||||
drawList,
|
||||
min,
|
||||
max,
|
||||
UI::EditorTextureIconKind::MainLightGizmo);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void DrawSceneViewportSceneIcons(
|
||||
ImDrawList* drawList,
|
||||
const SceneViewportHudOverlayData& overlay,
|
||||
const ImVec2& viewportMin,
|
||||
const ImVec2& viewportMax) {
|
||||
if (drawList == nullptr ||
|
||||
!overlay.showSceneIcons ||
|
||||
overlay.overlayFrameData == nullptr ||
|
||||
overlay.overlayFrameData->worldSprites.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const float viewportWidth = viewportMax.x - viewportMin.x;
|
||||
const float viewportHeight = viewportMax.y - viewportMin.y;
|
||||
if (viewportWidth <= 1.0f || viewportHeight <= 1.0f) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<const SceneViewportOverlaySpritePrimitive*> sortedSprites = {};
|
||||
sortedSprites.reserve(overlay.overlayFrameData->worldSprites.size());
|
||||
for (const SceneViewportOverlaySpritePrimitive& sprite : overlay.overlayFrameData->worldSprites) {
|
||||
sortedSprites.push_back(&sprite);
|
||||
}
|
||||
|
||||
std::sort(
|
||||
sortedSprites.begin(),
|
||||
sortedSprites.end(),
|
||||
[](const SceneViewportOverlaySpritePrimitive* lhs, const SceneViewportOverlaySpritePrimitive* rhs) {
|
||||
if (lhs == rhs) {
|
||||
return false;
|
||||
}
|
||||
if (lhs == nullptr) {
|
||||
return false;
|
||||
}
|
||||
if (rhs == nullptr) {
|
||||
return true;
|
||||
}
|
||||
return lhs->sortDepth > rhs->sortDepth;
|
||||
});
|
||||
|
||||
for (const SceneViewportOverlaySpritePrimitive* sprite : sortedSprites) {
|
||||
if (sprite == nullptr ||
|
||||
sprite->sizePixels.x <= Math::EPSILON ||
|
||||
sprite->sizePixels.y <= Math::EPSILON) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const SceneViewportProjectedPoint projectedPoint = ProjectSceneViewportWorldPoint(
|
||||
overlay.sceneOverlay,
|
||||
viewportWidth,
|
||||
viewportHeight,
|
||||
sprite->worldPosition);
|
||||
if (!projectedPoint.visible) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const ImVec2 halfSize(sprite->sizePixels.x * 0.5f, sprite->sizePixels.y * 0.5f);
|
||||
const ImVec2 center(
|
||||
viewportMin.x + projectedPoint.screenPosition.x,
|
||||
viewportMin.y + projectedPoint.screenPosition.y);
|
||||
DrawSceneViewportSpriteIcon(
|
||||
drawList,
|
||||
ImVec2(center.x - halfSize.x, center.y - halfSize.y),
|
||||
ImVec2(center.x + halfSize.x, center.y + halfSize.y),
|
||||
sprite->textureKind);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void DrawSceneViewportHudOverlay(
|
||||
@@ -25,6 +122,11 @@ void DrawSceneViewportHudOverlay(
|
||||
}
|
||||
|
||||
drawList->PushClipRect(viewportMin, viewportMax, true);
|
||||
DrawSceneViewportSceneIcons(
|
||||
drawList,
|
||||
overlay,
|
||||
viewportMin,
|
||||
viewportMax);
|
||||
if (overlay.showOrientationGizmo) {
|
||||
DrawSceneViewportOrientationGizmo(
|
||||
drawList,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "IViewportHostService.h"
|
||||
#include "SceneViewportEditorOverlayData.h"
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
@@ -26,18 +26,28 @@ struct SceneViewportHudOverlayHitResult {
|
||||
struct SceneViewportHudOverlayData {
|
||||
SceneViewportOverlayData sceneOverlay = {};
|
||||
bool showOrientationGizmo = true;
|
||||
bool showSceneIcons = true;
|
||||
const SceneViewportOverlayFrameData* overlayFrameData = nullptr;
|
||||
|
||||
bool HasVisibleElements() const {
|
||||
return sceneOverlay.valid && showOrientationGizmo;
|
||||
return sceneOverlay.valid &&
|
||||
(showOrientationGizmo ||
|
||||
(showSceneIcons &&
|
||||
overlayFrameData != nullptr &&
|
||||
!overlayFrameData->worldSprites.empty()));
|
||||
}
|
||||
};
|
||||
|
||||
inline SceneViewportHudOverlayData BuildSceneViewportHudOverlayData(
|
||||
const SceneViewportOverlayData& sceneOverlay,
|
||||
bool showOrientationGizmo = true) {
|
||||
bool showOrientationGizmo = true,
|
||||
const SceneViewportOverlayFrameData* overlayFrameData = nullptr,
|
||||
bool showSceneIcons = true) {
|
||||
SceneViewportHudOverlayData data = {};
|
||||
data.sceneOverlay = sceneOverlay;
|
||||
data.showOrientationGizmo = showOrientationGizmo;
|
||||
data.showSceneIcons = showSceneIcons;
|
||||
data.overlayFrameData = overlayFrameData;
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
@@ -143,6 +143,7 @@ inline bool ShouldFocusSceneViewportAfterInteraction(
|
||||
struct SceneViewportPresentationRequest {
|
||||
IEditorContext* context = nullptr;
|
||||
IViewportHostService* viewportHostService = nullptr;
|
||||
const SceneViewportOverlayFrameData* overlayFrameData = nullptr;
|
||||
bool hasInteractiveViewport = false;
|
||||
SceneViewportFrameGeometry geometry = {};
|
||||
SceneViewportTransformGizmoFrameOptions gizmoFrameOptions = {};
|
||||
@@ -182,7 +183,10 @@ inline void RefreshAndDrawSceneViewportPresentation(const SceneViewportPresentat
|
||||
|
||||
DrawSceneViewportHudOverlay(
|
||||
request.drawList,
|
||||
BuildSceneViewportHudOverlayData(overlay),
|
||||
BuildSceneViewportHudOverlayData(
|
||||
overlay,
|
||||
true,
|
||||
request.overlayFrameData),
|
||||
request.viewportMin,
|
||||
request.viewportMax);
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ inline SceneViewportRenderPlanBuildResult BuildSceneViewportRenderPlan(
|
||||
}
|
||||
}
|
||||
|
||||
if (editorOverlayFrameData.HasOverlayPrimitives() &&
|
||||
if (editorOverlayFrameData.HasRenderPassPrimitives() &&
|
||||
overlayPassFactory != nullptr) {
|
||||
std::unique_ptr<Rendering::RenderPass> overlayPass = overlayPassFactory(editorOverlayFrameData);
|
||||
if (overlayPass != nullptr) {
|
||||
|
||||
Reference in New Issue
Block a user