25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

925 lines
28 KiB

  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 */