Esempio n. 1
0
        private void GetBufferData <T>(int offsetInBytes, T[] data, int startIndex, int elementCount) where T : struct
        {
            GL.BindBuffer(BufferTarget.ArrayBuffer, ibo);
            REngine.CheckGLError();
            var    elementSizeInByte = Marshal.SizeOf(typeof(T));
            IntPtr ptr = GL.MapBuffer(BufferTarget.ArrayBuffer, BufferAccess.ReadOnly);

            // Pointer to the start of data to read in the index buffer
            ptr = new IntPtr(ptr.ToInt64() + offsetInBytes);
            if (typeof(T) == typeof(byte))
            {
                byte[] buffer = data as byte[];
                // If data is already a byte[] we can skip the temporary buffer
                // Copy from the index buffer to the destination array
                Marshal.Copy(ptr, buffer, 0, buffer.Length);
            }
            else
            {
                // Temporary buffer to store the copied section of data
                byte[] buffer = new byte[elementCount * elementSizeInByte];
                // Copy from the index buffer to the temporary buffer
                Marshal.Copy(ptr, buffer, 0, buffer.Length);
                // Copy from the temporary buffer to the destination array
                System.Buffer.BlockCopy(buffer, 0, data, startIndex * elementSizeInByte, elementCount * elementSizeInByte);
            }
            GL.UnmapBuffer(BufferTarget.ArrayBuffer);
            REngine.CheckGLError();
        }
Esempio n. 2
0
        private void BufferData <T>(int offsetInBytes, T[] data, int startIndex, int elementCount, RVertexDataOptions 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 == RIndexElementSize.SixteenBits ? 2 : 4);

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

            if (options == RVertexDataOptions.Discard)
            {
                // By assigning NULL data to the buffer this gives a hint
                // to the device to discard the previous content.
                GL.BufferData(BufferTarget.ElementArrayBuffer,
                              (IntPtr)bufferSize,
                              IntPtr.Zero,
                              _isDynamic ? BufferUsageHint.StreamDraw : BufferUsageHint.StaticDraw);
                REngine.CheckGLError();
            }

            GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)bufferSize, dataPtr, _isDynamic ? BufferUsageHint.StreamDraw : BufferUsageHint.StaticDraw);
            REngine.CheckGLError();
            GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0);
            REngine.CheckGLError();
            dataHandle.Free();
        }
Esempio n. 3
0
        private void Build(int width, int height, bool mipMap,
                           RSurfaceFormat preferredFormat, RDepthFormat preferredDepthFormat, int preferredMultiSampleCount, bool shared)
        {
            var depth   = 0;
            var stencil = 0;


            BackBuffer = new RTexture2D();
            BackBuffer.Create(width, height, RPixelFormat.Rgba, preferredFormat);
            GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, TextureTarget.Texture2D, BackBuffer.Id, 0);



            if (preferredDepthFormat != RDepthFormat.None)
            {
                DepthBuffer = new RTexture2D();

                if (preferredDepthFormat == RDepthFormat.Depth24Stencil8 || preferredDepthFormat == RDepthFormat.Depth32Stencil8)
                {
                    DepthBuffer.CreateDepth(width, height, RPixelFormat.DepthStencil, preferredDepthFormat);
                    GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.DepthStencilAttachment, TextureTarget.Texture2D, DepthBuffer.Id, 0);
                }
                else
                {
                    DepthBuffer.CreateDepth(width, height, RPixelFormat.DepthComponent, preferredDepthFormat);
                    GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.DepthAttachment, TextureTarget.Texture2D, DepthBuffer.Id, 0);
                }
                REngine.CheckGLError();
            }
            if (GL.CheckFramebufferStatus(FramebufferTarget.Framebuffer) != FramebufferErrorCode.FramebufferComplete)
            {
                throw new Exception("Error creating frame buffer: framebuffer is not complete");
            }
        }
