Esempio n. 1
0
        /// <summary>
        /// Creates a <see cref="VertexAttribDescription"/> where the format of the data declared
        /// in the shader isn't the same as the format the data will be read as.
        /// </summary>
        /// <param name="attribType">The type of the attribute declared in the shader.</param>
        /// <param name="normalized">Whether the vertex data should be normalized before being loaded into the shader.</param>
        /// <param name="dataBaseType">The base type in which the data will be read from the buffer.</param>
        /// <param name="attribDivisor">The divisor that defines how reading this attribute advances on instanced rendering.</param>
        public VertexAttribDescription(AttributeType attribType, bool normalized, AttributeBaseType dataBaseType, uint attribDivisor = 0)
        {
            ValidateAttribDivisor(attribDivisor);

            if (normalized)
            {
                if (!TrippyUtils.IsVertexAttribIntegerType(dataBaseType))
                {
                    throw new ArgumentException("For normalized vertex attributes, the dataBaseType must be an integer", nameof(dataBaseType));
                }

                if (!(TrippyUtils.IsVertexAttribFloatType(attribType) || TrippyUtils.IsVertexAttribDoubleType(attribType)))
                {
                    throw new ArgumentException("For normalized vertex attributes, the attribType must be a float or a double", nameof(attribType));
                }
            }

            Normalized            = normalized;
            AttribDivisor         = attribDivisor;
            AttribBaseType        = dataBaseType;
            AttribType            = attribType;
            Size                  = TrippyUtils.GetVertexAttribTypeSize(attribType);
            AttribIndicesUseCount = TrippyUtils.GetVertexAttribTypeIndexCount(attribType);
            SizeInBytes           = TrippyUtils.GetVertexAttribSizeInBytes(dataBaseType) * (uint)Size * AttribIndicesUseCount;
        }
Esempio n. 2
0
        /// <summary>
        /// Gets the size in bytes of the given <see cref="AttributeBaseType"/>.
        /// </summary>
        public static uint GetVertexAttribSizeInBytes(AttributeBaseType type)
        {
            switch (type)
            {
            case AttributeBaseType.Byte:
            case AttributeBaseType.UnsignedByte:
                return(1);

            case AttributeBaseType.Short:
            case AttributeBaseType.UnsignedShort:
            case AttributeBaseType.HalfFloat:
                return(2);

            case AttributeBaseType.Float:
            case AttributeBaseType.Int:
            case AttributeBaseType.UnsignedInt:
            case AttributeBaseType.Fixed:
                return(4);

            case AttributeBaseType.Double:
                return(8);

            default:
                throw new NotSupportedException(string.Concat("Cannot get size for " + nameof(AttributeBaseType) + ":", type.ToString()));
            }
        }
Esempio n. 3
0
 public AttributeDefinition(string name, AttributeBaseType baseType, int dimensions)
 {
     this.name = name;
     type      = new AttributeType {
         baseType = baseType, dimensions = dimensions
     };
     defaultValue = NullValue();
 }
Esempio n. 4
0
        /// <summary>
        /// Creates a <see cref="VertexAttribDescription"/> that represents no real attributes and is
        /// used to indicate padding (unused, ignored buffer memory in between other vertex attribs).
        /// </summary>
        /// <param name="paddingBytes">The amount of padding in bytes.</param>
        public VertexAttribDescription(uint paddingBytes)
        {
            if (paddingBytes <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(paddingBytes), paddingBytes, nameof(paddingBytes) + " must be greater than 0");
            }

            Size                  = 0;
            AttribBaseType        = 0;
            SizeInBytes           = paddingBytes; // The only non-zero field when a VertexAttribDescription is used for padding, stores the padding in bytes
            Normalized            = false;
            AttribIndicesUseCount = 0;            // We'll use this value to be the one that decides whether this is padding. If it uses 0 indices, it's padding.
            AttribType            = default;
            AttribDivisor         = 0;
        }
