hdr.cpp 18 KB

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