예제 #1
0
 /// <summary>
 /// Virtual Unbind implementation.
 /// </summary>
 /// <param name="ctx">
 /// A <see cref="GraphicsContext"/> used for binding.
 /// </param>
 protected virtual void UnbindCore(GraphicsContext ctx)
 {
     if (ctx.Caps.GlExtensions.VertexBufferObject_ARB)
     {
         Gl.BindBuffer(BufferType, InvalidObjectName);
     }
 }
예제 #2
0
        public void BindAttributes(ShaderProgram program)
        {
            GenericVBO elementArray = new GenericVBO(0, "", 0, 0, VertexAttribPointerType.Byte, BufferTarget.ArrayBuffer);

            for (int i = 0; i < vbos.Length; i++)
            {
                if (vbos[i].bufferTarget == BufferTarget.ElementArrayBuffer)
                {
                    elementArray = vbos[i];
                    continue;
                }

                int loc = Gl.GetAttribLocation(program.ProgramID, vbos[i].name);
                if (loc == -1)
                {
                    throw new Exception(string.Format("Shader did not contain '{0}'.", vbos[i].name));
                }

                Gl.EnableVertexAttribArray((uint)loc);
                Gl.BindBuffer(vbos[i].bufferTarget, vbos[i].vboID);
                Gl.VertexAttribPointer((uint)loc, vbos[i].size, vbos[i].pointerType, true, vbos[i].size * SizeOfType(vbos[i].pointerType), IntPtr.Zero);
            }

            if (elementArray.vboID != 0)
            {
                Gl.BindBuffer(BufferTarget.ElementArrayBuffer, elementArray.vboID);
                VertexCount = elementArray.length;
            }
        }
예제 #3
0
        /// <summary>
        /// Generic method for binding the VBOs to their respective attribute locations.
        /// OpenGL.dll assumes the common naming conventions below:
        ///     vertices: vec3 in_position
        ///     normals: vec3 in_normal
        ///     uv: vec2 in_uv
        ///     tangent: vec3 in_tangent
        /// </summary>
        public void BindAttributes(ShaderProgram program)
        {
            if (vertex == null || vertex.vboID == 0)
            {
                throw new Exception("Error binding attributes.  No vertices were supplied.");
            }
            if (element == null || element.vboID == 0)
            {
                throw new Exception("Error binding attributes.  No element array was supplied.");
            }

            // Note:  Since the shader is already compiled, we cannot set the attribute locations.
            //  Instead we must query the shader for the locations that the linker chose and use them.
            int loc = Gl.GetAttribLocation(program.ProgramID, "in_position");

            if (loc == -1)
            {
                throw new Exception("Shader did not contain 'in_position'.");
            }

            Gl.EnableVertexAttribArray((uint)loc);
            Gl.BindBuffer(vertex.BufferTarget, vertex.vboID);
            Gl.VertexAttribPointer((uint)loc, vertex.Size, vertex.PointerType, true, 12, IntPtr.Zero);

            if (normal != null && normal.vboID != 0)
            {
                loc = Gl.GetAttribLocation(program.ProgramID, "in_normal");
                if (loc != -1)
                {
                    Gl.EnableVertexAttribArray((uint)loc);
                    Gl.BindBuffer(normal.BufferTarget, normal.vboID);
                    Gl.VertexAttribPointer((uint)loc, normal.Size, normal.PointerType, true, 12, IntPtr.Zero);
                }
            }

            if (uv != null && uv.vboID != 0)
            {
                loc = Gl.GetAttribLocation(program.ProgramID, "in_uv");
                if (loc != -1)
                {
                    Gl.EnableVertexAttribArray((uint)loc);
                    Gl.BindBuffer(uv.BufferTarget, uv.vboID);
                    Gl.VertexAttribPointer((uint)loc, uv.Size, uv.PointerType, true, 8, IntPtr.Zero);
                }
            }

            if (tangent != null && tangent.vboID != 0)
            {
                loc = Gl.GetAttribLocation(program.ProgramID, "in_tangent");
                if (loc != -1)
                {
                    Gl.EnableVertexAttribArray((uint)loc);
                    Gl.BindBuffer(tangent.BufferTarget, tangent.vboID);
                    Gl.VertexAttribPointer((uint)loc, tangent.Size, tangent.PointerType, true, 12, IntPtr.Zero);
                }
            }

            Gl.BindBuffer(BufferTarget.ElementArrayBuffer, element.vboID);
        }
