Advertisement
Guest User

SpriteRenderer V1

a guest
Dec 9th, 2017
143
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.73 KB | None | 0 0
  1. #include "SpriteRenderer.h"
  2. #include "BufferModule.h"
  3. #include "AssetLoader.h"
  4. #include "SpriteVertex.h"
  5. #include "Rect.h"
  6. #include <algorithm>
  7. #include <d3d11.h>
  8.  
  9. //Remove later
  10. #include "SystemUtil.h"
  11.  
  12. const UINT SpriteRenderer::VERTEX_PER_QUAD = 6;
  13. const UINT SpriteRenderer::MAX_SPRITE_COUNT = 10000;
  14. const UINT SpriteRenderer::MAX_VERTEX_COUNT_FOR_BUFFER = VERTEX_PER_QUAD * MAX_SPRITE_COUNT;
  15. const UINT SpriteRenderer::STRIDE_PER_VERTEX = sizeof(SpriteVertex);
  16. const UINT SpriteRenderer::BYTES_PER_SPRITE = STRIDE_PER_VERTEX * VERTEX_PER_QUAD;
  17. const UINT SpriteRenderer::VERTEX_BUFFER_OFFSET = 0;
  18. SpriteRenderer::SpriteRenderer() : Renderer()
  19. {
  20.     Logger::info("Sprite Renderer constructor called!");
  21.    
  22.     vertexCountInBuffer = 0;
  23.     vertexCountToDraw = 0;
  24.     vertexCountDrawnOffset = 0;
  25.     vertexBufferMapType = D3D11_MAP_WRITE_DISCARD;
  26.     renderListSortNeeded = false;
  27.     graphicsDevice = nullptr;
  28.     inputLayout = nullptr;
  29.     vertexBuffer = nullptr;
  30.     mvpConstBuffer = nullptr;
  31.     boundTexture = nullptr;
  32.     defaultVertexShader = nullptr;
  33.     defaultPixelShader = nullptr;
  34.     renderList.clear();
  35.  
  36.     //REMOVE later
  37.     drawCallCount = 0;
  38.     elap = 0.0;
  39.  
  40.     QueryPerformanceFrequency(&frq);
  41. }
  42.  
  43. SpriteRenderer::~SpriteRenderer()
  44. {
  45.     Logger::info("Sprite Renderer constructor called!");
  46.     release();
  47. }
  48.  
  49. void SpriteRenderer::release()
  50. {
  51.     if (vertexBuffer != nullptr)
  52.     {
  53.         delete vertexBuffer;
  54.         vertexBuffer = nullptr;
  55.     }
  56.  
  57.     if (mvpConstBuffer != nullptr)
  58.     {
  59.         delete mvpConstBuffer;
  60.         mvpConstBuffer = nullptr;
  61.     }
  62.  
  63.     if (inputLayout != nullptr)
  64.     {
  65.         delete inputLayout;
  66.         inputLayout = nullptr;
  67.     }
  68. }
  69.  
  70. void SpriteRenderer::init()
  71. {
  72.  
  73.     projectionMatrix.makeOrtho(800.0f, 600.0f, 0.0f, 1000.0f);
  74.     defaultVertexShader = AssetLoader::shaders.createVertexShader(L"defaultSpriteShader.sh", ShaderTarget::ShaderModel4);
  75.     defaultPixelShader = AssetLoader::shaders.createPixelShader(L"defaultSpriteShader.sh", ShaderTarget::ShaderModel4);
  76.  
  77.     vertexBuffer = BufferModule::createVertexBuffer(D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE, sizeof(SpriteVertex) * MAX_VERTEX_COUNT_FOR_BUFFER);
  78.     mvpConstBuffer = BufferModule::createConstantBuffer(sizeof(Matrix4));
  79.     D3D11_INPUT_ELEMENT_DESC inputDescription[3] = {
  80.         { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
  81.         { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
  82.         { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
  83.     };
  84.     inputLayout = BufferModule::createInputLayout(inputDescription, 3, defaultVertexShader);
  85.  
  86. }
  87.  
  88. void SpriteRenderer::add(Sprite* sprite)
  89. {
  90.     renderList.push_back(sprite);
  91.     renderListSortNeeded = true;
  92. }
  93.  
  94. void SpriteRenderer::remove(Sprite* sprite)
  95. {
  96.     std::vector<Sprite*>::iterator i = std::find(renderList.begin(), renderList.end(), sprite);
  97.     if (i != renderList.end())
  98.     {
  99.         renderList.erase(i);
  100.         renderListSortNeeded = true;
  101.     }
  102. }
  103.  
  104. void SpriteRenderer::sortRenderList()
  105. {
  106.     if (renderListSortNeeded == false)
  107.         return;
  108.  
  109.     std::sort(renderList.begin(), renderList.end(), compareSprites);
  110.     renderListSortNeeded = false;
  111. }
  112.  
  113. void SpriteRenderer::addToVertexBuffer(Sprite* sprite)
  114. {
  115.     //Check if we need to flush the buffer because we changed textures
  116.     Texture* spriteTexture = sprite->getTexture();
  117.     if (spriteTexture != boundTexture)
  118.     {
  119.         flushVertexBuffer();
  120.         bindTexture(spriteTexture);
  121.     }
  122.  
  123.     //Check if we need to flush the buffer because we have no more room in it
  124.     if (vertexCountInBuffer == MAX_VERTEX_COUNT_FOR_BUFFER)
  125.     {
  126.         flushVertexBuffer();
  127.         vertexCountInBuffer = 0;
  128.         vertexCountDrawnOffset = 0;
  129.         vertexBufferMapType = D3D11_MAP_WRITE_DISCARD;
  130.     }
  131.  
  132.     float width;
  133.     float height;
  134.     float u = 0.0f;
  135.     float v = 0.0f;
  136.     float uWidth = 1.0f;
  137.     float vHeight = 1.0f;
  138.     float textureWidth = (float)spriteTexture->getWidth();
  139.     float textureHeight = (float)spriteTexture->getHeight();
  140.     SpriteVertex verts[6];
  141.  
  142.     //Vertex setup depending on use of a texture clip rectangle
  143.     Rect* rect = sprite->getTextureClippingRectangle();
  144.     if (rect == nullptr)
  145.     {
  146.         width = textureWidth / 2.0f;
  147.         height = textureHeight / 2.0f;
  148.     }
  149.     else
  150.     {
  151.         width = rect->width / 2.0f;
  152.         height = rect->height / 2.0f;
  153.  
  154.         u = rect->x / textureWidth;
  155.         v = rect->y / textureHeight;
  156.         uWidth = (rect->x + rect->width) / textureWidth;
  157.         vHeight = (rect->y + rect->height) / textureHeight;
  158.     }
  159.     verts[0].position.setXYZ(-width, -height, 0.0f);
  160.     verts[1].position.setXYZ(width, height, 0.0f);
  161.     verts[2].position.setXYZ(width, -height, 0.0f);
  162.     verts[3].position.setXYZ(-width, -height, 0.0f);
  163.     verts[4].position.setXYZ(-width, height, 0.0f);
  164.     verts[5].position.setXYZ(width, height, 0.0f);
  165.  
  166.     //Set the texture coords based on if the sprite should be flipped
  167.     if (sprite->isFlipped() == false)
  168.     {
  169.         verts[0].texCoords.setXY(u, vHeight);
  170.         verts[1].texCoords.setXY(uWidth, v);
  171.         verts[2].texCoords.setXY(uWidth, vHeight);
  172.         verts[3].texCoords.setXY(u, vHeight);
  173.         verts[4].texCoords.setXY(u, v);
  174.         verts[5].texCoords.setXY(uWidth, v);
  175.     }
  176.     else
  177.     {
  178.         verts[0].texCoords.setXY(uWidth, vHeight);
  179.         verts[1].texCoords.setXY(u, v);
  180.         verts[2].texCoords.setXY(u, vHeight);
  181.         verts[3].texCoords.setXY(uWidth, vHeight);
  182.         verts[4].texCoords.setXY(uWidth, v);
  183.         verts[5].texCoords.setXY(u, v);
  184.     }
  185.  
  186.     //Later on tinting will be added
  187.     verts[0].color.setRGB(0.0f, 0.0f, 0.0f);
  188.     verts[1].color.setRGB(0.0f, 0.0f, 0.0f);
  189.     verts[2].color.setRGB(0.0f, 0.0f, 0.0f);
  190.     verts[3].color.setRGB(0.0f, 0.0f, 0.0f);
  191.     verts[4].color.setRGB(0.0f, 0.0f, 0.0f);
  192.     verts[5].color.setRGB(0.0f, 0.0f, 0.0f);
  193.  
  194.     //Pre transform the positions
  195.     Matrix4 model = sprite->getModelMatrix(); // returns the result of translationMatrix * rotationMatrix * scaleMatrix
  196.     verts[0].position = model * verts[0].position;
  197.     verts[1].position = model * verts[1].position;
  198.     verts[2].position = model * verts[2].position;
  199.     verts[3].position = model * verts[3].position;
  200.     verts[4].position = model * verts[4].position;
  201.     verts[5].position = model * verts[5].position;
  202.  
  203.     //Map the data into the vertex buffer
  204.     D3D11_MAPPED_SUBRESOURCE resource = vertexBuffer->map(vertexBufferMapType);
  205.     memcpy(((SpriteVertex*)resource.pData) + vertexCountInBuffer, verts, BYTES_PER_SPRITE);
  206.     vertexBuffer->unmap();
  207.  
  208.     vertexCountToDraw += VERTEX_PER_QUAD;
  209.     vertexCountInBuffer += VERTEX_PER_QUAD;
  210.     vertexBufferMapType = D3D11_MAP_WRITE_NO_OVERWRITE;
  211. }
  212.  
  213. void SpriteRenderer::flushVertexBuffer()
  214. {
  215.     if (vertexCountToDraw == 0)
  216.         return;
  217.  
  218.     D3D11_MAPPED_SUBRESOURCE resource = mvpConstBuffer->map(D3D11_MAP_WRITE_DISCARD);
  219.     memcpy(resource.pData, projectionMatrix.getData(), sizeof(Matrix4));
  220.     mvpConstBuffer->unmap();
  221.  
  222.     //Draw the sprites that we need to
  223.     graphicsDevice->getDeviceContext()->Draw(vertexCountToDraw, vertexCountDrawnOffset);
  224.     vertexCountDrawnOffset += vertexCountToDraw;
  225.     vertexCountToDraw = 0;
  226.  
  227.     ++drawCallCount;
  228.  
  229. }
  230.  
  231. void SpriteRenderer::render(double deltaTime)
  232. {
  233.     QueryPerformanceCounter(&startTime);
  234.  
  235.     renderStart();
  236.     sortRenderList();
  237.    
  238.     Sprite* sprite = nullptr;
  239.     for (std::vector<Sprite*>::iterator i = renderList.begin(); i != renderList.end(); ++i)
  240.     {
  241.         sprite = (*i);
  242.         if (sprite->isVisible() == false)
  243.             continue;
  244.  
  245.         addToVertexBuffer(sprite);
  246.     }
  247.  
  248.     flushVertexBuffer();
  249.  
  250.     //Returns roughly around ~40ms to renderer 10K Sprites. All of them use the same texture
  251.     QueryPerformanceCounter(&endTime);
  252.     Logger::info("RENDER TIME: " + std::to_string(((endTime.QuadPart - startTime.QuadPart) * 1000) / frq.QuadPart));
  253.  
  254.     elap += deltaTime;
  255.     if (elap >= 1000.0)
  256.     {
  257.         Logger::info("Draw call count: " + std::to_string(drawCallCount));
  258.         elap = 0.0;
  259.         drawCallCount = 0;
  260.     }
  261.  
  262.  
  263. }
  264.  
  265. void SpriteRenderer::renderStart()
  266. {
  267.     graphicsDevice = GraphicsDeviceModule::getGraphicsDevice();
  268.     graphicsDevice->getDeviceContext()->VSSetShader(defaultVertexShader->getShader(), 0, 0);
  269.     graphicsDevice->getDeviceContext()->VSSetConstantBuffers(0, 1, mvpConstBuffer->getBuffer());
  270.     graphicsDevice->getDeviceContext()->PSSetShader(defaultPixelShader->getShader(), 0, 0);
  271.     graphicsDevice->getDeviceContext()->IASetInputLayout(inputLayout->getInputLayout());
  272.     graphicsDevice->getDeviceContext()->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
  273.     graphicsDevice->getDeviceContext()->IASetVertexBuffers(0, 1, vertexBuffer->getBuffer(), &STRIDE_PER_VERTEX, &VERTEX_BUFFER_OFFSET);
  274.  
  275.     boundTexture = nullptr;
  276. }
  277.  
  278. void SpriteRenderer::bindTexture(Texture* texture)
  279. {
  280.     boundTexture = texture;
  281.     graphicsDevice->getDeviceContext()->PSSetSamplers(0, 1, boundTexture->getSamplerState());
  282.     graphicsDevice->getDeviceContext()->PSSetShaderResources(0, 1, boundTexture->getShaderResourceView());
  283. }
  284.  
  285. bool SpriteRenderer::compareSprites(Sprite* a, Sprite* b)
  286. {
  287.     return a->getTexture() < b->getTexture();
  288. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement