BsBansheeLitTexRenderableController.cpp 13 KB

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