Exemple #1
0
        /// <summary>
        /// Frees up any OpenGL resources that this RenderTarget might have occupied.
        /// </summary>
        public void FreeOpenGLRes()
        {
            DualityApp.GuardSingleThreadState();

            if (this.glFboId != 0)
            {
                GL.Ext.DeleteFramebuffers(1, ref this.glFboId);
                this.glFboId = 0;
            }
            if (this.glRboIdDepth != 0)
            {
                GL.Ext.DeleteRenderbuffers(1, ref this.glRboIdDepth);
                this.glRboIdDepth = 0;
            }
            if (this.glFboIdMSAA != 0)
            {
                GL.Ext.DeleteFramebuffers(1, ref this.glFboIdMSAA);
                this.glFboIdMSAA = 0;
            }
            for (int i = 0; i < this.targetInfo.Count; i++)
            {
                TargetInfo infoTemp = this.targetInfo[i];
                if (this.targetInfo[i].glRboIdColorMSAA != 0)
                {
                    GL.Ext.DeleteRenderbuffers(1, ref infoTemp.glRboIdColorMSAA);
                    infoTemp.glRboIdColorMSAA = 0;
                }
                this.targetInfo[i] = infoTemp;
            }
        }
Exemple #2
0
        /// <summary>
        /// Compiles the ShaderProgram. This is done automatically when loading the ShaderProgram
        /// or when binding it.
        /// </summary>
        public void Compile()
        {
            DualityApp.GuardSingleThreadState();

            if (this.glProgramId == 0)
            {
                return;
            }
            if (this.compiled)
            {
                return;
            }

            GL.LinkProgram(this.glProgramId);

            int result;

            GL.GetProgram(this.glProgramId, GetProgramParameterName.LinkStatus, out result);
            if (result == 0)
            {
                string infoLog = GL.GetProgramInfoLog(this.glProgramId);
                Log.Core.WriteError("Error linking shader program. InfoLog:{1}{0}", infoLog, Environment.NewLine);
                return;
            }
            this.compiled = true;

            // Collect variable infos from sub programs
            ShaderVarInfo[] fragVarArray = this.frag.IsAvailable ? this.frag.Res.VarInfo : null;
            ShaderVarInfo[] vertVarArray = this.vert.IsAvailable ? this.vert.Res.VarInfo : null;
            if (fragVarArray != null && vertVarArray != null)
            {
                this.varInfo = vertVarArray.Union(fragVarArray).ToArray();
            }
            else if (vertVarArray != null)
            {
                this.varInfo = vertVarArray.ToArray();
            }
            else
            {
                this.varInfo = fragVarArray.ToArray();
            }
            // Determine actual variable locations
            for (int i = 0; i < this.varInfo.Length; i++)
            {
                if (this.varInfo[i].scope == ShaderVarScope.Uniform)
                {
                    this.varInfo[i].glVarLoc = GL.GetUniformLocation(this.glProgramId, this.varInfo[i].name);
                }
                else
                {
                    this.varInfo[i].glVarLoc = GL.GetAttribLocation(this.glProgramId, this.varInfo[i].name);
                }
            }
        }
