public new void DrawInRect(GLKView view, CGRect rect) { if (designMode) { return; } // create the contexts if not done already if (context == null) { var glInterface = GRGlInterface.Create(); context = GRContext.CreateGl(glInterface); } // get the new surface size var newSize = new SKSizeI((int)DrawableWidth, (int)DrawableHeight); // manage the drawing surface if (renderTarget == null || lastSize != newSize || !renderTarget.IsValid) { // create or update the dimensions lastSize = newSize; // read the info from the buffer Gles.glGetIntegerv(Gles.GL_FRAMEBUFFER_BINDING, out var framebuffer); Gles.glGetIntegerv(Gles.GL_STENCIL_BITS, out var stencil); Gles.glGetIntegerv(Gles.GL_SAMPLES, out var samples); var maxSamples = context.GetMaxSurfaceSampleCount(colorType); if (samples > maxSamples) { samples = maxSamples; } glInfo = new GRGlFramebufferInfo((uint)framebuffer, colorType.ToGlSizedFormat()); // destroy the old surface surface?.Dispose(); surface = null; canvas = null; // re-create the render target renderTarget?.Dispose(); renderTarget = new GRBackendRenderTarget(newSize.Width, newSize.Height, samples, stencil, glInfo); } // create the surface if (surface == null) { surface = SKSurface.Create(context, renderTarget, surfaceOrigin, colorType); canvas = surface.Canvas; } using (new SKAutoCanvasRestore(canvas, true)) { // start drawing var e = new SKPaintGLSurfaceEventArgs(surface, renderTarget, surfaceOrigin, colorType, glInfo); OnPaintSurface(e); #pragma warning disable CS0618 // Type or member is obsolete DrawInSurface(e.Surface, e.RenderTarget); #pragma warning restore CS0618 // Type or member is obsolete } // flush the SkiaSharp contents to GL canvas.Flush(); context.Flush(); }
public override void DrawInCGLContext(CGLContext glContext, CGLPixelFormat pixelFormat, double timeInterval, ref CVTimeStamp timeStamp) { CGLContext.CurrentContext = glContext; if (context == null) { // get the bits for SkiaSharp var glInterface = GRGlInterface.CreateNativeGlInterface(); context = GRContext.Create(GRBackend.OpenGL, glInterface); } // manage the drawing surface var surfaceWidth = (int)(Bounds.Width * ContentsScale); var surfaceHeight = (int)(Bounds.Height * ContentsScale); var newSize = new SKSizeI(surfaceWidth, surfaceHeight); if (renderTarget == null || lastSize != newSize || !renderTarget.IsValid) { // create or update the dimensions lastSize = newSize; // read the info from the buffer Gles.glGetIntegerv(Gles.GL_FRAMEBUFFER_BINDING, out var framebuffer); Gles.glGetIntegerv(Gles.GL_STENCIL_BITS, out var stencil); Gles.glGetIntegerv(Gles.GL_SAMPLES, out var samples); var maxSamples = context.GetMaxSurfaceSampleCount(colorType); if (samples > maxSamples) { samples = maxSamples; } glInfo = new GRGlFramebufferInfo((uint)framebuffer, colorType.ToGlSizedFormat()); // destroy the old surface surface?.Dispose(); surface = null; canvas = null; // re-create the render target renderTarget?.Dispose(); renderTarget = new GRBackendRenderTarget(newSize.Width, newSize.Height, samples, stencil, glInfo); } // create the surface if (surface == null) { surface = SKSurface.Create(context, renderTarget, surfaceOrigin, colorType); canvas = surface.Canvas; } using (new SKAutoCanvasRestore(canvas, true)) { // start drawing var e = new SKPaintGLSurfaceEventArgs(surface, renderTarget, surfaceOrigin, colorType, glInfo); OnPaintSurface(e); #pragma warning disable CS0618 // Type or member is obsolete DrawInSurface(e.Surface, e.RenderTarget); SKDelegate?.DrawInSurface(e.Surface, e.RenderTarget); #pragma warning restore CS0618 // Type or member is obsolete } // flush the SkiaSharp context to the GL context canvas.Flush(); context.Flush(); base.DrawInCGLContext(glContext, pixelFormat, timeInterval, ref timeStamp); }
private void Render(int cornerCount = 100, int maxVisibleDistance = 200) { // create the field if needed or if the size changed if (field == null || field.width != glControl1.Width || field.height != glControl1.Height) { field = new IntroAnimation.Field(glControl1.Width, glControl1.Height, cornerCount); } // step the field forward in time field.StepForward(3); // Create a Skia surface using the OpenGL control SKColorType colorType = SKColorType.Rgba8888; GRContext contextOpenGL = GRContext.Create(GRBackend.OpenGL, GRGlInterface.CreateNativeGlInterface()); GL.GetInteger(GetPName.FramebufferBinding, out var framebuffer); GRGlFramebufferInfo glInfo = new GRGlFramebufferInfo((uint)framebuffer, colorType.ToGlSizedFormat()); GL.GetInteger(GetPName.StencilBits, out var stencil); GRBackendRenderTarget renderTarget = new GRBackendRenderTarget(glControl1.Width, glControl1.Height, contextOpenGL.GetMaxSurfaceSampleCount(colorType), stencil, glInfo); SKSurface surface = SKSurface.Create(contextOpenGL, renderTarget, GRSurfaceOrigin.BottomLeft, colorType); SKCanvas canvas = surface.Canvas; // draw the stuff var bgColor = field.GetBackgroundColor(); canvas.Clear(new SKColor(bgColor.R, bgColor.G, bgColor.B)); // draw circles at every corner var paint = new SKPaint { Color = new SKColor(255, 255, 255), IsAntialias = true }; float radius = 2; for (int cornerIndex = 0; cornerIndex < field.corners.Length; cornerIndex++) { canvas.DrawCircle((float)field.corners[cornerIndex].X, (float)field.corners[cornerIndex].Y, radius, paint); } // draw lines between every corner and every other corner for (int i = 0; i < field.corners.Length; i++) { for (int j = 0; j < field.corners.Length; j++) { double distance = field.GetDistance(i, j); if (distance < maxVisibleDistance && distance != 0) { SKPoint pt1 = new SKPoint((float)field.corners[i].X, (float)field.corners[i].Y); SKPoint pt2 = new SKPoint((float)field.corners[j].X, (float)field.corners[j].Y); double distanceFraction = distance / maxVisibleDistance; byte alpha = (byte)(255 - distanceFraction * 256); var linePaint = new SKPaint { Color = new SKColor(255, 255, 255, alpha), IsAntialias = true }; canvas.DrawLine(pt1, pt2, linePaint); } } } // Force a display surface.Canvas.Flush(); glControl1.SwapBuffers(); // dispose to prevent memory access violations while exiting renderTarget?.Dispose(); contextOpenGL?.Dispose(); canvas?.Dispose(); surface?.Dispose(); // update the FPS display Text = field.GetBenchmarkMessage(); }
public void OnDrawFrame(IGL10 gl) { GLES10.GlClear(GLES10.GlColorBufferBit | GLES10.GlDepthBufferBit | GLES10.GlStencilBufferBit); // create the contexts if not done already if (context == null) { var glInterface = GRGlInterface.Create(); context = GRContext.CreateGl(glInterface); } // manage the drawing surface if (renderTarget == null || lastSize != newSize || !renderTarget.IsValid) { // create or update the dimensions lastSize = newSize; // read the info from the buffer var buffer = new int[3]; GLES20.GlGetIntegerv(GLES20.GlFramebufferBinding, buffer, 0); GLES20.GlGetIntegerv(GLES20.GlStencilBits, buffer, 1); GLES20.GlGetIntegerv(GLES20.GlSamples, buffer, 2); var samples = buffer[2]; var maxSamples = context.GetMaxSurfaceSampleCount(colorType); if (samples > maxSamples) { samples = maxSamples; } glInfo = new GRGlFramebufferInfo((uint)buffer[0], colorType.ToGlSizedFormat()); // destroy the old surface surface?.Dispose(); surface = null; canvas = null; // re-create the render target renderTarget?.Dispose(); renderTarget = new GRBackendRenderTarget(newSize.Width, newSize.Height, samples, buffer[1], glInfo); } // create the surface if (surface == null) { surface = SKSurface.Create(context, renderTarget, surfaceOrigin, colorType); canvas = surface.Canvas; } using (new SKAutoCanvasRestore(canvas, true)) { // start drawing var e = new SKPaintGLSurfaceEventArgs(surface, renderTarget, surfaceOrigin, colorType, glInfo); OnPaintSurface(e); #pragma warning disable CS0618 // Type or member is obsolete OnDrawFrame(e.Surface, e.RenderTarget); #pragma warning restore CS0618 // Type or member is obsolete } // flush the SkiaSharp contents to GL canvas.Flush(); context.Flush(); }
public virtual void Render() { if (glContext == null) { PrepareGLContexts(); } EAGLContext.SetCurrentContext(glContext); // get the new surface size var newSize = lastSize; if (recreateSurface) { Gles.glGetRenderbufferParameteriv(Gles.GL_RENDERBUFFER, Gles.GL_RENDERBUFFER_WIDTH, out var bufferWidth); Gles.glGetRenderbufferParameteriv(Gles.GL_RENDERBUFFER, Gles.GL_RENDERBUFFER_HEIGHT, out var bufferHeight); newSize = new SKSizeI(bufferWidth, bufferHeight); } // manage the drawing surface if (recreateSurface || renderTarget == null || lastSize != newSize || !renderTarget.IsValid) { // create or update the dimensions lastSize = newSize; // read the info from the buffer Gles.glGetIntegerv(Gles.GL_FRAMEBUFFER_BINDING, out var framebuffer); Gles.glGetIntegerv(Gles.GL_STENCIL_BITS, out var stencil); Gles.glGetIntegerv(Gles.GL_SAMPLES, out var samples); var maxSamples = context.GetMaxSurfaceSampleCount(colorType); if (samples > maxSamples) { samples = maxSamples; } glInfo = new GRGlFramebufferInfo((uint)framebuffer, colorType.ToGlSizedFormat()); // destroy the old surface surface?.Dispose(); surface = null; canvas = null; // re-create the render target renderTarget?.Dispose(); renderTarget = new GRBackendRenderTarget(newSize.Width, newSize.Height, samples, stencil, glInfo); } // create the surface if (surface == null) { surface = SKSurface.Create(context, renderTarget, surfaceOrigin, colorType); canvas = surface.Canvas; } using (new SKAutoCanvasRestore(canvas, true)) { // start drawing #pragma warning disable CS0618 // Type or member is obsolete var e = new SKPaintGLSurfaceEventArgs(surface, renderTarget, surfaceOrigin, colorType, glInfo); OnPaintSurface(e); DrawInSurface(e.Surface, e.RenderTarget); SKDelegate?.DrawInSurface(e.Surface, e.RenderTarget); #pragma warning restore CS0618 // Type or member is obsolete } // flush the SkiaSharp context to the GL context canvas.Flush(); context.Flush(); // present the GL buffers glContext.PresentRenderBuffer(Gles.GL_RENDERBUFFER); EAGLContext.SetCurrentContext(null); }
protected override void OnRenderFrame(Rect rect) { // clear everything Gles.glClear(Gles.GL_COLOR_BUFFER_BIT | Gles.GL_DEPTH_BUFFER_BIT | Gles.GL_STENCIL_BUFFER_BIT); // create the SkiaSharp context if (context == null) { glInterface = GRGlInterface.Create(); context = GRContext.CreateGl(glInterface); } // get the new surface size var newSize = new SKSizeI((int)rect.Width, (int)rect.Height); // manage the drawing surface if (renderTarget == null || lastSize != newSize || !renderTarget.IsValid) { // create or update the dimensions lastSize = newSize; // read the info from the buffer Gles.glGetIntegerv(Gles.GL_FRAMEBUFFER_BINDING, out var framebuffer); Gles.glGetIntegerv(Gles.GL_STENCIL_BITS, out var stencil); Gles.glGetIntegerv(Gles.GL_SAMPLES, out var samples); var maxSamples = context.GetMaxSurfaceSampleCount(colorType); if (samples > maxSamples) { samples = maxSamples; } glInfo = new GRGlFramebufferInfo((uint)framebuffer, colorType.ToGlSizedFormat()); // destroy the old surface surface?.Dispose(); surface = null; canvas = null; // re-create the render target renderTarget?.Dispose(); renderTarget = new GRBackendRenderTarget(newSize.Width, newSize.Height, samples, stencil, glInfo); } // create the surface if (surface == null) { surface = SKSurface.Create(context, renderTarget, surfaceOrigin, colorType); canvas = surface.Canvas; } using (new SKAutoCanvasRestore(canvas, true)) { // start drawing #pragma warning disable CS0612 // Type or member is obsolete OnPaintSurface(new SKPaintGLSurfaceEventArgs(surface, renderTarget, surfaceOrigin, colorType, glInfo)); #pragma warning restore CS0612 // Type or member is obsolete } // update the control canvas.Flush(); context.Flush(); }
protected override void OnPaint(PaintEventArgs e) { if (designMode) { e.Graphics.Clear(BackColor); return; } base.OnPaint(e); MakeCurrent(); // create the contexts if not done already if (grContext == null) { var glInterface = GRGlInterface.Create(); grContext = GRContext.CreateGl(glInterface); } // get the new surface size var newSize = new SKSizeI(Width, Height); // manage the drawing surface if (renderTarget == null || lastSize != newSize || !renderTarget.IsValid) { // create or update the dimensions lastSize = newSize; GL.GetInteger(GetPName.FramebufferBinding, out var framebuffer); GL.GetInteger(GetPName.StencilBits, out var stencil); GL.GetInteger(GetPName.Samples, out var samples); var maxSamples = grContext.GetMaxSurfaceSampleCount(colorType); if (samples > maxSamples) { samples = maxSamples; } glInfo = new GRGlFramebufferInfo((uint)framebuffer, colorType.ToGlSizedFormat()); // destroy the old surface surface?.Dispose(); surface = null; canvas = null; // re-create the render target renderTarget?.Dispose(); renderTarget = new GRBackendRenderTarget(newSize.Width, newSize.Height, samples, stencil, glInfo); } // create the surface if (surface == null) { surface = SKSurface.Create(grContext, renderTarget, surfaceOrigin, colorType); canvas = surface.Canvas; } using (new SKAutoCanvasRestore(canvas, true)) { // start drawing OnPaintSurface(new SKPaintGLSurfaceEventArgs(surface, renderTarget, surfaceOrigin, colorType, glInfo)); } // update the control canvas.Flush(); SwapBuffers(); }
public SKPaintGLSurfaceEventArgs(SKSurface surface, GRBackendRenderTarget renderTarget, GRSurfaceOrigin origin, SKColorType colorType, GRGlFramebufferInfo glInfo) { Surface = surface; BackendRenderTarget = renderTarget; ColorType = colorType; Origin = origin; #pragma warning disable CS0612 // Type or member is obsolete rtDesc = CreateDesc(glInfo); #pragma warning restore CS0612 // Type or member is obsolete }
public static void Main(string[] args) { Glfw.SetErrorCallback((error, description) => { Console.WriteLine($"GLFW Error {error}: {description}"); }); Glfw.Init(); IntPtr primaryMonitorPtr = Glfw.GetPrimaryMonitor(); Glfw.VidMode videoMode = Glfw.GetVideoMode(primaryMonitorPtr); Glfw.GetMonitorWorkarea(primaryMonitorPtr, out var workAreaX, out var workAreaY, out var workAreaWidth, out var workAreaHeight); // For a full-screen game, replace IntPtr.Zero with primaryMonitorPtr IntPtr monitorPtr = IntPtr.Zero; // Create a GLFW window var windowPtr = Glfw.CreateWindow(workAreaWidth, workAreaHeight, "C# tutorial for Mats", monitorPtr, IntPtr.Zero); Glfw.GetWindowSize(windowPtr, out var viewWidth, out var viewHeight); // Switch to full screen. // Glfw.SetWindowMonitor(windowPtr, primaryMonitorPtr, 0, 0, workAreaWidth, workAreaHeight, 60); // Make sure the OpenGL rendering context is set on the current thread, // otherwise Skia's GRContext.Create(GRBackend.OpenGL) will return null Glfw.MakeContextCurrent(windowPtr); var frameBufferInfo = new GRGlFramebufferInfo((uint)new UIntPtr(0), GRPixelConfig.Rgba8888.ToGlSizedFormat()); using var backendRenderTarget = new GRBackendRenderTarget(viewWidth, viewHeight, 0, 8, frameBufferInfo); using var grContext = GRContext.Create(GRBackend.OpenGL); using var skSurface = SKSurface.Create(grContext, backendRenderTarget, GRSurfaceOrigin.BottomLeft, SKImageInfo.PlatformColorType); // get the canvas from the surface using var skCanvas = skSurface.Canvas; var scene = Level.Load(); var frameDuration = TimeSpan.FromSeconds(1.0 / videoMode.RefreshRate); var stopwatch = new Stopwatch(); using var fpsTextPaint = new SKPaint { Style = SKPaintStyle.Fill, Color = SKColors.White, IsAntialias = true, TextSize = 20, }; TimeSpan renderDuration = default; TimeSpan updateDuration = default; var viewScale = viewWidth / Grid.Width * 0.95f; var viewTransform = new SKMatrix( viewScale, 0, viewWidth / 2f, 0, viewScale, viewHeight / 2f, 0, 0, 1); var inputState = new InputState(windowPtr, viewTransform); while (Glfw.WindowShouldClose(windowPtr) == Glfw.False) { stopwatch.Restart(); // Let GLFW process any queued input events, like keyboard, mouse, ... Glfw.PollEvents(); skCanvas.Save(); skCanvas.SetMatrix(viewTransform); // Clear the drawing canvas skCanvas.Clear(SKColors.DimGray); // Draw to scene to the canvas scene.Draw(skCanvas); skCanvas.Restore(); // skCanvas.DrawText($"Render: {renderDuration.TotalMilliseconds:0.0}ms Update: {updateDuration.TotalMilliseconds:0.0}ms", fpsTextPaint.TextSize, fpsTextPaint.TextSize, fpsTextPaint); // Flush all pending Skia drawing commands grContext.Flush(); // Present the canvas on the display Glfw.SwapBuffers(windowPtr); renderDuration = stopwatch.Elapsed; stopwatch.Restart(); // Update the scene, moving it forward in time. scene.Update((float)frameDuration.TotalSeconds, inputState); inputState.Update(); updateDuration = stopwatch.Elapsed; //Glfw.SetWindowTitle(windowPtr, ); if (inputState.IsKeyDown(Key.Enter) && inputState.IsKeyDown(Key.LeftAlt)) { if (Glfw.GetWindowMonitor(windowPtr) == IntPtr.Zero) { // Switch to full screen. Glfw.SetWindowMonitor(windowPtr, primaryMonitorPtr, 0, 0, Grid.Width, Grid.Height, 60); } else { // Switch to windowed mode Glfw.SetWindowMonitor(windowPtr, IntPtr.Zero, workAreaX + (workAreaWidth - Grid.Width) / 2, workAreaY + (workAreaHeight - Grid.Height) / 2, Grid.Width, Grid.Height, 0); } } // Glfw.SetWindowTitle(windowPtr, $"FPS = {1 / frameDuration.TotalSeconds:000.0}"); } }