Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "SpriteRenderer.h"
- #include "BufferModule.h"
- #include "AssetLoader.h"
- #include "SpriteVertex.h"
- #include "Rect.h"
- #include <algorithm>
- #include <d3d11.h>
- //Remove later
- #include "SystemUtil.h"
- const UINT SpriteRenderer::VERTEX_PER_QUAD = 6;
- const UINT SpriteRenderer::MAX_SPRITE_COUNT = 10000;
- const UINT SpriteRenderer::MAX_VERTEX_COUNT_FOR_BUFFER = VERTEX_PER_QUAD * MAX_SPRITE_COUNT;
- const UINT SpriteRenderer::STRIDE_PER_VERTEX = sizeof(SpriteVertex);
- const UINT SpriteRenderer::BYTES_PER_SPRITE = STRIDE_PER_VERTEX * VERTEX_PER_QUAD;
- const UINT SpriteRenderer::VERTEX_BUFFER_OFFSET = 0;
- SpriteRenderer::SpriteRenderer() : Renderer()
- {
- Logger::info("Sprite Renderer constructor called!");
- vertexCountInBuffer = 0;
- vertexCountToDraw = 0;
- vertexCountDrawnOffset = 0;
- vertexBufferMapType = D3D11_MAP_WRITE_DISCARD;
- renderListSortNeeded = false;
- graphicsDevice = nullptr;
- inputLayout = nullptr;
- vertexBuffer = nullptr;
- mvpConstBuffer = nullptr;
- boundTexture = nullptr;
- defaultVertexShader = nullptr;
- defaultPixelShader = nullptr;
- renderList.clear();
- //REMOVE later
- drawCallCount = 0;
- elap = 0.0;
- QueryPerformanceFrequency(&frq);
- }
- SpriteRenderer::~SpriteRenderer()
- {
- Logger::info("Sprite Renderer constructor called!");
- release();
- }
- void SpriteRenderer::release()
- {
- if (vertexBuffer != nullptr)
- {
- delete vertexBuffer;
- vertexBuffer = nullptr;
- }
- if (mvpConstBuffer != nullptr)
- {
- delete mvpConstBuffer;
- mvpConstBuffer = nullptr;
- }
- if (inputLayout != nullptr)
- {
- delete inputLayout;
- inputLayout = nullptr;
- }
- }
- void SpriteRenderer::init()
- {
- projectionMatrix.makeOrtho(800.0f, 600.0f, 0.0f, 1000.0f);
- defaultVertexShader = AssetLoader::shaders.createVertexShader(L"defaultSpriteShader.sh", ShaderTarget::ShaderModel4);
- defaultPixelShader = AssetLoader::shaders.createPixelShader(L"defaultSpriteShader.sh", ShaderTarget::ShaderModel4);
- vertexBuffer = BufferModule::createVertexBuffer(D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE, sizeof(SpriteVertex) * MAX_VERTEX_COUNT_FOR_BUFFER);
- mvpConstBuffer = BufferModule::createConstantBuffer(sizeof(Matrix4));
- D3D11_INPUT_ELEMENT_DESC inputDescription[3] = {
- { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
- { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
- { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
- };
- inputLayout = BufferModule::createInputLayout(inputDescription, 3, defaultVertexShader);
- }
- void SpriteRenderer::add(Sprite* sprite)
- {
- renderList.push_back(sprite);
- renderListSortNeeded = true;
- }
- void SpriteRenderer::remove(Sprite* sprite)
- {
- std::vector<Sprite*>::iterator i = std::find(renderList.begin(), renderList.end(), sprite);
- if (i != renderList.end())
- {
- renderList.erase(i);
- renderListSortNeeded = true;
- }
- }
- void SpriteRenderer::sortRenderList()
- {
- if (renderListSortNeeded == false)
- return;
- std::sort(renderList.begin(), renderList.end(), compareSprites);
- renderListSortNeeded = false;
- }
- void SpriteRenderer::addToVertexBuffer(Sprite* sprite)
- {
- //Check if we need to flush the buffer because we changed textures
- Texture* spriteTexture = sprite->getTexture();
- if (spriteTexture != boundTexture)
- {
- flushVertexBuffer();
- bindTexture(spriteTexture);
- }
- //Check if we need to flush the buffer because we have no more room in it
- if (vertexCountInBuffer == MAX_VERTEX_COUNT_FOR_BUFFER)
- {
- flushVertexBuffer();
- vertexCountInBuffer = 0;
- vertexCountDrawnOffset = 0;
- vertexBufferMapType = D3D11_MAP_WRITE_DISCARD;
- }
- float width;
- float height;
- float u = 0.0f;
- float v = 0.0f;
- float uWidth = 1.0f;
- float vHeight = 1.0f;
- float textureWidth = (float)spriteTexture->getWidth();
- float textureHeight = (float)spriteTexture->getHeight();
- SpriteVertex verts[6];
- //Vertex setup depending on use of a texture clip rectangle
- Rect* rect = sprite->getTextureClippingRectangle();
- if (rect == nullptr)
- {
- width = textureWidth / 2.0f;
- height = textureHeight / 2.0f;
- }
- else
- {
- width = rect->width / 2.0f;
- height = rect->height / 2.0f;
- u = rect->x / textureWidth;
- v = rect->y / textureHeight;
- uWidth = (rect->x + rect->width) / textureWidth;
- vHeight = (rect->y + rect->height) / textureHeight;
- }
- verts[0].position.setXYZ(-width, -height, 0.0f);
- verts[1].position.setXYZ(width, height, 0.0f);
- verts[2].position.setXYZ(width, -height, 0.0f);
- verts[3].position.setXYZ(-width, -height, 0.0f);
- verts[4].position.setXYZ(-width, height, 0.0f);
- verts[5].position.setXYZ(width, height, 0.0f);
- //Set the texture coords based on if the sprite should be flipped
- if (sprite->isFlipped() == false)
- {
- verts[0].texCoords.setXY(u, vHeight);
- verts[1].texCoords.setXY(uWidth, v);
- verts[2].texCoords.setXY(uWidth, vHeight);
- verts[3].texCoords.setXY(u, vHeight);
- verts[4].texCoords.setXY(u, v);
- verts[5].texCoords.setXY(uWidth, v);
- }
- else
- {
- verts[0].texCoords.setXY(uWidth, vHeight);
- verts[1].texCoords.setXY(u, v);
- verts[2].texCoords.setXY(u, vHeight);
- verts[3].texCoords.setXY(uWidth, vHeight);
- verts[4].texCoords.setXY(uWidth, v);
- verts[5].texCoords.setXY(u, v);
- }
- //Later on tinting will be added
- verts[0].color.setRGB(0.0f, 0.0f, 0.0f);
- verts[1].color.setRGB(0.0f, 0.0f, 0.0f);
- verts[2].color.setRGB(0.0f, 0.0f, 0.0f);
- verts[3].color.setRGB(0.0f, 0.0f, 0.0f);
- verts[4].color.setRGB(0.0f, 0.0f, 0.0f);
- verts[5].color.setRGB(0.0f, 0.0f, 0.0f);
- //Pre transform the positions
- Matrix4 model = sprite->getModelMatrix(); // returns the result of translationMatrix * rotationMatrix * scaleMatrix
- verts[0].position = model * verts[0].position;
- verts[1].position = model * verts[1].position;
- verts[2].position = model * verts[2].position;
- verts[3].position = model * verts[3].position;
- verts[4].position = model * verts[4].position;
- verts[5].position = model * verts[5].position;
- //Map the data into the vertex buffer
- D3D11_MAPPED_SUBRESOURCE resource = vertexBuffer->map(vertexBufferMapType);
- memcpy(((SpriteVertex*)resource.pData) + vertexCountInBuffer, verts, BYTES_PER_SPRITE);
- vertexBuffer->unmap();
- vertexCountToDraw += VERTEX_PER_QUAD;
- vertexCountInBuffer += VERTEX_PER_QUAD;
- vertexBufferMapType = D3D11_MAP_WRITE_NO_OVERWRITE;
- }
- void SpriteRenderer::flushVertexBuffer()
- {
- if (vertexCountToDraw == 0)
- return;
- D3D11_MAPPED_SUBRESOURCE resource = mvpConstBuffer->map(D3D11_MAP_WRITE_DISCARD);
- memcpy(resource.pData, projectionMatrix.getData(), sizeof(Matrix4));
- mvpConstBuffer->unmap();
- //Draw the sprites that we need to
- graphicsDevice->getDeviceContext()->Draw(vertexCountToDraw, vertexCountDrawnOffset);
- vertexCountDrawnOffset += vertexCountToDraw;
- vertexCountToDraw = 0;
- ++drawCallCount;
- }
- void SpriteRenderer::render(double deltaTime)
- {
- QueryPerformanceCounter(&startTime);
- renderStart();
- sortRenderList();
- Sprite* sprite = nullptr;
- for (std::vector<Sprite*>::iterator i = renderList.begin(); i != renderList.end(); ++i)
- {
- sprite = (*i);
- if (sprite->isVisible() == false)
- continue;
- addToVertexBuffer(sprite);
- }
- flushVertexBuffer();
- //Returns roughly around ~40ms to renderer 10K Sprites. All of them use the same texture
- QueryPerformanceCounter(&endTime);
- Logger::info("RENDER TIME: " + std::to_string(((endTime.QuadPart - startTime.QuadPart) * 1000) / frq.QuadPart));
- elap += deltaTime;
- if (elap >= 1000.0)
- {
- Logger::info("Draw call count: " + std::to_string(drawCallCount));
- elap = 0.0;
- drawCallCount = 0;
- }
- }
- void SpriteRenderer::renderStart()
- {
- graphicsDevice = GraphicsDeviceModule::getGraphicsDevice();
- graphicsDevice->getDeviceContext()->VSSetShader(defaultVertexShader->getShader(), 0, 0);
- graphicsDevice->getDeviceContext()->VSSetConstantBuffers(0, 1, mvpConstBuffer->getBuffer());
- graphicsDevice->getDeviceContext()->PSSetShader(defaultPixelShader->getShader(), 0, 0);
- graphicsDevice->getDeviceContext()->IASetInputLayout(inputLayout->getInputLayout());
- graphicsDevice->getDeviceContext()->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
- graphicsDevice->getDeviceContext()->IASetVertexBuffers(0, 1, vertexBuffer->getBuffer(), &STRIDE_PER_VERTEX, &VERTEX_BUFFER_OFFSET);
- boundTexture = nullptr;
- }
- void SpriteRenderer::bindTexture(Texture* texture)
- {
- boundTexture = texture;
- graphicsDevice->getDeviceContext()->PSSetSamplers(0, 1, boundTexture->getSamplerState());
- graphicsDevice->getDeviceContext()->PSSetShaderResources(0, 1, boundTexture->getShaderResourceView());
- }
- bool SpriteRenderer::compareSprites(Sprite* a, Sprite* b)
- {
- return a->getTexture() < b->getTexture();
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement