Framebuffer.h 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. #ifndef FRAMEBUFFER_H
  2. #define FRAMEBUFFER_H
  3. #include <iostream>
  4. #include "utils/List.h"
  5. #include "utils/Size.h"
  6. #include "wrapper/Texture.h"
  7. template<int N>
  8. class Framebuffer final {
  9. List<Texture, N> textures;
  10. GLuint buffer;
  11. public:
  12. template<typename... Args>
  13. Framebuffer(const TextureFormat& a, Args&&... args) : buffer(0) {
  14. const int size = sizeof...(args) + 1;
  15. TextureFormat init[size] = {a, args...};
  16. static_assert(N == size, "framebuffer size and amount of arguments do not match");
  17. for(int i = 0; i < N; i++) {
  18. textures.add(init[i]);
  19. textures[i].setClampWrap();
  20. if(init[i].linear) {
  21. textures[i].setLinearFilter();
  22. }
  23. }
  24. }
  25. ~Framebuffer() {
  26. glDeleteFramebuffers(1, &buffer);
  27. }
  28. Framebuffer(const Framebuffer&) = delete;
  29. Framebuffer(Framebuffer&&) = delete;
  30. Framebuffer& operator=(const Framebuffer&) = delete;
  31. Framebuffer& operator=(Framebuffer&&) = delete;
  32. bool init(const Size& size) {
  33. glGenFramebuffers(1, &buffer);
  34. glBindFramebuffer(GL_FRAMEBUFFER, buffer);
  35. List<GLenum, N> attachments;
  36. for(Texture& t : textures) {
  37. t.setData(size.width, size.height);
  38. if(t.format.depth) {
  39. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, t.texture, 0);
  40. } else {
  41. GLenum c = GL_COLOR_ATTACHMENT0 + attachments.getLength();
  42. glFramebufferTexture2D(GL_FRAMEBUFFER, c, GL_TEXTURE_2D, t.texture, 0);
  43. attachments.add(c);
  44. }
  45. }
  46. glDrawBuffers(attachments.getLength(), attachments.begin());
  47. return hasError();
  48. }
  49. void bindAndClear() {
  50. glBindFramebuffer(GL_FRAMEBUFFER, buffer);
  51. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
  52. }
  53. void bindTextureTo(int index, int textureUnit) const {
  54. textures[index].bindTo(textureUnit);
  55. }
  56. void resize(const Size& size) {
  57. for(Texture& t : textures) {
  58. t.setData(size.width, size.height);
  59. }
  60. }
  61. private:
  62. bool hasError() const {
  63. GLenum error = glCheckFramebufferStatus(GL_FRAMEBUFFER);
  64. if(error == GL_FRAMEBUFFER_COMPLETE) {
  65. return false;
  66. }
  67. switch(error) {
  68. case GL_FRAMEBUFFER_UNDEFINED: std::cout << "undefined framebuffer\n"; return true;
  69. case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: std::cout << "incomplete framebuffer attachment\n"; return true;
  70. case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
  71. std::cout << "incomplete missing framebuffer attachment\n";
  72. return true;
  73. case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
  74. std::cout << "incomplete framebuffer draw buffer\n";
  75. return true;
  76. case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
  77. std::cout << "incomplete framebuffer read buffer\n";
  78. return true;
  79. case GL_FRAMEBUFFER_UNSUPPORTED: std::cout << "unsupported framebuffer\n"; return true;
  80. case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
  81. std::cout << "incomplete framebuffer multisample\n";
  82. return true;
  83. case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS:
  84. std::cout << "incomplete framebuffer layer targets\n";
  85. return true;
  86. }
  87. return "unknown error";
  88. }
  89. };
  90. #endif