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