466 řádky
14 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright: (c) 2010-2012 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://sam.zoy.org/projects/COPYING.WTFPL for more details.
  9. //
  10. #if defined HAVE_CONFIG_H
  11. # include "config.h"
  12. #endif
  13. #include <cstdlib>
  14. #include <cmath>
  15. #ifdef WIN32
  16. # define WIN32_LEAN_AND_MEAN
  17. # include <windows.h>
  18. #endif
  19. #include "core.h"
  20. #include "lolgl.h"
  21. namespace lol
  22. {
  23. struct Tile
  24. {
  25. TileSet *tileset;
  26. uint32_t prio;
  27. vec3 pos;
  28. vec2 scale;
  29. int id, o;
  30. };
  31. static Shader *stdshader = NULL;
  32. /*
  33. * Scene implementation class
  34. */
  35. class SceneData
  36. {
  37. friend class Scene;
  38. private:
  39. static int Compare(void const *p1, void const *p2)
  40. {
  41. Tile const *t1 = (Tile const *)p1;
  42. Tile const *t2 = (Tile const *)p2;
  43. return t2->prio - t1->prio;
  44. }
  45. mat4 model_matrix;
  46. Tile *tiles;
  47. int ntiles;
  48. float angle;
  49. #if defined USE_D3D9 || defined _XBOX
  50. # if defined __GNUC__
  51. # warning Scene not implemented
  52. # else
  53. # define STR0(x) #x
  54. # define STR(x) STR0(x)
  55. # pragma message(__FILE__ "(" STR(__LINE__) "): warning: Scene not implemented")
  56. # undef STR
  57. # undef STR0
  58. # endif
  59. #else
  60. #if defined HAVE_GL_2X && !defined __APPLE__
  61. GLuint vao;
  62. #endif
  63. GLuint *bufs;
  64. int nbufs;
  65. #endif
  66. static Scene *scene;
  67. };
  68. Scene *SceneData::scene = NULL;
  69. /*
  70. * Public Scene class
  71. */
  72. Scene::Scene(float angle)
  73. : data(new SceneData())
  74. {
  75. data->tiles = 0;
  76. data->ntiles = 0;
  77. data->angle = angle;
  78. #if defined USE_D3D9 || defined _XBOX
  79. /* TODO */
  80. #else
  81. data->bufs = 0;
  82. data->nbufs = 0;
  83. # if defined HAVE_GL_2X && !defined __APPLE__
  84. glGenVertexArrays(1, &data->vao);
  85. # endif
  86. #endif
  87. }
  88. Scene::~Scene()
  89. {
  90. #if defined USE_D3D9 || defined _XBOX
  91. /* TODO */
  92. #else
  93. /* FIXME: this must be done while the GL context is still active.
  94. * Change the code architecture to make sure of that. */
  95. /* XXX: The test is necessary because of a crash with PSGL. */
  96. if (data->nbufs > 0)
  97. glDeleteBuffers(data->nbufs, data->bufs);
  98. #if defined HAVE_GL_2X && !defined __APPLE__
  99. glDeleteVertexArrays(1, &data->vao);
  100. #endif
  101. free(data->bufs);
  102. #endif
  103. delete data;
  104. }
  105. Scene *Scene::GetDefault()
  106. {
  107. if (!SceneData::scene)
  108. SceneData::scene = new Scene(0.0f);
  109. return SceneData::scene;
  110. }
  111. void Scene::Reset()
  112. {
  113. if (SceneData::scene)
  114. delete SceneData::scene;
  115. SceneData::scene = NULL;
  116. }
  117. void Scene::AddTile(TileSet *tileset, int id, vec3 pos, int o, vec2 scale)
  118. {
  119. #if !defined USE_D3D9 && !defined _XBOX
  120. if ((data->ntiles % 1024) == 0)
  121. data->tiles = (Tile *)realloc(data->tiles,
  122. (data->ntiles + 1024) * sizeof(Tile));
  123. /* FIXME: this sorting only works for a 45-degree camera */
  124. data->tiles[data->ntiles].prio = -pos.y - 2 * 32 * pos.z + (o ? 0 : 32);
  125. data->tiles[data->ntiles].tileset = tileset;
  126. data->tiles[data->ntiles].id = id;
  127. data->tiles[data->ntiles].pos = pos;
  128. data->tiles[data->ntiles].o = o;
  129. data->tiles[data->ntiles].scale = scale;
  130. data->ntiles++;
  131. #endif
  132. }
  133. void Scene::Render() // XXX: rename to Blit()
  134. {
  135. #if !defined USE_D3D9 && !defined _XBOX /* No WPOS on Xbox, what about Win32? */
  136. if (!stdshader)
  137. {
  138. #if !defined _XBOX && !defined __CELLOS_LV2__
  139. stdshader = Shader::Create(
  140. #if !defined HAVE_GLES_2X
  141. "#version 130\n"
  142. #endif
  143. "\n"
  144. #if defined HAVE_GLES_2X
  145. "attribute vec3 in_Position;\n"
  146. "attribute vec2 in_TexCoord;\n"
  147. "varying vec2 pass_TexCoord;\n"
  148. #else
  149. "in vec3 in_Position;\n"
  150. "in vec2 in_TexCoord;\n"
  151. #endif
  152. "uniform mat4 proj_matrix;\n"
  153. "uniform mat4 view_matrix;\n"
  154. "uniform mat4 model_matrix;\n"
  155. "\n"
  156. "void main()\n"
  157. "{\n"
  158. " gl_Position = proj_matrix * view_matrix * model_matrix"
  159. " * vec4(in_Position, 1.0);\n"
  160. #if defined HAVE_GLES_2X
  161. " pass_TexCoord = in_TexCoord;\n"
  162. #else
  163. " gl_TexCoord[0] = vec4(in_TexCoord, 0.0, 0.0);\n"
  164. #endif
  165. "}\n",
  166. #if !defined HAVE_GLES_2X
  167. "#version 130\n"
  168. #else
  169. "precision mediump float;\n"
  170. #endif
  171. "\n"
  172. "uniform sampler2D in_Texture;\n"
  173. #if defined HAVE_GLES_2X
  174. "varying vec2 pass_TexCoord;\n"
  175. #endif
  176. "\n"
  177. "void main()\n"
  178. "{\n"
  179. #if defined HAVE_GLES_2X
  180. " vec4 col = texture2D(in_Texture, pass_TexCoord);\n"
  181. //" vec4 col = vec4(0.5, 1.0, 0.0, 0.5);\n"
  182. //" vec4 col = vec4(pass_TexCoord * 4.0, 0.0, 0.25);\n"
  183. #else
  184. " vec4 col = texture2D(in_Texture, vec2(gl_TexCoord[0]));\n"
  185. #endif
  186. #if 0
  187. " float mul = 2.0;\n"
  188. #if 1
  189. " vec2 d1 = mod(vec2(gl_FragCoord), vec2(2.0, 2.0));\n"
  190. " float t1 = mod(3.0 * d1.x + 2.0 * d1.y, 4.0);\n"
  191. " float dx2 = mod(floor(gl_FragCoord.x * 0.5), 2.0);\n"
  192. " float dy2 = mod(floor(gl_FragCoord.y * 0.5), 2.0);\n"
  193. " float t2 = mod(3.0 * dx2 + 2.0 * dy2, 4.0);\n"
  194. " float dx3 = mod(floor(gl_FragCoord.x * 0.25), 2.0);\n"
  195. " float dy3 = mod(floor(gl_FragCoord.y * 0.25), 2.0);\n"
  196. " float t3 = mod(3.0 * dx3 + 2.0 * dy3, 4.0);\n"
  197. " t1 = (1.0 + 16.0 * t1 + 4.0 * t2 + t3) / 65.0;\n"
  198. " t2 = t1;\n"
  199. " t3 = t1;\n"
  200. #else
  201. " float rand = sin(gl_FragCoord.x * 1.23456) * 123.456\n"
  202. " + cos(gl_FragCoord.y * 2.34567) * 789.012;\n"
  203. " float t1 = mod(sin(rand) * 17.13043, 1.0);\n"
  204. " float t2 = mod(sin(rand) * 27.13043, 1.0);\n"
  205. " float t3 = mod(sin(rand) * 37.13043, 1.0);\n"
  206. #endif
  207. " float fracx = fract(col.x * mul);\n"
  208. " float fracy = fract(col.y * mul);\n"
  209. " float fracz = fract(col.z * mul);\n"
  210. " fracx = fracx > t1 ? 1.0 : 0.0;\n"
  211. " fracy = fracy > t2 ? 1.0 : 0.0;\n"
  212. " fracz = fracz > t3 ? 1.0 : 0.0;\n"
  213. " col.x = (floor(col.x * mul) + fracx) / mul;\n"
  214. " col.y = (floor(col.y * mul) + fracy) / mul;\n"
  215. " col.z = (floor(col.z * mul) + fracz) / mul;\n"
  216. #endif
  217. " gl_FragColor = col;\n"
  218. "}\n");
  219. #else
  220. stdshader = Shader::Create(
  221. "void main(float4 in_Position : POSITION,"
  222. " float2 in_TexCoord : TEXCOORD0,"
  223. " uniform float4x4 proj_matrix,"
  224. " uniform float4x4 view_matrix,"
  225. " uniform float4x4 model_matrix,"
  226. " out float2 out_TexCoord : TEXCOORD0,"
  227. " out float4 out_Position : POSITION)"
  228. "{"
  229. " out_Position = mul(proj_matrix, mul(view_matrix, mul(model_matrix, in_Position)));"
  230. " out_TexCoord = in_TexCoord;"
  231. "}",
  232. "void main(float2 in_TexCoord : TEXCOORD0,"
  233. " float4 in_FragCoord : WPOS,"
  234. " uniform sampler2D tex,"
  235. " out float4 out_FragColor : COLOR)"
  236. "{"
  237. " float4 col = tex2D(tex, in_TexCoord);"
  238. #if 0
  239. " float mul = 2.0;\n"
  240. " float t1, t2, t3;\n"
  241. #if 1
  242. " float dx1 = frac(in_FragCoord.x * 0.5) * 2.0;\n"
  243. " float dy1 = frac(in_FragCoord.y * 0.5) * 2.0;\n"
  244. " t1 = frac((3.0 * dx1 + 2.0 * dy1) / 4.0) * 4.0;\n"
  245. " float dx2 = frac(floor(in_FragCoord.x * 0.5) * 0.5) * 2.0;\n"
  246. " float dy2 = frac(floor(in_FragCoord.y * 0.5) * 0.5) * 2.0;\n"
  247. " t2 = frac((3.0 * dx2 + 2.0 * dy2) / 4.0) * 4.0;\n"
  248. " float dx3 = frac(floor(in_FragCoord.x * 0.25) * 0.5) * 2.0;\n"
  249. " float dy3 = frac(floor(in_FragCoord.y * 0.25) * 0.5) * 2.0;\n"
  250. " t3 = frac((3.0 * dx3 + 2.0 * dy3) / 4.0) * 4.0;\n"
  251. " t1 = (1.0 + 4.0 * t1 + t2) / 17.0;\n"
  252. " t2 = t1;\n"
  253. " t3 = t1;\n"
  254. #else
  255. " float rand = sin(in_FragCoord.x * 1.23456) * 123.456\n"
  256. " + cos(in_FragCoord.y * 2.34567) * 789.012;\n"
  257. " t1 = frac(sin(rand) * 17.13043);\n"
  258. " t2 = frac(sin(rand) * 27.13043);\n"
  259. " t3 = frac(sin(rand) * 37.13043);\n"
  260. #endif
  261. " float fracx = frac(col.x * mul);\n"
  262. " float fracy = frac(col.y * mul);\n"
  263. " float fracz = frac(col.z * mul);\n"
  264. " fracx = fracx > t1 ? 1.0 : 0.0;\n"
  265. " fracy = fracy > t2 ? 1.0 : 0.0;\n"
  266. " fracz = fracz > t3 ? 1.0 : 0.0;\n"
  267. " col.x = (floor(col.x * mul) + fracx) / mul;\n"
  268. " col.y = (floor(col.y * mul) + fracy) / mul;\n"
  269. " col.z = (floor(col.z * mul) + fracz) / mul;\n"
  270. #endif
  271. " out_FragColor = col;"
  272. "}");
  273. #endif
  274. }
  275. #if 0
  276. // Randomise, then sort.
  277. for (int i = 0; i < data->ntiles; i++)
  278. {
  279. Tile tmp = data->tiles[i];
  280. int j = rand() % data->ntiles;
  281. data->tiles[i] = data->tiles[j];
  282. data->tiles[j] = tmp;
  283. }
  284. #endif
  285. qsort(data->tiles, data->ntiles, sizeof(Tile), SceneData::Compare);
  286. // XXX: debug stuff
  287. data->model_matrix = mat4::translate(320.0f, 240.0f, 0.0f);
  288. data->model_matrix *= mat4::rotate(-data->angle, 1.0f, 0.0f, 0.0f);
  289. #if 0
  290. static float f = 0.0f;
  291. f += 0.01f;
  292. data->model_matrix *= mat4::rotate(6.0f * sinf(f), 1.0f, 0.0f, 0.0f);
  293. data->model_matrix *= mat4::rotate(17.0f * cosf(f), 0.0f, 0.0f, 1.0f);
  294. #endif
  295. data->model_matrix *= mat4::translate(-320.0f, -240.0f, 0.0f);
  296. // XXX: end of debug stuff
  297. ShaderUniform uni_mat, uni_tex;
  298. int attr_pos, attr_tex;
  299. #if !defined __CELLOS_LV2__
  300. attr_pos = stdshader->GetAttribLocation("in_Position");
  301. attr_tex = stdshader->GetAttribLocation("in_TexCoord");
  302. #endif
  303. stdshader->Bind();
  304. uni_mat = stdshader->GetUniformLocation("proj_matrix");
  305. stdshader->SetUniform(uni_mat, Video::GetProjMatrix());
  306. uni_mat = stdshader->GetUniformLocation("view_matrix");
  307. stdshader->SetUniform(uni_mat, Video::GetViewMatrix());
  308. uni_mat = stdshader->GetUniformLocation("model_matrix");
  309. stdshader->SetUniform(uni_mat, data->model_matrix);
  310. uni_tex = stdshader->GetUniformLocation("in_Texture");
  311. stdshader->SetUniform(uni_tex, 0);
  312. #if defined USE_D3D9 || defined _XBOX
  313. /* TODO */
  314. #else
  315. #if !defined HAVE_GLES_2X
  316. glEnable(GL_TEXTURE_2D);
  317. #endif
  318. glEnable(GL_DEPTH_TEST);
  319. glDepthFunc(GL_LEQUAL);
  320. #if defined HAVE_GL_2X && !defined __APPLE__
  321. glEnable(GL_ALPHA_TEST);
  322. glAlphaFunc(GL_GEQUAL, 0.01f);
  323. #endif
  324. glEnable(GL_BLEND);
  325. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  326. #endif
  327. for (int buf = 0, i = 0, n; i < data->ntiles; i = n, buf += 2)
  328. {
  329. #if defined USE_D3D9 || defined _XBOX
  330. /* TODO */
  331. #else
  332. /* Generate new vertex / texture coord buffers if necessary */
  333. if (buf + 2 > data->nbufs)
  334. {
  335. data->bufs = (uint32_t *)realloc(data->bufs, (buf + 2) * sizeof(uint32_t));
  336. glGenBuffers(buf + 2 - data->nbufs, data->bufs + data->nbufs);
  337. data->nbufs = buf + 2;
  338. }
  339. #endif
  340. /* Count how many quads will be needed */
  341. for (n = i + 1; n < data->ntiles; n++)
  342. if (data->tiles[i].tileset != data->tiles[n].tileset)
  343. break;
  344. /* Create a vertex array object */
  345. float *vertex = (float *)malloc(6 * 3 * (n - i) * sizeof(float));
  346. float *texture = (float *)malloc(6 * 2 * (n - i) * sizeof(float));
  347. for (int j = i; j < n; j++)
  348. {
  349. data->tiles[i].tileset->BlitTile(data->tiles[j].id,
  350. data->tiles[j].pos, data->tiles[j].o,
  351. data->tiles[j].scale,
  352. vertex + 18 * (j - i), texture + 12 * (j - i));
  353. }
  354. stdshader->Bind();
  355. /* Bind texture */
  356. data->tiles[i].tileset->Bind();
  357. /* Bind vertex, color and texture coordinate buffers */
  358. #if defined HAVE_GL_2X && !defined __APPLE__
  359. glBindVertexArray(data->vao);
  360. #endif
  361. #if defined USE_D3D9 || defined _XBOX
  362. /* TODO */
  363. #else
  364. #if !defined __CELLOS_LV2__ // Use cgGLEnableClientState etc.
  365. glEnableVertexAttribArray(attr_pos);
  366. glEnableVertexAttribArray(attr_tex);
  367. glBindBuffer(GL_ARRAY_BUFFER, data->bufs[buf]);
  368. glBufferData(GL_ARRAY_BUFFER, 18 * (n - i) * sizeof(GLfloat),
  369. vertex, GL_STATIC_DRAW);
  370. glVertexAttribPointer(attr_pos, 3, GL_FLOAT, GL_FALSE, 0, 0);
  371. glBindBuffer(GL_ARRAY_BUFFER, data->bufs[buf + 1]);
  372. glBufferData(GL_ARRAY_BUFFER, 12 * (n - i) * sizeof(GLfloat),
  373. texture, GL_STATIC_DRAW);
  374. glVertexAttribPointer(attr_tex, 2, GL_FLOAT, GL_FALSE, 0, 0);
  375. #else
  376. glEnableClientState(GL_VERTEX_ARRAY);
  377. glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  378. glVertexPointer(3, GL_FLOAT, 0, vertex);
  379. glTexCoordPointer(2, GL_FLOAT, 0, texture);
  380. #endif
  381. /* Draw arrays */
  382. glDrawArrays(GL_TRIANGLES, 0, (n - i) * 6);
  383. #if defined HAVE_GL_2X && !defined __APPLE__
  384. glBindVertexArray(0);
  385. #endif
  386. #if !defined __CELLOS_LV2__ // Use cgGLEnableClientState etc.
  387. glDisableVertexAttribArray(attr_pos);
  388. glDisableVertexAttribArray(attr_tex);
  389. #else
  390. glDisableClientState(GL_VERTEX_ARRAY);
  391. glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  392. #endif
  393. #endif
  394. free(vertex);
  395. free(texture);
  396. }
  397. free(data->tiles);
  398. data->tiles = 0;
  399. data->ntiles = 0;
  400. #if defined USE_D3D9 || defined _XBOX
  401. /* TODO */
  402. #else
  403. #if !defined HAVE_GLES_2X
  404. glDisable(GL_TEXTURE_2D);
  405. #endif
  406. glDisable(GL_DEPTH_TEST);
  407. #if defined HAVE_GL_2X && !defined __APPLE__
  408. glDisable(GL_ALPHA_TEST);
  409. #endif
  410. glDisable(GL_BLEND);
  411. #endif
  412. #endif /* _XBOX || USE_D3D9 */
  413. }
  414. } /* namespace lol */