public void Dispose() { shader.Dispose(); GL.BindVertexArray(0); GL.DeleteVertexArray(quadVAO); frameBuffer?.Dispose(); }
public void RenderBorderFront(AGSBoundingBox square) { if (_settings.WindowSize.Equals(_lastWindowSize) && _lastSquare.SameSize(square) && _glUtils.DrawQuad(_frameBuffer, square, _quad)) { return; } _frameBuffer?.Dispose(); _lastSquare = square; _lastWindowSize = _settings.WindowSize; float width = _glUtils.CurrentResolution.Width - _padding; float height = _glUtils.CurrentResolution.Height - _padding; _frameBuffer = _glUtils.BeginFrameBuffer(square, _settings); if (_frameBuffer == null) { return; } _glUtils.DrawLine(_padding, _padding, width, height, _lineWidth, _color.R, _color.G, _color.B, _color.A); _glUtils.DrawLine(_padding, height, width, _padding, _lineWidth, _color.R, _color.G, _color.B, _color.A); _frameBuffer.End(); _glUtils.DrawQuad(_frameBuffer, square, _quad); }
public void BeginFrame(int2 scroll, float zoom) { Context.Clear(); var surfaceSize = Window.SurfaceSize; var surfaceBufferSize = surfaceSize.NextPowerOf2(); if (screenSprite == null || screenSprite.Sheet.Size != surfaceBufferSize) { if (screenBuffer != null) { screenBuffer.Dispose(); } // Render the screen into a frame buffer to simplify reading back screenshots screenBuffer = Context.CreateFrameBuffer(surfaceBufferSize, Color.FromArgb(0xFF, 0, 0, 0)); } if (screenSprite == null || surfaceSize.Width != screenSprite.Bounds.Width || -surfaceSize.Height != screenSprite.Bounds.Height) { var screenSheet = new Sheet(SheetType.BGRA, screenBuffer.Texture); // Flip sprite in Y to match OpenGL's bottom-left origin var screenBounds = Rectangle.FromLTRB(0, surfaceSize.Height, surfaceSize.Width, 0); screenSprite = new Sprite(screenSheet, screenBounds, TextureChannel.RGBA); } screenBuffer.Bind(); SetViewportParams(scroll, zoom); }
public void BeginWorld(Rectangle worldViewport) { if (renderType != RenderType.None) { throw new InvalidOperationException("BeginWorld called with renderType = {0}, expected RenderType.None.".F(renderType)); } BeginFrame(); var worldBufferSize = worldViewport.Size.NextPowerOf2(); if (worldSprite == null || worldSprite.Sheet.Size != worldBufferSize) { if (worldBuffer != null) { worldBuffer.Dispose(); } // Render the world into a framebuffer at 1:1 scaling to allow the depth buffer to match the artwork at all zoom levels worldBuffer = Context.CreateFrameBuffer(worldBufferSize); // Pixel art scaling mode is a customized bilinear sampling worldBuffer.Texture.ScaleFilter = TextureScaleFilter.Linear; } if (worldSprite == null || worldViewport.Size != worldSprite.Bounds.Size) { var worldSheet = new Sheet(SheetType.BGRA, worldBuffer.Texture); worldSprite = new Sprite(worldSheet, new Rectangle(int2.Zero, worldViewport.Size), TextureChannel.RGBA); } worldBuffer.Bind(); if (worldBufferSize != lastWorldBufferSize || lastWorldViewport != worldViewport) { var depthScale = worldBufferSize.Height / (worldBufferSize.Height + depthMargin); WorldSpriteRenderer.SetViewportParams(worldBufferSize, depthScale, depthScale / 2, worldViewport.Location); WorldModelRenderer.SetViewportParams(worldBufferSize, worldViewport.Location); lastWorldViewport = worldViewport; lastWorldBufferSize = worldBufferSize; } renderType = RenderType.World; }
void BeginFrame() { Context.Clear(); var surfaceSize = Window.SurfaceSize; var surfaceBufferSize = surfaceSize.NextPowerOf2(); if (screenSprite == null || screenSprite.Sheet.Size != surfaceBufferSize) { if (screenBuffer != null) { screenBuffer.Dispose(); } // Render the screen into a frame buffer to simplify reading back screenshots screenBuffer = Context.CreateFrameBuffer(surfaceBufferSize, Color.FromArgb(0xFF, 0, 0, 0)); } if (screenSprite == null || surfaceSize.Width != screenSprite.Bounds.Width || -surfaceSize.Height != screenSprite.Bounds.Height) { var screenSheet = new Sheet(SheetType.BGRA, screenBuffer.Texture); // Flip sprite in Y to match OpenGL's bottom-left origin var screenBounds = Rectangle.FromLTRB(0, surfaceSize.Height, surfaceSize.Width, 0); screenSprite = new Sprite(screenSheet, screenBounds, TextureChannel.RGBA); } // In HiDPI windows we follow Apple's convention of defining window coordinates as for standard resolution windows // but to have a higher resolution backing surface with more than 1 texture pixel per viewport pixel. // We must convert the surface buffer size to a viewport size - in general this is NOT just the window size // rounded to the next power of two, as the NextPowerOf2 calculation is done in the surface pixel coordinates var scale = Window.EffectiveWindowScale; var bufferSize = new Size((int)(surfaceBufferSize.Width / scale), (int)(surfaceBufferSize.Height / scale)); if (lastBufferSize != bufferSize) { SpriteRenderer.SetViewportParams(bufferSize, 0f, 0f, int2.Zero); lastBufferSize = bufferSize; } }
public void SetMaximumViewportSize(Size size) { // Aim to render the world into a framebuffer at 1:1 scaling which is then up/downscaled using a custom // filter to provide crisp scaling and avoid rendering glitches when the depth buffer is used and samples don't match. // This approach does not scale well to large sizes, first saturating GPU fill rate and then crashing when // reaching the framebuffer size limits (typically 16k). We therefore clamp the maximum framebuffer size to // twice the window surface size, which strikes a reasonable balance between rendering quality and performance. // Mods that use the depth buffer must instead limit their artwork resolution or maximum zoom-out levels. Size worldBufferSize; if (depthMargin == 0) { var surfaceSize = Window.SurfaceSize; worldBufferSize = new Size(Math.Min(size.Width, 2 * surfaceSize.Width), Math.Min(size.Height, 2 * surfaceSize.Height)).NextPowerOf2(); } else { worldBufferSize = size.NextPowerOf2(); } if (worldSprite == null || worldSheet.Size != worldBufferSize) { worldBuffer?.Dispose(); // If enableWorldFrameBufferDownscale and the world is more than twice the size of the final output size do we allow it to be downsampled! worldBuffer = Context.CreateFrameBuffer(worldBufferSize); // Pixel art scaling mode is a customized bilinear sampling worldBuffer.Texture.ScaleFilter = TextureScaleFilter.Linear; worldSheet = new Sheet(SheetType.BGRA, worldBuffer.Texture); // Invalidate cached state to force a shader update lastWorldViewport = Rectangle.Empty; worldSprite = null; } lastMaximumViewportSize = size; }