Example #1
0
        public OpenGLSceneProcessor(IServiceProvider serviceProvider, IRenderWindow renderWindow, SceneGraph sceneGraph)
        {
            _serviceProvider          = serviceProvider;
            _cancellationTokenManager = _serviceProvider.GetRequiredService <CancellationTokenSource>();
            _logger         = _serviceProvider.GetRequiredService <ILogger <RenderWindow> >();
            _shaderCompiler = _serviceProvider.GetRequiredService <IShaderCompiler>();
            _textureLoader  = _serviceProvider.GetRequiredService <ITextureLoader>();

            _renderWindow   = renderWindow; // This cannot be passed via the service provider otherwise there will be a cycle in the DI graph
            _sceneGraph     = sceneGraph;
            _renderList     = new LinkedList <IRenderCommand>();
            _renderInfo     = new RenderInfo();
            _requestPicking = null;

            GL.LoadBindings(new GLFWBindingsContext());

            // Get human readable log messages during debugging
            if (Debugger.IsAttached)
            {
                GL.Enable(EnableCap.DebugOutput);
                _debugProc = DebugMessageCallback;
                _gcHandle  = GCHandle.Alloc(_debugProc);
                GL.DebugMessageCallback(_debugProc, IntPtr.Zero);
            }

            GL.Enable(EnableCap.DepthTest);

            // Save default frame buffer id for later blitting
            GL.GetInteger(GetPName.FramebufferBinding, out _defaultFrameBufferId);
            GL.BindFramebuffer(FramebufferTarget.Framebuffer, _defaultFrameBufferId);

            InitFrameBuffer(640, 360);
        }
Example #2
0
        public void UpdateState(IRenderCommand renderCommand)
        {
            if (renderCommand is RequestPickingInfo requestPicking)
            {
                _requestPicking = requestPicking;
            }

            renderCommand.SetState(_renderInfo);

            InsertCommandInRenderOrder(renderCommand);
        }
Example #3
0
        public void Render(double timeSinceLastFrameSeconds)
        {
            _renderInfo.TotalRenderTime        += timeSinceLastFrameSeconds;
            _renderInfo.FrameRate               = 1.0 / timeSinceLastFrameSeconds;
            _renderInfo.CurrentViewMatrix       = _sceneGraph.ViewMatrix;
            _renderInfo.CurrentProjectionMatrix = _sceneGraph.ProjectionMatrix;

            // Resize frame buffer object (FBO) to account for resized window
            if (_windowSizeChanged)
            {
                GL.BindFramebuffer(FramebufferTarget.Framebuffer, _defaultFrameBufferId);
                GL.Viewport(0, 0, _renderInfo.Width, _renderInfo.Height);

                // Clean up existing frame buffer
                GL.DeleteFramebuffer(_mrtFrameBufferId);
                GL.DeleteTextures(2, new[] { _mrtFrameBufferPickingTextureId, _mrtFrameBufferMainTextureId });
                GL.DeleteRenderbuffer(_mrtFrameBufferDepthId);

                // Create new MRT frameobuffer with resized dimensions
                InitFrameBuffer(_renderInfo.Width, _renderInfo.Height);

                _windowSizeChanged = false;
                _logger.LogInformation($"Window resized to {_renderInfo.Width}x{_renderInfo.Height}={_renderInfo.Width * _renderInfo.Height} pixels");
            }

            GL.BindFramebuffer(FramebufferTarget.Framebuffer, _mrtFrameBufferId);
            GL.DrawBuffers(2, new[] { DrawBuffersEnum.ColorAttachment0, DrawBuffersEnum.ColorAttachment1 });

            if (!_renderList.Any())
            {
                return;
            }

            // Render content
            GL.Clear(ClearBufferMask.DepthBufferBit);
            GL.ClearBuffer(ClearBuffer.Color, 1, new float[] { 0, 0, 0, 0 });
            var currentNode = _renderList.First;

            while (currentNode != null)
            {
                var command = currentNode.Value;
                command.Render(_renderInfo);
                var next = currentNode.Next;
                if (command.SelfDestruct)
                {
                    _renderList.Remove(currentNode);
                    if (command is IDisposable disposable)
                    {
                        disposable.Dispose();
                    }
                }
                currentNode = next;
            }

            // Process picking request
            if (_requestPicking != null)
            {
                var pickingInfo = GetPickingInfo(_renderInfo, _requestPicking.ScreenX, _requestPicking.ScreenY);
                var writeTask   = Task.Run(async() =>
                {
                    await _renderWindow.EventChannel.Writer.WriteAsync(new PickingFeedback(pickingInfo),
                                                                       _cancellationTokenManager.Token);
                });
                writeTask.Wait();
                _requestPicking = null;
            }

            // Blit MRT source to default frame buffer to display it
            GL.ReadBuffer(ReadBufferMode.ColorAttachment0); // copy main texture
            GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, _mrtFrameBufferId);
            GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, _defaultFrameBufferId);
            GL.BlitFramebuffer(0, 0, _renderInfo.Width - 1, _renderInfo.Height - 1, // source
                               0, 0, _renderInfo.Width - 1, _renderInfo.Height - 1, // destination
                               ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit, BlitFramebufferFilter.Nearest);
        }