texturev.cpp 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577
  1. /*
  2. * Copyright 2011-2017 Branimir Karadzic. All rights reserved.
  3. * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
  4. */
  5. #include "common.h"
  6. #include <bgfx/bgfx.h>
  7. #include <bx/commandline.h>
  8. #include <bx/os.h>
  9. #include <bx/filepath.h>
  10. #include <bx/uint32_t.h>
  11. #include <bx/math.h>
  12. #include <bx/easing.h>
  13. #include <entry/entry.h>
  14. #include <entry/input.h>
  15. #include <entry/cmd.h>
  16. #include <imgui/imgui.h>
  17. #include <bgfx_utils.h>
  18. #include <dirent.h>
  19. #include <bx/file.h>
  20. #include <bx/process.h>
  21. #include <tinystl/allocator.h>
  22. #include <tinystl/vector.h>
  23. #include <string>
  24. namespace stl = tinystl;
  25. #include <bimg/decode.h>
  26. #include <bgfx/embedded_shader.h>
  27. #include "vs_texture.bin.h"
  28. #include "vs_texture_cube.bin.h"
  29. #include "fs_texture.bin.h"
  30. #include "fs_texture_array.bin.h"
  31. #include "fs_texture_cube.bin.h"
  32. #include "fs_texture_cube2.bin.h"
  33. #include "fs_texture_sdf.bin.h"
  34. #include "fs_texture_3d.bin.h"
  35. #define BACKGROUND_VIEW_ID 0
  36. #define IMAGE_VIEW_ID 1
  37. #define BGFX_TEXTUREV_VERSION_MAJOR 1
  38. #define BGFX_TEXTUREV_VERSION_MINOR 0
  39. static const bgfx::EmbeddedShader s_embeddedShaders[] =
  40. {
  41. BGFX_EMBEDDED_SHADER(vs_texture),
  42. BGFX_EMBEDDED_SHADER(fs_texture),
  43. BGFX_EMBEDDED_SHADER(fs_texture_array),
  44. BGFX_EMBEDDED_SHADER(vs_texture_cube),
  45. BGFX_EMBEDDED_SHADER(fs_texture_cube),
  46. BGFX_EMBEDDED_SHADER(fs_texture_cube2),
  47. BGFX_EMBEDDED_SHADER(fs_texture_sdf),
  48. BGFX_EMBEDDED_SHADER(fs_texture_3d),
  49. BGFX_EMBEDDED_SHADER_END()
  50. };
  51. static const char* s_supportedExt[] =
  52. {
  53. "bmp",
  54. "dds",
  55. "exr",
  56. "gif",
  57. "jpg",
  58. "jpeg",
  59. "hdr",
  60. "ktx",
  61. "png",
  62. "psd",
  63. "pvr",
  64. "tga",
  65. };
  66. struct Binding
  67. {
  68. enum Enum
  69. {
  70. App,
  71. View,
  72. Help,
  73. Count
  74. };
  75. };
  76. struct Geometry
  77. {
  78. enum Enum
  79. {
  80. Quad,
  81. Cross,
  82. Hexagon,
  83. Count
  84. };
  85. };
  86. static const InputBinding s_bindingApp[] =
  87. {
  88. { entry::Key::KeyQ, entry::Modifier::None, 1, NULL, "exit" },
  89. { entry::Key::KeyF, entry::Modifier::None, 1, NULL, "graphics fullscreen" },
  90. INPUT_BINDING_END
  91. };
  92. const char* s_resetCmd =
  93. "view zoom 1.0\n"
  94. "view rotate 0\n"
  95. "view cubemap\n"
  96. "view pan\n"
  97. ;
  98. static const InputBinding s_bindingView[] =
  99. {
  100. { entry::Key::Esc, entry::Modifier::None, 1, NULL, "exit" },
  101. { entry::Key::Comma, entry::Modifier::None, 1, NULL, "view mip prev" },
  102. { entry::Key::Period, entry::Modifier::None, 1, NULL, "view mip next" },
  103. { entry::Key::Comma, entry::Modifier::LeftShift, 1, NULL, "view mip" },
  104. { entry::Key::Comma, entry::Modifier::RightShift, 1, NULL, "view mip" },
  105. { entry::Key::Slash, entry::Modifier::None, 1, NULL, "view filter" },
  106. { entry::Key::Key1, entry::Modifier::None, 1, NULL, "view zoom 1.0\n"
  107. "view fit\n" },
  108. { entry::Key::Key0, entry::Modifier::None, 1, NULL, s_resetCmd },
  109. { entry::Key::Plus, entry::Modifier::None, 1, NULL, "view zoom +0.1" },
  110. { entry::Key::Minus, entry::Modifier::None, 1, NULL, "view zoom -0.1" },
  111. { entry::Key::KeyZ, entry::Modifier::None, 1, NULL, "view rotate -90" },
  112. { entry::Key::KeyZ, entry::Modifier::LeftShift, 1, NULL, "view rotate +90" },
  113. { entry::Key::Up, entry::Modifier::None, 1, NULL, "view pan\n"
  114. "view file-up" },
  115. { entry::Key::Down, entry::Modifier::None, 1, NULL, "view pan\n"
  116. "view file-down" },
  117. { entry::Key::PageUp, entry::Modifier::None, 1, NULL, "view pan\n"
  118. "view file-pgup" },
  119. { entry::Key::PageDown, entry::Modifier::None, 1, NULL, "view pan\n"
  120. "view file-pgdown" },
  121. { entry::Key::Left, entry::Modifier::None, 1, NULL, "view layer prev" },
  122. { entry::Key::Right, entry::Modifier::None, 1, NULL, "view layer next" },
  123. { entry::Key::KeyR, entry::Modifier::None, 1, NULL, "view rgb r" },
  124. { entry::Key::KeyG, entry::Modifier::None, 1, NULL, "view rgb g" },
  125. { entry::Key::KeyB, entry::Modifier::None, 1, NULL, "view rgb b" },
  126. { entry::Key::KeyA, entry::Modifier::None, 1, NULL, "view rgb a" },
  127. { entry::Key::KeyH, entry::Modifier::None, 1, NULL, "view help" },
  128. { entry::Key::KeyS, entry::Modifier::None, 1, NULL, "view sdf" },
  129. { entry::Key::Space, entry::Modifier::None, 1, NULL, "view geo\n"
  130. "view pan\n" },
  131. INPUT_BINDING_END
  132. };
  133. static const InputBinding s_bindingHelp[] =
  134. {
  135. { entry::Key::Esc, entry::Modifier::None, 1, NULL, "view help" },
  136. { entry::Key::KeyH, entry::Modifier::None, 1, NULL, "view help" },
  137. INPUT_BINDING_END
  138. };
  139. static const char* s_bindingName[] =
  140. {
  141. "App",
  142. "View",
  143. "Help",
  144. };
  145. BX_STATIC_ASSERT(Binding::Count == BX_COUNTOF(s_bindingName) );
  146. static const InputBinding* s_binding[] =
  147. {
  148. s_bindingApp,
  149. s_bindingView,
  150. s_bindingHelp,
  151. };
  152. BX_STATIC_ASSERT(Binding::Count == BX_COUNTOF(s_binding) );
  153. struct View
  154. {
  155. View()
  156. : m_cubeMapGeo(Geometry::Quad)
  157. , m_fileIndex(0)
  158. , m_scaleFn(0)
  159. , m_mip(0)
  160. , m_layer(0)
  161. , m_abgr(UINT32_MAX)
  162. , m_posx(0.0f)
  163. , m_posy(0.0f)
  164. , m_angx(0.0f)
  165. , m_angy(0.0f)
  166. , m_zoom(1.0f)
  167. , m_angle(0.0f)
  168. , m_filter(true)
  169. , m_fit(true)
  170. , m_alpha(false)
  171. , m_help(false)
  172. , m_sdf(false)
  173. {
  174. }
  175. ~View()
  176. {
  177. }
  178. int32_t cmd(int32_t _argc, char const* const* _argv)
  179. {
  180. if (_argc >= 2)
  181. {
  182. if (0 == bx::strCmp(_argv[1], "mip") )
  183. {
  184. if (_argc >= 3)
  185. {
  186. uint32_t mip = m_mip;
  187. if (0 == bx::strCmp(_argv[2], "next") )
  188. {
  189. ++mip;
  190. }
  191. else if (0 == bx::strCmp(_argv[2], "prev") )
  192. {
  193. --mip;
  194. }
  195. else if (0 == bx::strCmp(_argv[2], "last") )
  196. {
  197. mip = INT32_MAX;
  198. }
  199. else
  200. {
  201. mip = atoi(_argv[2]);
  202. }
  203. m_mip = bx::uint32_iclamp(mip, 0, m_info.numMips-1);
  204. }
  205. else
  206. {
  207. m_mip = 0;
  208. }
  209. }
  210. if (0 == bx::strCmp(_argv[1], "layer") )
  211. {
  212. if (_argc >= 3)
  213. {
  214. uint32_t layer = m_layer;
  215. if (0 == bx::strCmp(_argv[2], "next") )
  216. {
  217. ++layer;
  218. }
  219. else if (0 == bx::strCmp(_argv[2], "prev") )
  220. {
  221. --layer;
  222. }
  223. else if (0 == bx::strCmp(_argv[2], "last") )
  224. {
  225. layer = INT32_MAX;
  226. }
  227. else
  228. {
  229. layer = atoi(_argv[2]);
  230. }
  231. m_layer = bx::uint32_iclamp(layer, 0, m_info.numLayers-1);
  232. }
  233. else
  234. {
  235. m_layer = 0;
  236. }
  237. }
  238. else if (0 == bx::strCmp(_argv[1], "pan") )
  239. {
  240. if (_argc >= 3)
  241. {
  242. if (_argc >= 4)
  243. {
  244. float yy;
  245. bx::fromString(&yy, _argv[3]);
  246. if (_argv[3][0] == '+'
  247. || _argv[3][0] == '-')
  248. {
  249. m_posy += yy;
  250. }
  251. else
  252. {
  253. m_posy = yy;
  254. }
  255. }
  256. float xx;
  257. bx::fromString(&xx, _argv[2]);
  258. if (_argv[2][0] == '+'
  259. || _argv[2][0] == '-')
  260. {
  261. m_posx += xx;
  262. }
  263. else
  264. {
  265. m_posx = xx;
  266. }
  267. }
  268. else
  269. {
  270. m_posx = 0.0f;
  271. m_posy = 0.0f;
  272. }
  273. }
  274. else if (0 == bx::strCmp(_argv[1], "cubemap") )
  275. {
  276. if (_argc >= 3)
  277. {
  278. if (_argc >= 4)
  279. {
  280. float yy;
  281. bx::fromString(&yy, _argv[3]);
  282. if (_argv[3][0] == '+'
  283. || _argv[3][0] == '-')
  284. {
  285. m_angy += bx::toRad(yy);
  286. }
  287. else
  288. {
  289. m_angy = bx::toRad(yy);
  290. }
  291. }
  292. float xx;
  293. bx::fromString(&xx, _argv[2]);
  294. if (_argv[2][0] == '+'
  295. || _argv[2][0] == '-')
  296. {
  297. m_angx += bx::toRad(xx);
  298. }
  299. else
  300. {
  301. m_angx = bx::toRad(xx);
  302. }
  303. }
  304. else
  305. {
  306. m_angx = 0.0f;
  307. m_angy = 0.0f;
  308. }
  309. }
  310. else if (0 == bx::strCmp(_argv[1], "zoom") )
  311. {
  312. if (_argc >= 3)
  313. {
  314. float zoom;
  315. bx::fromString(&zoom, _argv[2]);
  316. if (_argv[2][0] == '+'
  317. || _argv[2][0] == '-')
  318. {
  319. m_zoom += zoom;
  320. }
  321. else
  322. {
  323. m_zoom = zoom;
  324. }
  325. m_zoom = bx::fclamp(m_zoom, 0.01f, 10.0f);
  326. }
  327. else
  328. {
  329. m_zoom = 1.0f;
  330. }
  331. }
  332. else if (0 == bx::strCmp(_argv[1], "rotate") )
  333. {
  334. if (_argc >= 3)
  335. {
  336. float angle;
  337. bx::fromString(&angle, _argv[2]);
  338. if (_argv[2][0] == '+'
  339. || _argv[2][0] == '-')
  340. {
  341. m_angle += bx::toRad(angle);
  342. }
  343. else
  344. {
  345. m_angle = bx::toRad(angle);
  346. }
  347. m_angle = bx::fwrap(m_angle, bx::kPi*2.0f);
  348. }
  349. else
  350. {
  351. m_angle = 0.0f;
  352. }
  353. }
  354. else if (0 == bx::strCmp(_argv[1], "filter") )
  355. {
  356. if (_argc >= 3)
  357. {
  358. m_filter = bx::toBool(_argv[2]);
  359. }
  360. else
  361. {
  362. m_filter ^= true;
  363. }
  364. }
  365. else if (0 == bx::strCmp(_argv[1], "fit") )
  366. {
  367. if (_argc >= 3)
  368. {
  369. m_fit = bx::toBool(_argv[2]);
  370. }
  371. else
  372. {
  373. m_fit ^= true;
  374. }
  375. }
  376. else if (0 == bx::strCmp(_argv[1], "file-up") )
  377. {
  378. m_fileIndex = bx::uint32_satsub(m_fileIndex, 1);
  379. }
  380. else if (0 == bx::strCmp(_argv[1], "file-down") )
  381. {
  382. uint32_t numFiles = bx::uint32_satsub(uint32_t(m_fileList.size() ), 1);
  383. ++m_fileIndex;
  384. m_fileIndex = bx::uint32_min(m_fileIndex, numFiles);
  385. }
  386. else if (0 == bx::strCmp(_argv[1], "rgb") )
  387. {
  388. if (_argc >= 3)
  389. {
  390. if (_argv[2][0] == 'r')
  391. {
  392. m_abgr ^= 0x000000ff;
  393. }
  394. else if (_argv[2][0] == 'g')
  395. {
  396. m_abgr ^= 0x0000ff00;
  397. }
  398. else if (_argv[2][0] == 'b')
  399. {
  400. m_abgr ^= 0x00ff0000;
  401. }
  402. else if (_argv[2][0] == 'a')
  403. {
  404. m_alpha ^= true;
  405. }
  406. }
  407. else
  408. {
  409. m_abgr = UINT32_MAX;
  410. m_alpha = false;
  411. }
  412. }
  413. else if (0 == bx::strCmp(_argv[1], "sdf") )
  414. {
  415. m_sdf ^= true;
  416. }
  417. else if (0 == bx::strCmp(_argv[1], "geo") )
  418. {
  419. if (_argc >= 3)
  420. {
  421. if (bx::toLower(_argv[2][0]) == 'c')
  422. {
  423. m_cubeMapGeo = Geometry::Cross;
  424. }
  425. else if (bx::toLower(_argv[2][0]) == 'h')
  426. {
  427. m_cubeMapGeo = Geometry::Hexagon;
  428. }
  429. else
  430. {
  431. m_cubeMapGeo = Geometry::Quad;
  432. }
  433. }
  434. else
  435. {
  436. m_cubeMapGeo = Geometry::Enum( (m_cubeMapGeo + 1) % Geometry::Count);
  437. }
  438. }
  439. else if (0 == bx::strCmp(_argv[1], "help") )
  440. {
  441. m_help ^= true;
  442. }
  443. }
  444. return 0;
  445. }
  446. void updateFileList(const char* _path, const bx::StringView& _fileName)
  447. {
  448. std::string path = _path;
  449. DIR* dir = opendir(_path);
  450. if (NULL == dir)
  451. {
  452. path = ".";
  453. }
  454. dir = opendir(path.c_str() );
  455. if (NULL != dir)
  456. {
  457. for (dirent* item = readdir(dir); NULL != item; item = readdir(dir) )
  458. {
  459. if (0 == (item->d_type & DT_DIR) )
  460. {
  461. const char* ext = bx::strRFind(item->d_name, '.');
  462. if (NULL != ext)
  463. {
  464. ext += 1;
  465. bool supported = false;
  466. for (uint32_t ii = 0; ii < BX_COUNTOF(s_supportedExt); ++ii)
  467. {
  468. if (0 == bx::strCmpI(ext, s_supportedExt[ii]) )
  469. {
  470. supported = true;
  471. break;
  472. }
  473. }
  474. if (supported)
  475. {
  476. if (0 == bx::strCmp(item->d_name, _fileName) )
  477. {
  478. m_fileIndex = uint32_t(m_fileList.size() );
  479. }
  480. std::string name = path;
  481. char ch = name[name.size()-1];
  482. name += '/' == ch || '\\' == ch ? "" : "/";
  483. name += item->d_name;
  484. m_fileList.push_back(name);
  485. }
  486. }
  487. }
  488. }
  489. closedir(dir);
  490. }
  491. }
  492. typedef stl::vector<std::string> FileList;
  493. FileList m_fileList;
  494. bgfx::TextureInfo m_info;
  495. Geometry::Enum m_cubeMapGeo;
  496. uint32_t m_fileIndex;
  497. uint32_t m_scaleFn;
  498. uint32_t m_mip;
  499. uint32_t m_layer;
  500. uint32_t m_abgr;
  501. float m_posx;
  502. float m_posy;
  503. float m_angx;
  504. float m_angy;
  505. float m_zoom;
  506. float m_angle;
  507. bool m_filter;
  508. bool m_fit;
  509. bool m_alpha;
  510. bool m_help;
  511. bool m_sdf;
  512. };
  513. int cmdView(CmdContext* /*_context*/, void* _userData, int _argc, char const* const* _argv)
  514. {
  515. View* view = static_cast<View*>(_userData);
  516. return view->cmd(_argc, _argv);
  517. }
  518. struct PosUvwColorVertex
  519. {
  520. float m_x;
  521. float m_y;
  522. float m_u;
  523. float m_v;
  524. float m_w;
  525. uint32_t m_abgr;
  526. static void init()
  527. {
  528. ms_decl
  529. .begin()
  530. .add(bgfx::Attrib::Position, 2, bgfx::AttribType::Float)
  531. .add(bgfx::Attrib::TexCoord0, 3, bgfx::AttribType::Float)
  532. .add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true)
  533. .end();
  534. }
  535. void set(float _x, float _y, float _u, float _v, float _w, uint32_t _abgr)
  536. {
  537. m_x = _x;
  538. m_y = _y;
  539. m_u = _u;
  540. m_v = _v;
  541. m_w = _w;
  542. m_abgr = _abgr;
  543. }
  544. static bgfx::VertexDecl ms_decl;
  545. };
  546. bgfx::VertexDecl PosUvwColorVertex::ms_decl;
  547. static uint32_t addQuad(uint16_t* _indices, uint16_t _idx0, uint16_t _idx1, uint16_t _idx2, uint16_t _idx3)
  548. {
  549. _indices[0] = _idx0;
  550. _indices[1] = _idx3;
  551. _indices[2] = _idx1;
  552. _indices[3] = _idx1;
  553. _indices[4] = _idx3;
  554. _indices[5] = _idx2;
  555. return 6;
  556. }
  557. void setGeometry(
  558. Geometry::Enum _type
  559. , int32_t _x
  560. , int32_t _y
  561. , int32_t _width
  562. , uint32_t _height
  563. , uint32_t _abgr
  564. , float _maxu = 1.0f
  565. , float _maxv = 1.0f
  566. )
  567. {
  568. if (Geometry::Quad == _type)
  569. {
  570. if (6 == bgfx::getAvailTransientVertexBuffer(6, PosUvwColorVertex::ms_decl) )
  571. {
  572. bgfx::TransientVertexBuffer vb;
  573. bgfx::allocTransientVertexBuffer(&vb, 6, PosUvwColorVertex::ms_decl);
  574. PosUvwColorVertex* vertex = (PosUvwColorVertex*)vb.data;
  575. const float widthf = float(_width);
  576. const float heightf = float(_height);
  577. const float minx = float(_x);
  578. const float miny = float(_y);
  579. const float maxx = minx+widthf;
  580. const float maxy = miny+heightf;
  581. const float minu = 0.0f;
  582. const float maxu = _maxu;
  583. const float minv = 0.0f;
  584. const float maxv = _maxv;
  585. vertex->set(minx, miny, minu, minv, 0.0f, _abgr); ++vertex;
  586. vertex->set(maxx, miny, maxu, minv, 0.0f, _abgr); ++vertex;
  587. vertex->set(maxx, maxy, maxu, maxv, 0.0f, _abgr); ++vertex;
  588. vertex->set(maxx, maxy, maxu, maxv, 0.0f, _abgr); ++vertex;
  589. vertex->set(minx, maxy, minu, maxv, 0.0f, _abgr); ++vertex;
  590. vertex->set(minx, miny, minu, minv, 0.0f, _abgr); ++vertex;
  591. bgfx::setVertexBuffer(0, &vb);
  592. }
  593. }
  594. else
  595. {
  596. const uint32_t numVertices = 14;
  597. const uint32_t numIndices = 36;
  598. if (checkAvailTransientBuffers(numVertices, PosUvwColorVertex::ms_decl, numIndices) )
  599. {
  600. bgfx::TransientVertexBuffer tvb;
  601. bgfx::allocTransientVertexBuffer(&tvb, numVertices, PosUvwColorVertex::ms_decl);
  602. bgfx::TransientIndexBuffer tib;
  603. bgfx::allocTransientIndexBuffer(&tib, numIndices);
  604. PosUvwColorVertex* vertex = (PosUvwColorVertex*)tvb.data;
  605. uint16_t* indices = (uint16_t*)tib.data;
  606. if (Geometry::Cross == _type)
  607. {
  608. const float sx = _width /1.5f;
  609. const float sy = _height/1.5f;
  610. const float px = float(_x)-sx/4.0f;
  611. const float py = float(_y);
  612. vertex->set(0.0f*sx+px, 0.5f*sy+py, -1.0f, 1.0f, -1.0f, _abgr); ++vertex;
  613. vertex->set(0.0f*sx+px, 1.0f*sy+py, -1.0f, -1.0f, -1.0f, _abgr); ++vertex;
  614. vertex->set(0.5f*sx+px, 0.0f*sy+py, -1.0f, 1.0f, -1.0f, _abgr); ++vertex;
  615. vertex->set(0.5f*sx+px, 0.5f*sy+py, -1.0f, 1.0f, 1.0f, _abgr); ++vertex;
  616. vertex->set(0.5f*sx+px, 1.0f*sy+py, -1.0f, -1.0f, 1.0f, _abgr); ++vertex;
  617. vertex->set(0.5f*sx+px, 1.5f*sy+py, -1.0f, -1.0f, -1.0f, _abgr); ++vertex;
  618. vertex->set(1.0f*sx+px, 0.0f*sy+py, 1.0f, 1.0f, -1.0f, _abgr); ++vertex;
  619. vertex->set(1.0f*sx+px, 0.5f*sy+py, 1.0f, 1.0f, 1.0f, _abgr); ++vertex;
  620. vertex->set(1.0f*sx+px, 1.0f*sy+py, 1.0f, -1.0f, 1.0f, _abgr); ++vertex;
  621. vertex->set(1.0f*sx+px, 1.5f*sy+py, 1.0f, -1.0f, -1.0f, _abgr); ++vertex;
  622. vertex->set(1.5f*sx+px, 0.5f*sy+py, 1.0f, 1.0f, -1.0f, _abgr); ++vertex;
  623. vertex->set(1.5f*sx+px, 1.0f*sy+py, 1.0f, -1.0f, -1.0f, _abgr); ++vertex;
  624. vertex->set(2.0f*sx+px, 0.5f*sy+py, -1.0f, 1.0f, -1.0f, _abgr); ++vertex;
  625. vertex->set(2.0f*sx+px, 1.0f*sy+py, -1.0f, -1.0f, -1.0f, _abgr); ++vertex;
  626. indices += addQuad(indices, 0, 3, 4, 1);
  627. indices += addQuad(indices, 2, 6, 7, 3);
  628. indices += addQuad(indices, 3, 7, 8, 4);
  629. indices += addQuad(indices, 4, 8, 9, 5);
  630. indices += addQuad(indices, 7, 10, 11, 8);
  631. indices += addQuad(indices, 10, 12, 13, 11);
  632. }
  633. else
  634. {
  635. const float sx = float(_width);
  636. const float sy = float(_height);
  637. const float px = float(_x) - sx/2.0f;
  638. const float py = float(_y);
  639. vertex->set(0.0f*sx+px, 0.25f*sy+py, -1.0f, 1.0f, -1.0f, _abgr); ++vertex;
  640. vertex->set(0.0f*sx+px, 0.75f*sy+py, -1.0f, -1.0f, -1.0f, _abgr); ++vertex;
  641. vertex->set(0.5f*sx+px, 0.00f*sy+py, -1.0f, 1.0f, 1.0f, _abgr); ++vertex;
  642. vertex->set(0.5f*sx+px, 0.50f*sy+py, -1.0f, -1.0f, 1.0f, _abgr); ++vertex;
  643. vertex->set(0.5f*sx+px, 1.00f*sy+py, 1.0f, -1.0f, -1.0f, _abgr); ++vertex;
  644. vertex->set(1.0f*sx+px, 0.25f*sy+py, 1.0f, 1.0f, 1.0f, _abgr); ++vertex;
  645. vertex->set(1.0f*sx+px, 0.75f*sy+py, 1.0f, -1.0f, 1.0f, _abgr); ++vertex;
  646. vertex->set(1.0f*sx+px, 0.25f*sy+py, 1.0f, 1.0f, 1.0f, _abgr); ++vertex;
  647. vertex->set(1.0f*sx+px, 0.75f*sy+py, 1.0f, -1.0f, 1.0f, _abgr); ++vertex;
  648. vertex->set(1.5f*sx+px, 0.00f*sy+py, -1.0f, 1.0f, 1.0f, _abgr); ++vertex;
  649. vertex->set(1.5f*sx+px, 0.50f*sy+py, 1.0f, 1.0f, -1.0f, _abgr); ++vertex;
  650. vertex->set(1.5f*sx+px, 1.00f*sy+py, 1.0f, -1.0f, -1.0f, _abgr); ++vertex;
  651. vertex->set(2.0f*sx+px, 0.25f*sy+py, -1.0f, 1.0f, -1.0f, _abgr); ++vertex;
  652. vertex->set(2.0f*sx+px, 0.75f*sy+py, -1.0f, -1.0f, -1.0f, _abgr); ++vertex;
  653. indices += addQuad(indices, 0, 2, 3, 1);
  654. indices += addQuad(indices, 1, 3, 6, 4);
  655. indices += addQuad(indices, 2, 5, 6, 3);
  656. indices += addQuad(indices, 7, 9, 12, 10);
  657. indices += addQuad(indices, 7, 10, 11, 8);
  658. indices += addQuad(indices, 10, 12, 13, 11);
  659. }
  660. bgfx::setVertexBuffer(0, &tvb);
  661. bgfx::setIndexBuffer(&tib);
  662. }
  663. }
  664. }
  665. template<bx::LerpFn lerpT, bx::EaseFn easeT>
  666. struct InterpolatorT
  667. {
  668. float from;
  669. float to;
  670. float duration;
  671. int64_t offset;
  672. InterpolatorT(float _value)
  673. {
  674. reset(_value);
  675. }
  676. void reset(float _value)
  677. {
  678. from = _value;
  679. to = _value;
  680. duration = 0.0;
  681. offset = bx::getHPCounter();
  682. }
  683. void set(float _value, float _duration)
  684. {
  685. if (_value != to)
  686. {
  687. from = getValue();
  688. to = _value;
  689. duration = _duration;
  690. offset = bx::getHPCounter();
  691. }
  692. }
  693. float getValue()
  694. {
  695. if (duration > 0.0)
  696. {
  697. const double freq = double(bx::getHPFrequency() );
  698. int64_t now = bx::getHPCounter();
  699. float time = (float)(double(now - offset) / freq);
  700. float lerp = bx::fclamp(time, 0.0, duration) / duration;
  701. return lerpT(from, to, easeT(lerp) );
  702. }
  703. return to;
  704. }
  705. };
  706. typedef InterpolatorT<bx::flerp, bx::easeInOutQuad> Interpolator;
  707. typedef InterpolatorT<bx::angleLerp, bx::easeInOutCubic> InterpolatorAngle;
  708. void keyBindingHelp(const char* _bindings, const char* _description)
  709. {
  710. ImGui::TextColored(ImVec4(1.0f, 1.0f, 0.0f, 1.0f), _bindings);
  711. ImGui::SameLine(100);
  712. ImGui::Text(_description);
  713. }
  714. void associate()
  715. {
  716. #if BX_PLATFORM_WINDOWS
  717. std::string str;
  718. char exec[MAX_PATH];
  719. GetModuleFileNameA(GetModuleHandleA(NULL), exec, MAX_PATH);
  720. std::string strExec = bx::replaceAll<std::string>(exec, "\\", "\\\\");
  721. std::string value;
  722. bx::stringPrintf(value, "@=\"\\\"%s\\\" \\\"%%1\\\"\"\r\n\r\n", strExec.c_str() );
  723. str += "Windows Registry Editor Version 5.00\r\n\r\n";
  724. str += "[HKEY_CLASSES_ROOT\\texturev\\shell\\open\\command]\r\n";
  725. str += value;
  726. str += "[HKEY_CLASSES_ROOT\\Applications\\texturev.exe\\shell\\open\\command]\r\n";
  727. str += value;
  728. for (uint32_t ii = 0; ii < BX_COUNTOF(s_supportedExt); ++ii)
  729. {
  730. const char* ext = s_supportedExt[ii];
  731. bx::stringPrintf(str, "[-HKEY_CLASSES_ROOT\\.%s]\r\n\r\n", ext);
  732. bx::stringPrintf(str, "[-HKEY_CURRENT_USER\\Software\\Classes\\.%s]\r\n\r\n", ext);
  733. bx::stringPrintf(str, "[HKEY_CLASSES_ROOT\\.%s]\r\n@=\"texturev\"\r\n\r\n", ext);
  734. bx::stringPrintf(str, "[HKEY_CURRENT_USER\\Software\\Classes\\.%s]\r\n@=\"texturev\"\r\n\r\n", ext);
  735. }
  736. bx::FilePath filePath(bx::TempDir::Tag);
  737. filePath.join("texture.reg");
  738. bx::FileWriter writer;
  739. bx::Error err;
  740. if (bx::open(&writer, filePath, false, &err) )
  741. {
  742. bx::write(&writer, str.c_str(), uint32_t(str.length()), &err);
  743. bx::close(&writer);
  744. if (err.isOk() )
  745. {
  746. std::string cmd;
  747. bx::stringPrintf(cmd, "/s %s", filePath.get() );
  748. bx::ProcessReader reader;
  749. if (bx::open(&reader, "regedit.exe", cmd.c_str(), &err) )
  750. {
  751. bx::close(&reader);
  752. }
  753. }
  754. }
  755. #elif BX_PLATFORM_LINUX
  756. std::string str;
  757. str += "#/bin/bash\n\n";
  758. for (uint32_t ii = 0; ii < BX_COUNTOF(s_supportedExt); ++ii)
  759. {
  760. const char* ext = s_supportedExt[ii];
  761. bx::stringPrintf(str, "xdg-mime default texturev.desktop image/%s\n", ext);
  762. }
  763. str += "\n";
  764. bx::FileWriter writer;
  765. bx::Error err;
  766. if (bx::open(&writer, "/tmp/texturev.sh", false, &err) )
  767. {
  768. bx::write(&writer, str.c_str(), uint32_t(str.length()), &err);
  769. bx::close(&writer);
  770. if (err.isOk() )
  771. {
  772. bx::ProcessReader reader;
  773. if (bx::open(&reader, "/bin/bash", "/tmp/texturev.sh", &err) )
  774. {
  775. bx::close(&reader);
  776. }
  777. }
  778. }
  779. #endif // BX_PLATFORM_WINDOWS
  780. }
  781. void help(const char* _error = NULL)
  782. {
  783. if (NULL != _error)
  784. {
  785. fprintf(stderr, "Error:\n%s\n\n", _error);
  786. }
  787. fprintf(stderr
  788. , "texturev, bgfx texture viewer tool, version %d.%d.%d.\n"
  789. "Copyright 2011-2017 Branimir Karadzic. All rights reserved.\n"
  790. "License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause\n\n"
  791. , BGFX_TEXTUREV_VERSION_MAJOR
  792. , BGFX_TEXTUREV_VERSION_MINOR
  793. , BGFX_API_VERSION
  794. );
  795. fprintf(stderr
  796. , "Usage: texturev <file path>\n"
  797. "\n"
  798. "Supported input file types:\n"
  799. );
  800. for (uint32_t ii = 0; ii < BX_COUNTOF(s_supportedExt); ++ii)
  801. {
  802. fprintf(stderr, " *.%s\n", s_supportedExt[ii]);
  803. }
  804. fprintf(stderr
  805. , "\n"
  806. "Options:\n"
  807. " -h, --help Help.\n"
  808. " -v, --version Version information only.\n"
  809. " --associate Associate file extensions with texturev.\n"
  810. "\n"
  811. "For additional information, see https://github.com/bkaradzic/bgfx\n"
  812. );
  813. }
  814. int _main_(int _argc, char** _argv)
  815. {
  816. bx::CommandLine cmdLine(_argc, _argv);
  817. if (cmdLine.hasArg('v', "version") )
  818. {
  819. fprintf(stderr
  820. , "texturev, bgfx texture viewer tool, version %d.%d.%d.\n"
  821. , BGFX_TEXTUREV_VERSION_MAJOR
  822. , BGFX_TEXTUREV_VERSION_MINOR
  823. , BGFX_API_VERSION
  824. );
  825. return bx::kExitSuccess;
  826. }
  827. if (cmdLine.hasArg('h', "help") )
  828. {
  829. help();
  830. return bx::kExitFailure;
  831. }
  832. else if (cmdLine.hasArg("associate") )
  833. {
  834. associate();
  835. return bx::kExitFailure;
  836. }
  837. uint32_t width = 1280;
  838. uint32_t height = 720;
  839. uint32_t debug = BGFX_DEBUG_TEXT;
  840. uint32_t reset = BGFX_RESET_VSYNC;
  841. inputAddBindings(s_bindingName[Binding::App], s_binding[Binding::App]);
  842. inputAddBindings(s_bindingName[Binding::View], s_binding[Binding::View]);
  843. View view;
  844. cmdAdd("view", cmdView, &view);
  845. bgfx::init();
  846. bgfx::reset(width, height, reset);
  847. // Set view 0 clear state.
  848. bgfx::setViewClear(BACKGROUND_VIEW_ID
  849. , BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH
  850. , 0x000000ff
  851. , 1.0f
  852. , 0
  853. );
  854. imguiCreate();
  855. PosUvwColorVertex::init();
  856. const bgfx::Caps* caps = bgfx::getCaps();
  857. bgfx::RendererType::Enum type = caps->rendererType;
  858. bgfx::UniformHandle s_texColor = bgfx::createUniform("s_texColor", bgfx::UniformType::Int1);
  859. bgfx::UniformHandle u_mtx = bgfx::createUniform("u_mtx", bgfx::UniformType::Mat4);
  860. bgfx::UniformHandle u_params = bgfx::createUniform("u_params", bgfx::UniformType::Vec4);
  861. bgfx::ShaderHandle vsTexture = bgfx::createEmbeddedShader(s_embeddedShaders, type, "vs_texture");
  862. bgfx::ShaderHandle fsTexture = bgfx::createEmbeddedShader(s_embeddedShaders, type, "fs_texture");
  863. bgfx::ShaderHandle fsTextureArray = bgfx::createEmbeddedShader(s_embeddedShaders, type, "fs_texture_array");
  864. bgfx::ProgramHandle textureProgram = bgfx::createProgram(
  865. vsTexture
  866. , fsTexture
  867. , true
  868. );
  869. bgfx::ProgramHandle textureArrayProgram = bgfx::createProgram(
  870. vsTexture
  871. , bgfx::isValid(fsTextureArray)
  872. ? fsTextureArray
  873. : fsTexture
  874. , true
  875. );
  876. bgfx::ProgramHandle textureCubeProgram = bgfx::createProgram(
  877. bgfx::createEmbeddedShader(s_embeddedShaders, type, "vs_texture_cube")
  878. , bgfx::createEmbeddedShader(s_embeddedShaders, type, "fs_texture_cube")
  879. , true
  880. );
  881. bgfx::ProgramHandle textureCube2Program = bgfx::createProgram(
  882. vsTexture
  883. , bgfx::createEmbeddedShader(s_embeddedShaders, type, "fs_texture_cube2")
  884. , true
  885. );
  886. bgfx::ProgramHandle textureSdfProgram = bgfx::createProgram(
  887. vsTexture
  888. , bgfx::createEmbeddedShader(s_embeddedShaders, type, "fs_texture_sdf")
  889. , true
  890. );
  891. bgfx::ProgramHandle texture3DProgram = bgfx::createProgram(
  892. vsTexture
  893. , bgfx::createEmbeddedShader(s_embeddedShaders, type, "fs_texture_3d")
  894. , true
  895. );
  896. const uint32_t checkerBoardSize = 64;
  897. bgfx::TextureHandle checkerBoard;
  898. {
  899. const bgfx::Memory* mem = bgfx::alloc(checkerBoardSize*checkerBoardSize*4);
  900. bimg::imageCheckerboard(mem->data, checkerBoardSize, checkerBoardSize, 8, 0xff8e8e8e, 0xff5d5d5d);
  901. checkerBoard = bgfx::createTexture2D(checkerBoardSize, checkerBoardSize, false, 1
  902. , bgfx::TextureFormat::BGRA8
  903. , 0
  904. | BGFX_TEXTURE_MIN_POINT
  905. | BGFX_TEXTURE_MIP_POINT
  906. | BGFX_TEXTURE_MAG_POINT
  907. , mem
  908. );
  909. }
  910. float speed = 0.37f;
  911. float time = 0.0f;
  912. Interpolator mip(0.0f);
  913. Interpolator layer(0.0f);
  914. Interpolator zoom(1.0f);
  915. Interpolator scale(1.0f);
  916. Interpolator posx(0.0f);
  917. Interpolator posy(0.0f);
  918. InterpolatorAngle angle(0.0f);
  919. InterpolatorAngle angx(0.0f);
  920. InterpolatorAngle angy(0.0f);
  921. const char* filePath = _argc < 2 ? "" : _argv[1];
  922. bool directory = false;
  923. bx::FileInfo fi;
  924. bx::stat(filePath, fi);
  925. directory = bx::FileInfo::Directory == fi.m_type;
  926. std::string path = filePath;
  927. if (!directory)
  928. {
  929. bx::FilePath fp(filePath);
  930. path.assign(fp.getPath().getPtr(), fp.getPath().getTerm() );
  931. view.updateFileList(path.c_str(), fp.getFileName() );
  932. }
  933. else
  934. {
  935. view.updateFileList(path.c_str(), "");
  936. }
  937. int exitcode = bx::kExitSuccess;
  938. bgfx::TextureHandle texture = BGFX_INVALID_HANDLE;
  939. if (view.m_fileList.empty() )
  940. {
  941. exitcode = bx::kExitFailure;
  942. if (2 > _argc)
  943. {
  944. help("File path is not specified.");
  945. }
  946. else
  947. {
  948. fprintf(stderr, "Unable to load '%s' texture.\n", filePath);
  949. }
  950. }
  951. else
  952. {
  953. uint32_t fileIndex = 0;
  954. bool dragging = false;
  955. entry::MouseState mouseStatePrev;
  956. entry::MouseState mouseState;
  957. while (!entry::processEvents(width, height, debug, reset, &mouseState) )
  958. {
  959. imguiBeginFrame(mouseState.m_mx
  960. , mouseState.m_my
  961. , (mouseState.m_buttons[entry::MouseButton::Left ] ? IMGUI_MBUT_LEFT : 0)
  962. | (mouseState.m_buttons[entry::MouseButton::Right ] ? IMGUI_MBUT_RIGHT : 0)
  963. | (mouseState.m_buttons[entry::MouseButton::Middle] ? IMGUI_MBUT_MIDDLE : 0)
  964. , mouseState.m_mz
  965. , uint16_t(width)
  966. , uint16_t(height)
  967. );
  968. static bool help = false;
  969. static bool mouseDelta = false;
  970. if (!mouseDelta)
  971. {
  972. mouseStatePrev = mouseState;
  973. mouseDelta = true;
  974. }
  975. int32_t zoomDelta = mouseState.m_mz - mouseStatePrev.m_mz;
  976. if (zoomDelta != 0)
  977. {
  978. char exec[64];
  979. bx::snprintf(exec, BX_COUNTOF(exec), "view zoom %+f", -zoomDelta*0.1f);
  980. cmdExec(exec);
  981. }
  982. const float xDelta = float(mouseStatePrev.m_mx - mouseState.m_mx);
  983. const float yDelta = float(mouseStatePrev.m_my - mouseState.m_my);
  984. if (!ImGui::MouseOverArea()
  985. && !help
  986. && mouseState.m_buttons[entry::MouseButton::Left] != mouseStatePrev.m_buttons[entry::MouseButton::Left])
  987. {
  988. dragging = !!mouseState.m_buttons[entry::MouseButton::Left];
  989. }
  990. if (dragging)
  991. {
  992. if (view.m_info.cubeMap
  993. && Geometry::Quad == view.m_cubeMapGeo)
  994. {
  995. char exec[64];
  996. bx::snprintf(exec, BX_COUNTOF(exec), "view cubemap %+f %+f", -yDelta, -xDelta);
  997. cmdExec(exec);
  998. }
  999. else
  1000. {
  1001. char exec[64];
  1002. bx::snprintf(exec, BX_COUNTOF(exec), "view pan %+f %+f", xDelta, yDelta);
  1003. cmdExec(exec);
  1004. }
  1005. }
  1006. mouseStatePrev = mouseState;
  1007. if (ImGui::BeginPopupContextVoid("Menu") )
  1008. {
  1009. // if (ImGui::MenuItem("Open") )
  1010. {
  1011. }
  1012. // if (ImGui::MenuItem("Save As") )
  1013. {
  1014. }
  1015. if (ImGui::MenuItem("Reset") )
  1016. {
  1017. cmdExec(s_resetCmd);
  1018. }
  1019. ImGui::Separator();
  1020. if (ImGui::BeginMenu("Options"))
  1021. {
  1022. bool filter = view.m_filter;
  1023. if (ImGui::MenuItem("Filter", NULL, &filter) )
  1024. {
  1025. cmdExec("view filter");
  1026. }
  1027. if (ImGui::BeginMenu("Cubemap", view.m_info.cubeMap) )
  1028. {
  1029. if (ImGui::MenuItem("Quad", NULL, Geometry::Quad == view.m_cubeMapGeo) )
  1030. {
  1031. cmdExec("view geo quad");
  1032. }
  1033. if (ImGui::MenuItem("Cross", NULL, Geometry::Cross == view.m_cubeMapGeo) )
  1034. {
  1035. cmdExec("view geo cross");
  1036. }
  1037. if (ImGui::MenuItem("Hexagon", NULL, Geometry::Hexagon == view.m_cubeMapGeo) )
  1038. {
  1039. cmdExec("view geo hexagon");
  1040. }
  1041. ImGui::EndMenu();
  1042. }
  1043. bool rr = 0 != (view.m_abgr & 0x000000ff);
  1044. if (ImGui::MenuItem("R", NULL, &rr) )
  1045. {
  1046. cmdExec("view rgb r");
  1047. }
  1048. bool gg = 0 != (view.m_abgr & 0x0000ff00);
  1049. if (ImGui::MenuItem("G", NULL, &gg) )
  1050. {
  1051. cmdExec("view rgb g");
  1052. }
  1053. bool bb = 0 != (view.m_abgr & 0x00ff0000);
  1054. if (ImGui::MenuItem("B", NULL, &bb) )
  1055. {
  1056. cmdExec("view rgb b");
  1057. }
  1058. bool alpha = view.m_alpha;
  1059. if (ImGui::MenuItem("Checkerboard", NULL, &alpha) )
  1060. {
  1061. cmdExec("view rgb a");
  1062. }
  1063. ImGui::EndMenu();
  1064. }
  1065. ImGui::Separator();
  1066. if (ImGui::MenuItem("Help") )
  1067. {
  1068. cmdExec("view help");
  1069. }
  1070. ImGui::Separator();
  1071. if (ImGui::MenuItem("Exit") )
  1072. {
  1073. cmdExec("exit");
  1074. }
  1075. ImGui::EndPopup();
  1076. }
  1077. if (help != view.m_help)
  1078. {
  1079. if (!help)
  1080. {
  1081. ImGui::OpenPopup("Help");
  1082. inputRemoveBindings(s_bindingName[Binding::View]);
  1083. inputAddBindings(s_bindingName[Binding::Help], s_binding[Binding::Help]);
  1084. }
  1085. else
  1086. {
  1087. inputRemoveBindings(s_bindingName[Binding::Help]);
  1088. inputAddBindings(s_bindingName[Binding::View], s_binding[Binding::View]);
  1089. }
  1090. help = view.m_help;
  1091. }
  1092. if (ImGui::BeginPopupModal("Help", NULL, ImGuiWindowFlags_AlwaysAutoResize) )
  1093. {
  1094. ImGui::SetWindowFontScale(1.0f);
  1095. ImGui::Text(
  1096. "texturev, bgfx texture viewer tool " ICON_KI_WRENCH ", version %d.%d.%d.\n"
  1097. "Copyright 2011-2017 Branimir Karadzic. All rights reserved.\n"
  1098. "License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause\n"
  1099. , BGFX_TEXTUREV_VERSION_MAJOR
  1100. , BGFX_TEXTUREV_VERSION_MINOR
  1101. , BGFX_API_VERSION
  1102. );
  1103. ImGui::Separator();
  1104. ImGui::NextLine();
  1105. ImGui::Text("Key bindings:\n\n");
  1106. ImGui::PushFont(ImGui::Font::Mono);
  1107. keyBindingHelp("ESC", "Exit.");
  1108. keyBindingHelp("h", "Toggle help screen.");
  1109. keyBindingHelp("f", "Toggle full-screen.");
  1110. ImGui::NextLine();
  1111. keyBindingHelp("LMB+drag", "Pan.");
  1112. keyBindingHelp("=/- or MW", "Zoom in/out.");
  1113. keyBindingHelp("z/Z", "Rotate.");
  1114. keyBindingHelp("0", "Reset.");
  1115. keyBindingHelp("1", "Fit to window.");
  1116. ImGui::NextLine();
  1117. keyBindingHelp("<", "Reset MIP level.");
  1118. keyBindingHelp(",/,", "MIP level up/down.");
  1119. keyBindingHelp("/", "Toggle linear/point texture sampling.");
  1120. keyBindingHelp("[space]", "Change cubemap mode.");
  1121. ImGui::NextLine();
  1122. keyBindingHelp("left", "Previous layer in texture array.");
  1123. keyBindingHelp("right", "Next layer in texture array.");
  1124. ImGui::NextLine();
  1125. keyBindingHelp("up", "Previous texture.");
  1126. keyBindingHelp("down", "Next texture.");
  1127. ImGui::NextLine();
  1128. keyBindingHelp("r/g/b", "Toggle R, G, or B color channel.");
  1129. keyBindingHelp("a", "Toggle alpha blending.");
  1130. ImGui::NextLine();
  1131. keyBindingHelp("s", "Toggle Multi-channel SDF rendering");
  1132. ImGui::NextLine();
  1133. ImGui::PopFont();
  1134. ImGui::Dummy(ImVec2(0.0f, 0.0f) );
  1135. ImGui::SameLine(ImGui::GetWindowWidth() - 136.0f);
  1136. if (ImGui::Button("Close", ImVec2(128.0f, 0.0f) )
  1137. || !view.m_help)
  1138. {
  1139. view.m_help = false;
  1140. ImGui::CloseCurrentPopup();
  1141. }
  1142. ImGui::EndPopup();
  1143. }
  1144. imguiEndFrame();
  1145. if (!bgfx::isValid(texture)
  1146. || view.m_fileIndex != fileIndex)
  1147. {
  1148. if (bgfx::isValid(texture) )
  1149. {
  1150. bgfx::destroyTexture(texture);
  1151. }
  1152. fileIndex = view.m_fileIndex;
  1153. filePath = view.m_fileList[view.m_fileIndex].c_str();
  1154. texture = loadTexture(filePath
  1155. , 0
  1156. | BGFX_TEXTURE_U_CLAMP
  1157. | BGFX_TEXTURE_V_CLAMP
  1158. | BGFX_TEXTURE_W_CLAMP
  1159. , 0
  1160. , &view.m_info
  1161. );
  1162. std::string title;
  1163. if (isValid(texture) )
  1164. {
  1165. const char* name = "";
  1166. if (view.m_info.cubeMap)
  1167. {
  1168. name = " CubeMap";
  1169. }
  1170. else if (1 < view.m_info.depth)
  1171. {
  1172. name = " 3D";
  1173. view.m_info.numLayers = view.m_info.depth;
  1174. }
  1175. else if (1 < view.m_info.numLayers)
  1176. {
  1177. name = " 2D Array";
  1178. }
  1179. bx::stringPrintf(title, "%s (%d x %d%s, mips: %d, layers %d, %s)"
  1180. , filePath
  1181. , view.m_info.width
  1182. , view.m_info.height
  1183. , name
  1184. , view.m_info.numMips
  1185. , view.m_info.numLayers
  1186. , bimg::getName(bimg::TextureFormat::Enum(view.m_info.format) )
  1187. );
  1188. }
  1189. else
  1190. {
  1191. bx::stringPrintf(title, "Failed to load %s!", filePath);
  1192. }
  1193. entry::WindowHandle handle = { 0 };
  1194. entry::setWindowTitle(handle, title.c_str() );
  1195. }
  1196. int64_t now = bx::getHPCounter();
  1197. static int64_t last = now;
  1198. const int64_t frameTime = now - last;
  1199. last = now;
  1200. const double freq = double(bx::getHPFrequency() );
  1201. time += (float)(frameTime*speed/freq);
  1202. float transitionTime = dragging ? 0.0f : 0.25f;
  1203. posx.set(view.m_posx, transitionTime);
  1204. posy.set(view.m_posy, transitionTime);
  1205. float ortho[16];
  1206. bx::mtxOrtho(
  1207. ortho
  1208. , 0.0f
  1209. , float(width)
  1210. , float(height)
  1211. , 0.0f
  1212. , 0.0f
  1213. , 1000.0f
  1214. , 0.0f
  1215. , caps->homogeneousDepth
  1216. );
  1217. bgfx::setViewTransform(BACKGROUND_VIEW_ID, NULL, ortho);
  1218. bgfx::setViewRect(BACKGROUND_VIEW_ID, 0, 0, uint16_t(width), uint16_t(height) );
  1219. setGeometry(Geometry::Quad
  1220. , 0
  1221. , 0
  1222. , width
  1223. , height
  1224. , view.m_alpha ? UINT32_MAX : 0
  1225. , float(width )/float(checkerBoardSize)
  1226. , float(height)/float(checkerBoardSize)
  1227. );
  1228. bgfx::setTexture(0
  1229. , s_texColor
  1230. , checkerBoard
  1231. );
  1232. bgfx::setState(0
  1233. | BGFX_STATE_RGB_WRITE
  1234. | BGFX_STATE_ALPHA_WRITE
  1235. );
  1236. bgfx::submit(BACKGROUND_VIEW_ID
  1237. , textureProgram
  1238. );
  1239. float px = posx.getValue();
  1240. float py = posy.getValue();
  1241. bx::mtxOrtho(
  1242. ortho
  1243. , px-width/2.0f
  1244. , px+width/2.0f
  1245. , py+height/2.0f
  1246. , py-height/2.0f
  1247. , 0.0f
  1248. , 1000.0f
  1249. , 0.0f
  1250. , caps->homogeneousDepth
  1251. );
  1252. bgfx::setViewTransform(IMAGE_VIEW_ID, NULL, ortho);
  1253. bgfx::setViewRect(IMAGE_VIEW_ID, 0, 0, uint16_t(width), uint16_t(height) );
  1254. bgfx::dbgTextClear();
  1255. if (view.m_fit)
  1256. {
  1257. scale.set(bx::fmin(float(width) / float(view.m_info.width)
  1258. , float(height) / float(view.m_info.height) )
  1259. , 0.1f
  1260. );
  1261. }
  1262. else
  1263. {
  1264. scale.set(1.0f, 0.1f);
  1265. }
  1266. zoom.set(view.m_zoom, transitionTime);
  1267. angle.set(view.m_angle, transitionTime);
  1268. angx.set(view.m_angx, transitionTime);
  1269. angy.set(view.m_angy, transitionTime);
  1270. float ss = scale.getValue()
  1271. * zoom.getValue()
  1272. ;
  1273. setGeometry(view.m_info.cubeMap ? view.m_cubeMapGeo : Geometry::Quad
  1274. , -int(view.m_info.width * ss)/2
  1275. , -int(view.m_info.height * ss)/2
  1276. , int(view.m_info.width * ss)
  1277. , int(view.m_info.height * ss)
  1278. , view.m_abgr
  1279. );
  1280. float rotz[16];
  1281. bx::mtxRotateZ(rotz, angle.getValue() );
  1282. bgfx::setTransform(rotz);
  1283. float mtx[16];
  1284. bx::mtxRotateXY(mtx, angx.getValue(), angy.getValue() );
  1285. bgfx::setUniform(u_mtx, mtx);
  1286. mip.set(float(view.m_mip), 0.5f);
  1287. layer.set(float(view.m_layer), 0.25f);
  1288. float params[4] = { mip.getValue(), layer.getValue(), 0.0f, 0.0f };
  1289. if (1 < view.m_info.depth)
  1290. {
  1291. params[1] = layer.getValue()/view.m_info.depth;
  1292. }
  1293. bgfx::setUniform(u_params, params);
  1294. const uint32_t textureFlags = 0
  1295. | BGFX_TEXTURE_U_CLAMP
  1296. | BGFX_TEXTURE_V_CLAMP
  1297. | BGFX_TEXTURE_W_CLAMP
  1298. | (view.m_filter ? 0 : 0
  1299. | BGFX_TEXTURE_MIN_POINT
  1300. | BGFX_TEXTURE_MIP_POINT
  1301. | BGFX_TEXTURE_MAG_POINT
  1302. )
  1303. ;
  1304. bgfx::setTexture(0
  1305. , s_texColor
  1306. , texture
  1307. , textureFlags
  1308. );
  1309. bgfx::setState(0
  1310. | BGFX_STATE_RGB_WRITE
  1311. | BGFX_STATE_ALPHA_WRITE
  1312. | (view.m_alpha ? BGFX_STATE_BLEND_ALPHA : BGFX_STATE_NONE)
  1313. );
  1314. bgfx:: ProgramHandle program = textureProgram;
  1315. if (1 < view.m_info.depth)
  1316. {
  1317. program = texture3DProgram;
  1318. }
  1319. else if (view.m_info.cubeMap)
  1320. {
  1321. program = Geometry::Quad == view.m_cubeMapGeo
  1322. ? textureCubeProgram
  1323. : textureCube2Program
  1324. ;
  1325. }
  1326. else if (1 < view.m_info.numLayers)
  1327. {
  1328. program = textureArrayProgram;
  1329. }
  1330. else if (view.m_sdf)
  1331. {
  1332. program = textureSdfProgram;
  1333. }
  1334. bgfx::submit(IMAGE_VIEW_ID, program);
  1335. bgfx::frame();
  1336. }
  1337. }
  1338. if (bgfx::isValid(texture) )
  1339. {
  1340. bgfx::destroyTexture(texture);
  1341. }
  1342. bgfx::destroyTexture(checkerBoard);
  1343. bgfx::destroyUniform(s_texColor);
  1344. bgfx::destroyUniform(u_mtx);
  1345. bgfx::destroyUniform(u_params);
  1346. bgfx::destroyProgram(textureProgram);
  1347. bgfx::destroyProgram(textureArrayProgram);
  1348. bgfx::destroyProgram(textureCubeProgram);
  1349. bgfx::destroyProgram(textureCube2Program);
  1350. bgfx::destroyProgram(textureSdfProgram);
  1351. bgfx::destroyProgram(texture3DProgram);
  1352. imguiDestroy();
  1353. bgfx::shutdown();
  1354. return exitcode;
  1355. }