BsBansheeLitTexRenderableController.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. #include "BsBansheeLitTexRenderableController.h"
  2. #include "BsRenderableProxy.h"
  3. #include "BsShader.h"
  4. #include "BsShaderProxy.h"
  5. #include "BsGpuParams.h"
  6. #include "BsBansheeRenderer.h"
  7. #include "BsHardwareBufferManager.h"
  8. #include "BsGpuParamBlockBuffer.h"
  9. #include "BsTechnique.h"
  10. #include "BsPass.h"
  11. #include "BsRenderSystem.h"
  12. namespace BansheeEngine
  13. {
  14. LitTexRenderableController::LitTexRenderableController()
  15. {
  16. defaultShader = createDefaultShader();
  17. TechniquePtr defaultTechnique = defaultShader->getBestTechnique();
  18. PassPtr 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. ShaderProxyPtr shader = element->material->shader;
  115. const Map<String, SHADER_PARAM_BLOCK_DESC>& paramBlockDescs = shader->paramBlocks;
  116. const Map<String, SHADER_DATA_PARAM_DESC>& dataParamDescs = shader->dataParams;
  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 idx = 0;
  142. for (auto& gpuParams : element->material->params)
  143. {
  144. const GpuParamDesc& paramsDesc = gpuParams->getParamDesc();
  145. if (staticBlockName != "")
  146. {
  147. auto findIter = paramsDesc.paramBlocks.find(staticBlockName);
  148. if (findIter != paramsDesc.paramBlocks.end())
  149. {
  150. // TODO - We only compare block sizes but not actual contents. Should I check them too?
  151. // Probably shouldn't concern myself with that here, instead check that on a higher level.
  152. if (findIter->second.blockSize == staticParamBlockDesc.blockSize)
  153. {
  154. UINT32 slotIdx = findIter->second.slot;
  155. element->material->rendererBuffers.push_back(MaterialProxy::BufferBindInfo(idx, slotIdx, staticParamBuffer));
  156. }
  157. }
  158. }
  159. if (perFrameBlockName != "")
  160. {
  161. auto findIter = paramsDesc.paramBlocks.find(perFrameBlockName);
  162. if (findIter != paramsDesc.paramBlocks.end())
  163. {
  164. if (findIter->second.blockSize == perFrameParamBlockDesc.blockSize)
  165. {
  166. UINT32 slotIdx = findIter->second.slot;
  167. element->material->rendererBuffers.push_back(MaterialProxy::BufferBindInfo(idx, slotIdx, perFrameParamBuffer));
  168. }
  169. }
  170. }
  171. if (perObjectBlockName != "")
  172. {
  173. auto findIter = paramsDesc.paramBlocks.find(perObjectBlockName);
  174. if (findIter != paramsDesc.paramBlocks.end())
  175. {
  176. if (findIter->second.blockSize == perObjectParamBlockDesc.blockSize)
  177. {
  178. if (rendererData->perObjectParamBuffer == nullptr)
  179. rendererData->perObjectParamBuffer = HardwareBufferCoreManager::instance().createGpuParamBlockBuffer(perObjectParamBlockDesc.blockSize * sizeof(UINT32));
  180. rendererData->perObjectBuffers.push_back(MaterialProxy::BufferBindInfo(idx, findIter->second.slot, rendererData->perObjectParamBuffer));
  181. if (!rendererData->hasWVPParam && wvpParamName != "")
  182. {
  183. auto findIter2 = paramsDesc.params.find(wvpParamName);
  184. if (findIter2 != paramsDesc.params.end())
  185. {
  186. if (paramsMatch(findIter2->second, wvpParamDesc))
  187. {
  188. gpuParams->getParam(wvpParamName, rendererData->wvpParam);
  189. rendererData->hasWVPParam = true;
  190. }
  191. }
  192. }
  193. }
  194. }
  195. }
  196. idx++;
  197. }
  198. bindGlobalBuffers(element);
  199. }
  200. void LitTexRenderableController::bindPerObjectBuffers(const RenderableElement* element)
  201. {
  202. const PerObjectData* rendererData = any_cast_unsafe<PerObjectData>(&element->rendererData);
  203. for (auto& perObjectBuffer : rendererData->perObjectBuffers)
  204. {
  205. SPtr<GpuParamsCore> params = element->material->params[perObjectBuffer.paramsIdx];
  206. params->setParamBlockBuffer(perObjectBuffer.slotIdx, rendererData->perObjectParamBuffer);
  207. }
  208. }
  209. void LitTexRenderableController::updateGlobalBuffers(float time)
  210. {
  211. timeParam.set(time);
  212. staticParams->updateHardwareBuffers();
  213. perFrameParams->updateHardwareBuffers();
  214. }
  215. void LitTexRenderableController::updatePerObjectBuffers(RenderableElement* element, const Matrix4& wvpMatrix)
  216. {
  217. PerObjectData* rendererData = any_cast_unsafe<PerObjectData>(&element->rendererData);
  218. if (rendererData->hasWVPParam)
  219. rendererData->wvpParam.set(wvpMatrix);
  220. if (rendererData->perObjectParamBuffer != nullptr)
  221. rendererData->perObjectParamBuffer->flushToGPU();
  222. }
  223. ShaderPtr LitTexRenderableController::createDefaultShader()
  224. {
  225. String rsName = RenderSystem::instance().getName();
  226. HGpuProgram vsProgram;
  227. HGpuProgram psProgram;
  228. if (rsName == RenderSystemDX11)
  229. {
  230. String vsCode = R"(
  231. cbuffer PerFrame
  232. {
  233. float time;
  234. }
  235. cbuffer PerObject
  236. {
  237. float4x4 matWorldViewProj;
  238. }
  239. void vs_main(in float3 inPos : POSITION,
  240. out float4 oPosition : SV_Position)
  241. {
  242. oPosition = mul(matWorldViewProj, float4(inPos.xyz + float3(sin(time), 0, 0), 1));
  243. })";
  244. String psCode = R"(
  245. cbuffer Static
  246. {
  247. float4 lightDir;
  248. }
  249. float4 ps_main() : SV_Target
  250. {
  251. return dot(lightDir, float4(0.5f, 0.5f, 0.5f, 0.5f));
  252. })";
  253. vsProgram = GpuProgram::create(vsCode, "vs_main", "hlsl", GPT_VERTEX_PROGRAM, GPP_VS_4_0);
  254. psProgram = GpuProgram::create(psCode, "ps_main", "hlsl", GPT_FRAGMENT_PROGRAM, GPP_FS_4_0);
  255. }
  256. else if (rsName == RenderSystemDX9)
  257. {
  258. String vsCode = R"(
  259. BS_PARAM_BLOCK PerFrame { time }
  260. BS_PARAM_BLOCK PerObject { matWorldViewProj }
  261. float time;
  262. float4x4 matWorldViewProj;
  263. void vs_main(in float3 inPos : POSITION,
  264. out float4 oPosition : POSITION)
  265. {
  266. oPosition = mul(matWorldViewProj, float4(inPos.xyz + float3(sin(time), 0, 0), 1));
  267. })";
  268. String psCode = R"(
  269. BS_PARAM_BLOCK Static { lightDir }
  270. float4 lightDir;
  271. float4 ps_main() : COLOR0
  272. {
  273. return dot(lightDir, float4(0.5f, 0.5f, 0.5f, 0.5f));
  274. })";
  275. vsProgram = GpuProgram::create(vsCode, "vs_main", "hlsl", GPT_VERTEX_PROGRAM, GPP_VS_2_0);
  276. psProgram = GpuProgram::create(psCode, "ps_main", "hlsl", GPT_FRAGMENT_PROGRAM, GPP_FS_2_0);
  277. }
  278. else if (rsName == RenderSystemOpenGL)
  279. {
  280. String vsCode = R"(#version 400
  281. uniform PerFrame
  282. {
  283. float time;
  284. };
  285. uniform PerObject
  286. {
  287. mat4 matWorldViewProj;
  288. };
  289. in vec3 bs_position;
  290. void main()
  291. {
  292. gl_Position = matWorldViewProj * vec4(bs_position.xyz + vec3(sin(time), 0, 0), 1);
  293. })";
  294. String psCode = R"(#version 400
  295. uniform Static
  296. {
  297. vec4 lightDir;
  298. };
  299. out vec4 fragColor;
  300. void main()
  301. {
  302. fragColor = lightDir * vec4(0.5f, 0.5f, 0.5f, 0.5f);
  303. })";
  304. vsProgram = GpuProgram::create(vsCode, "main", "glsl", GPT_VERTEX_PROGRAM, GPP_VS_4_0);
  305. psProgram = GpuProgram::create(psCode, "main", "glsl", GPT_FRAGMENT_PROGRAM, GPP_FS_4_0);
  306. }
  307. vsProgram.synchronize();
  308. psProgram.synchronize();
  309. ShaderPtr defaultShader = Shader::create("LitTexDefault");
  310. defaultShader->setParamBlockAttribs("Static", true, GPBU_DYNAMIC, RBS_Static);
  311. defaultShader->setParamBlockAttribs("PerFrame", true, GPBU_DYNAMIC, RBS_PerFrame);
  312. defaultShader->setParamBlockAttribs("PerObject", true, GPBU_DYNAMIC, RBS_PerObject);
  313. defaultShader->addParameter("lightDir", "lightDir", GPDT_FLOAT4, RPS_LightDir);
  314. defaultShader->addParameter("time", "time", GPDT_FLOAT1, RPS_Time);
  315. defaultShader->addParameter("matWorldViewProj", "matWorldViewProj", GPDT_MATRIX_4X4, RPS_WorldViewProjTfrm);
  316. TechniquePtr newTechnique = defaultShader->addTechnique(rsName, RendererDefault);
  317. PassPtr newPass = newTechnique->addPass();
  318. newPass->setVertexProgram(vsProgram);
  319. newPass->setFragmentProgram(psProgram);
  320. return defaultShader;
  321. }
  322. }