Framebuffer.cpp 4.9 KB

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