DecalComponent.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  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/Scene/Components/DecalComponent.h>
  6. #include <AnKi/Scene/SceneGraph.h>
  7. #include <AnKi/Resource/ResourceManager.h>
  8. #include <AnKi/Shaders/Include/ClusteredShadingTypes.h>
  9. namespace anki {
  10. ANKI_SCENE_COMPONENT_STATICS(DecalComponent)
  11. DecalComponent::DecalComponent(SceneNode* node)
  12. : SceneComponent(node, getStaticClassId())
  13. , m_node(node)
  14. {
  15. ANKI_ASSERT(node);
  16. if(node->getSceneGraph().getResourceManager().loadResource("EngineAssets/GreenDecal.ankitex", m_debugImage))
  17. {
  18. ANKI_SCENE_LOGF("Failed to load resources");
  19. }
  20. }
  21. DecalComponent::~DecalComponent()
  22. {
  23. }
  24. Error DecalComponent::setLayer(CString texAtlasFname, CString texAtlasSubtexName, F32 blendFactor, LayerType type)
  25. {
  26. Layer& l = m_layers[type];
  27. ANKI_CHECK(m_node->getSceneGraph().getResourceManager().loadResource(texAtlasFname, l.m_atlas));
  28. ANKI_CHECK(l.m_atlas->getSubImageInfo(texAtlasSubtexName, &l.m_uv[0]));
  29. // Add a border to the UVs to avoid complex shader logic
  30. if(l.m_atlas->getSubImageMargin() < ATLAS_SUB_IMAGE_MARGIN)
  31. {
  32. ANKI_SCENE_LOGE("Need image atlas with margin at least %u", ATLAS_SUB_IMAGE_MARGIN);
  33. return Error::USER_DATA;
  34. }
  35. const Vec2 marginf =
  36. F32(ATLAS_SUB_IMAGE_MARGIN / 2) / Vec2(F32(l.m_atlas->getWidth()), F32(l.m_atlas->getHeight()));
  37. const Vec2 minUv = l.m_uv.xy() - marginf;
  38. const Vec2 sizeUv = (l.m_uv.zw() - l.m_uv.xy()) + 2.0f * marginf;
  39. l.m_uv = Vec4(minUv.x(), minUv.y(), minUv.x() + sizeUv.x(), minUv.y() + sizeUv.y());
  40. l.m_blendFactor = blendFactor;
  41. return Error::NONE;
  42. }
  43. void DecalComponent::updateInternal()
  44. {
  45. const Vec3 halfBoxSize = m_boxSize / 2.0f;
  46. // Calculate the texture matrix
  47. const Mat4 worldTransform(m_trf);
  48. const Mat4 viewMat = worldTransform.getInverse();
  49. const Mat4 projMat =
  50. Mat4::calculateOrthographicProjectionMatrix(halfBoxSize.x(), -halfBoxSize.x(), halfBoxSize.y(),
  51. -halfBoxSize.y(), CLUSTER_OBJECT_FRUSTUM_NEAR_PLANE, m_boxSize.z());
  52. static const Mat4 biasMat4(0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.5f, 0.0f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
  53. 1.0f);
  54. m_biasProjViewMat = biasMat4 * projMat * viewMat;
  55. // Calculate the OBB
  56. const Vec4 center(0.0f, 0.0f, -halfBoxSize.z(), 0.0f);
  57. const Vec4 extend(halfBoxSize.x(), halfBoxSize.y(), halfBoxSize.z(), 0.0f);
  58. const Obb obbL(center, Mat3x4::getIdentity(), extend);
  59. m_obb = obbL.getTransformed(m_trf);
  60. }
  61. void DecalComponent::draw(RenderQueueDrawContext& ctx) const
  62. {
  63. const Mat3 rot = m_obb.getRotation().getRotationPart();
  64. const Vec4 tsl = m_obb.getCenter().xyz1();
  65. const Vec3 scale = m_obb.getExtend().xyz();
  66. Mat3 nonUniScale = Mat3::getZero();
  67. nonUniScale(0, 0) = scale.x();
  68. nonUniScale(1, 1) = scale.y();
  69. nonUniScale(2, 2) = scale.z();
  70. const Mat4 mvp = ctx.m_viewProjectionMatrix * Mat4(tsl, rot * nonUniScale, 1.0f);
  71. const Bool enableDepthTest = ctx.m_debugDrawFlags.get(RenderQueueDebugDrawFlag::DEPTH_TEST_ON);
  72. if(enableDepthTest)
  73. {
  74. ctx.m_commandBuffer->setDepthCompareOperation(CompareOperation::LESS);
  75. }
  76. else
  77. {
  78. ctx.m_commandBuffer->setDepthCompareOperation(CompareOperation::ALWAYS);
  79. }
  80. m_node->getSceneGraph().getDebugDrawer().drawCubes(
  81. ConstWeakArray<Mat4>(&mvp, 1), Vec4(0.0f, 1.0f, 0.0f, 1.0f), 1.0f,
  82. ctx.m_debugDrawFlags.get(RenderQueueDebugDrawFlag::DITHERED_DEPTH_TEST_ON), 2.0f, *ctx.m_stagingGpuAllocator,
  83. ctx.m_commandBuffer);
  84. const Vec3 pos = m_obb.getCenter().xyz();
  85. m_node->getSceneGraph().getDebugDrawer().drawBillboardTextures(
  86. ctx.m_projectionMatrix, ctx.m_viewMatrix, ConstWeakArray<Vec3>(&pos, 1), Vec4(1.0f),
  87. ctx.m_debugDrawFlags.get(RenderQueueDebugDrawFlag::DITHERED_DEPTH_TEST_ON), m_debugImage->getTextureView(),
  88. ctx.m_sampler, Vec2(0.75f), *ctx.m_stagingGpuAllocator, ctx.m_commandBuffer);
  89. // Restore state
  90. if(!enableDepthTest)
  91. {
  92. ctx.m_commandBuffer->setDepthCompareOperation(CompareOperation::LESS);
  93. }
  94. }
  95. } // end namespace anki