예제 #4
0
 /// <summary>
 /// Virtual Bind implementation.
 /// </summary>
 /// <param name="ctx">
 /// A <see cref="GraphicsContext"/> used for binding.
 /// </param>
 protected virtual void BindCore(GraphicsContext ctx)
 {
     if (ctx.Caps.GlExtensions.VertexBufferObject_ARB)
     {
         CheckThisExistence(ctx);
         Gl.BindBuffer(BufferType, ObjectName);
     }
 }
예제 #5
0
        /// <summary>
        /// Binds a VBO to a shader attribute.
        /// </summary>
        /// <param name="buffer">The VBO to bind to the shader attribute.</param>
        /// <param name="program">The shader program whose attribute will be bound to.</param>
        /// <param name="attributeName">The name of the shader attribute to be bound to.</param>
        public static void BindBufferToShaderAttribute <T>(VBO <T> buffer, ShaderProgram program, string attributeName)
            where T : struct
        {
            uint location = (uint)Gl.GetAttribLocation(program.ProgramID, attributeName);

            Gl.EnableVertexAttribArray(location);
            Gl.BindBuffer(buffer);
            Gl.VertexAttribPointer(location, buffer.Size, buffer.PointerType, true, Marshal.SizeOf(typeof(T)), IntPtr.Zero);
        }
예제 #6
0
        /// <summary>
        /// Unbind this BufferObject.
        /// </summary>
        /// <param name="ctx">
        /// The <see cref="GraphicsContext"/> used for unbinding any BufferObject.
        /// </param>
        internal virtual void Unbind(GraphicsContext ctx)
        {
            CheckCurrentContext(ctx);

            if (ctx.Caps.GlExtensions.VertexBufferObject_ARB)
            {
                Gl.BindBuffer(BufferType, InvalidObjectName);
            }
        }
예제 #7
0
        /// <summary>
        /// Creates a standard VBO of type T where the length of the VBO is less than or equal to the length of the data.
        /// </summary>
        /// <typeparam name="T">The type of the data being stored in the VBO (make sure it's byte aligned).</typeparam>
        /// <param name="target">The VBO BufferTarget (usually ArrayBuffer or ElementArrayBuffer).</param>
        /// <param name="data">The data to store in the VBO.</param>
        /// <param name="hint">The buffer usage hint (usually StaticDraw).</param>
        /// <param name="length">The length of the VBO (will take the first 'length' elements from data).</param>
        /// <returns>The buffer ID of the VBO on success, 0 on failure.</returns>
        public static uint CreateVBO <T>(BufferTarget target, [InAttribute, OutAttribute] T[] data, BufferUsageHint hint, int position, int length)
            where T : struct
        {
            uint vboHandle = Gl.GenBuffer();

            if (vboHandle == 0)
            {
                return(0);
            }

            Gl.BindBuffer(target, vboHandle);
            Gl.BufferData <T>(target, position * Marshal.SizeOf(typeof(T)), length * Marshal.SizeOf(typeof(T)), data, hint);
            Gl.BindBuffer(target, 0);
            return(vboHandle);
        }
예제 #8
0
        /// <summary>
        /// Updates a subset of the buffer object's data store.
        /// </summary>
        /// <typeparam name="T">The type of data in the data array.</typeparam>
        /// <param name="vboID">The VBO whose buffer will be updated.</param>
        /// <param name="target">Specifies the target buffer object.  Must be ArrayBuffer, ElementArrayBuffer, PixelPackBuffer or PixelUnpackBuffer.</param>
        /// <param name="data">The new data that will be copied to the data store.</param>
        /// <param name="length">The size in bytes of the data store region being replaced.</param>
        public static void BufferSubData <T>(uint vboID, BufferTarget target, T[] data, int length)
            where T : struct
        {
            GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);

            try
            {
                Gl.BindBuffer(target, vboID);
                Gl.BufferSubData(target, IntPtr.Zero, (IntPtr)(Marshal.SizeOf(data[0]) * length), handle.AddrOfPinnedObject());
            }
            finally
            {
                handle.Free();
            }
        }
