Brenta Engine 1.2
Loading...
Searching...
No Matches
texture.hpp
1// SPDX-License-Identifier: MIT
2// Author: Giovanni Santini
3// Mail: giovanni.santini@proton.me
4// Github: @San7o
5
6#pragma once
7
8#include <brenta/renderer/opengl/gl.hpp>
9#include <brenta/color.hpp>
10
11#include <tenno/vector.hpp>
12
13#include <filesystem>
14
15namespace brenta
16{
17
18//
19// Texture
20// -------
21//
22// This class provides an interface to interact with opengl
23// textures. There are several types of textures, as well as target
24// and with different properties.
25//
26// To bind a texture, use the bind() method. Before this, you need
27// to make sure that you set the coorect active_texture(), which
28// is the index that the shader will use to access the bound texture.
29//
31{
32public:
33
34 using Id = unsigned int;
35
36 enum Type
37 {
38 None,
39 Diffuse,
40 Specular,
41 };
42
43 enum Target
44 {
45 Texture1D = GL_TEXTURE_1D,
46 Texture2D = GL_TEXTURE_2D,
47 Texture3D = GL_TEXTURE_3D,
48 Texture1DArray = GL_TEXTURE_1D_ARRAY,
49 Texture2DArray = GL_TEXTURE_2D_ARRAY,
50 TextureRectangle = GL_TEXTURE_RECTANGLE,
51 TextureCubeMap = GL_TEXTURE_CUBE_MAP,
52 TextureCubeMapArray = GL_TEXTURE_CUBE_MAP_ARRAY,
53 TextureBuffer = GL_TEXTURE_BUFFER,
54 Texture2DMultisample = GL_TEXTURE_2D_MULTISAMPLE,
55 Texture2DMultisampleArray = GL_TEXTURE_2D_MULTISAMPLE_ARRAY,
56 };
57
58 enum Wrapping
59 {
60 // Repeats the texture image. This is the default begaviour
61 Repeat = GL_REPEAT,
62 // Same as Repeat byt mirrirs the image with each repeat
63 MirroredRepeat = GL_MIRRORED_REPEAT,
64 // Clamps the coordinates between 0 and 1. The result is that
65 // higher coordinates become clamped to the edge, resulting in a
66 // stretched edge pattern
67 ClampToEdge = GL_CLAMP_TO_EDGE,
68 // Coordinates outsize the range are now given a use-specified
69 // border color
70 ClampToBorder = GL_CLAMP_TO_BORDER,
71 };
72
73 enum Filtering
74 {
75 // Select the closest color to the texture coordinate
76 Nearest = GL_NEAREST,
77 // Interpolates the neighbouring pixels to get an approximate
78 // color
79 Linear = GL_LINEAR,
80 // Selects the mipmap that most closely matches the size of the
81 // pixel being textured and uses the GL_NEAREST criterion (the
82 // texture element nearest to the center of the pixel) to produce
83 // a texture value.
84 NearestMipmapNearest = GL_NEAREST_MIPMAP_NEAREST,
85 // Selects the mipmap that most closely matches the size of the
86 // pixel being textured and uses the GL_LINEAR criterion (a
87 // weighted average of the four texture elements that are closest
88 // to the center of the pixel) to produce a texture value.
89 NearestMipmapLinear = GL_NEAREST_MIPMAP_LINEAR,
90 // Selects the two mipmaps that most closely match the size of the
91 // pixel being textured and uses the GL_NEAREST criterion (the
92 // texture element nearest to the center of the pixel) to produce
93 // a texture value from each mipmap. The final texture value is a
94 // weighted average of those two values.
95 LinearMipmapNearest = GL_LINEAR_MIPMAP_NEAREST,
96 // Selects the two mipmaps that most closely match the size of the
97 // pixel being textured and uses the GL_LINEAR criterion (a
98 // weighted average of the texture elements that are closest to
99 // the center of the pixel) to produce a texture value from each
100 // mipmap. The final texture value is a weighted average of those
101 // two values.
102 LinearMipmapLinear = GL_LINEAR_MIPMAP_LINEAR,
103 };
104
105 struct Config;
106 struct Properties;
107 class Builder;
108
110 {
111
112 Texture::Wrapping wrapping = Texture::Wrapping::Repeat;
113 Texture::Filtering filtering_min = Texture::Filtering::Nearest;
114 Texture::Filtering filtering_mag = Texture::Filtering::Nearest;
115 GLboolean has_mipmap = Gl::True;
116 Texture::Filtering mipmap_min = Texture::Filtering::LinearMipmapLinear;
117 Texture::Filtering mipmap_mag = Texture::Filtering::Linear;
118 GLboolean flipped = false;
119
120 // Setters
121
122 Properties &set_wrapping(Texture::Wrapping wrapping);
123 Properties &set_filtering_min(Texture::Filtering filtering);
124 Properties &set_filtering_mag(Texture::Filtering filtering);
125 Properties &set_has_mipmap(GLboolean mipmap);
126 Properties &set_mipmap_min(Texture::Filtering filtering);
127 Properties &set_mipmap_mag(Texture::Filtering filtering);
128 Properties &set_flipped(GLboolean flipped);
129
130 };
131
132 // This tells the shader where to find the texture
133 static void active_texture(int texture);
134 // Loads texture from path, sets [loaded_memory] with the number
135 // of bytes loaded and returns the id of the loaded texture
136 static Texture::Id load(const std::filesystem::path &path,
137 int &loaded_memory, bool flip = true);
138 static Texture::Id load_solid_color(Color color);
139 static void bind_id(Texture::Target target, Texture::Id id);
140 static void bind_id(Texture::Target target, Texture::Id id,
141 const Texture::Properties &properties);
142
143 // Non static
144
145 // Used for profiling
146 int memory = 0;
147 static int tot_memory;
148
149 Texture() {}
150 Texture(const Config &conf);
151
152 Texture(const Texture&) = delete;
153 Texture &operator=(const Texture&) = delete;
154
155 Texture(Texture&& other) noexcept
156 {
157 this->id = other.id;
158 this->path = other.path;
159 this->type = other.type;
160 this->target = other.target;
161 this->properties = other.properties;
162 this->memory = other.memory;
163
164 other.id = 0;
165 other.memory = 0;
166 }
167
168 Texture& operator=(Texture&& other) noexcept
169 {
170 this->id = other.id;
171 this->type = other.type;
172 this->path = other.path;
173 this->target = other.target;
174 this->properties = other.properties;
175 this->memory = other.memory;
176
177 other.id = 0;
178 other.memory = 0;
179 return *this;
180 }
181
182 ~Texture();
183
184 Texture::Id get_id() const;
185 std::filesystem::path get_path() const;
186 Texture::Type get_type() const;
187 Texture::Target get_target() const;
188 Texture::Properties &get_properties();
189
190 void bind();
191
192protected:
193
194 Texture::Id id = 0;
195 Texture::Type type;
196 Texture::Target target;
197 std::filesystem::path path;
198 Texture::Properties properties;
199
200 // Returns the number of bytes loaded
201 static int read_image(const std::filesystem::path &path, bool flip);
202
203};
204
206{
207 Texture::Type type = Texture::Type::None;
208 Texture::Target target = Texture::Target::Texture2D;
209 std::filesystem::path path = "";
210 Texture::Properties properties = {};
211 std::optional<Color> color = {};
212};
213
215{
216public:
217
218 Builder& type(Texture::Type type);
219 Builder& target(Texture::Target target);
220 Builder& path(const std::filesystem::path& path);
221 Builder& flipped(bool flipped);
222 Builder& properties(const Texture::Properties& prop);
223 Builder& color(Color color);
224
225 // Add path to be watched for hot-reloading
226 Builder &watch(const std::filesystem::path &path);
227
228 Texture build();
229 tenno::vector<std::filesystem::path> get_watch_paths() const;
230
231private:
232
233 Texture::Config conf = {};
234 tenno::vector<std::filesystem::path> watch_paths = {};
235
236};
237
238} // namespace brenta