MaterialComponent.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  1. // Copyright (C) 2009-present, 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/Scene/Components/MaterialComponent.h>
  6. #include <AnKi/Scene/Components/SkinComponent.h>
  7. #include <AnKi/Scene/Components/MeshComponent.h>
  8. #include <AnKi/Scene/Components/MoveComponent.h>
  9. #include <AnKi/Scene/Components/ParticleEmitter2Component.h>
  10. #include <AnKi/Resource/MeshResource.h>
  11. #include <AnKi/Resource/MaterialResource.h>
  12. #include <AnKi/Resource/ResourceManager.h>
  13. #include <AnKi/Core/App.h>
  14. #include <AnKi/Shaders/Include/GpuSceneFunctions.h>
  15. namespace anki {
  16. MaterialComponent::MaterialComponent(SceneNode* node)
  17. : SceneComponent(node, kClassType)
  18. {
  19. m_gpuSceneRenderable.allocate();
  20. }
  21. MaterialComponent::~MaterialComponent()
  22. {
  23. m_gpuSceneRenderable.free();
  24. }
  25. MaterialComponent& MaterialComponent::setMaterialFilename(CString fname)
  26. {
  27. MaterialResourcePtr newRsrc;
  28. if(ResourceManager::getSingleton().loadResource(fname, newRsrc))
  29. {
  30. ANKI_SCENE_LOGE("Failed to load resource: %s", fname.cstr());
  31. }
  32. else
  33. {
  34. m_anyDirty = !m_resource || (m_resource->getUuid() != newRsrc->getUuid());
  35. m_resource = std::move(newRsrc);
  36. m_castsShadow = m_resource->castsShadow();
  37. }
  38. return *this;
  39. }
  40. CString MaterialComponent::getMaterialFilename() const
  41. {
  42. if(m_resource)
  43. {
  44. return m_resource->getFilename();
  45. }
  46. else
  47. {
  48. return "*Error*";
  49. }
  50. }
  51. MaterialComponent& MaterialComponent::setSubmeshIndex(U32 submeshIdx)
  52. {
  53. if(m_submeshIdx != submeshIdx)
  54. {
  55. m_submeshIdx = submeshIdx;
  56. m_anyDirty = true;
  57. }
  58. return *this;
  59. }
  60. void MaterialComponent::onOtherComponentRemovedOrAdded(SceneComponent* other, Bool added)
  61. {
  62. ANKI_ASSERT(other);
  63. if(other->getType() == SceneComponentType::kMesh)
  64. {
  65. bookkeepComponent(m_meshComponent, other, added);
  66. m_anyDirty = true;
  67. }
  68. if(other->getType() == SceneComponentType::kSkin)
  69. {
  70. bookkeepComponent(m_skinComponent, other, added);
  71. m_anyDirty = true;
  72. }
  73. if(other->getType() == SceneComponentType::kParticleEmitter2)
  74. {
  75. bookkeepComponent(m_emitterComponent, other, added);
  76. m_anyDirty = true;
  77. }
  78. }
  79. Bool MaterialComponent::isValid() const
  80. {
  81. Bool valid = !!m_resource && m_resource->isLoaded();
  82. if(m_meshComponent)
  83. {
  84. valid = valid && m_meshComponent->isValid();
  85. }
  86. if(m_emitterComponent)
  87. {
  88. valid = valid && m_emitterComponent->isValid();
  89. }
  90. valid = valid && (m_meshComponent || m_emitterComponent);
  91. if(m_skinComponent)
  92. {
  93. valid = valid && m_skinComponent->isValid();
  94. }
  95. return valid;
  96. }
  97. Aabb MaterialComponent::computeAabb(const SceneNode& node) const
  98. {
  99. const Bool prioritizeEmitter = m_emitterComponent != nullptr;
  100. Aabb aabbWorld;
  101. if(prioritizeEmitter)
  102. {
  103. aabbWorld = Aabb(m_emitterComponent->getBoundingVolume()[0], m_emitterComponent->getBoundingVolume()[1]);
  104. }
  105. else
  106. {
  107. Aabb aabbLocal;
  108. U32 firstIndex, indexCount, firstMeshlet, meshletCount;
  109. m_meshComponent->getMeshResource().getSubMeshInfo(0, m_submeshIdx, firstIndex, indexCount, firstMeshlet, meshletCount, aabbLocal);
  110. if(m_skinComponent && m_skinComponent->isValid())
  111. {
  112. aabbLocal = m_skinComponent->getBoneBoundingVolumeLocalSpace().getCompoundShape(aabbLocal);
  113. }
  114. aabbWorld = aabbLocal.getTransformed(node.getWorldTransform());
  115. }
  116. return aabbWorld;
  117. }
  118. void MaterialComponent::update(SceneComponentUpdateInfo& info, Bool& updated)
  119. {
  120. if(!isValid()) [[unlikely]]
  121. {
  122. m_gpuSceneRenderableAabbGBuffer.free();
  123. m_gpuSceneRenderableAabbDepth.free();
  124. m_gpuSceneRenderableAabbForward.free();
  125. m_gpuSceneRenderableAabbRt.free();
  126. for(RenderingTechnique t : EnumIterable<RenderingTechnique>())
  127. {
  128. RenderStateBucketContainer::getSingleton().removeUser(m_renderStateBucketIndices[t]);
  129. }
  130. return;
  131. }
  132. // From now on the component is considered valid
  133. const Bool moved = info.m_node->movedThisFrame();
  134. const Bool movedLastFrame = m_movedLastFrame;
  135. m_movedLastFrame = moved;
  136. Bool dirty = m_anyDirty || moved != movedLastFrame;
  137. const Bool prioritizeEmitter = !!m_emitterComponent;
  138. const MaterialResource& mtl = *m_resource;
  139. if(m_skinComponent)
  140. {
  141. dirty = dirty || m_skinComponent->gpuSceneReallocationsThisFrame();
  142. }
  143. if(m_emitterComponent)
  144. {
  145. dirty = dirty || m_emitterComponent->gpuSceneReallocationsThisFrame();
  146. }
  147. if(m_meshComponent)
  148. {
  149. dirty = dirty || m_meshComponent->gpuSceneReallocationsThisFrame();
  150. }
  151. if(!dirty) [[likely]]
  152. {
  153. // Update Scene bounds
  154. if(info.m_forceUpdateSceneBounds || m_skinComponent) [[unlikely]]
  155. {
  156. const Aabb aabbWorld = computeAabb(*info.m_node);
  157. info.updateSceneBounds(aabbWorld.getMin().xyz(), aabbWorld.getMax().xyz());
  158. }
  159. // Update the GPU scene AABBs
  160. if(prioritizeEmitter || m_skinComponent)
  161. {
  162. const Aabb aabbWorld = computeAabb(*info.m_node);
  163. for(RenderingTechnique t : EnumBitsIterable<RenderingTechnique, RenderingTechniqueBit>(mtl.getRenderingTechniques()))
  164. {
  165. const GpuSceneRenderableBoundingVolume gpuVolume = initGpuSceneRenderableBoundingVolume(
  166. aabbWorld.getMin().xyz(), aabbWorld.getMax().xyz(), m_gpuSceneRenderable.getIndex(), m_renderStateBucketIndices[t].get());
  167. switch(t)
  168. {
  169. case RenderingTechnique::kGBuffer:
  170. m_gpuSceneRenderableAabbGBuffer.uploadToGpuScene(gpuVolume);
  171. break;
  172. case RenderingTechnique::kDepth:
  173. m_gpuSceneRenderableAabbDepth.uploadToGpuScene(gpuVolume);
  174. break;
  175. case RenderingTechnique::kForward:
  176. m_gpuSceneRenderableAabbForward.uploadToGpuScene(gpuVolume);
  177. break;
  178. case RenderingTechnique::kRtMaterialFetch:
  179. m_gpuSceneRenderableAabbRt.uploadToGpuScene(gpuVolume);
  180. break;
  181. default:
  182. ANKI_ASSERT(0);
  183. }
  184. }
  185. }
  186. return;
  187. }
  188. // From now on something is dirty, update everything
  189. updated = true;
  190. m_anyDirty = false;
  191. // Sanitize
  192. m_submeshIdx = min(m_submeshIdx, (m_meshComponent) ? (m_meshComponent->getMeshResource().getSubMeshCount() - 1) : 0);
  193. // Extract the diffuse color
  194. Vec3 averageDiffuse(0.0f);
  195. {
  196. const MaterialVariable* diffuseRelatedMtlVar = nullptr;
  197. for(const MaterialVariable& mtlVar : mtl.getVariables())
  198. {
  199. SceneString name = mtlVar.getName();
  200. name.toLower();
  201. if(name.find("diffuse") != String::kNpos || name.find("albedo") != String::kNpos)
  202. {
  203. if(diffuseRelatedMtlVar)
  204. {
  205. if(name.find("tex") != String::kNpos)
  206. {
  207. diffuseRelatedMtlVar = &mtlVar;
  208. }
  209. }
  210. else
  211. {
  212. diffuseRelatedMtlVar = &mtlVar;
  213. }
  214. }
  215. }
  216. if(diffuseRelatedMtlVar)
  217. {
  218. if(diffuseRelatedMtlVar->getDataType() >= ShaderVariableDataType::kTextureFirst
  219. && diffuseRelatedMtlVar->getDataType() <= ShaderVariableDataType::kTextureLast)
  220. {
  221. averageDiffuse = diffuseRelatedMtlVar->getValue<ImageResourcePtr>()->getAverageColor().xyz();
  222. }
  223. else if(diffuseRelatedMtlVar->getDataType() == ShaderVariableDataType::kVec3)
  224. {
  225. averageDiffuse = diffuseRelatedMtlVar->getValue<Vec3>();
  226. }
  227. else if(diffuseRelatedMtlVar->getDataType() == ShaderVariableDataType::kU32 && diffuseRelatedMtlVar->tryGetImageResource())
  228. {
  229. // Bindless texture
  230. averageDiffuse = diffuseRelatedMtlVar->tryGetImageResource()->getAverageColor().xyz();
  231. }
  232. else
  233. {
  234. ANKI_SCENE_LOGW("Couldn't extract a diffuse value for material: %s", mtl.getFilename().cstr());
  235. }
  236. }
  237. }
  238. // Update the constants
  239. {
  240. ConstWeakArray<U8> preallocatedConsts = mtl.getPrefilledLocalConstants();
  241. if(!m_gpuSceneConstants || m_gpuSceneConstants.getAllocatedSize() != preallocatedConsts.getSizeInBytes())
  242. {
  243. GpuSceneBuffer::getSingleton().deferredFree(m_gpuSceneConstants);
  244. m_gpuSceneConstants = GpuSceneBuffer::getSingleton().allocate(preallocatedConsts.getSizeInBytes(), 4);
  245. }
  246. GpuSceneMicroPatcher::getSingleton().newCopy(*info.m_framePool, m_gpuSceneConstants.getOffset(), m_gpuSceneConstants.getAllocatedSize(),
  247. preallocatedConsts.getBegin());
  248. }
  249. // Update renderable
  250. {
  251. const MoveComponent& movec = info.m_node->getFirstComponentOfType<MoveComponent>();
  252. GpuSceneRenderable gpuRenderable = {};
  253. gpuRenderable.m_worldTransformsIndex = movec.getGpuSceneTransformsIndex();
  254. gpuRenderable.m_constantsOffset = m_gpuSceneConstants.getOffset();
  255. gpuRenderable.m_meshLodsIndex =
  256. (prioritizeEmitter) ? m_emitterComponent->getGpuSceneMeshLodIndex(m_submeshIdx) : m_meshComponent->getGpuSceneMeshLodsIndex(m_submeshIdx);
  257. gpuRenderable.m_boneTransformsOffset = (m_skinComponent) ? m_skinComponent->getBoneTransformsGpuSceneOffset() : 0;
  258. gpuRenderable.m_particleEmitterIndex = (prioritizeEmitter) ? m_emitterComponent->getGpuSceneParticleEmitter2Index() : kMaxU32;
  259. if(!!(mtl.getRenderingTechniques() & RenderingTechniqueBit::kRtShadow))
  260. {
  261. const RenderingKey key(RenderingTechnique::kRtShadow, 0, false, false, false);
  262. const MaterialVariant& variant = mtl.getOrCreateVariant(key);
  263. gpuRenderable.m_rtShadowsShaderHandleIndex = variant.getRtShaderGroupHandleIndex();
  264. }
  265. if(!!(mtl.getRenderingTechniques() & RenderingTechniqueBit::kRtMaterialFetch))
  266. {
  267. const RenderingKey key(RenderingTechnique::kRtMaterialFetch, 0, false, false, false);
  268. const MaterialVariant& variant = mtl.getOrCreateVariant(key);
  269. gpuRenderable.m_rtMaterialFetchShaderHandleIndex = variant.getRtShaderGroupHandleIndex();
  270. }
  271. gpuRenderable.m_uuid = SceneGraph::getSingleton().getNewUuid();
  272. const UVec3 u3(averageDiffuse.xyz().clamp(0.0f, 1.0f) * 255.0f);
  273. gpuRenderable.m_diffuseColor = ((u3.x() << 16u) | (u3.y() << 8u) | u3.z()) & 0xFFFFFFF;
  274. m_gpuSceneRenderable.uploadToGpuScene(gpuRenderable);
  275. }
  276. // Update scene bounds
  277. {
  278. const Aabb aabbWorld = computeAabb(*info.m_node);
  279. info.updateSceneBounds(aabbWorld.getMin().xyz(), aabbWorld.getMax().xyz());
  280. }
  281. // Update the buckets
  282. for(RenderingTechnique t : EnumIterable<RenderingTechnique>())
  283. {
  284. RenderStateBucketContainer::getSingleton().removeUser(m_renderStateBucketIndices[t]);
  285. if(!(RenderingTechniqueBit(1 << t) & mtl.getRenderingTechniques()))
  286. {
  287. continue;
  288. }
  289. // Fill the state
  290. RenderingKey key;
  291. key.setLod(0); // Materials don't care
  292. key.setRenderingTechnique(t);
  293. key.setSkinned(m_skinComponent != nullptr);
  294. key.setVelocity(moved);
  295. key.setMeshletRendering(!prioritizeEmitter
  296. && (GrManager::getSingleton().getDeviceCapabilities().m_meshShaders || g_cvarCoreMeshletRendering));
  297. const MaterialVariant& mvariant = mtl.getOrCreateVariant(key);
  298. RenderStateInfo state;
  299. state.m_primitiveTopology = PrimitiveTopology::kTriangles;
  300. state.m_program = mvariant.getShaderProgram();
  301. Bool wantsMesletCount = false;
  302. U32 meshletCount = 0;
  303. if(!prioritizeEmitter)
  304. {
  305. U32 firstIndex, indexCount, firstMeshlet;
  306. Aabb aabb;
  307. m_meshComponent->getMeshResource().getSubMeshInfo(0, m_submeshIdx, firstIndex, indexCount, firstMeshlet, meshletCount, aabb);
  308. wantsMesletCount = key.getMeshletRendering() && !(RenderingTechniqueBit(1 << t) & RenderingTechniqueBit::kAllRt);
  309. }
  310. m_renderStateBucketIndices[t] = RenderStateBucketContainer::getSingleton().addUser(state, t, (wantsMesletCount) ? meshletCount : 0);
  311. }
  312. // Upload the AABBs to the GPU scene
  313. {
  314. const Aabb aabbWorld = computeAabb(*info.m_node);
  315. // Raster
  316. for(RenderingTechnique t : EnumBitsIterable<RenderingTechnique, RenderingTechniqueBit>(RenderingTechniqueBit::kAllRaster))
  317. {
  318. const RenderingTechniqueBit bit = RenderingTechniqueBit(1 << t);
  319. if(!(mtl.getRenderingTechniques() & bit))
  320. {
  321. switch(t)
  322. {
  323. case RenderingTechnique::kGBuffer:
  324. m_gpuSceneRenderableAabbGBuffer.free();
  325. break;
  326. case RenderingTechnique::kDepth:
  327. m_gpuSceneRenderableAabbDepth.free();
  328. break;
  329. case RenderingTechnique::kForward:
  330. m_gpuSceneRenderableAabbForward.free();
  331. break;
  332. default:
  333. ANKI_ASSERT(0);
  334. }
  335. }
  336. else
  337. {
  338. const GpuSceneRenderableBoundingVolume gpuVolume = initGpuSceneRenderableBoundingVolume(
  339. aabbWorld.getMin().xyz(), aabbWorld.getMax().xyz(), m_gpuSceneRenderable.getIndex(), m_renderStateBucketIndices[t].get());
  340. switch(t)
  341. {
  342. case RenderingTechnique::kGBuffer:
  343. if(!m_gpuSceneRenderableAabbGBuffer.isValid())
  344. {
  345. m_gpuSceneRenderableAabbGBuffer.allocate();
  346. }
  347. m_gpuSceneRenderableAabbGBuffer.uploadToGpuScene(gpuVolume);
  348. break;
  349. case RenderingTechnique::kDepth:
  350. if(!m_gpuSceneRenderableAabbDepth.isValid())
  351. {
  352. m_gpuSceneRenderableAabbDepth.allocate();
  353. }
  354. m_gpuSceneRenderableAabbDepth.uploadToGpuScene(gpuVolume);
  355. break;
  356. case RenderingTechnique::kForward:
  357. if(!m_gpuSceneRenderableAabbForward.isValid())
  358. {
  359. m_gpuSceneRenderableAabbForward.allocate();
  360. }
  361. m_gpuSceneRenderableAabbForward.uploadToGpuScene(gpuVolume);
  362. break;
  363. default:
  364. ANKI_ASSERT(0);
  365. }
  366. }
  367. }
  368. // RT
  369. if(!!(mtl.getRenderingTechniques() & RenderingTechniqueBit::kAllRt))
  370. {
  371. if(!m_gpuSceneRenderableAabbRt.isValid())
  372. {
  373. m_gpuSceneRenderableAabbRt.allocate();
  374. }
  375. const U32 bucketIdx = 0;
  376. const GpuSceneRenderableBoundingVolume gpuVolume =
  377. initGpuSceneRenderableBoundingVolume(aabbWorld.getMin().xyz(), aabbWorld.getMax().xyz(), m_gpuSceneRenderable.getIndex(), bucketIdx);
  378. m_gpuSceneRenderableAabbRt.uploadToGpuScene(gpuVolume);
  379. }
  380. else
  381. {
  382. m_gpuSceneRenderableAabbRt.free();
  383. }
  384. }
  385. }
  386. } // end namespace anki