/// <summary> /// /// </summary> public void Draw() { int instanceCount = this.InstanceCount; uint mode = (uint)this.CurrentMode; IndexBuffer indexBuffer = this.indexBuffer; int vertexCount = indexBuffer.Length; IndexBufferElementType elementType = indexBuffer.ElementType; IntPtr offset = GetOffset(elementType, this.FirstVertex); uint rs = this.PrimitiveRestartIndex; if (rs != 0) { GL.Instance.Enable(GL.GL_PRIMITIVE_RESTART); glPrimitiveRestartIndex(rs); } GLBuffer.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, indexBuffer.BufferId); glDrawElementsInstanced(mode, this.VertexCount, (uint)elementType, offset, instanceCount); GLBuffer.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, 0); if (rs != 0) { GL.Instance.Disable(GL.GL_PRIMITIVE_RESTART); } }
/// <summary> /// The indexes in which order the rendering command renders vertexes. /// </summary> /// <param name="bufferId">用glGenBuffers()得到的VBO的Id。<para>Id got from glGenBuffers();</para></param> /// <param name="elementType">type in glDrawElements(uint mode, int count, uint type, IntPtr indices);</param> /// <param name="byteLength">此VBO中的数据在内存中占用多少个字节?<para>How many bytes in this buffer</para></param> internal IndexBuffer(uint bufferId, IndexBufferElementType elementType, int byteLength) : base(bufferId, byteLength / elementType.GetSize(), byteLength) { this.Target = BufferTarget.ElementArrayBuffer; this.ElementType = elementType; }
/// <summary> /// /// </summary> /// <param name="mode"></param> /// <param name="count"></param> /// <param name="type">type of indices' element.</param> private MultiDrawElementsCmd(DrawMode mode, int[] count, IndexBufferElementType type) { this.Mode = mode; this.CurrentMode = mode; this.count = count; this.type = type; }
/// <summary> /// Creates a <see cref="OneIndexBuffer"/> object directly in server side(GPU) without initializing its value. /// </summary> /// <param name="type"></param> /// <param name="length">How many indexes are there?(How many uint/ushort/bytes?)</param> /// <param name="mode"></param> /// <param name="usage"></param> /// <returns></returns> public static OneIndexBuffer Create(IndexBufferElementType type, int length, DrawMode mode, BufferUsage usage) { if (glGenBuffers == null) { glGenBuffers = OpenGL.GetDelegateFor <OpenGL.glGenBuffers>(); } if (glBindBuffer == null) { glBindBuffer = OpenGL.GetDelegateFor <OpenGL.glBindBuffer>(); } if (glBufferData == null) { glBufferData = OpenGL.GetDelegateFor <OpenGL.glBufferData>(); } int byteLength = GetSize(type) * length; uint[] buffers = new uint[1]; glGenBuffers(1, buffers); const uint target = OpenGL.GL_ELEMENT_ARRAY_BUFFER; glBindBuffer(target, buffers[0]); glBufferData(target, byteLength, IntPtr.Zero, (uint)usage); glBindBuffer(target, 0); var buffer = new OneIndexBuffer( buffers[0], mode, type, length, byteLength); return(buffer); }
/// <summary> /// 生成一个用于存储索引的IBO。索引指定了<see cref="VertexBuffer"/>里各个顶点的渲染顺序。 /// Generates a Index Buffer Object storing vertexes' indexes, which indicate the rendering order of each vertex. /// </summary> /// <param name="array"></param> /// <param name="type"></param> /// <param name="usage"></param> /// <param name="first"></param> /// <param name="count"></param> /// <returns></returns> public static IndexBuffer GenIndexBuffer <T>(this T[] array, IndexBufferElementType type, BufferUsage usage, int first, int count) where T : struct { if (array == null) { throw new ArgumentNullException("array"); } if (first < 0) { throw new ArgumentOutOfRangeException("first"); } if (count < 0) { throw new ArgumentOutOfRangeException("count"); } if (array.Length < first + count) { throw new ArgumentOutOfRangeException("first + count"); } GCHandle pinned = GCHandle.Alloc(array, GCHandleType.Pinned); //IntPtr header = pinned.AddrOfPinnedObject(); // same result with: IntPtr header = Marshal.UnsafeAddrOfPinnedArrayElement(array, 0); IntPtr header = Marshal.UnsafeAddrOfPinnedArrayElement(array, first); UnmanagedArrayBase unmanagedArray = new TempUnmanagedArray <T>(header, count);// It's not necessary to call Dispose() for this unmanaged array. IndexBuffer buffer = GenIndexBuffer(unmanagedArray, type, usage); pinned.Free(); return(buffer); }
/// <summary> /// Creates a new instance of the <see cref="DynamicIndexBuffer"/> class. /// </summary> /// <param name="itype">The index element type.</param> /// <param name="icount">The index element count.</param> /// <returns>The instance of <see cref="DynamicIndexBuffer"/> that was created.</returns> public static new DynamicIndexBuffer Create(IndexBufferElementType itype, Int32 icount) { Contract.EnsureRange(icount > 0, "icount"); var uv = UltravioletContext.DemandCurrent(); return uv.GetFactoryMethod<DynamicIndexBufferFactory>()(uv, itype, icount); }
/// <summary> /// /// </summary> /// <param name="mode"></param> /// <param name="count"></param> /// <param name="type">type of indices' element.</param> /// <param name="baseVertex"></param> private MultiDrawElementsCmd(DrawMode mode, int[] count, IndexBufferElementType type, int[] baseVertex = null) { this.Mode = mode; this.count = count; this.type = type; this.baseVertex = baseVertex; }
/// <summary> /// Creates a new instance of the <see cref="IndexBuffer"/> class. /// </summary> /// <param name="itype">The index element type.</param> /// <param name="icount">The index element count.</param> /// <returns>The instance of <see cref="IndexBuffer"/> that was created.</returns> public static IndexBuffer Create(IndexBufferElementType itype, Int32 icount) { Contract.EnsureRange(icount > 0, nameof(icount)); var uv = UltravioletContext.DemandCurrent(); return(uv.GetFactoryMethod <IndexBufferFactory>()(uv, itype, icount)); }
/// <summary> /// Wraps glDrawElements(uint mode, int count, uint type, IntPtr indices). /// </summary> /// <param name="bufferId">用glGenBuffers()得到的VBO的Id。<para>Id got from glGenBuffers();</para></param> /// <param name="mode">用哪种方式渲染各个顶点?(GL.GL_TRIANGLES etc.)</param> /// <param name="elementType">type in glDrawElements(uint mode, int count, uint type, IntPtr indices); /// <para>表示第3个参数,表示索引元素的类型。</para></param> /// <param name="vertexCount">此VBO含有多个个元素?<para>How many elements?</para></param> /// <param name="byteLength">此VBO中的数据在内存中占用多少个字节?<para>How many bytes in this buffer?</para></param> /// <param name="primCount">primCount in instanced rendering.</param> /// <param name="frameCount">How many frames are there?</param> internal OneIndexBuffer(uint bufferId, DrawMode mode, IndexBufferElementType elementType, int vertexCount, int byteLength, int primCount = 1, int frameCount = 1) : base(mode, bufferId, 0, vertexCount, byteLength, primCount, frameCount) { this.Target = BufferTarget.ElementArrayBuffer; this.ElementType = elementType; }
/// <summary> /// Wraps glDrawElements(uint mode, int count, uint type, IntPtr indices). /// </summary> /// <param name="bufferId">用glGenBuffers()得到的VBO的Id。<para>Id got from glGenBuffers();</para></param> /// <param name="mode">用哪种方式渲染各个顶点?(OpenGL.GL_TRIANGLES etc.)</param> /// <param name="elementType">type in glDrawElements(uint mode, int count, uint type, IntPtr indices); /// <para>表示第3个参数,表示索引元素的类型。</para></param> /// <param name="length">此VBO含有多个个元素?<para>How many elements?</para></param> /// <param name="byteLength">此VBO中的数据在内存中占用多少个字节?<para>How many bytes in this buffer?</para></param> /// <param name="primCount">primCount in instanced rendering.</param> internal OneIndexBuffer(uint bufferId, DrawMode mode, IndexBufferElementType elementType, int length, int byteLength, int primCount = 1) : base(mode, bufferId, length, byteLength, primCount) { this.ElementCount = length; //this.OriginalElementCount = length; this.ElementType = elementType; }
/// <summary> /// Initializes a new instance of the <see cref="IndexBuffer"/> class. /// </summary> /// <param name="uv">The Ultraviolet context.</param> /// <param name="itype">The index element type.</param> /// <param name="icount">The index element count.</param> protected IndexBuffer(UltravioletContext uv, IndexBufferElementType itype, Int32 icount) : base(uv) { Contract.EnsureRange(icount > 0, nameof(icount)); this.itype = itype; this.icount = icount; }
/// <summary> /// /// </summary> /// <returns></returns> public override string ToString() { uint mode = (uint)this.CurrentMode; IndexBuffer indexBuffer = this.indexBuffer; IndexBufferElementType elementType = indexBuffer.ElementType; IntPtr offset = GetOffset(elementType, this.FirstVertex); return(string.Format("glDrawElementsBaseVertex(mode: {0}, frameVertexCount: {1}, type: {2}, offset: {3}, baseVertex: {4});", mode, this.FrameVertexCount, elementType, offset, this.BaseVertex)); }
/// <summary> /// /// </summary> /// <returns></returns> public override string ToString() { IndexBuffer indexBuffer = this.indexBuffer; int vertexCount = indexBuffer.Length; IndexBufferElementType elementType = indexBuffer.ElementType; IntPtr offset = GetOffset(elementType, this.FirstVertex); return(string.Format("glDrawElements(mode: {0}, vertexCount: {1}, type: {2}, offset: {3});", this.CurrentMode, this.VertexCount, elementType, offset)); }
/// <summary> /// 生成一个用于存储索引的IBO。索引指定了<see cref="VertexBuffer"/>里各个顶点的渲染顺序。 /// Generates a Index Buffer Object storing vertexes' indexes, which indicate the rendering order of each vertex. /// </summary> /// <param name="array"></param> /// <param name="type"></param> /// <param name="usage"></param> /// <param name="first"></param> /// <returns></returns> public static IndexBuffer GenIndexBuffer <T>(this T[] array, IndexBufferElementType type, BufferUsage usage, int first) where T : struct { if (array == null) { throw new ArgumentNullException("array"); } return(GenIndexBuffer(array, type, usage, first, array.Length)); }
/// <summary> /// /// </summary> /// <returns></returns> public override string ToString() { var mode = this.CurrentMode; IndexBuffer indexBuffer = this.indexBuffer; IndexBufferElementType elementType = indexBuffer.ElementType; IntPtr offset = GetOffset(elementType, this.FirstVertex); return(string.Format("glDrawElementsInstanced(mode: {0}, vertexCount: {1}, type: {2}, offset: {3}, primCount: {4});", mode, this.VertexCount, elementType, offset, this.InstanceCount)); }
/// <summary> /// 生成若干用于存储索引的IBO。索引指定了<see cref="VertexBuffer"/>里各个顶点的渲染顺序。 /// Generates some Index Buffer Objects storing vertexes' indexes, which indicate the rendering order of each vertex. /// </summary> /// <param name="array"></param> /// <param name="type"></param> /// <param name="usage"></param> /// <param name="blockSize">How many elements per index buffer?(sometimes except the last one)</param> /// <returns></returns> public static IndexBuffer[] GenIndexBuffers <T>(this T[] array, IndexBufferElementType type, BufferUsage usage, int blockSize) where T : struct { if (array == null) { throw new ArgumentNullException("array"); } const int first = 0; return(GenIndexBuffers(array, type, usage, first, blockSize)); }
/// <summary> /// /// </summary> /// <param name="mode"></param> /// <param name="count"></param> /// <param name="type">type of indices' element.</param> /// <param name="baseVertex"></param> private MultiDrawElementsBaseVertexCmd(DrawMode mode, int[] count, IndexBufferElementType type, int[] baseVertex = null) { if (this.baseVertex == null) { throw new ArgumentNullException("baseVertex"); } this.Mode = mode; this.CurrentMode = mode; this.count = count; this.type = type; this.baseVertex = baseVertex; }
/// <summary> /// 生成一个用于存储索引的IBO。索引指定了<see cref="VertexBuffer"/>里各个顶点的渲染顺序。 /// Generates a Index Buffer Object storing vertexes' indexes, which indicate the rendering order of each vertex. /// </summary> /// <param name="array"></param> /// <param name="type"></param> /// <param name="usage"></param> /// <returns></returns> public static IndexBuffer GenIndexBuffer(this UnmanagedArrayBase array, IndexBufferElementType type, BufferUsage usage) { var ids = new uint[1]; { glGenBuffers(1, ids); const uint target = GL.GL_ELEMENT_ARRAY_BUFFER; glBindBuffer(target, ids[0]); glBufferData(target, array.ByteLength, array.Header, (uint)usage); glBindBuffer(target, 0); } var buffer = new IndexBuffer(ids[0], type, array.ByteLength); return(buffer); }
/// <summary> /// Gets the OpenGL index element format that corresponds to the specified Ultraviolet index element type. /// </summary> /// <param name="type">The index element type to convert.</param> /// <param name="size">The index element size in bytes.</param> /// <returns>The converted index element format.</returns> private static UInt32 GetIndexFormatGL(IndexBufferElementType type, out Int32 size) { switch (type) { case IndexBufferElementType.Int16: size = sizeof(short); return(gl.GL_UNSIGNED_SHORT); case IndexBufferElementType.Int32: size = sizeof(int); return(gl.GL_UNSIGNED_INT); default: throw new NotSupportedException(OpenGLStrings.UnsupportedIndexFormat); } }
/// <summary> /// Creates a <see cref="IndexBuffer"/> object directly in server side(GPU) without initializing its value. /// </summary> /// <param name="type"></param> /// <param name="length">How many indexes are there?(How many uint/ushort/bytes?)</param> /// <param name="usage"></param> /// <returns></returns> public static IndexBuffer Create(IndexBufferElementType type, int length, BufferUsage usage) { int byteLength = type.GetSize() * length; uint[] buffers = new uint[1]; { glGenBuffers(1, buffers); const uint target = GL.GL_ELEMENT_ARRAY_BUFFER; glBindBuffer(target, buffers[0]); glBufferData(target, byteLength, IntPtr.Zero, (uint)usage); glBindBuffer(target, 0); } var buffer = new IndexBuffer(buffers[0], type, byteLength); return(buffer); }
/// <summary> /// Creates a <see cref="OneIndexBuffer"/> object directly in server side(GPU) without initializing its value. /// </summary> /// <param name="type"></param> /// <param name="length">How many indexes are there?(How many uint/ushort/bytes?)</param> /// <param name="mode"></param> /// <param name="usage"></param> /// <returns></returns> public static OneIndexBuffer Create(IndexBufferElementType type, int length, DrawMode mode, BufferUsage usage) { if (glGenBuffers == null) { glGenBuffers = OpenGL.GetDelegateFor<OpenGL.glGenBuffers>(); } if (glBindBuffer == null) { glBindBuffer = OpenGL.GetDelegateFor<OpenGL.glBindBuffer>(); } if (glBufferData == null) { glBufferData = OpenGL.GetDelegateFor<OpenGL.glBufferData>(); } int byteLength = GetSize(type) * length; uint[] buffers = new uint[1]; glGenBuffers(1, buffers); const uint target = OpenGL.GL_ELEMENT_ARRAY_BUFFER; glBindBuffer(target, buffers[0]); glBufferData(target, byteLength, IntPtr.Zero, (uint)usage); glBindBuffer(target, 0); var buffer = new OneIndexBuffer( buffers[0], mode, type, length, byteLength); return buffer; }
/// <summary> /// Initializes a new instance of the OpenGLIndexBuffer. /// </summary> /// <param name="uv">The Ultraviolet context.</param> /// <param name="itype">The index element type.</param> /// <param name="icount">The index element count.</param> /// <param name="usage">The buffer's usage type.</param> public OpenGLIndexBuffer(UltravioletContext uv, IndexBufferElementType itype, Int32 icount, UInt32 usage) : base(uv, itype, icount) { Contract.EnsureRange(icount >= 0, nameof(icount)); this.usage = usage; this.size = new IntPtr(GetElementSize() * icount); var buffer = 0u; uv.QueueWorkItem(state => { using (OpenGLState.ScopedCreateElementArrayBuffer(out buffer)) { gl.NamedBufferData(buffer, gl.GL_ELEMENT_ARRAY_BUFFER, size, null, usage); gl.ThrowIfError(); } }).Wait(); this.buffer = buffer; }
/// <summary> /// /// </summary> /// <param name="indexElementType"></param> public PrimitiveRestartState(IndexBufferElementType indexElementType) : base(OpenGL.GL_PRIMITIVE_RESTART, true) { switch (indexElementType) { case IndexBufferElementType.UByte: this.RestartIndex = byte.MaxValue; break; case IndexBufferElementType.UShort: this.RestartIndex = ushort.MaxValue; break; case IndexBufferElementType.UInt: this.RestartIndex = uint.MaxValue; break; default: break; } }
/// <summary> /// /// </summary> /// <param name="indexElementType"></param> /// <param name="enableCapacity"></param> public PrimitiveRestartState(IndexBufferElementType indexElementType, bool enableCapacity = true) : base(GL.GL_PRIMITIVE_RESTART, enableCapacity) { switch (indexElementType) { case IndexBufferElementType.UByte: this.RestartIndex = byte.MaxValue; break; case IndexBufferElementType.UShort: this.RestartIndex = ushort.MaxValue; break; case IndexBufferElementType.UInt: this.RestartIndex = uint.MaxValue; break; default: throw new NotDealWithNewEnumItemException(typeof(IndexBufferElementType)); } }
/// <summary> /// 生成若干用于存储索引的IBO。索引指定了<see cref="VertexBuffer"/>里各个顶点的渲染顺序。 /// Generates some Index Buffer Objects storing vertexes' indexes, which indicate the rendering order of each vertex. /// </summary> /// <param name="array"></param> /// <param name="type"></param> /// <param name="usage"></param> /// <param name="first"></param> /// <param name="blockSize">How many elements per index buffer?(sometimes except the last one)</param> /// <returns></returns> public static IndexBuffer[] GenIndexBuffers <T>(this T[] array, IndexBufferElementType type, BufferUsage usage, int first, int blockSize) where T : struct { if (array == null) { throw new ArgumentNullException("array"); } if (first < 0) { throw new ArgumentOutOfRangeException("first"); } if (blockSize <= 0) { throw new ArgumentOutOfRangeException("count"); } if (array.Length <= first) { throw new ArgumentOutOfRangeException("first"); } GCHandle pinned = GCHandle.Alloc(array, GCHandleType.Pinned); //IntPtr header = pinned.AddrOfPinnedObject(); // same result with: IntPtr header = Marshal.UnsafeAddrOfPinnedArrayElement(array, 0); var list = new List <IndexBuffer>(); int current = first; int totalLength = array.Length; do { IntPtr header = Marshal.UnsafeAddrOfPinnedArrayElement(array, current); int length = (current + blockSize <= totalLength) ? blockSize : (totalLength - current); UnmanagedArrayBase unmanagedArray = new TempUnmanagedArray <T>(header, length);// It's not necessary to call Dispose() for this unmanaged array. IndexBuffer buffer = GenIndexBuffer(unmanagedArray, type, usage); list.Add(buffer); current += length; } while (current < totalLength); pinned.Free(); return(list.ToArray()); }
/// <summary> /// Creates a <see cref="OneIndexBuffer"/> object directly in server side(GPU) without initializing its value. /// </summary> /// <param name="array"></param> /// <param name="type"></param> /// <param name="mode"></param> /// <param name="usage"></param> /// <returns></returns> public static OneIndexBuffer GenIndexBuffer <T>(this T[] array, IndexBufferElementType type, DrawMode mode, BufferUsage usage) where T : struct { GCHandle pinned = GCHandle.Alloc(array, GCHandleType.Pinned); IntPtr header = pinned.AddrOfPinnedObject(); // same result with: IntPtr header = Marshal.UnsafeAddrOfPinnedArrayElement(array, 0); UnmanagedArrayBase unmanagedArray = new TempUnmanagedArray <T>(header, array.Length);// It's not neecessary to call Dispose() for this unmanaged array. int byteLength = unmanagedArray.ByteLength; uint[] buffers = new uint[1]; { glGenBuffers(1, buffers); const uint target = GL.GL_ELEMENT_ARRAY_BUFFER; glBindBuffer(target, buffers[0]); glBufferData(target, byteLength, unmanagedArray.Header, (uint)usage); glBindBuffer(target, 0); } pinned.Free(); var buffer = new OneIndexBuffer( buffers[0], mode, type, byteLength / type.GetSize(), byteLength); return(buffer); }
private IntPtr GetOffset(IndexBufferElementType elementType, int firstIndex) { IntPtr offset; switch (elementType) { case IndexBufferElementType.UByte: offset = new IntPtr(firstIndex * sizeof(byte)); break; case IndexBufferElementType.UShort: offset = new IntPtr(firstIndex * sizeof(ushort)); break; case IndexBufferElementType.UInt: offset = new IntPtr(firstIndex * sizeof(uint)); break; default: throw new Exception("Unexpected IndexBufferElementType!"); } return(offset); }
private IntPtr GetOffset(IndexBufferElementType elementType, int firstIndex) { IntPtr offset; switch (elementType) { case IndexBufferElementType.UByte: offset = new IntPtr(firstIndex * sizeof(byte)); break; case IndexBufferElementType.UShort: offset = new IntPtr(firstIndex * sizeof(ushort)); break; case IndexBufferElementType.UInt: offset = new IntPtr(firstIndex * sizeof(uint)); break; default: throw new NotDealWithNewEnumItemException(typeof(IndexBufferElementType)); } return(offset); }
private PrimitiveRestartState GetPrimitiveRestartState(IndexBufferElementType type) { PrimitiveRestartState result = null; switch (type) { case IndexBufferElementType.UByte: if (this.ubyteRestartIndexState == null) { this.ubyteRestartIndexState = new PrimitiveRestartState(type); } result = this.ubyteRestartIndexState; break; case IndexBufferElementType.UShort: if (this.ushortRestartIndexState == null) { this.ushortRestartIndexState = new PrimitiveRestartState(type); } result = this.ushortRestartIndexState; break; case IndexBufferElementType.UInt: if (this.uintRestartIndexState == null) { this.uintRestartIndexState = new PrimitiveRestartState(type); } result = this.uintRestartIndexState; break; default: throw new NotDealWithNewEnumItemException(typeof(IndexBufferElementType)); } return(result); }
private static int GetSize(IndexBufferElementType type) { int result = 0; switch (type) { case IndexBufferElementType.UByte: result = sizeof(byte); break; case IndexBufferElementType.UShort: result = sizeof(ushort); break; case IndexBufferElementType.UInt: result = sizeof(uint); break; default: throw new NotImplementedException(); } return(result); }
public static int GetSize(this IndexBufferElementType type) { int result = 0; switch (type) { case IndexBufferElementType.UByte: result = sizeof(byte); break; case IndexBufferElementType.UShort: result = sizeof(ushort); break; case IndexBufferElementType.UInt: result = sizeof(uint); break; default: throw new NotDealWithNewEnumItemException(typeof(IndexBufferElementType)); } return(result); }
private static int GetSize(IndexBufferElementType type) { int result = 0; switch (type) { case IndexBufferElementType.UByte: result = sizeof(byte); break; case IndexBufferElementType.UShort: result = sizeof(ushort); break; case IndexBufferElementType.UInt: result = sizeof(uint); break; default: break; } return result; }
/// <summary> /// Initializes a new instance of the <see cref="DynamicIndexBuffer"/> class. /// </summary> /// <param name="uv">The Ultraviolet context.</param> /// <param name="itype">The index element type.</param> /// <param name="icount">The index element count.</param> public DynamicIndexBuffer(UltravioletContext uv, IndexBufferElementType itype, Int32 icount) : base(uv, itype, icount) { }
/// <summary> /// Gets the OpenGL index element format that corresponds to the specified Ultraviolet index element type. /// </summary> /// <param name="type">The index element type to convert.</param> /// <param name="size">The index element size in bytes.</param> /// <returns>The converted index element format.</returns> private static UInt32 GetIndexFormatGL(IndexBufferElementType type, out Int32 size) { switch (type) { case IndexBufferElementType.Int16: size = sizeof(short); return gl.GL_UNSIGNED_SHORT; case IndexBufferElementType.Int32: size = sizeof(int); return gl.GL_UNSIGNED_INT; default: throw new NotSupportedException(OpenGLStrings.UnsupportedIndexFormat); } }
/// <inheritdoc/> public override void Attach(IndexBuffer ibuffer) { Contract.Require(ibuffer, nameof(ibuffer)); Contract.EnsureNot(HasIndices, UltravioletStrings.GeometryStreamAlreadyHasIndices); Contract.EnsureNotDisposed(this, Disposed); Ultraviolet.ValidateResource(ibuffer); var sdlIndexBuffer = (OpenGLIndexBuffer)ibuffer; var sdlIndexBufferName = sdlIndexBuffer.OpenGLName; this.ibuffer = sdlIndexBuffer; if (IsUsingVertexArrayObject) { using (OpenGLState.ScopedBindVertexArrayObject(vao, 0, 0, true)) { gl.BindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, sdlIndexBufferName); gl.ThrowIfError(); } } this.glElementArrayBufferBinding = sdlIndexBufferName; this.indexBufferElementType = ibuffer.IndexElementType; }