BsRendererUtility.cpp 14 KB

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