BsStaticRenderableHandler.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  1. #include "BsStaticRenderableHandler.h"
  2. #include "BsShader.h"
  3. #include "BsGpuParams.h"
  4. #include "BsRenderBeast.h"
  5. #include "BsHardwareBufferManager.h"
  6. #include "BsGpuParamBlockBuffer.h"
  7. #include "BsTechnique.h"
  8. #include "BsPass.h"
  9. #include "BsMaterial.h"
  10. #include "BsRenderAPI.h"
  11. namespace BansheeEngine
  12. {
  13. StaticRenderableHandler::StaticRenderableHandler()
  14. {
  15. defaultShader = createDefaultShader();
  16. SPtr<TechniqueCore> defaultTechnique = defaultShader->getBestTechnique();
  17. SPtr<PassCore> defaultPass = defaultTechnique->getPass(0);
  18. GpuParamDescPtr vertParamDesc = defaultPass->getVertexProgram()->getParamDesc();
  19. GpuParamDescPtr fragParamDesc = defaultPass->getFragmentProgram()->getParamDesc();
  20. GpuParamDescPtr staticParamsDesc = bs_shared_ptr_new<GpuParamDesc>();
  21. GpuParamDescPtr perFrameParamsDesc = bs_shared_ptr_new<GpuParamDesc>();
  22. GpuParamDescPtr perObjectParamsDesc = bs_shared_ptr_new<GpuParamDesc>();
  23. GpuParamDescPtr perCameraParamsDesc = bs_shared_ptr_new<GpuParamDesc>();
  24. bool foundLightDir = false;
  25. bool foundTime = false;
  26. bool foundWVP = false;
  27. bool foundViewDir = false;
  28. bool foundStatic = false;
  29. bool foundPerFrame = false;
  30. bool foundPerObject = false;
  31. bool foundPerCamera = false;
  32. const Map<String, SHADER_DATA_PARAM_DESC>& dataParams = defaultShader->getDataParams();
  33. for (auto& param : dataParams)
  34. {
  35. if (!foundLightDir && param.second.rendererSemantic == RPS_LightDir)
  36. {
  37. auto iterFind = fragParamDesc->params.find(param.second.gpuVariableName);
  38. if (iterFind == fragParamDesc->params.end())
  39. continue;
  40. lightDirParamDesc = iterFind->second;
  41. staticParamsDesc->params[iterFind->first] = iterFind->second;
  42. foundLightDir = true;
  43. }
  44. else if (!foundTime && param.second.rendererSemantic == RPS_Time)
  45. {
  46. auto iterFind = vertParamDesc->params.find(param.second.gpuVariableName);
  47. if (iterFind == vertParamDesc->params.end())
  48. continue;
  49. timeParamDesc = iterFind->second;
  50. perFrameParamsDesc->params[iterFind->first] = iterFind->second;
  51. foundTime = true;
  52. }
  53. else if (!foundWVP && param.second.rendererSemantic == RPS_WorldViewProjTfrm)
  54. {
  55. auto iterFind = vertParamDesc->params.find(param.second.gpuVariableName);
  56. if (iterFind == vertParamDesc->params.end())
  57. continue;
  58. wvpParamDesc = iterFind->second;
  59. perObjectParamsDesc->params[iterFind->first] = iterFind->second;
  60. foundWVP = true;
  61. }
  62. else if (!foundViewDir && param.second.rendererSemantic == RPS_ViewDir)
  63. {
  64. auto iterFind = fragParamDesc->params.find(param.second.gpuVariableName);
  65. if (iterFind == fragParamDesc->params.end())
  66. continue;
  67. viewDirParamDesc = iterFind->second;
  68. perCameraParamsDesc->params[iterFind->first] = iterFind->second;
  69. foundViewDir = true;
  70. }
  71. }
  72. const Map<String, SHADER_PARAM_BLOCK_DESC>& paramBlocks = defaultShader->getParamBlocks();
  73. for (auto& block : paramBlocks)
  74. {
  75. if (!foundStatic && block.second.rendererSemantic == RBS_Static)
  76. {
  77. auto iterFind = fragParamDesc->paramBlocks.find(block.second.name);
  78. if (iterFind == fragParamDesc->paramBlocks.end())
  79. continue;
  80. staticParamBlockDesc = iterFind->second;
  81. staticParamsDesc->paramBlocks[iterFind->first] = iterFind->second;
  82. foundStatic = true;
  83. }
  84. else if (!foundPerFrame && block.second.rendererSemantic == RBS_PerFrame)
  85. {
  86. auto iterFind = vertParamDesc->paramBlocks.find(block.second.name);
  87. if (iterFind == vertParamDesc->paramBlocks.end())
  88. continue;
  89. perFrameParamBlockDesc = iterFind->second;
  90. perFrameParamsDesc->paramBlocks[iterFind->first] = iterFind->second;
  91. foundPerFrame = true;
  92. }
  93. else if (!foundPerCamera && block.second.rendererSemantic == RBS_PerCamera)
  94. {
  95. auto iterFind = fragParamDesc->paramBlocks.find(block.second.name);
  96. if (iterFind == fragParamDesc->paramBlocks.end())
  97. continue;
  98. perCameraParamBlockDesc = iterFind->second;
  99. perCameraParamsDesc->paramBlocks[iterFind->first] = iterFind->second;
  100. foundPerCamera = true;
  101. }
  102. else if (!foundPerObject && block.second.rendererSemantic == RBS_PerObject)
  103. {
  104. auto iterFind = vertParamDesc->paramBlocks.find(block.second.name);
  105. if (iterFind == vertParamDesc->paramBlocks.end())
  106. continue;
  107. perObjectParamBlockDesc = iterFind->second;
  108. perObjectParamsDesc->paramBlocks[iterFind->first] = iterFind->second;
  109. foundPerObject = true;
  110. }
  111. }
  112. if (!foundLightDir || !foundTime || !foundWVP || !foundViewDir || !foundStatic || !foundPerFrame || !foundPerCamera || !foundPerObject)
  113. BS_EXCEPT(InternalErrorException, "Invalid default shader.");
  114. // Create global GPU param buffers and get parameter handles
  115. staticParams = GpuParamsCore::create(staticParamsDesc, false);
  116. perFrameParams = GpuParamsCore::create(perFrameParamsDesc, false);
  117. perCameraParams = GpuParamsCore::create(perCameraParamsDesc, false);
  118. staticParamBuffer = HardwareBufferCoreManager::instance().createGpuParamBlockBuffer(staticParamBlockDesc.blockSize * sizeof(UINT32));
  119. perFrameParamBuffer = HardwareBufferCoreManager::instance().createGpuParamBlockBuffer(perFrameParamBlockDesc.blockSize * sizeof(UINT32));
  120. perCameraParamBuffer = HardwareBufferCoreManager::instance().createGpuParamBlockBuffer(perCameraParamBlockDesc.blockSize * sizeof(UINT32));
  121. perObjectParamBuffer = HardwareBufferCoreManager::instance().createGpuParamBlockBuffer(perObjectParamBlockDesc.blockSize * sizeof(UINT32));
  122. staticParams->setParamBlockBuffer(staticParamBlockDesc.slot, staticParamBuffer);
  123. perFrameParams->setParamBlockBuffer(perFrameParamBlockDesc.slot, perFrameParamBuffer);
  124. perCameraParams->setParamBlockBuffer(perCameraParamBlockDesc.slot, perCameraParamBuffer);
  125. staticParams->getParam(lightDirParamDesc.name, lightDirParam);
  126. perFrameParams->getParam(timeParamDesc.name, timeParam);
  127. perCameraParams->getParam(viewDirParamDesc.name, viewDirParam);
  128. lightDirParam.set(Vector4(0.707f, 0.707f, 0.707f, 0.0f));
  129. staticParams->updateHardwareBuffers();
  130. }
  131. void StaticRenderableHandler::initializeRenderElem(RenderableElement& element)
  132. {
  133. static auto paramsMatch = [](const GpuParamDataDesc& a, const GpuParamDataDesc& b)
  134. {
  135. return a.gpuMemOffset == b.gpuMemOffset && a.elementSize == b.elementSize &&
  136. a.arraySize == b.arraySize && a.arrayElementStride == b.arrayElementStride;
  137. };
  138. element.rendererData = PerObjectData();
  139. PerObjectData* rendererData = any_cast_unsafe<PerObjectData>(&element.rendererData);
  140. SPtr<ShaderCore> shader = element.material->getShader();
  141. if (shader == nullptr)
  142. {
  143. LOGWRN("Missing shader on material.");
  144. return;
  145. }
  146. const Map<String, SHADER_PARAM_BLOCK_DESC>& paramBlockDescs = shader->getParamBlocks();
  147. const Map<String, SHADER_DATA_PARAM_DESC>& dataParamDescs = shader->getDataParams();
  148. String staticBlockName;
  149. String perFrameBlockName;
  150. String perCameraBlockName;
  151. String perObjectBlockName;
  152. String wvpParamName;
  153. for (auto& paramBlockDesc : paramBlockDescs)
  154. {
  155. if (paramBlockDesc.second.rendererSemantic == RBS_Static)
  156. staticBlockName = paramBlockDesc.second.name;
  157. else if (paramBlockDesc.second.rendererSemantic == RBS_PerFrame)
  158. perFrameBlockName = paramBlockDesc.second.name;
  159. else if (paramBlockDesc.second.rendererSemantic == RBS_PerCamera)
  160. perCameraBlockName = paramBlockDesc.second.name;
  161. else if (paramBlockDesc.second.rendererSemantic == RBS_PerObject)
  162. perObjectBlockName = paramBlockDesc.second.name;
  163. }
  164. for (auto& paramDesc : dataParamDescs)
  165. {
  166. if (paramDesc.second.rendererSemantic == RPS_WorldViewProjTfrm)
  167. wvpParamName = paramDesc.second.gpuVariableName;
  168. }
  169. UINT32 numPasses = element.material->getNumPasses();
  170. for (UINT32 i = 0; i < numPasses; i++)
  171. {
  172. SPtr<PassParametersCore> passParams = element.material->getPassParameters(i);
  173. for (UINT32 j = 0; j < PassParametersCore::NUM_PARAMS; j++)
  174. {
  175. SPtr<GpuParamsCore> gpuParams = passParams->getParamByIdx(j);
  176. if (gpuParams == nullptr)
  177. continue;
  178. const GpuParamDesc& paramsDesc = gpuParams->getParamDesc();
  179. if (staticBlockName != "")
  180. {
  181. auto findIter = paramsDesc.paramBlocks.find(staticBlockName);
  182. if (findIter != paramsDesc.paramBlocks.end())
  183. {
  184. // TODO - We only compare block sizes but not actual contents. Should I check them too?
  185. // Probably shouldn't concern myself with that here, instead check that on a higher level.
  186. if (findIter->second.blockSize == staticParamBlockDesc.blockSize)
  187. {
  188. UINT32 slotIdx = findIter->second.slot;
  189. element.rendererBuffers.push_back(RenderableElement::BufferBindInfo(i, j, slotIdx, staticParamBuffer));
  190. }
  191. }
  192. }
  193. if (perFrameBlockName != "")
  194. {
  195. auto findIter = paramsDesc.paramBlocks.find(perFrameBlockName);
  196. if (findIter != paramsDesc.paramBlocks.end())
  197. {
  198. if (findIter->second.blockSize == perFrameParamBlockDesc.blockSize)
  199. {
  200. UINT32 slotIdx = findIter->second.slot;
  201. element.rendererBuffers.push_back(RenderableElement::BufferBindInfo(i, j, slotIdx, perFrameParamBuffer));
  202. }
  203. }
  204. }
  205. if (perCameraBlockName != "")
  206. {
  207. auto findIter = paramsDesc.paramBlocks.find(perCameraBlockName);
  208. if (findIter != paramsDesc.paramBlocks.end())
  209. {
  210. if (findIter->second.blockSize == perCameraParamBlockDesc.blockSize)
  211. {
  212. UINT32 slotIdx = findIter->second.slot;
  213. element.rendererBuffers.push_back(RenderableElement::BufferBindInfo(i, j, slotIdx, perCameraParamBuffer));
  214. }
  215. }
  216. }
  217. if (perObjectBlockName != "")
  218. {
  219. auto findIter = paramsDesc.paramBlocks.find(perObjectBlockName);
  220. if (findIter != paramsDesc.paramBlocks.end())
  221. {
  222. if (findIter->second.blockSize == perObjectParamBlockDesc.blockSize)
  223. {
  224. rendererData->perObjectBuffers.push_back(RenderableElement::BufferBindInfo(i, j, findIter->second.slot, perObjectParamBuffer));
  225. if (rendererData->wvpParam == nullptr && wvpParamName != "")
  226. {
  227. auto findIter2 = paramsDesc.params.find(wvpParamName);
  228. if (findIter2 != paramsDesc.params.end())
  229. {
  230. if (paramsMatch(findIter2->second, wvpParamDesc))
  231. gpuParams->getParam(wvpParamName, rendererData->wvpParam);
  232. }
  233. }
  234. }
  235. }
  236. }
  237. }
  238. }
  239. }
  240. void StaticRenderableHandler::bindPerObjectBuffers(const RenderableElement& element)
  241. {
  242. const PerObjectData* rendererData = any_cast_unsafe<PerObjectData>(&element.rendererData);
  243. for (auto& perObjectBuffer : rendererData->perObjectBuffers)
  244. {
  245. SPtr<GpuParamsCore> params = element.material->getPassParameters(perObjectBuffer.passIdx)->getParamByIdx(perObjectBuffer.paramsIdx);
  246. params->setParamBlockBuffer(perObjectBuffer.slotIdx, perObjectParamBuffer);
  247. }
  248. }
  249. void StaticRenderableHandler::updatePerFrameBuffers(float time)
  250. {
  251. timeParam.set(time);
  252. perFrameParams->updateHardwareBuffers();
  253. }
  254. void StaticRenderableHandler::updatePerCameraBuffers(const Vector3& viewDir)
  255. {
  256. viewDirParam.set(viewDir);
  257. perCameraParams->updateHardwareBuffers();
  258. }
  259. void StaticRenderableHandler::updatePerObjectBuffers(RenderableElement& element, const Matrix4& wvpMatrix)
  260. {
  261. PerObjectData* rendererData = any_cast_unsafe<PerObjectData>(&element.rendererData);
  262. rendererData->wvpParam.set(wvpMatrix);
  263. }
  264. SPtr<ShaderCore> StaticRenderableHandler::createDefaultShader()
  265. {
  266. StringID rsName = RenderAPICore::instance().getName();
  267. SPtr<GpuProgramCore> vsProgram;
  268. SPtr<GpuProgramCore> psProgram;
  269. if (rsName == RenderAPIDX11)
  270. {
  271. String vsCode = R"(
  272. cbuffer PerFrame
  273. {
  274. float time;
  275. }
  276. cbuffer PerObject
  277. {
  278. float4x4 matWorldViewProj;
  279. }
  280. void vs_main(in float3 inPos : POSITION,
  281. out float4 oPosition : SV_Position)
  282. {
  283. oPosition = mul(matWorldViewProj, float4(inPos.xyz + float3(sin(time), 0, 0), 1));
  284. })";
  285. String psCode = R"(
  286. cbuffer Static
  287. {
  288. float4 lightDir;
  289. }
  290. cbuffer PerCamera
  291. {
  292. float3 viewDir;
  293. }
  294. float4 ps_main() : SV_Target
  295. {
  296. return dot(lightDir, float4(0.5f, 0.5f, 0.5f, 0.5f)) + dot(viewDir, float4(0.5f, 0.5f, 0.5f, 0.5f));
  297. })";
  298. vsProgram = GpuProgramCore::create(vsCode, "vs_main", "hlsl", GPT_VERTEX_PROGRAM, GPP_VS_4_0);
  299. psProgram = GpuProgramCore::create(psCode, "ps_main", "hlsl", GPT_FRAGMENT_PROGRAM, GPP_FS_4_0);
  300. }
  301. else if (rsName == RenderAPIDX9)
  302. {
  303. String vsCode = R"(
  304. BS_PARAM_BLOCK PerFrame { time }
  305. BS_PARAM_BLOCK PerObject { matWorldViewProj }
  306. float time;
  307. float4x4 matWorldViewProj;
  308. void vs_main(in float3 inPos : POSITION,
  309. out float4 oPosition : POSITION)
  310. {
  311. oPosition = mul(matWorldViewProj, float4(inPos.xyz + float3(sin(time), 0, 0), 1));
  312. })";
  313. String psCode = R"(
  314. BS_PARAM_BLOCK Static { lightDir }
  315. BS_PARAM_BLOCK PerCamera { viewDir }
  316. float4 lightDir;
  317. float3 viewDir;
  318. float4 ps_main() : COLOR0
  319. {
  320. return dot(lightDir, float4(0.5f, 0.5f, 0.5f, 0.5f)) + dot(viewDir, float4(0.5f, 0.5f, 0.5f, 0.5f));
  321. })";
  322. vsProgram = GpuProgramCore::create(vsCode, "vs_main", "hlsl9", GPT_VERTEX_PROGRAM, GPP_VS_2_0);
  323. psProgram = GpuProgramCore::create(psCode, "ps_main", "hlsl9", GPT_FRAGMENT_PROGRAM, GPP_FS_2_0);
  324. }
  325. else if (rsName == RenderAPIOpenGL)
  326. {
  327. String vsCode = R"(
  328. uniform PerFrame
  329. {
  330. float time;
  331. };
  332. uniform PerObject
  333. {
  334. mat4 matWorldViewProj;
  335. };
  336. in vec3 bs_position;
  337. out gl_PerVertex
  338. {
  339. vec4 gl_Position;
  340. };
  341. void main()
  342. {
  343. gl_Position = matWorldViewProj * vec4(bs_position.xyz + vec3(sin(time), 0, 0), 1);
  344. })";
  345. String psCode = R"(
  346. uniform Static
  347. {
  348. vec4 lightDir;
  349. };
  350. uniform PerCamera
  351. {
  352. vec3 viewDir;
  353. };
  354. out vec4 fragColor;
  355. void main()
  356. {
  357. fragColor.x = dot(lightDir.xyz, vec3(0.5f, 0.5f, 0.5f)) + dot(viewDir, vec3(0.5f, 0.5f, 0.5f));
  358. })";
  359. vsProgram = GpuProgramCore::create(vsCode, "main", "glsl", GPT_VERTEX_PROGRAM, GPP_VS_4_0);
  360. psProgram = GpuProgramCore::create(psCode, "main", "glsl", GPT_FRAGMENT_PROGRAM, GPP_FS_4_0);
  361. }
  362. PASS_DESC_CORE passDesc;
  363. passDesc.vertexProgram = vsProgram;
  364. passDesc.fragmentProgram = psProgram;
  365. SPtr<PassCore> newPass = PassCore::create(passDesc);
  366. SPtr<TechniqueCore> newTechnique = TechniqueCore::create(rsName, RendererDefault, { newPass });
  367. SHADER_DESC_CORE shaderDesc;
  368. shaderDesc.setParamBlockAttribs("Static", true, GPBU_DYNAMIC, RBS_Static);
  369. shaderDesc.setParamBlockAttribs("PerFrame", true, GPBU_DYNAMIC, RBS_PerFrame);
  370. shaderDesc.setParamBlockAttribs("PerCamera", true, GPBU_DYNAMIC, RBS_PerCamera);
  371. shaderDesc.setParamBlockAttribs("PerObject", true, GPBU_DYNAMIC, RBS_PerObject);
  372. shaderDesc.addParameter("lightDir", "lightDir", GPDT_FLOAT4, RPS_LightDir);
  373. shaderDesc.addParameter("time", "time", GPDT_FLOAT1, RPS_Time);
  374. shaderDesc.addParameter("viewDir", "viewDir", GPDT_FLOAT4, RPS_ViewDir);
  375. shaderDesc.addParameter("matWorldViewProj", "matWorldViewProj", GPDT_MATRIX_4X4, RPS_WorldViewProjTfrm);
  376. SPtr<ShaderCore> defaultShader = ShaderCore::create("LitTexDefault", shaderDesc, { newTechnique });
  377. return defaultShader;
  378. }
  379. }