BsRendererUtility.cpp 12 KB

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