Esempio n. 4
0
        internal void PlatformApplyState()
        {
            GL.Enable(EnableCap.Blend);
            GL.BlendFunc(this.ColorSourceBlend.GetBlendFactor(), this.ColorDestinationBlend.GetBlendFactor());

            GL.BlendColor(
                this.BlendFactor.R / 255.0f,
                this.BlendFactor.G / 255.0f,
                this.BlendFactor.B / 255.0f,
                this.BlendFactor.A / 255.0f);
            REngine.CheckGLError();

            GL.BlendEquationSeparate(
                this.ColorBlendFunction.GetBlendEquationMode(),
                this.AlphaBlendFunction.GetBlendEquationMode());
            REngine.CheckGLError();

            GL.BlendFuncSeparate(
                this.ColorSourceBlend.GetBlendFactorSrc(),
                this.ColorDestinationBlend.GetBlendFactorDest(),
                this.AlphaSourceBlend.GetBlendFactorSrc(),
                this.AlphaDestinationBlend.GetBlendFactorDest());
            REngine.CheckGLError();

            GL.ColorMask(
                (this.ColorWriteChannels & RColorWriteChannels.Red) != 0,
                (this.ColorWriteChannels & RColorWriteChannels.Green) != 0,
                (this.ColorWriteChannels & RColorWriteChannels.Blue) != 0,
                (this.ColorWriteChannels & RColorWriteChannels.Alpha) != 0);
            REngine.CheckGLError();
        }
Esempio n. 5
0
        internal void Draw(PrimitiveType primitiveType, Matrix world)
        {
            Threading.EnsureUIThread();
            GL.FrontFace(FrontFaceDirection.Ccw);
            GL.CullFace(CullFaceMode.Back);

            GL.Enable(EnableCap.CullFace);
            GL.Enable(EnableCap.DepthTest);
            GL.DepthFunc(DepthFunction.Less);
            Material.Shader.Bind();
            Material.Apply();

            VertexBuffer.BindVertexArray();
            VertexBuffer.Bind();
            IndexBuffer.Bind();
            VertexBuffer.VertexDeclaration.Apply(Material.Shader, IntPtr.Zero);

            REngine.CheckGLError();

            Material.Shader.BindSemantics(Matrix.Identity * world, REngine.camera.View, REngine.camera.Projection);
            REngine.CheckGLError();


            GL.DrawElements(primitiveType, IndexBuffer.IndexCount, DrawElementsType.UnsignedInt, IntPtr.Zero);

            Material.Shader.Unbind();
            IndexBuffer.Unbind();
            VertexBuffer.Unbind();
            VertexBuffer.UnbindVertexArray();
        }
Esempio n. 6
0
        private void SetBufferData <T>(int bufferSize, int elementSizeInBytes, int offsetInBytes, T[] data, int startIndex, int elementCount, int vertexStride, RVertexDataOptions options) where T : struct
        {
            GenerateIfRequired();

            var sizeInBytes = elementSizeInBytes * elementCount;

            GL.BindBuffer(BufferTarget.ArrayBuffer, vbo);
            REngine.CheckGLError();

            if (options == RVertexDataOptions.Discard)
            {
                // By assigning NULL data to the buffer this gives a hint
                // to the device to discard the previous content.
                GL.BufferData(BufferTarget.ArrayBuffer,
                              (IntPtr)bufferSize,
                              IntPtr.Zero,
                              _isDynamic ? BufferUsageHint.StreamDraw : BufferUsageHint.StaticDraw);
                REngine.CheckGLError();
            }

            var dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned);
            var dataPtr    = (IntPtr)(dataHandle.AddrOfPinnedObject().ToInt64() + startIndex * elementSizeInBytes);

            GL.BufferSubData(BufferTarget.ArrayBuffer, (IntPtr)offsetInBytes, (IntPtr)sizeInBytes, dataPtr);
            REngine.CheckGLError();

            dataHandle.Free();
        }
Esempio n. 7
0
        /// <summary>
        /// Runs the given action on the UI thread and blocks the current thread while the action is running.
        /// If the current thread is the UI thread, the action will run immediately.
        /// </summary>
        /// <param name="action">The action to be run on the UI thread</param>
        internal static void BlockOnUIThread(Action action)
        {
            if (action == null)
            {
                throw new ArgumentNullException("action");
            }

            // If we are already on the UI thread, just call the action and be done with it
            if (IsOnUIThread())
            {
                action();
                return;
            }

            lock (BackgroundContext)
            {
                // Make the context current on this thread
                BackgroundContext.MakeCurrent(WindowInfo);
                // Execute the action
                action();
                // Must flush the GL calls so the texture is ready for the main context to use
                GL.Flush();
                REngine.CheckGLError();
                // Must make the context not current on this thread or the next thread will get error 170 from the MakeCurrent call
                BackgroundContext.MakeCurrent(null);
            }
        }
