BsRenderBeast.cpp 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136
  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 "BsBlendState.h"
  10. #include "BsRasterizerState.h"
  11. #include "BsDepthStencilState.h"
  12. #include "BsSamplerState.h"
  13. #include "BsCoreApplication.h"
  14. #include "BsViewport.h"
  15. #include "BsRenderTarget.h"
  16. #include "BsRenderQueue.h"
  17. #include "BsCoreThread.h"
  18. #include "BsGpuParams.h"
  19. #include "BsProfilerCPU.h"
  20. #include "BsShader.h"
  21. #include "BsGpuParamBlockBuffer.h"
  22. #include "BsStaticRenderableHandler.h"
  23. #include "BsTime.h"
  24. #include "BsRenderableElement.h"
  25. #include "BsCoreObjectManager.h"
  26. #include "BsRenderBeastOptions.h"
  27. #include "BsSamplerOverrides.h"
  28. #include "BsLight.h"
  29. #include "BsRenderTexturePool.h"
  30. #include "BsRenderTargets.h"
  31. #include "BsRendererUtility.h"
  32. #include "BsRenderStateManager.h"
  33. using namespace std::placeholders;
  34. namespace BansheeEngine
  35. {
  36. RenderBeast::RenderBeast()
  37. : mDefaultMaterial(nullptr), mPointLightInMat(nullptr), mPointLightOutMat(nullptr), mDirLightMat(nullptr)
  38. , mStaticHandler(nullptr), mOptions(bs_shared_ptr_new<RenderBeastOptions>()), mOptionsDirty(true)
  39. {
  40. }
  41. const StringID& RenderBeast::getName() const
  42. {
  43. static StringID name = "RenderBeast";
  44. return name;
  45. }
  46. void RenderBeast::initialize()
  47. {
  48. CoreRenderer::initialize();
  49. CoreThread::instance().queueCommand(std::bind(&RenderBeast::initializeCore, this));
  50. }
  51. void RenderBeast::destroy()
  52. {
  53. CoreRenderer::destroy();
  54. gCoreAccessor().queueCommand(std::bind(&RenderBeast::destroyCore, this));
  55. gCoreAccessor().submitToCoreThread(true);
  56. }
  57. void RenderBeast::initializeCore()
  58. {
  59. RendererUtility::startUp();
  60. mCoreOptions = bs_shared_ptr_new<RenderBeastOptions>();
  61. mStaticHandler = bs_new<StaticRenderableHandler>();
  62. mDefaultMaterial = bs_new<DefaultMaterial>();
  63. mPointLightInMat = bs_new<PointLightInMat>();
  64. mPointLightOutMat = bs_new<PointLightOutMat>();
  65. mDirLightMat = bs_new<DirectionalLightMat>();
  66. RenderTexturePool::startUp();
  67. PostProcessing::startUp();
  68. }
  69. void RenderBeast::destroyCore()
  70. {
  71. if (mStaticHandler != nullptr)
  72. bs_delete(mStaticHandler);
  73. mRenderTargets.clear();
  74. mCameraData.clear();
  75. mRenderables.clear();
  76. PostProcessing::shutDown();
  77. RenderTexturePool::shutDown();
  78. bs_delete(mDefaultMaterial);
  79. bs_delete(mPointLightInMat);
  80. bs_delete(mPointLightOutMat);
  81. bs_delete(mDirLightMat);
  82. RendererUtility::shutDown();
  83. assert(mSamplerOverrides.empty());
  84. }
  85. void RenderBeast::notifyRenderableAdded(RenderableCore* renderable)
  86. {
  87. UINT32 renderableId = (UINT32)mRenderables.size();
  88. renderable->setRendererId(renderableId);
  89. mRenderables.push_back(RenderableData());
  90. mRenderableShaderData.push_back(RenderableShaderData());
  91. mWorldBounds.push_back(renderable->getBounds());
  92. RenderableData& renderableData = mRenderables.back();
  93. renderableData.renderable = renderable;
  94. RenderableShaderData& shaderData = mRenderableShaderData.back();
  95. shaderData.worldTransform = renderable->getTransform();
  96. shaderData.invWorldTransform = shaderData.worldTransform.inverseAffine();
  97. shaderData.worldNoScaleTransform = renderable->getTransformNoScale();
  98. shaderData.invWorldNoScaleTransform = shaderData.worldNoScaleTransform.inverseAffine();
  99. shaderData.worldDeterminantSign = shaderData.worldTransform.determinant3x3() >= 0.0f ? 1.0f : -1.0f;
  100. if (renderable->getRenderableType() == RenType_LitTextured)
  101. renderableData.controller = mStaticHandler;
  102. else
  103. renderableData.controller = nullptr;
  104. SPtr<MeshCore> mesh = renderable->getMesh();
  105. if (mesh != nullptr)
  106. {
  107. const MeshProperties& meshProps = mesh->getProperties();
  108. SPtr<VertexDeclarationCore> vertexDecl = mesh->getVertexData()->vertexDeclaration;
  109. for (UINT32 i = 0; i < meshProps.getNumSubMeshes(); i++)
  110. {
  111. renderableData.elements.push_back(BeastRenderableElement());
  112. BeastRenderableElement& renElement = renderableData.elements.back();
  113. renElement.mesh = mesh;
  114. renElement.subMesh = meshProps.getSubMesh(i);
  115. renElement.renderableId = renderableId;
  116. renElement.material = renderable->getMaterial(i);
  117. if (renElement.material == nullptr)
  118. renElement.material = renderable->getMaterial(0);
  119. if (renElement.material != nullptr && renElement.material->getShader() == nullptr)
  120. renElement.material = nullptr;
  121. // Validate mesh <-> shader vertex bindings
  122. if (renElement.material != nullptr)
  123. {
  124. UINT32 numPasses = renElement.material->getNumPasses();
  125. for (UINT32 j = 0; j < numPasses; j++)
  126. {
  127. SPtr<PassCore> pass = renElement.material->getPass(j);
  128. SPtr<VertexDeclarationCore> shaderDecl = pass->getVertexProgram()->getInputDeclaration();
  129. if (!vertexDecl->isCompatible(shaderDecl))
  130. {
  131. Vector<VertexElement> missingElements = vertexDecl->getMissingElements(shaderDecl);
  132. StringStream wrnStream;
  133. wrnStream << "Provided mesh is missing required vertex attributes to render with the provided shader. Missing elements: " << std::endl;
  134. for (auto& entry : missingElements)
  135. wrnStream << "\t" << toString(entry.getSemantic()) << entry.getSemanticIdx() << std::endl;
  136. LOGWRN(wrnStream.str());
  137. break;
  138. }
  139. }
  140. }
  141. // If no material use the default material
  142. if (renElement.material == nullptr)
  143. renElement.material = mDefaultMaterial->getMaterial();
  144. auto iterFind = mSamplerOverrides.find(renElement.material);
  145. if (iterFind != mSamplerOverrides.end())
  146. {
  147. renElement.samplerOverrides = iterFind->second;
  148. iterFind->second->refCount++;
  149. }
  150. else
  151. {
  152. MaterialSamplerOverrides* samplerOverrides = SamplerOverrideUtility::generateSamplerOverrides(renElement.material, mCoreOptions);
  153. mSamplerOverrides[renElement.material] = samplerOverrides;
  154. renElement.samplerOverrides = samplerOverrides;
  155. samplerOverrides->refCount++;
  156. }
  157. if (renderableData.controller != nullptr)
  158. renderableData.controller->initializeRenderElem(renElement);
  159. }
  160. }
  161. }
  162. void RenderBeast::notifyRenderableRemoved(RenderableCore* renderable)
  163. {
  164. UINT32 renderableId = renderable->getRendererId();
  165. RenderableCore* lastRenerable = mRenderables.back().renderable;
  166. UINT32 lastRenderableId = lastRenerable->getRendererId();
  167. Vector<BeastRenderableElement>& elements = mRenderables[renderableId].elements;
  168. for (auto& element : elements)
  169. {
  170. auto iterFind = mSamplerOverrides.find(element.material);
  171. assert(iterFind != mSamplerOverrides.end());
  172. MaterialSamplerOverrides* samplerOverrides = iterFind->second;
  173. samplerOverrides->refCount--;
  174. if (samplerOverrides->refCount == 0)
  175. {
  176. SamplerOverrideUtility::destroySamplerOverrides(samplerOverrides);
  177. mSamplerOverrides.erase(iterFind);
  178. }
  179. element.samplerOverrides = nullptr;
  180. }
  181. if (renderableId != lastRenderableId)
  182. {
  183. // Swap current last element with the one we want to erase
  184. std::swap(mRenderables[renderableId], mRenderables[lastRenderableId]);
  185. std::swap(mWorldBounds[renderableId], mWorldBounds[lastRenderableId]);
  186. std::swap(mRenderableShaderData[renderableId], mRenderableShaderData[lastRenderableId]);
  187. lastRenerable->setRendererId(renderableId);
  188. for (auto& element : elements)
  189. element.renderableId = renderableId;
  190. }
  191. // Last element is the one we want to erase
  192. mRenderables.erase(mRenderables.end() - 1);
  193. mWorldBounds.erase(mWorldBounds.end() - 1);
  194. mRenderableShaderData.erase(mRenderableShaderData.end() - 1);
  195. }
  196. void RenderBeast::notifyRenderableUpdated(RenderableCore* renderable)
  197. {
  198. UINT32 renderableId = renderable->getRendererId();
  199. RenderableShaderData& shaderData = mRenderableShaderData[renderableId];
  200. shaderData.worldTransform = renderable->getTransform();
  201. shaderData.invWorldTransform = shaderData.worldTransform.inverseAffine();
  202. shaderData.worldNoScaleTransform = renderable->getTransformNoScale();
  203. shaderData.invWorldNoScaleTransform = shaderData.worldNoScaleTransform.inverseAffine();
  204. shaderData.worldDeterminantSign = shaderData.worldTransform.determinant3x3() >= 0.0f ? 1.0f : -1.0f;
  205. mWorldBounds[renderableId] = renderable->getBounds();
  206. }
  207. void RenderBeast::notifyLightAdded(LightCore* light)
  208. {
  209. if (light->getType() == LightType::Directional)
  210. {
  211. UINT32 lightId = (UINT32)mDirectionalLights.size();
  212. light->setRendererId(lightId);
  213. mDirectionalLights.push_back(LightData());
  214. LightData& lightData = mDirectionalLights.back();
  215. lightData.internal = light;
  216. }
  217. else
  218. {
  219. UINT32 lightId = (UINT32)mPointLights.size();
  220. light->setRendererId(lightId);
  221. mPointLights.push_back(LightData());
  222. mLightWorldBounds.push_back(light->getBounds());
  223. LightData& lightData = mPointLights.back();
  224. lightData.internal = light;
  225. }
  226. }
  227. void RenderBeast::notifyLightUpdated(LightCore* light)
  228. {
  229. UINT32 lightId = light->getRendererId();
  230. if (light->getType() != LightType::Directional)
  231. mLightWorldBounds[lightId] = light->getBounds();
  232. }
  233. void RenderBeast::notifyLightRemoved(LightCore* light)
  234. {
  235. UINT32 lightId = light->getRendererId();
  236. if (light->getType() == LightType::Directional)
  237. {
  238. LightCore* lastLight = mDirectionalLights.back().internal;
  239. UINT32 lastLightId = lastLight->getRendererId();
  240. if (lightId != lastLightId)
  241. {
  242. // Swap current last element with the one we want to erase
  243. std::swap(mDirectionalLights[lightId], mDirectionalLights[lastLightId]);
  244. lastLight->setRendererId(lightId);
  245. }
  246. // Last element is the one we want to erase
  247. mDirectionalLights.erase(mDirectionalLights.end() - 1);
  248. }
  249. else
  250. {
  251. LightCore* lastLight = mPointLights.back().internal;
  252. UINT32 lastLightId = lastLight->getRendererId();
  253. if (lightId != lastLightId)
  254. {
  255. // Swap current last element with the one we want to erase
  256. std::swap(mPointLights[lightId], mPointLights[lastLightId]);
  257. std::swap(mLightWorldBounds[lightId], mLightWorldBounds[lastLightId]);
  258. lastLight->setRendererId(lightId);
  259. }
  260. // Last element is the one we want to erase
  261. mPointLights.erase(mPointLights.end() - 1);
  262. mLightWorldBounds.erase(mLightWorldBounds.end() - 1);
  263. }
  264. }
  265. void RenderBeast::notifyCameraAdded(const CameraCore* camera)
  266. {
  267. updateCameraData(camera);
  268. }
  269. void RenderBeast::notifyCameraUpdated(const CameraCore* camera, UINT32 updateFlag)
  270. {
  271. if((updateFlag & (UINT32)CameraDirtyFlag::Everything) != 0)
  272. {
  273. updateCameraData(camera);
  274. }
  275. else if((updateFlag & (UINT32)CameraDirtyFlag::PostProcess) != 0)
  276. {
  277. CameraData& camData = mCameraData[camera];
  278. camData.postProcessInfo.settings = camera->getPostProcessSettings();
  279. camData.postProcessInfo.settingDirty = true;
  280. }
  281. }
  282. void RenderBeast::notifyCameraRemoved(const CameraCore* camera)
  283. {
  284. updateCameraData(camera, true);
  285. }
  286. void RenderBeast::updateCameraData(const CameraCore* camera, bool forceRemove)
  287. {
  288. SPtr<RenderTargetCore> renderTarget = camera->getViewport()->getTarget();
  289. if(forceRemove)
  290. {
  291. mCameraData.erase(camera);
  292. renderTarget = nullptr;
  293. }
  294. else
  295. {
  296. CameraData& camData = mCameraData[camera];
  297. camData.opaqueQueue = bs_shared_ptr_new<RenderQueue>(mCoreOptions->stateReductionMode);
  298. StateReduction transparentStateReduction = mCoreOptions->stateReductionMode;
  299. if (transparentStateReduction == StateReduction::Material)
  300. transparentStateReduction = StateReduction::Distance; // Transparent object MUST be sorted by distance
  301. camData.transparentQueue = bs_shared_ptr_new<RenderQueue>(transparentStateReduction);
  302. camData.postProcessInfo.settings = camera->getPostProcessSettings();
  303. camData.postProcessInfo.settingDirty = true;
  304. }
  305. // Remove from render target list
  306. int rtChanged = 0; // 0 - No RT, 1 - RT found, 2 - RT changed
  307. for (auto iterTarget = mRenderTargets.begin(); iterTarget != mRenderTargets.end(); ++iterTarget)
  308. {
  309. RenderTargetData& target = *iterTarget;
  310. for (auto iterCam = target.cameras.begin(); iterCam != target.cameras.end(); ++iterCam)
  311. {
  312. if (camera == *iterCam)
  313. {
  314. if (renderTarget != target.target)
  315. {
  316. target.cameras.erase(iterCam);
  317. rtChanged = 2;
  318. }
  319. else
  320. rtChanged = 1;
  321. break;
  322. }
  323. }
  324. if (target.cameras.empty())
  325. {
  326. mRenderTargets.erase(iterTarget);
  327. break;
  328. }
  329. }
  330. // Register in render target list
  331. if (renderTarget != nullptr && (rtChanged == 0 || rtChanged == 2))
  332. {
  333. auto findIter = std::find_if(mRenderTargets.begin(), mRenderTargets.end(),
  334. [&](const RenderTargetData& x) { return x.target == renderTarget; });
  335. if (findIter != mRenderTargets.end())
  336. {
  337. findIter->cameras.push_back(camera);
  338. }
  339. else
  340. {
  341. mRenderTargets.push_back(RenderTargetData());
  342. RenderTargetData& renderTargetData = mRenderTargets.back();
  343. renderTargetData.target = renderTarget;
  344. renderTargetData.cameras.push_back(camera);
  345. }
  346. // Sort render targets based on priority
  347. auto cameraComparer = [&](const CameraCore* a, const CameraCore* b) { return a->getPriority() > b->getPriority(); };
  348. auto renderTargetInfoComparer = [&](const RenderTargetData& a, const RenderTargetData& b)
  349. { return a.target->getProperties().getPriority() > b.target->getProperties().getPriority(); };
  350. std::sort(begin(mRenderTargets), end(mRenderTargets), renderTargetInfoComparer);
  351. for (auto& camerasPerTarget : mRenderTargets)
  352. {
  353. Vector<const CameraCore*>& cameras = camerasPerTarget.cameras;
  354. std::sort(begin(cameras), end(cameras), cameraComparer);
  355. }
  356. }
  357. }
  358. void RenderBeast::setOptions(const SPtr<CoreRendererOptions>& options)
  359. {
  360. mOptions = std::static_pointer_cast<RenderBeastOptions>(options);
  361. mOptionsDirty = true;
  362. }
  363. SPtr<CoreRendererOptions> RenderBeast::getOptions() const
  364. {
  365. return mOptions;
  366. }
  367. void RenderBeast::renderAll()
  368. {
  369. // Sync all dirty sim thread CoreObject data to core thread
  370. CoreObjectManager::instance().syncToCore(gCoreAccessor());
  371. if (mOptionsDirty)
  372. {
  373. gCoreAccessor().queueCommand(std::bind(&RenderBeast::syncRenderOptions, this, *mOptions));
  374. mOptionsDirty = false;
  375. }
  376. gCoreAccessor().queueCommand(std::bind(&RenderBeast::renderAllCore, this, gTime().getTime(), gTime().getFrameDelta()));
  377. }
  378. void RenderBeast::syncRenderOptions(const RenderBeastOptions& options)
  379. {
  380. bool filteringChanged = mCoreOptions->filtering != options.filtering;
  381. if (options.filtering == RenderBeastFiltering::Anisotropic)
  382. filteringChanged |= mCoreOptions->anisotropyMax != options.anisotropyMax;
  383. if (filteringChanged)
  384. refreshSamplerOverrides(true);
  385. *mCoreOptions = options;
  386. for (auto& cameraData : mCameraData)
  387. {
  388. cameraData.second.opaqueQueue->setStateReduction(mCoreOptions->stateReductionMode);
  389. StateReduction transparentStateReduction = mCoreOptions->stateReductionMode;
  390. if (transparentStateReduction == StateReduction::Material)
  391. transparentStateReduction = StateReduction::Distance; // Transparent object MUST be sorted by distance
  392. cameraData.second.transparentQueue->setStateReduction(transparentStateReduction);
  393. }
  394. }
  395. void RenderBeast::renderAllCore(float time, float delta)
  396. {
  397. THROW_IF_NOT_CORE_THREAD;
  398. gProfilerCPU().beginSample("renderAllCore");
  399. // Note: I'm iterating over all sampler states every frame. If this ends up being a performance
  400. // issue consider handling this internally in MaterialCore which can only do it when sampler states
  401. // are actually modified after sync
  402. refreshSamplerOverrides();
  403. // Update global per-frame hardware buffers
  404. mStaticHandler->updatePerFrameBuffers(time);
  405. // Generate render queues per camera
  406. for (auto& cameraData : mCameraData)
  407. {
  408. const CameraCore* camera = cameraData.first;
  409. determineVisible(*camera);
  410. }
  411. // Render everything, target by target
  412. for (auto& renderTargetData : mRenderTargets)
  413. {
  414. SPtr<RenderTargetCore> target = renderTargetData.target;
  415. Vector<const CameraCore*>& cameras = renderTargetData.cameras;
  416. RenderAPICore::instance().beginFrame();
  417. UINT32 numCameras = (UINT32)cameras.size();
  418. for (UINT32 i = 0; i < numCameras; i++)
  419. {
  420. bool isOverlayCamera = cameras[i]->getFlags().isSet(CameraFlag::Overlay);
  421. if (!isOverlayCamera)
  422. render(renderTargetData, i, delta);
  423. else
  424. renderOverlay(renderTargetData, i, delta);
  425. }
  426. RenderAPICore::instance().endFrame();
  427. RenderAPICore::instance().swapBuffers(target);
  428. }
  429. gProfilerCPU().endSample("renderAllCore");
  430. }
  431. void RenderBeast::render(RenderTargetData& rtData, UINT32 camIdx, float delta)
  432. {
  433. gProfilerCPU().beginSample("Render");
  434. const CameraCore* camera = rtData.cameras[camIdx];
  435. CameraData& camData = mCameraData[camera];
  436. SPtr<ViewportCore> viewport = camera->getViewport();
  437. CameraShaderData cameraShaderData = getCameraShaderData(*camera);
  438. assert(!camera->getFlags().isSet(CameraFlag::Overlay));
  439. mStaticHandler->updatePerCameraBuffers(cameraShaderData);
  440. bool useHDR = camera->getFlags().isSet(CameraFlag::HDR);
  441. UINT32 msaaCount = camera->getMSAACount();
  442. // Render scene objects to g-buffer
  443. bool createGBuffer = camData.target == nullptr ||
  444. camData.target->getHDR() != useHDR ||
  445. camData.target->getNumSamples() != msaaCount;
  446. if (createGBuffer)
  447. camData.target = RenderTargets::create(viewport, useHDR, msaaCount);
  448. camData.target->allocate();
  449. camData.target->bindGBuffer();
  450. // Trigger pre-scene callbacks
  451. auto iterCameraCallbacks = mRenderCallbacks.find(camera);
  452. if (iterCameraCallbacks != mRenderCallbacks.end())
  453. {
  454. for (auto& callbackPair : iterCameraCallbacks->second)
  455. {
  456. const RenderCallbackData& callbackData = callbackPair.second;
  457. if (callbackData.overlay)
  458. continue;
  459. if (callbackPair.first >= 0)
  460. break;
  461. callbackData.callback();
  462. }
  463. }
  464. // Render base pass
  465. const Vector<RenderQueueElement>& opaqueElements = camData.opaqueQueue->getSortedElements();
  466. for (auto iter = opaqueElements.begin(); iter != opaqueElements.end(); ++iter)
  467. {
  468. BeastRenderableElement* renderElem = static_cast<BeastRenderableElement*>(iter->renderElem);
  469. SPtr<MaterialCore> material = renderElem->material;
  470. UINT32 rendererId = renderElem->renderableId;
  471. Matrix4 worldViewProjMatrix = cameraShaderData.viewProj * mRenderableShaderData[rendererId].worldTransform;
  472. mStaticHandler->updatePerObjectBuffers(*renderElem, mRenderableShaderData[rendererId], worldViewProjMatrix);
  473. mStaticHandler->bindGlobalBuffers(*renderElem); // Note: If I can keep global buffer slot indexes the same between shaders I could only bind these once
  474. mStaticHandler->bindPerObjectBuffers(*renderElem);
  475. if (iter->applyPass)
  476. {
  477. SPtr<PassCore> pass = material->getPass(iter->passIdx);
  478. setPass(pass);
  479. }
  480. SPtr<PassParametersCore> passParams = material->getPassParameters(iter->passIdx);
  481. if (renderElem->samplerOverrides != nullptr)
  482. setPassParams(passParams, &renderElem->samplerOverrides->passes[iter->passIdx]);
  483. else
  484. setPassParams(passParams, nullptr);
  485. gRendererUtility().draw(iter->renderElem->mesh, iter->renderElem->subMesh);
  486. }
  487. camData.target->bindSceneColor(true);
  488. // Render light pass
  489. {
  490. SPtr<GpuParamBlockBufferCore> perCameraBuffer = mStaticHandler->getPerCameraParams().getBuffer();
  491. SPtr<MaterialCore> dirMaterial = mDirLightMat->getMaterial();
  492. SPtr<PassCore> dirPass = dirMaterial->getPass(0);
  493. setPass(dirPass);
  494. mDirLightMat->setStaticParameters(camData.target, perCameraBuffer);
  495. for (auto& light : mDirectionalLights)
  496. {
  497. if (!light.internal->getIsActive())
  498. continue;
  499. mDirLightMat->setParameters(light.internal);
  500. // TODO - Bind parameters to the pipeline manually as I don't need to re-bind gbuffer textures for every light
  501. // - I can't think of a good way to do this automatically. Probably best to do it in setParameters()
  502. setPassParams(dirMaterial->getPassParameters(0), nullptr);
  503. gRendererUtility().drawScreenQuad();
  504. }
  505. // Draw point lights which our camera is within
  506. SPtr<MaterialCore> pointInsideMaterial = mPointLightInMat->getMaterial();
  507. SPtr<PassCore> pointInsidePass = pointInsideMaterial->getPass(0);
  508. // TODO - Possibly use instanced drawing here as only two meshes are drawn with various properties
  509. setPass(pointInsidePass);
  510. mPointLightInMat->setStaticParameters(camData.target, perCameraBuffer);
  511. // TODO - Cull lights based on visibility, right now I just iterate over all of them.
  512. for (auto& light : mPointLights)
  513. {
  514. if (!light.internal->getIsActive())
  515. continue;
  516. float distToLight = (light.internal->getBounds().getCenter() - camera->getPosition()).squaredLength();
  517. float boundRadius = light.internal->getBounds().getRadius() * 1.05f + camera->getNearClipDistance() * 2.0f;
  518. bool cameraInLightGeometry = distToLight < boundRadius * boundRadius;
  519. if (!cameraInLightGeometry)
  520. continue;
  521. mPointLightInMat->setParameters(light.internal);
  522. // TODO - Bind parameters to the pipeline manually as I don't need to re-bind gbuffer textures for every light
  523. // - I can't think of a good way to do this automatically. Probably best to do it in setParameters()
  524. setPassParams(pointInsideMaterial->getPassParameters(0), nullptr);
  525. SPtr<MeshCore> mesh = light.internal->getMesh();
  526. gRendererUtility().draw(mesh, mesh->getProperties().getSubMesh(0));
  527. }
  528. // Draw other point lights
  529. SPtr<MaterialCore> pointOutsideMaterial = mPointLightOutMat->getMaterial();
  530. SPtr<PassCore> pointOutsidePass = pointOutsideMaterial->getPass(0);
  531. setPass(pointOutsidePass);
  532. mPointLightOutMat->setStaticParameters(camData.target, perCameraBuffer);
  533. for (auto& light : mPointLights)
  534. {
  535. if (!light.internal->getIsActive())
  536. continue;
  537. float distToLight = (light.internal->getBounds().getCenter() - camera->getPosition()).squaredLength();
  538. float boundRadius = light.internal->getBounds().getRadius() * 1.05f + camera->getNearClipDistance() * 2.0f;
  539. bool cameraInLightGeometry = distToLight < boundRadius * boundRadius;
  540. if (cameraInLightGeometry)
  541. continue;
  542. mPointLightOutMat->setParameters(light.internal);
  543. // TODO - Bind parameters to the pipeline manually as I don't need to re-bind gbuffer textures for every light
  544. setPassParams(pointOutsideMaterial->getPassParameters(0), nullptr);
  545. SPtr<MeshCore> mesh = light.internal->getMesh();
  546. gRendererUtility().draw(mesh, mesh->getProperties().getSubMesh(0));
  547. }
  548. }
  549. camData.target->bindSceneColor(false);
  550. // Render transparent objects (TODO - No lighting yet)
  551. const Vector<RenderQueueElement>& transparentElements = camData.transparentQueue->getSortedElements();
  552. for (auto iter = transparentElements.begin(); iter != transparentElements.end(); ++iter)
  553. {
  554. BeastRenderableElement* renderElem = static_cast<BeastRenderableElement*>(iter->renderElem);
  555. SPtr<MaterialCore> material = renderElem->material;
  556. UINT32 rendererId = renderElem->renderableId;
  557. Matrix4 worldViewProjMatrix = cameraShaderData.viewProj * mRenderableShaderData[rendererId].worldTransform;
  558. mStaticHandler->updatePerObjectBuffers(*renderElem, mRenderableShaderData[rendererId], worldViewProjMatrix);
  559. mStaticHandler->bindGlobalBuffers(*renderElem); // Note: If I can keep global buffer slot indexes the same between shaders I could only bind these once
  560. mStaticHandler->bindPerObjectBuffers(*renderElem);
  561. if (iter->applyPass)
  562. {
  563. SPtr<PassCore> pass = material->getPass(iter->passIdx);
  564. setPass(pass);
  565. }
  566. SPtr<PassParametersCore> passParams = material->getPassParameters(iter->passIdx);
  567. if (renderElem->samplerOverrides != nullptr)
  568. setPassParams(passParams, &renderElem->samplerOverrides->passes[iter->passIdx]);
  569. else
  570. setPassParams(passParams, nullptr);
  571. gRendererUtility().draw(iter->renderElem->mesh, iter->renderElem->subMesh);
  572. }
  573. camData.opaqueQueue->clear();
  574. camData.transparentQueue->clear();
  575. // Render non-overlay post-scene callbacks
  576. if (iterCameraCallbacks != mRenderCallbacks.end())
  577. {
  578. for (auto& callbackPair : iterCameraCallbacks->second)
  579. {
  580. const RenderCallbackData& callbackData = callbackPair.second;
  581. if (callbackData.overlay || callbackPair.first < 0)
  582. continue;
  583. callbackData.callback();
  584. }
  585. }
  586. // TODO - If GBuffer has multiple samples, I should resolve them before post-processing
  587. PostProcessing::instance().postProcess(camData.target->getSceneColorRT(),
  588. camera, camData.postProcessInfo, delta);
  589. // Render overlay post-scene callbacks
  590. if (iterCameraCallbacks != mRenderCallbacks.end())
  591. {
  592. for (auto& callbackPair : iterCameraCallbacks->second)
  593. {
  594. const RenderCallbackData& callbackData = callbackPair.second;
  595. if (!callbackData.overlay)
  596. continue;
  597. callbackData.callback();
  598. }
  599. }
  600. camData.target->release();
  601. gProfilerCPU().endSample("Render");
  602. }
  603. void RenderBeast::renderOverlay(RenderTargetData& rtData, UINT32 camIdx, float delta)
  604. {
  605. gProfilerCPU().beginSample("RenderOverlay");
  606. const CameraCore* camera = rtData.cameras[camIdx];
  607. assert(camera->getFlags().isSet(CameraFlag::Overlay));
  608. SPtr<ViewportCore> viewport = camera->getViewport();
  609. CameraShaderData cameraShaderData = getCameraShaderData(*camera);
  610. mStaticHandler->updatePerCameraBuffers(cameraShaderData);
  611. SPtr<RenderTargetCore> target = rtData.target;
  612. RenderAPICore::instance().setRenderTarget(target);
  613. RenderAPICore::instance().setViewport(viewport->getNormArea());
  614. // If first camera in render target, prepare the render target
  615. if (camIdx == 0)
  616. {
  617. UINT32 clearBuffers = 0;
  618. if (viewport->getRequiresColorClear())
  619. clearBuffers |= FBT_COLOR;
  620. if (viewport->getRequiresDepthClear())
  621. clearBuffers |= FBT_DEPTH;
  622. if (viewport->getRequiresStencilClear())
  623. clearBuffers |= FBT_STENCIL;
  624. if (clearBuffers != 0)
  625. {
  626. RenderAPICore::instance().clearViewport(clearBuffers, viewport->getClearColor(),
  627. viewport->getClearDepthValue(), viewport->getClearStencilValue());
  628. }
  629. }
  630. // Render overlay post-scene callbacks
  631. auto iterCameraCallbacks = mRenderCallbacks.find(camera);
  632. if (iterCameraCallbacks != mRenderCallbacks.end())
  633. {
  634. for (auto& callbackPair : iterCameraCallbacks->second)
  635. {
  636. const RenderCallbackData& callbackData = callbackPair.second;
  637. if (!callbackData.overlay)
  638. continue;
  639. callbackData.callback();
  640. }
  641. }
  642. gProfilerCPU().endSample("RenderOverlay");
  643. }
  644. void RenderBeast::determineVisible(const CameraCore& camera)
  645. {
  646. bool isOverlayCamera = camera.getFlags().isSet(CameraFlag::Overlay);
  647. if (isOverlayCamera)
  648. return;
  649. CameraData& cameraData = mCameraData[&camera];
  650. UINT64 cameraLayers = camera.getLayers();
  651. ConvexVolume worldFrustum = camera.getWorldFrustum();
  652. // Update per-object param buffers and queue render elements
  653. for (auto& renderableData : mRenderables)
  654. {
  655. RenderableCore* renderable = renderableData.renderable;
  656. UINT32 rendererId = renderable->getRendererId();
  657. if ((renderable->getLayer() & cameraLayers) == 0)
  658. continue;
  659. // Do frustum culling
  660. // TODO - This is bound to be a bottleneck at some point. When it is ensure that intersect
  661. // methods use vector operations, as it is trivial to update them.
  662. const Sphere& boundingSphere = mWorldBounds[rendererId].getSphere();
  663. if (worldFrustum.intersects(boundingSphere))
  664. {
  665. // More precise with the box
  666. const AABox& boundingBox = mWorldBounds[rendererId].getBox();
  667. if (worldFrustum.intersects(boundingBox))
  668. {
  669. float distanceToCamera = (camera.getPosition() - boundingBox.getCenter()).length();
  670. for (auto& renderElem : renderableData.elements)
  671. {
  672. bool isTransparent = (renderElem.material->getShader()->getFlags() & (UINT32)ShaderFlags::Transparent) != 0;
  673. if (isTransparent)
  674. cameraData.transparentQueue->add(&renderElem, distanceToCamera);
  675. else
  676. cameraData.opaqueQueue->add(&renderElem, distanceToCamera);
  677. }
  678. }
  679. }
  680. }
  681. cameraData.opaqueQueue->sort();
  682. cameraData.transparentQueue->sort();
  683. }
  684. Vector2 RenderBeast::getDeviceZTransform(const Matrix4& projMatrix)
  685. {
  686. // Returns a set of values that will transform depth buffer values (e.g. [0, 1] in DX, [-1, 1] in GL) to a distance
  687. // in world space. This involes applying the inverse projection transform to the depth value. When you multiply
  688. // a vector with the projection matrix you get [clipX, clipY, Az + B, C * z], where we don't care about clipX/clipY.
  689. // A is [2, 2], B is [2, 3] and C is [3, 2] elements of the projection matrix (only ones that matter for our depth
  690. // value). The hardware will also automatically divide the z value with w to get the depth, therefore the final
  691. // formula is:
  692. // depth = (Az + B) / (C * z)
  693. // To get the z coordinate back we simply do the opposite:
  694. // z = B / (depth * C - A)
  695. // However some APIs will also do a transformation on the depth values before storing them to the texture
  696. // (e.g. OpenGL will transform from [-1, 1] to [0, 1]). And we need to reverse that as well. Therefore the final
  697. // formula is:
  698. // z = B / ((depth * (maxDepth - minDepth) + minDepth) * C - A)
  699. // Are we reorganize it because it needs to fit the "(1.0f / (depth + y)) * x" format used in the shader:
  700. // z = 1.0f / (depth + minDepth/(maxDepth - minDepth) - A/((maxDepth - minDepth) * C)) * B/((maxDepth - minDepth) * C)
  701. RenderAPICore& rapi = RenderAPICore::instance();
  702. const RenderAPIInfo& rapiInfo = rapi.getAPIInfo();
  703. float depthRange = rapiInfo.getMaximumDepthInputValue() - rapiInfo.getMinimumDepthInputValue();
  704. float minDepth = rapiInfo.getMinimumDepthInputValue();
  705. float a = projMatrix[2][2];
  706. float b = projMatrix[2][3];
  707. float c = projMatrix[3][2];
  708. Vector2 output;
  709. output.x = b / (depthRange * c);
  710. output.y = minDepth / depthRange - a / (depthRange * c);
  711. return output;
  712. }
  713. CameraShaderData RenderBeast::getCameraShaderData(const CameraCore& camera)
  714. {
  715. CameraShaderData data;
  716. data.proj = camera.getProjectionMatrixRS();
  717. data.view = camera.getViewMatrix();
  718. data.viewProj = data.proj * data.view;
  719. data.invProj = data.proj.inverse();
  720. data.invViewProj = data.viewProj.inverse(); // Note: Calculate inverses separately (better precision possibly)
  721. // Construct a special inverse view-projection matrix that had projection entries that affect z and w eliminated.
  722. // Used to transform a vector(clip_x, clip_y, view_z, view_w), where clip_x/clip_y are in clip space, and
  723. // view_z/view_w in view space, into world space.
  724. // Only projects z/w coordinates
  725. Matrix4 projZ = Matrix4::IDENTITY;
  726. projZ[2][2] = data.proj[2][2];
  727. projZ[2][3] = data.proj[2][3];
  728. projZ[3][2] = data.proj[3][2];
  729. projZ[3][3] = 0.0f;
  730. data.screenToWorld = data.invViewProj * projZ;
  731. data.viewDir = camera.getForward();
  732. data.viewOrigin = camera.getPosition();
  733. data.deviceZToWorldZ = getDeviceZTransform(data.proj);
  734. SPtr<ViewportCore> viewport = camera.getViewport();
  735. SPtr<RenderTargetCore> rt = viewport->getTarget();
  736. float halfWidth = viewport->getWidth() * 0.5f;
  737. float halfHeight = viewport->getHeight() * 0.5f;
  738. float rtWidth = (float)rt->getProperties().getWidth();
  739. float rtHeight = (float)rt->getProperties().getHeight();
  740. RenderAPICore& rapi = RenderAPICore::instance();
  741. const RenderAPIInfo& rapiInfo = rapi.getAPIInfo();
  742. data.clipToUVScaleOffset.x = halfWidth / rtWidth;
  743. data.clipToUVScaleOffset.y = -halfHeight / rtHeight;
  744. data.clipToUVScaleOffset.z = viewport->getX() / rtWidth + (halfWidth + rapiInfo.getHorizontalTexelOffset()) / rtWidth;
  745. data.clipToUVScaleOffset.w = viewport->getY() / rtHeight + (halfHeight + rapiInfo.getVerticalTexelOffset()) / rtHeight;
  746. if (!rapiInfo.getNDCYAxisDown())
  747. data.clipToUVScaleOffset.y = -data.clipToUVScaleOffset.y;
  748. return data;
  749. }
  750. void RenderBeast::refreshSamplerOverrides(bool force)
  751. {
  752. for (auto& entry : mSamplerOverrides)
  753. {
  754. SPtr<MaterialCore> material = entry.first;
  755. if (force)
  756. {
  757. SamplerOverrideUtility::destroySamplerOverrides(entry.second);
  758. entry.second = SamplerOverrideUtility::generateSamplerOverrides(material, mCoreOptions);
  759. }
  760. else
  761. {
  762. MaterialSamplerOverrides* materialOverrides = entry.second;
  763. UINT32 numPasses = material->getNumPasses();
  764. assert(numPasses == materialOverrides->numPasses);
  765. for (UINT32 i = 0; i < numPasses; i++)
  766. {
  767. SPtr<PassParametersCore> passParams = material->getPassParameters(i);
  768. PassSamplerOverrides& passOverrides = materialOverrides->passes[i];
  769. for (UINT32 j = 0; j < PassParametersCore::NUM_PARAMS; j++)
  770. {
  771. StageSamplerOverrides& stageOverrides = passOverrides.stages[j];
  772. SPtr<GpuParamsCore> params = passParams->getParamByIdx(j);
  773. if (params == nullptr)
  774. continue;
  775. const GpuParamDesc& paramDesc = params->getParamDesc();
  776. for (auto iter = paramDesc.samplers.begin(); iter != paramDesc.samplers.end(); ++iter)
  777. {
  778. UINT32 slot = iter->second.slot;
  779. SPtr<SamplerStateCore> samplerState = params->getSamplerState(slot);
  780. assert(stageOverrides.numStates > slot);
  781. if (samplerState != stageOverrides.stateOverrides[slot])
  782. {
  783. if (samplerState != nullptr)
  784. stageOverrides.stateOverrides[slot] = SamplerOverrideUtility::generateSamplerOverride(samplerState, mCoreOptions);
  785. else
  786. stageOverrides.stateOverrides[slot] = SamplerOverrideUtility::generateSamplerOverride(SamplerStateCore::getDefault(), mCoreOptions);;
  787. }
  788. }
  789. }
  790. }
  791. }
  792. }
  793. }
  794. void RenderBeast::setPass(const SPtr<PassCore>& pass)
  795. {
  796. THROW_IF_NOT_CORE_THREAD;
  797. RenderAPICore& rs = RenderAPICore::instance();
  798. struct StageData
  799. {
  800. GpuProgramType type;
  801. bool enable;
  802. SPtr<GpuProgramCore> program;
  803. };
  804. const UINT32 numStages = 6;
  805. StageData stages[numStages] =
  806. {
  807. { GPT_VERTEX_PROGRAM, pass->hasVertexProgram(), pass->getVertexProgram() },
  808. { GPT_FRAGMENT_PROGRAM, pass->hasFragmentProgram(), pass->getFragmentProgram() },
  809. { GPT_GEOMETRY_PROGRAM, pass->hasGeometryProgram(), pass->getGeometryProgram() },
  810. { GPT_HULL_PROGRAM, pass->hasHullProgram(), pass->getHullProgram() },
  811. { GPT_DOMAIN_PROGRAM, pass->hasDomainProgram(), pass->getDomainProgram() },
  812. { GPT_COMPUTE_PROGRAM, pass->hasComputeProgram(), pass->getComputeProgram() }
  813. };
  814. for (UINT32 i = 0; i < numStages; i++)
  815. {
  816. const StageData& stage = stages[i];
  817. if (stage.enable)
  818. rs.bindGpuProgram(stage.program);
  819. else
  820. rs.unbindGpuProgram(stage.type);
  821. }
  822. // Set up non-texture related pass settings
  823. if (pass->getBlendState() != nullptr)
  824. rs.setBlendState(pass->getBlendState());
  825. else
  826. rs.setBlendState(BlendStateCore::getDefault());
  827. if (pass->getDepthStencilState() != nullptr)
  828. rs.setDepthStencilState(pass->getDepthStencilState(), pass->getStencilRefValue());
  829. else
  830. rs.setDepthStencilState(DepthStencilStateCore::getDefault(), pass->getStencilRefValue());
  831. if (pass->getRasterizerState() != nullptr)
  832. rs.setRasterizerState(pass->getRasterizerState());
  833. else
  834. rs.setRasterizerState(RasterizerStateCore::getDefault());
  835. }
  836. void RenderBeast::setPassParams(const SPtr<PassParametersCore>& passParams, const PassSamplerOverrides* samplerOverrides)
  837. {
  838. THROW_IF_NOT_CORE_THREAD;
  839. RenderAPICore& rs = RenderAPICore::instance();
  840. struct StageData
  841. {
  842. GpuProgramType type;
  843. SPtr<GpuParamsCore> params;
  844. };
  845. const UINT32 numStages = 6;
  846. StageData stages[numStages] =
  847. {
  848. { GPT_VERTEX_PROGRAM, passParams->mVertParams },
  849. { GPT_FRAGMENT_PROGRAM, passParams->mFragParams },
  850. { GPT_GEOMETRY_PROGRAM, passParams->mGeomParams },
  851. { GPT_HULL_PROGRAM, passParams->mHullParams },
  852. { GPT_DOMAIN_PROGRAM, passParams->mDomainParams },
  853. { GPT_COMPUTE_PROGRAM, passParams->mComputeParams }
  854. };
  855. for (UINT32 i = 0; i < numStages; i++)
  856. {
  857. const StageData& stage = stages[i];
  858. SPtr<GpuParamsCore> params = stage.params;
  859. if (params == nullptr)
  860. continue;
  861. const GpuParamDesc& paramDesc = params->getParamDesc();
  862. for (auto iter = paramDesc.samplers.begin(); iter != paramDesc.samplers.end(); ++iter)
  863. {
  864. SPtr<SamplerStateCore> samplerState;
  865. if (samplerOverrides != nullptr)
  866. samplerState = samplerOverrides->stages[i].stateOverrides[iter->second.slot];
  867. else
  868. samplerState = params->getSamplerState(iter->second.slot);
  869. if (samplerState == nullptr)
  870. rs.setSamplerState(stage.type, iter->second.slot, SamplerStateCore::getDefault());
  871. else
  872. rs.setSamplerState(stage.type, iter->second.slot, samplerState);
  873. }
  874. for (auto iter = paramDesc.textures.begin(); iter != paramDesc.textures.end(); ++iter)
  875. {
  876. SPtr<TextureCore> texture = params->getTexture(iter->second.slot);
  877. if (texture == nullptr)
  878. rs.setTexture(stage.type, iter->second.slot, false, nullptr);
  879. else
  880. rs.setTexture(stage.type, iter->second.slot, true, texture);
  881. }
  882. for (auto iter = paramDesc.loadStoreTextures.begin(); iter != paramDesc.loadStoreTextures.end(); ++iter)
  883. {
  884. SPtr<TextureCore> texture = params->getLoadStoreTexture(iter->second.slot);
  885. const TextureSurface& surface = params->getLoadStoreSurface(iter->second.slot);
  886. if (texture == nullptr)
  887. rs.setLoadStoreTexture(stage.type, iter->second.slot, false, nullptr, surface);
  888. else
  889. rs.setLoadStoreTexture(stage.type, iter->second.slot, true, texture, surface);
  890. }
  891. rs.setConstantBuffers(stage.type, params);
  892. }
  893. }
  894. void DefaultMaterial::_initDefines(ShaderDefines& defines)
  895. {
  896. // Do nothing
  897. }
  898. }