Exemple #3
0
 protected override void OnDisposing(bool manually)
 {
     base.OnDisposing(manually);
     if (DualityApp.ExecContext != DualityApp.ExecutionContext.Terminated &&
         this.glTexId != 0)
     {
         DualityApp.GuardSingleThreadState();
         GL.DeleteTexture(this.glTexId);
         this.glTexId = 0;
     }
 }
        /// <summary>
        /// Sets up the Textures OpenGL resources, clearing previously uploaded pixel data.
        /// </summary>
        protected void SetupOpenGLRes()
        {
            DualityApp.GuardSingleThreadState();
            if (!initialized)
            {
                Init();
            }
            if (this.glTexId == 0)
            {
                this.glTexId = GL.GenTexture();
            }

            int lastTexId;

            GL.GetInteger(GetPName.TextureBinding2D, out lastTexId);
            if (lastTexId != this.glTexId)
            {
                GL.BindTexture(TextureTarget.Texture2D, this.glTexId);
            }

            // Set texture parameters
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)this.filterMin);
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)this.filterMag);
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)this.wrapX);
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)this.wrapY);

            // Anisotropic filtering
            GL.TexParameter(TextureTarget.Texture2D, (TextureParameterName)ExtTextureFilterAnisotropic.TextureMaxAnisotropyExt, this.anisoFilter ? maxAnisoLevel : 1.0f);

            // If needed, care for Mipmaps
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.GenerateMipmap, this.HasMipmaps ? 1 : 0);

            // Setup pixel format
            if (this.compressed)
            {
                this.pixelformat = PixelInternalFormat.CompressedRgbaS3tcDxt5Ext;
            }

            if (this.pixelType == 0)
            {
                this.pixelType = PixelType.UnsignedByte;
            }

            GL.TexImage2D(TextureTarget.Texture2D, 0,
                          this.pixelformat, this.texWidth, this.texHeight, 0,
                          GLPixelFormat.Bgra, this.pixelType, IntPtr.Zero);

            if (lastTexId != this.glTexId)
            {
                GL.BindTexture(TextureTarget.Texture2D, lastTexId);
            }
        }
        public void LoadData(IntPtr data, int width, int height)
        {
            DualityApp.GuardSingleThreadState();
            if (this.glTexId == 0)
            {
                this.glTexId = GL.GenTexture();
            }

            int lastTexId;

            GL.GetInteger(GetPName.TextureBinding2D, out lastTexId);
            GL.BindTexture(TextureTarget.Texture2D, this.glTexId);

            if (data == IntPtr.Zero)
            {
                return;
            }
            AdjustSize(width, height);
            this.SetupOpenGLRes();
            // Load pixel data to video memory
            if (Compressed)
            {
                var imageSize = ((this.PixelWidth + 3) / 4) * ((this.PixelHeight + 3) / 4) * 16;
                GL.CompressedTexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.CompressedRgbaS3tcDxt5Ext, this.PixelWidth,
                                        this.PixelHeight, 0, imageSize, data);
            }
            else
            {
                GL.TexImage2D(TextureTarget.Texture2D, 0,
                              this.pixelformat, this.PixelWidth, this.PixelHeight, 0,
                              GLPixelFormat.Rgba, PixelType.UnsignedByte,
                              data);
            }

            // Adjust atlas to represent UV coordinates
            if (this.atlas != null)
            {
                Vector2 scale;
                scale.X = this.uvRatio.X / this.pxWidth;
                scale.Y = this.uvRatio.Y / this.pxHeight;
                for (int i = 0; i < this.atlas.Length; i++)
                {
                    this.atlas[i].X *= scale.X;
                    this.atlas[i].W *= scale.X;
                    this.atlas[i].Y *= scale.Y;
                    this.atlas[i].H *= scale.Y;
                }
            }

            GL.BindTexture(TextureTarget.Texture2D, lastTexId);
        }
Exemple #6
0
 private void Dispose(bool manually)
 {
     if (!this.disposed)
     {
         if (DualityApp.ExecContext != DualityApp.ExecutionContext.Terminated &&
             this.hndlPrimaryVBO != 0)
         {
             DualityApp.GuardSingleThreadState();
             GL.DeleteBuffers(1, ref this.hndlPrimaryVBO);
             this.hndlPrimaryVBO = 0;
         }
         this.disposed = true;
     }
 }
Exemple #7
0
        protected override void OnDisposing(bool manually)
        {
            base.OnDisposing(manually);

            // Dispose unmanages Resources
            if (DualityApp.ExecContext != DualityApp.ExecutionContext.Terminated &&
                this.glTexId != 0)
            {
                DualityApp.GuardSingleThreadState();
                GL.DeleteTexture(this.glTexId);
                this.glTexId = 0;
            }

            // Get rid of big data references, so the GC can collect them.
            this.basePixmap.Detach();
        }
