DecalComponent.cpp 4.0 KB

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