texturev.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528
  1. /*
  2. * Copyright 2011-2016 Branimir Karadzic. All rights reserved.
  3. * License: http://www.opensource.org/licenses/BSD-2-Clause
  4. */
  5. #include "common.h"
  6. #include <bgfx/bgfx.h>
  7. #include <bx/os.h>
  8. #include <bx/string.h>
  9. #include <bx/uint32_t.h>
  10. #include <dirent.h>
  11. #include <entry/entry.h>
  12. #include <entry/input.h>
  13. #include <entry/cmd.h>
  14. #include <bgfx_utils.h>
  15. #include "vs_texture.bin.h"
  16. #include "fs_texture.bin.h"
  17. #include "vs_texture_cube.bin.h"
  18. #include "fs_texture_cube.bin.h"
  19. #include <bx/crtimpl.h>
  20. struct Binding
  21. {
  22. enum Enum
  23. {
  24. App,
  25. Dir,
  26. View,
  27. Count
  28. };
  29. };
  30. static const InputBinding s_bindingApp[] =
  31. {
  32. { entry::Key::Esc, entry::Modifier::None, 1, NULL, "exit" },
  33. INPUT_BINDING_END
  34. };
  35. static const InputBinding s_bindingDir[] =
  36. {
  37. { entry::Key::Up, entry::Modifier::None, 1, NULL, "dir up" },
  38. { entry::Key::Down, entry::Modifier::None, 1, NULL, "dir down" },
  39. { entry::Key::PageUp, entry::Modifier::None, 1, NULL, "dir up" },
  40. { entry::Key::PageDown, entry::Modifier::None, 1, NULL, "dir down" },
  41. { entry::Key::Left, entry::Modifier::None, 1, NULL, "dir back" },
  42. { entry::Key::Backspace, entry::Modifier::None, 1, NULL, "dir back" },
  43. { entry::Key::Right, entry::Modifier::None, 1, NULL, "dir enter" },
  44. { entry::Key::Return, entry::Modifier::None, 1, NULL, "dir enter" },
  45. INPUT_BINDING_END
  46. };
  47. static const InputBinding s_bindingView[] =
  48. {
  49. { entry::Key::Comma, entry::Modifier::None, 1, NULL, "view mip prev" },
  50. { entry::Key::Period, entry::Modifier::None, 1, NULL, "view mip next" },
  51. { entry::Key::Comma, entry::Modifier::LeftShift, 1, NULL, "view mip" },
  52. { entry::Key::Comma, entry::Modifier::RightShift, 1, NULL, "view mip" },
  53. { entry::Key::Slash, entry::Modifier::None, 1, NULL, "view filter" },
  54. { entry::Key::Key0, entry::Modifier::None, 1, NULL, "view zoom 1.0" },
  55. { entry::Key::Plus, entry::Modifier::None, 1, NULL, "view zoom +0.1" },
  56. { entry::Key::Minus, entry::Modifier::None, 1, NULL, "view zoom -0.1" },
  57. INPUT_BINDING_END
  58. };
  59. static const char* s_bindingName[] =
  60. {
  61. "App",
  62. "Dir",
  63. "View",
  64. };
  65. BX_STATIC_ASSERT(Binding::Count == BX_COUNTOF(s_bindingName) );
  66. static const InputBinding* s_binding[] =
  67. {
  68. s_bindingApp,
  69. s_bindingDir,
  70. s_bindingView,
  71. };
  72. BX_STATIC_ASSERT(Binding::Count == BX_COUNTOF(s_binding) );
  73. struct View
  74. {
  75. View()
  76. : m_scaleFn(0)
  77. , m_mip(0)
  78. , m_zoom(1.0f)
  79. , m_filter(true)
  80. {
  81. }
  82. ~View()
  83. {
  84. }
  85. int32_t cmd(int32_t _argc, char const* const* _argv)
  86. {
  87. if (_argc >= 2)
  88. {
  89. if (0 == strcmp(_argv[1], "mip") )
  90. {
  91. if (_argc >= 3)
  92. {
  93. uint32_t mip = m_mip;
  94. if (0 == strcmp(_argv[2], "next") )
  95. {
  96. ++mip;
  97. }
  98. else if (0 == strcmp(_argv[2], "prev") )
  99. {
  100. --mip;
  101. }
  102. else if (0 == strcmp(_argv[2], "last") )
  103. {
  104. mip = INT32_MAX;
  105. }
  106. else
  107. {
  108. mip = atoi(_argv[2]);
  109. }
  110. m_mip = bx::uint32_iclamp(mip, 0, m_info.numMips-1);
  111. }
  112. else
  113. {
  114. m_mip = 0;
  115. }
  116. }
  117. else if (0 == strcmp(_argv[1], "zoom") )
  118. {
  119. if (_argc >= 3)
  120. {
  121. float zoom = (float)atof(_argv[2]);
  122. if (_argv[2][0] == '+'
  123. || _argv[2][0] == '-')
  124. {
  125. m_zoom += zoom;
  126. }
  127. else
  128. {
  129. m_zoom = zoom;
  130. }
  131. m_zoom = bx::fclamp(m_zoom, 0.001f, 10.0f);
  132. }
  133. else
  134. {
  135. m_zoom = 1.0f;
  136. }
  137. }
  138. else if (0 == strcmp(_argv[1], "filter") )
  139. {
  140. if (_argc >= 3)
  141. {
  142. m_filter = bx::toBool(_argv[2]);
  143. }
  144. else
  145. {
  146. m_filter ^= true;
  147. }
  148. }
  149. }
  150. return 0;
  151. }
  152. bgfx::TextureInfo m_info;
  153. uint32_t m_scaleFn;
  154. uint32_t m_mip;
  155. float m_zoom;
  156. bool m_filter;
  157. };
  158. int cmdView(CmdContext* /*_context*/, void* _userData, int _argc, char const* const* _argv)
  159. {
  160. View* view = static_cast<View*>(_userData);
  161. return view->cmd(_argc, _argv);
  162. }
  163. struct PosUvColorVertex
  164. {
  165. float m_x;
  166. float m_y;
  167. float m_u;
  168. float m_v;
  169. uint32_t m_abgr;
  170. static void init()
  171. {
  172. ms_decl
  173. .begin()
  174. .add(bgfx::Attrib::Position, 2, bgfx::AttribType::Float)
  175. .add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Float)
  176. .add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true)
  177. .end();
  178. }
  179. static bgfx::VertexDecl ms_decl;
  180. };
  181. bgfx::VertexDecl PosUvColorVertex::ms_decl;
  182. bool screenQuad(int32_t _x, int32_t _y, int32_t _width, uint32_t _height, bool _originBottomLeft = false)
  183. {
  184. if (bgfx::checkAvailTransientVertexBuffer(6, PosUvColorVertex::ms_decl) )
  185. {
  186. bgfx::TransientVertexBuffer vb;
  187. bgfx::allocTransientVertexBuffer(&vb, 6, PosUvColorVertex::ms_decl);
  188. PosUvColorVertex* vertex = (PosUvColorVertex*)vb.data;
  189. const float widthf = float(_width);
  190. const float heightf = float(_height);
  191. const float minx = float(_x);
  192. const float miny = float(_y);
  193. const float maxx = minx+widthf;
  194. const float maxy = miny+heightf;
  195. float m_halfTexel = 0.0f;
  196. const float texelHalfW = m_halfTexel/widthf;
  197. const float texelHalfH = m_halfTexel/heightf;
  198. const float minu = texelHalfW;
  199. const float maxu = 1.0f - texelHalfW;
  200. const float minv = _originBottomLeft ? texelHalfH+1.0f : texelHalfH ;
  201. const float maxv = _originBottomLeft ? texelHalfH : texelHalfH+1.0f;
  202. vertex[0].m_x = minx;
  203. vertex[0].m_y = miny;
  204. vertex[0].m_u = minu;
  205. vertex[0].m_v = minv;
  206. vertex[1].m_x = maxx;
  207. vertex[1].m_y = miny;
  208. vertex[1].m_u = maxu;
  209. vertex[1].m_v = minv;
  210. vertex[2].m_x = maxx;
  211. vertex[2].m_y = maxy;
  212. vertex[2].m_u = maxu;
  213. vertex[2].m_v = maxv;
  214. vertex[3].m_x = maxx;
  215. vertex[3].m_y = maxy;
  216. vertex[3].m_u = maxu;
  217. vertex[3].m_v = maxv;
  218. vertex[4].m_x = minx;
  219. vertex[4].m_y = maxy;
  220. vertex[4].m_u = minu;
  221. vertex[4].m_v = maxv;
  222. vertex[5].m_x = minx;
  223. vertex[5].m_y = miny;
  224. vertex[5].m_u = minu;
  225. vertex[5].m_v = minv;
  226. vertex[0].m_abgr = UINT32_MAX;
  227. vertex[1].m_abgr = UINT32_MAX;
  228. vertex[2].m_abgr = UINT32_MAX;
  229. vertex[3].m_abgr = UINT32_MAX;
  230. vertex[4].m_abgr = UINT32_MAX;
  231. vertex[5].m_abgr = UINT32_MAX;
  232. bgfx::setVertexBuffer(&vb);
  233. return true;
  234. }
  235. return false;
  236. }
  237. struct Interpolator
  238. {
  239. float from;
  240. float to;
  241. float duration;
  242. int64_t offset;
  243. Interpolator(float _value)
  244. {
  245. reset(_value);
  246. }
  247. void reset(float _value)
  248. {
  249. from = _value;
  250. to = _value;
  251. duration = 0.0;
  252. offset = bx::getHPCounter();
  253. }
  254. void set(float _value, float _duration)
  255. {
  256. if (_value != to)
  257. {
  258. from = getValue();
  259. to = _value;
  260. duration = _duration;
  261. offset = bx::getHPCounter();
  262. }
  263. }
  264. float getValue()
  265. {
  266. if (duration > 0.0)
  267. {
  268. const double freq = double(bx::getHPFrequency() );
  269. int64_t now = bx::getHPCounter();
  270. float time = (float)(double(now - offset) / freq);
  271. float lerp = bx::fclamp(time, 0.0, duration) / duration;
  272. return bx::flerp(from, to, lerp);
  273. }
  274. return to;
  275. }
  276. };
  277. void help(const char* _error = NULL)
  278. {
  279. if (NULL != _error)
  280. {
  281. fprintf(stderr, "Error:\n%s\n\n", _error);
  282. }
  283. fprintf(stderr
  284. , "texturev, bgfx texture viewer tool\n"
  285. "Copyright 2011-2016 Branimir Karadzic. All rights reserved.\n"
  286. "License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause\n\n"
  287. );
  288. fprintf(stderr
  289. , "Usage: texturev <file path>\n"
  290. "\n"
  291. "For additional information, see https://github.com/bkaradzic/bgfx\n"
  292. );
  293. }
  294. int _main_(int _argc, char** _argv)
  295. {
  296. if (2 > _argc)
  297. {
  298. help("File path is not specified.");
  299. return EXIT_FAILURE;
  300. }
  301. uint32_t width = 1280;
  302. uint32_t height = 720;
  303. uint32_t debug = BGFX_DEBUG_TEXT;
  304. uint32_t reset = BGFX_RESET_VSYNC;
  305. inputAddBindings(s_bindingName[Binding::App], s_binding[Binding::App]);
  306. inputAddBindings(s_bindingName[Binding::Dir], s_binding[Binding::Dir]);
  307. inputAddBindings(s_bindingName[Binding::View], s_binding[Binding::View]);
  308. View view;
  309. cmdAdd("view", cmdView, &view);
  310. bgfx::init();
  311. bgfx::reset(width, height, reset);
  312. // Set view 0 clear state.
  313. bgfx::setViewClear(0
  314. , BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH
  315. , 0x101010ff
  316. , 1.0f
  317. , 0
  318. );
  319. PosUvColorVertex::init();
  320. const bgfx::Memory* vs_texture;
  321. const bgfx::Memory* fs_texture;
  322. const bgfx::Memory* vs_texture_cube;
  323. const bgfx::Memory* fs_texture_cube;
  324. switch (bgfx::getRendererType())
  325. {
  326. case bgfx::RendererType::Direct3D9:
  327. vs_texture = bgfx::makeRef(vs_texture_dx9, sizeof(vs_texture_dx9) );
  328. fs_texture = bgfx::makeRef(fs_texture_dx9, sizeof(fs_texture_dx9) );
  329. vs_texture_cube = bgfx::makeRef(vs_texture_cube_dx9, sizeof(vs_texture_cube_dx9) );
  330. fs_texture_cube = bgfx::makeRef(fs_texture_cube_dx9, sizeof(fs_texture_cube_dx9) );
  331. break;
  332. case bgfx::RendererType::Direct3D11:
  333. case bgfx::RendererType::Direct3D12:
  334. vs_texture = bgfx::makeRef(vs_texture_dx11, sizeof(vs_texture_dx11) );
  335. fs_texture = bgfx::makeRef(fs_texture_dx11, sizeof(fs_texture_dx11) );
  336. vs_texture_cube = bgfx::makeRef(vs_texture_cube_dx11, sizeof(vs_texture_cube_dx11) );
  337. fs_texture_cube = bgfx::makeRef(fs_texture_cube_dx11, sizeof(fs_texture_cube_dx11) );
  338. break;
  339. default:
  340. vs_texture = bgfx::makeRef(vs_texture_glsl, sizeof(vs_texture_glsl) );
  341. fs_texture = bgfx::makeRef(fs_texture_glsl, sizeof(fs_texture_glsl) );
  342. vs_texture_cube = bgfx::makeRef(vs_texture_cube_glsl, sizeof(vs_texture_cube_glsl) );
  343. fs_texture_cube = bgfx::makeRef(fs_texture_cube_glsl, sizeof(fs_texture_cube_glsl) );
  344. break;
  345. }
  346. bgfx::ProgramHandle textureProgram = bgfx::createProgram(
  347. bgfx::createShader(vs_texture)
  348. , bgfx::createShader(fs_texture)
  349. , true
  350. );
  351. bgfx::ProgramHandle textureCubeProgram = bgfx::createProgram(
  352. bgfx::createShader(vs_texture_cube)
  353. , bgfx::createShader(fs_texture_cube)
  354. , true
  355. );
  356. bgfx::UniformHandle s_texColor = bgfx::createUniform("s_texColor", bgfx::UniformType::Int1);
  357. bgfx::UniformHandle u_mtx = bgfx::createUniform("u_mtx", bgfx::UniformType::Mat4);
  358. bgfx::UniformHandle u_params = bgfx::createUniform("u_params", bgfx::UniformType::Vec4);
  359. bgfx::TextureHandle texture = BGFX_INVALID_HANDLE;
  360. float speed = 0.37f;
  361. float time = 0.0f;
  362. Interpolator mip(0.0);
  363. Interpolator zoom(1.0);
  364. Interpolator scale(1.0);
  365. texture = loadTexture(_argv[1]
  366. , 0
  367. | BGFX_TEXTURE_U_CLAMP
  368. | BGFX_TEXTURE_V_CLAMP
  369. | BGFX_TEXTURE_W_CLAMP
  370. , 0
  371. , &view.m_info
  372. );
  373. int exitcode = EXIT_SUCCESS;
  374. if (!bgfx::isValid(texture) )
  375. {
  376. fprintf(stderr, "Unable to load '%s' texture.\n", _argv[1]);
  377. exitcode = EXIT_FAILURE;
  378. }
  379. else
  380. {
  381. entry::MouseState mouseState;
  382. while (!entry::processEvents(width, height, debug, reset, &mouseState) )
  383. {
  384. int64_t now = bx::getHPCounter();
  385. static int64_t last = now;
  386. const int64_t frameTime = now - last;
  387. last = now;
  388. const double freq = double(bx::getHPFrequency() );
  389. time += (float)(frameTime*speed/freq);
  390. float ortho[16];
  391. bx::mtxOrtho(ortho, 0.0f, (float)width, (float)height, 0.0f, 0.0f, 1000.0f);
  392. bgfx::setViewTransform(0, NULL, ortho);
  393. bgfx::setViewRect(0, 0, 0, width, height);
  394. bgfx::touch(0);
  395. bgfx::dbgTextClear();
  396. scale.set(bx::fmin( float(width) / float(view.m_info.width)
  397. , float(height) / float(view.m_info.height)
  398. )
  399. , 0.1f
  400. );
  401. zoom.set(view.m_zoom, 0.25);
  402. float ss = scale.getValue() * zoom.getValue();
  403. screenQuad( int(width - view.m_info.width * ss)/2
  404. , int(height - view.m_info.height * ss)/2
  405. , int(view.m_info.width * ss)
  406. , int(view.m_info.height * ss)
  407. );
  408. float mtx[16];
  409. bx::mtxRotateXY(mtx, 0.0f, time);
  410. bgfx::setUniform(u_mtx, mtx);
  411. mip.set( float(view.m_mip), 0.5f);
  412. float params[4] = { mip.getValue(), 0.0f, 0.0f, 0.0f };
  413. bgfx::setUniform(u_params, params);
  414. bgfx::setTexture(0
  415. , s_texColor
  416. , texture
  417. , view.m_filter
  418. ? BGFX_TEXTURE_NONE
  419. : 0
  420. | BGFX_TEXTURE_MIN_POINT
  421. | BGFX_TEXTURE_MIP_POINT
  422. | BGFX_TEXTURE_MAG_POINT
  423. );
  424. bgfx::setState(0
  425. | BGFX_STATE_RGB_WRITE
  426. | BGFX_STATE_ALPHA_WRITE
  427. );
  428. bgfx::submit(0, view.m_info.cubeMap ? textureCubeProgram : textureProgram);
  429. bgfx::frame();
  430. }
  431. }
  432. if (bgfx::isValid(texture) )
  433. {
  434. bgfx::destroyTexture(texture);
  435. }
  436. bgfx::destroyUniform(s_texColor);
  437. bgfx::destroyUniform(u_mtx);
  438. bgfx::destroyUniform(u_params);
  439. bgfx::destroyProgram(textureProgram);
  440. bgfx::destroyProgram(textureCubeProgram);
  441. bgfx::shutdown();
  442. return exitcode;
  443. }