Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.
 
 
 

761 řádky
21 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright © 2010—2020 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. std::vector<Scene*> Scene::g_scenes;
  33. static std::vector<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.push_back(display);
  49. }
  50. size_t SceneDisplay::GetCount()
  51. {
  52. return g_scene_displays.size();
  53. }
  54. SceneDisplay* SceneDisplay::GetDisplay(int index)
  55. {
  56. return g_scene_displays[index];
  57. }
  58. void SceneDisplay::DestroyAll()
  59. {
  60. for (SceneDisplay* display : g_scene_displays)
  61. delete display;
  62. g_scene_displays.clear();
  63. }
  64. void SceneDisplay::Enable()
  65. {
  66. // TODO: PROFILER STUFF
  67. }
  68. void SceneDisplay::Disable()
  69. {
  70. // TODO: PROFILER STUFF
  71. }
  72. /*
  73. * Primitive implementation class
  74. */
  75. void PrimitiveSource::Render(Scene& scene) { UNUSED(scene); }
  76. void PrimitiveRenderer::Render(Scene& scene, std::shared_ptr<PrimitiveSource> primitive)
  77. {
  78. UNUSED(scene);
  79. UNUSED(primitive);
  80. }
  81. /*
  82. * Scene implementation class
  83. */
  84. uint64_t Scene::g_used_id = 1;
  85. mutex Scene::g_prim_mutex;
  86. std::map<uintptr_t, std::vector<std::shared_ptr<PrimitiveSource>>> Scene::g_prim_sources;
  87. /*
  88. * Public Scene class
  89. */
  90. Scene::Scene(ivec2 size)
  91. : m_size(size),
  92. m_wanted_size(size),
  93. m_renderer(std::make_shared<Renderer>(size))
  94. {
  95. /* TODO: FIX THAT */
  96. ASSERT(!(g_used_id & ((uint64_t)1 << 63)), "Too many scenes !!!!");
  97. m_mask_id = g_used_id;
  98. g_used_id = g_used_id << 1;
  99. for (int i = 0; i < 4; ++i)
  100. m_renderbuffer[i] = std::make_shared<Framebuffer>(m_size);
  101. m_pp.blit_shader = Shader::Create(LOLFX_RESOURCE_NAME(gpu_blit));
  102. m_pp.pp_shader = Shader::Create(LOLFX_RESOURCE_NAME(gpu_postprocess));
  103. m_pp.blit_pos_attr = m_pp.blit_shader->GetAttribLocation(VertexUsage::Position, 0);
  104. m_pp.pp_pos_attr = m_pp.pp_shader->GetAttribLocation(VertexUsage::Position, 0);
  105. m_pp.quad_vdecl = std::make_shared<VertexDeclaration>(VertexStream<vec2>(VertexUsage::Position));
  106. m_pp.m_buffer_uni[0][0] = m_pp.blit_shader->GetUniformLocation("u_buffer");
  107. m_pp.m_buffer_uni[1][0] = m_pp.pp_shader->GetUniformLocation("u_buffer");
  108. m_pp.m_buffer_uni[1][1] = m_pp.pp_shader->GetUniformLocation("u_prev_buffer");
  109. m_pp.m_buffer_uni[1][2] = m_pp.pp_shader->GetUniformLocation("u_prev_final");
  110. std::vector<vec2> quad { vec2( 1.0, 1.0), vec2(-1.0, -1.0), vec2( 1.0, -1.0),
  111. vec2(-1.0, -1.0), vec2( 1.0, 1.0), vec2(-1.0, 1.0), };
  112. m_pp.quad_vbo = std::make_shared<VertexBuffer>(quad.size() * sizeof(vec2));
  113. m_pp.quad_vbo->set_data(quad.data(), quad.size() * sizeof(vec2));
  114. /* Create a default orthographic camera, in case the user doesn’t. */
  115. m_default_cam = new Camera();
  116. mat4 proj = mat4::ortho(0.f, (float)m_size.x, 0.f, (float)m_size.y, -1000.f, 1000.f);
  117. m_default_cam->SetProjection(proj);
  118. PushCamera(m_default_cam);
  119. m_tile_api.m_cam = -1;
  120. m_tile_api.m_shader = 0;
  121. m_tile_api.m_palette_shader = 0;
  122. m_tile_api.m_vdecl = std::make_shared<VertexDeclaration>(VertexStream<vec3>(VertexUsage::Position),
  123. VertexStream<vec2>(VertexUsage::TexCoord));
  124. m_line_api.m_shader = 0;
  125. m_line_api.m_vdecl = std::make_shared<VertexDeclaration>(VertexStream<vec4,vec4>(VertexUsage::Position, VertexUsage::Color));
  126. m_line_api.m_debug_mask = 1;
  127. }
  128. void Scene::resize(ivec2 size)
  129. {
  130. m_wanted_size = size;
  131. }
  132. Scene::~Scene()
  133. {
  134. PopCamera(m_default_cam);
  135. /* FIXME: this must be done while the GL context is still active.
  136. * Change the code architecture to make sure of that. */
  137. /* FIXME: also, make sure we do not add code to Reset() that will
  138. * reallocate stuff */
  139. Reset();
  140. }
  141. void Scene::AddNew(ivec2 size)
  142. {
  143. Scene::g_scenes.push_back(new Scene(size));
  144. }
  145. void Scene::DestroyScene(Scene* scene)
  146. {
  147. remove_item(Scene::g_scenes, scene);
  148. delete scene;
  149. }
  150. void Scene::DestroyAll()
  151. {
  152. while (Scene::g_scenes.size())
  153. {
  154. delete Scene::g_scenes.back();
  155. Scene::g_scenes.pop_back();
  156. }
  157. }
  158. size_t Scene::GetCount()
  159. {
  160. return g_scenes.size();
  161. }
  162. bool Scene::IsReady(int index)
  163. {
  164. return 0 <= index && index < int(g_scenes.size()) && !!g_scenes[index];
  165. }
  166. Scene& Scene::GetScene(int index)
  167. {
  168. return *g_scenes[index];
  169. }
  170. void Scene::Link(entity* entity)
  171. {
  172. entity->m_scene_mask |= m_mask_id;
  173. }
  174. bool Scene::IsRelevant(entity* entity)
  175. {
  176. return !!(entity->m_scene_mask & m_mask_id);
  177. }
  178. Camera* Scene::GetCamera(int cam_idx)
  179. {
  180. return (0 <= cam_idx && cam_idx < int(m_camera_stack.size())) ?
  181. m_camera_stack[cam_idx] :
  182. m_camera_stack.back();
  183. }
  184. int Scene::PushCamera(Camera *cam)
  185. {
  186. Ticker::Ref(cam);
  187. m_camera_stack.push_back(cam);
  188. return int(m_camera_stack.size()) - 1;
  189. }
  190. void Scene::PopCamera(Camera *cam)
  191. {
  192. /* Parse from the end because that’s probably where we’ll find
  193. * our camera first. */
  194. for (size_t i = m_camera_stack.size(); i--;)
  195. {
  196. if (m_camera_stack[i] == cam)
  197. {
  198. Ticker::Unref(cam);
  199. remove_at(m_camera_stack, i);
  200. return;
  201. }
  202. }
  203. ASSERT(false, "trying to pop a nonexistent camera from the scene");
  204. }
  205. void Scene::SetTileCam(int cam_idx)
  206. {
  207. m_tile_api.m_cam = cam_idx;
  208. }
  209. void Scene::Reset()
  210. {
  211. /* New scenegraph: Release fire&forget primitives */
  212. for (uintptr_t key : keys(m_prim_renderers))
  213. {
  214. for (size_t idx = 0; idx < m_prim_renderers[key].size(); ++idx)
  215. if (m_prim_renderers[key][idx]->m_fire_and_forget)
  216. ReleasePrimitiveRenderer(idx--, key);
  217. }
  218. m_tile_api.m_bufs.clear();
  219. m_tile_api.m_lights.clear();
  220. }
  221. //
  222. // Primitive source stuff
  223. //
  224. int Scene::HasPrimitiveSource(uintptr_t key)
  225. {
  226. int count;
  227. g_prim_mutex.lock();
  228. {
  229. count = int(g_prim_sources[key].size());
  230. }
  231. g_prim_mutex.unlock();
  232. return count;
  233. }
  234. int Scene::AddPrimitiveSource(uintptr_t key, std::shared_ptr<PrimitiveSource> source)
  235. {
  236. int count;
  237. g_prim_mutex.lock();
  238. {
  239. count = int(g_prim_sources[key].size());
  240. g_prim_sources[key].push_back(source);
  241. }
  242. g_prim_mutex.unlock();
  243. return count;
  244. }
  245. void Scene::SetPrimitiveSource(int index, uintptr_t key, std::shared_ptr<PrimitiveSource> source)
  246. {
  247. ASSERT(source);
  248. ASSERT(index >= 0);
  249. // Keep reference to old source until AFTER we release the lock
  250. std::shared_ptr<PrimitiveSource> old;
  251. g_prim_mutex.lock();
  252. {
  253. if (index < int(g_prim_sources[key].size()))
  254. old = g_prim_sources[key][index];
  255. else
  256. g_prim_sources[key].resize(index + 1);
  257. g_prim_sources[key][index] = source;
  258. }
  259. g_prim_mutex.unlock();
  260. }
  261. void Scene::ReleasePrimitiveSource(int index, uintptr_t key)
  262. {
  263. std::shared_ptr<PrimitiveSource> old;
  264. g_prim_mutex.lock();
  265. {
  266. ASSERT(0 <= index && index < int(g_prim_sources[key].size()));
  267. old = g_prim_sources[key][index];
  268. remove_at(g_prim_sources[key], index);
  269. }
  270. g_prim_mutex.unlock();
  271. }
  272. void Scene::ReleaseAllPrimitiveSources(uintptr_t key)
  273. {
  274. // Delete oldies AFTER having released the lock
  275. std::vector<std::shared_ptr<PrimitiveSource>> oldies;
  276. g_prim_mutex.lock();
  277. {
  278. oldies.reserve(g_prim_sources[key].size());
  279. for (auto source : g_prim_sources[key])
  280. oldies.push_back(source);
  281. g_prim_sources[key].clear();
  282. }
  283. g_prim_mutex.unlock();
  284. }
  285. //
  286. // Primitive renderer stuff
  287. //
  288. int Scene::HasPrimitiveRenderer(uintptr_t key)
  289. {
  290. return int(m_prim_renderers[key].size());
  291. }
  292. void Scene::AddPrimitiveRenderer(uintptr_t key, std::shared_ptr<PrimitiveRenderer> renderer)
  293. {
  294. renderer->m_fire_and_forget = true;
  295. m_prim_renderers[key].push_back(renderer);
  296. }
  297. void Scene::SetPrimitiveRenderer(int index, uintptr_t key, std::shared_ptr<PrimitiveRenderer> renderer)
  298. {
  299. ASSERT(renderer);
  300. ASSERT(index >= 0);
  301. if (index >= int(m_prim_renderers[key].size()))
  302. m_prim_renderers[key].resize(index + 1);
  303. m_prim_renderers[key][index] = renderer;
  304. }
  305. void Scene::ReleasePrimitiveRenderer(int index, uintptr_t key)
  306. {
  307. remove_at(m_prim_renderers[key], index);
  308. }
  309. void Scene::ReleaseAllPrimitiveRenderers(uintptr_t key)
  310. {
  311. m_prim_renderers[key].clear();
  312. }
  313. void Scene::AddTile(TileSet *tileset, int id, vec3 pos, vec2 scale, float radians)
  314. {
  315. ASSERT(id < tileset->GetTileCount());
  316. ivec2 size = tileset->GetTileSize(id);
  317. mat4 model = mat4::translate(pos)
  318. * mat4::scale(scale.x, scale.y, 1.f)
  319. * mat4::translate(size.x * 0.5f, size.y * 0.5f, 0.f)
  320. * mat4::rotate(scale.x * scale.y < 0 ? radians : -radians,
  321. vec3::axis_z);
  322. AddTile(tileset, id, model);
  323. }
  324. void Scene::AddTile(TileSet *tileset, int id, mat4 model)
  325. {
  326. ASSERT(id < tileset->GetTileCount());
  327. Tile t;
  328. t.m_model = model;
  329. t.m_tileset = tileset;
  330. t.m_id = id;
  331. if (tileset->GetPalette())
  332. m_tile_api.m_palettes.push_back(t);
  333. else
  334. m_tile_api.m_tiles.push_back(t);
  335. }
  336. void Scene::AddLine(vec3 a, vec3 b, vec4 col)
  337. {
  338. struct line l { a, b, col, -1.f, 0xFFFFFFFF, false, false };
  339. m_line_api.m_lines.push_back(l);
  340. }
  341. void Scene::AddLine(vec3 a, vec3 b, vec4 col, float duration, uint32_t mask)
  342. {
  343. struct line l { a, b, col, duration, mask, false, false };
  344. m_line_api.m_lines.push_back(l);
  345. }
  346. void Scene::AddLight(Light *l)
  347. {
  348. m_tile_api.m_lights.push_back(l);
  349. }
  350. std::vector<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 (size_t idx = 0; idx < m_prim_renderers[key].size(); ++idx)
  469. {
  470. /* TODO: Not sure if thread compliant */
  471. std::shared_ptr<PrimitiveSource> source;
  472. if (idx < g_prim_sources[key].size())
  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.empty() && m_tile_api.m_palettes.empty())
  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.empty())
  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.empty())
  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 (size_t buf = 0, i = 0, n; i < tiles.size(); i = n, buf += 2)
  516. {
  517. /* Count how many quads will be needed */
  518. for (n = i + 1; n < tiles.size(); 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_back(vb1);
  527. m_tile_api.m_bufs.push_back(vb2);
  528. for (size_t 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.empty())
  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. size_t linecount = m_line_api.m_lines.size();
  579. if (!m_line_api.m_shader)
  580. m_line_api.m_shader = Shader::Create(LOLFX_RESOURCE_NAME(gpu_line));
  581. std::vector<std::tuple<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. UNUSED(inv_view_proj);
  586. for (size_t i = 0; i < linecount; i++)
  587. {
  588. if (m_line_api.m_lines[i].mask & m_line_api.m_debug_mask)
  589. {
  590. std::get<0>(buff[real_linecount]) = vec4(m_line_api.m_lines[i].a, (float)m_line_api.m_lines[i].wtf1);
  591. std::get<1>(buff[real_linecount]) = m_line_api.m_lines[i].col;
  592. std::get<2>(buff[real_linecount]) = vec4(m_line_api.m_lines[i].b, (float)m_line_api.m_lines[i].wtf2);
  593. std::get<3>(buff[real_linecount]) = m_line_api.m_lines[i].col;
  594. real_linecount++;
  595. }
  596. m_line_api.m_lines[i].duration -= seconds;
  597. if (m_line_api.m_lines[i].duration < 0.f)
  598. {
  599. remove_at(m_line_api.m_lines, i--);
  600. linecount--;
  601. }
  602. }
  603. auto vb = std::make_shared<VertexBuffer>(buff.size() * sizeof(buff[0]));
  604. vb->set_data(buff.data(), buff.size() * sizeof(buff[0]));
  605. m_line_api.m_shader->Bind();
  606. ShaderUniform uni_mat, uni_tex;
  607. ShaderAttrib attr_pos, attr_col;
  608. attr_pos = m_line_api.m_shader->GetAttribLocation(VertexUsage::Position, 0);
  609. attr_col = m_line_api.m_shader->GetAttribLocation(VertexUsage::Color, 0);
  610. m_line_api.m_shader->Bind();
  611. uni_mat = m_line_api.m_shader->GetUniformLocation("u_projection");
  612. m_line_api.m_shader->SetUniform(uni_mat, GetCamera()->GetProjection());
  613. uni_mat = m_line_api.m_shader->GetUniformLocation("u_view");
  614. m_line_api.m_shader->SetUniform(uni_mat, GetCamera()->GetView());
  615. m_line_api.m_vdecl->Bind();
  616. m_line_api.m_vdecl->SetStream(vb, attr_pos, attr_col);
  617. m_line_api.m_vdecl->DrawElements(MeshPrimitive::Lines, 0, 2 * real_linecount);
  618. m_line_api.m_vdecl->Unbind();
  619. m_line_api.m_shader->Unbind();
  620. //m_line_api.m_lines.clear();
  621. }
  622. } /* namespace lol */