A 2D tile-based sandbox game.
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

Renderer.cc 16KB

3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610
  1. #include "Renderer.h"
  2. #include <iostream>
  3. #include <stdio.h>
  4. #include <swan-common/constants.h>
  5. #include <string.h>
  6. // std::endian was originally in type_traits, was moved to bit
  7. #include <type_traits>
  8. #include <bit>
  9. #include "gl.h"
  10. #include "shaders.h"
  11. #include "GlWrappers.h"
  12. #include "TileAtlas.h"
  13. #include "util.h"
  14. namespace Cygnet {
  15. struct ChunkProg: public GlProgram {
  16. template<typename... T>
  17. ChunkProg(const T &... shaders): GlProgram(shaders...) { init(); }
  18. ~ChunkProg() { deinit(); }
  19. GLint camera = uniformLoc("camera");
  20. GLint pos = uniformLoc("pos");
  21. GLint vertex = attribLoc("vertex");
  22. GLint tileAtlas = uniformLoc("tileAtlas");
  23. GLint tileAtlasSize = uniformLoc("tileAtlasSize");
  24. GLint tiles = uniformLoc("tiles");
  25. GLuint vbo;
  26. static constexpr float ch = (float)SwanCommon::CHUNK_HEIGHT;
  27. static constexpr float cw = (float)SwanCommon::CHUNK_WIDTH;
  28. static constexpr GLfloat vertexes[] = {
  29. 0.0f, 0.0f, // pos 0: top left
  30. 0.0f, ch , // pos 1: bottom left
  31. cw, ch, // pos 2: bottom right
  32. cw, ch, // pos 2: bottom right
  33. cw, 0.0f, // pos 3: top right
  34. 0.0f, 0.0f, // pos 0: top left
  35. };
  36. void enable() {
  37. glUseProgram(id());
  38. glBindBuffer(GL_ARRAY_BUFFER, vbo);
  39. glVertexAttribPointer(vertex, 2, GL_FLOAT, GL_FALSE, 0, (void *)0);
  40. glEnableVertexAttribArray(vertex);
  41. glCheck();
  42. glUniform1i(tileAtlas, 0);
  43. glUniform1i(tiles, 1);
  44. }
  45. void disable() {
  46. glDisableVertexAttribArray(vertex);
  47. glCheck();
  48. }
  49. void init() {
  50. glGenBuffers(1, &vbo);
  51. glCheck();
  52. glBindBuffer(GL_ARRAY_BUFFER, vbo);
  53. glBufferData(GL_ARRAY_BUFFER, sizeof(vertexes), vertexes, GL_STATIC_DRAW);
  54. glCheck();
  55. }
  56. void deinit() {
  57. glDeleteBuffers(1, &vbo);
  58. glCheck();
  59. }
  60. };
  61. struct ChunkShadowProg: public GlProgram {
  62. template<typename... T>
  63. ChunkShadowProg(const T &... shaders): GlProgram(shaders...) { init(); }
  64. ~ChunkShadowProg() { deinit(); }
  65. GLint camera = uniformLoc("camera");
  66. GLint pos = uniformLoc("pos");
  67. GLint vertex = attribLoc("vertex");
  68. GLint tex = uniformLoc("tex");
  69. GLuint vbo;
  70. static constexpr float ch = (float)SwanCommon::CHUNK_HEIGHT;
  71. static constexpr float cw = (float)SwanCommon::CHUNK_WIDTH;
  72. static constexpr GLfloat vertexes[] = {
  73. 0.0f, 0.0f, // pos 0: top left
  74. 0.0f, ch , // pos 1: bottom left
  75. cw, ch, // pos 2: bottom right
  76. cw, ch, // pos 2: bottom right
  77. cw, 0.0f, // pos 3: top right
  78. 0.0f, 0.0f, // pos 0: top left
  79. };
  80. void enable() {
  81. glUseProgram(id());
  82. glBindBuffer(GL_ARRAY_BUFFER, vbo);
  83. glVertexAttribPointer(vertex, 2, GL_FLOAT, GL_FALSE, 0, (void *)0);
  84. glEnableVertexAttribArray(vertex);
  85. glCheck();
  86. glUniform1i(tex, 0);
  87. }
  88. void disable() {
  89. glDisableVertexAttribArray(vertex);
  90. glCheck();
  91. }
  92. void init() {
  93. glGenBuffers(1, &vbo);
  94. glCheck();
  95. glBindBuffer(GL_ARRAY_BUFFER, vbo);
  96. glBufferData(GL_ARRAY_BUFFER, sizeof(vertexes), vertexes, GL_STATIC_DRAW);
  97. glCheck();
  98. }
  99. void deinit() {
  100. glDeleteBuffers(1, &vbo);
  101. glCheck();
  102. }
  103. };
  104. struct TileProg: public GlProgram {
  105. template<typename... T>
  106. TileProg(const T &... shaders): GlProgram(shaders...) { init(); }
  107. ~TileProg() { deinit(); }
  108. GLint camera = uniformLoc("camera");
  109. GLint transform = uniformLoc("transform");
  110. GLint vertex = attribLoc("vertex");
  111. GLint tileAtlas = uniformLoc("tileAtlas");
  112. GLint tileAtlasSize = uniformLoc("tileAtlasSize");
  113. GLint tileID = uniformLoc("tileID");
  114. GLuint vbo;
  115. static constexpr GLfloat vertexes[] = {
  116. 0.0f, 0.0f, // pos 0: top left
  117. 0.0f, 1.0f, // pos 1: bottom left
  118. 1.0f, 1.0f, // pos 2: bottom right
  119. 1.0f, 1.0f, // pos 2: bottom right
  120. 1.0f, 0.0f, // pos 3: top right
  121. 0.0f, 0.0f, // pos 0: top left
  122. };
  123. void enable() {
  124. glUseProgram(id());
  125. glBindBuffer(GL_ARRAY_BUFFER, vbo);
  126. glVertexAttribPointer(vertex, 2, GL_FLOAT, GL_FALSE, 0, (void *)0);
  127. glEnableVertexAttribArray(vertex);
  128. glCheck();
  129. glUniform1i(tileAtlas, 0);
  130. }
  131. void disable() {
  132. glDisableVertexAttribArray(vertex);
  133. glCheck();
  134. }
  135. void init() {
  136. glGenBuffers(1, &vbo);
  137. glCheck();
  138. glBindBuffer(GL_ARRAY_BUFFER, vbo);
  139. glBufferData(GL_ARRAY_BUFFER, sizeof(vertexes), vertexes, GL_STATIC_DRAW);
  140. glCheck();
  141. }
  142. void deinit() {
  143. glDeleteBuffers(1, &vbo);
  144. glCheck();
  145. }
  146. };
  147. struct SpriteProg: public GlProgram {
  148. template<typename... T>
  149. SpriteProg(const T &... shaders): GlProgram(shaders...) { init(); }
  150. ~SpriteProg() { deinit(); }
  151. GLint camera = uniformLoc("camera");
  152. GLint transform = uniformLoc("transform");
  153. GLint frameSize = uniformLoc("frameSize");
  154. GLint frameInfo = uniformLoc("frameInfo");
  155. GLint vertex = attribLoc("vertex");
  156. GLint tex = uniformLoc("tex");
  157. GLuint vbo;
  158. static constexpr GLfloat vertexes[] = {
  159. 0.0f, 0.0f, // pos 0: top left
  160. 0.0f, 1.0f, // pos 1: bottom left
  161. 1.0f, 1.0f, // pos 2: bottom right
  162. 1.0f, 1.0f, // pos 2: bottom right
  163. 1.0f, 0.0f, // pos 3: top right
  164. 0.0f, 0.0f, // pos 0: top left
  165. };
  166. void enable() {
  167. glUseProgram(id());
  168. glBindBuffer(GL_ARRAY_BUFFER, vbo);
  169. glVertexAttribPointer(vertex, 2, GL_FLOAT, GL_FALSE, 0, (void *)0);
  170. glEnableVertexAttribArray(vertex);
  171. glCheck();
  172. glUniform1i(tex, 0);
  173. }
  174. void disable() {
  175. glDisableVertexAttribArray(vertex);
  176. glCheck();
  177. }
  178. void init() {
  179. glGenBuffers(1, &vbo);
  180. glCheck();
  181. glBindBuffer(GL_ARRAY_BUFFER, vbo);
  182. glBufferData(GL_ARRAY_BUFFER, sizeof(vertexes), vertexes, GL_STATIC_DRAW);
  183. glCheck();
  184. }
  185. void deinit() {
  186. glDeleteBuffers(1, &vbo);
  187. glCheck();
  188. }
  189. };
  190. struct RectProg: public GlProgram {
  191. template<typename... T>
  192. RectProg(const T &... shaders): GlProgram(shaders...) { init(); }
  193. ~RectProg() { deinit(); }
  194. GLint camera = uniformLoc("camera");
  195. GLint pos = uniformLoc("pos");
  196. GLint size = uniformLoc("size");
  197. GLint vertex = attribLoc("vertex");
  198. GLuint vbo;
  199. static constexpr GLfloat vertexes[] = {
  200. 0.0f, 0.0f, // pos 0: top left
  201. 0.0f, 1.0f, // pos 1: bottom left
  202. 1.0f, 1.0f, // pos 2: bottom right
  203. 1.0f, 1.0f, // pos 2: bottom right
  204. 1.0f, 0.0f, // pos 3: top right
  205. 0.0f, 0.0f, // pos 0: top left
  206. };
  207. void enable() {
  208. glUseProgram(id());
  209. glBindBuffer(GL_ARRAY_BUFFER, vbo);
  210. glVertexAttribPointer(vertex, 2, GL_FLOAT, GL_FALSE, 0, (void *)0);
  211. glEnableVertexAttribArray(vertex);
  212. glCheck();
  213. }
  214. void disable() {
  215. glDisableVertexAttribArray(vertex);
  216. glCheck();
  217. }
  218. void init() {
  219. glGenBuffers(1, &vbo);
  220. glCheck();
  221. glBindBuffer(GL_ARRAY_BUFFER, vbo);
  222. glBufferData(GL_ARRAY_BUFFER, sizeof(vertexes), vertexes, GL_STATIC_DRAW);
  223. glCheck();
  224. }
  225. void deinit() {
  226. glDeleteBuffers(1, &vbo);
  227. glCheck();
  228. }
  229. };
  230. struct RendererState {
  231. GlVxShader chunkVx{Shaders::chunkVx};
  232. GlFrShader chunkFr{Shaders::chunkFr};
  233. GlVxShader chunkShadowVx{Shaders::chunkShadowVx};
  234. GlFrShader chunkShadowFr{Shaders::chunkShadowFr};
  235. GlVxShader tileVx{Shaders::tileVx};
  236. GlFrShader tileFr{Shaders::tileFr};
  237. GlVxShader spriteVx{Shaders::spriteVx};
  238. GlFrShader spriteFr{Shaders::spriteFr};
  239. GlVxShader rectVx{Shaders::rectVx};
  240. GlFrShader rectFr{Shaders::rectFr};
  241. ChunkProg chunkProg{chunkVx, chunkFr};
  242. ChunkShadowProg chunkShadowProg{chunkShadowVx, chunkShadowFr};
  243. TileProg tileProg{tileVx, tileFr};
  244. SpriteProg spriteProg{spriteVx, spriteFr};
  245. RectProg rectProg{rectVx, rectFr};
  246. GLuint atlasTex;
  247. SwanCommon::Vec2 atlasTexSize;
  248. };
  249. Renderer::Renderer(): state_(std::make_unique<RendererState>()) {
  250. glGenTextures(1, &state_->atlasTex);
  251. glCheck();
  252. }
  253. Renderer::~Renderer() = default;
  254. void Renderer::draw(const RenderCamera &cam) {
  255. Mat3gf camMat;
  256. camMat.translate(-cam.pos);
  257. if (cam.size.y > cam.size.x) {
  258. float ratio = (float)cam.size.y / (float)cam.size.x;
  259. winScale_ = {1/ratio, 1};
  260. camMat.scale({cam.zoom * ratio, -cam.zoom});
  261. } else {
  262. float ratio = (float)cam.size.x / (float)cam.size.y;
  263. winScale_ = {1, 1/ratio};
  264. camMat.scale({cam.zoom, -cam.zoom * ratio});
  265. }
  266. auto &chunkProg = state_->chunkProg;
  267. auto &chunkShadowProg = state_->chunkShadowProg;
  268. auto &tileProg = state_->tileProg;
  269. auto &spriteProg = state_->spriteProg;
  270. auto &rectProg = state_->rectProg;
  271. {
  272. chunkProg.enable();
  273. glUniformMatrix3fv(chunkProg.camera, 1, GL_TRUE, camMat.data());
  274. glCheck();
  275. glUniform2f(chunkProg.tileAtlasSize, state_->atlasTexSize.x, state_->atlasTexSize.y);
  276. glCheck();
  277. glActiveTexture(GL_TEXTURE0);
  278. glBindTexture(GL_TEXTURE_2D, state_->atlasTex);
  279. glCheck();
  280. glActiveTexture(GL_TEXTURE1);
  281. for (auto [pos, chunk]: drawChunks_) {
  282. glUniform2f(chunkProg.pos, pos.x, pos.y);
  283. glBindTexture(GL_TEXTURE_2D, chunk.tex);
  284. glDrawArrays(GL_TRIANGLES, 0, 6);
  285. glCheck();
  286. }
  287. drawChunks_.clear();
  288. chunkProg.disable();
  289. }
  290. {
  291. tileProg.enable();
  292. glUniformMatrix3fv(tileProg.camera, 1, GL_TRUE, camMat.data());
  293. glCheck();
  294. glUniform2f(tileProg.tileAtlasSize, state_->atlasTexSize.x, state_->atlasTexSize.y);
  295. glCheck();
  296. glActiveTexture(GL_TEXTURE0);
  297. glBindTexture(GL_TEXTURE_2D, state_->atlasTex);
  298. glCheck();
  299. glActiveTexture(GL_TEXTURE1);
  300. for (auto [mat, id]: drawTiles_) {
  301. glUniformMatrix3fv(tileProg.transform, 1, GL_TRUE, mat.data());
  302. glUniform1f(tileProg.tileID, id);
  303. glDrawArrays(GL_TRIANGLES, 0, 6);
  304. glCheck();
  305. }
  306. drawTiles_.clear();
  307. tileProg.disable();
  308. }
  309. {
  310. spriteProg.enable();
  311. glUniformMatrix3fv(spriteProg.camera, 1, GL_TRUE, camMat.data());
  312. glCheck();
  313. glActiveTexture(GL_TEXTURE0);
  314. for (auto [mat, frame, sprite]: drawSprites_) {
  315. glUniformMatrix3fv(spriteProg.transform, 1, GL_TRUE, mat.data());
  316. glUniform2f(spriteProg.frameSize, sprite.scale.x, sprite.scale.y);
  317. glUniform2f(spriteProg.frameInfo, sprite.frameCount, frame);
  318. glBindTexture(GL_TEXTURE_2D, sprite.tex);
  319. glDrawArrays(GL_TRIANGLES, 0, 6);
  320. glCheck();
  321. }
  322. drawSprites_.clear();
  323. spriteProg.disable();
  324. }
  325. {
  326. rectProg.enable();
  327. glUniformMatrix3fv(rectProg.camera, 1, GL_TRUE, camMat.data());
  328. glCheck();
  329. for (auto [pos, size]: drawRects_) {
  330. glUniform2f(rectProg.pos, pos.x, pos.y);
  331. glUniform2f(rectProg.size, size.x, size.y);
  332. glDrawArrays(GL_TRIANGLES, 0, 6);
  333. glCheck();
  334. }
  335. drawRects_.clear();
  336. rectProg.disable();
  337. }
  338. {
  339. chunkShadowProg.enable();
  340. glUniformMatrix3fv(chunkShadowProg.camera, 1, GL_TRUE, camMat.data());
  341. glCheck();
  342. glActiveTexture(GL_TEXTURE0);
  343. for (auto [pos, shadow]: drawChunkShadows_) {
  344. glUniform2f(chunkShadowProg.pos, pos.x, pos.y);
  345. glBindTexture(GL_TEXTURE_2D, shadow.tex);
  346. glDrawArrays(GL_TRIANGLES, 0, 6);
  347. glCheck();
  348. }
  349. drawChunkShadows_.clear();
  350. chunkShadowProg.disable();
  351. }
  352. }
  353. void Renderer::uploadTileAtlas(const void *data, int width, int height) {
  354. glBindTexture(GL_TEXTURE_2D, state_->atlasTex);
  355. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
  356. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  357. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  358. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  359. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  360. glCheck();
  361. state_->atlasTexSize = {
  362. (float)(int)(width / SwanCommon::TILE_SIZE),
  363. (float)(int)(height / SwanCommon::TILE_SIZE) };
  364. }
  365. void Renderer::modifyTile(TileID id, const void *data) {
  366. int w = (int)state_->atlasTexSize.x;
  367. int x = id % w;
  368. int y = id / w;
  369. glActiveTexture(GL_TEXTURE0);
  370. glBindTexture(GL_TEXTURE_2D, state_->atlasTex);
  371. glTexSubImage2D(
  372. GL_TEXTURE_2D, 0, x * SwanCommon::TILE_SIZE, y * SwanCommon::TILE_SIZE,
  373. SwanCommon::TILE_SIZE, SwanCommon::TILE_SIZE,
  374. GL_RGBA, GL_UNSIGNED_BYTE, data);
  375. glCheck();
  376. }
  377. RenderChunk Renderer::createChunk(
  378. TileID tiles[SwanCommon::CHUNK_WIDTH * SwanCommon::CHUNK_HEIGHT]) {
  379. RenderChunk chunk;
  380. glGenTextures(1, &chunk.tex);
  381. glCheck();
  382. glActiveTexture(GL_TEXTURE0);
  383. glBindTexture(GL_TEXTURE_2D, chunk.tex);
  384. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  385. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  386. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  387. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  388. glCheck();
  389. static_assert(
  390. std::endian::native == std::endian::big ||
  391. std::endian::native == std::endian::little,
  392. "Expected either big or little endian");
  393. if constexpr (std::endian::native == std::endian::little) {
  394. glTexImage2D(
  395. GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA,
  396. SwanCommon::CHUNK_WIDTH, SwanCommon::CHUNK_HEIGHT,
  397. 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, tiles);
  398. } else if constexpr (std::endian::native == std::endian::big) {
  399. uint8_t buf[SwanCommon::CHUNK_WIDTH * SwanCommon::CHUNK_HEIGHT * 2];
  400. for (size_t y = 0; y < SwanCommon::CHUNK_HEIGHT; ++y) {
  401. for (size_t x = 0; x < SwanCommon::CHUNK_WIDTH; ++x) {
  402. size_t dst = y * SwanCommon::CHUNK_WIDTH * 2 + x * 2;
  403. size_t src = y * SwanCommon::CHUNK_WIDTH + x;
  404. buf[dst + 0] = tiles[src] & 0xff;
  405. buf[dst + 1] = (tiles[src] & 0xff00) >> 8;
  406. }
  407. }
  408. glTexImage2D(
  409. GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA,
  410. SwanCommon::CHUNK_WIDTH, SwanCommon::CHUNK_HEIGHT,
  411. 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, buf);
  412. }
  413. glCheck();
  414. return chunk;
  415. }
  416. void Renderer::modifyChunk(RenderChunk chunk, SwanCommon::Vec2i pos, TileID id) {
  417. glActiveTexture(GL_TEXTURE0);
  418. glBindTexture(GL_TEXTURE_2D, chunk.tex);
  419. glCheck();
  420. static_assert(
  421. std::endian::native == std::endian::big ||
  422. std::endian::native == std::endian::little,
  423. "Expected either big or little endian");
  424. if constexpr (std::endian::native == std::endian::little) {
  425. glTexSubImage2D(
  426. GL_TEXTURE_2D, 0, pos.x, pos.y, 1, 1,
  427. GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, &id);
  428. } else if constexpr (std::endian::native == std::endian::big) {
  429. uint8_t buf[] = { (uint8_t)(id & 0xff), (uint8_t)((id & 0xff00) >> 8) };
  430. glTexSubImage2D(
  431. GL_TEXTURE_2D, 0, pos.x, pos.y, 1, 1,
  432. GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, buf);
  433. }
  434. glCheck();
  435. }
  436. void Renderer::destroyChunk(RenderChunk chunk) {
  437. glDeleteTextures(1, &chunk.tex);
  438. glCheck();
  439. }
  440. RenderChunkShadow Renderer::createChunkShadow(
  441. uint8_t data[SwanCommon::CHUNK_WIDTH * SwanCommon::CHUNK_HEIGHT]) {
  442. RenderChunkShadow shadow;
  443. glGenTextures(1, &shadow.tex);
  444. glCheck();
  445. glActiveTexture(GL_TEXTURE0);
  446. glBindTexture(GL_TEXTURE_2D, shadow.tex);
  447. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  448. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  449. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  450. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  451. glCheck();
  452. glTexImage2D(
  453. GL_TEXTURE_2D, 0, GL_LUMINANCE,
  454. SwanCommon::CHUNK_WIDTH, SwanCommon::CHUNK_HEIGHT,
  455. 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
  456. glCheck();
  457. return shadow;
  458. }
  459. void Renderer::modifyChunkShadow(
  460. RenderChunkShadow shadow,
  461. uint8_t data[SwanCommon::CHUNK_WIDTH * SwanCommon::CHUNK_HEIGHT]) {
  462. glActiveTexture(GL_TEXTURE0);
  463. glBindTexture(GL_TEXTURE_2D, shadow.tex);
  464. glTexImage2D(
  465. GL_TEXTURE_2D, 0, GL_LUMINANCE,
  466. SwanCommon::CHUNK_WIDTH, SwanCommon::CHUNK_HEIGHT,
  467. 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
  468. glCheck();
  469. }
  470. void Renderer::destroyChunkShadow(RenderChunkShadow shadow) {
  471. glDeleteTextures(1, &shadow.tex);
  472. glCheck();
  473. }
  474. RenderSprite Renderer::createSprite(void *data, int width, int height, int fh) {
  475. RenderSprite sprite;
  476. sprite.scale = {
  477. (float)width / SwanCommon::TILE_SIZE,
  478. (float)fh / SwanCommon::TILE_SIZE };
  479. sprite.frameCount = height / fh;
  480. glGenTextures(1, &sprite.tex);
  481. glCheck();
  482. glActiveTexture(GL_TEXTURE0);
  483. glBindTexture(GL_TEXTURE_2D, sprite.tex);
  484. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  485. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  486. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  487. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  488. glCheck();
  489. glTexImage2D(
  490. GL_TEXTURE_2D, 0, GL_RGBA, width, height,
  491. 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
  492. glCheck();
  493. return sprite;
  494. }
  495. RenderSprite Renderer::createSprite(void *data, int width, int height) {
  496. return createSprite(data, width, height, height);
  497. }
  498. void Renderer::destroySprite(RenderSprite sprite) {
  499. glDeleteTextures(1, &sprite.tex);
  500. }
  501. }