BsLitTexRenderableController.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  1. #include "BsLitTexRenderableController.h"
  2. #include "BsShader.h"
  3. #include "BsGpuParams.h"
  4. #include "BsBansheeRenderer.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. LitTexRenderableController::LitTexRenderableController()
  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<GpuParamDesc>();
  21. GpuParamDescPtr perFrameParamsDesc = bs_shared_ptr<GpuParamDesc>();
  22. GpuParamDescPtr perObjectParamsDesc = bs_shared_ptr<GpuParamDesc>();
  23. GpuParamDescPtr perCameraParamsDesc = bs_shared_ptr<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. staticParams->setParamBlockBuffer(staticParamBlockDesc.slot, staticParamBuffer);
  122. perFrameParams->setParamBlockBuffer(perFrameParamBlockDesc.slot, perFrameParamBuffer);
  123. perCameraParams->setParamBlockBuffer(perCameraParamBlockDesc.slot, perCameraParamBuffer);
  124. staticParams->getParam(lightDirParamDesc.name, lightDirParam);
  125. perFrameParams->getParam(timeParamDesc.name, timeParam);
  126. perCameraParams->getParam(viewDirParamDesc.name, viewDirParam);
  127. lightDirParam.set(Vector4(0.707f, 0.707f, 0.707f, 0.0f));
  128. staticParams->updateHardwareBuffers();
  129. }
  130. void LitTexRenderableController::initializeRenderElem(RenderableElement& element)
  131. {
  132. static auto paramsMatch = [](const GpuParamDataDesc& a, const GpuParamDataDesc& b)
  133. {
  134. return a.gpuMemOffset == b.gpuMemOffset && a.elementSize == b.elementSize &&
  135. a.arraySize == b.arraySize && a.arrayElementStride == b.arrayElementStride;
  136. };
  137. element.rendererData = PerObjectData();
  138. PerObjectData* rendererData = any_cast_unsafe<PerObjectData>(&element.rendererData);
  139. SPtr<ShaderCore> shader = element.material->getShader();
  140. if (shader == nullptr)
  141. {
  142. LOGWRN("Missing shader on material.");
  143. return;
  144. }
  145. const Map<String, SHADER_PARAM_BLOCK_DESC>& paramBlockDescs = shader->getParamBlocks();
  146. const Map<String, SHADER_DATA_PARAM_DESC>& dataParamDescs = shader->getDataParams();
  147. String staticBlockName;
  148. String perFrameBlockName;
  149. String perCameraBlockName;
  150. String perObjectBlockName;
  151. String wvpParamName;
  152. for (auto& paramBlockDesc : paramBlockDescs)
  153. {
  154. if (paramBlockDesc.second.rendererSemantic == RBS_Static)
  155. staticBlockName = paramBlockDesc.second.name;
  156. else if (paramBlockDesc.second.rendererSemantic == RBS_PerFrame)
  157. perFrameBlockName = paramBlockDesc.second.name;
  158. else if (paramBlockDesc.second.rendererSemantic == RBS_PerCamera)
  159. perCameraBlockName = paramBlockDesc.second.name;
  160. else if (paramBlockDesc.second.rendererSemantic == RBS_PerObject)
  161. perObjectBlockName = paramBlockDesc.second.name;
  162. }
  163. for (auto& paramDesc : dataParamDescs)
  164. {
  165. if (paramDesc.second.rendererSemantic == RPS_WorldViewProjTfrm)
  166. wvpParamName = paramDesc.second.gpuVariableName;
  167. }
  168. UINT32 numPasses = element.material->getNumPasses();
  169. for (UINT32 i = 0; i < numPasses; i++)
  170. {
  171. SPtr<PassParametersCore> passParams = element.material->getPassParameters(i);
  172. for (UINT32 j = 0; j < passParams->getNumParams(); j++)
  173. {
  174. SPtr<GpuParamsCore> gpuParams = passParams->getParamByIdx(j);
  175. if (gpuParams == nullptr)
  176. continue;
  177. const GpuParamDesc& paramsDesc = gpuParams->getParamDesc();
  178. if (staticBlockName != "")
  179. {
  180. auto findIter = paramsDesc.paramBlocks.find(staticBlockName);
  181. if (findIter != paramsDesc.paramBlocks.end())
  182. {
  183. // TODO - We only compare block sizes but not actual contents. Should I check them too?
  184. // Probably shouldn't concern myself with that here, instead check that on a higher level.
  185. if (findIter->second.blockSize == staticParamBlockDesc.blockSize)
  186. {
  187. UINT32 slotIdx = findIter->second.slot;
  188. element.rendererBuffers.push_back(RenderableElement::BufferBindInfo(i, j, slotIdx, staticParamBuffer));
  189. }
  190. }
  191. }
  192. if (perFrameBlockName != "")
  193. {
  194. auto findIter = paramsDesc.paramBlocks.find(perFrameBlockName);
  195. if (findIter != paramsDesc.paramBlocks.end())
  196. {
  197. if (findIter->second.blockSize == perFrameParamBlockDesc.blockSize)
  198. {
  199. UINT32 slotIdx = findIter->second.slot;
  200. element.rendererBuffers.push_back(RenderableElement::BufferBindInfo(i, j, slotIdx, perFrameParamBuffer));
  201. }
  202. }
  203. }
  204. if (perCameraBlockName != "")
  205. {
  206. auto findIter = paramsDesc.paramBlocks.find(perCameraBlockName);
  207. if (findIter != paramsDesc.paramBlocks.end())
  208. {
  209. if (findIter->second.blockSize == perCameraParamBlockDesc.blockSize)
  210. {
  211. UINT32 slotIdx = findIter->second.slot;
  212. element.rendererBuffers.push_back(RenderableElement::BufferBindInfo(i, j, slotIdx, perCameraParamBuffer));
  213. }
  214. }
  215. }
  216. if (perObjectBlockName != "")
  217. {
  218. auto findIter = paramsDesc.paramBlocks.find(perObjectBlockName);
  219. if (findIter != paramsDesc.paramBlocks.end())
  220. {
  221. if (findIter->second.blockSize == perObjectParamBlockDesc.blockSize)
  222. {
  223. if (rendererData->perObjectParamBuffer == nullptr)
  224. rendererData->perObjectParamBuffer = HardwareBufferCoreManager::instance().createGpuParamBlockBuffer(perObjectParamBlockDesc.blockSize * sizeof(UINT32));
  225. rendererData->perObjectBuffers.push_back(RenderableElement::BufferBindInfo(i, j, findIter->second.slot, rendererData->perObjectParamBuffer));
  226. if (rendererData->wvpParam == nullptr && wvpParamName != "")
  227. {
  228. auto findIter2 = paramsDesc.params.find(wvpParamName);
  229. if (findIter2 != paramsDesc.params.end())
  230. {
  231. if (paramsMatch(findIter2->second, wvpParamDesc))
  232. gpuParams->getParam(wvpParamName, rendererData->wvpParam);
  233. }
  234. }
  235. }
  236. }
  237. }
  238. }
  239. }
  240. bindGlobalBuffers(element);
  241. }
  242. void LitTexRenderableController::bindPerObjectBuffers(const RenderableElement& element)
  243. {
  244. const PerObjectData* rendererData = any_cast_unsafe<PerObjectData>(&element.rendererData);
  245. for (auto& perObjectBuffer : rendererData->perObjectBuffers)
  246. {
  247. SPtr<GpuParamsCore> params = element.material->getPassParameters(perObjectBuffer.passIdx)->getParamByIdx(perObjectBuffer.paramsIdx);
  248. params->setParamBlockBuffer(perObjectBuffer.slotIdx, rendererData->perObjectParamBuffer);
  249. }
  250. }
  251. void LitTexRenderableController::updatePerFrameBuffers(float time)
  252. {
  253. timeParam.set(time);
  254. perFrameParams->updateHardwareBuffers();
  255. }
  256. void LitTexRenderableController::updatePerCameraBuffers(const Vector3& viewDir)
  257. {
  258. viewDirParam.set(viewDir);
  259. perCameraParams->updateHardwareBuffers();
  260. }
  261. void LitTexRenderableController::updatePerObjectBuffers(RenderableElement& element, const Matrix4& wvpMatrix)
  262. {
  263. PerObjectData* rendererData = any_cast_unsafe<PerObjectData>(&element.rendererData);
  264. rendererData->wvpParam.set(wvpMatrix);
  265. if (rendererData->perObjectParamBuffer != nullptr)
  266. rendererData->perObjectParamBuffer->flushToGPU();
  267. }
  268. SPtr<ShaderCore> LitTexRenderableController::createDefaultShader()
  269. {
  270. StringID rsName = RenderAPICore::instance().getName();
  271. SPtr<GpuProgramCore> vsProgram;
  272. SPtr<GpuProgramCore> psProgram;
  273. if (rsName == RenderAPIDX11)
  274. {
  275. String vsCode = R"(
  276. cbuffer PerFrame
  277. {
  278. float time;
  279. }
  280. cbuffer PerObject
  281. {
  282. float4x4 matWorldViewProj;
  283. }
  284. void vs_main(in float3 inPos : POSITION,
  285. out float4 oPosition : SV_Position)
  286. {
  287. oPosition = mul(matWorldViewProj, float4(inPos.xyz + float3(sin(time), 0, 0), 1));
  288. })";
  289. String psCode = R"(
  290. cbuffer Static
  291. {
  292. float4 lightDir;
  293. }
  294. cbuffer PerCamera
  295. {
  296. float3 viewDir;
  297. }
  298. float4 ps_main() : SV_Target
  299. {
  300. return dot(lightDir, float4(0.5f, 0.5f, 0.5f, 0.5f)) + dot(viewDir, float4(0.5f, 0.5f, 0.5f, 0.5f));
  301. })";
  302. vsProgram = GpuProgramCore::create(vsCode, "vs_main", "hlsl", GPT_VERTEX_PROGRAM, GPP_VS_4_0);
  303. psProgram = GpuProgramCore::create(psCode, "ps_main", "hlsl", GPT_FRAGMENT_PROGRAM, GPP_FS_4_0);
  304. }
  305. else if (rsName == RenderAPIDX9)
  306. {
  307. String vsCode = R"(
  308. BS_PARAM_BLOCK PerFrame { time }
  309. BS_PARAM_BLOCK PerObject { matWorldViewProj }
  310. float time;
  311. float4x4 matWorldViewProj;
  312. void vs_main(in float3 inPos : POSITION,
  313. out float4 oPosition : POSITION)
  314. {
  315. oPosition = mul(matWorldViewProj, float4(inPos.xyz + float3(sin(time), 0, 0), 1));
  316. })";
  317. String psCode = R"(
  318. BS_PARAM_BLOCK Static { lightDir }
  319. BS_PARAM_BLOCK PerCamera { viewDir }
  320. float4 lightDir;
  321. float3 viewDir;
  322. float4 ps_main() : COLOR0
  323. {
  324. return dot(lightDir, float4(0.5f, 0.5f, 0.5f, 0.5f)) + dot(viewDir, float4(0.5f, 0.5f, 0.5f, 0.5f));
  325. })";
  326. vsProgram = GpuProgramCore::create(vsCode, "vs_main", "hlsl9", GPT_VERTEX_PROGRAM, GPP_VS_2_0);
  327. psProgram = GpuProgramCore::create(psCode, "ps_main", "hlsl9", GPT_FRAGMENT_PROGRAM, GPP_FS_2_0);
  328. }
  329. else if (rsName == RenderAPIOpenGL)
  330. {
  331. String vsCode = R"(
  332. uniform PerFrame
  333. {
  334. float time;
  335. };
  336. uniform PerObject
  337. {
  338. mat4 matWorldViewProj;
  339. };
  340. in vec3 bs_position;
  341. out gl_PerVertex
  342. {
  343. vec4 gl_Position;
  344. };
  345. void main()
  346. {
  347. gl_Position = matWorldViewProj * vec4(bs_position.xyz + vec3(sin(time), 0, 0), 1);
  348. })";
  349. String psCode = R"(
  350. uniform Static
  351. {
  352. vec4 lightDir;
  353. };
  354. uniform PerCamera
  355. {
  356. vec3 viewDir;
  357. };
  358. out vec4 fragColor;
  359. void main()
  360. {
  361. fragColor.x = dot(lightDir.xyz, vec3(0.5f, 0.5f, 0.5f)) + dot(viewDir, vec3(0.5f, 0.5f, 0.5f));
  362. })";
  363. vsProgram = GpuProgramCore::create(vsCode, "main", "glsl", GPT_VERTEX_PROGRAM, GPP_VS_4_0);
  364. psProgram = GpuProgramCore::create(psCode, "main", "glsl", GPT_FRAGMENT_PROGRAM, GPP_FS_4_0);
  365. }
  366. PASS_DESC_CORE passDesc;
  367. passDesc.vertexProgram = vsProgram;
  368. passDesc.fragmentProgram = psProgram;
  369. SPtr<PassCore> newPass = PassCore::create(passDesc);
  370. SPtr<TechniqueCore> newTechnique = TechniqueCore::create(rsName, RendererDefault, { newPass });
  371. SHADER_DESC_CORE shaderDesc;
  372. shaderDesc.setParamBlockAttribs("Static", true, GPBU_DYNAMIC, RBS_Static);
  373. shaderDesc.setParamBlockAttribs("PerFrame", true, GPBU_DYNAMIC, RBS_PerFrame);
  374. shaderDesc.setParamBlockAttribs("PerCamera", true, GPBU_DYNAMIC, RBS_PerCamera);
  375. shaderDesc.setParamBlockAttribs("PerObject", true, GPBU_DYNAMIC, RBS_PerObject);
  376. shaderDesc.addParameter("lightDir", "lightDir", GPDT_FLOAT4, RPS_LightDir);
  377. shaderDesc.addParameter("time", "time", GPDT_FLOAT1, RPS_Time);
  378. shaderDesc.addParameter("viewDir", "viewDir", GPDT_FLOAT4, RPS_ViewDir);
  379. shaderDesc.addParameter("matWorldViewProj", "matWorldViewProj", GPDT_MATRIX_4X4, RPS_WorldViewProjTfrm);
  380. SPtr<ShaderCore> defaultShader = ShaderCore::create("LitTexDefault", shaderDesc, { newTechnique });
  381. return defaultShader;
  382. }
  383. }