/// <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);
        }
Example #2
0
        private void CheckStatus()
        {
            FramebufferStatus status = GL.CheckFramebufferStatus(FramebufferTarget.Framebuffer);

            if (status != FramebufferStatus.Complete)
            {
                throw new CKGLException("Invalid Framebuffer: " + status);
            }
        }
Example #3
0
        private static void RenderOsdFramebuffer(DeviceContext deviceContext)
        {
            IntPtr glContext    = IntPtr.Zero;
            uint   framebuffer  = 0;
            uint   renderbuffer = 0;

            try {
                // Create context and make current on this thread
                if ((glContext = deviceContext.CreateContext(IntPtr.Zero)) == IntPtr.Zero)
                {
                    throw new System.ComponentModel.Win32Exception(System.Runtime.InteropServices.Marshal.GetLastWin32Error());                         // XXX
                }
                deviceContext.MakeCurrent(glContext);

                // Create framebuffer resources
                int w = Math.Min(800, Gl.CurrentLimits.MaxRenderbufferSize);
                int h = Math.Min(600, Gl.CurrentLimits.MaxRenderbufferSize);

                renderbuffer = Gl.GenRenderbuffer();
                Gl.BindRenderbuffer(RenderbufferTarget.Renderbuffer, renderbuffer);
                Gl.RenderbufferStorage(RenderbufferTarget.Renderbuffer, InternalFormat.Rgb8, w, h);

                framebuffer = Gl.GenFramebuffer();
                Gl.BindFramebuffer(FramebufferTarget.ReadFramebuffer, framebuffer);
                Gl.BindFramebuffer(FramebufferTarget.Framebuffer, framebuffer);
                Gl.FramebufferRenderbuffer(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, RenderbufferTarget.Renderbuffer, renderbuffer);

                FramebufferStatus framebufferStatus = Gl.CheckFramebufferStatus(FramebufferTarget.Framebuffer);
                if (framebufferStatus != FramebufferStatus.FramebufferComplete)
                {
                    throw new InvalidOperationException("framebuffer not complete");
                }

                Gl.DrawBuffers(Gl.COLOR_ATTACHMENT0);

                RenderOsd(w, h);

                Gl.ReadBuffer(ReadBufferMode.ColorAttachment0);

                SnapshotOsd(w, h);
            } finally {
                if (renderbuffer != 0)
                {
                    Gl.DeleteRenderbuffers(renderbuffer);
                }
                if (framebuffer != 0)
                {
                    Gl.DeleteFramebuffers(framebuffer);
                }
                if (glContext != IntPtr.Zero)
                {
                    deviceContext.DeleteContext(glContext);
                }
            }
        }
        /// <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);
        }
Example #5
0
        void BindFramebuffer(FramebufferTarget Target)
        {
#if DEBUG
            FramebufferStatus S = Gl.CheckNamedFramebufferStatus(ID, Target);
            if (S != FramebufferStatus.FramebufferComplete)
            {
                throw new InvalidOperationException("Incomplete framebuffer");
            }
#endif

            this.Target = Target;
            Gl.BindFramebuffer(Target, ID);
        }