Esempio n. 8
0
 public void Dispose()
 {
     GL.DeleteFramebuffer(Id);
     DepthBuffer.Dispose();
     BackBuffer.Dispose();
     REngine.CheckGLError();
 }
Esempio n. 9
0
 public void Dispose()
 {
     Threading.BlockOnUIThread(() =>
     {
         GL.DeleteBuffers(1, ref ibo);
         REngine.CheckGLError();
     });
 }
Esempio n. 10
0
 protected void CreateProperties(TextureTarget target, bool mipmapped = false)
 {
     textureTarget = target;
     SetTextureMagFilter(RTextureMagFilter.Linear);
     SetTextureMinFilter(mipmapped ? RTextureMinFilter.LinearMipmapLinear : RTextureMinFilter.Linear);
     SetTextureWrapMode(RTextureWrapMode.Repeat, RTextureWrapMode.Repeat);
     REngine.CheckGLError();
 }
Esempio n. 11
0
 public void SetData(RColor[] colors, RPixelFormat format, int x, int y, int width, int height)
 {
     Bind();
     GL.TexSubImage2D <RColor>(textureTarget, 0, x, y, width, height, (PixelFormat)format, PixelType.UnsignedByte, colors);
     REngine.CheckGLError();
     Unbind();
     REngine.CheckGLError();
 }
Esempio n. 12
0
 public void SetTextureMinFilter(RTextureMinFilter value)
 {
     if (Id != 0)
     {
         GL.TexParameter(textureTarget, TextureParameterName.TextureMinFilter, (int)value);
         REngine.CheckGLError();
     }
 }
Esempio n. 13
0
        internal void LoadFromDisk(string filename)
        {
            if (Path.GetExtension(filename).ToLower() == ".dds")
            {
                try
                {
                    ImageDDS.LoadFromDisk(RFileSystem.Instance.GetFilePath(filename), out Id, out textureTarget, out pixelFormat, out pixelType);
                }catch (Exception e) {
                    RLog.Error("Error loading texture from: " + filename);
                    RLog.Error(e);
                }
            }
            else
            {
                try
                {
                    ImageGDI.LoadFromDisk(RFileSystem.Instance.GetFilePath(filename), out Id, out textureTarget, out pixelFormat, out pixelType);
                }catch (Exception e) {
                    RLog.Error("Error loading texture from: " + filename);
                    RLog.Error(e);
                    return;
                }
            }
            if (Id == 0 || textureTarget == 0)
            {
                RLog.Error("Error generating OpenGL texture from: " + filename);
                return;
            }

            // load succeeded, Texture can be used.
            Bind();
            int max_level = 0;
            int min_level = 0;

            REngine.CheckGLError();
            GL.TexParameterI(textureTarget, TextureParameterName.TextureBaseLevel, ref min_level);
            REngine.CheckGLError();
            GL.TexParameterI(textureTarget, TextureParameterName.TextureMaxLevel, ref max_level);
            REngine.CheckGLError();
            GL.TexParameter(textureTarget, TextureParameterName.TextureMagFilter, (int)RTextureMagFilter.Linear);
            REngine.CheckGLError();
            GL.TexParameter(textureTarget, TextureParameterName.TextureMinFilter, (int)RTextureMinFilter.Linear);
            REngine.CheckGLError();
            GL.TexParameter(textureTarget, TextureParameterName.TextureMaxLod, 0);
            REngine.CheckGLError();
            GL.TexParameter(textureTarget, TextureParameterName.TextureMinLod, 0);
            REngine.CheckGLError();
            int height, width;

            GL.GetTexLevelParameter(textureTarget, 0, GetTextureParameter.TextureHeight, out height);
            REngine.CheckGLError();
            GL.GetTexLevelParameter(textureTarget, 0, GetTextureParameter.TextureWidth, out width);
            REngine.CheckGLError();
            Bounds = new Reactor.Math.Rectangle(0, 0, width, height);
            RLog.Info("Texture loaded from: " + filename);
        }
