1 /// This module defines one texture type for each sort of OpenGL texture. 2 module gfm.opengl.texture; 3 4 import std..string; 5 6 import bindbc.opengl; 7 8 import gfm.opengl.opengl; 9 import gfm.math.vector; 10 11 /// OpenGL Texture wrapper. 12 /// 13 /// TODO: 14 /// $(UL 15 /// $(LI Support partial updates.) 16 /// $(LI Support glStorage through pseudo-code given in OpenGL specification.) 17 /// ) 18 class GLTexture 19 { 20 public 21 { 22 /// Creates a texture. You should create a child class instead of calling 23 /// this constructor directly. 24 /// Throws: $(D OpenGLException) on error. 25 this(GLuint target) 26 { 27 _target = target; 28 glGenTextures(1, &_handle); 29 runtimeCheck(); 30 _initialized = true; 31 _textureUnit = -1; 32 } 33 34 /// Releases the OpenGL texture resource. 35 ~this() 36 { 37 if (_initialized) 38 { 39 debug ensureNotInGC("GLTexture"); 40 glDeleteTextures(1, &_handle); 41 _initialized = false; 42 } 43 } 44 45 /// Use this texture, binding it to a texture unit. 46 /// Params: 47 /// textureUnit = Index of the texture unit to use. 48 final void use(int textureUnit = 0) 49 { 50 setActiveTexture(textureUnit); 51 bind(); 52 } 53 54 /// Unuse this texture. 55 final void unuse() 56 { 57 // do nothing: texture unit binding is as needed 58 } 59 60 /// Returns: Requested texture parameter. 61 /// Throws: $(D OpenGLException) on error. 62 /// Warning: Calling $(D glGetTexParameteriv) is generally not recommended 63 /// since it could stall the OpenGL pipeline. 64 final int getParam(GLenum paramName) 65 { 66 int res; 67 bind(); 68 glGetTexParameteriv(_target, paramName, &res); 69 runtimeCheck(); 70 return res; 71 } 72 73 /// Returns: Requested texture level parameter. 74 /// Throws: $(D OpenGLException) on error. 75 /// Warning: Calling $(D glGetTexLevelParameteriv) is generally not recommended 76 /// since it could stall the OpenGL pipeline. 77 final int getLevelParam(GLenum paramName, int level) 78 { 79 int res; 80 bind(); 81 glGetTexLevelParameteriv(_target, level, paramName, &res); 82 runtimeCheck(); 83 return res; 84 } 85 86 /// Sets the texture base level. 87 /// Throws: $(D OpenGLException) on error. 88 final void setBaseLevel(int level) 89 { 90 bind(); 91 glTexParameteri(_target, GL_TEXTURE_BASE_LEVEL, level); 92 runtimeCheck(); 93 } 94 95 /// Sets the texture maximum level. 96 /// Throws: $(D OpenGLException) on error. 97 final void setMaxLevel(int level) 98 { 99 bind(); 100 glTexParameteri(_target, GL_TEXTURE_MAX_LEVEL, level); 101 runtimeCheck(); 102 } 103 104 // Texture "sampler" parameters which are now in Sampler Objects too 105 // but are also here for legacy cards. 106 107 /// Sets the texture minimum LOD. 108 /// Throws: $(D OpenGLException) on error. 109 final void setMinLOD(float lod) 110 { 111 bind(); 112 glTexParameterf(_target, GL_TEXTURE_MIN_LOD, lod); 113 runtimeCheck(); 114 } 115 116 /// Sets the texture maximum LOD. 117 /// Throws: $(D OpenGLException) on error. 118 final void setMaxLOD(float lod) 119 { 120 bind(); 121 glTexParameterf(_target, GL_TEXTURE_MAX_LOD, lod); 122 runtimeCheck(); 123 } 124 125 /// Sets the texture LOD bias. 126 /// Throws: $(D OpenGLException) on error. 127 final void setLODBias(float lodBias) 128 { 129 bind(); 130 glTexParameterf(_target, GL_TEXTURE_LOD_BIAS, lodBias); 131 runtimeCheck(); 132 } 133 134 /// Sets the wrap mode for 1st texture coordinate. 135 /// Throws: $(D OpenGLException) on error. 136 final void setWrapS(GLenum wrapS) 137 { 138 bind(); 139 glTexParameteri(_target, GL_TEXTURE_WRAP_S, wrapS); 140 runtimeCheck(); 141 } 142 143 /// Sets the wrap mode for 2nd texture coordinate. 144 /// Throws: $(D OpenGLException) on error. 145 final void setWrapT(GLenum wrapT) 146 { 147 bind(); 148 glTexParameteri(_target, GL_TEXTURE_WRAP_T, wrapT); 149 runtimeCheck(); 150 } 151 152 /// Sets the wrap mode for 3rd texture coordinate. 153 /// Throws: $(D OpenGLException) on error. 154 final void setWrapR(GLenum wrapR) 155 { 156 bind(); 157 glTexParameteri(_target, GL_TEXTURE_WRAP_R, wrapR); 158 runtimeCheck(); 159 } 160 161 /// Sets the texture minification filter mode. 162 /// Throws: $(D OpenGLException) on error. 163 final void setMinFilter(GLenum minFilter) 164 { 165 bind(); 166 glTexParameteri(_target, GL_TEXTURE_MIN_FILTER, minFilter); 167 runtimeCheck(); 168 } 169 170 /// Sets the texture magnification filter mode. 171 /// Throws: $(D OpenGLException) on error. 172 final void setMagFilter(GLenum magFilter) 173 { 174 bind(); 175 glTexParameteri(_target, GL_TEXTURE_MAG_FILTER, magFilter); 176 runtimeCheck(); 177 } 178 179 /// Sets the texture anisotropic filter level. 180 /// If texture anisotropy isn't supported, fail silently. 181 /// Throws: $(D OpenGLException) on error. 182 final void setMaxAnisotropy(float f) 183 { 184 bind(); 185 glTexParameterf(_target, /* GL_TEXTURE_MAX_ANISOTROPY_EXT */ 0x84FE, f); 186 runtimeCheck(); 187 } 188 189 /// Sets the texture border color. 190 /// Throws: $(D OpenGLException) on error. 191 final void setBorderColor(vec4f color) 192 { 193 bind(); 194 glTexParameterfv(_target, GL_TEXTURE_BORDER_COLOR, color.ptr); 195 runtimeCheck(); 196 } 197 198 /// Sets the texture compare mode. 199 /// Throws: $(D OpenGLException) on error. 200 final void setCompareMode(GLenum compareMode) 201 { 202 bind(); 203 glTexParameteri(_target, GL_TEXTURE_COMPARE_MODE, compareMode); 204 runtimeCheck(); 205 } 206 207 /// Sets the texture compare mode. 208 /// Throws: $(D OpenGLException) on error. 209 final void setCompareFunc(GLenum compareFunc) 210 { 211 bind(); 212 glTexParameteri(_target, GL_TEXTURE_COMPARE_FUNC, compareFunc); 213 runtimeCheck(); 214 } 215 216 /// Gets the texture data. 217 /// Throws: $(D OpenGLException) on error. 218 final void getTexImage(int level, GLenum format, GLenum type, void* data) 219 { 220 bind(); 221 glGetTexImage(_target, level, format, type, data); 222 runtimeCheck(); 223 } 224 225 /// Returns: Wrapped OpenGL resource handle. 226 GLuint handle() pure const nothrow 227 { 228 return _handle; 229 } 230 231 GLuint target() pure const nothrow 232 { 233 return _target; 234 } 235 236 /// Regenerates the mipmapped levels. 237 /// Throws: $(D OpenGLException) on error. 238 void generateMipmap() 239 { 240 bind(); 241 glGenerateMipmap(_target); 242 runtimeCheck(); 243 } 244 } 245 246 package 247 { 248 GLuint _target; 249 } 250 251 private 252 { 253 GLuint _handle; 254 bool _initialized; 255 int _textureUnit; 256 257 void bind() 258 { 259 // Bind on whatever the current texture unit is! 260 glBindTexture(target, _handle); 261 runtimeCheck(); 262 } 263 } 264 } 265 266 /// Wrapper for 1D texture. 267 final class GLTexture1D : GLTexture 268 { 269 public 270 { 271 /// Creates a 1D texture. 272 /// Throws: $(D OpenGLException) on error. 273 this() 274 { 275 super(GL_TEXTURE_1D); 276 } 277 278 /// Sets texture content. 279 /// Throws: $(D OpenGLException) on error. 280 void setImage(int level, GLint internalFormat, int width, int border, GLenum format, GLenum type, void* data) 281 { 282 glTexImage1D(_target, level, internalFormat, width, border, format, type, data); 283 runtimeCheck(); 284 } 285 } 286 287 } 288 289 /// Wrapper for 2D texture. 290 final class GLTexture2D : GLTexture 291 { 292 public 293 { 294 /// Creates a 2D texture. 295 /// Throws: $(D OpenGLException) on error. 296 this() 297 { 298 super(GL_TEXTURE_2D); 299 } 300 301 /// Sets texture content. 302 /// Throws: $(D OpenGLException) on error. 303 void setImage(int level, GLint internalFormat, int width, int height, int border, GLenum format, GLenum type, void* data) 304 { 305 glTexImage2D(_target, level, internalFormat, width, height, border, format, type, data); 306 runtimeCheck(); 307 } 308 } 309 310 } 311 312 /// Wrapper for 3D texture. 313 final class GLTexture3D : GLTexture 314 { 315 public 316 { 317 /// Creates a 3D texture. 318 /// Throws: $(D OpenGLException) on error. 319 this() 320 { 321 super(GL_TEXTURE_3D); 322 } 323 324 /// Sets texture content. 325 /// Throws: $(D OpenGLException) on error. 326 void setImage(int level, GLint internalFormat, int width, int height, int depth, int border, GLenum format, GLenum type, void* data) 327 { 328 glTexImage3D(_target, level, internalFormat, width, height, depth, border, format, type, data); 329 runtimeCheck(); 330 } 331 } 332 } 333 334 /// Wrapper for 1D texture array. 335 final class GLTexture1DArray : GLTexture 336 { 337 public 338 { 339 /// Creates a 1D texture array. 340 /// Throws: $(D OpenGLException) on error. 341 this() 342 { 343 super(GL_TEXTURE_1D_ARRAY); 344 } 345 346 /// Sets texture content. 347 /// Throws: $(D OpenGLException) on error. 348 void setImage(int level, GLint internalFormat, int width, int height, int border, GLenum format, GLenum type, void* data) 349 { 350 glTexImage2D(_target, level, internalFormat, width, height, border, format, type, null); 351 runtimeCheck(); 352 } 353 } 354 } 355 356 /// Wrapper for 2D texture array. 357 final class GLTexture2DArray : GLTexture 358 { 359 public 360 { 361 /// Creates a 2D texture array. 362 /// Throws: $(D OpenGLException) on error. 363 this() 364 { 365 super(GL_TEXTURE_2D_ARRAY); 366 } 367 368 /// Sets texture content. 369 /// Throws: $(D OpenGLException) on error. 370 void setImage(int level, GLint internalFormat, int width, int height, int depth, int border, GLenum format, GLenum type, void* data) 371 { 372 glTexImage3D(_target, level, internalFormat, width, height, depth, border, format, type, data); 373 runtimeCheck(); 374 } 375 376 /// Sets partial texture content. 377 /// Throws: $(D OpenGLException) on error. 378 void setSubImage(int level, int xoffset, int yoffset, int zoffset, int width, int height, int depth, GLenum format, GLenum type, void* data) 379 { 380 glTexSubImage3D(_target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, data); 381 runtimeCheck(); 382 } 383 } 384 } 385 386 /// Wrapper for texture rectangle. 387 final class GLTextureRectangle : GLTexture 388 { 389 public 390 { 391 /// Creates a texture rectangle. 392 /// Throws: $(D OpenGLException) on error. 393 this() 394 { 395 super(GL_TEXTURE_RECTANGLE); 396 } 397 398 /// Sets texture content. 399 /// Throws: $(D OpenGLException) on error. 400 void setImage(int level, GLint internalFormat, int width, int height, int border, GLenum format, GLenum type, void* data) 401 { 402 glTexImage2D(_target, level, internalFormat, width, height, border, format, type, null); 403 runtimeCheck(); 404 } 405 } 406 } 407 408 /// Wrapper for 2D multisampled texture. 409 final class GLTexture2DMultisample : GLTexture 410 { 411 public 412 { 413 /// Creates a 2D multisampled texture. 414 /// Throws: $(D OpenGLException) on error. 415 this() 416 { 417 super(GL_TEXTURE_2D_MULTISAMPLE); 418 } 419 420 /// Sets texture content. 421 /// Throws: $(D OpenGLException) on error. 422 void setImage(int level, int samples, GLint internalFormat, int width, int height, bool fixedsamplelocations) 423 { 424 glTexImage2DMultisample(_target, samples, internalFormat, width, height, fixedsamplelocations ? GL_TRUE : GL_FALSE); 425 runtimeCheck(); 426 } 427 } 428 } 429 430 /// Wrapper for 2D multisampled texture array. 431 final class GLTexture2DMultisampleArray : GLTexture 432 { 433 public 434 { 435 /// Creates a 2D multisampled texture array. 436 /// Throws: $(D OpenGLException) on error. 437 this() 438 { 439 super(GL_TEXTURE_2D_MULTISAMPLE_ARRAY); 440 } 441 442 /// Sets texture content. 443 /// Throws: $(D OpenGLException) on error. 444 void setImage(int level, int samples, GLint internalFormat, int width, int height, int depth, bool fixedsamplelocations) 445 { 446 glTexImage3DMultisample(_target, samples, internalFormat, width, height, depth, fixedsamplelocations ? GL_TRUE : GL_FALSE); 447 runtimeCheck(); 448 } 449 } 450 } 451 452