예제 #1
0
 /// <summary>
 /// 链接顶点属性(Enable Or Disable)
 /// </summary>
 /// <param name="attrs"></param>
 internal void SetVertexAttributeArray(bool[] attrs)
 {
     for (int i = 0; i < attrs.Length; i++)
     {
         if (attrs[i] && !_enabledVertexAttributes.Contains(i))
         {
             _enabledVertexAttributes.Add(i);
             GL.EnableVertexAttribArray(i);
             GraphicsExtensions.CheckGLError();
         }
         else if (!attrs[i] && _enabledVertexAttributes.Contains(i))
         {
             _enabledVertexAttributes.Remove(i);
             GL.DisableVertexAttribArray(i);
             GraphicsExtensions.CheckGLError();
         }
     }
 }
예제 #2
0
        /// <summary>
        /// 设定OpenGL 渲染窗口维度
        /// </summary>
        /// <param name="value"></param>
        private void PlatformSetViewport(ref Viewport value)
        {
            if (IsRenderTargetBound)
            {
                GL.Viewport(value.X, value.Y, value.Width, value.Height);
            }
            else
            {
                GL.Viewport(value.X, PresentationParameters.BackBufferHeight - value.Y - value.Height, value.Width, value.Height);
            }
            GraphicsExtensions.LogGLError("GraphicsDevice.Viewport_set() GL.Viewport");

#if GLES
            GL.DepthRange(value.MinDepth, value.MaxDepth);
#endif
            GraphicsExtensions.LogGLError("GraphicsDevice.Viewport_set() GL.DepthRange");

            _vertexShaderDirty = true;
        }
예제 #3
0
        /// <summary>
        /// 生成顶点缓冲对象
        /// </summary>
        void GenerateIfRequired()
        {
            if (vbo == 0)
            {
                GL.GenBuffers(1, out this.vbo);//
                GraphicsExtensions.CheckGLError();
                //bind to the buffer,Future commands will affect this buffer specifically
                GL.BindBuffer(BufferTarget.ArrayBuffer, this.vbo);
                GraphicsExtensions.CheckGLError();
                //定义的顶点数据复制到缓冲的内存中
                //parameter1:目标缓冲的类型
                //parameter2:传输数据的大小(以字节为单位)
                //parameter3:希望发送的实际数据
                //parameter4:显卡如何管理给定的数据    (StreamDraw:数据每次绘制都会改变 staticDraw:数据不会或几乎不会改变)
                GL.BufferData(BufferTarget.ArrayBuffer, new IntPtr(VertexDeclaration.VertexStride * VertexCount), IntPtr.Zero, _isDynamic ? BufferUsageHint.StreamDraw : BufferUsageHint.StaticDraw);

                GraphicsExtensions.CheckGLError();
            }
        }
예제 #4
0
        /// <summary>
        /// 链接顶点属性
        /// (顶点数据的哪一部分对应着色器的哪一个顶点属性)
        /// </summary>
        /// <param name="shader"></param>
        /// <param name="offset"></param>
        /// <param name="programHash"></param>
        internal void Apply(Shader shader, IntPtr offset, int programHash)
        {
            VertexDeclarationAttributeInfo attrInfo;

            if (!shaderAttributeInfo.TryGetValue(programHash, out attrInfo))
            {
                // Get the vertex attribute info and cache it
                attrInfo = new VertexDeclarationAttributeInfo(GraphicsDevice.MaxVertexAttributes);

                foreach (var ve in InternalVertexElements)
                {
                    var attributeLocation = shader.GetAttribLocation(ve.VertexElementUsage, ve.UsageIndex);
                    if (attributeLocation >= 0)
                    {
                        attrInfo.Elements.Add(new VertexDeclarationAttributeInfo.Element {
                            Offset               = ve.Offset,
                            AttributeLocation    = attributeLocation,
                            NumberOfElements     = ve.VertexElementFormat.OpenGLNumberOfElements(),
                            VertexAttribPointerT = ve.VertexElementFormat.OpenGLVertexAttribPointerT(),
                            Normalized           = ve.OpenGLVertexAttribNormalized(),
                        });
                        attrInfo.EnabledAttributes[attributeLocation] = true;
                    }
                }

                shaderAttributeInfo.Add(programHash, attrInfo);
            }

            //Apply the vertex attribute info
            foreach (var element in attrInfo.Elements)
            {
                GL.VertexAttribPointer(element.AttributeLocation,
                                       element.NumberOfElements,
                                       element.VertexAttribPointerT,
                                       element.Normalized,
                                       this.VertexStride,
                                       (IntPtr)(offset.ToInt64() + element.Offset));
                GraphicsExtensions.CheckGLError();
            }
            GraphicsDevice.SetVertexAttributeArray(attrInfo.EnabledAttributes);
        }
