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.opengl3.gl3; 7 8 import gfm.opengl.opengl; 9 10 /// OpenGL Texture wrapper. 11 /// 12 /// TODO: 13 /// $(UL 14 /// $(LI Support partial updates.) 15 /// $(LI Support glStorage through pseudo-code given in OpenGL specification.) 16 /// ) 17 class GLTexture 18 { 19 public 20 { 21 /// Creates a texture. You should create a child class instead of calling 22 /// this constructor directly. 23 /// Throws: $(D OpenGLException) on error. 24 this(OpenGL gl, GLuint target) 25 { 26 _gl = gl; 27 _target = target; 28 glGenTextures(1, &_handle); 29 _gl.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 deprecated("Use .destroy instead") void close(){} 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, f); 187 _gl.runtimeCheck(); 188 } 189 190 /// Gets the texture data. 191 /// Throws: $(D OpenGLException) on error. 192 final void getTexImage(int level, GLenum format, GLenum type, void* data) 193 { 194 bind(); 195 glGetTexImage(_target, level, format, type, data); 196 _gl.runtimeCheck(); 197 } 198 199 /// Returns: Wrapped OpenGL resource handle. 200 GLuint handle() pure const nothrow 201 { 202 return _handle; 203 } 204 205 GLuint target() pure const nothrow 206 { 207 return _target; 208 } 209 210 /// Regenerates the mipmapped levels. 211 /// Throws: $(D OpenGLException) on error. 212 void generateMipmap() 213 { 214 bind(); 215 glGenerateMipmap(_target); 216 _gl.runtimeCheck(); 217 } 218 } 219 220 package 221 { 222 GLuint _target; 223 } 224 225 private 226 { 227 OpenGL _gl; 228 GLuint _handle; 229 bool _initialized; 230 int _textureUnit; 231 232 void bind() 233 { 234 // Bind on whatever the current texture unit is! 235 glBindTexture(target, _handle); 236 _gl.runtimeCheck(); 237 } 238 } 239 } 240 241 /// Wrapper for 1D texture. 242 final class GLTexture1D : GLTexture 243 { 244 public 245 { 246 /// Creates a 1D texture. 247 /// Throws: $(D OpenGLException) on error. 248 this(OpenGL gl) 249 { 250 super(gl, GL_TEXTURE_1D); 251 } 252 253 /// Sets texture content. 254 /// Throws: $(D OpenGLException) on error. 255 void setImage(int level, GLint internalFormat, int width, int border, GLenum format, GLenum type, void* data) 256 { 257 glTexImage1D(_target, level, internalFormat, width, border, format, type, data); 258 _gl.runtimeCheck(); 259 } 260 } 261 262 } 263 264 /// Wrapper for 2D texture. 265 final class GLTexture2D : GLTexture 266 { 267 public 268 { 269 /// Creates a 2D texture. 270 /// Throws: $(D OpenGLException) on error. 271 this(OpenGL gl) 272 { 273 super(gl, GL_TEXTURE_2D); 274 } 275 276 /// Sets texture content. 277 /// Throws: $(D OpenGLException) on error. 278 void setImage(int level, GLint internalFormat, int width, int height, int border, GLenum format, GLenum type, void* data) 279 { 280 glTexImage2D(_target, level, internalFormat, width, height, border, format, type, data); 281 _gl.runtimeCheck(); 282 } 283 } 284 285 } 286 287 /// Wrapper for 3D texture. 288 final class GLTexture3D : GLTexture 289 { 290 public 291 { 292 /// Creates a 3D texture. 293 /// Throws: $(D OpenGLException) on error. 294 this(OpenGL gl) 295 { 296 super(gl, GL_TEXTURE_3D); 297 } 298 299 /// Sets texture content. 300 /// Throws: $(D OpenGLException) on error. 301 void setImage(int level, GLint internalFormat, int width, int height, int depth, int border, GLenum format, GLenum type, void* data) 302 { 303 glTexImage3D(_target, level, internalFormat, width, height, depth, border, format, type, data); 304 _gl.runtimeCheck(); 305 } 306 } 307 } 308 309 /// Wrapper for 1D texture array. 310 final class GLTexture1DArray : GLTexture 311 { 312 public 313 { 314 /// Creates a 1D texture array. 315 /// Throws: $(D OpenGLException) on error. 316 this(OpenGL gl) 317 { 318 super(gl, GL_TEXTURE_1D_ARRAY); 319 } 320 321 /// Sets texture content. 322 /// Throws: $(D OpenGLException) on error. 323 void setImage(int level, GLint internalFormat, int width, int height, int border, GLenum format, GLenum type, void* data) 324 { 325 glTexImage2D(_target, level, internalFormat, width, height, border, format, type, null); 326 _gl.runtimeCheck(); 327 } 328 } 329 } 330 331 /// Wrapper for 2D texture array. 332 final class GLTexture2DArray : GLTexture 333 { 334 public 335 { 336 /// Creates a 2D texture array. 337 /// Throws: $(D OpenGLException) on error. 338 this(OpenGL gl) 339 { 340 super(gl, GL_TEXTURE_2D_ARRAY); 341 } 342 343 /// Sets texture content. 344 /// Throws: $(D OpenGLException) on error. 345 void setImage(int level, GLint internalFormat, int width, int height, int depth, int border, GLenum format, GLenum type, void* data) 346 { 347 glTexImage3D(_target, level, internalFormat, width, height, depth, border, format, type, data); 348 _gl.runtimeCheck(); 349 } 350 351 /// Sets partial texture content. 352 /// Throws: $(D OpenGLException) on error. 353 void setSubImage(int level, int xoffset, int yoffset, int zoffset, int width, int height, int depth, GLenum format, GLenum type, void* data) 354 { 355 glTexSubImage3D(_target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, data); 356 _gl.runtimeCheck(); 357 } 358 } 359 } 360 361 /// Wrapper for texture rectangle. 362 final class GLTextureRectangle : GLTexture 363 { 364 public 365 { 366 /// Creates a texture rectangle. 367 /// Throws: $(D OpenGLException) on error. 368 this(OpenGL gl) 369 { 370 super(gl, GL_TEXTURE_RECTANGLE); 371 } 372 373 /// Sets texture content. 374 /// Throws: $(D OpenGLException) on error. 375 void setImage(int level, GLint internalFormat, int width, int height, int border, GLenum format, GLenum type, void* data) 376 { 377 glTexImage2D(_target, level, internalFormat, width, height, border, format, type, null); 378 _gl.runtimeCheck(); 379 } 380 } 381 } 382 383 /// Wrapper for 2D multisampled texture. 384 final class GLTexture2DMultisample : GLTexture 385 { 386 public 387 { 388 /// Creates a 2D multisampled texture. 389 /// Throws: $(D OpenGLException) on error. 390 this(OpenGL gl) 391 { 392 super(gl, GL_TEXTURE_2D_MULTISAMPLE); 393 } 394 395 /// Sets texture content. 396 /// Throws: $(D OpenGLException) on error. 397 void setImage(int level, int samples, GLint internalFormat, int width, int height, bool fixedsamplelocations) 398 { 399 glTexImage2DMultisample(_target, samples, internalFormat, width, height, fixedsamplelocations ? GL_TRUE : GL_FALSE); 400 _gl.runtimeCheck(); 401 } 402 } 403 } 404 405 /// Wrapper for 2D multisampled texture array. 406 final class GLTexture2DMultisampleArray : GLTexture 407 { 408 public 409 { 410 /// Creates a 2D multisampled texture array. 411 /// Throws: $(D OpenGLException) on error. 412 this(OpenGL gl) 413 { 414 super(gl, GL_TEXTURE_2D_MULTISAMPLE_ARRAY); 415 } 416 417 /// Sets texture content. 418 /// Throws: $(D OpenGLException) on error. 419 void setImage(int level, int samples, GLint internalFormat, int width, int height, int depth, bool fixedsamplelocations) 420 { 421 glTexImage3DMultisample(_target, samples, internalFormat, width, height, depth, fixedsamplelocations ? GL_TRUE : GL_FALSE); 422 _gl.runtimeCheck(); 423 } 424 } 425 } 426 427