/// <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); }
/// <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); }
/// <inheritdoc /> public override void UploadToTexture(IntPtr data, Vector2 size, TextureInternalFormat internalFormat, TexturePixelFormat pixelFormat) { InternalFormat intFormat = (InternalFormat)Enum.Parse(typeof(InternalFormat), internalFormat.ToString()); PixelFormat glFormat = (PixelFormat)Enum.Parse(typeof(PixelFormat), pixelFormat.ToString()); GLThread.ExecuteGLThread(() => { // Set scaling to pixel perfect. Gl.TexParameter(TextureTarget.Texture2d, TextureParameterName.TextureMinFilter, Gl.NEAREST); Gl.TexParameter(TextureTarget.Texture2d, TextureParameterName.TextureMagFilter, Gl.NEAREST); Gl.TexImage2D(TextureTarget.Texture2d, 0, intFormat, (int)size.X, (int)size.Y, 0, glFormat, PixelType.UnsignedByte, data); Gl.GenerateMipmap(TextureTarget.Texture2d); CheckError("after uploading texture"); }); }