25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.
 
 
 

754 satır
22 KiB

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