Esempio n. 14
0
 public void CreateDepth(int width, int height, RPixelFormat format, RDepthFormat depthFormat)
 {
     GL.GenTextures(1, out Id);
     textureTarget = TextureTarget.Texture2D;
     GL.BindTexture(textureTarget, Id);
     REngine.CheckGLError();
     GL.TexImage2D(textureTarget, 0, GetPixelInternalForDepth(depthFormat), width, height, 0, (PixelFormat)format, GetPixelTypeForDepth(depthFormat), IntPtr.Zero);
     REngine.CheckGLError();
     CreateProperties(textureTarget, false);
     REngine.CheckGLError();
 }
Esempio n. 15
0
 public void SetUniformValue(string name, bool value)
 {
     if (value)
     {
         GL.Uniform1(GetUniformLocation(name), 1);
     }
     else
     {
         GL.Uniform1(GetUniformLocation(name), 0);
     }
     REngine.CheckGLError();
 }
Esempio n. 16
0
 public void Dispose()
 {
     if (!IsDisposed)
     {
         Threading.BlockOnUIThread(() =>
         {
             GL.DeleteBuffers(1, ref vbo);
             REngine.CheckGLError();
         });
     }
     IsDisposed = true;
 }
Esempio n. 17
0
 public void UnbindVertexArray()
 {
     if (!Threading.IsOnUIThread())
     {
         Threading.BlockOnUIThread(() => { UnbindVertexArray(); });
     }
     else
     {
         GL.BindVertexArray(0);
         REngine.CheckGLError();
     }
 }
Esempio n. 18
0
 public void Bind()
 {
     if (Id != 0)
     {
         GL.UseProgram(Id);
         REngine.CheckGLError();
     }
     else
     {
         throw new EngineGLException("You must first compile a shader program before you can bind it");
     }
 }
Esempio n. 19
0
 public void Dispose()
 {
     try
     {
         if (GL.IsShader(Id))
         {
             GL.DeleteShader(Id);
             REngine.CheckGLError();
         }
     }
     catch { }
 }
Esempio n. 20
0
 public void Unbind()
 {
     if (Threading.IsOnUIThread())
     {
         GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
         REngine.CheckGLError();
     }
     else
     {
         Threading.BlockOnUIThread(() => { Unbind(); });
     }
 }
Esempio n. 21
0
        private void GetBufferData <T>(int offsetInBytes, T[] data, int startIndex, int elementCount, int vertexStride) where T : struct
        {
            GL.BindBuffer(BufferTarget.ArrayBuffer, vbo);
            REngine.CheckGLError();
            var    elementSizeInByte = Marshal.SizeOf(typeof(T));
            IntPtr ptr = GL.MapBuffer(BufferTarget.ArrayBuffer, BufferAccess.ReadOnly);

            REngine.CheckGLError();
            // Pointer to the start of data to read in the index buffer
            ptr = new IntPtr(ptr.ToInt64() + offsetInBytes);
            if (typeof(T) == typeof(byte))
            {
                byte[] buffer = data as byte[];
                // If data is already a byte[] we can skip the temporary buffer
                // Copy from the vertex buffer to the destination array
                Marshal.Copy(ptr, buffer, 0, buffer.Length);
            }
            else
            {
                // Temporary buffer to store the copied section of data
                byte[] buffer = new byte[elementCount * vertexStride - offsetInBytes];
                // Copy from the vertex buffer to the temporary buffer
                Marshal.Copy(ptr, buffer, 0, buffer.Length);

                var dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned);
                var dataPtr    = (IntPtr)(dataHandle.AddrOfPinnedObject().ToInt64() + startIndex * elementSizeInByte);

                // Copy from the temporary buffer to the destination array

                int dataSize = Marshal.SizeOf(typeof(T));
                if (dataSize == vertexStride)
                {
                    Marshal.Copy(buffer, 0, dataPtr, buffer.Length);
                }
                else
                {
                    // If the user is asking for a specific element within the vertex buffer, copy them one by one...
                    for (int i = 0; i < elementCount; i++)
                    {
                        Marshal.Copy(buffer, i * vertexStride, dataPtr, dataSize);
                        dataPtr = (IntPtr)(dataPtr.ToInt64() + dataSize);
                    }
                }

                dataHandle.Free();

                //Buffer.BlockCopy(buffer, 0, data, startIndex * elementSizeInByte, elementCount * elementSizeInByte);
            }
            GL.UnmapBuffer(BufferTarget.ArrayBuffer);
            REngine.CheckGLError();
        }