예제 #5
0
        /// <summary>
        /// 链接着色器->着色器程序
        /// </summary>
        /// <param name="pixelShader"></param>
        /// <param name="vertexShader"></param>
        /// <returns></returns>
        private ShaderProgram Link(Shader pixelShader, Shader vertexShader)
        {
            var program = GL.CreateProgram();

            GraphicsExtensions.CheckGLError();

            GL.AttachShader(program, vertexShader.GetShaderHandle());
            GraphicsExtensions.CheckGLError();

            GL.AttachShader(program, pixelShader.GetShaderHandle());
            GraphicsExtensions.CheckGLError();

            GL.LinkProgram(program);
            GraphicsExtensions.CheckGLError();

            GL.UseProgram(program);
            GraphicsExtensions.CheckGLError();

            vertexShader.GetVertexAttributeLocations(program);

            pixelShader.ApplySamplerTextureUnits(program);

            var linked = 0;

            GL.GetProgram(program, GetProgramParameterName.LinkStatus, out linked);

            if (linked == (int)Bool.False)
            {
                GL.DetachShader(program, vertexShader.GetShaderHandle());
                GL.DetachShader(program, pixelShader.GetShaderHandle());

                GL.DeleteProgram(program);

                throw new InvalidOperationException("Unable to link effect program");
            }


            return(new ShaderProgram(program));
        }
예제 #6
0
        /// <summary>
        ///
        /// </summary>
        private unsafe void ActivateShaderProgram()
        {
            var shaderProgram = _programCache.GetProgram(VertexShader, PixelShader);

            if (shaderProgram.Program == -1)
            {
                return;
            }
            if (_shaderProgram != shaderProgram)
            {
                GL.UseProgram(shaderProgram.Program);
                GraphicsExtensions.CheckGLError();
                _shaderProgram = shaderProgram;
            }

            var posFixupLoc = shaderProgram.GetUnitformLocation("posFixup");

            if (posFixupLoc == -1)
            {
                return;
            }

            _posFilxup[0] = 1.0f;
            _posFilxup[1] = 1.0f;
            _posFilxup[2] = (63.0f / 64.0f) / Viewport.Width;
            _posFilxup[3] = -(63.0f / 64.0f) / Viewport.Height;

            if (IsRenderTargetBound)
            {
            }

            fixed(float *floatPtr = _posFilxup)
            {
                GL.Uniform4(posFixupLoc, 1, floatPtr);
            }

            GraphicsExtensions.CheckGLError();
        }
