LZScene

Форк
0
/
GLTexture.pas 
3547 строк · 96.9 Кб
1
//
2
// This unit is part of the GLScene Engine https://github.com/glscene
3
//
4
{
5
    Handles all the color and texture stuff.
6
}
7
unit GLTexture;
8

9
interface
10

11
{$I GLScene.inc}
12

13
uses
14
  Classes, SysUtils,
15

16
  GLStrings, GLCrossPlatform, GLBaseClasses, OpenGLTokens,
17
  GLVectorGeometry, GLGraphics, GLContext, GLState, GLColor, GLCoordinates,
18
  GLRenderContextInfo, GLTextureFormat, GLApplicationFileIO, GLUtils;
19

20
const
21
  cDefaultNormalMapScale = 0.125;
22

23
  CmtPX = 0;
24
  CmtNX = 1;
25
  CmtPY = 2;
26
  CmtNY = 3;
27
  CmtPZ = 4;
28
  CmtNZ = 5;
29

30
type
31
  TGLMinFilter =
32
  (
33
    miNearest,
34
    miLinear,
35
    miNearestMipmapNearest,
36
    miLinearMipmapNearest,
37
    miNearestMipmapLinear,
38
    miLinearMipmapLinear
39
  );
40

41
  TGLMagFilter = (maNearest, maLinear);
42

43
  TGLTextureMode = (tmDecal, tmModulate, tmBlend, tmReplace, tmAdd);
44
  TGLTextureWrap = (twBoth, twNone, twVertical, twHorizontal, twSeparate);
45

46
  // Specifies how depth values should be treated
47
  // during filtering and texture application
48
  TGLDepthTextureMode = (dtmLuminance, dtmIntensity, dtmAlpha);
49

50
  // Specifies the depth comparison function.
51
  TGLDepthCompareFunc = TDepthFunction;
52

53
  { Texture format for OpenGL (rendering) use.
54
  Internally, GLScene handles all "base" images as 32 Bits RGBA, but you can
55
  specify a generic format to reduce OpenGL texture memory use: }
56
  TGLTextureFormat = (
57
    tfDefault,
58
    tfRGB, // = tfRGB8
59
    tfRGBA, // = tfRGBA8
60
    tfRGB16, // = tfRGB5
61
    tfRGBA16, // = tfRGBA4
62
    tfAlpha, // = tfALPHA8
63
    tfLuminance, // = tfLUMINANCE8
64
    tfLuminanceAlpha, // = tfLUMINANCE8_ALPHA8
65
    tfIntensity, // = tfINTENSITY8
66
    tfNormalMap, // = tfRGB8
67
    tfRGBAFloat16, // = tfRGBA_FLOAT16_ATI
68
    tfRGBAFloat32, // = tfRGBA_FLOAT32_ATI
69
    tfExtended);
70

71
  // TGLTextureCompression
72
  //
73
  TGLTextureCompression = TGLInternalCompression;
74

75
  TGLTexture = class;
76

77
  IGLTextureNotifyAble = interface(IGLNotifyAble)
78
    ['{0D9DC0B0-ECE4-4513-A8A1-5AE7022C9426}']
79
    procedure NotifyTexMapChange(Sender: TObject);
80
  end;
81

82
  // TTextureNeededEvent
83
  //
84
  TTextureNeededEvent = procedure(Sender: TObject; var textureFileName: string)
85
    of object;
86

87
  TGLTextureChange = (tcImage, tcParams);
88
  TGLTextureChanges = set of TGLTextureChange;
89

90
  { Defines how and if Alpha channel is defined for a texture image. 
91
    tiaDefault : uses the alpha channel in the image if any
92
    tiaAlphaFromIntensity : the alpha channel value is deduced from other
93
    RGB components intensity (the brighter, the more opaque)
94
    tiaSuperBlackTransparent : pixels with a RGB color of (0, 0, 0) are
95
    completely transparent, others are completely opaque
96
    tiaLuminance : the luminance value is calculated for each pixel
97
    and used for RGB and Alpha values
98
    tiaLuminanceSqrt : same as tiaLuminance but with an Sqrt(Luminance)
99
        tiaOpaque : alpha channel is uniformously set to 1.0
100
        tiaTopLeftPointColorTransparent : points of the same color as the
101
          top left point of the bitmap are transparent, others are opaque.
102
        
103
    }
104
  TGLTextureImageAlpha =
105
  (
106
    tiaDefault,
107
    tiaAlphaFromIntensity,
108
    tiaSuperBlackTransparent,
109
    tiaLuminance,
110
    tiaLuminanceSqrt,
111
    tiaOpaque,
112
    tiaTopLeftPointColorTransparent,
113
    tiaInverseLuminance,
114
    tiaInverseLuminanceSqrt,
115
    tiaBottomRightPointColorTransparent
116
  );
117

118
  // TGLTextureImage
119
  //
120
  { Base class for texture image data.
121
   Basicly, subclasses are to be considered as different ways of getting
122
   a HBitmap (interfacing the actual source). 
123
   SubClasses should be registered using RegisterGLTextureImageClass to allow
124
   proper persistence and editability in the IDE experts. }
125
  TGLTextureImage = class(TGLUpdateAbleObject)
126
  private
127
    function GetResourceName: string;
128
  protected
129
    FOwnerTexture: TGLTexture;
130
    FOnTextureNeeded: TTextureNeededEvent;
131
    FResourceFile: string;
132
    class function IsSelfLoading: Boolean; virtual;
133
    procedure LoadTexture(AInternalFormat: TGLInternalFormat); virtual;
134
    function GetTextureTarget: TGLTextureTarget; virtual; abstract;
135
    function GetHeight: Integer; virtual; abstract;
136
    function GetWidth: Integer; virtual; abstract;
137
    function GetDepth: Integer; virtual; abstract;
138

139
    property OnTextureNeeded: TTextureNeededEvent read FOnTextureNeeded write
140
      FOnTextureNeeded;
141
  public
142
    { Public Properties }
143
    constructor Create(AOwner: TPersistent); override;
144
    destructor Destroy; override;
145

146
    property OwnerTexture: TGLTexture read FOwnerTexture write FOwnerTexture;
147
    procedure NotifyChange(Sender: TObject); override;
148

149
    { Save textureImage to file.
150
     This may not save a picture, but for instance, parameters, if the
151
     textureImage is a procedural texture. }
152
    procedure SaveToFile(const fileName: string); dynamic;abstract;
153
    { Load textureImage from a file.
154
     This may not load a picture, but for instance, parameters, if the
155
     textureImage is a procedural texture. 
156
             Subclasses should invoke inherited which will take care of the
157
             "OnTextureNeeded" stuff. }
158
    procedure LoadFromFile(const fileName: string); dynamic;
159
    { Returns a user-friendly denomination for the class.
160
     This denomination is used for picking a texture image class
161
     in the IDE expert. }
162
    class function FriendlyName: string; virtual;abstract;
163
    { Returns a user-friendly description for the class.
164
     This denomination is used for helping the user when picking a
165
     texture image class in the IDE expert. If it's not overriden,
166
     takes its value from FriendlyName. }
167
    class function FriendlyDescription: string; virtual;
168

169
    { Request reload/refresh of data upon next use. }
170
    procedure Invalidate; dynamic;
171

172
    { Returns image's bitmap handle.
173
     If the actual image is not a windows bitmap (BMP), descendants should
174
     take care of properly converting to bitmap. }
175
    function GetBitmap32: TGLImage; virtual; abstract;
176
    { Request for unloading bitmapData, to free some memory.
177
     This one is invoked when GLScene no longer needs the Bitmap data
178
     it got through a call to GetHBitmap. 
179
     Subclasses may ignore this call if the HBitmap was obtained at
180
     no particular memory cost. }
181
    procedure ReleaseBitmap32; virtual;
182
    //{ AsBitmap : Returns the TextureImage as a TBitmap }
183
    function AsBitmap: TGLBitmap;
184
    procedure AssignToBitmap(aBitmap: TGLBitmap);
185

186
    property Width: Integer read GetWidth;
187
    property Height: Integer read GetHeight;
188
    property Depth: Integer read GetDepth;
189
    { Native opengl texture target. }
190
    property NativeTextureTarget: TGLTextureTarget read GetTextureTarget;
191
    property ResourceName: string read GetResourceName;
192
  end;
193

194
  TGLTextureImageClass = class of TGLTextureImage;
195

196
  // TGLBlankImage
197
  //
198
  { A texture image with no specified content, only a size.
199
       This texture image type is of use if the context of your texture is
200
       calculated at run-time (with a TGLMemoryViewer for instance). }
201
  TGLBlankImage = class(TGLTextureImage)
202
  private
203
     
204
    procedure SetWidth(val: Integer);
205
    procedure SetHeight(val: Integer);
206
    procedure SetDepth(val: Integer);
207
    procedure SetCubeMap(const val: Boolean);
208
    procedure SetArray(const val: Boolean);
209
  protected
210
     
211
    fBitmap: TGLImage;
212

213
    fWidth, fHeight, fDepth: Integer;
214
    { Store a icolor format, because fBitmap is not always defined}
215
    fColorFormat: GLenum;
216
    { Blank Cube Map }
217
    fCubeMap: Boolean;
218
    { Flag to interparate depth as layer }
219
    fArray: Boolean;
220

221
    function GetWidth: Integer; override;
222
    function GetHeight: Integer; override;
223
    function GetDepth: Integer; override;
224
    function GetTextureTarget: TGLTextureTarget; override;
225
  public
226
     
227
    constructor Create(AOwner: TPersistent); override;
228
    destructor Destroy; override;
229

230
    procedure Assign(Source: TPersistent); override;
231

232
    function GetBitmap32: TGLImage; override;
233
    procedure ReleaseBitmap32; override;
234

235
    procedure SaveToFile(const fileName: string); override;
236
    procedure LoadFromFile(const fileName: string); override;
237
    class function FriendlyName: string; override;
238
    class function FriendlyDescription: string; override;
239

240
  published
241
     
242
    { Width, heigth and depth of the blank image (for memory allocation). }
243
    property Width: Integer read GetWidth write SetWidth default 256;
244
    property Height: Integer read GetHeight write SetHeight default 256;
245
    property Depth: Integer read GetDepth write SetDepth default 0;
246
    property CubeMap: Boolean read fCubeMap write SetCubeMap default false;
247
    property TextureArray: Boolean read fArray write SetArray default false;
248
    property ColorFormat: GLenum read fColorFormat write fColorFormat;
249
  end;
250

251
  // TGLPictureImage
252
  //
253
  { Base class for image data classes internally based on a TPicture. }
254
  TGLPictureImage = class(TGLTextureImage)
255
  private
256
     
257
    FBitmap: TGLImage;
258
    FGLPicture: TGLPicture;
259
    FUpdateCounter: Integer;
260

261
  protected
262
     
263
    function GetHeight: Integer; override;
264
    function GetWidth: Integer; override;
265
    function GetDepth: Integer; override;
266
    function GetTextureTarget: TGLTextureTarget; override;
267

268
    function GetPicture: TGLPicture;
269
    procedure SetPicture(const aPicture: TGLPicture);
270
    procedure PictureChanged(Sender: TObject);
271

272
  public
273
     
274
    constructor Create(AOwner: TPersistent); override;
275
    destructor Destroy; override;
276

277
    procedure Assign(Source: TPersistent); override;
278

279
    { Use this function if you are going to modify the Picture directly.
280
     Each invokation MUST be balanced by a call to EndUpdate. }
281
    procedure BeginUpdate;
282
    { Ends a direct picture modification session.
283
       Follows a BeginUpdate. }
284
    procedure EndUpdate;
285
    function GetBitmap32: TGLImage; override;
286
    procedure ReleaseBitmap32; override;
287

288
    { Holds the image content. }
289
    property Picture: TGLPicture read GetPicture write SetPicture;
290
  end;
291

292
  // TGLPersistentImage
293
  //
294
  { Stores any image compatible with Delphi's TPicture mechanism.
295
   The picture's data is actually stored into the DFM, the original
296
   picture name or path is not remembered. It is similar in behaviour
297
   to Delphi's TImage.
298
   Note that if original image is for instance JPEG format, only the JPEG
299
   data will be stored in the DFM (compact) }
300
  TGLPersistentImage = class(TGLPictureImage)
301
  private
302

303
  public
304
     
305
    constructor Create(AOwner: TPersistent); override;
306
    destructor Destroy; override;
307

308
    procedure SaveToFile(const fileName: string); override;
309
    procedure LoadFromFile(const fileName: string); override;
310
    class function FriendlyName: string; override;
311
    class function FriendlyDescription: string; override;
312
    property NativeTextureTarget;
313
  published
314
     
315
    property Picture;
316
  end;
317

318
  // TGLPicFileImage
319
  //
320
  { Uses a picture whose data is found in a file (only filename is stored).
321
       The image is unloaded after upload to OpenGL. }
322
  TGLPicFileImage = class(TGLPictureImage)
323
  private
324
    FPictureFileName: string;
325
    FAlreadyWarnedAboutMissingFile: Boolean;
326
    FWidth: Integer;
327
    FHeight: Integer;
328

329
  protected
330
    procedure SetPictureFileName(const val: string);
331
    function GetWidth: Integer; override;
332
    function GetHeight: Integer; override;
333
    function GetDepth: Integer; override;
334

335
  public
336
     
337
    constructor Create(AOwner: TPersistent); override;
338
    destructor Destroy; override;
339

340
    procedure Assign(Source: TPersistent); override;
341

342
    // Only picture file name is saved
343
    procedure SaveToFile(const fileName: string); override;
344
    { Load picture file name or use fileName as picture filename.
345
       The autodetection is based on the filelength and presence of zeros. }
346
    procedure LoadFromFile(const fileName: string); override;
347
    class function FriendlyName: string; override;
348
    class function FriendlyDescription: string; override;
349
    property NativeTextureTarget;
350

351
    function GetBitmap32: TGLImage; override;
352
    procedure Invalidate; override;
353

354
  published
355
    { Filename of the picture to use. }
356
    property PictureFileName: string read FPictureFileName write
357
      SetPictureFileName;
358
  end;
359

360

361
  // TGLCubeMapTarget
362
  //
363
 TGLCubeMapTarget = Integer;
364

365
  // TGLCubeMapImage
366
  //
367
  { A texture image used for specifying and stroing a cube map.
368
       Not unlike TGLPictureImage, but storing 6 of them instead of just one. 
369
       Saving & loading as a whole currently not supported. }
370
  TGLCubeMapImage = class(TGLTextureImage)
371
  private
372
     
373
    FImage: TGLImage;
374
    FUpdateCounter: Integer;
375
    FPicture: array[cmtPX..cmtNZ] of TGLPicture;
376
  protected
377
     
378
    function GetWidth: Integer; override;
379
    function GetHeight: Integer; override;
380
    function GetDepth: Integer; override;
381
    procedure SetPicture(index: TGLCubeMapTarget; const val: TGLPicture);
382
    function GetPicture(index: TGLCubeMapTarget): TGLPicture;
383
    function GetTextureTarget: TGLTextureTarget; override;
384

385
    procedure PictureChanged(Sender: TObject);
386

387
  public
388
     
389
    constructor Create(AOwner: TPersistent); override;
390
    destructor Destroy; override;
391

392
    procedure Assign(Source: TPersistent); override;
393

394
    function GetBitmap32: TGLImage; override;
395
    procedure ReleaseBitmap32; override;
396

397
    { Use this function if you are going to modify the Picture directly.
398
     Each invokation MUST be balanced by a call to EndUpdate. }
399
    procedure BeginUpdate;
400
    procedure EndUpdate;
401

402
    procedure SaveToFile(const fileName: string); override;
403
    procedure LoadFromFile(const fileName: string); override;
404
    class function FriendlyName: string; override;
405
    class function FriendlyDescription: string; override;
406
    property NativeTextureTarget;
407

