Is.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798
  1. // Copyright (C) 2009-2015, 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/Pps.h"
  9. #include "anki/renderer/Tiler.h"
  10. #include "anki/scene/Camera.h"
  11. #include "anki/scene/Light.h"
  12. #include "anki/scene/Visibility.h"
  13. #include "anki/core/Counters.h"
  14. #include "anki/util/Logger.h"
  15. #include "anki/misc/ConfigSet.h"
  16. namespace anki {
  17. //==============================================================================
  18. // Misc =
  19. //==============================================================================
  20. //==============================================================================
  21. // Shader structs and block representations. All positions and directions in
  22. // viewspace
  23. // For documentation see the shaders
  24. namespace shader {
  25. struct Tile
  26. {
  27. U32 m_offset;
  28. U32 m_pointLightsCount;
  29. U32 m_spotLightsCount;
  30. U32 m_spotTexLightsCount;
  31. };
  32. struct Light
  33. {
  34. Vec4 m_posRadius;
  35. Vec4 m_diffuseColorShadowmapId;
  36. Vec4 m_specularColorTexId;
  37. };
  38. struct PointLight: Light
  39. {};
  40. struct SpotLight: Light
  41. {
  42. Vec4 m_lightDir;
  43. Vec4 m_outerCosInnerCos;
  44. Mat4 m_texProjectionMat; ///< Texture projection matrix
  45. };
  46. struct CommonUniforms
  47. {
  48. Vec4 m_projectionParams;
  49. Vec4 m_sceneAmbientColor;
  50. Vec4 m_groundLightDir;
  51. };
  52. } // end namespace shader
  53. //==============================================================================
  54. using Lid = U32; ///< Light ID type
  55. static const U MAX_TYPED_LIGHTS_PER_TILE = 16;
  56. class TileData
  57. {
  58. public:
  59. Atomic<U32> m_pointCount;
  60. Atomic<U32> m_spotCount;
  61. Atomic<U32> m_spotTexCount;
  62. Array<Lid, MAX_TYPED_LIGHTS_PER_TILE> m_pointIds;
  63. Array<Lid, MAX_TYPED_LIGHTS_PER_TILE> m_spotIds;
  64. Array<Lid, MAX_TYPED_LIGHTS_PER_TILE> m_spotTexIds;
  65. };
  66. /// Common data for all tasks.
  67. class TaskCommonData
  68. {
  69. public:
  70. // To fill the light buffers
  71. SArray<shader::PointLight> m_pointLights;
  72. SArray<shader::SpotLight> m_spotLights;
  73. SArray<shader::SpotLight> m_spotTexLights;
  74. SArray<Lid> m_lightIds;
  75. SArray<shader::Tile> m_tiles;
  76. Atomic<U32> m_pointLightsCount;
  77. Atomic<U32> m_spotLightsCount;
  78. Atomic<U32> m_spotTexLightsCount;
  79. // To fill the tile buffers
  80. Array2d<TileData, ANKI_RENDERER_MAX_TILES_Y, ANKI_RENDERER_MAX_TILES_X>
  81. m_tempTiles;
  82. // To fill the light index buffer
  83. Atomic<U32> m_lightIdsCount;
  84. // Misc
  85. VisibilityTestResults::Container::ConstIterator m_lightsBegin = nullptr;
  86. VisibilityTestResults::Container::ConstIterator m_lightsEnd = nullptr;
  87. WeakPtr<Barrier> m_barrier;
  88. Is* m_is = nullptr;
  89. };
  90. /// Write the lights to the GPU buffers.
  91. class WriteLightsTask: public Threadpool::Task
  92. {
  93. public:
  94. TaskCommonData* m_data = nullptr;
  95. Error operator()(U32 threadId, PtrSize threadsCount)
  96. {
  97. m_data->m_is->binLights(threadId, threadsCount, *m_data);
  98. return ErrorCode::NONE;
  99. }
  100. };
  101. //==============================================================================
  102. const PixelFormat Is::RT_PIXEL_FORMAT(
  103. ComponentFormat::R11G11B10, TransformFormat::FLOAT);
  104. //==============================================================================
  105. Is::Is(Renderer* r)
  106. : RenderingPass(r)
  107. , m_sm(r)
  108. {}
  109. //==============================================================================
  110. Is::~Is()
  111. {
  112. if(m_barrier)
  113. {
  114. getAllocator().deleteInstance(&m_barrier.get());
  115. }
  116. }
  117. //==============================================================================
  118. Error Is::init(const ConfigSet& config)
  119. {
  120. Error err = initInternal(config);
  121. if(err)
  122. {
  123. ANKI_LOGE("Failed to init IS");
  124. }
  125. return err;
  126. }
  127. //==============================================================================
  128. Error Is::initInternal(const ConfigSet& config)
  129. {
  130. m_groundLightEnabled = config.getNumber("is.groundLightEnabled");
  131. m_maxPointLights = config.getNumber("is.maxPointLights");
  132. m_maxSpotLights = config.getNumber("is.maxSpotLights");
  133. m_maxSpotTexLights = config.getNumber("is.maxSpotTexLights");
  134. if(m_maxPointLights < 1 || m_maxSpotLights < 1 || m_maxSpotTexLights < 1)
  135. {
  136. ANKI_LOGE("Incorrect number of max lights");
  137. return ErrorCode::USER_DATA;
  138. }
  139. m_maxLightIds = config.getNumber("is.maxLightsPerTile");
  140. if(m_maxLightIds == 0)
  141. {
  142. ANKI_LOGE("Incorrect number of max light indices");
  143. return ErrorCode::USER_DATA;
  144. }
  145. m_maxLightIds *= m_r->getTilesCountXY();
  146. //
  147. // Init the passes
  148. //
  149. ANKI_CHECK(m_sm.init(config));
  150. //
  151. // Load the programs
  152. //
  153. StringAuto pps(getAllocator());
  154. pps.sprintf(
  155. "\n#define TILES_X_COUNT %u\n"
  156. "#define TILES_Y_COUNT %u\n"
  157. "#define TILES_COUNT %u\n"
  158. "#define RENDERER_WIDTH %u\n"
  159. "#define RENDERER_HEIGHT %u\n"
  160. "#define MAX_POINT_LIGHTS %u\n"
  161. "#define MAX_SPOT_LIGHTS %u\n"
  162. "#define MAX_SPOT_TEX_LIGHTS %u\n"
  163. "#define MAX_LIGHT_INDICES %u\n"
  164. "#define GROUND_LIGHT %u\n"
  165. "#define TILES_BLOCK_BINDING %u\n"
  166. "#define POISSON %u\n",
  167. m_r->getTilesCount().x(),
  168. m_r->getTilesCount().y(),
  169. (m_r->getTilesCount().x() * m_r->getTilesCount().y()),
  170. m_r->getWidth(),
  171. m_r->getHeight(),
  172. m_maxPointLights,
  173. m_maxSpotLights,
  174. m_maxSpotTexLights,
  175. m_maxLightIds,
  176. m_groundLightEnabled,
  177. TILES_BLOCK_BINDING,
  178. m_sm.getPoissonEnabled());
  179. // point light
  180. ANKI_CHECK(m_lightVert.loadToCache(&getResourceManager(),
  181. "shaders/IsLp.vert.glsl", pps.toCString(), "r_"));
  182. ANKI_CHECK(m_lightFrag.loadToCache(&getResourceManager(),
  183. "shaders/IsLp.frag.glsl", pps.toCString(), "r_"));
  184. PipelineInitializer init;
  185. init.m_inputAssembler.m_topology = PrimitiveTopology::TRIANGLE_STRIP;
  186. init.m_depthStencil.m_depthWriteEnabled = false;
  187. init.m_depthStencil.m_depthCompareFunction = CompareOperation::ALWAYS;
  188. init.m_color.m_attachmentCount = 1;
  189. init.m_color.m_attachments[0].m_format = RT_PIXEL_FORMAT;
  190. init.m_shaders[U(ShaderType::VERTEX)] = m_lightVert->getGrShader();
  191. init.m_shaders[U(ShaderType::FRAGMENT)] = m_lightFrag->getGrShader();
  192. m_lightPpline = getGrManager().newInstance<Pipeline>(init);
  193. //
  194. // Create framebuffer
  195. //
  196. m_r->createRenderTarget(
  197. m_r->getWidth(), m_r->getHeight(),
  198. RT_PIXEL_FORMAT, 1, SamplingFilter::LINEAR, MIPMAPS_COUNT, m_rt);
  199. FramebufferInitializer fbInit;
  200. fbInit.m_colorAttachmentsCount = 1;
  201. fbInit.m_colorAttachments[0].m_texture = m_rt;
  202. fbInit.m_colorAttachments[0].m_loadOperation =
  203. AttachmentLoadOperation::DONT_CARE;
  204. m_fb = getGrManager().newInstance<Framebuffer>(fbInit);
  205. //
  206. // Create UBOs
  207. //
  208. m_pLightsBuffSize = m_maxPointLights * sizeof(shader::PointLight);
  209. m_sLightsBuffSize = m_maxSpotLights * sizeof(shader::SpotLight);
  210. m_stLightsBuffSize = m_maxSpotTexLights * sizeof(shader::SpotLight);
  211. for(U i = 0; i < m_pLightsBuffs.getSize(); ++i)
  212. {
  213. // Point lights
  214. m_pLightsBuffs[i] = getGrManager().newInstance<Buffer>(
  215. m_pLightsBuffSize, BufferUsageBit::STORAGE,
  216. BufferAccessBit::CLIENT_MAP_WRITE);
  217. // Spot lights
  218. m_sLightsBuffs[i] = getGrManager().newInstance<Buffer>(
  219. m_sLightsBuffSize, BufferUsageBit::STORAGE,
  220. BufferAccessBit::CLIENT_MAP_WRITE);
  221. // Spot tex lights
  222. m_stLightsBuffs[i] = getGrManager().newInstance<Buffer>(
  223. m_stLightsBuffSize, BufferUsageBit::STORAGE,
  224. BufferAccessBit::CLIENT_MAP_WRITE);
  225. // Tiles
  226. m_tilesBuffers[i] = getGrManager().newInstance<Buffer>(
  227. m_r->getTilesCountXY() * sizeof(shader::Tile),
  228. BufferUsageBit::STORAGE, BufferAccessBit::CLIENT_MAP_WRITE);
  229. // Index
  230. m_lightIdsBuffers[i] = getGrManager().newInstance<Buffer>(
  231. (m_maxPointLights * m_maxSpotLights * m_maxSpotTexLights)
  232. * sizeof(U32),
  233. BufferUsageBit::STORAGE, BufferAccessBit::CLIENT_MAP_WRITE);
  234. }
  235. //
  236. // Create resource groups
  237. //
  238. for(U i = 0; i < m_rcGroups.getSize(); ++i)
  239. {
  240. ResourceGroupInitializer init;
  241. init.m_textures[0].m_texture = m_r->getMs().getRt0();
  242. init.m_textures[1].m_texture = m_r->getMs().getRt1();
  243. init.m_textures[2].m_texture = m_r->getMs().getRt2();
  244. init.m_textures[3].m_texture = m_r->getMs().getDepthRt();
  245. init.m_textures[4].m_texture = m_sm.getTextureArray();
  246. init.m_storageBuffers[0].m_buffer = m_pLightsBuffs[i];
  247. init.m_storageBuffers[1].m_buffer = m_sLightsBuffs[i];
  248. init.m_storageBuffers[2].m_buffer = m_stLightsBuffs[i];
  249. init.m_storageBuffers[3].m_buffer = m_tilesBuffers[i];
  250. init.m_storageBuffers[4].m_buffer = m_lightIdsBuffers[i];
  251. m_rcGroups[i] = getGrManager().newInstance<ResourceGroup>(init);
  252. }
  253. //
  254. // Misc
  255. //
  256. Threadpool& threadPool = m_r->getThreadpool();
  257. m_barrier = getAllocator().newInstance<Barrier>(
  258. threadPool.getThreadsCount());
  259. return ErrorCode::NONE;
  260. }
  261. //==============================================================================
  262. Error Is::lightPass(CommandBufferPtr& cmdBuff)
  263. {
  264. Threadpool& threadPool = m_r->getThreadpool();
  265. m_cam = &m_r->getActiveCamera();
  266. FrustumComponent& fr = m_cam->getComponent<FrustumComponent>();
  267. VisibilityTestResults& vi = fr.getVisibilityTestResults();
  268. m_currentFrame = getGlobalTimestamp() % MAX_FRAMES_IN_FLIGHT;
  269. U tilesCount = m_r->getTilesCountXY();
  270. //
  271. // Quickly get the lights
  272. //
  273. U visiblePointLightsCount = 0;
  274. U visibleSpotLightsCount = 0;
  275. U visibleSpotTexLightsCount = 0;
  276. Array<SceneNode*, Sm::MAX_SHADOW_CASTERS> shadowCasters;
  277. auto it = vi.getLightsBegin();
  278. auto lend = vi.getLightsEnd();
  279. for(; it != lend; ++it)
  280. {
  281. SceneNode* node = (*it).m_node;
  282. LightComponent& light = node->getComponent<LightComponent>();
  283. switch(light.getLightType())
  284. {
  285. case LightComponent::LightType::POINT:
  286. ++visiblePointLightsCount;
  287. break;
  288. case LightComponent::LightType::SPOT:
  289. {
  290. if(light.getShadowEnabled())
  291. {
  292. shadowCasters[visibleSpotTexLightsCount++] = node;
  293. }
  294. else
  295. {
  296. ++visibleSpotLightsCount;
  297. }
  298. break;
  299. }
  300. default:
  301. ANKI_ASSERT(0);
  302. break;
  303. }
  304. }
  305. // Sanitize the counters
  306. visiblePointLightsCount = min<U>(visiblePointLightsCount, m_maxPointLights);
  307. visibleSpotLightsCount = min<U>(visibleSpotLightsCount, m_maxSpotLights);
  308. visibleSpotTexLightsCount =
  309. min<U>(visibleSpotTexLightsCount, m_maxSpotTexLights);
  310. ANKI_COUNTER_INC(RENDERER_LIGHTS_COUNT,
  311. U64(visiblePointLightsCount + visibleSpotLightsCount
  312. + visibleSpotTexLightsCount));
  313. //
  314. // Do shadows pass
  315. //
  316. ANKI_CHECK(m_sm.run(&shadowCasters[0], visibleSpotTexLightsCount, cmdBuff));
  317. //
  318. // Write the lights and tiles UBOs
  319. //
  320. Array<WriteLightsTask, Threadpool::MAX_THREADS> tasks;
  321. TaskCommonData taskData;
  322. memset(&taskData, 0, sizeof(taskData));
  323. if(visiblePointLightsCount)
  324. {
  325. void* data = m_pLightsBuffs[m_currentFrame]->map(
  326. 0, visiblePointLightsCount * sizeof(shader::PointLight),
  327. BufferAccessBit::CLIENT_MAP_WRITE);
  328. taskData.m_pointLights = SArray<shader::PointLight>(
  329. static_cast<shader::PointLight*>(data), visiblePointLightsCount);
  330. }
  331. if(visibleSpotLightsCount)
  332. {
  333. void* data = m_sLightsBuffs[m_currentFrame]->map(
  334. 0, visibleSpotLightsCount * sizeof(shader::SpotLight),
  335. BufferAccessBit::CLIENT_MAP_WRITE);
  336. taskData.m_spotLights = SArray<shader::SpotLight>(
  337. static_cast<shader::SpotLight*>(data), visibleSpotLightsCount);
  338. }
  339. if(visibleSpotTexLightsCount)
  340. {
  341. void* data = m_stLightsBuffs[m_currentFrame]->map(
  342. 0, visibleSpotTexLightsCount * sizeof(shader::SpotLight),
  343. BufferAccessBit::CLIENT_MAP_WRITE);
  344. taskData.m_spotTexLights = SArray<shader::SpotLight>(
  345. static_cast<shader::SpotLight*>(data), visibleSpotTexLightsCount);
  346. }
  347. taskData.m_lightsBegin = vi.getLightsBegin();
  348. taskData.m_lightsEnd = vi.getLightsEnd();
  349. taskData.m_barrier = m_barrier;
  350. taskData.m_is = this;
  351. // Map tiles
  352. void* data = m_tilesBuffers[m_currentFrame]->map(
  353. 0,
  354. tilesCount * sizeof(shader::Tile),
  355. BufferAccessBit::CLIENT_MAP_WRITE);
  356. taskData.m_tiles = SArray<shader::Tile>(
  357. static_cast<shader::Tile*>(data), tilesCount);
  358. // Map light IDs
  359. data = m_lightIdsBuffers[m_currentFrame]->map(
  360. 0,
  361. m_maxLightIds * sizeof(Lid),
  362. BufferAccessBit::CLIENT_MAP_WRITE);
  363. taskData.m_lightIds = SArray<Lid>(static_cast<Lid*>(data), m_maxLightIds);
  364. for(U i = 0; i < threadPool.getThreadsCount(); i++)
  365. {
  366. tasks[i].m_data = &taskData;
  367. threadPool.assignNewTask(i, &tasks[i]);
  368. }
  369. // In the meantime set the state
  370. setState(cmdBuff);
  371. // Update uniforms
  372. updateCommonBlock(cmdBuff);
  373. // Sync
  374. ANKI_CHECK(threadPool.waitForAllThreadsToFinish());
  375. //
  376. // Unmap
  377. //
  378. if(visiblePointLightsCount)
  379. {
  380. m_pLightsBuffs[m_currentFrame]->unmap();
  381. }
  382. if(visibleSpotLightsCount)
  383. {
  384. m_sLightsBuffs[m_currentFrame]->unmap();
  385. }
  386. if(visibleSpotTexLightsCount)
  387. {
  388. m_stLightsBuffs[m_currentFrame]->unmap();
  389. }
  390. m_tilesBuffers[m_currentFrame]->unmap();
  391. m_lightIdsBuffers[m_currentFrame]->unmap();
  392. //
  393. // Draw
  394. //
  395. cmdBuff->drawArrays(4, m_r->getTilesCountXY());
  396. return ErrorCode::NONE;
  397. }
  398. //==============================================================================
  399. void Is::binLights(U32 threadId, PtrSize threadsCount, TaskCommonData& task)
  400. {
  401. U ligthsCount = task.m_lightsEnd - task.m_lightsBegin;
  402. const FrustumComponent& camfrc = m_cam->getComponent<FrustumComponent>();
  403. const MoveComponent& cammove = m_cam->getComponent<MoveComponent>();
  404. // Iterate lights and bin them
  405. PtrSize start, end;
  406. Threadpool::Task::choseStartEnd(
  407. threadId, threadsCount, ligthsCount, start, end);
  408. for(U64 i = start; i < end; i++)
  409. {
  410. SceneNode* snode = (*(task.m_lightsBegin + i)).m_node;
  411. MoveComponent& move = snode->getComponent<MoveComponent>();
  412. LightComponent& light = snode->getComponent<LightComponent>();
  413. SpatialComponent& sp = snode->getComponent<SpatialComponent>();
  414. switch(light.getLightType())
  415. {
  416. case LightComponent::LightType::POINT:
  417. {
  418. I pos = writePointLight(light, move, camfrc, task);
  419. if(pos != -1)
  420. {
  421. binLight(sp, pos, 0, task);
  422. }
  423. }
  424. break;
  425. case LightComponent::LightType::SPOT:
  426. {
  427. const FrustumComponent* frc =
  428. snode->tryGetComponent<FrustumComponent>();
  429. I pos = writeSpotLight(light, move, frc, cammove, camfrc, task);
  430. if(pos != -1)
  431. {
  432. binLight(sp, pos, light.getShadowEnabled() ? 2 : 1, task);
  433. }
  434. }
  435. break;
  436. default:
  437. ANKI_ASSERT(0);
  438. break;
  439. }
  440. }
  441. //
  442. // Last thing, update the real tiles
  443. //
  444. task.m_barrier->wait();
  445. const UVec2 tilesCount2d = m_r->getTilesCount();
  446. U tilesCount = tilesCount2d.x() * tilesCount2d.y();
  447. Threadpool::Task::choseStartEnd(
  448. threadId, threadsCount, tilesCount, start, end);
  449. // Run per tile
  450. for(U i = start; i < end; ++i)
  451. {
  452. U y = i / tilesCount2d.x();
  453. U x = i % tilesCount2d.x();
  454. const auto& tile = task.m_tempTiles[y][x];
  455. const U countP = tile.m_pointCount.load();
  456. const U countS = tile.m_spotCount.load();
  457. const U countST = tile.m_spotTexCount.load();
  458. const U count = countP + countS + countST;
  459. const U offset = task.m_lightIdsCount.fetchAdd(count);
  460. auto& t = task.m_tiles[i];
  461. if(offset + count <= m_maxLightIds)
  462. {
  463. t.m_offset = offset;
  464. if(countP > 0)
  465. {
  466. t.m_pointLightsCount = countP;
  467. memcpy(&task.m_lightIds[offset], &tile.m_pointIds[0],
  468. countP * sizeof(Lid));
  469. }
  470. else
  471. {
  472. t.m_pointLightsCount = 0;
  473. }
  474. if(countS > 0)
  475. {
  476. t.m_spotLightsCount = countS;
  477. memcpy(&task.m_lightIds[offset + countP], &tile.m_spotIds[0],
  478. countS * sizeof(Lid));
  479. }
  480. else
  481. {
  482. t.m_spotLightsCount = 0;
  483. }
  484. if(countST > 0)
  485. {
  486. t.m_spotTexLightsCount = countST;
  487. memcpy(&task.m_lightIds[offset + countP + countS],
  488. &tile.m_spotTexIds[0], countST * sizeof(Lid));
  489. }
  490. else
  491. {
  492. t.m_spotTexLightsCount = 0;
  493. }
  494. }
  495. else
  496. {
  497. memset(&t, 0, sizeof(t));
  498. ANKI_LOGW("Light IDs buffer too small");
  499. }
  500. }
  501. }
  502. //==============================================================================
  503. I Is::writePointLight(const LightComponent& lightc,
  504. const MoveComponent& lightMove,
  505. const FrustumComponent& camFrc, TaskCommonData& task)
  506. {
  507. // Get GPU light
  508. I i = task.m_pointLightsCount.fetchAdd(1);
  509. if(ANKI_UNLIKELY(i >= I(m_maxPointLights)))
  510. {
  511. return -1;
  512. }
  513. shader::PointLight& slight = task.m_pointLights[i];
  514. Vec4 pos = camFrc.getViewMatrix()
  515. * lightMove.getWorldTransform().getOrigin().xyz1();
  516. slight.m_posRadius = Vec4(pos.xyz(), -1.0 / lightc.getRadius());
  517. slight.m_diffuseColorShadowmapId = lightc.getDiffuseColor();
  518. slight.m_specularColorTexId = lightc.getSpecularColor();
  519. return i;
  520. }
  521. //==============================================================================
  522. I Is::writeSpotLight(const LightComponent& lightc,
  523. const MoveComponent& lightMove, const FrustumComponent* lightFrc,
  524. const MoveComponent& camMove, const FrustumComponent& camFrc,
  525. TaskCommonData& task)
  526. {
  527. Bool isTexLight = lightc.getShadowEnabled();
  528. I i;
  529. shader::SpotLight* baseslight = nullptr;
  530. if(isTexLight)
  531. {
  532. // Spot tex light
  533. i = task.m_spotTexLightsCount.fetchAdd(1);
  534. if(ANKI_UNLIKELY(i >= I(m_maxSpotTexLights)))
  535. {
  536. return -1;
  537. }
  538. shader::SpotLight& slight = task.m_spotTexLights[i];
  539. baseslight = &slight;
  540. // Write matrix
  541. static const Mat4 biasMat4(
  542. 0.5, 0.0, 0.0, 0.5,
  543. 0.0, 0.5, 0.0, 0.5,
  544. 0.0, 0.0, 0.5, 0.5,
  545. 0.0, 0.0, 0.0, 1.0);
  546. // bias * proj_l * view_l * world_c
  547. slight.m_texProjectionMat =
  548. biasMat4
  549. * lightFrc->getViewProjectionMatrix()
  550. * Mat4(camMove.getWorldTransform());
  551. // Transpose because of driver bug
  552. slight.m_texProjectionMat.transpose();
  553. }
  554. else
  555. {
  556. // Spot light without texture
  557. i = task.m_spotLightsCount.fetchAdd(1);
  558. if(ANKI_UNLIKELY(i >= I(m_maxSpotLights)))
  559. {
  560. return -1;
  561. }
  562. shader::SpotLight& slight = task.m_spotLights[i];
  563. baseslight = &slight;
  564. }
  565. // Write common stuff
  566. ANKI_ASSERT(baseslight);
  567. // Pos & dist
  568. Vec4 pos =
  569. camFrc.getViewMatrix()
  570. * lightMove.getWorldTransform().getOrigin().xyz1();
  571. baseslight->m_posRadius = Vec4(pos.xyz(), -1.0 / lightc.getDistance());
  572. // Diff color and shadowmap ID now
  573. baseslight->m_diffuseColorShadowmapId =
  574. Vec4(lightc.getDiffuseColor().xyz(), (F32)lightc.getShadowMapIndex());
  575. // Spec color
  576. baseslight->m_specularColorTexId = lightc.getSpecularColor();
  577. // Light dir
  578. Vec3 lightDir = -lightMove.getWorldTransform().getRotation().getZAxis();
  579. lightDir = camFrc.getViewMatrix().getRotationPart() * lightDir;
  580. baseslight->m_lightDir = Vec4(lightDir, 0.0);
  581. // Angles
  582. baseslight->m_outerCosInnerCos = Vec4(
  583. lightc.getOuterAngleCos(),
  584. lightc.getInnerAngleCos(),
  585. 1.0,
  586. 1.0);
  587. // extend points
  588. const PerspectiveFrustum& frustum =
  589. static_cast<const PerspectiveFrustum&>(lightFrc->getFrustum());
  590. return i;
  591. }
  592. //==============================================================================
  593. void Is::binLight(
  594. SpatialComponent& sp,
  595. U pos,
  596. U lightType,
  597. TaskCommonData& task)
  598. {
  599. // Do the tests
  600. Tiler::TestResult visTiles;
  601. Tiler::TestParameters params;
  602. params.m_collisionShape = &sp.getSpatialCollisionShape();
  603. params.m_collisionShapeBox = &sp.getAabb();
  604. params.m_nearPlane = true;
  605. params.m_output = &visTiles;
  606. m_r->getTiler().test(params);
  607. // Bin to the correct tiles
  608. for(U t = 0; t < visTiles.m_count; t++)
  609. {
  610. U x = visTiles.m_tileIds[t].m_x;
  611. U y = visTiles.m_tileIds[t].m_y;
  612. auto& tile = task.m_tempTiles[y][x];
  613. U idx;
  614. switch(lightType)
  615. {
  616. case 0:
  617. idx = tile.m_pointCount.fetchAdd(1) % MAX_TYPED_LIGHTS_PER_TILE;
  618. tile.m_pointIds[idx] = pos;
  619. break;
  620. case 1:
  621. idx = tile.m_spotCount.fetchAdd(1) % MAX_TYPED_LIGHTS_PER_TILE;
  622. tile.m_spotIds[idx] = pos;
  623. break;
  624. case 2:
  625. idx = tile.m_spotTexCount.fetchAdd(1) % MAX_TYPED_LIGHTS_PER_TILE;
  626. tile.m_spotTexIds[idx] = pos;
  627. break;
  628. default:
  629. ANKI_ASSERT(0);
  630. }
  631. }
  632. }
  633. //==============================================================================
  634. void Is::setState(CommandBufferPtr& cmdBuff)
  635. {
  636. cmdBuff->bindFramebuffer(m_fb);
  637. cmdBuff->setViewport(0, 0, m_r->getWidth(), m_r->getHeight());
  638. cmdBuff->bindPipeline(m_lightPpline);
  639. cmdBuff->bindResourceGroup(m_rcGroups[m_currentFrame]);
  640. }
  641. //==============================================================================
  642. Error Is::run(CommandBufferPtr& cmdBuff)
  643. {
  644. // Do the light pass including the shadow passes
  645. return lightPass(cmdBuff);
  646. }
  647. //==============================================================================
  648. void Is::updateCommonBlock(CommandBufferPtr& cmdb)
  649. {
  650. shader::CommonUniforms* blk;
  651. cmdb->updateDynamicUniforms(sizeof(*blk), blk);
  652. // Start writing
  653. blk->m_projectionParams = m_r->getProjectionParameters();
  654. blk->m_sceneAmbientColor = m_ambientColor;
  655. Vec3 groundLightDir;
  656. if(m_groundLightEnabled)
  657. {
  658. const Mat4& viewMat =
  659. m_cam->getComponent<FrustumComponent>().getViewMatrix();
  660. blk->m_groundLightDir = Vec4(-viewMat.getColumn(1).xyz(), 1.0);
  661. }
  662. }
  663. } // end namespace anki