Esempio n. 5
0
 public AttributeDefinition AddFaceAttribute(string name, AttributeBaseType baseType, int dimensions)
 {
     return(AddFaceAttribute(new AttributeDefinition(name, baseType, dimensions)));
 }
Esempio n. 6
0
 /// <summary>
 /// Creates a <see cref="VertexAttribSource"/> with a given <see cref="BufferObjectSubset"/> and specifies
 /// a vertex attribute where the data format in the shader and the buffer don't match and need conversion.
 /// </summary>
 /// <param name="bufferSubset">The <see cref="BufferObjectSubset"/> where the vertex attrib data is located. Must be a subset usable for vertex data.</param>
 /// <param name="attribType">The type of attribute declared in the shader.</param>
 /// <param name="normalized">Whether the data needs to be normalized (uint/ushort/byte -> float between 0 and 1, or int/short/sbyte -> float between -1 and 1).</param>
 /// <param name="dataBaseType">The base type of the data found on the buffer. If normalized is true, this must be an integer type.</param>
 /// <param name="attribDivisor">The divisor that defines how reading this attribute advances on instanced rendering.</param>
 public VertexAttribSource(DataBufferSubset bufferSubset, AttributeType attribType, bool normalized, AttributeBaseType dataBaseType, uint attribDivisor = 0)
     : this(bufferSubset, new VertexAttribDescription(attribType, normalized, dataBaseType, attribDivisor))
 {
 }
Esempio n. 7
0
 /// <summary>
 /// Creates a <see cref="VertexAttribSource"/> that specifies padding for an
 /// amount of bytes calculated based on the baseType and size parameters.
 /// </summary>
 /// <param name="bufferSubset">The buffer subset in which the padding will be applied.</param>
 /// <param name="baseType">The base type of the attribute.</param>
 /// <param name="size">The size of the attribute.</param>
 public static VertexAttribSource CreatePadding(DataBufferSubset bufferSubset, AttributeBaseType baseType, uint size)
 {
     return(new VertexAttribSource(bufferSubset, VertexAttribDescription.CreatePadding(baseType, size)));
 }
Esempio n. 8
0
 /// <summary>
 /// Creates a <see cref="VertexAttribDescription"/> that specifies padding for an
 /// amount of bytes calculated based on the baseType and size parameters.
 /// </summary>
 /// <remarks>
 /// Padding indicators ignore padding based on type that occurs when using compensation
 /// for struct padding (which is the default behavior in <see cref="VertexArray"/>).
 /// </remarks>
 public static VertexAttribDescription CreatePadding(AttributeBaseType baseType, uint size)
 {
     return(new VertexAttribDescription(TrippyUtils.GetVertexAttribSizeInBytes(baseType) * size));
 }
