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