Example #6
0
        public override unsafe Bitmap Bitmap(RectangleI rectangle)
        {
            switch (Type)
            {
            //case TextureType.Texture1D when Platform.GraphicsBackend == GraphicsBackend.OpenGL: // Not available in OpenGL ES
            //	break;
            //case TextureType.Texture1DArray when Platform.GraphicsBackend == GraphicsBackend.OpenGL: // Not available in OpenGL ES
            //	break;
            case TextureType.Texture2D:
                #region Old OpenGL-only implementation with glTexImage
                //Colour[] data = new Colour[Width * Height];
                //Bind();
                //fixed (Colour* ptr = data)
                //	GL.GetTexImage(TextureTarget, 0, Format.ToOpenGL().PixelFormat(), Format.ToOpenGL().PixelType(), ptr);
                //return new Bitmap(data, Width, Height);
                #endregion

                // OpenGL ES friendly implementation with crop functionality
                Framebuffer originalFramebuffer = Framebuffer.Current;

                GLuint tempFramebuffer = GL.GenFramebuffer();
                GL.BindFramebuffer(FramebufferTarget.Framebuffer, tempFramebuffer);
                //Framebuffer.Swaps++; // TODO

                GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, TextureAttachment.Colour0.ToOpenGL(), TextureTarget, ID, 0);
                FramebufferStatus status = GL.CheckFramebufferStatus(FramebufferTarget.Framebuffer);
                if (status != FramebufferStatus.Complete)
                {
                    throw new CKGLException("Invalid Framebuffer: " + status);
                }

                GL.ReadBuffer(ReadBuffer.Colour0);
                Bitmap bitmap = new Bitmap(GL.ReadPixelsAsColourArray(rectangle, PixelFormat.RGBA), rectangle.W, rectangle.H);

                GL.DeleteFramebuffer(tempFramebuffer);

                originalFramebuffer.Bind();

                return(bitmap);

            //case TextureType.Texture2DArray:
            //	break;
            //case TextureType.Texture2DMultisample:
            //	break;
            //case TextureType.Texture3D:
            //	break;
            default:
                throw new IllegalValueException(typeof(TextureType), Type);
            }
        }
Example #7
0
        /// <summary>
        /// Validate this Framebuffer.
        /// </summary>
        /// <param name="ctx">
        /// A <see cref="GraphicsContext"/> used for validating this Framebuffer.
        /// </param>
        /// <exception cref="InvalidOperationException">
        /// Exception thrown whenever this Framebuffer is not valid.
        /// </exception>
        private static void Validate(GraphicsContext ctx)
        {
            // Check frambuffer completeness
            FramebufferStatus status = Gl.CheckFramebufferStatus(FramebufferTarget.Framebuffer);

            if (status != FramebufferStatus.FramebufferComplete)
            {
                switch (status)
                {
                case FramebufferStatus.FramebufferComplete:
                    return;                                     // No error

                case FramebufferStatus.FramebufferUndefined:
                    throw new InvalidOperationException("framebuffer undefined");

                case FramebufferStatus.FramebufferIncompleteAttachment:
                    throw new InvalidOperationException("framebuffer incomplete attachment");

                case FramebufferStatus.FramebufferIncompleteMissingAttachment:
                    throw new InvalidOperationException("framebuffer incomplete missing attachment");

#if !MONODROID
                case FramebufferStatus.FramebufferIncompleteReadBuffer:
                    throw new InvalidOperationException("framebuffer incomplete read buffer");
#endif
                case FramebufferStatus.FramebufferUnsupported:
                    throw new InvalidOperationException("framebuffer unsupported");

                case FramebufferStatus.FramebufferIncompleteMultisample:
                    throw new InvalidOperationException("framebuffer incomplete multisample");

                case FramebufferStatus.FramebufferIncompleteLayerTargets:
                    throw new InvalidOperationException("framebuffer incomplete layer targets");

                default:
                    throw new InvalidOperationException(String.Format("unknown error code 0x{0}", status.ToString("X8")));
                }
            }
        }
