diff --git a/Source/Engine/Renderer/GBufferPass.cpp b/Source/Engine/Renderer/GBufferPass.cpp
index 1881aac3b..e62970f83 100644
--- a/Source/Engine/Renderer/GBufferPass.cpp
+++ b/Source/Engine/Renderer/GBufferPass.cpp
@@ -158,6 +158,7 @@ void GBufferPass::Fill(RenderContext& renderContext, GPUTexture* lightBuffer)
renderContext.Buffers->GBuffer3->View(),
};
renderContext.View.Pass = DrawPass::GBuffer;
+ context->SetViewportAndScissors(renderContext.Buffers->GetViewport());
// Clear GBuffer
{
diff --git a/Source/Engine/UI/GUI/CanvasRootControl.cs b/Source/Engine/UI/GUI/CanvasRootControl.cs
index 4697c5051..db6722090 100644
--- a/Source/Engine/UI/GUI/CanvasRootControl.cs
+++ b/Source/Engine/UI/GUI/CanvasRootControl.cs
@@ -25,12 +25,12 @@ namespace FlaxEngine.GUI
///
/// Gets a value indicating whether canvas is 2D (screen-space).
///
- public bool Is2D => _canvas.RenderMode == CanvasRenderMode.ScreenSpace;
+ public bool Is2D => _canvas.Is2D;
///
/// Gets a value indicating whether canvas is 3D (world-space or camera-space).
///
- public bool Is3D => _canvas.RenderMode != CanvasRenderMode.ScreenSpace;
+ public bool Is3D => _canvas.Is3D;
///
/// Initializes a new instance of the class.
diff --git a/Source/Engine/UI/GUI/CanvasScaler.cs b/Source/Engine/UI/GUI/CanvasScaler.cs
index 1e30fd22f..8dc1fcd4d 100644
--- a/Source/Engine/UI/GUI/CanvasScaler.cs
+++ b/Source/Engine/UI/GUI/CanvasScaler.cs
@@ -298,6 +298,7 @@ namespace FlaxEngine.GUI
{
case CanvasRenderMode.WorldSpace:
case CanvasRenderMode.WorldSpaceFaceCamera:
+ case CanvasRenderMode.GPUTexture:
scale = 1.0f;
break;
default:
diff --git a/Source/Engine/UI/UICanvas.cs b/Source/Engine/UI/UICanvas.cs
index 20c81ce1c..df542aacf 100644
--- a/Source/Engine/UI/UICanvas.cs
+++ b/Source/Engine/UI/UICanvas.cs
@@ -33,6 +33,11 @@ namespace FlaxEngine
/// The world space rendering mode that places Canvas as any other object in the scene and orients it to face the camera. The size of the Canvas can be set manually using its Transform, and UI elements will render in front of or behind other objects in the scene based on 3D placement. This is useful for UIs that are meant to be a part of the world. This is also known as a 'diegetic interface'.
///
WorldSpaceFaceCamera = 3,
+
+ ///
+ /// The off-screen rendering mode that draws the contents of the canvas into a GPU texture that can be used in the scene or by other systems. The size of the canvas is automatically set to the size of the texture.
+ ///
+ GPUTexture = 4,
}
///
@@ -105,7 +110,7 @@ namespace FlaxEngine
private CanvasRenderMode _renderMode;
private readonly CanvasRootControl _guiRoot;
private CanvasRenderer _renderer;
- private bool _isLoading, _isRegisteredForTick;
+ private bool _isLoading, _isRegisteredForTick, _isRegisteredForOnDraw;
///
/// Gets or sets the canvas rendering mode.
@@ -169,6 +174,8 @@ namespace FlaxEngine
private bool Editor_IsCameraSpace => _renderMode == CanvasRenderMode.CameraSpace;
+ private bool Editor_IsGPUTexture => _renderMode == CanvasRenderMode.GPUTexture;
+
private bool Editor_UseRenderCamera => _renderMode == CanvasRenderMode.CameraSpace || _renderMode == CanvasRenderMode.WorldSpaceFaceCamera;
#endif
@@ -206,6 +213,12 @@ namespace FlaxEngine
[EditorOrder(60), Limit(0.01f), EditorDisplay("Canvas"), VisibleIf("Editor_IsCameraSpace"), Tooltip("Distance from the RenderCamera to place the plane with GUI. If the screen is resized, changes resolution, or the camera frustum changes, the Canvas will automatically change size to match as well.")]
public float Distance { get; set; } = 500;
+ ///
+ /// Gets or sets the output texture for the canvas when render mode is set to . The size of the canvas will be automatically set to the size of the texture. The canvas will render its content into this texture.
+ ///
+ [EditorOrder(70), NoSerialize, EditorDisplay("Canvas"), VisibleIf("Editor_IsGPUTexture")]
+ public GPUTexture OutputTexture { get; set; }
+
///
/// Gets the canvas GUI root control.
///
@@ -329,6 +342,11 @@ namespace FlaxEngine
_isRegisteredForTick = false;
Scripting.Update -= OnUpdate;
}
+ if (_isRegisteredForOnDraw)
+ {
+ _isRegisteredForOnDraw = false;
+ Scripting.Draw -= OnDraw;
+ }
}
///
@@ -358,7 +376,7 @@ namespace FlaxEngine
///
/// Gets a value indicating whether canvas is 3D (world-space or camera-space).
///
- public bool Is3D => _renderMode != CanvasRenderMode.ScreenSpace;
+ public bool Is3D => _renderMode != CanvasRenderMode.ScreenSpace && _renderMode != CanvasRenderMode.GPUTexture;
///
/// Gets the world matrix used to transform the GUI from the local space to the world space. Handles canvas rendering mode
@@ -491,6 +509,11 @@ namespace FlaxEngine
{
if (_isLoading)
return;
+ if (_isRegisteredForOnDraw)
+ {
+ _isRegisteredForOnDraw = false;
+ Scripting.Draw -= OnDraw;
+ }
switch (_renderMode)
{
@@ -563,7 +586,32 @@ namespace FlaxEngine
}
break;
}
+ case CanvasRenderMode.GPUTexture:
+ {
+ if (!_isRegisteredForOnDraw)
+ {
+ _isRegisteredForOnDraw = true;
+ Scripting.Draw += OnDraw;
+ }
+ break;
}
+ }
+ }
+
+ private void OnDraw()
+ {
+ var outputTexture = OutputTexture;
+ if (!outputTexture || !outputTexture.IsAllocated)
+ return;
+ var context = GPUDevice.Instance.MainContext;
+ _guiRoot.Size = outputTexture.Size;
+
+ Profiler.BeginEvent("UI Canvas");
+ Profiler.BeginEventGPU("UI Canvas");
+ context.Clear(outputTexture.View(), Color.Transparent);
+ Render2D.CallDrawing(GUI, context, outputTexture);
+ Profiler.EndEvent();
+ Profiler.EndEventGPU();
}
private void OnUpdate()