Esempio n. 1
0
	void SpriteBatch::Impl::FlushBatch()
	{
		SortSprites();

		// Walk through sprite list, looking for entries that share a texture.
		size_t batchStart = 0;
		std::shared_ptr<Texture> batchTexture = nullptr;

		for (size_t index = 0; index < m_queueCount; ++index)
		{
			std::shared_ptr<Texture> texture = m_sortedSprites[index]->texture;

			if (texture != batchTexture)
			{
				if (index > batchStart)
					RenderBatch(batchTexture, &m_sortedSprites[batchStart], index - batchStart);

				batchTexture = texture;
				batchStart = index;
			}
		}

		// Render final batch
		RenderBatch(batchTexture, &m_sortedSprites[batchStart], m_queueCount - batchStart);

		// Reset queue
		m_queueCount = 0;

		m_sortedSprites.clear();
	}
void SpriteRenderer::RenderBatch(ID3D11ShaderResourceView* texture,
                                 const SpriteDrawData* drawData,
                                 uint64 numSprites)
{
    _ASSERT(context);
    _ASSERT(initialized);

    D3DPERF_BeginEvent(0xFFFFFFFF, L"SpriteRenderer RenderBatch");

    // Set the vertex shader
    context->VSSetShader(vertexShaderInstanced, nullptr, 0);

    // Set the input layout
    context->IASetInputLayout(inputLayoutInstanced);

    // Set per-batch constants
    D3D11_TEXTURE2D_DESC desc = SetPerBatchData(texture);

    // Make sure the draw rects are all valid
    for (uint64 i = 0; i < numSprites; ++i)
    {
        Float4 drawRect = drawData[i].DrawRect;
        _ASSERT(drawRect.x >= 0 && drawRect.x < desc.Width);
        _ASSERT(drawRect.y >= 0 && drawRect.y < desc.Height);
        _ASSERT(drawRect.z > 0 && drawRect.x + drawRect.z <= desc.Width);
        _ASSERT(drawRect.w > 0 && drawRect.y + drawRect.w <= desc.Height);
    }

    uint64 numSpritesToDraw = std::min(numSprites, MaxBatchSize);

    // Copy in the instance data
    D3D11_MAPPED_SUBRESOURCE mapped;
    DXCall(context->Map(instanceDataBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped));
    CopyMemory(mapped.pData, drawData, static_cast<size_t>(sizeof(SpriteDrawData) * numSpritesToDraw));
    context->Unmap(instanceDataBuffer, 0);

    // Set the constant buffer
    ID3D11Buffer* constantBuffers [1] = { vsPerBatchCB };
    context->VSSetConstantBuffers(0, 1, constantBuffers);

    // Set the vertex buffers
    UINT strides [2] = { sizeof(SpriteVertex), sizeof(SpriteDrawData) };
    UINT offsets [2] = { 0, 0 };
    ID3D11Buffer* vertexBuffers [2] = { vertexBuffer, instanceDataBuffer };
    context->IASetVertexBuffers(0, 2, vertexBuffers, strides, offsets);

    // Set the texture
    context->PSSetShaderResources(0, 1, &texture);

    // Draw
    context->DrawIndexedInstanced(6, static_cast<UINT>(numSpritesToDraw), 0, 0, 0);

    D3DPERF_EndEvent();

    // If there's any left to be rendered, do it recursively
    if(numSprites > numSpritesToDraw)
        RenderBatch(texture, drawData + numSpritesToDraw, numSprites - numSpritesToDraw);
}
Esempio n. 3
0
    void SpriteRenderer::End() {
        SortSpriteData(spriteSortMode);

        Texture2D* batchTexture = sprites[0].texture;
        vector<InstanceData> instanceData;
        while(!sprites.empty()) {
            const SpriteData& nextSprite = sprites.back();
            if (nextSprite.texture != batchTexture) {
                RenderBatch(instanceData.begin(), instanceData.end(), batchTexture);
                instanceData.clear();
                batchTexture = nextSprite.texture;
            } else {
                InstanceData instance(nextSprite.transform, nextSprite.color);
                instanceData.push_back(instance);
                sprites.pop_back();
            }
        }

        if (!instanceData.empty()) {
            RenderBatch(instanceData.begin(), instanceData.end(), batchTexture);
        }
        
        sprites.clear();
    }
