Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

406 рядки
13 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. VertexDeclaration *m_vdecl;
  50. VertexBuffer **bufs;
  51. int nbufs;
  52. static Scene *scene;
  53. };
  54. Scene *SceneData::scene = NULL;
  55. /*
  56. * Public Scene class
  57. */
  58. Scene::Scene(float angle)
  59. : data(new SceneData())
  60. {
  61. data->tiles = 0;
  62. data->ntiles = 0;
  63. data->angle = angle;
  64. data->bufs = 0;
  65. data->nbufs = 0;
  66. data->m_vdecl = new VertexDeclaration(VertexStream<vec3>(VertexUsage::Position),
  67. VertexStream<vec2>(VertexUsage::TexCoord));
  68. }
  69. Scene::~Scene()
  70. {
  71. /* FIXME: this must be done while the GL context is still active.
  72. * Change the code architecture to make sure of that. */
  73. /* XXX: The test is necessary because of a crash with PSGL. */
  74. for (int i = 0; i < data->nbufs; i++)
  75. delete data->bufs[i];
  76. free(data->bufs);
  77. delete data->m_vdecl;
  78. delete data;
  79. }
  80. Scene *Scene::GetDefault()
  81. {
  82. if (!SceneData::scene)
  83. SceneData::scene = new Scene(0.0f);
  84. return SceneData::scene;
  85. }
  86. void Scene::Reset()
  87. {
  88. if (SceneData::scene)
  89. delete SceneData::scene;
  90. SceneData::scene = NULL;
  91. }
  92. void Scene::AddTile(TileSet *tileset, int id, vec3 pos, int o, vec2 scale)
  93. {
  94. if ((data->ntiles % 1024) == 0)
  95. data->tiles = (Tile *)realloc(data->tiles,
  96. (data->ntiles + 1024) * sizeof(Tile));
  97. /* FIXME: this sorting only works for a 45-degree camera */
  98. data->tiles[data->ntiles].prio = -pos.y - 2 * 32 * pos.z + (o ? 0 : 32);
  99. data->tiles[data->ntiles].tileset = tileset;
  100. data->tiles[data->ntiles].id = id;
  101. data->tiles[data->ntiles].pos = pos;
  102. data->tiles[data->ntiles].o = o;
  103. data->tiles[data->ntiles].scale = scale;
  104. data->ntiles++;
  105. }
  106. void Scene::Render() // XXX: rename to Blit()
  107. {
  108. if (!stdshader)
  109. {
  110. #if !defined _XBOX && !defined __CELLOS_LV2__ && !defined USE_D3D9
  111. stdshader = Shader::Create(
  112. # if !defined HAVE_GLES_2X
  113. "#version 130\n"
  114. # endif
  115. "\n"
  116. # if defined HAVE_GLES_2X
  117. "attribute vec3 in_Position;\n"
  118. "attribute vec2 in_TexCoord;\n"
  119. "varying vec2 pass_TexCoord;\n"
  120. # else
  121. "in vec3 in_Position;\n"
  122. "in vec2 in_TexCoord;\n"
  123. # endif
  124. "uniform mat4 proj_matrix;\n"
  125. "uniform mat4 view_matrix;\n"
  126. "uniform mat4 model_matrix;\n"
  127. "\n"
  128. "void main()\n"
  129. "{\n"
  130. " gl_Position = proj_matrix * view_matrix * model_matrix"
  131. " * vec4(in_Position, 1.0);\n"
  132. # if defined HAVE_GLES_2X
  133. " pass_TexCoord = in_TexCoord;\n"
  134. # else
  135. " gl_TexCoord[0] = vec4(in_TexCoord, 0.0, 0.0);\n"
  136. # endif
  137. "}\n",
  138. # if !defined HAVE_GLES_2X
  139. "#version 130\n"
  140. # else
  141. "precision mediump float;\n"
  142. # endif
  143. "\n"
  144. "uniform sampler2D in_Texture;\n"
  145. # if defined HAVE_GLES_2X
  146. "varying vec2 pass_TexCoord;\n"
  147. # endif
  148. "\n"
  149. "void main()\n"
  150. "{\n"
  151. # if defined HAVE_GLES_2X
  152. " vec4 col = texture2D(in_Texture, pass_TexCoord);\n"
  153. //" vec4 col = vec4(0.5, 1.0, 0.0, 0.5);\n"
  154. //" vec4 col = vec4(pass_TexCoord * 4.0, 0.0, 0.25);\n"
  155. # else
  156. " vec4 col = texture2D(in_Texture, vec2(gl_TexCoord[0]));\n"
  157. # endif
  158. # if 0
  159. " float mul = 2.0;\n"
  160. # if 1
  161. " vec2 d1 = mod(vec2(gl_FragCoord), vec2(2.0, 2.0));\n"
  162. " float t1 = mod(3.0 * d1.x + 2.0 * d1.y, 4.0);\n"
  163. " float dx2 = mod(floor(gl_FragCoord.x * 0.5), 2.0);\n"
  164. " float dy2 = mod(floor(gl_FragCoord.y * 0.5), 2.0);\n"
  165. " float t2 = mod(3.0 * dx2 + 2.0 * dy2, 4.0);\n"
  166. " float dx3 = mod(floor(gl_FragCoord.x * 0.25), 2.0);\n"
  167. " float dy3 = mod(floor(gl_FragCoord.y * 0.25), 2.0);\n"
  168. " float t3 = mod(3.0 * dx3 + 2.0 * dy3, 4.0);\n"
  169. " t1 = (1.0 + 16.0 * t1 + 4.0 * t2 + t3) / 65.0;\n"
  170. " t2 = t1;\n"
  171. " t3 = t1;\n"
  172. # else
  173. " float rand = sin(gl_FragCoord.x * 1.23456) * 123.456\n"
  174. " + cos(gl_FragCoord.y * 2.34567) * 789.012;\n"
  175. " float t1 = mod(sin(rand) * 17.13043, 1.0);\n"
  176. " float t2 = mod(sin(rand) * 27.13043, 1.0);\n"
  177. " float t3 = mod(sin(rand) * 37.13043, 1.0);\n"
  178. # endif
  179. " float fracx = fract(col.x * mul);\n"
  180. " float fracy = fract(col.y * mul);\n"
  181. " float fracz = fract(col.z * mul);\n"
  182. " fracx = fracx > t1 ? 1.0 : 0.0;\n"
  183. " fracy = fracy > t2 ? 1.0 : 0.0;\n"
  184. " fracz = fracz > t3 ? 1.0 : 0.0;\n"
  185. " col.x = (floor(col.x * mul) + fracx) / mul;\n"
  186. " col.y = (floor(col.y * mul) + fracy) / mul;\n"
  187. " col.z = (floor(col.z * mul) + fracz) / mul;\n"
  188. # endif
  189. " gl_FragColor = col;\n"
  190. "}\n");
  191. #else
  192. stdshader = Shader::Create(
  193. "void main(float4 in_Position : POSITION,"
  194. " float2 in_TexCoord : TEXCOORD0,"
  195. " uniform float4x4 proj_matrix,"
  196. " uniform float4x4 view_matrix,"
  197. " uniform float4x4 model_matrix,"
  198. " out float2 out_TexCoord : TEXCOORD0,"
  199. " out float4 out_Position : POSITION)"
  200. "{"
  201. " out_Position = mul(proj_matrix, mul(view_matrix, mul(model_matrix, in_Position)));"
  202. " out_TexCoord = in_TexCoord;"
  203. "}",
  204. "void main(float2 in_TexCoord : TEXCOORD0,"
  205. # if 0
  206. " float4 in_FragCoord : WPOS,"
  207. # endif
  208. " uniform sampler2D tex,"
  209. " out float4 out_FragColor : COLOR)"
  210. "{"
  211. " float4 col = tex2D(tex, in_TexCoord);"
  212. # if 0
  213. " float mul = 2.0;\n"
  214. " float t1, t2, t3;\n"
  215. # if 1
  216. " float dx1 = frac(in_FragCoord.x * 0.5) * 2.0;\n"
  217. " float dy1 = frac(in_FragCoord.y * 0.5) * 2.0;\n"
  218. " t1 = frac((3.0 * dx1 + 2.0 * dy1) / 4.0) * 4.0;\n"
  219. " float dx2 = frac(floor(in_FragCoord.x * 0.5) * 0.5) * 2.0;\n"
  220. " float dy2 = frac(floor(in_FragCoord.y * 0.5) * 0.5) * 2.0;\n"
  221. " t2 = frac((3.0 * dx2 + 2.0 * dy2) / 4.0) * 4.0;\n"
  222. " float dx3 = frac(floor(in_FragCoord.x * 0.25) * 0.5) * 2.0;\n"
  223. " float dy3 = frac(floor(in_FragCoord.y * 0.25) * 0.5) * 2.0;\n"
  224. " t3 = frac((3.0 * dx3 + 2.0 * dy3) / 4.0) * 4.0;\n"
  225. " t1 = (1.0 + 4.0 * t1 + t2) / 17.0;\n"
  226. " t2 = t1;\n"
  227. " t3 = t1;\n"
  228. # else
  229. " float rand = sin(in_FragCoord.x * 1.23456) * 123.456\n"
  230. " + cos(in_FragCoord.y * 2.34567) * 789.012;\n"
  231. " t1 = frac(sin(rand) * 17.13043);\n"
  232. " t2 = frac(sin(rand) * 27.13043);\n"
  233. " t3 = frac(sin(rand) * 37.13043);\n"
  234. # endif
  235. " float fracx = frac(col.x * mul);\n"
  236. " float fracy = frac(col.y * mul);\n"
  237. " float fracz = frac(col.z * mul);\n"
  238. " fracx = fracx > t1 ? 1.0 : 0.0;\n"
  239. " fracy = fracy > t2 ? 1.0 : 0.0;\n"
  240. " fracz = fracz > t3 ? 1.0 : 0.0;\n"
  241. " col.x = (floor(col.x * mul) + fracx) / mul;\n"
  242. " col.y = (floor(col.y * mul) + fracy) / mul;\n"
  243. " col.z = (floor(col.z * mul) + fracz) / mul;\n"
  244. # endif
  245. " out_FragColor = col;"
  246. "}");
  247. #endif
  248. }
  249. #if 0
  250. // Randomise, then sort.
  251. for (int i = 0; i < data->ntiles; i++)
  252. {
  253. Tile tmp = data->tiles[i];
  254. int j = rand() % data->ntiles;
  255. data->tiles[i] = data->tiles[j];
  256. data->tiles[j] = tmp;
  257. }
  258. #endif
  259. qsort(data->tiles, data->ntiles, sizeof(Tile), SceneData::Compare);
  260. // XXX: debug stuff
  261. data->model_matrix = mat4::translate(320.0f, 240.0f, 0.0f);
  262. data->model_matrix *= mat4::rotate(-data->angle, 1.0f, 0.0f, 0.0f);
  263. #if 0
  264. static float f = 0.0f;
  265. f += 0.01f;
  266. data->model_matrix *= mat4::rotate(6.0f * sinf(f), 1.0f, 0.0f, 0.0f);
  267. data->model_matrix *= mat4::rotate(17.0f * cosf(f), 0.0f, 0.0f, 1.0f);
  268. #endif
  269. data->model_matrix *= mat4::translate(-320.0f, -240.0f, 0.0f);
  270. // XXX: end of debug stuff
  271. ShaderUniform uni_mat, uni_tex;
  272. ShaderAttrib attr_pos, attr_tex;
  273. attr_pos = stdshader->GetAttribLocation("in_Position", VertexUsage::Position, 0);
  274. attr_tex = stdshader->GetAttribLocation("in_TexCoord", VertexUsage::TexCoord, 0);
  275. stdshader->Bind();
  276. uni_mat = stdshader->GetUniformLocation("proj_matrix");
  277. stdshader->SetUniform(uni_mat, Video::GetProjMatrix());
  278. uni_mat = stdshader->GetUniformLocation("view_matrix");
  279. stdshader->SetUniform(uni_mat, Video::GetViewMatrix());
  280. uni_mat = stdshader->GetUniformLocation("model_matrix");
  281. stdshader->SetUniform(uni_mat, data->model_matrix);
  282. #if defined USE_D3D9 || defined _XBOX
  283. #else
  284. uni_tex = stdshader->GetUniformLocation("in_Texture");
  285. stdshader->SetUniform(uni_tex, 0);
  286. #if !defined HAVE_GLES_2X
  287. glEnable(GL_TEXTURE_2D);
  288. #endif
  289. glEnable(GL_DEPTH_TEST);
  290. glDepthFunc(GL_LEQUAL);
  291. #if defined HAVE_GL_2X && !defined __APPLE__
  292. glEnable(GL_ALPHA_TEST);
  293. glAlphaFunc(GL_GEQUAL, 0.01f);
  294. #endif
  295. glEnable(GL_BLEND);
  296. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  297. #endif
  298. for (int buf = 0, i = 0, n; i < data->ntiles; i = n, buf += 2)
  299. {
  300. /* Generate new vertex / texture coord buffers if necessary */
  301. if (buf + 2 > data->nbufs)
  302. {
  303. data->bufs = (VertexBuffer **)realloc(data->bufs, (buf + 2) * sizeof(VertexBuffer *));
  304. data->nbufs = buf + 2;
  305. }
  306. else
  307. {
  308. delete data->bufs[buf];
  309. delete data->bufs[buf + 1];
  310. }
  311. /* Count how many quads will be needed */
  312. for (n = i + 1; n < data->ntiles; n++)
  313. if (data->tiles[i].tileset != data->tiles[n].tileset)
  314. break;
  315. /* Create a vertex array object */
  316. data->bufs[buf] = new VertexBuffer(6 * 3 * (n - i) * sizeof(float));
  317. float *vertex = (float *)data->bufs[buf]->Lock(0, 0);
  318. data->bufs[buf + 1] = new VertexBuffer(6 * 2 * (n - i) * sizeof(float));
  319. float *texture = (float *)data->bufs[buf + 1]->Lock(0, 0);
  320. for (int j = i; j < n; j++)
  321. {
  322. data->tiles[i].tileset->BlitTile(data->tiles[j].id,
  323. data->tiles[j].pos, data->tiles[j].o,
  324. data->tiles[j].scale,
  325. vertex + 18 * (j - i), texture + 12 * (j - i));
  326. }
  327. data->bufs[buf]->Unlock();
  328. data->bufs[buf + 1]->Unlock();
  329. /* Bind texture */
  330. data->tiles[i].tileset->Bind();
  331. /* Bind vertex and texture coordinate buffers */
  332. data->m_vdecl->Bind();
  333. data->m_vdecl->SetStream(data->bufs[buf], attr_pos);
  334. data->m_vdecl->SetStream(data->bufs[buf + 1], attr_tex);
  335. /* Draw arrays */
  336. data->m_vdecl->DrawElements(MeshPrimitive::Triangles, 0, (n - i) * 2);
  337. data->m_vdecl->Unbind();
  338. data->tiles[i].tileset->Unbind();
  339. }
  340. free(data->tiles);
  341. data->tiles = 0;
  342. data->ntiles = 0;
  343. stdshader->Unbind();
  344. #if defined USE_D3D9 || defined _XBOX
  345. /* TODO */
  346. #else
  347. #if !defined HAVE_GLES_2X
  348. glDisable(GL_TEXTURE_2D);
  349. #endif
  350. glDisable(GL_DEPTH_TEST);
  351. #if defined HAVE_GL_2X && !defined __APPLE__
  352. glDisable(GL_ALPHA_TEST);
  353. #endif
  354. glDisable(GL_BLEND);
  355. #endif
  356. }
  357. } /* namespace lol */