Example #8
0
        /// <summary>
        /// Creates a framebuffer object and its associated resources (depth and frame buffers).
        /// </summary>
        /// <param name="size">Specifies the size (in pixels) of the framebuffer and its associated buffers.</param>
        /// <param name="attachments">Specifies the attachments to use for the frame buffer.</param>
        /// <param name="format">Specifies the internal pixel format for the frame buffer.</param>
        /// <param name="mipmaps">Specifies whether to build mipmaps after the frame buffer is unbound.</param>
        /// <param name="filterType">Specifies the type of filtering to apply to the frame buffer when bound as a texture.</param>
        /// <param name="pixelType">Specifies the pixel type to use for the underlying format of the frame buffer.</param>
        public FBO(Sizei size, FramebufferAttachment[] attachments, PixelInternalFormat format, bool mipmaps = false, TextureParameter filterType = TextureParameter.Linear, PixelType pixelType = PixelType.UnsignedByte, bool renderbuffer = true, bool multisampled = false)
        {
            Size         = size;
            Attachments  = attachments;
            Format       = format;
            MipMaps      = mipmaps;
            Multisampled = multisampled;

            // First create the framebuffer
            BufferID = GL.GenFramebuffer();
            GL.BindFramebuffer(FramebufferTarget.Framebuffer, BufferID);

            _attachementMap = new Dictionary <FramebufferAttachment, uint>();
            TextureTarget textureTarget = Multisampled ? TextureTarget.Texture2DMultisample : TextureTarget.Texture2D;

            if (Attachments.Length == 1 && Attachments[0] == FramebufferAttachment.DepthAttachment)
            {
                // if this is a depth attachment only
                TextureID = new uint[] { GL.GenTexture() };
                GL.BindTexture(textureTarget, TextureID[0]);

                if (Multisampled)
                {
                    GL.TexImage2DMultisample(textureTarget, GameSettings.MultisampleLevel, Format, Size.Width, Size.Height, true);
                }
                else
                {
                    GL.TexImage2D(textureTarget, 0, Format, Size.Width, Size.Height, 0, PixelFormat.DepthComponent, PixelType.Float, IntPtr.Zero);
                    GL.TexParameteri(textureTarget, TextureParameterName.TextureMagFilter, TextureParameter.Nearest);
                    GL.TexParameteri(textureTarget, TextureParameterName.TextureMinFilter, TextureParameter.Nearest);
                    GL.TexParameteri(textureTarget, TextureParameterName.TextureWrapS, TextureParameter.ClampToEdge);
                    GL.TexParameteri(textureTarget, TextureParameterName.TextureWrapT, TextureParameter.ClampToEdge);
                }

                GL.BindTexture(textureTarget, 0);
                GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.DepthAttachment, textureTarget, TextureID[0], 0);
                GL.DrawBuffer(DrawBufferMode.None);
                GL.ReadBuffer(ReadBufferMode.None);

                _attachementMap.Add(FramebufferAttachment.DepthAttachment, 0);
            }
            else
            {
                // Create n texture buffers (known by the number of attachments)
                TextureID = new uint[Attachments.Length];
                GL.GenTextures(Attachments.Length, TextureID);

                // Bind the n texture buffers to the framebuffer
                for (int i = 0; i < Attachments.Length; i++)
                {
                    GL.BindTexture(textureTarget, TextureID[i]);

                    if (Multisampled)
                    {
                        GL.TexImage2DMultisample(textureTarget, GameSettings.MultisampleLevel, Format, Size.Width, Size.Height, true);
                    }
                    else
                    {
                        GL.TexImage2D(textureTarget, 0, Format, Size.Width, Size.Height, 0, PixelFormat.Rgba, pixelType, IntPtr.Zero);

                        if (MipMaps)
                        {
                            GL.TexParameteri(textureTarget, TextureParameterName.TextureMagFilter, TextureParameter.Linear);
                            GL.TexParameteri(textureTarget, TextureParameterName.TextureMinFilter, TextureParameter.LinearMipMapLinear);
                            GL.GenerateMipmap(Multisampled ? GenerateMipmapTarget.Texture2DMultisample : GenerateMipmapTarget.Texture2D);
                        }
                        else
                        {
                            GL.TexParameteri(textureTarget, TextureParameterName.TextureMagFilter, filterType);
                            GL.TexParameteri(textureTarget, TextureParameterName.TextureMinFilter, filterType);
                        }
                    }

                    GL.BindTexture(textureTarget, 0);
                    GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, Attachments[i], textureTarget, TextureID[i], 0);

                    _attachementMap.Add(Attachments[i], TextureID[i]);
                }

                if (renderbuffer)
                {
                    // Create and attach a 24-bit depth buffer to the framebuffer
                    DepthID = GL.GenRenderbuffer();
                    GL.BindRenderbuffer(RenderbufferTarget.Renderbuffer, DepthID);

                    if (Multisampled)
                    {
                        GL.RenderbufferStorageMultisample(RenderbufferTarget.Renderbuffer, GameSettings.MultisampleLevel, PixelInternalFormat.Depth32fStencil8, Size.Width, Size.Height);
                    }
                    else
                    {
                        GL.RenderbufferStorage(RenderbufferTarget.Renderbuffer, PixelInternalFormat.Depth24Stencil8, Size.Width, Size.Height);
                    }

                    GL.BindRenderbuffer(RenderbufferTarget.Renderbuffer, 0);
                    GL.FramebufferRenderbuffer(FramebufferTarget.Framebuffer, FramebufferAttachment.DepthStencilAttachment, RenderbufferTarget.Renderbuffer, DepthID);

                    //GL.TexParameteri(textureTarget, TextureParameterName.TextureMagFilter, TextureParameter.Nearest);
                    //GL.TexParameteri(textureTarget, TextureParameterName.TextureMinFilter, TextureParameter.Nearest);
                    //GL.TexParameteri(textureTarget, TextureParameterName.TextureWrapS, TextureParameter.ClampToEdge);
                    //GL.TexParameteri(textureTarget, TextureParameterName.TextureWrapT, TextureParameter.ClampToEdge);

                    //GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.DepthAttachment, textureTarget, DepthID, 0);
                    //GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.StencilAttachment, textureTarget, DepthID, 0);

                    _attachementMap.Add(FramebufferAttachment.DepthStencilAttachment, DepthID);
                    //_attachementMap.Add(FramebufferAttachment.StencilAttachment, DepthID);
                }
            }

            // Build the framebuffer and check for errors
            FramebufferStatus status = GL.CheckFramebufferStatus(FramebufferTarget.Framebuffer);

            if (status != FramebufferStatus.FramebufferComplete)
            {
                Console.WriteLine("Frame buffer did not compile correctly.  Returned {0}, glError: {1}", status.ToString(), GL.GetError().ToString());
            }

            // Make sure this framebuffer is not modified from outside
            GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0);

            // Register this framebuffer as a disposable object
            ResourcesManager.AddDisposableResource(this);
        }
        /// <summary>
        /// Updates the <see cref="FramebufferObject"/>'s parameters and checks that the framebuffer is valid.
        /// This should always be called after being done attaching or detaching resources.
        /// </summary>
        public void UpdateFramebufferData()
        {
            uint width   = uint.MaxValue;
            uint height  = uint.MaxValue;
            uint samples = uint.MaxValue;

            for (int i = 0; i < textureAttachments.Count; i++)
            {
                Texture tex = textureAttachments[i].Texture;
                if (tex is Texture1D tex1d)
                {
                    ValidateSize(tex1d.Width, 1);
                }
                else if (tex is Texture2D tex2d)
                {
                    ValidateSize(tex2d.Width, tex2d.Height);
                }
                else
                {
                    throw new FramebufferException("The texture format cannot be attached: " + tex.TextureType);
                }

                ValidateSamples(tex is TextureMultisamplable ms ? ms.Samples : 0);
            }

            for (int i = 0; i < renderbufferAttachments.Count; i++)
            {
                RenderbufferObject rend = renderbufferAttachments[i].Renderbuffer;
                ValidateSize(rend.Width, rend.Height);
                ValidateSamples(rend.Samples);
            }

            Width   = width;
            Height  = height;
            Samples = samples;

            void ValidateSize(uint w, uint h)
            {
                if (width == uint.MaxValue)
                {
                    width = w;
                }
                else if (width != w)
                {
                    throw new FramebufferException("All the attachments must be the same size");
                }

                if (height == uint.MaxValue)
                {
                    height = h;
                }
                else if (height != h)
                {
                    throw new FramebufferException("All the attachments must be the same size");
                }
            }

            void ValidateSamples(uint s)
            {
                if (samples == uint.MaxValue)
                {
                    samples = s;
                }
                else if (samples != s)
                {
                    throw new FramebufferException("All the attachments must have the same amount of samples");
                }
            }

            FramebufferStatus c = GetStatus();

            if (c != FramebufferStatus.FramebufferComplete)
            {
                throw new FramebufferException("The " + nameof(FramebufferObject) + " is not complete: " + c);
            }
        }
