BsRendererUtility.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "BsRendererUtility.h"
  4. #include "BsRenderAPI.h"
  5. #include "BsMesh.h"
  6. #include "BsVertexDataDesc.h"
  7. #include "BsMaterial.h"
  8. #include "BsGpuParamsSet.h"
  9. #include "BsPass.h"
  10. #include "BsBlendState.h"
  11. #include "BsDepthStencilState.h"
  12. #include "BsRasterizerState.h"
  13. #include "BsGpuParams.h"
  14. #include "BsGpuParamDesc.h"
  15. #include "BsGpuParamBlockBuffer.h"
  16. #include "BsShapeMeshes3D.h"
  17. #include "BsLight.h"
  18. #include "BsShader.h"
  19. namespace BansheeEngine
  20. {
  21. RendererUtility::RendererUtility()
  22. {
  23. {
  24. SPtr<VertexDataDesc> vertexDesc = bs_shared_ptr_new<VertexDataDesc>();
  25. vertexDesc->addVertElem(VET_FLOAT3, VES_POSITION);
  26. vertexDesc->addVertElem(VET_FLOAT2, VES_TEXCOORD);
  27. mFullScreenQuadMesh = MeshCore::create(4, 6, vertexDesc);
  28. }
  29. {
  30. SPtr<VertexDataDesc> vertexDesc = bs_shared_ptr_new<VertexDataDesc>();
  31. vertexDesc->addVertElem(VET_FLOAT3, VES_POSITION);
  32. UINT32 numVertices = 0;
  33. UINT32 numIndices = 0;
  34. ShapeMeshes3D::getNumElementsSphere(3, numVertices, numIndices);
  35. SPtr<MeshData> meshData = bs_shared_ptr_new<MeshData>(numVertices, numIndices, vertexDesc);
  36. UINT32* indexData = meshData->getIndices32();
  37. UINT8* positionData = meshData->getElementData(VES_POSITION);
  38. Sphere localSphere(Vector3::ZERO, 1.0f);
  39. ShapeMeshes3D::solidSphere(localSphere, positionData, nullptr, 0,
  40. vertexDesc->getVertexStride(), indexData, 0, 3);
  41. mPointLightStencilMesh = MeshCore::create(meshData);
  42. }
  43. {
  44. UINT32 numSides = LightCore::LIGHT_CONE_NUM_SIDES;
  45. UINT32 numSlices = LightCore::LIGHT_CONE_NUM_SLICES;
  46. SPtr<VertexDataDesc> vertexDesc = bs_shared_ptr_new<VertexDataDesc>();
  47. vertexDesc->addVertElem(VET_FLOAT3, VES_POSITION);
  48. UINT32 numVertices = numSides * numSlices * 2;
  49. UINT32 numIndices = ((numSides * 2) * (numSlices - 1) * 2) * 3;
  50. SPtr<MeshData> meshData = bs_shared_ptr_new<MeshData>(numVertices, numIndices, vertexDesc);
  51. UINT32* indexData = meshData->getIndices32();
  52. UINT8* positionData = meshData->getElementData(VES_POSITION);
  53. UINT32 stride = vertexDesc->getVertexStride();
  54. // Dummy vertex positions, actual ones generated in shader
  55. for (UINT32 i = 0; i < numVertices; i++)
  56. {
  57. memcpy(positionData, &Vector3::ZERO, sizeof(Vector3));
  58. positionData += stride;
  59. }
  60. // Cone indices
  61. UINT32 curIdx = 0;
  62. for (UINT32 sliceIdx = 0; sliceIdx < (numSlices - 1); sliceIdx++)
  63. {
  64. for (UINT32 sideIdx = 0; sideIdx < numSides; sideIdx++)
  65. {
  66. indexData[curIdx++] = sliceIdx * numSides + sideIdx;
  67. indexData[curIdx++] = sliceIdx * numSides + (sideIdx + 1) % numSides;
  68. indexData[curIdx++] = (sliceIdx + 1) * numSides + sideIdx;
  69. indexData[curIdx++] = sliceIdx * numSides + (sideIdx + 1) % numSides;
  70. indexData[curIdx++] = (sliceIdx + 1) * numSides + (sideIdx + 1) % numSides;
  71. indexData[curIdx++] = (sliceIdx + 1) * numSides + sideIdx;
  72. }
  73. }
  74. // Sphere cap indices
  75. UINT32 coneOffset = numSides * numSlices;
  76. for (UINT32 sliceIdx = 0; sliceIdx < (numSlices - 1); sliceIdx++)
  77. {
  78. for (UINT32 sideIdx = 0; sideIdx < numSides; sideIdx++)
  79. {
  80. indexData[curIdx++] = coneOffset + sliceIdx * numSides + sideIdx;
  81. indexData[curIdx++] = coneOffset + sliceIdx * numSides + (sideIdx + 1) % numSides;
  82. indexData[curIdx++] = coneOffset + (sliceIdx + 1) * numSides + sideIdx;
  83. indexData[curIdx++] = coneOffset + sliceIdx * numSides + (sideIdx + 1) % numSides;
  84. indexData[curIdx++] = coneOffset + (sliceIdx + 1) * numSides + (sideIdx + 1) % numSides;
  85. indexData[curIdx++] = coneOffset + (sliceIdx + 1) * numSides + sideIdx;
  86. }
  87. }
  88. mSpotLightStencilMesh = MeshCore::create(meshData);
  89. }
  90. // TODO - When I add proper preprocessor support, merge these into a single material
  91. mResolveMat = bs_shared_ptr_new<ResolveMat>();
  92. mBlitMat = bs_shared_ptr_new<BlitMat>();
  93. }
  94. RendererUtility::~RendererUtility()
  95. {
  96. }
  97. void RendererUtility::setPass(const SPtr<MaterialCore>& material, UINT32 passIdx, UINT32 techniqueIdx)
  98. {
  99. RenderAPICore& rapi = RenderAPICore::instance();
  100. SPtr<PassCore> pass = material->getPass(passIdx, techniqueIdx);
  101. struct StageData
  102. {
  103. GpuProgramType type;
  104. bool enable;
  105. SPtr<GpuProgramCore> program;
  106. };
  107. const UINT32 numStages = 5;
  108. StageData stages[numStages] =
  109. {
  110. { GPT_VERTEX_PROGRAM, pass->hasVertexProgram(), pass->getVertexProgram() },
  111. { GPT_FRAGMENT_PROGRAM, pass->hasFragmentProgram(), pass->getFragmentProgram() },
  112. { GPT_GEOMETRY_PROGRAM, pass->hasGeometryProgram(), pass->getGeometryProgram() },
  113. { GPT_HULL_PROGRAM, pass->hasHullProgram(), pass->getHullProgram() },
  114. { GPT_DOMAIN_PROGRAM, pass->hasDomainProgram(), pass->getDomainProgram() }
  115. };
  116. for (UINT32 i = 0; i < numStages; i++)
  117. {
  118. const StageData& stage = stages[i];
  119. if (stage.enable)
  120. rapi.bindGpuProgram(stage.program);
  121. else
  122. rapi.unbindGpuProgram(stage.type);
  123. }
  124. // Set up non-texture related pass settings
  125. if (pass->getBlendState() != nullptr)
  126. rapi.setBlendState(pass->getBlendState());
  127. else
  128. rapi.setBlendState(BlendStateCore::getDefault());
  129. if (pass->getDepthStencilState() != nullptr)
  130. rapi.setDepthStencilState(pass->getDepthStencilState(), pass->getStencilRefValue());
  131. else
  132. rapi.setDepthStencilState(DepthStencilStateCore::getDefault(), pass->getStencilRefValue());
  133. if (pass->getRasterizerState() != nullptr)
  134. rapi.setRasterizerState(pass->getRasterizerState());
  135. else
  136. rapi.setRasterizerState(RasterizerStateCore::getDefault());
  137. }
  138. void RendererUtility::setComputePass(const SPtr<MaterialCore>& material, UINT32 passIdx)
  139. {
  140. RenderAPICore& rapi = RenderAPICore::instance();
  141. SPtr<PassCore> pass = material->getPass(passIdx);
  142. if(pass->hasComputeProgram())
  143. rapi.bindGpuProgram(pass->getComputeProgram());
  144. else
  145. rapi.unbindGpuProgram(GPT_COMPUTE_PROGRAM);
  146. }
  147. void RendererUtility::setPassParams(const SPtr<GpuParamsSetCore>& params, UINT32 passIdx)
  148. {
  149. const UINT32 numStages = 6;
  150. GpuProgramType stages[numStages] =
  151. {
  152. { GPT_VERTEX_PROGRAM },
  153. { GPT_FRAGMENT_PROGRAM },
  154. { GPT_GEOMETRY_PROGRAM },
  155. { GPT_HULL_PROGRAM },
  156. { GPT_DOMAIN_PROGRAM },
  157. { GPT_COMPUTE_PROGRAM }
  158. };
  159. for (UINT32 i = 0; i < numStages; i++)
  160. {
  161. SPtr<GpuParamsCore> gpuParams = params->getGpuParams(stages[i], passIdx);
  162. if (gpuParams == nullptr)
  163. continue;
  164. setGpuParams(stages[i], gpuParams);
  165. }
  166. }
  167. void RendererUtility::setGpuParams(GpuProgramType type, const SPtr<GpuParamsCore>& params)
  168. {
  169. RenderAPICore& rapi = RenderAPICore::instance();
  170. const GpuParamDesc& paramDesc = params->getParamDesc();
  171. for (auto iter = paramDesc.samplers.begin(); iter != paramDesc.samplers.end(); ++iter)
  172. {
  173. SPtr<SamplerStateCore> samplerState = params->getSamplerState(iter->second.slot);
  174. if (samplerState == nullptr)
  175. rapi.setSamplerState(type, iter->second.slot, SamplerStateCore::getDefault());
  176. else
  177. rapi.setSamplerState(type, iter->second.slot, samplerState);
  178. }
  179. for (auto iter = paramDesc.textures.begin(); iter != paramDesc.textures.end(); ++iter)
  180. {
  181. SPtr<TextureCore> texture = params->getTexture(iter->second.slot);
  182. rapi.setTexture(type, iter->second.slot, texture);
  183. }
  184. for (auto iter = paramDesc.loadStoreTextures.begin(); iter != paramDesc.loadStoreTextures.end(); ++iter)
  185. {
  186. SPtr<TextureCore> texture = params->getLoadStoreTexture(iter->second.slot);
  187. const TextureSurface& surface = params->getLoadStoreSurface(iter->second.slot);
  188. if (texture == nullptr)
  189. rapi.setLoadStoreTexture(type, iter->second.slot, false, nullptr, surface);
  190. else
  191. rapi.setLoadStoreTexture(type, iter->second.slot, true, texture, surface);
  192. }
  193. for (auto iter = paramDesc.buffers.begin(); iter != paramDesc.buffers.end(); ++iter)
  194. {
  195. SPtr<GpuBufferCore> buffer = params->getBuffer(iter->second.slot);
  196. bool isLoadStore = iter->second.type != GPOT_BYTE_BUFFER &&
  197. iter->second.type != GPOT_STRUCTURED_BUFFER;
  198. rapi.setBuffer(type, iter->second.slot, buffer, isLoadStore);
  199. }
  200. for (auto iter = paramDesc.paramBlocks.begin(); iter != paramDesc.paramBlocks.end(); ++iter)
  201. {
  202. SPtr<GpuParamBlockBufferCore> blockBuffer = params->getParamBlockBuffer(iter->second.slot);
  203. blockBuffer->flushToGPU();
  204. rapi.setParamBuffer(type, iter->second.slot, blockBuffer, paramDesc);
  205. }
  206. }
  207. void RendererUtility::draw(const SPtr<MeshCoreBase>& mesh, const SubMesh& subMesh, UINT32 numInstances)
  208. {
  209. RenderAPICore& rapi = RenderAPICore::instance();
  210. SPtr<VertexData> vertexData = mesh->getVertexData();
  211. rapi.setVertexDeclaration(mesh->getVertexData()->vertexDeclaration);
  212. auto& vertexBuffers = vertexData->getBuffers();
  213. if (vertexBuffers.size() > 0)
  214. {
  215. SPtr<VertexBufferCore> buffers[MAX_BOUND_VERTEX_BUFFERS];
  216. UINT32 endSlot = 0;
  217. UINT32 startSlot = MAX_BOUND_VERTEX_BUFFERS;
  218. for (auto iter = vertexBuffers.begin(); iter != vertexBuffers.end(); ++iter)
  219. {
  220. if (iter->first >= MAX_BOUND_VERTEX_BUFFERS)
  221. BS_EXCEPT(InvalidParametersException, "Buffer index out of range");
  222. startSlot = std::min(iter->first, startSlot);
  223. endSlot = std::max(iter->first, endSlot);
  224. }
  225. for (auto iter = vertexBuffers.begin(); iter != vertexBuffers.end(); ++iter)
  226. {
  227. buffers[iter->first - startSlot] = iter->second;
  228. }
  229. rapi.setVertexBuffers(startSlot, buffers, endSlot - startSlot + 1);
  230. }
  231. SPtr<IndexBufferCore> indexBuffer = mesh->getIndexBuffer();
  232. rapi.setIndexBuffer(indexBuffer);
  233. rapi.setDrawOperation(subMesh.drawOp);
  234. UINT32 indexCount = subMesh.indexCount;
  235. rapi.drawIndexed(subMesh.indexOffset + mesh->getIndexOffset(), indexCount, mesh->getVertexOffset(),
  236. vertexData->vertexCount, numInstances);
  237. mesh->_notifyUsedOnGPU();
  238. }
  239. void RendererUtility::drawMorph(const SPtr<MeshCoreBase>& mesh, const SubMesh& subMesh,
  240. const SPtr<VertexBufferCore>& morphVertices)
  241. {
  242. // Bind buffers and draw
  243. RenderAPICore& rapi = RenderAPICore::instance();
  244. SPtr<VertexData> vertexData = mesh->getVertexData();
  245. rapi.setVertexDeclaration(mesh->getVertexData()->vertexDeclaration); // TODO - Set valid declaration
  246. auto& meshBuffers = vertexData->getBuffers();
  247. SPtr<VertexBufferCore> allBuffers[MAX_BOUND_VERTEX_BUFFERS];
  248. UINT32 endSlot = 0;
  249. UINT32 startSlot = MAX_BOUND_VERTEX_BUFFERS;
  250. for (auto iter = meshBuffers.begin(); iter != meshBuffers.end(); ++iter)
  251. {
  252. if (iter->first >= MAX_BOUND_VERTEX_BUFFERS)
  253. BS_EXCEPT(InvalidParametersException, "Buffer index out of range");
  254. startSlot = std::min(iter->first, startSlot);
  255. endSlot = std::max(iter->first, endSlot);
  256. }
  257. for (auto iter = meshBuffers.begin(); iter != meshBuffers.end(); ++iter)
  258. allBuffers[iter->first - startSlot] = iter->second;
  259. allBuffers[1] = morphVertices;
  260. rapi.setVertexBuffers(startSlot, allBuffers, endSlot - startSlot + 1);
  261. SPtr<IndexBufferCore> indexBuffer = mesh->getIndexBuffer();
  262. rapi.setIndexBuffer(indexBuffer);
  263. rapi.setDrawOperation(subMesh.drawOp);
  264. UINT32 indexCount = subMesh.indexCount;
  265. rapi.drawIndexed(subMesh.indexOffset + mesh->getIndexOffset(), indexCount, mesh->getVertexOffset(),
  266. vertexData->vertexCount, 1);
  267. mesh->_notifyUsedOnGPU();
  268. }
  269. void RendererUtility::blit(const SPtr<TextureCore>& texture, const Rect2I& area)
  270. {
  271. auto& texProps = texture->getProperties();
  272. SPtr<MaterialCore> mat;
  273. SPtr<GpuParamsSetCore> params;
  274. if (texProps.getMultisampleCount() > 1)
  275. {
  276. mat = mResolveMat->getMaterial();
  277. params = mResolveMat->getParamsSet();
  278. mResolveMat->setParameters(texture);
  279. }
  280. else
  281. {
  282. mat = mBlitMat->getMaterial();
  283. params = mBlitMat->getParamsSet();
  284. mBlitMat->setParameters(texture);
  285. }
  286. setPass(mat);
  287. setPassParams(params);
  288. Rect2 fArea((float)area.x, (float)area.y, (float)area.width, (float)area.height);
  289. if(area.width == 0 || area.height == 0)
  290. {
  291. fArea.x = 0.0f;
  292. fArea.y = 0.0f;
  293. fArea.width = (float)texProps.getWidth();
  294. fArea.height = (float)texProps.getHeight();
  295. }
  296. drawScreenQuad(fArea);
  297. }
  298. void RendererUtility::drawScreenQuad(const Rect2& uv, const Vector2I& textureSize, UINT32 numInstances)
  299. {
  300. // Note: Consider drawing the quad using a single large triangle for possibly better performance
  301. Vector3 vertices[4];
  302. vertices[0] = Vector3(-1.0f, 1.0f, 0.0f);
  303. vertices[1] = Vector3(1.0f, 1.0f, 0.0f);
  304. vertices[2] = Vector3(-1.0f, -1.0f, 0.0f);
  305. vertices[3] = Vector3(1.0f, -1.0f, 0.0f);
  306. Vector2 uvs[4];
  307. if (RenderAPICore::instance().getAPIInfo().getNDCYAxisDown())
  308. {
  309. uvs[0] = Vector2(uv.x, uv.y);
  310. uvs[1] = Vector2(uv.x + uv.width, uv.y);
  311. uvs[2] = Vector2(uv.x, uv.y + uv.height);
  312. uvs[3] = Vector2(uv.x + uv.width, uv.y + uv.height);
  313. }
  314. else
  315. {
  316. uvs[0] = Vector2(uv.x, uv.y + uv.height);
  317. uvs[1] = Vector2(uv.x + uv.width, uv.y + uv.height);
  318. uvs[2] = Vector2(uv.x, uv.y);
  319. uvs[3] = Vector2(uv.x + uv.width, uv.y);
  320. }
  321. for (int i = 0; i < 4; i++)
  322. {
  323. uvs[i].x /= (float)textureSize.x;
  324. uvs[i].y /= (float)textureSize.y;
  325. }
  326. SPtr<VertexDataDesc> vertexDesc = mFullScreenQuadMesh->getVertexDesc();
  327. SPtr<MeshData> meshData = bs_shared_ptr_new<MeshData>(4, 6, vertexDesc);
  328. auto vecIter = meshData->getVec3DataIter(VES_POSITION);
  329. for (UINT32 i = 0; i < 4; i++)
  330. vecIter.addValue(vertices[i]);
  331. auto uvIter = meshData->getVec2DataIter(VES_TEXCOORD);
  332. for (UINT32 i = 0; i < 4; i++)
  333. uvIter.addValue(uvs[i]);
  334. auto indices = meshData->getIndices32();
  335. indices[0] = 0;
  336. indices[1] = 1;
  337. indices[2] = 2;
  338. indices[3] = 1;
  339. indices[4] = 3;
  340. indices[5] = 2;
  341. mFullScreenQuadMesh->writeSubresource(0, *meshData, true, false);
  342. draw(mFullScreenQuadMesh, mFullScreenQuadMesh->getProperties().getSubMesh(), numInstances);
  343. }
  344. RendererUtility& gRendererUtility()
  345. {
  346. return RendererUtility::instance();
  347. }
  348. BlitMat::BlitMat()
  349. {
  350. mSource = mMaterial->getParamTexture("gSource");
  351. }
  352. void BlitMat::_initDefines(ShaderDefines& defines)
  353. {
  354. // Do nothing
  355. }
  356. void BlitMat::setParameters(const SPtr<TextureCore>& source)
  357. {
  358. mSource.set(source);
  359. mMaterial->updateParamsSet(mParamsSet);
  360. }
  361. ResolveMat::ResolveMat()
  362. {
  363. mSource = mMaterial->getParamTexture("gSource");
  364. mMaterial->getParam("gNumSamples", mNumSamples);
  365. }
  366. void ResolveMat::_initDefines(ShaderDefines& defines)
  367. {
  368. // Do nothing
  369. }
  370. void ResolveMat::setParameters(const SPtr<TextureCore>& source)
  371. {
  372. mSource.set(source);
  373. UINT32 sampleCount = source->getProperties().getMultisampleCount();
  374. mNumSamples.set(sampleCount);
  375. mMaterial->updateParamsSet(mParamsSet);
  376. }
  377. }