예제 #7
0
        /// <summary>
        ///
        /// </summary>
        private void PlatformSetup()
        {
            MaxTextureSlots = 16;

            GL.GetInteger(GetPName.MaxTextureImageUnits, out MaxTextureSlots);
            GraphicsExtensions.CheckGLError();

            GL.GetInteger(GetPName.MaxVertexAttribs, out MaxVertexAttributes);
            GraphicsExtensions.CheckGLError();

            GL.GetInteger(GetPName.MaxTextureSize, out MaxTextureSize);
            GraphicsExtensions.CheckGLError();

            SpriteBatch.NeedsHalfPixelOffset = true;

            try
            {
                string   version      = GL.GetString(StringName.Version);
                string[] versionSplit = version.Split(' ');
                if (versionSplit.Length > 2 && versionSplit[0].Equals("OpenGL") && versionSplit[1].Equals("ES"))
                {
                    glMajorVersion = Convert.ToInt32(versionSplit[2].Substring(0, 1));
                    glMinorVersion = Convert.ToInt32(versionSplit[2].Substring(2, 1));
                }
                else
                {
                    glMajorVersion = 1;
                    glMinorVersion = 1;
                }
            }
            catch (FormatException)
            {
                glMajorVersion = 1;
                glMinorVersion = 1;
            }

            _extensions = GetGLExtensions();
        }
예제 #8
0
 /// <summary>
 /// 创建一个帧缓冲的纹理
 /// </summary>
 private void GenerateGLTextureIfRequired()
 {
     if (this.glTexture < 0)
     {
         GL.GenTextures(1, out this.glTexture);
         GraphicsExtensions.CheckGLError();
         var wrap = TextureWrapMode.Repeat;
         if ((width & (width - 1)) != 0 || ((height & (height - 1)) != 0))
         {
             wrap = TextureWrapMode.ClampToEdge;
         }
         GL.BindTexture(TextureTarget.Texture2D, this.glTexture);
         GraphicsExtensions.CheckGLError();
         GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (_levelCount > 1) ? (int)TextureMinFilter.LinearMipmapLinear : (int)TextureMinFilter.Linear);
         GraphicsExtensions.CheckGLError();
         GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
         GraphicsExtensions.CheckGLError();
         GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)wrap);
         GraphicsExtensions.CheckGLError();
         GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)wrap);
         GraphicsExtensions.CheckGLError();
     }
 }
예제 #9
0
        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="offsetInBytes"></param>
        /// <param name="data"></param>
        /// <param name="startIndex"></param>
        /// <param name="elementCount"></param>
        /// <param name="options"></param>
        private void BufferData <T>(int offsetInBytes, T[] data, int startIndex, int elementCount, SetDataOptions options) where T : struct
        {
            GenerateIfRequired();

            var elementSizeInByte = Marshal.SizeOf(typeof(T));
            var sizeInBytes       = elementSizeInByte * elementCount;
            var dataHandle        = GCHandle.Alloc(data, GCHandleType.Pinned);
            var dataPtr           = (IntPtr)(dataHandle.AddrOfPinnedObject().ToInt64() + startIndex * elementSizeInByte);
            var bufferSize        = IndexCount * (IndexElementSize == IndexElementSize.SixteenBits ? 2 : 4);

            GL.BindBuffer(BufferTarget.ElementArrayBuffer, ibo);
            GraphicsExtensions.CheckGLError();

            if (options == SetDataOptions.Discard)
            {
                GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)bufferSize, IntPtr.Zero, _isDynamic ? OpenTK.Graphics.ES20.BufferUsage.StreamDraw : OpenTK.Graphics.ES20.BufferUsage.StaticDraw);
                GraphicsExtensions.CheckGLError();
            }
            GL.BufferSubData(BufferTarget.ElementArrayBuffer, (IntPtr)offsetInBytes, (IntPtr)sizeInBytes, dataPtr);
            GraphicsExtensions.CheckGLError();

            dataHandle.Free();
        }