Example #10
0
        /// <summary>
        /// initializes the Fbo with <b>with</b> and <b>height</b>. You have to call that, when <see cref="FboHandle"/> less than 0 or when the size of the fbo has changed.
        /// </summary>
        /// <param name="Width">is the width.</param>
        /// <param name="Height">is the height.</param>
        public virtual void Init(int Width, int Height)
        {
            if (FboHandle > 0)
            {
                Dispose();
            }
            width         = Width; height = Height;
            ActiveTexture = GL.GetInteger(GetPName.TextureBinding2D);
            if (FboHandle < 0)
            {
                _GenFramebuffers(1, out _Fbo[0]);
            }
            if (FboHandle < 0)
            {
                throw new System.Exception("Can not create a frame buffer");
            }
            _BindFramebuffer(FramebufferTarget.Framebuffer, FboHandle);
            if (Depthbuffer < 0)
            {
                _GenRenderbuffers(1, out _Depth[0]);
            }


            _BindRenderbuffer(RenderbufferTarget.Renderbuffer, Depthbuffer);
            GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.DepthComponent, width, height, 0, PixelFormat.DepthComponent, PixelType.UnsignedInt, IntPtr.Zero);
            if (GL.GetError() != OpenTK.Graphics.OpenGL.ErrorCode.NoError)
            {
                Dispose();
                throw new Exception("OutOf Memory");
            }
            //     GL.RenderbufferStorage(RenderbufferTarget.Renderbuffer, RenderbufferStorage.DepthComponent16, Width, Height);
            _RenderbufferStorage(RenderbufferTarget.Renderbuffer, RenderbufferStorage.DepthComponent16, Width, Height);
            _BindFramebuffer(FramebufferTarget.DrawFramebuffer, FboHandle);
            if (FboTexture < 0)
            {
                GL.GenTextures(1, _Texture);
            }

            GL.BindTexture(TextureTarget.Texture2D, FboTexture);
            GL.TexParameterI(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, ref GL_NEAREST);
            GL.TexParameterI(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, ref GL_NEAREST);
            {
                GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, Width, Height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, IntPtr.Zero);
                _FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, TextureTarget.Texture2D, FboTexture, 0);
                _FramebufferRenderbuffer(FramebufferTarget.Framebuffer, FramebufferAttachment.DepthAttachment, RenderbufferTarget.Renderbuffer, Depthbuffer);
            }
            int status           = (int)GL.CheckFramebufferStatus(FramebufferTarget.Framebuffer);
            FramebufferStatus FS = (FramebufferStatus)(status - 0x8CD5);

            if (FS != FramebufferStatus.FRAMEBUFFER_COMPLETE)
            {
                int[] FB = new int[] { 1 };
                Dispose();
                throw new System.Exception(FS.ToString());
            }
            _BindFramebuffer(FramebufferTarget.Framebuffer, 0);
            _BindFramebuffer(FramebufferTarget.DrawFramebuffer, 0);
            _BindRenderbuffer(RenderbufferTarget.Renderbuffer, 0);
            GL.BindTexture(TextureTarget.Texture2D, ActiveTexture);

            ;
        }
