Guest User

Untitled

a guest
May 23rd, 2018
99
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.21 KB | None | 0 0
  1. namespace Math {
  2. // this is a full class in it's own header
  3. template <typename T>
  4. struct RectPP {
  5. glm::tvec2<T> min;
  6. glm::tvec2<T> max;
  7. };
  8. }
  9.  
  10. namespace G2D {
  11. struct Vertex {
  12. glm::vec3 pos;
  13. glm::vec2 texCoord;
  14. };
  15. using Quad = std::array<Vertex, 4>;
  16.  
  17. // the values of the uniforms
  18. struct RenderParams {
  19. // camera matrix
  20. glm::mat3 viewProj = {};
  21. // ID of a texture stored in G2D::Renderer
  22. TextureID tex = 0;
  23. // color to be multiplied by the texture sample in the fragment shader
  24. glm::vec4 color = glm::vec4(1.0f);
  25. };
  26.  
  27. enum class PlusXY {
  28. RIGHT_UP,
  29. LEFT_UP,
  30. RIGHT_DOWN,
  31. LEFT_DOWN
  32. };
  33.  
  34. enum class Origin {
  35. TOP_LEFT,
  36. TOP_MID,
  37. TOP_RIGHT,
  38. MID_RIGHT,
  39. BOTTOM_RIGHT,
  40. BOTTOM_MID,
  41. BOTTOM_LEFT,
  42. MID_LEFT,
  43. CENTER
  44. };
  45.  
  46. /// Get the depth of a depth enum. The last enumerator must be COUNT
  47. template <typename Enum>
  48. constexpr float depth(const Enum e) {
  49. return static_cast<float>(e) / static_cast<float>(Enum::COUNT);
  50. }
  51.  
  52. class QuadWriter {
  53. public:
  54. QuadWriter();
  55.  
  56. /// Remove all of the sections
  57. void clear();
  58.  
  59. /// Start a new section with the given rendering parameters
  60. void section(const RenderParams &);
  61. /// Make space for the given number of quads to avoid further reallocations
  62. void sectionSize(size_t);
  63.  
  64. /// Sort the quads in the current section by the given sorting predicate
  65. template <typename Function>
  66. void sort(Function &&);
  67.  
  68. /// Start a new quad and return it
  69. Quad &quad();
  70. /// Start a new quad the is a duplicate of the previous quad and return it
  71. Quad &dup();
  72.  
  73. /// Set the depth of the current quad
  74. void depth(float);
  75. /// Set the depth of the current quad using an enum. The last enumerator
  76. /// must be COUNT
  77. template <typename Enum>
  78. void depth(Enum);
  79.  
  80. /// Copy the positions of the verticies from the previous quad into the
  81. /// current quad
  82. void dupPos();
  83. /// Copy the positions of the verticies and the depth from the previous
  84. /// quad into the current quad
  85. void dupPosDepth();
  86. /// Write positions of verticies on the current quad as an axis-aligned
  87. /// rectangle.
  88. void tilePos(glm::vec2, glm::vec2 = {1.0f, 1.0f});
  89. /// Write positions of verticies on the current quad as a rectangle rotated
  90. /// around it's center. The quad is position relative to it's bottom left
  91. /// corner like tilePos.
  92. void rotTilePos(float, glm::vec2, glm::vec2 = {1.0f, 1.0f});
  93. /// Write positions of verticies on the current quad as rectangle rotated
  94. /// around a given origin. The quad is positioned relative to the origin.
  95. /// This function isn't quite as fast as rotTilePos without an origin.
  96. template <Origin ORIGIN>
  97. void rotTilePos(float, glm::vec2, glm::vec2 = {1.0f, 1.0f});
  98.  
  99. /// Copy the texture coordinates of the verticies on the previous quad onto
  100. /// the current quad
  101. void dupTex();
  102. /// Write texture coordinates of vertices on the current quad assuming that
  103. /// the texture is sampled as an axis-aligned rectangle
  104. template <PlusXY PLUS_XY = PlusXY::RIGHT_UP>
  105. void tileTex(glm::vec2, glm::vec2);
  106. /// Write texture coordinates of vertices on the current quad assuming that
  107. /// the texture is sampled as an axis-aligned rectangle
  108. template <PlusXY PLUS_XY = PlusXY::RIGHT_UP>
  109. void tileTex(Math::RectPP<float>);
  110.  
  111. /// Copy the quads into GPU memory and issue an number of draw calls
  112. //void render(Renderer &) const;
  113.  
  114. private:
  115. std::vector<Quad> quads;
  116. // each section is an index to it's first quad
  117. std::vector<size_t> sections;
  118. std::vector<RenderParams> params;
  119. };
  120. }
  121.  
  122. #include "quad writer.inl"
  123.  
  124. #include <algorithm>
  125. #include <glm/gtc/constants.hpp>
  126.  
  127. inline G2D::QuadWriter::QuadWriter() {
  128. quads.reserve(2048);
  129. sections.reserve(64);
  130. params.reserve(64);
  131. }
  132.  
  133. inline void G2D::QuadWriter::clear() {
  134. quads.clear();
  135. sections.clear();
  136. params.clear();
  137. }
  138.  
  139. inline void G2D::QuadWriter::section(const RenderParams &param) {
  140. sections.push_back(quads.size());
  141. params.push_back(param);
  142. }
  143.  
  144. inline void G2D::QuadWriter::sectionSize(const size_t size) {
  145. quads.reserve(quads.size() + size);
  146. }
  147.  
  148. template <typename Function>
  149. void G2D::QuadWriter::sort(Function &&function) {
  150. assert(sections.size());
  151.  
  152. std::sort(
  153. quads.data() + sections.back(),
  154. quads.data() + quads.size(),
  155. function
  156. );
  157. }
  158.  
  159. inline G2D::Quad &G2D::QuadWriter::quad() {
  160. assert(sections.size());
  161.  
  162. quads.push_back({});
  163. return quads.back();
  164. }
  165.  
  166. inline G2D::Quad &G2D::QuadWriter::dup() {
  167. assert(sections.size() && quads.size());
  168.  
  169. quads.push_back(quads.back());
  170. return quads.back();
  171. }
  172.  
  173. inline void G2D::QuadWriter::depth(const float depth) {
  174. assert(quads.size() && sections.size());
  175.  
  176. Quad &quad = quads.back();
  177. quad[0].pos.z =
  178. quad[1].pos.z =
  179. quad[2].pos.z =
  180. quad[3].pos.z = depth;
  181. }
  182.  
  183. template <typename Enum>
  184. void G2D::QuadWriter::depth(const Enum e) {
  185. depth(G2D::depth(e));
  186. }
  187.  
  188. namespace G2D::detail {
  189. inline void setPos(glm::vec3 &dst, const glm::vec2 src) {
  190. dst.x = src.x;
  191. dst.y = src.y;
  192. }
  193. }
  194.  
  195. inline void G2D::QuadWriter::dupPos() {
  196. assert(quads.size() > 1 && sections.size());
  197.  
  198. Quad &quad = quads.back();
  199. const Quad &prev = *(quads.cend() - 2);
  200. for (size_t i = 0; i != 4; ++i) {
  201. detail::setPos(quad[i].pos, prev[i].pos);
  202. }
  203. }
  204.  
  205. inline void G2D::QuadWriter::dupPosDepth() {
  206. assert(quads.size() > 1 && sections.size());
  207.  
  208. Quad &quad = quads.back();
  209. const Quad &prev = *(quads.cend() - 2);
  210. for (size_t i = 0; i != 4; ++i) {
  211. quad[i].pos = prev[i].pos;
  212. }
  213. }
  214.  
  215. inline void G2D::QuadWriter::tilePos(
  216. const glm::vec2 pos,
  217. const glm::vec2 size
  218. ) {
  219. assert(quads.size() && sections.size());
  220.  
  221. Quad &quad = quads.back();
  222. detail::setPos(quad[0].pos, pos);
  223. detail::setPos(quad[1].pos, {pos.x + size.x, pos.y});
  224. detail::setPos(quad[2].pos, pos + size);
  225. detail::setPos(quad[3].pos, {pos.x, pos.y + size.y});
  226. }
  227.  
  228. inline void G2D::QuadWriter::rotTilePos(
  229. const float angle,
  230. const glm::vec2 pos,
  231. const glm::vec2 size
  232. ) {
  233. assert(quads.size() && sections.size());
  234.  
  235. const glm::vec2 halfSize = size * 0.5f;
  236. const glm::vec2 topRight = glm::vec2(
  237. std::cos(angle + glm::quarter_pi<float>()),
  238. std::sin(angle + glm::quarter_pi<float>())
  239. ) * halfSize * glm::root_two<float>();
  240. const glm::vec2 topLeft = {-topRight.y, topRight.x};
  241. const glm::vec2 botLeft = -topRight;
  242. const glm::vec2 botRight = -topLeft;
  243. const glm::vec2 shift = pos + halfSize;
  244.  
  245. Quad &quad = quads.back();
  246. detail::setPos(quad[0].pos, botLeft + shift);
  247. detail::setPos(quad[1].pos, botRight + shift);
  248. detail::setPos(quad[2].pos, topRight + shift);
  249. detail::setPos(quad[3].pos, topLeft + shift);
  250. }
  251.  
  252. template <G2D::Origin ORIGIN>
  253. void G2D::QuadWriter::rotTilePos(
  254. const float angle,
  255. const glm::vec2 pos,
  256. const glm::vec2 size
  257. ) {
  258. assert(quads.size() && sections.size());
  259.  
  260. constexpr glm::vec2 ORIGIN_POS[9] = {
  261. {0.5f, -0.5f}, {0.0f, -0.5f}, {-0.5f, -0.5f}, {-0.5f, 0.0f},
  262. {-0.5f, 0.5f}, {0.0f, 0.5f}, {0.5f, 0.5f}, {0.5f, 0.0f},
  263. {0.0f, 0.0f}
  264. };
  265. constexpr glm::vec2 originPos = ORIGIN_POS[static_cast<size_t>(ORIGIN)];
  266.  
  267. const glm::vec2 origin = originPos * size;
  268.  
  269. const float c = std::cos(angle);
  270. const float s = std::sin(angle);
  271. const glm::mat2 rot = {
  272. {c, s},
  273. {-s, c}
  274. };
  275.  
  276. const glm::vec2 halfSize = size * 0.5f;
  277. const glm::vec2 tr = halfSize;
  278. const glm::vec2 bl = -halfSize;
  279. const glm::vec2 tl = {bl.x, tr.y};
  280. const glm::vec2 br = {tr.x, bl.y};
  281.  
  282. Quad &quad = quads.back();
  283. detail::setPos(quad[0].pos, pos + rot * (bl + origin));
  284. detail::setPos(quad[1].pos, pos + rot * (br + origin));
  285. detail::setPos(quad[2].pos, pos + rot * (tr + origin));
  286. detail::setPos(quad[3].pos, pos + rot * (tl + origin));
  287. }
  288.  
  289. inline void G2D::QuadWriter::dupTex() {
  290. assert(quads.size() > 1 && sections.size());
  291.  
  292. Quad &quad = quads.back();
  293. const Quad &prev = *(quads.cend() - 2);
  294. for (size_t i = 0; i != 4; ++i) {
  295. quad[i].texCoord = prev[i].texCoord;
  296. }
  297. }
  298.  
  299. template <G2D::PlusXY PLUS_XY>
  300. void G2D::QuadWriter::tileTex(const glm::vec2 min, const glm::vec2 max) {
  301. assert(quads.size() && sections.size());
  302.  
  303. constexpr size_t Is[4][4] = {
  304. // +x +y
  305. {0, 1, 2, 3}, // right up
  306. {1, 0, 3, 2}, // left up
  307. {3, 2, 1, 0}, // right down
  308. {2, 3, 0, 1} // left down
  309. };
  310. constexpr size_t i = static_cast<size_t>(PLUS_XY);
  311.  
  312. Quad &quad = quads.back();
  313. quad[Is[i][0]].texCoord = min;
  314. quad[Is[i][1]].texCoord = {max.x, min.y};
  315. quad[Is[i][2]].texCoord = max;
  316. quad[Is[i][3]].texCoord = {min.x, max.y};
  317. }
  318.  
  319. template <G2D::PlusXY PLUS_XY>
  320. void G2D::QuadWriter::tileTex(const Math::RectPP<float> coords) {
  321. tileTex<PLUS_XY>(coords.min, coords.max);
  322. }
  323.  
  324. /*
  325. Copy all of the quads directly into the GPU buffer with a single call to
  326. glBufferSubData
  327.  
  328. For each section,
  329. set uniforms to the values in RenderParams
  330. make a call glDrawElements
  331.  
  332. inline void G2D::QuadWriter::render(Renderer &renderer) const {
  333. renderer.writeQuads({0, quads.size()}, quads.data());
  334. if (sections.empty()) {
  335. return;
  336. }
  337. QuadRange range;
  338. range.begin = sections[0];
  339. for (size_t s = 1; s != sections.size(); ++s) {
  340. range.end = sections[s];
  341. renderer.render(range, params[s - 1]);
  342. range.begin = range.end;
  343. }
  344. range.end = quads.size();
  345. renderer.render(range, params.back());
  346. }*/
Add Comment
Please, Sign In to add comment