Exemple #8
0
        /// <summary>
        /// Attaches the specified <see cref="VertexShader">Vertex-</see> and <see cref="FragmentShader"/> to this ShaderProgram.
        /// </summary>
        /// <param name="v"></param>
        /// <param name="f"></param>
        public void AttachShaders(ContentRef <VertexShader> v, ContentRef <FragmentShader> f, ContentRef <GeometryShader> g = new ContentRef <GeometryShader>())
        {
            DualityApp.GuardSingleThreadState();

            if (this.glProgramId == 0)
            {
                this.glProgramId = GL.CreateProgram();
            }
            else
            {
                this.DetachShaders();
            }

            this.compiled = false;
            this.vert     = v;
            this.frag     = f;
            this.geom     = g;

            // Assure all shaders are compiled
            if (this.vert.IsAvailable)
            {
                this.vert.Res.Compile();
            }
            if (this.frag.IsAvailable)
            {
                this.frag.Res.Compile();
            }
            if (this.geom.IsAvailable)
            {
                this.geom.Res.Compile();
            }

            // Attach all shaders
            if (this.vert.IsAvailable)
            {
                GL.AttachShader(this.glProgramId, this.vert.Res.OglShaderId);
            }
            if (this.frag.IsAvailable)
            {
                GL.AttachShader(this.glProgramId, this.frag.Res.OglShaderId);
            }
            if (this.geom.IsAvailable)
            {
                GL.AttachShader(this.glProgramId, this.geom.Res.OglShaderId);
            }
        }
Exemple #9
0
        /// <summary>
        /// Retrieves the pixel data that is currently stored in video memory.
        /// </summary>
        /// <returns></returns>
        public Pixmap.Layer RetrievePixelData()
        {
            DualityApp.GuardSingleThreadState();

            int lastTexId;

            GL.GetInteger(GetPName.TextureBinding2D, out lastTexId);
            GL.BindTexture(TextureTarget.Texture2D, this.glTexId);

            byte[] data = new byte[this.texWidth * this.texHeight * 4];
            GL.GetTexImage(TextureTarget.Texture2D, 0,
                           GLPixelFormat.Rgba, PixelType.UnsignedByte,
                           data);

            GL.BindTexture(TextureTarget.Texture2D, lastTexId);

            Pixmap.Layer result = new Pixmap.Layer();
            result.SetPixelDataRgba(data, this.texWidth, this.texHeight);
            return(result);
        }
Exemple #10
0
        /// <summary>
        /// Loads the specified <see cref="Duality.Resources.Pixmap">Pixmaps</see> pixel data.
        /// </summary>
        /// <param name="basePixmap">The <see cref="Duality.Resources.Pixmap"/> that is used as pixel data source.</param>
        /// <param name="sizeMode">Specifies behaviour in case the source data has non-power-of-two dimensions.</param>
        public void LoadData(ContentRef <Pixmap> basePixmap, SizeMode sizeMode)
        {
            DualityApp.GuardSingleThreadState();
            if (this.glTexId == 0)
            {
                this.glTexId = GL.GenTexture();
            }
            this.needsReload = false;
            this.basePixmap  = basePixmap;
            this.texSizeMode = sizeMode;

            int lastTexId;

            GL.GetInteger(GetPName.TextureBinding2D, out lastTexId);
            GL.BindTexture(TextureTarget.Texture2D, this.glTexId);

            if (!this.basePixmap.IsExplicitNull)
            {
                Pixmap.Layer pixelData     = null;
                Pixmap       basePixmapRes = this.basePixmap.IsAvailable ? this.basePixmap.Res : null;
                if (basePixmapRes != null)
                {
                    pixelData  = basePixmapRes.MainLayer;
                    this.atlas = basePixmapRes.Atlas != null?basePixmapRes.Atlas.ToArray() : null;
                }

                if (pixelData == null)
                {
                    pixelData = Pixmap.Checkerboard.Res.MainLayer;
                }

                this.AdjustSize(pixelData.Width, pixelData.Height);
                this.SetupOpenGLRes();
                if (this.texSizeMode != SizeMode.NonPowerOfTwo &&
                    (this.pxWidth != this.texWidth || this.pxHeight != this.texHeight))
                {
                    if (this.texSizeMode == SizeMode.Enlarge)
                    {
                        Pixmap.Layer oldData = pixelData;
                        pixelData = oldData.CloneResize(this.texWidth, this.texHeight);
                        // Fill border pixels manually - that's cheaper than ColorTransparentPixels here.
                        oldData.DrawOnto(pixelData, BlendMode.Solid, this.pxWidth, 0, 1, this.pxHeight, this.pxWidth - 1, 0);
                        oldData.DrawOnto(pixelData, BlendMode.Solid, 0, this.pxHeight, this.pxWidth, 1, 0, this.pxHeight - 1);
                    }
                    else
                    {
                        pixelData = pixelData.CloneRescale(this.texWidth, this.texHeight, Pixmap.FilterMethod.Linear);
                    }
                }

                // Load pixel data to video memory
                GL.TexImage2D(TextureTarget.Texture2D, 0,
                              this.pixelformat, pixelData.Width, pixelData.Height, 0,
                              GLPixelFormat.Rgba, PixelType.UnsignedByte,
                              pixelData.Data);

                // Adjust atlas to represent UV coordinates
                if (this.atlas != null)
                {
                    Vector2 scale;
                    scale.X = this.uvRatio.X / this.pxWidth;
                    scale.Y = this.uvRatio.Y / this.pxHeight;
                    for (int i = 0; i < this.atlas.Length; i++)
                    {
                        this.atlas[i].X *= scale.X;
                        this.atlas[i].W *= scale.X;
                        this.atlas[i].Y *= scale.Y;
                        this.atlas[i].H *= scale.Y;
                    }
                }
            }
            else
            {
                this.atlas = null;
                this.AdjustSize(this.size.X, this.size.Y);
                this.SetupOpenGLRes();
            }

            GL.BindTexture(TextureTarget.Texture2D, lastTexId);
        }
