768 lines
21 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright © 2010—2019 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 <map>
  15. #include <cstdlib>
  16. #if defined(_WIN32)
  17. # define WIN32_LEAN_AND_MEAN 1
  18. # include <windows.h>
  19. # undef WIN32_LEAN_AND_MEAN
  20. #endif
  21. #include "lolgl.h"
  22. LOLFX_RESOURCE_DECLARE(gpu_tile);
  23. LOLFX_RESOURCE_DECLARE(gpu_palette);
  24. LOLFX_RESOURCE_DECLARE(gpu_line);
  25. LOLFX_RESOURCE_DECLARE(gpu_blit);
  26. LOLFX_RESOURCE_DECLARE(gpu_postprocess);
  27. namespace lol
  28. {
  29. /*
  30. * The global g_scenes object, initialised by Video::Init
  31. */
  32. array<Scene*> Scene::g_scenes;
  33. static array<SceneDisplay*> g_scene_displays;
  34. static inline void gpu_marker(char const *message)
  35. {
  36. #if LOL_USE_GLEW && defined glStringMarkerGREMEDY
  37. if (GLEW_GREMEDY_string_marker)
  38. glStringMarkerGREMEDY(0, message);
  39. #else
  40. UNUSED(message);
  41. #endif
  42. }
  43. //
  44. // Public SceneDisplay class
  45. //
  46. void SceneDisplay::Add(SceneDisplay* display)
  47. {
  48. g_scene_displays << display;
  49. }
  50. int SceneDisplay::GetCount()
  51. {
  52. return g_scene_displays.count();
  53. }
  54. SceneDisplay* SceneDisplay::GetDisplay(int index)
  55. {
  56. ASSERT(0 <= index && index < g_scene_displays.count(),
  57. "invalid display index %d", index);
  58. return g_scene_displays[index];
  59. }
  60. void SceneDisplay::DestroyAll()
  61. {
  62. for (SceneDisplay* display : g_scene_displays)
  63. delete display;
  64. g_scene_displays.clear();
  65. }
  66. void SceneDisplay::Enable()
  67. {
  68. // TODO: PROFILER STUFF
  69. }
  70. void SceneDisplay::Disable()
  71. {
  72. // TODO: PROFILER STUFF
  73. }
  74. /*
  75. * Primitive implementation class
  76. */
  77. void PrimitiveSource::Render(Scene& scene) { UNUSED(scene); }
  78. void PrimitiveRenderer::Render(Scene& scene, std::shared_ptr<PrimitiveSource> primitive)
  79. {
  80. UNUSED(scene);
  81. UNUSED(primitive);
  82. }
  83. /*
  84. * Scene implementation class
  85. */
  86. uint64_t Scene::g_used_id = 1;
  87. mutex Scene::g_prim_mutex;
  88. std::map<uintptr_t, array<std::shared_ptr<PrimitiveSource>>> Scene::g_prim_sources;
  89. /*
  90. * Public Scene class
  91. */
  92. Scene::Scene(ivec2 size)
  93. : m_size(size),
  94. m_wanted_size(size),
  95. m_renderer(std::make_shared<Renderer>(size))
  96. {
  97. /* TODO: FIX THAT */
  98. ASSERT(!(g_used_id & ((uint64_t)1 << 63)), "Too many scenes !!!!");
  99. m_mask_id = g_used_id;
  100. g_used_id = g_used_id << 1;
  101. for (int i = 0; i < 4; ++i)
  102. m_renderbuffer[i] = std::make_shared<Framebuffer>(m_size);
  103. m_pp.m_shader[0] = Shader::Create(LOLFX_RESOURCE_NAME(gpu_blit));
  104. m_pp.m_shader[1] = Shader::Create(LOLFX_RESOURCE_NAME(gpu_postprocess));
  105. m_pp.m_coord[0] = m_pp.m_shader[0]->GetAttribLocation(VertexUsage::Position, 0);
  106. m_pp.m_coord[1] = m_pp.m_shader[1]->GetAttribLocation(VertexUsage::Position, 0);
  107. m_pp.m_vdecl = std::make_shared<VertexDeclaration>(VertexStream<vec2>(VertexUsage::Position));
  108. m_pp.m_buffer_uni[0][0] = m_pp.m_shader[0]->GetUniformLocation("u_buffer");
  109. m_pp.m_buffer_uni[1][0] = m_pp.m_shader[1]->GetUniformLocation("u_buffer");
  110. m_pp.m_buffer_uni[1][1] = m_pp.m_shader[1]->GetUniformLocation("u_prev_buffer");
  111. m_pp.m_buffer_uni[1][2] = m_pp.m_shader[1]->GetUniformLocation("u_prev_final");
  112. array<vec2> quad { vec2( 1.0, 1.0), vec2(-1.0, -1.0), vec2( 1.0, -1.0),
  113. vec2(-1.0, -1.0), vec2( 1.0, 1.0), vec2(-1.0, 1.0), };
  114. m_pp.m_vbo = std::make_shared<VertexBuffer>(quad.bytes());
  115. void *vertices = m_pp.m_vbo->Lock(0, 0);
  116. memcpy(vertices, quad.data(), quad.bytes());
  117. m_pp.m_vbo->Unlock();
  118. /* Create a default orthographic camera, in case the user doesn’t. */
  119. m_default_cam = new Camera();
  120. mat4 proj = mat4::ortho(0.f, (float)m_size.x, 0.f, (float)m_size.y, -1000.f, 1000.f);
  121. m_default_cam->SetProjection(proj);
  122. PushCamera(m_default_cam);
  123. m_tile_api.m_cam = -1;
  124. m_tile_api.m_shader = 0;
  125. m_tile_api.m_palette_shader = 0;
  126. m_tile_api.m_vdecl = std::make_shared<VertexDeclaration>(VertexStream<vec3>(VertexUsage::Position),
  127. VertexStream<vec2>(VertexUsage::TexCoord));
  128. m_line_api.m_shader = 0;
  129. m_line_api.m_vdecl = std::make_shared<VertexDeclaration>(VertexStream<vec4,vec4>(VertexUsage::Position, VertexUsage::Color));
  130. m_line_api.m_debug_mask = 1;
  131. }
  132. void Scene::resize(ivec2 size)
  133. {
  134. m_wanted_size = size;
  135. }
  136. Scene::~Scene()
  137. {
  138. PopCamera(m_default_cam);
  139. /* FIXME: this must be done while the GL context is still active.
  140. * Change the code architecture to make sure of that. */
  141. /* FIXME: also, make sure we do not add code to Reset() that will
  142. * reallocate stuff */
  143. Reset();
  144. }
  145. void Scene::AddNew(ivec2 size)
  146. {
  147. Scene::g_scenes << new Scene(size);
  148. }
  149. void Scene::DestroyScene(Scene* scene)
  150. {
  151. Scene::g_scenes.remove_item(scene);
  152. delete scene;
  153. }
  154. void Scene::DestroyAll()
  155. {
  156. while (Scene::g_scenes.count())
  157. delete Scene::g_scenes.pop();
  158. }
  159. int Scene::GetCount()
  160. {
  161. return g_scenes.count();
  162. }
  163. bool Scene::IsReady(int index)
  164. {
  165. return 0 <= index && index < g_scenes.count() && !!g_scenes[index];
  166. }
  167. Scene& Scene::GetScene(int index)
  168. {
  169. ASSERT(0 <= index && index < g_scenes.count() && !!g_scenes[index],
  170. "Trying to get a non-existent scene %d", index);
  171. return *g_scenes[index];
  172. }
  173. void Scene::Link(Entity* entity)
  174. {
  175. entity->m_scene_mask |= m_mask_id;
  176. }
  177. bool Scene::IsRelevant(Entity* entity)
  178. {
  179. return !!(entity->m_scene_mask & m_mask_id);
  180. }
  181. Camera* Scene::GetCamera(int cam_idx)
  182. {
  183. return (0 <= cam_idx && cam_idx < m_camera_stack.count()) ?
  184. m_camera_stack[cam_idx] :
  185. m_camera_stack.last();
  186. }
  187. int Scene::PushCamera(Camera *cam)
  188. {
  189. Ticker::Ref(cam);
  190. m_camera_stack.push(cam);
  191. return (int)m_camera_stack.count() - 1;
  192. }
  193. void Scene::PopCamera(Camera *cam)
  194. {
  195. /* Parse from the end because that’s probably where we’ll find
  196. * our camera first. */
  197. for (int i = m_camera_stack.count(); i--;)
  198. {
  199. if (m_camera_stack[i] == cam)
  200. {
  201. Ticker::Unref(cam);
  202. m_camera_stack.remove(i);
  203. return;
  204. }
  205. }
  206. ASSERT(false, "trying to pop a nonexistent camera from the scene");
  207. }
  208. void Scene::SetTileCam(int cam_idx)
  209. {
  210. m_tile_api.m_cam = cam_idx;
  211. }
  212. void Scene::Reset()
  213. {
  214. /* New scenegraph: Release fire&forget primitives */
  215. for (uintptr_t key : keys(m_prim_renderers))
  216. {
  217. for (int idx = 0; idx < m_prim_renderers[key].count(); ++idx)
  218. if (m_prim_renderers[key][idx]->m_fire_and_forget)
  219. ReleasePrimitiveRenderer(idx--, key);
  220. }
  221. m_tile_api.m_bufs.clear();
  222. m_tile_api.m_lights.clear();
  223. }
  224. //
  225. // Primitive source stuff
  226. //
  227. int Scene::HasPrimitiveSource(uintptr_t key)
  228. {
  229. int count;
  230. g_prim_mutex.lock();
  231. {
  232. count = g_prim_sources[key].count();
  233. }
  234. g_prim_mutex.unlock();
  235. return count;
  236. }
  237. int Scene::AddPrimitiveSource(uintptr_t key, std::shared_ptr<PrimitiveSource> source)
  238. {
  239. int count;
  240. g_prim_mutex.lock();
  241. {
  242. count = g_prim_sources[key].count();
  243. g_prim_sources[key].push(source);
  244. }
  245. g_prim_mutex.unlock();
  246. return count;
  247. }
  248. void Scene::SetPrimitiveSource(int index, uintptr_t key, std::shared_ptr<PrimitiveSource> source)
  249. {
  250. ASSERT(source);
  251. ASSERT(index >= 0);
  252. // Keep reference to old source until AFTER we release the lock
  253. std::shared_ptr<PrimitiveSource> old;
  254. g_prim_mutex.lock();
  255. {
  256. if (index < g_prim_sources[key].count())
  257. old = g_prim_sources[key][index];
  258. else
  259. g_prim_sources[key].resize(index + 1);
  260. g_prim_sources[key][index] = source;
  261. }
  262. g_prim_mutex.unlock();
  263. }
  264. void Scene::ReleasePrimitiveSource(int index, uintptr_t key)
  265. {
  266. std::shared_ptr<PrimitiveSource> old;
  267. g_prim_mutex.lock();
  268. {
  269. ASSERT(0 <= index && index < g_prim_sources[key].count());
  270. old = g_prim_sources[key][index];
  271. g_prim_sources[key].remove(index);
  272. }
  273. g_prim_mutex.unlock();
  274. }
  275. void Scene::ReleaseAllPrimitiveSources(uintptr_t key)
  276. {
  277. // Delete oldies AFTER having released the lock
  278. array<std::shared_ptr<PrimitiveSource>> oldies;
  279. g_prim_mutex.lock();
  280. {
  281. oldies.reserve(g_prim_sources[key].count());
  282. for (auto source : g_prim_sources[key])
  283. oldies << source;
  284. g_prim_sources[key].clear();
  285. }
  286. g_prim_mutex.unlock();
  287. }
  288. //
  289. // Primitive renderer stuff
  290. //
  291. int Scene::HasPrimitiveRenderer(uintptr_t key)
  292. {
  293. return m_prim_renderers[key].count();
  294. }
  295. void Scene::AddPrimitiveRenderer(uintptr_t key, std::shared_ptr<PrimitiveRenderer> renderer)
  296. {
  297. renderer->m_fire_and_forget = true;
  298. m_prim_renderers[key].push(renderer);
  299. }
  300. void Scene::SetPrimitiveRenderer(int index, uintptr_t key, std::shared_ptr<PrimitiveRenderer> renderer)
  301. {
  302. ASSERT(renderer);
  303. ASSERT(index >= 0);
  304. if (index >= m_prim_renderers[key].count())
  305. m_prim_renderers[key].resize(index + 1);
  306. m_prim_renderers[key][index] = renderer;
  307. }
  308. void Scene::ReleasePrimitiveRenderer(int index, uintptr_t key)
  309. {
  310. ASSERT(0 <= index && index < m_prim_renderers[key].count());
  311. m_prim_renderers[key].remove(index);
  312. }
  313. void Scene::ReleaseAllPrimitiveRenderers(uintptr_t key)
  314. {
  315. m_prim_renderers[key].clear();
  316. }
  317. void Scene::AddTile(TileSet *tileset, int id, vec3 pos, vec2 scale, float radians)
  318. {
  319. ASSERT(id < tileset->GetTileCount());
  320. ivec2 size = tileset->GetTileSize(id);
  321. mat4 model = mat4::translate(pos)
  322. * mat4::scale(scale.x, scale.y, 1.f)
  323. * mat4::translate(size.x * 0.5f, size.y * 0.5f, 0.f)
  324. * mat4::rotate(scale.x * scale.y < 0 ? radians : -radians,
  325. vec3::axis_z);
  326. AddTile(tileset, id, model);
  327. }
  328. void Scene::AddTile(TileSet *tileset, int id, mat4 model)
  329. {
  330. ASSERT(id < tileset->GetTileCount());
  331. Tile t;
  332. t.m_model = model;
  333. t.m_tileset = tileset;
  334. t.m_id = id;
  335. if (tileset->GetPalette())
  336. m_tile_api.m_palettes.push(t);
  337. else
  338. m_tile_api.m_tiles.push(t);
  339. }
  340. void Scene::AddLine(vec3 a, vec3 b, vec4 color)
  341. {
  342. m_line_api.m_lines.push(a, b, color, -1.f, 0xFFFFFFFF, false, false);
  343. }
  344. void Scene::AddLine(vec3 a, vec3 b, vec4 color, float duration, int mask)
  345. {
  346. m_line_api.m_lines.push(a, b, color, duration, mask, false, false);
  347. }
  348. void Scene::AddLight(Light *l)
  349. {
  350. m_tile_api.m_lights.push(l);
  351. }
  352. array<Light *> const &Scene::GetLights()
  353. {
  354. return m_tile_api.m_lights;
  355. }
  356. void Scene::SetDisplay(SceneDisplay* display)
  357. {
  358. m_display = display;
  359. }
  360. void Scene::EnableDisplay()
  361. {
  362. // If no display has been set, use the default one
  363. if (!m_display)
  364. SetDisplay(SceneDisplay::GetDisplay());
  365. m_display->Enable();
  366. }
  367. void Scene::DisableDisplay()
  368. {
  369. ASSERT(m_display);
  370. m_display->Disable();
  371. }
  372. static bool do_pp = true;
  373. void Scene::pre_render(float)
  374. {
  375. gpu_marker("Pre Render");
  376. // Handle resize event
  377. if (m_size != m_wanted_size)
  378. {
  379. m_size = m_wanted_size;
  380. for (int i = 0; i < 4; ++i)
  381. m_renderbuffer[i] = std::make_shared<Framebuffer>(m_size);
  382. mat4 proj = mat4::ortho(0.f, (float)m_size.x, 0.f, (float)m_size.y, -1000.f, 1000.f);
  383. m_default_cam->SetProjection(proj);
  384. }
  385. /* First render into the offline buffer */
  386. if (do_pp)
  387. {
  388. m_renderbuffer[0]->Bind();
  389. }
  390. {
  391. render_context rc(m_renderer);
  392. if (do_pp)
  393. {
  394. rc.clear_color(vec4(0.f, 0.f, 0.f, 1.f));
  395. rc.clear_depth(1.f);
  396. }
  397. m_renderer->Clear(ClearMask::Color | ClearMask::Depth);
  398. }
  399. }
  400. /* Render everything that the scene contains */
  401. void Scene::render(float seconds)
  402. {
  403. gpu_marker("Render");
  404. // FIXME: get rid of the delta time argument
  405. render_primitives();
  406. render_tiles();
  407. render_lines(seconds);
  408. }
  409. void Scene::post_render(float)
  410. {
  411. gpu_marker("Post Render");
  412. if (do_pp)
  413. {
  414. m_renderbuffer[0]->Unbind();
  415. gpu_marker("PostProcess");
  416. m_renderbuffer[3]->Bind();
  417. render_context rc(m_renderer);
  418. rc.clear_color(vec4(0.f, 0.f, 0.f, 1.f));
  419. rc.clear_depth(1.f);
  420. m_renderer->Clear(ClearMask::Color | ClearMask::Depth);
  421. /* Execute post process */
  422. m_pp.m_shader[1]->Bind();
  423. m_pp.m_shader[1]->SetUniform(m_pp.m_buffer_uni[1][0], m_renderbuffer[0]->GetTextureUniform(), 0);
  424. m_pp.m_shader[1]->SetUniform(m_pp.m_buffer_uni[1][1], m_renderbuffer[1]->GetTextureUniform(), 1);
  425. m_pp.m_shader[1]->SetUniform(m_pp.m_buffer_uni[1][2], m_renderbuffer[2]->GetTextureUniform(), 2);
  426. m_pp.m_vdecl->SetStream(m_pp.m_vbo, m_pp.m_coord[1]);
  427. m_pp.m_vdecl->Bind();
  428. m_pp.m_vdecl->DrawElements(MeshPrimitive::Triangles, 0, 6);
  429. m_pp.m_vdecl->Unbind();
  430. m_pp.m_shader[1]->Unbind();
  431. m_renderbuffer[3]->Unbind();
  432. }
  433. if (do_pp)
  434. {
  435. gpu_marker("Blit frame");
  436. m_pp.m_shader[0]->Bind();
  437. render_context rc(m_renderer);
  438. rc.clear_color(vec4(0.f, 0.f, 0.f, 1.f));
  439. rc.clear_depth(1.f);
  440. m_renderer->Clear(ClearMask::Color | ClearMask::Depth);
  441. /* Blit final image to screen */
  442. m_pp.m_shader[0]->SetUniform(m_pp.m_buffer_uni[0][0], m_renderbuffer[3]->GetTextureUniform(), 3);
  443. m_pp.m_vdecl->SetStream(m_pp.m_vbo, m_pp.m_coord[0]);
  444. m_pp.m_vdecl->Bind();
  445. m_pp.m_vdecl->DrawElements(MeshPrimitive::Triangles, 0, 6);
  446. m_pp.m_vdecl->Unbind();
  447. m_pp.m_shader[0]->Unbind();
  448. }
  449. if (do_pp)
  450. {
  451. /* Swap back buffers */
  452. std::swap(m_renderbuffer[0], m_renderbuffer[1]);
  453. std::swap(m_renderbuffer[2], m_renderbuffer[3]);
  454. }
  455. gpu_marker("End Render");
  456. }
  457. void Scene::render_primitives()
  458. {
  459. /* FIXME: Temp fix for mesh having no render context*/
  460. render_context rc(m_renderer);
  461. rc.cull_mode(CullMode::Clockwise);
  462. rc.depth_func(DepthFunc::LessOrEqual);
  463. /* new scenegraph */
  464. for (uintptr_t key : keys(m_prim_renderers))
  465. {
  466. for (int idx = 0; idx < m_prim_renderers[key].count(); ++idx)
  467. {
  468. /* TODO: Not sure if thread compliant */
  469. std::shared_ptr<PrimitiveSource> source;
  470. if (idx < g_prim_sources[key].count())
  471. source = g_prim_sources[key][idx];
  472. m_prim_renderers[key][idx]->Render(*this, source);
  473. }
  474. }
  475. }
  476. void Scene::render_tiles() // XXX: rename to Blit()
  477. {
  478. render_context rc(m_renderer);
  479. /* Early test if nothing needs to be rendered */
  480. if (!m_tile_api.m_tiles.count() && !m_tile_api.m_palettes.count())
  481. return;
  482. /* FIXME: we disable culling for now because we don’t have a reliable
  483. * way to know which side is facing the camera. */
  484. rc.cull_mode(CullMode::Disabled);
  485. rc.depth_func(DepthFunc::LessOrEqual);
  486. rc.blend_func(BlendFunc::SrcAlpha, BlendFunc::OneMinusSrcAlpha);
  487. rc.blend_equation(BlendEquation::Add, BlendEquation::Max);
  488. rc.alpha_func(AlphaFunc::GreaterOrEqual, 0.01f);
  489. #if (defined LOL_USE_GLEW || defined HAVE_GL_2X) && !defined HAVE_GLES_2X
  490. glEnable(GL_TEXTURE_2D);
  491. #endif
  492. if (!m_tile_api.m_shader)
  493. m_tile_api.m_shader = Shader::Create(LOLFX_RESOURCE_NAME(gpu_tile));
  494. if (!m_tile_api.m_palette_shader && m_tile_api.m_palettes.count())
  495. m_tile_api.m_palette_shader = Shader::Create(LOLFX_RESOURCE_NAME(gpu_palette));
  496. for (int p = 0; p < 2; p++)
  497. {
  498. auto shader = (p == 0) ? m_tile_api.m_shader : m_tile_api.m_palette_shader;
  499. auto &tiles = (p == 0) ? m_tile_api.m_tiles : m_tile_api.m_palettes;
  500. if (tiles.count() == 0)
  501. continue;
  502. ShaderUniform uni_mat, uni_tex, uni_pal, uni_texsize;
  503. ShaderAttrib attr_pos, attr_tex;
  504. attr_pos = shader->GetAttribLocation(VertexUsage::Position, 0);
  505. attr_tex = shader->GetAttribLocation(VertexUsage::TexCoord, 0);
  506. shader->Bind();
  507. uni_mat = shader->GetUniformLocation("u_projection");
  508. shader->SetUniform(uni_mat, GetCamera(m_tile_api.m_cam)->GetProjection());
  509. uni_mat = shader->GetUniformLocation("u_view");
  510. shader->SetUniform(uni_mat, GetCamera(m_tile_api.m_cam)->GetView());
  511. uni_mat = shader->GetUniformLocation("u_model");
  512. shader->SetUniform(uni_mat, mat4(1.f));
  513. uni_tex = shader->GetUniformLocation("u_texture");
  514. uni_pal = m_tile_api.m_palette_shader ? m_tile_api.m_palette_shader->GetUniformLocation("u_palette") : ShaderUniform();
  515. uni_texsize = shader->GetUniformLocation("u_texsize");
  516. for (int buf = 0, i = 0, n; i < tiles.count(); i = n, buf += 2)
  517. {
  518. /* Count how many quads will be needed */
  519. for (n = i + 1; n < tiles.count(); n++)
  520. if (tiles[i].m_tileset != tiles[n].m_tileset)
  521. break;
  522. /* Create a vertex array object */
  523. auto vb1 = std::make_shared<VertexBuffer>(6 * (n - i) * sizeof(vec3));
  524. vec3 *vertex = (vec3 *)vb1->Lock(0, 0);
  525. auto vb2 = std::make_shared<VertexBuffer>(6 * (n - i) * sizeof(vec2));
  526. vec2 *texture = (vec2 *)vb2->Lock(0, 0);
  527. m_tile_api.m_bufs.push(vb1);
  528. m_tile_api.m_bufs.push(vb2);
  529. for (int j = i; j < n; j++)
  530. {
  531. tiles[i].m_tileset->BlitTile(tiles[j].m_id, tiles[j].m_model,
  532. vertex + 6 * (j - i), texture + 6 * (j - i));
  533. }
  534. vb1->Unlock();
  535. vb2->Unlock();
  536. /* Bind texture */
  537. if (tiles[i].m_tileset->GetPalette())
  538. {
  539. if (tiles[i].m_tileset->GetTexture())
  540. shader->SetUniform(uni_tex, tiles[i].m_tileset->GetTexture()->GetTextureUniform(), 0);
  541. if (tiles[i].m_tileset->GetPalette()->GetTexture())
  542. shader->SetUniform(uni_pal, tiles[i].m_tileset->GetPalette()->GetTexture()->GetTextureUniform(), 1);
  543. }
  544. else
  545. {
  546. shader->SetUniform(uni_tex, 0);
  547. if (tiles[i].m_tileset->GetTexture())
  548. shader->SetUniform(uni_tex, tiles[i].m_tileset->GetTexture()->GetTextureUniform(), 0);
  549. tiles[i].m_tileset->Bind();
  550. }
  551. shader->SetUniform(uni_texsize,
  552. (vec2)tiles[i].m_tileset->GetTextureSize());
  553. /* Bind vertex and texture coordinate buffers */
  554. m_tile_api.m_vdecl->Bind();
  555. m_tile_api.m_vdecl->SetStream(vb1, attr_pos);
  556. m_tile_api.m_vdecl->SetStream(vb2, attr_tex);
  557. /* Draw arrays */
  558. m_tile_api.m_vdecl->DrawElements(MeshPrimitive::Triangles, 0, (n - i) * 6);
  559. m_tile_api.m_vdecl->Unbind();
  560. tiles[i].m_tileset->Unbind();
  561. }
  562. tiles.clear();
  563. shader->Unbind();
  564. if (!m_tile_api.m_palette_shader)
  565. break;
  566. }
  567. #if (defined LOL_USE_GLEW || defined HAVE_GL_2X) && !defined HAVE_GLES_2X
  568. glDisable(GL_TEXTURE_2D);
  569. #endif
  570. }
  571. // FIXME: get rid of the delta time argument
  572. // XXX: rename to Blit()
  573. void Scene::render_lines(float seconds)
  574. {
  575. render_context rc(m_renderer);
  576. if (!m_line_api.m_lines.count())
  577. return;
  578. rc.depth_func(DepthFunc::LessOrEqual);
  579. rc.blend_func(BlendFunc::SrcAlpha, BlendFunc::OneMinusSrcAlpha);
  580. rc.blend_equation(BlendEquation::Add, BlendEquation::Max);
  581. rc.alpha_func(AlphaFunc::GreaterOrEqual, 0.01f);
  582. int linecount = (int)m_line_api.m_lines.count();
  583. if (!m_line_api.m_shader)
  584. m_line_api.m_shader = Shader::Create(LOLFX_RESOURCE_NAME(gpu_line));
  585. array<vec4, vec4, vec4, vec4> buff;
  586. buff.resize(linecount);
  587. int real_linecount = 0;
  588. mat4 const inv_view_proj = inverse(GetCamera()->GetProjection() * GetCamera()->GetView());
  589. for (int i = 0; i < linecount; i++)
  590. {
  591. if (m_line_api.m_lines[i].m5 & m_line_api.m_debug_mask)
  592. {
  593. buff[real_linecount].m1 = vec4(m_line_api.m_lines[i].m1, (float)m_line_api.m_lines[i].m6);
  594. buff[real_linecount].m2 = m_line_api.m_lines[i].m3;
  595. buff[real_linecount].m3 = vec4(m_line_api.m_lines[i].m2, (float)m_line_api.m_lines[i].m7);
  596. buff[real_linecount].m4 = m_line_api.m_lines[i].m3;
  597. real_linecount++;
  598. }
  599. m_line_api.m_lines[i].m4 -= seconds;
  600. if (m_line_api.m_lines[i].m4 < 0.f)
  601. {
  602. m_line_api.m_lines.remove_swap(i--);
  603. linecount--;
  604. }
  605. }
  606. auto vb = std::make_shared<VertexBuffer>(buff.bytes());
  607. float *vertex = (float *)vb->Lock(0, 0);
  608. memcpy(vertex, buff.data(), buff.bytes());
  609. vb->Unlock();
  610. m_line_api.m_shader->Bind();
  611. ShaderUniform uni_mat, uni_tex;
  612. ShaderAttrib attr_pos, attr_col;
  613. attr_pos = m_line_api.m_shader->GetAttribLocation(VertexUsage::Position, 0);
  614. attr_col = m_line_api.m_shader->GetAttribLocation(VertexUsage::Color, 0);
  615. m_line_api.m_shader->Bind();
  616. uni_mat = m_line_api.m_shader->GetUniformLocation("u_projection");
  617. m_line_api.m_shader->SetUniform(uni_mat, GetCamera()->GetProjection());
  618. uni_mat = m_line_api.m_shader->GetUniformLocation("u_view");
  619. m_line_api.m_shader->SetUniform(uni_mat, GetCamera()->GetView());
  620. m_line_api.m_vdecl->Bind();
  621. m_line_api.m_vdecl->SetStream(vb, attr_pos, attr_col);
  622. m_line_api.m_vdecl->DrawElements(MeshPrimitive::Lines, 0, 2 * real_linecount);
  623. m_line_api.m_vdecl->Unbind();
  624. m_line_api.m_shader->Unbind();
  625. //m_line_api.m_lines.clear();
  626. }
  627. } /* namespace lol */