Example #11
0
        internal Screen(Application.Client client)
        {
            Instance = this;

            Client = client;

            client.Resize += OnResize;

            #region MULTISAMPLED FBO

            int maxSamples = GL.GetInteger(GetPName.MaxSamples);
            samples = Math.Clamp(Client.Graphics.SampleCount, min: 1, maxSamples);

            logger.LogDebug(
                Events.VisualQuality,
                "Set sample count to {Samples}, of maximum {Max} possible samples",
                samples,
                maxSamples);

            GL.Enable(EnableCap.DepthTest);
            GL.Enable(EnableCap.CullFace);
            GL.Enable(EnableCap.Multisample);

            msTex = GL.GenTexture();
            GL.BindTexture(TextureTarget.Texture2DMultisample, msTex);

            GL.TexImage2DMultisample(
                TextureTargetMultisample.Texture2DMultisample,
                samples,
                PixelInternalFormat.Rgba8,
                Size.X,
                Size.Y,
                fixedsamplelocations: true);

            GL.BindTexture(TextureTarget.Texture2DMultisample, texture: 0);

            GL.CreateFramebuffers(n: 1, out msFBO);
            GL.NamedFramebufferTexture(msFBO, FramebufferAttachment.ColorAttachment0, msTex, level: 0);

            FramebufferStatus multisampledFboStatus =
                GL.CheckNamedFramebufferStatus(msFBO, FramebufferTarget.Framebuffer);

            while (multisampledFboStatus != FramebufferStatus.FramebufferComplete)
            {
                logger.LogWarning(
                    Events.VisualsSetup,
                    "Multi-sampled FBO not complete [{Status}], waiting...",
                    multisampledFboStatus);

                Thread.Sleep(millisecondsTimeout: 100);

                multisampledFboStatus = GL.CheckNamedFramebufferStatus(msFBO, FramebufferTarget.Framebuffer);
            }

            GL.CreateRenderbuffers(n: 1, out msRBO);
            GL.NamedRenderbufferStorageMultisample(msRBO, samples, RenderbufferStorage.Depth24Stencil8, Size.X, Size.Y);

            GL.NamedFramebufferRenderbuffer(
                msFBO,
                FramebufferAttachment.DepthStencilAttachment,
                RenderbufferTarget.Renderbuffer,
                msRBO);

            GL.BindFramebuffer(FramebufferTarget.Framebuffer, msFBO);
            GL.DrawBuffer(DrawBufferMode.ColorAttachment0);

            #endregion MULTISAMPLED FBO

            #region DEPTH TEXTURE

            depthTex = GL.GenTexture();
            GL.ActiveTexture(TextureUnit.Texture20);
            GL.BindTexture(TextureTarget.Texture2D, depthTex);

            GL.TexImage2D(
                TextureTarget.Texture2D,
                level: 0,
                PixelInternalFormat.DepthComponent,
                Size.X,
                Size.Y,
                border: 0,
                PixelFormat.DepthComponent,
                PixelType.Float,
                IntPtr.Zero);

            GL.TexParameter(
                TextureTarget.Texture2D,
                TextureParameterName.TextureMinFilter,
                (int)TextureMinFilter.Nearest);

            GL.TexParameter(
                TextureTarget.Texture2D,
                TextureParameterName.TextureMagFilter,
                (int)TextureMagFilter.Nearest);

            GL.CreateFramebuffers(n: 1, out depthFBO);
            GL.NamedFramebufferTexture(depthFBO, FramebufferAttachment.DepthAttachment, depthTex, level: 0);

            FramebufferStatus depthFboStatus = GL.CheckNamedFramebufferStatus(depthFBO, FramebufferTarget.Framebuffer);

            while (depthFboStatus != FramebufferStatus.FramebufferComplete)
            {
                logger.LogWarning(Events.VisualsSetup, "Depth FBO not complete [{Status}], waiting...", depthFboStatus);
                Thread.Sleep(millisecondsTimeout: 100);

                depthFboStatus = GL.CheckNamedFramebufferStatus(depthFBO, FramebufferTarget.Framebuffer);
            }

            GL.ActiveTexture(TextureUnit.Texture0);

            #endregion DEPTH TEXTURE

            #region SCREENSHOT FBO

            GL.CreateFramebuffers(n: 1, out screenshotFBO);

            GL.CreateRenderbuffers(n: 1, out screenshotRBO);
            GL.NamedRenderbufferStorage(screenshotRBO, RenderbufferStorage.Rgba8, Size.X, Size.Y);

            GL.NamedFramebufferRenderbuffer(
                screenshotFBO,
                FramebufferAttachment.ColorAttachment0,
                RenderbufferTarget.Renderbuffer,
                screenshotRBO);

            FramebufferStatus screenshotFboStatus =
                GL.CheckNamedFramebufferStatus(screenshotFBO, FramebufferTarget.Framebuffer);

            while (screenshotFboStatus != FramebufferStatus.FramebufferComplete)
            {
                logger.LogWarning(
                    Events.VisualsSetup,
                    "Screenshot FBO not complete [{Status}], waiting...",
                    screenshotFboStatus);

                Thread.Sleep(millisecondsTimeout: 100);

                screenshotFboStatus = GL.CheckNamedFramebufferStatus(screenshotFBO, FramebufferTarget.Framebuffer);
            }

            #endregion SCREENSHOT FBO
        }
