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