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

796 lines
23 KiB

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