hdr.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768
  1. /*
  2. * Copyright 2011-2013 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::RenderTargetHandle rt = bgfx::createRenderTarget(width, height, BGFX_RENDER_TARGET_COLOR_RGBA8|BGFX_RENDER_TARGET_DEPTH);
  393. bgfx::RenderTargetHandle lum[5];
  394. lum[0] = bgfx::createRenderTarget(128, 128, BGFX_RENDER_TARGET_COLOR_RGBA8);
  395. lum[1] = bgfx::createRenderTarget( 64, 64, BGFX_RENDER_TARGET_COLOR_RGBA8);
  396. lum[2] = bgfx::createRenderTarget( 16, 16, BGFX_RENDER_TARGET_COLOR_RGBA8);
  397. lum[3] = bgfx::createRenderTarget( 4, 4, BGFX_RENDER_TARGET_COLOR_RGBA8);
  398. lum[4] = bgfx::createRenderTarget( 1, 1, BGFX_RENDER_TARGET_COLOR_RGBA8);
  399. bgfx::RenderTargetHandle bright;
  400. bright = bgfx::createRenderTarget(width/2, height/2, BGFX_RENDER_TARGET_COLOR_RGBA8);
  401. bgfx::RenderTargetHandle blur;
  402. blur = bgfx::createRenderTarget(width/8, height/8, BGFX_RENDER_TARGET_COLOR_RGBA8);
  403. FILE* file = fopen("font/droidsans.ttf", "rb");
  404. uint32_t size = (uint32_t)fsize(file);
  405. void* data = malloc(size);
  406. size_t ignore = fread(data, 1, size, file);
  407. BX_UNUSED(ignore);
  408. fclose(file);
  409. imguiCreate(data, size);
  410. free(data);
  411. float speed = 0.37f;
  412. float middleGray = 0.18f;
  413. float white = 1.1f;
  414. float treshold = 1.5f;
  415. int32_t scrollArea = 0;
  416. uint32_t oldWidth = 0;
  417. uint32_t oldHeight = 0;
  418. entry::MouseState mouseState;
  419. float time = 0.0f;
  420. while (!entry::processEvents(width, height, debug, reset, &mouseState) )
  421. {
  422. if (oldWidth != width
  423. || oldHeight != height)
  424. {
  425. // Recreate variable size render targets when resolution changes.
  426. oldWidth = width;
  427. oldHeight = height;
  428. bgfx::destroyRenderTarget(rt);
  429. bgfx::destroyRenderTarget(bright);
  430. bgfx::destroyRenderTarget(blur);
  431. rt = bgfx::createRenderTarget(width, height, BGFX_RENDER_TARGET_COLOR_RGBA8|BGFX_RENDER_TARGET_DEPTH);
  432. bright = bgfx::createRenderTarget(width/2, height/2, BGFX_RENDER_TARGET_COLOR_RGBA8);
  433. blur = bgfx::createRenderTarget(width/8, height/8, BGFX_RENDER_TARGET_COLOR_RGBA8);
  434. }
  435. imguiBeginFrame(mouseState.m_mx
  436. , mouseState.m_my
  437. , (mouseState.m_buttons[entry::MouseButton::Left ] ? IMGUI_MBUT_LEFT : 0)
  438. | (mouseState.m_buttons[entry::MouseButton::Right ] ? IMGUI_MBUT_RIGHT : 0)
  439. , 0
  440. , width
  441. , height
  442. );
  443. imguiBeginScrollArea("Settings", width - width / 5 - 10, 10, width / 5, height / 3, &scrollArea);
  444. imguiSeparatorLine();
  445. imguiSlider("Speed", &speed, 0.0f, 1.0f, 0.01f);
  446. imguiSeparator();
  447. imguiSlider("Middle gray", &middleGray, 0.1f, 1.0f, 0.01f);
  448. imguiSlider("White point", &white, 0.1f, 2.0f, 0.01f);
  449. imguiSlider("Treshold", &treshold, 0.1f, 2.0f, 0.01f);
  450. imguiEndScrollArea();
  451. imguiEndFrame();
  452. // This dummy draw call is here to make sure that view 0 is cleared
  453. // if no other draw calls are submitted to view 0.
  454. bgfx::submit(0);
  455. int64_t now = bx::getHPCounter();
  456. static int64_t last = now;
  457. const int64_t frameTime = now - last;
  458. last = now;
  459. const double freq = double(bx::getHPFrequency() );
  460. const double toMs = 1000.0/freq;
  461. time += (float)(frameTime*speed/freq);
  462. bgfx::setUniform(u_time, &time);
  463. // Use debug font to print information about this example.
  464. bgfx::dbgTextClear();
  465. bgfx::dbgTextPrintf(0, 1, 0x4f, "bgfx/examples/09-hdr");
  466. bgfx::dbgTextPrintf(0, 2, 0x6f, "Description: Using multiple views and render targets.");
  467. bgfx::dbgTextPrintf(0, 3, 0x0f, "Frame: % 7.3f[ms]", double(frameTime)*toMs);
  468. // Set views.
  469. bgfx::setViewRectMask(0x1f, 0, 0, width, height);
  470. bgfx::setViewRenderTargetMask(0x3, rt);
  471. bgfx::setViewRect(2, 0, 0, 128, 128);
  472. bgfx::setViewRenderTarget(2, lum[0]);
  473. bgfx::setViewRect(3, 0, 0, 64, 64);
  474. bgfx::setViewRenderTarget(3, lum[1]);
  475. bgfx::setViewRect(4, 0, 0, 16, 16);
  476. bgfx::setViewRenderTarget(4, lum[2]);
  477. bgfx::setViewRect(5, 0, 0, 4, 4);
  478. bgfx::setViewRenderTarget(5, lum[3]);
  479. bgfx::setViewRect(6, 0, 0, 1, 1);
  480. bgfx::setViewRenderTarget(6, lum[4]);
  481. bgfx::setViewRect(7, 0, 0, width/2, height/2);
  482. bgfx::setViewRenderTarget(7, bright);
  483. bgfx::setViewRect(8, 0, 0, width/8, height/8);
  484. bgfx::setViewRenderTarget(8, blur);
  485. bgfx::setViewRect(9, 0, 0, width, height);
  486. float view[16];
  487. float proj[16];
  488. mtxIdentity(view);
  489. mtxOrtho(proj, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 100.0f);
  490. // Set view and projection matrix for view 0.
  491. bgfx::setViewTransformMask(0
  492. |(1<<0)
  493. |(1<<2)
  494. |(1<<3)
  495. |(1<<4)
  496. |(1<<5)
  497. |(1<<6)
  498. |(1<<7)
  499. |(1<<8)
  500. |(1<<9)
  501. , view
  502. , proj
  503. );
  504. float at[3] = { 0.0f, 1.0f, 0.0f };
  505. float eye[3] = { 0.0f, 1.0f, -2.5f };
  506. float mtx[16];
  507. mtxRotateXY(mtx
  508. , 0.0f
  509. , time
  510. );
  511. float temp[4];
  512. vec3MulMtx(temp, eye, mtx);
  513. mtxLookAt(view, temp, at);
  514. mtxProj(proj, 60.0f, float(width)/float(height), 0.1f, 100.0f);
  515. // Set view and projection matrix for view 1.
  516. bgfx::setViewTransformMask(1<<1, view, proj);
  517. bgfx::setUniform(u_mtx, mtx);
  518. // Render skybox into view 0.
  519. bgfx::setTexture(0, u_texCube, uffizi);
  520. bgfx::setProgram(skyProgram);
  521. bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE);
  522. screenSpaceQuad( (float)width, (float)height, true);
  523. bgfx::submit(0);
  524. // Render mesh into view 1
  525. bgfx::setTexture(0, u_texCube, uffizi);
  526. mesh.submit(1, meshProgram, NULL);
  527. // Calculate luminance.
  528. setOffsets2x2Lum(u_offset, 128, 128);
  529. bgfx::setTexture(0, u_texColor, rt);
  530. bgfx::setProgram(lumProgram);
  531. bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE);
  532. screenSpaceQuad(128.0f, 128.0f, s_flipV);
  533. bgfx::submit(2);
  534. // Downscale luminance 0.
  535. setOffsets4x4Lum(u_offset, 128, 128);
  536. bgfx::setTexture(0, u_texColor, lum[0]);
  537. bgfx::setProgram(lumAvgProgram);
  538. bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE);
  539. screenSpaceQuad(64.0f, 64.0f, s_flipV);
  540. bgfx::submit(3);
  541. // Downscale luminance 1.
  542. setOffsets4x4Lum(u_offset, 64, 64);
  543. bgfx::setTexture(0, u_texColor, lum[1]);
  544. bgfx::setProgram(lumAvgProgram);
  545. bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE);
  546. screenSpaceQuad(16.0f, 16.0f, s_flipV);
  547. bgfx::submit(4);
  548. // Downscale luminance 2.
  549. setOffsets4x4Lum(u_offset, 16, 16);
  550. bgfx::setTexture(0, u_texColor, lum[2]);
  551. bgfx::setProgram(lumAvgProgram);
  552. bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE);
  553. screenSpaceQuad(4.0f, 4.0f, s_flipV);
  554. bgfx::submit(5);
  555. // Downscale luminance 3.
  556. setOffsets4x4Lum(u_offset, 4, 4);
  557. bgfx::setTexture(0, u_texColor, lum[3]);
  558. bgfx::setProgram(lumAvgProgram);
  559. bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE);
  560. screenSpaceQuad(1.0f, 1.0f, s_flipV);
  561. bgfx::submit(6);
  562. float tonemap[4] = { middleGray, square(white), treshold, 0.0f };
  563. bgfx::setUniform(u_tonemap, tonemap);
  564. // Bright pass treshold is tonemap[3].
  565. setOffsets4x4Lum(u_offset, width/2, height/2);
  566. bgfx::setTexture(0, u_texColor, rt);
  567. bgfx::setTexture(1, u_texLum, lum[4]);
  568. bgfx::setProgram(brightProgram);
  569. bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE);
  570. screenSpaceQuad( (float)width/2.0f, (float)height/2.0f, s_flipV);
  571. bgfx::submit(7);
  572. // Blur bright pass vertically.
  573. bgfx::setTexture(0, u_texColor, bright);
  574. bgfx::setProgram(blurProgram);
  575. bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE);
  576. screenSpaceQuad( (float)width/8.0f, (float)height/8.0f, s_flipV);
  577. bgfx::submit(8);
  578. // Blur bright pass horizontally, do tonemaping and combine.
  579. bgfx::setTexture(0, u_texColor, rt);
  580. bgfx::setTexture(1, u_texLum, lum[4]);
  581. bgfx::setTexture(2, u_texBlur, blur);
  582. bgfx::setProgram(tonemapProgram);
  583. bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE);
  584. screenSpaceQuad( (float)width, (float)height, s_flipV);
  585. bgfx::submit(9);
  586. // Advance to next frame. Rendering thread will be kicked to
  587. // process submitted rendering primitives.
  588. bgfx::frame();
  589. }
  590. imguiDestroy();
  591. // Cleanup.
  592. mesh.unload();
  593. bgfx::destroyRenderTarget(lum[0]);
  594. bgfx::destroyRenderTarget(lum[1]);
  595. bgfx::destroyRenderTarget(lum[2]);
  596. bgfx::destroyRenderTarget(lum[3]);
  597. bgfx::destroyRenderTarget(lum[4]);
  598. bgfx::destroyRenderTarget(bright);
  599. bgfx::destroyRenderTarget(blur);
  600. bgfx::destroyRenderTarget(rt);
  601. bgfx::destroyProgram(meshProgram);
  602. bgfx::destroyProgram(skyProgram);
  603. bgfx::destroyProgram(tonemapProgram);
  604. bgfx::destroyProgram(lumProgram);
  605. bgfx::destroyProgram(lumAvgProgram);
  606. bgfx::destroyProgram(blurProgram);
  607. bgfx::destroyProgram(brightProgram);
  608. bgfx::destroyTexture(uffizi);
  609. bgfx::destroyUniform(u_time);
  610. bgfx::destroyUniform(u_texCube);
  611. bgfx::destroyUniform(u_texColor);
  612. bgfx::destroyUniform(u_texLum);
  613. bgfx::destroyUniform(u_texBlur);
  614. bgfx::destroyUniform(u_mtx);
  615. bgfx::destroyUniform(u_tonemap);
  616. bgfx::destroyUniform(u_offset);
  617. bgfx::destroyUniform(u_weight);
  618. // Shutdown bgfx.
  619. bgfx::shutdown();
  620. return 0;
  621. }