2
0

TextureViewerMain.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  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/AnKi.h>
  6. using namespace anki;
  7. class TextureViewerUiNode : public SceneNode
  8. {
  9. public:
  10. TextureResourcePtr m_textureResource;
  11. TextureViewerUiNode(SceneGraph* scene, CString name)
  12. : SceneNode(scene, name)
  13. {
  14. SpatialComponent* spatialc = newComponent<SpatialComponent>();
  15. spatialc->setAlwaysVisible(true);
  16. UiComponent* uic = newComponent<UiComponent>();
  17. uic->init([](CanvasPtr& canvas, void* ud) { static_cast<TextureViewerUiNode*>(ud)->draw(canvas); }, this);
  18. ANKI_CHECK_AND_IGNORE(getSceneGraph().getUiManager().newInstance(m_font, "EngineAssets/UbuntuMonoRegular.ttf",
  19. Array<U32, 1>{16}));
  20. ANKI_CHECK_AND_IGNORE(getSceneGraph().getResourceManager().loadResource(
  21. "AnKi/Shaders/UiVisualizeImage.ankiprog", m_imageProgram));
  22. const ShaderProgramResourceVariant* variant;
  23. m_imageProgram->getOrCreateVariant(variant);
  24. m_imageGrProgram = variant->getProgram();
  25. }
  26. Error frameUpdate(Second prevUpdateTime, Second crntTime)
  27. {
  28. if(!m_textureView.isCreated())
  29. {
  30. m_textureView = m_textureResource->getGrTextureView();
  31. }
  32. return Error::NONE;
  33. }
  34. private:
  35. FontPtr m_font;
  36. ShaderProgramResourcePtr m_imageProgram;
  37. ShaderProgramPtr m_imageGrProgram;
  38. TextureViewPtr m_textureView;
  39. U32 m_crntMip = 0;
  40. F32 m_zoom = 1.0f;
  41. Bool m_pointSampling = true;
  42. Array<Bool, 4> m_colorChannel = {true, true, true, true};
  43. void draw(CanvasPtr& canvas)
  44. {
  45. const Texture& grTex = *m_textureResource->getGrTexture().get();
  46. const U32 colorComponentCount = getFormatInfo(grTex.getFormat()).m_componentCount;
  47. ImGui::Begin("Console", nullptr,
  48. ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove);
  49. canvas->pushFont(m_font, 16);
  50. ImGui::SetWindowPos(Vec2(0.0f, 0.0f));
  51. ImGui::SetWindowSize(Vec2(F32(canvas->getWidth()), F32(canvas->getHeight())));
  52. ImGui::BeginChild("Tools", Vec2(-1.0f, 30.0f), false, ImGuiWindowFlags_AlwaysAutoResize);
  53. // Zoom
  54. if(ImGui::Button("-"))
  55. {
  56. m_zoom -= 0.1f;
  57. }
  58. ImGui::SameLine();
  59. ImGui::DragFloat("", &m_zoom, 0.01f, 0.1f, 20.0f, "Zoom %.3f");
  60. ImGui::SameLine();
  61. if(ImGui::Button("+"))
  62. {
  63. m_zoom += 0.1f;
  64. }
  65. ImGui::SameLine();
  66. ImGui::Spacing();
  67. ImGui::SameLine();
  68. // Sampling
  69. ImGui::Checkbox("Point sampling", &m_pointSampling);
  70. ImGui::SameLine();
  71. ImGui::Spacing();
  72. ImGui::SameLine();
  73. // Colors
  74. ImGui::Checkbox("Red", &m_colorChannel[0]);
  75. ImGui::SameLine();
  76. ImGui::Checkbox("Green", &m_colorChannel[1]);
  77. ImGui::SameLine();
  78. ImGui::Checkbox("Blue", &m_colorChannel[2]);
  79. ImGui::SameLine();
  80. if(colorComponentCount == 4)
  81. {
  82. ImGui::Checkbox("Alpha", &m_colorChannel[3]);
  83. ImGui::SameLine();
  84. }
  85. ImGui::Spacing();
  86. ImGui::SameLine();
  87. // Mips combo
  88. {
  89. StringListAuto mipLabels(getFrameAllocator());
  90. for(U32 mip = 0; mip < grTex.getMipmapCount(); ++mip)
  91. {
  92. mipLabels.pushBackSprintf("Mip %u (%llux%llu)", mip, grTex.getWidth() >> mip, grTex.getHeight() >> mip);
  93. }
  94. const U32 lastCrntMip = m_crntMip;
  95. if(ImGui::BeginCombo("##Mipmap", (mipLabels.getBegin() + m_crntMip)->cstr(), ImGuiComboFlags_HeightLarge))
  96. {
  97. for(U32 mip = 0; mip < grTex.getMipmapCount(); ++mip)
  98. {
  99. const Bool isSelected = (m_crntMip == mip);
  100. if(ImGui::Selectable((mipLabels.getBegin() + mip)->cstr(), isSelected))
  101. {
  102. m_crntMip = mip;
  103. }
  104. if(isSelected)
  105. {
  106. ImGui::SetItemDefaultFocus();
  107. }
  108. }
  109. ImGui::EndCombo();
  110. }
  111. if(lastCrntMip != m_crntMip)
  112. {
  113. // Re-create the image view
  114. TextureViewInitInfo viewInitInf(m_textureResource->getGrTexture());
  115. viewInitInf.m_firstMipmap = m_crntMip;
  116. viewInitInf.m_mipmapCount = 1;
  117. m_textureView = getSceneGraph().getGrManager().newTextureView(viewInitInf);
  118. }
  119. }
  120. ImGui::EndChild();
  121. ImGui::BeginChild("Image", Vec2(-1.0f, -1.0f), false,
  122. ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_HorizontalScrollbar);
  123. // Image
  124. {
  125. // Center image
  126. const Vec2 imageSize = Vec2(F32(grTex.getWidth()), F32(grTex.getHeight())) * m_zoom;
  127. class ExtraPushConstants
  128. {
  129. public:
  130. Vec4 m_colorScale;
  131. } pc;
  132. pc.m_colorScale.x() = F32(m_colorChannel[0]);
  133. pc.m_colorScale.y() = F32(m_colorChannel[1]);
  134. pc.m_colorScale.z() = F32(m_colorChannel[2]);
  135. pc.m_colorScale.w() = F32(m_colorChannel[3]);
  136. canvas->setShaderProgram(m_imageGrProgram, &pc, sizeof(pc));
  137. ImGui::Image(UiImageId(m_textureView, m_pointSampling), imageSize, Vec2(0.0f), Vec2(1.0f), Vec4(1.0f),
  138. Vec4(0.0f, 0.0f, 0.0f, 1.0f));
  139. canvas->clearShaderProgram();
  140. if(ImGui::IsItemHovered())
  141. {
  142. if(ImGui::GetIO().KeyCtrl)
  143. {
  144. // Zoom
  145. const F32 zoomSpeed = 0.05f;
  146. if(ImGui::GetIO().MouseWheel > 0.0f)
  147. {
  148. m_zoom *= 1.0f + zoomSpeed;
  149. }
  150. else if(ImGui::GetIO().MouseWheel < 0.0f)
  151. {
  152. m_zoom *= 1.0f - zoomSpeed;
  153. }
  154. // Pan
  155. if(ImGui::GetIO().MouseDown[0])
  156. {
  157. const Vec2 velocity = toAnki(ImGui::GetIO().MouseDelta);
  158. if(velocity.x() != 0.0f)
  159. {
  160. ImGui::SetScrollX(ImGui::GetScrollX() - velocity.x());
  161. }
  162. if(velocity.y() != 0.0f)
  163. {
  164. ImGui::SetScrollY(ImGui::GetScrollY() - velocity.y());
  165. }
  166. }
  167. }
  168. }
  169. }
  170. ImGui::EndChild();
  171. canvas->popFont();
  172. ImGui::End();
  173. }
  174. };
  175. class MyApp : public App
  176. {
  177. public:
  178. Error init(int argc, char** argv, CString appName)
  179. {
  180. if(argc < 2)
  181. {
  182. ANKI_LOGE("Wrong number of arguments");
  183. return Error::USER_DATA;
  184. }
  185. HeapAllocator<U32> alloc(allocAligned, nullptr);
  186. StringAuto mainDataPath(alloc, ANKI_SOURCE_DIRECTORY);
  187. ConfigSet config = DefaultConfigSet::get();
  188. config.set("window_fullscreen", false);
  189. config.set("rsrc_dataPaths", mainDataPath);
  190. config.set("gr_validation", 0);
  191. ANKI_CHECK(config.setFromCommandLineArguments(argc - 2, argv + 2));
  192. ANKI_CHECK(App::init(config, allocAligned, nullptr));
  193. // Load the texture
  194. TextureResourcePtr tex;
  195. ANKI_CHECK(getResourceManager().loadResource(argv[1], tex, false));
  196. // Change window name
  197. StringAuto title(alloc);
  198. title.sprintf("%s %llux%llu Mips %u", argv[1], tex->getWidth(), tex->getHeight(),
  199. tex->getGrTexture()->getMipmapCount());
  200. getWindow().setWindowTitle(title);
  201. // Create the node
  202. SceneGraph& scene = getSceneGraph();
  203. TextureViewerUiNode* node;
  204. ANKI_CHECK(scene.newSceneNode("TextureViewer", node));
  205. node->m_textureResource = tex;
  206. return Error::NONE;
  207. }
  208. Error userMainLoop(Bool& quit, Second elapsedTime) override
  209. {
  210. Input& input = getInput();
  211. if(input.getKey(KeyCode::ESCAPE))
  212. {
  213. quit = true;
  214. }
  215. return Error::NONE;
  216. }
  217. };
  218. int main(int argc, char* argv[])
  219. {
  220. Error err = Error::NONE;
  221. MyApp* app = new MyApp;
  222. err = app->init(argc, argv, "Texture Viewer");
  223. if(!err)
  224. {
  225. err = app->mainLoop();
  226. }
  227. delete app;
  228. if(err)
  229. {
  230. ANKI_LOGE("Error reported. Bye!!");
  231. }
  232. else
  233. {
  234. ANKI_LOGI("Bye!!");
  235. }
  236. return 0;
  237. }