private void OnUpdate() { if (_queue.Count == 0 || (_task != null && _task.Enabled)) { return; } // TODO: add delay when processing the requests to reduce perf impact (eg. 0.2s before actual rendering) // Setup pipeline if (_atlases == null) { _atlases = new List <Atlas>(4); } if (_output == null) { _output = GPUDevice.Instance.CreateTexture("CameraCutMedia.Output"); var desc = GPUTextureDescription.New2D(Width, Height, PixelFormat.R8G8B8A8_UNorm); _output.Init(ref desc); } if (_task == null) { _task = Object.New <SceneRenderTask>(); _task.Output = _output; _task.Begin += OnBegin; _task.End += OnEnd; } // Kick off the rendering _task.Enabled = true; }
/// <summary> /// Synchronizes size of the back buffer with the size of the control. /// </summary> public void SyncBackbufferSize() { float scale = ResolutionScale * Platform.DpiScale; int width = Mathf.CeilToInt(Width * scale); int height = Mathf.CeilToInt(Height * scale); if (_backBuffer == null || _backBuffer.Width == width && _backBuffer.Height == height) { return; } if (width < 1 || height < 1) { _backBuffer.ReleaseGPU(); Object.Destroy(ref _backBufferOld); return; } // Cache old backbuffer to remove flickering effect if (_backBufferOld == null && _backBuffer.IsAllocated) { _backBufferOld = _backBuffer; _backBuffer = GPUDevice.Instance.CreateTexture(); } // Set timeout to remove old buffer _oldBackbufferLiveTimeLeft = 3; // Resize backbuffer var desc = GPUTextureDescription.New2D(width, height, BackBufferFormat); _backBuffer.Init(ref desc); _task.Output = _backBuffer; }
public static GPUTexture CreateOutputTexture(Vector2 size) { var texture = GPUDevice.CreateTexture(); var description = GPUTextureDescription.New2D((int)size.X, (int)size.Y, PixelFormat.R8G8B8A8_UNorm); texture.Init(ref description); return(texture); }
/// <inheritdoc /> public override void Render(GPUContext context, SceneRenderTask task, GPUTexture input, GPUTexture output) { if (Viewport == null) { throw new NullReferenceException(); } Profiler.BeginEventGPU("Editor Primitives"); // Check if use MSAA var format = output.Format; GPUDevice.GetFeatures(format, out var formatSupport); bool enableMsaa = formatSupport.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); // Draw gizmos and other editor primitives (collect draw calls only) _drawCallsCollector.Clear(); for (int i = 0; i < Viewport.Gizmos.Count; i++) { Viewport.Gizmos[i].Draw(_drawCallsCollector); } Viewport.DrawEditorPrimitives(context, task, target, targetDepth, _drawCallsCollector); // Draw gizmos (actual drawing) _drawCallsCollector.ExecuteDrawCalls(context, task, target, DrawPass.GBuffer); _drawCallsCollector.ExecuteDrawCalls(context, task, target, DrawPass.Forward); // Resolve MSAA texture if (enableMsaa) { context.ResolveMultisample(target, output); } else { context.Draw(output, target); } // Cleanup RenderTargetPool.Release(targetDepth); RenderTargetPool.Release(target); Profiler.EndEventGPU(); }
public override void Initialize() { _output = GPUDevice.CreateTexture(); _cachedSize = SizeGetter(); var description = GPUTextureDescription.New2D(_cachedSize.X, _cachedSize.Y, PixelFormat.R8G8B8A8_UNorm); _output.Init(ref description); _outputPromise.SetResult(_output); Task.Render = OnRender; Task.Enabled = true; }
/// <inheritdoc /> public override void OnInit() { // Create cache folder if (!Directory.Exists(_cacheFolder)) { Directory.CreateDirectory(_cacheFolder); } // Find atlases in a Editor cache directory var files = Directory.GetFiles(_cacheFolder, "cache_*.flax", SearchOption.TopDirectoryOnly); int atlases = 0; for (int i = 0; i < files.Length; i++) { // Load asset var asset = FlaxEngine.Content.LoadAsync(files[i]); if (asset == null) { continue; } // Validate type if (asset is PreviewsCache atlas) { // Cache atlas atlases++; _cache.Add(atlas); } else { // Skip asset Editor.LogWarning(string.Format("Asset \'{0}\' is inside Editor\'s private directory for Assets Thumbnails Cache. Please move it.", asset.Path)); } } Editor.Log(string.Format("Previews cache count: {0} (capacity for {1} icons)", atlases, atlases * PreviewsCache.AssetIconsPerAtlas)); // Prepare at least one atlas if (_cache.Count == 0) { GetValidAtlas(); } // Create render task but disabled for now _output = GPUDevice.Instance.CreateTexture("ThumbnailsOutput"); var desc = GPUTextureDescription.New2D(PreviewsCache.AssetIconSize, PreviewsCache.AssetIconSize, PreviewsCache.AssetIconsAtlasFormat); _output.Init(ref desc); _task = Object.New <RenderTask>(); _task.Order = 50; // Render this task later _task.Enabled = false; _task.Render += OnRender; }
private void StartRendering() { if (_isRendering) { return; } var editor = Editor.Instance; // Check if save the asset before rendering if (_window.IsEdited) { var result = MessageBox.Show("Save scene animation asset to file before rendering?", "Save?", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question); if (result == DialogResult.Yes) { _window.Save(); } else if (result != DialogResult.No) { return; } } // Update UI _isRendering = true; _presenter.Panel.Enabled = false; _presenter.BuildLayoutOnUpdate(); // Start rendering Editor.Log("Starting scene animation rendering " + _options.Animation); _dt = 1.0f / _options.FrameRate; _player = new SceneAnimationPlayer { Animation = _options.Animation, HideFlags = HideFlags.FullyHidden, RestoreStateOnStop = true, PlayOnStart = false, RandomStartTime = false, StartTime = _options.StartTime, UpdateMode = SceneAnimationPlayer.UpdateModes.Manual, }; FlaxEngine.Scripting.Update += Tick; _wasGamePaused = Time.GamePaused; Time.GamePaused = false; Time.SetFixedDeltaTime(true, _dt); Time.UpdateFPS = Time.DrawFPS = _options.FrameRate; if (!Editor.IsPlayMode) { Time.PhysicsFPS = 0; } Level.SpawnActor(_player); var gameWin = editor.Windows.GameWin; var resolution = _options.GetResolution(); gameWin.Viewport.CustomResolution = resolution; gameWin.Viewport.BackgroundColor = Color.Black; gameWin.Viewport.KeepAspectRatio = true; gameWin.Viewport.Task.PostRender += OnPostRender; if (!gameWin.Visible) { gameWin.Show(); } else if (!gameWin.IsFocused) { gameWin.Focus(); } _gameWindow = gameWin; _warmUpTimeLeft = _options.WarmUpTime; _animationFrame = 0; var stagingTextureDesc = GPUTextureDescription.New2D(resolution.X, resolution.Y, gameWin.Viewport.Task.Output.Format, GPUTextureFlags.None); stagingTextureDesc.Usage = GPUResourceUsage.StagingReadback; for (int i = 0; i < _stagingTextures.Length; i++) { _stagingTextures[i].Texture = new GPUTexture(); _stagingTextures[i].Texture.Init(ref stagingTextureDesc); _stagingTextures[i].AnimationFrame = -1; _stagingTextures[i].TaskFrame = -1; } _player.Play(); if (!_player.IsPlaying) { Editor.LogError("Scene Animation Player failed to start playing."); CancelRendering(); return; } if (_warmUpTimeLeft > 0.0f) { // Start warmup time _player.Tick(0.0f); _player.Pause(); _state = States.Warmup; } else { // Render first frame _state = States.Render; } if (!Editor.IsPlayMode) { _editorState = new RenderEditorState(editor, this); editor.StateMachine.AddState(_editorState); editor.StateMachine.GoToState(_editorState); } _progress = new RenderProgress(); editor.ProgressReporting.RegisterHandler(_progress); _progress.Start(); }
/// <inheritdoc /> 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; for (int i = 0; i < Viewport.Gizmos.Count; i++) { Viewport.Gizmos[i].Draw(ref renderContext); } Viewport.DrawEditorPrimitives(context, ref renderContext, target, targetDepth); // 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(); }
public override void Initialize() { StringBuilder sb = new StringBuilder(512); ETrackedPropertyError error = ETrackedPropertyError.TrackedProp_Success; uint ret = _vrSystem.GetStringTrackedDeviceProperty( OVR.k_unTrackedDeviceIndex_Hmd, ETrackedDeviceProperty.Prop_TrackingSystemName_String, sb, 512u, ref error); if (error != ETrackedPropertyError.TrackedProp_Success) { _deviceName = "<Unknown OpenVR Device>"; } else { _deviceName = sb.ToString(); } uint eyeWidth = 0; uint eyeHeight = 0; _vrSystem.GetRecommendedRenderTargetSize(ref eyeWidth, ref eyeHeight); _leftEyeGT = GPUDevice.CreateTexture(); var descLeftEye = GPUTextureDescription.New2D((int)eyeWidth, (int)eyeHeight, 1, PixelFormat.R8G8B8A8_UNorm, msaaLevel: _options.EyeRenderTargetSampleCount); _leftEyeGT.Init(ref descLeftEye); _rightEyeGT = GPUDevice.CreateTexture(); var descRightEye = GPUTextureDescription.New2D((int)eyeWidth, (int)eyeHeight, 1, PixelFormat.R8G8B8A8_UNorm, msaaLevel: _options.EyeRenderTargetSampleCount); _rightEyeGT.Init(ref descRightEye); Matrix eyeToHeadLeft = ToSysMatrix(_vrSystem.GetEyeToHeadTransform(EVREye.Eye_Left)); Matrix.Invert(ref eyeToHeadLeft, out _headToEyeLeft); Matrix eyeToHeadRight = ToSysMatrix(_vrSystem.GetEyeToHeadTransform(EVREye.Eye_Right)); Matrix.Invert(ref eyeToHeadRight, out _headToEyeRight); // Default RH matrices /*_projLeft = ToSysMatrix(_vrSystem.GetProjectionMatrix(EVREye.Eye_Left, 0.1f, 10000f)); * _projRight = ToSysMatrix(_vrSystem.GetProjectionMatrix(EVREye.Eye_Right, 0.1f, 10000f));*/ // Build LH projection matrices (https://github.com/ValveSoftware/openvr/wiki/IVRSystem::GetProjectionRaw) float pLeft = 0; float pRight = 0; float pTop = 0; float pBottom = 0; // Default values float zNear = 0.1f; float zFar = 20000f; _vrSystem.GetProjectionRaw(EVREye.Eye_Left, ref pLeft, ref pRight, ref pTop, ref pBottom); _projLeft = Matrix.PerspectiveOffCenter(pLeft * zNear, pRight * zNear, pBottom * zNear * -1f, pTop * zNear * -1f, zNear, zFar); _vrSystem.GetProjectionRaw(EVREye.Eye_Right, ref pLeft, ref pRight, ref pTop, ref pBottom); _projRight = Matrix.PerspectiveOffCenter(pLeft * zNear, pRight * zNear, pBottom * zNear * -1f, pTop * zNear * -1f, zNear, zFar); }