// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using System;
using FlaxEngine;
namespace FlaxEditor.Gizmo
{
///
/// Interface for editor viewports that can contain and use .
///
[HideInEditor]
public interface IEditorPrimitivesOwner
{
///
/// Draws the custom editor primitives.
///
/// The GPU commands context.
/// The rendering context.
/// The output texture to render to.
/// The scene depth buffer that can be used to z-buffering.
void DrawEditorPrimitives(GPUContext context, ref RenderContext renderContext, GPUTexture target, GPUTexture targetDepth);
}
///
/// In-build postFx used to render debug shapes, gizmo tools and other editor primitives to MSAA render target and composite it with the editor preview window.
///
[HideInEditor]
public sealed class EditorPrimitives : PostProcessEffect
{
///
/// The target viewport.
///
public IEditorPrimitivesOwner Viewport;
///
public EditorPrimitives()
{
Order = -100;
}
///
public override void Render(GPUContext context, ref RenderContext renderContext, GPUTexture input, GPUTexture output)
{
if (Viewport == null)
throw new NullReferenceException();
Profiler.BeginEventGPU("Editor Primitives");
// Check if use MSAA
var format = output.Format;
var formatFeatures = GPUDevice.Instance.GetFormatFeatures(format);
bool enableMsaa = formatFeatures.MSAALevelMax >= MSAALevel.X4 && Editor.Instance.Options.Options.Visual.EnableMSAAForDebugDraw;
// Prepare
var msaaLevel = enableMsaa ? MSAALevel.X4 : MSAALevel.None;
var width = output.Width;
var height = output.Height;
var desc = GPUTextureDescription.New2D(width, height, format, GPUTextureFlags.RenderTarget | GPUTextureFlags.ShaderResource, 1, 1, msaaLevel);
var target = RenderTargetPool.Get(ref desc);
desc = GPUTextureDescription.New2D(width, height, PixelFormat.D24_UNorm_S8_UInt, GPUTextureFlags.DepthStencil, 1, 1, msaaLevel);
var targetDepth = RenderTargetPool.Get(ref desc);
// Copy frame and clear depth
context.Draw(target, input);
context.ClearDepth(targetDepth.View());
context.SetViewport(width, height);
context.SetRenderTarget(targetDepth.View(), target.View());
// Draw gizmos and other editor primitives
var renderList = RenderList.GetFromPool();
var prevList = renderContext.List;
renderContext.List = renderList;
renderContext.View.Pass = DrawPass.GBuffer | DrawPass.Forward;
try
{
Viewport.DrawEditorPrimitives(context, ref renderContext, target, targetDepth);
}
catch (Exception ex)
{
Editor.LogWarning(ex);
}
// Sort draw calls
renderList.SortDrawCalls(ref renderContext, false, DrawCallsListType.GBuffer);
renderList.SortDrawCalls(ref renderContext, false, DrawCallsListType.GBufferNoDecals);
renderList.SortDrawCalls(ref renderContext, true, DrawCallsListType.Forward);
// Perform the rendering
renderContext.View.Pass = DrawPass.GBuffer;
renderList.ExecuteDrawCalls(ref renderContext, DrawCallsListType.GBuffer);
renderList.ExecuteDrawCalls(ref renderContext, DrawCallsListType.GBufferNoDecals);
renderContext.View.Pass = DrawPass.Forward;
renderList.ExecuteDrawCalls(ref renderContext, DrawCallsListType.Forward);
// Resolve MSAA texture
if (enableMsaa)
context.ResolveMultisample(target, output);
else
context.Draw(output, target);
// Cleanup
RenderTargetPool.Release(targetDepth);
RenderTargetPool.Release(target);
RenderList.ReturnToPool(renderList);
renderContext.List = prevList;
Profiler.EndEventGPU();
}
}
}