galaxy 1.0.0
Real-Time C++23 Game Programming Framework. Built on data-driven design principles and agile software engineering.
Loading...
Searching...
No Matches
Texture.cpp
Go to the documentation of this file.
1
7
8#include <entt/locator/locator.hpp>
9#include <glad/glad.h>
10#include <stb_image.h>
11#include <stb_image_write.h>
12
18
19#include "Texture.hpp"
20
21#ifdef GALAXY_WIN_PLATFORM
22#pragma warning(push)
23#pragma warning(disable : 26493)
24#endif
25
26namespace galaxy
27{
29 : m_id {0}
30 , m_handle {0}
31 , m_width {0}
32 , m_height {0}
33 {
34 glCreateTextures(GL_TEXTURE_2D, 1, &m_id);
35 }
36
38 {
39 this->destroy();
40
41 this->m_id = t.m_id;
42 this->m_handle = t.m_handle;
43 this->m_width = t.m_width;
44 this->m_height = t.m_height;
45
46 t.m_id = 0;
47 t.m_handle = 0;
48 }
49
51 {
52 if (this != &t)
53 {
54 this->destroy();
55
56 this->m_id = t.m_id;
57 this->m_handle = t.m_handle;
58 this->m_width = t.m_width;
59 this->m_height = t.m_height;
60
61 t.m_id = 0;
62 t.m_handle = 0;
63 }
64
65 return *this;
66 }
67
69 {
70 destroy();
71 }
72
73 bool Texture::load(const std::string& file)
74 {
75 auto& fs = entt::locator<VirtualFileSystem>::value();
76
77 auto data = fs.read_binary(file);
78 return load_mem(data);
79 }
80
81 bool Texture::load_mem(std::span<std::uint8_t> buffer)
82 {
83 auto result = true;
84
85 if (!buffer.empty())
86 {
87 stbi_set_flip_vertically_on_load(true);
88 unsigned char* data = stbi_load_from_memory(buffer.data(), static_cast<int>(buffer.size_bytes()), &m_width, &m_height, nullptr, STBI_rgb_alpha);
89
90 if (data)
91 {
92 glTextureStorage2D(m_id, 1, GL_RGBA8, m_width, m_height);
93 glTextureSubImage2D(m_id, 0, 0, 0, m_width, m_height, GL_RGBA, GL_UNSIGNED_BYTE, data);
94
95 set_filter();
96 set_mode();
98
99 m_handle = glGetTextureHandleARB(m_id);
100 glMakeTextureHandleResidentARB(m_handle);
101 }
102 else
103 {
104 GALAXY_LOG(GALAXY_ERROR, "Failed to load texture from memory because '{0}'.", stbi_failure_reason());
105 result = false;
106 }
107
108 stbi_image_free(data);
109 }
110 else
111 {
112 GALAXY_LOG(GALAXY_ERROR, "Tried to pass empty buffer to loading texture from memory.");
113 result = false;
114 }
115
116 return result;
117 }
118
119 void Texture::save(std::string_view file)
120 {
121 auto& fs = entt::locator<VirtualFileSystem>::value();
122
123 auto path = std::filesystem::path(file);
124 if (!path.is_absolute())
125 {
126 path = Settings::root_dir() / path;
127 }
128
129 if (!path.has_extension())
130 {
131 path.replace_extension(".png");
132 }
133
134 if (!std::filesystem::exists(path.parent_path()))
135 {
136 std::filesystem::create_directories(path.parent_path());
137 }
138
139 std::vector<unsigned int> pixels(static_cast<unsigned int>(m_width) * static_cast<unsigned int>(m_height) * 4u, 0);
140
141 glGetTextureImage(m_id, 0, GL_RGBA, GL_UNSIGNED_BYTE, static_cast<GLsizei>(pixels.size()), pixels.data());
142
143 stbi_flip_vertically_on_write(true);
144
145 int len = 0;
146
147 unsigned char* png = stbi_write_png_to_mem((const unsigned char*)pixels.data(), m_width * 4, m_width, m_height, 4, &len);
148
149 if (!fs.write_raw(png, len, path.string()))
150 {
151 GALAXY_LOG(GALAXY_ERROR, "Failed to write '{0}' to disk.", path.string());
152 }
153
154 std::free(png);
155 }
156
157 void Texture::bind() const noexcept
158 {
159 glBindTexture(GL_TEXTURE_2D, m_id);
160 }
161
162 void Texture::unbind() const noexcept
163 {
164 glBindTexture(GL_TEXTURE_2D, 0);
165 }
166
168 {
169 if (m_handle != 0)
170 {
171 glMakeTextureHandleNonResidentARB(m_handle);
172 m_handle = 0;
173 }
174
175 if (m_id != 0)
176 {
177 glDeleteTextures(1, &m_id);
178 m_id = 0;
179 }
180 }
181
183 {
184 destroy();
185 glCreateTextures(GL_TEXTURE_2D, 1, &m_id);
186 }
187
188 float Texture::width() const noexcept
189 {
190 return static_cast<float>(m_width);
191 }
192
193 float Texture::height() const noexcept
194 {
195 return static_cast<float>(m_height);
196 }
197
198 unsigned int Texture::id() const noexcept
199 {
200 return m_id;
201 }
202
203 std::uint64_t Texture::handle() const noexcept
204 {
205 return m_handle;
206 }
207
208 void Texture::set_filter() const noexcept
209 {
210 if (Settings::mipmap())
211 {
212 glGenerateTextureMipmap(m_id);
213
214 switch (Settings::texture_filter())
215 {
217 glTextureParameteri(m_id, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
218 glTextureParameteri(m_id, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
219 break;
221 glTextureParameteri(m_id, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
222 glTextureParameteri(m_id, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
223 break;
225 glTextureParameteri(m_id, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
226 glTextureParameteri(m_id, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
227 break;
228 }
229 }
230 else
231 {
233 {
234 glTextureParameteri(m_id, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
235 glTextureParameteri(m_id, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
236 }
237 else
238 {
239 glTextureParameteri(m_id, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
240 glTextureParameteri(m_id, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
241 }
242 }
243 }
244
245 void Texture::set_mode() const noexcept
246 {
247 glTextureParameteri(m_id, GL_TEXTURE_WRAP_S, static_cast<GLint>(GLTextureMode::CLAMP_TO_EDGE));
248 glTextureParameteri(m_id, GL_TEXTURE_WRAP_T, static_cast<GLint>(GLTextureMode::CLAMP_TO_EDGE));
249 }
250
251 void Texture::set_anisotropy() const noexcept
252 {
253 auto ansio = std::clamp(Settings::ansiotrophy(), 0, 16);
254 if (ansio <= 0)
255 {
256 ansio = 0;
257 }
258 else if (ansio <= 2)
259 {
260 ansio = 2;
261 }
262 else if (ansio <= 4)
263 {
264 ansio = 4;
265 }
266 else if (ansio <= 8)
267 {
268 ansio = 8;
269 }
270 else
271 {
272 ansio = 16;
273 }
274
275 glTextureParameterf(m_id, GL_TEXTURE_MAX_ANISOTROPY, static_cast<float>(ansio));
276 }
277} // namespace galaxy
278
279#ifdef GALAXY_WIN_PLATFORM
280#pragma warning(pop)
281#endif
#define GALAXY_LOG(level, msg,...)
Definition Log.hpp:28
#define GALAXY_ERROR
Definition Log.hpp:24
Bindless OpenGL 2D Texture.
Definition Texture.hpp:22
void unbind() const noexcept
Deactivate sampler.
Definition Texture.cpp:162
void set_anisotropy() const noexcept
Set ansiotropic filtering level.
Definition Texture.cpp:251
Texture & operator=(Texture &&) noexcept
Move assignment operator.
Definition Texture.cpp:50
~Texture()
Destructor.
Definition Texture.cpp:68
bool load(const std::string &file)
Load a texture from vfs.
Definition Texture.cpp:73
bool load_mem(std::span< std::uint8_t > buffer)
Loads texture from memory.
Definition Texture.cpp:81
int m_width
Texture width.
Definition Texture.hpp:177
void set_filter() const noexcept
Sets filter when texture is (up/down)scaled in OpenGL.
Definition Texture.cpp:208
std::uint64_t m_handle
Bindless handle.
Definition Texture.hpp:172
unsigned int m_id
OpenGL id.
Definition Texture.hpp:167
void save(std::string_view file)
Saves texture to file on disk.
Definition Texture.cpp:119
void set_mode() const noexcept
Set texture mode.
Definition Texture.cpp:245
void bind() const noexcept
Bind to sampler.
Definition Texture.cpp:157
int m_height
Texture height.
Definition Texture.hpp:182
void destroy()
Destroy texture.
Definition Texture.cpp:167
Texture()
Constructor.
Definition Texture.cpp:28
float height() const noexcept
Get texture height.
Definition Texture.cpp:193
unsigned int id() const noexcept
Get OpenGL texture id.
Definition Texture.cpp:198
void recreate()
Deletes texture data and configuration in OpenGL.
Definition Texture.cpp:182
std::uint64_t handle() const noexcept
Get OpenGL bindless handle.
Definition Texture.cpp:203
float width() const noexcept
Get texture width.
Definition Texture.cpp:188
Animated.cpp galaxy.
Definition Animated.cpp:16
@ NEAREST
Nearest-neighbour.
@ CLAMP_TO_EDGE
GL_CLAMP_TO_EDGE.
static auto root_dir() noexcept -> std::filesystem::path
Current root directory of application, unless it has been changed.
Definition Settings.cpp:243
static auto ansiotrophy() noexcept -> int
Ansiotropic filtering level.
Definition Settings.cpp:192
static auto mipmap() noexcept -> bool
Mipmapping.
Definition Settings.cpp:197
static auto texture_filter() noexcept -> GLTextureFilter
Texture filtering type.
Definition Settings.cpp:202