A 2D tile-based sandbox game.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Renderer.cc 5.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. #include "Renderer.h"
  2. #include <iostream>
  3. #include <stdio.h>
  4. #include <SDL_opengles2.h>
  5. #include <swan-common/constants.h>
  6. #include <string.h>
  7. #include "shaders.h"
  8. #include "GlWrappers.h"
  9. #include "TileAtlas.h"
  10. #include "util.h"
  11. namespace Cygnet {
  12. struct SpriteProg: public GlProgram {
  13. template<typename... T>
  14. SpriteProg(const T &... shaders): GlProgram(shaders...) { init(); }
  15. ~SpriteProg() { deinit(); }
  16. GLint camera = uniformLoc("camera");
  17. GLint transform = uniformLoc("transform");
  18. GLint vertex = attribLoc("vertex");
  19. GLint texCoord = attribLoc("texCoord");
  20. GLint tex = uniformLoc("tex");
  21. GLuint vbo;
  22. static constexpr GLfloat vertexes[] = {
  23. -0.5f, 0.5f, // pos 0: top left
  24. 0.0f, 0.0f, // tex 0: top left
  25. -0.5f, -0.5f, // pos 1: bottom left
  26. 0.0f, 1.0f, // tex 1: bottom left
  27. 0.5f, -0.5f, // pos 2: bottom right
  28. 1.0f, 1.0f, // tex 2: bottom right
  29. 0.5f, -0.5f, // pos 2: bottom right
  30. 1.0f, 1.0f, // tex 2: bottom right
  31. 0.5f, 0.5f, // pos 3: top right
  32. 1.0f, 0.0f, // tex 3: top right
  33. -0.5f, 0.5f, // pos 0: top left
  34. 0.0f, 0.0f, // tex 0: top left
  35. };
  36. void enable() {
  37. glUseProgram(id());
  38. glBindBuffer(GL_ARRAY_BUFFER, vbo);
  39. glVertexAttribPointer(vertex, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (void *)0);
  40. glVertexAttribPointer(texCoord, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (void *)(2 * sizeof(GLfloat)));
  41. glEnableVertexAttribArray(vertex);
  42. glEnableVertexAttribArray(texCoord);
  43. glCheck();
  44. }
  45. void disable() {
  46. glDisableVertexAttribArray(vertex);
  47. glDisableVertexAttribArray(texCoord);
  48. glCheck();
  49. }
  50. void init() {
  51. glGenBuffers(1, &vbo);
  52. glCheck();
  53. glBindBuffer(GL_ARRAY_BUFFER, vbo);
  54. glBufferData(GL_ARRAY_BUFFER, sizeof(vertexes), vertexes, GL_STATIC_DRAW);
  55. glCheck();
  56. }
  57. void deinit() {
  58. glDeleteBuffers(1, &vbo);
  59. glCheck();
  60. }
  61. };
  62. struct ChunkProg: public GlProgram {
  63. template<typename... T>
  64. ChunkProg(const T &... shaders): GlProgram(shaders...) { init(); }
  65. ~ChunkProg() { deinit(); }
  66. GLint camera = uniformLoc("camera");
  67. GLint pos = uniformLoc("pos");
  68. GLint vertex = attribLoc("vertex");
  69. GLint tileAtlas = uniformLoc("tileAtlas");
  70. GLint tileAtlasSize = uniformLoc("tileAtlasSize");
  71. GLint tiles = uniformLoc("tiles");
  72. GLuint tilesTex;
  73. GLuint vbo;
  74. static constexpr float ch = (float)SwanCommon::CHUNK_HEIGHT;
  75. static constexpr float cw = (float)SwanCommon::CHUNK_WIDTH;
  76. static constexpr GLfloat vertexes[] = {
  77. 0.0f, 0.0f, // pos 0: top left
  78. 0.0f, -ch , // pos 1: bottom left
  79. cw, -ch, // pos 2: bottom right
  80. cw, -ch, // pos 2: bottom right
  81. cw, 0.0f, // pos 3: top right
  82. 0.0f, 0.0f, // pos 0: top left
  83. };
  84. void enable() {
  85. glUseProgram(id());
  86. glBindBuffer(GL_ARRAY_BUFFER, vbo);
  87. glVertexAttribPointer(vertex, 2, GL_FLOAT, GL_FALSE, 0, (void *)0);
  88. glEnableVertexAttribArray(vertex);
  89. glCheck();
  90. }
  91. void disable() {
  92. glDisableVertexAttribArray(vertex);
  93. glCheck();
  94. }
  95. void init() {
  96. glGenBuffers(1, &vbo);
  97. glCheck();
  98. glGenTextures(1, &tilesTex);
  99. glCheck();
  100. glBindTexture(GL_TEXTURE_2D, tilesTex);
  101. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  102. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  103. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  104. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  105. glCheck();
  106. glBindBuffer(GL_ARRAY_BUFFER, vbo);
  107. glBufferData(GL_ARRAY_BUFFER, sizeof(vertexes), vertexes, GL_STATIC_DRAW);
  108. glCheck();
  109. }
  110. void deinit() {
  111. glDeleteBuffers(1, &vbo);
  112. glDeleteTextures(1, &tilesTex);
  113. glCheck();
  114. }
  115. };
  116. struct RendererState {
  117. GlVxShader spriteVx{Shaders::spriteVx};
  118. GlFrShader spriteFr{Shaders::spriteFr};
  119. GlVxShader chunkVx{Shaders::chunkVx};
  120. GlFrShader chunkFr{Shaders::chunkFr};
  121. SpriteProg spriteProg{spriteVx, spriteFr};
  122. ChunkProg chunkProg{chunkVx, chunkFr};
  123. TileAtlas atlas;
  124. GlTexture atlasTex;
  125. Mat3gf camera;
  126. };
  127. Renderer::Renderer(): state_(std::make_unique<RendererState>()) {}
  128. Renderer::~Renderer() = default;
  129. void Renderer::draw() {
  130. state_->chunkProg.enable();
  131. glActiveTexture(GL_TEXTURE1);
  132. glBindTexture(GL_TEXTURE_2D, state_->chunkProg.tilesTex); // Necessary?
  133. glUniform1i(state_->chunkProg.tiles, 1);
  134. uint8_t tiles[SwanCommon::CHUNK_WIDTH * SwanCommon::CHUNK_HEIGHT * 2];
  135. memset(tiles, 0x00, sizeof(tiles));
  136. tiles[1] = 1;
  137. tiles[3] = 2;
  138. tiles[5] = 3;
  139. glTexImage2D(
  140. GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, SwanCommon::CHUNK_WIDTH, SwanCommon::CHUNK_HEIGHT,
  141. 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, tiles);
  142. glCheck();
  143. glUniform2f(state_->chunkProg.tileAtlasSize,
  144. (float)(int)(state_->atlasTex.width() / SwanCommon::TILE_SIZE),
  145. (float)(int)(state_->atlasTex.height() / SwanCommon::TILE_SIZE));
  146. state_->camera.reset().translate(-0.9, 0.9).scale(0.025, 0.025);
  147. glUniformMatrix3fv(state_->chunkProg.camera, 1, GL_TRUE, state_->camera.data());
  148. glActiveTexture(GL_TEXTURE0);
  149. glBindTexture(GL_TEXTURE_2D, state_->atlasTex.id());
  150. glUniform1i(state_->chunkProg.tileAtlas, 0);
  151. glCheck();
  152. glDrawArrays(GL_TRIANGLES, 0, 6);
  153. glCheck();
  154. state_->chunkProg.disable();
  155. /*
  156. state_->spriteProg.enable();
  157. state_->camera.translate(-0.00001, 0);
  158. glUniformMatrix3fv(state_->spriteProg.transform, 1, GL_TRUE, Mat3gf::IDENTITY.data());
  159. glUniformMatrix3fv(state_->spriteProg.camera, 1, GL_TRUE, state_->camera.data());
  160. glCheck();
  161. glActiveTexture(GL_TEXTURE0);
  162. glBindTexture(GL_TEXTURE_2D,state_->atlasTex.id()); // Necessary?
  163. glUniform1i(state_->spriteProg.tex, 0);
  164. glCheck();
  165. glDrawArrays(GL_TRIANGLES, 0, 6);
  166. glCheck();
  167. state_->spriteProg.disable();
  168. */
  169. }
  170. void Renderer::registerTileTexture(size_t tileId, const void *data, size_t len) {
  171. state_->atlas.addTile(tileId, data, len);
  172. }
  173. void Renderer::uploadTileTexture() {
  174. size_t w, h;
  175. const unsigned char *data = state_->atlas.getImage(&w, &h);
  176. state_->atlasTex.upload(w, h, (void *)data, GL_RGBA, GL_UNSIGNED_BYTE);
  177. std::cerr << "Uploaded image of size " << w << 'x' << h << '\n';
  178. }
  179. }