💿🐜 Antkeeper source code https://antkeeper.com
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.

220 lines
5.8 KiB

  1. /*
  2. * Copyright (C) 2023 Christopher J. Howard
  3. *
  4. * This file is part of Antkeeper source code.
  5. *
  6. * Antkeeper source code is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Antkeeper source code is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include <engine/gl/rasterizer.hpp>
  20. #include <engine/gl/framebuffer.hpp>
  21. #include <engine/gl/shader-program.hpp>
  22. #include <engine/gl/vertex-array.hpp>
  23. #include <glad/glad.h>
  24. #include <engine/debug/log.hpp>
  25. #include <stdexcept>
  26. namespace gl {
  27. static constexpr GLenum drawing_mode_lut[] =
  28. {
  29. GL_POINTS,
  30. GL_LINE_STRIP,
  31. GL_LINE_LOOP,
  32. GL_LINES,
  33. GL_LINE_STRIP_ADJACENCY,
  34. GL_LINES_ADJACENCY,
  35. GL_TRIANGLE_STRIP,
  36. GL_TRIANGLE_FAN,
  37. GL_TRIANGLES,
  38. GL_TRIANGLE_STRIP_ADJACENCY,
  39. GL_TRIANGLES_ADJACENCY
  40. };
  41. static constexpr GLenum element_array_type_lut[] =
  42. {
  43. GL_UNSIGNED_BYTE,
  44. GL_UNSIGNED_SHORT,
  45. GL_UNSIGNED_INT
  46. };
  47. rasterizer::rasterizer():
  48. bound_vao(nullptr),
  49. bound_shader_program(nullptr)
  50. {
  51. // Determine dimensions of default framebuffer
  52. GLint scissor_box[4] = {0, 0, 0, 0};
  53. glGetIntegerv(GL_SCISSOR_BOX, scissor_box);
  54. // Setup default framebuffer
  55. default_framebuffer = std::make_unique<framebuffer>();
  56. default_framebuffer->m_gl_framebuffer_id = 0;
  57. default_framebuffer->m_dimensions = {scissor_box[2], scissor_box[3]};
  58. // Bind default framebuffer
  59. bound_framebuffer = default_framebuffer.get();
  60. // Enable seamless filtering across cubemap faces
  61. glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
  62. if (GLAD_GL_ARB_clip_control)
  63. {
  64. // Improve depth buffer precision by setting depth range to `[0, 1]`.
  65. glClipControl(GL_LOWER_LEFT, GL_ZERO_TO_ONE);
  66. }
  67. else
  68. {
  69. debug::log::error("glClipControl not supported");
  70. throw std::runtime_error("glClipControl not supported");
  71. }
  72. // glClipControl alternative for OpenGL < v4.5 (need to adjust shadow scale-bias matrix too)
  73. // glDepthRange(-1.0f, 1.0f);
  74. // Set clear depth to `0` for reversed depth
  75. glClearDepth(0.0f);
  76. glDisable(GL_MULTISAMPLE);
  77. dummy_vao = std::make_unique<gl::vertex_array>();
  78. }
  79. rasterizer::~rasterizer()
  80. {}
  81. void rasterizer::context_resized(int width, int height)
  82. {
  83. default_framebuffer->m_dimensions = {width, height};
  84. }
  85. void rasterizer::use_framebuffer(const gl::framebuffer& framebuffer)
  86. {
  87. if (bound_framebuffer != &framebuffer)
  88. {
  89. glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.m_gl_framebuffer_id);
  90. bound_framebuffer = &framebuffer;
  91. }
  92. }
  93. void rasterizer::set_clear_color(float r, float g, float b, float a)
  94. {
  95. glClearColor(r, g, b, a);
  96. }
  97. void rasterizer::set_clear_depth(float depth)
  98. {
  99. glClearDepth(depth);
  100. }
  101. void rasterizer::set_clear_stencil(int s)
  102. {
  103. glClearStencil(s);
  104. }
  105. void rasterizer::clear_framebuffer(bool color, bool depth, bool stencil)
  106. {
  107. GLbitfield mask = 0;
  108. if (color)
  109. mask |= GL_COLOR_BUFFER_BIT;
  110. if (depth)
  111. mask |= GL_DEPTH_BUFFER_BIT;
  112. if (stencil)
  113. mask |= GL_STENCIL_BUFFER_BIT;
  114. glClear(mask);
  115. }
  116. void rasterizer::set_viewport(int x, int y, int width, int height)
  117. {
  118. glViewport(x, y, static_cast<GLsizei>(width), static_cast<GLsizei>(height));
  119. }
  120. void rasterizer::use_program(const shader_program& program)
  121. {
  122. if (bound_shader_program != &program)
  123. {
  124. glUseProgram(program.gl_program_id);
  125. bound_shader_program = &program;
  126. }
  127. }
  128. void rasterizer::draw_arrays(const vertex_array& vao, drawing_mode mode, std::size_t offset, std::size_t count)
  129. {
  130. GLenum gl_mode = drawing_mode_lut[static_cast<std::size_t>(mode)];
  131. if (bound_vao != &vao)
  132. {
  133. glBindVertexArray(vao.gl_array_id);
  134. bound_vao = &vao;
  135. }
  136. glDrawArrays(gl_mode, static_cast<GLint>(offset), static_cast<GLsizei>(count));
  137. }
  138. void rasterizer::draw_arrays(drawing_mode mode, std::size_t offset, std::size_t count)
  139. {
  140. GLenum gl_mode = drawing_mode_lut[static_cast<std::size_t>(mode)];
  141. if (bound_vao != dummy_vao.get())
  142. {
  143. glBindVertexArray(dummy_vao->gl_array_id);
  144. bound_vao = dummy_vao.get();
  145. }
  146. glDrawArrays(gl_mode, static_cast<GLint>(offset), static_cast<GLsizei>(count));
  147. }
  148. void rasterizer::draw_arrays_instanced(const vertex_array& vao, drawing_mode mode, std::size_t offset, std::size_t count, std::size_t instance_count)
  149. {
  150. GLenum gl_mode = drawing_mode_lut[static_cast<std::size_t>(mode)];
  151. if (bound_vao != &vao)
  152. {
  153. glBindVertexArray(vao.gl_array_id);
  154. bound_vao = &vao;
  155. }
  156. glDrawArraysInstanced(gl_mode, static_cast<GLint>(offset), static_cast<GLsizei>(count), static_cast<GLsizei>(instance_count));
  157. }
  158. void rasterizer::draw_elements(const vertex_array& vao, drawing_mode mode, std::size_t offset, std::size_t count, element_array_type type)
  159. {
  160. GLenum gl_mode = drawing_mode_lut[static_cast<std::size_t>(mode)];
  161. GLenum gl_type = element_array_type_lut[static_cast<std::size_t>(type)];
  162. if (bound_vao != &vao)
  163. {
  164. glBindVertexArray(vao.gl_array_id);
  165. bound_vao = &vao;
  166. }
  167. glDrawElements(gl_mode, static_cast<GLsizei>(count), gl_type, reinterpret_cast<const GLvoid*>(offset));
  168. }
  169. void rasterizer::draw_elements(drawing_mode mode, std::size_t offset, std::size_t count, element_array_type type)
  170. {
  171. GLenum gl_mode = drawing_mode_lut[static_cast<std::size_t>(mode)];
  172. GLenum gl_type = element_array_type_lut[static_cast<std::size_t>(type)];
  173. if (bound_vao != dummy_vao.get())
  174. {
  175. glBindVertexArray(dummy_vao->gl_array_id);
  176. bound_vao = dummy_vao.get();
  177. }
  178. glDrawElements(gl_mode, static_cast<GLsizei>(count), gl_type, reinterpret_cast<const GLvoid*>(offset));
  179. }
  180. } // namespace gl