BsRenderer.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. #include "BsRenderer.h"
  2. #include "BsCoreThread.h"
  3. #include "BsRenderSystem.h"
  4. #include "BsMaterialProxy.h"
  5. #include "BsMeshProxy.h"
  6. #include "BsMesh.h"
  7. #include "BsBlendState.h"
  8. #include "BsDepthStencilState.h"
  9. #include "BsRasterizerState.h"
  10. namespace BansheeEngine
  11. {
  12. void Renderer::setPass(const MaterialProxy& material, UINT32 passIdx)
  13. {
  14. THROW_IF_NOT_CORE_THREAD;
  15. RenderSystem& rs = RenderSystem::instance();
  16. const MaterialProxyPass& pass = material.passes[passIdx];
  17. if (pass.vertexProg)
  18. {
  19. rs.bindGpuProgram(pass.vertexProg);
  20. rs.bindGpuParams(GPT_VERTEX_PROGRAM, material.params[pass.vertexProgParamsIdx]);
  21. }
  22. else
  23. rs.unbindGpuProgram(GPT_VERTEX_PROGRAM);
  24. if (pass.fragmentProg)
  25. {
  26. rs.bindGpuProgram(pass.fragmentProg);
  27. rs.bindGpuParams(GPT_FRAGMENT_PROGRAM, material.params[pass.fragmentProgParamsIdx]);
  28. }
  29. else
  30. rs.unbindGpuProgram(GPT_FRAGMENT_PROGRAM);
  31. if (pass.geometryProg)
  32. {
  33. rs.bindGpuProgram(pass.geometryProg);
  34. rs.bindGpuParams(GPT_GEOMETRY_PROGRAM, material.params[pass.geometryProgParamsIdx]);
  35. }
  36. else
  37. rs.unbindGpuProgram(GPT_GEOMETRY_PROGRAM);
  38. if (pass.hullProg)
  39. {
  40. rs.bindGpuProgram(pass.hullProg);
  41. rs.bindGpuParams(GPT_HULL_PROGRAM, material.params[pass.hullProgParamsIdx]);
  42. }
  43. else
  44. rs.unbindGpuProgram(GPT_HULL_PROGRAM);
  45. if (pass.domainProg)
  46. {
  47. rs.bindGpuProgram(pass.domainProg);
  48. rs.bindGpuParams(GPT_DOMAIN_PROGRAM, material.params[pass.domainProgParamsIdx]);
  49. }
  50. else
  51. rs.unbindGpuProgram(GPT_DOMAIN_PROGRAM);
  52. if (pass.computeProg)
  53. {
  54. rs.bindGpuProgram(pass.computeProg);
  55. rs.bindGpuParams(GPT_COMPUTE_PROGRAM, material.params[pass.computeProgParamsIdx]);
  56. }
  57. else
  58. rs.unbindGpuProgram(GPT_COMPUTE_PROGRAM);
  59. // TODO - Try to limit amount of state changes, if previous state is already the same
  60. // Set up non-texture related pass settings
  61. if (pass.blendState != nullptr)
  62. rs.setBlendState(pass.blendState.getInternalPtr());
  63. else
  64. rs.setBlendState(BlendState::getDefault());
  65. if (pass.depthStencilState != nullptr)
  66. rs.setDepthStencilState(pass.depthStencilState.getInternalPtr(), pass.stencilRefValue);
  67. else
  68. rs.setDepthStencilState(DepthStencilState::getDefault(), pass.stencilRefValue);
  69. if (pass.rasterizerState != nullptr)
  70. rs.setRasterizerState(pass.rasterizerState.getInternalPtr());
  71. else
  72. rs.setRasterizerState(RasterizerState::getDefault());
  73. }
  74. void Renderer::draw(const MeshProxy& meshProxy)
  75. {
  76. THROW_IF_NOT_CORE_THREAD;
  77. RenderSystem& rs = RenderSystem::instance();
  78. MeshBasePtr mesh;
  79. // TODO: Instead of this lock consider just storing all needed data in MeshProxy and not referencing Mesh at all?
  80. if (!meshProxy.mesh.expired())
  81. mesh = meshProxy.mesh.lock();
  82. else
  83. return;
  84. std::shared_ptr<VertexData> vertexData = mesh->_getVertexData();
  85. rs.setVertexDeclaration(vertexData->vertexDeclaration);
  86. auto vertexBuffers = vertexData->getBuffers();
  87. if (vertexBuffers.size() > 0)
  88. {
  89. VertexBufferPtr buffers[MAX_BOUND_VERTEX_BUFFERS];
  90. UINT32 endSlot = 0;
  91. UINT32 startSlot = MAX_BOUND_VERTEX_BUFFERS;
  92. for (auto iter = vertexBuffers.begin(); iter != vertexBuffers.end(); ++iter)
  93. {
  94. if (iter->first >= MAX_BOUND_VERTEX_BUFFERS)
  95. BS_EXCEPT(InvalidParametersException, "Buffer index out of range");
  96. startSlot = std::min(iter->first, startSlot);
  97. endSlot = std::max(iter->first, endSlot);
  98. }
  99. for (auto iter = vertexBuffers.begin(); iter != vertexBuffers.end(); ++iter)
  100. {
  101. buffers[iter->first - startSlot] = iter->second;
  102. }
  103. rs.setVertexBuffers(startSlot, buffers, endSlot - startSlot + 1);
  104. }
  105. SubMesh subMesh = meshProxy.subMesh;
  106. rs.setDrawOperation(subMesh.drawOp);
  107. IndexBufferPtr indexBuffer = mesh->_getIndexBuffer();
  108. UINT32 indexCount = subMesh.indexCount;
  109. rs.setIndexBuffer(indexBuffer);
  110. rs.drawIndexed(subMesh.indexOffset + mesh->_getIndexOffset(), indexCount, mesh->_getVertexOffset(), vertexData->vertexCount);
  111. mesh->_notifyUsedOnGPU();
  112. }
  113. }