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
19
20#include "Texture.hpp"
21
22#ifdef GALAXY_WIN_PLATFORM
23#pragma warning(push)
24#pragma warning(disable : 26493)
25#endif
26
27namespace galaxy
28{
30 : m_id {0}
31 , m_handle {0}
32 , m_width {0}
33 , m_height {0}
34 {
35 glCreateTextures(GL_TEXTURE_2D, 1, &m_id);
36 }
37
39 {
40 this->destroy();
41
42 this->m_id = t.m_id;
43 this->m_handle = t.m_handle;
44 this->m_width = t.m_width;
45 this->m_height = t.m_height;
46
47 t.m_id = 0;
48 t.m_handle = 0;
49 }
50
52 {
53 if (this != &t)
54 {
55 this->destroy();
56
57 this->m_id = t.m_id;
58 this->m_handle = t.m_handle;
59 this->m_width = t.m_width;
60 this->m_height = t.m_height;
61
62 t.m_id = 0;
63 t.m_handle = 0;
64 }
65
66 return *this;
67 }
68
70 {
71 destroy();
72 }
73
74 bool Texture::load(const std::string& file)
75 {
76 auto& fs = entt::locator<VirtualFileSystem>::value();
77
78 auto data = fs.read_binary(file);
79 return load_mem(data);
80 }
81
82 bool Texture::load_mem(std::span<std::uint8_t> buffer)
83 {
84 auto result = true;
85
86 if (!buffer.empty())
87 {
88 stbi_set_flip_vertically_on_load(true);
89 unsigned char* data = stbi_load_from_memory(buffer.data(), static_cast<int>(buffer.size_bytes()), &m_width, &m_height, nullptr, STBI_rgb_alpha);
90
91 if (data)
92 {
93 glTextureStorage2D(m_id, 1, GL_RGBA8, m_width, m_height);
94 glTextureSubImage2D(m_id, 0, 0, 0, m_width, m_height, GL_RGBA, GL_UNSIGNED_BYTE, data);
95
96 if (Settings::mipmap())
97 {
98 glGenerateTextureMipmap(m_id);
99 }
100
101 m_handle = glGetTextureSamplerHandleARB(m_id, entt::locator<Sampler>::value().id());
102 glMakeTextureHandleResidentARB(m_handle);
103 }
104 else
105 {
106 GALAXY_LOG(GALAXY_ERROR, "Failed to load texture from memory because '{0}'.", stbi_failure_reason());
107 result = false;
108 }
109
110 stbi_image_free(data);
111 }
112 else
113 {
114 GALAXY_LOG(GALAXY_ERROR, "Tried to pass empty buffer to loading texture from memory.");
115 result = false;
116 }
117
118 return result;
119 }
120
121 void Texture::save(std::string_view file)
122 {
123 auto& fs = entt::locator<VirtualFileSystem>::value();
124
125 auto path = std::filesystem::path(file);
126 if (!path.is_absolute())
127 {
128 path = Settings::root_dir() / path;
129 }
130
131 if (!path.has_extension())
132 {
133 path.replace_extension(".png");
134 }
135
136 if (!std::filesystem::exists(path.parent_path()))
137 {
138 std::filesystem::create_directories(path.parent_path());
139 }
140
141 std::vector<unsigned int> pixels(static_cast<unsigned int>(m_width) * static_cast<unsigned int>(m_height) * 4u, 0);
142
143 glGetTextureImage(m_id, 0, GL_RGBA, GL_UNSIGNED_BYTE, static_cast<GLsizei>(pixels.size()), pixels.data());
144
145 stbi_flip_vertically_on_write(true);
146
147 int len = 0;
148
149 unsigned char* png = stbi_write_png_to_mem((const unsigned char*)pixels.data(), m_width * 4, m_width, m_height, 4, &len);
150
151 if (!fs.write_raw(png, len, path.string()))
152 {
153 GALAXY_LOG(GALAXY_ERROR, "Failed to write '{0}' to disk.", path.string());
154 }
155
156 std::free(png);
157 }
158
159 TextureView Texture::get_view(const unsigned int minlevel, const unsigned int numlevels, const unsigned int minlayer, const unsigned int numlayers) const noexcept
160 {
161 return {m_id, minlevel, numlevels, minlayer, numlayers};
162 }
163
164 void Texture::bind() const noexcept
165 {
166 glBindTexture(GL_TEXTURE_2D, m_id);
167 }
168
169 void Texture::unbind() const noexcept
170 {
171 glBindTexture(GL_TEXTURE_2D, 0);
172 }
173
175 {
176 if (m_handle != 0)
177 {
178 glMakeTextureHandleNonResidentARB(m_handle);
179 m_handle = 0;
180 }
181
182 if (m_id != 0)
183 {
184 glDeleteTextures(1, &m_id);
185 m_id = 0;
186 }
187 }
188
189 float Texture::width() const noexcept
190 {
191 return static_cast<float>(m_width);
192 }
193
194 float Texture::height() const noexcept
195 {
196 return static_cast<float>(m_height);
197 }
198
199 unsigned int Texture::id() const noexcept
200 {
201 return m_id;
202 }
203
204 std::uint64_t Texture::handle() const noexcept
205 {
206 return m_handle;
207 }
208} // namespace galaxy
209
210#ifdef GALAXY_WIN_PLATFORM
211#pragma warning(pop)
212#endif
#define GALAXY_LOG(level, msg,...)
Definition Log.hpp:28
#define GALAXY_ERROR
Definition Log.hpp:24
OpenGL 2D TextureView.
Bindless OpenGL 2D Texture.
Definition Texture.hpp:24
void unbind() const noexcept
Unbind sampler.
Definition Texture.cpp:169
Texture & operator=(Texture &&) noexcept
Move assignment operator.
Definition Texture.cpp:51
~Texture()
Destructor.
Definition Texture.cpp:69
bool load(const std::string &file)
Load a texture from vfs.
Definition Texture.cpp:74
bool load_mem(std::span< std::uint8_t > buffer)
Loads texture from memory.
Definition Texture.cpp:82
int m_width
Texture width.
Definition Texture.hpp:166
std::uint64_t m_handle
Bindless handle.
Definition Texture.hpp:161
unsigned int m_id
OpenGL id.
Definition Texture.hpp:156
void save(std::string_view file)
Saves texture to file on disk.
Definition Texture.cpp:121
void bind() const noexcept
Bind to sampler.
Definition Texture.cpp:164
int m_height
Texture height.
Definition Texture.hpp:171
void destroy()
Destroy texture.
Definition Texture.cpp:174
Texture()
Constructor.
Definition Texture.cpp:29
float height() const noexcept
Get texture height.
Definition Texture.cpp:194
unsigned int id() const noexcept
Get OpenGL texture id.
Definition Texture.cpp:199
TextureView get_view(const unsigned int minlevel, const unsigned int numlevels, const unsigned int minlayer, const unsigned int numlayers) const noexcept
Generate a texture view handle.
Definition Texture.cpp:159
std::uint64_t handle() const noexcept
Get OpenGL bindless handle.
Definition Texture.cpp:204
float width() const noexcept
Get texture width.
Definition Texture.cpp:189
Animated.cpp galaxy.
Definition Animated.cpp:16
static auto root_dir() noexcept -> std::filesystem::path
Current root directory of application, unless it has been changed.
Definition Settings.cpp:250
static auto mipmap() noexcept -> bool
Mipmapping.
Definition Settings.cpp:199