예제 #9
0
        /// <summary>
        /// Creates a standard VBO of type T where the length of the VBO is less than or equal to the length of the data.
        /// </summary>
        /// <typeparam name="T">The type of the data being stored in the VBO (make sure it's byte aligned).</typeparam>
        /// <param name="target">The VBO BufferTarget (usually ArrayBuffer or ElementArrayBuffer).</param>
        /// <param name="data">The data to store in the VBO.</param>
        /// <param name="hint">The buffer usage hint (usually StaticDraw).</param>
        /// <param name="length">The length of the VBO (will take the first 'length' elements from data).</param>
        /// <returns>The buffer ID of the VBO on success, 0 on failure.</returns>
        public static uint CreateVBO<T>(BufferTarget target, [In, Out] T[] data, BufferUsageHint hint, int length)
            where T : struct
        {
            uint vboHandle = Gl.GenBuffer();
            if (vboHandle == 0) return 0;

            int size = length * Marshal.SizeOf(typeof(T));

            #if MEMORY_LOGGER
            MemoryLogger.AllocateVBO(vboHandle, size);
            #endif

            Gl.BindBuffer(target, vboHandle);
            Gl.BufferData<T>(target, size, data, hint);
            Gl.BindBuffer(target, 0);
            return vboHandle;
        }
예제 #10
0
        /// <summary>
        /// Updates a subset of the buffer object's data store.
        /// </summary>
        /// <param name="data">The new data that will be copied to the data store.</param>
        /// <param name="size">The size in bytes of the data store region being replaced.</param>
        /// <param name="offset">The offset in bytes into the buffer object's data store where data replacement will begin.</param>
        public void BufferSubData(T[] data, int size, int offset)
        {
            if (BufferTarget != OpenGL.BufferTarget.ArrayBuffer && BufferTarget != OpenGL.BufferTarget.ElementArrayBuffer &&
                BufferTarget != OpenGL.BufferTarget.PixelPackBuffer && BufferTarget != OpenGL.BufferTarget.PixelUnpackBuffer)
            {
                throw new InvalidOperationException(string.Format("BufferSubData cannot be called with a BufferTarget of type {0}", BufferTarget.ToString()));
            }

            GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);

            try
            {
                Gl.BindBuffer(this);
                Gl.BufferSubData(BufferTarget, (IntPtr)offset, (IntPtr)size, handle.AddrOfPinnedObject());
            }
            finally
            {
                handle.Free();
            }
        }
예제 #11
0
        /// <summary>
        /// Creates a vertex array object based on a series of attribute arrays and and attribute names.
        /// </summary>
        /// <param name="program">The shader program that contains the attributes to be bound to.</param>
        /// <param name="vbo">The VBO containing all of the attribute data.</param>
        /// <param name="sizes">An array of sizes which correspond to the size of each attribute.</param>
        /// <param name="types">An array of the attribute pointer types.</param>
        /// <param name="targets">An array of the buffer targets.</param>
        /// <param name="names">An array of the attribute names.</param>
        /// <param name="stride">The stride of the VBO.</param>
        /// <param name="eboHandle">The element buffer handle.</param>
        /// <returns>The vertex array object (VAO) ID.</returns>
        public static uint CreateVAO(ShaderProgram program, uint vbo, int[] sizes, VertexAttribPointerType[] types, BufferTarget[] targets, string[] names, int stride, uint eboHandle)
        {
            uint vaoHandle = Gl.GenVertexArray();
            Gl.BindVertexArray(vaoHandle);

            int offset = 0;

            for (uint i = 0; i < names.Length; i++)
            {
                Gl.EnableVertexAttribArray(i);
                Gl.BindBuffer(targets[i], vbo);
                Gl.VertexAttribPointer(i, sizes[i], types[i], true, stride, new IntPtr(offset));
                Gl.BindAttribLocation(program.ProgramID, i, names[i]);
            }

            Gl.BindBuffer(BufferTarget.ElementArrayBuffer, eboHandle);
            Gl.BindVertexArray(0);

            return vaoHandle;
        }
