/// <summary> /// Generates an independent buffer. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="array"></param> /// <param name="target"></param> /// <param name="usage"></param> /// <returns></returns> private static Buffer GenIndependentBuffer <T>(this T[] array, IndependentBufferTarget target, BufferUsage usage) where T : struct { GCHandle pinned = GCHandle.Alloc(array, GCHandleType.Pinned); IntPtr header = Marshal.UnsafeAddrOfPinnedArrayElement(array, 0); UnmanagedArrayBase unmanagedArray = UnmanagedArray <T> .FromHandle(header, array.Length);// It's not neecessary to call Dispose() for this unmanaged array. Buffer buffer = GenIndependentBuffer(unmanagedArray, target, usage); pinned.Free(); return(buffer); }
/// <summary> /// 获取顶点属性Buffer。描述顶点的位置或颜色或UV等各种属性。 /// <para>每个<see cref="VertexBuffer"/>仅描述其中一个属性。</para> /// <para>Vertex Buffer Object that describes vertex' property(position, color, uv coordinate, etc.).</para> /// <para>Each <see cref="VertexBuffer"/> describes only 1 property.</para> /// </summary> /// <param name="array"></param> /// <param name="config">This <paramref name="config"/> decides parameters' values in glVertexAttribPointer(attributeLocation, size, type, false, 0, IntPtr.Zero);</param> /// <param name="varNameInVertexShader">此顶点属性VBO对应于vertex shader中的哪个in变量?<para>Mapping variable's name in vertex shader.</para></param> /// <param name="usage"></param> /// <param name="instancedDivisor">0: not instanced. 1: instanced divisor is 1.</param> /// <param name="patchVertexes">How many vertexes makes a patch? No patch if <paramref name="patchVertexes"/> is 0.</param> /// <returns></returns> public static VertexBuffer GenVertexBuffer <T>(this T[] array, VBOConfig config, string varNameInVertexShader, BufferUsage usage, uint instancedDivisor = 0, int patchVertexes = 0) where T : struct { GCHandle pinned = GCHandle.Alloc(array, GCHandleType.Pinned); IntPtr header = Marshal.UnsafeAddrOfPinnedArrayElement(array, 0); UnmanagedArrayBase unmanagedArray = UnmanagedArray <T> .FromHandle(header, array.Length);// It's not neecessary to call Dispose() for this unmanaged array. VertexBuffer buffer = GenVertexBuffer(unmanagedArray, config, varNameInVertexShader, usage, instancedDivisor, patchVertexes); pinned.Free(); return(buffer); }
/// <summary> /// Fill all or part of buffer object's data store with a fixed value. /// </summary> /// <param name="offset">The offset, in basic machine units into the buffer object's data store at which to start filling.</param> /// <param name="size">The size, in basic machine units of the range of the data store to fill.</param> /// <param name="data">Specifies a pointer to a single pixel of data to upload. This parameter may not be null.</param> /// <param name="autoBind">Automatically call glBindBuffer() inside this method.</param> /// <returns></returns> public bool ClearBufferSubData(int offset, uint size, vec3 data, bool autoBind = true) { var array = new vec3[] { data }; GCHandle pin = GCHandle.Alloc(array, GCHandleType.Pinned); IntPtr header = Marshal.UnsafeAddrOfPinnedArrayElement(array, 0); UnmanagedArrayBase unmanagedArray = UnmanagedArray <vec3> .FromHandle(header, 1); bool result = ClearBufferSubData(OpenGL.GL_RGB32F, new IntPtr(offset), size, OpenGL.GL_RGB, OpenGL.GL_FLOAT, unmanagedArray, autoBind); pin.Free(); return(result); }
/// <summary> /// 生成一个用于存储索引的VBO。索引指定了<see cref="VertexBuffer"/>里各个顶点的渲染顺序。 /// Generates a Vertex Buffer Object storing vertexes' indexes, which indicate the rendering order of each vertex. /// </summary> /// <param name="array"></param> /// <param name="mode">用哪种方式渲染各个顶点?(OpenGL.GL_TRIANGLES etc.)</param> /// <param name="usage"></param> /// <param name="primCount">primCount in instanced rendering.</param> /// <returns></returns> private static OneIndexBuffer GenIndexBuffer <T>(this T[] array, DrawMode mode, BufferUsage usage, int primCount = 1) where T : struct { IndexBufferElementType elementType; if (typeof(T) == typeof(uint)) { elementType = IndexBufferElementType.UInt; } else if (typeof(T) == typeof(ushort)) { elementType = IndexBufferElementType.UShort; } else if (typeof(T) == typeof(byte)) { elementType = IndexBufferElementType.UByte; } else { throw new ArgumentException(string.Format("Only uint/ushort/byte are allowed!")); } if (glGenBuffers == null) { InitFunctions(); } GCHandle pinned = GCHandle.Alloc(array, GCHandleType.Pinned); IntPtr header = Marshal.UnsafeAddrOfPinnedArrayElement(array, 0); UnmanagedArrayBase unmanagedArray = UnmanagedArray <T> .FromHandle(header, array.Length);// It's not neecessary to call Dispose() for this unmanaged array. var buffers = new uint[1]; { glGenBuffers(1, buffers); const uint target = OpenGL.GL_ELEMENT_ARRAY_BUFFER; glBindBuffer(target, buffers[0]); glBufferData(target, unmanagedArray.ByteLength, unmanagedArray.Header, (uint)usage); glBindBuffer(target, 0); } pinned.Free(); var buffer = new OneIndexBuffer(buffers[0], mode, elementType, unmanagedArray.Length, unmanagedArray.ByteLength, primCount); return(buffer); }