Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 

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