1 /+ 2 The MIT License (MIT) 3 4 Copyright (c) <2013> <Oleg Butko (deviator), Anton Akzhigitov (Akzwar)> 5 6 Permission is hereby granted, free of charge, to any person obtaining a copy 7 of this software and associated documentation files (the "Software"), to deal 8 in the Software without restriction, including without limitation the rights 9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 copies of the Software, and to permit persons to whom the Software is 11 furnished to do so, subject to the following conditions: 12 13 The above copyright notice and this permission notice shall be included in 14 all copies or substantial portions of the Software. 15 16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 THE SOFTWARE. 23 +/ 24 25 module des.gl.base.texture; 26 27 import std..string; 28 29 public import derelict.opengl3.gl3; 30 31 import des.gl.base.type; 32 33 import des.il; 34 35 import std.algorithm; 36 import des.util.stdext.algorithm; 37 38 /// 39 class GLTextureException : DesGLException 40 { 41 /// 42 this( string msg, string file=__FILE__, size_t line=__LINE__ ) @safe pure nothrow 43 { super( msg, file, line ); } 44 } 45 46 /// 47 class GLTexture : DesObject 48 { 49 mixin DES; 50 mixin ClassLogger; 51 private: 52 uint _id; 53 54 protected: 55 /// 56 texsize_t img_size; 57 58 override void selfDestroy() 59 { 60 unbind(); 61 checkGLCall!glDeleteTextures( 1, &_id ); 62 } 63 64 Target _target; 65 66 /// 67 nothrow @property GLenum gltype() const { return cast(GLenum)_target; } 68 69 /// 70 InternalFormat liformat; 71 /// 72 Format lformat; 73 /// 74 Type ltype; 75 76 /// texture unit 77 uint _unit; 78 79 /// 80 enum Parameter 81 { 82 DEPTH_STENCIL_TEXTURE_MODE = GL_DEPTH_STENCIL_TEXTURE_MODE, /// `GL_DEPTH_STENCIL_TEXTURE_MODE` 83 BASE_LEVEL = GL_TEXTURE_BASE_LEVEL, /// `GL_TEXTURE_BASE_LEVEL` 84 MAX_LEVEL = GL_TEXTURE_MAX_LEVEL, /// `GL_TEXTURE_MAX_LEVEL` 85 BORDER_COLOR = GL_TEXTURE_BORDER_COLOR, /// `GL_TEXTURE_BORDER_COLOR` 86 COMPARE_FUNC = GL_TEXTURE_COMPARE_FUNC, /// `GL_TEXTURE_COMPARE_FUNC` 87 COMPARE_MODE = GL_TEXTURE_COMPARE_MODE, /// `GL_TEXTURE_COMPARE_MODE` 88 LOD_BIAS = GL_TEXTURE_LOD_BIAS, /// `GL_TEXTURE_LOD_BIAS` 89 MIN_FILTER = GL_TEXTURE_MIN_FILTER, /// `GL_TEXTURE_MIN_FILTER` 90 MAG_FILTER = GL_TEXTURE_MAG_FILTER, /// `GL_TEXTURE_MAG_FILTER` 91 MIN_LOD = GL_TEXTURE_MIN_LOD, /// `GL_TEXTURE_MIN_LOD` 92 MAX_LOD = GL_TEXTURE_MAX_LOD, /// `GL_TEXTURE_MAX_LOD` 93 SWIZZLE_R = GL_TEXTURE_SWIZZLE_R, /// `GL_TEXTURE_SWIZZLE_R` 94 SWIZZLE_G = GL_TEXTURE_SWIZZLE_G, /// `GL_TEXTURE_SWIZZLE_G` 95 SWIZZLE_B = GL_TEXTURE_SWIZZLE_B, /// `GL_TEXTURE_SWIZZLE_B` 96 SWIZZLE_A = GL_TEXTURE_SWIZZLE_A, /// `GL_TEXTURE_SWIZZLE_A` 97 SWIZZLE_RGBA = GL_TEXTURE_SWIZZLE_RGBA, /// `GL_TEXTURE_SWIZZLE_RGBA` 98 WRAP_S = GL_TEXTURE_WRAP_S, /// `GL_TEXTURE_WRAP_S` 99 WRAP_T = GL_TEXTURE_WRAP_T, /// `GL_TEXTURE_WRAP_T` 100 WRAP_R = GL_TEXTURE_WRAP_R /// `GL_TEXTURE_WRAP_R` 101 } 102 103 public: 104 105 alias CrdVector!3 texsize_t; 106 107 @property 108 { 109 /// 110 Target target() const { return _target; } 111 /// 112 void target( Target trg ) { _target = trg; } 113 } 114 115 /// 116 enum Target 117 { 118 T1D = GL_TEXTURE_1D, /// `GL_TEXTURE_1D` 119 T2D = GL_TEXTURE_2D, /// `GL_TEXTURE_2D` 120 T3D = GL_TEXTURE_3D, /// `GL_TEXTURE_3D` 121 T1D_ARRAY = GL_TEXTURE_1D_ARRAY, /// `GL_TEXTURE_1D_ARRAY` 122 T2D_ARRAY = GL_TEXTURE_2D_ARRAY, /// `GL_TEXTURE_2D_ARRAY` 123 RECTANGLE = GL_TEXTURE_RECTANGLE, /// `GL_TEXTURE_RECTANGLE` 124 CUBE_MAP = GL_TEXTURE_CUBE_MAP, /// `GL_TEXTURE_CUBE_MAP` 125 CUBE_MAP_ARRAY = GL_TEXTURE_CUBE_MAP_ARRAY, /// `GL_TEXTURE_CUBE_MAP_ARRAY` 126 127 BUFFER = GL_TEXTURE_BUFFER, /// `GL_TEXTURE_BUFFER` 128 T2D_MULTISAMPLE = GL_TEXTURE_2D_MULTISAMPLE, /// `GL_TEXTURE_2D_MULTISAMPLE` 129 T2D_MULTISAMPLE_ARRAY = GL_TEXTURE_2D_MULTISAMPLE_ARRAY, /// `GL_TEXTURE_2D_MULTISAMPLE_ARRAY` 130 131 CUBE_MAP_POSITIVE_X = GL_TEXTURE_CUBE_MAP_POSITIVE_X, /// `GL_TEXTURE_CUBE_MAP_POSITIVE_X` 132 CUBE_MAP_NEGATIVE_X = GL_TEXTURE_CUBE_MAP_NEGATIVE_X, /// `GL_TEXTURE_CUBE_MAP_NEGATIVE_X` 133 CUBE_MAP_POSITIVE_Y = GL_TEXTURE_CUBE_MAP_POSITIVE_Y, /// `GL_TEXTURE_CUBE_MAP_POSITIVE_Y` 134 CUBE_MAP_NEGATIVE_Y = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, /// `GL_TEXTURE_CUBE_MAP_NEGATIVE_Y` 135 CUBE_MAP_POSITIVE_Z = GL_TEXTURE_CUBE_MAP_POSITIVE_Z, /// `GL_TEXTURE_CUBE_MAP_POSITIVE_Z` 136 CUBE_MAP_NEGATIVE_Z = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z /// `GL_TEXTURE_CUBE_MAP_NEGATIVE_Z` 137 } 138 139 /// 140 enum DepthStencilTextureMode 141 { 142 DEPTH = GL_DEPTH_COMPONENT, /// `GL_DEPTH_COMPONENT` 143 STENCIL = GL_STENCIL_COMPONENTS /// `GL_STENCIL_COMPONENTS` 144 } 145 146 /// 147 enum CompareFunc 148 { 149 LEQUAL = GL_LEQUAL, /// `GL_LEQUAL` 150 GEQUAL = GL_GEQUAL, /// `GL_GEQUAL` 151 LESS = GL_LESS, /// `GL_LESS` 152 GREATER = GL_GREATER, /// `GL_GREATER` 153 EQUAL = GL_EQUAL, /// `GL_EQUAL` 154 NOTEQUAL = GL_NOTEQUAL, /// `GL_NOTEQUAL` 155 ALWAYS = GL_ALWAYS, /// `GL_ALWAYS` 156 NEVER = GL_NEVER /// `GL_NEVER` 157 } 158 159 /// 160 enum CompareMode 161 { 162 REF_TO_TEXTURE = GL_COMPARE_REF_TO_TEXTURE, /// `GL_COMPARE_REF_TO_TEXTURE` 163 NONE = GL_NONE /// `GL_NONE` 164 } 165 166 /// 167 enum Filter 168 { 169 NEAREST = GL_NEAREST, /// `GL_NEAREST` 170 LINEAR = GL_LINEAR, /// `GL_LINEAR` 171 NEAREST_MIPMAP_NEAREST = GL_NEAREST_MIPMAP_NEAREST, /// `GL_NEAREST_MIPMAP_NEAREST` 172 LINEAR_MIPMAP_NEAREST = GL_LINEAR_MIPMAP_NEAREST, /// `GL_LINEAR_MIPMAP_NEAREST` 173 NEAREST_MIPMAP_LINEAR = GL_NEAREST_MIPMAP_LINEAR, /// `GL_NEAREST_MIPMAP_LINEAR` 174 LINEAR_MIPMAP_LINEAR = GL_LINEAR_MIPMAP_LINEAR /// `GL_LINEAR_MIPMAP_LINEAR` 175 } 176 177 /// 178 enum Swizzle 179 { 180 RED = GL_RED, /// `GL_RED` 181 GREEN = GL_GREEN,/// `GL_GREEN` 182 BLUE = GL_BLUE, /// `GL_BLUE` 183 ALPHA = GL_ALPHA,/// `GL_ALPHA` 184 ONE = GL_ONE, /// `GL_ONE` 185 ZERO = GL_ZERO /// `GL_ZERO` 186 } 187 188 /// 189 enum Wrap 190 { 191 CLAMP_TO_EDGE = GL_CLAMP_TO_EDGE, /// `GL_CLAMP_TO_EDGE` 192 CLAMP_TO_BORDER = GL_CLAMP_TO_BORDER, /// `GL_CLAMP_TO_BORDER` 193 MIRRORED_REPEAT = GL_MIRRORED_REPEAT, /// `GL_MIRRORED_REPEAT` 194 REPEAT = GL_REPEAT /// `GL_REPEAT` 195 } 196 197 /// 198 enum InternalFormat 199 { 200 COMPRESSED_RED = GL_COMPRESSED_RED, /// `GL_COMPRESSED_RED` 201 COMPRESSED_RG = GL_COMPRESSED_RG, /// `GL_COMPRESSED_RG` 202 COMPRESSED_RGB = GL_COMPRESSED_RGB, /// `GL_COMPRESSED_RGB` 203 COMPRESSED_RGBA = GL_COMPRESSED_RGBA, /// `GL_COMPRESSED_RGBA` 204 COMPRESSED_SRGB = GL_COMPRESSED_SRGB, /// `GL_COMPRESSED_SRGB` 205 COMPRESSED_SRGB_ALPHA = GL_COMPRESSED_SRGB_ALPHA, /// `GL_COMPRESSED_SRGB_ALPHA` 206 DEPTH = GL_DEPTH_COMPONENT, /// `GL_DEPTH_COMPONENT` 207 DEPTH16 = GL_DEPTH_COMPONENT16, /// `GL_DEPTH_COMPONENT16` 208 DEPTH24 = GL_DEPTH_COMPONENT24, /// `GL_DEPTH_COMPONENT24` 209 DEPTH32 = GL_DEPTH_COMPONENT32, /// `GL_DEPTH_COMPONENT32` 210 DEPTH32F = GL_DEPTH_COMPONENT32F, /// `GL_DEPTH_COMPONENT32F` 211 DEPTH_STENCIL = GL_DEPTH_STENCIL, /// `GL_DEPTH_STENCIL` 212 R3_G3_B2 = GL_R3_G3_B2, /// `GL_R3_G3_B2` 213 RED = GL_RED, /// `GL_RED` 214 RG = GL_RG, /// `GL_RG` 215 RGB = GL_RGB, /// `GL_RGB` 216 RGB4 = GL_RGB4, /// `GL_RGB4` 217 RGB5 = GL_RGB5, /// `GL_RGB5` 218 RGB8 = GL_RGB8, /// `GL_RGB8` 219 RGB10 = GL_RGB10, /// `GL_RGB10` 220 RGB12 = GL_RGB12, /// `GL_RGB12` 221 RGB16 = GL_RGB16, /// `GL_RGB16` 222 RGBA = GL_RGBA, /// `GL_RGBA` 223 RGBA2 = GL_RGBA2, /// `GL_RGBA2` 224 RGBA4 = GL_RGBA4, /// `GL_RGBA4` 225 RGB5_A1 = GL_RGB5_A1, /// `GL_RGB5_A1` 226 RGBA8 = GL_RGBA8, /// `GL_RGBA8` 227 RGB10_A2 = GL_RGB10_A2, /// `GL_RGB10_A2` 228 RGBA12 = GL_RGBA12, /// `GL_RGBA12` 229 RGBA16 = GL_RGBA16, /// `GL_RGBA16` 230 SRGB = GL_SRGB, /// `GL_SRGB` 231 SRGB8 = GL_SRGB8, /// `GL_SRGB8` 232 SRGB_ALPHA = GL_SRGB_ALPHA, /// `GL_SRGB_ALPHA` 233 SRGB8_ALPHA8 = GL_SRGB8_ALPHA8 /// `GL_SRGB8_ALPHA8` 234 } 235 236 /// 237 enum Format 238 { 239 RED = GL_RED, /// `GL_RED` 240 RG = GL_RG, /// `GL_RG` 241 RGB = GL_RGB, /// `GL_RGB` 242 RGBA = GL_RGBA, /// `GL_RGBA` 243 244 BGR = GL_BGR, /// `GL_BGR` 245 BGRA = GL_BGRA, /// `GL_BGRA` 246 247 DEPTH = GL_DEPTH_COMPONENT, /// `GL_DEPTH_COMPONENT` 248 DEPTH_STENCIL = GL_DEPTH_STENCIL /// `GL_DEPTH_STENCIL` 249 } 250 251 /// 252 enum Type 253 { 254 UNSIGNED_BYTE = GL_UNSIGNED_BYTE, /// `GL_UNSIGNED_BYTE` 255 BYTE = GL_BYTE, /// `GL_BYTE` 256 UNSIGNED_SHORT = GL_UNSIGNED_SHORT, /// `GL_UNSIGNED_SHORT` 257 SHORT = GL_SHORT, /// `GL_SHORT` 258 UNSIGNED_INT = GL_UNSIGNED_INT, /// `GL_UNSIGNED_INT` 259 INT = GL_INT, /// `GL_INT` 260 HALF_FLOAT = GL_HALF_FLOAT, /// `GL_HALF_FLOAT` 261 FLOAT = GL_FLOAT, /// `GL_FLOAT` 262 263 UNSIGNED_BYTE_3_3_2 = GL_UNSIGNED_BYTE_3_3_2, /// `GL_UNSIGNED_BYTE_3_3_2` 264 UNSIGNED_BYTE_2_3_3_REV = GL_UNSIGNED_BYTE_2_3_3_REV, /// `GL_UNSIGNED_BYTE_2_3_3_REV` 265 UNSIGNED_SHORT_5_6_5 = GL_UNSIGNED_SHORT_5_6_5, /// `GL_UNSIGNED_SHORT_5_6_5` 266 UNSIGNED_SHORT_5_6_5_REV = GL_UNSIGNED_SHORT_5_6_5_REV, /// `GL_UNSIGNED_SHORT_5_6_5_REV` 267 UNSIGNED_SHORT_4_4_4_4 = GL_UNSIGNED_SHORT_4_4_4_4, /// `GL_UNSIGNED_SHORT_4_4_4_4` 268 UNSIGNED_SHORT_4_4_4_4_REV = GL_UNSIGNED_SHORT_4_4_4_4_REV, /// `GL_UNSIGNED_SHORT_4_4_4_4_REV` 269 UNSIGNED_SHORT_5_5_5_1 = GL_UNSIGNED_SHORT_5_5_5_1, /// `GL_UNSIGNED_SHORT_5_5_5_1` 270 UNSIGNED_SHORT_1_5_5_5_REV = GL_UNSIGNED_SHORT_1_5_5_5_REV, /// `GL_UNSIGNED_SHORT_1_5_5_5_REV` 271 UNSIGNED_INT_8_8_8_8 = GL_UNSIGNED_INT_8_8_8_8, /// `GL_UNSIGNED_INT_8_8_8_8` 272 UNSIGNED_INT_8_8_8_8_REV = GL_UNSIGNED_INT_8_8_8_8_REV, /// `GL_UNSIGNED_INT_8_8_8_8_REV` 273 UNSIGNED_INT_10_10_10_2 = GL_UNSIGNED_INT_10_10_10_2, /// `GL_UNSIGNED_INT_10_10_10_2` 274 UNSIGNED_INT_2_10_10_10_REV = GL_UNSIGNED_INT_2_10_10_10_REV, /// `GL_UNSIGNED_INT_2_10_10_10_REV` 275 UNSIGNED_INT_24_8 = GL_UNSIGNED_INT_24_8, /// `GL_UNSIGNED_INT_24_8` 276 UNSIGNED_INT_10F_11F_11F_REV = GL_UNSIGNED_INT_10F_11F_11F_REV, /// `GL_UNSIGNED_INT_10F_11F_11F_REV` 277 UNSIGNED_INT_5_9_9_9_REV = GL_UNSIGNED_INT_5_9_9_9_REV, /// `GL_UNSIGNED_INT_5_9_9_9_REV` 278 FLOAT_32_UNSIGNED_INT_24_8_REV = GL_FLOAT_32_UNSIGNED_INT_24_8_REV /// `GL_FLOAT_32_UNSIGNED_INT_24_8_REV` 279 } 280 281 /// 282 this( Target tg, uint tu = 0 ) 283 in 284 { 285 assert( isBase(tg) ); 286 int max_tu; 287 checkGLCall!glGetIntegerv( GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_tu ); 288 assert( tu < max_tu ); 289 } 290 body 291 { 292 _unit = tu; 293 checkGLCall!glGenTextures( 1, &_id ); 294 logger = new InstanceLogger( this, format( "%d:%d", tu, _id ) ); 295 _target = tg; 296 logger.Debug( "with target [%s]", _target ); 297 } 298 299 final pure @property 300 { 301 /// 302 uint id() const { return _id; } 303 /// 304 uint unit() const { return _unit; } 305 /// 306 void unit( uint tu ) { _unit = tu; } 307 } 308 309 /// bind, glGenerateMipmap 310 void genMipmap() 311 in { assert( isMipmapable(_target) ); } body 312 { 313 bind(); 314 checkGLCall!glGenerateMipmap(gltype); 315 logger.Debug( "with target [%s]", _target ); 316 } 317 318 /// 319 void setParam( GLenum param, int val ) 320 { 321 bind(); 322 checkGLCall!glTexParameteri( gltype, param, val ); 323 } 324 325 /// 326 void setParam( GLenum param, int[] val ) 327 { 328 bind(); 329 checkGLCall!glTexParameteriv( gltype, param, val.ptr ); 330 } 331 332 /// 333 void setParam( GLenum param, float val ) 334 { 335 bind(); 336 checkGLCall!glTexParameterf( gltype, param, val ); 337 } 338 339 /// 340 void setParam( GLenum param, float[] val ) 341 { 342 bind(); 343 checkGLCall!glTexParameterfv( gltype, param, val.ptr ); 344 } 345 346 /// 347 void setMinFilter( Filter filter ) 348 { 349 setParam( Parameter.MIN_FILTER, filter ); 350 logger.Debug( "to [%s]", filter ); 351 } 352 353 /// 354 void setMagFilter( Filter filter ) 355 { 356 setParam( Parameter.MAG_FILTER, filter ); 357 logger.Debug( "to [%s]", filter ); 358 } 359 360 /// 361 void setWrapS( Wrap wrap ) 362 { 363 setParam( Parameter.WRAP_S, wrap ); 364 logger.Debug( "to [%s]", wrap ); 365 } 366 367 /// 368 void setWrapT( Wrap wrap ) 369 { 370 setParam( Parameter.WRAP_T, wrap ); 371 logger.Debug( "to [%s]", wrap ); 372 } 373 374 /// 375 void setWrapR( Wrap wrap ) 376 { 377 setParam( Parameter.WRAP_R, wrap ); 378 logger.Debug( "to [%s]", wrap ); 379 } 380 381 /// 382 void setMinLOD( float v ) 383 { 384 setParam( Parameter.MIN_LOD, v ); 385 logger.Debug( "to [%f]", v ); 386 } 387 388 /// 389 void setMaxLOD( float v ) 390 { 391 setParam( Parameter.MAX_LOD, v ); 392 logger.Debug( "to [%f]", v ); 393 } 394 395 /// 396 void setLODBais( float v ) 397 { 398 setParam( Parameter.LOD_BIAS, v ); 399 logger.Debug( "to [%f]", v ); 400 } 401 402 /// 403 void setBaseLevel( int v ) 404 { 405 setParam( Parameter.BASE_LEVEL, v ); 406 logger.Debug( "to [%d]", v ); 407 } 408 409 /// 410 void setMaxLevel( int v ) 411 { 412 setParam( Parameter.MAX_LEVEL, v ); 413 logger.Debug( "to [%d]", v ); 414 } 415 416 /// 417 void setBorderColor( vec4 clr ) 418 { 419 setParam( Parameter.BORDER_COLOR, clr.data ); 420 logger.Debug( "to [%f,%f,%f,%f]", clr.r, clr.g, clr.b, clr.a ); 421 } 422 423 /// 424 void setCompareFunc( CompareFunc cf ) 425 { 426 setParam( Parameter.COMPARE_FUNC, cf ); 427 logger.Debug( "to [%s]", cf ); 428 } 429 430 /// 431 void setCompareMode( CompareMode cm ) 432 { 433 setParam( Parameter.COMPARE_MODE, cm ); 434 logger.Debug( "to [%s]", cm ); 435 } 436 437 /// 438 void setSwizzleR( Swizzle s ) 439 { 440 setParam( Parameter.SWIZZLE_R, s ); 441 logger.Debug( "to [%s]", s ); 442 } 443 444 /// 445 void setSwizzleG( Swizzle s ) 446 { 447 setParam( Parameter.SWIZZLE_G, s ); 448 logger.Debug( "to [%s]", s ); 449 } 450 451 /// 452 void setSwizzleB( Swizzle s ) 453 { 454 setParam( Parameter.SWIZZLE_B, s ); 455 logger.Debug( "to [%s]", s ); 456 } 457 458 /// 459 void setSwizzleA( Swizzle s ) 460 { 461 setParam( Parameter.SWIZZLE_A, s ); 462 logger.Debug( "to [%s]", s ); 463 } 464 465 /// 466 void setSwizzleRGBA( Swizzle[4] s ) 467 { 468 setParam( Parameter.SWIZZLE_RGBA, to!(int[])(s) ); 469 logger.Debug( "to %s", s ); 470 } 471 472 /// 473 void setDepthStencilTextureMode( DepthStencilTextureMode dstm ) 474 { 475 setParam( Parameter.DEPTH_STENCIL_TEXTURE_MODE, dstm ); 476 logger.Debug( "to [%s]", dstm ); 477 } 478 479 final nothrow 480 { 481 /// glActiveTexture, glBindTexture 482 void bind() 483 { 484 ntCheckGLCall!glActiveTexture( GL_TEXTURE0 + _unit ); 485 ntCheckGLCall!glBindTexture( gltype, _id ); 486 debug logger.trace( "pass" ); 487 } 488 489 /// 490 void unbind() 491 { 492 ntCheckGLCall!glActiveTexture( GL_TEXTURE0 + _unit ); 493 ntCheckGLCall!glBindTexture( gltype, 0 ); 494 debug logger.trace( "pass" ); 495 } 496 497 /// 498 texsize_t size() const { return img_size; } 499 } 500 501 /// 502 void resize(size_t N,T)( in Vector!(N,T) sz ) 503 if( (N==1 || N==2 || N==3) && isIntegral!T ) 504 { image( sz, liformat, lformat, ltype ); } 505 506 /// set image 507 void image(size_t N,T)( in Vector!(N,T) sz, InternalFormat internal_format, 508 Format data_format, Type data_type, in void* data=null ) 509 if( (N==1 || N==2 || N==3) && isIntegral!T ) 510 { 511 enum N = sz.length; 512 img_size = texsize_t( sz, [1,1][0 .. 3-N] ); 513 514 liformat = internal_format; 515 lformat = data_format; 516 ltype = data_type; 517 518 bind(); 519 mixin( format(` 520 glTexImage%1dD( gltype, 0, cast(int)internal_format, %s, 0, 521 cast(GLenum)data_format, cast(GLenum)data_type, data ); 522 `, N, accessVecFields!(sz) ) ); 523 524 debug checkGL; 525 logger.Debug( "[%d]: size %s, internal format [%s], format [%s], type [%s], with data [%s]", 526 _id, sz.data.dup, internal_format, data_format, data_type, data?true:false ); 527 } 528 529 /// ditto 530 final void image(size_t N)( in Image!N img ) if( N >= 1 && N <= 3 ) 531 in 532 { 533 switch( N ) 534 { 535 case 1: assert( target == Target.T1D ); break; 536 case 2: assert( target == Target.T2D ); break; 537 case 3: assert( target == Target.T3D ); break; 538 default: assert(0); 539 } 540 } 541 body 542 { 543 Type type = typeFromImageDataType( img.info.comp ); 544 auto fmt = formatFromImageChanelsCount( img.info.channels ); 545 image( img.size, fmt[0], fmt[1], type, img.data.ptr ); 546 } 547 548 /// 549 final void getImage( ref Image!2 img ) 550 in { assert( _target == Target.T2D ); } body 551 { getImage( img, ltype ); } 552 553 /// 554 final void getImage( ref Image!2 img, Type type ) 555 in { assert( _target == Target.T2D ); } body 556 { 557 enum uint level = 0; 558 559 bind(); 560 debug checkGL; 561 int w, h; 562 glGetTexLevelParameteriv( GL_TEXTURE_2D, level, GL_TEXTURE_WIDTH, &(w)); 563 debug checkGL; 564 glGetTexLevelParameteriv( GL_TEXTURE_2D, level, GL_TEXTURE_HEIGHT, &(h)); 565 debug checkGL; 566 567 auto elemSize = formatElemCount(lformat) * sizeofType(type); 568 569 auto dsize = w * h * elemSize; 570 571 if( img.size != CrdVector!2(w,h) || img.info.bpe != elemSize ) 572 { 573 img.size = ivec2( w, h ); 574 img.info = imageElemInfo( lformat, type ); 575 } 576 577 glGetTexImage( GL_TEXTURE_2D, level, cast(GLenum)lformat, cast(GLenum)type, img.data.ptr ); 578 debug checkGL; 579 unbind(); 580 debug checkGL; 581 debug logger.trace( "[%d] size [%d,%d], format [%s], type [%s]", _id, w,h, lformat, type ); 582 } 583 584 protected static 585 { 586 /// 587 bool isBase( Target trg ) 588 { 589 switch(trg) 590 { 591 case Target.T1D: 592 case Target.T2D: 593 case Target.T3D: 594 case Target.T1D_ARRAY: 595 case Target.T2D_ARRAY: 596 case Target.RECTANGLE: 597 case Target.CUBE_MAP: 598 case Target.CUBE_MAP_ARRAY: return true; 599 default: return false; 600 } 601 } 602 603 /// 604 bool isParametric( Target trg ) 605 { 606 switch(trg) 607 { 608 case Target.T1D: 609 case Target.T2D: 610 case Target.T3D: 611 case Target.T1D_ARRAY: 612 case Target.T2D_ARRAY: 613 case Target.RECTANGLE: 614 case Target.CUBE_MAP: return true; 615 default: return false; 616 } 617 } 618 619 /// 620 bool isMipmapable( Target trg ) 621 { 622 switch(trg) 623 { 624 case Target.T1D: 625 case Target.T2D: 626 case Target.T3D: 627 case Target.T1D_ARRAY: 628 case Target.T2D_ARRAY: 629 case Target.CUBE_MAP: return true; 630 default: return false; 631 } 632 } 633 634 /// 635 size_t formatElemCount( Format fmt ) 636 { 637 final switch(fmt) 638 { 639 case Format.RED: return 1; 640 case Format.RG: return 2; 641 642 case Format.RGB: 643 case Format.BGR: 644 return 3; 645 646 case Format.RGBA: 647 case Format.BGRA: 648 return 4; 649 650 case Format.DEPTH: 651 return 1; 652 653 case Format.DEPTH_STENCIL: 654 return 2; 655 } 656 } 657 658 /// 659 size_t sizeofType( Type type ) 660 { 661 final switch(type) 662 { 663 case Type.BYTE: 664 case Type.UNSIGNED_BYTE: 665 case Type.UNSIGNED_BYTE_3_3_2: 666 case Type.UNSIGNED_BYTE_2_3_3_REV: 667 return byte.sizeof; 668 669 case Type.SHORT: 670 case Type.UNSIGNED_SHORT: 671 case Type.UNSIGNED_SHORT_5_6_5: 672 case Type.UNSIGNED_SHORT_5_6_5_REV: 673 case Type.UNSIGNED_SHORT_4_4_4_4: 674 case Type.UNSIGNED_SHORT_4_4_4_4_REV: 675 case Type.UNSIGNED_SHORT_5_5_5_1: 676 case Type.UNSIGNED_SHORT_1_5_5_5_REV: 677 return short.sizeof; 678 679 case Type.INT: 680 case Type.UNSIGNED_INT: 681 case Type.UNSIGNED_INT_8_8_8_8: 682 case Type.UNSIGNED_INT_8_8_8_8_REV: 683 case Type.UNSIGNED_INT_10_10_10_2: 684 case Type.UNSIGNED_INT_2_10_10_10_REV: 685 case Type.UNSIGNED_INT_24_8: 686 case Type.UNSIGNED_INT_10F_11F_11F_REV: 687 case Type.UNSIGNED_INT_5_9_9_9_REV: 688 case Type.FLOAT_32_UNSIGNED_INT_24_8_REV: 689 return int.sizeof; 690 691 case Type.HALF_FLOAT: return float.sizeof / 2; 692 case Type.FLOAT: return float.sizeof; 693 } 694 } 695 696 /// 697 auto imageElemInfo( Format fmt, Type type ) 698 { 699 auto cnt = formatElemCount(fmt); 700 auto ict = imageDataType(type); 701 if( ict == DataType.RAWBYTE ) 702 return ElemInfo( sizeofType(type) * cnt ); 703 else 704 return ElemInfo( ict, cnt ); 705 } 706 707 /// 708 DataType imageDataType( Type type ) 709 { 710 switch( type ) 711 { 712 case Type.BYTE: return DataType.BYTE; 713 case Type.UNSIGNED_BYTE: return DataType.UBYTE; 714 case Type.SHORT: return DataType.SHORT; 715 case Type.UNSIGNED_SHORT: return DataType.USHORT; 716 case Type.INT: return DataType.INT; 717 case Type.UNSIGNED_INT: return DataType.UINT; 718 case Type.FLOAT: return DataType.FLOAT; 719 default: return DataType.RAWBYTE; 720 } 721 } 722 723 /// 724 @property bool isParameterEnum(T)() 725 { 726 return is(T==DepthStencilTextureMode) || 727 is(T==CompareFunc) || 728 is(T==CompareMode) || 729 is(T==Filter) || 730 is(T==Swizzle) || 731 is(T==Wrap); 732 } 733 734 /// 735 Type typeFromImageDataType( DataType ctype ) 736 { 737 switch( ctype ) 738 { 739 case DataType.BYTE: return Type.BYTE; 740 case DataType.UBYTE: 741 case DataType.RAWBYTE: return Type.UNSIGNED_BYTE; 742 case DataType.SHORT: return Type.SHORT; 743 case DataType.USHORT: return Type.UNSIGNED_SHORT; 744 case DataType.INT: return Type.INT; 745 case DataType.UINT: return Type.UNSIGNED_INT; 746 case DataType.NORM_FIXED: return Type.INT; 747 case DataType.UNORM_FIXED: return Type.UNSIGNED_INT; 748 case DataType.FLOAT: return Type.FLOAT; 749 default: 750 throw new GLTextureException( "uncompatible image component type" ); 751 } 752 } 753 754 /// 755 auto formatFromImageChanelsCount( size_t channels ) 756 { 757 switch( channels ) 758 { 759 case 1: return tuple(InternalFormat.RED, Format.RED ); 760 case 2: return tuple(InternalFormat.RG, Format.RG ); 761 case 3: return tuple(InternalFormat.RGB, Format.RGB ); 762 case 4: return tuple(InternalFormat.RGBA, Format.RGBA ); 763 default: 764 throw new GLTextureException( "uncompatible image chanels count" ); 765 } 766 } 767 } 768 } 769 770 private @property string accessVecFields(alias T)() 771 { 772 string[] ret; 773 foreach( i; 0 .. T.length ) 774 ret ~= format( "cast(int)(%s[%d])", T.stringof, i ); 775 return ret.join(","); 776 }