2
0

Is.cpp 21 KB

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