Otclient  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  } else
81  glImage = image;
82 
83  bind();
84 
85  if(buildMipmaps) {
86  int level = 0;
87  do {
88  setupPixels(level++, glImage->getSize(), glImage->getPixelData(), glImage->getBpp(), compress);
89  } while(glImage->nextMipmap());
90  m_hasMipmaps = true;
91  } else
92  setupPixels(0, glImage->getSize(), glImage->getPixelData(), glImage->getBpp(), compress);
93 
94  setupWrap();
95  setupFilters();
96 }
97 
99 {
100  // must reset painter texture state
101  g_painter->setTexture(this);
102  glBindTexture(GL_TEXTURE_2D, m_id);
103 }
104 
105 void Texture::copyFromScreen(const Rect& screenRect)
106 {
107  bind();
108  glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, screenRect.x(), screenRect.y(), screenRect.width(), screenRect.height());
109 }
110 
112 {
114  return false;
115 
116  bind();
117 
118  if(!m_hasMipmaps) {
119  m_hasMipmaps = true;
120  setupFilters();
121  }
122 
123  glGenerateMipmap(GL_TEXTURE_2D);
124  return true;
125 }
126 
127 void Texture::setSmooth(bool smooth)
128 {
129  if(smooth && !g_graphics.canUseBilinearFiltering())
130  return;
131 
132  if(smooth == m_smooth)
133  return;
134 
135  m_smooth = smooth;
136  bind();
137  setupFilters();
138 }
139 
140 void Texture::setRepeat(bool repeat)
141 {
142  if(m_repeat == repeat)
143  return;
144 
145  m_repeat = repeat;
146  bind();
147  setupWrap();
148 }
149 
150 void Texture::setUpsideDown(bool upsideDown)
151 {
152  if(m_upsideDown == upsideDown)
153  return;
154  m_upsideDown = upsideDown;
156 }
157 
159 {
160  glGenTextures(1, &m_id);
161  assert(m_id != 0);
162 }
163 
164 bool Texture::setupSize(const Size& size, bool forcePowerOfTwo)
165 {
166  Size glSize;
167  if(!g_graphics.canUseNonPowerOfTwoTextures() || forcePowerOfTwo)
169  else
170  glSize = size;
171 
172  // checks texture max size
173  if(std::max<int>(glSize.width(), glSize.height()) > g_graphics.getMaxTextureSize()) {
174  g_logger.error(stdext::format("loading texture with size %dx%d failed, "
175  "the maximum size allowed by the graphics card is %dx%d,"
176  "to prevent crashes the texture will be displayed as a blank texture",
178  return false;
179  }
180 
181  m_size = size;
182  m_glSize = glSize;
184  return true;
185 }
186 
188 {
189  int texParam;
191  texParam = GL_CLAMP_TO_EDGE;
192  else
193  texParam = GL_REPEAT;
194 
195  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, texParam);
196  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, texParam);
197 }
198 
200 {
201  int minFilter;
202  int magFilter;
203  if(m_smooth) {
204  minFilter = m_hasMipmaps ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
205  magFilter = GL_LINEAR;
206  } else {
207  minFilter = m_hasMipmaps ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST;
208  magFilter = GL_NEAREST;
209  }
210  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
211  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
212 }
213 
215 {
216  if(m_upsideDown) {
217  m_transformMatrix = { 1.0f/m_glSize.width(), 0.0f, 0.0f,
218  0.0f, -1.0f/m_glSize.height(), 0.0f,
219  0.0f, m_size.height()/(float)m_glSize.height(), 1.0f };
220  } else {
221  m_transformMatrix = { 1.0f/m_glSize.width(), 0.0f, 0.0f,
222  0.0f, 1.0f/m_glSize.height(), 0.0f,
223  0.0f, 0.0f, 1.0f };
224  }
225 }
226 
227 void Texture::setupPixels(int level, const Size& size, uchar* pixels, int channels, bool compress)
228 {
229  GLenum format = 0;
230  switch(channels) {
231  case 4:
232  format = GL_RGBA;
233  break;
234  case 3:
235  format = GL_RGB;
236  break;
237  case 2:
238  format = GL_LUMINANCE_ALPHA;
239  break;
240  case 1:
241  format = GL_LUMINANCE;
242  break;
243  }
244 
245  GLenum internalFormat = GL_RGBA;
246 
247 #ifdef OPENGL_ES
248  //TODO
249 #else
250  if(compress)
251  internalFormat = GL_COMPRESSED_RGBA;
252 #endif
253 
254  glTexImage2D(GL_TEXTURE_2D, level, internalFormat, size.width(), size.height(), 0, format, GL_UNSIGNED_BYTE, pixels);
255 }
Texture::setupWrap
void setupWrap()
Definition: texture.cpp:187
Texture::createTexture
void createTexture()
Definition: texture.cpp:158
Texture::m_upsideDown
stdext::boolean< false > m_upsideDown
Definition: texture.h:73
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:66
Texture::setUpsideDown
void setUpsideDown(bool upsideDown)
Definition: texture.cpp:150
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:82
Texture::setupSize
bool setupSize(const Size &size, bool forcePowerOfTwo=false)
Definition: texture.cpp:164
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:68
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:71
Texture::m_time
ticks_t m_time
Definition: texture.h:67
Texture::bind
void bind()
Definition: texture.cpp:98
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:227
image.h
Texture::m_glSize
Size m_glSize
Definition: texture.h:69
g_graphics
Graphics g_graphics
Definition: graphics.cpp:44
Texture::m_repeat
stdext::boolean< false > m_repeat
Definition: texture.h:74
Texture::copyFromScreen
void copyFromScreen(const Rect &screenRect)
Definition: texture.cpp:105
g_app
ConsoleApplication g_app
Definition: consoleapplication.cpp:32
Texture::buildHardwareMipmaps
virtual bool buildHardwareMipmaps()
Definition: texture.cpp:111
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:214
Texture::setSmooth
virtual void setSmooth(bool smooth)
Definition: texture.cpp:127
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:72
framebuffer.h
Texture::m_transformMatrix
Matrix3 m_transformMatrix
Definition: texture.h:70
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 >
application.h
Texture::setupFilters
void setupFilters()
Definition: texture.cpp:199
Texture::setRepeat
virtual void setRepeat(bool repeat)
Definition: texture.cpp:140