/// <summary> /// The primary rendering logic. Here, the current object is rendered using OpenGL. /// </summary> public void RenderFrame() { ThrowIfDisposed(); lock (_renderTargetLock) { // Make sure the viewport is accurate for the current widget size on screen var widgetWidth = _viewportWidget.AllocatedWidth; var widgetHeight = _viewportWidget.AllocatedHeight; GL.Viewport(0, 0, widgetWidth, widgetHeight); GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); if (!this.HasRenderTarget || this.RenderTarget is null) { return; } // Calculate the current relative movement of the camera if (this.WantsToMove) { switch (this.RenderTarget.Projection) { case ProjectionType.Orthographic: { Calculate2DMovement(); break; } case ProjectionType.Perspective: { Calculate3DMovement(); break; } } } // Render the current object // Tick the actor, advancing any time-dependent behaviour var tickingRenderable = this.RenderTarget as ITickingActor; tickingRenderable?.Tick(this.DeltaTime); // Update the camera with new parameters _camera.ViewportHeight = widgetHeight; _camera.ViewportWidth = widgetWidth; var view = _camera.GetViewMatrix(); var projection = _camera.GetProjectionMatrix(); if (this.RenderTarget.Projection == ProjectionType.Perspective) { _grid?.Render(view, projection, _camera); } // Then render the visual component this.RenderTarget.Render(view, projection, _camera); } }