void SpriteRenderer::RenderText(const SpriteFont& font,
                                const wchar* text,
                                const Float4x4& transform,
                                const Float4& color)
{
    D3DPERF_BeginEvent(0xFFFFFFFF, L"SpriteRenderer RenderText");

    size_t length = wcslen(text);

    Float4x4 textTransform;

    uint64 numCharsToDraw = std::min(length, MaxBatchSize);
    uint64 currentDraw = 0;
    for(uint64 i = 0; i < numCharsToDraw; ++i)
    {
        wchar character = text[i];
        if(character == ' ')
            textTransform._41 += font.SpaceWidth();
        else if(character == '\n')
        {
            textTransform._42 += font.CharHeight();
            textTransform._41 = 0;
        }
        else
        {
            SpriteFont::CharDesc desc = font.GetCharDescriptor(character);

            textDrawData[currentDraw].Transform = textTransform * transform;
            textDrawData[currentDraw].Color = color;
            textDrawData[currentDraw].DrawRect.x = desc.X;
            textDrawData[currentDraw].DrawRect.y = desc.Y;
            textDrawData[currentDraw].DrawRect.z = desc.Width;
            textDrawData[currentDraw].DrawRect.w = desc.Height;
            currentDraw++;

            textTransform._41 += desc.Width + 1;
        }
    }

    // Submit a batch
    RenderBatch(font.SRView(), textDrawData, currentDraw);

    D3DPERF_EndEvent();

    if(length > numCharsToDraw)
        RenderText(font, text + numCharsToDraw, textTransform, color);
}
void SpriteRenderer::RenderText(const SpriteFont& font,
                                const WCHAR* text,
            				    const XMMATRIX& transform,
                                const XMFLOAT4& color)
{
    D3DPERF_BeginEvent(0xFFFFFFFF, L"SpriteRenderer RenderText");

    size_t length = wcslen(text);

    XMMATRIX textTransform = XMMatrixIdentity();

    UINT64 numCharsToDraw = min(length, MaxBatchSize);
    UINT64 currentDraw = 0;
    for (UINT64 i = 0; i < numCharsToDraw; ++i)
    {
        WCHAR character = text[i];
        if(character == ' ')
            textTransform._41 += font.SpaceWidth();
        else if(character == '\n')
        {
            textTransform._42 += font.CharHeight();
            textTransform._41 = 0;
        }
        else
        {
            SpriteFont::CharDesc desc = font.GetCharDescriptor(character);

            textDrawData[currentDraw].Transform = XMMatrixMultiply(textTransform, transform);
            textDrawData[currentDraw].Color = color;
            textDrawData[currentDraw].DrawRect.x = desc.X;
            textDrawData[currentDraw].DrawRect.y = desc.Y;
            textDrawData[currentDraw].DrawRect.z = desc.Width;
            textDrawData[currentDraw].DrawRect.w = desc.Height;
            currentDraw++;

            textTransform._41 += desc.Width + 1;
        }
    }

    // Submit a batch
    RenderBatch(font.SRView(), textDrawData, currentDraw);

    D3DPERF_EndEvent();

    if(length > numCharsToDraw)
        RenderText(font, text + numCharsToDraw, textTransform, color);
}
void VBOBatcher2D::prepare(bool splitEveryGlyph) {
	if (glyphs.size() == 0)
		return;

	std::vector<Vertex2D> verticies;
	int c = 0;

	for (unsigned int i = 0; i < glyphs.size(); i++) {
		c += glyphs[i]->vertexes.size();
	}

	verticies.resize(c);
	unsigned int offset = 0;
	unsigned int cv = 0;

	batches.emplace_back(RenderBatch(*glyphs[0], offset));
	for (unsigned int i = 0; i < glyphs[0]->vertexes.size(); i++) {
		verticies[cv++] = glyphs[0]->vertexes[i];
		offset++;
	}

	for (unsigned int cg = 1; cg < glyphs.size(); cg++) {
		if (splitEveryGlyph || batches.back() != *(glyphs[cg])) {
			batches.emplace_back(*(glyphs[cg]), offset);
		} else {
			batches.back().size += glyphs[cg]->vertexes.size();
		}

		for (unsigned int i = 0; i < glyphs[cg]->vertexes.size(); i++) {
			verticies[cv++] = glyphs[cg]->vertexes[i];
			offset++;
		}
	}

	vbo.bufferData(verticies);
}