408
    { Indexed access to the cube map's sub pictures. }
409
    property Picture[index: TGLCubeMapTarget]: TGLPicture read GetPicture write
410
    SetPicture;
411

412
  published
413
     
414
    property PicturePX: TGLPicture index cmtPX read GetPicture write SetPicture;
415
    property PictureNX: TGLPicture index cmtNX read GetPicture write SetPicture;
416
    property PicturePY: TGLPicture index cmtPY read GetPicture write SetPicture;
417
    property PictureNY: TGLPicture index cmtNY read GetPicture write SetPicture;
418
    property PicturePZ: TGLPicture index cmtPZ read GetPicture write SetPicture;
419
    property PictureNZ: TGLPicture index cmtNZ read GetPicture write SetPicture;
420
  end;
421

422
  // TGLTextureMappingMode
423
  //
424
  TGLTextureMappingMode = (tmmUser, tmmObjectLinear, tmmEyeLinear, tmmSphere,
425
    tmmCubeMapReflection, tmmCubeMapNormal,
426
    tmmCubeMapLight0, tmmCubeMapCamera);
427

428
  // TGLTexture
429
  //
430
    { Defines basic texturing properties.
431
       You can control texture wrapping, smoothing/filtering and of course define
432
       the texture map (note that texturing is disabled by default).
433
       A built-in mechanism (through ImageAlpha) allows auto-generation of an
434
       Alpha channel for all bitmaps (see TGLTextureImageAlpha). }
435
  TGLTexture = class(TGLUpdateAbleObject)
436
  private
437
     
438
    FTextureHandle: TGLTextureHandle;
439
    FSamplerHandle: TGLVirtualHandle;
440
    FTextureFormat: TGLInternalFormat;
441
    FTextureMode: TGLTextureMode;
442
    FTextureWrap: TGLTextureWrap;
443
    FMinFilter: TGLMinFilter;
444
    FMagFilter: TGLMagFilter;
445
    FDisabled: Boolean;
446
    FImage: TGLTextureImage;
447
    FImageAlpha: TGLTextureImageAlpha;
448
    FImageBrightness: Single;
449
    FImageGamma: Single;
450
    FMappingMode: TGLTextureMappingMode;
451
    FMapSCoordinates: TGLCoordinates4;
452
    FMapTCoordinates: TGLCoordinates4;
453
    FMapRCoordinates: TGLCoordinates4;
454
    FMapQCoordinates: TGLCoordinates4;
455
    FOnTextureNeeded: TTextureNeededEvent;
456
    FCompression: TGLTextureCompression;
457
    FRequiredMemorySize: Integer;
458
    FFilteringQuality: TGLTextureFilteringQuality;
459
    FTexWidth: Integer;
460
    FTexHeight: Integer;
461
    FTexDepth: Integer;
462
    FEnvColor: TGLColor;
463
    FBorderColor: TGLColor;
464
    FNormalMapScale: Single;
465
    FTextureWrapS: TGLSeparateTextureWrap;
466
    FTextureWrapT: TGLSeparateTextureWrap;
467
    FTextureWrapR: TGLSeparateTextureWrap;
468
    fTextureCompareMode: TGLTextureCompareMode;
469
    fTextureCompareFunc: TGLDepthCompareFunc;
470
    fDepthTextureMode: TGLDepthTextureMode;
471
    FKeepImageAfterTransfer: Boolean;
472
  protected
473
     
474
    procedure SetImage(AValue: TGLTextureImage);
475
    procedure SetImageAlpha(const val: TGLTextureImageAlpha);
476
    procedure SetImageBrightness(const val: Single);
477
    function StoreBrightness: Boolean;
478
    procedure SetImageGamma(const val: Single);
479
    function StoreGamma: Boolean;
480
    procedure SetMagFilter(AValue: TGLMagFilter);
481
    procedure SetMinFilter(AValue: TGLMinFilter);
482
    procedure SetTextureMode(AValue: TGLTextureMode);
483
    procedure SetTextureWrap(AValue: TGLTextureWrap);
484
    procedure SetTextureWrapS(AValue: TGLSeparateTextureWrap);
485
    procedure SetTextureWrapT(AValue: TGLSeparateTextureWrap);
486
    procedure SetTextureWrapR(AValue: TGLSeparateTextureWrap);
487
    function GetTextureFormat: TGLTextureFormat;
488
    procedure SetTextureFormat(const val: TGLTextureFormat);
489
    procedure SetTextureFormatEx(const val: TGLInternalFormat);
490
    function StoreTextureFormatEx: Boolean;
491
    procedure SetCompression(const val: TGLTextureCompression);
492
    procedure SetFilteringQuality(const val: TGLTextureFilteringQuality);
493
    procedure SetMappingMode(const val: TGLTextureMappingMode);
494
    function GetMappingSCoordinates: TGLCoordinates4;
495
    procedure SetMappingSCoordinates(const val: TGLCoordinates4);
496
    function StoreMappingSCoordinates: Boolean;
497
    function GetMappingTCoordinates: TGLCoordinates4;
498
    procedure SetMappingTCoordinates(const val: TGLCoordinates4);
499
    function StoreMappingTCoordinates: Boolean;
500
    function GetMappingRCoordinates: TGLCoordinates4;
501
    procedure SetMappingRCoordinates(const val: TGLCoordinates4);
502
    function StoreMappingRCoordinates: Boolean;
503
    function GetMappingQCoordinates: TGLCoordinates4;
504
    procedure SetMappingQCoordinates(const val: TGLCoordinates4);
505
    function StoreMappingQCoordinates: Boolean;
506
    procedure SetDisabled(AValue: Boolean);
507
    procedure SetEnabled(const val: Boolean);
508
    function GetEnabled: Boolean;
509
    procedure SetEnvColor(const val: TGLColor);
510
    procedure SetBorderColor(const val: TGLColor);
511
    procedure SetNormalMapScale(const val: Single);
512
    procedure SetTextureCompareMode(const val: TGLTextureCompareMode);
513
    procedure SetTextureCompareFunc(const val: TGLDepthCompareFunc);
514
    procedure SetDepthTextureMode(const val: TGLDepthTextureMode);
515
    function StoreNormalMapScale: Boolean;
516

517
    function StoreImageClassName: Boolean;
518

519
    function GetHandle: TGLuint; virtual;
520
    // Load texture to OpenGL subsystem
521
    procedure PrepareImage(target: TGLUInt); virtual;
522
    // Setup OpenGL texture parameters
523
    procedure PrepareParams(target: TGLUInt); virtual;
524

525
    procedure DoOnTextureNeeded(Sender: TObject; var textureFileName: string);
526
    procedure OnSamplerAllocate(Sender: TGLVirtualHandle; var Handle: Cardinal);
527
    procedure OnSamplerDestroy(Sender: TGLVirtualHandle; var Handle: Cardinal);
528
    // Shows a special image that indicates an error
529
    procedure SetTextureErrorImage;
530
  public
531
     
532
    constructor Create(AOwner: TPersistent); override;
533
    destructor Destroy; override;
534

535
    property OnTextureNeeded: TTextureNeededEvent read FOnTextureNeeded write
536
      FOnTextureNeeded;
537

538
    procedure PrepareBuildList;
539
    procedure ApplyMappingMode;
540
    procedure UnApplyMappingMode;
541
    procedure Apply(var rci: TGLRenderContextInfo);
542
    procedure UnApply(var rci: TGLRenderContextInfo);
543
    { Applies to TEXTURE1 }
544
    procedure ApplyAsTexture2(var rci: TGLRenderContextInfo; textureMatrix: PMatrix
545
      = nil);
546
    procedure UnApplyAsTexture2(var rci: TGLRenderContextInfo;
547
      reloadIdentityTextureMatrix: boolean);
548
    { N=1 for TEXTURE0, N=2 for TEXTURE1, etc. }
549
    procedure ApplyAsTextureN(n: Integer; var rci: TGLRenderContextInfo;
550
      textureMatrix: PMatrix = nil);
551
    procedure UnApplyAsTextureN(n: Integer; var rci: TGLRenderContextInfo;
552
      reloadIdentityTextureMatrix: boolean);
553

554
    procedure Assign(Source: TPersistent); override;
555
    procedure NotifyChange(Sender: TObject); override;
556
    procedure NotifyImageChange;
557
    procedure NotifyParamsChange;
558

559
    procedure DestroyHandles;
560

561
    procedure SetImageClassName(const val: string);
562
    function GetImageClassName: string;
563

564
    { Returns the OpenGL memory used by the texture.
565
      The compressed size is returned if, and only if texture compression
566
      if active and possible, and the texture has been allocated (Handle
567
      is defined), otherwise the estimated size (from TextureFormat
568
      specification) is returned. }
569
    function TextureImageRequiredMemory: Integer;
570
    { Allocates the texture handle if not already allocated.
571
      The texture is binded and parameters are setup, but no image data
572
      is initialized by this call - for expert use only. }
573
    function AllocateHandle: TGLuint;
574
    function IsHandleAllocated: Boolean;
575
    { Returns OpenGL texture format corresponding to current options. }
576
    function OpenGLTextureFormat: Integer;
577
    { Returns if of float data type}
578
    function IsFloatType: Boolean;
579
    { Is the texture enabled?.
580
      Always equals to 'not Disabled'. }
581
    property Enabled: Boolean read GetEnabled write SetEnabled;
582
    { Handle to the OpenGL texture object.
583
      If the handle hasn't already been allocated, it will be allocated
584
      by this call (ie. do not use if no OpenGL context is active!) }
585
    property Handle: TGLuint read GetHandle;
586
    property TextureHandle: TGLTextureHandle read FTextureHandle;
587

588
    { Actual width, height and depth used for last texture
589
      specification binding. }
590
    property TexWidth: Integer read FTexWidth;
591
    property TexHeight: Integer read FTexHeight;
592
    property TexDepth: Integer read FTexDepth;
593
    { Give texture rendering context }
594
  published
595
     
596

597
    { Image ClassName for enabling True polymorphism.
598
    This is ugly, but since the default streaming mechanism does a
599
    really bad job at storing	polymorphic owned-object properties,
600
    and neither TFiler nor TPicture allow proper use of the built-in
601
    streaming, that's the only way I found to allow a user-extensible
602
    mechanism. }
603
    property ImageClassName: string read GetImageClassName write
604
      SetImageClassName stored StoreImageClassName;
605
    { Image data for the texture. }
606
    property Image: TGLTextureImage read FImage write SetImage;
607

608
    { Automatic Image Alpha setting.
609
    Allows to control how and if the image's Alpha channel (transparency)
610
    is computed. }
611
    property ImageAlpha: TGLTextureImageAlpha read FImageAlpha write
612
      SetImageAlpha default tiaDefault;
613
    { Texture brightness correction.
614
    This correction is applied upon loading a TGLTextureImage, it's a
615
    simple saturating scaling applied to the RGB components of
616
    the 32 bits image, before it is passed to OpenGL, and before
617
    gamma correction (if any). }
618
    property ImageBrightness: Single read FImageBrightness write
619
      SetImageBrightness stored StoreBrightness;
620
    { Texture gamma correction.
621
    The gamma correction is applied upon loading a TGLTextureImage,
622
    applied to the RGB components of the 32 bits image, before it is
623
    passed to OpenGL, after brightness correction (if any). }
624
    property ImageGamma: Single read FImageGamma write SetImageGamma stored
625
      StoreGamma;
626

627
    { Texture magnification filter. }
628
    property MagFilter: TGLMagFilter read FMagFilter write SetMagFilter default
629
      maLinear;
630
    { Texture minification filter. }
631
    property MinFilter: TGLMinFilter read FMinFilter write SetMinFilter default
632
      miLinearMipMapLinear;
633
    { Texture application mode. }
634
    property TextureMode: TGLTextureMode read FTextureMode write SetTextureMode
635
      default tmDecal;
636
    { Wrapping mode for the texture. }
637
    property TextureWrap: TGLTextureWrap read FTextureWrap write SetTextureWrap
638
      default twBoth;
639
    { Wrapping mode for the texture when TextureWrap=twSeparate. }
640
    property TextureWrapS: TGLSeparateTextureWrap read FTextureWrapS write
641
      SetTextureWrapS default twRepeat;
642
    property TextureWrapT: TGLSeparateTextureWrap read FTextureWrapT write
643
      SetTextureWrapT default twRepeat;
644
    property TextureWrapR: TGLSeparateTextureWrap read FTextureWrapR write
645
      SetTextureWrapR default twRepeat;
646

647
    { Texture format for use by the renderer.
648
    See TGLTextureFormat for details. }
649
    property TextureFormat: TGLTextureFormat read GetTextureFormat write
650
      SetTextureFormat default tfDefault;
651
    property TextureFormatEx: TGLInternalFormat read FTextureFormat write
652
      SetTextureFormatEx stored StoreTextureFormatEx;
653

654
    { Texture compression control.
655
    If True the compressed TextureFormat variant (the OpenGL ICD must
656
    support GL_ARB_texture_compression, or this option is ignored). }
657
    property Compression: TGLTextureCompression read FCompression write
658
      SetCompression default tcDefault;
659
    { Specifies texture filtering quality.
660
    You can choose between bilinear and trilinear filetring (anisotropic).
661
    The OpenGL ICD must support GL_EXT_texture_filter_anisotropic or
662
    this property is ignored. }
663
    property FilteringQuality: TGLTextureFilteringQuality read FFilteringQuality
664
      write SetFilteringQuality default tfIsotropic;
665

666
    { Texture coordinates mapping mode.
667
    This property controls automatic texture coordinates generation. }
668
    property MappingMode: TGLTextureMappingMode read FMappingMode write
669
      SetMappingMode default tmmUser;
670
    { Texture mapping coordinates mode for S, T, R and Q axis.
671
    This property stores the coordinates for automatic texture
672
    coordinates generation. }
673
    property MappingSCoordinates: TGLCoordinates4 read GetMappingSCoordinates
674
      write SetMappingSCoordinates stored StoreMappingSCoordinates;
675
    property MappingTCoordinates: TGLCoordinates4 read GetMappingTCoordinates
676
      write SetMappingTCoordinates stored StoreMappingTCoordinates;
677
    property MappingRCoordinates: TGLCoordinates4 read GetMappingRCoordinates
678
      write SetMappingRCoordinates stored StoreMappingRCoordinates;
679
    property MappingQCoordinates: TGLCoordinates4 read GetMappingQCoordinates
680
      write SetMappingQCoordinates stored StoreMappingQCoordinates;
681

682
    { Texture Environment color. }
683
    property EnvColor: TGLColor read FEnvColor write SetEnvColor;
684
    { Texture Border color. }
685
    property BorderColor: TGLColor read FBorderColor write SetBorderColor;
686
    { If true, the texture is disabled (not used). }
687
    property Disabled: Boolean read FDisabled write SetDisabled default True;
688

689
    { Normal Map scaling.
690
    Only applies when TextureFormat is tfNormalMap, this property defines
691
    the scaling that is applied during normal map generation (ie. controls
692
    the intensity of the bumps). }
693
    property NormalMapScale: Single read FNormalMapScale write SetNormalMapScale
694
      stored StoreNormalMapScale;
695

696
    property TextureCompareMode: TGLTextureCompareMode read fTextureCompareMode
697
      write SetTextureCompareMode default tcmNone;
698
    property TextureCompareFunc: TGLDepthCompareFunc read fTextureCompareFunc
699
      write SetTextureCompareFunc default cfLequal;
700
    property DepthTextureMode: TGLDepthTextureMode read fDepthTextureMode write
701
      SetDepthTextureMode default dtmLuminance;
702

703
    { Disable image release after transfering it to VGA. }
704
    property KeepImageAfterTransfer: Boolean read FKeepImageAfterTransfer
705
      write FKeepImageAfterTransfer default False;
706
  end;
707

708
  // TGLTextureExItem
709
  //
710
  TGLTextureExItem = class(TCollectionItem, IGLTextureNotifyAble)
711
  private
712
    { Private Decalarations }
713
    FTexture: TGLTexture;
714
    FTextureIndex: Integer;
715
    FTextureOffset, FTextureScale: TGLCoordinates;
716
    FTextureMatrixIsIdentity: Boolean;
717
    FTextureMatrix: TMatrix;
718
    FApplied: Boolean;
719

720
    //implementing IInterface
721

722

723
      function QueryInterface(constref IID: TGUID; out Obj): HResult; {$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
724
      function _AddRef: Integer; {$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
725
      function _Release: Integer; {$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
726

727
  protected
728
    { Protected Decalarations }
729
    function GetDisplayName: string; override;
730
    function GetOwner: TPersistent; override;
731
    procedure SetTexture(const Value: TGLTexture);
732
    procedure SetTextureIndex(const Value: Integer);
733
    procedure SetTextureOffset(const Value: TGLCoordinates);
734
    procedure SetTextureScale(const Value: TGLCoordinates);
735
    procedure NotifyTexMapChange(Sender: TObject);
736

737
    procedure CalculateTextureMatrix;
738

739
    procedure OnNotifyChange(Sender: TObject);
740

741
  public
742
    { Public Decalarations }
743
    constructor Create(ACollection: TCollection); override;
744
    destructor Destroy; override;
745

746
    procedure Assign(Source: TPersistent); override;
747
    procedure NotifyChange(Sender: TObject);
748

749
    procedure Apply(var rci: TGLRenderContextInfo);
750
    procedure UnApply(var rci: TGLRenderContextInfo);
751

752
  published
753
    { Published Decalarations }
754
    property Texture: TGLTexture read FTexture write SetTexture;
755
    property TextureIndex: Integer read FTextureIndex write SetTextureIndex;
756
    property TextureOffset: TGLCoordinates read FTextureOffset write
757
      SetTextureOffset;
758
    property TextureScale: TGLCoordinates read FTextureScale write
759
      SetTextureScale;
760

761
  end;
762

763
  // TGLTextureEx
764
  //
765
  TGLTextureEx = class(TCollection)
766
  private
767
    FOwner: TGLUpdateAbleObject;
768

769
  protected
770
    { Protected Decalarations }
771
    procedure SetItems(index: Integer; const Value: TGLTextureExItem);
772
    function GetItems(index: Integer): TGLTextureExItem;
773
    function GetOwner: TPersistent; override;
774
  public
775
    { Public Decalarations }
776
    constructor Create(AOwner: TGLUpdateAbleObject);
777

778
    procedure NotifyChange(Sender: TObject);
779
    procedure Apply(var rci: TGLRenderContextInfo);
780
    procedure UnApply(var rci: TGLRenderContextInfo);
781
    function IsTextureEnabled(Index: Integer): Boolean;
782

783
    function Add: TGLTextureExItem;
784

785
    property Items[index: Integer]: TGLTextureExItem read GetItems write
786
    SetItems; default;
787
    procedure Loaded;
788
  end;
789

790
  ETexture = class(Exception);
791
  EGLShaderException = class(Exception);
792

793
  // Register a TGLTextureImageClass (used for persistence and IDE purposes)
794
procedure RegisterGLTextureImageClass(textureImageClass: TGLTextureImageClass);
795
// Finds a registerer TGLTextureImageClass using its classname
796
function FindGLTextureImageClass(const className: string): TGLTextureImageClass;
797
// Finds a registerer TGLTextureImageClass using its FriendlyName
798
function FindGLTextureImageClassByFriendlyName(const friendlyName: string):
799
  TGLTextureImageClass;
800
// Defines a TStrings with the list of registered TGLTextureImageClass.
801
procedure SetGLTextureImageClassesToStrings(aStrings: TStrings);
802
{ Creates a TStrings with the list of registered TGLTextureImageClass.
803
 To be freed by caller. }
804
function GetGLTextureImageClassesAsStrings: TStrings;
805

806
procedure RegisterTGraphicClassFileExtension(const extension: string;
807
  const aClass: TGraphicClass);
808
function CreateGraphicFromFile(const fileName: string): TGLGraphic;
809

810
//------------------------------------------------------------------------------
811
//------------------------------------------------------------------------------
812
//------------------------------------------------------------------------------
813
implementation
814
//------------------------------------------------------------------------------
815
//------------------------------------------------------------------------------
816
//------------------------------------------------------------------------------
817

818
// TODO: remove dependancy on GLScene.pas unit (related to tmmCubeMapLight0)
819

820
uses
821
  GLScene,
822
  XOpenGL,
823
  PictureRegisteredFormats
824
  , GLVectorTypes;
825

826
const
827
  cTextureMode: array[tmDecal..tmAdd] of TGLEnum =
828
    (GL_DECAL, GL_MODULATE, GL_BLEND, GL_REPLACE, GL_ADD);
829

830
  cOldTextureFormatToInternalFormat: array[tfRGB..tfRGBAFloat32] of
831
    TGLInternalFormat = (
832
    tfRGB8,
833
    tfRGBA8,
834
    tfRGB5,
835
    tfRGBA4,
836
    tfALPHA8,
837
    tfLUMINANCE8,
838
    tfLUMINANCE8_ALPHA8,
839
    tfINTENSITY8,
840
    tfRGB8,
841
    tfRGBA_FLOAT16,
842
    tfRGBA_FLOAT32);
843

844
var
845
  vGLTextureImageClasses: TList;
846
  vTGraphicFileExtension: array of string;
847
  vTGraphicClass: array of TGraphicClass;
848

849
type
850
  TFriendlyImage = class(TGLBaseImage);
851

852

853

854
{%region%=====  'Helper functions ================================}
855

856
  // RegisterTGraphicClassFileExtension
857
  //
858

859
procedure RegisterTGraphicClassFileExtension(const extension: string;
860
  const aClass: TGraphicClass);
861
var
862
  n: Integer;
863
begin
864
  n := Length(vTGraphicFileExtension);
865
  SetLength(vTGraphicFileExtension, n + 1);
866
  SetLength(vTGraphicClass, n + 1);
867
  vTGraphicFileExtension[n] := LowerCase(extension);
868
  vTGraphicClass[n] := aClass;
869
end;
870

871
// CreateGraphicFromFile
872
//
873

874
function CreateGraphicFromFile(const fileName: string): TGLGraphic;
875
var
876
  i: Integer;
877
  ext: string;
878
  fs: TStream;
879
  graphicClass: TGraphicClass;
880
begin
881
  Result := nil;
882
  if FileStreamExists(fileName) then
883
  begin
884
    graphicClass := nil;
885
    ext := LowerCase(ExtractFileExt(fileName));
886
    for i := 0 to High(vTGraphicFileExtension) do
887
    begin
888
      if vTGraphicFileExtension[i] = ext then
889
      begin
890
        graphicClass := TGraphicClass(vTGraphicClass[i]);
891
        Break;
892
      end;
893
    end;
894
    if graphicClass = nil then
895
      graphicClass := GraphicClassForExtension(ext);
896
    if graphicClass <> nil then
897
    begin
898
      Result := graphicClass.Create;
899
      try
900
        fs := CreateFileStream(fileName, fmOpenRead);
901
        try
902
          Result.LoadFromStream(fs);
903
        finally
904
          fs.Free;
905
        end;
906
      except
907
        FreeAndNil(Result);
908
        raise;
909
      end;
910
    end;
911
  end;
912
end;
913

914
// RegisterGLTextureImageClass
915
//
916

917
procedure RegisterGLTextureImageClass(textureImageClass: TGLTextureImageClass);
918
begin
919
  if not Assigned(vGLTextureImageClasses) then
920
    vGLTextureImageClasses := TList.Create;
921
  vGLTextureImageClasses.Add(textureImageClass);
922
end;
923

924
// FindGLTextureImageClass
925
//
926

927
function FindGLTextureImageClass(const className: string): TGLTextureImageClass;
928
var
929
  i: Integer;
930
  tic: TGLTextureImageClass;
931
begin
932
  Result := nil;
933
  if Assigned(vGLTextureImageClasses) then
934
    for i := 0 to vGLTextureImageClasses.Count - 1 do
935
    begin
936
      tic := TGLTextureImageClass(vGLTextureImageClasses[i]);
937
      if tic.ClassName = className then
938
      begin
939
        Result := tic;
940
        Break;
941
      end;
942
    end;
943

944
end;
945

946
// FindGLTextureImageClassByFriendlyName
947
//
948

949
function FindGLTextureImageClassByFriendlyName(const friendlyName: string):
950
  TGLTextureImageClass;
951
var
952
  i: Integer;
953
  tic: TGLTextureImageClass;
954
begin
955
  Result := nil;
956
  if Assigned(vGLTextureImageClasses) then
957
    for i := 0 to vGLTextureImageClasses.Count - 1 do
958
    begin
959
      tic := TGLTextureImageClass(vGLTextureImageClasses[i]);
960
      if tic.FriendlyName = friendlyName then
961
      begin
962
        Result := tic;
963
        Break;
964
      end;
965
    end;
966
end;
967

968
// SetGLTextureImageClassesToStrings
969
//
970

971
procedure SetGLTextureImageClassesToStrings(aStrings: TStrings);
972
var
973
  i: Integer;
974
  tic: TGLTextureImageClass;
975
begin
976
  with aStrings do
977
  begin
978
    BeginUpdate;
979
    Clear;
980
    if Assigned(vGLTextureImageClasses) then
981
      for i := 0 to vGLTextureImageClasses.Count - 1 do
982
      begin
983
        tic := TGLTextureImageClass(vGLTextureImageClasses[i]);
984
        AddObject(tic.FriendlyName, TObject(Pointer(tic)));
985
      end;
986
    EndUpdate;
987
  end;
988
end;
989

990
// GetGLTextureImageClassesAsStrings
991
//
992

993
function GetGLTextureImageClassesAsStrings: TStrings;
994
begin
995
  Result := TStringList.Create;
996
  SetGLTextureImageClassesToStrings(Result);
997
end;
998

999
{%endregion%}
1000

1001
{%region%=====  'TGLTextureImage ================================}
1002

1003
// Create
1004
//
1005

1006
constructor TGLTextureImage.Create(AOwner: TPersistent);
1007
begin
1008
  inherited;
1009
  FOwnerTexture := (AOwner as TGLTexture);
1010
end;
1011

1012
// Destroy
1013
//
1014

1015
destructor TGLTextureImage.Destroy;
1016
begin
1017
  inherited Destroy;
1018
end;
1019

1020
// FriendlyDescription
1021
//
1022

1023
class function TGLTextureImage.FriendlyDescription: string;
1024
begin
1025
  Result := FriendlyName;
1026
end;
1027

1028
procedure TGLTextureImage.Invalidate;
1029
begin
1030
  ReleaseBitmap32;
1031
  NotifyChange(Self);
1032
end;
1033

1034
// ReleaseBitmap32
1035
//
1036

1037
procedure TGLTextureImage.ReleaseBitmap32;
1038
begin
1039
  // nothing here.
1040
end;
1041

1042
// AsBitmap : Returns the TextureImage as a TBitmap
1043
// WARNING: This Creates a new bitmap. Remember to free it, to prevent leaks.
1044
// If possible, rather use AssignToBitmap.
1045
//
1046

1047
function TGLTextureImage.AsBitmap: TGLBitmap;
1048
begin
1049
  result := self.GetBitmap32.Create32BitsBitmap;
1050
end;
1051

1052
// AssignToBitmap
1053
//
1054

1055
procedure TGLTextureImage.AssignToBitmap(aBitmap: TGLBitmap);
1056
begin
1057
  Self.GetBitmap32.AssignToBitmap(aBitmap);
1058
end;
1059

1060
// NotifyChange
1061
//
1062

1063
procedure TGLTextureImage.NotifyChange(Sender: TObject);
1064
begin
1065
  if Assigned(FOwnerTexture) then
1066
  begin
1067
    FOwnerTexture.FTextureHandle.NotifyChangesOfData;
1068
    FOwnerTexture.FSamplerHandle.NotifyChangesOfData;
1069
    // Check for texture target change
1070
    GetTextureTarget;
1071
    FOwnerTexture.NotifyChange(Self);
1072
  end;
1073
end;
1074

1075
 
1076
//
1077

1078
procedure TGLTextureImage.LoadFromFile(const fileName: string);
1079
var
1080
  buf: string;
1081
begin
1082
  if Assigned(FOnTextureNeeded) then
1083
  begin
1084
    buf := fileName;
1085
    FOnTextureNeeded(Self, buf);
1086
  end;
1087
end;
1088

1089
// GetResourceFile
1090
//
1091

1092
function TGLTextureImage.GetResourceName: string;
1093
begin
1094
  Result := FResourceFile;
1095
end;
1096

1097
class function TGLTextureImage.IsSelfLoading: Boolean;
1098
begin
1099
  Result := False;
1100
end;
1101

1102
procedure TGLTextureImage.LoadTexture(AInternalFormat: TGLInternalFormat);
1103
begin
1104
end;
1105

1106
{%endregion%}
1107

1108
{%region%=====  'TGLBlankImage ================================}
1109

1110

1111
constructor TGLBlankImage.Create(AOwner: TPersistent);
1112
begin
1113
  inherited;
1114
  fWidth := 256;
1115
  fHeight := 256;
1116
  fDepth := 0;
1117
  fColorFormat := GL_RGBA;
1118
end;
1119

1120
destructor TGLBlankImage.Destroy;
1121
begin
1122
  ReleaseBitmap32;
1123
  inherited Destroy;
1124
end;
1125

1126
procedure TGLBlankImage.Assign(Source: TPersistent);
1127
var
1128
  img: TGLBlankImage;
1129
begin
1130
  if Assigned(Source) then
1131
  begin
1132
    if (Source is TGLBlankImage) then
1133
    begin
1134
      img := Source as TGLBlankImage;
1135
      FWidth := img.Width;
1136
      FHeight := img.Height;
1137
      FDepth := img.Depth;
1138
      FCubeMap := img.fCubeMap;
1139
      FArray := img.fArray;
1140
      fColorFormat := img.ColorFormat;
1141
      FResourceFile := img.ResourceName;
1142
      Invalidate;
1143
    end
1144
    else
1145
      GetBitmap32.Assign(Source);
1146
    NotifyChange(Self);
1147
  end
1148
  else
1149
    inherited;
1150
end;
1151

1152
procedure TGLBlankImage.SetWidth(val: Integer);
1153
begin
1154
  if val <> FWidth then
1155
  begin
1156
    FWidth := val;
1157
    if FWidth < 1 then
1158
      FWidth := 1;
1159
    Invalidate;
1160
  end;
1161
end;
1162

1163
function TGLBlankImage.GetWidth: Integer;
1164
begin
1165
  Result := FWidth;
1166
end;
1167

1168
procedure TGLBlankImage.SetHeight(val: Integer);
1169
begin
1170
  if val <> FHeight then
1171
  begin
1172
    FHeight := val;
1173
    if FHeight < 1 then
1174
      FHeight := 1;
1175
    Invalidate;
1176
  end;
1177
end;
1178

1179
function TGLBlankImage.GetHeight: Integer;
1180
begin
1181
  Result := FHeight;
1182
end;
1183

1184
procedure TGLBlankImage.SetDepth(val: Integer);
1185
begin
1186
  if val <> FDepth then
1187
  begin
1188
    FDepth := val;
1189
    if FDepth < 0 then
1190
      FDepth := 0;
1191
    Invalidate;
1192
  end;
1193
end;
1194

1195
function TGLBlankImage.GetDepth: Integer;
1196
begin
1197
  Result := fDepth;
1198
end;
1199

1200
procedure TGLBlankImage.SetCubeMap(const val: Boolean);
1201
begin
1202
  if val <> fCubeMap then
1203
  begin
1204
    fCubeMap := val;
1205
    Invalidate;
1206
  end;
1207
end;
1208

1209
procedure TGLBlankImage.SetArray(const val: Boolean);
1210
begin
1211
  if val <> fArray then
1212
  begin
1213
    fArray := val;
1214
    Invalidate;
1215
  end;
1216
end;
1217

1218
function TGLBlankImage.GetBitmap32: TGLImage;
1219
begin
1220
  if not Assigned(FBitmap) then
1221
  begin
1222
    fBitmap := TGLImage.Create;
1223
    fBitmap.Width := FWidth;
1224
    fBitmap.Height := FHeight;
1225
    fBitmap.Depth := FDepth;
1226
    fBitmap.CubeMap := FCubeMap;
1227
    fBitmap.TextureArray := FArray;
1228
    fBitmap.SetColorFormatDataType(FColorFormat, GL_UNSIGNED_BYTE);
1229
  end;
1230
  Result := FBitmap;
1231
end;
1232

1233
procedure TGLBlankImage.ReleaseBitmap32;
1234
begin
1235
  if Assigned(FBitmap) then
1236
  begin
1237
    FBitmap.Free;
1238
    FBitmap := nil;
1239
  end;
1240
end;
1241

1242
procedure TGLBlankImage.SaveToFile(const fileName: string);
1243
begin
1244
  SaveAnsiStringToFile(fileName, AnsiString(
1245
    '[BlankImage]'#13#10'Width=' + IntToStr(Width) +
1246
    #13#10'Height=' + IntToStr(Height) +
1247
    #13#10'Depth=' + IntToStr(Depth)));
1248
end;
1249

1250
procedure TGLBlankImage.LoadFromFile(const fileName: string);
1251
var
1252
  sl: TStringList;
1253
  buf, temp: string;
1254
begin
1255
  buf := fileName;
1256
  if Assigned(FOnTextureNeeded) then
1257
    FOnTextureNeeded(Self, buf);
1258
  if FileExists(buf) then
1259
  begin
1260
    sl := TStringList.Create;
1261
    try
1262
      sl.LoadFromFile(buf{$IFDEF GLS_DELPHI_2009_UP}, TEncoding.ASCII{$ENDIF});
1263
      FWidth := StrToInt(sl.Values['Width']);
1264
      FHeight := StrToInt(sl.Values['Height']);
1265
      temp := sl.Values['Depth'];
1266
      if Length(temp) > 0 then
1267
        FDepth := StrToInt(temp)
1268
      else
1269
        FDepth := 1;
1270
    finally
1271
      sl.Free;
1272
    end;
1273
  end
1274
  else
1275
  begin
1276
    Assert(False, Format(glsFailedOpenFile, [fileName]));
1277
  end;
1278
end;
1279

1280
class function TGLBlankImage.FriendlyName: string;
1281
begin
1282
  Result := 'Blank Image';
1283
end;
1284

1285
class function TGLBlankImage.FriendlyDescription: string;
1286
begin
1287
  Result := 'Blank Image (Width x Height x Depth)';
1288
end;
1289

1290
function TGLBlankImage.GetTextureTarget: TGLTextureTarget;
1291
begin
1292
  Result := ttTexture2D;
1293
  // Choose a texture target
1294
  if Assigned(fBitmap) then
1295
  begin
1296
    FWidth := fBitmap.Width;
1297
    FHeight := fBitmap.Height;
1298
    FDepth := fBitmap.Depth;
1299
    FCubeMap := fBitmap.CubeMap;
1300
    FArray := fBitmap.TextureArray;
1301
  end;
1302

1303
  if FHeight = 1 then
1304
    Result := ttTexture1D;
1305
  if FCubeMap then
1306
    Result := ttTextureCube;
1307
  if FDepth > 0 then
1308
    Result := ttTexture3D;
1309
  if FArray then
1310
  begin
1311
    if FDepth < 2 then
1312
      Result := ttTexture1DArray
1313
    else
1314
      Result := ttTexture2DArray;
1315
    if FCubeMap then
1316
      Result := ttTextureCubeArray;
1317
  end;
1318

1319
  if Assigned(FOwnerTexture) then
1320
  begin
1321
    if ((FOwnerTexture.FTextureFormat >= tfFLOAT_R16)
1322
      and (FOwnerTexture.FTextureFormat <= tfFLOAT_RGBA32)) then
1323
      Result := ttTextureRect;
1324
  end;
1325
end;
1326

1327
{%endregion%}
1328

1329
{%region%=====  'TGLPictureImage ================================}
1330

1331
// Create
1332
//
1333

1334
constructor TGLPictureImage.Create(AOwner: TPersistent);
1335
begin
1336
  inherited;
1337
end;
1338

1339
// Destroy
1340
//
1341

1342
destructor TGLPictureImage.Destroy;
1343
begin
1344
  ReleaseBitmap32;
1345
  FGLPicture.Free;
1346
  inherited Destroy;
1347
end;
1348

1349
 
1350
//
1351

1352
procedure TGLPictureImage.Assign(Source: TPersistent);
1353
var
1354
  bmp: TGLBitmap;
1355
begin
1356
  if Assigned(Source) then
1357
  begin
1358
    if (Source is TGLPersistentImage) then
1359
      Picture.Assign(TGLPersistentImage(Source).Picture)
1360
    else if (Source is TGLGraphic) then
1361
      Picture.Assign(Source)
1362
    else if (Source is TGLPicture) then
1363
      Picture.Assign(Source)
1364
    else if (Source is TGLImage) then
1365
    begin
1366
      bmp := TGLImage(Source).Create32BitsBitmap;
1367
      Picture.Graphic := bmp;
1368
      bmp.Free;
1369
      FResourceFile := TGLImage(Source).ResourceName;
1370
    end
1371
    else
1372
      inherited;
1373
  end
1374
  else
1375
    inherited;
1376
end;
1377

1378
// BeginUpdate
1379
//
1380

1381
procedure TGLPictureImage.BeginUpdate;
1382
begin
1383
  Inc(FUpdateCounter);
1384
  Picture.OnChange := nil;
1385
end;
1386

1387
// EndUpdate
1388
//
1389

1390
procedure TGLPictureImage.EndUpdate;
1391
begin
1392
  Assert(FUpdateCounter > 0, ClassName + ': Unbalanced Begin/EndUpdate');
1393
  Dec(FUpdateCounter);
1394
  Picture.OnChange := PictureChanged;
1395
  if FUpdateCounter = 0 then
1396
    PictureChanged(Picture);
1397
end;
1398

1399
// GetHeight
1400
//
1401

1402
function TGLPictureImage.GetHeight: Integer;
1403
begin
1404
  Result := Picture.Height;
1405
end;
1406

1407
// GetWidth
1408
//
1409

1410
function TGLPictureImage.GetWidth: Integer;
1411
begin
1412
  Result := Picture.Width;
1413
end;
1414

1415
// GetDepth
1416
//
1417

1418
function TGLPictureImage.GetDepth: Integer;
1419
begin
1420
  Result := 0;
1421
end;
1422

1423
// GetBitmap32
1424
//
1425

1426
function TGLPictureImage.GetBitmap32: TGLImage;
1427
begin
1428
  if not Assigned(FBitmap) then
1429
  begin
1430
    FBitmap := TGLImage.Create;
1431
    // we need to deactivate OnChange, due to a "glitch" in some TGraphics,
1432
    // for instance, TJPegImage triggers an OnChange when it is drawn...
1433
    if Assigned(Picture.Graphic) then
1434
    begin
1435
      if Assigned(Picture.OnChange) then
1436
      begin
1437
        Picture.OnChange := nil;
1438
        try
1439
          FBitmap.Assign(Picture.Graphic);
1440
        finally
1441
          Picture.OnChange := PictureChanged;
1442
        end;
1443
      end
1444
      else
1445
        FBitmap.Assign(Picture.Graphic);
1446
    end
1447
    else
1448
      FBitmap.SetErrorImage;
1449
  end;
1450
  Result := FBitmap;
1451
end;
1452

1453
// ReleaseBitmap32
1454
//
1455

1456
procedure TGLPictureImage.ReleaseBitmap32;
1457
begin
1458
  if Assigned(FBitmap) then
1459
  begin
1460
    FBitmap.Free;
1461
    FBitmap := nil;
1462
  end;
1463
end;
1464

1465
// PictureChanged
1466
//
1467

1468
procedure TGLPictureImage.PictureChanged(Sender: TObject);
1469
begin
1470
  Invalidate;
1471
end;
1472

1473
// GetPicture
1474
//
1475

1476
function TGLPictureImage.GetPicture: TGLPicture;
1477
begin
1478
  if not Assigned(FGLPicture) then
1479
  begin
1480
    FGLPicture := TGLPicture.Create;
1481
    FGLPicture.OnChange := PictureChanged;
1482
  end;
1483
  Result := FGLPicture;
1484
end;
1485

1486
// SetPicture
1487
//
1488

1489
procedure TGLPictureImage.SetPicture(const aPicture: TGLPicture);
1490
begin
1491
  Picture.Assign(aPicture);
1492
end;
1493

1494
// GetTextureTarget
1495
//
1496

1497
function TGLPictureImage.GetTextureTarget: TGLTextureTarget;
1498
begin
1499
  Result := ttTexture2D;
1500
end;
1501

1502
{%endregion%}
1503

1504
{%region%=====  'TGLPersistentImage ================================}
1505

1506
// Create
1507
//
1508

1509
constructor TGLPersistentImage.Create(AOwner: TPersistent);
1510
begin
1511
  inherited;
1512
end;
1513

1514
// Destroy
1515
//
1516

1517
destructor TGLPersistentImage.Destroy;
1518
begin
1519
  inherited Destroy;
1520
end;
1521

1522
// SaveToFile
1523
//
1524

1525
procedure TGLPersistentImage.SaveToFile(const fileName: string);
1526
begin
1527
  Picture.SaveToFile(fileName);
1528
  FResourceFile := fileName;
1529
end;
1530

1531
 
1532
//
1533

1534
procedure TGLPersistentImage.LoadFromFile(const fileName: string);
1535
var
1536
  buf: string;
1537
  gr: TGLGraphic;
1538
begin
1539
  buf := fileName;
1540
  FResourceFile := fileName;
1541
  if Assigned(FOnTextureNeeded) then
1542
    FOnTextureNeeded(Self, buf);
1543
  if ApplicationFileIODefined then
1544
  begin
1545
    gr := CreateGraphicFromFile(buf);
1546
    if Assigned(gr) then
1547
    begin
1548
      Picture.Graphic := gr;
1549
      gr.Free;
1550
      Exit;
1551
    end;
1552
  end
1553
  else if FileExists(buf) then
1554
  begin
1555
    Picture.LoadFromFile(buf);
1556
    Exit;
1557
  end;
1558
  Picture.Graphic := nil;
1559
  raise ETexture.CreateFmt(glsFailedOpenFile, [fileName]);
1560
end;
1561

1562
 
1563
//
1564

1565
class function TGLPersistentImage.FriendlyName: string;
1566
begin
1567
  Result := 'Persistent Image';
1568
end;
1569

1570
// FriendlyDescription
1571
//
1572

1573
class function TGLPersistentImage.FriendlyDescription: string;
1574
begin
1575
  Result := 'Image data is stored in its original format with other form resources,'
1576
    + 'ie. in the DFM at design-time, and embedded in the EXE at run-time.';
1577
end;
1578

1579
{%endregion%}
1580

1581

1582
{%region%=====  'TGLPicFileImage ================================}
1583

1584
// Create
1585
//
1586

1587
constructor TGLPicFileImage.Create(AOwner: TPersistent);
1588
begin
1589
  inherited;
1590
end;
1591

1592
// Destroy
1593
//
1594

1595
destructor TGLPicFileImage.Destroy;
1596
begin
1597
  inherited;
1598
end;
1599

1600
 
1601
//
1602

1603
procedure TGLPicFileImage.Assign(Source: TPersistent);
1604
begin
1605
  if Source is TGLPicFileImage then
1606
  begin
1607
    FPictureFileName := TGLPicFileImage(Source).FPictureFileName;
1608
    FResourceFile := TGLPicFileImage(Source).ResourceName;
1609
  end
1610
  else
1611
    inherited;
1612
end;
1613

1614
// SetPictureFileName
1615
//
1616

1617
procedure TGLPicFileImage.SetPictureFileName(const val: string);
1618
begin
1619
  if val <> FPictureFileName then
1620
  begin
1621
    FPictureFileName := val;
1622
    FResourceFile := val;
1623
    FAlreadyWarnedAboutMissingFile := False;
1624
    Invalidate;
1625
  end;
1626
end;
1627

1628
procedure TGLPicFileImage.Invalidate;
1629
begin
1630
  Picture.OnChange := nil;
1631
  try
1632
    Picture.Assign(nil);
1633
    FBitmap := nil;
1634
  finally
1635
    Picture.OnChange := PictureChanged;
1636
  end;
1637
  inherited;
1638
end;
1639

1640
function TGLPicFileImage.GetHeight: Integer;
1641
begin
1642
  Result := FHeight;
1643
end;
1644

1645
// GetWidth
1646
//
1647

1648
function TGLPicFileImage.GetWidth: Integer;
1649
begin
1650
  Result := FWidth;
1651
end;
1652

1653
function TGLPicFileImage.GetDepth: Integer;
1654
begin
1655
  Result := 0;
1656
end;
1657

1658
function TGLPicFileImage.GetBitmap32: TGLImage;
1659
var
1660
  buf: string;
1661
  gr: TGLGraphic;
1662
begin
1663
  if (GetWidth <= 0) and (PictureFileName <> '') then
1664
  begin
1665
    Picture.OnChange := nil;
1666
    try
1667
      buf := PictureFileName;
1668
      SetExeDirectory;
1669
      if Assigned(FOnTextureNeeded) then
1670
        FOnTextureNeeded(Self, buf);
1671
      if FileStreamExists(buf) then
1672
      begin
1673
        gr := CreateGraphicFromFile(buf);
1674
        Picture.Graphic := gr;
1675
        gr.Free;
1676
      end
1677
      else
1678
      begin
1679
        Picture.Graphic := nil;
1680
        if not FAlreadyWarnedAboutMissingFile then
1681
        begin
1682
          FAlreadyWarnedAboutMissingFile := True;
1683
          GLOKMessageBox(Format(glsFailedOpenFileFromCurrentDir, [PictureFileName, GetCurrentDir]),glsError);
1684
        end;
1685
      end;
1686
      Result := inherited GetBitmap32;
1687
      FWidth := Result.Width;
1688
      FHeight := Result.Height;
1689
      Picture.Graphic := nil;
1690
    finally
1691
      Picture.OnChange := PictureChanged;
1692
    end;
1693
  end
1694
  else
1695
    Result := inherited GetBitmap32;
1696
end;
1697

1698
// SaveToFile
1699
//
1700

1701
procedure TGLPicFileImage.SaveToFile(const fileName: string);
1702
begin
1703
  FResourceFile := fileName;
1704
  SaveAnsiStringToFile(fileName, AnsiString(PictureFileName));
1705
end;
1706

1707
 
1708
//
1709

1710
procedure TGLPicFileImage.LoadFromFile(const fileName: string);
1711
var
1712
  buf: string;
1713
begin
1714
  inherited;
1715
  // attempt to autodetect if we are pointed to a file containing
1716
  // a filename or directly to an image
1717
  if SizeOfFile(fileName) < 512 then
1718
  begin
1719
    buf := string(LoadAnsiStringFromFile(fileName));
1720
    if Pos(#0, buf) > 0 then
1721
      PictureFileName := fileName
1722
    else
1723
      PictureFileName := buf;
1724
  end
1725
  else
1726
    PictureFileName := fileName;
1727
  FResourceFile := FPictureFileName;
1728
end;
1729

1730
 
1731
//
1732

1733
class function TGLPicFileImage.FriendlyName: string;
1734
begin
1735
  Result := 'PicFile Image';
1736
end;
1737

1738
// FriendlyDescription
1739
//
1740

1741
class function TGLPicFileImage.FriendlyDescription: string;
1742
begin
1743
  Result := 'Image data is retrieved from a file.';
1744
end;
1745

1746
{%endregion%}
1747

1748
{%region%=====  'TGLCubeMapImage ================================}
1749

1750
// Create
1751
//
1752

1753
constructor TGLCubeMapImage.Create(AOwner: TPersistent);
1754
var
1755
  i: TGLCubeMapTarget;
1756
begin
1757
  inherited;
1758
  for i := Low(FPicture) to High(FPicture) do
1759
  begin
1760
    FPicture[i] := TGLPicture.Create;
1761
    FPicture[i].OnChange := PictureChanged;
1762
  end;
1763
end;
1764

1765
// Destroy
1766
//
1767

1768
destructor TGLCubeMapImage.Destroy;
1769
var
1770
  i: TGLCubeMapTarget;
1771
begin
1772
  ReleaseBitmap32;
1773
  for i := Low(FPicture) to High(FPicture) do
1774
    FPicture[i].Free;
1775
  inherited Destroy;
1776
end;
1777

1778
 
1779
//
1780

1781
procedure TGLCubeMapImage.Assign(Source: TPersistent);
1782
var
1783
  i: TGLCubeMapTarget;
1784
begin
1785
  if Assigned(Source) then
1786
  begin
1787
    if (Source is TGLCubeMapImage) then
1788
    begin
1789
      for i := Low(FPicture) to High(FPicture) do
1790
        FPicture[i].Assign(TGLCubeMapImage(Source).FPicture[i]);
1791
      Invalidate;
1792
    end
1793
    else
1794
      inherited;
1795
  end
1796
  else
1797
    inherited;
1798
end;
1799

1800
// GetWidth
1801
//
1802

1803
function TGLCubeMapImage.GetWidth: Integer;
1804
begin
1805
  Result := FPicture[cmtPX].Width;
1806
end;
1807

1808
// GetHeight
1809
//
1810

1811
function TGLCubeMapImage.GetHeight: Integer;
1812
begin
1813
  Result := FPicture[cmtPX].Height;
1814
end;
1815

1816
// GetDepth
1817
//
1818

1819
function TGLCubeMapImage.GetDepth: Integer;
1820
begin
1821
  Result := 0;
1822
end;
1823

1824
// GetBitmap32
1825
//
1826

1827
function TGLCubeMapImage.GetBitmap32: TGLImage;
1828
var
1829
  I: Integer;
1830
  LImage: TGLImage;
1831
begin
1832
  if Assigned(FImage) then
1833
    FImage.Free;
1834
  LImage := TGLImage.Create;
1835
  LImage.VerticalReverseOnAssignFromBitmap := True;
1836

1837
  try
1838
    for I := 0 to 5 do
1839
    begin
1840
      FPicture[TGLCubeMapTarget(I)].OnChange := nil;
1841
      try
1842
        LImage.Assign(FPicture[TGLCubeMapTarget(I)].Graphic);
1843
        if not Assigned(FImage) then
1844
        begin
1845
          FImage := TGLImage.Create;
1846
          FImage.Blank := True;
1847
          FImage.Width := LImage.Width;
1848
          FImage.Height := LImage.Height;
1849
          FImage.SetColorFormatDataType(LImage.ColorFormat, LImage.DataType);
1850
          FImage.CubeMap := True;
1851
          FImage.Blank := False;
1852
        end;
1853
        Move(LImage.Data^, TFriendlyImage(FImage).GetLevelAddress(0, I)^, LImage.LevelSizeInByte[0]);
1854
      finally
1855
        FPicture[TGLCubeMapTarget(I)].OnChange := PictureChanged;
1856
      end;
1857
    end;
1858
  finally
1859
    LImage.Destroy;
1860
  end;
1861
  Result := FImage;
1862
end;
1863

1864
// ReleaseBitmap32
1865
//
1866

1867
procedure TGLCubeMapImage.ReleaseBitmap32;
1868
begin
1869
  if Assigned(FImage) then
1870
  begin
1871
    FImage.Free;
1872
    FImage := nil;
1873
  end;
1874
end;
1875

1876
// BeginUpdate
1877
//
1878

1879
procedure TGLCubeMapImage.BeginUpdate;
1880
var
1881
  i: TGLCubeMapTarget;
1882
begin
1883
  Inc(FUpdateCounter);
1884
  for i := Low(FPicture) to High(FPicture) do
1885
    FPicture[i].OnChange := nil;
1886
end;
1887

1888
// EndUpdate
1889
//
1890

1891
procedure TGLCubeMapImage.EndUpdate;
1892
var
1893
  i: TGLCubeMapTarget;
1894
begin
1895
  Assert(FUpdateCounter > 0, ClassName + ': Unbalanced Begin/EndUpdate');
1896
  Dec(FUpdateCounter);
1897
  for i := Low(FPicture) to High(FPicture) do
1898
    FPicture[i].OnChange := PictureChanged;
1899
  if FUpdateCounter = 0 then
1900
    PictureChanged(FPicture[cmtPX]);
1901
end;
1902

1903
// SaveToFile
1904
//
1905

1906
procedure TGLCubeMapImage.SaveToFile(const fileName: string);
1907
var
1908
  fs: TFileStream;
1909
  bmp: TGLBitmap;
1910
  i: TGLCubeMapTarget;
1911
  version: Word;
1912
begin
1913
  fs := TFileStream.Create(fileName, fmCreate);
1914
  bmp := TGLBitmap.Create;
1915
  try
1916
    version := $0100;
1917
    fs.Write(version, 2);
1918
    for i := Low(FPicture) to High(FPicture) do
1919
    begin
1920
      bmp.Assign(FPicture[i].Graphic);
1921
      bmp.SaveToStream(fs);
1922
    end;
1923
  finally
1924
    bmp.Free;
1925
    fs.Free;
1926
  end;
1927
end;
1928

1929
 
1930
//
1931

1932
procedure TGLCubeMapImage.LoadFromFile(const fileName: string);
1933
var
1934
  fs: TFileStream;
1935
  bmp: TGLBitmap;
1936
  i: TGLCubeMapTarget;
1937
  version: Word;
1938
begin
1939
  fs := TFileStream.Create(fileName, fmOpenRead + fmShareDenyWrite);
1940
  bmp := TGLBitmap.Create;
1941
  try
1942
    fs.Read(version, 2);
1943
    Assert(version = $0100);
1944
    for i := Low(FPicture) to High(FPicture) do
1945
    begin
1946
      bmp.LoadFromStream(fs);
1947
      FPicture[i].Graphic := bmp;
1948
    end;
1949
  finally
1950
    bmp.Free;
1951
    fs.Free;
1952
  end;
1953
end;
1954

1955
 
1956
//
1957

1958
class function TGLCubeMapImage.FriendlyName: string;
1959
begin
1960
  Result := 'CubeMap Image';
1961
end;
1962

1963
// FriendlyDescription
1964
//
1965

1966
class function TGLCubeMapImage.FriendlyDescription: string;
1967
begin
1968
  Result := 'Image data is contain 6 pictures of cubemap faces.';
1969
end;
1970

1971
// PictureChanged
1972
//
1973

1974
procedure TGLCubeMapImage.PictureChanged(Sender: TObject);
1975
begin
1976
  Invalidate;
1977
end;
1978

1979
// GetTextureTarget
1980
//
1981

1982
function TGLCubeMapImage.GetTextureTarget: TGLTextureTarget;
1983
begin
1984
  Result := ttTextureCube;
1985
end;
1986

1987
// SetPicture
1988
//
1989

1990
procedure TGLCubeMapImage.SetPicture(index: TGLCubeMapTarget; const val:
1991
  TGLPicture);
1992
begin
1993
  FPicture[index].Assign(val);
1994
end;
1995

1996
function TGLCubeMapImage.GetPicture(index: TGLCubeMapTarget): TGLPicture;
1997
begin
1998
  Result := FPicture[index];
1999
end;
2000

2001
{%endregion%}
2002

2003

2004
{%region%=====  'TGLTexture ================================}
2005

2006

2007
constructor TGLTexture.Create(AOwner: TPersistent);
2008
begin
2009
  inherited;
2010
  FDisabled := True;
2011
  FImage := TGLPersistentImage.Create(Self);
2012
  FImage.OnTextureNeeded := DoOnTextureNeeded;
2013
  FImageAlpha := tiaDefault;
2014
  FImageBrightness := 1.0;
2015
  FImageGamma := 1.0;
2016
  FMagFilter := maLinear;
2017
  FMinFilter := miLinearMipMapLinear;
2018
  FFilteringQuality := tfIsotropic;
2019
  FRequiredMemorySize := -1;
2020
  FTextureHandle := TGLTextureHandle.Create;
2021
  FSamplerHandle := TGLVirtualHandle.Create;
2022
  FSamplerHandle.OnAllocate := OnSamplerAllocate;
2023
  FSamplerHandle.OnDestroy := OnSamplerDestroy;
2024
  FMappingMode := tmmUser;
2025
  FEnvColor := TGLColor.CreateInitialized(Self, clrTransparent);
2026
  FBorderColor := TGLColor.CreateInitialized(Self, clrTransparent);
2027
  FNormalMapScale := cDefaultNormalMapScale;
2028
  FTextureCompareMode := tcmNone;
2029
  FTextureCompareFunc := cfLequal;
2030
  FDepthTextureMode := dtmLuminance;
2031
  TextureFormat := tfDefault;
2032
  FCompression := tcDefault;
2033
  FKeepImageAfterTransfer := False;
2034
end;
2035

2036
destructor TGLTexture.Destroy;
2037
begin
2038
  FEnvColor.Free;
2039
  FBorderColor.Free;
2040
  FMapSCoordinates.Free;
2041
  FMapTCoordinates.Free;
2042
  FMapRCoordinates.Free;
2043
  FMapQCoordinates.Free;
2044
  DestroyHandles;
2045
  FTextureHandle.Free;
2046
  FSamplerHandle.Free;
2047
  FImage.Free;
2048
  inherited Destroy;
2049
end;
2050

2051
procedure TGLTexture.Assign(Source: TPersistent);
2052
begin
2053
  if Assigned(Source) then
2054
  begin
2055
    if (Source is TGLTexture) then
2056
    begin
2057
      if Source <> Self then
2058
      begin
2059
        FImageAlpha := TGLTexture(Source).FImageAlpha;
2060
        FTextureMode := TGLTexture(Source).FTextureMode;
2061
        FTextureWrap := TGLTexture(Source).FTextureWrap;
2062
        FTextureFormat := TGLTexture(Source).FTextureFormat;
2063
        FCompression := TGLTexture(Source).FCompression;
2064
        FMinFilter := TGLTexture(Source).FMinFilter;
2065
        FMagFilter := TGLTexture(Source).FMagFilter;
2066
        FMappingMode := TGLTexture(Source).FMappingMode;
2067
        MappingSCoordinates.Assign(TGLTexture(Source).MappingSCoordinates);
2068
        MappingTCoordinates.Assign(TGLTexture(Source).MappingTCoordinates);
2069
        MappingRCoordinates.Assign(TGLTexture(Source).MappingRCoordinates);
2070
        MappingQCoordinates.Assign(TGLTexture(Source).MappingQCoordinates);
2071
        FDisabled := TGLTexture(Source).FDisabled;
2072
        SetImage(TGLTexture(Source).FImage);
2073
        FImageBrightness := TGLTexture(Source).FImageBrightness;
2074
        FImageGamma := TGLTexture(Source).FImageGamma;
2075
        FFilteringQuality := TGLTexture(Source).FFilteringQuality;
2076
        FEnvColor.Assign(TGLTexture(Source).FEnvColor);
2077
        FBorderColor.Assign(TGLTexture(Source).FBorderColor);
2078
        FNormalMapScale := TGLTexture(Source).FNormalMapScale;
2079
        // Probably don't need to assign these....
2080
        // FOnTextureNeeded := TGLTexture(Source).FImageGamma;
2081
        // FRequiredMemorySize  : Integer;
2082
        // FTexWidth, FTexHeight : Integer;
2083
        FTextureHandle.NotifyChangesOfData;
2084
        FSamplerHandle.NotifyChangesOfData;
2085
      end;
2086
    end
2087
    else if (Source is TGLGraphic) then
2088
      Image.Assign(Source)
2089
    else if (Source is TGLPicture) then
2090
      Image.Assign(TGLPicture(Source).Graphic)
2091
    else
2092
      inherited Assign(Source);
2093
  end
2094
  else
2095
  begin
2096
    FDisabled := True;
2097
    SetImage(nil);
2098
    FTextureHandle.NotifyChangesOfData;
2099
    FSamplerHandle.NotifyChangesOfData;
2100
  end;
2101
end;
2102

2103
procedure TGLTexture.NotifyChange(Sender: TObject);
2104
begin
2105
  if Assigned(Owner) then
2106
  begin
2107
    if Owner is TGLTextureExItem then
2108
      TGLTextureExItem(Owner).NotifyChange(Self);
2109
  end;
2110
  if Sender is TGLTextureImage then
2111
    FTextureHandle.NotifyChangesOfData;
2112

2113
  inherited;
2114
end;
2115

2116
procedure TGLTexture.NotifyImageChange;
2117
begin
2118
  FTextureHandle.NotifyChangesOfData;
2119
  NotifyChange(Self);
2120
end;
2121

2122
procedure TGLTexture.NotifyParamsChange;
2123
begin
2124
  FSamplerHandle.NotifyChangesOfData;
2125
  NotifyChange(Self);
2126
end;
2127

2128
procedure TGLTexture.SetImage(AValue: TGLTextureImage);
2129
begin
2130
  if Assigned(aValue) then
2131
  begin
2132
    if FImage.ClassType <> AValue.ClassType then
2133
    begin
2134
      FImage.Free;
2135
      FImage := TGLTextureImageClass(AValue.ClassType).Create(Self);
2136
      FImage.OnTextureNeeded := DoOnTextureNeeded;
2137
    end;
2138
    FImage.Assign(AValue);
2139
  end
2140
  else
2141
  begin
2142
    FImage.Free;
2143
    FImage := TGLPersistentImage.Create(Self);
2144
    FImage.OnTextureNeeded := DoOnTextureNeeded;
2145
  end;
2146
end;
2147

2148
procedure TGLTexture.SetImageClassName(const val: string);
2149
var
2150
  newImage: TGLTextureImage;
2151
  newImageClass: TGLTextureImageClass;
2152
begin
2153
  if val <> '' then
2154
    if FImage.ClassName <> val then
2155
    begin
2156
      newImageClass := FindGLTextureImageClass(val);
2157
      Assert(newImageClass <> nil, 'Make sure you include the unit for ' + val +
2158
        ' in your uses clause');
2159
      if newImageClass = nil then
2160
        exit;
2161
      newImage := newImageClass.Create(Self);
2162
      newImage.OnTextureNeeded := DoOnTextureNeeded;
2163
      FImage.Free;
2164
      FImage := newImage;
2165
    end;
2166
end;
2167

2168
function TGLTexture.GetImageClassName: string;
2169
begin
2170
  Result := FImage.ClassName;
2171
end;
2172

2173
function TGLTexture.TextureImageRequiredMemory: Integer;
2174
var
2175
  w, h, e, levelSize: Integer;
2176
begin
2177
  if FRequiredMemorySize < 0 then
2178
  begin
2179
    if IsCompressedFormat(fTextureFormat) then
2180
    begin
2181
      w := (Image.Width + 3) div 4;
2182
      h := (Image.Height + 3) div 4;
2183
    end
2184
    else
2185
    begin
2186
      w := Image.Width;
2187
      h := Image.Height;
2188
    end;
2189

2190
    e := GetTextureElementSize(fTextureFormat);
2191
    FRequiredMemorySize := w * h * e;
2192
    if Image.Depth > 0 then
2193
      FRequiredMemorySize := FRequiredMemorySize * Image.Depth;
2194

2195
    if not (MinFilter in [miNearest, miLinear]) then
2196
    begin
2197
      levelSize := FRequiredMemorySize;
2198
      while e < levelSize do
2199
      begin
2200
        levelSize := levelSize div 4;
2201
        FRequiredMemorySize := FRequiredMemorySize + levelSize;
2202
      end;
2203
    end;
2204

2205
    if Image.NativeTextureTarget = ttTextureCube then
2206
      FRequiredMemorySize := FRequiredMemorySize * 6;
2207
  end;
2208
  Result := FRequiredMemorySize;
2209
end;
2210

2211
procedure TGLTexture.SetImageAlpha(const val: TGLTextureImageAlpha);
2212
begin
2213
  if FImageAlpha <> val then
2214
  begin
2215
    FImageAlpha := val;
2216
    NotifyImageChange;
2217
  end;
2218
end;
2219

2220
procedure TGLTexture.SetImageBrightness(const val: Single);
2221
begin
2222
  if FImageBrightness <> val then
2223
  begin
2224
    FImageBrightness := val;
2225
    NotifyImageChange;
2226
  end;
2227
end;
2228

2229
function TGLTexture.StoreBrightness: Boolean;
2230
begin
2231
  Result := (FImageBrightness <> 1.0);
2232
end;
2233

2234
procedure TGLTexture.SetImageGamma(const val: Single);
2235
begin
2236
  if FImageGamma <> val then
2237
  begin
2238
    FImageGamma := val;
2239
    NotifyImageChange;
2240
  end;
2241
end;
2242

2243
function TGLTexture.StoreGamma: Boolean;
2244
begin
2245
  Result := (FImageGamma <> 1.0);
2246
end;
2247

2248
procedure TGLTexture.SetMagFilter(AValue: TGLMagFilter);
2249
begin
2250
  if AValue <> FMagFilter then
2251
  begin
2252
    FMagFilter := AValue;
2253
    NotifyParamsChange;
2254
  end;
2255
end;
2256

2257
procedure TGLTexture.SetMinFilter(AValue: TGLMinFilter);
2258
begin
2259
  if AValue <> FMinFilter then
2260
  begin
2261
    FMinFilter := AValue;
2262
    NotifyParamsChange;
2263
  end;
2264
end;
2265

2266
procedure TGLTexture.SetTextureMode(AValue: TGLTextureMode);
2267
begin
2268
  if AValue <> FTextureMode then
2269
  begin
2270
    FTextureMode := AValue;
2271
    NotifyParamsChange;
2272
  end;
2273
end;
2274

2275
procedure TGLTexture.SetDisabled(AValue: Boolean);
2276
var
2277
  intf: IGLTextureNotifyAble;
2278
begin
2279
  if AValue <> FDisabled then
2280
  begin
2281
    FDisabled := AValue;
2282
    if Supports(Owner, IGLTextureNotifyAble, intf) then
2283
      intf.NotifyTexMapChange(Self)
2284
    else
2285
      NotifyChange(Self);
2286
  end;
2287
end;
2288

2289
procedure TGLTexture.SetEnabled(const val: Boolean);
2290
begin
2291
  Disabled := not val;
2292
end;
2293

2294
function TGLTexture.GetEnabled: Boolean;
2295
begin
2296
  Result := not Disabled;
2297
end;
2298

2299
procedure TGLTexture.SetEnvColor(const val: TGLColor);
2300
begin
2301
  FEnvColor.Assign(val);
2302
  NotifyParamsChange;
2303
end;
2304

2305
procedure TGLTexture.SetBorderColor(const val: TGLColor);
2306
begin
2307
  FBorderColor.Assign(val);
2308
  NotifyParamsChange;
2309
end;
2310

2311
procedure TGLTexture.SetNormalMapScale(const val: Single);
2312
begin
2313
  if val <> FNormalMapScale then
2314
  begin
2315
    FNormalMapScale := val;
2316
    if TextureFormat = tfNormalMap then
2317
      NotifyImageChange;
2318
  end;
2319
end;
2320

2321
function TGLTexture.StoreNormalMapScale: Boolean;
2322
begin
2323
  Result := (FNormalMapScale <> cDefaultNormalMapScale);
2324
end;
2325

2326
procedure TGLTexture.SetTextureWrap(AValue: TGLTextureWrap);
2327
begin
2328
  if AValue <> FTextureWrap then
2329
  begin
2330
    FTextureWrap := AValue;
2331
    NotifyParamsChange;
2332
  end;
2333
end;
2334

2335
procedure TGLTexture.SetTextureWrapS(AValue: TGLSeparateTextureWrap);
2336
begin
2337
  if AValue <> FTextureWrapS then
2338
  begin
2339
    FTextureWrapS := AValue;
2340
    NotifyParamsChange;
2341
  end;
2342
end;
2343

2344
procedure TGLTexture.SetTextureWrapT(AValue: TGLSeparateTextureWrap);
2345
begin
2346
  if AValue <> FTextureWrapT then
2347
  begin
2348
    FTextureWrapT := AValue;
2349
    NotifyParamsChange;
2350
  end;
2351
end;
2352

2353
procedure TGLTexture.SetTextureWrapR(AValue: TGLSeparateTextureWrap);
2354
begin
2355
  if AValue <> FTextureWrapR then
2356
  begin
2357
    FTextureWrapR := AValue;
2358
    NotifyParamsChange;
2359
  end;
2360
end;
2361

2362
function TGLTexture.GetTextureFormat: TGLTextureFormat;
2363
var
2364
  i: TGLTextureFormat;
2365
begin
2366
  if vDefaultTextureFormat = FTextureFormat then
2367
  begin
2368
    Result := tfDefault;
2369
    Exit;
2370
  end;
2371
  for i := tfRGB to tfRGBAFloat32 do
2372
  begin
2373
    if cOldTextureFormatToInternalFormat[i] = FTextureFormat then
2374
    begin
2375
      Result := i;
2376
      Exit;
2377
    end;
2378
  end;
2379
  Result := tfExtended;
2380
end;
2381

2382
procedure TGLTexture.SetTextureFormat(const val: TGLTextureFormat);
2383
begin
2384
  if val = tfDefault then
2385
  begin
2386
    FTextureFormat := vDefaultTextureFormat;
2387
  end
2388
  else if val < tfExtended then
2389
  begin
2390
    FTextureFormat := cOldTextureFormatToInternalFormat[val];
2391
  end;
2392
end;
2393

2394
procedure TGLTexture.SetTextureFormatEx(const val: TGLInternalFormat);
2395
begin
2396
  if val <> FTextureFormat then
2397
  begin
2398
    FTextureFormat := val;
2399
    NotifyImageChange;
2400
  end;
2401
end;
2402

2403
function TGLTexture.StoreTextureFormatEx: Boolean;
2404
begin
2405
  Result := GetTextureFormat >= tfExtended;
2406
end;
2407

2408
procedure TGLTexture.SetCompression(const val: TGLTextureCompression);
2409
begin
2410
  if val <> FCompression then
2411
  begin
2412
    FCompression := val;
2413
    NotifyParamsChange;
2414
  end;
2415
end;
2416

2417
procedure TGLTexture.SetFilteringQuality(const val: TGLTextureFilteringQuality);
2418
begin
2419
  if val <> FFilteringQuality then
2420
  begin
2421
    FFilteringQuality := val;
2422
    NotifyParamsChange;
2423
  end;
2424
end;
2425

2426
procedure TGLTexture.SetMappingMode(const val: TGLTextureMappingMode);
2427
var
2428
  texMapChange: Boolean;
2429
  intf: IGLTextureNotifyAble;
2430
begin
2431
  if val <> FMappingMode then
2432
  begin
2433
    texMapChange := ((val = tmmUser) and (FMappingMode <> tmmUser))
2434
      or ((val = tmmUser) and (FMappingMode <> tmmUser));
2435
    FMappingMode := val;
2436
    if texMapChange then
2437
    begin
2438
      // when switching between texGen modes and user mode, the geometry
2439
      // must be rebuilt in whole (to specify/remove texCoord data!)
2440
      if Supports(Owner, IGLTextureNotifyAble, intf) then
2441
        intf.NotifyTexMapChange(Self);
2442
    end
2443
    else
2444
      NotifyChange(Self);
2445
  end;
2446
end;
2447

2448
procedure TGLTexture.SetMappingSCoordinates(const val: TGLCoordinates4);
2449
begin
2450
  MappingSCoordinates.Assign(val);
2451
end;
2452

2453
function TGLTexture.GetMappingSCoordinates: TGLCoordinates4;
2454
begin
2455
  if not Assigned(FMapSCoordinates) then
2456
    FMapSCoordinates := TGLCoordinates4.CreateInitialized(Self, XHmgVector,
2457
      csVector);
2458
  Result := FMapSCoordinates;
2459
end;
2460

2461

2462
function TGLTexture.StoreMappingSCoordinates: Boolean;
2463
begin
2464
  if Assigned(FMapSCoordinates) then
2465
    Result := not VectorEquals(FMapSCoordinates.AsVector, XHmgVector)
2466
  else
2467
    Result := false;
2468
end;
2469

2470
procedure TGLTexture.SetMappingTCoordinates(const val: TGLCoordinates4);
2471
begin
2472
  MappingTCoordinates.Assign(val);
2473
end;
2474

2475
function TGLTexture.GetMappingTCoordinates: TGLCoordinates4;
2476
begin
2477
  if not Assigned(FMapTCoordinates) then
2478
    FMapTCoordinates := TGLCoordinates4.CreateInitialized(Self, YHmgVector,
2479
      csVector);
2480
  Result := FMapTCoordinates;
2481
end;
2482

2483
function TGLTexture.StoreMappingTCoordinates: Boolean;
2484
begin
2485
  if Assigned(FMapTCoordinates) then
2486
    Result := not VectorEquals(FMapTCoordinates.AsVector, YHmgVector)
2487
  else
2488
    Result := false;
2489
end;
2490

2491

2492
procedure TGLTexture.SetMappingRCoordinates(const val: TGLCoordinates4);
2493
begin
2494
  MappingRCoordinates.Assign(val);
2495
end;
2496

2497
function TGLTexture.GetMappingRCoordinates: TGLCoordinates4;
2498
begin
2499
  if not Assigned(FMapRCoordinates) then
2500
    FMapRCoordinates := TGLCoordinates4.CreateInitialized(Self, ZHmgVector,
2501
      csVector);
2502
  Result := FMapRCoordinates;
2503
end;
2504

2505
function TGLTexture.StoreMappingRCoordinates: Boolean;
2506
begin
2507
  if Assigned(FMapRCoordinates) then
2508
    Result := not VectorEquals(FMapRCoordinates.AsVector, ZHmgVector)
2509
  else
2510
    Result := false;
2511
end;
2512

2513
procedure TGLTexture.SetMappingQCoordinates(const val: TGLCoordinates4);
2514
begin
2515
  MappingQCoordinates.Assign(val);
2516
end;
2517

2518
function TGLTexture.GetMappingQCoordinates: TGLCoordinates4;
2519
begin
2520
  if not Assigned(FMapQCoordinates) then
2521
    FMapQCoordinates := TGLCoordinates4.CreateInitialized(Self, WHmgVector,
2522
      csVector);
2523
  Result := FMapQCoordinates;
2524
end;
2525

2526
function TGLTexture.StoreMappingQCoordinates: Boolean;
2527
begin
2528
  if Assigned(FMapQCoordinates) then
2529
    Result := not VectorEquals(FMapQCoordinates.AsVector, WHmgVector)
2530
  else
2531
    Result := false;
2532
end;
2533

2534
function TGLTexture.StoreImageClassName: Boolean;
2535
begin
2536
  Result := (FImage.ClassName <> TGLPersistentImage.ClassName);
2537
end;
2538

2539
procedure TGLTexture.SetTextureCompareMode(const val: TGLTextureCompareMode);
2540
begin
2541
  if val <> fTextureCompareMode then
2542
  begin
2543
    fTextureCompareMode := val;
2544
    NotifyParamsChange;
2545
  end;
2546
end;
2547

2548
procedure TGLTexture.SetTextureCompareFunc(const val: TGLDepthCompareFunc);
2549
begin
2550
  if val <> fTextureCompareFunc then
2551
  begin
2552
    fTextureCompareFunc := val;
2553
    NotifyParamsChange;
2554
  end;
2555
end;
2556

2557
procedure TGLTexture.SetDepthTextureMode(const val: TGLDepthTextureMode);
2558
begin
2559
  if val <> fDepthTextureMode then
2560
  begin
2561
    fDepthTextureMode := val;
2562
    NotifyParamsChange;
2563
  end;
2564
end;
2565

2566
procedure TGLTexture.PrepareBuildList;
2567
begin
2568
  GetHandle;
2569
end;
2570

2571

2572
procedure TGLTexture.ApplyMappingMode;
2573
var
2574
  R_Dim: Boolean;
2575
begin
2576
  R_Dim := GL.ARB_texture_cube_map or GL.EXT_texture3D;
2577
  case MappingMode of
2578
    tmmUser: ; // nothing to do, but checked first (common case)
2579
    tmmObjectLinear:
2580
      begin
2581
        GL.TexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
2582
        GL.TexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
2583
        GL.TexGenfv(GL_S, GL_OBJECT_PLANE, @MappingSCoordinates.DirectVector);
2584
        GL.TexGenfv(GL_T, GL_OBJECT_PLANE, @MappingTCoordinates.DirectVector);
2585
        GL.Enable(GL_TEXTURE_GEN_S);
2586
        GL.Enable(GL_TEXTURE_GEN_T);
2587

2588
        if R_Dim then
2589
        begin
2590
          GL.TexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
2591
          GL.TexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
2592
          GL.TexGenfv(GL_R, GL_OBJECT_PLANE, @MappingRCoordinates.DirectVector);
2593
          GL.TexGenfv(GL_Q, GL_OBJECT_PLANE, @MappingQCoordinates.DirectVector);
2594
          GL.Enable(GL_TEXTURE_GEN_R);
2595
          GL.Enable(GL_TEXTURE_GEN_Q);
2596
        end;
2597
      end;
2598
    tmmEyeLinear:
2599
      begin
2600
        GL.TexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
2601
        GL.TexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
2602
        // specify planes in eye space, not world space
2603
        GL.MatrixMode(GL_MODELVIEW);
2604
        GL.PushMatrix;
2605
        GL.LoadIdentity;
2606
        GL.TexGenfv(GL_S, GL_EYE_PLANE, @MappingSCoordinates.DirectVector);
2607
        GL.TexGenfv(GL_T, GL_EYE_PLANE, @MappingTCoordinates.DirectVector);
2608
        GL.Enable(GL_TEXTURE_GEN_S);
2609
        GL.Enable(GL_TEXTURE_GEN_T);
2610
        if R_Dim then
2611
        begin
2612
          GL.TexGenfv(GL_R, GL_EYE_PLANE, @MappingRCoordinates.DirectVector);
2613
          GL.TexGenfv(GL_Q, GL_EYE_PLANE, @MappingQCoordinates.DirectVector);
2614
          GL.Enable(GL_TEXTURE_GEN_R);
2615
          GL.Enable(GL_TEXTURE_GEN_Q);
2616
        end;
2617
        GL.PopMatrix;
2618
      end;
2619
    tmmSphere:
2620
      begin
2621
        GL.TexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
2622
        GL.TexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
2623
        GL.Enable(GL_TEXTURE_GEN_S);
2624
        GL.Enable(GL_TEXTURE_GEN_T);
2625
      end;
2626
    tmmCubeMapReflection, tmmCubeMapCamera: if GL.ARB_texture_cube_map then
2627
      begin
2628
        GL.TexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
2629
        GL.TexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
2630
        GL.TexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
2631
        GL.Enable(GL_TEXTURE_GEN_S);
2632
        GL.Enable(GL_TEXTURE_GEN_T);
2633
        GL.Enable(GL_TEXTURE_GEN_R);
2634
      end;
2635
    tmmCubeMapNormal, tmmCubeMapLight0: if GL.ARB_texture_cube_map then
2636
      begin
2637
        GL.TexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP);
2638
        GL.TexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP);
2639
        GL.TexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP);
2640
        GL.Enable(GL_TEXTURE_GEN_S);
2641
        GL.Enable(GL_TEXTURE_GEN_T);
2642
        GL.Enable(GL_TEXTURE_GEN_R);
2643
      end;
2644
  else
2645
    Assert(False);
2646
  end;
2647
end;
2648

2649
procedure TGLTexture.UnApplyMappingMode;
2650
begin
2651
  if MappingMode <> tmmUser then
2652
  begin
2653
    GL.Disable(GL_TEXTURE_GEN_S);
2654
    GL.Disable(GL_TEXTURE_GEN_T);
2655
    if GL.EXT_texture3D or GL.ARB_texture_cube_map then
2656
    begin
2657
      GL.Disable(GL_TEXTURE_GEN_R);
2658
      GL.Disable(GL_TEXTURE_GEN_Q);
2659
    end;
2660
  end;
2661
end;
2662

2663
procedure TGLTexture.Apply(var rci: TGLRenderContextInfo);
2664

2665
  procedure SetCubeMapTextureMatrix;
2666
  var
2667
    m, mm: TMatrix;
2668
  begin
2669
    // compute model view matrix for proper viewing
2670
    case MappingMode of
2671
      tmmCubeMapReflection, tmmCubeMapNormal:
2672
        begin
2673
          m := rci.PipelineTransformation.ViewMatrix;
2674
          NormalizeMatrix(m);
2675
          TransposeMatrix(m);
2676
          rci.GLStates.SetGLTextureMatrix(m);
2677
        end;
2678
      tmmCubeMapLight0:
2679
        begin
2680
          with TGLScene(rci.scene).Lights do
2681
            if Count > 0 then
2682
            begin
2683
              m := TGLLightSource(Items[0]).AbsoluteMatrix;
2684
              NormalizeMatrix(m);
2685
              mm := rci.PipelineTransformation.ViewMatrix;
2686
              NormalizeMatrix(mm);
2687
              TransposeMatrix(mm);
2688
              m := MatrixMultiply(m, mm);
2689
              rci.GLStates.SetGLTextureMatrix(m);
2690
            end;
2691
        end;
2692
      tmmCubeMapCamera:
2693
        begin
2694
          m.V[0] := VectorCrossProduct(rci.cameraUp, rci.cameraDirection);
2695
          m.V[1] := VectorNegate(rci.cameraDirection);
2696
          m.V[2] := rci.cameraUp;
2697
          m.V[3] := WHmgPoint;
2698
          mm := rci.PipelineTransformation.ViewMatrix;
2699
          NormalizeMatrix(mm);
2700
          TransposeMatrix(mm);
2701
          m := MatrixMultiply(m, mm);
2702
          rci.GLStates.SetGLTextureMatrix(m);
2703
        end;
2704
    end;
2705
  end;
2706
var
2707
  H : TGLuint;
2708
begin
2709
  // Multisample image do not work with FFP
2710
  if (FTextureHandle.Target = ttTexture2DMultisample) or
2711
    (FTextureHandle.Target = ttTexture2DMultisampleArray) then
2712
    exit;
2713

2714
  H := Handle;
2715
  if not Disabled and (H > 0) then
2716
  begin
2717
    with rci.GLStates do
2718
    begin
2719
      ActiveTexture := 0;
2720
      TextureBinding[0, FTextureHandle.Target] := H;
2721
      ActiveTextureEnabled[FTextureHandle.Target] := True;
2722
    end;
2723

2724
    if not rci.GLStates.ForwardContext then
2725
    begin
2726
      if FTextureHandle.Target = ttTextureCube then
2727
        SetCubeMapTextureMatrix;
2728
      GL.TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,
2729
        cTextureMode[FTextureMode]);
2730
      GL.TexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, FEnvColor.AsAddress);
2731
      ApplyMappingMode;
2732
      xgl.MapTexCoordToMain;
2733
    end;
2734
  end
2735
  else if not rci.GLStates.ForwardContext then
2736
  begin // default
2737
    xgl.MapTexCoordToMain;
2738
  end;
2739
end;
2740

2741
procedure TGLTexture.UnApply(var rci: TGLRenderContextInfo);
2742
begin
2743
  if not Disabled
2744
    and not rci.GLStates.ForwardContext then
2745
  begin
2746
    // Multisample image do not work with FFP
2747
    if FTextureHandle.Target in [ttNoShape, ttTexture2DMultisample, ttTexture2DMultisampleArray] then
2748
      exit;
2749
    with rci.GLStates do
2750
    begin
2751
      ActiveTexture := 0;
2752
      ActiveTextureEnabled[FTextureHandle.Target] := False;
2753
      if FTextureHandle.Target = ttTextureCube then
2754
        ResetGLTextureMatrix;
2755
    end;
2756
    UnApplyMappingMode;
2757
  end;
2758
end;
2759

2760
procedure TGLTexture.ApplyAsTexture2(var rci: TGLRenderContextInfo; textureMatrix:
2761
  PMatrix = nil);
2762
begin
2763
  ApplyAsTextureN(2, rci, textureMatrix);
2764
end;
2765

2766
procedure TGLTexture.UnApplyAsTexture2(var rci: TGLRenderContextInfo;
2767
  reloadIdentityTextureMatrix: boolean);
2768
begin
2769
  UnApplyAsTextureN(2, rci, reloadIdentityTextureMatrix);
2770
end;
2771

2772
procedure TGLTexture.ApplyAsTextureN(n: Integer; var rci: TGLRenderContextInfo;
2773
  textureMatrix: PMatrix = nil);
2774
var
2775
  m: TMatrix;
2776
begin
2777
  if not Disabled then
2778
  begin
2779
    // Multisample image do not work with FFP
2780
    if (FTextureHandle.Target = ttTexture2DMultisample) or
2781
      (FTextureHandle.Target = ttTexture2DMultisampleArray) then
2782
      exit;
2783
    with rci.GLStates do
2784
    begin
2785
      ActiveTexture := n - 1;
2786
      TextureBinding[n - 1, FTextureHandle.Target] := Handle;
2787
      ActiveTextureEnabled[FTextureHandle.Target] := True;
2788
      if Assigned(textureMatrix) then
2789
        SetGLTextureMatrix(textureMatrix^)
2790
      else if FTextureHandle.Target = ttTextureCube then
2791
      begin
2792
        m := rci.PipelineTransformation.ModelViewMatrix;
2793
        NormalizeMatrix(m);
2794
        TransposeMatrix(m);
2795
        rci.GLStates.SetGLTextureMatrix(m);
2796
      end;
2797

2798
      if not ForwardContext then
2799
      begin
2800
        GL.TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, cTextureMode[FTextureMode]);
2801
        GL.TexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, FEnvColor.AsAddress);
2802
        ApplyMappingMode;
2803
        ActiveTexture := 0;
2804
      end;
2805
    end;
2806
  end;
2807
end;
2808

2809
procedure TGLTexture.UnApplyAsTextureN(n: Integer; var rci: TGLRenderContextInfo;
2810
  reloadIdentityTextureMatrix: boolean);
2811
begin
2812
  if not rci.GLStates.ForwardContext then
2813
  begin
2814
    // Multisample image do not work with FFP
2815
    if (FTextureHandle.Target = ttTexture2DMultisample) or
2816
      (FTextureHandle.Target = ttTexture2DMultisampleArray) then
2817
      exit;
2818
    with rci.GLStates do
2819
    begin
2820
      ActiveTexture := n - 1;
2821
      ActiveTextureEnabled[FTextureHandle.Target] := False;
2822
      UnApplyMappingMode;
2823
      if (FTextureHandle.Target = ttTextureCube) or reloadIdentityTextureMatrix then
2824
        ResetGLTextureMatrix;
2825
      ActiveTexture := 0;
2826
    end;
2827
  end;
2828
end;
2829

2830
function TGLTexture.AllocateHandle: TGLuint;
2831
var
2832
  vTarget: TGLTextureTarget;
2833
begin
2834
  vTarget := Image.NativeTextureTarget;
2835
  if (vTarget <> ttNoShape) and (FTextureHandle.Target <> vTarget) then
2836
    FTextureHandle.DestroyHandle;
2837

2838
  Result := FTextureHandle.Handle;
2839
  if Result = 0 then
2840
  begin
2841
    FTextureHandle.AllocateHandle;
2842
    Result := FTextureHandle.Handle;
2843
  end;
2844
  if FTextureHandle.IsDataNeedUpdate then
2845
  begin
2846
    FTextureHandle.Target := vTarget;
2847
    FSamplerHandle.NotifyChangesOfData;
2848
  end;
2849
  if FSamplerHandle.Handle = 0 then
2850
    FSamplerHandle.AllocateHandle;
2851

2852
  // bind texture
2853
  if (FTextureHandle.Target <> ttNoShape) and
2854
    IsTargetSupported(FTextureHandle.Target) then
2855
  begin
2856
    if FSamplerHandle.IsDataNeedUpdate then
2857
    begin
2858
      with CurrentGLContext.GLStates do
2859
        TextureBinding[ActiveTexture, FTextureHandle.Target] := Result;
2860
      PrepareParams(DecodeGLTextureTarget(FTextureHandle.Target));
2861
      FSamplerHandle.NotifyDataUpdated;
2862
    end;
2863
  end
2864
  else
2865
    Result := 0;
2866
end;
2867

2868
function TGLTexture.IsHandleAllocated: Boolean;
2869
begin
2870
  Result := (FTextureHandle.Handle <> 0);
2871
end;
2872

2873

2874
function TGLTexture.GetHandle: TGLuint;
2875
var
2876
  target: TGLUInt;
2877
  LBinding: array[TGLTextureTarget] of TGLuint;
2878

2879
  procedure StoreBindings;
2880
  var
2881
    t: TGLTextureTarget;
2882
  begin
2883
    with CurrentGLContext.GLStates do
2884
    begin
2885
      if TextureBinding[ActiveTexture, FTextureHandle.Target] = FTextureHandle.Handle then
2886
        TextureBinding[ActiveTexture, FTextureHandle.Target] := 0;
2887
      for t := Low(TGLTextureTarget) to High(TGLTextureTarget) do
2888
        LBinding[t] := TextureBinding[ActiveTexture, t];
2889
    end;
2890
  end;
2891

2892
  procedure RestoreBindings;
2893
  var
2894
    t: TGLTextureTarget;
2895
  begin
2896
    with CurrentGLContext.GLStates do
2897
      for t := Low(TGLTextureTarget) to High(TGLTextureTarget) do
2898
        TextureBinding[ActiveTexture, t] := LBinding[t];
2899
  end;
2900

2901
begin
2902
  with CurrentGLContext.GLStates do
2903
  begin
2904
    StoreBindings;
2905
    try
2906
      Result := AllocateHandle;
2907
      if FTextureHandle.IsDataNeedUpdate then
2908
      begin
2909
        FTextureHandle.NotifyDataUpdated;
2910
        // Check supporting
2911
        target := DecodeGLTextureTarget(Image.NativeTextureTarget);
2912
        if not IsTargetSupported(target) or not IsFormatSupported(TextureFormatEx) then
2913
        begin
2914
          SetTextureErrorImage;
2915
          target := GL_TEXTURE_2D;
2916
        end;
2917
        // Load images
2918
        if not GL.EXT_direct_state_access then
2919
          TextureBinding[ActiveTexture, FTextureHandle.Target] := Result;
2920
        PrepareImage(target);
2921
      end;
2922
    finally
2923
      RestoreBindings;
2924
    end;
2925
  end;
2926
end;
2927

2928
procedure TGLTexture.DestroyHandles;
2929
begin
2930
  FTextureHandle.DestroyHandle;
2931
  FSamplerHandle.DestroyHandle;
2932
  FRequiredMemorySize := -1;
2933
end;
2934

2935
function TGLTexture.IsFloatType: Boolean;
2936
begin
2937
  Result := IsFloatFormat(TextureFormatEx);
2938
end;
2939

2940
function TGLTexture.OpenGLTextureFormat: Integer;
2941
var
2942
  texComp: TGLTextureCompression;
2943
begin
2944
  if GL.ARB_texture_compression then
2945
  begin
2946
    if Compression = tcDefault then
2947
      if vDefaultTextureCompression = tcDefault then
2948
        texComp := tcNone
2949
      else
2950
        texComp := vDefaultTextureCompression
2951
    else
2952
      texComp := Compression;
2953
  end
2954
  else
2955
    texComp := tcNone;
2956

2957
  if IsFloatType then
2958
    texComp := tcNone; // no compression support for float_type
2959

2960
  if (texComp <> tcNone) and (TextureFormat <= tfNormalMap) then
2961
    with CurrentGLContext.GLStates do
2962
    begin
2963
      case texComp of
2964
        tcStandard: TextureCompressionHint := hintDontCare;
2965
        tcHighQuality: TextureCompressionHint := hintNicest;
2966
        tcHighSpeed: TextureCompressionHint := hintFastest;
2967
      else
2968
        Assert(False);
2969
      end;
2970
      Result := CompressedInternalFormatToOpenGL(TextureFormatEx);
2971
    end
2972
  else
2973
    Result := InternalFormatToOpenGLFormat(TextureFormatEx);
2974
end;
2975

2976
procedure TGLTexture.PrepareImage(target: TGLUInt);
2977
var
2978
  bitmap32: TGLImage;
2979
  texComp: TGLTextureCompression;
2980
  glFormat: TGLEnum;
2981
begin
2982
  if Image.IsSelfLoading then
2983
  begin
2984
    Image.LoadTexture(FTextureFormat);
2985
  end
2986
  else
2987
  begin
2988

2989
    bitmap32 := Image.GetBitmap32;
2990

2991
    if (bitmap32 = nil) or bitmap32.IsEmpty then
2992
      Exit;
2993

2994
    if TextureFormat = tfNormalMap then
2995
      bitmap32.GrayScaleToNormalMap(NormalMapScale,
2996
        TextureWrap in [twBoth, twHorizontal],
2997
        TextureWrap in [twBoth, twVertical]);
2998
    // prepare AlphaChannel
2999
    case ImageAlpha of
3000
      tiaDefault: ; // nothing to do
3001
      tiaAlphaFromIntensity:
3002
        bitmap32.SetAlphaFromIntensity;
3003
      tiaSuperBlackTransparent:
3004
        bitmap32.SetAlphaTransparentForColor($000000);
3005
      tiaLuminance:
3006
        bitmap32.SetAlphaFromIntensity;
3007
      tiaLuminanceSqrt:
3008
        begin
3009
          bitmap32.SetAlphaFromIntensity;
3010
          bitmap32.SqrtAlpha;
3011
        end;
3012
      tiaOpaque:
3013
        bitmap32.SetAlphaToValue(255);
3014
      tiaTopLeftPointColorTransparent:
3015
        begin
3016
          bitmap32.Narrow;
3017
          bitmap32.SetAlphaTransparentForColor(bitmap32.Data^[0]);
3018
        end;
3019
      tiaInverseLuminance:
3020
        begin
3021
          bitmap32.SetAlphaFromIntensity;
3022
          bitmap32.InvertAlpha;
3023
        end;
3024
      tiaInverseLuminanceSqrt:
3025
        begin
3026
          bitmap32.SetAlphaFromIntensity;
3027
          bitmap32.SqrtAlpha;
3028
          bitmap32.InvertAlpha;
3029
        end;
3030
      tiaBottomRightPointColorTransparent:
3031
        begin
3032
          bitmap32.Narrow;
3033
          bitmap32.SetAlphaTransparentForColor(bitmap32.Data^[bitmap32.Width - 1]);
3034
        end;
3035
    else
3036
      Assert(False);
3037
    end;
3038
    // apply brightness correction
3039
    if FImageBrightness <> 1.0 then
3040
      bitmap32.BrightnessCorrection(FImageBrightness);
3041
    // apply gamma correction
3042
    if FImageGamma <> 1.0 then
3043
      bitmap32.GammaCorrection(FImageGamma);
3044

3045
    if GL.ARB_texture_compression
3046
      and (TextureFormat <> tfExtended) then
3047
    begin
3048
      if Compression = tcDefault then
3049
        if vDefaultTextureCompression = tcDefault then
3050
          texComp := tcNone
3051
        else
3052
          texComp := vDefaultTextureCompression
3053
      else
3054
        texComp := Compression;
3055
      if IsFloatType then
3056
        texComp := tcNone;
3057

3058
    end
3059
    else
3060
      texComp := tcNone;
3061

3062
    if (texComp <> tcNone) and (TextureFormat <= tfNormalMap) then
3063
      with CurrentGLContext.GLStates do
3064
      begin
3065
        case texComp of
3066
          tcStandard: TextureCompressionHint := hintDontCare;
3067
          tcHighQuality: TextureCompressionHint := hintNicest;
3068
          tcHighSpeed: TextureCompressionHint := hintFastest;
3069
        else
3070
          Assert(False, glsErrorEx + glsUnknownType);
3071
        end;
3072
        glFormat := CompressedInternalFormatToOpenGL(FTextureFormat);
3073
      end
3074
    else
3075
      glFormat := InternalFormatToOpenGLFormat(FTextureFormat);
3076

3077
    bitmap32.RegisterAsOpenGLTexture(
3078
      FTextureHandle,
3079
      not (FMinFilter in [miNearest, miLinear]),
3080
      glFormat,
3081
      FTexWidth,
3082
      FTexHeight,
3083
      FTexDepth);
3084
  end;
3085

3086
  if GL.GetError <> GL_NO_ERROR then
3087
  begin
3088
    GL.ClearError;
3089
    SetTextureErrorImage;
3090
  end
3091
  else
3092
  begin
3093
    FRequiredMemorySize := -1;
3094
    TextureImageRequiredMemory;
3095
    if not IsDesignTime and not FKeepImageAfterTransfer then
3096
      Image.ReleaseBitmap32;
3097
  end;
3098
end;
3099

3100
procedure TGLTexture.PrepareParams(target: TGLUInt);
3101
const
3102
  cTextureSWrap: array[twBoth..twHorizontal] of TGLEnum =
3103
    (GL_REPEAT, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_REPEAT);
3104
  cTextureTWrap: array[twBoth..twHorizontal] of TGLEnum =
3105
    (GL_REPEAT, GL_CLAMP_TO_EDGE, GL_REPEAT, GL_CLAMP_TO_EDGE);
3106
  cTextureRWrap: array[twBoth..twHorizontal] of TGLEnum =
3107
    (GL_REPEAT, GL_CLAMP_TO_EDGE, GL_REPEAT, GL_CLAMP_TO_EDGE);
3108
  cTextureSWrapOld: array[twBoth..twHorizontal] of TGLEnum =
3109
    (GL_REPEAT, GL_CLAMP, GL_CLAMP, GL_REPEAT);
3110
  cTextureTWrapOld: array[twBoth..twHorizontal] of TGLEnum =
3111
    (GL_REPEAT, GL_CLAMP, GL_REPEAT, GL_CLAMP);
3112
  cTextureMagFilter: array[maNearest..maLinear] of TGLEnum =
3113
    (GL_NEAREST, GL_LINEAR);
3114
  cTextureMinFilter: array[miNearest..miLinearMipmapLinear] of TGLEnum =
3115
    (GL_NEAREST, GL_LINEAR, GL_NEAREST_MIPMAP_NEAREST,
3116
    GL_LINEAR_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR,
3117
    GL_LINEAR_MIPMAP_LINEAR);
3118
  cFilteringQuality: array[tfIsotropic..tfAnisotropic] of Integer = (1, 2);
3119
  cSeparateTextureWrap: array[twRepeat..twMirrorClampToBorder] of TGLenum =
3120
    (GL_REPEAT, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER,
3121
    GL_MIRRORED_REPEAT, GL_MIRROR_CLAMP_TO_EDGE_ATI, GL_MIRROR_CLAMP_TO_BORDER_EXT);
3122
  cTextureCompareMode: array[tcmNone..tcmCompareRtoTexture] of TGLenum =
3123
    (GL_NONE, GL_COMPARE_R_TO_TEXTURE);
3124
  cDepthTextureMode: array[dtmLuminance..dtmAlpha] of TGLenum =
3125
    (GL_LUMINANCE, GL_INTENSITY, GL_ALPHA);
3126

3127
var
3128
  R_Dim: Boolean;
3129
  lMinFilter: TGLMinFilter;
3130
begin
3131
  if (target = GL_TEXTURE_2D_MULTISAMPLE)
3132
    or (target = GL_TEXTURE_2D_MULTISAMPLE_ARRAY) then
3133
    Exit;
3134

3135
  R_Dim := GL.ARB_texture_cube_map or GL.EXT_texture3D;
3136

3137
  with CurrentGLContext.GLStates do
3138
  begin
3139
    UnpackAlignment := 1;
3140
    UnpackRowLength := 0;
3141
    UnpackSkipRows := 0;
3142
    UnpackSkipPixels := 0;
3143
  end;
3144

3145
  GL.TexParameterfv(target, GL_TEXTURE_BORDER_COLOR, FBorderColor.AsAddress);
3146

3147
  if (GL.VERSION_1_2 or GL.EXT_texture_edge_clamp) then
3148
  begin
3149
    if FTextureWrap = twSeparate then
3150
    begin
3151
      GL.TexParameteri(target, GL_TEXTURE_WRAP_S,
3152
        cSeparateTextureWrap[FTextureWrapS]);
3153
      GL.TexParameteri(target, GL_TEXTURE_WRAP_T,
3154
        cSeparateTextureWrap[FTextureWrapT]);
3155
      if R_Dim then
3156
        GL.TexParameteri(target, GL_TEXTURE_WRAP_R,
3157
          cSeparateTextureWrap[FTextureWrapR]);
3158
    end
3159
    else
3160
    begin
3161
      GL.TexParameteri(target, GL_TEXTURE_WRAP_S, cTextureSWrap[FTextureWrap]);
3162
      GL.TexParameteri(target, GL_TEXTURE_WRAP_T, cTextureTWrap[FTextureWrap]);
3163
      if R_Dim then
3164
        GL.TexParameteri(target, GL_TEXTURE_WRAP_R, cTextureRWrap[FTextureWrap]);
3165
    end;
3166
  end
3167
  else
3168
  begin
3169
    GL.TexParameteri(target, GL_TEXTURE_WRAP_S, cTextureSWrapOld[FTextureWrap]);
3170
    GL.TexParameteri(target, GL_TEXTURE_WRAP_T, cTextureTWrapOld[FTextureWrap]);
3171
  end;
3172

3173
  lMinFilter := FMinFilter;
3174
  // Down paramenter to rectangular texture supported
3175
  if (target = GL_TEXTURE_RECTANGLE)
3176
    or not (GL.EXT_texture_lod or GL.SGIS_texture_lod) then
3177
  begin
3178
    if lMinFilter in [miNearestMipmapNearest, miNearestMipmapLinear] then
3179
      lMinFilter := miNearest;
3180
    if FMinFilter in [miLinearMipmapNearest, miLinearMipmapLinear] then
3181
      lMinFilter := miLinear;
3182
  end;
3183

3184
  GL.TexParameteri(target, GL_TEXTURE_MIN_FILTER, cTextureMinFilter[lMinFilter]);
3185
  GL.TexParameteri(target, GL_TEXTURE_MAG_FILTER, cTextureMagFilter[FMagFilter]);
3186

3187
  if GL.EXT_texture_filter_anisotropic then
3188
    GL.TexParameteri(target, GL_TEXTURE_MAX_ANISOTROPY_EXT,
3189
      cFilteringQuality[FFilteringQuality]);
3190

3191
  if IsDepthFormat(fTextureFormat) then
3192
  begin
3193
    GL.TexParameteri(target, GL_TEXTURE_COMPARE_MODE,
3194
      cTextureCompareMode[fTextureCompareMode]);
3195
    GL.TexParameteri(target, GL_TEXTURE_COMPARE_FUNC,
3196
      cGLComparisonFunctionToGLEnum[fTextureCompareFunc]);
3197
    if not FTextureHandle.RenderingContext.GLStates.ForwardContext then
3198
      GL.TexParameteri(target, GL_DEPTH_TEXTURE_MODE,
3199
        cDepthTextureMode[fDepthTextureMode]);
3200
  end;
3201
end;
3202

3203
procedure TGLTexture.DoOnTextureNeeded(Sender: TObject; var textureFileName:
3204
  string);
3205
begin
3206
  if Assigned(FOnTextureNeeded) then
3207
    FOnTextureNeeded(Sender, textureFileName);
3208
end;
3209

3210
procedure TGLTexture.OnSamplerAllocate(Sender: TGLVirtualHandle; var Handle: Cardinal);
3211
begin
3212
  Handle := 1;
3213
end;
3214

3215
procedure TGLTexture.OnSamplerDestroy(Sender: TGLVirtualHandle; var Handle: Cardinal);
3216
begin
3217
  Handle := 0;
3218
end;
3219

3220
procedure TGLTexture.SetTextureErrorImage;
3221
var
3222
  img: TGLImage;
3223
begin
3224
  img := TGLImage.Create;
3225
  img.SetErrorImage;
3226

3227
  ImageClassName := TGLBlankImage.className;
3228
  TGLBlankImage(Image).Assign(img);
3229
  img.Free;
3230

3231
  MagFilter := maNearest;
3232
  MinFilter := miNearest;
3233
  TextureWrap := twBoth;
3234
  MappingMode := tmmUser;
3235
  Compression := tcNone;
3236
  AllocateHandle;
3237
end;
3238

3239

3240
{%endregion%}
3241

3242
{%region%=====  'TGLTextureExItem ================================}
3243

3244
constructor TGLTextureExItem.Create(ACollection: TCollection);
3245
begin
3246
  inherited;
3247

3248
  FTexture := TGLTexture.Create(Self);
3249
  FTextureOffset := TGLCoordinates.CreateInitialized(Self, NullHMGVector,
3250
    csPoint);
3251
  FTextureOffset.OnNotifyChange := OnNotifyChange;
3252
  FTextureScale := TGLCoordinates.CreateInitialized(Self, XYZHmgVector,
3253
    csPoint);
3254
  FTextureScale.OnNotifyChange := OnNotifyChange;
3255

3256
  FTextureIndex := ID;
3257
  FTextureMatrix := IdentityHMGMatrix;
3258

3259
  //DanB - hmmm, not very flexible code, assumes it's owned by a material,
3260
  // that has a Texture property, but may need to re-implement it somehow
3261
{  if ACollection is TGLTextureEx then
3262
    if TGLTextureEx(ACollection).FOwner <> nil then
3263
      FTexture.OnTextureNeeded := TGLTextureEx(ACollection).FOwner.Texture.OnTextureNeeded;
3264
      }
3265
end;
3266

3267

3268
destructor TGLTextureExItem.Destroy;
3269
begin
3270
  FTexture.Free;
3271
  FTextureOffset.Free;
3272
  FTextureScale.Free;
3273

3274
  inherited;
3275
end;
3276

3277

3278
  function TGLTextureExItem.QueryInterface(constref IID: TGUID; out Obj): HResult; {$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
3279

3280

3281
begin
3282
  if GetInterface(IID, Obj) then
3283
    Result := S_OK
3284
  else
3285
    Result := E_NOINTERFACE;
3286
end;
3287

3288

3289
  function TGLTextureExItem._AddRef: Integer; {$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
3290

3291

3292
begin
3293
  Result := -1; //ignore
3294
end;
3295

3296
  function TGLTextureExItem._Release: Integer; {$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
3297

3298

3299
begin
3300
  Result := -1; //ignore
3301
end;
3302

3303
procedure TGLTextureExItem.Assign(Source: TPersistent);
3304
begin
3305
  if Source is TGLTextureExItem then
3306
  begin
3307
    Texture := TGLTextureExItem(Source).Texture;
3308
    TextureIndex := TGLTextureExItem(Source).TextureIndex;
3309
    TextureOffset := TGLTextureExItem(Source).TextureOffset;
3310
    TextureScale := TGLTextureExItem(Source).TextureScale;
3311
    NotifyChange(Self);
3312
  end
3313
  else
3314
    inherited;
3315
end;
3316

3317
procedure TGLTextureExItem.NotifyChange(Sender: TObject);
3318
begin
3319
  if Assigned(Collection) then
3320
    TGLTextureEx(Collection).NotifyChange(Self);
3321
end;
3322

3323
procedure TGLTextureExItem.Apply(var rci: TGLRenderContextInfo);
3324
begin
3325
  FApplied := False;
3326
  if FTexture.Enabled then
3327
  begin
3328
    rci.GLStates.ActiveTexture := FTextureIndex;
3329
    GL.MatrixMode(GL_TEXTURE);
3330
    GL.PushMatrix;
3331
    if FTextureMatrixIsIdentity then
3332
      GL.LoadIdentity
3333
    else
3334
      GL.LoadMatrixf(@FTextureMatrix.V[0].V[0]);
3335
    GL.MatrixMode(GL_MODELVIEW);
3336
    rci.GLStates.ActiveTexture := 0;
3337
    if FTextureIndex = 0 then
3338
      FTexture.Apply(rci)
3339
    else if FTextureIndex = 1 then
3340
      FTexture.ApplyAsTexture2(rci, nil)
3341
    else if FTextureIndex >= 2 then
3342
      FTexture.ApplyAsTextureN(FTextureIndex + 1, rci, nil);
3343
    FApplied := True;
3344
  end;
3345
end;
3346

3347
procedure TGLTextureExItem.UnApply(var rci: TGLRenderContextInfo);
3348
begin
3349
  if FApplied then
3350
  begin
3351
    if FTextureIndex = 0 then
3352
      FTexture.UnApply(rci)
3353
    else if FTextureIndex = 1 then
3354
      FTexture.UnApplyAsTexture2(rci, false)
3355
    else if FTextureIndex >= 2 then
3356
      FTexture.UnApplyAsTextureN(FTextureIndex + 1, rci, false);
3357
    rci.GLStates.ActiveTexture := FTextureIndex;
3358
    GL.MatrixMode(GL_TEXTURE);
3359
    GL.PopMatrix;
3360
    GL.MatrixMode(GL_MODELVIEW);
3361
    rci.GLStates.ActiveTexture := 0;
3362
    FApplied := False;
3363
  end;
3364
end;
3365

3366
function TGLTextureExItem.GetDisplayName: string;
3367
begin
3368
  Result := Format('Tex [%d]', [FTextureIndex]);
3369
end;
3370

3371
function TGLTextureExItem.GetOwner: TPersistent;
3372
begin
3373
  Result := Collection;
3374
end;
3375

3376
procedure TGLTextureExItem.NotifyTexMapChange(Sender: TObject);
3377
var
3378
  intf: IGLTextureNotifyAble;
3379
begin
3380
  if Supports(TObject(TGLTextureEx(Collection).FOwner), IGLTextureNotifyAble,
3381
    intf) then
3382
    intf.NotifyTexMapChange(Sender);
3383
end;
3384

3385
procedure TGLTextureExItem.SetTexture(const Value: TGLTexture);
3386
begin
3387
  FTexture.Assign(Value);
3388
  NotifyChange(Self);
3389
end;
3390

3391
procedure TGLTextureExItem.SetTextureIndex(const Value: Integer);
3392
var
3393
  temp: Integer;
3394
begin
3395
  temp := Value;
3396
  if temp < 0 then
3397
    temp := 0;
3398
  if temp <> FTextureIndex then
3399
  begin
3400
    FTextureIndex := temp;
3401
    NotifyChange(Self);
3402
  end;
3403
end;
3404

3405
procedure TGLTextureExItem.SetTextureOffset(const Value: TGLCoordinates);
3406
begin
3407
  FTextureOffset.Assign(Value);
3408
  NotifyChange(Self);
3409
end;
3410

3411
procedure TGLTextureExItem.SetTextureScale(const Value: TGLCoordinates);
3412
begin
3413
  FTextureScale.Assign(Value);
3414
  NotifyChange(Self);
3415
end;
3416

3417
procedure TGLTextureExItem.CalculateTextureMatrix;
3418
begin
3419
  if TextureOffset.Equals(NullHmgVector) and TextureScale.Equals(XYZHmgVector) then
3420
    FTextureMatrixIsIdentity := True
3421
  else
3422
  begin
3423
    FTextureMatrixIsIdentity := False;
3424
    FTextureMatrix := CreateScaleAndTranslationMatrix(TextureScale.AsVector,
3425
      TextureOffset.AsVector);
3426
  end;
3427
  NotifyChange(Self);
3428
end;
3429

3430
procedure TGLTextureExItem.OnNotifyChange(Sender: TObject);
3431
begin
3432
  CalculateTextureMatrix;
3433
end;
3434

3435
{%endregion%}
3436

3437
{%region%===== TGLTextureEx ================================}
3438

3439

3440
constructor TGLTextureEx.Create(AOwner: TGLUpdateAbleObject);
3441
begin
3442
  inherited Create(TGLTextureExItem);
3443

3444
  FOwner := AOwner;
3445
end;
3446

3447

3448
procedure TGLTextureEx.NotifyChange(Sender: TObject);
3449
begin
3450
  if Assigned(FOwner) then
3451
    FOwner.NotifyChange(Self);
3452
end;
3453

3454

3455
procedure TGLTextureEx.Apply(var rci: TGLRenderContextInfo);
3456
var
3457
  i, texUnits: Integer;
3458
  units: Cardinal;
3459
begin
3460
  if not GL.ARB_multitexture then
3461
    exit;
3462

3463
  units := 0;
3464
  GL.GetIntegerv(GL_MAX_TEXTURE_UNITS, @texUnits);
3465
  for i := 0 to Count - 1 do
3466
  begin
3467
    if Items[i].TextureIndex < texUnits then
3468
    begin
3469
      Items[i].Apply(rci);
3470
      if Items[i].FApplied then
3471
        if (Items[i].TextureIndex > 0) and (Items[i].Texture.MappingMode =
3472
          tmmUser) then
3473
          units := units or (1 shl Items[i].TextureIndex);
3474
    end;
3475
  end;
3476
  if units > 0 then
3477
    xgl.MapTexCoordToArbitraryAdd(units);
3478
end;
3479

3480

3481
procedure TGLTextureEx.UnApply(var rci: TGLRenderContextInfo);
3482
var
3483
  i: Integer;
3484
begin
3485
  if not GL.ARB_multitexture then
3486
    exit;
3487
  for i := 0 to Count - 1 do
3488
    Items[i].UnApply(rci);
3489
end;
3490

3491
function TGLTextureEx.Add: TGLTextureExItem;
3492
begin
3493
  Result := TGLTextureExItem(inherited Add);
3494
end;
3495

3496
procedure TGLTextureEx.Loaded;
3497
var
3498
  i: Integer;
3499
begin
3500
  for i := 0 to Count - 1 do
3501
    Items[i].CalculateTextureMatrix;
3502
end;
3503

3504
function TGLTextureEx.GetOwner: TPersistent;
3505
begin
3506
  Result := FOwner;
3507
end;
3508

3509
procedure TGLTextureEx.SetItems(index: Integer; const Value: TGLTextureExItem);
3510
begin
3511
  inherited SetItem(index, Value);
3512
end;
3513

3514
function TGLTextureEx.GetItems(index: Integer): TGLTextureExItem;
3515
begin
3516
  Result := TGLTextureExItem(inherited GetItem(index));
3517
end;
3518

3519
function TGLTextureEx.IsTextureEnabled(Index: Integer): Boolean;
3520
var
3521
  i: Integer;
3522
begin
3523
  Result := False;
3524
  if Self = nil then
3525
    Exit;
3526
  for i := 0 to Count - 1 do
3527
    if Items[i].TextureIndex = Index then
3528
      Result := Result or Items[i].Texture.Enabled;
3529
end;
3530

3531
{%endregion%}
3532

3533
initialization
3534

3535
  RegisterGLTextureImageClass(TGLBlankImage);
3536
  RegisterGLTextureImageClass(TGLPersistentImage);
3537
  RegisterGLTextureImageClass(TGLPicFileImage);
3538
  RegisterGLTextureImageClass(TGLCubeMapImage);
3539

3540
  RegisterTGraphicClassFileExtension('.bmp', TGLBitmap);
3541

3542
finalization
3543

3544
  vGLTextureImageClasses.Free;
3545
  vGLTextureImageClasses := nil;
3546

3547
end.
3548

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.