예제 #12
0
        /// <summary>
        /// Creates a standard VBO of type T where the length of the VBO is less than or equal to the length of the data.
        /// </summary>
        /// <typeparam name="T">The type of the data being stored in the VBO (make sure it's byte aligned).</typeparam>
        /// <param name="target">The VBO BufferTarget (usually ArrayBuffer or ElementArrayBuffer).</param>
        /// <param name="data">The data to store in the VBO.</param>
        /// <param name="hint">The buffer usage hint (usually StaticDraw).</param>
        /// <param name="length">The length of the VBO (will take the first 'length' elements from data).</param>
        /// <returns>The buffer ID of the VBO on success, 0 on failure.</returns>
        public static uint CreateVBO <T>(BufferTarget target, [InAttribute, OutAttribute] T[] data, BufferUsageHint hint, int position, int length)
            where T : struct
        {
            uint vboHandle = Gl.GenBuffer();

            if (vboHandle == 0)
            {
                return(0);
            }

            int offset = position * Marshal.SizeOf(typeof(T));
            int size   = length * Marshal.SizeOf(typeof(T));

#if MEMORY_LOGGER
            MemoryLogger.AllocateVBO(vboHandle, size - offset);
#endif

            Gl.BindBuffer(target, vboHandle);
            Gl.BufferData <T>(target, offset, size, data, hint);
            Gl.BindBuffer(target, 0);
            return(vboHandle);
        }
예제 #13
0
 /// <summary>
 /// Binds a VBO based on the buffer target.
 /// </summary>
 /// <param name="buffer">The VBO to bind.</param>
 public static void BindBuffer <T>(VBO <T> buffer)
     where T : struct
 {
     Gl.BindBuffer(buffer.BufferTarget, buffer.vboID);
 }
예제 #14
0
        public void BindAttributes(ShaderProgram program)
        {
            IGenericVBO elementArray = null;

            for (int i = 0; i < vbos.Length; i++)
            {
                if (vbos[i].BufferTarget == BufferTarget.ElementArrayBuffer)
                {
                    elementArray = vbos[i];

                    // To not break compatibility with previous versions of this call,
                    // int is allowed as an element type even though the specs don't allow it.
                    // All cases where int is used as the default element type have been marked obsolete
                    // but until it's completely removed, this will serve to support that use case.
                    if (allowIntAsElementType && vbos[i].PointerType == VertexAttribPointerType.Int)
                    {
                        elementType = DrawElementsType.UnsignedInt;
                    }
                    else
                    {
                        // Check if the element array can be used as an indice buffer.
                        if (!ValidElementTypes.ContainsKey(vbos[i].PointerType))
                        {
                            throw new Exception($"The element buffer must be an unsigned integral type. See {nameof(DrawElementsType)} enum for valid types.");
                        }
                        elementType = ValidElementTypes[vbos[i].PointerType];
                    }
                    continue;
                }

                // According to OGL spec then, if there is no location for an attribute, -1 is returned.
                // The same error representation is used here.
                int loc = program[vbos[i].Name]?.Location ?? -1;
                if (loc == -1)
                {
                    throw new Exception(string.Format("Shader did not contain '{0}'.", vbos[i].Name));
                }

                Gl.EnableVertexAttribArray((uint)loc);
                Gl.BindBuffer(vbos[i].BufferTarget, vbos[i].ID);

                if (vbos[i].CastToFloat)
                {
                    Gl.VertexAttribPointer((uint)loc, vbos[i].Size, vbos[i].PointerType, vbos[i].Normalize, 0, IntPtr.Zero);
                }
                else if (vbos[i].IsIntegralType)
                {
                    Gl.VertexAttribIPointer((uint)loc, vbos[i].Size, vbos[i].PointerType, 0, IntPtr.Zero);
                }
                else if (vbos[i].PointerType == VertexAttribPointerType.Double)
                {
                    Gl.VertexAttribLPointer((uint)loc, vbos[i].Size, vbos[i].PointerType, 0, IntPtr.Zero);
                }
                else
                {
                    throw new Exception("VBO shouldn't be cast to float, isn't an integral type and is not a float. No vertex attribute support this combination.");
                }

                // 0 is the divisors default value.
                // No need to set the divisor to its default value.
                if (vbos[i].Divisor != 0)
                {
                    Gl.VertexAttribDivisor((uint)loc, vbos[i].Divisor);
                }
            }

            if (elementArray != null)
            {
                Gl.BindBuffer(BufferTarget.ElementArrayBuffer, elementArray.ID);
                VertexCount = elementArray.Length;
            }
        }