Is.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801
  1. // Copyright (C) 2009-2016, Panagiotis Christopoulos Charitos.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <anki/renderer/Is.h>
  6. #include <anki/renderer/Renderer.h>
  7. #include <anki/renderer/Ms.h>
  8. #include <anki/renderer/Sm.h>
  9. #include <anki/renderer/Pps.h>
  10. #include <anki/renderer/Ir.h>
  11. #include <anki/scene/Camera.h>
  12. #include <anki/scene/Light.h>
  13. #include <anki/scene/Visibility.h>
  14. #include <anki/core/Trace.h>
  15. #include <anki/util/Logger.h>
  16. #include <anki/misc/ConfigSet.h>
  17. namespace anki
  18. {
  19. //==============================================================================
  20. // Misc =
  21. //==============================================================================
  22. // Shader structs and block representations. All positions and directions in
  23. // viewspace
  24. // For documentation see the shaders
  25. struct ShaderCluster
  26. {
  27. /// If m_combo = 0xFFFFAABB then FFFF is the light index offset, AA the
  28. /// number of point lights and BB the number of spot lights
  29. U32 m_combo;
  30. };
  31. struct ShaderLight
  32. {
  33. Vec4 m_posRadius;
  34. Vec4 m_diffuseColorShadowmapId;
  35. Vec4 m_specularColorTexId;
  36. };
  37. struct ShaderPointLight : ShaderLight
  38. {
  39. };
  40. struct ShaderSpotLight : ShaderLight
  41. {
  42. Vec4 m_lightDir;
  43. Vec4 m_outerCosInnerCos;
  44. Mat4 m_texProjectionMat; ///< Texture projection matrix
  45. };
  46. struct ShaderCommonUniforms
  47. {
  48. Vec4 m_projectionParams;
  49. Vec4 m_sceneAmbientColor;
  50. Vec4 m_rendererSizeTimePad1;
  51. Vec4 m_nearFarClustererMagicPad1;
  52. Mat4 m_viewMat;
  53. UVec4 m_tileCount;
  54. };
  55. using Lid = U32; ///< Light ID
  56. static const U MAX_TYPED_LIGHTS_PER_CLUSTER = 16;
  57. static const F32 INVALID_TEXTURE_INDEX = 128.0;
  58. class ClusterData
  59. {
  60. public:
  61. Atomic<U32> m_pointCount;
  62. Atomic<U32> m_spotCount;
  63. Array<Lid, MAX_TYPED_LIGHTS_PER_CLUSTER> m_pointIds;
  64. Array<Lid, MAX_TYPED_LIGHTS_PER_CLUSTER> m_spotIds;
  65. void sortLightIds()
  66. {
  67. const U pointCount = m_pointCount.load() % MAX_TYPED_LIGHTS_PER_CLUSTER;
  68. const U spotCount = m_spotCount.load() % MAX_TYPED_LIGHTS_PER_CLUSTER;
  69. if(pointCount > 1)
  70. {
  71. std::sort(&m_pointIds[0], &m_pointIds[0] + pointCount);
  72. }
  73. if(spotCount > 1)
  74. {
  75. std::sort(&m_spotIds[0], &m_spotIds[0] + spotCount);
  76. }
  77. }
  78. Bool operator==(const ClusterData& b) const
  79. {
  80. const U pointCount = m_pointCount.load() % MAX_TYPED_LIGHTS_PER_CLUSTER;
  81. const U spotCount = m_spotCount.load() % MAX_TYPED_LIGHTS_PER_CLUSTER;
  82. const U pointCount2 =
  83. b.m_pointCount.load() % MAX_TYPED_LIGHTS_PER_CLUSTER;
  84. const U spotCount2 =
  85. b.m_spotCount.load() % MAX_TYPED_LIGHTS_PER_CLUSTER;
  86. if(pointCount != pointCount2 || spotCount != spotCount2)
  87. {
  88. return false;
  89. }
  90. if(pointCount > 0)
  91. {
  92. if(memcmp(
  93. &m_pointIds[0], &b.m_pointIds[0], sizeof(Lid) * pointCount)
  94. != 0)
  95. {
  96. return false;
  97. }
  98. }
  99. if(spotCount > 0)
  100. {
  101. if(memcmp(&m_spotIds[0], &b.m_spotIds[0], sizeof(Lid) * spotCount)
  102. != 0)
  103. {
  104. return false;
  105. }
  106. }
  107. return true;
  108. }
  109. };
  110. /// Common data for all tasks.
  111. class TaskCommonData
  112. {
  113. public:
  114. TaskCommonData(StackAllocator<U8> alloc)
  115. : m_tempClusters(alloc)
  116. {
  117. }
  118. // To fill the light buffers
  119. SArray<ShaderPointLight> m_pointLights;
  120. SArray<ShaderSpotLight> m_spotLights;
  121. SArray<Lid> m_lightIds;
  122. SArray<ShaderCluster> m_clusters;
  123. Atomic<U32> m_pointLightsCount = {0};
  124. Atomic<U32> m_spotLightsCount = {0};
  125. // To fill the tile buffers
  126. DArrayAuto<ClusterData> m_tempClusters;
  127. // To fill the light index buffer
  128. Atomic<U32> m_lightIdsCount = {0};
  129. // Misc
  130. const VisibleNode* m_lightsBegin = nullptr;
  131. const VisibleNode* m_lightsEnd = nullptr;
  132. Is* m_is = nullptr;
  133. };
  134. /// Write the lights to the GPU buffers.
  135. class WriteLightsTask : public ThreadPool::Task
  136. {
  137. public:
  138. TaskCommonData* m_data = nullptr;
  139. Error operator()(U32 threadId, PtrSize threadsCount)
  140. {
  141. ANKI_TRACE_START_EVENT(RENDER_IS);
  142. m_data->m_is->binLights(threadId, threadsCount, *m_data);
  143. ANKI_TRACE_STOP_EVENT(RENDER_IS);
  144. return ErrorCode::NONE;
  145. }
  146. };
  147. //==============================================================================
  148. // Is =
  149. //==============================================================================
  150. const PixelFormat Is::RT_PIXEL_FORMAT(
  151. ComponentFormat::R11G11B10, TransformFormat::FLOAT);
  152. //==============================================================================
  153. Is::Is(Renderer* r)
  154. : RenderingPass(r)
  155. {
  156. }
  157. //==============================================================================
  158. Is::~Is()
  159. {
  160. if(m_barrier)
  161. {
  162. getAllocator().deleteInstance(m_barrier.get());
  163. }
  164. }
  165. //==============================================================================
  166. Error Is::init(const ConfigSet& config)
  167. {
  168. Error err = initInternal(config);
  169. if(err)
  170. {
  171. ANKI_LOGE("Failed to init IS");
  172. }
  173. return err;
  174. }
  175. //==============================================================================
  176. Error Is::initInternal(const ConfigSet& config)
  177. {
  178. m_groundLightEnabled = config.getNumber("is.groundLightEnabled");
  179. m_maxPointLights = config.getNumber("is.maxPointLights");
  180. m_maxSpotLights = config.getNumber("is.maxSpotLights");
  181. m_maxSpotTexLights = config.getNumber("is.maxSpotTexLights");
  182. if(m_maxPointLights < 1 || m_maxSpotLights < 1 || m_maxSpotTexLights < 1)
  183. {
  184. ANKI_LOGE("Incorrect number of max lights");
  185. return ErrorCode::USER_DATA;
  186. }
  187. m_maxLightIds = config.getNumber("is.maxLightsPerCluster");
  188. if(m_maxLightIds == 0)
  189. {
  190. ANKI_LOGE("Incorrect number of max light indices");
  191. return ErrorCode::USER_DATA;
  192. }
  193. m_maxLightIds *= m_r->getClusterCount();
  194. //
  195. // Load the programs
  196. //
  197. StringAuto pps(getAllocator());
  198. pps.sprintf("\n#define TILE_COUNT_X %u\n"
  199. "#define TILE_COUNT_Y %u\n"
  200. "#define CLUSTER_COUNT %u\n"
  201. "#define RENDERER_WIDTH %u\n"
  202. "#define RENDERER_HEIGHT %u\n"
  203. "#define MAX_POINT_LIGHTS %u\n"
  204. "#define MAX_SPOT_LIGHTS %u\n"
  205. "#define MAX_LIGHT_INDICES %u\n"
  206. "#define GROUND_LIGHT %u\n"
  207. "#define POISSON %u\n"
  208. "#define INDIRECT_ENABLED %u\n"
  209. "#define IR_MIPMAP_COUNT %u\n",
  210. m_r->getTileCountXY().x(),
  211. m_r->getTileCountXY().y(),
  212. m_r->getClusterCount(),
  213. m_r->getWidth(),
  214. m_r->getHeight(),
  215. m_maxPointLights,
  216. m_maxSpotLights,
  217. m_maxLightIds,
  218. m_groundLightEnabled,
  219. m_r->getSmEnabled() ? m_r->getSm().getPoissonEnabled() : 0,
  220. m_r->getIrEnabled(),
  221. (m_r->getIrEnabled()) ? m_r->getIr().getCubemapArrayMipmapCount() : 0);
  222. // point light
  223. ANKI_CHECK(getResourceManager().loadResourceToCache(
  224. m_lightVert, "shaders/IsLp.vert.glsl", pps.toCString(), "r_"));
  225. ANKI_CHECK(getResourceManager().loadResourceToCache(
  226. m_lightFrag, "shaders/IsLp.frag.glsl", pps.toCString(), "r_"));
  227. PipelineInitInfo init;
  228. init.m_inputAssembler.m_topology = PrimitiveTopology::TRIANGLE_STRIP;
  229. init.m_depthStencil.m_depthWriteEnabled = false;
  230. init.m_depthStencil.m_depthCompareFunction = CompareOperation::ALWAYS;
  231. init.m_color.m_attachmentCount = 1;
  232. init.m_color.m_attachments[0].m_format = RT_PIXEL_FORMAT;
  233. init.m_shaders[U(ShaderType::VERTEX)] = m_lightVert->getGrShader();
  234. init.m_shaders[U(ShaderType::FRAGMENT)] = m_lightFrag->getGrShader();
  235. m_lightPpline = getGrManager().newInstance<Pipeline>(init);
  236. //
  237. // Create framebuffer
  238. //
  239. m_r->createRenderTarget(m_r->getWidth(),
  240. m_r->getHeight(),
  241. RT_PIXEL_FORMAT,
  242. 1,
  243. SamplingFilter::LINEAR,
  244. MIPMAPS_COUNT,
  245. m_rt);
  246. FramebufferInitInfo fbInit;
  247. fbInit.m_colorAttachmentsCount = 1;
  248. fbInit.m_colorAttachments[0].m_texture = m_rt;
  249. fbInit.m_colorAttachments[0].m_loadOperation =
  250. AttachmentLoadOperation::DONT_CARE;
  251. m_fb = getGrManager().newInstance<Framebuffer>(fbInit);
  252. //
  253. // Create resource group
  254. //
  255. {
  256. ResourceGroupInitInfo init;
  257. init.m_textures[0].m_texture = m_r->getMs().getRt0();
  258. init.m_textures[1].m_texture = m_r->getMs().getRt1();
  259. init.m_textures[2].m_texture = m_r->getMs().getRt2();
  260. init.m_textures[3].m_texture = m_r->getMs().getDepthRt();
  261. if(m_r->getSmEnabled())
  262. {
  263. init.m_textures[4].m_texture = m_r->getSm().getSpotTextureArray();
  264. init.m_textures[5].m_texture = m_r->getSm().getOmniTextureArray();
  265. }
  266. init.m_storageBuffers[0].m_dynamic = true;
  267. init.m_storageBuffers[1].m_dynamic = true;
  268. init.m_storageBuffers[2].m_dynamic = true;
  269. init.m_storageBuffers[3].m_dynamic = true;
  270. init.m_storageBuffers[4].m_dynamic = true;
  271. m_rcGroup = getGrManager().newInstance<ResourceGroup>(init);
  272. }
  273. //
  274. // Misc
  275. //
  276. ThreadPool& threadPool = m_r->getThreadPool();
  277. m_barrier =
  278. getAllocator().newInstance<Barrier>(threadPool.getThreadsCount());
  279. getGrManager().finish();
  280. return ErrorCode::NONE;
  281. }
  282. //==============================================================================
  283. Error Is::lightPass(RenderingContext& ctx)
  284. {
  285. ANKI_TRACE_START_EVENT(RENDER_IS);
  286. CommandBufferPtr& cmdb = ctx.m_commandBuffer;
  287. ThreadPool& threadPool = m_r->getThreadPool();
  288. m_frc = ctx.m_frustumComponent;
  289. VisibilityTestResults& vi = m_frc->getVisibilityTestResults();
  290. U clusterCount = m_r->getClusterCount();
  291. //
  292. // Quickly get the lights
  293. //
  294. U visiblePointLightsCount = 0;
  295. U visibleSpotLightsCount = 0;
  296. auto it = vi.getBegin(VisibilityGroupType::LIGHTS);
  297. auto lend = vi.getEnd(VisibilityGroupType::LIGHTS);
  298. for(; it != lend; ++it)
  299. {
  300. SceneNode* node = (*it).m_node;
  301. LightComponent& light = node->getComponent<LightComponent>();
  302. switch(light.getLightType())
  303. {
  304. case LightComponent::LightType::POINT:
  305. ++visiblePointLightsCount;
  306. break;
  307. case LightComponent::LightType::SPOT:
  308. ++visibleSpotLightsCount;
  309. break;
  310. default:
  311. ANKI_ASSERT(0);
  312. break;
  313. }
  314. }
  315. // Sanitize the counters
  316. visiblePointLightsCount = min<U>(visiblePointLightsCount, m_maxPointLights);
  317. visibleSpotLightsCount = min<U>(visibleSpotLightsCount, m_maxSpotLights);
  318. ANKI_TRACE_INC_COUNTER(
  319. RENDERER_LIGHTS, visiblePointLightsCount + visibleSpotLightsCount);
  320. //
  321. // Write the lights and tiles UBOs
  322. //
  323. Array<WriteLightsTask, ThreadPool::MAX_THREADS> tasks;
  324. TaskCommonData taskData(getFrameAllocator());
  325. taskData.m_tempClusters.create(m_r->getClusterCount());
  326. if(visiblePointLightsCount)
  327. {
  328. ShaderPointLight* data = static_cast<ShaderPointLight*>(
  329. getGrManager().allocateFrameHostVisibleMemory(
  330. sizeof(ShaderPointLight) * visiblePointLightsCount,
  331. BufferUsage::STORAGE,
  332. m_pLightsToken));
  333. taskData.m_pointLights =
  334. SArray<ShaderPointLight>(data, visiblePointLightsCount);
  335. }
  336. else
  337. {
  338. m_pLightsToken.markUnused();
  339. }
  340. if(visibleSpotLightsCount)
  341. {
  342. ShaderSpotLight* data = static_cast<ShaderSpotLight*>(
  343. getGrManager().allocateFrameHostVisibleMemory(
  344. sizeof(ShaderSpotLight) * visibleSpotLightsCount,
  345. BufferUsage::STORAGE,
  346. m_sLightsToken));
  347. taskData.m_spotLights =
  348. SArray<ShaderSpotLight>(data, visibleSpotLightsCount);
  349. }
  350. else
  351. {
  352. m_sLightsToken.markUnused();
  353. }
  354. taskData.m_lightsBegin = vi.getBegin(VisibilityGroupType::LIGHTS);
  355. taskData.m_lightsEnd = vi.getEnd(VisibilityGroupType::LIGHTS);
  356. taskData.m_is = this;
  357. // Get mem for clusters
  358. ShaderCluster* data = static_cast<ShaderCluster*>(
  359. getGrManager().allocateFrameHostVisibleMemory(
  360. sizeof(ShaderCluster) * clusterCount,
  361. BufferUsage::STORAGE,
  362. m_clustersToken));
  363. taskData.m_clusters = SArray<ShaderCluster>(data, clusterCount);
  364. // Allocate light IDs
  365. Lid* data2 =
  366. static_cast<Lid*>(getGrManager().allocateFrameHostVisibleMemory(
  367. m_maxLightIds * sizeof(Lid),
  368. BufferUsage::STORAGE,
  369. m_lightIdsToken));
  370. taskData.m_lightIds = SArray<Lid>(data2, m_maxLightIds);
  371. for(U i = 0; i < threadPool.getThreadsCount(); i++)
  372. {
  373. tasks[i].m_data = &taskData;
  374. threadPool.assignNewTask(i, &tasks[i]);
  375. }
  376. // Update uniforms
  377. updateCommonBlock(*m_frc);
  378. // In the meantime set the state
  379. setState(cmdb);
  380. // Sync
  381. ANKI_CHECK(threadPool.waitForAllThreadsToFinish());
  382. //
  383. // Draw
  384. //
  385. cmdb->drawArrays(4, m_r->getTileCount());
  386. ANKI_TRACE_STOP_EVENT(RENDER_IS);
  387. return ErrorCode::NONE;
  388. }
  389. //==============================================================================
  390. void Is::binLights(U32 threadId, PtrSize threadsCount, TaskCommonData& task)
  391. {
  392. U lightsCount = task.m_lightsEnd - task.m_lightsBegin;
  393. const FrustumComponent& camfrc = *m_frc;
  394. const MoveComponent& cammove =
  395. m_frc->getSceneNode().getComponent<MoveComponent>();
  396. // Iterate lights and bin them
  397. PtrSize start, end;
  398. ThreadPool::Task::choseStartEnd(
  399. threadId, threadsCount, lightsCount, start, end);
  400. ClustererTestResult testResult;
  401. m_r->getClusterer().initTestResults(getFrameAllocator(), testResult);
  402. for(auto i = start; i < end; i++)
  403. {
  404. SceneNode* snode = (*(task.m_lightsBegin + i)).m_node;
  405. MoveComponent& move = snode->getComponent<MoveComponent>();
  406. LightComponent& light = snode->getComponent<LightComponent>();
  407. SpatialComponent& sp = snode->getComponent<SpatialComponent>();
  408. switch(light.getLightType())
  409. {
  410. case LightComponent::LightType::POINT:
  411. {
  412. I pos = writePointLight(light, move, camfrc, task);
  413. if(pos != -1)
  414. {
  415. binLight(sp, pos, 0, task, testResult);
  416. }
  417. }
  418. break;
  419. case LightComponent::LightType::SPOT:
  420. {
  421. const FrustumComponent* frc =
  422. snode->tryGetComponent<FrustumComponent>();
  423. I pos = writeSpotLight(light, move, frc, cammove, camfrc, task);
  424. if(pos != -1)
  425. {
  426. binLight(sp, pos, 1, task, testResult);
  427. }
  428. }
  429. break;
  430. default:
  431. ANKI_ASSERT(0);
  432. break;
  433. }
  434. }
  435. //
  436. // Last thing, update the real clusters
  437. //
  438. m_barrier->wait();
  439. U clusterCount = m_r->getClusterCount();
  440. ThreadPool::Task::choseStartEnd(
  441. threadId, threadsCount, clusterCount, start, end);
  442. // Run per tile
  443. for(U i = start; i < end; ++i)
  444. {
  445. auto& cluster = task.m_tempClusters[i];
  446. const U countP =
  447. cluster.m_pointCount.load() % MAX_TYPED_LIGHTS_PER_CLUSTER;
  448. const U countS =
  449. cluster.m_spotCount.load() % MAX_TYPED_LIGHTS_PER_CLUSTER;
  450. const U count = countP + countS;
  451. auto& c = task.m_clusters[i];
  452. c.m_combo = 0;
  453. // Early exit
  454. if(ANKI_UNLIKELY(count == 0))
  455. {
  456. continue;
  457. }
  458. // Check if the previous cluster contains the same lights as this one
  459. // and if yes then merge them. This will avoid allocating new IDs (and
  460. // thrashing GPU caches).
  461. cluster.sortLightIds();
  462. if(i != start)
  463. {
  464. const auto& clusterB = task.m_tempClusters[i - 1];
  465. if(cluster == clusterB)
  466. {
  467. c.m_combo = task.m_clusters[i - 1].m_combo;
  468. continue;
  469. }
  470. }
  471. const U offset = task.m_lightIdsCount.fetchAdd(count);
  472. if(offset + count <= m_maxLightIds)
  473. {
  474. ANKI_ASSERT(offset <= 0xFFFF);
  475. c.m_combo = offset << 16;
  476. if(countP > 0)
  477. {
  478. ANKI_ASSERT(countP <= 0xFF);
  479. c.m_combo |= countP << 8;
  480. memcpy(&task.m_lightIds[offset],
  481. &cluster.m_pointIds[0],
  482. countP * sizeof(Lid));
  483. }
  484. if(countS > 0)
  485. {
  486. ANKI_ASSERT(countS <= 0xFF);
  487. c.m_combo |= countS;
  488. memcpy(&task.m_lightIds[offset + countP],
  489. &cluster.m_spotIds[0],
  490. countS * sizeof(Lid));
  491. }
  492. }
  493. else
  494. {
  495. ANKI_LOGW("Light IDs buffer too small");
  496. }
  497. }
  498. }
  499. //==============================================================================
  500. I Is::writePointLight(const LightComponent& lightc,
  501. const MoveComponent& lightMove,
  502. const FrustumComponent& camFrc,
  503. TaskCommonData& task)
  504. {
  505. // Get GPU light
  506. I i = task.m_pointLightsCount.fetchAdd(1);
  507. if(ANKI_UNLIKELY(i >= I(m_maxPointLights)))
  508. {
  509. return -1;
  510. }
  511. ShaderPointLight& slight = task.m_pointLights[i];
  512. Vec4 pos = camFrc.getViewMatrix()
  513. * lightMove.getWorldTransform().getOrigin().xyz1();
  514. slight.m_posRadius =
  515. Vec4(pos.xyz(), 1.0 / (lightc.getRadius() * lightc.getRadius()));
  516. slight.m_diffuseColorShadowmapId = lightc.getDiffuseColor();
  517. if(!lightc.getShadowEnabled() || !m_r->getSmEnabled())
  518. {
  519. slight.m_diffuseColorShadowmapId.w() = INVALID_TEXTURE_INDEX;
  520. }
  521. else
  522. {
  523. slight.m_diffuseColorShadowmapId.w() = lightc.getShadowMapIndex();
  524. }
  525. slight.m_specularColorTexId = lightc.getSpecularColor();
  526. return i;
  527. }
  528. //==============================================================================
  529. I Is::writeSpotLight(const LightComponent& lightc,
  530. const MoveComponent& lightMove,
  531. const FrustumComponent* lightFrc,
  532. const MoveComponent& camMove,
  533. const FrustumComponent& camFrc,
  534. TaskCommonData& task)
  535. {
  536. I i = task.m_spotLightsCount.fetchAdd(1);
  537. if(ANKI_UNLIKELY(i >= I(m_maxSpotTexLights)))
  538. {
  539. return -1;
  540. }
  541. ShaderSpotLight& light = task.m_spotLights[i];
  542. F32 shadowmapIndex = INVALID_TEXTURE_INDEX;
  543. if(lightc.getShadowEnabled() && m_r->getSmEnabled())
  544. {
  545. // Write matrix
  546. static const Mat4 biasMat4(0.5,
  547. 0.0,
  548. 0.0,
  549. 0.5,
  550. 0.0,
  551. 0.5,
  552. 0.0,
  553. 0.5,
  554. 0.0,
  555. 0.0,
  556. 0.5,
  557. 0.5,
  558. 0.0,
  559. 0.0,
  560. 0.0,
  561. 1.0);
  562. // bias * proj_l * view_l * world_c
  563. light.m_texProjectionMat = biasMat4
  564. * lightFrc->getViewProjectionMatrix()
  565. * Mat4(camMove.getWorldTransform());
  566. shadowmapIndex = (F32)lightc.getShadowMapIndex();
  567. }
  568. // Pos & dist
  569. Vec4 pos = camFrc.getViewMatrix()
  570. * lightMove.getWorldTransform().getOrigin().xyz1();
  571. light.m_posRadius =
  572. Vec4(pos.xyz(), 1.0 / (lightc.getDistance() * lightc.getDistance()));
  573. // Diff color and shadowmap ID now
  574. light.m_diffuseColorShadowmapId =
  575. Vec4(lightc.getDiffuseColor().xyz(), shadowmapIndex);
  576. // Spec color
  577. light.m_specularColorTexId = lightc.getSpecularColor();
  578. // Light dir
  579. Vec3 lightDir = -lightMove.getWorldTransform().getRotation().getZAxis();
  580. lightDir = camFrc.getViewMatrix().getRotationPart() * lightDir;
  581. light.m_lightDir = Vec4(lightDir, 0.0);
  582. // Angles
  583. light.m_outerCosInnerCos =
  584. Vec4(lightc.getOuterAngleCos(), lightc.getInnerAngleCos(), 1.0, 1.0);
  585. return i;
  586. }
  587. //==============================================================================
  588. void Is::binLight(SpatialComponent& sp,
  589. U pos,
  590. U lightType,
  591. TaskCommonData& task,
  592. ClustererTestResult& testResult)
  593. {
  594. m_r->getClusterer().bin(
  595. sp.getSpatialCollisionShape(), sp.getAabb(), testResult);
  596. // Bin to the correct tiles
  597. auto it = testResult.getClustersBegin();
  598. auto end = testResult.getClustersEnd();
  599. for(; it != end; ++it)
  600. {
  601. U x = (*it)[0];
  602. U y = (*it)[1];
  603. U z = (*it)[2];
  604. U i =
  605. m_r->getTileCountXY().x() * (z * m_r->getTileCountXY().y() + y) + x;
  606. auto& cluster = task.m_tempClusters[i];
  607. switch(lightType)
  608. {
  609. case 0:
  610. i = cluster.m_pointCount.fetchAdd(1) % MAX_TYPED_LIGHTS_PER_CLUSTER;
  611. cluster.m_pointIds[i] = pos;
  612. break;
  613. case 1:
  614. i = cluster.m_spotCount.fetchAdd(1) % MAX_TYPED_LIGHTS_PER_CLUSTER;
  615. cluster.m_spotIds[i] = pos;
  616. break;
  617. default:
  618. ANKI_ASSERT(0);
  619. }
  620. }
  621. }
  622. //==============================================================================
  623. void Is::setState(CommandBufferPtr& cmdb)
  624. {
  625. cmdb->bindFramebuffer(m_fb);
  626. cmdb->setViewport(0, 0, m_r->getWidth(), m_r->getHeight());
  627. cmdb->bindPipeline(m_lightPpline);
  628. DynamicBufferInfo dyn;
  629. dyn.m_storageBuffers[0] = m_commonVarsToken;
  630. dyn.m_storageBuffers[1] = m_pLightsToken;
  631. dyn.m_storageBuffers[2] = m_sLightsToken;
  632. dyn.m_storageBuffers[3] = m_clustersToken;
  633. dyn.m_storageBuffers[4] = m_lightIdsToken;
  634. cmdb->bindResourceGroup(m_rcGroup, 0, &dyn);
  635. if(m_r->getIrEnabled())
  636. {
  637. DynamicBufferInfo dyn;
  638. dyn.m_storageBuffers[0] = m_r->getIr().getProbesToken();
  639. dyn.m_storageBuffers[1] = m_r->getIr().getProbeIndicesToken();
  640. dyn.m_storageBuffers[2] = m_r->getIr().getClustersToken();
  641. cmdb->bindResourceGroup(m_r->getIr().getResourceGroup(), 1, &dyn);
  642. }
  643. }
  644. //==============================================================================
  645. Error Is::run(RenderingContext& ctx)
  646. {
  647. // Do the light pass including the shadow passes
  648. return lightPass(ctx);
  649. }
  650. //==============================================================================
  651. void Is::updateCommonBlock(const FrustumComponent& fr)
  652. {
  653. ShaderCommonUniforms* blk = static_cast<ShaderCommonUniforms*>(
  654. getGrManager().allocateFrameHostVisibleMemory(
  655. sizeof(ShaderCommonUniforms),
  656. BufferUsage::STORAGE,
  657. m_commonVarsToken));
  658. // Start writing
  659. blk->m_projectionParams = fr.getProjectionParameters();
  660. blk->m_sceneAmbientColor = m_ambientColor;
  661. blk->m_viewMat = fr.getViewMatrix().getTransposed();
  662. blk->m_nearFarClustererMagicPad1 = Vec4(fr.getFrustum().getNear(),
  663. fr.getFrustum().getFar(),
  664. m_r->getClusterer().getShaderMagicValue(),
  665. 0.0);
  666. blk->m_rendererSizeTimePad1 = Vec4(
  667. m_r->getWidth(), m_r->getHeight(), HighRezTimer::getCurrentTime(), 0.0);
  668. blk->m_tileCount = UVec4(m_r->getTileCountXY(), m_r->getTileCount(), 0);
  669. }
  670. } // end namespace anki