Exemple #11
0
        /// <summary>
        /// Compiles the shader. This is done automatically when loading the shader
        /// or attaching it to a <see cref="Duality.Resources.ShaderProgram"/>.
        /// </summary>
        public void Compile()
        {
            DualityApp.GuardSingleThreadState();

            if (this.compiled)
            {
                return;
            }
            if (String.IsNullOrEmpty(this.source))
            {
                return;
            }
            if (this.glShaderId == 0)
            {
                this.glShaderId = GL.CreateShader(this.OglShaderType);
            }
            GL.ShaderSource(this.glShaderId, this.source);
            GL.CompileShader(this.glShaderId);

            int result;

            GL.GetShader(this.glShaderId, ShaderParameter.CompileStatus, out result);
            if (result == 0)
            {
                string infoLog = GL.GetShaderInfoLog(this.glShaderId);
                Log.Core.WriteError("Error compiling {0}. InfoLog:\n{1}", this.OglShaderType, infoLog);
                return;
            }
            this.compiled = true;

            // Remove comments from source code before extracting variables
            string sourceWithoutComments;
            {
                const string blockComments   = @"/\*(.*?)\*/";
                const string lineComments    = @"//(.*?)\r?\n";
                const string strings         = @"""((\\[^\n]|[^""\n])*)""";
                const string verbatimStrings = @"@(""[^""]*"")+";
                sourceWithoutComments = Regex.Replace(this.source,
                                                      blockComments + "|" + lineComments + "|" + strings + "|" + verbatimStrings,
                                                      me => {
                    if (me.Value.StartsWith("/*") || me.Value.StartsWith("//"))
                    {
                        return(me.Value.StartsWith("//") ? Environment.NewLine : "");
                    }
                    // Keep the literal strings
                    return(me.Value);
                },
                                                      RegexOptions.Singleline);
            }

            // Scan remaining code chunk for variable declarations
            List <ShaderVarInfo> varInfoList = new List <ShaderVarInfo>();

            string[]      lines   = sourceWithoutComments.Split(new[] { ';', '\n' }, StringSplitOptions.RemoveEmptyEntries);
            ShaderVarInfo varInfo = new ShaderVarInfo();

            foreach (string t in lines)
            {
                string curLine = t.TrimStart();

                if (curLine.StartsWith("uniform"))
                {
                    varInfo.scope = ShaderVarScope.Uniform;
                }
                else if (curLine.StartsWith("attribute"))
                {
                    varInfo.scope = ShaderVarScope.Attribute;
                }
                else
                {
                    continue;
                }

                string[] curLineSplit = curLine.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                switch (curLineSplit[1].ToUpper())
                {
                case "FLOAT":           varInfo.type = ShaderVarType.Float; break;

                case "VEC2":            varInfo.type = ShaderVarType.Vec2; break;

                case "VEC3":            varInfo.type = ShaderVarType.Vec3; break;

                case "VEC4":            varInfo.type = ShaderVarType.Vec4; break;

                case "MAT2":            varInfo.type = ShaderVarType.Mat2; break;

                case "MAT3":            varInfo.type = ShaderVarType.Mat3; break;

                case "MAT4":            varInfo.type = ShaderVarType.Mat4; break;

                case "INT":                     varInfo.type = ShaderVarType.Int; break;

                case "SAMPLER2D":       varInfo.type = ShaderVarType.Sampler2D; break;
                }

                curLineSplit      = curLineSplit[2].Split(new char[] { '[', ']' }, StringSplitOptions.RemoveEmptyEntries);
                varInfo.name      = curLineSplit[0];
                varInfo.arraySize = (curLineSplit.Length > 1) ? int.Parse(curLineSplit[1]) : 1;
                varInfo.glVarLoc  = -1;

                varInfoList.Add(varInfo);
            }

            this.varInfo = varInfoList.ToArray();
        }
