stencil.cpp 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473
  1. /*
  2. * Copyright 2013-2014 Dario Manesku. All rights reserved.
  3. * License: http://www.opensource.org/licenses/BSD-2-Clause
  4. */
  5. #include <string>
  6. #include <vector>
  7. #include "common.h"
  8. #include <bgfx.h>
  9. #include <bx/timer.h>
  10. #include <bx/readerwriter.h>
  11. #include <bx/fpumath.h>
  12. #include "entry/entry.h"
  13. #include "camera.h"
  14. #include "imgui/imgui.h"
  15. #define RENDER_VIEWID_RANGE1_PASS_0 1
  16. #define RENDER_VIEWID_RANGE1_PASS_1 2
  17. #define RENDER_VIEWID_RANGE1_PASS_2 3
  18. #define RENDER_VIEWID_RANGE1_PASS_3 4
  19. #define RENDER_VIEWID_RANGE1_PASS_4 5
  20. #define RENDER_VIEWID_RANGE1_PASS_5 6
  21. #define RENDER_VIEWID_RANGE5_PASS_6 7
  22. #define RENDER_VIEWID_RANGE1_PASS_7 13
  23. #define MAX_NUM_LIGHTS 5
  24. uint32_t packUint32(uint8_t _x, uint8_t _y, uint8_t _z, uint8_t _w)
  25. {
  26. union
  27. {
  28. uint32_t ui32;
  29. uint8_t arr[4];
  30. } un;
  31. un.arr[0] = _x;
  32. un.arr[1] = _y;
  33. un.arr[2] = _z;
  34. un.arr[3] = _w;
  35. return un.ui32;
  36. }
  37. uint32_t packF4u(float _x, float _y = 0.0f, float _z = 0.0f, float _w = 0.0f)
  38. {
  39. const uint8_t xx = uint8_t(_x*127.0f + 128.0f);
  40. const uint8_t yy = uint8_t(_y*127.0f + 128.0f);
  41. const uint8_t zz = uint8_t(_z*127.0f + 128.0f);
  42. const uint8_t ww = uint8_t(_w*127.0f + 128.0f);
  43. return packUint32(xx, yy, zz, ww);
  44. }
  45. struct PosNormalTexcoordVertex
  46. {
  47. float m_x;
  48. float m_y;
  49. float m_z;
  50. uint32_t m_normal;
  51. float m_u;
  52. float m_v;
  53. static void init()
  54. {
  55. ms_decl
  56. .begin()
  57. .add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float)
  58. .add(bgfx::Attrib::Normal, 4, bgfx::AttribType::Uint8, true, true)
  59. .add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Float)
  60. .end();
  61. }
  62. static bgfx::VertexDecl ms_decl;
  63. };
  64. bgfx::VertexDecl PosNormalTexcoordVertex::ms_decl;
  65. static const float s_texcoord = 5.0f;
  66. static PosNormalTexcoordVertex s_hplaneVertices[] =
  67. {
  68. { -1.0f, 0.0f, 1.0f, packF4u(0.0f, 1.0f, 0.0f), s_texcoord, s_texcoord },
  69. { 1.0f, 0.0f, 1.0f, packF4u(0.0f, 1.0f, 0.0f), s_texcoord, 0.0f },
  70. { -1.0f, 0.0f, -1.0f, packF4u(0.0f, 1.0f, 0.0f), 0.0f, s_texcoord },
  71. { 1.0f, 0.0f, -1.0f, packF4u(0.0f, 1.0f, 0.0f), 0.0f, 0.0f },
  72. };
  73. static PosNormalTexcoordVertex s_vplaneVertices[] =
  74. {
  75. { -1.0f, 1.0f, 0.0f, packF4u(0.0f, 0.0f, -1.0f), 1.0f, 1.0f },
  76. { 1.0f, 1.0f, 0.0f, packF4u(0.0f, 0.0f, -1.0f), 1.0f, 0.0f },
  77. { -1.0f, -1.0f, 0.0f, packF4u(0.0f, 0.0f, -1.0f), 0.0f, 1.0f },
  78. { 1.0f, -1.0f, 0.0f, packF4u(0.0f, 0.0f, -1.0f), 0.0f, 0.0f },
  79. };
  80. static const PosNormalTexcoordVertex s_cubeVertices[] =
  81. {
  82. { -1.0f, 1.0f, 1.0f, packF4u( 0.0f, 1.0f, 0.0f), 1.0f, 1.0f },
  83. { 1.0f, 1.0f, 1.0f, packF4u( 0.0f, 1.0f, 0.0f), 0.0f, 1.0f },
  84. { -1.0f, 1.0f, -1.0f, packF4u( 0.0f, 1.0f, 0.0f), 1.0f, 0.0f },
  85. { 1.0f, 1.0f, -1.0f, packF4u( 0.0f, 1.0f, 0.0f), 0.0f, 0.0f },
  86. { -1.0f, -1.0f, 1.0f, packF4u( 0.0f, -1.0f, 0.0f), 1.0f, 1.0f },
  87. { 1.0f, -1.0f, 1.0f, packF4u( 0.0f, -1.0f, 0.0f), 0.0f, 1.0f },
  88. { -1.0f, -1.0f, -1.0f, packF4u( 0.0f, -1.0f, 0.0f), 1.0f, 0.0f },
  89. { 1.0f, -1.0f, -1.0f, packF4u( 0.0f, -1.0f, 0.0f), 0.0f, 0.0f },
  90. { 1.0f, -1.0f, 1.0f, packF4u( 0.0f, 0.0f, 1.0f), 0.0f, 0.0f },
  91. { 1.0f, 1.0f, 1.0f, packF4u( 0.0f, 0.0f, 1.0f), 0.0f, 1.0f },
  92. { -1.0f, -1.0f, 1.0f, packF4u( 0.0f, 0.0f, 1.0f), 1.0f, 0.0f },
  93. { -1.0f, 1.0f, 1.0f, packF4u( 0.0f, 0.0f, 1.0f), 1.0f, 1.0f },
  94. { 1.0f, -1.0f, -1.0f, packF4u( 0.0f, 0.0f, -1.0f), 0.0f, 0.0f },
  95. { 1.0f, 1.0f, -1.0f, packF4u( 0.0f, 0.0f, -1.0f), 0.0f, 1.0f },
  96. { -1.0f, -1.0f, -1.0f, packF4u( 0.0f, 0.0f, -1.0f), 1.0f, 0.0f },
  97. { -1.0f, 1.0f, -1.0f, packF4u( 0.0f, 0.0f, -1.0f), 1.0f, 1.0f },
  98. { 1.0f, 1.0f, -1.0f, packF4u( 1.0f, 0.0f, 0.0f), 1.0f, 1.0f },
  99. { 1.0f, 1.0f, 1.0f, packF4u( 1.0f, 0.0f, 0.0f), 0.0f, 1.0f },
  100. { 1.0f, -1.0f, -1.0f, packF4u( 1.0f, 0.0f, 0.0f), 1.0f, 0.0f },
  101. { 1.0f, -1.0f, 1.0f, packF4u( 1.0f, 0.0f, 0.0f), 0.0f, 0.0f },
  102. { -1.0f, 1.0f, -1.0f, packF4u(-1.0f, 0.0f, 0.0f), 1.0f, 1.0f },
  103. { -1.0f, 1.0f, 1.0f, packF4u(-1.0f, 0.0f, 0.0f), 0.0f, 1.0f },
  104. { -1.0f, -1.0f, -1.0f, packF4u(-1.0f, 0.0f, 0.0f), 1.0f, 0.0f },
  105. { -1.0f, -1.0f, 1.0f, packF4u(-1.0f, 0.0f, 0.0f), 0.0f, 0.0f },
  106. };
  107. static const uint16_t s_cubeIndices[] =
  108. {
  109. 0, 1, 2,
  110. 1, 3, 2,
  111. 4, 6, 5,
  112. 5, 6, 7,
  113. 8, 9, 10,
  114. 9, 11, 10,
  115. 12, 14, 13,
  116. 13, 14, 15,
  117. 16, 17, 18,
  118. 17, 19, 18,
  119. 20, 22, 21,
  120. 21, 22, 23,
  121. };
  122. static const uint16_t s_planeIndices[] =
  123. {
  124. 0, 1, 2,
  125. 1, 3, 2,
  126. };
  127. static const char* s_shaderPath = NULL;
  128. static bool s_flipV = false;
  129. static uint32_t s_viewMask = 0;
  130. static uint32_t s_clearMask = 0;
  131. static bgfx::UniformHandle u_texColor;
  132. static void shaderFilePath(char* _out, const char* _name)
  133. {
  134. strcpy(_out, s_shaderPath);
  135. strcat(_out, _name);
  136. strcat(_out, ".bin");
  137. }
  138. long int fsize(FILE* _file)
  139. {
  140. long int pos = ftell(_file);
  141. fseek(_file, 0L, SEEK_END);
  142. long int size = ftell(_file);
  143. fseek(_file, pos, SEEK_SET);
  144. return size;
  145. }
  146. static const bgfx::Memory* load(const char* _filePath)
  147. {
  148. FILE* file = fopen(_filePath, "rb");
  149. if (NULL != file)
  150. {
  151. uint32_t size = (uint32_t)fsize(file);
  152. const bgfx::Memory* mem = bgfx::alloc(size+1);
  153. size_t ignore = fread(mem->data, 1, size, file);
  154. BX_UNUSED(ignore);
  155. fclose(file);
  156. mem->data[mem->size-1] = '\0';
  157. return mem;
  158. }
  159. return NULL;
  160. }
  161. static const bgfx::Memory* loadShader(const char* _name)
  162. {
  163. char filePath[512];
  164. shaderFilePath(filePath, _name);
  165. return load(filePath);
  166. }
  167. static const bgfx::Memory* loadTexture(const char* _name)
  168. {
  169. char filePath[512];
  170. strcpy(filePath, "textures/");
  171. strcat(filePath, _name);
  172. return load(filePath);
  173. }
  174. static bgfx::ProgramHandle loadProgram(const char* _vsName, const char* _fsName)
  175. {
  176. const bgfx::Memory* mem;
  177. // Load vertex shader.
  178. mem = loadShader(_vsName);
  179. bgfx::ShaderHandle vsh = bgfx::createShader(mem);
  180. // Load fragment shader.
  181. mem = loadShader(_fsName);
  182. bgfx::ShaderHandle fsh = bgfx::createShader(mem);
  183. // Create program from shaders.
  184. return bgfx::createProgram(vsh, fsh, true /* destroy shaders when program is destroyed */);
  185. }
  186. void mtxReflected(float*__restrict _result
  187. , const float* __restrict _p /* plane */
  188. , const float* __restrict _n /* normal */
  189. )
  190. {
  191. float dot = bx::vec3Dot(_p, _n);
  192. _result[ 0] = 1.0f - 2.0f * _n[0] * _n[0]; //1-2Nx^2
  193. _result[ 1] = -2.0f * _n[0] * _n[1]; //-2*Nx*Ny
  194. _result[ 2] = -2.0f * _n[0] * _n[2]; //-2*NxNz
  195. _result[ 3] = 0.0f; //0
  196. _result[ 4] = -2.0f * _n[0] * _n[1]; //-2*NxNy
  197. _result[ 5] = 1.0f - 2.0f * _n[1] * _n[1]; //1-2*Ny^2
  198. _result[ 6] = -2.0f * _n[1] * _n[2]; //-2*NyNz
  199. _result[ 7] = 0.0f; //0
  200. _result[ 8] = -2.0f * _n[0] * _n[2]; //-2*NxNz
  201. _result[ 9] = -2.0f * _n[1] * _n[2]; //-2NyNz
  202. _result[10] = 1.0f - 2.0f * _n[2] * _n[2]; //1-2*Nz^2
  203. _result[11] = 0.0f; //0
  204. _result[12] = 2.0f * dot * _n[0]; //2*dot*Nx
  205. _result[13] = 2.0f * dot * _n[1]; //2*dot*Ny
  206. _result[14] = 2.0f * dot * _n[2]; //2*dot*Nz
  207. _result[15] = 1.0f; //1
  208. }
  209. void mtxShadow(float* __restrict _result
  210. , const float* __restrict _ground
  211. , const float* __restrict _light
  212. )
  213. {
  214. float dot = _ground[0] * _light[0]
  215. + _ground[1] * _light[1]
  216. + _ground[2] * _light[2]
  217. + _ground[3] * _light[3]
  218. ;
  219. _result[ 0] = dot - _light[0] * _ground[0];
  220. _result[ 1] = 0.0f - _light[1] * _ground[0];
  221. _result[ 2] = 0.0f - _light[2] * _ground[0];
  222. _result[ 3] = 0.0f - _light[3] * _ground[0];
  223. _result[ 4] = 0.0f - _light[0] * _ground[1];
  224. _result[ 5] = dot - _light[1] * _ground[1];
  225. _result[ 6] = 0.0f - _light[2] * _ground[1];
  226. _result[ 7] = 0.0f - _light[3] * _ground[1];
  227. _result[ 8] = 0.0f - _light[0] * _ground[2];
  228. _result[ 9] = 0.0f - _light[1] * _ground[2];
  229. _result[10] = dot - _light[2] * _ground[2];
  230. _result[11] = 0.0f - _light[3] * _ground[2];
  231. _result[12] = 0.0f - _light[0] * _ground[3];
  232. _result[13] = 0.0f - _light[1] * _ground[3];
  233. _result[14] = 0.0f - _light[2] * _ground[3];
  234. _result[15] = dot - _light[3] * _ground[3];
  235. }
  236. void mtxBillboard(float* __restrict _result
  237. , const float* __restrict _view
  238. , const float* __restrict _pos
  239. , const float* __restrict _scale)
  240. {
  241. _result[ 0] = _view[0] * _scale[0];
  242. _result[ 1] = _view[4] * _scale[0];
  243. _result[ 2] = _view[8] * _scale[0];
  244. _result[ 3] = 0.0f;
  245. _result[ 4] = _view[1] * _scale[1];
  246. _result[ 5] = _view[5] * _scale[1];
  247. _result[ 6] = _view[9] * _scale[1];
  248. _result[ 7] = 0.0f;
  249. _result[ 8] = _view[2] * _scale[2];
  250. _result[ 9] = _view[6] * _scale[2];
  251. _result[10] = _view[10] * _scale[2];
  252. _result[11] = 0.0f;
  253. _result[12] = _pos[0];
  254. _result[13] = _pos[1];
  255. _result[14] = _pos[2];
  256. _result[15] = 1.0f;
  257. }
  258. struct Uniforms
  259. {
  260. void init()
  261. {
  262. m_params.m_ambientPass = 1.0f;
  263. m_params.m_lightningPass = 1.0f;
  264. m_params.m_lightCount = 4.0f;
  265. m_params.m_lightIndex = 4.0f;
  266. m_ambient[0] = 0.02f;
  267. m_ambient[1] = 0.02f;
  268. m_ambient[2] = 0.02f;
  269. m_ambient[3] = 0.0f; //unused
  270. m_diffuse[0] = 0.2f;
  271. m_diffuse[1] = 0.2f;
  272. m_diffuse[2] = 0.2f;
  273. m_diffuse[3] = 0.0f; //unused
  274. m_specular_shininess[0] = 1.0f;
  275. m_specular_shininess[1] = 1.0f;
  276. m_specular_shininess[2] = 1.0f;
  277. m_specular_shininess[3] = 10.0f; //shininess
  278. m_color[0] = 1.0f;
  279. m_color[1] = 1.0f;
  280. m_color[2] = 1.0f;
  281. m_color[3] = 1.0f;
  282. m_time = 0.0f;
  283. for (uint8_t ii = 0; ii < MAX_NUM_LIGHTS; ++ii)
  284. {
  285. m_lightPosRadius[ii][0] = 0.0f;
  286. m_lightPosRadius[ii][1] = 0.0f;
  287. m_lightPosRadius[ii][2] = 0.0f;
  288. m_lightPosRadius[ii][3] = 1.0f;
  289. m_lightRgbInnerR[ii][0] = 1.0f;
  290. m_lightRgbInnerR[ii][1] = 1.0f;
  291. m_lightRgbInnerR[ii][2] = 1.0f;
  292. m_lightRgbInnerR[ii][3] = 1.0f;
  293. }
  294. u_params = bgfx::createUniform("u_params", bgfx::UniformType::Uniform4fv);
  295. u_ambient = bgfx::createUniform("u_ambient", bgfx::UniformType::Uniform4fv);
  296. u_diffuse = bgfx::createUniform("u_diffuse", bgfx::UniformType::Uniform4fv);
  297. u_specular_shininess = bgfx::createUniform("u_specular_shininess", bgfx::UniformType::Uniform4fv);
  298. u_color = bgfx::createUniform("u_color", bgfx::UniformType::Uniform4fv);
  299. u_time = bgfx::createUniform("u_time", bgfx::UniformType::Uniform1f );
  300. u_lightPosRadius = bgfx::createUniform("u_lightPosRadius", bgfx::UniformType::Uniform4fv, MAX_NUM_LIGHTS);
  301. u_lightRgbInnerR = bgfx::createUniform("u_lightRgbInnerR", bgfx::UniformType::Uniform4fv, MAX_NUM_LIGHTS);
  302. }
  303. //call this once at initialization
  304. void submitConstUniforms()
  305. {
  306. bgfx::setUniform(u_ambient, &m_ambient);
  307. bgfx::setUniform(u_diffuse, &m_diffuse);
  308. bgfx::setUniform(u_specular_shininess, &m_specular_shininess);
  309. }
  310. //call this once per frame
  311. void submitPerFrameUniforms()
  312. {
  313. bgfx::setUniform(u_time, &m_time);
  314. }
  315. //call this before each draw call
  316. void submitPerDrawUniforms()
  317. {
  318. bgfx::setUniform(u_params, &m_params);
  319. bgfx::setUniform(u_color, &m_color);
  320. bgfx::setUniform(u_lightPosRadius, &m_lightPosRadius, MAX_NUM_LIGHTS);
  321. bgfx::setUniform(u_lightRgbInnerR, &m_lightRgbInnerR, MAX_NUM_LIGHTS);
  322. }
  323. void destroy()
  324. {
  325. bgfx::destroyUniform(u_params);
  326. bgfx::destroyUniform(u_ambient);
  327. bgfx::destroyUniform(u_diffuse);
  328. bgfx::destroyUniform(u_specular_shininess);
  329. bgfx::destroyUniform(u_color);
  330. bgfx::destroyUniform(u_time);
  331. bgfx::destroyUniform(u_lightPosRadius);
  332. bgfx::destroyUniform(u_lightRgbInnerR);
  333. }
  334. struct Params
  335. {
  336. float m_ambientPass;
  337. float m_lightningPass;
  338. float m_lightCount;
  339. float m_lightIndex;
  340. };
  341. struct SvParams
  342. {
  343. float m_useStencilTex;
  344. float m_dfail;
  345. float m_unused0;
  346. float m_unused1;
  347. };
  348. Params m_params;
  349. SvParams m_svparams;
  350. float m_ambient[4];
  351. float m_diffuse[4];
  352. float m_specular_shininess[4];
  353. float m_color[4];
  354. float m_time;
  355. float m_lightPosRadius[MAX_NUM_LIGHTS][4];
  356. float m_lightRgbInnerR[MAX_NUM_LIGHTS][4];
  357. /**
  358. * u_params.x - u_ambientPass
  359. * u_params.y - u_lightningPass
  360. * u_params.z - u_lightCount
  361. * u_params.w - u_lightIndex
  362. */
  363. bgfx::UniformHandle u_params;
  364. bgfx::UniformHandle u_ambient;
  365. bgfx::UniformHandle u_diffuse;
  366. bgfx::UniformHandle u_specular_shininess;
  367. bgfx::UniformHandle u_color;
  368. bgfx::UniformHandle u_time;
  369. bgfx::UniformHandle u_lightPosRadius;
  370. bgfx::UniformHandle u_lightRgbInnerR;
  371. };
  372. static Uniforms s_uniforms;
  373. //-------------------------------------------------
  374. // Render state
  375. //-------------------------------------------------
  376. struct RenderState
  377. {
  378. enum Enum
  379. {
  380. StencilReflection_CraftStencil = 0,
  381. StencilReflection_DrawReflected,
  382. StencilReflection_BlendPlane,
  383. StencilReflection_DrawScene,
  384. ProjectionShadows_DrawAmbient,
  385. ProjectionShadows_CraftStencil,
  386. ProjectionShadows_DrawDiffuse,
  387. Custom_BlendLightTexture,
  388. Custom_DrawPlaneBottom,
  389. Count
  390. };
  391. uint64_t m_state;
  392. uint32_t m_blendFactorRgba;
  393. uint32_t m_fstencil;
  394. uint32_t m_bstencil;
  395. };
  396. static RenderState s_renderStates[RenderState::Count] =
  397. {
  398. { // StencilReflection_CraftStencil
  399. BGFX_STATE_RGB_WRITE
  400. | BGFX_STATE_DEPTH_WRITE
  401. | BGFX_STATE_DEPTH_TEST_LESS
  402. | BGFX_STATE_MSAA
  403. , UINT32_MAX
  404. , BGFX_STENCIL_TEST_ALWAYS // pass always
  405. | BGFX_STENCIL_FUNC_REF(1) // value = 1
  406. | BGFX_STENCIL_FUNC_RMASK(0xff)
  407. | BGFX_STENCIL_OP_FAIL_S_REPLACE
  408. | BGFX_STENCIL_OP_FAIL_Z_REPLACE
  409. | BGFX_STENCIL_OP_PASS_Z_REPLACE // store the value
  410. , BGFX_STENCIL_NONE
  411. },
  412. { // StencilReflection_DrawReflected
  413. BGFX_STATE_RGB_WRITE
  414. | BGFX_STATE_ALPHA_WRITE
  415. | BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA)
  416. | BGFX_STATE_DEPTH_WRITE
  417. | BGFX_STATE_DEPTH_TEST_LESS
  418. | BGFX_STATE_CULL_CW //reflection matrix has inverted normals. using CCW instead of CW.
  419. | BGFX_STATE_MSAA
  420. , UINT32_MAX
  421. , BGFX_STENCIL_TEST_EQUAL
  422. | BGFX_STENCIL_FUNC_REF(1)
  423. | BGFX_STENCIL_FUNC_RMASK(1)
  424. | BGFX_STENCIL_OP_FAIL_S_KEEP
  425. | BGFX_STENCIL_OP_FAIL_Z_KEEP
  426. | BGFX_STENCIL_OP_PASS_Z_KEEP
  427. , BGFX_STENCIL_NONE
  428. },
  429. { // StencilReflection_BlendPlane
  430. BGFX_STATE_RGB_WRITE
  431. | BGFX_STATE_DEPTH_WRITE
  432. | BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_ONE, BGFX_STATE_BLEND_SRC_COLOR)
  433. | BGFX_STATE_DEPTH_TEST_LESS
  434. | BGFX_STATE_CULL_CCW
  435. | BGFX_STATE_MSAA
  436. , UINT32_MAX
  437. , BGFX_STENCIL_NONE
  438. , BGFX_STENCIL_NONE
  439. },
  440. { // StencilReflection_DrawScene
  441. BGFX_STATE_RGB_WRITE
  442. | BGFX_STATE_DEPTH_WRITE
  443. | BGFX_STATE_DEPTH_TEST_LESS
  444. | BGFX_STATE_CULL_CCW
  445. | BGFX_STATE_MSAA
  446. , UINT32_MAX
  447. , BGFX_STENCIL_NONE
  448. , BGFX_STENCIL_NONE
  449. },
  450. { // ProjectionShadows_DrawAmbient
  451. BGFX_STATE_RGB_WRITE
  452. | BGFX_STATE_DEPTH_WRITE // write depth !
  453. | BGFX_STATE_DEPTH_TEST_LESS
  454. | BGFX_STATE_CULL_CCW
  455. | BGFX_STATE_MSAA
  456. , UINT32_MAX
  457. , BGFX_STENCIL_NONE
  458. , BGFX_STENCIL_NONE
  459. },
  460. { // ProjectionShadows_CraftStencil
  461. BGFX_STATE_DEPTH_TEST_LESS
  462. | BGFX_STATE_MSAA
  463. , UINT32_MAX
  464. , BGFX_STENCIL_TEST_ALWAYS // pass always
  465. | BGFX_STENCIL_FUNC_REF(1) // value = 1
  466. | BGFX_STENCIL_FUNC_RMASK(0xff)
  467. | BGFX_STENCIL_OP_FAIL_S_KEEP
  468. | BGFX_STENCIL_OP_FAIL_Z_KEEP
  469. | BGFX_STENCIL_OP_PASS_Z_REPLACE // store the value
  470. , BGFX_STENCIL_NONE
  471. },
  472. { // ProjectionShadows_DrawDiffuse
  473. BGFX_STATE_RGB_WRITE
  474. | BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_ONE, BGFX_STATE_BLEND_ONE)
  475. | BGFX_STATE_DEPTH_TEST_EQUAL
  476. | BGFX_STATE_CULL_CCW
  477. | BGFX_STATE_MSAA
  478. , UINT32_MAX
  479. , BGFX_STENCIL_TEST_NOTEQUAL
  480. | BGFX_STENCIL_FUNC_REF(1)
  481. | BGFX_STENCIL_FUNC_RMASK(1)
  482. | BGFX_STENCIL_OP_FAIL_S_KEEP
  483. | BGFX_STENCIL_OP_FAIL_Z_KEEP
  484. | BGFX_STENCIL_OP_PASS_Z_KEEP
  485. , BGFX_STENCIL_NONE
  486. },
  487. { // Custom_BlendLightTexture
  488. BGFX_STATE_RGB_WRITE
  489. | BGFX_STATE_ALPHA_WRITE
  490. | BGFX_STATE_DEPTH_WRITE
  491. | BGFX_STATE_DEPTH_TEST_LESS
  492. | BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_COLOR, BGFX_STATE_BLEND_INV_SRC_COLOR)
  493. | BGFX_STATE_CULL_CCW
  494. | BGFX_STATE_MSAA
  495. , UINT32_MAX
  496. , BGFX_STENCIL_NONE
  497. , BGFX_STENCIL_NONE
  498. },
  499. { // Custom_DrawPlaneBottom
  500. BGFX_STATE_RGB_WRITE
  501. | BGFX_STATE_CULL_CW
  502. | BGFX_STATE_MSAA
  503. , UINT32_MAX
  504. , BGFX_STENCIL_NONE
  505. , BGFX_STENCIL_NONE
  506. },
  507. };
  508. struct ViewState
  509. {
  510. ViewState(uint32_t _width = 1280, uint32_t _height = 720)
  511. : m_width(_width)
  512. , m_height(_height)
  513. {
  514. }
  515. uint32_t m_width;
  516. uint32_t m_height;
  517. float m_view[16];
  518. float m_proj[16];
  519. };
  520. struct ClearValues
  521. {
  522. ClearValues(uint32_t _clearRgba = 0x30303000
  523. , float _clearDepth = 1.0f
  524. , uint8_t _clearStencil = 0
  525. )
  526. : m_clearRgba(_clearRgba)
  527. , m_clearDepth(_clearDepth)
  528. , m_clearStencil(_clearStencil)
  529. { }
  530. uint32_t m_clearRgba;
  531. float m_clearDepth;
  532. uint8_t m_clearStencil;
  533. };
  534. void clearView(uint8_t _id, uint8_t _flags, const ClearValues& _clearValues)
  535. {
  536. bgfx::setViewClear(_id
  537. , _flags
  538. , _clearValues.m_clearRgba
  539. , _clearValues.m_clearDepth
  540. , _clearValues.m_clearStencil
  541. );
  542. // Keep track of cleared views
  543. s_clearMask |= 1 << _id;
  544. }
  545. void clearViewMask(uint32_t _viewMask, uint8_t _flags, const ClearValues& _clearValues)
  546. {
  547. bgfx::setViewClearMask(_viewMask
  548. , _flags
  549. , _clearValues.m_clearRgba
  550. , _clearValues.m_clearDepth
  551. , _clearValues.m_clearStencil
  552. );
  553. // Keep track of cleared views
  554. s_clearMask |= _viewMask;
  555. }
  556. struct Aabb
  557. {
  558. float m_min[3];
  559. float m_max[3];
  560. };
  561. struct Obb
  562. {
  563. float m_mtx[16];
  564. };
  565. struct Sphere
  566. {
  567. float m_center[3];
  568. float m_radius;
  569. };
  570. struct Primitive
  571. {
  572. uint32_t m_startIndex;
  573. uint32_t m_numIndices;
  574. uint32_t m_startVertex;
  575. uint32_t m_numVertices;
  576. Sphere m_sphere;
  577. Aabb m_aabb;
  578. Obb m_obb;
  579. };
  580. typedef std::vector<Primitive> PrimitiveArray;
  581. struct Group
  582. {
  583. Group()
  584. {
  585. reset();
  586. }
  587. void reset()
  588. {
  589. m_vbh.idx = bgfx::invalidHandle;
  590. m_ibh.idx = bgfx::invalidHandle;
  591. m_prims.clear();
  592. }
  593. bgfx::VertexBufferHandle m_vbh;
  594. bgfx::IndexBufferHandle m_ibh;
  595. Sphere m_sphere;
  596. Aabb m_aabb;
  597. Obb m_obb;
  598. PrimitiveArray m_prims;
  599. };
  600. namespace bgfx
  601. {
  602. int32_t read(bx::ReaderI* _reader, bgfx::VertexDecl& _decl);
  603. }
  604. struct Mesh
  605. {
  606. void load(const void* _vertices, uint32_t _numVertices, const bgfx::VertexDecl _decl
  607. , const uint16_t* _indices, uint32_t _numIndices)
  608. {
  609. Group group;
  610. const bgfx::Memory* mem;
  611. uint32_t size;
  612. size = _numVertices*_decl.getStride();
  613. mem = bgfx::makeRef(_vertices, size);
  614. group.m_vbh = bgfx::createVertexBuffer(mem, _decl);
  615. size = _numIndices*2;
  616. mem = bgfx::makeRef(_indices, size);
  617. group.m_ibh = bgfx::createIndexBuffer(mem);
  618. //TODO:
  619. // group.m_sphere = ...
  620. // group.m_aabb = ...
  621. // group.m_obb = ...
  622. // group.m_prims = ...
  623. m_groups.push_back(group);
  624. }
  625. void load(const char* _filePath)
  626. {
  627. #define BGFX_CHUNK_MAGIC_VB BX_MAKEFOURCC('V', 'B', ' ', 0x1)
  628. #define BGFX_CHUNK_MAGIC_IB BX_MAKEFOURCC('I', 'B', ' ', 0x0)
  629. #define BGFX_CHUNK_MAGIC_PRI BX_MAKEFOURCC('P', 'R', 'I', 0x0)
  630. bx::CrtFileReader reader;
  631. reader.open(_filePath);
  632. Group group;
  633. uint32_t chunk;
  634. while (4 == bx::read(&reader, chunk) )
  635. {
  636. switch (chunk)
  637. {
  638. case BGFX_CHUNK_MAGIC_VB:
  639. {
  640. bx::read(&reader, group.m_sphere);
  641. bx::read(&reader, group.m_aabb);
  642. bx::read(&reader, group.m_obb);
  643. bgfx::read(&reader, m_decl);
  644. uint16_t stride = m_decl.getStride();
  645. uint16_t numVertices;
  646. bx::read(&reader, numVertices);
  647. const bgfx::Memory* mem = bgfx::alloc(numVertices*stride);
  648. bx::read(&reader, mem->data, mem->size);
  649. group.m_vbh = bgfx::createVertexBuffer(mem, m_decl);
  650. }
  651. break;
  652. case BGFX_CHUNK_MAGIC_IB:
  653. {
  654. uint32_t numIndices;
  655. bx::read(&reader, numIndices);
  656. const bgfx::Memory* mem = bgfx::alloc(numIndices*2);
  657. bx::read(&reader, mem->data, mem->size);
  658. group.m_ibh = bgfx::createIndexBuffer(mem);
  659. }
  660. break;
  661. case BGFX_CHUNK_MAGIC_PRI:
  662. {
  663. uint16_t len;
  664. bx::read(&reader, len);
  665. std::string material;
  666. material.resize(len);
  667. bx::read(&reader, const_cast<char*>(material.c_str() ), len);
  668. uint16_t num;
  669. bx::read(&reader, num);
  670. for (uint32_t ii = 0; ii < num; ++ii)
  671. {
  672. bx::read(&reader, len);
  673. std::string name;
  674. name.resize(len);
  675. bx::read(&reader, const_cast<char*>(name.c_str() ), len);
  676. Primitive prim;
  677. bx::read(&reader, prim.m_startIndex);
  678. bx::read(&reader, prim.m_numIndices);
  679. bx::read(&reader, prim.m_startVertex);
  680. bx::read(&reader, prim.m_numVertices);
  681. bx::read(&reader, prim.m_sphere);
  682. bx::read(&reader, prim.m_aabb);
  683. bx::read(&reader, prim.m_obb);
  684. group.m_prims.push_back(prim);
  685. }
  686. m_groups.push_back(group);
  687. group.reset();
  688. }
  689. break;
  690. default:
  691. DBG("%08x at %d", chunk, reader.seek() );
  692. abort();
  693. break;
  694. }
  695. }
  696. reader.close();
  697. }
  698. void unload()
  699. {
  700. for (GroupArray::const_iterator it = m_groups.begin(), itEnd = m_groups.end(); it != itEnd; ++it)
  701. {
  702. const Group& group = *it;
  703. bgfx::destroyVertexBuffer(group.m_vbh);
  704. if (bgfx::invalidHandle != group.m_ibh.idx)
  705. {
  706. bgfx::destroyIndexBuffer(group.m_ibh);
  707. }
  708. }
  709. m_groups.clear();
  710. }
  711. void submit(uint8_t _viewId, float* _mtx, bgfx::ProgramHandle _program, const RenderState& _renderState)
  712. {
  713. bgfx::TextureHandle texture = BGFX_INVALID_HANDLE;
  714. submit(_viewId, _mtx, _program, _renderState, texture);
  715. }
  716. void submit(uint8_t _viewId, float* _mtx, bgfx::ProgramHandle _program, const RenderState& _renderState, bgfx::TextureHandle _texture)
  717. {
  718. for (GroupArray::const_iterator it = m_groups.begin(), itEnd = m_groups.end(); it != itEnd; ++it)
  719. {
  720. const Group& group = *it;
  721. // Set uniforms
  722. s_uniforms.submitPerDrawUniforms();
  723. // Set model matrix for rendering.
  724. bgfx::setTransform(_mtx);
  725. bgfx::setProgram(_program);
  726. bgfx::setIndexBuffer(group.m_ibh);
  727. bgfx::setVertexBuffer(group.m_vbh);
  728. // Set texture
  729. if (bgfx::invalidHandle != _texture.idx)
  730. {
  731. bgfx::setTexture(0, u_texColor, _texture);
  732. }
  733. // Apply render state
  734. bgfx::setStencil(_renderState.m_fstencil, _renderState.m_bstencil);
  735. bgfx::setState(_renderState.m_state, _renderState.m_blendFactorRgba);
  736. // Submit
  737. bgfx::submit(_viewId);
  738. // Keep track of submited view ids
  739. s_viewMask |= 1 << _viewId;
  740. }
  741. }
  742. bgfx::VertexDecl m_decl;
  743. typedef std::vector<Group> GroupArray;
  744. GroupArray m_groups;
  745. };
  746. int _main_(int /*_argc*/, char** /*_argv*/)
  747. {
  748. ViewState viewState(1280, 720);
  749. ClearValues clearValues(0x30303000, 1.0f, 0);
  750. uint32_t debug = BGFX_DEBUG_TEXT;
  751. uint32_t reset = BGFX_RESET_VSYNC;
  752. bgfx::init();
  753. bgfx::reset(viewState.m_width, viewState.m_height, reset);
  754. // Enable debug text.
  755. bgfx::setDebug(debug);
  756. // Setup root path for binary shaders. Shader binaries are different
  757. // for each renderer.
  758. switch (bgfx::getRendererType() )
  759. {
  760. default:
  761. case bgfx::RendererType::Direct3D9:
  762. s_shaderPath = "shaders/dx9/";
  763. break;
  764. case bgfx::RendererType::Direct3D11:
  765. s_shaderPath = "shaders/dx11/";
  766. break;
  767. case bgfx::RendererType::OpenGL:
  768. s_shaderPath = "shaders/glsl/";
  769. s_flipV = true;
  770. break;
  771. case bgfx::RendererType::OpenGLES:
  772. s_shaderPath = "shaders/gles/";
  773. s_flipV = true;
  774. break;
  775. }
  776. FILE* file = fopen("font/droidsans.ttf", "rb");
  777. uint32_t size = (uint32_t)fsize(file);
  778. void* data = malloc(size);
  779. size_t ignore = fread(data, 1, size, file);
  780. BX_UNUSED(ignore);
  781. fclose(file);
  782. imguiCreate(data);
  783. free(data);
  784. PosNormalTexcoordVertex::init();
  785. s_uniforms.init();
  786. s_uniforms.submitConstUniforms();
  787. u_texColor = bgfx::createUniform("u_texColor", bgfx::UniformType::Uniform1iv);
  788. bgfx::ProgramHandle programTextureLightning = loadProgram("vs_stencil_texture_lightning", "fs_stencil_texture_lightning");
  789. bgfx::ProgramHandle programColorLightning = loadProgram("vs_stencil_color_lightning", "fs_stencil_color_lightning" );
  790. bgfx::ProgramHandle programColorTexture = loadProgram("vs_stencil_color_texture", "fs_stencil_color_texture" );
  791. bgfx::ProgramHandle programColorBlack = loadProgram("vs_stencil_color", "fs_stencil_color_black" );
  792. bgfx::ProgramHandle programTexture = loadProgram("vs_stencil_texture", "fs_stencil_texture" );
  793. Mesh bunnyMesh;
  794. Mesh columnMesh;
  795. Mesh cubeMesh;
  796. Mesh hplaneMesh;
  797. Mesh vplaneMesh;
  798. bunnyMesh.load("meshes/bunny.bin");
  799. columnMesh.load("meshes/column.bin");
  800. cubeMesh.load(s_cubeVertices, BX_COUNTOF(s_cubeVertices), PosNormalTexcoordVertex::ms_decl, s_cubeIndices, BX_COUNTOF(s_cubeIndices) );
  801. hplaneMesh.load(s_hplaneVertices, BX_COUNTOF(s_hplaneVertices), PosNormalTexcoordVertex::ms_decl, s_planeIndices, BX_COUNTOF(s_planeIndices) );
  802. vplaneMesh.load(s_vplaneVertices, BX_COUNTOF(s_vplaneVertices), PosNormalTexcoordVertex::ms_decl, s_planeIndices, BX_COUNTOF(s_planeIndices) );
  803. const bgfx::Memory* mem;
  804. mem = loadTexture("figure-rgba.dds");
  805. bgfx::TextureHandle figureTex = bgfx::createTexture(mem);
  806. mem = loadTexture("flare.dds");
  807. bgfx::TextureHandle flareTex = bgfx::createTexture(mem);
  808. mem = loadTexture("fieldstone-rgba.dds");
  809. bgfx::TextureHandle fieldstoneTex = bgfx::createTexture(mem);
  810. // Setup lights.
  811. const float rgbInnerR[][4] =
  812. {
  813. { 1.0f, 0.7f, 0.2f, 0.0f }, //yellow
  814. { 0.7f, 0.2f, 1.0f, 0.0f }, //purple
  815. { 0.2f, 1.0f, 0.7f, 0.0f }, //cyan
  816. { 1.0f, 0.4f, 0.2f, 0.0f }, //orange
  817. { 0.7f, 0.7f, 0.7f, 0.0f }, //white
  818. };
  819. float lightRgbInnerR[MAX_NUM_LIGHTS][4];
  820. for (uint8_t ii = 0, jj = 0; ii < MAX_NUM_LIGHTS; ++ii, ++jj)
  821. {
  822. const uint8_t index = jj%BX_COUNTOF(rgbInnerR);
  823. lightRgbInnerR[ii][0] = rgbInnerR[index][0];
  824. lightRgbInnerR[ii][1] = rgbInnerR[index][1];
  825. lightRgbInnerR[ii][2] = rgbInnerR[index][2];
  826. lightRgbInnerR[ii][3] = rgbInnerR[index][3];
  827. }
  828. memcpy(s_uniforms.m_lightRgbInnerR, lightRgbInnerR, MAX_NUM_LIGHTS * 4*sizeof(float));
  829. // Set view and projection matrices.
  830. const float aspect = float(viewState.m_width)/float(viewState.m_height);
  831. bx::mtxProj(viewState.m_proj, 60.0f, aspect, 0.1f, 100.0f);
  832. float initialPos[3] = { 0.0f, 18.0f, -40.0f };
  833. cameraCreate();
  834. cameraSetPosition(initialPos);
  835. cameraSetVerticalAngle(-0.35f);
  836. cameraGetViewMtx(viewState.m_view);
  837. int64_t timeOffset = bx::getHPCounter();
  838. enum Scene
  839. {
  840. StencilReflectionScene = 0,
  841. ProjectionShadowsScene,
  842. };
  843. Scene scene = StencilReflectionScene;
  844. float settings_numLights = 4.0f;
  845. float settings_reflectionValue = 0.8f;
  846. bool settings_updateLights = true;
  847. bool settings_updateScene = true;
  848. static const char* titles[3] =
  849. {
  850. "Stencil Reflection Scene",
  851. "Projection Shadows Scene",
  852. };
  853. entry::MouseState mouseState;
  854. while (!entry::processEvents(viewState.m_width, viewState.m_height, debug, reset, &mouseState) )
  855. {
  856. imguiBeginFrame(mouseState.m_mx
  857. , mouseState.m_my
  858. , (mouseState.m_buttons[entry::MouseButton::Left ] ? IMGUI_MBUT_LEFT : 0)
  859. | (mouseState.m_buttons[entry::MouseButton::Right ] ? IMGUI_MBUT_RIGHT : 0)
  860. , 0
  861. , viewState.m_width
  862. , viewState.m_height
  863. );
  864. static int32_t scrollArea = 0;
  865. imguiBeginScrollArea("Settings", viewState.m_width - 256 - 10, 10, 256, 215, &scrollArea);
  866. if (imguiCheck(titles[StencilReflectionScene], StencilReflectionScene == scene) )
  867. {
  868. scene = StencilReflectionScene;
  869. settings_numLights = 4.0f;
  870. }
  871. if (imguiCheck(titles[ProjectionShadowsScene], ProjectionShadowsScene == scene) )
  872. {
  873. scene = ProjectionShadowsScene;
  874. settings_numLights = 1.0f;
  875. }
  876. imguiSeparatorLine();
  877. imguiSlider("Lights", settings_numLights, 1.0f, float(MAX_NUM_LIGHTS), 1.0f);
  878. if (scene == StencilReflectionScene)
  879. {
  880. imguiSlider("Reflection value", settings_reflectionValue, 0.0f, 1.0f, 0.01f);
  881. }
  882. if (imguiCheck("Update lights", settings_updateLights) )
  883. {
  884. settings_updateLights = !settings_updateLights;
  885. }
  886. if (imguiCheck("Update scene", settings_updateScene) )
  887. {
  888. settings_updateScene = !settings_updateScene;
  889. }
  890. imguiEndScrollArea();
  891. imguiEndFrame();
  892. // Update settings.
  893. uint8_t numLights = (uint8_t)settings_numLights;
  894. s_uniforms.m_params.m_ambientPass = 1.0f;
  895. s_uniforms.m_params.m_lightningPass = 1.0f;
  896. s_uniforms.m_params.m_lightCount = settings_numLights;
  897. s_uniforms.m_params.m_lightIndex = 0.0f;
  898. s_uniforms.m_color[3] = settings_reflectionValue;
  899. s_uniforms.submitPerFrameUniforms();
  900. // Time.
  901. int64_t now = bx::getHPCounter();
  902. static int64_t last = now;
  903. const int64_t frameTime = now - last;
  904. last = now;
  905. const double freq = double(bx::getHPFrequency() );
  906. const double toMs = 1000.0/freq;
  907. float time = (float)( (now - timeOffset)/double(bx::getHPFrequency() ) );
  908. const float deltaTime = float(frameTime/freq);
  909. s_uniforms.m_time = time;
  910. // Use debug font to print information about this example.
  911. bgfx::dbgTextClear();
  912. bgfx::dbgTextPrintf(0, 1, 0x4f, "bgfx/examples/13-stencil");
  913. bgfx::dbgTextPrintf(0, 2, 0x6f, "Description: Stencil reflections and shadows.");
  914. bgfx::dbgTextPrintf(0, 3, 0x0f, "Frame: % 7.3f[ms]", double(frameTime)*toMs);
  915. // Update camera.
  916. cameraUpdate(deltaTime, mouseState.m_mx, mouseState.m_my, !!mouseState.m_buttons[entry::MouseButton::Right]);
  917. cameraGetViewMtx(viewState.m_view);
  918. static float lightTimeAccumulator = 0.0f;
  919. if (settings_updateLights)
  920. {
  921. lightTimeAccumulator += deltaTime;
  922. }
  923. static float sceneTimeAccumulator = 0.0f;
  924. if (settings_updateScene)
  925. {
  926. sceneTimeAccumulator += deltaTime;
  927. }
  928. float lightPosRadius[MAX_NUM_LIGHTS][4];
  929. const float radius = (scene == StencilReflectionScene) ? 15.0f : 25.0f;
  930. for (uint8_t ii = 0; ii < numLights; ++ii)
  931. {
  932. lightPosRadius[ii][0] = sin( (lightTimeAccumulator*1.1f + ii*0.03f + float(ii*M_PI_2)*1.07f ) )*20.0f;
  933. lightPosRadius[ii][1] = 8.0f + (1.0f - cos( (lightTimeAccumulator*1.5f + ii*0.29f + float(ii*M_PI_2)*1.49f ) ))*4.0f;
  934. lightPosRadius[ii][2] = cos( (lightTimeAccumulator*1.3f + ii*0.13f + float(ii*M_PI_2)*1.79f ) )*20.0f;
  935. lightPosRadius[ii][3] = radius;
  936. }
  937. memcpy(s_uniforms.m_lightPosRadius, lightPosRadius, numLights * 4*sizeof(float));
  938. // Floor position.
  939. float floorMtx[16];
  940. bx::mtxSRT(floorMtx
  941. , 20.0f //scaleX
  942. , 20.0f //scaleY
  943. , 20.0f //scaleZ
  944. , 0.0f //rotX
  945. , 0.0f //rotY
  946. , 0.0f //rotZ
  947. , 0.0f //translateX
  948. , 0.0f //translateY
  949. , 0.0f //translateZ
  950. );
  951. // Bunny position.
  952. float bunnyMtx[16];
  953. bx::mtxSRT(bunnyMtx
  954. , 5.0f
  955. , 5.0f
  956. , 5.0f
  957. , 0.0f
  958. , 1.56f - sceneTimeAccumulator
  959. , 0.0f
  960. , 0.0f
  961. , 2.0f
  962. , 0.0f
  963. );
  964. // Columns position.
  965. const float dist = 14.0f;
  966. const float columnPositions[4][3] =
  967. {
  968. { dist, 0.0f, dist },
  969. { -dist, 0.0f, dist },
  970. { dist, 0.0f, -dist },
  971. { -dist, 0.0f, -dist },
  972. };
  973. float columnMtx[4][16];
  974. for (uint8_t ii = 0; ii < 4; ++ii)
  975. {
  976. bx::mtxSRT(columnMtx[ii]
  977. , 1.0f
  978. , 1.0f
  979. , 1.0f
  980. , 0.0f
  981. , 0.0f
  982. , 0.0f
  983. , columnPositions[ii][0]
  984. , columnPositions[ii][1]
  985. , columnPositions[ii][2]
  986. );
  987. }
  988. const uint8_t numCubes = 9;
  989. float cubeMtx[numCubes][16];
  990. for (uint16_t ii = 0; ii < numCubes; ++ii)
  991. {
  992. bx::mtxSRT(cubeMtx[ii]
  993. , 1.0f
  994. , 1.0f
  995. , 1.0f
  996. , 0.0f
  997. , 0.0f
  998. , 0.0f
  999. , sin(ii * 2.0f + 13.0f - sceneTimeAccumulator) * 13.0f
  1000. , 4.0f
  1001. , cos(ii * 2.0f + 13.0f - sceneTimeAccumulator) * 13.0f
  1002. );
  1003. }
  1004. // Make sure at the beginning everything gets cleared.
  1005. clearView(0, BGFX_CLEAR_COLOR_BIT | BGFX_CLEAR_DEPTH_BIT | BGFX_CLEAR_STENCIL_BIT, clearValues);
  1006. bgfx::submit(0);
  1007. s_viewMask |= 1;
  1008. // Bunny and columns color.
  1009. s_uniforms.m_color[0] = 0.70f;
  1010. s_uniforms.m_color[1] = 0.65f;
  1011. s_uniforms.m_color[2] = 0.60f;
  1012. switch (scene)
  1013. {
  1014. case StencilReflectionScene:
  1015. {
  1016. // First pass - Draw plane.
  1017. // Setup params for this scene.
  1018. s_uniforms.m_params.m_ambientPass = 1.0f;
  1019. s_uniforms.m_params.m_lightningPass = 1.0f;
  1020. // Floor.
  1021. hplaneMesh.submit(RENDER_VIEWID_RANGE1_PASS_0
  1022. , floorMtx
  1023. , programColorBlack
  1024. , s_renderStates[RenderState::StencilReflection_CraftStencil]
  1025. );
  1026. // Second pass - Draw reflected objects.
  1027. // Clear depth from previous pass.
  1028. clearView(RENDER_VIEWID_RANGE1_PASS_1, BGFX_CLEAR_DEPTH_BIT, clearValues);
  1029. // Compute reflected matrix.
  1030. float reflectMtx[16];
  1031. float plane_pos[3] = { 0.0f, 0.01f, 0.0f };
  1032. float normal[3] = { 0.0f, 1.0f, 0.0f };
  1033. mtxReflected(reflectMtx, plane_pos, normal);
  1034. // Reflect lights.
  1035. float reflectedLights[MAX_NUM_LIGHTS][4];
  1036. for (uint8_t ii = 0; ii < numLights; ++ii)
  1037. {
  1038. bx::vec3MulMtx(reflectedLights[ii], lightPosRadius[ii], reflectMtx);
  1039. reflectedLights[ii][3] = lightPosRadius[ii][3];
  1040. }
  1041. memcpy(s_uniforms.m_lightPosRadius, reflectedLights, numLights * 4*sizeof(float));
  1042. // Reflect and submit bunny.
  1043. float mtxReflectedBunny[16];
  1044. bx::mtxMul(mtxReflectedBunny, bunnyMtx, reflectMtx);
  1045. bunnyMesh.submit(RENDER_VIEWID_RANGE1_PASS_1
  1046. , mtxReflectedBunny
  1047. , programColorLightning
  1048. , s_renderStates[RenderState::StencilReflection_DrawReflected]
  1049. );
  1050. // Reflect and submit columns.
  1051. float mtxReflectedColumn[16];
  1052. for (uint8_t ii = 0; ii < 4; ++ii)
  1053. {
  1054. bx::mtxMul(mtxReflectedColumn, columnMtx[ii], reflectMtx);
  1055. columnMesh.submit(RENDER_VIEWID_RANGE1_PASS_1
  1056. , mtxReflectedColumn
  1057. , programColorLightning
  1058. , s_renderStates[RenderState::StencilReflection_DrawReflected]
  1059. );
  1060. }
  1061. // Set lights back.
  1062. memcpy(s_uniforms.m_lightPosRadius, lightPosRadius, numLights * 4*sizeof(float));
  1063. // Third pass - Blend plane.
  1064. // Floor.
  1065. hplaneMesh.submit(RENDER_VIEWID_RANGE1_PASS_2
  1066. , floorMtx
  1067. , programTextureLightning
  1068. , s_renderStates[RenderState::StencilReflection_BlendPlane]
  1069. , fieldstoneTex
  1070. );
  1071. // Fourth pass - Draw everything else but the plane.
  1072. // Bunny.
  1073. bunnyMesh.submit(RENDER_VIEWID_RANGE1_PASS_3
  1074. , bunnyMtx
  1075. , programColorLightning
  1076. , s_renderStates[RenderState::StencilReflection_DrawScene]
  1077. );
  1078. // Columns.
  1079. for (uint8_t ii = 0; ii < 4; ++ii)
  1080. {
  1081. columnMesh.submit(RENDER_VIEWID_RANGE1_PASS_3
  1082. , columnMtx[ii]
  1083. , programColorLightning
  1084. , s_renderStates[RenderState::StencilReflection_DrawScene]
  1085. );
  1086. }
  1087. }
  1088. break;
  1089. case ProjectionShadowsScene:
  1090. {
  1091. // First pass - Draw entire scene. (ambient only).
  1092. s_uniforms.m_params.m_ambientPass = 1.0f;
  1093. s_uniforms.m_params.m_lightningPass = 0.0f;
  1094. // Bunny.
  1095. bunnyMesh.submit(RENDER_VIEWID_RANGE1_PASS_0
  1096. , bunnyMtx
  1097. , programColorLightning
  1098. , s_renderStates[RenderState::ProjectionShadows_DrawAmbient]
  1099. );
  1100. // Floor.
  1101. hplaneMesh.submit(RENDER_VIEWID_RANGE1_PASS_0
  1102. , floorMtx
  1103. , programTextureLightning
  1104. , s_renderStates[RenderState::ProjectionShadows_DrawAmbient]
  1105. , fieldstoneTex
  1106. );
  1107. // Cubes.
  1108. for (uint8_t ii = 0; ii < numCubes; ++ii)
  1109. {
  1110. cubeMesh.submit(RENDER_VIEWID_RANGE1_PASS_0
  1111. , cubeMtx[ii]
  1112. , programTextureLightning
  1113. , s_renderStates[RenderState::ProjectionShadows_DrawAmbient]
  1114. , figureTex
  1115. );
  1116. }
  1117. // Ground plane.
  1118. float ground[4];
  1119. float plane_pos[3] = { 0.0f, 0.0f, 0.0f };
  1120. float normal[3] = { 0.0f, 1.0f, 0.0f };
  1121. memcpy(ground, normal, sizeof(float) * 3);
  1122. ground[3] = -bx::vec3Dot(plane_pos, normal) - 0.01f; // - 0.01 against z-fighting
  1123. for (uint8_t ii = 0, viewId = RENDER_VIEWID_RANGE5_PASS_6; ii < numLights; ++ii, ++viewId)
  1124. {
  1125. // Clear stencil for this light source.
  1126. clearView(viewId, BGFX_CLEAR_STENCIL_BIT, clearValues);
  1127. // Draw shadow projection of scene objects.
  1128. // Get homogeneous light pos.
  1129. float* lightPos = lightPosRadius[ii];
  1130. float pos[4];
  1131. memcpy(pos, lightPos, sizeof(float) * 3);
  1132. pos[3] = 1.0f;
  1133. // Calculate shadow mtx for current light.
  1134. float shadowMtx[16];
  1135. mtxShadow(shadowMtx, ground, pos);
  1136. // Submit bunny's shadow.
  1137. float mtxShadowedBunny[16];
  1138. bx::mtxMul(mtxShadowedBunny, bunnyMtx, shadowMtx);
  1139. bunnyMesh.submit(viewId
  1140. , mtxShadowedBunny
  1141. , programColorBlack
  1142. , s_renderStates[RenderState::ProjectionShadows_CraftStencil]
  1143. );
  1144. // Submit cube shadows.
  1145. float mtxShadowedCube[16];
  1146. for (uint8_t jj = 0; jj < numCubes; ++jj)
  1147. {
  1148. bx::mtxMul(mtxShadowedCube, cubeMtx[jj], shadowMtx);
  1149. cubeMesh.submit(viewId
  1150. , mtxShadowedCube
  1151. , programColorBlack
  1152. , s_renderStates[RenderState::ProjectionShadows_CraftStencil]
  1153. );
  1154. }
  1155. // Draw entire scene. (lightning pass only. blending is on)
  1156. s_uniforms.m_params.m_ambientPass = 0.0f;
  1157. s_uniforms.m_params.m_lightningPass = 1.0f;
  1158. s_uniforms.m_params.m_lightCount = 1.0f;
  1159. s_uniforms.m_params.m_lightIndex = float(ii);
  1160. // Bunny.
  1161. bunnyMesh.submit(viewId
  1162. , bunnyMtx
  1163. , programColorLightning
  1164. , s_renderStates[RenderState::ProjectionShadows_DrawDiffuse]
  1165. );
  1166. // Floor.
  1167. hplaneMesh.submit(viewId
  1168. , floorMtx
  1169. , programTextureLightning
  1170. , s_renderStates[RenderState::ProjectionShadows_DrawDiffuse]
  1171. , fieldstoneTex
  1172. );
  1173. // Cubes.
  1174. for (uint8_t ii = 0; ii < numCubes; ++ii)
  1175. {
  1176. cubeMesh.submit(viewId
  1177. , cubeMtx[ii]
  1178. , programTextureLightning
  1179. , s_renderStates[RenderState::ProjectionShadows_DrawDiffuse]
  1180. , figureTex
  1181. );
  1182. }
  1183. }
  1184. // Reset these to default..
  1185. s_uniforms.m_params.m_ambientPass = 1.0f;
  1186. s_uniforms.m_params.m_lightningPass = 1.0f;
  1187. }
  1188. break;
  1189. };
  1190. //lights
  1191. const float lightScale[3] = { 1.5f, 1.5f, 1.5f };
  1192. float lightMtx[16];
  1193. for (uint8_t ii = 0; ii < numLights; ++ii)
  1194. {
  1195. s_uniforms.m_color[0] = lightRgbInnerR[ii][0];
  1196. s_uniforms.m_color[1] = lightRgbInnerR[ii][1];
  1197. s_uniforms.m_color[2] = lightRgbInnerR[ii][2];
  1198. mtxBillboard(lightMtx, viewState.m_view, lightPosRadius[ii], lightScale);
  1199. vplaneMesh.submit(RENDER_VIEWID_RANGE1_PASS_7
  1200. , lightMtx
  1201. , programColorTexture
  1202. , s_renderStates[RenderState::Custom_BlendLightTexture]
  1203. , flareTex
  1204. );
  1205. }
  1206. // Draw floor bottom.
  1207. float floorBottomMtx[16];
  1208. bx::mtxSRT(floorBottomMtx
  1209. , 20.0f //scaleX
  1210. , 20.0f //scaleY
  1211. , 20.0f //scaleZ
  1212. , 0.0f //rotX
  1213. , 0.0f //rotY
  1214. , 0.0f //rotZ
  1215. , 0.0f //translateX
  1216. , -0.1f //translateY
  1217. , 0.0f //translateZ
  1218. );
  1219. hplaneMesh.submit(RENDER_VIEWID_RANGE1_PASS_7
  1220. , floorBottomMtx
  1221. , programTexture
  1222. , s_renderStates[RenderState::Custom_DrawPlaneBottom]
  1223. , figureTex
  1224. );
  1225. // Setup view rect and transform for all used views.
  1226. bgfx::setViewRectMask(s_viewMask, 0, 0, viewState.m_width, viewState.m_height);
  1227. bgfx::setViewTransformMask(s_viewMask, viewState.m_view, viewState.m_proj);
  1228. s_viewMask = 0;
  1229. // Advance to next frame. Rendering thread will be kicked to
  1230. // process submitted rendering primitives.
  1231. bgfx::frame();
  1232. //reset clear values on used views
  1233. clearViewMask(s_clearMask, BGFX_CLEAR_NONE, clearValues);
  1234. s_clearMask = 0;
  1235. }
  1236. // Cleanup.
  1237. bunnyMesh.unload();
  1238. columnMesh.unload();
  1239. cubeMesh.unload();
  1240. hplaneMesh.unload();
  1241. vplaneMesh.unload();
  1242. bgfx::destroyTexture(figureTex);
  1243. bgfx::destroyTexture(fieldstoneTex);
  1244. bgfx::destroyTexture(flareTex);
  1245. bgfx::destroyProgram(programTextureLightning);
  1246. bgfx::destroyProgram(programColorLightning);
  1247. bgfx::destroyProgram(programColorTexture);
  1248. bgfx::destroyProgram(programColorBlack);
  1249. bgfx::destroyProgram(programTexture);
  1250. bgfx::destroyUniform(u_texColor);
  1251. s_uniforms.destroy();
  1252. cameraDestroy();
  1253. imguiDestroy();
  1254. // Shutdown bgfx.
  1255. bgfx::shutdown();
  1256. return 0;
  1257. }