hdr.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782
  1. /*
  2. * Copyright 2011-2014 Branimir Karadzic. All rights reserved.
  3. * License: http://www.opensource.org/licenses/BSD-2-Clause
  4. */
  5. #include <vector>
  6. #include <string>
  7. #include "common.h"
  8. #include <bgfx.h>
  9. #include <bx/timer.h>
  10. #include <bx/readerwriter.h>
  11. #include "fpumath.h"
  12. #include "imgui/imgui.h"
  13. #include <string.h>
  14. static const char* s_shaderPath = NULL;
  15. static void shaderFilePath(char* _out, const char* _name)
  16. {
  17. strcpy(_out, s_shaderPath);
  18. strcat(_out, _name);
  19. strcat(_out, ".bin");
  20. }
  21. long int fsize(FILE* _file)
  22. {
  23. long int pos = ftell(_file);
  24. fseek(_file, 0L, SEEK_END);
  25. long int size = ftell(_file);
  26. fseek(_file, pos, SEEK_SET);
  27. return size;
  28. }
  29. static const bgfx::Memory* load(const char* _filePath)
  30. {
  31. FILE* file = fopen(_filePath, "rb");
  32. if (NULL != file)
  33. {
  34. uint32_t size = (uint32_t)fsize(file);
  35. const bgfx::Memory* mem = bgfx::alloc(size+1);
  36. size_t ignore = fread(mem->data, 1, size, file);
  37. BX_UNUSED(ignore);
  38. fclose(file);
  39. mem->data[mem->size-1] = '\0';
  40. return mem;
  41. }
  42. return NULL;
  43. }
  44. static const bgfx::Memory* loadShader(const char* _name)
  45. {
  46. char filePath[512];
  47. shaderFilePath(filePath, _name);
  48. return load(filePath);
  49. }
  50. static bgfx::ProgramHandle loadProgram(const char* _vshName, const char* _fshName)
  51. {
  52. const bgfx::Memory* mem;
  53. mem = loadShader(_vshName);
  54. bgfx::VertexShaderHandle vsh = bgfx::createVertexShader(mem);
  55. mem = loadShader(_fshName);
  56. bgfx::FragmentShaderHandle fsh = bgfx::createFragmentShader(mem);
  57. bgfx::ProgramHandle program = bgfx::createProgram(vsh, fsh);
  58. bgfx::destroyVertexShader(vsh);
  59. bgfx::destroyFragmentShader(fsh);
  60. return program;
  61. }
  62. static const bgfx::Memory* loadTexture(const char* _name)
  63. {
  64. char filePath[512];
  65. strcpy(filePath, "textures/");
  66. strcat(filePath, _name);
  67. return load(filePath);
  68. }
  69. struct Aabb
  70. {
  71. float m_min[3];
  72. float m_max[3];
  73. };
  74. struct Obb
  75. {
  76. float m_mtx[16];
  77. };
  78. struct Sphere
  79. {
  80. float m_center[3];
  81. float m_radius;
  82. };
  83. struct Primitive
  84. {
  85. uint32_t m_startIndex;
  86. uint32_t m_numIndices;
  87. uint32_t m_startVertex;
  88. uint32_t m_numVertices;
  89. Sphere m_sphere;
  90. Aabb m_aabb;
  91. Obb m_obb;
  92. };
  93. typedef std::vector<Primitive> PrimitiveArray;
  94. struct Group
  95. {
  96. Group()
  97. {
  98. reset();
  99. }
  100. void reset()
  101. {
  102. m_vbh.idx = bgfx::invalidHandle;
  103. m_ibh.idx = bgfx::invalidHandle;
  104. m_prims.clear();
  105. }
  106. bgfx::VertexBufferHandle m_vbh;
  107. bgfx::IndexBufferHandle m_ibh;
  108. Sphere m_sphere;
  109. Aabb m_aabb;
  110. Obb m_obb;
  111. PrimitiveArray m_prims;
  112. };
  113. struct Mesh
  114. {
  115. void load(const char* _filePath)
  116. {
  117. #define BGFX_CHUNK_MAGIC_VB BX_MAKEFOURCC('V', 'B', ' ', 0x0)
  118. #define BGFX_CHUNK_MAGIC_IB BX_MAKEFOURCC('I', 'B', ' ', 0x0)
  119. #define BGFX_CHUNK_MAGIC_PRI BX_MAKEFOURCC('P', 'R', 'I', 0x0)
  120. bx::CrtFileReader reader;
  121. reader.open(_filePath);
  122. Group group;
  123. uint32_t chunk;
  124. while (4 == bx::read(&reader, chunk) )
  125. {
  126. switch (chunk)
  127. {
  128. case BGFX_CHUNK_MAGIC_VB:
  129. {
  130. bx::read(&reader, group.m_sphere);
  131. bx::read(&reader, group.m_aabb);
  132. bx::read(&reader, group.m_obb);
  133. bx::read(&reader, m_decl);
  134. uint16_t stride = m_decl.getStride();
  135. uint16_t numVertices;
  136. bx::read(&reader, numVertices);
  137. const bgfx::Memory* mem = bgfx::alloc(numVertices*stride);
  138. bx::read(&reader, mem->data, mem->size);
  139. group.m_vbh = bgfx::createVertexBuffer(mem, m_decl);
  140. }
  141. break;
  142. case BGFX_CHUNK_MAGIC_IB:
  143. {
  144. uint32_t numIndices;
  145. bx::read(&reader, numIndices);
  146. const bgfx::Memory* mem = bgfx::alloc(numIndices*2);
  147. bx::read(&reader, mem->data, mem->size);
  148. group.m_ibh = bgfx::createIndexBuffer(mem);
  149. }
  150. break;
  151. case BGFX_CHUNK_MAGIC_PRI:
  152. {
  153. uint16_t len;
  154. bx::read(&reader, len);
  155. std::string material;
  156. material.resize(len);
  157. bx::read(&reader, const_cast<char*>(material.c_str() ), len);
  158. uint16_t num;
  159. bx::read(&reader, num);
  160. for (uint32_t ii = 0; ii < num; ++ii)
  161. {
  162. bx::read(&reader, len);
  163. std::string name;
  164. name.resize(len);
  165. bx::read(&reader, const_cast<char*>(name.c_str() ), len);
  166. Primitive prim;
  167. bx::read(&reader, prim.m_startIndex);
  168. bx::read(&reader, prim.m_numIndices);
  169. bx::read(&reader, prim.m_startVertex);
  170. bx::read(&reader, prim.m_numVertices);
  171. bx::read(&reader, prim.m_sphere);
  172. bx::read(&reader, prim.m_aabb);
  173. bx::read(&reader, prim.m_obb);
  174. group.m_prims.push_back(prim);
  175. }
  176. m_groups.push_back(group);
  177. group.reset();
  178. }
  179. break;
  180. default:
  181. DBG("%08x at %d", chunk, reader.seek() );
  182. break;
  183. }
  184. }
  185. reader.close();
  186. }
  187. void unload()
  188. {
  189. for (GroupArray::const_iterator it = m_groups.begin(), itEnd = m_groups.end(); it != itEnd; ++it)
  190. {
  191. const Group& group = *it;
  192. bgfx::destroyVertexBuffer(group.m_vbh);
  193. if (bgfx::isValid(group.m_ibh) )
  194. {
  195. bgfx::destroyIndexBuffer(group.m_ibh);
  196. }
  197. }
  198. m_groups.clear();
  199. }
  200. void submit(uint8_t _view, bgfx::ProgramHandle _program, float* _mtx)
  201. {
  202. for (GroupArray::const_iterator it = m_groups.begin(), itEnd = m_groups.end(); it != itEnd; ++it)
  203. {
  204. const Group& group = *it;
  205. // Set model matrix for rendering.
  206. bgfx::setTransform(_mtx);
  207. bgfx::setProgram(_program);
  208. bgfx::setIndexBuffer(group.m_ibh);
  209. bgfx::setVertexBuffer(group.m_vbh);
  210. // Set render states.
  211. bgfx::setState(0
  212. | BGFX_STATE_RGB_WRITE
  213. | BGFX_STATE_ALPHA_WRITE
  214. | BGFX_STATE_DEPTH_WRITE
  215. | BGFX_STATE_DEPTH_TEST_LESS
  216. | BGFX_STATE_CULL_CCW
  217. | BGFX_STATE_MSAA
  218. );
  219. // Submit primitive for rendering to view 0.
  220. bgfx::submit(_view);
  221. }
  222. }
  223. bgfx::VertexDecl m_decl;
  224. typedef std::vector<Group> GroupArray;
  225. GroupArray m_groups;
  226. };
  227. static bool s_flipV = false;
  228. static float s_texelHalf = 0.0f;
  229. struct PosColorTexCoord0Vertex
  230. {
  231. float m_x;
  232. float m_y;
  233. float m_z;
  234. uint32_t m_rgba;
  235. float m_u;
  236. float m_v;
  237. static void init()
  238. {
  239. ms_decl.begin();
  240. ms_decl.add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float);
  241. ms_decl.add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true);
  242. ms_decl.add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Float);
  243. ms_decl.end();
  244. }
  245. static bgfx::VertexDecl ms_decl;
  246. };
  247. bgfx::VertexDecl PosColorTexCoord0Vertex::ms_decl;
  248. void screenSpaceQuad(float _textureWidth, float _textureHeight, bool _originBottomLeft = false, float _width = 1.0f, float _height = 1.0f)
  249. {
  250. if (bgfx::checkAvailTransientVertexBuffer(3, PosColorTexCoord0Vertex::ms_decl) )
  251. {
  252. bgfx::TransientVertexBuffer vb;
  253. bgfx::allocTransientVertexBuffer(&vb, 3, PosColorTexCoord0Vertex::ms_decl);
  254. PosColorTexCoord0Vertex* vertex = (PosColorTexCoord0Vertex*)vb.data;
  255. const float zz = 0.0f;
  256. const float minx = -_width;
  257. const float maxx = _width;
  258. const float miny = 0.0f;
  259. const float maxy = _height*2.0f;
  260. const float texelHalfW = s_texelHalf/_textureWidth;
  261. const float texelHalfH = s_texelHalf/_textureHeight;
  262. const float minu = -1.0f + texelHalfW;
  263. const float maxu = 1.0f + texelHalfW;
  264. float minv = texelHalfH;
  265. float maxv = 2.0f + texelHalfH;
  266. if (_originBottomLeft)
  267. {
  268. std::swap(minv, maxv);
  269. minv -= 1.0f;
  270. maxv -= 1.0f;
  271. }
  272. vertex[0].m_x = minx;
  273. vertex[0].m_y = miny;
  274. vertex[0].m_z = zz;
  275. vertex[0].m_rgba = 0xffffffff;
  276. vertex[0].m_u = minu;
  277. vertex[0].m_v = minv;
  278. vertex[1].m_x = maxx;
  279. vertex[1].m_y = miny;
  280. vertex[1].m_z = zz;
  281. vertex[1].m_rgba = 0xffffffff;
  282. vertex[1].m_u = maxu;
  283. vertex[1].m_v = minv;
  284. vertex[2].m_x = maxx;
  285. vertex[2].m_y = maxy;
  286. vertex[2].m_z = zz;
  287. vertex[2].m_rgba = 0xffffffff;
  288. vertex[2].m_u = maxu;
  289. vertex[2].m_v = maxv;
  290. bgfx::setVertexBuffer(&vb);
  291. }
  292. }
  293. void setOffsets2x2Lum(bgfx::UniformHandle _handle, uint32_t _width, uint32_t _height)
  294. {
  295. float offsets[16][4];
  296. float du = 1.0f/_width;
  297. float dv = 1.0f/_height;
  298. uint32_t num = 0;
  299. for (uint32_t yy = 0; yy < 3; ++yy)
  300. {
  301. for (uint32_t xx = 0; xx < 3; ++xx)
  302. {
  303. offsets[num][0] = (xx - s_texelHalf) * du;
  304. offsets[num][1] = (yy - s_texelHalf) * dv;
  305. ++num;
  306. }
  307. }
  308. bgfx::setUniform(_handle, offsets, num);
  309. }
  310. void setOffsets4x4Lum(bgfx::UniformHandle _handle, uint32_t _width, uint32_t _height)
  311. {
  312. float offsets[16][4];
  313. float du = 1.0f/_width;
  314. float dv = 1.0f/_height;
  315. uint32_t num = 0;
  316. for (uint32_t yy = 0; yy < 4; ++yy)
  317. {
  318. for (uint32_t xx = 0; xx < 4; ++xx)
  319. {
  320. offsets[num][0] = (xx - 1.0f - s_texelHalf) * du;
  321. offsets[num][1] = (yy - 1.0f - s_texelHalf) * dv;
  322. ++num;
  323. }
  324. }
  325. bgfx::setUniform(_handle, offsets, num);
  326. }
  327. inline float square(float _x)
  328. {
  329. return _x*_x;
  330. }
  331. int _main_(int /*_argc*/, char** /*_argv*/)
  332. {
  333. PosColorTexCoord0Vertex::init();
  334. uint32_t width = 1280;
  335. uint32_t height = 720;
  336. uint32_t debug = BGFX_DEBUG_TEXT;
  337. uint32_t reset = BGFX_RESET_VSYNC;
  338. bgfx::init();
  339. bgfx::reset(width, height, reset);
  340. // Enable debug text.
  341. bgfx::setDebug(debug);
  342. // Set view 0 clear state.
  343. bgfx::setViewClear(0
  344. , BGFX_CLEAR_COLOR_BIT|BGFX_CLEAR_DEPTH_BIT
  345. , 0x303030ff
  346. , 1.0f
  347. , 0
  348. );
  349. // Setup root path for binary shaders. Shader binaries are different
  350. // for each renderer.
  351. switch (bgfx::getRendererType() )
  352. {
  353. default:
  354. case bgfx::RendererType::Direct3D9:
  355. s_shaderPath = "shaders/dx9/";
  356. s_texelHalf = 0.5f;
  357. break;
  358. case bgfx::RendererType::Direct3D11:
  359. s_shaderPath = "shaders/dx11/";
  360. break;
  361. case bgfx::RendererType::OpenGL:
  362. s_shaderPath = "shaders/glsl/";
  363. s_flipV = true;
  364. break;
  365. case bgfx::RendererType::OpenGLES2:
  366. case bgfx::RendererType::OpenGLES3:
  367. s_shaderPath = "shaders/gles/";
  368. s_flipV = true;
  369. break;
  370. }
  371. const bgfx::Memory* mem;
  372. mem = loadTexture("uffizi.dds");
  373. bgfx::TextureHandle uffizi = bgfx::createTexture(mem, BGFX_TEXTURE_U_CLAMP|BGFX_TEXTURE_V_CLAMP|BGFX_TEXTURE_W_CLAMP);
  374. bgfx::UniformHandle u_time = bgfx::createUniform("u_time", bgfx::UniformType::Uniform1f);
  375. bgfx::UniformHandle u_texCube = bgfx::createUniform("u_texCube", bgfx::UniformType::Uniform1i);
  376. bgfx::UniformHandle u_texColor = bgfx::createUniform("u_texColor", bgfx::UniformType::Uniform1i);
  377. bgfx::UniformHandle u_texLum = bgfx::createUniform("u_texLum", bgfx::UniformType::Uniform1i);
  378. bgfx::UniformHandle u_texBlur = bgfx::createUniform("u_texBlur", bgfx::UniformType::Uniform1i);
  379. bgfx::UniformHandle u_mtx = bgfx::createUniform("u_mtx", bgfx::UniformType::Uniform4x4fv);
  380. bgfx::UniformHandle u_tonemap = bgfx::createUniform("u_tonemap", bgfx::UniformType::Uniform4fv);
  381. bgfx::UniformHandle u_offset = bgfx::createUniform("u_offset", bgfx::UniformType::Uniform4fv, 16);
  382. bgfx::UniformHandle u_weight = bgfx::createUniform("u_weight", bgfx::UniformType::Uniform4fv, 16);
  383. bgfx::ProgramHandle skyProgram = loadProgram("vs_hdr_skybox", "fs_hdr_skybox");
  384. bgfx::ProgramHandle lumProgram = loadProgram("vs_hdr_lum", "fs_hdr_lum");
  385. bgfx::ProgramHandle lumAvgProgram = loadProgram("vs_hdr_lumavg", "fs_hdr_lumavg");
  386. bgfx::ProgramHandle blurProgram = loadProgram("vs_hdr_blur", "fs_hdr_blur");
  387. bgfx::ProgramHandle brightProgram = loadProgram("vs_hdr_bright", "fs_hdr_bright");
  388. bgfx::ProgramHandle meshProgram = loadProgram("vs_hdr_mesh", "fs_hdr_mesh");
  389. bgfx::ProgramHandle tonemapProgram = loadProgram("vs_hdr_tonemap", "fs_hdr_tonemap");
  390. Mesh mesh;
  391. mesh.load("meshes/bunny.bin");
  392. bgfx::FrameBufferHandle fbh;
  393. bgfx::TextureHandle fbtextures[] =
  394. {
  395. bgfx::createTexture2D(width, height, 1, bgfx::TextureFormat::BGRA8, BGFX_TEXTURE_RT),
  396. bgfx::createTexture2D(width, height, 1, bgfx::TextureFormat::D16, BGFX_TEXTURE_RT_BUFFER_ONLY),
  397. };
  398. fbh = bgfx::createFrameBuffer(BX_COUNTOF(fbtextures), fbtextures, true);
  399. bgfx::FrameBufferHandle lum[5];
  400. lum[0] = bgfx::createFrameBuffer(128, 128, bgfx::TextureFormat::BGRA8);
  401. lum[1] = bgfx::createFrameBuffer( 64, 64, bgfx::TextureFormat::BGRA8);
  402. lum[2] = bgfx::createFrameBuffer( 16, 16, bgfx::TextureFormat::BGRA8);
  403. lum[3] = bgfx::createFrameBuffer( 4, 4, bgfx::TextureFormat::BGRA8);
  404. lum[4] = bgfx::createFrameBuffer( 1, 1, bgfx::TextureFormat::BGRA8);
  405. bgfx::FrameBufferHandle bright;
  406. bright = bgfx::createFrameBuffer(width/2, height/2, bgfx::TextureFormat::BGRA8);
  407. bgfx::FrameBufferHandle blur;
  408. blur = bgfx::createFrameBuffer(width/8, height/8, bgfx::TextureFormat::BGRA8);
  409. FILE* file = fopen("font/droidsans.ttf", "rb");
  410. uint32_t size = (uint32_t)fsize(file);
  411. void* data = malloc(size);
  412. size_t ignore = fread(data, 1, size, file);
  413. BX_UNUSED(ignore);
  414. fclose(file);
  415. imguiCreate(data, size);
  416. free(data);
  417. float speed = 0.37f;
  418. float middleGray = 0.18f;
  419. float white = 1.1f;
  420. float treshold = 1.5f;
  421. int32_t scrollArea = 0;
  422. uint32_t oldWidth = 0;
  423. uint32_t oldHeight = 0;
  424. uint32_t oldReset = reset;
  425. entry::MouseState mouseState;
  426. float time = 0.0f;
  427. while (!entry::processEvents(width, height, debug, reset, &mouseState) )
  428. {
  429. if (oldWidth != width
  430. || oldHeight != height
  431. || oldReset != reset)
  432. {
  433. // Recreate variable size render targets when resolution changes.
  434. oldWidth = width;
  435. oldHeight = height;
  436. oldReset = reset;
  437. uint32_t msaa = (reset&BGFX_RESET_MSAA_MASK)>>BGFX_RESET_MSAA_SHIFT;
  438. bgfx::destroyFrameBuffer(fbh);
  439. bgfx::destroyFrameBuffer(bright);
  440. bgfx::destroyFrameBuffer(blur);
  441. fbtextures[0] = bgfx::createTexture2D(width, height, 1, bgfx::TextureFormat::BGRA8, ( (msaa+1)<<BGFX_TEXTURE_RT_MSAA_SHIFT) );
  442. fbtextures[1] = bgfx::createTexture2D(width, height, 1, bgfx::TextureFormat::D16, BGFX_TEXTURE_RT_BUFFER_ONLY|( (msaa+1)<<BGFX_TEXTURE_RT_MSAA_SHIFT) );
  443. fbh = bgfx::createFrameBuffer(BX_COUNTOF(fbtextures), fbtextures, true);
  444. bright = bgfx::createFrameBuffer(width/2, height/2, bgfx::TextureFormat::BGRA8);
  445. blur = bgfx::createFrameBuffer(width/8, height/8, bgfx::TextureFormat::BGRA8);
  446. }
  447. imguiBeginFrame(mouseState.m_mx
  448. , mouseState.m_my
  449. , (mouseState.m_buttons[entry::MouseButton::Left ] ? IMGUI_MBUT_LEFT : 0)
  450. | (mouseState.m_buttons[entry::MouseButton::Right ] ? IMGUI_MBUT_RIGHT : 0)
  451. , 0
  452. , width
  453. , height
  454. );
  455. imguiBeginScrollArea("Settings", width - width / 5 - 10, 10, width / 5, height / 3, &scrollArea);
  456. imguiSeparatorLine();
  457. imguiSlider("Speed", &speed, 0.0f, 1.0f, 0.01f);
  458. imguiSeparator();
  459. imguiSlider("Middle gray", &middleGray, 0.1f, 1.0f, 0.01f);
  460. imguiSlider("White point", &white, 0.1f, 2.0f, 0.01f);
  461. imguiSlider("Treshold", &treshold, 0.1f, 2.0f, 0.01f);
  462. imguiEndScrollArea();
  463. imguiEndFrame();
  464. // This dummy draw call is here to make sure that view 0 is cleared
  465. // if no other draw calls are submitted to view 0.
  466. bgfx::submit(0);
  467. int64_t now = bx::getHPCounter();
  468. static int64_t last = now;
  469. const int64_t frameTime = now - last;
  470. last = now;
  471. const double freq = double(bx::getHPFrequency() );
  472. const double toMs = 1000.0/freq;
  473. time += (float)(frameTime*speed/freq);
  474. bgfx::setUniform(u_time, &time);
  475. // Use debug font to print information about this example.
  476. bgfx::dbgTextClear();
  477. bgfx::dbgTextPrintf(0, 1, 0x4f, "bgfx/examples/09-hdr");
  478. bgfx::dbgTextPrintf(0, 2, 0x6f, "Description: Using multiple views and render targets.");
  479. bgfx::dbgTextPrintf(0, 3, 0x0f, "Frame: % 7.3f[ms]", double(frameTime)*toMs);
  480. // Set views.
  481. bgfx::setViewRectMask(0x1f, 0, 0, width, height);
  482. bgfx::setViewFrameBufferMask(0x3, fbh);
  483. bgfx::setViewRect(2, 0, 0, 128, 128);
  484. bgfx::setViewFrameBuffer(2, lum[0]);
  485. bgfx::setViewRect(3, 0, 0, 64, 64);
  486. bgfx::setViewFrameBuffer(3, lum[1]);
  487. bgfx::setViewRect(4, 0, 0, 16, 16);
  488. bgfx::setViewFrameBuffer(4, lum[2]);
  489. bgfx::setViewRect(5, 0, 0, 4, 4);
  490. bgfx::setViewFrameBuffer(5, lum[3]);
  491. bgfx::setViewRect(6, 0, 0, 1, 1);
  492. bgfx::setViewFrameBuffer(6, lum[4]);
  493. bgfx::setViewRect(7, 0, 0, width/2, height/2);
  494. bgfx::setViewFrameBuffer(7, bright);
  495. bgfx::setViewRect(8, 0, 0, width/8, height/8);
  496. bgfx::setViewFrameBuffer(8, blur);
  497. bgfx::setViewRect(9, 0, 0, width, height);
  498. float view[16];
  499. float proj[16];
  500. mtxIdentity(view);
  501. mtxOrtho(proj, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 100.0f);
  502. // Set view and projection matrix for view 0.
  503. bgfx::setViewTransformMask(0
  504. |(1<<0)
  505. |(1<<2)
  506. |(1<<3)
  507. |(1<<4)
  508. |(1<<5)
  509. |(1<<6)
  510. |(1<<7)
  511. |(1<<8)
  512. |(1<<9)
  513. , view
  514. , proj
  515. );
  516. float at[3] = { 0.0f, 1.0f, 0.0f };
  517. float eye[3] = { 0.0f, 1.0f, -2.5f };
  518. float mtx[16];
  519. mtxRotateXY(mtx
  520. , 0.0f
  521. , time
  522. );
  523. float temp[4];
  524. vec3MulMtx(temp, eye, mtx);
  525. mtxLookAt(view, temp, at);
  526. mtxProj(proj, 60.0f, float(width)/float(height), 0.1f, 100.0f);
  527. // Set view and projection matrix for view 1.
  528. bgfx::setViewTransformMask(1<<1, view, proj);
  529. bgfx::setUniform(u_mtx, mtx);
  530. // Render skybox into view 0.
  531. bgfx::setTexture(0, u_texCube, uffizi);
  532. bgfx::setProgram(skyProgram);
  533. bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE);
  534. screenSpaceQuad( (float)width, (float)height, true);
  535. bgfx::submit(0);
  536. // Render mesh into view 1
  537. bgfx::setTexture(0, u_texCube, uffizi);
  538. mesh.submit(1, meshProgram, NULL);
  539. // Calculate luminance.
  540. setOffsets2x2Lum(u_offset, 128, 128);
  541. bgfx::setTexture(0, u_texColor, fbtextures[0]);
  542. bgfx::setProgram(lumProgram);
  543. bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE);
  544. screenSpaceQuad(128.0f, 128.0f, s_flipV);
  545. bgfx::submit(2);
  546. // Downscale luminance 0.
  547. setOffsets4x4Lum(u_offset, 128, 128);
  548. bgfx::setTexture(0, u_texColor, lum[0]);
  549. bgfx::setProgram(lumAvgProgram);
  550. bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE);
  551. screenSpaceQuad(64.0f, 64.0f, s_flipV);
  552. bgfx::submit(3);
  553. // Downscale luminance 1.
  554. setOffsets4x4Lum(u_offset, 64, 64);
  555. bgfx::setTexture(0, u_texColor, lum[1]);
  556. bgfx::setProgram(lumAvgProgram);
  557. bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE);
  558. screenSpaceQuad(16.0f, 16.0f, s_flipV);
  559. bgfx::submit(4);
  560. // Downscale luminance 2.
  561. setOffsets4x4Lum(u_offset, 16, 16);
  562. bgfx::setTexture(0, u_texColor, lum[2]);
  563. bgfx::setProgram(lumAvgProgram);
  564. bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE);
  565. screenSpaceQuad(4.0f, 4.0f, s_flipV);
  566. bgfx::submit(5);
  567. // Downscale luminance 3.
  568. setOffsets4x4Lum(u_offset, 4, 4);
  569. bgfx::setTexture(0, u_texColor, lum[3]);
  570. bgfx::setProgram(lumAvgProgram);
  571. bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE);
  572. screenSpaceQuad(1.0f, 1.0f, s_flipV);
  573. bgfx::submit(6);
  574. float tonemap[4] = { middleGray, square(white), treshold, 0.0f };
  575. bgfx::setUniform(u_tonemap, tonemap);
  576. // Bright pass treshold is tonemap[3].
  577. setOffsets4x4Lum(u_offset, width/2, height/2);
  578. bgfx::setTexture(0, u_texColor, fbtextures[0]);
  579. bgfx::setTexture(1, u_texLum, lum[4]);
  580. bgfx::setProgram(brightProgram);
  581. bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE);
  582. screenSpaceQuad( (float)width/2.0f, (float)height/2.0f, s_flipV);
  583. bgfx::submit(7);
  584. // Blur bright pass vertically.
  585. bgfx::setTexture(0, u_texColor, bright);
  586. bgfx::setProgram(blurProgram);
  587. bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE);
  588. screenSpaceQuad( (float)width/8.0f, (float)height/8.0f, s_flipV);
  589. bgfx::submit(8);
  590. // Blur bright pass horizontally, do tonemaping and combine.
  591. bgfx::setTexture(0, u_texColor, fbtextures[0]);
  592. bgfx::setTexture(1, u_texLum, lum[4]);
  593. bgfx::setTexture(2, u_texBlur, blur);
  594. bgfx::setProgram(tonemapProgram);
  595. bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE);
  596. screenSpaceQuad( (float)width, (float)height, s_flipV);
  597. bgfx::submit(9);
  598. // Advance to next frame. Rendering thread will be kicked to
  599. // process submitted rendering primitives.
  600. bgfx::frame();
  601. }
  602. imguiDestroy();
  603. // Cleanup.
  604. mesh.unload();
  605. for (uint32_t ii = 0; ii < BX_COUNTOF(lum); ++ii)
  606. {
  607. bgfx::destroyFrameBuffer(lum[ii]);
  608. }
  609. bgfx::destroyFrameBuffer(bright);
  610. bgfx::destroyFrameBuffer(blur);
  611. bgfx::destroyFrameBuffer(fbh);
  612. bgfx::destroyProgram(meshProgram);
  613. bgfx::destroyProgram(skyProgram);
  614. bgfx::destroyProgram(tonemapProgram);
  615. bgfx::destroyProgram(lumProgram);
  616. bgfx::destroyProgram(lumAvgProgram);
  617. bgfx::destroyProgram(blurProgram);
  618. bgfx::destroyProgram(brightProgram);
  619. bgfx::destroyTexture(uffizi);
  620. bgfx::destroyUniform(u_time);
  621. bgfx::destroyUniform(u_texCube);
  622. bgfx::destroyUniform(u_texColor);
  623. bgfx::destroyUniform(u_texLum);
  624. bgfx::destroyUniform(u_texBlur);
  625. bgfx::destroyUniform(u_mtx);
  626. bgfx::destroyUniform(u_tonemap);
  627. bgfx::destroyUniform(u_offset);
  628. bgfx::destroyUniform(u_weight);
  629. // Shutdown bgfx.
  630. bgfx::shutdown();
  631. return 0;
  632. }