예제 #10
0
        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="level">多级渐远纹理的级别</param>
        /// <param name="arraySize"></param>
        /// <param name="rect"></param>
        /// <param name="data">图像数据</param>
        /// <param name="startIndex"></param>
        /// <param name="elementCount"></param>
        private void PlatformSetData <T>(int level, int arraySize, Rectangle rect, T[] data, int startIndex, int elementCount) where T : struct
        {
            Threading.BlockOnUIThread(() => {
                var elementSizeInByte = Marshal.SizeOf(typeof(T));
                var dataHandle        = GCHandle.Alloc(data, GCHandleType.Pinned);
                try
                {
                    var startBytes = startIndex * elementSizeInByte;
                    var dataPtr    = (IntPtr)(dataHandle.AddrOfPinnedObject().ToInt64() + startBytes);

                    //Store the current bound texture
                    var prevTexture = GraphicsExtensions.GetBoundTexture2D();

                    GenerateGLTextureIfRequired();

                    GL.BindTexture(TextureTarget.Texture2D, this.glTexture);
                    GraphicsExtensions.CheckGLError();

                    if (glFormat == (PixelFormat)GLPixelFormat.CompressedTextureFormats)
                    {
                    }
                    else
                    {
                        GL.TexSubImage2D(TextureTarget.Texture2D, level, rect.X, rect.Y, rect.Width, rect.Height, glFormat, glType, dataPtr);
                        GraphicsExtensions.CheckGLError();
                    }

                    //Restore the bound texture.
                    GL.BindTexture(TextureTarget.Texture2D, prevTexture);
                    GraphicsExtensions.CheckGLError();
                }
                finally
                {
                    dataHandle.Free();
                }
            });
        }
예제 #11
0
 internal virtual void BindFramebuffer(int framebuffer)
 {
     GL.BindFramebuffer(FramebufferTarget.Framebuffer, framebuffer);
     GraphicsExtensions.CheckGLError();
 }
예제 #12
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="device"></param>
        /// <param name="force"></param>
        internal void PlatformApplyState(GraphicsDevice device, bool force = false)
        {
            var offscreen = device.IsRenderTargetBound;

            if (force)
            {
                GL.Disable(EnableCap.Dither);
            }

            if (CullMode == CullMode.None)
            {
                GL.Disable(EnableCap.CullFace);
                GraphicsExtensions.CheckGLError();
            }
            else
            {
                GL.Enable(EnableCap.CullFace);
                GraphicsExtensions.CheckGLError();
                GL.CullFace(CullFaceMode.Back);//   只剔除背面
                GraphicsExtensions.CheckGLError();

                if (CullMode == CullMode.CullClockwiseFace)
                {
                    if (offscreen)
                    {
                        GL.FrontFace(FrontFaceDirection.Cw);    //顺时针方向为正面
                    }
                    else
                    {
                        GL.FrontFace(FrontFaceDirection.Ccw);   //逆时针方向为正面
                    }
                    GraphicsExtensions.CheckGLError();
                }
                else
                {
                    if (offscreen)
                    {
                        GL.FrontFace(FrontFaceDirection.Ccw);
                    }
                    else
                    {
                        GL.FrontFace(FrontFaceDirection.Cw);
                    }
                    GraphicsExtensions.CheckGLError();
                }
            }

            if (FillMode != FillMode.Solid)
            {
                throw new NotImplementedException();
            }



            if (force || this.ScissorTestEnable != device._lastRasterizerState.ScissorTestEnable)
            {
                if (ScissorTestEnable)
                {
                    GL.Enable(EnableCap.ScissorTest);
                }
                else
                {
                    GL.Disable(EnableCap.ScissorTest);
                }

                GraphicsExtensions.CheckGLError();
                device._lastRasterizerState.ScissorTestEnable = this.ScissorTestEnable;
            }

            if (force || this.DepthBias != device._lastRasterizerState.DepthBias || this.SlopeScaleDepthBias != device._lastRasterizerState.SlopeScaleDepthBias)
            {
                if (this.DepthBias != 0 || this.SlopeScaleDepthBias != 0)
                {
                }
                else
                {
                    GL.Disable(EnableCap.PolygonOffsetFill);
                }

                GraphicsExtensions.CheckGLError();
                device._lastRasterizerState.DepthBias           = this.DepthBias;
                device._lastRasterizerState.SlopeScaleDepthBias = this.SlopeScaleDepthBias;
            }

            if (device.GraphicsCapabilities.SupportsDepthClamp && (force || this.DepthClipEnable != device._lastRasterizerState.DepthClipEnable))
            {
                if (!DepthClipEnable)
                {
                    GL.Enable((EnableCap)0x864F);
                }
                else
                {
                    GL.Disable((EnableCap)0x864F);
                }
                GraphicsExtensions.CheckGLError();
                device._lastRasterizerState.DepthClipEnable = this.DepthClipEnable;
            }
        }