Exemple #12
0
        /// <summary>
        /// Sets up all necessary OpenGL resources for this RenderTarget.
        /// </summary>
        public void SetupOpenGLRes()
        {
            DualityApp.GuardSingleThreadState();
            if (this.targetInfo == null || this.targetInfo.Count == 0)
            {
                return;
            }

            int highestAALevel = MathF.RoundToInt(MathF.Log(MathF.Max(MaxRenderTargetSamples, 1.0f), 2.0f));
            int targetAALevel  = highestAALevel;

            switch (this.multisampling)
            {
            case AAQuality.High:    targetAALevel = highestAALevel;         break;

            case AAQuality.Medium:  targetAALevel = highestAALevel / 2; break;

            case AAQuality.Low:             targetAALevel = highestAALevel / 4; break;

            case AAQuality.Off:             targetAALevel = 0;                                      break;
            }
            int targetSampleCount = MathF.RoundToInt(MathF.Pow(2.0f, targetAALevel));

            OpenTK.Graphics.GraphicsMode sampleMode =
                DualityApp.AvailableModes.LastOrDefault(m => m.Samples <= targetSampleCount) ??
                DualityApp.AvailableModes.Last();

            this.samples = sampleMode.Samples;

            #region Setup FBO & RBO: Non-multisampled
            if (this.samples == 0)
            {
                // Generate FBO
                if (this.glFboId == 0)
                {
                    GL.Ext.GenFramebuffers(1, out this.glFboId);
                }
                GL.Ext.BindFramebuffer(FramebufferTarget.FramebufferExt, this.glFboId);

                // Attach textures
                int oglWidth  = 0;
                int oglHeight = 0;
                for (int i = 0; i < this.targetInfo.Count; i++)
                {
                    if (!this.targetInfo[i].target.IsAvailable)
                    {
                        continue;
                    }
                    FramebufferAttachment attachment = (FramebufferAttachment)((int)FramebufferAttachment.ColorAttachment0Ext + i);
                    GL.Ext.FramebufferTexture2D(
                        FramebufferTarget.FramebufferExt,
                        attachment,
                        TextureTarget.Texture2D,
                        this.targetInfo[i].target.Res.OglTexId,
                        0);
                    oglWidth  = this.targetInfo[i].target.Res.TexelWidth;
                    oglHeight = this.targetInfo[i].target.Res.TexelHeight;
                }

                // Generate Depth Renderbuffer
                if (this.glRboIdDepth == 0)
                {
                    GL.Ext.GenRenderbuffers(1, out this.glRboIdDepth);
                }
                GL.Ext.BindRenderbuffer(RenderbufferTarget.RenderbufferExt, this.glRboIdDepth);
                GL.Ext.RenderbufferStorage(RenderbufferTarget.RenderbufferExt, RenderbufferStorage.DepthComponent24, oglWidth, oglHeight);
                GL.Ext.FramebufferRenderbuffer(FramebufferTarget.FramebufferExt, FramebufferAttachment.DepthAttachmentExt, RenderbufferTarget.RenderbufferExt, this.glRboIdDepth);

                // Check status
                FramebufferErrorCode status = GL.Ext.CheckFramebufferStatus(FramebufferTarget.FramebufferExt);
                if (status != FramebufferErrorCode.FramebufferCompleteExt)
                {
                    Log.Core.WriteError("Can't create RenderTarget '{0}'. Incomplete Framebuffer: {1}", this.path, status);
                }

                GL.Ext.BindRenderbuffer(RenderbufferTarget.RenderbufferExt, 0);
                GL.Ext.BindFramebuffer(FramebufferTarget.FramebufferExt, 0);
            }
            #endregion

            #region Setup FBO & RBO: Multisampled
            if (this.samples > 0)
            {
                // Generate texture target FBO
                if (this.glFboId == 0)
                {
                    GL.Ext.GenFramebuffers(1, out this.glFboId);
                }
                GL.Ext.BindFramebuffer(FramebufferTarget.FramebufferExt, this.glFboId);

                // Attach textures
                int oglWidth  = 0;
                int oglHeight = 0;
                for (int i = 0; i < this.targetInfo.Count; i++)
                {
                    if (!this.targetInfo[i].target.IsAvailable)
                    {
                        continue;
                    }
                    FramebufferAttachment attachment = (FramebufferAttachment)((int)FramebufferAttachment.ColorAttachment0Ext + i);
                    GL.Ext.FramebufferTexture2D(
                        FramebufferTarget.FramebufferExt,
                        attachment,
                        TextureTarget.Texture2D,
                        this.targetInfo[i].target.Res.OglTexId,
                        0);
                    oglWidth  = this.targetInfo[i].target.Res.TexelWidth;
                    oglHeight = this.targetInfo[i].target.Res.TexelHeight;
                }

                // Check status
                FramebufferErrorCode status = GL.Ext.CheckFramebufferStatus(FramebufferTarget.FramebufferExt);
                if (status != FramebufferErrorCode.FramebufferCompleteExt)
                {
                    Log.Core.WriteError("Can't create RenderTarget '{0}'. Incomplete Texture Framebuffer: {1}", this.path, status);
                }

                // Generate rendering FBO
                if (this.glFboIdMSAA == 0)
                {
                    GL.Ext.GenFramebuffers(1, out this.glFboIdMSAA);
                }
                GL.Ext.BindFramebuffer(FramebufferTarget.FramebufferExt, this.glFboIdMSAA);

                // Attach color renderbuffers
                for (int i = 0; i < this.targetInfo.Count; i++)
                {
                    if (!this.targetInfo[i].target.IsAvailable)
                    {
                        continue;
                    }
                    TargetInfo            info          = this.targetInfo[i];
                    FramebufferAttachment attachment    = (FramebufferAttachment)((int)FramebufferAttachment.ColorAttachment0Ext + i);
                    RenderbufferStorage   rbColorFormat = TexFormatToRboFormat(info.target.Res.PixelFormat);

                    if (info.glRboIdColorMSAA == 0)
                    {
                        GL.GenRenderbuffers(1, out info.glRboIdColorMSAA);
                    }
                    GL.Ext.BindRenderbuffer(RenderbufferTarget.RenderbufferExt, info.glRboIdColorMSAA);
                    GL.Ext.RenderbufferStorageMultisample(RenderbufferTarget.RenderbufferExt, this.samples, rbColorFormat, oglWidth, oglHeight);
                    GL.Ext.FramebufferRenderbuffer(FramebufferTarget.FramebufferExt, attachment, RenderbufferTarget.RenderbufferExt, info.glRboIdColorMSAA);
                    this.targetInfo[i] = info;
                }
                GL.Ext.BindRenderbuffer(RenderbufferTarget.Renderbuffer, 0);

                // Attach depth renderbuffer
                if (this.glRboIdDepth == 0)
                {
                    GL.Ext.GenRenderbuffers(1, out this.glRboIdDepth);
                }
                GL.Ext.BindRenderbuffer(RenderbufferTarget.RenderbufferExt, this.glRboIdDepth);
                GL.Ext.RenderbufferStorageMultisample(RenderbufferTarget.RenderbufferExt, this.samples, RenderbufferStorage.DepthComponent24, oglWidth, oglHeight);
                GL.Ext.FramebufferRenderbuffer(FramebufferTarget.FramebufferExt, FramebufferAttachment.DepthAttachmentExt, RenderbufferTarget.RenderbufferExt, this.glRboIdDepth);
                GL.Ext.BindRenderbuffer(RenderbufferTarget.RenderbufferExt, 0);

                // Check status
                status = GL.Ext.CheckFramebufferStatus(FramebufferTarget.FramebufferExt);
                if (status != FramebufferErrorCode.FramebufferCompleteExt)
                {
                    Log.Core.WriteError("Can't create RenderTarget '{0}'. Incomplete Multisample Framebuffer: {1}", this.path, status);
                }

                GL.Ext.BindFramebuffer(FramebufferTarget.FramebufferExt, 0);
            }
            #endregion
        }