Otclient 1.0  14/8/2020
texture.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010-2020 OTClient <https://github.com/edubart/otclient>
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20  * THE SOFTWARE.
21  */
22 
23 #include "texture.h"
24 #include "graphics.h"
25 #include "framebuffer.h"
26 #include "image.h"
27 
29 
31 {
32  m_id = 0;
33  m_time = 0;
34 }
35 
36 Texture::Texture(const Size& size)
37 {
38  m_id = 0;
39  m_time = 0;
40 
41  if (!setupSize(size))
42  return;
43 
44  createTexture();
45  bind();
46  setupPixels(0, m_glSize, nullptr, 4);
47  setupWrap();
48  setupFilters();
49 }
50 
51 Texture::Texture(const ImagePtr& image, bool buildMipmaps, bool compress)
52 {
53  m_id = 0;
54  m_time = 0;
55 
56  createTexture();
57 
58  uploadPixels(image, buildMipmaps, compress);
59 }
60 
62 {
63 #ifndef NDEBUG
64  assert(!g_app.isTerminated());
65 #endif
66  // free texture from gl memory
67  if (g_graphics.ok() && m_id != 0)
68  glDeleteTextures(1, &m_id);
69 }
70 
71 void Texture::uploadPixels(const ImagePtr& image, bool buildMipmaps, bool compress)
72 {
73  if (!setupSize(image->getSize(), buildMipmaps))
74  return;
75 
76  ImagePtr glImage = image;
77  if (m_size != m_glSize) {
78  glImage = ImagePtr(new Image(m_glSize, image->getBpp()));
79  glImage->paste(image);
80  }
81  else
82  glImage = image;
83 
84  bind();
85 
86  if (buildMipmaps) {
87  int level = 0;
88  do {
89  setupPixels(level++, glImage->getSize(), glImage->getPixelData(), glImage->getBpp(), compress);
90  } while (glImage->nextMipmap());
91  m_hasMipmaps = true;
92  }
93  else
94  setupPixels(0, glImage->getSize(), glImage->getPixelData(), glImage->getBpp(), compress);
95 
96  setupWrap();
97  setupFilters();
98 
99  m_opaque = !image->hasTransparentPixel();
100 }
101 
103 {
104  // must reset painter texture state
105  g_painter->setTexture(this);
106  glBindTexture(GL_TEXTURE_2D, m_id);
107 }
108 
109 void Texture::copyFromScreen(const Rect& screenRect)
110 {
111  bind();
112  glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, screenRect.x(), screenRect.y(), screenRect.width(), screenRect.height());
113 }
114 
116 {
118  return false;
119 
120  bind();
121 
122  if (!m_hasMipmaps) {
123  m_hasMipmaps = true;
124  setupFilters();
125  }
126 
127  glGenerateMipmap(GL_TEXTURE_2D);
128  return true;
129 }
130 
131 void Texture::setSmooth(bool smooth)
132 {
133  if (smooth && !g_graphics.canUseBilinearFiltering())
134  return;
135 
136  if (smooth == m_smooth)
137  return;
138 
139  m_smooth = smooth;
140  bind();
141  setupFilters();
142 }
143 
144 void Texture::setRepeat(bool repeat)
145 {
146  if (m_repeat == repeat)
147  return;
148 
149  m_repeat = repeat;
150  bind();
151  setupWrap();
152 }
153 
154 void Texture::setUpsideDown(bool upsideDown)
155 {
156  if (m_upsideDown == upsideDown)
157  return;
158  m_upsideDown = upsideDown;
160 }
161 
163 {
164  glGenTextures(1, &m_id);
165  assert(m_id != 0);
166 }
167 
168 bool Texture::setupSize(const Size& size, bool forcePowerOfTwo)
169 {
170  Size glSize;
171  if (!g_graphics.canUseNonPowerOfTwoTextures() || forcePowerOfTwo)
173  else
174  glSize = size;
175 
176  // checks texture max size
177  if (std::max<int>(glSize.width(), glSize.height()) > g_graphics.getMaxTextureSize()) {
178  g_logger.error(stdext::format("loading texture with size %dx%d failed, "
179  "the maximum size allowed by the graphics card is %dx%d,"
180  "to prevent crashes the texture will be displayed as a blank texture",
182  return false;
183  }
184 
185  m_size = size;
186  m_glSize = glSize;
188  return true;
189 }
190 
192 {
193  int texParam;
195  texParam = GL_CLAMP_TO_EDGE;
196  else
197  texParam = GL_REPEAT;
198 
199  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, texParam);
200  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, texParam);
201 }
202 
204 {
205  int minFilter;
206  int magFilter;
207  if (m_smooth) {
208  minFilter = m_hasMipmaps ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
209  magFilter = GL_LINEAR;
210  }
211  else {
212  minFilter = m_hasMipmaps ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST;
213  magFilter = GL_NEAREST;
214  }
215  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
216  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
217 }
218 
220 {
221  if (m_upsideDown) {
222  m_transformMatrix = { 1.0f / m_glSize.width(), 0.0f, 0.0f,
223  0.0f, -1.0f / m_glSize.height(), 0.0f,
224  0.0f, m_size.height() / static_cast<float>(m_glSize.height()), 1.0f };
225  }
226  else {
227  m_transformMatrix = { 1.0f / m_glSize.width(), 0.0f, 0.0f,
228  0.0f, 1.0f / m_glSize.height(), 0.0f,
229  0.0f, 0.0f, 1.0f };
230  }
231 }
232 
233 void Texture::setupPixels(int level, const Size& size, uchar* pixels, int channels, bool compress)
234 {
235  GLenum format = 0;
236  switch (channels) {
237  case 4:
238  format = GL_RGBA;
239  break;
240  case 3:
241  format = GL_RGB;
242  break;
243  case 2:
244  format = GL_LUMINANCE_ALPHA;
245  break;
246  case 1:
247  format = GL_LUMINANCE;
248  break;
249  }
250 
251  GLenum internalFormat = GL_RGBA;
252 
253 #ifdef OPENGL_ES
254  //TODO
255 #else
256  if (compress)
257  internalFormat = GL_COMPRESSED_RGBA;
258 #endif
259 
260  glTexImage2D(GL_TEXTURE_2D, level, internalFormat, size.width(), size.height(), 0, format, GL_UNSIGNED_BYTE, pixels);
261 }
Texture::setupWrap
void setupWrap()
Definition: texture.cpp:191
Texture::createTexture
void createTexture()
Definition: texture.cpp:162
Texture::m_upsideDown
stdext::boolean< false > m_upsideDown
Definition: texture.h:74
graphics.h
Painter::setTexture
virtual void setTexture(Texture *texture)=0
Graphics::ok
bool ok()
Definition: graphics.h:65
TRect< int >
TRect::x
T x() const
Definition: rect.h:58
Texture::m_id
uint m_id
Definition: texture.h:67
Texture::setUpsideDown
void setUpsideDown(bool upsideDown)
Definition: texture.cpp:154
Graphics::canUseBilinearFiltering
bool canUseBilinearFiltering()
Definition: graphics.cpp:308
Logger::error
void error(const std::string &what)
Definition: logger.h:54
Texture::Texture
Texture()
Definition: texture.cpp:30
Graphics::getMaxTextureSize
int getMaxTextureSize()
Definition: graphics.h:55
stdext::format
std::string format()
Definition: format.h:84
Texture::setupSize
bool setupSize(const Size &size, bool forcePowerOfTwo=false)
Definition: texture.cpp:168
Texture::~Texture
virtual ~Texture()
Definition: texture.cpp:61
ImagePtr
stdext::shared_object_ptr< Image > ImagePtr
Definition: declarations.h:46
TSize::width
int width() const
Definition: size.h:43
Graphics::canUseClampToEdge
bool canUseClampToEdge()
Definition: graphics.cpp:363
Image
Definition: image.h:29
Texture::m_size
Size m_size
Definition: texture.h:69
Texture::uploadPixels
void uploadPixels(const ImagePtr &image, bool buildMipmaps=false, bool compress=false)
Definition: texture.cpp:71
Texture::m_hasMipmaps
stdext::boolean< false > m_hasMipmaps
Definition: texture.h:72
Texture::m_time
ticks_t m_time
Definition: texture.h:68
Texture::bind
void bind()
Definition: texture.cpp:102
Graphics::canUseHardwareMipmaps
bool canUseHardwareMipmaps()
Definition: graphics.cpp:349
g_logger
Logger g_logger
Definition: logger.cpp:35
TRect::y
T y() const
Definition: rect.h:59
TSize::resize
void resize(T w, T h)
Definition: size.h:46
Texture::setupPixels
void setupPixels(int level, const Size &size, uchar *pixels, int channels=4, bool compress=false)
Definition: texture.cpp:233
image.h
Texture::m_glSize
Size m_glSize
Definition: texture.h:70
g_graphics
Graphics g_graphics
Definition: graphics.cpp:44
Texture::m_repeat
stdext::boolean< false > m_repeat
Definition: texture.h:75
Texture::copyFromScreen
void copyFromScreen(const Rect &screenRect)
Definition: texture.cpp:109
g_app
ConsoleApplication g_app
Definition: consoleapplication.cpp:32
Texture::buildHardwareMipmaps
virtual bool buildHardwareMipmaps()
Definition: texture.cpp:115
TSize::height
int height() const
Definition: size.h:44
uchar
unsigned char uchar
Definition: types.h:29
Graphics::canUseNonPowerOfTwoTextures
bool canUseNonPowerOfTwoTextures()
Definition: graphics.cpp:329
texture.h
stdext::shared_object_ptr
Definition: shared_object.h:39
Texture::setupTranformMatrix
void setupTranformMatrix()
Definition: texture.cpp:219
Texture::setSmooth
virtual void setSmooth(bool smooth)
Definition: texture.cpp:131
Application::isTerminated
bool isTerminated()
Definition: application.h:50
g_painter
Painter * g_painter
Definition: painter.cpp:28
TRect::height
T height() const
Definition: rect.h:70
Texture::m_smooth
stdext::boolean< false > m_smooth
Definition: texture.h:73
framebuffer.h
Texture::m_transformMatrix
Matrix3 m_transformMatrix
Definition: texture.h:71
TRect::width
T width() const
Definition: rect.h:69
stdext::to_power_of_two
size_t to_power_of_two(size_t v)
Definition: math.h:32
TSize< int >
Texture::m_opaque
stdext::boolean< false > m_opaque
Definition: texture.h:76
application.h
Texture::setupFilters
void setupFilters()
Definition: texture.cpp:203
Texture::setRepeat
virtual void setRepeat(bool repeat)
Definition: texture.cpp:144