您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 

337 行
9.6 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright: (c) 2010-2011 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. vec3i pos;
  28. int id, o;
  29. };
  30. static Shader *stdshader = NULL;
  31. /*
  32. * Scene implementation class
  33. */
  34. class SceneData
  35. {
  36. friend class Scene;
  37. private:
  38. static int Compare(void const *p1, void const *p2)
  39. {
  40. Tile const *t1 = (Tile const *)p1;
  41. Tile const *t2 = (Tile const *)p2;
  42. return t2->prio - t1->prio;
  43. }
  44. mat4 model_matrix;
  45. Tile *tiles;
  46. int ntiles;
  47. float angle;
  48. #if defined HAVE_GL_2X
  49. GLuint vao;
  50. #endif
  51. GLuint *bufs;
  52. int nbufs;
  53. static Scene *scene;
  54. };
  55. Scene *SceneData::scene = NULL;
  56. /*
  57. * Public Scene class
  58. */
  59. Scene::Scene(float angle)
  60. : data(new SceneData())
  61. {
  62. data->tiles = 0;
  63. data->ntiles = 0;
  64. data->angle = angle;
  65. data->bufs = 0;
  66. data->nbufs = 0;
  67. #if defined HAVE_GL_2X
  68. glGenVertexArrays(1, &data->vao);
  69. #endif
  70. }
  71. Scene::~Scene()
  72. {
  73. /* FIXME: this must be done while the GL context is still active.
  74. * Change the architecture to make sure of that. */
  75. glDeleteBuffers(data->nbufs, data->bufs);
  76. #if defined HAVE_GL_2X
  77. glDeleteVertexArrays(1, &data->vao);
  78. #endif
  79. free(data->bufs);
  80. delete data;
  81. }
  82. Scene *Scene::GetDefault()
  83. {
  84. if (!SceneData::scene)
  85. SceneData::scene = new Scene(0.0f);
  86. return SceneData::scene;
  87. }
  88. void Scene::Reset()
  89. {
  90. if (SceneData::scene)
  91. delete SceneData::scene;
  92. SceneData::scene = NULL;
  93. }
  94. void Scene::AddTile(TileSet *tileset, int id, vec3i pos, int o)
  95. {
  96. if ((data->ntiles % 1024) == 0)
  97. data->tiles = (Tile *)realloc(data->tiles,
  98. (data->ntiles + 1024) * sizeof(Tile));
  99. /* FIXME: this sorting only works for a 45-degree camera */
  100. data->tiles[data->ntiles].prio = -pos.y - 2 * 32 * pos.z + (o ? 0 : 32);
  101. data->tiles[data->ntiles].tileset = tileset;
  102. data->tiles[data->ntiles].id = id;
  103. data->tiles[data->ntiles].pos = pos;
  104. data->tiles[data->ntiles].o = o;
  105. data->ntiles++;
  106. }
  107. void Scene::Render() // XXX: rename to Blit()
  108. {
  109. if (!stdshader)
  110. {
  111. stdshader = Shader::Create(
  112. "#version 130\n"
  113. "\n"
  114. #if defined HAVE_GLES_2X
  115. "attribute vec3 in_Position;\n"
  116. "attribute vec2 in_TexCoord;\n"
  117. "varying vec2 pass_TexCoord;\n"
  118. #else
  119. "in vec3 in_Position;\n"
  120. "in vec2 in_TexCoord;\n"
  121. #endif
  122. "uniform mat4 proj_matrix;\n"
  123. "uniform mat4 view_matrix;\n"
  124. "uniform mat4 model_matrix;\n"
  125. "\n"
  126. "void main()\n"
  127. "{\n"
  128. " gl_Position = proj_matrix * view_matrix * model_matrix"
  129. " * vec4(in_Position, 1.0);\n"
  130. #if defined HAVE_GLES_2X
  131. " pass_TexCoord = in_TexCoord;\n"
  132. #else
  133. " gl_TexCoord[0] = vec4(in_TexCoord, 0.0, 0.0);\n"
  134. #endif
  135. "}\n",
  136. "#version 130\n"
  137. "\n"
  138. "uniform sampler2D in_Texture;\n"
  139. #if defined HAVE_GLES_2X
  140. "varying vec2 pass_TexCoord;\n"
  141. #endif
  142. "\n"
  143. "void main()\n"
  144. "{\n"
  145. #if defined HAVE_GLES_2X
  146. " vec4 col = texture2D(in_Texture, pass_TexCoord);\n"
  147. //" vec4 col = vec4(0.5, 1.0, 0.0, 0.5);\n"
  148. //" vec4 col = vec4(pass_TexCoord * 4.0, 0.0, 0.25);\n"
  149. #else
  150. " vec4 col = texture2D(in_Texture, vec2(gl_TexCoord[0]));\n"
  151. #endif
  152. #if 0
  153. " float mul = 2.0;\n"
  154. #if 0
  155. " vec2 d1 = mod(vec2(gl_FragCoord), vec2(2.0, 2.0));\n"
  156. " float t1 = mod(3.0 * d1.x + 2.0 * d1.y, 4.0);\n"
  157. " float dx2 = mod(floor(gl_FragCoord.x * 0.5), 2.0);\n"
  158. " float dy2 = mod(floor(gl_FragCoord.y * 0.5), 2.0);\n"
  159. " float t2 = mod(3.0 * dx2 + 2.0 * dy2, 4.0);\n"
  160. " float dx3 = mod(floor(gl_FragCoord.x * 0.25), 2.0);\n"
  161. " float dy3 = mod(floor(gl_FragCoord.y * 0.25), 2.0);\n"
  162. " float t3 = mod(3.0 * dx3 + 2.0 * dy3, 4.0);\n"
  163. " float t1 = (1.0 + 16.0 * t1 + 4.0 * t2 + t3) / 65.0;\n"
  164. " float t2 = t1;\n"
  165. " float t3 = t1;\n"
  166. #else
  167. " float rand = sin(gl_FragCoord.x * 1.23456) * 123.456\n"
  168. " + cos(gl_FragCoord.y * 2.34567) * 789.012;\n"
  169. " float t1 = mod(sin(rand) * 17.13043, 1.0);\n"
  170. " float t2 = mod(sin(rand) * 27.13043, 1.0);\n"
  171. " float t3 = mod(sin(rand) * 37.13043, 1.0);\n"
  172. #endif
  173. " float fracx = fract(col.x * mul);\n"
  174. " float fracy = fract(col.y * mul);\n"
  175. " float fracz = fract(col.z * mul);\n"
  176. " fracx = fracx > t1 ? 1.0 : 0.0;\n"
  177. " fracy = fracy > t2 ? 1.0 : 0.0;\n"
  178. " fracz = fracz > t3 ? 1.0 : 0.0;\n"
  179. " col.x = (floor(col.x * mul) + fracx) / mul;\n"
  180. " col.y = (floor(col.y * mul) + fracy) / mul;\n"
  181. " col.z = (floor(col.z * mul) + fracz) / mul;\n"
  182. #endif
  183. " gl_FragColor = col;\n"
  184. "}\n");
  185. }
  186. #if 0
  187. // Randomise, then sort.
  188. for (int i = 0; i < data->ntiles; i++)
  189. {
  190. Tile tmp = data->tiles[i];
  191. int j = rand() % data->ntiles;
  192. data->tiles[i] = data->tiles[j];
  193. data->tiles[j] = tmp;
  194. }
  195. #endif
  196. qsort(data->tiles, data->ntiles, sizeof(Tile), SceneData::Compare);
  197. // XXX: debug stuff
  198. data->model_matrix = mat4::translate(320.0f, 240.0f, 0.0f);
  199. data->model_matrix *= mat4::rotate(-data->angle, 1.0f, 0.0f, 0.0f);
  200. #if 0
  201. static float f = 0.0f;
  202. f += 0.01f;
  203. data->model_matrix *= mat4::rotate(0.1f * sinf(f), 1.0f, 0.0f, 0.0f);
  204. data->model_matrix *= mat4::rotate(0.3f * cosf(f), 0.0f, 0.0f, 1.0f);
  205. #endif
  206. data->model_matrix *= mat4::translate(-320.0f, -240.0f, 0.0f);
  207. // XXX: end of debug stuff
  208. GLuint uni_mat, uni_tex, attr_pos, attr_tex;
  209. attr_pos = stdshader->GetAttribLocation("in_Position");
  210. attr_tex = stdshader->GetAttribLocation("in_TexCoord");
  211. #if !defined __CELLOS_LV2__ // Use cgGetNamedParameter etc.
  212. stdshader->Bind();
  213. uni_mat = stdshader->GetUniformLocation("proj_matrix");
  214. glUniformMatrix4fv(uni_mat, 1, GL_FALSE, &Video::GetProjMatrix()[0][0]);
  215. uni_mat = stdshader->GetUniformLocation("view_matrix");
  216. glUniformMatrix4fv(uni_mat, 1, GL_FALSE, &Video::GetViewMatrix()[0][0]);
  217. uni_mat = stdshader->GetUniformLocation("model_matrix");
  218. glUniformMatrix4fv(uni_mat, 1, GL_FALSE, &data->model_matrix[0][0]);
  219. uni_tex = stdshader->GetUniformLocation("in_Texture");
  220. glUniform1i(uni_tex, 0);
  221. #endif
  222. glEnable(GL_TEXTURE_2D);
  223. glEnable(GL_DEPTH_TEST);
  224. glDepthFunc(GL_LEQUAL);
  225. #if defined HAVE_GL_2X
  226. glEnable(GL_ALPHA_TEST);
  227. glAlphaFunc(GL_GEQUAL, 0.01f);
  228. #endif
  229. glEnable(GL_BLEND);
  230. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  231. for (int buf = 0, i = 0, n; i < data->ntiles; i = n, buf += 2)
  232. {
  233. /* Generate new vertex / texture coord buffers if necessary */
  234. if (buf + 2 > data->nbufs)
  235. {
  236. data->bufs = (GLuint *)realloc(data->bufs, (buf + 2) * sizeof(GLuint));
  237. glGenBuffers(buf + 2 - data->nbufs, data->bufs + data->nbufs);
  238. data->nbufs = buf + 2;
  239. }
  240. /* Count how many quads will be needed */
  241. for (n = i + 1; n < data->ntiles; n++)
  242. if (data->tiles[i].tileset != data->tiles[n].tileset)
  243. break;
  244. /* Create a vertex array object */
  245. float *vertex = (float *)malloc(6 * 3 * (n - i) * sizeof(float));
  246. float *texture = (float *)malloc(6 * 2 * (n - i) * sizeof(float));
  247. for (int j = i; j < n; j++)
  248. {
  249. data->tiles[i].tileset->BlitTile(data->tiles[j].id,
  250. data->tiles[j].pos, data->tiles[j].o,
  251. vertex + 18 * (j - i), texture + 12 * (j - i));
  252. }
  253. stdshader->Bind();
  254. /* Bind texture */
  255. data->tiles[i].tileset->Bind();
  256. /* Bind vertex, color and texture coordinate buffers */
  257. #if defined HAVE_GL_2X
  258. glBindVertexArray(data->vao);
  259. #endif
  260. #if !defined __CELLOS_LV2__ // Use cgGLEnableClientState etc.
  261. glEnableVertexAttribArray(attr_pos);
  262. glEnableVertexAttribArray(attr_tex);
  263. glBindBuffer(GL_ARRAY_BUFFER, data->bufs[buf]);
  264. glBufferData(GL_ARRAY_BUFFER, 18 * (n - i) * sizeof(GLfloat),
  265. vertex, GL_STATIC_DRAW);
  266. glVertexAttribPointer(attr_pos, 3, GL_FLOAT, GL_FALSE, 0, 0);
  267. glBindBuffer(GL_ARRAY_BUFFER, data->bufs[buf + 1]);
  268. glBufferData(GL_ARRAY_BUFFER, 12 * (n - i) * sizeof(GLfloat),
  269. texture, GL_STATIC_DRAW);
  270. glVertexAttribPointer(attr_tex, 2, GL_FLOAT, GL_FALSE, 0, 0);
  271. #endif
  272. /* Draw arrays */
  273. glDrawArrays(GL_TRIANGLES, 0, (n - i) * 6);
  274. #if defined HAVE_GL_2X
  275. glBindVertexArray(0);
  276. #endif
  277. #if !defined __CELLOS_LV2__ // Use cgGLEnableClientState etc.
  278. glDisableVertexAttribArray(attr_pos);
  279. glDisableVertexAttribArray(attr_tex);
  280. #endif
  281. free(vertex);
  282. free(texture);
  283. }
  284. free(data->tiles);
  285. data->tiles = 0;
  286. data->ntiles = 0;
  287. }
  288. } /* namespace lol */