예제 #13
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="device"></param>
        /// <param name="force"></param>
        internal void PlatformApplyState(GraphicsDevice device, bool force = false)
        {
            //Enable/Disable Éî¶È»º³å
            if (force || this.DepthBufferEnable != device._lastDepthStencilState.DepthBufferEnable)
            {
                if (!DepthBufferEnable)
                {
                    GL.Disable(EnableCap.DepthTest);
                    GraphicsExtensions.CheckGLError();
                }
                else
                {
                    GL.Enable(EnableCap.DepthTest);
                    GraphicsExtensions.CheckGLError();
                }
                device._lastDepthStencilState.DepthBufferEnable = this.DepthBufferEnable;
            }

            if (force || this.DepthBufferFunction != device._lastDepthStencilState.DepthBufferFunction)
            {
                GL.DepthFunc(this.DepthBufferFunction.GetDepthFunction());
                GraphicsExtensions.CheckGLError();
                device._lastDepthStencilState.DepthBufferFunction = this.DepthBufferFunction;
            }

            if (force || this.DepthBufferWriteEnable != device._lastDepthStencilState.DepthBufferWriteEnable)
            {
                GL.DepthMask(DepthBufferWriteEnable);
                GraphicsExtensions.CheckGLError();
                device._lastDepthStencilState.DepthBufferWriteEnable = this.DepthBufferWriteEnable;
            }

            if (force || this.StencilEnable != device._lastDepthStencilState.StencilEnable)
            {
                if (!StencilEnable)
                {
                    GL.Disable(EnableCap.StencilTest);
                    GraphicsExtensions.CheckGLError();
                }
                else
                {
                    GL.Enable(EnableCap.StencilTest);
                    GraphicsExtensions.CheckGLError();
                }
                device._lastDepthStencilState.StencilEnable = this.StencilEnable;
            }

            if (force || this.StencilWriteMask != device._lastDepthStencilState.StencilWriteMask)
            {
                GL.StencilMask(this.StencilWriteMask);
                GraphicsExtensions.CheckGLError();
                device._lastDepthStencilState.StencilWriteMask = StencilWriteMask;
            }

            if (this.TwoSidedStencilMode)
            {
            }
            else
            {
                if (force || this.TwoSidedStencilMode != device._lastDepthStencilState.TwoSidedStencilMode ||
                    this.StencilFunction != device._lastDepthStencilState.StencilFunction ||
                    this.ReferenceStencil != device._lastDepthStencilState.ReferenceStencil ||
                    this.StencilMask != device._lastDepthStencilState.StencilMask)
                {
                    GL.StencilFunc(GetStencilFunc(this.StencilFunction), ReferenceStencil, this.StencilMask);
                    GraphicsExtensions.CheckGLError();

                    device._lastDepthStencilState.StencilFunction  = StencilFunction;
                    device._lastDepthStencilState.ReferenceStencil = ReferenceStencil;
                    device._lastDepthStencilState.StencilMask      = StencilMask;
                }

                if (force || this.TwoSidedStencilMode != device._lastDepthStencilState.TwoSidedStencilMode ||
                    this.StencilFail != device._lastDepthStencilState.StencilFail ||
                    this.StencilDetphBufferFail != device._lastDepthStencilState.StencilDetphBufferFail ||
                    this.StencilPass != device._lastDepthStencilState.StencilPass)
                {
                    GL.StencilOp(GetStencilOp(this.StencilFail), GetStencilOp(this.StencilDetphBufferFail), GetStencilOp(this.StencilPass));
                    GraphicsExtensions.CheckGLError();

                    device._lastDepthStencilState.StencilFail            = this.StencilFail;
                    device._lastDepthStencilState.StencilDetphBufferFail = this.StencilDetphBufferFail;
                    device._lastDepthStencilState.StencilPass            = this.StencilPass;
                }
            }

            device._lastDepthStencilState.TwoSidedStencilMode = this.TwoSidedStencilMode;
        }
