ibl.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547
  1. /*
  2. * Copyright 2014 Dario Manesku. 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_utils.h"
  9. #include "imgui/imgui.h"
  10. #include "nanovg/nanovg.h"
  11. #include <bx/readerwriter.h>
  12. #include <bx/string.h>
  13. static float s_texelHalf = 0.0f;
  14. struct Uniforms
  15. {
  16. void init()
  17. {
  18. m_time = 0.0f;
  19. bx::mtxIdentity(m_mtx);
  20. u_time = bgfx::createUniform("u_time", bgfx::UniformType::Uniform1f);
  21. u_mtx = bgfx::createUniform("u_mtx", bgfx::UniformType::Uniform4x4fv);
  22. u_params = bgfx::createUniform("u_params", bgfx::UniformType::Uniform4fv);
  23. u_flags = bgfx::createUniform("u_flags", bgfx::UniformType::Uniform4fv);
  24. u_camPos = bgfx::createUniform("u_camPos", bgfx::UniformType::Uniform3fv);
  25. u_rgbDiff = bgfx::createUniform("u_rgbDiff", bgfx::UniformType::Uniform3fv);
  26. u_rgbSpec = bgfx::createUniform("u_rgbSpec", bgfx::UniformType::Uniform3fv);
  27. }
  28. // Call this once per frame.
  29. void submitPerFrameUniforms()
  30. {
  31. bgfx::setUniform(u_time, &m_time);
  32. bgfx::setUniform(u_mtx, m_mtx);
  33. bgfx::setUniform(u_flags, m_flags);
  34. bgfx::setUniform(u_camPos, m_camPos);
  35. bgfx::setUniform(u_rgbDiff, m_rgbDiff);
  36. bgfx::setUniform(u_rgbSpec, m_rgbSpec);
  37. }
  38. // Call this before each draw call.
  39. void submitPerDrawUniforms()
  40. {
  41. bgfx::setUniform(u_params, m_params);
  42. }
  43. void destroy()
  44. {
  45. bgfx::destroyUniform(u_rgbSpec);
  46. bgfx::destroyUniform(u_rgbDiff);
  47. bgfx::destroyUniform(u_camPos);
  48. bgfx::destroyUniform(u_flags);
  49. bgfx::destroyUniform(u_params);
  50. bgfx::destroyUniform(u_mtx);
  51. bgfx::destroyUniform(u_time);
  52. }
  53. union
  54. {
  55. struct
  56. {
  57. float m_glossiness;
  58. float m_exposure;
  59. float m_diffspec;
  60. float m_unused0;
  61. };
  62. float m_params[4];
  63. };
  64. union
  65. {
  66. struct
  67. {
  68. float m_diffuse;
  69. float m_specular;
  70. float m_diffuseIbl;
  71. float m_specularIbl;
  72. };
  73. float m_flags[4];
  74. };
  75. float m_time;
  76. float m_mtx[16];
  77. float m_camPos[3];
  78. float m_rgbDiff[3];
  79. float m_rgbSpec[3];
  80. bgfx::UniformHandle u_time;
  81. bgfx::UniformHandle u_mtx;
  82. bgfx::UniformHandle u_params;
  83. bgfx::UniformHandle u_flags;
  84. bgfx::UniformHandle u_camPos;
  85. bgfx::UniformHandle u_rgbDiff;
  86. bgfx::UniformHandle u_rgbSpec;
  87. };
  88. static Uniforms s_uniforms;
  89. struct PosColorTexCoord0Vertex
  90. {
  91. float m_x;
  92. float m_y;
  93. float m_z;
  94. uint32_t m_rgba;
  95. float m_u;
  96. float m_v;
  97. static void init()
  98. {
  99. ms_decl
  100. .begin()
  101. .add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float)
  102. .add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true)
  103. .add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Float)
  104. .end();
  105. }
  106. static bgfx::VertexDecl ms_decl;
  107. };
  108. bgfx::VertexDecl PosColorTexCoord0Vertex::ms_decl;
  109. void screenSpaceQuad(float _textureWidth, float _textureHeight, bool _originBottomLeft = false, float _width = 1.0f, float _height = 1.0f)
  110. {
  111. if (bgfx::checkAvailTransientVertexBuffer(3, PosColorTexCoord0Vertex::ms_decl) )
  112. {
  113. bgfx::TransientVertexBuffer vb;
  114. bgfx::allocTransientVertexBuffer(&vb, 3, PosColorTexCoord0Vertex::ms_decl);
  115. PosColorTexCoord0Vertex* vertex = (PosColorTexCoord0Vertex*)vb.data;
  116. const float zz = 0.0f;
  117. const float minx = -_width;
  118. const float maxx = _width;
  119. const float miny = 0.0f;
  120. const float maxy = _height*2.0f;
  121. const float texelHalfW = s_texelHalf/_textureWidth;
  122. const float texelHalfH = s_texelHalf/_textureHeight;
  123. const float minu = -1.0f + texelHalfW;
  124. const float maxu = 1.0f + texelHalfW;
  125. float minv = texelHalfH;
  126. float maxv = 2.0f + texelHalfH;
  127. if (_originBottomLeft)
  128. {
  129. std::swap(minv, maxv);
  130. minv -= 1.0f;
  131. maxv -= 1.0f;
  132. }
  133. vertex[0].m_x = minx;
  134. vertex[0].m_y = miny;
  135. vertex[0].m_z = zz;
  136. vertex[0].m_rgba = 0xffffffff;
  137. vertex[0].m_u = minu;
  138. vertex[0].m_v = minv;
  139. vertex[1].m_x = maxx;
  140. vertex[1].m_y = miny;
  141. vertex[1].m_z = zz;
  142. vertex[1].m_rgba = 0xffffffff;
  143. vertex[1].m_u = maxu;
  144. vertex[1].m_v = minv;
  145. vertex[2].m_x = maxx;
  146. vertex[2].m_y = maxy;
  147. vertex[2].m_z = zz;
  148. vertex[2].m_rgba = 0xffffffff;
  149. vertex[2].m_u = maxu;
  150. vertex[2].m_v = maxv;
  151. bgfx::setVertexBuffer(&vb);
  152. }
  153. }
  154. struct LightProbe
  155. {
  156. enum Enum
  157. {
  158. Wells,
  159. Uffizi,
  160. Pisa,
  161. Ennis,
  162. Grace,
  163. Count
  164. };
  165. void load(const char* _name)
  166. {
  167. char filePath[512];
  168. strcpy(filePath, _name);
  169. strcat(filePath, "_lod.dds");
  170. m_tex = loadTexture(filePath, BGFX_TEXTURE_U_CLAMP|BGFX_TEXTURE_V_CLAMP|BGFX_TEXTURE_W_CLAMP);
  171. strcpy(filePath, _name);
  172. strcat(filePath, "_irr.dds");
  173. m_texIrr = loadTexture(filePath, BGFX_TEXTURE_U_CLAMP|BGFX_TEXTURE_V_CLAMP|BGFX_TEXTURE_W_CLAMP);
  174. }
  175. void destroy()
  176. {
  177. bgfx::destroyTexture(m_tex);
  178. bgfx::destroyTexture(m_texIrr);
  179. }
  180. bgfx::TextureHandle m_tex;
  181. bgfx::TextureHandle m_texIrr;
  182. };
  183. int _main_(int /*_argc*/, char** /*_argv*/)
  184. {
  185. uint32_t width = 1280;
  186. uint32_t height = 720;
  187. uint32_t debug = BGFX_DEBUG_TEXT;
  188. uint32_t reset = BGFX_RESET_VSYNC;
  189. bgfx::init();
  190. bgfx::reset(width, height, reset);
  191. // Enable debug text.
  192. bgfx::setDebug(debug);
  193. // Set views clear state.
  194. bgfx::setViewClear(0
  195. , BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH
  196. , 0x303030ff
  197. , 1.0f
  198. , 0
  199. );
  200. // Imgui.
  201. imguiCreate();
  202. // Uniforms.
  203. s_uniforms.init();
  204. // Vertex declarations.
  205. PosColorTexCoord0Vertex::init();
  206. LightProbe lightProbes[LightProbe::Count];
  207. lightProbes[LightProbe::Wells ].load("wells");
  208. lightProbes[LightProbe::Uffizi].load("uffizi");
  209. lightProbes[LightProbe::Pisa ].load("pisa");
  210. lightProbes[LightProbe::Ennis ].load("ennis");
  211. lightProbes[LightProbe::Grace ].load("grace");
  212. LightProbe::Enum currentLightProbe = LightProbe::Wells;
  213. bgfx::UniformHandle u_time = bgfx::createUniform("u_time", bgfx::UniformType::Uniform1f);
  214. bgfx::UniformHandle u_mtx = bgfx::createUniform("u_mtx", bgfx::UniformType::Uniform4x4fv);
  215. bgfx::UniformHandle u_params = bgfx::createUniform("u_params", bgfx::UniformType::Uniform4fv);
  216. bgfx::UniformHandle u_flags = bgfx::createUniform("u_flags", bgfx::UniformType::Uniform4fv);
  217. bgfx::UniformHandle u_camPos = bgfx::createUniform("u_camPos", bgfx::UniformType::Uniform3fv);
  218. bgfx::UniformHandle u_texCube = bgfx::createUniform("u_texCube", bgfx::UniformType::Uniform1i);
  219. bgfx::UniformHandle u_texCubeIrr = bgfx::createUniform("u_texCubeIrr", bgfx::UniformType::Uniform1i);
  220. bgfx::ProgramHandle programMesh = loadProgram("vs_ibl_mesh", "fs_ibl_mesh");
  221. bgfx::ProgramHandle programSky = loadProgram("vs_ibl_skybox", "fs_ibl_skybox");
  222. Mesh* meshBunny;
  223. meshBunny = meshLoad("meshes/bunny.bin");
  224. struct Settings
  225. {
  226. float m_speed;
  227. float m_glossiness;
  228. float m_exposure;
  229. float m_diffspec;
  230. float m_rgbDiff[3];
  231. float m_rgbSpec[3];
  232. bool m_diffuse;
  233. bool m_specular;
  234. bool m_diffuseIbl;
  235. bool m_specularIbl;
  236. bool m_showDiffColorWheel;
  237. bool m_showSpecColorWheel;
  238. ImguiCubemap::Enum m_crossCubemapPreview;
  239. };
  240. Settings settings;
  241. settings.m_speed = 0.37f;
  242. settings.m_glossiness = 1.0f;
  243. settings.m_exposure = 0.0f;
  244. settings.m_diffspec = 0.65f;
  245. settings.m_rgbDiff[0] = 0.2f;
  246. settings.m_rgbDiff[1] = 0.2f;
  247. settings.m_rgbDiff[2] = 0.2f;
  248. settings.m_rgbSpec[0] = 1.0f;
  249. settings.m_rgbSpec[1] = 1.0f;
  250. settings.m_rgbSpec[2] = 1.0f;
  251. settings.m_diffuse = true;
  252. settings.m_specular = true;
  253. settings.m_diffuseIbl = true;
  254. settings.m_specularIbl = true;
  255. settings.m_showDiffColorWheel = true;
  256. settings.m_showSpecColorWheel = false;
  257. settings.m_crossCubemapPreview = ImguiCubemap::Cross;
  258. float time = 0.0f;
  259. int32_t leftScrollArea = 0;
  260. entry::MouseState mouseState;
  261. while (!entry::processEvents(width, height, debug, reset, &mouseState) )
  262. {
  263. imguiBeginFrame(mouseState.m_mx
  264. , mouseState.m_my
  265. , (mouseState.m_buttons[entry::MouseButton::Left ] ? IMGUI_MBUT_LEFT : 0)
  266. | (mouseState.m_buttons[entry::MouseButton::Right ] ? IMGUI_MBUT_RIGHT : 0)
  267. , 0
  268. , width
  269. , height
  270. );
  271. static int32_t rightScrollArea = 0;
  272. imguiBeginScrollArea("Settings", width - 256 - 10, 10, 256, 540, &rightScrollArea);
  273. imguiLabel("Shade:");
  274. imguiSeparator();
  275. imguiBool("Diffuse", settings.m_diffuse);
  276. imguiBool("Specular", settings.m_specular);
  277. imguiBool("IBL Diffuse", settings.m_diffuseIbl);
  278. imguiBool("IBL Specular", settings.m_specularIbl);
  279. imguiSeparatorLine();
  280. imguiSlider("Speed", settings.m_speed, 0.0f, 1.0f, 0.01f);
  281. imguiSeparatorLine();
  282. imguiSeparator();
  283. imguiSlider("Exposure", settings.m_exposure, -8.0f, 8.0f, 0.01f);
  284. imguiSeparator();
  285. imguiLabel("Environment:");
  286. currentLightProbe = LightProbe::Enum(imguiChoose(currentLightProbe
  287. , "Wells"
  288. , "Uffizi"
  289. , "Pisa"
  290. , "Ennis"
  291. , "Grace"
  292. ) );
  293. static float lod = 0.0f;
  294. if (imguiCube(lightProbes[currentLightProbe].m_tex, lod, settings.m_crossCubemapPreview, true) )
  295. {
  296. settings.m_crossCubemapPreview = ImguiCubemap::Enum( (settings.m_crossCubemapPreview+1) % ImguiCubemap::Count);
  297. }
  298. imguiSlider("Texture LOD", lod, float(0.0f), 10.1f, 0.1f);
  299. imguiEndScrollArea();
  300. imguiBeginScrollArea("Settings", 10, 70, 256, 576, &leftScrollArea);
  301. imguiLabel("Material properties:");
  302. imguiSeparator();
  303. imguiSlider("Diffuse - Specular", settings.m_diffspec, 0.0f, 1.0f, 0.01f);
  304. imguiSlider("Glossiness" , settings.m_glossiness, 0.0f, 1.0f, 0.01f);
  305. imguiSeparator();
  306. imguiColorWheel("Diffuse color:", &settings.m_rgbDiff[0], settings.m_showDiffColorWheel);
  307. imguiSeparator();
  308. imguiColorWheel("Specular color:", &settings.m_rgbSpec[0], settings.m_showSpecColorWheel);
  309. imguiSeparator();
  310. imguiLabel("Predefined materials:");
  311. imguiSeparator();
  312. if (imguiButton("Gold") )
  313. {
  314. settings.m_glossiness = 0.8f;
  315. settings.m_diffspec = 1.0f;
  316. settings.m_rgbDiff[0] = 0.0f;
  317. settings.m_rgbDiff[1] = 0.0f;
  318. settings.m_rgbDiff[2] = 0.0f;
  319. settings.m_rgbSpec[0] = 1.0f;
  320. settings.m_rgbSpec[1] = 0.86f;
  321. settings.m_rgbSpec[2] = 0.58f;
  322. }
  323. if (imguiButton("Copper") )
  324. {
  325. settings.m_glossiness = 0.67f;
  326. settings.m_diffspec = 1.0f;
  327. settings.m_rgbDiff[0] = 0.0f;
  328. settings.m_rgbDiff[1] = 0.0f;
  329. settings.m_rgbDiff[2] = 0.0f;
  330. settings.m_rgbSpec[0] = 0.98f;
  331. settings.m_rgbSpec[1] = 0.82f;
  332. settings.m_rgbSpec[2] = 0.76f;
  333. }
  334. if (imguiButton("Titanium") )
  335. {
  336. settings.m_glossiness = 0.57f;
  337. settings.m_diffspec = 1.0f;
  338. settings.m_rgbDiff[0] = 0.0f;
  339. settings.m_rgbDiff[1] = 0.0f;
  340. settings.m_rgbDiff[2] = 0.0f;
  341. settings.m_rgbSpec[0] = 0.76f;
  342. settings.m_rgbSpec[1] = 0.73f;
  343. settings.m_rgbSpec[2] = 0.71f;
  344. }
  345. if (imguiButton("Steel") )
  346. {
  347. settings.m_glossiness = 0.82f;
  348. settings.m_diffspec = 1.0f;
  349. settings.m_rgbDiff[0] = 0.0f;
  350. settings.m_rgbDiff[1] = 0.0f;
  351. settings.m_rgbDiff[2] = 0.0f;
  352. settings.m_rgbSpec[0] = 0.77f;
  353. settings.m_rgbSpec[1] = 0.78f;
  354. settings.m_rgbSpec[2] = 0.77f;
  355. }
  356. imguiEndScrollArea();
  357. imguiEndFrame();
  358. s_uniforms.m_glossiness = settings.m_glossiness;
  359. s_uniforms.m_exposure = settings.m_exposure;
  360. s_uniforms.m_diffspec = settings.m_diffspec;
  361. s_uniforms.m_flags[0] = float(settings.m_diffuse);
  362. s_uniforms.m_flags[1] = float(settings.m_specular);
  363. s_uniforms.m_flags[2] = float(settings.m_diffuseIbl);
  364. s_uniforms.m_flags[3] = float(settings.m_specularIbl);
  365. memcpy(s_uniforms.m_rgbDiff, settings.m_rgbDiff, 3*sizeof(float));
  366. memcpy(s_uniforms.m_rgbSpec, settings.m_rgbSpec, 3*sizeof(float));
  367. s_uniforms.submitPerFrameUniforms();
  368. int64_t now = bx::getHPCounter();
  369. static int64_t last = now;
  370. const int64_t frameTime = now - last;
  371. last = now;
  372. const double freq = double(bx::getHPFrequency() );
  373. const double toMs = 1000.0/freq;
  374. time += (float)(frameTime*settings.m_speed/freq);
  375. s_uniforms.m_time = time;
  376. // Use debug font to print information about this example.
  377. bgfx::dbgTextClear();
  378. bgfx::dbgTextPrintf(0, 1, 0x4f, "bgfx/examples/18-ibl");
  379. bgfx::dbgTextPrintf(0, 2, 0x6f, "Description: Image based lightning.");
  380. bgfx::dbgTextPrintf(0, 3, 0x0f, "Frame: % 7.3f[ms]", double(frameTime)*toMs);
  381. float at[3] = { 0.0f, 0.0f, 0.0f };
  382. float eye[3] = { 0.0f, 0.0f, -3.0f };
  383. bx::mtxRotateXY(s_uniforms.m_mtx
  384. , 0.0f
  385. , time
  386. );
  387. float view[16];
  388. float proj[16];
  389. bx::mtxIdentity(view);
  390. bx::mtxOrtho(proj, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 100.0f);
  391. bgfx::setViewTransform(0, view, proj);
  392. bx::mtxLookAt(view, eye, at);
  393. memcpy(s_uniforms.m_camPos, eye, 3*sizeof(float));
  394. bx::mtxProj(proj, 60.0f, float(width)/float(height), 0.1f, 100.0f);
  395. bgfx::setViewTransform(1, view, proj);
  396. bgfx::setViewRect(0, 0, 0, width, height);
  397. bgfx::setViewRect(1, 0, 0, width, height);
  398. // View 0.
  399. bgfx::setTexture(4, u_texCube, lightProbes[currentLightProbe].m_tex);
  400. bgfx::setProgram(programSky);
  401. bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE);
  402. screenSpaceQuad( (float)width, (float)height, true);
  403. s_uniforms.submitPerDrawUniforms();
  404. bgfx::submit(0);
  405. // View 1.
  406. float mtx[16];
  407. bx::mtxSRT(mtx
  408. , 1.0f
  409. , 1.0f
  410. , 1.0f
  411. , 0.0f
  412. , bx::pi+time
  413. , 0.0f
  414. , 0.0f
  415. , -1.0f
  416. , 0.0f
  417. );
  418. bgfx::setTexture(4, u_texCube, lightProbes[currentLightProbe].m_tex);
  419. bgfx::setTexture(5, u_texCubeIrr, lightProbes[currentLightProbe].m_texIrr);
  420. meshSubmit(meshBunny, 1, programMesh, mtx);
  421. // Advance to next frame. Rendering thread will be kicked to
  422. // process submitted rendering primitives.
  423. bgfx::frame();
  424. }
  425. meshUnload(meshBunny);
  426. // Cleanup.
  427. bgfx::destroyProgram(programMesh);
  428. bgfx::destroyProgram(programSky);
  429. bgfx::destroyUniform(u_camPos);
  430. bgfx::destroyUniform(u_flags);
  431. bgfx::destroyUniform(u_params);
  432. bgfx::destroyUniform(u_mtx);
  433. bgfx::destroyUniform(u_time);
  434. bgfx::destroyUniform(u_texCube);
  435. bgfx::destroyUniform(u_texCubeIrr);
  436. for (uint8_t ii = 0; ii < LightProbe::Count; ++ii)
  437. {
  438. lightProbes[ii].destroy();
  439. }
  440. s_uniforms.destroy();
  441. imguiDestroy();
  442. // Shutdown bgfx.
  443. bgfx::shutdown();
  444. return 0;
  445. }