texture.cpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. #include "texture.h"
  2. #include <GL/gl.h>
  3. #include <QDebug>
  4. #include <QImage>
  5. #include <qglobal.h>
  6. #include <qhashfunctions.h>
  7. #include <qimage.h>
  8. namespace Render::GL {
  9. Texture::Texture() = default;
  10. Texture::~Texture() {
  11. if (m_texture != 0) {
  12. glDeleteTextures(1, &m_texture);
  13. }
  14. }
  15. auto Texture::loadFromFile(const QString &path) -> bool {
  16. initializeOpenGLFunctions();
  17. QImage image;
  18. if (!image.load(path)) {
  19. qWarning() << "Failed to load texture:" << path;
  20. return false;
  21. }
  22. image = image.convertToFormat(QImage::Format_RGBA8888).mirrored();
  23. m_width = image.width();
  24. m_height = image.height();
  25. m_format = Format::RGBA;
  26. bind();
  27. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_RGBA,
  28. GL_UNSIGNED_BYTE, image.constBits());
  29. setFilter(Filter::Linear, Filter::Linear);
  30. setWrap(Wrap::Repeat, Wrap::Repeat);
  31. glGenerateMipmap(GL_TEXTURE_2D);
  32. unbind();
  33. return true;
  34. }
  35. auto Texture::createEmpty(int width, int height, Format format) -> bool {
  36. initializeOpenGLFunctions();
  37. m_width = width;
  38. m_height = height;
  39. m_format = format;
  40. bind();
  41. GLenum const gl_format = getGLFormat(format);
  42. GLenum internal_format = gl_format;
  43. GLenum type = GL_UNSIGNED_BYTE;
  44. if (format == Format::Depth) {
  45. internal_format = GL_DEPTH_COMPONENT;
  46. type = GL_FLOAT;
  47. }
  48. glTexImage2D(GL_TEXTURE_2D, 0, internal_format, width, height, 0, gl_format,
  49. type, nullptr);
  50. setFilter(Filter::Linear, Filter::Linear);
  51. setWrap(Wrap::ClampToEdge, Wrap::ClampToEdge);
  52. unbind();
  53. return true;
  54. }
  55. void Texture::bind(int unit) {
  56. initializeOpenGLFunctions();
  57. if (m_texture == 0U) {
  58. glGenTextures(1, &m_texture);
  59. }
  60. glActiveTexture(GL_TEXTURE0 + unit);
  61. glBindTexture(GL_TEXTURE_2D, m_texture);
  62. }
  63. void Texture::unbind() {
  64. initializeOpenGLFunctions();
  65. glBindTexture(GL_TEXTURE_2D, 0);
  66. }
  67. void Texture::setFilter(Filter minFilter, Filter magFilter) {
  68. bind();
  69. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, getGLFilter(minFilter));
  70. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, getGLFilter(magFilter));
  71. }
  72. void Texture::setWrap(Wrap sWrap, Wrap tWrap) {
  73. bind();
  74. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, getGLWrap(sWrap));
  75. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, getGLWrap(tWrap));
  76. }
  77. auto Texture::getGLFormat(Format format) -> GLenum {
  78. switch (format) {
  79. case Format::RGB:
  80. return GL_RGB;
  81. case Format::RGBA:
  82. return GL_RGBA;
  83. case Format::Depth:
  84. return GL_DEPTH_COMPONENT;
  85. }
  86. return GL_RGBA;
  87. }
  88. auto Texture::getGLFilter(Filter filter) -> GLenum {
  89. switch (filter) {
  90. case Filter::Nearest:
  91. return GL_NEAREST;
  92. case Filter::Linear:
  93. return GL_LINEAR;
  94. }
  95. return GL_LINEAR;
  96. }
  97. auto Texture::getGLWrap(Wrap wrap) -> GLenum {
  98. switch (wrap) {
  99. case Wrap::Repeat:
  100. return GL_REPEAT;
  101. case Wrap::ClampToEdge:
  102. return GL_CLAMP_TO_EDGE;
  103. case Wrap::ClampToBorder:
  104. return GL_CLAMP_TO_BORDER;
  105. }
  106. return GL_REPEAT;
  107. }
  108. } // namespace Render::GL