예제 #14
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="applyShaders"></param>
        internal void PlatformApplyState(bool applyShaders)
        {
            if (_scissorRectangleDirty)
            {
                var scissorRect = _scissorRectangle;
                if (!IsRenderTargetBound)
                {
                    scissorRect.Y = _viewport.Height - scissorRect.Y - scissorRect.Height;
                }
                GL.Scissor(scissorRect.X, scissorRect.Y, scissorRect.Width, scissorRect.Height);
                GraphicsExtensions.CheckGLError();
                _scissorRectangleDirty = false;
            }

            if (!applyShaders)
            {
                return;
            }

            if (_indexBufferDirty)
            {
                if (_indexBuffer != null)
                {
                    GL.BindBuffer(BufferTarget.ElementArrayBuffer, _indexBuffer.ibo);
                    GraphicsExtensions.CheckGLError();
                }
                _indexBufferDirty = false;
            }

            if (_vertexBuffersDirty)
            {
                if (_vertexBuffers.Count > 0)
                {
                    GL.BindBuffer(BufferTarget.ArrayBuffer, _vertexBuffers.Get(0).VertexBuffer.vbo);
                    GraphicsExtensions.CheckGLError();
                }
                _vertexBuffersDirty = false;
            }
            if (_vertexShader == null)
            {
                throw new InvalidOperationException("A Vertex Shader Must Be Set!");
            }
            if (_pixelShader == null)
            {
                throw new InvalidOperationException("A Pixel Shader Must Be Set!");
            }
            if (_vertexShaderDirty || _pixelShaderDirty)
            {
                ActivateShaderProgram();
                if (_vertexShaderDirty)
                {
                    unchecked
                    {
                        _graphicsMetrics._vertexShaderCount++;
                    }
                }

                if (_pixelShaderDirty)
                {
                    unchecked
                    {
                        _graphicsMetrics._pixelShaderCount++;
                    }
                }
                _vertexShaderDirty = _pixelShaderDirty = false;
            }

            _vertexConstantBuffers.SetConstantBuffers(this, _shaderProgram);
            _pixelConstantBuffers.SetConstantBuffers(this, _shaderProgram);

            Textures.SetTextures(this);
            SamplerStates.PlatformSetSamplers(this);
        }
예제 #15
0
 internal virtual void GenerateMipmap(int target)
 {
     GL.GenerateMipmap((TextureTarget)target);
     GraphicsExtensions.CheckGLError();
 }
예제 #16
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="attachement"></param>
 /// <param name="renderbuffer"></param>
 /// <param name="level"></param>
 internal virtual void FramebufferRenderbuffer(int attachement, int renderbuffer, int level = 0)
 {
     GL.FramebufferRenderbuffer(FramebufferTarget.Framebuffer, (FramebufferSlot)attachement, RenderbufferTarget.Renderbuffer, renderbuffer);
     GraphicsExtensions.CheckGLError();
 }
예제 #17
0
 internal virtual void DeleteRenderbuffer(int renderbuffer)
 {
     GL.DeleteRenderbuffers(1, ref renderbuffer);
     GraphicsExtensions.CheckGLError();
 }
예제 #18
0
 internal virtual void BindRenderbuffer(int renderbuffer)
 {
     GL.BindRenderbuffer(RenderbufferTarget.Renderbuffer, renderbuffer);
     GraphicsExtensions.CheckGLError();
 }