Esempio n. 9
0
        /// <summary>
        /// Updates the places where vertex data is read from for this <see cref="VertexArray"/>.
        /// Call this whenever you modify a buffer subset used by this <see cref="VertexArray"/>.
        /// </summary>
        /// <param name="compensateStructPadding">Whether to compensate for struct padding. Default is true.</param>
        /// <param name="paddingPackValue">The struct packing value for compensating for padding. Default is 4.</param>
        public void UpdateVertexAttributes(bool compensateStructPadding = true, uint paddingPackValue = 4)
        {
            // Makes all glVertexAttribPointer calls to specify the vertex attrib data on the VAO and enables the vertex attributes.
            // The parameters of glVertexAttribPointer are calculated based on the VertexAttribSource-s from AttribSources

            GraphicsDevice.VertexArray = this;

            AttribCallDesc[] calls = new AttribCallDesc[attribSources.Length];

            uint attribIndex = 0;

            for (int i = 0; i < calls.Length; i++)
            {
                calls[i] = new AttribCallDesc
                {
                    source        = attribSources[i],
                    index         = attribIndex,
                    originalIndex = i
                };
                attribIndex += calls[i].source.AttribDescription.AttribIndicesUseCount;
            }

            // Sort by buffer object, so all sources that share BufferObject are grouped together.
            // This facilitates calculating the offset values, since we only need to work with one offset at a time
            // rather than save the offset of each buffer simultaneously.
            Array.Sort(calls);
            // The calls array is now sorted. First by buffer handle, secondly by attrib index
            // and lastly, if two items have the same buffer handle and attrib index, they are sorted
            // by the original index they had in the calls array.
            // This logic is implemented in AttribCallDesc.CompareTo()

            if (compensateStructPadding)
            {
                #region CalculateOffsetsWithPadding
                uint offset = 0;
                BufferObjectSubset prevSubset      = null; // Setting this to null ensures the first for loop will enter the "different subset" if and initialize these variables
                AttributeBaseType  currentBaseType = 0;

                for (int i = 0; i < calls.Length; i++)
                {
                    if (calls[i].source.BufferSubset != prevSubset)
                    {
                        // it's a different buffer subset, so let's calculate the padding values as for a new, different struct
                        offset          = 0;
                        prevSubset      = calls[i].source.BufferSubset;
                        currentBaseType = calls[i].source.AttribDescription.AttribBaseType;
                        calls[i].offset = 0;
                    }
                    else if (currentBaseType != calls[i].source.AttribDescription.AttribBaseType)
                    {
                        // the base type has changed, let's ensure padding is applied to offset
                        currentBaseType = calls[i].source.AttribDescription.AttribBaseType;
                        if (!calls[i].source.IsPadding)
                        {                                                                                                       // We add the manual padding, unless it is padding added specifically by the user
                            uint packval = Math.Min(TrippyUtils.GetVertexAttribSizeInBytes(currentBaseType), paddingPackValue); // offset should be aligned by the default packing value or the size of the base type
                            offset = (offset + packval - 1) / packval * packval;                                                // Make offset be greater or equal to offset and divisible by packval
                        }
                    }

                    calls[i].offset = offset;
                    offset         += calls[i].source.AttribDescription.SizeInBytes;
                }
                #endregion
            }
            else
            {
                #region CalculateOffsetsWithoutPadding
                uint offset           = 0;
                uint prevBufferHandle = 0;
                for (int i = 0; i < calls.Length; i++)
                {
                    if (prevBufferHandle != calls[i].source.BufferSubset.BufferHandle)
                    {
                        prevBufferHandle = calls[i].source.BufferSubset.BufferHandle;
                        offset           = 0;
                    }

                    calls[i].offset = offset;
                    offset         += calls[i].source.AttribDescription.SizeInBytes;
                }
                #endregion
            }

            for (int i = 0; i < calls.Length; i++)
            {
                calls[i].CallGlVertexAttribPointer(GL);
            }

            GL.BindBuffer(BufferTargetARB.ElementArrayBuffer, IndexBuffer == null ? 0 : IndexBuffer.BufferHandle);
        }
Esempio n. 10
0
 /// <summary>
 /// Gets the corresponding variables for the given <see cref="AttributeType"/>.
 /// </summary>
 /// <param name="attribType">The <see cref="AttributeType"/> type to get variables for.</param>
 /// <param name="indexUseCount">The amount of attribute indices it will need.</param>
 /// <param name="size">The amount of components each index will have.</param>
 /// <param name="type">The base type of each component.</param>
 public static void GetVertexAttribTypeData(AttributeType attribType, out uint indexUseCount, out int size, out AttributeBaseType type)
 {
     indexUseCount = GetVertexAttribTypeIndexCount(attribType);
     size          = GetVertexAttribTypeSize(attribType);
     type          = GetVertexAttribBaseType(attribType);
 }
Esempio n. 11
0
 /// <summary>
 /// Returns whether the given <see cref="AttributeBaseType"/> is of integer format (such as byte, ushort, int, uint).
 /// </summary>
 public static bool IsVertexAttribIntegerType(AttributeBaseType dataBaseType)
 {
     return(dataBaseType >= AttributeBaseType.Byte && dataBaseType <= AttributeBaseType.UnsignedInt);
     // accepted: Byte, UnsignedByte, Short, UnsignedShort, Int, UnsignedInt
 }