Example #12
0
        /// <summary>
        /// Start your app.
        /// </summary>
        /// <param name="width">Stage width</param>
        /// <param name="height">Stage height</param>
        /// <param name="viewportHeight"></param>
        /// <param name="viewportWidth"></param>
        /// <param name="rootType">The root class of your app</param>
        /// <exception cref="InvalidOperationException">When rootType is null or this function is called twice</exception>
        /// <exception cref="NotSupportedException">When the OpenGL framebuffer creation fails.</exception>
        /// <exception cref="ArgumentException">When width or height are less than 32.</exception>
        public static void Start(uint width, uint height, uint viewportWidth, uint viewportHeight, Type rootType)
        {
            Debug.WriteLine("Sparrow starting");
            if (width < 32 || height < 32 || viewportWidth < 32 || viewportHeight < 32)
            {
                throw new ArgumentException($"Invalid dimensions: {width}x{height}");
            }

            var ver = Gl.CurrentVersion;

            if (ver.Api == "gl")
            {
                if (ver.Major < 4)
                {
                    throw new NotSupportedException("You need at least OpenGL 4.0 to run Sparrow!");
                }
            }
            else
            {
                if (ver.Major < 3)
                {
                    throw new NotSupportedException("You need at least OpenGL ES 3.0 to run Sparrow!");
                }
                IsRunningOpenGLES = true;
            }

            Gl.Disable(EnableCap.CullFace);
            Gl.Disable(EnableCap.Dither);

            Gl.Enable(EnableCap.DepthTest);
            Gl.DepthFunc(DepthFunction.Always);

            BlendMode.Get(BlendMode.NORMAL).Activate();

            FramebufferStatus status = Gl.CheckFramebufferStatus(FramebufferTarget.Framebuffer);

            if (status != FramebufferStatus.FramebufferComplete)
            {
                throw new NotSupportedException("GL Framebuffer creation error. Status: " + status);
            }
            _viewPort         = Rectangle.Create(0, 0, viewportWidth, viewportHeight);
            _previousViewPort = Rectangle.Create();
            GPUInfo.PrintGPUInfo();

            // Desktop GL core profile needs a VAO for vertex attrib pointers to work.
            uint vao = Gl.GenVertexArray();

            Gl.BindVertexArray(vao);

            if (rootType == null)
            {
                throw new InvalidOperationException("Root cannot be null!");
            }

            if (Root != null)
            {
                throw new InvalidOperationException("App already initialized!");
            }

            _painter       = new Painter(width, height);
            Stage          = new Stage(width, height);
            DefaultJuggler = new Juggler();

            UpdateViewPort(true);

            Root = (DisplayObject)Activator.CreateInstance(rootType);
            Stage.AddChild(Root);
            _frameId = 1; // starts with 1, so things on the first frame are cached
        }