예제 #19
0
 internal virtual void DeleteFramebuffer(int framebuffer)
 {
     GL.DeleteFramebuffers(1, ref framebuffer);
     GraphicsExtensions.CheckGLError();
 }
예제 #20
0
 internal virtual void BindReadFramebuffer(int readFramebuffer)
 {
     GL.BindFramebuffer((FramebufferTarget)AllReadFramebuffer, readFramebuffer);
     GraphicsExtensions.CheckGLError();
 }
예제 #21
0
 internal virtual void BlitFramebuffer(int iColorAttachment, int width, int height)
 {
     this.GLBlitFramebuffer(0, 0, width, height, 0, 0, width, height, ClearBufferMask.ColorBufferBit, TextureMagFilter.Nearest);
     GraphicsExtensions.CheckGLError();
 }
예제 #22
0
        /// <summary>
        ///
        /// </summary>
        private void PlatformResolveRenderTargets()
        {
            if (_currentRenderTargetCount == 0)
            {
                return;
            }

            var renderTargetBinding = this._currentRenderTargetBindings[0];
            var renderTarget        = renderTargetBinding.RenderTarget as IRenderTarget;

            if (renderTarget.MultiSampleCount > 0 && this.framebufferHelper.SupportsBlitFramebuffer)
            {
                var glResolveFramebuffer = 0;
                if (!this.glResolveFramebuffeers.TryGetValue(this._currentRenderTargetBindings, out glResolveFramebuffer))
                {
                    this.framebufferHelper.GenFramebuffer(out glResolveFramebuffer);
                    this.framebufferHelper.BindFramebuffer(glResolveFramebuffer);

                    for (var i = 0; i < this._currentRenderTargetCount; i++)
                    {
                        this.framebufferHelper.FramebufferTexture2D((int)(FramebufferAttachment.ColorAttachment0 + i), (int)renderTarget.GetFramebufferTarget(renderTargetBinding), renderTarget.GLTexture);
                    }

                    this.glResolveFramebuffeers.Add((RenderTargetBinding[])this._currentRenderTargetBindings.Clone(), glResolveFramebuffer);
                }
                else
                {
                    this.framebufferHelper.BindFramebuffer(glResolveFramebuffer);
                }

                if (this._lastRasterizerState.ScissorTestEnable)
                {
                    GL.Disable(EnableCap.ScissorTest);
                    GraphicsExtensions.CheckGLError();
                }

                var glFramebuffer = this.glFramebuffers[this._currentRenderTargetBindings];
                this.framebufferHelper.BindReadFramebuffer(glFramebuffer);

                for (var i = 0; i < this._currentRenderTargetCount; i++)
                {
                    renderTargetBinding = this._currentRenderTargetBindings[i];
                    renderTarget        = renderTargetBinding.RenderTarget as IRenderTarget;
                    this.framebufferHelper.BlitFramebuffer(i, renderTarget.Width, renderTarget.Height);
                }

                if (renderTarget.RenderTargetUsage == RenderTargetUsage.DiscardContents && this.framebufferHelper.SupportsInvalidateFramebuffer)
                {
                    this.framebufferHelper.InvalidateReadFramebuffer();
                }

                if (this._lastRasterizerState.ScissorTestEnable)
                {
                    GL.Enable(EnableCap.ScissorTest);
                    GraphicsExtensions.CheckGLError();
                }
            }

            for (var i = 0; i < _currentRenderTargetCount; i++)
            {
                renderTargetBinding = _currentRenderTargetBindings[i];
                renderTarget        = renderTargetBinding.RenderTarget as IRenderTarget;

                if (renderTarget.LevelCount > 1)
                {
                    GL.BindTexture(renderTarget.GLTarget, renderTarget.GLTexture);
                    GraphicsExtensions.CheckGLError();
                    this.framebufferHelper.GenerateMipmap((int)renderTarget.GLTarget);
                }
            }
        }