/// <inheritdoc /> public override RenderTarget CreateRenderTarget(Vector2 size, bool smooth = false, TextureInternalFormat internalFormat = TextureInternalFormat.Rgba, TexturePixelFormat pixelFormat = TexturePixelFormat.Rgba, bool attachStencil = false) { RenderTarget resultTarget = null; InternalFormat intFormat = (InternalFormat)Enum.Parse(typeof(InternalFormat), internalFormat.ToString()); PixelFormat glFormat = (PixelFormat)Enum.Parse(typeof(PixelFormat), pixelFormat.ToString()); GLThread.ExecuteGLThread(() => { // Create the FBO which rendering will be done to. uint newFbo = Gl.GenFramebuffer(); Gl.BindFramebuffer(FramebufferTarget.Framebuffer, newFbo); // Create the texture. uint renderTexture = Gl.GenTexture(); Gl.BindTexture(TextureTarget.Texture2d, renderTexture); Gl.TexImage2D(TextureTarget.Texture2d, 0, intFormat, (int)size.X, (int)size.Y, 0, glFormat, PixelType.UnsignedByte, IntPtr.Zero); Gl.TexParameter(TextureTarget.Texture2d, TextureParameterName.TextureMinFilter, smooth ? Gl.LINEAR : Gl.NEAREST); Gl.TexParameter(TextureTarget.Texture2d, TextureParameterName.TextureMagFilter, smooth ? Gl.LINEAR : Gl.NEAREST); // Attach the texture to the frame buffer. Gl.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, TextureTarget.Texture2d, renderTexture, 0); // Attach color components. int[] modes = { Gl.COLOR_ATTACHMENT0 }; Gl.DrawBuffers(modes); // Create render buffer. uint depthBuffer = Gl.GenRenderbuffer(); Gl.BindRenderbuffer(RenderbufferTarget.Renderbuffer, depthBuffer); Gl.RenderbufferStorage(RenderbufferTarget.Renderbuffer, InternalFormat.Depth24Stencil8, (int)size.X, (int)size.Y); Gl.FramebufferRenderbuffer(FramebufferTarget.Framebuffer, attachStencil ? FramebufferAttachment.DepthStencilAttachment : FramebufferAttachment.DepthAttachment, RenderbufferTarget.Renderbuffer, depthBuffer); // Check status. FramebufferStatus status = Gl.CheckFramebufferStatus(FramebufferTarget.Framebuffer); if (status != FramebufferStatus.FramebufferComplete) { Engine.Log.Warning($"Framebuffer creation failed. Error code {status}.", MessageSource.GL); } // Create the texture object. Texture targetTexture = new GLTexture(renderTexture, new Vector2(size.X, size.Y), null, $"FBO {newFbo} Texture"); // Create the render target object. resultTarget = new GlRenderTarget(newFbo, size, targetTexture); // Clear the target. ClearScreen(); CheckError("creating scale fbo"); // Restore bindings and so on. Engine.Renderer?.EnsureRenderTarget(); }); return(resultTarget); }
/// <summary> /// Submit that an error has happened. Handles logging and closing of the engine safely. /// </summary> /// <param name="ex">The exception connected with the error occured.</param> public static void SubmitError(Exception ex) { // Log the error. Engine.Log.Error(ex); // Check if suppressing errors. if (SuppressErrors) { return; } // Dispose of the host because you don't want to be stuck in fullscreen with an error. GLThread.ExecuteGLThread(() => { Engine.Host.Dispose(); }); // If the debugger is attached, break so the error can be inspected. if (Debugger.IsAttached) { Debugger.Break(); } // Display the error box. Engine.Host.DisplayErrorMessage($"Fatal error occured!\n{ex}"); // Check whether to crash - and do so. if (Engine.Flags.CrashOnError) { Engine.Quit(); } }
/// <inheritdoc /> public override void CopyRenderTarget(RenderTarget source, RenderTarget dest, Rectangle?sourceRect = null, Rectangle?destRect = null, bool smooth = false) { GLThread.ExecuteGLThread(() => { RenderTarget srcTarget = source ?? Engine.Renderer.BaseTarget; RenderTarget destTarget = dest ?? Engine.Renderer.BaseTarget; Vector2 sourceSize = srcTarget.Size; Vector2 destSize = destTarget.Size; Rectangle srcRect = sourceRect ?? new Rectangle(0, 0, sourceSize); Rectangle dstRect = destRect ?? new Rectangle(0, 0, destSize); uint srcPointer = (uint)((GlRenderTarget)srcTarget)?.Pointer; uint destPointer = (uint)((GlRenderTarget)destTarget)?.Pointer; Gl.BindFramebuffer(FramebufferTarget.ReadFramebuffer, srcPointer); Gl.BindFramebuffer(FramebufferTarget.DrawFramebuffer, destPointer); Gl.BlitFramebuffer((int)srcRect.X, (int)srcRect.Y, (int)srcRect.Width, (int)srcRect.Height, (int)dstRect.X, (int)dstRect.Y, (int)dstRect.Width, (int)dstRect.Height, ClearBufferMask.ColorBufferBit, smooth ? BlitFramebufferFilter.Linear : BlitFramebufferFilter.Nearest); // Restore bindings and so on. Engine.Renderer.EnsureRenderTarget(); }); }
protected override bool OnFileLoaded(XMLAsset <AnimatedSprite> file) { ResetEditors(); _selectedAnimation = file.Content.Animations.First().Key; var assetFileLoaded = Engine.AssetLoader.Get <TextureAsset>(file.Content.AssetFile, false); _currentAssetTexture = assetFileLoaded?.Texture; _controller = new SpriteAnimationController(file.Content); _controller.SetAnimation(_selectedAnimation); GLThread.ExecuteGLThreadAsync(() => { if (_textureFb == null) { _textureFb = new FrameBuffer(_currentAssetTexture.Size).WithColor(); } else { _textureFb.Resize(_currentAssetTexture.Size); } }); // Patch legacy files foreach (KeyValuePair <string, SpriteAnimationData> anim in file.Content.Animations) { // ReSharper disable once ConditionIsAlwaysTrueOrFalse if (anim.Value.FrameIndices == null) { anim.Value.FrameIndices = Array.Empty <int>(); } } return(true); }
/// <inheritdoc /> public override uint GetBoundVertexArrayBuffer() { int id = 0; GLThread.ExecuteGLThread(() => Gl.Get(Gl.VERTEX_ARRAY_BINDING, out id)); return((uint)id); }
/// <inheritdoc /> public override bool BindIndexBuffer(uint bufferId) { #if DEBUG uint actualBound = GetBoundIndexBuffer(); if (BoundIndexBuffer != 0 && BoundIndexBuffer != actualBound) { Engine.Log.Warning($"Bound index buffer was thought to be {BoundIndexBuffer} but is actually {actualBound}.", MessageSource.GL); } #endif // Check if already bound. if (BoundIndexBuffer != 0 && BoundIndexBuffer == bufferId) { return(false); } GLThread.ExecuteGLThread(() => { Gl.BindBuffer(BufferTarget.ElementArrayBuffer, bufferId); BoundIndexBuffer = bufferId; CheckError("after binding index buffer"); }); return(true); }
/// <inheritdoc /> public override void Setup(Vector2 renderSize) { Gl.BindAPI(s => Glfw.GetProcAddress(s)); Gl.QueryContextVersion(); // Check if context was created. if (Gl.CurrentVersion == null) { ErrorHandler.SubmitError(new Exception("Couldn't connect to OpenGL context.")); return; } // Bind current thread as the GLThread. GLThread.BindThread(); // Renderer bootstrap. Engine.Log.Info("Creating OpenGL GraphicsManager...", MessageSource.GL); Engine.Log.Info($"GL: {Gl.CurrentVersion} on {Gl.CurrentRenderer}", MessageSource.GL); Engine.Log.Info($"GLSL: {Gl.CurrentShadingVersion}", MessageSource.GL); CreateDefaultShader(); CreateDefaultIbo(); // Set default state. DefaultGLState(); ResetState(); // Clear to transparent black. Gl.ClearColor(0, 0, 0, 0); Engine.Log.Info("GraphicsManager ready.", MessageSource.GL); }
private static void TestLoop(Action tick, Action frame) { while (Engine.Status == EngineStatus.Running) { if (!Engine.Host.Update()) { break; } Engine.DeltaTime = 0; GLThread.Run(); bool run = TestLoopUpdate(); if (!run) { continue; } Engine.DeltaTime = 16; tick(); frame(); _loopQueue.TryPeek(out CustomLoop customLoop); if (customLoop != null && customLoop.Ready) { customLoop.Waiter.Set(); _loopQueue.Dequeue(); } } Engine.Quit(); }
/// <inheritdoc /> public override uint GetBoundRenderTarget() { int id = 0; GLThread.ExecuteGLThread(() => Gl.Get(Gl.DRAW_FRAMEBUFFER_BINDING, out id)); return((uint)id); }
/// <inheritdoc /> public override uint GetBoundDataBuffer() { int id = 0; GLThread.ExecuteGLThread(() => Gl.Get(Gl.ARRAY_BUFFER_BINDING, out id)); return((uint)id); }
private static void RunFrame() { PerfProfiler.FrameStart(); // Run the GLThread queued commands. PerfProfiler.FrameEventStart("GLThread.Run"); GLThread.Run(); PerfProfiler.FrameEventEnd("GLThread.Run"); PerfProfiler.FrameEventStart("StartFrame"); Renderer.StartFrame(); PerfProfiler.FrameEventEnd("StartFrame"); PerfProfiler.FrameEventStart("Scene.Draw"); SceneManager.Draw(Renderer); PerfProfiler.FrameEventEnd("Scene.Draw"); PerfProfiler.FrameEventStart("EndFrame"); Renderer.EndFrame(); PerfProfiler.FrameEventEnd("EndFrame"); PerfProfiler.FrameEventStart("BufferSwap"); Host.Window.Context.SwapBuffers(); PerfProfiler.FrameEventEnd("BufferSwap"); #if TIMING_DEBUG _frameId++; Console.Write(_curUpdateC); #endif PerfProfiler.FrameEnd(); }
/// <summary> /// Is run every frame by the host. /// </summary> private static void LoopDraw(float frameTime) { // If not focused, or the renderer tells us not to render the frame - don't draw. if (!Host.Focused || !Renderer.RenderFrame()) { Task.Delay(1).Wait(); return; } // Run the thread manager. GLThread.Run(); // Get frame time and increment total time. FrameTime = frameTime; TotalTime += frameTime; // Clear the screen. Renderer.Clear(); Helpers.CheckError("renderer clear"); // Draw the layers. LayerManager.Draw(); Helpers.CheckError("layer draw"); // Finish rendering. Renderer.End(); Helpers.CheckError("renderer end"); // Draw debug. Debugger.Draw(); // Swap buffers. Host.SwapBuffers(); }
public void Load() { _tileMntTexture = Engine.AssetLoader.Get <TextureAsset>("Image/mnt.png"); _tileGrs1Texture = Engine.AssetLoader.Get <TextureAsset>("Image/grs1.png"); _tileGrs2Texture = Engine.AssetLoader.Get <TextureAsset>("Image/grs2.png"); // _ubuntuFontAsset = Engine.AssetLoader.Get<FontAsset>("font/UbuntuMono-R.ttf").GetAtlas(16f); GenHeightMap(); GetTileMap(); Rectangle boundsOfMap = Rectangle.BoundsFromPolygonPoints(new[] { tiles[0, 0].Vertex0, tiles[MAP_WIDTH - 1, 0].Vertex1, tiles[MAP_WIDTH - 1, MAP_HEIGHT - 1].Vertex2, tiles[0, MAP_HEIGHT - 1].Vertex3, }); quadTree = new QuadTree <TileQuadrilateral>(boundsOfMap, 100); foreach (var tile in tiles) { quadTree.Add(tile); } GLThread.ExecuteGLThread(() => { _frameBuffer = new FrameBuffer(new Texture(Engine.Renderer.DrawBuffer.Size)); }); }
public override void Load() { // These operations need to be performed on the GL thread. // This can be further optimized by creating the objects on another thread and then just passing them. GLThread.ExecuteGLThread(() => { // Create a new map buffer. _buffer = new QuadMapBuffer(Renderer.MaxRenderable); // Map buffer. int x = 0; int y = 0; const int size = 5; for (int i = 0; i < Renderer.MaxRenderable; i++) { // Add objects one after another of a random color. Color randomColor = new Color(Utilities.GenerateRandomNumber(0, 255), Utilities.GenerateRandomNumber(0, 255), Utilities.GenerateRandomNumber(0, 255)); _buffer.MapNextQuad(new Vector3(x * size, y * size, 1), new Vector2(size, size), randomColor); x++; if (x * size < 960) { continue; } x = 0; y++; } }); }
/// <inheritdoc /> public override void DeleteTexture(uint pointer) { GLThread.ExecuteGLThread(() => { Gl.DeleteTextures(pointer); CheckError("after texture deletion"); }); }
public override void DetachedFromController(UIController controller) { if (_textureFb != null) { GLThread.ExecuteGLThreadAsync(_textureFb.Dispose); } base.DetachedFromController(controller); }
/// <inheritdoc /> public override void SetTextureSmooth(bool smooth) { GLThread.ExecuteGLThread(() => { Gl.TexParameter(TextureTarget.Texture2d, TextureParameterName.TextureMinFilter, smooth ? Gl.LINEAR : Gl.NEAREST); Gl.TexParameter(TextureTarget.Texture2d, TextureParameterName.TextureMagFilter, smooth ? Gl.LINEAR : Gl.NEAREST); }); }
private StepMode Interpreter_Step(object sender, DebugInformation e) { // Check if on GL Thread - we don't want to block it. if (GLThread.IsGLThread()) { _currentScriptExec = "Found script, but it was on the GL Thread where it can't be debugged."; return(StepMode.None); } // If this errors it will break the script, that's why it should be in a try-catch. try { // Get the source and write it down. string sourceFull = e.CurrentStatement.Location.Source; if (string.IsNullOrEmpty(sourceFull)) { _currentScriptExec = "Unknown Script Source"; } else { _currentScriptExec = sourceFull; _currentStatement = sourceFull.Substring(e.CurrentStatement.Range[0], e.CurrentStatement.Range[1] - e.CurrentStatement.Range[0]); } _canStepInto = true; if (e.CallStack.Count > 0) { _canStepOut = true; } bool wait = true; StepMode exit = StepMode.None; _stepFunction = mode => { exit = mode; wait = false; }; while (wait) { if (!Open) { return(StepMode.Into); } Engine.ScriptingEngine.Interpreter.ResetTimeoutTicks(); } _canStepInto = false; _canStepOut = false; return(exit); } catch (Exception ex) { Engine.Log.Warning($"Rationale script debugger encountered an error: {ex}", MessageSource.Other); return(StepMode.Into); } }
/// <summary> /// Bind the textures in use. /// </summary> public virtual void BindTextures() { Debug.Assert(GLThread.IsGLThread()); for (uint i = 0; i < TextureSlotUtilization; i++) { Texture.EnsureBound(_textureBinding[i], i); } }
public void ThreadInvocationScheduleNew() { int resp = GLThread.ExecuteGLThread(DoWork, "adsad", "gegwe", "hhrhr"); if (resp != 15) { throw new Exception("whaa"); } }
public override void Dispose() { if (RenderBufferPtr != 0) { GLThread.ExecuteGLThreadAsync(() => Gl.DeleteRenderbuffers(RenderBufferPtr)); } base.Dispose(); }
public SpriteArrayFrameSource(Texture t) { GLThread.ExecuteGLThreadAsync(() => { Frames = AutoDetectFrames(t); FrameOffsets = new Vector2[Frames.Length]; FrameOrigins = new OriginPosition[Frames.Length]; }); }
/// <summary> /// Create a shader program from shader strings. /// </summary> /// <param name="fragmentShader">The program's fragment shader.</param> /// <param name="vertexShader">The program's vertex shader.</param> public ShaderProgram(string vertexShader, string fragmentShader) { GLThread.ExecuteGLThread(() => { Shader vert = string.IsNullOrEmpty(vertexShader) ? DefaultVertShader : new Shader(ShaderType.VertexShader, vertexShader); Shader frag = string.IsNullOrEmpty(fragmentShader) ? DefaultFragShader : new Shader(ShaderType.FragmentShader, fragmentShader); Init(vert, frag); }); }
/// <inheritdoc /> public override void SetClipRect(int x, int y, int width, int height) { GLThread.ExecuteGLThread(() => { Gl.Enable(EnableCap.ScissorTest); Gl.Scissor(x, (int)(Engine.Renderer.CurrentTarget.Size.Y - height - y), width, height); CheckError("setting clip rect"); }); }
/// <inheritdoc /> public override RenderTarget CreateMSAARenderTarget(int samples, Vector2 size, TextureInternalFormat internalFormat = TextureInternalFormat.Rgba, bool attachStencil = false) { RenderTarget resultTarget = null; InternalFormat intFormat = (InternalFormat)Enum.Parse(typeof(InternalFormat), internalFormat.ToString()); GLThread.ExecuteGLThread(() => { // Create the FBO. uint newFbo = Gl.GenFramebuffer(); Gl.BindFramebuffer(FramebufferTarget.Framebuffer, newFbo); // Create the texture. uint renderTexture = Gl.GenTexture(); Gl.BindTexture(TextureTarget.Texture2dMultisample, renderTexture); Gl.TexImage2DMultisample(TextureTarget.Texture2dMultisample, samples, intFormat, (int)size.X, (int)size.Y, true); // Attach the texture to the frame buffer. Gl.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, TextureTarget.Texture2dMultisample, renderTexture, 0); // Attach color components. int[] modes = { Gl.COLOR_ATTACHMENT0 }; Gl.DrawBuffers(modes); // Create render buffer. uint depthBuffer = Gl.GenRenderbuffer(); Gl.BindRenderbuffer(RenderbufferTarget.Renderbuffer, depthBuffer); Gl.RenderbufferStorageMultisample(RenderbufferTarget.Renderbuffer, samples, InternalFormat.Depth24Stencil8, (int)size.X, (int)size.Y); Gl.FramebufferRenderbuffer(FramebufferTarget.Framebuffer, attachStencil ? FramebufferAttachment.DepthStencilAttachment : FramebufferAttachment.DepthAttachment, RenderbufferTarget.Renderbuffer, depthBuffer); // Check status. FramebufferStatus status = Gl.CheckFramebufferStatus(FramebufferTarget.Framebuffer); if (status != FramebufferStatus.FramebufferComplete) { Engine.Log.Warning($"MSAA Framebuffer creation failed. Error code {status}.", MessageSource.GL); } // Construct a texture object for it. Texture targetTexture = new GLTexture(renderTexture, new Vector2(size.X, size.Y), null, $"MSAA{samples} FBO Texture"); // Create the render target object. resultTarget = new GlRenderTarget(newFbo, size, targetTexture); // Clear the target. ClearScreen(); CheckError("creating msaa fbo"); // Restore bindings and so on. Engine.Renderer?.EnsureRenderTarget(); }); return(resultTarget); }
protected override void DisposeInternal() { base.DisposeInternal(); GLThread.ExecuteGLThreadAsync(() => { BaseTexture.Dispose(); foreach (KeyValuePair <Palette, Texture> p in PaletteSwaps) { p.Value.Dispose(); } }); }
/// <inheritdoc /> public override StreamBuffer CreateStreamBuffer(uint vbo, uint vao, uint ibo, uint objectSize, uint size, uint indicesPerObject, bool polygonMode = false) { StreamBuffer streamBuffer = null; GLThread.ExecuteGLThread(() => { // Create a GL stream buffer. streamBuffer = new GlStreamBuffer(vbo, vao, ibo, objectSize, size * objectSize, indicesPerObject, polygonMode ? PrimitiveType.TriangleFan : PrimitiveType.Triangles); }); return(streamBuffer); }
/// <inheritdoc /> public override uint CreateTexture() { uint newTexture = 0; GLThread.ExecuteGLThread(() => { newTexture = Gl.GenTexture(); CheckError("after texture creation"); }); return(newTexture); }
/// <inheritdoc /> public override bool BindTexture(uint pointer, uint slot = 0) { GLThread.ExecuteGLThread(() => { Gl.ActiveTexture(TextureUnit.Texture0 + (int)slot); Gl.BindTexture(TextureTarget.Texture2d, pointer); CheckError("after binding texture"); }); return(true); }
/// <inheritdoc /> public override void SetTextureMask(uint r = 0xff000000, uint g = 0x00ff0000, uint b = 0x0000ff00, uint a = 0x000000ff) { GLThread.ExecuteGLThread(() => { Gl.TexParameter(TextureTarget.Texture2d, TextureParameterName.TextureSwizzleR, MaskMeaning(r)); Gl.TexParameter(TextureTarget.Texture2d, TextureParameterName.TextureSwizzleG, MaskMeaning(g)); Gl.TexParameter(TextureTarget.Texture2d, TextureParameterName.TextureSwizzleB, MaskMeaning(b)); Gl.TexParameter(TextureTarget.Texture2d, TextureParameterName.TextureSwizzleA, MaskMeaning(a)); CheckError("setting texture mask"); }); }
/** * Inform the view that the activity is paused. The owner of this view must * call this method when the activity is paused. Calling this method will * pause the rendering thread. Must not be called before a renderer has been * set. */ public void OnPause() { this.mGLThread.OnPause(); this.mGLThread.RequestExitAndWait(); this.mGLThread = null; }
/** * Inform the view that the activity is resumed. The owner of this view must * call this method when the activity is resumed. Calling this method will * recreate the OpenGL display and resume the rendering thread. Must not be * called before a renderer has been set. */ public void OnResume() { if (this.mEGLConfigChooser == null) { this.mEGLConfigChooser = new SimpleEGLConfigChooser(true); } this.mGLThread = new GLThread(this.mRenderer); this.mGLThread.Start(); this.mGLThread.SetRenderMode(this.mRenderMode); if (this.mHasSurface) { this.mGLThread.SurfaceCreated(); } if (this.mSurfaceWidth > 0 && this.mSurfaceHeight > 0) { this.mGLThread.OnWindowResize(this.mSurfaceWidth, this.mSurfaceHeight); } this.mGLThread.OnResume(); }