Example #1
0
        public Order addRectangle(ref int z, ref Rect rectangle, float?width)
        {
            Order result = new Order(-1 - rectCommands.length, z);

            z++;

            var cmd = new sDrawRectCommand()
            {
                rect = rectangle, strokeWidth = width
            };

            rectCommands.add(ref cmd);
            return(result);
        }
Example #2
0
        void layoutBuffers(Span <sDrawCall> drawCallsSpan)
        {
            buffersLayout.clear();

            for (int i = 0; i < drawCallsSpan.Length; i++)
            {
                ref var dc = ref drawCallsSpan[i];
                int     sn = dc.order.sn;

                if (sn >= 0)
                {
                    buffersLayout.addMesh(i, drawMeshes.meshes[sn].mesh.meshInfo);
                    continue;
                }
                sn = -sn - 1;

                if (dc.drawCall.mesh == eMesh.SpriteRectangle)
                {
                    sMeshDataSize mds = new sMeshDataSize(SpriteMesh.countVertices, SpriteMesh.countTriangles);
                    buffersLayout.addTransparent(i, ref mds);
                    continue;
                }

                if (dc.drawCall.isText)
                {
                    // Glyph runs can be either opaque or transparent, depending on text background
                    sMeshDataSize mds = drawMeshes.textCommands[sn].meshDataSize;
                    buffersLayout.addTransparent(i, ref mds);
                    continue;
                }

                sDrawRectCommand cmd = drawMeshes.rectCommands[sn];
                sMeshDataSize    size;
                if (cmd.strokeWidth.HasValue)
                {
                    size = RectangleMesh.sizeStroked;
                }
                else
                {
                    size = RectangleMesh.sizeFilled;
                }
                buffersLayout.addOpaque(i, ref size);
            }
        void uploadVertices(IDeviceContext ic, Span <sDrawCall> drawCallsSpan)
        {
            ReadOnlySpan <int> baseVertices = buffersLayout.baseVertices;

            using (var mapped = resources.getVertexBuffer().map <sVertexWithId>(ic, buffersLayout.vertexBufferSize))
            {
                Span <sVertexWithId> span = mapped.span;

                for (int i = 0; i < drawCallsSpan.Length; i++)
                {
                    int bv = baseVertices[i];
                    if (bv < 0)
                    {
                        continue;                           // Empty draw call, i.e. completely clipped out
                    }
                    Span <sVertexWithId> dest = span.Slice(bv);

                    ref var dc = ref drawCallsSpan[i];
                    uint    id = VertexID.vertex(i);
                    int     sn = dc.order.sn;
                    if (sn >= 0)
                    {
                        drawMeshes.meshes[sn].mesh.mesh.copyVertices(dest, id);
                        continue;
                    }
                    sn = -sn - 1;

                    if (dc.drawCall.mesh == eMesh.SpriteRectangle)
                    {
                        Rect rc = drawMeshes.spriteCommands[sn].rect;
                        SpriteMesh.writeVertices(dest, ref rc, id);
                        continue;
                    }

                    if (dc.drawCall.isText)
                    {
                        var           text = drawMeshes.textCommands[sn];
                        sMeshDataSize mds;
                        if (text.consoleWidth.HasValue)
                        {
                            mds = text.font.renderConsole(dest, id, text.text, text.rectangle.topLeft, text.textRendering, text.consoleWidth.Value);
                        }
                        else
                        {
                            mds = text.font.renderBlock(dest, id, text.text, ref text.rectangle, text.textRendering);
                        }

                        Debug.Assert(mds.vertices <= text.meshDataSize.vertices && mds.triangles <= text.meshDataSize.triangles);
                        // Store the actual count of triangles written.
                        // uploadIndices function needs it later, to fill unused portion of the index buffer with UINT_MAX (32 bit IB) or 0xFFFF (16 bit IB) discarding the data.
                        // Technically that's wasted GPU bandwidth, however:
                        // (a) Not much of it, as normal text only contains a few of these soft hyphens and ligatures.
                        // (b) Saves substantial amount of resources allowing to generate the complete mesh with a single pass over the glyphs.
                        // With exact-sized buffers, we would have to build the complete text mesh in managed memory, then copy to GPU.
                        // Current implementation only buffers 1 word for left aligned blocks, or 1 line for middle or right aligned blocks, or nothing at all for single-line text. The vertices go straight to mapped GPU verftex buffer.
                        text.actualTriangles        = mds.triangles;
                        drawMeshes.textCommands[sn] = text;

                        // dbgPrintGlyphVertices( dest );
                        continue;
                    }

                    sDrawRectCommand cmd = drawMeshes.rectCommands[sn];
                    if (cmd.strokeWidth.HasValue)
                    {
                        RectangleMesh.strokedVertices(dest, id, ref cmd.rect, cmd.strokeWidth.Value);
                    }
                    else
                    {
                        RectangleMesh.filledVertices(dest, id, ref cmd.rect);
                    }
                }
            }