BsRenderBeast.cpp 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "BsRenderBeast.h"
  4. #include "BsCCamera.h"
  5. #include "BsCRenderable.h"
  6. #include "BsMaterial.h"
  7. #include "BsMesh.h"
  8. #include "BsPass.h"
  9. #include "BsSamplerState.h"
  10. #include "BsCoreApplication.h"
  11. #include "BsViewport.h"
  12. #include "BsRenderTarget.h"
  13. #include "BsRenderQueue.h"
  14. #include "BsCoreThread.h"
  15. #include "BsGpuParams.h"
  16. #include "BsProfilerCPU.h"
  17. #include "BsShader.h"
  18. #include "BsGpuParamBlockBuffer.h"
  19. #include "BsTime.h"
  20. #include "BsRenderableElement.h"
  21. #include "BsCoreObjectManager.h"
  22. #include "BsRenderBeastOptions.h"
  23. #include "BsSamplerOverrides.h"
  24. #include "BsLight.h"
  25. #include "BsRenderTexturePool.h"
  26. #include "BsRenderTargets.h"
  27. #include "BsRendererUtility.h"
  28. #include "BsAnimationManager.h"
  29. #include "BsSkeleton.h"
  30. #include "BsGpuBuffer.h"
  31. #include "BsGpuParamsSet.h"
  32. #include "BsMeshData.h"
  33. using namespace std::placeholders;
  34. namespace bs
  35. {
  36. RenderBeast::RendererFrame::RendererFrame(float delta, const RendererAnimationData& animData)
  37. :delta(delta), animData(animData)
  38. { }
  39. RenderBeast::RenderBeast()
  40. : mDefaultMaterial(nullptr), mPointLightInMat(nullptr), mPointLightOutMat(nullptr), mDirLightMat(nullptr)
  41. , mObjectRenderer(nullptr), mOptions(bs_shared_ptr_new<RenderBeastOptions>()), mOptionsDirty(true)
  42. { }
  43. const StringID& RenderBeast::getName() const
  44. {
  45. static StringID name = "RenderBeast";
  46. return name;
  47. }
  48. void RenderBeast::initialize()
  49. {
  50. CoreRenderer::initialize();
  51. gCoreThread().queueCommand(std::bind(&RenderBeast::initializeCore, this), CTQF_InternalQueue);
  52. }
  53. void RenderBeast::destroy()
  54. {
  55. CoreRenderer::destroy();
  56. gCoreThread().queueCommand(std::bind(&RenderBeast::destroyCore, this));
  57. gCoreThread().submit(true);
  58. }
  59. void RenderBeast::initializeCore()
  60. {
  61. RendererUtility::startUp();
  62. mCoreOptions = bs_shared_ptr_new<RenderBeastOptions>();
  63. mObjectRenderer = bs_new<ObjectRenderer>();
  64. mDefaultMaterial = bs_new<DefaultMaterial>();
  65. mPointLightInMat = bs_new<PointLightInMat>();
  66. mPointLightOutMat = bs_new<PointLightOutMat>();
  67. mDirLightMat = bs_new<DirectionalLightMat>();
  68. RenderTexturePool::startUp();
  69. PostProcessing::startUp();
  70. }
  71. void RenderBeast::destroyCore()
  72. {
  73. if (mObjectRenderer != nullptr)
  74. bs_delete(mObjectRenderer);
  75. for (auto& entry : mRenderables)
  76. bs_delete(entry);
  77. for (auto& entry : mCameras)
  78. bs_delete(entry.second);
  79. mRenderTargets.clear();
  80. mCameras.clear();
  81. mRenderables.clear();
  82. mVisibility.clear();
  83. PostProcessing::shutDown();
  84. RenderTexturePool::shutDown();
  85. bs_delete(mDefaultMaterial);
  86. bs_delete(mPointLightInMat);
  87. bs_delete(mPointLightOutMat);
  88. bs_delete(mDirLightMat);
  89. RendererUtility::shutDown();
  90. assert(mSamplerOverrides.empty());
  91. }
  92. void RenderBeast::notifyRenderableAdded(RenderableCore* renderable)
  93. {
  94. UINT32 renderableId = (UINT32)mRenderables.size();
  95. renderable->setRendererId(renderableId);
  96. mRenderables.push_back(bs_new<RendererObject>());
  97. mWorldBounds.push_back(renderable->getBounds());
  98. mVisibility.push_back(false);
  99. RendererObject* rendererObject = mRenderables.back();
  100. rendererObject->renderable = renderable;
  101. rendererObject->updatePerObjectBuffer();
  102. SPtr<MeshCore> mesh = renderable->getMesh();
  103. if (mesh != nullptr)
  104. {
  105. const MeshProperties& meshProps = mesh->getProperties();
  106. SPtr<VertexDeclarationCore> vertexDecl = mesh->getVertexData()->vertexDeclaration;
  107. for (UINT32 i = 0; i < meshProps.getNumSubMeshes(); i++)
  108. {
  109. rendererObject->elements.push_back(BeastRenderableElement());
  110. BeastRenderableElement& renElement = rendererObject->elements.back();
  111. renElement.mesh = mesh;
  112. renElement.subMesh = meshProps.getSubMesh(i);
  113. renElement.renderableId = renderableId;
  114. renElement.animType = renderable->getAnimType();
  115. renElement.animationId = renderable->getAnimationId();
  116. renElement.morphShapeVersion = 0;
  117. renElement.morphShapeBuffer = renderable->getMorphShapeBuffer();
  118. renElement.boneMatrixBuffer = renderable->getBoneMatrixBuffer();
  119. renElement.morphVertexDeclaration = renderable->getMorphVertexDeclaration();
  120. renElement.material = renderable->getMaterial(i);
  121. if (renElement.material == nullptr)
  122. renElement.material = renderable->getMaterial(0);
  123. if (renElement.material != nullptr && renElement.material->getShader() == nullptr)
  124. renElement.material = nullptr;
  125. // If no material use the default material
  126. if (renElement.material == nullptr)
  127. renElement.material = mDefaultMaterial->getMaterial();
  128. // Determine which technique to use
  129. static StringID techniqueIDLookup[4] = { StringID::NONE, RTag_Skinned, RTag_Morph, RTag_SkinnedMorph };
  130. static_assert((UINT32)RenderableAnimType::Count == 4, "RenderableAnimType is expected to have four sequential entries.");
  131. UINT32 techniqueIdx = -1;
  132. RenderableAnimType animType = renderable->getAnimType();
  133. if(animType != RenderableAnimType::None)
  134. techniqueIdx = renElement.material->findTechnique(techniqueIDLookup[(int)animType]);
  135. if (techniqueIdx == (UINT32)-1)
  136. techniqueIdx = renElement.material->getDefaultTechnique();
  137. renElement.techniqueIdx = techniqueIdx;
  138. // Validate mesh <-> shader vertex bindings
  139. if (renElement.material != nullptr)
  140. {
  141. UINT32 numPasses = renElement.material->getNumPasses(techniqueIdx);
  142. for (UINT32 j = 0; j < numPasses; j++)
  143. {
  144. SPtr<PassCore> pass = renElement.material->getPass(j, techniqueIdx);
  145. SPtr<VertexDeclarationCore> shaderDecl = pass->getVertexProgram()->getInputDeclaration();
  146. if (!vertexDecl->isCompatible(shaderDecl))
  147. {
  148. Vector<VertexElement> missingElements = vertexDecl->getMissingElements(shaderDecl);
  149. // If using morph shapes ignore POSITION1 and NORMAL1 missing since we assign them from within the renderer
  150. if(animType == RenderableAnimType::Morph || animType == RenderableAnimType::SkinnedMorph)
  151. {
  152. auto removeIter = std::remove_if(missingElements.begin(), missingElements.end(), [](const VertexElement& x)
  153. {
  154. return (x.getSemantic() == VES_POSITION && x.getSemanticIdx() == 1) ||
  155. (x.getSemantic() == VES_NORMAL && x.getSemanticIdx() == 1);
  156. });
  157. missingElements.erase(removeIter, missingElements.end());
  158. }
  159. if (!missingElements.empty())
  160. {
  161. StringStream wrnStream;
  162. wrnStream << "Provided mesh is missing required vertex attributes to render with the provided shader. Missing elements: " << std::endl;
  163. for (auto& entry : missingElements)
  164. wrnStream << "\t" << toString(entry.getSemantic()) << entry.getSemanticIdx() << std::endl;
  165. LOGWRN(wrnStream.str());
  166. break;
  167. }
  168. }
  169. }
  170. }
  171. // Generate or assigned renderer specific data for the material
  172. Any materialInfo = renElement.material->getRendererData();
  173. if(materialInfo.empty())
  174. {
  175. RendererMaterial matInfo;
  176. matInfo.params.resize(techniqueIdx + 1);
  177. matInfo.params[techniqueIdx] = renElement.material->createParamsSet(techniqueIdx);
  178. matInfo.matVersion = renElement.material->getVersion();
  179. renElement.material->updateParamsSet(matInfo.params[techniqueIdx], techniqueIdx, true);
  180. renElement.material->setRendererData(matInfo);
  181. renElement.params = matInfo.params[techniqueIdx];
  182. }
  183. else
  184. {
  185. RendererMaterial& matInfo = any_cast_ref<RendererMaterial>(materialInfo);
  186. if (matInfo.params.size() <= techniqueIdx)
  187. matInfo.params.resize(techniqueIdx + 1);
  188. if(matInfo.params[techniqueIdx] == nullptr || matInfo.matVersion != renElement.material->getVersion())
  189. {
  190. matInfo.params[techniqueIdx] = renElement.material->createParamsSet(techniqueIdx);
  191. matInfo.matVersion = renElement.material->getVersion();
  192. renElement.material->updateParamsSet(matInfo.params[techniqueIdx], techniqueIdx, true);
  193. }
  194. renElement.params = matInfo.params[techniqueIdx];
  195. }
  196. // Generate or assign sampler state overrides
  197. SamplerOverrideKey samplerKey(renElement.material, techniqueIdx);
  198. auto iterFind = mSamplerOverrides.find(samplerKey);
  199. if (iterFind != mSamplerOverrides.end())
  200. {
  201. renElement.samplerOverrides = iterFind->second;
  202. iterFind->second->refCount++;
  203. }
  204. else
  205. {
  206. SPtr<ShaderCore> shader = renElement.material->getShader();
  207. MaterialSamplerOverrides* samplerOverrides = SamplerOverrideUtility::generateSamplerOverrides(shader,
  208. renElement.material->_getInternalParams(), renElement.params, mCoreOptions);
  209. mSamplerOverrides[samplerKey] = samplerOverrides;
  210. renElement.samplerOverrides = samplerOverrides;
  211. samplerOverrides->refCount++;
  212. }
  213. mObjectRenderer->initElement(*rendererObject, renElement);
  214. }
  215. }
  216. }
  217. void RenderBeast::notifyRenderableRemoved(RenderableCore* renderable)
  218. {
  219. UINT32 renderableId = renderable->getRendererId();
  220. RenderableCore* lastRenerable = mRenderables.back()->renderable;
  221. UINT32 lastRenderableId = lastRenerable->getRendererId();
  222. RendererObject* rendererObject = mRenderables[renderableId];
  223. Vector<BeastRenderableElement>& elements = rendererObject->elements;
  224. for (auto& element : elements)
  225. {
  226. SamplerOverrideKey samplerKey(element.material, element.techniqueIdx);
  227. auto iterFind = mSamplerOverrides.find(samplerKey);
  228. assert(iterFind != mSamplerOverrides.end());
  229. MaterialSamplerOverrides* samplerOverrides = iterFind->second;
  230. samplerOverrides->refCount--;
  231. if (samplerOverrides->refCount == 0)
  232. {
  233. SamplerOverrideUtility::destroySamplerOverrides(samplerOverrides);
  234. mSamplerOverrides.erase(iterFind);
  235. }
  236. element.samplerOverrides = nullptr;
  237. }
  238. if (renderableId != lastRenderableId)
  239. {
  240. // Swap current last element with the one we want to erase
  241. std::swap(mRenderables[renderableId], mRenderables[lastRenderableId]);
  242. std::swap(mWorldBounds[renderableId], mWorldBounds[lastRenderableId]);
  243. lastRenerable->setRendererId(renderableId);
  244. for (auto& element : elements)
  245. element.renderableId = renderableId;
  246. }
  247. // Last element is the one we want to erase
  248. mRenderables.erase(mRenderables.end() - 1);
  249. mWorldBounds.erase(mWorldBounds.end() - 1);
  250. mVisibility.erase(mVisibility.end() - 1);
  251. bs_delete(rendererObject);
  252. }
  253. void RenderBeast::notifyRenderableUpdated(RenderableCore* renderable)
  254. {
  255. UINT32 renderableId = renderable->getRendererId();
  256. mRenderables[renderableId]->updatePerObjectBuffer();
  257. mWorldBounds[renderableId] = renderable->getBounds();
  258. }
  259. void RenderBeast::notifyLightAdded(LightCore* light)
  260. {
  261. if (light->getType() == LightType::Directional)
  262. {
  263. UINT32 lightId = (UINT32)mDirectionalLights.size();
  264. light->setRendererId(lightId);
  265. mDirectionalLights.push_back(RendererLight());
  266. RendererLight& lightData = mDirectionalLights.back();
  267. lightData.internal = light;
  268. }
  269. else
  270. {
  271. UINT32 lightId = (UINT32)mPointLights.size();
  272. light->setRendererId(lightId);
  273. mPointLights.push_back(RendererLight());
  274. mLightWorldBounds.push_back(light->getBounds());
  275. RendererLight& lightData = mPointLights.back();
  276. lightData.internal = light;
  277. }
  278. }
  279. void RenderBeast::notifyLightUpdated(LightCore* light)
  280. {
  281. UINT32 lightId = light->getRendererId();
  282. if (light->getType() != LightType::Directional)
  283. mLightWorldBounds[lightId] = light->getBounds();
  284. }
  285. void RenderBeast::notifyLightRemoved(LightCore* light)
  286. {
  287. UINT32 lightId = light->getRendererId();
  288. if (light->getType() == LightType::Directional)
  289. {
  290. LightCore* lastLight = mDirectionalLights.back().internal;
  291. UINT32 lastLightId = lastLight->getRendererId();
  292. if (lightId != lastLightId)
  293. {
  294. // Swap current last element with the one we want to erase
  295. std::swap(mDirectionalLights[lightId], mDirectionalLights[lastLightId]);
  296. lastLight->setRendererId(lightId);
  297. }
  298. // Last element is the one we want to erase
  299. mDirectionalLights.erase(mDirectionalLights.end() - 1);
  300. }
  301. else
  302. {
  303. LightCore* lastLight = mPointLights.back().internal;
  304. UINT32 lastLightId = lastLight->getRendererId();
  305. if (lightId != lastLightId)
  306. {
  307. // Swap current last element with the one we want to erase
  308. std::swap(mPointLights[lightId], mPointLights[lastLightId]);
  309. std::swap(mLightWorldBounds[lightId], mLightWorldBounds[lastLightId]);
  310. lastLight->setRendererId(lightId);
  311. }
  312. // Last element is the one we want to erase
  313. mPointLights.erase(mPointLights.end() - 1);
  314. mLightWorldBounds.erase(mLightWorldBounds.end() - 1);
  315. }
  316. }
  317. void RenderBeast::notifyCameraAdded(const CameraCore* camera)
  318. {
  319. RendererCamera* renCamera = updateCameraData(camera);
  320. renCamera->updatePerCameraBuffer();
  321. }
  322. void RenderBeast::notifyCameraUpdated(const CameraCore* camera, UINT32 updateFlag)
  323. {
  324. RendererCamera* rendererCam;
  325. if((updateFlag & (UINT32)CameraDirtyFlag::Everything) != 0)
  326. {
  327. rendererCam = updateCameraData(camera);
  328. }
  329. else if((updateFlag & (UINT32)CameraDirtyFlag::PostProcess) != 0)
  330. {
  331. rendererCam = mCameras[camera];
  332. rendererCam->updatePP();
  333. }
  334. else
  335. rendererCam = mCameras[camera];
  336. rendererCam->updatePerCameraBuffer();
  337. }
  338. void RenderBeast::notifyCameraRemoved(const CameraCore* camera)
  339. {
  340. updateCameraData(camera, true);
  341. }
  342. SPtr<PostProcessSettings> RenderBeast::createPostProcessSettings() const
  343. {
  344. return bs_shared_ptr_new<StandardPostProcessSettings>();
  345. }
  346. RendererCamera* RenderBeast::updateCameraData(const CameraCore* camera, bool forceRemove)
  347. {
  348. RendererCamera* output;
  349. SPtr<RenderTargetCore> renderTarget = camera->getViewport()->getTarget();
  350. if(forceRemove)
  351. {
  352. auto iterFind = mCameras.find(camera);
  353. if(iterFind != mCameras.end())
  354. {
  355. bs_delete(iterFind->second);
  356. mCameras.erase(iterFind);
  357. }
  358. renderTarget = nullptr;
  359. output = nullptr;
  360. }
  361. else
  362. {
  363. output = bs_new<RendererCamera>(camera, mCoreOptions->stateReductionMode);
  364. mCameras[camera] = output;
  365. }
  366. // Remove from render target list
  367. int rtChanged = 0; // 0 - No RT, 1 - RT found, 2 - RT changed
  368. for (auto iterTarget = mRenderTargets.begin(); iterTarget != mRenderTargets.end(); ++iterTarget)
  369. {
  370. RendererRenderTarget& target = *iterTarget;
  371. for (auto iterCam = target.cameras.begin(); iterCam != target.cameras.end(); ++iterCam)
  372. {
  373. if (camera == *iterCam)
  374. {
  375. if (renderTarget != target.target)
  376. {
  377. target.cameras.erase(iterCam);
  378. rtChanged = 2;
  379. }
  380. else
  381. rtChanged = 1;
  382. break;
  383. }
  384. }
  385. if (target.cameras.empty())
  386. {
  387. mRenderTargets.erase(iterTarget);
  388. break;
  389. }
  390. }
  391. // Register in render target list
  392. if (renderTarget != nullptr && (rtChanged == 0 || rtChanged == 2))
  393. {
  394. auto findIter = std::find_if(mRenderTargets.begin(), mRenderTargets.end(),
  395. [&](const RendererRenderTarget& x) { return x.target == renderTarget; });
  396. if (findIter != mRenderTargets.end())
  397. {
  398. findIter->cameras.push_back(camera);
  399. }
  400. else
  401. {
  402. mRenderTargets.push_back(RendererRenderTarget());
  403. RendererRenderTarget& renderTargetData = mRenderTargets.back();
  404. renderTargetData.target = renderTarget;
  405. renderTargetData.cameras.push_back(camera);
  406. }
  407. // Sort render targets based on priority
  408. auto cameraComparer = [&](const CameraCore* a, const CameraCore* b) { return a->getPriority() > b->getPriority(); };
  409. auto renderTargetInfoComparer = [&](const RendererRenderTarget& a, const RendererRenderTarget& b)
  410. { return a.target->getProperties().getPriority() > b.target->getProperties().getPriority(); };
  411. std::sort(begin(mRenderTargets), end(mRenderTargets), renderTargetInfoComparer);
  412. for (auto& camerasPerTarget : mRenderTargets)
  413. {
  414. Vector<const CameraCore*>& cameras = camerasPerTarget.cameras;
  415. std::sort(begin(cameras), end(cameras), cameraComparer);
  416. }
  417. }
  418. return output;
  419. }
  420. void RenderBeast::setOptions(const SPtr<CoreRendererOptions>& options)
  421. {
  422. mOptions = std::static_pointer_cast<RenderBeastOptions>(options);
  423. mOptionsDirty = true;
  424. }
  425. SPtr<CoreRendererOptions> RenderBeast::getOptions() const
  426. {
  427. return mOptions;
  428. }
  429. void RenderBeast::syncOptions(const RenderBeastOptions& options)
  430. {
  431. bool filteringChanged = mCoreOptions->filtering != options.filtering;
  432. if (options.filtering == RenderBeastFiltering::Anisotropic)
  433. filteringChanged |= mCoreOptions->anisotropyMax != options.anisotropyMax;
  434. if (filteringChanged)
  435. refreshSamplerOverrides(true);
  436. *mCoreOptions = options;
  437. for (auto& entry : mCameras)
  438. {
  439. RendererCamera* rendererCam = entry.second;
  440. rendererCam->update(mCoreOptions->stateReductionMode);
  441. }
  442. }
  443. void RenderBeast::renderAll()
  444. {
  445. // Sync all dirty sim thread CoreObject data to core thread
  446. CoreObjectManager::instance().syncToCore();
  447. if (mOptionsDirty)
  448. {
  449. gCoreThread().queueCommand(std::bind(&RenderBeast::syncOptions, this, *mOptions));
  450. mOptionsDirty = false;
  451. }
  452. gCoreThread().queueCommand(std::bind(&RenderBeast::renderAllCore, this, gTime().getTime(), gTime().getFrameDelta()));
  453. }
  454. void RenderBeast::renderAllCore(float time, float delta)
  455. {
  456. THROW_IF_NOT_CORE_THREAD;
  457. gProfilerCPU().beginSample("renderAllCore");
  458. // Note: I'm iterating over all sampler states every frame. If this ends up being a performance
  459. // issue consider handling this internally in MaterialCore which can only do it when sampler states
  460. // are actually modified after sync
  461. refreshSamplerOverrides();
  462. // Update global per-frame hardware buffers
  463. mObjectRenderer->setParamFrameParams(time);
  464. // Generate render queues per camera
  465. mVisibility.assign(mVisibility.size(), false);
  466. for (auto& entry : mCameras)
  467. entry.second->determineVisible(mRenderables, mWorldBounds, mVisibility);
  468. // Retrieve animation data
  469. AnimationManager::instance().waitUntilComplete();
  470. const RendererAnimationData& animData = AnimationManager::instance().getRendererData();
  471. RendererFrame frameInfo(delta, animData);
  472. // Update per-object, bone matrix and morph shape GPU buffers
  473. UINT32 numRenderables = (UINT32)mRenderables.size();
  474. for (UINT32 i = 0; i < numRenderables; i++)
  475. {
  476. if (!mVisibility[i])
  477. continue;
  478. // Note: Before uploading bone matrices perhaps check if they has actually been changed since last frame
  479. mRenderables[i]->renderable->updateAnimationBuffers(animData);
  480. // Note: Could this step be moved in notifyRenderableUpdated, so it only triggers when material actually gets
  481. // changed? Although it shouldn't matter much because if the internal dirty flags.
  482. for (auto& element : mRenderables[i]->elements)
  483. element.material->updateParamsSet(element.params, element.techniqueIdx);
  484. mRenderables[i]->perObjectParams.flushToGPU();
  485. }
  486. // Render everything, target by target
  487. for (auto& rtInfo : mRenderTargets)
  488. {
  489. SPtr<RenderTargetCore> target = rtInfo.target;
  490. Vector<const CameraCore*>& cameras = rtInfo.cameras;
  491. RenderAPICore::instance().beginFrame();
  492. UINT32 numCameras = (UINT32)cameras.size();
  493. for (UINT32 i = 0; i < numCameras; i++)
  494. {
  495. bool isOverlayCamera = cameras[i]->getFlags().isSet(CameraFlag::Overlay);
  496. if (!isOverlayCamera)
  497. render(frameInfo, rtInfo, i);
  498. else
  499. renderOverlay(frameInfo, rtInfo, i);
  500. }
  501. RenderAPICore::instance().endFrame();
  502. RenderAPICore::instance().swapBuffers(target);
  503. }
  504. gProfilerCPU().endSample("renderAllCore");
  505. }
  506. void RenderBeast::render(const RendererFrame& frameInfo, RendererRenderTarget& rtInfo, UINT32 camIdx)
  507. {
  508. gProfilerCPU().beginSample("Render");
  509. const CameraCore* camera = rtInfo.cameras[camIdx];
  510. RendererCamera* rendererCam = mCameras[camera];
  511. PerCameraParamBuffer& parCameraBuffer = rendererCam->getPerCameraBuffer();
  512. parCameraBuffer.flushToGPU();
  513. assert(!camera->getFlags().isSet(CameraFlag::Overlay));
  514. Matrix4 proj = camera->getProjectionMatrixRS();
  515. Matrix4 view = camera->getViewMatrix();
  516. Matrix4 viewProj = proj * view;
  517. // Assign camera and per-call data to all relevant renderables
  518. const Vector<bool>& visibility = rendererCam->getVisibilityMask();
  519. UINT32 numRenderables = (UINT32)mRenderables.size();
  520. for (UINT32 i = 0; i < numRenderables; i++)
  521. {
  522. if (!visibility[i])
  523. continue;
  524. RendererObject* rendererObject = mRenderables[i];
  525. rendererObject->updatePerCallBuffer(viewProj);
  526. for (auto& element : mRenderables[i]->elements)
  527. {
  528. if (element.perCameraBindingIdx != -1)
  529. element.params->setParamBlockBuffer(element.perCameraBindingIdx, parCameraBuffer.getBuffer(), true);
  530. }
  531. }
  532. rendererCam->beginRendering(true);
  533. SPtr<RenderTargets> renderTargets = rendererCam->getRenderTargets();
  534. renderTargets->bindGBuffer();
  535. //// Trigger pre-scene callbacks
  536. auto iterCameraCallbacks = mRenderCallbacks.find(camera);
  537. if (iterCameraCallbacks != mRenderCallbacks.end())
  538. {
  539. for (auto& callbackPair : iterCameraCallbacks->second)
  540. {
  541. const RenderCallbackData& callbackData = callbackPair.second;
  542. if (callbackData.overlay)
  543. continue;
  544. if (callbackPair.first >= 0)
  545. break;
  546. callbackData.callback();
  547. }
  548. }
  549. //// Render base pass
  550. const Vector<RenderQueueElement>& opaqueElements = rendererCam->getOpaqueQueue()->getSortedElements();
  551. for (auto iter = opaqueElements.begin(); iter != opaqueElements.end(); ++iter)
  552. {
  553. BeastRenderableElement* renderElem = static_cast<BeastRenderableElement*>(iter->renderElem);
  554. renderElement(*renderElem, iter->passIdx, iter->applyPass, frameInfo, viewProj);
  555. }
  556. renderTargets->bindSceneColor(true);
  557. //// Render light pass
  558. {
  559. SPtr<GpuParamBlockBufferCore> perCameraBuffer = rendererCam->getPerCameraBuffer().getBuffer();;
  560. mDirLightMat->bind(renderTargets, perCameraBuffer);
  561. for (auto& light : mDirectionalLights)
  562. {
  563. if (!light.internal->getIsActive())
  564. continue;
  565. mDirLightMat->setPerLightParams(light.internal);
  566. gRendererUtility().drawScreenQuad();
  567. }
  568. // Draw point lights which our camera is within
  569. // TODO - Possibly use instanced drawing here as only two meshes are drawn with various properties
  570. mPointLightInMat->bind(renderTargets, perCameraBuffer);
  571. // TODO - Cull lights based on visibility, right now I just iterate over all of them.
  572. for (auto& light : mPointLights)
  573. {
  574. if (!light.internal->getIsActive())
  575. continue;
  576. float distToLight = (light.internal->getBounds().getCenter() - camera->getPosition()).squaredLength();
  577. float boundRadius = light.internal->getBounds().getRadius() * 1.05f + camera->getNearClipDistance() * 2.0f;
  578. bool cameraInLightGeometry = distToLight < boundRadius * boundRadius;
  579. if (!cameraInLightGeometry)
  580. continue;
  581. mPointLightInMat->setPerLightParams(light.internal);
  582. SPtr<MeshCore> mesh = light.internal->getMesh();
  583. gRendererUtility().draw(mesh, mesh->getProperties().getSubMesh(0));
  584. }
  585. // Draw other point lights
  586. mPointLightOutMat->bind(renderTargets, perCameraBuffer);
  587. for (auto& light : mPointLights)
  588. {
  589. if (!light.internal->getIsActive())
  590. continue;
  591. float distToLight = (light.internal->getBounds().getCenter() - camera->getPosition()).squaredLength();
  592. float boundRadius = light.internal->getBounds().getRadius() * 1.05f + camera->getNearClipDistance() * 2.0f;
  593. bool cameraInLightGeometry = distToLight < boundRadius * boundRadius;
  594. if (cameraInLightGeometry)
  595. continue;
  596. mPointLightOutMat->setPerLightParams(light.internal);
  597. SPtr<MeshCore> mesh = light.internal->getMesh();
  598. gRendererUtility().draw(mesh, mesh->getProperties().getSubMesh(0));
  599. }
  600. }
  601. renderTargets->bindSceneColor(false);
  602. // Render transparent objects (TODO - No lighting yet)
  603. const Vector<RenderQueueElement>& transparentElements = rendererCam->getTransparentQueue()->getSortedElements();
  604. for (auto iter = transparentElements.begin(); iter != transparentElements.end(); ++iter)
  605. {
  606. BeastRenderableElement* renderElem = static_cast<BeastRenderableElement*>(iter->renderElem);
  607. renderElement(*renderElem, iter->passIdx, iter->applyPass, frameInfo, viewProj);
  608. }
  609. // Render non-overlay post-scene callbacks
  610. if (iterCameraCallbacks != mRenderCallbacks.end())
  611. {
  612. for (auto& callbackPair : iterCameraCallbacks->second)
  613. {
  614. const RenderCallbackData& callbackData = callbackPair.second;
  615. if (callbackData.overlay || callbackPair.first < 0)
  616. continue;
  617. callbackData.callback();
  618. }
  619. }
  620. // TODO - If GBuffer has multiple samples, I should resolve them before post-processing
  621. PostProcessing::instance().postProcess(renderTargets->getSceneColorRT(),
  622. camera, rendererCam->getPPInfo(), frameInfo.delta);
  623. // Render overlay post-scene callbacks
  624. if (iterCameraCallbacks != mRenderCallbacks.end())
  625. {
  626. for (auto& callbackPair : iterCameraCallbacks->second)
  627. {
  628. const RenderCallbackData& callbackData = callbackPair.second;
  629. if (!callbackData.overlay)
  630. continue;
  631. callbackData.callback();
  632. }
  633. }
  634. rendererCam->endRendering();
  635. gProfilerCPU().endSample("Render");
  636. }
  637. void RenderBeast::renderOverlay(const RendererFrame& frameInfo, RendererRenderTarget& rtData, UINT32 camIdx)
  638. {
  639. gProfilerCPU().beginSample("RenderOverlay");
  640. const CameraCore* camera = rtData.cameras[camIdx];
  641. assert(camera->getFlags().isSet(CameraFlag::Overlay));
  642. SPtr<ViewportCore> viewport = camera->getViewport();
  643. RendererCamera* rendererCam = mCameras[camera];
  644. rendererCam->getPerCameraBuffer().flushToGPU();
  645. rendererCam->beginRendering(false);
  646. SPtr<RenderTargetCore> target = rtData.target;
  647. RenderAPICore::instance().setRenderTarget(target);
  648. RenderAPICore::instance().setViewport(viewport->getNormArea());
  649. // If first camera in render target, prepare the render target
  650. if (camIdx == 0)
  651. {
  652. UINT32 clearBuffers = 0;
  653. if (viewport->getRequiresColorClear())
  654. clearBuffers |= FBT_COLOR;
  655. if (viewport->getRequiresDepthClear())
  656. clearBuffers |= FBT_DEPTH;
  657. if (viewport->getRequiresStencilClear())
  658. clearBuffers |= FBT_STENCIL;
  659. if (clearBuffers != 0)
  660. {
  661. RenderAPICore::instance().clearViewport(clearBuffers, viewport->getClearColor(),
  662. viewport->getClearDepthValue(), viewport->getClearStencilValue());
  663. }
  664. }
  665. // Render overlay post-scene callbacks
  666. auto iterCameraCallbacks = mRenderCallbacks.find(camera);
  667. if (iterCameraCallbacks != mRenderCallbacks.end())
  668. {
  669. for (auto& callbackPair : iterCameraCallbacks->second)
  670. {
  671. const RenderCallbackData& callbackData = callbackPair.second;
  672. if (!callbackData.overlay)
  673. continue;
  674. callbackData.callback();
  675. }
  676. }
  677. rendererCam->endRendering();
  678. gProfilerCPU().endSample("RenderOverlay");
  679. }
  680. void RenderBeast::renderElement(const BeastRenderableElement& element, UINT32 passIdx, bool bindPass,
  681. const RendererFrame& frameInfo, const Matrix4& viewProj)
  682. {
  683. SPtr<MaterialCore> material = element.material;
  684. if (bindPass)
  685. gRendererUtility().setPass(material, passIdx, element.techniqueIdx);
  686. gRendererUtility().setPassParams(element.params, passIdx);
  687. if(element.morphVertexDeclaration == nullptr)
  688. gRendererUtility().draw(element.mesh, element.subMesh);
  689. else
  690. gRendererUtility().drawMorph(element.mesh, element.subMesh, element.morphShapeBuffer,
  691. element.morphVertexDeclaration);
  692. }
  693. void RenderBeast::refreshSamplerOverrides(bool force)
  694. {
  695. bool anyDirty = false;
  696. for (auto& entry : mSamplerOverrides)
  697. {
  698. SPtr<MaterialParamsCore> materialParams = entry.first.material->_getInternalParams();
  699. MaterialSamplerOverrides* materialOverrides = entry.second;
  700. for(UINT32 i = 0; i < materialOverrides->numOverrides; i++)
  701. {
  702. SamplerOverride& override = materialOverrides->overrides[i];
  703. const MaterialParamsBase::ParamData* materialParamData = materialParams->getParamData(override.paramIdx);
  704. SPtr<SamplerStateCore> samplerState;
  705. materialParams->getSamplerState(materialParamData->index, samplerState);
  706. UINT64 hash = 0;
  707. if (samplerState != nullptr)
  708. hash = samplerState->getProperties().getHash();
  709. if (hash != override.originalStateHash || force)
  710. {
  711. if (samplerState != nullptr)
  712. override.state = SamplerOverrideUtility::generateSamplerOverride(samplerState, mCoreOptions);
  713. else
  714. override.state = SamplerOverrideUtility::generateSamplerOverride(SamplerStateCore::getDefault(), mCoreOptions);
  715. override.originalStateHash = override.state->getProperties().getHash();
  716. materialOverrides->isDirty = true;
  717. }
  718. // Dirty flag can also be set externally, so check here even though we assign it above
  719. if (materialOverrides->isDirty)
  720. anyDirty = true;
  721. }
  722. }
  723. // Early exit if possible
  724. if (!anyDirty)
  725. return;
  726. UINT32 numRenderables = (UINT32)mRenderables.size();
  727. for (UINT32 i = 0; i < numRenderables; i++)
  728. {
  729. for(auto& element : mRenderables[i]->elements)
  730. {
  731. MaterialSamplerOverrides* overrides = element.samplerOverrides;
  732. if(overrides != nullptr && overrides->isDirty)
  733. {
  734. UINT32 numPasses = element.material->getNumPasses();
  735. for(UINT32 j = 0; j < numPasses; j++)
  736. {
  737. SPtr<GpuParamsCore> params = element.params->getGpuParams(j);
  738. const UINT32 numStages = 6;
  739. for (UINT32 k = 0; k < numStages; k++)
  740. {
  741. GpuProgramType type = (GpuProgramType)k;
  742. SPtr<GpuParamDesc> paramDesc = params->getParamDesc(type);
  743. if (paramDesc == nullptr)
  744. continue;
  745. for (auto& samplerDesc : paramDesc->samplers)
  746. {
  747. UINT32 set = samplerDesc.second.set;
  748. UINT32 slot = samplerDesc.second.slot;
  749. UINT32 overrideIndex = overrides->passes[j].stateOverrides[set][slot];
  750. if (overrideIndex == (UINT32)-1)
  751. continue;
  752. params->setSamplerState(set, slot, overrides->overrides[overrideIndex].state);
  753. }
  754. }
  755. }
  756. }
  757. }
  758. }
  759. for (auto& entry : mSamplerOverrides)
  760. entry.second->isDirty = false;
  761. }
  762. }