ClusterBinning.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485
  1. // Copyright (C) 2009-2021, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <AnKi/Renderer/ClusterBinning.h>
  6. #include <AnKi/Renderer/Renderer.h>
  7. #include <AnKi/Renderer/RenderQueue.h>
  8. #include <AnKi/Renderer/VolumetricLightingAccumulation.h>
  9. #include <AnKi/Core/ConfigSet.h>
  10. #include <AnKi/Util/Tracer.h>
  11. #include <AnKi/Util/ThreadHive.h>
  12. #include <AnKi/Util/HighRezTimer.h>
  13. #include <AnKi/Collision/Plane.h>
  14. #include <AnKi/Collision/Functions.h>
  15. namespace anki
  16. {
  17. ClusterBinning::ClusterBinning(Renderer* r)
  18. : RendererObject(r)
  19. {
  20. }
  21. ClusterBinning::~ClusterBinning()
  22. {
  23. }
  24. Error ClusterBinning::init(const ConfigSet& config)
  25. {
  26. ANKI_R_LOGI("Initializing clusterer binning");
  27. ANKI_CHECK(getResourceManager().loadResource("Shaders/ClusterBinning.ankiprog", m_prog));
  28. ShaderProgramResourceVariantInitInfo variantInitInfo(m_prog);
  29. variantInitInfo.addConstant("TILE_SIZE", m_r->getTileSize());
  30. variantInitInfo.addConstant("TILE_COUNT_X", m_r->getTileCounts().x());
  31. variantInitInfo.addConstant("TILE_COUNT_Y", m_r->getTileCounts().y());
  32. variantInitInfo.addConstant("Z_SPLIT_COUNT", m_r->getZSplitCount());
  33. variantInitInfo.addConstant("RENDERING_SIZE", UVec2(m_r->getWidth(), m_r->getHeight()));
  34. const ShaderProgramResourceVariant* variant;
  35. m_prog->getOrCreateVariant(variantInitInfo, variant);
  36. m_grProg = variant->getProgram();
  37. m_tileCount = m_r->getTileCounts().x() * m_r->getTileCounts().y();
  38. m_clusterCount = m_tileCount + m_r->getZSplitCount();
  39. return Error::NONE;
  40. }
  41. void ClusterBinning::populateRenderGraph(RenderingContext& ctx)
  42. {
  43. m_runCtx.m_ctx = &ctx;
  44. writeClustererBuffers(ctx);
  45. ctx.m_clusteredShading.m_clustersBufferHandle = ctx.m_renderGraphDescr.importBuffer(
  46. ctx.m_clusteredShading.m_clustersToken.m_buffer, BufferUsageBit::NONE,
  47. ctx.m_clusteredShading.m_clustersToken.m_offset, ctx.m_clusteredShading.m_clustersToken.m_range);
  48. const RenderQueue& rqueue = *m_runCtx.m_ctx->m_renderQueue;
  49. if(ANKI_LIKELY(rqueue.m_pointLights.getSize() || rqueue.m_spotLights.getSize() || rqueue.m_decals.getSize()
  50. || rqueue.m_reflectionProbes.getSize() || rqueue.m_fogDensityVolumes.getSize()
  51. || rqueue.m_giProbes.getSize()))
  52. {
  53. RenderGraphDescription& rgraph = ctx.m_renderGraphDescr;
  54. ComputeRenderPassDescription& pass = rgraph.newComputeRenderPass("Cluster Binning");
  55. pass.setWork(
  56. [](RenderPassWorkContext& rgraphCtx) {
  57. static_cast<ClusterBinning*>(rgraphCtx.m_userData)->run(rgraphCtx);
  58. },
  59. this, 0);
  60. pass.newDependency(
  61. RenderPassDependency(ctx.m_clusteredShading.m_clustersBufferHandle, BufferUsageBit::STORAGE_COMPUTE_WRITE));
  62. }
  63. }
  64. void ClusterBinning::run(RenderPassWorkContext& rgraphCtx)
  65. {
  66. CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
  67. const ClusteredShadingContext& tokens = m_runCtx.m_ctx->m_clusteredShading;
  68. cmdb->bindShaderProgram(m_grProg);
  69. bindUniforms(cmdb, 0, 0, tokens.m_clusteredShadingUniformsToken);
  70. bindStorage(cmdb, 0, 1, tokens.m_clustersToken);
  71. bindUniforms(cmdb, 0, 2, tokens.m_pointLightsToken);
  72. bindUniforms(cmdb, 0, 3, tokens.m_spotLightsToken);
  73. bindUniforms(cmdb, 0, 4, tokens.m_reflectionProbesToken);
  74. bindUniforms(cmdb, 0, 5, tokens.m_globalIlluminationProbesToken);
  75. bindUniforms(cmdb, 0, 6, tokens.m_fogDensityVolumesToken);
  76. bindUniforms(cmdb, 0, 7, tokens.m_decalsToken);
  77. const U32 sampleCount = 4;
  78. const U32 sizex = m_tileCount * sampleCount;
  79. const RenderQueue& rqueue = *m_runCtx.m_ctx->m_renderQueue;
  80. U32 clusterObjectCounts = rqueue.m_pointLights.getSize();
  81. clusterObjectCounts += rqueue.m_spotLights.getSize();
  82. clusterObjectCounts += rqueue.m_reflectionProbes.getSize();
  83. clusterObjectCounts += rqueue.m_giProbes.getSize();
  84. clusterObjectCounts += rqueue.m_fogDensityVolumes.getSize();
  85. clusterObjectCounts += rqueue.m_decals.getSize();
  86. cmdb->dispatchCompute((sizex + 64 - 1) / 64, clusterObjectCounts, 1);
  87. }
  88. void ClusterBinning::writeClustererBuffers(RenderingContext& ctx)
  89. {
  90. ANKI_TRACE_SCOPED_EVENT(R_WRITE_CLUSTER_SHADING_OBJECTS);
  91. // Check limits
  92. RenderQueue& rqueue = *ctx.m_renderQueue;
  93. if(ANKI_UNLIKELY(rqueue.m_pointLights.getSize() > MAX_VISIBLE_POINT_LIGHTS))
  94. {
  95. ANKI_R_LOGW("Visible point lights exceed the max value by %u",
  96. rqueue.m_pointLights.getSize() - MAX_VISIBLE_POINT_LIGHTS);
  97. rqueue.m_pointLights.setArray(rqueue.m_pointLights.getBegin(), MAX_VISIBLE_POINT_LIGHTS);
  98. }
  99. if(ANKI_UNLIKELY(rqueue.m_spotLights.getSize() > MAX_VISIBLE_SPOT_LIGHTS))
  100. {
  101. ANKI_R_LOGW("Visible spot lights exceed the max value by %u",
  102. rqueue.m_spotLights.getSize() - MAX_VISIBLE_SPOT_LIGHTS);
  103. rqueue.m_spotLights.setArray(rqueue.m_spotLights.getBegin(), MAX_VISIBLE_SPOT_LIGHTS);
  104. }
  105. if(ANKI_UNLIKELY(rqueue.m_decals.getSize() > MAX_VISIBLE_DECALS))
  106. {
  107. ANKI_R_LOGW("Visible decals exceed the max value by %u", rqueue.m_decals.getSize() - MAX_VISIBLE_DECALS);
  108. rqueue.m_decals.setArray(rqueue.m_decals.getBegin(), MAX_VISIBLE_DECALS);
  109. }
  110. if(ANKI_UNLIKELY(rqueue.m_fogDensityVolumes.getSize() > MAX_VISIBLE_FOG_DENSITY_VOLUMES))
  111. {
  112. ANKI_R_LOGW("Visible fog volumes exceed the max value by %u",
  113. rqueue.m_fogDensityVolumes.getSize() - MAX_VISIBLE_FOG_DENSITY_VOLUMES);
  114. rqueue.m_fogDensityVolumes.setArray(rqueue.m_fogDensityVolumes.getBegin(), MAX_VISIBLE_FOG_DENSITY_VOLUMES);
  115. }
  116. if(ANKI_UNLIKELY(rqueue.m_reflectionProbes.getSize() > MAX_VISIBLE_REFLECTION_PROBES))
  117. {
  118. ANKI_R_LOGW("Visible reflection probes exceed the max value by %u",
  119. rqueue.m_reflectionProbes.getSize() - MAX_VISIBLE_REFLECTION_PROBES);
  120. rqueue.m_reflectionProbes.setArray(rqueue.m_reflectionProbes.getBegin(), MAX_VISIBLE_REFLECTION_PROBES);
  121. }
  122. if(ANKI_UNLIKELY(rqueue.m_giProbes.getSize() > MAX_VISIBLE_GLOBAL_ILLUMINATION_PROBES))
  123. {
  124. ANKI_R_LOGW("Visible GI probes exceed the max value by %u",
  125. rqueue.m_giProbes.getSize() - MAX_VISIBLE_GLOBAL_ILLUMINATION_PROBES);
  126. rqueue.m_giProbes.setArray(rqueue.m_giProbes.getBegin(), MAX_VISIBLE_GLOBAL_ILLUMINATION_PROBES);
  127. }
  128. // Allocate buffers
  129. ClusteredShadingContext& cs = ctx.m_clusteredShading;
  130. StagingGpuMemoryManager& stagingMem = m_r->getStagingGpuMemoryManager();
  131. cs.m_clusteredShadingUniformsAddress = stagingMem.allocateFrame(
  132. sizeof(ClusteredShadingUniforms), StagingGpuMemoryType::UNIFORM, cs.m_clusteredShadingUniformsToken);
  133. if(rqueue.m_pointLights.getSize())
  134. {
  135. cs.m_pointLightsAddress = stagingMem.allocateFrame(rqueue.m_pointLights.getSize() * sizeof(PointLight),
  136. StagingGpuMemoryType::UNIFORM, cs.m_pointLightsToken);
  137. }
  138. else
  139. {
  140. cs.m_pointLightsToken.markUnused();
  141. }
  142. if(rqueue.m_spotLights.getSize())
  143. {
  144. cs.m_spotLightsAddress = stagingMem.allocateFrame(rqueue.m_spotLights.getSize() * sizeof(SpotLight),
  145. StagingGpuMemoryType::UNIFORM, cs.m_spotLightsToken);
  146. }
  147. else
  148. {
  149. cs.m_spotLightsToken.markUnused();
  150. }
  151. if(rqueue.m_reflectionProbes.getSize())
  152. {
  153. cs.m_reflectionProbesAddress =
  154. stagingMem.allocateFrame(rqueue.m_reflectionProbes.getSize() * sizeof(ReflectionProbe),
  155. StagingGpuMemoryType::UNIFORM, cs.m_reflectionProbesToken);
  156. }
  157. else
  158. {
  159. cs.m_reflectionProbesToken.markUnused();
  160. }
  161. if(rqueue.m_decals.getSize())
  162. {
  163. cs.m_decalsAddress = stagingMem.allocateFrame(rqueue.m_decals.getSize() * sizeof(Decal),
  164. StagingGpuMemoryType::UNIFORM, cs.m_decalsToken);
  165. }
  166. else
  167. {
  168. cs.m_decalsToken.markUnused();
  169. }
  170. if(rqueue.m_fogDensityVolumes.getSize())
  171. {
  172. cs.m_fogDensityVolumesAddress =
  173. stagingMem.allocateFrame(rqueue.m_fogDensityVolumes.getSize() * sizeof(FogDensityVolume),
  174. StagingGpuMemoryType::UNIFORM, cs.m_fogDensityVolumesToken);
  175. }
  176. else
  177. {
  178. cs.m_fogDensityVolumesToken.markUnused();
  179. }
  180. if(rqueue.m_giProbes.getSize())
  181. {
  182. cs.m_globalIlluminationProbesAddress =
  183. stagingMem.allocateFrame(rqueue.m_giProbes.getSize() * sizeof(GlobalIlluminationProbe),
  184. StagingGpuMemoryType::UNIFORM, cs.m_globalIlluminationProbesToken);
  185. }
  186. else
  187. {
  188. cs.m_globalIlluminationProbesToken.markUnused();
  189. }
  190. cs.m_clustersAddress =
  191. stagingMem.allocateFrame(sizeof(Cluster) * m_clusterCount, StagingGpuMemoryType::STORAGE, cs.m_clustersToken);
  192. }
  193. void ClusterBinning::writeClusterBuffersAsync()
  194. {
  195. m_r->getThreadHive().submitTask(
  196. [](void* userData, U32 threadId, ThreadHive& hive, ThreadHiveSemaphore* signalSemaphore) {
  197. static_cast<ClusterBinning*>(userData)->writeClustererBuffersTask();
  198. },
  199. this);
  200. }
  201. void ClusterBinning::writeClustererBuffersTask()
  202. {
  203. ANKI_TRACE_SCOPED_EVENT(R_WRITE_CLUSTER_SHADING_OBJECTS);
  204. RenderingContext& ctx = *m_runCtx.m_ctx;
  205. ClusteredShadingContext& cs = ctx.m_clusteredShading;
  206. const RenderQueue& rqueue = *ctx.m_renderQueue;
  207. // Point lights
  208. if(rqueue.m_pointLights.getSize())
  209. {
  210. PointLight* lights = static_cast<PointLight*>(cs.m_pointLightsAddress);
  211. for(U32 i = 0; i < rqueue.m_pointLights.getSize(); ++i)
  212. {
  213. PointLight& out = lights[i];
  214. const PointLightQueueElement& in = rqueue.m_pointLights[i];
  215. out.m_position = in.m_worldPosition;
  216. out.m_diffuseColor = in.m_diffuseColor;
  217. out.m_radius = in.m_radius;
  218. out.m_squareRadiusOverOne = 1.0f / (in.m_radius * in.m_radius);
  219. if(in.m_shadowRenderQueues[0] == nullptr)
  220. {
  221. out.m_shadowAtlasTileScale = -1.0f;
  222. out.m_shadowLayer = MAX_U32;
  223. }
  224. else
  225. {
  226. out.m_shadowLayer = in.m_shadowLayer;
  227. out.m_shadowAtlasTileScale = in.m_shadowAtlasTileSize;
  228. static_assert(sizeof(out.m_shadowAtlasTileOffsets) == sizeof(in.m_shadowAtlasTileOffsets), "See file");
  229. memcpy(&out.m_shadowAtlasTileOffsets[0], &in.m_shadowAtlasTileOffsets[0],
  230. sizeof(in.m_shadowAtlasTileOffsets));
  231. }
  232. }
  233. }
  234. // Spot lights
  235. if(rqueue.m_spotLights.getSize())
  236. {
  237. SpotLight* lights = static_cast<SpotLight*>(cs.m_spotLightsAddress);
  238. for(U32 i = 0; i < rqueue.m_spotLights.getSize(); ++i)
  239. {
  240. const SpotLightQueueElement& in = rqueue.m_spotLights[i];
  241. SpotLight& out = lights[i];
  242. out.m_position = in.m_worldTransform.getTranslationPart().xyz();
  243. memcpy(&out.m_edgePoints[0][0], &in.m_edgePoints[0][0], sizeof(out.m_edgePoints));
  244. out.m_diffuseColor = in.m_diffuseColor;
  245. out.m_radius = in.m_distance;
  246. out.m_squareRadiusOverOne = 1.0f / (in.m_distance * in.m_distance);
  247. out.m_shadowLayer = (in.hasShadow()) ? in.m_shadowLayer : MAX_U32;
  248. out.m_direction = -in.m_worldTransform.getRotationPart().getZAxis();
  249. out.m_outerCos = cos(in.m_outerAngle / 2.0f);
  250. out.m_innerCos = cos(in.m_innerAngle / 2.0f);
  251. if(in.hasShadow())
  252. {
  253. // bias * proj_l * view_l
  254. out.m_textureMatrix = in.m_textureMatrix;
  255. }
  256. else
  257. {
  258. out.m_textureMatrix = Mat4::getIdentity();
  259. }
  260. }
  261. }
  262. // Reflection probes
  263. if(rqueue.m_reflectionProbes.getSize())
  264. {
  265. ReflectionProbe* probes = static_cast<ReflectionProbe*>(cs.m_reflectionProbesAddress);
  266. for(U32 i = 0; i < rqueue.m_reflectionProbes.getSize(); ++i)
  267. {
  268. const ReflectionProbeQueueElement& in = rqueue.m_reflectionProbes[i];
  269. ReflectionProbe& out = probes[i];
  270. out.m_position = in.m_worldPosition;
  271. out.m_cubemapIndex = F32(in.m_textureArrayIndex);
  272. out.m_aabbMin = in.m_aabbMin;
  273. out.m_aabbMax = in.m_aabbMax;
  274. }
  275. }
  276. // Decals
  277. if(rqueue.m_decals.getSize())
  278. {
  279. Decal* decals = static_cast<Decal*>(cs.m_decalsAddress);
  280. TextureView* diffuseAtlas = nullptr;
  281. TextureView* specularRoughnessAtlas = nullptr;
  282. for(U32 i = 0; i < rqueue.m_decals.getSize(); ++i)
  283. {
  284. const DecalQueueElement& in = rqueue.m_decals[i];
  285. Decal& out = decals[i];
  286. if((diffuseAtlas != nullptr && diffuseAtlas != in.m_diffuseAtlas)
  287. || (specularRoughnessAtlas != nullptr && specularRoughnessAtlas != in.m_specularRoughnessAtlas))
  288. {
  289. ANKI_R_LOGF("All decals should have the same tex atlas");
  290. }
  291. diffuseAtlas = in.m_diffuseAtlas;
  292. specularRoughnessAtlas = in.m_specularRoughnessAtlas;
  293. // Diff
  294. Vec4 uv = in.m_diffuseAtlasUv;
  295. out.m_diffuseUv = Vec4(uv.x(), uv.y(), uv.z() - uv.x(), uv.w() - uv.y());
  296. out.m_blendFactors[0] = in.m_diffuseAtlasBlendFactor;
  297. // Other
  298. uv = in.m_specularRoughnessAtlasUv;
  299. out.m_normRoughnessUv = Vec4(uv.x(), uv.y(), uv.z() - uv.x(), uv.w() - uv.y());
  300. out.m_blendFactors[1] = in.m_specularRoughnessAtlasBlendFactor;
  301. // bias * proj_l * view
  302. out.m_textureMatrix = in.m_textureMatrix;
  303. // Transform
  304. const Mat4 trf(in.m_obbCenter.xyz1(), in.m_obbRotation, 1.0f);
  305. out.m_invertedTransform = trf.getInverse();
  306. out.m_obbExtend = in.m_obbExtend;
  307. }
  308. ANKI_ASSERT(diffuseAtlas || specularRoughnessAtlas);
  309. ctx.m_clusteredShading.m_diffuseDecalTextureView.reset(diffuseAtlas);
  310. ctx.m_clusteredShading.m_specularRoughnessDecalTextureView.reset(specularRoughnessAtlas);
  311. }
  312. // Fog volumes
  313. if(rqueue.m_fogDensityVolumes.getSize())
  314. {
  315. FogDensityVolume* volumes = static_cast<FogDensityVolume*>(cs.m_fogDensityVolumesAddress);
  316. for(U32 i = 0; i < rqueue.m_fogDensityVolumes.getSize(); ++i)
  317. {
  318. const FogDensityQueueElement& in = rqueue.m_fogDensityVolumes[i];
  319. FogDensityVolume& out = volumes[i];
  320. out.m_density = in.m_density;
  321. if(in.m_isBox)
  322. {
  323. out.m_isBox = 1;
  324. out.m_aabbMinOrSphereCenter = in.m_aabbMin;
  325. out.m_aabbMaxOrSphereRadiusSquared = in.m_aabbMax;
  326. }
  327. else
  328. {
  329. out.m_isBox = 0;
  330. out.m_aabbMinOrSphereCenter = in.m_sphereCenter;
  331. out.m_aabbMaxOrSphereRadiusSquared = Vec3(in.m_sphereRadius * in.m_sphereRadius);
  332. }
  333. }
  334. }
  335. // GI
  336. if(rqueue.m_giProbes.getSize())
  337. {
  338. GlobalIlluminationProbe* probes = static_cast<GlobalIlluminationProbe*>(cs.m_globalIlluminationProbesAddress);
  339. for(U32 i = 0; i < rqueue.m_giProbes.getSize(); ++i)
  340. {
  341. const GlobalIlluminationProbeQueueElement& in = rqueue.m_giProbes[i];
  342. GlobalIlluminationProbe& out = probes[i];
  343. out.m_aabbMin = in.m_aabbMin;
  344. out.m_aabbMax = in.m_aabbMax;
  345. out.m_textureIndex = U32(&in - &rqueue.m_giProbes.getFront());
  346. out.m_halfTexelSizeU = 1.0f / F32(F32(in.m_cellCounts.x()) * 6.0f) / 2.0f;
  347. out.m_fadeDistance = in.m_fadeDistance;
  348. }
  349. }
  350. // General uniforms
  351. {
  352. ClusteredShadingUniforms& unis = *static_cast<ClusteredShadingUniforms*>(cs.m_clusteredShadingUniformsAddress);
  353. unis.m_renderingSize = Vec2(F32(m_r->getWidth()), F32(m_r->getHeight()));
  354. unis.m_time = F32(HighRezTimer::getCurrentTime());
  355. unis.m_frame = m_r->getFrameCount() & MAX_U32;
  356. Plane nearPlane;
  357. extractClipPlane(rqueue.m_viewProjectionMatrix, FrustumPlaneType::NEAR, nearPlane);
  358. unis.m_nearPlaneWSpace = Vec4(nearPlane.getNormal().xyz(), nearPlane.getOffset());
  359. unis.m_near = rqueue.m_cameraNear;
  360. unis.m_far = rqueue.m_cameraFar;
  361. unis.m_cameraPosition = rqueue.m_cameraTransform.getTranslationPart().xyz();
  362. unis.m_tileCounts = m_r->getTileCounts();
  363. unis.m_zSplitCount = m_r->getZSplitCount();
  364. unis.m_zSplitCountOverFrustumLength = F32(m_r->getZSplitCount()) / (rqueue.m_cameraFar - rqueue.m_cameraNear);
  365. unis.m_zSplitMagic.x() =
  366. (rqueue.m_cameraNear - rqueue.m_cameraFar) / (rqueue.m_cameraNear * F32(m_r->getZSplitCount()));
  367. unis.m_zSplitMagic.y() = rqueue.m_cameraFar / (rqueue.m_cameraNear * F32(m_r->getZSplitCount()));
  368. unis.m_tileSize = m_r->getTileSize();
  369. unis.m_lightVolumeLastZSplit = m_r->getVolumetricLightingAccumulation().getFinalZSplit();
  370. unis.m_objectCountsUpTo[CLUSTER_OBJECT_TYPE_POINT_LIGHT] = rqueue.m_pointLights.getSize();
  371. unis.m_objectCountsUpTo[CLUSTER_OBJECT_TYPE_SPOT_LIGHT] =
  372. unis.m_objectCountsUpTo[CLUSTER_OBJECT_TYPE_SPOT_LIGHT - 1] + rqueue.m_spotLights.getSize();
  373. unis.m_objectCountsUpTo[CLUSTER_OBJECT_TYPE_DECAL] =
  374. unis.m_objectCountsUpTo[CLUSTER_OBJECT_TYPE_DECAL - 1] + rqueue.m_decals.getSize();
  375. unis.m_objectCountsUpTo[CLUSTER_OBJECT_TYPE_FOG_DENSITY_VOLUME] =
  376. unis.m_objectCountsUpTo[CLUSTER_OBJECT_TYPE_FOG_DENSITY_VOLUME - 1] + rqueue.m_fogDensityVolumes.getSize();
  377. unis.m_objectCountsUpTo[CLUSTER_OBJECT_TYPE_REFLECTION_PROBE] =
  378. unis.m_objectCountsUpTo[CLUSTER_OBJECT_TYPE_REFLECTION_PROBE - 1] + rqueue.m_reflectionProbes.getSize();
  379. unis.m_objectCountsUpTo[CLUSTER_OBJECT_TYPE_GLOBAL_ILLUMINATION_PROBE] =
  380. unis.m_objectCountsUpTo[CLUSTER_OBJECT_TYPE_GLOBAL_ILLUMINATION_PROBE - 1] + rqueue.m_giProbes.getSize();
  381. unis.m_matrices = ctx.m_matrices;
  382. unis.m_previousMatrices = ctx.m_prevMatrices;
  383. // Directional light
  384. if(rqueue.m_directionalLight.m_uuid != 0)
  385. {
  386. DirectionalLight& out = unis.m_directionalLight;
  387. const DirectionalLightQueueElement& in = rqueue.m_directionalLight;
  388. out.m_diffuseColor = in.m_diffuseColor;
  389. out.m_cascadeCount = in.m_shadowCascadeCount;
  390. out.m_direction = in.m_direction;
  391. out.m_active = 1;
  392. out.m_effectiveShadowDistance = in.m_effectiveShadowDistance;
  393. out.m_shadowCascadesDistancePower = in.m_shadowCascadesDistancePower;
  394. out.m_shadowLayer = (in.hasShadow()) ? in.m_shadowLayer : MAX_U32;
  395. for(U cascade = 0; cascade < in.m_shadowCascadeCount; ++cascade)
  396. {
  397. out.m_textureMatrices[cascade] = in.m_textureMatrices[cascade];
  398. }
  399. }
  400. else
  401. {
  402. unis.m_directionalLight.m_active = 0;
  403. }
  404. }
  405. // Zero the memory because atomics will happen
  406. memset(cs.m_clustersAddress, 0, sizeof(Cluster) * m_clusterCount);
  407. }
  408. } // end namespace anki