Esempio n. 22
0
 public void BindVertexArray()
 {
     if (!Threading.IsOnUIThread())
     {
         Threading.BlockOnUIThread(() => { BindVertexArray(); });
     }
     else
     {
         GenerateIfRequired();
         REngine.CheckGLError();
         GL.BindVertexArray(vao);
         REngine.CheckGLError();
     }
 }
Esempio n. 23
0
        public T[] GetData <T>() where T : struct
        {
            GL.ActiveTexture(TextureUnit.Texture0);
            REngine.CheckGLError();
            Bind();
            REngine.CheckGLError();
            T[] pixels = new T[Bounds.Width * Bounds.Height];
            GL.GetTexImage <T>(textureTarget, 0, (PixelFormat)pixelFormat, pixelType, pixels);
            REngine.CheckGLError();
            Unbind();
            REngine.CheckGLError();

            return(pixels);
        }
Esempio n. 24
0
        public void SetSamplerValue(RTextureLayer layer, RTexture texture)
        {
            int unival = GetTexUniformValue(layer);
            int loc    = GetTexUniformLocation(layer);

            GL.Uniform1(loc, unival);
            REngine.CheckGLError();
            TextureUnit unit = (TextureUnit)(int)layer;

            GL.ActiveTexture(unit);
            REngine.CheckGLError();
            texture.Bind();
            REngine.CheckGLError();
        }
Esempio n. 25
0
        internal void Render(ref RShader shader, ref RVertexBuffer vertexBuffer, ref RIndexBuffer indexBuffer, string text, Vector2 location, RColor color, Matrix matrix)
        {
            Vector2 pen = location;

            pen.Y += MeasureString(text).Height;
            float x = pen.X;
            List <RVertexData2D> quads = new List <RVertexData2D>();

            foreach (char c in text)
            {
                if (c == '\r')
                {
                    continue;
                }
                if (c == '\n')
                {
                    pen.X  = x;
                    pen.Y += LineHeight;
                    continue;
                }
                if (c == ' ')
                {
                    pen.X += SpaceWidth;
                    continue;
                }
                if (c == '\t')
                {
                    pen.X += (SpaceWidth * 3);
                    continue;
                }
                RFontGlyph glyph = GetGlyphForChar(c);
                var        dest  = new Reactor.Math.Rectangle();
                dest.X      = (int)(pen.X + glyph.Offset.X);
                dest.Y      = (int)pen.Y - ((int)glyph.Offset.Y);
                dest.Width  = glyph.Bounds.Width;
                dest.Height = glyph.Bounds.Height;

                vertexBuffer.SetData <RVertexData2D>(AddQuads(dest, glyph.UVBounds));
                vertexBuffer.Bind();
                vertexBuffer.BindVertexArray();
                indexBuffer.Bind();
                vertexBuffer.VertexDeclaration.Apply(shader, IntPtr.Zero);
                GL.DrawElements(PrimitiveType.Triangles, indexBuffer.IndexCount, DrawElementsType.UnsignedShort, IntPtr.Zero);
                REngine.CheckGLError();
                indexBuffer.Unbind();
                vertexBuffer.Unbind();
                vertexBuffer.UnbindVertexArray();
                pen.X += glyph.Advance;
            }
        }
Esempio n. 26
0
 public void SetData <T>(T[] data, RPixelFormat format, int x, int y, int width, int height, bool packAlignment = true) where T : struct
 {
     if (!packAlignment)
     {
         GL.PixelStore(PixelStoreParameter.UnpackAlignment, 1);
     }
     Bind();
     GL.TexSubImage2D <T>(textureTarget, 0, x, y, width, height, (PixelFormat)format, PixelType.UnsignedByte, data);
     REngine.CheckGLError();
     Unbind();
     if (!packAlignment)
     {
         GL.PixelStore(PixelStoreParameter.PackAlignment, 1);
     }
 }
