1 module des.gl.texture; 2 3 import std..string; 4 5 import des.gl.general; 6 7 public import des.il; 8 9 import std.algorithm; 10 import des.util.stdext.algorithm; 11 12 /// 13 class GLTextureException : DesGLException 14 { 15 /// 16 this( string msg, string file=__FILE__, size_t line=__LINE__ ) @safe pure nothrow 17 { super( msg, file, line ); } 18 } 19 20 /// 21 abstract class GLTexture : GLObject!("Texture",false) 22 { 23 mixin DES; 24 mixin ClassLogger; 25 26 protected: 27 28 /// 29 InternalFormat liformat; 30 /// 31 Format lformat; 32 /// 33 Type ltype; 34 35 /// texture unit 36 uint _unit; 37 38 uivec3 _size; 39 40 public: 41 42 /// 43 enum InternalFormat 44 { 45 COMPRESSED_RED = GL_COMPRESSED_RED, /// `GL_COMPRESSED_RED` 46 COMPRESSED_RG = GL_COMPRESSED_RG, /// `GL_COMPRESSED_RG` 47 COMPRESSED_RGB = GL_COMPRESSED_RGB, /// `GL_COMPRESSED_RGB` 48 COMPRESSED_RGBA = GL_COMPRESSED_RGBA, /// `GL_COMPRESSED_RGBA` 49 COMPRESSED_SRGB = GL_COMPRESSED_SRGB, /// `GL_COMPRESSED_SRGB` 50 COMPRESSED_SRGB_ALPHA = GL_COMPRESSED_SRGB_ALPHA, /// `GL_COMPRESSED_SRGB_ALPHA` 51 DEPTH = GL_DEPTH_COMPONENT, /// `GL_DEPTH_COMPONENT` 52 DEPTH16 = GL_DEPTH_COMPONENT16, /// `GL_DEPTH_COMPONENT16` 53 DEPTH24 = GL_DEPTH_COMPONENT24, /// `GL_DEPTH_COMPONENT24` 54 DEPTH32 = GL_DEPTH_COMPONENT32, /// `GL_DEPTH_COMPONENT32` 55 DEPTH32F = GL_DEPTH_COMPONENT32F, /// `GL_DEPTH_COMPONENT32F` 56 DEPTH_STENCIL = GL_DEPTH_STENCIL, /// `GL_DEPTH_STENCIL` 57 R3_G3_B2 = GL_R3_G3_B2, /// `GL_R3_G3_B2` 58 RED = GL_RED, /// `GL_RED` 59 RG = GL_RG, /// `GL_RG` 60 RGB = GL_RGB, /// `GL_RGB` 61 RGB4 = GL_RGB4, /// `GL_RGB4` 62 RGB5 = GL_RGB5, /// `GL_RGB5` 63 RGB8 = GL_RGB8, /// `GL_RGB8` 64 RGB10 = GL_RGB10, /// `GL_RGB10` 65 RGB12 = GL_RGB12, /// `GL_RGB12` 66 RGB16 = GL_RGB16, /// `GL_RGB16` 67 RGBA = GL_RGBA, /// `GL_RGBA` 68 RGBA2 = GL_RGBA2, /// `GL_RGBA2` 69 RGBA4 = GL_RGBA4, /// `GL_RGBA4` 70 RGB5_A1 = GL_RGB5_A1, /// `GL_RGB5_A1` 71 RGBA8 = GL_RGBA8, /// `GL_RGBA8` 72 RGB10_A2 = GL_RGB10_A2, /// `GL_RGB10_A2` 73 RGBA12 = GL_RGBA12, /// `GL_RGBA12` 74 RGBA16 = GL_RGBA16, /// `GL_RGBA16` 75 SRGB = GL_SRGB, /// `GL_SRGB` 76 SRGB8 = GL_SRGB8, /// `GL_SRGB8` 77 SRGB_ALPHA = GL_SRGB_ALPHA, /// `GL_SRGB_ALPHA` 78 SRGB8_ALPHA8 = GL_SRGB8_ALPHA8 /// `GL_SRGB8_ALPHA8` 79 } 80 81 enum Side 82 { 83 PX = GL_TEXTURE_CUBE_MAP_POSITIVE_X, /// `GL_TEXTURE_CUBE_MAP_POSITIVE_X` 84 NX = GL_TEXTURE_CUBE_MAP_NEGATIVE_X, /// `GL_TEXTURE_CUBE_MAP_NEGATIVE_X` 85 PY = GL_TEXTURE_CUBE_MAP_POSITIVE_Y, /// `GL_TEXTURE_CUBE_MAP_POSITIVE_Y` 86 NY = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, /// `GL_TEXTURE_CUBE_MAP_NEGATIVE_Y` 87 PZ = GL_TEXTURE_CUBE_MAP_POSITIVE_Z, /// `GL_TEXTURE_CUBE_MAP_POSITIVE_Z` 88 NZ = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z /// `GL_TEXTURE_CUBE_MAP_NEGATIVE_Z` 89 } 90 91 /// 92 enum Format 93 { 94 RED = GL_RED, /// `GL_RED` 95 RG = GL_RG, /// `GL_RG` 96 RGB = GL_RGB, /// `GL_RGB` 97 RGBA = GL_RGBA, /// `GL_RGBA` 98 99 BGR = GL_BGR, /// `GL_BGR` 100 BGRA = GL_BGRA, /// `GL_BGRA` 101 102 DEPTH = GL_DEPTH_COMPONENT, /// `GL_DEPTH_COMPONENT` 103 DEPTH_STENCIL = GL_DEPTH_STENCIL /// `GL_DEPTH_STENCIL` 104 } 105 106 /// 107 enum Type 108 { 109 UNSIGNED_BYTE = GL_UNSIGNED_BYTE, /// `GL_UNSIGNED_BYTE` 110 BYTE = GL_BYTE, /// `GL_BYTE` 111 UNSIGNED_SHORT = GL_UNSIGNED_SHORT, /// `GL_UNSIGNED_SHORT` 112 SHORT = GL_SHORT, /// `GL_SHORT` 113 UNSIGNED_INT = GL_UNSIGNED_INT, /// `GL_UNSIGNED_INT` 114 INT = GL_INT, /// `GL_INT` 115 HALF_FLOAT = GL_HALF_FLOAT, /// `GL_HALF_FLOAT` 116 FLOAT = GL_FLOAT, /// `GL_FLOAT` 117 118 UNSIGNED_BYTE_3_3_2 = GL_UNSIGNED_BYTE_3_3_2, /// `GL_UNSIGNED_BYTE_3_3_2` 119 UNSIGNED_BYTE_2_3_3_REV = GL_UNSIGNED_BYTE_2_3_3_REV, /// `GL_UNSIGNED_BYTE_2_3_3_REV` 120 UNSIGNED_SHORT_5_6_5 = GL_UNSIGNED_SHORT_5_6_5, /// `GL_UNSIGNED_SHORT_5_6_5` 121 UNSIGNED_SHORT_5_6_5_REV = GL_UNSIGNED_SHORT_5_6_5_REV, /// `GL_UNSIGNED_SHORT_5_6_5_REV` 122 UNSIGNED_SHORT_4_4_4_4 = GL_UNSIGNED_SHORT_4_4_4_4, /// `GL_UNSIGNED_SHORT_4_4_4_4` 123 UNSIGNED_SHORT_4_4_4_4_REV = GL_UNSIGNED_SHORT_4_4_4_4_REV, /// `GL_UNSIGNED_SHORT_4_4_4_4_REV` 124 UNSIGNED_SHORT_5_5_5_1 = GL_UNSIGNED_SHORT_5_5_5_1, /// `GL_UNSIGNED_SHORT_5_5_5_1` 125 UNSIGNED_SHORT_1_5_5_5_REV = GL_UNSIGNED_SHORT_1_5_5_5_REV, /// `GL_UNSIGNED_SHORT_1_5_5_5_REV` 126 UNSIGNED_INT_8_8_8_8 = GL_UNSIGNED_INT_8_8_8_8, /// `GL_UNSIGNED_INT_8_8_8_8` 127 UNSIGNED_INT_8_8_8_8_REV = GL_UNSIGNED_INT_8_8_8_8_REV, /// `GL_UNSIGNED_INT_8_8_8_8_REV` 128 UNSIGNED_INT_10_10_10_2 = GL_UNSIGNED_INT_10_10_10_2, /// `GL_UNSIGNED_INT_10_10_10_2` 129 UNSIGNED_INT_2_10_10_10_REV = GL_UNSIGNED_INT_2_10_10_10_REV, /// `GL_UNSIGNED_INT_2_10_10_10_REV` 130 UNSIGNED_INT_24_8 = GL_UNSIGNED_INT_24_8, /// `GL_UNSIGNED_INT_24_8` 131 UNSIGNED_INT_10F_11F_11F_REV = GL_UNSIGNED_INT_10F_11F_11F_REV, /// `GL_UNSIGNED_INT_10F_11F_11F_REV` 132 UNSIGNED_INT_5_9_9_9_REV = GL_UNSIGNED_INT_5_9_9_9_REV, /// `GL_UNSIGNED_INT_5_9_9_9_REV` 133 FLOAT_32_UNSIGNED_INT_24_8_REV = GL_FLOAT_32_UNSIGNED_INT_24_8_REV /// `GL_FLOAT_32_UNSIGNED_INT_24_8_REV` 134 } 135 136 /// 137 this( GLenum tg, uint tu = 0 ) 138 in 139 { 140 int max_tu; 141 checkGLCall!glGetIntegerv( GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_tu ); 142 assert( tu < max_tu ); 143 } 144 body 145 { 146 _unit = tu; 147 super( tg ); 148 logger.Debug( "with target [%s] texture unit [%d]", toGLTextureTarget(target), tu ); 149 setMinFilter( Filter.NEAREST ); 150 setMagFilter( Filter.NEAREST ); 151 } 152 153 enum Dim { ONE=1, TWO=2, THREE=3 } 154 155 pure nothrow @nogc @property 156 { 157 final 158 { 159 /// 160 uint unit() const { return _unit; } 161 /// 162 void unit( uint tu ) { _unit = tu; } 163 } 164 165 uivec3 size() const 166 { 167 final switch( allocDim ) 168 { 169 case Dim.ONE: return uivec3( _size.x, 1, 1 ); 170 case Dim.TWO: return uivec3( _size.xy, 1 ); 171 case Dim.THREE: return _size; 172 } 173 } 174 175 const 176 { 177 abstract bool mipmapable(); 178 abstract bool isArray(); 179 abstract Dim imageDim(); 180 abstract Dim allocDim(); 181 } 182 } 183 184 /// 185 void genMipmap() 186 { 187 if( !mipmapable ) throw new GLTextureException( this.toString ~ " is not mipmapable" ); 188 bind(); 189 checkGLCall!glGenerateMipmap(target); 190 logger.Debug( "with target [%s]", target ); 191 } 192 193 /// 194 void setParam( GLenum param, int val ) 195 { 196 bind(); 197 checkGLCall!glTexParameteri( target, param, val ); 198 } 199 200 /// 201 void setParam( GLenum param, int[] val ) 202 { 203 bind(); 204 checkGLCall!glTexParameteriv( target, param, val.ptr ); 205 } 206 207 /// 208 void setParam( GLenum param, float val ) 209 { 210 bind(); 211 checkGLCall!glTexParameterf( target, param, val ); 212 } 213 214 /// 215 void setParam( GLenum param, float[] val ) 216 { 217 bind(); 218 checkGLCall!glTexParameterfv( target, param, val.ptr ); 219 } 220 221 /// 222 enum Filter 223 { 224 NEAREST = GL_NEAREST, /// `GL_NEAREST` 225 LINEAR = GL_LINEAR, /// `GL_LINEAR` 226 NEAREST_MIPMAP_NEAREST = GL_NEAREST_MIPMAP_NEAREST, /// `GL_NEAREST_MIPMAP_NEAREST` 227 LINEAR_MIPMAP_NEAREST = GL_LINEAR_MIPMAP_NEAREST, /// `GL_LINEAR_MIPMAP_NEAREST` 228 NEAREST_MIPMAP_LINEAR = GL_NEAREST_MIPMAP_LINEAR, /// `GL_NEAREST_MIPMAP_LINEAR` 229 LINEAR_MIPMAP_LINEAR = GL_LINEAR_MIPMAP_LINEAR /// `GL_LINEAR_MIPMAP_LINEAR` 230 } 231 232 /// 233 void setMinFilter( Filter filter ) 234 { 235 setParam( GL_TEXTURE_MIN_FILTER, filter ); 236 logger.Debug( "to [%s]", filter ); 237 } 238 239 /// 240 void setMagFilter( Filter filter ) 241 { 242 setParam( GL_TEXTURE_MAG_FILTER, filter ); 243 logger.Debug( "to [%s]", filter ); 244 } 245 246 /// 247 enum Wrap 248 { 249 CLAMP_TO_EDGE = GL_CLAMP_TO_EDGE, /// `GL_CLAMP_TO_EDGE` 250 CLAMP_TO_BORDER = GL_CLAMP_TO_BORDER, /// `GL_CLAMP_TO_BORDER` 251 MIRRORED_REPEAT = GL_MIRRORED_REPEAT, /// `GL_MIRRORED_REPEAT` 252 REPEAT = GL_REPEAT /// `GL_REPEAT` 253 } 254 255 /// 256 void setWrapS( Wrap wrap ) 257 { 258 setParam( GL_TEXTURE_WRAP_S, wrap ); 259 logger.Debug( "to [%s]", wrap ); 260 } 261 262 /// 263 void setWrapT( Wrap wrap ) 264 { 265 setParam( GL_TEXTURE_WRAP_T, wrap ); 266 logger.Debug( "to [%s]", wrap ); 267 } 268 269 /// 270 void setWrapR( Wrap wrap ) 271 { 272 setParam( GL_TEXTURE_WRAP_R, wrap ); 273 logger.Debug( "to [%s]", wrap ); 274 } 275 276 /// 277 void setMinLOD( float v ) 278 { 279 setParam( GL_TEXTURE_MIN_LOD, v ); 280 logger.Debug( "to [%f]", v ); 281 } 282 283 /// 284 void setMaxLOD( float v ) 285 { 286 setParam( GL_TEXTURE_MAX_LOD, v ); 287 logger.Debug( "to [%f]", v ); 288 } 289 290 /// 291 void setLODBais( float v ) 292 { 293 setParam( GL_TEXTURE_LOD_BIAS, v ); 294 logger.Debug( "to [%f]", v ); 295 } 296 297 /// 298 void setBaseLevel( int v ) 299 { 300 setParam( GL_TEXTURE_BASE_LEVEL, v ); 301 logger.Debug( "to [%d]", v ); 302 } 303 304 /// 305 void setMaxLevel( int v ) 306 { 307 setParam( GL_TEXTURE_MAX_LEVEL, v ); 308 logger.Debug( "to [%d]", v ); 309 } 310 311 /// 312 void setBorderColor( vec4 clr ) 313 { 314 setParam( GL_TEXTURE_BORDER_COLOR, clr.data ); 315 logger.Debug( "to [%f,%f,%f,%f]", clr.r, clr.g, clr.b, clr.a ); 316 } 317 318 /// 319 enum CompareFunc 320 { 321 LEQUAL = GL_LEQUAL, /// `GL_LEQUAL` 322 GEQUAL = GL_GEQUAL, /// `GL_GEQUAL` 323 LESS = GL_LESS, /// `GL_LESS` 324 GREATER = GL_GREATER, /// `GL_GREATER` 325 EQUAL = GL_EQUAL, /// `GL_EQUAL` 326 NOTEQUAL = GL_NOTEQUAL, /// `GL_NOTEQUAL` 327 ALWAYS = GL_ALWAYS, /// `GL_ALWAYS` 328 NEVER = GL_NEVER /// `GL_NEVER` 329 } 330 331 /// 332 void setCompareFunc( CompareFunc cf ) 333 { 334 setParam( GL_TEXTURE_COMPARE_FUNC, cf ); 335 logger.Debug( "to [%s]", cf ); 336 } 337 338 /// 339 enum CompareMode 340 { 341 REF_TO_TEXTURE = GL_COMPARE_REF_TO_TEXTURE, /// `GL_COMPARE_REF_TO_TEXTURE` 342 NONE = GL_NONE /// `GL_NONE` 343 } 344 345 /// 346 void setCompareMode( CompareMode cm ) 347 { 348 setParam( GL_TEXTURE_COMPARE_MODE, cm ); 349 logger.Debug( "to [%s]", cm ); 350 } 351 352 /// 353 enum Swizzle 354 { 355 RED = GL_RED, /// `GL_RED` 356 GREEN = GL_GREEN,/// `GL_GREEN` 357 BLUE = GL_BLUE, /// `GL_BLUE` 358 ALPHA = GL_ALPHA,/// `GL_ALPHA` 359 ONE = GL_ONE, /// `GL_ONE` 360 ZERO = GL_ZERO /// `GL_ZERO` 361 } 362 363 /// 364 void setSwizzleR( Swizzle s ) 365 { 366 setParam( GL_TEXTURE_SWIZZLE_R, s ); 367 logger.Debug( "to [%s]", s ); 368 } 369 370 /// 371 void setSwizzleG( Swizzle s ) 372 { 373 setParam( GL_TEXTURE_SWIZZLE_G, s ); 374 logger.Debug( "to [%s]", s ); 375 } 376 377 /// 378 void setSwizzleB( Swizzle s ) 379 { 380 setParam( GL_TEXTURE_SWIZZLE_B, s ); 381 logger.Debug( "to [%s]", s ); 382 } 383 384 /// 385 void setSwizzleA( Swizzle s ) 386 { 387 setParam( GL_TEXTURE_SWIZZLE_A, s ); 388 logger.Debug( "to [%s]", s ); 389 } 390 391 /// 392 void setSwizzleRGBA( Swizzle[4] s ) 393 { 394 setParam( GL_TEXTURE_SWIZZLE_RGBA, to!(int[])(s) ); 395 logger.Debug( "to %s", s ); 396 } 397 398 /// 399 enum DepthStencilTextureMode 400 { 401 DEPTH = GL_DEPTH_COMPONENT, /// `GL_DEPTH_COMPONENT` 402 STENCIL = GL_STENCIL_COMPONENTS /// `GL_STENCIL_COMPONENTS` 403 } 404 405 /// 406 void setDepthStencilTextureMode( DepthStencilTextureMode dstm ) 407 { 408 setParam( GL_DEPTH_STENCIL_TEXTURE_MODE, dstm ); 409 logger.Debug( "to [%s]", dstm ); 410 } 411 412 final 413 { 414 /// glActiveTexture, glBindTexture 415 override void bind() 416 { 417 checkGLCall!glActiveTexture( GL_TEXTURE0 + _unit ); 418 checkGLCall!glBindTexture( target, id ); 419 debug logger.trace( "pass" ); 420 } 421 422 /// 423 override void unbind() 424 { 425 checkGLCall!glActiveTexture( GL_TEXTURE0 + _unit ); 426 checkGLCall!glBindTexture( target, 0 ); 427 debug logger.trace( "pass" ); 428 } 429 } 430 431 protected: 432 433 /// 434 void setImageTrg( ubyte N, GLenum trg, in uivec3 sz, InternalFormat store_format, 435 Format input_format, Type input_type, in void* data=null, uint level=0 ) 436 in 437 { 438 assert( N == 1 || N == 2 || N == 3 ); 439 assertNotCubeMap(trg); 440 } 441 body 442 { 443 bind(); 444 445 auto nsz = uivec3( redimSize( 3, N, sz.data ) ); 446 447 if( N == 1 ) 448 checkGLCall!glTexImage1D( trg, level, store_format, nsz.x, 0, 449 input_format, input_type, data ); 450 else if( N == 2 ) 451 checkGLCall!glTexImage2D( trg, level, store_format, nsz.x, nsz.y, 0, 452 input_format, input_type, data ); 453 else if( N == 3 ) 454 checkGLCall!glTexImage3D( trg, level, store_format, nsz.x, nsz.y, nsz.z, 0, 455 input_format, input_type, data ); 456 457 logger.Debug( "to [%s], size %s, internal format [%s], format [%s], type [%s], with data [%s]", 458 toGLTextureTarget(trg), sz, store_format, input_format, input_type, data?true:false ); 459 460 liformat = store_format; 461 lformat = input_format; 462 ltype = input_type; 463 464 _size = nsz; 465 } 466 467 /// 468 void setImageTrg( ubyte N, GLenum trg, in Image img, uint level=0 ) 469 in 470 { 471 assert( N == 1 || N == 2 || N == 3 ); 472 assertNotCubeMap(trg); 473 } 474 body 475 { 476 Type type = typeFromImageDataType( img.info.type ); 477 auto fmt = formatFromImageCompCount( img.info.comp ); 478 auto sz = uivec3( redimSize( 3, N, img.size ) ); 479 setImageTrg( N, trg, sz, fmt[0], fmt[1], type, img.data.ptr, level ); 480 } 481 482 /// 483 Image getImageTrg( GLenum trg, Type type, uint level=0 ) 484 { 485 bind(); 486 487 int w,h,d; 488 489 checkGLCall!glGetTexLevelParameteriv( trg, level, GL_TEXTURE_WIDTH, &w ); 490 checkGLCall!glGetTexLevelParameteriv( trg, level, GL_TEXTURE_HEIGHT, &h ); 491 checkGLCall!glGetTexLevelParameteriv( trg, level, GL_TEXTURE_DEPTH, &d ); 492 493 w = max( 1, w ); 494 h = max( 1, h ); 495 d = max( 1, d ); 496 497 auto ret = Image( ivec3(w,h,d), imageElemInfo( lformat, type ) ); 498 499 checkGLCall!glGetTexImage( trg, level, lformat, type, ret.data.ptr ); 500 501 debug logger.trace( "from [%s], size %s, format [%s], type [%s]", 502 toGLTextureTarget(trg), [w,h,d], lformat, type ); 503 504 return ret; 505 } 506 507 /// 508 static Type typeFromImageDataType( DataType ctype ) 509 { 510 switch( ctype ) 511 { 512 case DataType.BYTE: return Type.BYTE; 513 case DataType.UBYTE: 514 case DataType.RAWBYTE: return Type.UNSIGNED_BYTE; 515 case DataType.SHORT: return Type.SHORT; 516 case DataType.USHORT: return Type.UNSIGNED_SHORT; 517 case DataType.INT: return Type.INT; 518 case DataType.UINT: return Type.UNSIGNED_INT; 519 case DataType.NORM_FIXED: return Type.INT; 520 case DataType.UNORM_FIXED: return Type.UNSIGNED_INT; 521 case DataType.FLOAT: return Type.FLOAT; 522 default: 523 throw new GLTextureException( "uncompatible image component type" ); 524 } 525 } 526 527 /// 528 static auto formatFromImageCompCount( size_t channels ) 529 { 530 switch( channels ) 531 { 532 case 1: return tuple( InternalFormat.RED, Format.RED ); 533 case 2: return tuple( InternalFormat.RG, Format.RG ); 534 case 3: return tuple( InternalFormat.RGB, Format.RGB ); 535 case 4: return tuple( InternalFormat.RGBA, Format.RGBA ); 536 default: 537 throw new GLTextureException( "uncompatible image chanels count" ); 538 } 539 } 540 541 /// 542 static auto imageElemInfo( Format fmt, Type type ) 543 { 544 auto cnt = formatElemCount(fmt); 545 auto ict = imageDataType(type); 546 if( ict == DataType.RAWBYTE ) 547 return ElemInfo( sizeofType( type ) * cnt ); 548 else 549 return ElemInfo( cnt, ict ); 550 } 551 552 /// 553 static size_t formatElemCount( Format fmt ) 554 { 555 final switch(fmt) 556 { 557 case Format.RED: return 1; 558 case Format.RG: return 2; 559 case Format.RGB: case Format.BGR: return 3; 560 case Format.RGBA: case Format.BGRA: return 4; 561 case Format.DEPTH: return 1; 562 case Format.DEPTH_STENCIL: return 2; 563 } 564 } 565 566 /// 567 static DataType imageDataType( Type type ) 568 { 569 switch( type ) 570 { 571 case Type.BYTE: return DataType.BYTE; 572 case Type.UNSIGNED_BYTE: return DataType.UBYTE; 573 case Type.SHORT: return DataType.SHORT; 574 case Type.UNSIGNED_SHORT: return DataType.USHORT; 575 case Type.INT: return DataType.INT; 576 case Type.UNSIGNED_INT: return DataType.UINT; 577 case Type.FLOAT: return DataType.FLOAT; 578 default: return DataType.RAWBYTE; 579 } 580 } 581 582 /// 583 static size_t sizeofType( Type type ) 584 { 585 final switch(type) 586 { 587 case Type.BYTE: 588 case Type.UNSIGNED_BYTE: 589 case Type.UNSIGNED_BYTE_3_3_2: 590 case Type.UNSIGNED_BYTE_2_3_3_REV: 591 return byte.sizeof; 592 593 case Type.SHORT: 594 case Type.UNSIGNED_SHORT: 595 case Type.UNSIGNED_SHORT_5_6_5: 596 case Type.UNSIGNED_SHORT_5_6_5_REV: 597 case Type.UNSIGNED_SHORT_4_4_4_4: 598 case Type.UNSIGNED_SHORT_4_4_4_4_REV: 599 case Type.UNSIGNED_SHORT_5_5_5_1: 600 case Type.UNSIGNED_SHORT_1_5_5_5_REV: 601 return short.sizeof; 602 603 case Type.INT: 604 case Type.UNSIGNED_INT: 605 case Type.UNSIGNED_INT_8_8_8_8: 606 case Type.UNSIGNED_INT_8_8_8_8_REV: 607 case Type.UNSIGNED_INT_10_10_10_2: 608 case Type.UNSIGNED_INT_2_10_10_10_REV: 609 case Type.UNSIGNED_INT_24_8: 610 case Type.UNSIGNED_INT_10F_11F_11F_REV: 611 case Type.UNSIGNED_INT_5_9_9_9_REV: 612 case Type.FLOAT_32_UNSIGNED_INT_24_8_REV: 613 return int.sizeof; 614 615 case Type.HALF_FLOAT: return float.sizeof / 2; 616 case Type.FLOAT: return float.sizeof; 617 } 618 } 619 620 static void assertNotCubeMap( GLenum trg ) pure nothrow 621 { 622 assert( trg != GL_TEXTURE_CUBE_MAP && 623 trg != GL_TEXTURE_CUBE_MAP_ARRAY, 624 "is not cube map assert" ); 625 } 626 } 627 628 abstract class GLTextureBase(uint N) : GLTexture 629 if( N == 1 || N == 2 || N == 3 ) 630 { 631 public: 632 633 /// 634 this( GLenum trg, uint tu ) { super( trg, tu ); } 635 636 @property 637 { 638 final override const pure nothrow @nogc 639 { 640 /// 641 Dim allocDim() 642 { 643 static if( N == 1 ) return Dim.ONE; 644 else static if( N == 2 ) return Dim.TWO; 645 else static if( N == 3 ) return Dim.THREE; 646 else static assert(0,"unsuported texture size"); 647 } 648 } 649 } 650 } 651 652 abstract class GLTextureImgBase(uint N) : GLTextureBase!N 653 { 654 /// 655 this( GLenum trg, uint tu ) { super( trg, tu ); } 656 657 void size( in uivec3 sz ) @property { setImage( sz, liformat, lformat, ltype, null, 0 ); } 658 659 /// 660 void setImage( in uivec3 sz, InternalFormat store_format, 661 Format input_format, Type input_type, in void* data=null, uint level=0 ) 662 { setImageTrg( N, target, sz, store_format, input_format, input_type, data, level ); } 663 664 /// 665 void setImage( in Image img, uint level=0 ) { setImageTrg( N, target, img, level ); } 666 667 /// 668 Image getImage( Type type, uint level=0 ) 669 { return getImageTrg( target, type, level ); } 670 671 /// 672 Image getImage( uint level=0 ) { return getImage( ltype, level ); } 673 } 674 675 /// 676 class GLTexture1D : GLTextureImgBase!1 677 { 678 /// 679 this( uint tu ) { super( GL_TEXTURE_1D, tu ); } 680 681 final override const pure nothrow @nogc @property 682 { 683 /// 684 bool mipmapable() { return true; } 685 /// 686 bool isArray() { return false; } 687 /// 688 Dim imageDim() { return Dim.ONE; } 689 } 690 } 691 692 /// 693 class GLTexture1DArray : GLTextureImgBase!2 694 { 695 /// 696 this( uint tu ) { super( GL_TEXTURE_1D_ARRAY, tu ); } 697 698 final override const pure nothrow @nogc @property 699 { 700 /// 701 bool mipmapable() { return true; } 702 /// 703 bool isArray() { return true; } 704 /// 705 Dim imageDim() { return Dim.ONE; } 706 } 707 } 708 709 /// 710 class GLTexture2D : GLTextureImgBase!2 711 { 712 /// 713 this( uint tu ) { super( GL_TEXTURE_2D, tu ); } 714 715 final override const pure nothrow @nogc @property 716 { 717 /// 718 bool mipmapable() { return true; } 719 /// 720 bool isArray() { return false; } 721 /// 722 Dim imageDim() { return Dim.TWO; } 723 } 724 } 725 726 /// 727 class GLTexture2DArray : GLTextureImgBase!3 728 { 729 /// 730 this( uint tu ) { super( GL_TEXTURE_2D_ARRAY, tu ); } 731 732 final override const pure nothrow @nogc @property 733 { 734 /// 735 bool mipmapable() { return true; } 736 /// 737 bool isArray() { return true; } 738 /// 739 Dim imageDim() { return Dim.TWO; } 740 } 741 } 742 743 /// 744 class GLTextureRectangle : GLTextureImgBase!2 745 { 746 /// 747 this( uint tu ) { super( GL_TEXTURE_RECTANGLE, tu ); } 748 749 final override const pure nothrow @nogc @property 750 { 751 /// 752 bool mipmapable() { return false; } 753 /// 754 bool isArray() { return false; } 755 /// 756 Dim imageDim() { return Dim.TWO; } 757 } 758 } 759 760 /// 761 class GLTexture3D : GLTextureImgBase!3 762 { 763 /// 764 this( uint tu ) { super( GL_TEXTURE_3D, tu ); } 765 766 final override const pure nothrow @nogc @property 767 { 768 /// 769 bool mipmapable() { return true; } 770 /// 771 bool isArray() { return false; } 772 /// 773 Dim imageDim() { return Dim.THREE; } 774 } 775 } 776 777 abstract class GLTextureCubeBase(bool array) : GLTextureBase!(2+cast(uint)array) 778 { 779 protected enum CubeDim = 2u + cast(uint)array; 780 781 /// 782 this( GLenum trg, uint tu ) { super( trg, tu ); } 783 784 /// 785 void setImage( Side side, in uivec2 sz, InternalFormat store_format, 786 Format input_format, Type input_type, in void* data=null, uint level=0 ) 787 { setImageTrg( CubeDim, side, uivec3( sz, 1 ), store_format, input_format, input_type, data, level ); } 788 789 /// 790 void setImage( Side side, in Image img, uint level=0 ) 791 { setImageTrg( CubeDim, side, img, level ); } 792 793 /// 794 void setImages( in Image[6] imgs, uint level=0 ) 795 { 796 setImage( Side.PX, imgs[0], level ); 797 setImage( Side.NX, imgs[1], level ); 798 setImage( Side.PY, imgs[2], level ); 799 setImage( Side.NY, imgs[3], level ); 800 setImage( Side.PZ, imgs[4], level ); 801 setImage( Side.NZ, imgs[5], level ); 802 } 803 804 /// 805 void setImages( in Image img, uint width, uivec2[6] pos, 806 ImRepack[6] tr, uint level=0 ) 807 { 808 auto sssz = redimSize( 3, img.size ); 809 810 auto getRegion( uivec2 p, uint w ) 811 { 812 static if( CubeDim == 2 ) return Region!(2,uint)( p, uivec2(w) ); 813 else return Region!(3,uint)( p, sssz[2], uivec2(w), sssz[2] ); 814 } 815 816 setImage( Side.PX, imGetCopy( img, getRegion( pos[0], width ), tr[0] ), level ); 817 setImage( Side.NX, imGetCopy( img, getRegion( pos[1], width ), tr[1] ), level ); 818 setImage( Side.PY, imGetCopy( img, getRegion( pos[2], width ), tr[2] ), level ); 819 setImage( Side.NY, imGetCopy( img, getRegion( pos[3], width ), tr[3] ), level ); 820 setImage( Side.PZ, imGetCopy( img, getRegion( pos[4], width ), tr[4] ), level ); 821 setImage( Side.NZ, imGetCopy( img, getRegion( pos[5], width ), tr[5] ), level ); 822 } 823 824 /// 825 Image getImages( Type type, uint level=0 ) 826 { return getImageTrg( target, type, level ); } 827 828 /// 829 Image getImages( uint level=0 ) 830 { return getImages( ltype, level ); } 831 } 832 833 /// 834 class GLTextureCubeMap : GLTextureCubeBase!false 835 { 836 /// 837 this( uint tu ) { super( GL_TEXTURE_CUBE_MAP, tu ); } 838 839 final override const pure nothrow @nogc @property 840 { 841 /// 842 bool mipmapable() { return true; } 843 /// 844 bool isArray() { return false; } 845 /// 846 Dim imageDim() { return Dim.TWO; } 847 } 848 } 849 850 /// 851 class GLTextureCubeMapArray : GLTextureCubeBase!true 852 { 853 /// 854 this( uint tu ) { super( GL_TEXTURE_CUBE_MAP_ARRAY, tu ); } 855 856 final override const pure nothrow @nogc @property 857 { 858 /// 859 bool mipmapable() { return true; } 860 /// 861 bool isArray() { return true; } 862 /// 863 Dim imageDim() { return Dim.TWO; } 864 } 865 } 866 867 ///// 868 //abstract class GLMultisampleTexture : GLTexture 869 //{ 870 // /// 871 // this( GLenum trg, uint tu ) { super( trg, tu ); } 872 // 873 // final override const pure nothrow @nogc @property 874 // { 875 // /// 876 // bool mipmapable() { return false; } 877 // /// 878 // Dim imageDim() { return Dim.TWO; } 879 // } 880 //} 881 // 882 ///// 883 //class GLTexture2DMultisample : GLMultisampleTexture 884 //{ 885 // /// 886 // this( uint tu ) { super( GL_TEXTURE_2D_MULTISAMPLE, tu ); } 887 // 888 // final override const pure nothrow @nogc @property 889 // { 890 // /// 891 // bool isArray() { return false; } 892 // /// 893 // Dim allocDim() { return Dim.TWO; } 894 // } 895 //} 896 // 897 ///// 898 //class GLTexture2DMultisampleArray : GLMultisampleTexture 899 //{ 900 // /// 901 // this( uint tu ) { super( GL_TEXTURE_2D_MULTISAMPLE_ARRAY, tu ); } 902 // 903 // final override const pure nothrow @nogc @property 904 // { 905 // /// 906 // bool isArray() { return true; } 907 // /// 908 // Dim allocDim() { return Dim.THREE; } 909 // } 910 //}