Framebuffer.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. #include <iostream>
  2. #include "client/rendering/wrapper/Framebuffer.h"
  3. Framebuffer::Framebuffer(const WindowSize& size, uint mode, bool texCompare) : mode(mode), textures(0),
  4. buffer(0), error(false) {
  5. glGenFramebuffers(1, &buffer);
  6. glBindFramebuffer(GL_FRAMEBUFFER, buffer);
  7. data[0] = {POSITION, GL_RGB16F, GL_RGB, GL_FLOAT};
  8. data[1] = {NORMAL, GL_RGB16F, GL_RGB, GL_FLOAT};
  9. data[2] = {COLOR, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE};
  10. data[3] = {RED, GL_R32F, GL_RGB, GL_FLOAT};
  11. data[4] = {DEPTH, GL_DEPTH_COMPONENT32, GL_DEPTH_COMPONENT, GL_FLOAT};
  12. GLuint attachments[4];
  13. uint counter = 0;
  14. for(uint i = 0; i < 4; i++) {
  15. if(mode & data[i].mask) {
  16. setupTexture(i, size.width, size.height, attachments, counter);
  17. }
  18. }
  19. if(mode & DEPTH) {
  20. genTexture(4, size.width, size.height);
  21. if(texCompare) {
  22. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
  23. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
  24. }
  25. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, textures[4], 0);
  26. }
  27. glDrawBuffers(counter, attachments);
  28. GLenum error = glCheckFramebufferStatus(GL_FRAMEBUFFER);
  29. if(error != GL_FRAMEBUFFER_COMPLETE) {
  30. std::cout << "frame buffer error: " << getErrorString(error) << "\n";
  31. error = true;
  32. }
  33. }
  34. Framebuffer::~Framebuffer() {
  35. glDeleteFramebuffers(1, &buffer);
  36. for(GLuint& texture : textures) {
  37. glDeleteTextures(1, &texture);
  38. }
  39. }
  40. bool Framebuffer::hasError() const {
  41. return error;
  42. }
  43. void Framebuffer::bind() const {
  44. glBindFramebuffer(GL_FRAMEBUFFER, buffer);
  45. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
  46. }
  47. void Framebuffer::resize(uint width, uint height) const {
  48. for(uint i = 0; i < 5; i++) {
  49. if(mode & data[i].mask) {
  50. glBindTexture(GL_TEXTURE_2D, textures[i]);
  51. glTexImage2D(GL_TEXTURE_2D, 0, data[i].internalFormat, width, height, 0, data[i].format, data[i].type, nullptr);
  52. }
  53. }
  54. }
  55. void Framebuffer::bindTexture(uint textureUnit, GLuint texture) const {
  56. glActiveTexture(GL_TEXTURE0 + textureUnit);
  57. glBindTexture(GL_TEXTURE_2D, texture);
  58. }
  59. void Framebuffer::bindPositionTexture(uint textureUnit) const {
  60. bindTexture(textureUnit, textures[0]);
  61. }
  62. void Framebuffer::bindNormalTexture(uint textureUnit) const {
  63. bindTexture(textureUnit, textures[1]);
  64. }
  65. void Framebuffer::bindColorTexture(uint textureUnit) const {
  66. bindTexture(textureUnit, textures[2]);
  67. }
  68. void Framebuffer::bindRedTexture(uint textureUnit) const {
  69. bindTexture(textureUnit, textures[3]);
  70. }
  71. void Framebuffer::bindDepthTexture(uint textureUnit) const {
  72. bindTexture(textureUnit, textures[4]);
  73. }
  74. void Framebuffer::genTexture(uint index, uint width, uint height) {
  75. glGenTextures(1, textures + index);
  76. glBindTexture(GL_TEXTURE_2D, textures[index]);
  77. glTexImage2D(GL_TEXTURE_2D, 0, data[index].internalFormat, width, height, 0, data[index].format, data[index].type, nullptr);
  78. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  79. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  80. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  81. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  82. }
  83. void Framebuffer::setupTexture(uint index, uint width, uint height, GLuint* attachments, uint& counter) {
  84. genTexture(index, width, height);
  85. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + counter, GL_TEXTURE_2D, textures[index], 0);
  86. attachments[counter] = GL_COLOR_ATTACHMENT0 + counter;
  87. counter++;
  88. }
  89. const char* Framebuffer::getErrorString(GLenum error) const {
  90. switch(error) {
  91. case GL_FRAMEBUFFER_UNDEFINED: return "GL_FRAMEBUFFER_UNDEFINED";
  92. case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: return "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT";
  93. case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: return "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT";
  94. case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: return "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER";
  95. case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: return "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER";
  96. case GL_FRAMEBUFFER_UNSUPPORTED: return "GL_FRAMEBUFFER_UNSUPPORTED";
  97. case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: return "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE";
  98. case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS: return "GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS";
  99. }
  100. return "unknown error";
  101. }