Esempio n. 27
0
        /// <summary>
        /// If the IBO does not exist, create it.
        /// </summary>
        void GenerateIfRequired()
        {
            if (ibo == 0)
            {
                var sizeInBytes = IndexCount * (this.IndexElementSize == RIndexElementSize.SixteenBits ? 2 : 4);

                GL.GenBuffers(1, out ibo);

                REngine.CheckGLError();
                GL.BindBuffer(BufferTarget.ElementArrayBuffer, ibo);
                REngine.CheckGLError();
                GL.BufferData(BufferTarget.ElementArrayBuffer,
                              (IntPtr)sizeInBytes, IntPtr.Zero, _isDynamic ? BufferUsageHint.StreamDraw : BufferUsageHint.StaticDraw);
                REngine.CheckGLError();
            }
        }
Esempio n. 28
0
 public void SetTextureWrapMode(RTextureWrapMode modeS, RTextureWrapMode modeT)
 {
     if (Id != 0)
     {
         Bind();
         try
         {
             GL.TexParameter(textureTarget, TextureParameterName.TextureWrapS, (int)modeS);
             REngine.CheckGLError();
             GL.TexParameter(textureTarget, TextureParameterName.TextureWrapT, (int)modeT);
             REngine.CheckGLError();
         }catch (EngineGLException ex)
         {
         }
     }
 }
Esempio n. 29
0
        public RFrameBuffer(int width, int height, bool mipMap, RSurfaceFormat preferredFormat, RDepthFormat preferredDepthFormat, int preferredMultiSampleCount, bool shared)
        {
            Width              = width;
            Height             = height;
            DepthStencilFormat = preferredDepthFormat;
            SurfaceFormat      = preferredFormat;
            MultiSampleCount   = preferredMultiSampleCount;
            var id = 0;

            GL.GenFramebuffers(1, out id);
            REngine.CheckGLError();
            Id = id;
            Bind();
            Build(width, height, mipMap, preferredFormat, preferredDepthFormat, preferredMultiSampleCount, shared);
            Unbind();
        }
Esempio n. 30
0
        internal void Apply(RShader shader, IntPtr offset)
        {
            RVertexDeclarationAttributeInfo attrInfo;
            int shaderHash = shader.GetHashCode();

            if (!shaderAttributeInfo.TryGetValue(shaderHash, out attrInfo))
            {
                // Get the vertex attribute info and cache it
                attrInfo = new RVertexDeclarationAttributeInfo(16);

                foreach (var ve in _elements)
                {
                    var attributeLocation = shader.GetAttribLocation(ve.VertexElementUsage);

                    if (attributeLocation >= 0)
                    {
                        attrInfo.Elements.Add(new RVertexDeclarationAttributeInfo.Element()
                        {
                            Offset                  = ve.Offset,
                            AttributeLocation       = attributeLocation,
                            NumberOfElements        = RVertexElement.OpenGLNumberOfElements(ve.VertexElementFormat),
                            VertexAttribPointerType = RVertexElement.OpenGLVertexAttribPointerType(ve.VertexElementFormat),
                            Normalized              = RVertexElement.OpenGLVertexAttribNormalized(ve),
                        });
                        attrInfo.EnabledAttributes[attributeLocation] = true;
                    }
                }

                shaderAttributeInfo.Add(shaderHash, attrInfo);
            }

            // Apply the vertex attribute info
            foreach (var element in attrInfo.Elements)
            {
                GL.EnableVertexAttribArray(element.AttributeLocation);
                REngine.CheckGLError();
                GL.VertexAttribPointer(element.AttributeLocation,
                                       element.NumberOfElements,
                                       element.VertexAttribPointerType,
                                       element.Normalized,
                                       this.VertexStride,
                                       (IntPtr)(offset.ToInt64() + element.Offset));
                REngine.CheckGLError();
            }
            //GraphicsDevice.SetVertexAttributeArray(attrInfo.EnabledAttributes);
        }