You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

преди 11 години
преди 14 години
преди 14 години
преди 10 години
преди 11 години
преди 11 години
преди 11 години
преди 11 години
преди 11 години
преди 11 години
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924
  1. //
  2. // Lol Engine
  3. //
  4. // Copyright © 2010—2016 Sam Hocevar <sam@hocevar.net>
  5. // © 2014—2015 Benjamin “Touky” Huet <huet.benjamin@gmail.com>
  6. //
  7. // Lol Engine is free software. It comes without any warranty, to
  8. // the extent permitted by applicable law. You can redistribute it
  9. // and/or modify it under the terms of the Do What the Fuck You Want
  10. // to Public License, Version 2, as published by the WTFPL Task Force.
  11. // See http://www.wtfpl.net/ for more details.
  12. //
  13. #include <lol/engine-internal.h>
  14. #include <cstdlib>
  15. #if defined(_WIN32)
  16. # define WIN32_LEAN_AND_MEAN 1
  17. # include <windows.h>
  18. # undef WIN32_LEAN_AND_MEAN
  19. #endif
  20. #include "lolgl.h"
  21. LOLFX_RESOURCE_DECLARE(tile);
  22. LOLFX_RESOURCE_DECLARE(palette);
  23. LOLFX_RESOURCE_DECLARE(line);
  24. LOLFX_RESOURCE_DECLARE(blit);
  25. LOLFX_RESOURCE_DECLARE(postprocess);
  26. namespace lol
  27. {
  28. /*
  29. * The global g_scenes object, initialised by Video::Init
  30. */
  31. array<Scene*> Scene::g_scenes;
  32. /*
  33. * A quick and dirty Tile structure for 2D blits
  34. */
  35. struct Tile
  36. {
  37. mat4 m_model;
  38. TileSet *m_tileset;
  39. int m_id;
  40. };
  41. //-----------------------------------------------------------------------------
  42. static array<SceneDisplay*> m_scene_displays;
  43. static inline void gpu_marker(char const *message)
  44. {
  45. #if LOL_USE_GLEW
  46. if (GLEW_GREMEDY_string_marker)
  47. glStringMarkerGREMEDY(0, message);
  48. #endif
  49. }
  50. /*
  51. * Public SceneDisplay class
  52. */
  53. void SceneDisplay::Add(SceneDisplay* display)
  54. {
  55. m_scene_displays << display;
  56. }
  57. int SceneDisplay::GetCount()
  58. {
  59. return m_scene_displays.count();
  60. }
  61. SceneDisplay* SceneDisplay::GetDisplay(int index)
  62. {
  63. ASSERT(0 <= index && index < m_scene_displays.count(),
  64. "invalid display index %d", index);
  65. return m_scene_displays[index];
  66. }
  67. void SceneDisplay::DestroyAll()
  68. {
  69. for (SceneDisplay* display : m_scene_displays)
  70. delete display;
  71. m_scene_displays.empty();
  72. }
  73. /* ------------------------------------------------ */
  74. void SceneDisplay::Enable()
  75. {
  76. // TODO: PROFILER STUFF
  77. }
  78. void SceneDisplay::Disable()
  79. {
  80. // TODO: PROFILER STUFF
  81. }
  82. /*
  83. * Primitive implementation class
  84. */
  85. void PrimitiveSource::Render(Scene& scene) { UNUSED(scene); }
  86. void PrimitiveRenderer::Render(Scene& scene, PrimitiveSource* primitive)
  87. {
  88. UNUSED(scene);
  89. UNUSED(primitive);
  90. }
  91. /*
  92. * Scene implementation class
  93. */
  94. class SceneData
  95. {
  96. friend class Scene;
  97. private:
  98. SceneData()
  99. {
  100. /* TODO: FIX THAT */
  101. ASSERT(!(m_used_id & ((uint64_t)1 << 63)), "Too many scenes !!!!");
  102. m_mask_id = m_used_id;
  103. m_used_id = m_used_id << 1;
  104. }
  105. /* Mask ID */
  106. /* TODO: Do a mask class that handles more than 64 slots */
  107. static uint64_t m_used_id;
  108. uint64_t m_mask_id = 0;
  109. /* Scene display: if none has been set to the scene,
  110. * the default one created by the app will be used */
  111. SceneDisplay* m_display = nullptr;
  112. /** Render buffers: where to render to. */
  113. Framebuffer *m_renderbuffer[4];
  114. struct postprocess
  115. {
  116. Shader *m_shader[2];
  117. VertexBuffer *m_vbo = nullptr;
  118. VertexDeclaration *m_vdecl = nullptr;
  119. ShaderUniform m_buffer_uni[2][3];
  120. ShaderAttrib m_coord[2];
  121. }
  122. m_pp;
  123. /* Sources are shared by all scenes.
  124. * Renderers are scene-dependent. They get the primitive in the identical
  125. * slot to render with the given scene.
  126. * Primitives and renderers will be kept until:
  127. * - Updated by entity
  128. * - Marked Fire&Forget
  129. * - Scene is destroyed */
  130. map<uintptr_t, array<PrimitiveRenderer*>> m_prim_renderers;
  131. static map<uintptr_t, array<PrimitiveSource*>> m_prim_sources;
  132. static mutex m_prim_mutex;
  133. Camera *m_default_cam;
  134. array<Camera *> m_camera_stack;
  135. /* Old line API <P0, P1, COLOR, TIME, MASK> */
  136. struct line_api
  137. {
  138. float m_time, m_segment_size;
  139. vec4 m_color;
  140. array<vec3, vec3, vec4, float, int, bool, bool> m_lines;
  141. int m_mask, m_debug_mask;
  142. Shader *m_shader;
  143. VertexDeclaration *m_vdecl;
  144. }
  145. m_line_api;
  146. /* The old tiles API */
  147. struct tile_api
  148. {
  149. int m_cam;
  150. array<Tile> m_tiles;
  151. array<Tile> m_palettes;
  152. array<Light *> m_lights;
  153. Shader *m_shader;
  154. Shader *m_palette_shader;
  155. VertexDeclaration *m_vdecl;
  156. array<VertexBuffer *> m_bufs;
  157. }
  158. m_tile_api;
  159. };
  160. uint64_t SceneData::m_used_id = 1;
  161. map<uintptr_t, array<PrimitiveSource*>> SceneData::m_prim_sources;
  162. mutex SceneData::m_prim_mutex;
  163. /*
  164. * Public Scene class
  165. */
  166. Scene::Scene(ivec2 size)
  167. : data(new SceneData())
  168. {
  169. data->m_renderbuffer[0] = new Framebuffer(size);
  170. data->m_renderbuffer[1] = new Framebuffer(size);
  171. data->m_renderbuffer[2] = new Framebuffer(size);
  172. data->m_renderbuffer[3] = new Framebuffer(size);
  173. data->m_pp.m_shader[0] = Shader::Create(LOLFX_RESOURCE_NAME(blit));
  174. data->m_pp.m_shader[1] = Shader::Create(LOLFX_RESOURCE_NAME(postprocess));
  175. data->m_pp.m_coord[0] = data->m_pp.m_shader[0]->GetAttribLocation(VertexUsage::Position, 0);
  176. data->m_pp.m_coord[1] = data->m_pp.m_shader[1]->GetAttribLocation(VertexUsage::Position, 0);
  177. data->m_pp.m_vdecl = new VertexDeclaration(VertexStream<vec2>(VertexUsage::Position));
  178. data->m_pp.m_buffer_uni[0][0] = data->m_pp.m_shader[0]->GetUniformLocation("u_buffer");
  179. data->m_pp.m_buffer_uni[1][0] = data->m_pp.m_shader[1]->GetUniformLocation("u_buffer");
  180. data->m_pp.m_buffer_uni[1][1] = data->m_pp.m_shader[1]->GetUniformLocation("u_prev_buffer");
  181. data->m_pp.m_buffer_uni[1][2] = data->m_pp.m_shader[1]->GetUniformLocation("u_prev_final");
  182. array<vec2> quad { vec2( 1.0, 1.0), vec2(-1.0, -1.0), vec2( 1.0, -1.0),
  183. vec2(-1.0, -1.0), vec2( 1.0, 1.0), vec2(-1.0, 1.0), };
  184. data->m_pp.m_vbo = new VertexBuffer(quad.bytes());
  185. void *vertices = data->m_pp.m_vbo->Lock(0, 0);
  186. memcpy(vertices, quad.data(), quad.bytes());
  187. data->m_pp.m_vbo->Unlock();
  188. /* Create a default orthographic camera, in case the user doesn’t. */
  189. data->m_default_cam = new Camera();
  190. mat4 proj = mat4::ortho(0.f, (float)size.x, 0.f, (float)size.y, -1000.f, 1000.f);
  191. data->m_default_cam->SetProjection(proj);
  192. PushCamera(data->m_default_cam);
  193. data->m_tile_api.m_cam = -1;
  194. data->m_tile_api.m_shader = 0;
  195. data->m_tile_api.m_palette_shader = 0;
  196. data->m_tile_api.m_vdecl = new VertexDeclaration(VertexStream<vec3>(VertexUsage::Position),
  197. VertexStream<vec2>(VertexUsage::TexCoord));
  198. data->m_line_api.m_shader = 0;
  199. data->m_line_api.m_vdecl = new VertexDeclaration(VertexStream<vec4,vec4>(VertexUsage::Position, VertexUsage::Color));
  200. data->m_line_api.m_debug_mask = 1;
  201. SetLineTime();
  202. SetLineMask();
  203. SetLineSegmentSize();
  204. SetLineColor();
  205. }
  206. //-----------------------------------------------------------------------------
  207. Scene::~Scene()
  208. {
  209. PopCamera(data->m_default_cam);
  210. /* FIXME: this must be done while the GL context is still active.
  211. * Change the code architecture to make sure of that. */
  212. /* FIXME: also, make sure we do not add code to Reset() that will
  213. * reallocate stuff */
  214. Reset();
  215. delete data->m_line_api.m_vdecl;
  216. delete data->m_tile_api.m_vdecl;
  217. delete data;
  218. }
  219. //-----------------------------------------------------------------------------
  220. void Scene::AddNew(ivec2 size)
  221. {
  222. Scene::g_scenes << new Scene(size);
  223. }
  224. void Scene::DestroyScene(Scene* scene)
  225. {
  226. Scene::g_scenes.remove_item(scene);
  227. delete scene;
  228. }
  229. void Scene::DestroyAll()
  230. {
  231. while (Scene::g_scenes.count())
  232. delete Scene::g_scenes.pop();
  233. }
  234. int Scene::GetCount()
  235. {
  236. return g_scenes.count();
  237. }
  238. //-----------------------------------------------------------------------------
  239. bool Scene::IsReady(int index)
  240. {
  241. return 0 <= index && index < g_scenes.count() && !!g_scenes[index];
  242. }
  243. //-----------------------------------------------------------------------------
  244. Scene& Scene::GetScene(int index)
  245. {
  246. ASSERT(0 <= index && index < g_scenes.count() && !!g_scenes[index],
  247. "Trying to get a non-existent scene %d", index);
  248. return *g_scenes[index];
  249. }
  250. //-----------------------------------------------------------------------------
  251. void Scene::Link(Entity* entity)
  252. {
  253. entity->m_scene_mask |= data->m_mask_id;
  254. }
  255. //-----------------------------------------------------------------------------
  256. bool Scene::IsRelevant(Entity* entity)
  257. {
  258. return !!(entity->m_scene_mask & data->m_mask_id);
  259. }
  260. //-----------------------------------------------------------------------------
  261. Camera* Scene::GetCamera(int cam_idx)
  262. {
  263. ASSERT(!!data, "Trying to access a non-ready scene");
  264. return (0 <= cam_idx && cam_idx < data->m_camera_stack.count()) ?
  265. data->m_camera_stack[cam_idx] :
  266. data->m_camera_stack.last();
  267. }
  268. //-----------------------------------------------------------------------------
  269. int Scene::PushCamera(Camera *cam)
  270. {
  271. ASSERT(!!data, "Trying to access a non-ready scene");
  272. Ticker::Ref(cam);
  273. data->m_camera_stack.push(cam);
  274. return (int)data->m_camera_stack.count() - 1;
  275. }
  276. //-----------------------------------------------------------------------------
  277. void Scene::PopCamera(Camera *cam)
  278. {
  279. ASSERT(!!data, "Trying to access a non-ready scene");
  280. /* Parse from the end because that’s probably where we’ll find
  281. * our camera first. */
  282. for (int i = data->m_camera_stack.count(); i--;)
  283. {
  284. if (data->m_camera_stack[i] == cam)
  285. {
  286. Ticker::Unref(cam);
  287. data->m_camera_stack.remove(i);
  288. return;
  289. }
  290. }
  291. ASSERT(false, "trying to pop a nonexistent camera from the scene");
  292. }
  293. //-----------------------------------------------------------------------------
  294. void Scene::SetTileCam(int cam_idx)
  295. {
  296. ASSERT(!!data, "Trying to access a non-ready scene");
  297. data->m_tile_api.m_cam = cam_idx;
  298. }
  299. //-----------------------------------------------------------------------------
  300. void Scene::Reset()
  301. {
  302. ASSERT(!!data, "Trying to access a non-ready scene");
  303. /* New scenegraph: Release fire&forget primitives */
  304. array<uintptr_t> keys = data->m_prim_renderers.keys();
  305. for (uintptr_t key : keys)
  306. {
  307. for (int idx = 0; idx < data->m_prim_renderers[key].count(); ++idx)
  308. if (data->m_prim_renderers[key][idx]->m_fire_and_forget)
  309. ReleasePrimitiveRenderer(idx--, key);
  310. }
  311. for (int i = 0; i < data->m_tile_api.m_bufs.count(); i++)
  312. delete data->m_tile_api.m_bufs[i];
  313. data->m_tile_api.m_bufs.empty();
  314. data->m_tile_api.m_lights.empty();
  315. }
  316. //---- Primitive source stuff -------------------------------------------------
  317. int Scene::HasPrimitiveSource(uintptr_t key)
  318. {
  319. int count;
  320. SceneData::m_prim_mutex.lock();
  321. {
  322. count = SceneData::m_prim_sources[key].count();
  323. }
  324. SceneData::m_prim_mutex.unlock();
  325. return count;
  326. }
  327. int Scene::AddPrimitiveSource(uintptr_t key, PrimitiveSource* source)
  328. {
  329. int count;
  330. SceneData::m_prim_mutex.lock();
  331. {
  332. count = SceneData::m_prim_sources[key].count();
  333. SceneData::m_prim_sources[key].push(source);
  334. }
  335. SceneData::m_prim_mutex.unlock();
  336. return count;
  337. }
  338. void Scene::SetPrimitiveSource(int index, uintptr_t key, PrimitiveSource* source)
  339. {
  340. ASSERT(source);
  341. ASSERT(index >= 0);
  342. PrimitiveSource* old = nullptr;
  343. SceneData::m_prim_mutex.lock();
  344. {
  345. if (index < SceneData::m_prim_sources[key].count())
  346. old = SceneData::m_prim_sources[key][index];
  347. else
  348. SceneData::m_prim_sources[key].resize(index + 1);
  349. SceneData::m_prim_sources[key][index] = source;
  350. }
  351. SceneData::m_prim_mutex.unlock();
  352. // Delete old AFTER having released the lock
  353. delete old;
  354. }
  355. void Scene::ReleasePrimitiveSource(int index, uintptr_t key)
  356. {
  357. PrimitiveSource* old = nullptr;
  358. SceneData::m_prim_mutex.lock();
  359. {
  360. ASSERT(0 <= index && index < SceneData::m_prim_sources[key].count());
  361. old = SceneData::m_prim_sources[key][index];
  362. SceneData::m_prim_sources[key].remove(index);
  363. }
  364. SceneData::m_prim_mutex.unlock();
  365. // Delete old AFTER having released the lock
  366. delete old;
  367. }
  368. void Scene::ReleaseAllPrimitiveSources(uintptr_t key)
  369. {
  370. array<PrimitiveSource*> oldies;
  371. SceneData::m_prim_mutex.lock();
  372. {
  373. oldies.reserve(SceneData::m_prim_sources[key].count());
  374. for (PrimitiveSource* source : SceneData::m_prim_sources[key])
  375. oldies << source;
  376. SceneData::m_prim_sources[key].empty();
  377. }
  378. SceneData::m_prim_mutex.unlock();
  379. // Delete oldies AFTER having released the lock
  380. for (PrimitiveSource* old : oldies)
  381. delete old;
  382. }
  383. //---- Primitive renderer stuff -----------------------------------------------
  384. int Scene::HasPrimitiveRenderer(uintptr_t key)
  385. {
  386. return data->m_prim_renderers[key].count();
  387. }
  388. void Scene::AddPrimitiveRenderer(uintptr_t key, PrimitiveRenderer* renderer)
  389. {
  390. renderer->m_fire_and_forget = true;
  391. data->m_prim_renderers[key].push(renderer);
  392. }
  393. void Scene::SetPrimitiveRenderer(int index, uintptr_t key, PrimitiveRenderer* renderer)
  394. {
  395. ASSERT(renderer);
  396. ASSERT(index >= 0);
  397. if (index < data->m_prim_renderers[key].count())
  398. {
  399. ASSERT(data->m_prim_renderers[key][index]);
  400. delete data->m_prim_renderers[key][index];
  401. }
  402. else
  403. data->m_prim_renderers[key].resize(index + 1);
  404. data->m_prim_renderers[key][index] = renderer;
  405. }
  406. void Scene::ReleasePrimitiveRenderer(int index, uintptr_t key)
  407. {
  408. ASSERT(0 <= index && index < data->m_prim_renderers[key].count());
  409. delete data->m_prim_renderers[key][index];
  410. data->m_prim_renderers[key].remove(index);
  411. }
  412. void Scene::ReleaseAllPrimitiveRenderers(uintptr_t key)
  413. {
  414. for (PrimitiveRenderer*& renderer : data->m_prim_renderers[key])
  415. {
  416. delete renderer;
  417. renderer = nullptr;
  418. }
  419. }
  420. //-----------------------------------------------------------------------------
  421. void Scene::AddTile(TileSet *tileset, int id, vec3 pos, int o, vec2 scale, float radians)
  422. {
  423. ASSERT(id < tileset->GetTileCount());
  424. ivec2 size = tileset->GetTileSize(id);
  425. mat4 model = mat4::translate(pos)
  426. * mat4::scale(scale.x, scale.y, 1.f)
  427. * mat4::translate(size.x * 0.5f, size.y * 0.5f, 0.f)
  428. * mat4::rotate(scale.x * scale.y < 0 ? radians : -radians,
  429. vec3::axis_z);
  430. AddTile(tileset, id, model);
  431. }
  432. void Scene::AddTile(TileSet *tileset, int id, mat4 model)
  433. {
  434. ASSERT(id < tileset->GetTileCount());
  435. Tile t;
  436. t.m_model = model;
  437. t.m_tileset = tileset;
  438. t.m_id = id;
  439. if (tileset->GetPalette())
  440. data->m_tile_api.m_palettes.push(t);
  441. else
  442. data->m_tile_api.m_tiles.push(t);
  443. }
  444. //-----------------------------------------------------------------------------
  445. void Scene::SetLineTime(float new_time)
  446. {
  447. ASSERT(!!data, "Trying to access a non-ready scene");
  448. data->m_line_api.m_time = new_time;
  449. }
  450. void Scene::SetLineMask(int new_mask)
  451. {
  452. ASSERT(!!data, "Trying to access a non-ready scene");
  453. data->m_line_api.m_mask = new_mask;
  454. }
  455. void Scene::SetLineSegmentSize(float new_segment_size)
  456. {
  457. ASSERT(!!data, "Trying to access a non-ready scene");
  458. data->m_line_api.m_segment_size = new_segment_size;
  459. }
  460. void Scene::SetLineColor(vec4 new_color)
  461. {
  462. ASSERT(!!data, "Trying to access a non-ready scene");
  463. data->m_line_api.m_color = new_color;
  464. }
  465. //-----------------------------------------------------------------------------
  466. float Scene::GetLineSegmentSize()
  467. {
  468. ASSERT(!!data, "Trying to access a non-ready scene");
  469. return data->m_line_api.m_segment_size;
  470. }
  471. vec4 Scene::GetLineColor()
  472. {
  473. ASSERT(!!data, "Trying to access a non-ready scene");
  474. return data->m_line_api.m_color;
  475. }
  476. //-----------------------------------------------------------------------------
  477. void Scene::AddLine(vec3 a, vec3 b, vec4 color)
  478. {
  479. ASSERT(!!data, "Trying to access a non-ready scene");
  480. data->m_line_api.m_lines.push(a, b, color,
  481. data->m_line_api.m_time, data->m_line_api.m_mask, false, false);
  482. }
  483. //-----------------------------------------------------------------------------
  484. void Scene::AddLight(Light *l)
  485. {
  486. ASSERT(!!data, "Trying to access a non-ready scene");
  487. data->m_tile_api.m_lights.push(l);
  488. }
  489. //-----------------------------------------------------------------------------
  490. array<Light *> const &Scene::GetLights()
  491. {
  492. ASSERT(!!data, "Trying to access a non-ready scene");
  493. return data->m_tile_api.m_lights;
  494. }
  495. //-----------------------------------------------------------------------------
  496. void Scene::SetDisplay(SceneDisplay* display)
  497. {
  498. data->m_display = display;
  499. }
  500. //-----------------------------------------------------------------------------
  501. void Scene::EnableDisplay()
  502. {
  503. // If no display has been set, use the default one
  504. if (!data->m_display)
  505. SetDisplay(SceneDisplay::GetDisplay());
  506. data->m_display->Enable();
  507. }
  508. void Scene::DisableDisplay()
  509. {
  510. ASSERT(data->m_display);
  511. data->m_display->Disable();
  512. }
  513. /* Render everything that the scene contains */
  514. void Scene::render(float seconds)
  515. {
  516. bool do_pp = true;
  517. gpu_marker("Start Render");
  518. /* First render into the offline buffer */
  519. if (do_pp)
  520. {
  521. data->m_renderbuffer[0]->Bind();
  522. }
  523. {
  524. RenderContext rc;
  525. if (do_pp)
  526. {
  527. rc.SetClearColor(vec4(0.f, 0.f, 0.f, 1.f));
  528. rc.SetClearDepth(1.f);
  529. }
  530. Renderer::Get()->Clear(ClearMask::Color | ClearMask::Depth);
  531. // FIXME: get rid of the delta time argument
  532. render_primitives();
  533. render_tiles();
  534. render_lines(seconds);
  535. }
  536. if (do_pp)
  537. {
  538. data->m_renderbuffer[0]->Unbind();
  539. gpu_marker("PostProcess");
  540. data->m_renderbuffer[3]->Bind();
  541. RenderContext rc;
  542. rc.SetClearColor(vec4(0.f, 0.f, 0.f, 1.f));
  543. rc.SetClearDepth(1.f);
  544. Renderer::Get()->Clear(ClearMask::Color | ClearMask::Depth);
  545. /* Execute post process */
  546. data->m_pp.m_shader[1]->Bind();
  547. data->m_pp.m_shader[1]->SetUniform(data->m_pp.m_buffer_uni[1][0], data->m_renderbuffer[0]->GetTextureUniform(), 0);
  548. data->m_pp.m_shader[1]->SetUniform(data->m_pp.m_buffer_uni[1][1], data->m_renderbuffer[1]->GetTextureUniform(), 1);
  549. data->m_pp.m_shader[1]->SetUniform(data->m_pp.m_buffer_uni[1][2], data->m_renderbuffer[2]->GetTextureUniform(), 2);
  550. data->m_pp.m_vdecl->SetStream(data->m_pp.m_vbo, data->m_pp.m_coord[1]);
  551. data->m_pp.m_vdecl->Bind();
  552. data->m_pp.m_vdecl->DrawElements(MeshPrimitive::Triangles, 0, 6);
  553. data->m_pp.m_vdecl->Unbind();
  554. data->m_pp.m_shader[1]->Unbind();
  555. data->m_renderbuffer[3]->Unbind();
  556. }
  557. if (do_pp)
  558. {
  559. gpu_marker("Blit frame");
  560. data->m_pp.m_shader[0]->Bind();
  561. RenderContext rc;
  562. rc.SetClearColor(vec4(0.f, 0.f, 0.f, 1.f));
  563. rc.SetClearDepth(1.f);
  564. Renderer::Get()->Clear(ClearMask::Color | ClearMask::Depth);
  565. /* Blit final image to screen */
  566. data->m_pp.m_shader[0]->SetUniform(data->m_pp.m_buffer_uni[0][0], data->m_renderbuffer[3]->GetTextureUniform(), 3);
  567. data->m_pp.m_vdecl->SetStream(data->m_pp.m_vbo, data->m_pp.m_coord[0]);
  568. data->m_pp.m_vdecl->Bind();
  569. data->m_pp.m_vdecl->DrawElements(MeshPrimitive::Triangles, 0, 6);
  570. data->m_pp.m_vdecl->Unbind();
  571. data->m_pp.m_shader[0]->Unbind();
  572. }
  573. if (do_pp)
  574. {
  575. /* Swap back buffers */
  576. std::swap(data->m_renderbuffer[0], data->m_renderbuffer[1]);
  577. std::swap(data->m_renderbuffer[2], data->m_renderbuffer[3]);
  578. }
  579. gpu_marker("End Render");
  580. }
  581. //-----------------------------------------------------------------------------
  582. void Scene::render_primitives()
  583. {
  584. ASSERT(!!data, "Trying to access a non-ready scene");
  585. /* FIXME: Temp fix for mesh having no render context*/
  586. RenderContext rc;
  587. rc.SetCullMode(CullMode::Clockwise);
  588. rc.SetDepthFunc(DepthFunc::LessOrEqual);
  589. /* new scenegraph */
  590. array<uintptr_t> keys = data->m_prim_renderers.keys();
  591. for (uintptr_t key : keys)
  592. {
  593. for (int idx = 0; idx < data->m_prim_renderers[key].count(); ++idx)
  594. {
  595. /* TODO: Not sure if thread compliant */
  596. data->m_prim_renderers[key][idx]->Render(*this, idx < SceneData::m_prim_sources[key].count() ? SceneData::m_prim_sources[key][idx] : nullptr);
  597. }
  598. }
  599. }
  600. //-----------------------------------------------------------------------------
  601. void Scene::render_tiles() // XXX: rename to Blit()
  602. {
  603. ASSERT(!!data, "Trying to access a non-ready scene");
  604. RenderContext rc;
  605. /* Early test if nothing needs to be rendered */
  606. if (!data->m_tile_api.m_tiles.count() && !data->m_tile_api.m_palettes.count())
  607. return;
  608. /* FIXME: we disable culling for now because we don’t have a reliable
  609. * way to know which side is facing the camera. */
  610. rc.SetCullMode(CullMode::Disabled);
  611. rc.SetDepthFunc(DepthFunc::LessOrEqual);
  612. rc.SetBlendFunc(BlendFunc::SrcAlpha, BlendFunc::OneMinusSrcAlpha);
  613. rc.SetBlendEquation(BlendEquation::Add, BlendEquation::Max);
  614. rc.SetAlphaFunc(AlphaFunc::GreaterOrEqual, 0.01f);
  615. #if (defined LOL_USE_GLEW || defined HAVE_GL_2X) && !defined HAVE_GLES_2X
  616. glEnable(GL_TEXTURE_2D);
  617. #endif
  618. if (!data->m_tile_api.m_shader)
  619. data->m_tile_api.m_shader = Shader::Create(LOLFX_RESOURCE_NAME(tile));
  620. if (!data->m_tile_api.m_palette_shader)
  621. data->m_tile_api.m_palette_shader = Shader::Create(LOLFX_RESOURCE_NAME(palette));
  622. for (int p = 0; p < 2; p++)
  623. {
  624. Shader *shader = (p == 0) ? data->m_tile_api.m_shader : data->m_tile_api.m_palette_shader;
  625. array<Tile>& tiles = (p == 0) ? data->m_tile_api.m_tiles : data->m_tile_api.m_palettes;
  626. if (tiles.count() == 0)
  627. continue;
  628. ShaderUniform uni_mat, uni_tex, uni_pal, uni_texsize;
  629. ShaderAttrib attr_pos, attr_tex;
  630. attr_pos = shader->GetAttribLocation(VertexUsage::Position, 0);
  631. attr_tex = shader->GetAttribLocation(VertexUsage::TexCoord, 0);
  632. shader->Bind();
  633. uni_mat = shader->GetUniformLocation("u_projection");
  634. shader->SetUniform(uni_mat, GetCamera(data->m_tile_api.m_cam)->GetProjection());
  635. uni_mat = shader->GetUniformLocation("u_view");
  636. shader->SetUniform(uni_mat, GetCamera(data->m_tile_api.m_cam)->GetView());
  637. uni_mat = shader->GetUniformLocation("u_model");
  638. shader->SetUniform(uni_mat, mat4(1.f));
  639. uni_tex = shader->GetUniformLocation("u_texture");
  640. uni_pal = data->m_tile_api.m_palette_shader->GetUniformLocation("u_palette");
  641. uni_texsize = shader->GetUniformLocation("u_texsize");
  642. for (int buf = 0, i = 0, n; i < tiles.count(); i = n, buf += 2)
  643. {
  644. /* Count how many quads will be needed */
  645. for (n = i + 1; n < tiles.count(); n++)
  646. if (tiles[i].m_tileset != tiles[n].m_tileset)
  647. break;
  648. /* Create a vertex array object */
  649. VertexBuffer *vb1 = new VertexBuffer(6 * (n - i) * sizeof(vec3));
  650. vec3 *vertex = (vec3 *)vb1->Lock(0, 0);
  651. VertexBuffer *vb2 = new VertexBuffer(6 * (n - i) * sizeof(vec2));
  652. vec2 *texture = (vec2 *)vb2->Lock(0, 0);
  653. data->m_tile_api.m_bufs.push(vb1);
  654. data->m_tile_api.m_bufs.push(vb2);
  655. for (int j = i; j < n; j++)
  656. {
  657. tiles[i].m_tileset->BlitTile(tiles[j].m_id, tiles[j].m_model,
  658. vertex + 6 * (j - i), texture + 6 * (j - i));
  659. }
  660. vb1->Unlock();
  661. vb2->Unlock();
  662. /* Bind texture */
  663. if (tiles[i].m_tileset->GetPalette())
  664. {
  665. if (tiles[i].m_tileset->GetTexture())
  666. shader->SetUniform(uni_tex, tiles[i].m_tileset->GetTexture()->GetTextureUniform(), 0);
  667. if (tiles[i].m_tileset->GetPalette()->GetTexture())
  668. shader->SetUniform(uni_pal, tiles[i].m_tileset->GetPalette()->GetTexture()->GetTextureUniform(), 1);
  669. }
  670. else
  671. {
  672. shader->SetUniform(uni_tex, 0);
  673. if (tiles[i].m_tileset->GetTexture())
  674. shader->SetUniform(uni_tex, tiles[i].m_tileset->GetTexture()->GetTextureUniform(), 0);
  675. tiles[i].m_tileset->Bind();
  676. }
  677. shader->SetUniform(uni_texsize,
  678. (vec2)tiles[i].m_tileset->GetTextureSize());
  679. /* Bind vertex and texture coordinate buffers */
  680. data->m_tile_api.m_vdecl->Bind();
  681. data->m_tile_api.m_vdecl->SetStream(vb1, attr_pos);
  682. data->m_tile_api.m_vdecl->SetStream(vb2, attr_tex);
  683. /* Draw arrays */
  684. data->m_tile_api.m_vdecl->DrawElements(MeshPrimitive::Triangles, 0, (n - i) * 6);
  685. data->m_tile_api.m_vdecl->Unbind();
  686. tiles[i].m_tileset->Unbind();
  687. }
  688. tiles.empty();
  689. shader->Unbind();
  690. }
  691. #if (defined LOL_USE_GLEW || defined HAVE_GL_2X) && !defined HAVE_GLES_2X
  692. glDisable(GL_TEXTURE_2D);
  693. #endif
  694. }
  695. //-----------------------------------------------------------------------------
  696. // FIXME: get rid of the delta time argument
  697. // XXX: rename to Blit()
  698. void Scene::render_lines(float seconds)
  699. {
  700. ASSERT(!!data, "Trying to access a non-ready scene");
  701. RenderContext rc;
  702. if (!data->m_line_api.m_lines.count())
  703. return;
  704. rc.SetDepthFunc(DepthFunc::LessOrEqual);
  705. rc.SetBlendFunc(BlendFunc::SrcAlpha, BlendFunc::OneMinusSrcAlpha);
  706. rc.SetBlendEquation(BlendEquation::Add, BlendEquation::Max);
  707. rc.SetAlphaFunc(AlphaFunc::GreaterOrEqual, 0.01f);
  708. int linecount = (int)data->m_line_api.m_lines.count();
  709. if (!data->m_line_api.m_shader)
  710. data->m_line_api.m_shader = Shader::Create(LOLFX_RESOURCE_NAME(line));
  711. array<vec4, vec4, vec4, vec4> buff;
  712. buff.resize(linecount);
  713. int real_linecount = 0;
  714. mat4 const inv_view_proj = inverse(GetCamera()->GetProjection() * GetCamera()->GetView());
  715. for (int i = 0; i < linecount; i++)
  716. {
  717. if (data->m_line_api.m_lines[i].m5 & data->m_line_api.m_debug_mask)
  718. {
  719. buff[real_linecount].m1 = vec4(data->m_line_api.m_lines[i].m1, (float)data->m_line_api.m_lines[i].m6);
  720. buff[real_linecount].m2 = data->m_line_api.m_lines[i].m3;
  721. buff[real_linecount].m3 = vec4(data->m_line_api.m_lines[i].m2, (float)data->m_line_api.m_lines[i].m7);
  722. buff[real_linecount].m4 = data->m_line_api.m_lines[i].m3;
  723. real_linecount++;
  724. }
  725. data->m_line_api.m_lines[i].m4 -= seconds;
  726. if (data->m_line_api.m_lines[i].m4 < 0.f)
  727. {
  728. data->m_line_api.m_lines.remove_swap(i--);
  729. linecount--;
  730. }
  731. }
  732. VertexBuffer *vb = new VertexBuffer(buff.bytes());
  733. float *vertex = (float *)vb->Lock(0, 0);
  734. memcpy(vertex, buff.data(), buff.bytes());
  735. vb->Unlock();
  736. data->m_line_api.m_shader->Bind();
  737. ShaderUniform uni_mat, uni_tex;
  738. ShaderAttrib attr_pos, attr_col;
  739. attr_pos = data->m_line_api.m_shader->GetAttribLocation(VertexUsage::Position, 0);
  740. attr_col = data->m_line_api.m_shader->GetAttribLocation(VertexUsage::Color, 0);
  741. data->m_line_api.m_shader->Bind();
  742. uni_mat = data->m_line_api.m_shader->GetUniformLocation("u_projection");
  743. data->m_line_api.m_shader->SetUniform(uni_mat, GetCamera()->GetProjection());
  744. uni_mat = data->m_line_api.m_shader->GetUniformLocation("u_view");
  745. data->m_line_api.m_shader->SetUniform(uni_mat, GetCamera()->GetView());
  746. data->m_line_api.m_vdecl->Bind();
  747. data->m_line_api.m_vdecl->SetStream(vb, attr_pos, attr_col);
  748. data->m_line_api.m_vdecl->DrawElements(MeshPrimitive::Lines, 0, 2 * real_linecount);
  749. data->m_line_api.m_vdecl->Unbind();
  750. data->m_line_api.m_shader->Unbind();
  751. //data->m_line_api.m_lines.empty();
  752. delete vb;
  753. }
  754. } /* namespace lol */