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