Example #1
0
        /// <summary>
        /// Reuse a previously allocated SpriteBatchItem from the item pool.
        /// if there is none available grow the pool and initialize new items.
        /// </summary>
        public NeoBatchItem CreateBatchItem()
        {
            if (_batchItemCount >= _batchItemList.Length)
            {
                var oldSize = _batchItemList.Length;
                var newSize = oldSize + oldSize / 2;              // grow by x1.5
                newSize = (newSize + 63) & (~63);                 // grow in chunks of 64.
                Array.Resize(ref _batchItemList, newSize);
                for (int i = oldSize; i < newSize; i++)
                {
                    _batchItemList[i] = new NeoBatchItem();
                }

                EnsureArrayCapacity(Math.Min(newSize, MaxBatchSize));
            }
            var item = _batchItemList[_batchItemCount++];

            return(item);
        }
Example #2
0
        public void DrawGlyph(Texture2D atlas, Rectangle destinationRectangle, float left, float bottom, float right, float top, Color color)
        {
            var ntop    = atlas.Height - top;
            var nbottom = atlas.Height - bottom;

            NeoBatchItem item = _batcher.CreateBatchItem();

            item.Texture = atlas;

            _texCoordTL.X = left * (1f / (float)atlas.Width);
            _texCoordTL.Y = ntop * (1f / (float)atlas.Height);
            _texCoordBR.X = right * (1f / (float)atlas.Width);
            _texCoordBR.Y = nbottom * (1f / (float)atlas.Height);

            item.Set(destinationRectangle.X,
                     destinationRectangle.Y,
                     destinationRectangle.Width,
                     destinationRectangle.Height,
                     color,
                     _texCoordTL,
                     _texCoordBR);
            item.Type = NeoBatchItem.ItemType.Glyph;
        }
Example #3
0
        public NeoBatcher(GraphicsDevice device, Effect effect, int capacity = 0)
        {
            _device = device;
            _effect = effect;

            if (capacity <= 0)
            {
                capacity = InitialBatchSize;
            }
            else
            {
                capacity = (capacity + 63) & (~63);                 // ensure chunks of 64.
            }
            _batchItemList  = new NeoBatchItem[capacity];
            _batchItemCount = 0;

            for (int i = 0; i < capacity; i++)
            {
                _batchItemList[i] = new NeoBatchItem();
            }

            EnsureArrayCapacity(capacity);
        }
Example #4
0
        /// <summary>
        /// Sorts the batch items and then groups batch drawing into maximal allowed batch sets that do not
        /// overflow the 16 bit array indices for vertices.
        /// </summary>
        public unsafe void DrawBatch()
        {
            // Determine how many iterations through the drawing code we need to make
            int batchIndex = 0;
            int batchCount = _batchItemCount;

            // Iterate through the batches, doing short.MaxValue sets of vertices only.
            while (batchCount > 0)
            {
                // setup the vertexArray array
                var       startIndex = 0;
                var       index      = 0;
                Texture2D tex        = null;

                int numBatchesToProcess = batchCount;
                if (numBatchesToProcess > MaxBatchSize)
                {
                    numBatchesToProcess = MaxBatchSize;
                }
                NeoBatchItem.ItemType lastType;
                // Avoid the array checking overhead by using pointer indexing!
                fixed(BlockVertex *vertexArrayFixedPtr = _vertexArray)
                {
                    var vertexArrayPtr = vertexArrayFixedPtr;


                    if (_batchItemList[0] != null)
                    {
                        lastType = _batchItemList[0].Type;
                    }
                    else
                    {
                        lastType = NeoBatchItem.ItemType.Texture;
                    }

                    // Draw the batches
                    for (int i = 0; i < numBatchesToProcess; i++, batchIndex++, index += 4, vertexArrayPtr += 4)
                    {
                        NeoBatchItem item = _batchItemList[batchIndex];
                        // if the texture changed, we need to flush and bind the new texture
                        var shouldFlush = !(ReferenceEquals(item.Texture, tex) && (lastType == item.Type));
                        if (shouldFlush)
                        {
                            FlushVertexArray(startIndex, index, tex, lastType);

                            tex                 = item.Texture;
                            startIndex          = index = 0;
                            vertexArrayPtr      = vertexArrayFixedPtr;
                            _device.Textures[0] = tex;
                        }

                        // store the SpriteBatchItem data in our vertexArray
                        *(vertexArrayPtr + 0) = item.vertexTL;
                        *(vertexArrayPtr + 1) = item.vertexTR;
                        *(vertexArrayPtr + 2) = item.vertexBL;
                        *(vertexArrayPtr + 3) = item.vertexBR;

                        // Release the texture.
                        item.Texture = null;
                        lastType     = item.Type;
                    }
                }

                // flush the remaining vertexArray data
                FlushVertexArray(startIndex, index, tex, lastType);
                // Update our batch count to continue the process of culling down
                // large batches
                batchCount -= numBatchesToProcess;
            }
            // return items to the pool.
            _batchItemCount = 0;
        }