LZScene

Форк
0
/
GLMaterialEx.pas 
7429 строк · 213.7 Кб
1
//
2
// This unit is part of the GLScene Engine https://github.com/glscene
3
//
4
{
5
  Handles extended material and it components:
6
  textures, samplers, combiners, shaders and etc.
7

8
 Features:
9
   - material can contain different level of applying accordingly to hardware i.e. Feateres scaling.
10
   - if automatically or by user selected level failed, material down to lower level.
11
   - direct state access can be used for uniforms setting.
12
   - economy mode for texture bindig to active units,
13
     i.e. if textures less than maximum units may be not one binding occur per frame.
14

15
  History :  
16
       13/04/11 - Yar - Added TGLASMVertexProgram, fixed multitexturing
17
       11/04/11 - Yar - Added texture internal storing and streaming (yet only 2D images)
18
       11/03/11 - Yar - Created
19
    
20
}
21

22
unit GLMaterialEx;
23

24
interface
25

26
{$I GLScene.inc}
27

28
uses
29
  Classes, SysUtils,
30
  GLRenderContextInfo, GLBaseClasses, GLContext, GLVectorTypes,
31
  GLMaterial, GLTexture, GLColor, GLCoordinates, GLVectorGeometry, GLGraphics,
32
  GLPersistentClasses, GLCrossPlatform, GLState, GLTextureFormat, GLXCollection,
33
  GLTextureCombiners, OpenGLTokens, GLSLParameter,
34
  GLApplicationFileIO, GLStrings, GLImageUtils, GLUtils, XOpenGL,
35
  GLSLog;
36

37

38
type
39

40
  TGLMaterialComponentName = string;
41
  TGLMaterialLibraryEx = class;
42
  TGLMatLibComponents = class;
43
  TGLLibMaterialEx = class;
44
  TGLBaseShaderModel = class;
45
  TGLASMVertexProgram = class;
46

47
  TOnAsmProgSetting = procedure(Sender: TGLASMVertexProgram;
48
    var ARci: TGLRenderContextInfo) of object;
49
  TOnUniformInitialize = procedure(Sender: TGLBaseShaderModel) of object;
50
  TOnUniformSetting = procedure(Sender: TGLBaseShaderModel;
51
    var ARci: TGLRenderContextInfo) of object;
52

53
  // TGLBaseMaterialCollectionItem
54
  //
55

56
  TGLBaseMaterialCollectionItem = class(
57
      TGLXCollectionItem,
58
      IGLMaterialLibrarySupported)
59
  private
60
     
61
    FNameHashKey: Integer;
62
    FUserList: TPersistentObjectList;
63
    FDefferedInit: Boolean;
64
    FNotifying: Boolean;
65
    FIsValid: Boolean;
66
    function GetUserList: TPersistentObjectList;
67
    function GetMaterialLibraryEx: TGLMaterialLibraryEx;
68
  protected
69
     
70
    procedure SetName(const AValue: TGLMaterialComponentName); override;
71
    procedure NotifyChange(Sender: TObject); virtual;
72
    property UserList: TPersistentObjectList read GetUserList;
73
    procedure DoOnPrepare(Sender: TGLContext); virtual; abstract;
74
  public
75
     
76
    destructor Destroy; override;
77

78
    procedure RegisterUser(AUser: TGLUpdateAbleObject);
79
    procedure UnregisterUser(AUser: TGLUpdateAbleObject);
80
    function GetUserCount: Integer;
81
    function GetMaterialLibrary: TGLAbstractMaterialLibrary;
82

83
    property MaterialLibrary: TGLMaterialLibraryEx read GetMaterialLibraryEx;
84
    property IsValid: Boolean read FIsValid;
85
  published
86
     
87
    property Name: TGLMaterialComponentName read GetName write SetName;
88
    { Run-time flag, indicate that resource
89
       should initialize in case of failure material's level. }
90
    property DefferedInit: Boolean read FDefferedInit write FDefferedInit
91
      default False;
92
  end;
93

94
  CGLBaseMaterialCollectionItem = class of TGLBaseMaterialCollectionItem;
95

96
  // TGLLibMaterialProperty
97
  //
98

99
  TGLLibMaterialProperty = class(
100
      TGLUpdateAbleObject,
101
      IGLMaterialLibrarySupported)
102
  protected
103
     
104
    FEnabled: Boolean;
105
    FNextPassName: TGLLibMaterialName;
106
    function GetMaterial: TGLLibMaterialEx;
107
    function GetMaterialLibraryEx: TGLMaterialLibraryEx;
108
    procedure SetEnabled(AValue: Boolean); virtual;
109
    procedure SetNextPass(const AValue: TGLLibMaterialName);
110
    procedure Loaded; virtual;
111
    property NextPass: TGLLibMaterialName read FNextPassName write SetNextPass;
112
  public
113
     
114
    procedure NotifyChange(Sender: TObject); override;
115
    function GetMaterialLibrary: TGLAbstractMaterialLibrary;
116

117
    property MaterialLibrary: TGLMaterialLibraryEx read GetMaterialLibraryEx;
118
  published
119
     
120
    property Enabled: Boolean read FEnabled write SetEnabled;
121
  end;
122

123
  // TGLTextureSampler
124
  //
125

126
  TGLTextureSampler = class(TGLBaseMaterialCollectionItem)
127
  protected
128
     
129
    procedure WriteToFiler(AWriter: TWriter); override;
130
    procedure ReadFromFiler(AReader: TReader); override;
131
  private
132
     
133
    FHandle: TGLSamplerHandle;
134
    FMinFilter: TGLMinFilter;
135
    FMagFilter: TGLMagFilter;
136
    FFilteringQuality: TGLTextureFilteringQuality;
137
    FLODBias: Integer;
138
    FLODBiasFract: Single;
139
    FWrap: array[0..2] of TGLSeparateTextureWrap;
140
    FBorderColor: TGLColor;
141
    FCompareMode: TGLTextureCompareMode;
142
    FCompareFunc: TDepthFunction;
143
    FDecodeSRGB: Boolean;
144
    procedure SetMagFilter(AValue: TGLMagFilter);
145
    procedure SetMinFilter(AValue: TGLMinFilter);
146
    procedure SetLODBias(AValue: Integer);
147
    procedure SetFilteringQuality(AValue: TGLTextureFilteringQuality);
148
    function GetWrap(Index: Integer): TGLSeparateTextureWrap;
149
    procedure SetWrap(Index: Integer; AValue: TGLSeparateTextureWrap);
150
    procedure SetBorderColor(const AValue: TGLColor);
151
    procedure SetCompareMode(AValue: TGLTextureCompareMode);
152
    procedure SetCompareFunc(AValue: TDepthFunction);
153
    procedure SetDecodeSRGB(AValue: Boolean);
154
  public
155
     
156
    constructor Create(AOwner: TGLXCollection); override;
157
    destructor Destroy; override;
158
    procedure Assign(Source: TPersistent); override;
159

160
    procedure NotifyChange(Sender: TObject); override;
161

162
    procedure DoOnPrepare(Sender: TGLContext); override;
163
    procedure Apply(var ARci: TGLRenderContextInfo);
164
    procedure UnApply(var ARci: TGLRenderContextInfo);
165

166
    class function FriendlyName: string; override;
167

168
    property Handle: TGLSamplerHandle read FHandle;
169
  published
170
     
171

172
    { Texture magnification filter. }
173
    property MagFilter: TGLMagFilter read FMagFilter write SetMagFilter
174
      default maLinear;
175
    { Texture minification filter. }
176
    property MinFilter: TGLMinFilter read FMinFilter write SetMinFilter
177
      default miLinearMipMapLinear;
178
    property FilteringQuality: TGLTextureFilteringQuality read FFilteringQuality
179
      write SetFilteringQuality default tfAnisotropic;
180
    { : Texture LOD bias. }
181
    property LodBias: Integer read FLODBias write SetLODBias default 0;
182
    { : Address mode for the texture. }
183
    property WrapX: TGLSeparateTextureWrap index 0 read GetWrap write SetWrap
184
      default twRepeat;
185
    property WrapY: TGLSeparateTextureWrap index 1 read GetWrap write SetWrap
186
      default twRepeat;
187
    property WrapZ: TGLSeparateTextureWrap index 2 read GetWrap write SetWrap
188
      default twRepeat;
189
    { : Texture border color. }
190
    property BorderColor: TGLColor read FBorderColor
191
      write SetBorderColor;
192
    { : Compare mode and function for depth texture. }
193
    property CompareMode: TGLTextureCompareMode read FCompareMode
194
      write SetCompareMode default tcmNone;
195
    property CompareFunc: TDepthFunction read FCompareFunc
196
      write SetCompareFunc default cfLEqual;
197
    { Force retrieving the undecoded sRGB data from the
198
       texture and manipulate that directly. }
199
    property sRGB_Encode: Boolean read FDecodeSRGB write SetDecodeSRGB
200
      default True;
201
  end;
202

203
  // TGLAbstractTexture
204
  //
205

206
  TGLAbstractTexture = class(TGLBaseMaterialCollectionItem)
207
  protected
208
     
209
    FHandle: TGLTextureHandle;
210
    FInternalFormat: TGLInternalFormat;
211
    FWidth: Integer;
212
    FHeight: Integer;
213
    FDepth: Integer;
214
    FSwizzles: TSwizzleVector;
215
    FApplicableSampler: TGLTextureSampler;
216
    FLastSampler: TGLTextureSampler;
217
    function GetTextureTarget: TGLTextureTarget;
218
    procedure Apply(var ARci: TGLRenderContextInfo); virtual; abstract;
219
    procedure UnApply(var ARci: TGLRenderContextInfo); virtual; abstract;
220
  public
221
     
222
    property Handle: TGLTextureHandle read FHandle;
223
  published
224
     
225
    property Shape: TGLTextureTarget read GetTextureTarget;
226
  end;
227

228
  TMipmapGenerationMode =
229
    (
230
    mgmNoMip,
231
    mgmLeaveExisting,
232
    mgmOnFly,
233
    mgmBoxFilter,
234
    mgmTriangleFilter,
235
    mgmHermiteFilter,
236
    mgmBellFilter,
237
    mgmSplineFilter,
238
    mgmLanczos3Filter,
239
    mgmMitchellFilter
240
    );
241

242
  // TGLTextureImageEx
243
  //
244

245
  TGLTextureImageEx = class(TGLAbstractTexture)
246
  protected
247
     
248
    procedure WriteToFiler(AWriter: TWriter); override;
249
    procedure ReadFromFiler(AReader: TReader); override;
250
  private
251
     
252
    FCompression: TGLTextureCompression;
253
    FImage: TGLBaseImage;
254
    FImageAlpha: TGLTextureImageAlpha;
255
    FImageBrightness: Single;
256
    FImageGamma: Single;
257
    FHeightToNormalScale: Single;
258
    FSourceFile: string;
259
    FApplyCounter: Integer;
260
    FInternallyStored: Boolean;
261
    FMipGenMode: TMipmapGenerationMode;
262
    FUseStreaming: Boolean;
263
    FBaseLevel: Integer;
264
    FMaxLevel: Integer;
265
    FLastTime: Double;
266
    procedure SetInternalFormat(const AValue: TGLInternalFormat);
267
    procedure SetImageAlpha(const AValue: TGLTextureImageAlpha);
268
    procedure SetImageBrightness(const AValue: Single);
269
    function StoreBrightness: Boolean;
270
    procedure SetImageGamma(const AValue: Single);
271
    function StoreGamma: Boolean;
272
    procedure SetNormalMapScale(const AValue: Single);
273
    function StoreNormalMapScale: Boolean;
274
    procedure SetCompression(const AValue: TGLTextureCompression);
275
    procedure SetSourceFile(AValue: string);
276
    procedure SetInternallyStored(const AValue: Boolean);
277
    procedure SetMipGenMode(const AValue: TMipmapGenerationMode);
278
    procedure SetUseStreaming(const AValue: Boolean);
279
    procedure PrepareImage;
280
    procedure FullTransfer;
281
    procedure StreamTransfer;
282
    procedure CalcLODRange(out AFirstLOD, ALastLOD: Integer);
283
  public
284
     
285
    constructor Create(AOwner: TGLXCollection); override;
286
    destructor Destroy; override;
287
    procedure Assign(Source: TPersistent); override;
288

289
    procedure NotifyChange(Sender: TObject); override;
290

291
    procedure DoOnPrepare(Sender: TGLContext); override;
292
    procedure Apply(var ARci: TGLRenderContextInfo); override;
293
    procedure UnApply(var ARci: TGLRenderContextInfo); override;
294

295
    class function FriendlyName: string; override;
296
  published
297
     
298

299
    // Factual texture properties
300
    property InternalWidth: Integer read FWidth;
301
    property InternalHeight: Integer read FHeight;
302
    property InternalDepth: Integer read FDepth;
303
    property InternalFormat: TGLInternalFormat read FInternalFormat
304
      write SetInternalFormat default tfRGBA8;
305

306
    { Automatic Image Alpha setting.
307
      Allows to control how and if the image's Alpha channel (transparency)
308
      is computed. }
309
    property ImageAlpha: TGLTextureImageAlpha read FImageAlpha write
310
      SetImageAlpha default tiaDefault;
311
    { Texture brightness correction.
312
      This correction is applied upon loading a TGLTextureImage, it's a
313
      simple saturating scaling applied to the RGB components of
314
      the 32 bits image, before it is passed to OpenGL, and before
315
      gamma correction (if any). }
316
    property ImageBrightness: Single read FImageBrightness write
317
      SetImageBrightness stored StoreBrightness;
318
    { Texture gamma correction.
319
      The gamma correction is applied upon loading a TGLTextureImage,
320
      applied to the RGB components of the 32 bits image, before it is
321
      passed to OpenGL, after brightness correction (if any). }
322
    property ImageGamma: Single read FImageGamma write SetImageGamma stored
323
      StoreGamma;
324
    { Texture compression control.
325
      If True the compressed TextureFormat variant (the OpenGL ICD must
326
      support GL_ARB_texture_compression, or this option is ignored). }
327
    property Compression: TGLTextureCompression read FCompression write
328
      SetCompression default tcDefault;
329
    { Normal Map scaling.
330
      Force normal map generation from height map and controls
331
      the intensity of the bumps. }
332
    property HeightToNormalScale: Single read FHeightToNormalScale
333
      write SetNormalMapScale stored StoreNormalMapScale;
334
    { Source file path and name. }
335
    property SourceFile: string read FSourceFile write SetSourceFile;
336
    { Force to store image levels in separate files in ready to transfer format. }
337
    property InternallyStored: Boolean read FInternallyStored
338
      write SetInternallyStored default False;
339
    { Mipmap generation mode. }
340
    property MipGenMode: TMipmapGenerationMode read FMipGenMode
341
      write SetMipGenMode default mgmOnFly;
342
    { Enable streaming loading. }
343
    property UseStreaming: Boolean read FUseStreaming
344
      write SetUseStreaming default False;
345
  end;
346

347
  // TGLFrameBufferAttachment
348
  //
349

350
  TGLFrameBufferAttachment = class(TGLAbstractTexture)
351
  protected
352
     
353
    procedure WriteToFiler(AWriter: TWriter); override;
354
    procedure ReadFromFiler(AReader: TReader); override;
355
  private
356
     
357
    FRenderBufferHandle: TGLRenderbufferHandle;
358
    FLayered: Boolean;
359
    FCubeMap: Boolean;
360
    FSamples: Integer;
361
    FOnlyWrite: Boolean;
362
    FFixedSamplesLocation: Boolean;
363
    procedure SetWidth(AValue: Integer);
364
    procedure SetHeight(AValue: Integer);
365
    procedure SetDepth(AValue: Integer);
366
    procedure SetInternalFormat(const AValue: TGLInternalFormat);
367
    procedure SetOnlyWrite(AValue: Boolean);
368
    procedure SetLayered(AValue: Boolean);
369
    procedure SetCubeMap(AValue: Boolean);
370
    procedure SetSamples(AValue: Integer);
371
    procedure SetFixedSamplesLocation(AValue: Boolean);
372
  public
373
     
374
    constructor Create(AOwner: TGLXCollection); override;
375
    destructor Destroy; override;
376
    procedure Assign(Source: TPersistent); override;
377

378
    procedure NotifyChange(Sender: TObject); override;
379

380
    procedure DoOnPrepare(Sender: TGLContext); override;
381
    procedure Apply(var ARci: TGLRenderContextInfo); override;
382
    procedure UnApply(var ARci: TGLRenderContextInfo); override;
383

384
    class function FriendlyName: string; override;
385
  published
386
     
387
    property InternalWidth: Integer read FWidth
388
      write SetWidth default 256;
389
    property InternalHeight: Integer read FHeight
390
      write SetHeight default 256;
391
    property InternalDepth: Integer read FDepth
392
      write SetDepth default 0;
393
    property InternalFormat: TGLInternalFormat read FInternalFormat
394
      write SetInternalFormat default tfRGBA8;
395
    { This flag makes use render buffer as target which makes
396
        it impossible to read it as texture, but improves efficiency. }
397
    property OnlyWrite: Boolean read FOnlyWrite
398
      write SetOnlyWrite default False;
399
    { Force targe be texture array. }
400
    property Layered: Boolean read FLayered
401
      write SetLayered default False;
402
    { Force target be cube map. }
403
    property CubeMap: Boolean read FCubeMap
404
      write SetCubeMap default False;
405
    { Number of samples. Positive value makes texture be multisample. }
406
    property Samples: Integer read FSamples
407
      write SetSamples default -1;
408
    { FixedSamplesLocation flag makes image will use identical
409
      sample locations and the same number of samples for all texels in
410
      the image, and the sample locations will not depend on the
411
      internalformat or size of the image. }
412
    property FixedSamplesLocation: Boolean read FFixedSamplesLocation
413
      write SetFixedSamplesLocation default False;
414
  end;
415

416
  // TGLTextureSwizzling
417
  //
418
    { Swizzle the components of a texture fetches in
419
        shader or fixed-function pipeline. }
420
  TGLTextureSwizzling = class(TGLUpdateAbleObject)
421
  private
422
     
423
    FSwizzles: TSwizzleVector;
424
    function GetSwizzle(AIndex: Integer): TGLTextureSwizzle;
425
    procedure SetSwizzle(AIndex: Integer; AValue: TGLTextureSwizzle);
426
    function StoreSwizzle(AIndex: Integer): Boolean;
427
  public
428
    constructor Create(AOwner: TPersistent); override;
429
    procedure Assign(Source: TPersistent); override;
430

431
    procedure WriteToFiler(AWriter: TWriter);
432
    procedure ReadFromFiler(AReader: TReader);
433
  published
434
     
435
    property RedFrom: TGLTextureSwizzle index 0 read GetSwizzle
436
      write SetSwizzle stored StoreSwizzle;
437
    property GreenFrom: TGLTextureSwizzle index 1 read GetSwizzle
438
      write SetSwizzle stored StoreSwizzle;
439
    property BlueFrom: TGLTextureSwizzle index 2 read GetSwizzle
440
      write SetSwizzle stored StoreSwizzle;
441
    property AlphaFrom: TGLTextureSwizzle index 3 read GetSwizzle
442
      write SetSwizzle stored StoreSwizzle;
443
  end;
444

445
  // TGLTextureProperties
446
  //
447

448
  TGLTextureProperties = class(TGLLibMaterialProperty)
449
  private
450
     
451
    FLibTextureName: TGLMaterialComponentName;
452
    FLibSamplerName: TGLMaterialComponentName;
453
    FLibTexture: TGLAbstractTexture;
454
    FLibSampler: TGLTextureSampler;
455
    FTextureOffset, FTextureScale: TGLCoordinates;
456
    FTextureRotate: Single;
457
    FTextureMatrixIsIdentity: Boolean;
458
    FTextureOverride: Boolean;
459
    FTextureMatrix: TMatrix;
460
    FMappingMode: TGLTextureMappingMode;
461
    FEnvColor: TGLColor;
462
    FMapSCoordinates: TGLCoordinates4;
463
    FMapTCoordinates: TGLCoordinates4;
464
    FMapRCoordinates: TGLCoordinates4;
465
    FMapQCoordinates: TGLCoordinates4;
466
    FSwizzling: TGLTextureSwizzling;
467
    function GetLibTextureName: TGLMaterialComponentName;
468
    function GetLibSamplerName: TGLMaterialComponentName;
469
    procedure SetLibTextureName(const AValue: TGLMaterialComponentName);
470
    procedure SetLibSamplerName(const AValue: TGLMaterialComponentName);
471
    function GetTextureOffset: TGLCoordinates;
472
    procedure SetTextureOffset(const AValue: TGLCoordinates);
473
    function StoreTextureOffset: Boolean;
474
    function GetTextureScale: TGLCoordinates;
475
    procedure SetTextureScale(const AValue: TGLCoordinates);
476
    function StoreTextureScale: Boolean;
477
    procedure SetTextureMatrix(const AValue: TMatrix);
478
    procedure SetTextureRotate(AValue: Single);
479
    function StoreTextureRotate: Boolean;
480
    procedure SetMappingMode(const AValue: TGLTextureMappingMode);
481
    function GetMappingSCoordinates: TGLCoordinates4;
482
    procedure SetMappingSCoordinates(const AValue: TGLCoordinates4);
483
    function StoreMappingSCoordinates: Boolean;
484
    function GetMappingTCoordinates: TGLCoordinates4;
485
    procedure SetMappingTCoordinates(const AValue: TGLCoordinates4);
486
    function StoreMappingTCoordinates: Boolean;
487
    function GetMappingRCoordinates: TGLCoordinates4;
488
    procedure SetMappingRCoordinates(const AValue: TGLCoordinates4);
489
    function StoreMappingRCoordinates: Boolean;
490
    function GetMappingQCoordinates: TGLCoordinates4;
491
    procedure SetMappingQCoordinates(const AValue: TGLCoordinates4);
492
    function StoreMappingQCoordinates: Boolean;
493
    procedure SetSwizzling(const AValue: TGLTextureSwizzling);
494
    function StoreSwizzling: Boolean;
495
    procedure SetEnvColor(const AValue: TGLColor);
496

497
    procedure CalculateTextureMatrix;
498
    procedure ApplyMappingMode;
499
    procedure UnApplyMappingMode;
500
  protected
501
    procedure Loaded; override;
502
  public
503
     
504
    constructor Create(AOwner: TPersistent); override;
505
    destructor Destroy; override;
506
    procedure Assign(Source: TPersistent); override;
507

508
    procedure NotifyChange(Sender: TObject); override;
509
    procedure Notification(Sender: TObject; Operation: TOperation); override;
510

511
    function IsValid: Boolean;
512
    procedure Apply(var ARci: TGLRenderContextInfo);
513
    procedure UnApply(var ARci: TGLRenderContextInfo);
514

515
    property TextureMatrix: TMatrix read FTextureMatrix write SetTextureMatrix;
516
  published
517
     
518
    property LibTextureName: TGLMaterialComponentName read GetLibTextureName
519
      write SetLibTextureName;
520
    property LibSamplerName: TGLMaterialComponentName read GetLibSamplerName
521
      write SetLibSamplerName;
522
    property TextureOffset: TGLCoordinates read GetTextureOffset write
523
      SetTextureOffset stored StoreTextureOffset;
524
    { Texture coordinates scaling.
525
       Scaling is applied before applying the offset, and is applied
526
       to the texture coordinates, meaning that a scale factor of (2, 2, 2)
527
       will make your texture look twice <i>smaller</i>. }
528
    property TextureScale: TGLCoordinates read GetTextureScale write
529
      SetTextureScale stored StoreTextureScale;
530
    { Texture coordinates rotating.
531
       Rotating is applied after applying offset and scale,
532
       and rotate ST direction around R axis. }
533
    property TextureRotate: Single read FTextureRotate write
534
      SetTextureRotate stored StoreTextureRotate;
535
    { Texture Environment color. }
536
    property EnvColor: TGLColor read FEnvColor write SetEnvColor;
537
    { Texture coordinates mapping mode.
538
    This property controls automatic texture coordinates generation. }
539
    property MappingMode: TGLTextureMappingMode read FMappingMode write
540
      SetMappingMode default tmmUser;
541
    { Texture mapping coordinates mode for S, T, R and Q axis.
542
    This property stores the coordinates for automatic texture
543
    coordinates generation. }
544
    property MappingSCoordinates: TGLCoordinates4 read GetMappingSCoordinates
545
      write SetMappingSCoordinates stored StoreMappingSCoordinates;
546
    property MappingTCoordinates: TGLCoordinates4 read GetMappingTCoordinates
547
      write SetMappingTCoordinates stored StoreMappingTCoordinates;
548
    property MappingRCoordinates: TGLCoordinates4 read GetMappingRCoordinates
549
      write SetMappingRCoordinates stored StoreMappingRCoordinates;
550
    property MappingQCoordinates: TGLCoordinates4 read GetMappingQCoordinates
551
      write SetMappingQCoordinates stored StoreMappingQCoordinates;
552
    { Texture color fetching parameters. }
553
    property Swizzling: TGLTextureSwizzling read FSwizzling write
554
      SetSwizzling stored StoreSwizzling;
555
  end;
556

557
  //  TGLFixedFunctionProperties
558
  //
559
  TGLFixedFunctionProperties = class(TGLLibMaterialProperty)
560
  private
561
     
562
    FFrontProperties: TGLFaceProperties;
563
    FBackProperties: TGLFaceProperties;
564
    FDepthProperties: TGLDepthProperties;
565
    FBlendingMode: TBlendingMode;
566
    FBlendingParams: TGLBlendingParameters;
567
    FTexProp: TGLTextureProperties;
568
    FMaterialOptions: TMaterialOptions;
569
    FFaceCulling: TFaceCulling;
570
    FPolygonMode: TPolygonMode;
571
    FTextureMode: TGLTextureMode;
572
    function GetBackProperties: TGLFaceProperties;
573
    procedure SetBackProperties(AValues: TGLFaceProperties);
574
    procedure SetFrontProperties(AValues: TGLFaceProperties);
575
    procedure SetDepthProperties(AValues: TGLDepthProperties);
576
    procedure SetBlendingMode(const AValue: TBlendingMode);
577
    procedure SetMaterialOptions(const AValue: TMaterialOptions);
578
    procedure SetFaceCulling(const AValue: TFaceCulling);
579
    procedure SetPolygonMode(AValue: TPolygonMode);
580
    procedure SetBlendingParams(const AValue: TGLBlendingParameters);
581
    procedure SetTexProp(AValue: TGLTextureProperties);
582
    procedure SetTextureMode(AValue: TGLTextureMode);
583
  public
584
     
585
    constructor Create(AOwner: TPersistent); override;
586
    destructor Destroy; override;
587
    procedure Assign(Source: TPersistent); override;
588

589
    procedure Apply(var ARci: TGLRenderContextInfo);
590
    procedure UnApply(var ARci: TGLRenderContextInfo);
591
    { Returns True if the material is blended. }
592
    function Blended: Boolean;
593

594
  published
595
     
596
    property MaterialOptions: TMaterialOptions read FMaterialOptions write
597
      SetMaterialOptions default [];
598

599
    property BackProperties: TGLFaceProperties read GetBackProperties write
600
      SetBackProperties;
601
    property FrontProperties: TGLFaceProperties read FFrontProperties write
602
      SetFrontProperties;
603
    property DepthProperties: TGLDepthProperties read FDepthProperties write
604
      SetDepthProperties;
605
    property BlendingMode: TBlendingMode read FBlendingMode write SetBlendingMode
606
      default bmOpaque;
607
    property BlendingParams: TGLBlendingParameters read FBlendingParams write
608
      SetBlendingParams;
609

610
    property FaceCulling: TFaceCulling read FFaceCulling write SetFaceCulling
611
      default fcBufferDefault;
612
    property PolygonMode: TPolygonMode read FPolygonMode write SetPolygonMode
613
      default pmFill;
614
    property Texture: TGLTextureProperties read FTexProp write SetTexProp;
615
    { Texture application mode. }
616
    property TextureMode: TGLTextureMode read FTextureMode write SetTextureMode
617
      default tmDecal;
618
    { Next pass of FFP. }
619
    property NextPass;
620
  end;
621

622
  //  TGLTextureCombiner
623
  //
624

625
  TGLTextureCombiner = class(TGLBaseMaterialCollectionItem)
626
  protected
627
     
628
    procedure WriteToFiler(AWriter: TWriter); override;
629
    procedure ReadFromFiler(AReader: TReader); override;
630
  private
631
     
632
    FHandle: TGLVirtualHandle;
633
    FScript: TStringList;
634
    FCommandCache: TCombinerCache;
635
    procedure SetScript(AValue: TStringList);
636
    procedure DoAllocate(Sender: TGLVirtualHandle; var handle: TGLUint);
637
    procedure DoDeallocate(Sender: TGLVirtualHandle; var handle: TGLUint);
638
  public
639
     
640
    constructor Create(AOwner: TGLXCollection); override;
641
    destructor Destroy; override;
642
    procedure Assign(Source: TPersistent); override;
643

644
    procedure NotifyChange(Sender: TObject); override;
645

646
    procedure DoOnPrepare(Sender: TGLContext); override;
647

648
    class function FriendlyName: string; override;
649
  published
650
     
651
    property Script: TStringList read FScript write SetScript;
652
  end;
653

654
  // TGLARBVertexProgram
655
  //
656

657
  TGLASMVertexProgram = class(TGLBaseMaterialCollectionItem)
658
  protected
659
     
660
    procedure WriteToFiler(AWriter: TWriter); override;
661
    procedure ReadFromFiler(AReader: TReader); override;
662
  private
663
     
664
    FHandle: TGLARBVertexProgramHandle;
665
    FSource: TStringList;
666
    FSourceFile: string;
667
    FInfoLog: string;
668
    procedure SetSource(AValue: TStringList);
669
    procedure SetSourceFile(AValue: string);
670
    function GetHandle: TGLARBVertexProgramHandle;
671
  public
672
     
673
    constructor Create(AOwner: TGLXCollection); override;
674
    destructor Destroy; override;
675
    procedure Assign(Source: TPersistent); override;
676

677
    procedure DoOnPrepare(Sender: TGLContext); override;
678

679
    class function FriendlyName: string; override;
680

681
    procedure NotifyChange(Sender: TObject); override;
682
    property Handle: TGLARBVertexProgramHandle read GetHandle;
683
  published
684
     
685
    property Source: TStringList read FSource write SetSource;
686
    property SourceFile: string read FSourceFile write SetSourceFile;
687
    property InfoLog: string read FInfoLog;
688
  end;
689

690
  TLightDir2TexEnvColor = (
691
    l2eNone,
692
    l2eEnvColor0,
693
    l2eEnvColor1,
694
    l2eEnvColor2,
695
    l2eEnvColor3
696
    );
697

698
  // TGLMultitexturingProperties
699
  //
700

701
  TGLMultitexturingProperties = class(TGLLibMaterialProperty)
702
  private
703
    FLibCombiner: TGLTextureCombiner;
704
    FLibAsmProg: TGLASMVertexProgram;
705
    FLibCombinerName: TGLMaterialComponentName;
706
    FLibAsmProgName: TGLMaterialComponentName;
707
    FTexProps: array[0..3] of TGLTextureProperties;
708
    FTextureMode: TGLTextureMode;
709
    FLightDir: TLightDir2TexEnvColor;
710
    FLightSourceIndex: Integer;
711
    function GetLibCombinerName: string;
712
    function GetLibAsmProgName: string;
713
    procedure SetLibCombinerName(const AValue: string);
714
    procedure SetLibAsmProgName(const AValue: string);
715
    function GetTexProps(AIndex: Integer): TGLTextureProperties;
716
    procedure SetTexProps(AIndex: Integer; AValue: TGLTextureProperties);
717
    procedure SetTextureMode(AValue: TGLTextureMode);
718
    procedure SetLightSourceIndex(AValue: Integer);
719
  protected
720
    procedure Loaded; override;
721
  public
722
     
723
    constructor Create(AOwner: TPersistent); override;
724
    destructor Destroy; override;
725

726
    procedure Notification(Sender: TObject; Operation: TOperation); override;
727

728
    function IsValid: Boolean;
729
    procedure Apply(var ARci: TGLRenderContextInfo);
730
    procedure UnApply(var ARci: TGLRenderContextInfo);
731
  published
732
     
733
    property LibCombinerName: string read GetLibCombinerName
734
      write SetLibCombinerName;
735
    property LibAsmProgName: string read GetLibAsmProgName
736
      write SetLibAsmProgName;
737
    property Texture0: TGLTextureProperties index 0 read GetTexProps write
738
      SetTexProps;
739
    property Texture1: TGLTextureProperties index 1 read GetTexProps write
740
      SetTexProps;
741
    property Texture2: TGLTextureProperties index 2 read GetTexProps write
742
      SetTexProps;
743
    property Texture3: TGLTextureProperties index 3 read GetTexProps write
744
      SetTexProps;
745
    { Texture application mode. }
746
    property TextureMode: TGLTextureMode read FTextureMode write SetTextureMode
747
      default tmDecal;
748
    { Pass light source direction to enviroment color of choosen texture.
749
       Vector in model space. }
750
    property LightDirTo: TLightDir2TexEnvColor read FLightDir
751
      write FLightDir default l2eNone;
752
    { Specify index of light source for LightDirTo. }
753
    property LightSourceIndex: Integer read FLightSourceIndex
754
      write SetLightSourceIndex default 0;
755
    { Next pass of combiner. }
756
    property NextPass;
757
  end;
758

759
  TGLShaderType =
760
    (
761
    shtVertex,
762
    shtControl,
763
    shtEvaluation,
764
    shtGeometry,
765
    shtFragment
766
    );
767

768
  // TGLSLShaderEx
769
  //
770

771
  TGLShaderEx = class(TGLBaseMaterialCollectionItem)
772
  protected
773
     
774
    procedure WriteToFiler(AWriter: TWriter); override;
775
    procedure ReadFromFiler(AReader: TReader); override;
776
  private
777
     
778
    FHandle: array[TGLShaderType] of TGLShaderHandle;
779
    FSource: TStringList;
780
    FSourceFile: string;
781
    FShaderType: TGLShaderType;
782
    FInfoLog: string;
783
    FGeometryInput: TGLgsInTypes;
784
    FGeometryOutput: TGLgsOutTypes;
785
    FGeometryVerticesOut: TGLint;
786
    procedure SetSource(AValue: TStringList);
787
    procedure SetSourceFile(AValue: string);
788
    procedure SetShaderType(AValue: TGLShaderType);
789
    procedure SetGeometryInput(AValue: TGLgsInTypes);
790
    procedure SetGeometryOutput(AValue: TGLgsOutTypes);
791
    procedure SetGeometryVerticesOut(AValue: TGLint);
792
    function GetHandle: TGLShaderHandle;
793
  public
794
     
795
    constructor Create(AOwner: TGLXCollection); override;
796
    destructor Destroy; override;
797
    procedure Assign(Source: TPersistent); override;
798

799
    procedure DoOnPrepare(Sender: TGLContext); override;
800

801
    class function FriendlyName: string; override;
802

803
    procedure NotifyChange(Sender: TObject); override;
804
    property Handle: TGLShaderHandle read GetHandle;
805
  published
806
     
807
    property Source: TStringList read FSource write SetSource;
808
    property SourceFile: string read FSourceFile write SetSourceFile;
809
    property ShaderType: TGLShaderType read FShaderType
810
      write SetShaderType default shtVertex;
811
    property InfoLog: string read FInfoLog;
812
    property GeometryInput: TGLgsInTypes read FGeometryInput
813
      write SetGeometryInput default gsInPoints;
814
    property GeometryOutput: TGLgsOutTypes read FGeometryOutput
815
      write SetGeometryOutput default gsOutPoints;
816
    property GeometryVerticesOut: TGLint read FGeometryVerticesOut
817
      write SetGeometryVerticesOut default 1;
818
  end;
819

820
  // TGLAbstractShaderUniform
821
  //
822

823
  TGLAbstractShaderUniform = class(TGLUpdateAbleObject, IShaderParameter)
824
  protected
825
     
826
    FName: string;
827
    FNameHashCode: Integer;
828
    FType: TGLSLDataType;
829
    FSamplerType: TGLSLSamplerType;
830

831
    function GetName: string;
832
    function GetGLSLType: TGLSLDataType;
833
    function GetGLSLSamplerType: TGLSLSamplerType;
834

835
    function GetAutoSetMethod: string; virtual;
836
    function GetTextureName: string; virtual;
837
    function GetSamplerName: string; virtual;
838
    function GetTextureSwizzle: TSwizzleVector; virtual;
839
    procedure SetTextureName(const AValue: string); virtual;
840
    procedure SetSamplerName(const AValue: string); virtual;
841
    procedure SetAutoSetMethod(const AValue: string); virtual;
842
    procedure SetTextureSwizzle(const AValue: TSwizzleVector); virtual;
843

844
    function GetFloat: Single; virtual;
845
    function GetVec2: TVector2f; virtual;
846
    function GetVec3: TVector3f; virtual;
847
    function GetVec4: TVector; virtual;
848

849
    function GetInt: TGLint; virtual;
850
    function GetIVec2: TVector2i; virtual;
851
    function GetIVec3: TVector3i; virtual;
852
    function GetIVec4: TVector4i; virtual;
853

854
    function GetUInt: TGLuint; virtual;
855
    function GetUVec2: TVector2ui; virtual;
856
    function GetUVec3: TVector3ui; virtual;
857
    function GetUVec4: TVector4ui; virtual;
858

859
    procedure SetFloat(const Value: TGLFloat); virtual;
860
    procedure SetVec2(const Value: TVector2f); virtual;
861
    procedure SetVec3(const Value: TVector3f); virtual;
862
    procedure SetVec4(const Value: TVector4f); virtual;
863

864
    procedure SetInt(const Value: Integer); virtual;
865
    procedure SetIVec2(const Value: TVector2i); virtual;
866
    procedure SetIVec3(const Value: TVector3i); virtual;
867
    procedure SetIVec4(const Value: TVector4i); virtual;
868

869
    procedure SetUInt(const Value: GLuint); virtual;
870
    procedure SetUVec2(const Value: TVector2ui); virtual;
871
    procedure SetUVec3(const Value: TVector3ui); virtual;
872
    procedure SetUVec4(const Value: TVector4ui); virtual;
873

874
    function GetMat2: TMatrix2f; virtual;
875
    function GetMat3: TMatrix3f; virtual;
876
    function GetMat4: TMatrix4f; virtual;
877
    procedure SetMat2(const Value: TMatrix2f); virtual;
878
    procedure SetMat3(const Value: TMatrix3f); virtual;
879
    procedure SetMat4(const Value: TMatrix4f); virtual;
880

881
    procedure SetFloatArray(const Values: PGLFloat; Count: Integer); virtual;
882
    procedure SetIntArray(const Values: PGLInt; Count: Integer); virtual;
883
    procedure SetUIntArray(const Values: PGLUInt; Count: Integer); virtual;
884

885
    procedure WriteToFiler(AWriter: TWriter); virtual;
886
    procedure ReadFromFiler(AReader: TReader); virtual;
887
    procedure Apply(var ARci: TGLRenderContextInfo); virtual;
888
  end;
889

890
  CGLAbstractShaderUniform = class of TGLAbstractShaderUniform;
891

892
  // TGLShaderUniform
893
  //
894

895
  TGLShaderUniform = class(TGLAbstractShaderUniform, IShaderParameter)
896
  protected
897
     
898
    FLocation: TGLint;
899
    FStoreProgram: TGLuint;
900
    FAutoSet: TUniformAutoSetMethod;
901
    function GetProgram: TGLuint;
902
{$IFDEF GLS_INLINE} inline;
903
{$ENDIF}
904
    procedure PushProgram;
905
{$IFDEF GLS_INLINE} inline;
906
{$ENDIF}
907
    procedure PopProgram;
908
{$IFDEF GLS_INLINE} inline;
909
{$ENDIF}
910

911
    function GetFloat: Single; override;
912
    function GetVec2: TVector2f; override;
913
    function GetVec3: TVector3f; override;
914
    function GetVec4: TVector; override;
915

916
    function GetInt: TGLint; override;
917
    function GetIVec2: TVector2i; override;
918
    function GetIVec3: TVector3i; override;
919
    function GetIVec4: TVector4i; override;
920

921
    function GetUInt: TGLuint; override;
922
    function GetUVec2: TVector2ui; override;
923
    function GetUVec3: TVector3ui; override;
924
    function GetUVec4: TVector4ui; override;
925

926
    procedure SetFloat(const Value: TGLFloat); override;
927
    procedure SetVec2(const Value: TVector2f); override;
928
    procedure SetVec3(const Value: TVector3f); override;
929
    procedure SetVec4(const Value: TVector4f); override;
930

931
    procedure SetInt(const Value: Integer); override;
932
    procedure SetIVec2(const Value: TVector2i); override;
933
    procedure SetIVec3(const Value: TVector3i); override;
934
    procedure SetIVec4(const Value: TVector4i); override;
935

936
    procedure SetUInt(const Value: GLuint); override;
937
    procedure SetUVec2(const Value: TVector2ui); override;
938
    procedure SetUVec3(const Value: TVector3ui); override;
939
    procedure SetUVec4(const Value: TVector4ui); override;
940

941
    function GetMat2: TMatrix2f; override;
942
    function GetMat3: TMatrix3f; override;
943
    function GetMat4: TMatrix4f; override;
944
    procedure SetMat2(const Value: TMatrix2f); override;
945
    procedure SetMat3(const Value: TMatrix3f); override;
946
    procedure SetMat4(const Value: TMatrix4f); override;
947

948
    function GetAutoSetMethod: string; override;
949
    procedure SetAutoSetMethod(const AValue: string); override;
950

951
    procedure WriteToFiler(AWriter: TWriter); override;
952
    procedure ReadFromFiler(AReader: TReader); override;
953
  public
954
     
955
    procedure SetFloatArray(const Values: PGLFloat; Count: Integer); override;
956
    procedure SetIntArray(const Values: PGLInt; Count: Integer); override;
957
    procedure SetUIntArray(const Values: PGLUInt; Count: Integer); override;
958

959
    procedure Assign(Source: TPersistent); override;
960
    procedure Apply(var ARci: TGLRenderContextInfo); override;
961

962
    property Name: string read GetName;
963
    property Location: TGLint read FLocation;
964
    property GLSLType: TGLSLDataType read GetGLSLType;
965
  end;
966

967
  // TGLShaderUniformDSA
968
  //
969

970
  TGLShaderUniformDSA = class(TGLShaderUniform)
971
  protected
972
     
973
    procedure SetFloat(const Value: TGLFloat); override;
974
    procedure SetVec2(const Value: TVector2f); override;
975
    procedure SetVec3(const Value: TVector3f); override;
976
    procedure SetVec4(const Value: TVector4f); override;
977

978
    procedure SetInt(const Value: Integer); override;
979
    procedure SetIVec2(const Value: TVector2i); override;
980
    procedure SetIVec3(const Value: TVector3i); override;
981
    procedure SetIVec4(const Value: TVector4i); override;
982

983
    procedure SetUInt(const Value: GLuint); override;
984
    procedure SetUVec2(const Value: TVector2ui); override;
985
    procedure SetUVec3(const Value: TVector3ui); override;
986
    procedure SetUVec4(const Value: TVector4ui); override;
987

988
    procedure SetMat2(const Value: TMatrix2f); override;
989
    procedure SetMat3(const Value: TMatrix3f); override;
990
    procedure SetMat4(const Value: TMatrix4f); override;
991
  public
992
     
993
    procedure SetFloatArray(const Values: PGLFloat; Count: Integer); override;
994
    procedure SetIntArray(const Values: PGLInt; Count: Integer); override;
995
    procedure SetUIntArray(const Values: PGLUInt; Count: Integer); override;
996
  end;
997

998
  // TGLUniformTexture
999
  //
1000

1001
  TGLShaderUniformTexture = class(TGLShaderUniform)
1002
  private
1003
     
1004
    FLibTexture: TGLAbstractTexture;
1005
    FLibSampler: TGLTextureSampler;
1006
    FTarget: TGLTextureTarget;
1007
    FSwizzling: TSwizzleVector;
1008
  protected
1009
     
1010
    FLibTexureName: TGLMaterialComponentName;
1011
    FLibSamplerName: TGLMaterialComponentName;
1012
    function GetTextureName: string; override;
1013
    function GetSamplerName: string; override;
1014
    function GetTextureSwizzle: TSwizzleVector; override;
1015
    procedure SetTextureName(const AValue: string); override;
1016
    procedure SetSamplerName(const AValue: string); override;
1017
    procedure SetTextureSwizzle(const AValue: TSwizzleVector); override;
1018

1019
    procedure WriteToFiler(AWriter: TWriter); override;
1020
    procedure ReadFromFiler(AReader: TReader); override;
1021
    procedure Loaded;
1022
  public
1023
     
1024
    constructor Create(AOwner: TPersistent); override;
1025
    destructor Destroy; override;
1026
    procedure Assign(Source: TPersistent); override;
1027
    procedure Notification(Sender: TObject; Operation: TOperation); override;
1028

1029
    procedure Apply(var ARci: TGLRenderContextInfo); override;
1030

1031
    property LibTextureName: TGLMaterialComponentName read GetTextureName
1032
      write SetTextureName;
1033
    property LibSamplerName: TGLMaterialComponentName read GetSamplerName
1034
      write SetSamplerName;
1035
    property GLSLSampler: TGLSLSamplerType read GetGLSLSamplerType;
1036
    property Swizzling: TSwizzleVector read GetTextureSwizzle write
1037
      SetTextureSwizzle;
1038
  end;
1039

1040
  // TGLBaseShaderModel
1041
  //
1042

1043
  TGLBaseShaderModel = class(TGLLibMaterialProperty)
1044
  protected
1045
     
1046
    FHandle: TGLProgramHandle;
1047
    FLibShaderName: array[TGLShaderType] of string;
1048
    FShaders: array[TGLShaderType] of TGLShaderEx;
1049
    FIsValid: Boolean;
1050
    FInfoLog: string;
1051
    FUniforms: TPersistentObjectList;
1052
    FAutoFill: Boolean;
1053

1054
    function GetLibShaderName(AType: TGLShaderType): string;
1055
    procedure SetLibShaderName(AType: TGLShaderType; const AValue: string);
1056

1057
    function GetUniform(const AName: string): IShaderParameter;
1058
    class procedure ReleaseUniforms(AList: TPersistentObjectList);
1059

1060
    property LibVertexShaderName: TGLMaterialComponentName index shtVertex
1061
      read GetLibShaderName write SetLibShaderName;
1062
    property LibFragmentShaderName: TGLMaterialComponentName index shtFragment
1063
      read GetLibShaderName write SetLibShaderName;
1064
    property LibGeometryShaderName: TGLMaterialComponentName index shtGeometry
1065
      read GetLibShaderName write SetLibShaderName;
1066
    property LibTessEvalShaderName: TGLMaterialComponentName index shtEvaluation
1067
      read GetLibShaderName write SetLibShaderName;
1068
    property LibTessControlShaderName: TGLMaterialComponentName index shtControl
1069
      read GetLibShaderName write SetLibShaderName;
1070

1071
    procedure DefineProperties(Filer: TFiler); override;
1072
    procedure ReadUniforms(AStream: TStream);
1073
    procedure WriteUniforms(AStream: TStream);
1074
    procedure Loaded; override;
1075
    class function IsSupported: Boolean; virtual; abstract;
1076

1077
  public
1078
     
1079
    constructor Create(AOwner: TPersistent); override;
1080
    destructor Destroy; override;
1081
    procedure Assign(Source: TPersistent); override;
1082

1083
    procedure NotifyChange(Sender: TObject); override;
1084
    procedure Notification(Sender: TObject; Operation: TOperation); override;
1085

1086
    procedure DoOnPrepare(Sender: TGLContext);
1087
    procedure Apply(var ARci: TGLRenderContextInfo); virtual;
1088
    procedure UnApply(var ARci: TGLRenderContextInfo); virtual;
1089

1090
    procedure GetUniformNames(Proc: TGetStrProc);
1091

1092
    property Handle: TGLProgramHandle read FHandle;
1093
    property IsValid: Boolean read FIsValid;
1094
    property Uniforms[const AName: string]: IShaderParameter read GetUniform;
1095
  published
1096
     
1097
    // Compilation info log for design time
1098
    property InfoLog: string read FInfoLog;
1099
    // Turn on autofill of uniforms
1100
    property AutoFillOfUniforms: Boolean read FAutoFill
1101
      write FAutoFill stored False;
1102
    property NextPass;
1103
  end;
1104

1105
  TGLShaderModel3 = class(TGLBaseShaderModel)
1106
  public
1107
     
1108
    class function IsSupported: Boolean; override;
1109
  published
1110
     
1111
    property LibVertexShaderName;
1112
    property LibFragmentShaderName;
1113
  end;
1114

1115
  TGLShaderModel4 = class(TGLBaseShaderModel)
1116
  public
1117
     
1118
    class function IsSupported: Boolean; override;
1119
  published
1120
     
1121
    property LibVertexShaderName;
1122
    property LibGeometryShaderName;
1123
    property LibFragmentShaderName;
1124
  end;
1125

1126
  TGLShaderModel5 = class(TGLBaseShaderModel)
1127
  public
1128
     
1129
    procedure Apply(var ARci: TGLRenderContextInfo); override;
1130
    procedure UnApply(var ARci: TGLRenderContextInfo); override;
1131
    class function IsSupported: Boolean; override;
1132
  published
1133
     
1134
    property LibTessControlShaderName;
1135
    property LibTessEvalShaderName;
1136
    property LibVertexShaderName;
1137
    property LibGeometryShaderName;
1138
    property LibFragmentShaderName;
1139
  end;
1140

1141
  // TGLLibMaterialEx
1142
  //
1143

1144
  TGLLibMaterialEx = class(TGLAbstractLibMaterial)
1145
  private
1146
     
1147
    FHandle: TGLVirtualHandle;
1148
    FApplicableLevel: TGLMaterialLevel;
1149
    FSelectedLevel: TGLMaterialLevel;
1150
    FFixedFunc: TGLFixedFunctionProperties;
1151
    FMultitexturing: TGLMultitexturingProperties;
1152
    FSM3: TGLShaderModel3;
1153
    FSM4: TGLShaderModel4;
1154
    FSM5: TGLShaderModel5;
1155
    FOnAsmProgSetting: TOnAsmProgSetting;
1156
    FOnSM3UniformInit: TOnUniformInitialize;
1157
    FOnSM3UniformSetting: TOnUniformSetting;
1158
    FOnSM4UniformInit: TOnUniformInitialize;
1159
    FOnSM4UniformSetting: TOnUniformSetting;
1160
    FOnSM5UniformInit: TOnUniformInitialize;
1161
    FOnSM5UniformSetting: TOnUniformSetting;
1162
    FNextPass: TGLLibMaterialEx;
1163
    FStoreAmalgamating: Boolean;
1164
    procedure SetLevel(AValue: TGLMaterialLevel);
1165
    procedure SetFixedFunc(AValue: TGLFixedFunctionProperties);
1166
    procedure SetMultitexturing(AValue: TGLMultitexturingProperties);
1167
    procedure SetSM3(AValue: TGLShaderModel3);
1168
    procedure SetSM4(AValue: TGLShaderModel4);
1169
    procedure SetSM5(AValue: TGLShaderModel5);
1170
    procedure DoAllocate(Sender: TGLVirtualHandle; var handle: TGLUint);
1171
    procedure DoDeallocate(Sender: TGLVirtualHandle; var handle: TGLUint);
1172
  protected
1173
    procedure Loaded; override;
1174
    procedure RemoveDefferedInit;
1175
    procedure DoOnPrepare(Sender: TGLContext);
1176
  public
1177
     
1178
    constructor Create(ACollection: TCollection); override;
1179
    destructor Destroy; override;
1180

1181
    procedure Assign(Source: TPersistent); override;
1182
    procedure NotifyChange(Sender: TObject); override;
1183

1184
    procedure Apply(var ARci: TGLRenderContextInfo); override;
1185
    function UnApply(var ARci: TGLRenderContextInfo): Boolean; override;
1186

1187
    function Blended: Boolean; override;
1188
  published
1189
     
1190
    property ApplicableLevel: TGLMaterialLevel read FApplicableLevel write
1191
      SetLevel
1192
      default mlAuto;
1193
    property SelectedLevel: TGLMaterialLevel read FSelectedLevel;
1194
    property FixedFunction: TGLFixedFunctionProperties
1195
      read FFixedFunc write SetFixedFunc;
1196
    property Multitexturing: TGLMultitexturingProperties
1197
      read FMultitexturing write SetMultitexturing;
1198
    property ShaderModel3: TGLShaderModel3 read FSM3 write SetSM3;
1199
    property ShaderModel4: TGLShaderModel4 read FSM4 write SetSM4;
1200
    property ShaderModel5: TGLShaderModel5 read FSM5 write SetSM5;
1201

1202
    // Asm vertex program event
1203
    property OnAsmProgSetting: TOnAsmProgSetting read FOnAsmProgSetting
1204
      write FOnAsmProgSetting;
1205
    // Shader model 3 event
1206
    property OnSM3UniformInitialize: TOnUniformInitialize read FOnSM3UniformInit
1207
      write FOnSM3UniformInit;
1208
    property OnSM3UniformSetting: TOnUniformSetting read FOnSM3UniformSetting
1209
      write FOnSM3UniformSetting;
1210
    // Shader model 4 event
1211
    property OnSM4UniformInitialize: TOnUniformInitialize read FOnSM4UniformInit
1212
      write FOnSM4UniformInit;
1213
    property OnSM4UniformSetting: TOnUniformSetting read FOnSM4UniformSetting
1214
      write FOnSM4UniformSetting;
1215
    // Shader model 5 event
1216
    property OnSM5UniformInitialize: TOnUniformInitialize read FOnSM5UniformInit
1217
      write FOnSM5UniformInit;
1218
    property OnSM5UniformSetting: TOnUniformSetting read FOnSM5UniformSetting
1219
      write FOnSM5UniformSetting;
1220
  end;
1221

1222
  // TGLLibMaterialsEx
1223
  //
1224

1225
  TGLLibMaterialsEx = class(TGLAbstractLibMaterials)
1226
  protected
1227
    procedure SetItems(AIndex: Integer; const AValue: TGLLibMaterialEx);
1228
    function GetItems(AIndex: Integer): TGLLibMaterialEx;
1229
  public
1230
     
1231
    constructor Create(AOwner: TComponent);
1232

1233
    function MaterialLibrary: TGLMaterialLibraryEx;
1234

1235
    function IndexOf(const Item: TGLLibMaterialEx): Integer;
1236
    function Add: TGLLibMaterialEx;
1237
    function FindItemID(ID: Integer): TGLLibMaterialEx;
1238
    property Items[index: Integer]: TGLLibMaterialEx read GetItems
1239
    write SetItems; default;
1240
    function GetLibMaterialByName(const AName: TGLLibMaterialName):
1241
      TGLLibMaterialEx;
1242
  end;
1243

1244
  // TGLMatLibComponents
1245
  //
1246

1247
  TGLMatLibComponents = class(TGLXCollection)
1248
  protected
1249
     
1250
    function GetItems(index: Integer): TGLBaseMaterialCollectionItem;
1251
  public
1252
     
1253
    function GetNamePath: string; override;
1254
    class function ItemsClass: TGLXCollectionItemClass; override;
1255
    property Items[index: Integer]: TGLBaseMaterialCollectionItem
1256
    read GetItems; default;
1257

1258
    function GetItemByName(const AName: TGLMaterialComponentName):
1259
      TGLBaseMaterialCollectionItem;
1260
    function GetTextureByName(const AName: TGLMaterialComponentName):
1261
      TGLAbstractTexture;
1262
    function GetAttachmentByName(const AName: TGLMaterialComponentName):
1263
      TGLFrameBufferAttachment;
1264
    function GetSamplerByName(const AName: TGLMaterialComponentName):
1265
      TGLTextureSampler;
1266
    function GetCombinerByName(const AName: TGLMaterialComponentName):
1267
      TGLTextureCombiner;
1268
    function GetShaderByName(const AName: TGLMaterialComponentName):
1269
      TGLShaderEx;
1270
    function GetAsmProgByName(const AName: TGLMaterialComponentName):
1271
      TGLASMVertexProgram;
1272
    function MakeUniqueName(const AName: TGLMaterialComponentName):
1273
      TGLMaterialComponentName;
1274
  end;
1275

1276
  // TGLMaterialLibraryEx
1277
  //
1278

1279
  TGLMaterialLibraryEx = class(TGLAbstractMaterialLibrary)
1280
  private
1281
     
1282
    FComponents: TGLMatLibComponents;
1283
  protected
1284
     
1285
    procedure Loaded; override;
1286
    function GetMaterials: TGLLibMaterialsEx;
1287
    procedure SetMaterials(AValue: TGLLibMaterialsEx);
1288
    function StoreMaterials: Boolean;
1289
    procedure SetComponents(AValue: TGLMatLibComponents);
1290

1291
    procedure DefineProperties(Filer: TFiler); override;
1292
    procedure WriteComponents(AStream: TStream);
1293
    procedure ReadComponents(AStream: TStream);
1294
  public
1295
     
1296
    constructor Create(AOwner: TComponent); override;
1297
    destructor Destroy; override;
1298

1299
    procedure GetNames(Proc: TGetStrProc;
1300
      AClass: CGLBaseMaterialCollectionItem); overload;
1301

1302
    function AddTexture(const AName: TGLMaterialComponentName):
1303
      TGLTextureImageEx;
1304
    function AddAttachment(const AName: TGLMaterialComponentName):
1305
      TGLFrameBufferAttachment;
1306
    function AddSampler(const AName: TGLMaterialComponentName):
1307
      TGLTextureSampler;
1308
    function AddCombiner(const AName: TGLMaterialComponentName):
1309
      TGLTextureCombiner;
1310
    function AddShader(const AName: TGLMaterialComponentName): TGLShaderEx;
1311
    function AddAsmProg(const AName: TGLMaterialComponentName):
1312
      TGLASMVertexProgram;
1313

1314
    procedure SetLevelForAll(const ALevel: TGLMaterialLevel);
1315
  published
1316
     
1317
      { The materials collection. }
1318
    property Materials: TGLLibMaterialsEx read GetMaterials write SetMaterials
1319
      stored StoreMaterials;
1320
    property Components: TGLMatLibComponents read FComponents
1321
      write SetComponents;
1322
    property TexturePaths;
1323
  end;
1324

1325
procedure RegisterGLMaterialExNameChangeEvent(AEvent: TNotifyEvent);
1326
procedure DeRegisterGLMaterialExNameChangeEvent(AEvent: TNotifyEvent);
1327

1328
implementation
1329

1330
const
1331
  cTextureMagFilter: array[maNearest..maLinear] of TGLEnum =
1332
    (GL_NEAREST, GL_LINEAR);
1333
  cTextureMinFilter: array[miNearest..miLinearMipmapLinear] of TGLEnum =
1334
    (GL_NEAREST, GL_LINEAR, GL_NEAREST_MIPMAP_NEAREST,
1335
    GL_LINEAR_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR,
1336
    GL_LINEAR_MIPMAP_LINEAR);
1337
  cTextureWrapMode: array[twRepeat..twMirrorClampToBorder] of TGLenum =
1338
    (GL_REPEAT, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER,
1339
    GL_MIRRORED_REPEAT, GL_MIRROR_CLAMP_TO_EDGE_ATI,
1340
      GL_MIRROR_CLAMP_TO_BORDER_EXT);
1341
  cTextureCompareMode: array[tcmNone..tcmCompareRtoTexture] of TGLenum =
1342
    (GL_NONE, GL_COMPARE_R_TO_TEXTURE);
1343
  cSamplerToTexture: array[TGLSLSamplerType] of TGLTextureTarget =
1344
    (
1345
    ttNoShape,
1346
    ttTexture1D,
1347
    ttTexture2D,
1348
    ttTexture3D,
1349
    ttTextureCube,
1350
    ttTexture1D,
1351
    ttTexture2D,
1352
    ttTexture1DArray,
1353
    ttTexture2DArray,
1354
    ttTexture1DArray,
1355
    ttTexture1DArray,
1356
    ttTextureCube,
1357
    ttTexture1D,
1358
    ttTexture2D,
1359
    ttTexture3D,
1360
    ttTextureCube,
1361
    ttTexture1DArray,
1362
    ttTexture2DArray,
1363
    ttTexture1D,
1364
    ttTexture2D,
1365
    ttTexture3D,
1366
    ttTextureCube,
1367
    ttTexture1DArray,
1368
    ttTexture2DArray,
1369
    ttTextureRect,
1370
    ttTextureRect,
1371
    ttTextureBuffer,
1372
    ttTextureRect,
1373
    ttTextureBuffer,
1374
    ttTextureRect,
1375
    ttTextureBuffer,
1376
    ttTexture2DMultisample,
1377
    ttTexture2DMultisample,
1378
    ttTexture2DMultisample,
1379
    ttTexture2DMultisampleArray,
1380
    ttTexture2DMultisampleArray,
1381
    ttTexture2DMultisample
1382
    );
1383

1384
  cTextureSwizzle: array[TGLTextureSwizzle] of TGLEnum =
1385
    (
1386
    GL_RED,
1387
    GL_GREEN,
1388
    GL_BLUE,
1389
    GL_ALPHA,
1390
    GL_ZERO,
1391
    GL_ONE
1392
    );
1393

1394
const
1395
  cTextureMode: array[TGLTextureMode] of TGLEnum =
1396
    (GL_DECAL, GL_MODULATE, GL_BLEND, GL_REPLACE, GL_ADD);
1397

1398
const
1399
  cShaderTypeName: array[TGLShaderType] of string =
1400
    ('vertex', 'control', 'evaluation', 'geomtery', 'fragment');
1401

1402
type
1403
  TFriendlyImage = class(TGLBaseImage);
1404

1405
  TStandartUniformAutoSetExecutor = class
1406
  public
1407
    constructor Create;
1408
    procedure SetModelMatrix(Sender: IShaderParameter; var ARci:
1409
      TGLRenderContextInfo);
1410
    procedure SetViewMatrix(Sender: IShaderParameter; var ARci:
1411
      TGLRenderContextInfo);
1412
    procedure SetProjectionMatrix(Sender: IShaderParameter; var ARci:
1413
      TGLRenderContextInfo);
1414
    procedure SetInvModelMatrix(Sender: IShaderParameter; var ARci:
1415
      TGLRenderContextInfo);
1416
    procedure SetModelViewMatrix(Sender: IShaderParameter; var ARci:
1417
      TGLRenderContextInfo);
1418
    procedure SetNormalModelMatrix(Sender: IShaderParameter; var ARci:
1419
      TGLRenderContextInfo);
1420
    procedure SetInvModelViewMatrix(Sender: IShaderParameter; var ARci:
1421
      TGLRenderContextInfo);
1422
    procedure SetViewProjectionMatrix(Sender: IShaderParameter; var ARci:
1423
      TGLRenderContextInfo);
1424
    procedure SetWorldViewProjectionMatrix(Sender: IShaderParameter; var ARci:
1425
      TGLRenderContextInfo);
1426
    procedure SetCameraPosition(Sender: IShaderParameter; var ARci:
1427
      TGLRenderContextInfo);
1428
    // Lighting
1429
    procedure SetLightSource0Position(Sender: IShaderParameter; var ARci:
1430
      TGLRenderContextInfo);
1431
    // Material
1432
    procedure SetMaterialFrontAmbient(Sender: IShaderParameter; var ARci:
1433
      TGLRenderContextInfo);
1434
    procedure SetMaterialFrontDiffuse(Sender: IShaderParameter; var ARci:
1435
      TGLRenderContextInfo);
1436
    procedure SetMaterialFrontSpecular(Sender: IShaderParameter; var ARci:
1437
      TGLRenderContextInfo);
1438
    procedure SetMaterialFrontEmission(Sender: IShaderParameter; var ARci:
1439
      TGLRenderContextInfo);
1440
    procedure SetMaterialFrontShininess(Sender: IShaderParameter; var ARci:
1441
      TGLRenderContextInfo);
1442
    procedure SetMaterialBackAmbient(Sender: IShaderParameter; var ARci:
1443
      TGLRenderContextInfo);
1444
    procedure SetMaterialBackDiffuse(Sender: IShaderParameter; var ARci:
1445
      TGLRenderContextInfo);
1446
    procedure SetMaterialBackSpecular(Sender: IShaderParameter; var ARci:
1447
      TGLRenderContextInfo);
1448
    procedure SetMaterialBackShininess(Sender: IShaderParameter; var ARci:
1449
      TGLRenderContextInfo);
1450
    procedure SetMaterialBackEmission(Sender: IShaderParameter; var ARci:
1451
      TGLRenderContextInfo);
1452
  end;
1453

1454
var
1455
  vGLMaterialExNameChangeEvent: TNotifyEvent;
1456
  vStandartUniformAutoSetExecutor: TStandartUniformAutoSetExecutor;
1457
  vStoreBegin: procedure(mode: TGLEnum);
1458
{$IFDEF MSWINDOWS}stdcall;
1459
{$ENDIF}{$IFDEF UNIX}cdecl;
1460
{$ENDIF}
1461

1462
procedure RegisterGLMaterialExNameChangeEvent(AEvent: TNotifyEvent);
1463
begin
1464
  vGLMaterialExNameChangeEvent := AEvent;
1465
end;
1466

1467
procedure DeRegisterGLMaterialExNameChangeEvent(AEvent: TNotifyEvent);
1468
begin
1469
  vGLMaterialExNameChangeEvent := nil;
1470
end;
1471

1472
function ComputeNameHashKey(
1473
  const AName: string): Integer;
1474
var
1475
  i, n: Integer;
1476
begin
1477
  n := Length(AName);
1478
  Result := n;
1479
  for i := 1 to n do
1480
    Result := (Result shl 1) + Byte(AName[i]);
1481
end;
1482

1483
procedure Div2(var Value: Integer);
1484
{$IFDEF GLS_INLINE} inline;
1485
{$ENDIF}
1486
begin
1487
  Value := Value div 2;
1488
  if Value = 0 then
1489
    Value := 1;
1490
end;
1491

1492
function CalcTextureLevelNumber(ATarget: TGLTextureTarget; w, h, d: Integer):
1493
  Integer;
1494
begin
1495
  Result := 0;
1496

1497
  case ATarget of
1498

1499
    ttNoShape: ;
1500

1501
    ttTexture1D, ttTexture1DArray, ttTextureCube, ttTextureCubeArray:
1502
      repeat
1503
        Inc(Result);
1504
        Div2(w);
1505
      until w <= 1;
1506

1507
    ttTexture2D, ttTexture2DArray:
1508
      repeat
1509
        Inc(Result);
1510
        Div2(w);
1511
        Div2(h);
1512
      until (w <= 1) and (h <= 1);
1513

1514
    ttTexture3D:
1515
      repeat
1516
        Inc(Result);
1517
        Div2(w);
1518
        Div2(h);
1519
        Div2(d);
1520
      until (w <= 1) and (h <= 1) and (d <= 1);
1521

1522
    ttTextureRect, ttTextureBuffer,
1523
      ttTexture2DMultisample, ttTexture2DMultisampleArray:
1524
      Result := 1;
1525
  end;
1526
end;
1527

1528
{$IFDEF GLS_REGION}{$REGION 'TGLBaseMaterialCollectionItem'}{$ENDIF}
1529

1530
destructor TGLBaseMaterialCollectionItem.Destroy;
1531
var
1532
  I: Integer;
1533
begin
1534
  if Assigned(FUserList) then
1535
  begin
1536
    FNotifying := True;
1537
    for I := FUserList.Count - 1 downto 0 do
1538
      TGLLibMaterialProperty(FUserList[I]).Notification(Self, opRemove);
1539
    FreeAndNil(FUserList);
1540
  end;
1541
  inherited;
1542
end;
1543

1544
function TGLBaseMaterialCollectionItem.GetMaterialLibrary:
1545
  TGLAbstractMaterialLibrary;
1546
begin
1547
  Result := TGLAbstractMaterialLibrary(TGLMatLibComponents(Owner).Owner);
1548
end;
1549

1550
function TGLBaseMaterialCollectionItem.GetMaterialLibraryEx:
1551
  TGLMaterialLibraryEx;
1552
begin
1553
  Result := TGLMaterialLibraryEx(TGLMatLibComponents(Owner).Owner);
1554
end;
1555

1556
function TGLBaseMaterialCollectionItem.GetUserCount: Integer;
1557
begin
1558
  if Assigned(FUserList) then
1559
    Result := FUserList.Count
1560
  else
1561
    Result := 0;
1562
end;
1563

1564
function TGLBaseMaterialCollectionItem.GetUserList: TPersistentObjectList;
1565
begin
1566
  if FUserList = nil then
1567
  begin
1568
    FUserList := TPersistentObjectList.Create;
1569
    FNotifying := False;
1570
  end;
1571
  Result := FUserList;
1572
end;
1573

1574
procedure TGLBaseMaterialCollectionItem.NotifyChange(Sender: TObject);
1575
var
1576
  I: Integer;
1577
begin
1578
  if FNotifying then
1579
    exit;
1580
  FNotifying := True;
1581
  if GetUserCount > 0 then
1582
    for I := 0 to FUserList.Count - 1 do
1583
      TGLUpdateAbleObject(FUserList[I]).NotifyChange(Self);
1584
  FNotifying := False;
1585
end;
1586

1587
procedure TGLBaseMaterialCollectionItem.RegisterUser(
1588
  AUser: TGLUpdateAbleObject);
1589
begin
1590
  if not FNotifying and (UserList.IndexOf(AUser) < 0) then
1591
    UserList.Add(AUser);
1592
end;
1593

1594
procedure TGLBaseMaterialCollectionItem.UnregisterUser(
1595
  AUser: TGLUpdateAbleObject);
1596
begin
1597
  if not FNotifying then
1598
    UserList.Remove(AUser);
1599
end;
1600

1601
procedure TGLBaseMaterialCollectionItem.SetName(const AValue: string);
1602
begin
1603
  if AValue <> Name then
1604
  begin
1605
    if not IsValidIdent(AValue) then
1606
    begin
1607
      if IsDesignTime then
1608
        InformationDlg(AValue + ' - is not valid component name');
1609
      exit;
1610
    end;
1611
    if not (csLoading in MaterialLibrary.ComponentState) then
1612
    begin
1613
      if TGLMatLibComponents(Owner).GetItemByName(AValue) <> Self then
1614
        inherited SetName(TGLMatLibComponents(Owner).MakeUniqueName(AValue))
1615
      else
1616
        inherited SetName(AValue);
1617
    end
1618
    else
1619
      inherited SetName(AValue);
1620
    FNameHashKey := ComputeNameHashKey(Name);
1621
    // Notify users
1622
    NotifyChange(Self);
1623
    // Notify designer
1624
    if Assigned(vGLMaterialExNameChangeEvent) then
1625
      vGLMaterialExNameChangeEvent(Self);
1626
  end;
1627
end;
1628

1629
{$IFDEF GLS_REGION}{$ENDREGION}{$ENDIF}
1630

1631
{$IFDEF GLS_REGION}{$REGION 'TGLFixedFunctionProperties'}{$ENDIF}
1632

1633
procedure TGLFixedFunctionProperties.Apply(var ARci: TGLRenderContextInfo);
1634
begin
1635
  with ARci.GLStates do
1636
  begin
1637
    Disable(stColorMaterial);
1638
    PolygonMode := FPolygonMode;
1639

1640
    // Fixed functionality state
1641
    if not ARci.GLStates.ForwardContext then
1642
    begin
1643
      // Lighting switch
1644
      if (moNoLighting in MaterialOptions) or not ARci.bufferLighting then
1645
      begin
1646
        Disable(stLighting);
1647
        FFrontProperties.ApplyNoLighting(ARci, cmFront);
1648
      end
1649
      else
1650
      begin
1651
        Enable(stLighting);
1652
        FFrontProperties.Apply(ARci, cmFront);
1653
      end;
1654

1655
      if FPolygonMode = pmLines then
1656
        Disable(stLineStipple);
1657

1658
      // Fog switch
1659
      if (moIgnoreFog in MaterialOptions) or not ARci.bufferFog then
1660
        Disable(stFog)
1661
      else
1662
        Enable(stFog);
1663
    end;
1664

1665
    // Apply FaceCulling and BackProperties (if needs be)
1666
    case FFaceCulling of
1667
      fcBufferDefault:
1668
        begin
1669
          if ARci.bufferFaceCull then
1670
            Enable(stCullFace)
1671
          else
1672
            Disable(stCullFace);
1673
          BackProperties.Apply(ARci, cmBack);
1674
        end;
1675
      fcCull: Enable(stCullFace);
1676
      fcNoCull:
1677
        begin
1678
          Disable(stCullFace);
1679
          BackProperties.Apply(ARci, cmBack);
1680
        end;
1681
    end;
1682
    // note: Front + Back with different PolygonMode are no longer supported.
1683
    // Currently state cache just ignores back facing mode changes, changes to
1684
    // front affect both front + back PolygonMode
1685

1686
    // Apply Blending mode
1687
    if not ARci.ignoreBlendingRequests then
1688
      case FBlendingMode of
1689
        bmOpaque:
1690
          begin
1691
            Disable(stBlend);
1692
            Disable(stAlphaTest);
1693
          end;
1694
        bmTransparency:
1695
          begin
1696
            Enable(stBlend);
1697
            Enable(stAlphaTest);
1698
            SetBlendFunc(bfSrcAlpha, bfOneMinusSrcAlpha);
1699
            SetGLAlphaFunction(cfGreater, 0);
1700
          end;
1701
        bmAdditive:
1702
          begin
1703
            Enable(stBlend);
1704
            Enable(stAlphaTest);
1705
            SetBlendFunc(bfSrcAlpha, bfOne);
1706
            SetGLAlphaFunction(cfGreater, 0);
1707
          end;
1708
        bmAlphaTest50:
1709
          begin
1710
            Disable(stBlend);
1711
            Enable(stAlphaTest);
1712
            SetGLAlphaFunction(cfGEqual, 0.5);
1713
          end;
1714
        bmAlphaTest100:
1715
          begin
1716
            Disable(stBlend);
1717
            Enable(stAlphaTest);
1718
            SetGLAlphaFunction(cfGEqual, 1.0);
1719
          end;
1720
        bmModulate:
1721
          begin
1722
            Enable(stBlend);
1723
            Enable(stAlphaTest);
1724
            SetBlendFunc(bfDstColor, bfZero);
1725
            SetGLAlphaFunction(cfGreater, 0);
1726
          end;
1727
        bmCustom:
1728
          begin
1729
            FBlendingParams.Apply(ARci);
1730
          end;
1731
      end;
1732

1733
    // Apply depth properties
1734
    if not ARci.ignoreDepthRequests then
1735
      FDepthProperties.Apply(ARci);
1736

1737
    // Apply texturing
1738
    if ARci.currentMaterialLevel = mlFixedFunction then
1739
    begin
1740
      if FTexProp.Enabled and FTexProp.IsValid then
1741
      begin
1742
        ARci.GLStates.ActiveTexture := 0;
1743
        FTexProp.Apply(ARci);
1744
        GL.TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,
1745
          cTextureMode[FTextureMode]);
1746
      end;
1747
    end;
1748

1749
  end;
1750
end;
1751

1752
procedure TGLFixedFunctionProperties.Assign(Source: TPersistent);
1753
var
1754
  LFFP: TGLFixedFunctionProperties;
1755
begin
1756
  if Source is TGLFixedFunctionProperties then
1757
  begin
1758
    LFFP := TGLFixedFunctionProperties(Source);
1759
    if Assigned(LFFP.FBackProperties) then
1760
      BackProperties.Assign(LFFP.BackProperties)
1761
    else
1762
      FreeAndNil(FBackProperties);
1763
    FFrontProperties.Assign(LFFP.FFrontProperties);
1764
    FPolygonMode := LFFP.FPolygonMode;
1765
    FBlendingMode := LFFP.FBlendingMode;
1766
    FMaterialOptions := LFFP.FMaterialOptions;
1767
    FFaceCulling := LFFP.FFaceCulling;
1768
    FDepthProperties.Assign(LFFP.FDepthProperties);
1769
    FTexProp.Assign(LFFP.FTexProp);
1770
    FTextureMode := LFFP.TextureMode;
1771
    NotifyChange(Self);
1772
  end;
1773
  inherited;
1774
end;
1775

1776
function TGLFixedFunctionProperties.Blended: Boolean;
1777
begin
1778
  Result := not (FBlendingMode in [bmOpaque, bmAlphaTest50, bmAlphaTest100, bmCustom]);
1779
end;
1780

1781
constructor TGLFixedFunctionProperties.Create(AOwner: TPersistent);
1782
begin
1783
  inherited;
1784
  FFrontProperties := TGLFaceProperties.Create(Self);
1785
  FFaceCulling := fcBufferDefault;
1786
  FPolygonMode := pmFill;
1787
  FBlendingParams := TGLBlendingParameters.Create(Self);
1788
  FDepthProperties := TGLDepthProperties.Create(Self);
1789
  FTexProp := TGLTextureProperties.Create(Self);
1790
  FTextureMode := tmDecal;
1791
  FEnabled := True;
1792
end;
1793

1794
destructor TGLFixedFunctionProperties.Destroy;
1795
begin
1796
  FFrontProperties.Destroy;
1797
  FBackProperties.Free;
1798
  FDepthProperties.Destroy;
1799
  FBlendingParams.Destroy;
1800
  FTexProp.Destroy;
1801
  inherited;
1802
end;
1803

1804
function TGLFixedFunctionProperties.GetBackProperties: TGLFaceProperties;
1805
begin
1806
  if not Assigned(FBackProperties) then
1807
    FBackProperties := TGLFaceProperties.Create(Self);
1808
  Result := FBackProperties;
1809
end;
1810

1811
procedure TGLFixedFunctionProperties.SetBackProperties(AValues:
1812
  TGLFaceProperties);
1813
begin
1814
  BackProperties.Assign(AValues);
1815
  NotifyChange(Self);
1816
end;
1817

1818
procedure TGLFixedFunctionProperties.SetBlendingMode(const AValue:
1819
  TBlendingMode);
1820
begin
1821
  if AValue <> FBlendingMode then
1822
  begin
1823
    FBlendingMode := AValue;
1824
    NotifyChange(Self);
1825
  end;
1826
end;
1827

1828
procedure TGLFixedFunctionProperties.SetBlendingParams(const AValue:
1829
  TGLBlendingParameters);
1830
begin
1831
  FBlendingParams.Assign(AValue);
1832
  NotifyChange(Self);
1833
end;
1834

1835
procedure TGLFixedFunctionProperties.SetDepthProperties(AValues:
1836
  TGLDepthProperties);
1837
begin
1838
  FDepthProperties.Assign(AValues);
1839
  NotifyChange(Self);
1840
end;
1841

1842
procedure TGLFixedFunctionProperties.SetTexProp(AValue: TGLTextureProperties);
1843
begin
1844
  FTexProp.Assign(AValue);
1845
end;
1846

1847
procedure TGLFixedFunctionProperties.SetTextureMode(AValue: TGLTextureMode);
1848
begin
1849
  if AValue <> FTextureMode then
1850
  begin
1851
    FTextureMode := AValue;
1852
    NotifyChange(Self);
1853
  end;
1854
end;
1855

1856
procedure TGLFixedFunctionProperties.SetFaceCulling(const AValue: TFaceCulling);
1857
begin
1858
  if AValue <> FFaceCulling then
1859
  begin
1860
    FFaceCulling := AValue;
1861
    NotifyChange(Self);
1862
  end;
1863
end;
1864

1865
procedure TGLFixedFunctionProperties.SetFrontProperties(AValues:
1866
  TGLFaceProperties);
1867
begin
1868
  FFrontProperties.Assign(AValues);
1869
  NotifyChange(Self);
1870
end;
1871

1872
procedure TGLFixedFunctionProperties.SetMaterialOptions(const AValue:
1873
  TMaterialOptions);
1874
begin
1875
  if AValue <> FMaterialOptions then
1876
  begin
1877
    FMaterialOptions := AValue;
1878
    NotifyChange(Self);
1879
  end;
1880
end;
1881

1882
procedure TGLFixedFunctionProperties.SetPolygonMode(AValue: TPolygonMode);
1883
begin
1884
  if AValue <> FPolygonMode then
1885
  begin
1886
    FPolygonMode := AValue;
1887
    NotifyChange(Self);
1888
  end;
1889
end;
1890

1891
procedure TGLFixedFunctionProperties.UnApply(var ARci: TGLRenderContextInfo);
1892
begin
1893
  if FTexProp.Enabled and FTexProp.IsValid then
1894
    FTexProp.UnApply(ARci);
1895
end;
1896

1897
{$IFDEF GLS_REGION}{$ENDREGION}{$ENDIF}
1898

1899
{$IFDEF GLS_REGION}{$REGION 'TGLAbstractTexture'}{$ENDIF}
1900

1901
function TGLAbstractTexture.GetTextureTarget: TGLTextureTarget;
1902
begin
1903
  Result := FHandle.Target;
1904
end;
1905

1906
{$IFDEF GLS_REGION}{$ENDREGION}{$ENDIF}
1907

1908
{$IFDEF GLS_REGION}{$REGION 'TGLTextureImageEx'}{$ENDIF}
1909

1910
procedure TGLTextureImageEx.Apply(var ARci: TGLRenderContextInfo);
1911
begin
1912
  if FIsValid then
1913
  begin
1914
    // Just bind
1915
    with ARci.GLStates do
1916
    begin
1917
      TextureBinding[ActiveTexture, FHandle.Target] := FHandle.Handle;
1918
      ActiveTextureEnabled[FHandle.Target] := True;
1919
    end;
1920

1921
    if not IsDesignTime then
1922
    begin
1923
      if not FUseStreaming and Assigned(FImage) then
1924
      begin
1925
        Inc(FApplyCounter);
1926
        if FApplyCounter > 16 then
1927
          FreeAndNil(FImage);
1928
      end;
1929

1930
      if FUseStreaming then
1931
      begin
1932
        StreamTransfer;
1933
      end;
1934
    end;
1935
  end
1936
  else with ARci.GLStates do
1937
    TextureBinding[ActiveTexture, FHandle.Target] := 0;
1938
end;
1939

1940
procedure TGLTextureImageEx.Assign(Source: TPersistent);
1941
var
1942
  LTexture: TGLTextureImageEx;
1943
begin
1944
  if Source is TGLTextureImageEx then
1945
  begin
1946
    LTexture := TGLTextureImageEx(Source);
1947
    FCompression := LTexture.FCompression;
1948
    if Assigned(LTexture.FImage) then
1949
    begin
1950
      if not Assigned(FImage) then
1951
        FImage := TGLImage.Create;
1952
      FImage.Assign(LTexture.FImage);
1953
    end
1954
    else
1955
      FreeAndNil(FImage);
1956
    FImageAlpha := LTexture.FImageAlpha;
1957
    FImageBrightness := LTexture.FImageBrightness;
1958
    FImageGamma := LTexture.FImageGamma;
1959
    FHeightToNormalScale := LTexture.FHeightToNormalScale;
1960
    FSourceFile := LTexture.FSourceFile;
1961
    NotifyChange(Self);
1962
  end;
1963
  inherited;
1964
end;
1965

1966
constructor TGLTextureImageEx.Create(AOwner: TGLXCollection);
1967
begin
1968
  inherited;
1969
  FDefferedInit := False;
1970
  FHandle := TGLTextureHandle.Create;
1971
  FHandle.OnPrapare := DoOnPrepare;
1972
  FCompression := tcDefault;
1973
  FImageAlpha := tiaDefault;
1974
  FImageBrightness := 1.0;
1975
  FImageGamma := 1.0;
1976
  FHeightToNormalScale := 1.0;
1977
  FInternalFormat := tfRGBA8;
1978
  FInternallyStored := False;
1979
  FMipGenMode := mgmOnFly;
1980
  FUseStreaming := False;
1981
  Name := TGLMatLibComponents(AOwner).MakeUniqueName('Texture');
1982
end;
1983

1984
destructor TGLTextureImageEx.Destroy;
1985
begin
1986
  FHandle.Destroy;
1987
  FImage.Free;
1988
  inherited;
1989
end;
1990

1991
procedure TGLTextureImageEx.NotifyChange(Sender: TObject);
1992
begin
1993
  FHandle.NotifyChangesOfData;
1994
  inherited;
1995
end;
1996

1997
procedure TGLTextureImageEx.DoOnPrepare(Sender: TGLContext);
1998
var
1999
  LTarget: TGLTextureTarget;
2000
  rowSize: Integer;
2001
begin
2002
  if IsDesignTime and FDefferedInit then
2003
    exit;
2004

2005
  FHandle.AllocateHandle;
2006
  if not FHandle.IsDataNeedUpdate then
2007
    exit;
2008

2009
  try
2010
    PrepareImage;
2011

2012
    // Target
2013
    LTarget := FImage.GetTextureTarget;
2014

2015
    // Check supporting
2016
    if not IsTargetSupported(LTarget)
2017
      or not IsFormatSupported(FInternalFormat) then
2018
      Abort;
2019

2020
    if (FHandle.Target <> LTarget)
2021
      and (FHandle.Target <> ttNoShape) then
2022
    begin
2023
      FHandle.DestroyHandle;
2024
      FHandle.AllocateHandle;
2025
    end;
2026
    FHandle.Target := LTarget;
2027

2028
    // Check streaming support
2029
    if not IsDesignTime then
2030
    begin
2031
      FUseStreaming := FUseStreaming and TGLUnpackPBOHandle.IsSupported;
2032
      FUseStreaming := FUseStreaming and IsServiceContextAvaible;
2033
      FUseStreaming := FUseStreaming and (LTarget = ttTexture2D);
2034
    end;
2035

2036
    with Sender.GLStates do
2037
    begin
2038
      ActiveTextureEnabled[FHandle.Target] := True;
2039
      TextureBinding[ActiveTexture, FHandle.Target] := FHandle.Handle;
2040
      UnpackRowLength := 0;
2041
      UnpackSkipRows := 0;
2042
      UnpackSkipPixels := 0;
2043
      rowSize := FImage.LevelWidth[0] * FImage.ElementSize;
2044
      if (rowSize mod 8 = 0) and (FImage.ElementSize > 4) then
2045
        UnpackAlignment := 8
2046
      else
2047
      if rowSize mod 4 = 0 then
2048
        UnpackAlignment := 4
2049
      else if rowSize mod 2 = 0 then
2050
        UnpackAlignment := 2
2051
      else
2052
        UnpackAlignment := 1;
2053
    end;
2054

2055
    if not IsDesignTime and FUseStreaming then
2056
    begin
2057
      TFriendlyImage(FImage).StartStreaming;
2058
      FLastTime := GLSTime;
2059
      StreamTransfer;
2060
      FHandle.NotifyDataUpdated;
2061
    end
2062
    else
2063
      FullTransfer;
2064

2065
    Sender.GLStates.ActiveTextureEnabled[FHandle.Target] := False;
2066

2067
    FApplyCounter := 0;
2068
    FIsValid := True;
2069
  except
2070
    FIsValid := False;
2071
  end;
2072
end;
2073

2074
procedure TGLTextureImageEx.FullTransfer;
2075
var
2076
  LCompression: TGLTextureCompression;
2077
  glFormat: TGLEnum;
2078
begin
2079
  with GL do
2080
  begin
2081
    if ARB_texture_compression then
2082
    begin
2083
      if Compression = tcDefault then
2084
        if vDefaultTextureCompression = tcDefault then
2085
          LCompression := tcNone
2086
        else
2087
          LCompression := vDefaultTextureCompression
2088
      else
2089
        LCompression := Compression;
2090
    end
2091
    else
2092
      LCompression := tcNone;
2093

2094
    if LCompression <> tcNone then
2095
      with CurrentGLContext.GLStates do
2096
      begin
2097
        case LCompression of
2098
          tcStandard: TextureCompressionHint := hintDontCare;
2099
          tcHighQuality: TextureCompressionHint := hintNicest;
2100
          tcHighSpeed: TextureCompressionHint := hintFastest;
2101
        else
2102
          Assert(False, glsErrorEx + glsUnknownType);
2103
        end;
2104
        if not GetGenericCompressedFormat(
2105
          FInternalFormat,
2106
          FImage.ColorFormat,
2107
          glFormat) then
2108
          glFormat := InternalFormatToOpenGLFormat(FInternalFormat);
2109
      end
2110
    else
2111
      glFormat := InternalFormatToOpenGLFormat(FInternalFormat);
2112

2113
    FImage.RegisterAsOpenGLTexture(
2114
      FHandle,
2115
      FMipGenMode = mgmOnFly,
2116
      glFormat,
2117
      FWidth,
2118
      FHeight,
2119
      FDepth);
2120

2121
    if GetError <> GL_NO_ERROR then
2122
    begin
2123
      ClearError;
2124
      CurrentGLContext.GLStates.ActiveTextureEnabled[FHandle.Target] := False;
2125
      GLSLogger.LogErrorFmt('Unable to create texture "%s"', [Self.Name]);
2126
      Abort;
2127
    end
2128
    else
2129
      FHandle.NotifyDataUpdated;
2130
  end;
2131
end;
2132

2133
procedure TGLTextureImageEx.CalcLODRange(out AFirstLOD, ALastLOD: Integer);
2134
var
2135
  I, MaxLODSize, MinLODSize, MaxLODZSize: Integer;
2136
begin
2137
  case FHandle.Target of
2138
    ttTexture3D:
2139
      begin
2140
        MaxLODSize := CurrentGLContext.GLStates.Max3DTextureSize;
2141
        MaxLODZSize := MaxLODSize;
2142
      end;
2143

2144
    ttTextureCube:
2145
      begin
2146
        MaxLODSize := CurrentGLContext.GLStates.MaxCubeTextureSize;
2147
        MaxLODZSize := 0;
2148
      end;
2149

2150
    ttTexture1DArray,
2151
      ttTexture2DArray,
2152
      ttTextureCubeArray,
2153
      ttTexture2DMultisampleArray:
2154
      begin
2155
        MaxLODSize := CurrentGLContext.GLStates.MaxTextureSize;
2156
        MaxLODZSize := CurrentGLContext.GLStates.MaxArrayTextureSize;
2157
      end;
2158

2159
  else
2160
    begin
2161
      MaxLODSize := CurrentGLContext.GLStates.MaxTextureSize;
2162
      MaxLODZSize := 0;
2163
    end;
2164
  end;
2165

2166
  MinLODSize := 1;
2167

2168
  AFirstLOD := 0;
2169

2170
  for I := 0 to High(TGLImagePiramid) do
2171
  begin
2172
    if (FImage.LevelWidth[I] <= MaxLODSize)
2173
      and (FImage.LevelHeight[I] <= MaxLODSize)
2174
      and (FImage.LevelDepth[I] <= MaxLODZSize) then
2175
      break;
2176
    Inc(AFirstLOD);
2177
  end;
2178

2179
  AFirstLOD := MinInteger(AFirstLOD, FImage.LevelCount - 1);
2180
  ALastLOD := AFirstLOD;
2181

2182
  for I := AFirstLOD to High(TGLImagePiramid) do
2183
  begin
2184
    if (FImage.LevelWidth[I] < MinLODSize)
2185
      or (FImage.LevelHeight[I] < MinLODSize) then
2186
      break;
2187
    Inc(ALastLOD);
2188
  end;
2189
  ALastLOD := MinInteger(ALastLOD, FImage.LevelCount - 1);
2190
end;
2191

2192
procedure TGLTextureImageEx.StreamTransfer;
2193
var
2194
  LImage: TFriendlyImage;
2195
  bContinueStreaming: Boolean;
2196
  OldBaseLevel, level: Integer;
2197
  newTime: Double;
2198
  glInternalFormat: TGLEnum;
2199
  transferMethod: 0..3;
2200
begin
2201
  LImage := TFriendlyImage(FImage);
2202
  OldBaseLevel := FBaseLevel;
2203
  CalcLODRange(FBaseLevel, FMaxLevel);
2204

2205
  // Select transfer method
2206
  if FImage.IsCompressed then
2207
    transferMethod := 1
2208
  else
2209
    transferMethod := 0;
2210
  if GL.EXT_direct_state_access then
2211
    transferMethod := transferMethod + 2;
2212

2213
  bContinueStreaming := False;
2214
  for level := FMaxLevel downto FBaseLevel do
2215
  begin
2216

2217
    case LImage.LevelStreamingState[level] of
2218

2219
      ssKeeping:
2220
        begin
2221
          if FBaseLevel < Level then
2222
            FBaseLevel := FMaxLevel;
2223
          LImage.LevelStreamingState[Level] := ssLoading;
2224
          LImage.DoStreaming;
2225
          bContinueStreaming := True;
2226
        end;
2227

2228
      ssLoading:
2229
        begin
2230
          LImage.DoStreaming;
2231
          bContinueStreaming := True;
2232
          if FBaseLevel < Level then
2233
            FBaseLevel := FMaxLevel;
2234
        end;
2235

2236
      ssLoaded:
2237
        with GL do
2238
        begin
2239
          LImage.LevelPixelBuffer[Level].AllocateHandle;
2240
          LImage.LevelPixelBuffer[Level].Bind;
2241
          glInternalFormat := InternalFormatToOpenGLFormat(FInternalFormat);
2242
          case transferMethod of
2243
            0: TexImage2D(GL_TEXTURE_2D, Level, glInternalFormat, FImage.LevelWidth[level], FImage.LevelHeight[level], 0, FImage.ColorFormat, FImage.DataType, nil);
2244
            1: CompressedTexImage2D(GL_TEXTURE_2D, Level, glInternalFormat, FImage.LevelWidth[level], FImage.LevelHeight[level], 0, FImage.LevelSizeInByte[Level], nil);
2245
            2: TextureImage2D(FHandle.Handle, GL_TEXTURE_2D, Level, glInternalFormat, FImage.LevelWidth[level], FImage.LevelHeight[level], 0, FImage.ColorFormat, FImage.DataType, nil);
2246
            3: CompressedTextureImage2D(FHandle.Handle, GL_TEXTURE_2D, Level, glInternalFormat, FImage.LevelWidth[level], FImage.LevelHeight[level], 0, FImage.LevelSizeInByte[Level], nil);
2247
          end;
2248
          LImage.LevelPixelBuffer[Level].UnBind;
2249
          LImage.LevelStreamingState[Level] := ssTransfered;
2250
          GLSLogger.LogDebug(Format('Texture "%s" level %d loaded', [Name, Level]));
2251
        end;
2252

2253
      ssTransfered:
2254
        begin
2255
          if LImage.LevelPixelBuffer[Level].IsAllocatedForContext then
2256
            LImage.LevelPixelBuffer[Level].DestroyHandle;
2257
          FBaseLevel := Level;
2258
        end;
2259
    end; // of case
2260

2261
    if bContinueStreaming then
2262
      break;
2263
  end; // for level
2264

2265
  if bContinueStreaming then
2266
  with GL do
2267
  begin
2268
    TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, FMaxLevel);
2269
    TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, FBaseLevel);
2270
  end;
2271

2272

2273
  // Smooth transition between levels
2274
  if Assigned(FApplicableSampler) then
2275
  with FApplicableSampler do
2276
  begin
2277
    newTime := GLSTime;
2278
    if FLODBiasFract > 0 then
2279
      FLODBiasFract := FLODBiasFract - 0.05 * (newTime - FLastTime)
2280
    else if FLODBiasFract < 0 then
2281
      FLODBiasFract := 0;
2282
    FLastTime := newTime;
2283
    if OldBaseLevel > FBaseLevel then
2284
      FLODBiasFract := FLODBiasFract + (OldBaseLevel - FBaseLevel);
2285

2286
    if FApplicableSampler.IsValid then
2287
      GL.SamplerParameterf(FApplicableSampler.Handle.Handle,
2288
        GL_TEXTURE_LOD_BIAS, FLODBias + FLODBiasFract)
2289
    else
2290
      // To refrash texture parameters when sampler object not supported
2291
      FLastSampler := nil;
2292
  end;
2293
end;
2294

2295
class function TGLTextureImageEx.FriendlyName: string;
2296
begin
2297
  Result := 'Texture Image';
2298
end;
2299

2300
procedure TGLTextureImageEx.PrepareImage;
2301
const
2302
  cAlphaProc: array[TGLTextureImageAlpha] of TImageAlphaProc =
2303
    (
2304
    nil,
2305
    ImageAlphaFromIntensity,
2306
    ImageAlphaSuperBlackTransparent,
2307
    ImageAlphaLuminance,
2308
    ImageAlphaLuminanceSqrt,
2309
    ImageAlphaOpaque,
2310
    ImageAlphaTopLeftPointColorTransparent,
2311
    ImageAlphaInverseLuminance,
2312
    ImageAlphaInverseLuminanceSqrt,
2313
    ImageAlphaBottomRightPointColorTransparent
2314
    );
2315

2316
var
2317
  ext, filename: string;
2318
  BaseImageClass: TGLBaseImageClass;
2319
  LPicture: TGLPicture;
2320
  LGraphic: TGLGraphic;
2321
  LImage: TGLImage;
2322
  level: Integer;
2323
  glColorFormat, glDataType: TGLEnum;
2324
  bReadFromSource: Boolean;
2325
  LStream: TStream;
2326
  ptr: PByte;
2327

2328
  procedure ReplaceImageClass;
2329
  begin
2330
    if not (FImage is TGLImage) then
2331
    begin
2332
      LImage := TGLImage.Create;
2333
      LImage.Assign(FImage);
2334
      FImage.Destroy;
2335
      FImage := LImage;
2336
    end
2337
    else
2338
      LImage := TGLImage(FImage);
2339
  end;
2340

2341
begin
2342
  if not Assigned(FImage) then
2343
  begin
2344
    try
2345
      SetExeDirectory;
2346
      bReadFromSource := True;
2347

2348
      if FInternallyStored and not IsDesignTime then
2349
      begin
2350
        filename := Name+'.image';
2351
        if FileStreamExists(filename) then
2352
        begin
2353
          FImage := TGLImage.Create;
2354
          FImage.ResourceName := filename;
2355
          TFriendlyImage(FImage).LoadHeader;
2356
          if not FUseStreaming then
2357
          begin
2358
            ReallocMem(TFriendlyImage(FImage).fData, FImage.DataSize);
2359
            for level := FImage.LevelCount - 1 downto 0 do
2360
            begin
2361
              LStream := CreateFileStream(filename + IntToHex(level, 2), fmOpenRead);
2362
              ptr := PByte(TFriendlyImage(FImage).GetLevelAddress(level));
2363
              LStream.Read(ptr^, FImage.LevelSizeInByte[level]);
2364
              LStream.Destroy;
2365
            end;
2366
          end;
2367
          bReadFromSource := False;
2368
        end
2369
        else
2370
        begin
2371
          FInternallyStored := False;
2372
          FUseStreaming := False;
2373
        end;
2374
      end;
2375

2376
      if bReadFromSource then
2377
      begin
2378
        if (Length(FSourceFile) > 0) and FileStreamExists(FSourceFile) then
2379
        begin
2380
          // At first check moder image file loaders
2381
          ext := ExtractFileExt(FSourceFile);
2382
          System.Delete(ext, 1, 1);
2383
          BaseImageClass := GetRasterFileFormats.FindExt(ext);
2384

2385
          if Assigned(BaseImageClass) then
2386
          begin
2387
            FImage := BaseImageClass.Create;
2388
            FImage.LoadFromFile(FSourceFile);
2389
          end
2390
          else
2391
          begin
2392
            // Check old loaders
2393
            FImage := TGLImage.Create;
2394
            if ApplicationFileIODefined then
2395
            begin
2396
              LGraphic := CreateGraphicFromFile(FSourceFile);
2397
              FImage.Assign(LGraphic);
2398
              LGraphic.Free;
2399
            end
2400
            else
2401
            begin
2402
              LPicture := TGLPicture.Create;
2403
              LPicture.LoadFromFile(FSourceFile);
2404
              FImage.Assign(LPicture.Graphic);
2405
              LPicture.Destroy;
2406
            end;
2407
          end;
2408

2409
          if FInternalFormat <> FImage.InternalFormat then
2410
          begin
2411
            ReplaceImageClass;
2412
            FindCompatibleDataFormat(FInternalFormat, glColorFormat, glDataType);
2413
            TGLImage(FImage).SetColorFormatDataType(glColorFormat, glDataType);
2414
            TFriendlyImage(FImage).fInternalFormat := FInternalFormat;
2415
          end;
2416

2417
          if (ImageAlpha <> tiaDefault)
2418
            or (FImageBrightness <> 1.0)
2419
            or (FImageGamma <> 1.0) then
2420
          begin
2421
            ReplaceImageClass;
2422
            for level := 0 to FImage.LevelCount - 1 do
2423
            begin
2424
              AlphaGammaBrightCorrection(
2425
                TFriendlyImage(FImage).GetLevelAddress(level),
2426
                FImage.ColorFormat,
2427
                FImage.DataType,
2428
                FImage.LevelWidth[level],
2429
                FImage.LevelHeight[level],
2430
                cAlphaProc[ImageAlpha],
2431
                FImageBrightness,
2432
                FImageGamma);
2433
            end;
2434
          end
2435
          else if FHeightToNormalScale <> 1.0 then
2436
          begin
2437
            ReplaceImageClass;
2438
  //          HeightToNormalMap();
2439
  {$Message Hint 'TGLTextureImageEx.HeightToNormalScale not yet implemented' }
2440
          end;
2441

2442
          case FMipGenMode of
2443
            mgmNoMip:
2444
              FImage.UnMipmap;
2445

2446
            mgmLeaveExisting, mgmOnFly: ;
2447

2448
            mgmBoxFilter:
2449
              FImage.GenerateMipmap(ImageBoxFilter);
2450

2451
            mgmTriangleFilter:
2452
              FImage.GenerateMipmap(ImageTriangleFilter);
2453

2454
            mgmHermiteFilter:
2455
              FImage.GenerateMipmap(ImageHermiteFilter);
2456

2457
            mgmBellFilter:
2458
              FImage.GenerateMipmap(ImageBellFilter);
2459

2460
            mgmSplineFilter:
2461
              FImage.GenerateMipmap(ImageSplineFilter);
2462

2463
            mgmLanczos3Filter:
2464
              FImage.GenerateMipmap(ImageLanczos3Filter);
2465

2466
            mgmMitchellFilter:
2467
              FImage.GenerateMipmap(ImageMitchellFilter);
2468
          end;
2469

2470
          // Store cooked image
2471
          if FInternallyStored and IsDesignTime then
2472
          begin
2473
            filename := Name+'.image';
2474
            FImage.ResourceName := filename;
2475
            TFriendlyImage(FImage).SaveHeader;
2476
            for level := FImage.LevelCount - 1 downto 0 do
2477
            begin
2478
              LStream := CreateFileStream(filename + IntToHex(level, 2),
2479
                fmOpenWrite or fmCreate);
2480
              ptr := PByte(TFriendlyImage(FImage).GetLevelAddress(level));
2481
              LStream.Write(ptr^, FImage.LevelSizeInByte[level]);
2482
              LStream.Destroy;
2483
            end;
2484
          end;
2485

2486
        end
2487
        else
2488
        begin // no SourceFile
2489
          FImage := TGLImage.Create;
2490
          FImage.SetErrorImage;
2491
          GLSLogger.LogErrorFmt('Source file of texture "%s" image not found',
2492
            [Self.Name]);
2493
        end;
2494
      end; // if bReadFromSource
2495

2496
    except
2497
      on E: Exception do
2498
      begin
2499
        FImage.Free;
2500
        FImage := TGLImage.Create;
2501
        FImage.SetErrorImage;
2502
        if IsDesignTime then
2503
          InformationDlg(Self.Name + ' - ' + E.ClassName + ': ' + E.Message)
2504
        else
2505
          GLSLogger.LogError(Self.Name + ' - ' + E.ClassName + ': ' +
2506
            E.Message);
2507
      end;
2508
    end;
2509
  end; // of not Assigned
2510
end;
2511

2512
procedure TGLTextureImageEx.ReadFromFiler(AReader: TReader);
2513
var
2514
  archiveVersion: Integer;
2515
begin
2516
  with AReader do
2517
  begin
2518
    archiveVersion := ReadInteger;
2519
    if archiveVersion = 0 then
2520
    begin
2521
      Name := ReadWideString;
2522
      FDefferedInit := ReadBoolean;
2523
      FInternalFormat := TGLInternalFormat(ReadInteger);
2524
      FCompression := TGLTextureCompression(ReadInteger);
2525
      FImageAlpha := TGLTextureImageAlpha(ReadInteger);
2526
      FImageBrightness := ReadFloat;
2527
      FImageBrightness := ReadFloat;
2528
      FImageGamma := ReadFloat;
2529
      FHeightToNormalScale := ReadFloat;
2530
      FSourceFile := ReadWideString;
2531
      FInternallyStored := ReadBoolean;
2532
      FMipGenMode := TMipmapGenerationMode(ReadInteger);
2533
      FUseStreaming := ReadBoolean;
2534
    end
2535
    else
2536
      RaiseFilerException(archiveVersion);
2537
  end;
2538
end;
2539

2540
procedure TGLTextureImageEx.SetCompression(const AValue: TGLTextureCompression);
2541
begin
2542
  if AValue <> FCompression then
2543
  begin
2544
    FCompression := AValue;
2545
    NotifyChange(Self);
2546
  end;
2547
end;
2548

2549
procedure TGLTextureImageEx.SetImageAlpha(const AValue: TGLTextureImageAlpha);
2550
begin
2551
  if FImageAlpha <> AValue then
2552
  begin
2553
    FImageAlpha := AValue;
2554
    FreeAndNil(FImage);
2555
    NotifyChange(Self);
2556
  end;
2557
end;
2558

2559
procedure TGLTextureImageEx.SetImageBrightness(const AValue: Single);
2560
begin
2561
  if FImageBrightness <> AValue then
2562
  begin
2563
    FImageBrightness := AValue;
2564
    FreeAndNil(FImage);
2565
    NotifyChange(Self);
2566
  end;
2567
end;
2568

2569
procedure TGLTextureImageEx.SetImageGamma(const AValue: Single);
2570
begin
2571
  if FImageGamma <> AValue then
2572
  begin
2573
    FImageGamma := AValue;
2574
    FreeAndNil(FImage);
2575
    NotifyChange(Self);
2576
  end;
2577
end;
2578

2579
procedure TGLTextureImageEx.SetInternalFormat(const AValue: TGLInternalFormat);
2580
begin
2581
  if AValue <> FInternalFormat then
2582
  begin
2583
    FInternalFormat := AValue;
2584
    FreeAndNil(FImage);
2585
    NotifyChange(Self);
2586
  end;
2587
end;
2588

2589
procedure TGLTextureImageEx.SetInternallyStored(const AValue: Boolean);
2590
begin
2591
  if FInternallyStored <> AValue then
2592
  begin
2593
    FInternallyStored := AValue;
2594
    if not AValue then
2595
      FUseStreaming := AValue
2596
    else
2597
      FreeAndNil(FImage);
2598
    NotifyChange(Self);
2599
  end;
2600
end;
2601

2602
procedure TGLTextureImageEx.SetMipGenMode(const AValue: TMipmapGenerationMode);
2603
begin
2604
  if FMipGenMode <> AValue then
2605
  begin
2606
    FMipGenMode := AValue;
2607
    FreeAndNil(FImage);
2608
    NotifyChange(Self);
2609
  end;
2610
end;
2611

2612
procedure TGLTextureImageEx.SetNormalMapScale(const AValue: Single);
2613
begin
2614
  if AValue <> FHeightToNormalScale then
2615
  begin
2616
    FHeightToNormalScale := AValue;
2617
    NotifyChange(Self);
2618
  end;
2619
end;
2620

2621
procedure TGLTextureImageEx.SetSourceFile(AValue: string);
2622
begin
2623
  FixPathDelimiter(AValue);
2624
  if FSourceFile <> AValue then
2625
  begin
2626
    FSourceFile := AValue;
2627
    FUseStreaming := False;
2628
    FreeAndNil(FImage);
2629
    NotifyChange(Self);
2630
  end;
2631
end;
2632

2633
procedure TGLTextureImageEx.SetUseStreaming(const AValue: Boolean);
2634
begin
2635
  if AValue <> FUseStreaming then
2636
  begin
2637
    if AValue then
2638
    begin
2639
      if not Assigned(FImage) then
2640
        exit;
2641
      if FImage.LevelCount = 1 then
2642
      begin
2643
        if IsDesignTime then
2644
          InformationDlg('Image must be more than one level');
2645
        exit;
2646
      end;
2647
      FInternallyStored := True;
2648
    end;
2649
    FUseStreaming := AValue;
2650
    NotifyChange(Self);
2651
  end;
2652
end;
2653

2654
function TGLTextureImageEx.StoreBrightness: Boolean;
2655
begin
2656
  Result := (FImageBrightness <> 1.0);
2657
end;
2658

2659
function TGLTextureImageEx.StoreGamma: Boolean;
2660
begin
2661
  Result := (FImageGamma <> 1.0);
2662
end;
2663

2664
function TGLTextureImageEx.StoreNormalMapScale: Boolean;
2665
begin
2666
  Result := (FHeightToNormalScale <> cDefaultNormalMapScale);
2667
end;
2668

2669
procedure TGLTextureImageEx.UnApply(var ARci: TGLRenderContextInfo);
2670
begin
2671
  ARci.GLStates.ActiveTextureEnabled[FHandle.Target] := False;
2672
end;
2673

2674
procedure TGLTextureImageEx.WriteToFiler(AWriter: TWriter);
2675
begin
2676
  with AWriter do
2677
  begin
2678
    WriteInteger(0); // archive version
2679
    WriteString(Name);
2680
    WriteBoolean(FDefferedInit);
2681
    WriteInteger(Integer(FInternalFormat));
2682
    WriteInteger(Integer(FCompression));
2683
    WriteInteger(Integer(FImageAlpha));
2684
    WriteFloat(FImageBrightness);
2685
    WriteFloat(FImageBrightness);
2686
    WriteFloat(FImageGamma);
2687
    WriteFloat(FHeightToNormalScale);
2688
    WriteString(FSourceFile);
2689
    WriteBoolean(FInternallyStored);
2690
    WriteInteger(Integer(FMipGenMode));
2691
    WriteBoolean(FUseStreaming);
2692
  end;
2693
end;
2694

2695
{$IFDEF GLS_REGION}{$ENDREGION}{$ENDIF}
2696

2697
{$IFDEF GLS_REGION}{$REGION 'TGLTextureSampler'}{$ENDIF}
2698

2699
procedure TGLTextureSampler.Apply(var ARci: TGLRenderContextInfo);
2700
begin
2701
  if FIsValid then
2702
    ARci.GLStates.SamplerBinding[ARci.GLStates.ActiveTexture] := FHandle.Handle;
2703
end;
2704

2705
procedure TGLTextureSampler.Assign(Source: TPersistent);
2706
var
2707
  LSampler: TGLTextureSampler;
2708
begin
2709
  if Source is TGLTextureSampler then
2710
  begin
2711
    LSampler := TGLTextureSampler(Source);
2712
    FMinFilter := LSampler.FMinFilter;
2713
    FMagFilter := LSampler.FMagFilter;
2714
    FFilteringQuality := LSampler.FFilteringQuality;
2715
    FLODBias := LSampler.FLODBias;
2716
    FLODBiasFract := 0;
2717
    FBorderColor.Assign(LSampler.FBorderColor);
2718
    FWrap := LSampler.FWrap;
2719
    FCompareMode := LSampler.FCompareMode;
2720
    FCompareFunc := LSampler.FCompareFunc;
2721
    FDecodeSRGB := LSampler.FDecodeSRGB;
2722
    NotifyChange(Self);
2723
  end;
2724
  inherited;
2725
end;
2726

2727
constructor TGLTextureSampler.Create(AOwner: TGLXCollection);
2728
begin
2729
  inherited;
2730
  FDefferedInit := False;
2731
  FHandle := TGLSamplerHandle.Create;
2732
  FHandle.OnPrapare := DoOnPrepare;
2733
  FMagFilter := maLinear;
2734
  FMinFilter := miLinearMipMapLinear;
2735
  FFilteringQuality := tfAnisotropic;
2736
  FLODBias := 0;
2737
  FLODBiasFract := 0;
2738
  FWrap[0] := twRepeat;
2739
  FWrap[1] := twRepeat;
2740
  FWrap[2] := twRepeat;
2741
  FBorderColor := TGLColor.CreateInitialized(Self, clrTransparent);
2742
  FCompareMode := tcmNone;
2743
  FCompareFunc := cfLequal;
2744
  FDecodeSRGB := True;
2745
  Name := TGLMatLibComponents(AOwner).MakeUniqueName('Sampler');
2746
end;
2747

2748
destructor TGLTextureSampler.Destroy;
2749
begin
2750
  FHandle.Destroy;
2751
  FBorderColor.Destroy;
2752
  inherited;
2753
end;
2754

2755
function TGLTextureSampler.GetWrap(Index: Integer): TGLSeparateTextureWrap;
2756
begin
2757
  Result := FWrap[Index];
2758
end;
2759

2760
procedure TGLTextureSampler.NotifyChange(Sender: TObject);
2761
begin
2762
  FHandle.NotifyChangesOfData;
2763
  inherited;
2764
end;
2765

2766
procedure TGLTextureSampler.DoOnPrepare(Sender: TGLContext);
2767
var
2768
  ID: TGLUint;
2769
begin
2770
  if IsDesignTime and FDefferedInit then
2771
    exit;
2772
  try
2773
    if FHandle.IsSupported then
2774
    begin
2775
      FHandle.AllocateHandle;
2776
      ID := FHandle.Handle;
2777
      if FHandle.IsDataNeedUpdate then
2778
        with Sender.GL do
2779
        begin
2780
          SamplerParameterfv(ID, GL_TEXTURE_BORDER_COLOR,
2781
            FBorderColor.AsAddress);
2782
          SamplerParameteri(ID, GL_TEXTURE_WRAP_S, cTextureWrapMode[FWrap[0]]);
2783
          SamplerParameteri(ID, GL_TEXTURE_WRAP_T, cTextureWrapMode[FWrap[1]]);
2784
          SamplerParameteri(ID, GL_TEXTURE_WRAP_R, cTextureWrapMode[FWrap[2]]);
2785
          SamplerParameterf(ID, GL_TEXTURE_LOD_BIAS, FLODBias + FLODBiasFract);
2786
          SamplerParameteri(ID, GL_TEXTURE_MIN_FILTER,
2787
            cTextureMinFilter[FMinFilter]);
2788
          SamplerParameteri(ID, GL_TEXTURE_MAG_FILTER,
2789
            cTextureMagFilter[FMagFilter]);
2790

2791
          if EXT_texture_filter_anisotropic then
2792
          begin
2793
            if FFilteringQuality = tfAnisotropic then
2794
              SamplerParameteri(ID, GL_TEXTURE_MAX_ANISOTROPY_EXT,
2795
                CurrentGLContext.GLStates.MaxTextureAnisotropy)
2796
            else
2797
              SamplerParameteri(ID, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1);
2798
          end;
2799

2800
          SamplerParameteri(ID, GL_TEXTURE_COMPARE_MODE,
2801
            cTextureCompareMode[FCompareMode]);
2802
          SamplerParameteri(ID, GL_TEXTURE_COMPARE_FUNC,
2803
            cGLComparisonFunctionToGLEnum[FCompareFunc]);
2804

2805
          if EXT_texture_sRGB_decode then
2806
          begin
2807
            if FDecodeSRGB then
2808
              SamplerParameteri(ID, GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT)
2809
            else
2810
              SamplerParameteri(ID, GL_TEXTURE_SRGB_DECODE_EXT,
2811
                GL_SKIP_DECODE_EXT);
2812
          end;
2813
{$IFDEF GLS_OPENGL_DEBUG}
2814
          CheckError;
2815
{$ENDIF}
2816

2817
          FHandle.NotifyDataUpdated;
2818
        end;
2819
      FIsValid := True;
2820
    end
2821
    else
2822
      FIsValid := False;
2823

2824
  except
2825
    FIsValid := False;
2826
  end;
2827
end;
2828

2829
class function TGLTextureSampler.FriendlyName: string;
2830
begin
2831
  Result := 'Texture Sampler';
2832
end;
2833

2834
procedure TGLTextureSampler.ReadFromFiler(AReader: TReader);
2835
var
2836
  archiveVersion: Integer;
2837
begin
2838
  with AReader do
2839
  begin
2840
    archiveVersion := ReadInteger;
2841
    if archiveVersion = 0 then
2842
    begin
2843
      Name := ReadWideString;
2844
      FDefferedInit := ReadBoolean;
2845
      FMinFilter := TGLMinFilter(ReadInteger);
2846
      FMagFilter := TGLMagFilter(ReadInteger);
2847
      FFilteringQuality := TGLTextureFilteringQuality(ReadInteger);
2848
      FLODBias := ReadInteger;
2849
      FWrap[0] := TGLSeparateTextureWrap(ReadInteger);
2850
      FWrap[1] := TGLSeparateTextureWrap(ReadInteger);
2851
      FWrap[2] := TGLSeparateTextureWrap(ReadInteger);
2852
      Read(FBorderColor.AsAddress^, SizeOf(TColorVector));
2853
      FCompareMode := TGLTextureCompareMode(ReadInteger);
2854
      FCompareFunc := TDepthFunction(ReadInteger);
2855
      FDecodeSRGB := ReadBoolean;
2856
    end
2857
    else
2858
      RaiseFilerException(archiveVersion);
2859
  end;
2860
end;
2861

2862
procedure TGLTextureSampler.SetBorderColor(const AValue: TGLColor);
2863
begin
2864
  FBorderColor.Assign(AValue);
2865
  NotifyChange(Self);
2866
end;
2867

2868
procedure TGLTextureSampler.SetCompareFunc(AValue: TDepthFunction);
2869
begin
2870
  if FCompareFunc <> AValue then
2871
  begin
2872
    FCompareFunc := AValue;
2873
    NotifyChange(Self);
2874
  end;
2875
end;
2876

2877
procedure TGLTextureSampler.SetCompareMode(AValue: TGLTextureCompareMode);
2878
begin
2879
  if FCompareMode <> AValue then
2880
  begin
2881
    FCompareMode := AValue;
2882
    NotifyChange(Self);
2883
  end;
2884
end;
2885

2886
procedure TGLTextureSampler.SetDecodeSRGB(AValue: Boolean);
2887
begin
2888
  if FDecodeSRGB <> AValue then
2889
  begin
2890
    FDecodeSRGB := AValue;
2891
    NotifyChange(Self);
2892
  end;
2893
end;
2894

2895
procedure TGLTextureSampler.SetFilteringQuality(
2896
  AValue: TGLTextureFilteringQuality);
2897
begin
2898
  if FFilteringQuality <> AValue then
2899
  begin
2900
    FFilteringQuality := AValue;
2901
    NotifyChange(Self);
2902
  end;
2903
end;
2904

2905
procedure TGLTextureSampler.SetLODBias(AValue: Integer);
2906
begin
2907
  if FLODBias <> AValue then
2908
  begin
2909
    FLODBias := AValue;
2910
    NotifyChange(Self);
2911
  end;
2912
end;
2913

2914
procedure TGLTextureSampler.SetMagFilter(AValue: TGLMagFilter);
2915
begin
2916
  if FMagFilter <> AValue then
2917
  begin
2918
    FMagFilter := AValue;
2919
    NotifyChange(Self);
2920
  end;
2921
end;
2922

2923
procedure TGLTextureSampler.SetMinFilter(AValue: TGLMinFilter);
2924
begin
2925
  if FMinFilter <> AValue then
2926
  begin
2927
    FMinFilter := AValue;
2928
    NotifyChange(Self);
2929
  end;
2930
end;
2931

2932
procedure TGLTextureSampler.SetWrap(Index: Integer;
2933
  AValue: TGLSeparateTextureWrap);
2934
begin
2935
  if FWrap[Index] <> AValue then
2936
  begin
2937
    FWrap[Index] := AValue;
2938
    NotifyChange(Self);
2939
  end;
2940
end;
2941

2942
procedure TGLTextureSampler.UnApply(var ARci: TGLRenderContextInfo);
2943
begin
2944
  if FHandle.IsSupported then
2945
    with ARci.GLStates do
2946
      SamplerBinding[ActiveTexture] := 0;
2947
end;
2948

2949
procedure TGLTextureSampler.WriteToFiler(AWriter: TWriter);
2950
begin
2951
  with AWriter do
2952
  begin
2953
    WriteInteger(0); // archive version
2954
    WriteWideString(Name);
2955
    WriteBoolean(FDefferedInit);
2956
    WriteInteger(Integer(FMinFilter));
2957
    WriteInteger(Integer(FMagFilter));
2958
    WriteInteger(Integer(FFilteringQuality));
2959
    WriteInteger(FLODBias);
2960
    WriteInteger(Integer(FWrap[0]));
2961
    WriteInteger(Integer(FWrap[1]));
2962
    WriteInteger(Integer(FWrap[2]));
2963
    Write(FBorderColor.AsAddress^, SizeOf(TColorVector));
2964
    WriteInteger(Integer(FCompareMode));
2965
    WriteInteger(Integer(FCompareFunc));
2966
    WriteBoolean(FDecodeSRGB);
2967
  end;
2968
end;
2969

2970
{$IFDEF GLS_REGION}{$ENDREGION}{$ENDIF}
2971

2972
{$IFDEF GLS_REGION}{$REGION 'TGLTextureCombiner'}{$ENDIF}
2973

2974
procedure TGLTextureCombiner.Assign(Source: TPersistent);
2975
var
2976
  LCombiner: TGLTextureCombiner;
2977
begin
2978
  if Source is TGLTextureCombiner then
2979
  begin
2980
    LCombiner := TGLTextureCombiner(Source);
2981
    FScript.Assign(LCombiner.FScript);
2982
  end;
2983
  inherited;
2984
end;
2985

2986
constructor TGLTextureCombiner.Create(AOwner: TGLXCollection);
2987
begin
2988
  inherited;
2989
  FDefferedInit := False;
2990
  FHandle := TGLVirtualHandle.Create;
2991
  FHandle.OnAllocate := DoAllocate;
2992
  FHandle.OnDestroy := DoDeallocate;
2993
  FHandle.OnPrapare := DoOnPrepare;
2994
  FScript := TStringList.Create;
2995
  FScript.OnChange := NotifyChange;
2996
  FIsValid := True;
2997
  Name := TGLMatLibComponents(AOwner).MakeUniqueName('Combiner');
2998
end;
2999

3000
destructor TGLTextureCombiner.Destroy;
3001
begin
3002
  FHandle.Destroy;
3003
  FScript.Destroy;
3004
  inherited;
3005
end;
3006

3007
procedure TGLTextureCombiner.NotifyChange(Sender: TObject);
3008
begin
3009
  FHandle.NotifyChangesOfData;
3010
  inherited;
3011
end;
3012

3013
procedure TGLTextureCombiner.DoAllocate(Sender: TGLVirtualHandle;
3014
  var handle: TGLUint);
3015
begin
3016
  handle := 1;
3017
end;
3018

3019
procedure TGLTextureCombiner.DoDeallocate(Sender: TGLVirtualHandle;
3020
  var handle: TGLUint);
3021
begin
3022
  handle := 0;
3023
end;
3024

3025
procedure TGLTextureCombiner.DoOnPrepare(Sender: TGLContext);
3026
begin
3027
  if IsDesignTime and FDefferedInit then
3028
    exit;
3029
  if Sender.GL.ARB_multitexture then
3030
  begin
3031
    FHandle.AllocateHandle;
3032
    if FHandle.IsDataNeedUpdate then
3033
    begin
3034
      try
3035
        FCommandCache := GetTextureCombiners(FScript);
3036
        FIsValid := True;
3037
      except
3038
        on E: Exception do
3039
        begin
3040
          FIsValid := False;
3041
          if IsDesignTime then
3042
            InformationDlg(E.ClassName + ': ' + E.Message)
3043
          else
3044
            GLSLogger.LogError(E.ClassName + ': ' + E.Message);
3045
        end;
3046
      end;
3047
      FHandle.NotifyDataUpdated;
3048
    end;
3049
  end
3050
  else
3051
    FIsValid := False;
3052
end;
3053

3054
class function TGLTextureCombiner.FriendlyName: string;
3055
begin
3056
  Result := 'Texture Combiner';
3057
end;
3058

3059
procedure TGLTextureCombiner.ReadFromFiler(AReader: TReader);
3060
var
3061
  archiveVersion: Integer;
3062
begin
3063
  with AReader do
3064
  begin
3065
    archiveVersion := ReadInteger;
3066
    if archiveVersion = 0 then
3067
    begin
3068
      Name := ReadWideString;
3069
      FDefferedInit := ReadBoolean;
3070
      FScript.Text := ReadWideString;
3071
    end
3072
    else
3073
      RaiseFilerException(archiveVersion);
3074
  end;
3075
end;
3076

3077
procedure TGLTextureCombiner.SetScript(AValue: TStringList);
3078
begin
3079
  FScript.Assign(AValue);
3080
  NotifyChange(Self);
3081
end;
3082

3083
procedure TGLTextureCombiner.WriteToFiler(AWriter: TWriter);
3084
begin
3085
  with AWriter do
3086
  begin
3087
    WriteInteger(0); // archive version
3088
    WriteWideString(Name);
3089
    WriteBoolean(FDefferedInit);
3090
    WriteWideString(FScript.Text);
3091
  end;
3092
end;
3093

3094
{$IFDEF GLS_REGION}{$ENDREGION}{$ENDIF}
3095

3096
{$IFDEF GLS_REGION}{$REGION 'TGLLibMaterialEx'}{$ENDIF}
3097

3098
procedure TGLLibMaterialEx.Apply(var ARci: TGLRenderContextInfo);
3099
var
3100
  LevelReady: array[TGLMaterialLevel] of Boolean;
3101
  L, MaxLevel: TGLMaterialLevel;
3102
begin
3103
  if Assigned(FNextPass) then
3104
  begin
3105
    FNextPass := nil;
3106
    exit;
3107
  end;
3108

3109
  FHandle.AllocateHandle;
3110
  if FHandle.IsDataNeedUpdate then
3111
  begin
3112
    // Other value than mlAuto indicates a level failure
3113
    // Need remove deffered initialization and reinitialize used resources
3114
    if not IsDesignTime and (FSelectedLevel <> mlAuto) then
3115
      RemoveDefferedInit;
3116
    // Level selection
3117
    LevelReady[mlFixedFunction] := FFixedFunc.Enabled;
3118
    LevelReady[mlMultitexturing] := FMultitexturing.Enabled and
3119
      FMultitexturing.IsValid;
3120
    LevelReady[mlSM3] := FSM3.Enabled and FSM3.IsValid;
3121
    LevelReady[mlSM4] := FSM4.Enabled and FSM4.IsValid;
3122
    LevelReady[mlSM5] := FSM5.Enabled and FSM5.IsValid;
3123

3124
    if FApplicableLevel = mlAuto then
3125
      MaxLevel := mlSM5
3126
    else
3127
      MaxLevel := FApplicableLevel;
3128

3129
    FSelectedLevel := mlAuto;
3130
    for L := MaxLevel downto mlFixedFunction do
3131
      if LevelReady[L] then
3132
      begin
3133
        FSelectedLevel := L;
3134
        break;
3135
      end;
3136

3137
    FStoreAmalgamating := ARci.amalgamating;
3138
    ARci.amalgamating := True;
3139
    FHandle.NotifyDataUpdated;
3140
  end;
3141

3142
  ARci.currentMaterialLevel := FSelectedLevel;
3143

3144
  case FSelectedLevel of
3145
    mlAuto: ; // No one level can be used. Worst case.
3146

3147
    mlFixedFunction:
3148
      begin
3149
        FFixedFunc.Apply(ARci);
3150
      end;
3151

3152
    mlMultitexturing:
3153
      begin
3154
        if LevelReady[mlFixedFunction] then
3155
          FFixedFunc.Apply(ARci);
3156
        FMultitexturing.Apply(ARci);
3157
      end;
3158

3159
    mlSM3:
3160
      begin
3161
        if LevelReady[mlFixedFunction] then
3162
          FFixedFunc.Apply(ARci);
3163
        FSM3.Apply(ARci);
3164
      end;
3165

3166
    mlSM4:
3167
      begin
3168
        if LevelReady[mlFixedFunction] then
3169
          FFixedFunc.Apply(ARci);
3170
        FSM4.Apply(ARci);
3171
      end;
3172

3173
    mlSM5:
3174
      begin
3175
        if LevelReady[mlFixedFunction] then
3176
          FFixedFunc.Apply(ARci);
3177
        FSM5.Apply(ARci);
3178
      end;
3179
  end;
3180
end;
3181

3182
procedure TGLLibMaterialEx.Assign(Source: TPersistent);
3183
var
3184
  LMaterial: TGLLibMaterialEx;
3185
begin
3186
  if Source is TGLLibMaterialEx then
3187
  begin
3188
    LMaterial := TGLLibMaterialEx(Source);
3189
    FFixedFunc.Assign(LMaterial.FFixedFunc);
3190
    FMultitexturing.Assign(LMaterial.FMultitexturing);
3191
    FSM3.Assign(LMaterial.FSM3);
3192
    FSM4.Assign(LMaterial.FSM4);
3193
    FSM5.Assign(LMaterial.FSM5);
3194
    FApplicableLevel := LMaterial.FApplicableLevel;
3195
    NotifyChange(Self);
3196
  end;
3197
  inherited;
3198
end;
3199

3200
function TGLLibMaterialEx.Blended: Boolean;
3201
begin
3202
  Result := FFixedFunc.Blended;
3203
end;
3204

3205
constructor TGLLibMaterialEx.Create(ACollection: TCollection);
3206
begin
3207
  inherited;
3208
  FHandle := TGLVirtualHandle.Create;
3209
  FHandle.OnAllocate := DoAllocate;
3210
  FHandle.OnDestroy := DoDeallocate;
3211
  FHandle.OnPrapare := DoOnPrepare;
3212
  FApplicableLevel := mlAuto;
3213
  FSelectedLevel := mlAuto;
3214
  FFixedFunc := TGLFixedFunctionProperties.Create(Self);
3215
  FMultitexturing := TGLMultitexturingProperties.Create(Self);
3216
  FSM3 := TGLShaderModel3.Create(Self);
3217
  FSM4 := TGLShaderModel4.Create(Self);
3218
  FSM5 := TGLShaderModel5.Create(Self);
3219
end;
3220

3221
type
3222
  TGLFreindlyMaterial = class(TGLMaterial);
3223

3224
destructor TGLLibMaterialEx.Destroy;
3225
var
3226
  I: Integer;
3227
  LUser: TObject;
3228
begin
3229
  FHandle.Destroy;
3230
  FFixedFunc.Destroy;
3231
  FMultitexturing.Destroy;
3232
  FSM3.Destroy;
3233
  FSM4.Destroy;
3234
  FSM5.Destroy;
3235
  for I := 0 to FUserList.Count - 1 do
3236
  begin
3237
    LUser := TObject(FUserList[i]);
3238
    if LUser is TGLMaterial then
3239
      TGLFreindlyMaterial(LUser).NotifyLibMaterialDestruction;
3240
  end;
3241
  inherited;
3242
end;
3243

3244
procedure TGLLibMaterialEx.DoAllocate(Sender: TGLVirtualHandle;
3245
  var handle: TGLUint);
3246
begin
3247
  handle := 1;
3248
end;
3249

3250
procedure TGLLibMaterialEx.DoDeallocate(Sender: TGLVirtualHandle;
3251
  var handle: TGLUint);
3252
begin
3253
  handle := 0;
3254
end;
3255

3256
procedure TGLLibMaterialEx.DoOnPrepare(Sender: TGLContext);
3257
begin
3258
end;
3259

3260
procedure TGLLibMaterialEx.Loaded;
3261
begin
3262
  FFixedFunc.FTexProp.Loaded;
3263
  FMultitexturing.Loaded;
3264
  FSM3.Loaded;
3265
  FSM4.Loaded;
3266
  FSM5.Loaded;
3267
end;
3268

3269
procedure TGLLibMaterialEx.NotifyChange(Sender: TObject);
3270
begin
3271
  inherited;
3272
  FHandle.NotifyChangesOfData;
3273
end;
3274

3275
procedure TGLLibMaterialEx.RemoveDefferedInit;
3276
var
3277
  I: Integer;
3278
  ST: TGLShaderType;
3279
begin
3280
  if FFixedFunc.FTexProp.Enabled then
3281
  begin
3282
    if Assigned(FFixedFunc.FTexProp.FLibTexture) then
3283
      FFixedFunc.FTexProp.FLibTexture.FDefferedInit := False;
3284
    if Assigned(FFixedFunc.FTexProp.FLibSampler) then
3285
      FFixedFunc.FTexProp.FLibSampler.FDefferedInit := False;
3286
  end;
3287

3288
  if FMultitexturing.Enabled then
3289
  begin
3290
    if Assigned(FMultitexturing.FLibCombiner) then
3291
    begin
3292
      FMultitexturing.FLibCombiner.FDefferedInit := False;
3293
      for I := 0 to 3 do
3294
        if Assigned(FMultitexturing.FTexProps[I]) then
3295
          with FMultitexturing.FTexProps[I] do
3296
          begin
3297
            if Assigned(FLibTexture) then
3298
              FLibTexture.FDefferedInit := False;
3299
            if Assigned(FLibSampler) then
3300
              FLibSampler.FDefferedInit := False;
3301
          end;
3302
    end;
3303
  end;
3304

3305
  if FSM3.Enabled then
3306
  begin
3307
    for ST := Low(TGLShaderType) to High(TGLShaderType) do
3308
      if Assigned(FSM3.FShaders[ST]) then
3309
        FSM3.FShaders[ST].FDefferedInit := False;
3310
  end;
3311

3312
  if FSM4.Enabled then
3313
  begin
3314
    for ST := Low(TGLShaderType) to High(TGLShaderType) do
3315
      if Assigned(FSM4.FShaders[ST]) then
3316
        FSM4.FShaders[ST].FDefferedInit := False;
3317
  end;
3318

3319
  if FSM5.Enabled then
3320
  begin
3321
    for ST := Low(TGLShaderType) to High(TGLShaderType) do
3322
      if Assigned(FSM5.FShaders[ST]) then
3323
        FSM5.FShaders[ST].FDefferedInit := False;
3324
  end;
3325

3326
  CurrentGLContext.PrepareHandlesData;
3327
end;
3328

3329
procedure TGLLibMaterialEx.SetMultitexturing(AValue:
3330
  TGLMultitexturingProperties);
3331
begin
3332
  FMultitexturing.Assign(AValue);
3333
end;
3334

3335
procedure TGLLibMaterialEx.SetFixedFunc(AValue: TGLFixedFunctionProperties);
3336
begin
3337
  FFixedFunc.Assign(AValue);
3338
end;
3339

3340
procedure TGLLibMaterialEx.SetLevel(AValue: TGLMaterialLevel);
3341
begin
3342
  if FApplicableLevel <> AValue then
3343
  begin
3344
    FApplicableLevel := AValue;
3345
    NotifyChange(Self);
3346
  end;
3347
end;
3348

3349
procedure TGLLibMaterialEx.SetSM3(AValue: TGLShaderModel3);
3350
begin
3351
  FSM3.Assign(AValue);
3352
end;
3353

3354
procedure TGLLibMaterialEx.SetSM4(AValue: TGLShaderModel4);
3355
begin
3356
  FSM4.Assign(AValue);
3357
end;
3358

3359
procedure TGLLibMaterialEx.SetSM5(AValue: TGLShaderModel5);
3360
begin
3361
  FSM5.Assign(AValue);
3362
end;
3363

3364
function TGLLibMaterialEx.UnApply(var ARci: TGLRenderContextInfo): Boolean;
3365

3366
  procedure GetNextPass(AProp: TGLLibMaterialProperty);
3367
  begin
3368
    if Length(AProp.NextPass) > 0 then
3369
      FNextPass :=
3370
        TGLMaterialLibraryEx(GetMaterialLibrary).Materials.GetLibMaterialByName(AProp.NextPass)
3371
    else
3372
      FNextPass := nil;
3373

3374
    if FNextPass = Self then
3375
    begin
3376
      AProp.NextPass := '';
3377
      FNextPass := nil;
3378
    end;
3379
  end;
3380

3381
begin
3382
  if FStoreAmalgamating <> ARci.amalgamating then
3383
    ARci.amalgamating := FStoreAmalgamating;
3384

3385
  if Assigned(FNextPass) then
3386
  begin
3387
    Result := FNextPass.UnApply(ARci);
3388
    if Result then
3389
      FNextPass.Apply(ARci)
3390
    else
3391
      FNextPass := nil;
3392
    exit;
3393
  end;
3394

3395
  case FSelectedLevel of
3396
    mlFixedFunction:
3397
      begin
3398
        FFixedFunc.UnApply(ARci);
3399
        GetNextPass(FFixedFunc);
3400
      end;
3401

3402
    mlMultitexturing:
3403
      begin
3404
        if FFixedFunc.Enabled then
3405
          FFixedFunc.UnApply(ARci);
3406
        FMultitexturing.UnApply(ARci);
3407
        GetNextPass(FMultitexturing);
3408
      end;
3409

3410
    mlSM3:
3411
      begin
3412
        if FFixedFunc.Enabled then
3413
          FFixedFunc.UnApply(ARci);
3414
        FSM3.UnApply(ARci);
3415
        GetNextPass(FSM3);
3416
      end;
3417

3418
    mlSM4:
3419
      begin
3420
        if FFixedFunc.Enabled then
3421
          FFixedFunc.UnApply(ARci);
3422
        FSM4.UnApply(ARci);
3423
        GetNextPass(FSM4);
3424
      end;
3425

3426
    mlSM5:
3427
      begin
3428
        if FFixedFunc.Enabled then
3429
          FFixedFunc.UnApply(ARci);
3430
        FSM5.UnApply(ARci);
3431
        GetNextPass(FSM5);
3432
      end;
3433
  else
3434
    FNextPass := nil;
3435
  end;
3436
  ARci.GLStates.ActiveTexture := 0;
3437

3438
  Result := Assigned(FNextPass);
3439
  if Result then
3440
    FNextPass.Apply(ARCi);
3441
end;
3442

3443
{$IFDEF GLS_REGION}{$ENDREGION}{$ENDIF}
3444

3445
{$IFDEF GLS_REGION}{$REGION 'TGLMultitexturingProperties'}{$ENDIF}
3446

3447
procedure TGLMultitexturingProperties.Apply(var ARci: TGLRenderContextInfo);
3448
var
3449
  N, U: Integer;
3450
  LDir: TVector;
3451
begin
3452
  if FEnabled then
3453
  begin
3454
    if Assigned(FLibCombiner) and not FLibCombiner.FIsValid then
3455
      exit;
3456
    if Assigned(FLibAsmProg) and not FLibAsmProg.FIsValid then
3457
      exit;
3458

3459
    U := 0;
3460
    for N := 0 to High(FTexProps) do
3461
    begin
3462
      if Assigned(FTexProps[N]) and FTexProps[N].Enabled then
3463
      begin
3464
        ARci.GLStates.ActiveTexture := N;
3465
        FTexProps[N].Apply(ARci);
3466
        if Ord(FLightDir) = N+1 then
3467
        begin
3468
          LDir := ARci.GLStates.LightPosition[FLightSourceIndex];
3469
          LDir := VectorTransform(LDir, ARci.PipelineTransformation.InvModelMatrix);
3470
          NormalizeVector(LDir);
3471
          GL.TexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, @LDir);
3472
        end;
3473
        U := U or (1 shl N);
3474
      end;
3475
    end;
3476

3477
    if Assigned(FLibAsmProg) then
3478
    begin
3479
      FLibAsmProg.Handle.Bind;
3480
      GL.Enable(GL_VERTEX_PROGRAM_ARB);
3481
      if Assigned(GetMaterial.FOnAsmProgSetting) then
3482
        GetMaterial.FOnAsmProgSetting(Self.FLibAsmProg, ARci);
3483
    end;
3484

3485
    with GL, ARci.GLStates do
3486
    begin
3487
      if Assigned(FLibCombiner) and (Length(FLibCombiner.FCommandCache) > 0)
3488
        then
3489
      begin
3490
        for N := 0 to High(FLibCombiner.FCommandCache) do
3491
        begin
3492
          ActiveTexture := FLibCombiner.FCommandCache[N].ActiveUnit;
3493
          TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
3494
          TexEnvi(GL_TEXTURE_ENV,
3495
            FLibCombiner.FCommandCache[N].Arg1,
3496
            FLibCombiner.FCommandCache[N].Arg2);
3497
        end;
3498
      end;
3499
      TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, cTextureMode[FTextureMode]);
3500
      ActiveTexture := 0;
3501

3502
    end;
3503

3504
    XGL.BeginUpdate;
3505
    if U > 3 then
3506
      XGL.MapTexCoordToArbitrary(U)
3507
    else if (FTexProps[0].Enabled)
3508
      and (FTexProps[0].MappingMode = tmmUser) then
3509
      if FTexProps[1].MappingMode = tmmUser then
3510
        XGL.MapTexCoordToDual
3511
      else
3512
        XGL.MapTexCoordToMain
3513
    else if FTexProps[1].MappingMode = tmmUser then
3514
      XGL.MapTexCoordToSecond
3515
    else
3516
      XGL.MapTexCoordToMain;
3517
    XGL.EndUpdate;
3518

3519
  end;
3520
end;
3521

3522
constructor TGLMultitexturingProperties.Create(AOwner: TPersistent);
3523
begin
3524
  inherited;
3525
  FEnabled := False;
3526
  FTextureMode := tmDecal;
3527
  FLightDir := l2eNone;
3528
  FLightSourceIndex := 0;
3529
end;
3530

3531
destructor TGLMultitexturingProperties.Destroy;
3532
begin
3533
  if Assigned(FLibCombiner) then
3534
    FLibCombiner.UnregisterUser(Self);
3535
  if Assigned(FLibAsmProg) then
3536
    FLibAsmProg.UnregisterUser(Self);
3537
  FTexProps[0].Free;
3538
  FTexProps[1].Free;
3539
  FTexProps[2].Free;
3540
  FTexProps[3].Free;
3541
  inherited;
3542
end;
3543

3544
function TGLMultitexturingProperties.GetLibCombinerName: string;
3545
begin
3546
  if Assigned(FLibCombiner) then
3547
    Result := FLibCombiner.Name
3548
  else
3549
    Result := '';
3550
end;
3551

3552
function TGLMultitexturingProperties.GetLibAsmProgName: string;
3553
begin
3554
  if Assigned(FLibAsmProg) then
3555
    Result := FLibAsmProg.Name
3556
  else
3557
    Result := '';
3558
end;
3559

3560
function TGLMultitexturingProperties.IsValid: Boolean;
3561
var
3562
  I: Integer;
3563
begin
3564
  Result := True;
3565
  if Assigned(FLibCombiner) then
3566
    Result := Result and FLibCombiner.IsValid;
3567
  if Assigned(FLibAsmProg) then
3568
    Result := Result and FLibAsmProg.IsValid;
3569
  for I := 0 to High(FTexProps) do
3570
    if Assigned(FTexProps[I]) and FTexProps[I].FEnabled then
3571
      Result := Result and FTexProps[I].IsValid;
3572
end;
3573

3574
procedure TGLMultitexturingProperties.Loaded;
3575
var
3576
  I: Integer;
3577
begin
3578
  SetLibCombinerName(FLibCombinerName);
3579
  SetLibAsmProgName(FLibAsmProgName);
3580
  for I := 0 to High(FTexProps) do
3581
    if Assigned(FTexProps[I]) then
3582
      FTexProps[I].Loaded;
3583
end;
3584

3585
procedure TGLMultitexturingProperties.Notification(Sender: TObject; Operation:
3586
  TOperation);
3587
begin
3588
  if Operation = opRemove then
3589
  begin
3590
    if Sender = FLibCombiner then
3591
      FLibCombiner := nil;
3592
    if Sender = FLibAsmProg then
3593
      FLibAsmProg := nil;
3594
  end;
3595
  inherited;
3596
end;
3597

3598
procedure TGLMultitexturingProperties.SetLibCombinerName(const AValue: string);
3599
var
3600
  LCombiner: TGLTextureCombiner;
3601
begin
3602
  if csLoading in GetMaterialLibraryEx.ComponentState then
3603
  begin
3604
    FLibCombinerName := AValue;
3605
    exit;
3606
  end;
3607

3608
  if Assigned(FLibCombiner) then
3609
  begin
3610
    if FLibCombiner.Name = AValue then
3611
      exit;
3612
    FLibCombiner.UnregisterUser(Self);
3613
    FLibCombiner := nil;
3614
  end;
3615
  LCombiner := GetMaterialLibraryEx.Components.GetCombinerByName(AValue);
3616
  if Assigned(LCombiner) then
3617
  begin
3618
    LCombiner.RegisterUser(Self);
3619
    FLibCombiner := LCombiner;
3620
  end;
3621
  NotifyChange(Self);
3622
end;
3623

3624
procedure TGLMultitexturingProperties.SetLightSourceIndex(AValue: Integer);
3625
begin
3626
  if AValue < 0 then
3627
    AValue := 0
3628
  else if AValue > 7 then
3629
    AValue := 7;
3630
  FLightSourceIndex := AValue;
3631
end;
3632

3633
procedure TGLMultitexturingProperties.SetLibAsmProgName(const AValue: string);
3634
var
3635
  LProg: TGLASMVertexProgram;
3636
begin
3637
  if csLoading in GetMaterialLibraryEx.ComponentState then
3638
  begin
3639
    FLibAsmProgName := AValue;
3640
    exit;
3641
  end;
3642

3643
  if Assigned(FLibAsmProg) then
3644
  begin
3645
    if FLibAsmProg.Name = AValue then
3646
      exit;
3647
    FLibAsmProg.UnregisterUser(Self);
3648
    FLibAsmProg := nil;
3649
  end;
3650
  LProg := GetMaterialLibraryEx.Components.GetAsmProgByName(AValue);
3651
  if Assigned(LProg) then
3652
  begin
3653
    LProg.RegisterUser(Self);
3654
    FLibAsmProg := LProg;
3655
  end;
3656
  NotifyChange(Self);
3657
end;
3658

3659
function TGLMultitexturingProperties.GetTexProps(AIndex: Integer):
3660
  TGLTextureProperties;
3661
begin
3662
  if not Assigned(FTexProps[AIndex]) then
3663
    FTexProps[AIndex] := TGLTextureProperties.Create(Self);
3664
  Result := FTexProps[AIndex];
3665
end;
3666

3667
procedure TGLMultitexturingProperties.SetTexProps(AIndex: Integer;
3668
  AValue: TGLTextureProperties);
3669
begin
3670
  FTexProps[AIndex].Assign(AValue);
3671
end;
3672

3673
procedure TGLMultitexturingProperties.SetTextureMode(AValue: TGLTextureMode);
3674
begin
3675
  if AValue <> FTextureMode then
3676
  begin
3677
    FTextureMode := AValue;
3678
    NotifyChange(Self);
3679
  end;
3680
end;
3681

3682
procedure TGLMultitexturingProperties.UnApply(var ARci: TGLRenderContextInfo);
3683
var
3684
  N: Integer;
3685
begin
3686
  for N := 0 to High(FTexProps) do
3687
  begin
3688
    if FTexProps[N].Enabled then
3689
    begin
3690
      ARci.GLStates.ActiveTexture := N;
3691
      FTexProps[N].UnApply(ARci);
3692
    end;
3693
  end;
3694
  ARci.GLStates.ActiveTexture := 0;
3695

3696
  if Assigned(FLibAsmProg) then
3697
    GL.Disable(GL_VERTEX_PROGRAM_ARB);
3698
end;
3699

3700
{$IFDEF GLS_REGION}{$ENDREGION}{$ENDIF}
3701

3702
{$IFDEF GLS_REGION}{$REGION 'TGLTextureProperties'}{$ENDIF}
3703

3704
procedure TGLTextureProperties.Apply(var ARci: TGLRenderContextInfo);
3705
var
3706
  glTarget: TGLEnum;
3707
begin
3708
  if Assigned(FLibTexture) then
3709
    with GL do
3710
    begin
3711
      FLibTexture.FApplicableSampler := FLibSampler;
3712
      FLibTexture.Apply(ARci);
3713

3714
      // Apply swizzling if possible
3715
      glTarget := DecodeGLTextureTarget(FLibTexture.Shape);
3716
      if ARB_texture_swizzle or EXT_texture_swizzle then
3717
      begin
3718
        if FSwizzling.FSwizzles[0] <> FLibTexture.FSwizzles[0] then
3719
        begin
3720
          FLibTexture.FSwizzles[0] := FSwizzling.FSwizzles[0];
3721
          TexParameteri(glTarget, GL_TEXTURE_SWIZZLE_R,
3722
            cTextureSwizzle[FSwizzling.FSwizzles[0]]);
3723
        end;
3724
        if FSwizzling.FSwizzles[1] <> FLibTexture.FSwizzles[1] then
3725
        begin
3726
          FLibTexture.FSwizzles[1] := FSwizzling.FSwizzles[1];
3727
          TexParameteri(glTarget, GL_TEXTURE_SWIZZLE_G,
3728
            cTextureSwizzle[FSwizzling.FSwizzles[1]]);
3729
        end;
3730
        if FSwizzling.FSwizzles[2] <> FLibTexture.FSwizzles[2] then
3731
        begin
3732
          FLibTexture.FSwizzles[2] := FSwizzling.FSwizzles[2];
3733
          TexParameteri(glTarget, GL_TEXTURE_SWIZZLE_B,
3734
            cTextureSwizzle[FSwizzling.FSwizzles[2]]);
3735
        end;
3736
        if FSwizzling.FSwizzles[3] <> FLibTexture.FSwizzles[3] then
3737
        begin
3738
          FLibTexture.FSwizzles[3] := FSwizzling.FSwizzles[3];
3739
          TexParameteri(glTarget, GL_TEXTURE_SWIZZLE_A,
3740
            cTextureSwizzle[FSwizzling.FSwizzles[3]]);
3741
        end;
3742
      end;
3743

3744
      if Assigned(FLibSampler) then
3745
      begin
3746
        if FLibSampler.IsValid then
3747
          FLibSampler.Apply(ARci)
3748
        else if FLibTexture.FLastSampler <> FLibSampler then
3749
        begin
3750
          // Sampler object not supported, lets use texture states
3751
          TexParameterfv(glTarget, GL_TEXTURE_BORDER_COLOR,
3752
            FLibSampler.BorderColor.AsAddress);
3753
          TexParameteri(glTarget, GL_TEXTURE_WRAP_S,
3754
            cTextureWrapMode[FLibSampler.WrapX]);
3755
          TexParameteri(glTarget, GL_TEXTURE_WRAP_T,
3756
            cTextureWrapMode[FLibSampler.WrapY]);
3757
          TexParameteri(glTarget, GL_TEXTURE_WRAP_R,
3758
            cTextureWrapMode[FLibSampler.WrapZ]);
3759
          TexParameterf(glTarget, GL_TEXTURE_LOD_BIAS, FLibSampler.LODBias +
3760
            FLibSampler.FLODBiasFract);
3761
          TexParameteri(glTarget, GL_TEXTURE_MIN_FILTER,
3762
            cTextureMinFilter[FLibSampler.MinFilter]);
3763
          TexParameteri(glTarget, GL_TEXTURE_MAG_FILTER,
3764
            cTextureMagFilter[FLibSampler.MagFilter]);
3765

3766
          if EXT_texture_filter_anisotropic then
3767
          begin
3768
            if FLibSampler.FilteringQuality = tfAnisotropic then
3769
              TexParameteri(glTarget, GL_TEXTURE_MAX_ANISOTROPY_EXT,
3770
                CurrentGLContext.GLStates.MaxTextureAnisotropy)
3771
            else
3772
              TexParameteri(glTarget, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1);
3773
          end;
3774

3775
          TexParameteri(glTarget, GL_TEXTURE_COMPARE_MODE,
3776
            cTextureCompareMode[FLibSampler.CompareMode]);
3777
          TexParameteri(glTarget, GL_TEXTURE_COMPARE_FUNC,
3778
            cGLComparisonFunctionToGLEnum[FLibSampler.CompareFunc]);
3779

3780
          if EXT_texture_sRGB_decode then
3781
          begin
3782
            if FLibSampler.sRGB_Encode then
3783
              TexParameteri(glTarget, GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT)
3784
            else
3785
              TexParameteri(glTarget, GL_TEXTURE_SRGB_DECODE_EXT,
3786
                GL_SKIP_DECODE_EXT);
3787
          end;
3788

3789
          FLibTexture.FLastSampler := FLibSampler;
3790
        end;
3791
      end;
3792

3793
      if not FTextureMatrixIsIdentity and (MappingMode = tmmUser) then
3794
        ARci.GLStates.SetGLTextureMatrix(FTextureMatrix);
3795

3796
      if ARci.currentMaterialLevel < mlSM3 then
3797
      begin
3798
        GL.TexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, FEnvColor.AsAddress);
3799
        ApplyMappingMode;
3800
        if ARci.currentMaterialLevel = mlFixedFunction then
3801
          XGL.MapTexCoordToMain;
3802
      end;
3803
    end;
3804
end;
3805

3806
procedure TGLTextureProperties.ApplyMappingMode;
3807
var
3808
  R_Dim: Boolean;
3809
begin
3810
  with GL do
3811
  begin
3812
    R_Dim := ARB_texture_cube_map or EXT_texture3D;
3813

3814
    case MappingMode of
3815

3816
      tmmUser: ; // nothing to do, but checked first (common case)
3817

3818
      tmmObjectLinear:
3819
        begin
3820
          TexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
3821
          TexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
3822
          TexGenfv(GL_S, GL_OBJECT_PLANE, @MappingSCoordinates.DirectVector);
3823
          TexGenfv(GL_T, GL_OBJECT_PLANE, @MappingTCoordinates.DirectVector);
3824
          Enable(GL_TEXTURE_GEN_S);
3825
          Enable(GL_TEXTURE_GEN_T);
3826

3827
          if R_Dim then
3828
          begin
3829
            TexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
3830
            TexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
3831
            TexGenfv(GL_R, GL_OBJECT_PLANE, @MappingRCoordinates.DirectVector);
3832
            TexGenfv(GL_Q, GL_OBJECT_PLANE, @MappingQCoordinates.DirectVector);
3833
            Enable(GL_TEXTURE_GEN_R);
3834
            Enable(GL_TEXTURE_GEN_Q);
3835
          end;
3836
        end;
3837

3838
      tmmEyeLinear:
3839
        begin
3840
          TexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3841
          TexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3842
          // specify planes in eye space, not world space
3843
          MatrixMode(GL_MODELVIEW);
3844
          PushMatrix;
3845
          LoadIdentity;
3846
          TexGenfv(GL_S, GL_EYE_PLANE, @MappingSCoordinates.DirectVector);
3847
          TexGenfv(GL_T, GL_EYE_PLANE, @MappingTCoordinates.DirectVector);
3848
          Enable(GL_TEXTURE_GEN_S);
3849
          Enable(GL_TEXTURE_GEN_T);
3850
          if R_Dim then
3851
          begin
3852
            TexGenfv(GL_R, GL_EYE_PLANE, @MappingRCoordinates.DirectVector);
3853
            TexGenfv(GL_Q, GL_EYE_PLANE, @MappingQCoordinates.DirectVector);
3854
            Enable(GL_TEXTURE_GEN_R);
3855
            Enable(GL_TEXTURE_GEN_Q);
3856
          end;
3857
          PopMatrix;
3858
        end;
3859

3860
      tmmSphere:
3861
        begin
3862
          TexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
3863
          TexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
3864
          Enable(GL_TEXTURE_GEN_S);
3865
          Enable(GL_TEXTURE_GEN_T);
3866
        end;
3867

3868
      tmmCubeMapReflection, tmmCubeMapCamera:
3869
        if R_Dim then
3870
        begin
3871
          TexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
3872
          TexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
3873
          TexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
3874
          Enable(GL_TEXTURE_GEN_S);
3875
          Enable(GL_TEXTURE_GEN_T);
3876
          Enable(GL_TEXTURE_GEN_R);
3877
        end;
3878

3879
      tmmCubeMapNormal, tmmCubeMapLight0:
3880
        if R_Dim then
3881
        begin
3882
          TexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP);
3883
          TexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP);
3884
          TexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP);
3885
          Enable(GL_TEXTURE_GEN_S);
3886
          Enable(GL_TEXTURE_GEN_T);
3887
          Enable(GL_TEXTURE_GEN_R);
3888
        end;
3889
    end;
3890
  end;
3891
end;
3892

3893
procedure TGLTextureProperties.Assign(Source: TPersistent);
3894
var
3895
  LTexProp: TGLTextureProperties;
3896
begin
3897
  if Source is TGLTextureProperties then
3898
  begin
3899
    LTexProp := TGLTextureProperties(Source);
3900
    LibTextureName := LTexProp.LibTextureName;
3901
    LibSamplerName := LTexProp.LibSamplerName;
3902
    TextureOffset.Assign(LTexProp.TextureOffset);
3903
    TextureScale.Assign(LTexProp.TextureScale);
3904
    FTextureRotate := LTexProp.TextureRotate;
3905
    FEnvColor.Assign(LTexProp.EnvColor);
3906
    FMappingMode := LTexProp.MappingMode;
3907
    MappingSCoordinates.Assign(LTexProp.MappingSCoordinates);
3908
    MappingTCoordinates.Assign(LTexProp.MappingTCoordinates);
3909
    MappingRCoordinates.Assign(LTexProp.MappingRCoordinates);
3910
    MappingQCoordinates.Assign(LTexProp.MappingQCoordinates);
3911
  end;
3912
  inherited;
3913
end;
3914

3915
procedure TGLTextureProperties.CalculateTextureMatrix;
3916
begin
3917
  if not (Assigned(FTextureOffset) or Assigned(FTextureScale)
3918
    or StoreTextureRotate) then
3919
  begin
3920
    FTextureMatrixIsIdentity := True;
3921
    exit;
3922
  end;
3923

3924
  if TextureOffset.Equals(NullHmgVector)
3925
    and TextureScale.Equals(XYZHmgVector)
3926
    and not StoreTextureRotate then
3927
    FTextureMatrixIsIdentity := True
3928
  else
3929
  begin
3930
    FTextureMatrixIsIdentity := False;
3931
    FTextureMatrix := CreateScaleAndTranslationMatrix(
3932
      TextureScale.AsVector,
3933
      TextureOffset.AsVector);
3934
    if StoreTextureRotate then
3935
      FTextureMatrix := MatrixMultiply(FTextureMatrix,
3936
        CreateRotationMatrixZ(DegToRad(FTextureRotate)));
3937
  end;
3938
  FTextureOverride := False;
3939
  NotifyChange(Self);
3940
end;
3941

3942
constructor TGLTextureProperties.Create(AOwner: TPersistent);
3943
begin
3944
  inherited;
3945
  FTextureRotate := 0;
3946
  FMappingMode := tmmUser;
3947
  FTextureMatrix := IdentityHmgMatrix;
3948
  FEnabled := False;
3949
  FSwizzling := TGLTextureSwizzling.Create(Self);
3950
  FEnvColor := TGLColor.CreateInitialized(Self, clrTransparent);
3951
end;
3952

3953
destructor TGLTextureProperties.Destroy;
3954
begin
3955
  if Assigned(FLibSampler) then
3956
    FLibSampler.UnregisterUser(Self);
3957
  if Assigned(FLibTexture) then
3958
    FLibTexture.UnregisterUser(Self);
3959
  FTextureOffset.Free;
3960
  FTextureScale.Free;
3961
  FMapSCoordinates.Free;
3962
  FMapTCoordinates.Free;
3963
  FMapRCoordinates.Free;
3964
  FMapQCoordinates.Free;
3965
  FSwizzling.Destroy;
3966
  FEnvColor.Destroy;
3967
  inherited;
3968
end;
3969

3970
function TGLTextureProperties.GetLibSamplerName: TGLMaterialComponentName;
3971
begin
3972
  if Assigned(FLibSampler) then
3973
    Result := FLibSampler.Name
3974
  else
3975
    Result := '';
3976
end;
3977

3978
function TGLTextureProperties.GetLibTextureName: TGLMaterialComponentName;
3979
begin
3980
  if Assigned(FLibTexture) then
3981
    Result := FLibTexture.Name
3982
  else
3983
    Result := '';
3984
end;
3985

3986
function TGLTextureProperties.GetMappingQCoordinates: TGLCoordinates4;
3987
begin
3988
  if not Assigned(FMapQCoordinates) then
3989
    FMapQCoordinates := TGLCoordinates4.CreateInitialized(Self, WHmgVector,
3990
      csVector);
3991
  Result := FMapQCoordinates;
3992
end;
3993

3994
function TGLTextureProperties.GetMappingRCoordinates: TGLCoordinates4;
3995
begin
3996
  if not Assigned(FMapRCoordinates) then
3997
    FMapRCoordinates := TGLCoordinates4.CreateInitialized(Self, ZHmgVector,
3998
      csVector);
3999
  Result := FMapRCoordinates;
4000
end;
4001

4002
function TGLTextureProperties.GetMappingSCoordinates: TGLCoordinates4;
4003
begin
4004
  if not Assigned(FMapSCoordinates) then
4005
    FMapSCoordinates := TGLCoordinates4.CreateInitialized(Self, XHmgVector,
4006
      csVector);
4007
  Result := FMapSCoordinates;
4008
end;
4009

4010
function TGLTextureProperties.GetMappingTCoordinates: TGLCoordinates4;
4011
begin
4012
  if not Assigned(FMapTCoordinates) then
4013
    FMapTCoordinates := TGLCoordinates4.CreateInitialized(Self, YHmgVector,
4014
      csVector);
4015
  Result := FMapTCoordinates;
4016
end;
4017

4018
function TGLTextureProperties.GetTextureOffset: TGLCoordinates;
4019
begin
4020
  if not Assigned(FTextureOffset) then
4021
    FTextureOffset :=
4022
      TGLCoordinates3.CreateInitialized(Self, NullHmgVector, csPoint);
4023
  Result := FTextureOffset;
4024
end;
4025

4026
function TGLTextureProperties.GetTextureScale: TGLCoordinates;
4027
begin
4028
  if not Assigned(FTextureScale) then
4029
    FTextureScale :=
4030
      TGLCoordinates3.CreateInitialized(Self, VectorMake(1, 1, 1, 1), csVector);
4031
  Result := FTextureScale;
4032
end;
4033

4034
function TGLTextureProperties.IsValid: Boolean;
4035
begin
4036
  if Assigned(FLibTexture) then
4037
    Result := FLibTexture.IsValid
4038
  else
4039
    Result := False;
4040
end;
4041

4042
procedure TGLTextureProperties.Loaded;
4043
begin
4044
  SetLibTextureName(FLibTextureName);
4045
  SetLibSamplerName(FLibSamplerName);
4046
  CalculateTextureMatrix;
4047
end;
4048

4049
procedure TGLTextureProperties.Notification(Sender: TObject;
4050
  Operation: TOperation);
4051
begin
4052
  if Operation = opRemove then
4053
  begin
4054
    if Sender = FLibTexture then
4055
      FLibTexture := nil
4056
    else if Sender = FLibSampler then
4057
      FLibSampler := nil;
4058
  end;
4059
end;
4060

4061
procedure TGLTextureProperties.NotifyChange(Sender: TObject);
4062
begin
4063
  inherited;
4064
  if (Sender = FTextureOffset) or (Sender = FTextureScale) then
4065
    CalculateTextureMatrix;
4066
  if (Sender = FLibSampler) and Assigned(FLibTexture) then
4067
    FLibTexture.FLastSampler := nil;
4068
end;
4069

4070
procedure TGLTextureProperties.SetLibSamplerName(const AValue:
4071
  TGLMaterialComponentName);
4072
var
4073
  LSampler: TGLTextureSampler;
4074
begin
4075
  if csLoading in GetMaterialLibraryEx.ComponentState then
4076
  begin
4077
    FLibSamplerName := AValue;
4078
    exit;
4079
  end;
4080

4081
  if Assigned(FLibSampler) then
4082
  begin
4083
    if FLibSampler.Name = AValue then
4084
      exit;
4085
    FLibSampler.UnregisterUser(Self);
4086
    FLibSampler := nil;
4087
  end;
4088
  LSampler := GetMaterialLibraryEx.Components.GetSamplerByName(AValue);
4089
  if Assigned(LSampler) then
4090
  begin
4091
    LSampler.RegisterUser(Self);
4092
    FLibSampler := LSampler;
4093
  end;
4094
  NotifyChange(Self);
4095
end;
4096

4097
procedure TGLTextureProperties.SetLibTextureName(const AValue:
4098
  TGLMaterialComponentName);
4099
var
4100
  LTexture: TGLAbstractTexture;
4101
begin
4102
  if csLoading in GetMaterialLibraryEx.ComponentState then
4103
  begin
4104
    FLibTextureName := AValue;
4105
    exit;
4106
  end;
4107

4108
  if Assigned(FLibTexture) then
4109
  begin
4110
    if FLibTexture.Name = AValue then
4111
      exit;
4112
    FLibTexture.UnregisterUser(Self);
4113
    FLibTexture := nil;
4114
  end;
4115

4116
  LTexture := GetMaterialLibraryEx.Components.GetTextureByName(AValue);
4117

4118
  if Assigned(LTexture) then
4119
  begin
4120
    if LTexture is TGLFrameBufferAttachment then
4121
    begin
4122
      if TGLFrameBufferAttachment(LTexture).OnlyWrite then
4123
      begin
4124
        if IsDesignTime then
4125
          InformationDlg('Can not use write only attachment as texture')
4126
        else
4127
          GLSLogger.LogErrorFmt('Attempt to use write only attachment "%s" as texture',
4128
            [LTexture.Name]);
4129
        NotifyChange(Self);
4130
        exit;
4131
      end;
4132
    end;
4133
    LTexture.RegisterUser(Self);
4134
    FLibTexture := LTexture;
4135
  end;
4136
  NotifyChange(Self);
4137
end;
4138

4139
procedure TGLTextureProperties.SetMappingMode(
4140
  const AValue: TGLTextureMappingMode);
4141
begin
4142
  if AValue <> FMappingMode then
4143
  begin
4144
    FMappingMode := AValue;
4145
    NotifyChange(Self);
4146
  end;
4147
end;
4148

4149
procedure TGLTextureProperties.SetMappingQCoordinates(
4150
  const AValue: TGLCoordinates4);
4151
begin
4152
  MappingQCoordinates.Assign(AValue);
4153
end;
4154

4155
procedure TGLTextureProperties.SetMappingRCoordinates(
4156
  const AValue: TGLCoordinates4);
4157
begin
4158
  MappingRCoordinates.Assign(AValue);
4159
end;
4160

4161
procedure TGLTextureProperties.SetMappingSCoordinates(
4162
  const AValue: TGLCoordinates4);
4163
begin
4164
  MappingSCoordinates.Assign(AValue);
4165
end;
4166

4167
procedure TGLTextureProperties.SetMappingTCoordinates(
4168
  const AValue: TGLCoordinates4);
4169
begin
4170
  MappingTCoordinates.Assign(AValue);
4171
end;
4172

4173
procedure TGLTextureProperties.SetSwizzling(const AValue: TGLTextureSwizzling);
4174
begin
4175
  FSwizzling.Assign(AValue);
4176
end;
4177

4178
procedure TGLTextureProperties.SetTextureMatrix(const AValue: TMatrix);
4179
begin
4180
  FTextureMatrixIsIdentity := CompareMem(@AValue.V[0], @IdentityHmgMatrix.V[0],
4181
    SizeOf(TMatrix));
4182
  FTextureMatrix := AValue;
4183
  FTextureOverride := True;
4184
  NotifyChange(Self);
4185
end;
4186

4187
procedure TGLTextureProperties.SetTextureOffset(const AValue: TGLCoordinates);
4188
begin
4189
  TextureOffset.Assign(AValue);
4190
  CalculateTextureMatrix;
4191
end;
4192

4193
procedure TGLTextureProperties.SetTextureRotate(AValue: Single);
4194
begin
4195
  if AValue <> FTextureRotate then
4196
  begin
4197
    FTextureRotate := AValue;
4198
    CalculateTextureMatrix;
4199
    NotifyChange(Self);
4200
  end;
4201
end;
4202

4203
procedure TGLTextureProperties.SetTextureScale(const AValue: TGLCoordinates);
4204
begin
4205
  TextureScale.Assign(AValue);
4206
  CalculateTextureMatrix;
4207
end;
4208

4209
function TGLTextureProperties.StoreMappingQCoordinates: Boolean;
4210
begin
4211
  if Assigned(FMapQCoordinates) then
4212
    Result := not VectorEquals(FMapQCoordinates.AsVector, WHmgVector)
4213
  else
4214
    Result := false;
4215
end;
4216

4217
function TGLTextureProperties.StoreMappingRCoordinates: Boolean;
4218
begin
4219
  if Assigned(FMapRCoordinates) then
4220
    Result := not VectorEquals(FMapRCoordinates.AsVector, ZHmgVector)
4221
  else
4222
    Result := false;
4223
end;
4224

4225
function TGLTextureProperties.StoreMappingSCoordinates: Boolean;
4226
begin
4227
  if Assigned(FMapSCoordinates) then
4228
    Result := not VectorEquals(FMapSCoordinates.AsVector, XHmgVector)
4229
  else
4230
    Result := false;
4231
end;
4232

4233
function TGLTextureProperties.StoreMappingTCoordinates: Boolean;
4234
begin
4235
  if Assigned(FMapTCoordinates) then
4236
    Result := not VectorEquals(FMapTCoordinates.AsVector, YHmgVector)
4237
  else
4238
    Result := false;
4239
end;
4240

4241
function TGLTextureProperties.StoreSwizzling: Boolean;
4242
begin
4243
  Result := FSwizzling.StoreSwizzle(0);
4244
end;
4245

4246
function TGLTextureProperties.StoreTextureOffset: Boolean;
4247
begin
4248
  Result := Assigned(FTextureOffset);
4249
end;
4250

4251
function TGLTextureProperties.StoreTextureRotate: Boolean;
4252
begin
4253
  Result := Abs(FTextureRotate) > EPSILON;
4254
end;
4255

4256
function TGLTextureProperties.StoreTextureScale: Boolean;
4257
begin
4258
  Result := Assigned(FTextureScale);
4259
end;
4260

4261
procedure TGLTextureProperties.SetEnvColor(const AValue:
4262
  TGLColor);
4263
begin
4264
  FEnvColor.Assign(AValue);
4265
  NotifyChange(Self);
4266
end;
4267

4268
procedure TGLTextureProperties.UnApply(var ARci: TGLRenderContextInfo);
4269
begin
4270
  if Assigned(FLibTexture) then
4271
  begin
4272
    FLibTexture.UnApply(ARci);
4273
    if Assigned(FLibSampler) then
4274
      FLibSampler.UnApply(ARci);
4275

4276
    if ARci.currentMaterialLevel < mlSM3 then
4277
    begin
4278
      if not FTextureMatrixIsIdentity and (MappingMode = tmmUser) then
4279
        ARci.GLStates.SetGLTextureMatrix(IdentityHmgMatrix);
4280
      UnApplyMappingMode;
4281
    end;
4282
  end;
4283
end;
4284

4285
procedure TGLTextureProperties.UnApplyMappingMode;
4286
begin
4287
  if MappingMode <> tmmUser then
4288
    with GL do
4289
    begin
4290
      Disable(GL_TEXTURE_GEN_S);
4291
      Disable(GL_TEXTURE_GEN_T);
4292
      if EXT_texture3D or ARB_texture_cube_map then
4293
      begin
4294
        Disable(GL_TEXTURE_GEN_R);
4295
        Disable(GL_TEXTURE_GEN_Q);
4296
      end;
4297
    end;
4298
end;
4299

4300
{$IFDEF GLS_REGION}{$ENDREGION}{$ENDIF}
4301

4302
{$IFDEF GLS_REGION}{$REGION 'TGLShaderEx'}{$ENDIF}
4303

4304
procedure TGLShaderEx.Assign(Source: TPersistent);
4305
var
4306
  LShader: TGLShaderEx;
4307
begin
4308
  if Source is TGLShaderEx then
4309
  begin
4310
    LShader := TGLShaderEx(Source);
4311
    FSource.Assign(LShader.Source);
4312
    FShaderType := LShader.FShaderType;
4313
    NotifyChange(Self);
4314
  end;
4315
  inherited;
4316
end;
4317

4318
constructor TGLShaderEx.Create(AOwner: TGLXCollection);
4319
const
4320
  cShaderClasses: array[TGLShaderType] of TGLShaderHandleClass =
4321
    (
4322
    TGLVertexShaderHandle,
4323
    TGLTessControlShaderHandle,
4324
    TGLTessEvaluationShaderHandle,
4325
    TGLGeometryShaderHandle,
4326
    TGLFragmentShaderHandle
4327
    );
4328
var
4329
  S: TGLShaderType;
4330
begin
4331
  inherited;
4332
  FDefferedInit := False;
4333
  for S := Low(TGLShaderType) to High(TGLShaderType) do
4334
  begin
4335
    FHandle[S] := cShaderClasses[S].Create;
4336
    FHandle[S].OnPrapare := DoOnPrepare;
4337
  end;
4338
  FSource := TStringList.Create;
4339
  FSource.OnChange := NotifyChange;
4340
  FShaderType := shtVertex;
4341
  FGeometryInput := gsInPoints;
4342
  FGeometryOutput := gsOutPoints;
4343
  FGeometryVerticesOut := 1;
4344
  Name := TGLMatLibComponents(AOwner).MakeUniqueName('Shader');
4345
end;
4346

4347
destructor TGLShaderEx.Destroy;
4348
var
4349
  S: TGLShaderType;
4350
begin
4351
  for S := Low(TGLShaderType) to High(TGLShaderType) do
4352
    FHandle[S].Destroy;
4353
  FSource.Destroy;
4354
  inherited;
4355
end;
4356

4357
procedure TGLShaderEx.NotifyChange(Sender: TObject);
4358
var
4359
  S: TGLShaderType;
4360
begin
4361
  for S := Low(TGLShaderType) to High(TGLShaderType) do
4362
    FHandle[S].NotifyChangesOfData;
4363

4364
  if (Sender = FSource) and IsDesignTime and (Length(FSourceFile) > 0) then
4365
    FSource.SaveToFile(FSourceFile);
4366

4367
  inherited;
4368
end;
4369

4370
procedure TGLShaderEx.DoOnPrepare(Sender: TGLContext);
4371
begin
4372
  if not IsDesignTime and FDefferedInit then
4373
    exit;
4374
  try
4375
    if FHandle[FShaderType].IsSupported then
4376
    begin
4377
      FHandle[FShaderType].AllocateHandle;
4378
      if FHandle[FShaderType].IsDataNeedUpdate then
4379
      begin
4380
        SetExeDirectory;
4381
        if (Length(FSourceFile) > 0) and FileStreamExists(FSourceFile) then
4382
          FSource.LoadFromFile(FSourceFile);
4383
        FHandle[FShaderType].ShaderSource(AnsiString(FSource.Text));
4384
        FIsValid := FHandle[FShaderType].CompileShader;
4385
        if IsDesignTime then
4386
        begin
4387
          FInfoLog := FHandle[FShaderType].InfoLog;
4388
          if (Length(FInfoLog) = 0) and FIsValid then
4389
            FInfoLog := 'Compilation successful';
4390
        end
4391
        else if FIsValid then
4392
          GLSLogger.LogInfoFmt('Shader "%s" compilation successful - %s',
4393
            [Name, FHandle[FShaderType].InfoLog])
4394
        else
4395
          GLSLogger.LogErrorFmt('Shader "%s" compilation failed - %s',
4396
            [Name, FHandle[FShaderType].InfoLog]);
4397
        FHandle[FShaderType].NotifyDataUpdated;
4398
      end;
4399
    end
4400
    else
4401
    begin
4402
      FIsValid := False;
4403
      if IsDesignTime then
4404
        FInfoLog := 'Not supported by hardware';
4405
    end;
4406
  except
4407
    on E: Exception do
4408
    begin
4409
      FIsValid := False;
4410
      if IsDesignTime then
4411
        InformationDlg(E.ClassName + ': ' + E.Message)
4412
      else
4413
        GLSLogger.LogError(E.ClassName + ': ' + E.Message);
4414
    end;
4415
  end;
4416
end;
4417

4418
class function TGLShaderEx.FriendlyName: string;
4419
begin
4420
  Result := 'GLSL Shader';
4421
end;
4422

4423
function TGLShaderEx.GetHandle: TGLShaderHandle;
4424
begin
4425
  Result := FHandle[FShaderType];
4426
end;
4427

4428
procedure TGLShaderEx.ReadFromFiler(AReader: TReader);
4429
var
4430
  archiveVersion: Integer;
4431
begin
4432
  with AReader do
4433
  begin
4434
    archiveVersion := ReadInteger;
4435
    if archiveVersion = 0 then
4436
    begin
4437
      Name := ReadWideString;
4438
      FDefferedInit := ReadBoolean;
4439
      FSource.Text := ReadWideString;
4440
      FSourceFile := ReadWideString;
4441
      FShaderType := TGLShaderType(ReadInteger);
4442
      FGeometryInput := TGLgsInTypes(ReadInteger);
4443
      FGeometryOutput := TGLgsOutTypes(ReadInteger);
4444
      FGeometryVerticesOut := ReadInteger;
4445
    end
4446
    else
4447
      RaiseFilerException(archiveVersion);
4448
  end;
4449
end;
4450

4451
procedure TGLShaderEx.SetGeometryInput(AValue: TGLgsInTypes);
4452
begin
4453
  if AValue <> FGeometryInput then
4454
  begin
4455
    FGeometryInput := AValue;
4456
    NotifyChange(Self);
4457
  end;
4458
end;
4459

4460
procedure TGLShaderEx.SetGeometryOutput(AValue: TGLgsOutTypes);
4461
begin
4462
  if AValue <> FGeometryOutput then
4463
  begin
4464
    FGeometryOutput := AValue;
4465
    NotifyChange(Self);
4466
  end;
4467
end;
4468

4469
procedure TGLShaderEx.SetGeometryVerticesOut(AValue: TGLint);
4470
begin
4471
  if AValue < 1 then
4472
    AValue := 1
4473
  else if AValue > 1024 then
4474
    AValue := 1024;
4475

4476
  if AValue <> FGeometryVerticesOut then
4477
  begin
4478
    FGeometryVerticesOut := AValue;
4479
    NotifyChange(Self);
4480
  end;
4481
end;
4482

4483
procedure TGLShaderEx.SetShaderType(AValue: TGLShaderType);
4484
begin
4485
  if FShaderType <> AValue then
4486
  begin
4487
    FShaderType := AValue;
4488
    NotifyChange(Self);
4489
  end;
4490
end;
4491

4492
procedure TGLShaderEx.SetSource(AValue: TStringList);
4493
begin
4494
  FSource.Assign(AValue);
4495
end;
4496

4497
procedure TGLShaderEx.SetSourceFile(AValue: string);
4498
begin
4499
  FixPathDelimiter(AValue);
4500
  if FSourceFile <> AValue then
4501
  begin
4502
    FSourceFile := AValue;
4503
    NotifyChange(Self);
4504
  end;
4505
end;
4506

4507
procedure TGLShaderEx.WriteToFiler(AWriter: TWriter);
4508
begin
4509
  with AWriter do
4510
  begin
4511
    WriteInteger(0); // archive version
4512
    WriteWideString(Name);
4513
    WriteBoolean(FDefferedInit);
4514
    if Length(FSourceFile) = 0 then
4515
      WriteWideString(FSource.Text)
4516
    else
4517
      WriteWideString('');
4518
    WriteWideString(FSourceFile);
4519
    WriteInteger(Integer(FShaderType));
4520
    WriteInteger(Integer(FGeometryInput));
4521
    WriteInteger(Integer(FGeometryOutput));
4522
    WriteInteger(FGeometryVerticesOut);
4523
  end;
4524
end;
4525

4526
{$IFDEF GLS_REGION}{$ENDREGION}{$ENDIF}
4527

4528
{$IFDEF GLS_REGION}{$REGION 'TGLLibMaterialProperty'}{$ENDIF}
4529

4530
function TGLLibMaterialProperty.GetMaterial: TGLLibMaterialEx;
4531
begin
4532
  if Owner is TGLLibMaterialEx then
4533
    Result := TGLLibMaterialEx(Owner)
4534
  else if Owner is TGLLibMaterialProperty then
4535
    Result := TGLLibMaterialProperty(Owner).GetMaterial
4536
  else
4537
    Result := nil;
4538
end;
4539

4540
function TGLLibMaterialProperty.GetMaterialLibrary: TGLAbstractMaterialLibrary;
4541
begin
4542
  if Owner is TGLBaseMaterialCollectionItem then
4543
    Result := TGLBaseMaterialCollectionItem(Owner).GetMaterialLibrary
4544
  else
4545
    Result := GetMaterial.GetMaterialLibrary;
4546
end;
4547

4548
function TGLLibMaterialProperty.GetMaterialLibraryEx: TGLMaterialLibraryEx;
4549
begin
4550
  if Owner is TGLBaseMaterialCollectionItem then
4551
    Result := TGLBaseMaterialCollectionItem(Owner).GetMaterialLibraryEx
4552
  else
4553
    Result := TGLMaterialLibraryEx(GetMaterial.GetMaterialLibrary);
4554
end;
4555

4556
procedure TGLLibMaterialProperty.SetNextPass(const AValue: TGLLibMaterialName);
4557
begin
4558
  if AValue <> FNextPassName then
4559
  begin
4560
    FNextPassName := AValue;
4561
    NotifyChange(Self);
4562
  end;
4563
end;
4564

4565
procedure TGLLibMaterialProperty.Loaded;
4566
begin
4567
end;
4568

4569
procedure TGLLibMaterialProperty.NotifyChange(Sender: TObject);
4570
var
4571
  NA: IGLNotifyAble;
4572
begin
4573
  if Assigned(Owner) then
4574
  begin
4575
    if Supports(Owner, IGLNotifyAble, NA) then
4576
      NA.NotifyChange(Self)
4577
  end;
4578
  if Assigned(OnNotifyChange) then
4579
    OnNotifyChange(Self);
4580
end;
4581

4582
procedure TGLLibMaterialProperty.SetEnabled(AValue: Boolean);
4583
begin
4584
  if FEnabled <> AValue then
4585
  begin
4586
    FEnabled := AValue;
4587
    if Owner is TGLLibMaterialEx then
4588
      GetMaterial.NotifyChange(Self);
4589
  end;
4590
end;
4591

4592
{$IFDEF GLS_REGION}{$ENDREGION}{$ENDIF}
4593

4594
{$IFDEF GLS_REGION}{$REGION 'TGLLibMaterialsEx'}{$ENDIF}
4595

4596
function TGLLibMaterialsEx.Add: TGLLibMaterialEx;
4597
begin
4598
  Result := (inherited Add) as TGLLibMaterialEx;
4599
end;
4600

4601
constructor TGLLibMaterialsEx.Create(AOwner: TComponent);
4602
begin
4603
  inherited Create(AOwner, TGLLibMaterialEx);
4604
end;
4605

4606
function TGLLibMaterialsEx.FindItemID(ID: Integer): TGLLibMaterialEx;
4607
begin
4608
  Result := (inherited FindItemID(ID)) as TGLLibMaterialEx;
4609
end;
4610

4611
function TGLLibMaterialsEx.GetItems(AIndex: Integer): TGLLibMaterialEx;
4612
begin
4613
  Result := TGLLibMaterialEx(inherited Items[AIndex]);
4614
end;
4615

4616
function TGLLibMaterialsEx.GetLibMaterialByName(
4617
  const AName: string): TGLLibMaterialEx;
4618
var
4619
  LMaterial: TGLAbstractLibMaterial;
4620
begin
4621
  LMaterial := GetMaterial(AName);
4622
  if Assigned(LMaterial) and (LMaterial is TGLLibMaterialEx) then
4623
    Result := TGLLibMaterialEx(LMaterial)
4624
  else
4625
    Result := nil;
4626
end;
4627

4628
function TGLLibMaterialsEx.IndexOf(const Item: TGLLibMaterialEx): Integer;
4629
var
4630
  I: Integer;
4631
begin
4632
  Result := -1;
4633
  if Count <> 0 then
4634
    for I := 0 to Count - 1 do
4635
      if GetItems(I) = Item then
4636
      begin
4637
        Result := I;
4638
        Exit;
4639
      end;
4640
end;
4641

4642
function TGLLibMaterialsEx.MaterialLibrary: TGLMaterialLibraryEx;
4643
begin
4644
  Result := TGLMaterialLibraryEx(GetOwner);
4645
end;
4646

4647
procedure TGLLibMaterialsEx.SetItems(AIndex: Integer;
4648
  const AValue: TGLLibMaterialEx);
4649
begin
4650
  inherited Items[AIndex] := AValue;
4651
end;
4652

4653
{$IFDEF GLS_REGION}{$ENDREGION}{$ENDIF}
4654

4655
{$IFDEF GLS_REGION}{$REGION 'TGLBaseShaderModel'}{$ENDIF}
4656

4657
procedure TGLBaseShaderModel.Apply(var ARci: TGLRenderContextInfo);
4658
var
4659
  I: Integer;
4660
  LEvent: TOnUniformSetting;
4661
begin
4662
  if FIsValid then
4663
  begin
4664
    FHandle.UseProgramObject;
4665
    if FAutoFill then
4666
      for I := FUniforms.Count - 1 downto 0 do
4667
        TGLAbstractShaderUniform(FUniforms[I]).Apply(ARci);
4668

4669
    if Self is TGLShaderModel3 then
4670
      LEvent := GetMaterial.FOnSM3UniformSetting
4671
    else if Self is TGLShaderModel4 then
4672
      LEvent := GetMaterial.FOnSM4UniformSetting
4673
    else if Self is TGLShaderModel5 then
4674
      LEvent := GetMaterial.FOnSM5UniformSetting
4675
    else
4676
      LEvent := nil;
4677

4678
    if Assigned(LEvent) then
4679
      LEvent(Self, ARci);
4680
  end;
4681
end;
4682

4683
procedure TGLBaseShaderModel.Assign(Source: TPersistent);
4684
var
4685
  SM: TGLBaseShaderModel;
4686
begin
4687
  if Source is TGLBaseShaderModel then
4688
  begin
4689
    SM := TGLBaseShaderModel(Source);
4690
    LibVertexShaderName := SM.LibVertexShaderName;
4691
    LibFragmentShaderName := SM.LibFragmentShaderName;
4692
    LibGeometryShaderName := SM.LibGeometryShaderName;
4693
    LibTessControlShaderName := SM.LibTessControlShaderName;
4694
    LibTessEvalShaderName := SM.LibTessEvalShaderName;
4695
  end;
4696
  inherited;
4697
end;
4698

4699
constructor TGLBaseShaderModel.Create(AOwner: TPersistent);
4700
begin
4701
  inherited;
4702
  FHandle := TGLProgramHandle.Create;
4703
  FHandle.OnPrapare := DoOnPrepare;
4704
  FEnabled := False;
4705
  FUniforms := TPersistentObjectList.Create;
4706
  FAutoFill := True;
4707
end;
4708

4709
procedure TGLBaseShaderModel.DefineProperties(Filer: TFiler);
4710
begin
4711
  inherited;
4712
  Filer.DefineBinaryProperty(
4713
    'Uniforms',
4714
    ReadUniforms,
4715
    WriteUniforms,
4716
    FUniforms.Count > 0);
4717
end;
4718

4719
destructor TGLBaseShaderModel.Destroy;
4720
begin
4721
  FHandle.Destroy;
4722
  LibVertexShaderName := '';
4723
  LibFragmentShaderName := '';
4724
  LibGeometryShaderName := '';
4725
  LibTessControlShaderName := '';
4726
  LibTessEvalShaderName := '';
4727
  FUniforms.CleanFree;
4728
  inherited;
4729
end;
4730

4731
procedure TGLBaseShaderModel.DoOnPrepare(Sender: TGLContext);
4732
var
4733
  T: TGLShaderType;
4734
  LUniforms: TPersistentObjectList;
4735
  LUniform, LUniform2: TGLShaderUniform;
4736
  ID: TGLuint;
4737
  I, J, C: Integer;
4738
  buff: array[0..255] of AnsiChar;
4739
  Size: TGLInt;
4740
  Len: GLsizei;
4741
  Loc: TGLint;
4742
  AType: GLenum;
4743
  UName: string;
4744
  GLSLData: TGLSLDataType;
4745
  GLSLSampler: TGLSLSamplerType;
4746
  bSampler: Boolean;
4747
  bNew: Boolean;
4748
  LEvent: TOnUniformInitialize;
4749
begin
4750
  if FEnabled then
4751
    try
4752
      if IsSupported and FHandle.IsSupported then
4753
      begin
4754
        FHandle.AllocateHandle;
4755
        if FHandle.IsDataNeedUpdate then
4756
        begin
4757
          // Validate shaders
4758
          for T := Low(TGLShaderType) to High(TGLShaderType) do
4759
            if Assigned(FShaders[T]) then
4760
            begin
4761
              FShaders[T].DoOnPrepare(Sender);
4762
              if not FShaders[T].IsValid then
4763
              begin
4764
                if IsDesignTime then
4765
                  FInfoLog := Format('%s shader "%s" is invalid',
4766
                    [cShaderTypeName[FShaders[T].ShaderType],
4767
                      FShaders[T].Name]);
4768
                FIsValid := False;
4769
                exit;
4770
              end;
4771
            end;
4772
          // Gather shader
4773
          FHandle.DetachAllObject;
4774
          for T := Low(TGLShaderType) to High(TGLShaderType) do
4775
            if Assigned(FShaders[T]) then
4776
              FHandle.AttachObject(FShaders[T].Handle);
4777
          ID := FHandle.Handle;
4778

4779
          with GL do
4780
          begin
4781
            // Can be override by layouts in shader
4782
            if Assigned(FShaders[shtGeometry]) then
4783
            begin
4784
              ProgramParameteri(ID, GL_GEOMETRY_INPUT_TYPE_EXT,
4785
                cGLgsInTypes[FShaders[shtGeometry].GeometryInput]);
4786
              ProgramParameteri(ID, GL_GEOMETRY_OUTPUT_TYPE_EXT,
4787
                cGLgsOutTypes[FShaders[shtGeometry].GeometryOutput]);
4788
              ProgramParameteri(ID, GL_GEOMETRY_VERTICES_OUT_EXT,
4789
                FShaders[shtGeometry].GeometryVerticesOut);
4790
            end;
4791

4792
            if FHandle.LinkProgram then
4793
            begin
4794

4795
              // Get final values
4796
              if Assigned(FShaders[shtGeometry]) then
4797
              begin
4798
                GetProgramiv(ID, GL_GEOMETRY_INPUT_TYPE_EXT, @AType);
4799
                case AType of
4800
                  GL_POINTS: FShaders[shtGeometry].FGeometryInput := gsInPoints;
4801
                  GL_LINES: FShaders[shtGeometry].FGeometryInput := gsInLines;
4802
                  GL_LINES_ADJACENCY_EXT: FShaders[shtGeometry].FGeometryInput
4803
                    := gsInAdjLines;
4804
                  GL_TRIANGLES: FShaders[shtGeometry].FGeometryInput :=
4805
                    gsInTriangles;
4806
                  GL_TRIANGLES_ADJACENCY_EXT:
4807
                    FShaders[shtGeometry].FGeometryInput := gsInAdjTriangles;
4808
                end;
4809
                GetProgramiv(ID, GL_GEOMETRY_OUTPUT_TYPE_EXT, @AType);
4810
                case AType of
4811
                  GL_POINTS: FShaders[shtGeometry].FGeometryOutput :=
4812
                    gsOutPoints;
4813
                  GL_LINE_STRIP: FShaders[shtGeometry].FGeometryOutput :=
4814
                    gsOutLineStrip;
4815
                  GL_TRIANGLE_STRIP: FShaders[shtGeometry].FGeometryOutput :=
4816
                    sOutTriangleStrip;
4817
                end;
4818
                GetProgramiv(ID, GL_GEOMETRY_VERTICES_OUT_EXT, @I);
4819
                if I > 0 then
4820
                  FShaders[shtGeometry].FGeometryVerticesOut := I;
4821
                ClearError;
4822
              end;
4823

4824
              // Get uniforms
4825
              LUniforms := TPersistentObjectList.Create;
4826

4827
              GL.GetProgramiv(ID, GL_ACTIVE_UNIFORMS, @C);
4828
              for I := 0 to C - 1 do
4829
              begin
4830
                GetActiveUniform(
4831
                  ID,
4832
                  TGLuint(I),
4833
                  Length(buff),
4834
                  @Len,
4835
                  @Size,
4836
                  @AType,
4837
                  @buff[0]);
4838
                Loc := GetUniformLocation(ID, @buff[0]);
4839
                if Loc < 0 then
4840
                  continue;
4841
                UName := Copy(string(buff), 0, Len);
4842
                GLSLData := GLSLTypeUndefined;
4843
                GLSLSampler := GLSLSamplerUndefined;
4844
                case AType of
4845
                  GL_FLOAT: GLSLData := GLSLType1F;
4846
                  GL_FLOAT_VEC2: GLSLData := GLSLType2F;
4847
                  GL_FLOAT_VEC3: GLSLData := GLSLType3F;
4848
                  GL_FLOAT_VEC4: GLSLData := GLSLType4F;
4849
                  GL_INT: GLSLData := GLSLType1I;
4850
                  GL_INT_VEC2: GLSLData := GLSLType2I;
4851
                  GL_INT_VEC3: GLSLData := GLSLType3I;
4852
                  GL_INT_VEC4: GLSLData := GLSLType4I;
4853
                  GL_UNSIGNED_INT: GLSLData := GLSLType1UI;
4854
                  GL_UNSIGNED_INT_VEC2: GLSLData := GLSLType2UI;
4855
                  GL_UNSIGNED_INT_VEC3: GLSLData := GLSLType3UI;
4856
                  GL_UNSIGNED_INT_VEC4: GLSLData := GLSLType4UI;
4857
                  GL_BOOL: GLSLData := GLSLType1I;
4858
                  GL_BOOL_VEC2: GLSLData := GLSLType2I;
4859
                  GL_BOOL_VEC3: GLSLData := GLSLType3I;
4860
                  GL_BOOL_VEC4: GLSLData := GLSLType4I;
4861
                  GL_FLOAT_MAT2: GLSLData := GLSLTypeMat2F;
4862
                  GL_FLOAT_MAT3: GLSLData := GLSLTypeMat3F;
4863
                  GL_FLOAT_MAT4: GLSLData := GLSLTypeMat4F;
4864
                  //------------------------------------------------------------------------------
4865
                  GL_SAMPLER_1D: GLSLSampler := GLSLSampler1D;
4866
                  GL_SAMPLER_2D: GLSLSampler := GLSLSampler2D;
4867
                  GL_SAMPLER_3D: GLSLSampler := GLSLSampler3D;
4868
                  GL_SAMPLER_CUBE: GLSLSampler := GLSLSamplerCube;
4869
                  GL_SAMPLER_1D_SHADOW: GLSLSampler := GLSLSampler1DShadow;
4870
                  GL_SAMPLER_2D_SHADOW: GLSLSampler := GLSLSampler2DShadow;
4871
                  GL_SAMPLER_2D_RECT: GLSLSampler := GLSLSamplerRect;
4872
                  GL_SAMPLER_2D_RECT_SHADOW: GLSLSampler :=
4873
                    GLSLSamplerRectShadow;
4874
                  GL_SAMPLER_BUFFER: GLSLSampler := GLSLSamplerBuffer;
4875
                  GL_INT_SAMPLER_2D_RECT: GLSLSampler :=
4876
                    GLSLIntSamplerRect;
4877
                  GL_INT_SAMPLER_BUFFER: GLSLSampler :=
4878
                    GLSLIntSamplerBuffer;
4879
                  GL_UNSIGNED_INT_SAMPLER_1D: GLSLSampler :=
4880
                    GLSLUIntSampler1D;
4881
                  GL_UNSIGNED_INT_SAMPLER_2D: GLSLSampler :=
4882
                    GLSLUIntSampler2D;
4883
                  GL_UNSIGNED_INT_SAMPLER_3D: GLSLSampler :=
4884
                    GLSLUIntSampler3D;
4885
                  GL_UNSIGNED_INT_SAMPLER_CUBE: GLSLSampler :=
4886
                    GLSLUIntSamplerCube;
4887
                  GL_UNSIGNED_INT_SAMPLER_1D_ARRAY: GLSLSampler :=
4888
                    GLSLUIntSampler1DArray;
4889
                  GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: GLSLSampler :=
4890
                    GLSLUIntSampler2DArray;
4891
                  GL_UNSIGNED_INT_SAMPLER_2D_RECT: GLSLSampler :=
4892
                    GLSLUIntSamplerRect;
4893
                  GL_UNSIGNED_INT_SAMPLER_BUFFER: GLSLSampler :=
4894
                    GLSLUIntSamplerBuffer;
4895
                  GL_SAMPLER_2D_MULTISAMPLE: GLSLSampler :=
4896
                    GLSLSamplerMS;
4897
                  GL_INT_SAMPLER_2D_MULTISAMPLE: GLSLSampler :=
4898
                    GLSLIntSamplerMS;
4899
                  GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE: GLSLSampler :=
4900
                    GLSLUIntSamplerMS;
4901
                  GL_SAMPLER_2D_MULTISAMPLE_ARRAY: GLSLSampler :=
4902
                    GLSLSamplerMSArray;
4903
                  GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: GLSLSampler :=
4904
                    GLSLIntSamplerMSArray;
4905
                  GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: GLSLSampler :=
4906
                    GLSLUIntSamplerMSArray;
4907
                end;
4908

4909
                bSampler := False;
4910
                if (GLSLData = GLSLTypeUndefined) and (GLSLSampler =
4911
                  GLSLSamplerUndefined) then
4912
                begin
4913
                  GLSLogger.LogWarningFmt(
4914
                    'Detected active uniform "%s" with unknown type', [UName]);
4915
                  continue;
4916
                end
4917
                else if GLSLData <> GLSLTypeUndefined then
4918
                begin
4919
                  GLSLogger.LogInfoFmt('Detected active uniform: %s %s',
4920
                    [cGLSLTypeString[GLSLData], UName]);
4921
                end
4922
                else
4923
                begin
4924
                  bSampler := True;
4925
                  GLSLogger.LogInfoFmt('Detected active uniform: %s %s',
4926
                    [cGLSLSamplerString[GLSLSampler], UName]);
4927
                end;
4928

4929
                // Find already existing uniform
4930
                bNew := True;
4931
                for J := 0 to FUniforms.Count - 1 do
4932
                begin
4933
                  if not (FUniforms[J] is TGLShaderUniform) then
4934
                    continue;
4935
                  LUniform := TGLShaderUniform(FUniforms[J]);
4936
                  if not Assigned(LUniform) then
4937
                    continue;
4938
                  if LUniform.Name = UName then
4939
                  begin
4940
                    if bSampler and (LUniform is TGLShaderUniformTexture) then
4941
                    begin
4942
                      if TGLShaderUniformTexture(LUniform).FSamplerType =
4943
                        GLSLSampler then
4944
                      begin
4945
                        LUniform.FLocation := Loc;
4946
                        LUniform.FType := GLSLType1I;
4947
                        TGLShaderUniformTexture(LUniform).FTarget :=
4948
                          cSamplerToTexture[GLSLSampler];
4949
                        LUniforms.Add(LUniform);
4950
                        FUniforms[J] := nil;
4951
                        bNew := False;
4952
                        break;
4953
                      end
4954
                    end
4955
                    else
4956
                    begin
4957
                      if LUniform.FType = GLSLData then
4958
                      begin
4959
                        if (LUniform is TGLShaderUniformDSA)
4960
                          and not EXT_direct_state_access then
4961
                        begin
4962
                          LUniform2 := LUniform;
4963
                          LUniform := TGLShaderUniform.Create(Self);
4964
                          LUniform._AddRef;
4965
                          LUniform.Assign(LUniform2);
4966
                          LUniform2._Release;
4967
                        end;
4968
                        LUniform.FLocation := Loc;
4969
                        LUniforms.Add(LUniform);
4970
                        FUniforms[J] := nil;
4971
                        bNew := False;
4972
                        break;
4973
                      end;
4974
                    end;
4975
                  end;
4976
                end; // for J
4977

4978
                if bNew then
4979
                begin
4980
                  // Create new uniform
4981
                  if bSampler then
4982
                  begin
4983
                    LUniform := TGLShaderUniformTexture.Create(Self);
4984
                    LUniform.FType := GLSLType1I;
4985
                    TGLShaderUniformTexture(LUniform).FSamplerType :=
4986
                      GLSLSampler;
4987
                    TGLShaderUniformTexture(LUniform).FTarget :=
4988
                      cSamplerToTexture[GLSLSampler];
4989
                  end
4990
                  else
4991
                  begin
4992
                    if EXT_direct_state_access then
4993
                      LUniform := TGLShaderUniformDSA.Create(Self)
4994
                    else
4995
                      LUniform := TGLShaderUniform.Create(Self);
4996
                    LUniform.FType := GLSLData;
4997
                  end;
4998
                  LUniform._AddRef;
4999
                  LUniform.FName := UName;
5000
                  LUniform.FNameHashCode := ComputeNameHashKey(UName);
5001
                  LUniform.FLocation := Loc;
5002
                  LUniforms.Add(LUniform);
5003
                end;
5004
              end; // for I
5005

5006
              // Clean old unused uniforms
5007
              ReleaseUniforms(FUniforms);
5008
              // Assigned new one
5009
              FUniforms := LUniforms;
5010

5011
              FHandle.NotifyDataUpdated;
5012
              FIsValid := True;
5013

5014
              if Self is TGLShaderModel3 then
5015
                LEvent := GetMaterial.FOnSM3UniformInit
5016
              else if Self is TGLShaderModel4 then
5017
                LEvent := GetMaterial.FOnSM4UniformInit
5018
              else if Self is TGLShaderModel5 then
5019
                LEvent := GetMaterial.FOnSM5UniformInit
5020
              else
5021
                LEvent := nil;
5022

5023
              if Assigned(LEvent) then
5024
                LEvent(Self);
5025

5026
            end // if LinkProgram
5027
            else
5028
              FIsValid := False;
5029
          end; // with GL
5030

5031
          if IsDesignTime then
5032
          begin
5033
            FInfoLog := FHandle.InfoLog;
5034
            if (Length(FInfoLog) = 0) and FIsValid then
5035
              FInfoLog := 'Link successful';
5036
          end
5037
          else if FIsValid then
5038
            GLSLogger.LogInfoFmt('Program "%s" link successful - %s',
5039
              [GetMaterial.Name, FHandle.InfoLog])
5040
          else
5041
            GLSLogger.LogErrorFmt('Program "%s" link failed! - %s',
5042
              [GetMaterial.Name, FHandle.InfoLog]);
5043
        end;
5044
      end
5045
      else
5046
      begin
5047
        if IsDesignTime then
5048
          FInfoLog := 'Not supported by hardware';
5049
        FIsValid := False;
5050
      end;
5051

5052
    except
5053
      on E: Exception do
5054
      begin
5055
        FIsValid := False;
5056
        if IsDesignTime then
5057
          InformationDlg(E.ClassName + ': ' + E.Message)
5058
        else
5059
          GLSLogger.LogError(E.ClassName + ': ' + E.Message);
5060
      end;
5061
    end;
5062
end;
5063

5064
procedure TGLBaseShaderModel.Notification(Sender: TObject; Operation:
5065
  TOperation);
5066
var
5067
  st: TGLShaderType;
5068
begin
5069
  if Operation = opRemove then
5070
  begin
5071
    for st := Low(TGLShaderType) to High(TGLShaderType) do
5072
      if FShaders[st] = Sender then
5073
      begin
5074
        FShaders[st] := nil;
5075
        FLibShaderName[st] := '';
5076
        NotifyChange(Self);
5077
        exit;
5078
      end;
5079
  end;
5080
end;
5081

5082
procedure TGLBaseShaderModel.NotifyChange(Sender: TObject);
5083
begin
5084
  FHandle.NotifyChangesOfData;
5085
  inherited;
5086
end;
5087

5088
procedure TGLBaseShaderModel.ReadUniforms(AStream: TStream);
5089
var
5090
  LReader: TReader;
5091
  N, I: Integer;
5092
  str: string;
5093
  LUniform: TGLAbstractShaderUniform;
5094
  LClass: CGLAbstractShaderUniform;
5095
begin
5096
  LReader := TReader.Create(AStream, 16384);
5097
  try
5098
    N := LReader.ReadInteger;
5099
    for I := 0 to N - 1 do
5100
    begin
5101
      str := LReader.ReadWideString;
5102
      LClass := CGLAbstractShaderUniform(FindClass(str));
5103
      LUniform := LClass.Create(Self);
5104
      LUniform._AddRef;
5105
      LUniform.ReadFromFiler(LReader);
5106
      FUniforms.Add(LUniform);
5107
    end;
5108
  finally
5109
    LReader.Free;
5110
  end;
5111
end;
5112

5113
class procedure TGLBaseShaderModel.ReleaseUniforms(
5114
  AList: TPersistentObjectList);
5115
var
5116
  I: Integer;
5117
begin
5118
  for I := 0 to AList.Count - 1 do
5119
    if Assigned(AList[I]) then
5120
      TGLAbstractShaderUniform(AList[I])._Release;
5121
  AList.Destroy;
5122
end;
5123

5124
function TGLBaseShaderModel.GetLibShaderName(AType: TGLShaderType): string;
5125
begin
5126
  if Assigned(FShaders[AType]) then
5127
    Result := FShaders[AType].Name
5128
  else
5129
    Result := '';
5130
end;
5131

5132
function TGLBaseShaderModel.GetUniform(const AName: string): IShaderParameter;
5133
var
5134
  H, I: Integer;
5135
  U: TGLAbstractShaderUniform;
5136
begin
5137
  Result := nil;
5138
  H := ComputeNameHashKey(AName);
5139
  for I := 0 to FUniforms.Count - 1 do
5140
  begin
5141
    U := TGLAbstractShaderUniform(FUniforms[I]);
5142
    if (U.FNameHashCode = H) and (U.FName = AName) then
5143
    begin
5144
      Result := U;
5145
      exit;
5146
    end;
5147
  end;
5148

5149
  if not IsDesignTime then
5150
  begin
5151
    GLSLogger.LogErrorFmt('Attempt to use unknow uniform "%s" for material "%s"',
5152
      [AName, GetMaterial.Name]);
5153
    U := TGLAbstractShaderUniform.Create(Self);
5154
    U._AddRef;
5155
    U.FName := AName;
5156
    U.FNameHashCode := H;
5157
    FUniforms.Add(U);
5158
    Result := U;
5159
  end;
5160
end;
5161

5162
procedure TGLBaseShaderModel.Loaded;
5163
var
5164
  T: TGLShaderType;
5165
  I: Integer;
5166
begin
5167
  for T := Low(TGLShaderType) to High(TGLShaderType) do
5168
    SetLibShaderName(T, FLibShaderName[T]);
5169
  for I := 0 to FUniforms.Count - 1 do
5170
    if FUniforms[I] is TGLShaderUniformTexture then
5171
      TGLShaderUniformTexture(FUniforms[I]).Loaded;
5172
end;
5173

5174
procedure TGLBaseShaderModel.GetUniformNames(Proc: TGetStrProc);
5175
var
5176
  I: Integer;
5177
begin
5178
  for I := 0 to FUniforms.Count - 1 do
5179
    Proc(TGLAbstractShaderUniform(FUniforms[I]).FName);
5180
end;
5181

5182
procedure TGLBaseShaderModel.SetLibShaderName(AType: TGLShaderType;
5183
  const AValue: string);
5184
var
5185
  LShader: TGLShaderEx;
5186
begin
5187
  if csLoading in GetMaterialLibraryEx.ComponentState then
5188
  begin
5189
    FLibShaderName[AType] := AValue;
5190
    exit;
5191
  end;
5192

5193
  if Assigned(FShaders[AType]) then
5194
  begin
5195
    FShaders[AType].UnregisterUser(Self);
5196
    FShaders[AType] := nil;
5197
    FLibShaderName[AType] := '';
5198
  end;
5199

5200
  LShader := GetMaterialLibraryEx.Components.GetShaderByName(AValue);
5201
  if Assigned(LShader) then
5202
  begin
5203
    if LShader.ShaderType <> AType then
5204
    begin
5205
      if IsDesignTime then
5206
        InformationDlg(Format('Incompatible shader type, need %s shader',
5207
          [cShaderTypeName[AType]]));
5208
      exit;
5209
    end;
5210
    LShader.RegisterUser(Self);
5211
    FShaders[AType] := LShader;
5212
    FLibShaderName[AType] := AValue;
5213
  end;
5214
  NotifyChange(Self);
5215
end;
5216

5217
procedure TGLBaseShaderModel.UnApply(var ARci: TGLRenderContextInfo);
5218
begin
5219
  if FIsValid and not ARci.GLStates.ForwardContext then
5220
    FHandle.EndUseProgramObject;
5221
end;
5222

5223
procedure TGLBaseShaderModel.WriteUniforms(AStream: TStream);
5224
var
5225
  LWriter: TWriter;
5226
  I: Integer;
5227
begin
5228
  LWriter := TWriter.Create(AStream, 16384);
5229
  try
5230
    LWriter.WriteInteger(FUniforms.Count);
5231
    for I := 0 to FUniforms.Count - 1 do
5232
    begin
5233
      LWriter.WriteWideString(FUniforms[I].ClassName);
5234
      TGLAbstractShaderUniform(FUniforms[I]).WriteToFiler(LWriter);
5235
    end;
5236
  finally
5237
    LWriter.Free;
5238
  end;
5239
end;
5240

5241
class function TGLShaderModel3.IsSupported: Boolean;
5242
begin
5243
  Result := GL.ARB_shader_objects;
5244
end;
5245

5246
class function TGLShaderModel4.IsSupported: Boolean;
5247
begin
5248
  Result := GL.EXT_gpu_shader4;
5249
end;
5250

5251
class function TGLShaderModel5.IsSupported: Boolean;
5252
begin
5253
  Result := GL.ARB_gpu_shader5;
5254
end;
5255

5256
procedure BeginPatch(mode: TGLEnum);
5257
{$IFDEF MSWINDOWS} stdcall;
5258
{$ENDIF}{$IFDEF UNIX} cdecl;
5259
{$ENDIF}
5260
begin
5261
  if mode = GL_PATCHES then
5262
    vStoreBegin(GL_PATCHES)
5263
  else if (mode = GL_TRIANGLES)
5264
    or (mode = GL_TRIANGLE_STRIP)
5265
    or (mode = GL_TRIANGLE_FAN)
5266
    or (mode = GL_QUADS) then
5267
  begin
5268
    if mode = GL_QUADS then
5269
      GL.PatchParameteri(GL_PATCH_VERTICES, 4)
5270
    else
5271
      GL.PatchParameteri(GL_PATCH_VERTICES, 3);
5272
    vStoreBegin(GL_PATCHES);
5273
  end
5274
  else
5275
  begin
5276
    GL.Begin_ := vStoreBegin;
5277
    GLSLogger.LogError('glBegin called with unsupported primitive for tessellation');
5278
    Abort;
5279
  end;
5280
end;
5281

5282
procedure TGLShaderModel5.Apply(var ARci: TGLRenderContextInfo);
5283
begin
5284
  if Assigned(FShaders[shtControl]) or Assigned(FShaders[shtEvaluation]) then
5285
  begin
5286
    vStoreBegin := GL.Begin_;
5287
    GL.Begin_ := BeginPatch;
5288
    ARci.amalgamating := True;
5289
  end;
5290
  inherited;
5291
end;
5292

5293
procedure TGLShaderModel5.UnApply(var ARci: TGLRenderContextInfo);
5294
begin
5295
  inherited;
5296
  if Assigned(FShaders[shtControl]) or Assigned(FShaders[shtEvaluation]) then
5297
    GL.Begin_ := vStoreBegin;
5298
  ARci.amalgamating := False;
5299
end;
5300

5301
{$IFDEF GLS_REGION}{$ENDREGION}{$ENDIF}
5302

5303
{$IFDEF GLS_REGION}{$REGION 'TGLMatLibComponents'}{$ENDIF}
5304

5305
function TGLMatLibComponents.GetAttachmentByName(
5306
  const AName: TGLMaterialComponentName): TGLFrameBufferAttachment;
5307
var
5308
  N, I: Integer;
5309
begin
5310
  N := ComputeNameHashKey(AName);
5311
  for I := 0 to Count - 1 do
5312
  begin
5313
    if (Items[I] is TGLFrameBufferAttachment) and (Items[I].FNameHashKey = N)
5314
      then
5315
    begin
5316
      if Items[I].Name = AName then
5317
      begin
5318
        Result := TGLFrameBufferAttachment(Items[I]);
5319
        exit;
5320
      end;
5321
    end;
5322
  end;
5323
  Result := nil;
5324
end;
5325

5326
function TGLMatLibComponents.GetCombinerByName(
5327
  const AName: TGLMaterialComponentName): TGLTextureCombiner;
5328
var
5329
  N, I: Integer;
5330
begin
5331
  N := ComputeNameHashKey(AName);
5332
  for I := 0 to Count - 1 do
5333
  begin
5334
    if (Items[I] is TGLTextureCombiner) and (Items[I].FNameHashKey = N) then
5335
    begin
5336
      if Items[I].Name = AName then
5337
      begin
5338
        Result := TGLTextureCombiner(Items[I]);
5339
        exit;
5340
      end;
5341
    end;
5342
  end;
5343
  Result := nil;
5344
end;
5345

5346
function TGLMatLibComponents.GetItemByName(
5347
  const AName: TGLMaterialComponentName): TGLBaseMaterialCollectionItem;
5348
var
5349
  N, I: Integer;
5350
begin
5351
  N := ComputeNameHashKey(AName);
5352
  for I := 0 to Count - 1 do
5353
  begin
5354
    if (Items[I].FNameHashKey = N) and (Items[I].Name = AName) then
5355
    begin
5356
      Result := Items[I];
5357
      exit;
5358
    end;
5359
  end;
5360
  Result := nil;
5361
end;
5362

5363
function TGLMatLibComponents.GetItems(
5364
  index: Integer): TGLBaseMaterialCollectionItem;
5365
begin
5366
  Result := TGLBaseMaterialCollectionItem(inherited GetItems(index));
5367
end;
5368

5369
function TGLMatLibComponents.GetNamePath: string;
5370
var
5371
  s: string;
5372
begin
5373
  Result := ClassName;
5374
  if GetOwner = nil then
5375
    Exit;
5376
  s := GetOwner.GetNamePath;
5377
  if s = '' then
5378
    Exit;
5379
  Result := s + '.Components';
5380
end;
5381

5382
function TGLMatLibComponents.GetSamplerByName(
5383
  const AName: TGLMaterialComponentName): TGLTextureSampler;
5384
var
5385
  N, I: Integer;
5386
begin
5387
  N := ComputeNameHashKey(AName);
5388
  for I := 0 to Count - 1 do
5389
  begin
5390
    if (Items[I] is TGLTextureSampler) and (Items[I].FNameHashKey = N) then
5391
    begin
5392
      if Items[I].Name = AName then
5393
      begin
5394
        Result := TGLTextureSampler(Items[I]);
5395
        exit;
5396
      end;
5397
    end;
5398
  end;
5399
  Result := nil;
5400
end;
5401

5402
function TGLMatLibComponents.GetShaderByName(
5403
  const AName: TGLMaterialComponentName): TGLShaderEx;
5404
var
5405
  N, I: Integer;
5406
begin
5407
  N := ComputeNameHashKey(AName);
5408
  for I := 0 to Count - 1 do
5409
  begin
5410
    if (Items[I] is TGLShaderEx) and (Items[I].FNameHashKey = N) then
5411
    begin
5412
      if Items[I].Name = AName then
5413
      begin
5414
        Result := TGLShaderEx(Items[I]);
5415
        exit;
5416
      end;
5417
    end;
5418
  end;
5419
  Result := nil;
5420
end;
5421

5422
function TGLMatLibComponents.GetAsmProgByName(
5423
  const AName: TGLMaterialComponentName): TGLASMVertexProgram;
5424
var
5425
  N, I: Integer;
5426
begin
5427
  N := ComputeNameHashKey(AName);
5428
  for I := 0 to Count - 1 do
5429
  begin
5430
    if (Items[I] is TGLASMVertexProgram) and (Items[I].FNameHashKey = N) then
5431
    begin
5432
      if Items[I].Name = AName then
5433
      begin
5434
        Result := TGLASMVertexProgram(Items[I]);
5435
        exit;
5436
      end;
5437
    end;
5438
  end;
5439
  Result := nil;
5440
end;
5441

5442
function TGLMatLibComponents.GetTextureByName(
5443
  const AName: TGLMaterialComponentName): TGLAbstractTexture;
5444
var
5445
  N, I: Integer;
5446
begin
5447
  N := ComputeNameHashKey(AName);
5448
  for I := 0 to Count - 1 do
5449
  begin
5450
    if (Items[I] is TGLAbstractTexture) and (Items[I].FNameHashKey = N) then
5451
    begin
5452
      if Items[I].Name = AName then
5453
      begin
5454
        Result := TGLTextureImageEx(Items[I]);
5455
        exit;
5456
      end;
5457
    end;
5458
  end;
5459
  Result := nil;
5460
end;
5461

5462
class function TGLMatLibComponents.ItemsClass: TGLXCollectionItemClass;
5463
begin
5464
  Result := TGLBaseMaterialCollectionItem;
5465
end;
5466

5467
function TGLMatLibComponents.MakeUniqueName(const AName:
5468
  TGLMaterialComponentName): TGLMaterialComponentName;
5469
var
5470
  I: Integer;
5471
begin
5472
  Result := AName;
5473
  I := 1;
5474
  while GetItemByName(Result) <> nil do
5475
  begin
5476
    Result := AName + IntToStr(i);
5477
    Inc(i);
5478
  end;
5479
end;
5480

5481
{$IFDEF GLS_REGION}{$ENDREGION}{$ENDIF}
5482

5483
{$IFDEF GLS_REGION}{$REGION 'TGLMaterialLibraryEx'}{$ENDIF}
5484

5485
function TGLMaterialLibraryEx.AddAttachment(
5486
  const AName: TGLMaterialComponentName): TGLFrameBufferAttachment;
5487
begin
5488
  Result := TGLFrameBufferAttachment.Create(Components);
5489
  Result.Name := AName;
5490
  Components.Add(Result);
5491
end;
5492

5493
function TGLMaterialLibraryEx.AddCombiner(
5494
  const AName: TGLMaterialComponentName): TGLTextureCombiner;
5495
begin
5496
  Result := TGLTextureCombiner.Create(Components);
5497
  Result.Name := AName;
5498
  Components.Add(Result);
5499
end;
5500

5501
function TGLMaterialLibraryEx.AddSampler(
5502
  const AName: TGLMaterialComponentName): TGLTextureSampler;
5503
begin
5504
  Result := TGLTextureSampler.Create(Components);
5505
  Result.Name := AName;
5506
  Components.Add(Result);
5507
end;
5508

5509
function TGLMaterialLibraryEx.AddShader(
5510
  const AName: TGLMaterialComponentName): TGLShaderEx;
5511
begin
5512
  Result := TGLShaderEx.Create(Components);
5513
  Result.Name := AName;
5514
  Components.Add(Result);
5515
end;
5516

5517
function TGLMaterialLibraryEx.AddAsmProg(
5518
  const AName: TGLMaterialComponentName): TGLASMVertexProgram;
5519
begin
5520
  Result := TGLASMVertexProgram.Create(Components);
5521
  Result.Name := AName;
5522
  Components.Add(Result);
5523
end;
5524

5525
function TGLMaterialLibraryEx.AddTexture(
5526
  const AName: TGLMaterialComponentName): TGLTextureImageEx;
5527
begin
5528
  Result := TGLTextureImageEx.Create(Components);
5529
  Result.Name := AName;
5530
  Components.Add(Result);
5531
end;
5532

5533
constructor TGLMaterialLibraryEx.Create(AOwner: TComponent);
5534
begin
5535
  inherited;
5536
  FMaterials := TGLLibMaterialsEx.Create(Self);
5537
  FComponents := TGLMatLibComponents.Create(Self);
5538
end;
5539

5540
procedure TGLMaterialLibraryEx.DefineProperties(Filer: TFiler);
5541
begin
5542
  Filer.DefineBinaryProperty(
5543
    'ComponentsData',
5544
    ReadComponents,
5545
    WriteComponents,
5546
    Components.Count > 0);
5547
  inherited;
5548
end;
5549

5550
destructor TGLMaterialLibraryEx.Destroy;
5551
begin
5552
  FMaterials.Destroy;
5553
  FComponents.Destroy;
5554
  inherited;
5555
end;
5556

5557
function TGLMaterialLibraryEx.GetMaterials: TGLLibMaterialsEx;
5558
begin
5559
  Result := TGLLibMaterialsEx(FMaterials);
5560
end;
5561

5562
procedure TGLMaterialLibraryEx.GetNames(Proc: TGetStrProc;
5563
  AClass: CGLBaseMaterialCollectionItem);
5564
var
5565
  I: Integer;
5566
begin
5567
  for I := 0 to Components.Count - 1 do
5568
    if Components[I].ClassType = AClass then
5569
      Proc(Components[I].Name)
5570
end;
5571

5572
procedure TGLMaterialLibraryEx.Loaded;
5573
begin
5574
  inherited;
5575
end;
5576

5577
procedure TGLMaterialLibraryEx.ReadComponents(AStream: TStream);
5578
var
5579
  LReader: TReader;
5580
begin
5581
  LReader := TReader.Create(AStream, 16384);
5582
  try
5583
    Components.ReadFromFiler(LReader);
5584
  finally
5585
    LReader.Free;
5586
  end;
5587
end;
5588

5589
procedure TGLMaterialLibraryEx.SetComponents(AValue: TGLMatLibComponents);
5590
begin
5591
  FComponents.Assign(AValue);
5592
end;
5593

5594
procedure TGLMaterialLibraryEx.SetLevelForAll(const ALevel: TGLMaterialLevel);
5595
var
5596
  I: Integer;
5597
begin
5598
  for I := Materials.Count - 1 downto 0 do
5599
    Materials[I].ApplicableLevel := ALevel;
5600
end;
5601

5602
procedure TGLMaterialLibraryEx.SetMaterials(AValue: TGLLibMaterialsEx);
5603
begin
5604
  FMaterials.Assign(AValue);
5605
end;
5606

5607
function TGLMaterialLibraryEx.StoreMaterials: Boolean;
5608
begin
5609
  Result := (FMaterials.Count > 0);
5610
end;
5611

5612
procedure TGLMaterialLibraryEx.WriteComponents(AStream: TStream);
5613
var
5614
  LWriter: TWriter;
5615
begin
5616
  LWriter := TWriter.Create(AStream, 16384);
5617
  try
5618
    Components.WriteToFiler(LWriter);
5619
  finally
5620
    LWriter.Free;
5621
  end;
5622
end;
5623

5624
{$IFDEF GLS_REGION}{$ENDREGION}{$ENDIF}
5625

5626
{$IFDEF GLS_REGION}{$REGION 'TGLShaderUniformTexture'}{$ENDIF}
5627

5628
procedure TGLShaderUniformTexture.Apply(var ARci: TGLRenderContextInfo);
5629

5630
  function FindHotActiveUnit: Boolean;
5631
  var
5632
    ID: TGLuint;
5633
    I, J: Integer;
5634
    bindTime, minTime: Double;
5635
    LTex: TGLTextureImageEx;
5636
  begin
5637
    with ARci.GLStates do
5638
    begin
5639
      if Assigned(FLibTexture) and FLibTexture.IsValid then
5640
      begin
5641
        ID := FLibTexture.FHandle.Handle;
5642
        // Yar: may be need exract this to new method of TGLTextureImageEx ???
5643
        if FLibTexture is TGLTextureImageEx then
5644
        begin
5645
          LTex := TGLTextureImageEx(FLibTexture);
5646
          Inc(LTex.FApplyCounter);
5647
          if LTex.FApplyCounter > 16 then
5648
            FreeAndNil(LTex.FImage);
5649
        end;
5650
      end
5651
      else
5652
        ID := 0;
5653

5654
      // Find alredy binded texture unit
5655
      for I := 0 to MaxTextureImageUnits - 1 do
5656
      begin
5657
        if TextureBinding[I, FTarget] = ID then
5658
        begin
5659
          GL.Uniform1i(FLocation, I);
5660
          ActiveTexture := I;
5661
          Result := True;
5662
          exit;
5663
        end;
5664
      end;
5665
      // Find unused texture unit
5666
      for I := 0 to MaxTextureImageUnits - 1 do
5667
      begin
5668
        if TextureBinding[I, FTarget] = 0 then
5669
        begin
5670
          TextureBinding[I, FTarget] := ID;
5671
          GL.Uniform1i(FLocation, I);
5672
          ActiveTexture := I;
5673
          Result := True;
5674
          exit;
5675
        end;
5676
      end;
5677
      // Find most useless texture unit
5678
      minTime := GLSTime;
5679
      J := 0;
5680
      for I := 0 to MaxTextureImageUnits - 1 do
5681
      begin
5682
        bindTime := TextureBindingTime[I, FTarget];
5683
        if bindTime < minTime then
5684
        begin
5685
          minTime := bindTime;
5686
          J := I;
5687
        end;
5688
      end;
5689

5690
      TextureBinding[J, FTarget] := ID;
5691
      ActiveTexture := J;
5692
      GL.Uniform1i(FLocation, J);
5693
      Result := True;
5694
      exit;
5695
    end;
5696
    Result := False;
5697
  end;
5698

5699
var
5700
  glTarget: TGLEnum;
5701
begin
5702
  if FLocation > -1 then
5703
  begin
5704
    if FindHotActiveUnit and Assigned(FLibTexture) and Assigned(FLibSampler)
5705
      then
5706
      with GL do
5707
      begin
5708
        // Apply swizzling if possible
5709
        glTarget := DecodeGLTextureTarget(FLibTexture.Shape);
5710
        if ARB_texture_swizzle or EXT_texture_swizzle then
5711
        begin
5712

5713
          if FSwizzling[0] <> FLibTexture.FSwizzles[0] then
5714
          begin
5715
            FLibTexture.FSwizzles[0] := FSwizzling[0];
5716
            TexParameteri(glTarget, GL_TEXTURE_SWIZZLE_R,
5717
              cTextureSwizzle[FSwizzling[0]]);
5718
          end;
5719
          if FSwizzling[1] <> FLibTexture.FSwizzles[1] then
5720
          begin
5721
            FLibTexture.FSwizzles[1] := FSwizzling[1];
5722
            TexParameteri(glTarget, GL_TEXTURE_SWIZZLE_G,
5723
              cTextureSwizzle[FSwizzling[1]]);
5724
          end;
5725
          if FSwizzling[2] <> FLibTexture.FSwizzles[2] then
5726
          begin
5727
            FLibTexture.FSwizzles[2] := FSwizzling[2];
5728
            TexParameteri(glTarget, GL_TEXTURE_SWIZZLE_B,
5729
              cTextureSwizzle[FSwizzling[2]]);
5730
          end;
5731
          if FSwizzling[3] <> FLibTexture.FSwizzles[3] then
5732
          begin
5733
            FLibTexture.FSwizzles[3] := FSwizzling[3];
5734
            TexParameteri(glTarget, GL_TEXTURE_SWIZZLE_A,
5735
              cTextureSwizzle[FSwizzling[3]]);
5736
          end;
5737
        end;
5738

5739
        if FLibSampler.IsValid then
5740
          FLibSampler.Apply(ARci)
5741
        else if FLibTexture.FLastSampler <> FLibSampler then
5742
        begin
5743
          // Sampler object not supported, lets use texture states
5744
          TexParameterfv(glTarget, GL_TEXTURE_BORDER_COLOR,
5745
            FLibSampler.BorderColor.AsAddress);
5746
          TexParameteri(glTarget, GL_TEXTURE_WRAP_S,
5747
            cTextureWrapMode[FLibSampler.WrapX]);
5748
          TexParameteri(glTarget, GL_TEXTURE_WRAP_T,
5749
            cTextureWrapMode[FLibSampler.WrapY]);
5750
          TexParameteri(glTarget, GL_TEXTURE_WRAP_R,
5751
            cTextureWrapMode[FLibSampler.WrapZ]);
5752
          TexParameterf(glTarget, GL_TEXTURE_LOD_BIAS, FLibSampler.LODBias +
5753
            FLibSampler.FLODBiasFract);
5754
          TexParameteri(glTarget, GL_TEXTURE_MIN_FILTER,
5755
            cTextureMinFilter[FLibSampler.MinFilter]);
5756
          TexParameteri(glTarget, GL_TEXTURE_MAG_FILTER,
5757
            cTextureMagFilter[FLibSampler.MagFilter]);
5758

5759
          if EXT_texture_filter_anisotropic then
5760
          begin
5761
            if FLibSampler.FilteringQuality = tfAnisotropic then
5762
              TexParameteri(glTarget, GL_TEXTURE_MAX_ANISOTROPY_EXT,
5763
                CurrentGLContext.GLStates.MaxTextureAnisotropy)
5764
            else
5765
              TexParameteri(glTarget, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1);
5766
          end;
5767

5768
          TexParameteri(glTarget, GL_TEXTURE_COMPARE_MODE,
5769
            cTextureCompareMode[FLibSampler.CompareMode]);
5770
          TexParameteri(glTarget, GL_TEXTURE_COMPARE_FUNC,
5771
            cGLComparisonFunctionToGLEnum[FLibSampler.CompareFunc]);
5772

5773
          if EXT_texture_sRGB_decode then
5774
          begin
5775
            if FLibSampler.sRGB_Encode then
5776
              TexParameteri(glTarget, GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT)
5777
            else
5778
              TexParameteri(glTarget, GL_TEXTURE_SRGB_DECODE_EXT,
5779
                GL_SKIP_DECODE_EXT);
5780
          end;
5781

5782
          FLibTexture.FLastSampler := FLibSampler;
5783
        end;
5784

5785
      end; // with GL
5786
  end;
5787
end;
5788

5789
procedure TGLShaderUniformTexture.Assign(Source: TPersistent);
5790
var
5791
  LUniform: TGLShaderUniformTexture;
5792
begin
5793
  if Source is TGLShaderUniformTexture then
5794
  begin
5795
    LUniform := TGLShaderUniformTexture(Source);
5796
    LibTextureName := LUniform.LibTextureName;
5797
    LibSamplerName := LUniform.LibSamplerName;
5798
  end;
5799
  inherited;
5800
end;
5801

5802
constructor TGLShaderUniformTexture.Create(AOwner: TPersistent);
5803
begin
5804
  inherited;
5805
  FSwizzling := cDefaultSwizzleVector;
5806
end;
5807

5808
destructor TGLShaderUniformTexture.Destroy;
5809
begin
5810
  LibTextureName := '';
5811
  LibSamplerName := '';
5812
  inherited;
5813
end;
5814

5815
function TGLShaderUniformTexture.GetSamplerName: string;
5816
begin
5817
  if Assigned(FLibSampler) then
5818
    Result := FLibSampler.Name
5819
  else
5820
    Result := rstrNothing;
5821
end;
5822

5823
function TGLShaderUniformTexture.GetTextureName: string;
5824
begin
5825
  if Assigned(FLibTexture) then
5826
    Result := FLibTexture.Name
5827
  else
5828
    Result := rstrNothing;
5829
end;
5830

5831
function TGLShaderUniformTexture.GetTextureSwizzle: TSwizzleVector;
5832
begin
5833
  Result := FSwizzling;
5834
end;
5835

5836
procedure TGLShaderUniformTexture.Loaded;
5837
begin
5838
  SetTextureName(FLibTexureName);
5839
  SetSamplerName(FLibSamplerName);
5840
end;
5841

5842
procedure TGLShaderUniformTexture.Notification(Sender: TObject;
5843
  Operation: TOperation);
5844
begin
5845
  if Operation = opRemove then
5846
  begin
5847
    if Sender = FLibTexture then
5848
      FLibTexture := nil
5849
    else if Sender = FLibSampler then
5850
      FLibSampler := nil;
5851
  end;
5852
end;
5853

5854
procedure TGLShaderUniformTexture.ReadFromFiler(AReader: TReader);
5855
begin
5856
  with AReader do
5857
  begin
5858
    inherited;
5859
    LibTextureName := ReadWideString;
5860
    LibSamplerName := ReadWideString;
5861
    FSwizzling[0] := TGLTextureSwizzle(ReadInteger);
5862
    FSwizzling[1] := TGLTextureSwizzle(ReadInteger);
5863
    FSwizzling[2] := TGLTextureSwizzle(ReadInteger);
5864
    FSwizzling[3] := TGLTextureSwizzle(ReadInteger);
5865
  end;
5866
end;
5867

5868
procedure TGLShaderUniformTexture.SetTextureName(
5869
  const AValue: string);
5870
var
5871
  LTexture: TGLAbstractTexture;
5872
begin
5873
  if csLoading in TGLBaseShaderModel(Owner).GetMaterialLibraryEx.ComponentState
5874
    then
5875
  begin
5876
    FLibTexureName := AValue;
5877
    exit;
5878
  end;
5879

5880
  if Assigned(FLibTexture) then
5881
  begin
5882
    if FLibTexture.Name = AValue then
5883
      exit;
5884
    FLibTexture.UnregisterUser(Self);
5885
    FLibTexture := nil;
5886
  end;
5887

5888
  LTexture :=
5889
    TGLBaseShaderModel(Owner).GetMaterialLibraryEx.Components.GetTextureByName(AValue);
5890

5891
  if Assigned(LTexture) then
5892
  begin
5893
    if LTexture is TGLFrameBufferAttachment then
5894
    begin
5895
      if TGLFrameBufferAttachment(LTexture).OnlyWrite then
5896
      begin
5897
        if IsDesignTime then
5898
          InformationDlg('Can not use write only attachment as texture')
5899
        else
5900
          GLSLogger.LogErrorFmt('Attempt to write only attachment "%s" for uniform "%s"',
5901
            [LTexture.Name, Name]);
5902
        NotifyChange(Self);
5903
        exit;
5904
      end;
5905
    end;
5906
    LTexture.RegisterUser(Self);
5907
    FLibTexture := LTexture;
5908
  end;
5909
  NotifyChange(Self);
5910
end;
5911

5912
procedure TGLShaderUniformTexture.SetSamplerName(const AValue: string);
5913
var
5914
  LSampler: TGLTextureSampler;
5915
begin
5916
  if csLoading in TGLBaseShaderModel(Owner).GetMaterialLibraryEx.ComponentState
5917
    then
5918
  begin
5919
    FLibSamplerName := AValue;
5920
    exit;
5921
  end;
5922

5923
  if Assigned(FLibSampler) then
5924
  begin
5925
    if FLibSampler.Name = AValue then
5926
      exit;
5927
    FLibSampler.UnregisterUser(Self);
5928
    FLibSampler := nil;
5929
  end;
5930

5931
  LSampler :=
5932
    TGLBaseShaderModel(Owner).GetMaterialLibraryEx.Components.GetSamplerByName(AValue);
5933

5934
  if Assigned(LSampler) then
5935
  begin
5936
    LSampler.RegisterUser(Self);
5937
    FLibSampler := LSampler;
5938
  end;
5939

5940
  NotifyChange(Self);
5941
end;
5942

5943
procedure TGLShaderUniformTexture.SetTextureSwizzle(const AValue:
5944
  TSwizzleVector);
5945
begin
5946
  FSwizzling := AValue;
5947
end;
5948

5949
procedure TGLShaderUniformTexture.WriteToFiler(AWriter: TWriter);
5950
begin
5951
  with AWriter do
5952
  begin
5953
    inherited;
5954
    WriteWideString(LibTextureName);
5955
    WriteWideString(LibSamplerName);
5956
    WriteInteger(Integer(FSwizzling[0]));
5957
    WriteInteger(Integer(FSwizzling[1]));
5958
    WriteInteger(Integer(FSwizzling[2]));
5959
    WriteInteger(Integer(FSwizzling[3]));
5960
  end;
5961
end;
5962

5963
{$IFDEF GLS_REGION}{$ENDREGION}{$ENDIF}
5964

5965
{$IFDEF GLS_REGION}{$REGION 'TGLAbstractShaderUniform'}{$ENDIF}
5966

5967
function TGLAbstractShaderUniform.GetFloat: Single;
5968
begin
5969
  FillChar(Result, SizeOf(Result), $00);
5970
end;
5971

5972
function TGLAbstractShaderUniform.GetGLSLSamplerType: TGLSLSamplerType;
5973
begin
5974
  Result := FSamplerType;
5975
end;
5976

5977
function TGLAbstractShaderUniform.GetGLSLType: TGLSLDataType;
5978
begin
5979
  Result := FType;
5980
end;
5981

5982
function TGLAbstractShaderUniform.GetInt: TGLint;
5983
begin
5984
  FillChar(Result, SizeOf(Result), $00);
5985
end;
5986

5987
function TGLAbstractShaderUniform.GetIVec2: TVector2i;
5988
begin
5989
  FillChar(Result, SizeOf(Result), $00);
5990
end;
5991

5992
function TGLAbstractShaderUniform.GetIVec3: TVector3i;
5993
begin
5994
  FillChar(Result, SizeOf(Result), $00);
5995
end;
5996

5997
function TGLAbstractShaderUniform.GetIVec4: TVector4i;
5998
begin
5999
  FillChar(Result, SizeOf(Result), $00);
6000
end;
6001

6002
function TGLAbstractShaderUniform.GetMat2: TMatrix2f;
6003
begin
6004
  FillChar(Result, SizeOf(Result), $00);
6005
end;
6006

6007
function TGLAbstractShaderUniform.GetMat3: TMatrix3f;
6008
begin
6009
  FillChar(Result, SizeOf(Result), $00);
6010
end;
6011

6012
function TGLAbstractShaderUniform.GetMat4: TMatrix4f;
6013
begin
6014
  FillChar(Result, SizeOf(Result), $00);
6015
end;
6016

6017
function TGLAbstractShaderUniform.GetName: string;
6018
begin
6019
  Result := FName;
6020
end;
6021

6022
function TGLAbstractShaderUniform.GetSamplerName: string;
6023
begin
6024
  Result := rstrNothing;
6025
end;
6026

6027
procedure TGLAbstractShaderUniform.Apply(var ARci: TGLRenderContextInfo);
6028
begin
6029
end;
6030

6031
function TGLAbstractShaderUniform.GetAutoSetMethod: string;
6032
begin
6033
  Result := rstrNothing;
6034
end;
6035

6036
function TGLAbstractShaderUniform.GetTextureName: string;
6037
begin
6038
  Result := rstrNothing;
6039
end;
6040

6041
function TGLAbstractShaderUniform.GetTextureSwizzle: TSwizzleVector;
6042
begin
6043
  Result := cDefaultSwizzleVector;
6044
end;
6045

6046
function TGLAbstractShaderUniform.GetUInt: TGLuint;
6047
begin
6048
  FillChar(Result, SizeOf(Result), $00);
6049
end;
6050

6051
function TGLAbstractShaderUniform.GetUVec2: TVector2ui;
6052
begin
6053
  FillChar(Result, SizeOf(Result), $00);
6054
end;
6055

6056
function TGLAbstractShaderUniform.GetUVec3: TVector3ui;
6057
begin
6058
  FillChar(Result, SizeOf(Result), $00);
6059
end;
6060

6061
function TGLAbstractShaderUniform.GetUVec4: TVector4ui;
6062
begin
6063
  FillChar(Result, SizeOf(Result), $00);
6064
end;
6065

6066
function TGLAbstractShaderUniform.GetVec2: TVector2f;
6067
begin
6068
  FillChar(Result, SizeOf(Result), $00);
6069
end;
6070

6071
function TGLAbstractShaderUniform.GetVec3: TVector3f;
6072
begin
6073
  FillChar(Result, SizeOf(Result), $00);
6074
end;
6075

6076
function TGLAbstractShaderUniform.GetVec4: TVector;
6077
begin
6078
  FillChar(Result, SizeOf(Result), $00);
6079
end;
6080

6081
procedure TGLAbstractShaderUniform.ReadFromFiler(AReader: TReader);
6082
begin
6083
end;
6084

6085
procedure TGLAbstractShaderUniform.SetFloat(const Value: TGLFloat);
6086
begin
6087
end;
6088

6089
procedure TGLAbstractShaderUniform.SetFloatArray(const Values: PGLFloat;
6090
  Count: Integer);
6091
begin
6092
end;
6093

6094
procedure TGLAbstractShaderUniform.SetInt(const Value: Integer);
6095
begin
6096
end;
6097

6098
procedure TGLAbstractShaderUniform.SetIntArray(const Values: PGLInt;
6099
  Count: Integer);
6100
begin
6101
end;
6102

6103
procedure TGLAbstractShaderUniform.SetIVec2(const Value: TVector2i);
6104
begin
6105
end;
6106

6107
procedure TGLAbstractShaderUniform.SetIVec3(const Value: TVector3i);
6108
begin
6109
end;
6110

6111
procedure TGLAbstractShaderUniform.SetIVec4(const Value: TVector4i);
6112
begin
6113
end;
6114

6115
procedure TGLAbstractShaderUniform.SetMat2(const Value: TMatrix2f);
6116
begin
6117
end;
6118

6119
procedure TGLAbstractShaderUniform.SetMat3(const Value: TMatrix3f);
6120
begin
6121
end;
6122

6123
procedure TGLAbstractShaderUniform.SetMat4(const Value: TMatrix4f);
6124
begin
6125
end;
6126

6127
procedure TGLAbstractShaderUniform.SetSamplerName(const AValue: string);
6128
begin
6129
end;
6130

6131
procedure TGLAbstractShaderUniform.SetAutoSetMethod(const AValue: string);
6132
begin
6133
end;
6134

6135
procedure TGLAbstractShaderUniform.SetTextureName(const AValue: string);
6136
begin
6137
end;
6138

6139
procedure TGLAbstractShaderUniform.SetTextureSwizzle(const AValue:
6140
  TSwizzleVector);
6141
begin
6142
end;
6143

6144
procedure TGLAbstractShaderUniform.SetUInt(const Value: GLuint);
6145
begin
6146
end;
6147

6148
procedure TGLAbstractShaderUniform.SetUIntArray(const Values: PGLUInt;
6149
  Count: Integer);
6150
begin
6151
end;
6152

6153
procedure TGLAbstractShaderUniform.SetUVec2(const Value: TVector2ui);
6154
begin
6155
end;
6156

6157
procedure TGLAbstractShaderUniform.SetUVec3(const Value: TVector3ui);
6158
begin
6159
end;
6160

6161
procedure TGLAbstractShaderUniform.SetUVec4(const Value: TVector4ui);
6162
begin
6163
end;
6164

6165
procedure TGLAbstractShaderUniform.SetVec2(const Value: TVector2f);
6166
begin
6167
end;
6168

6169
procedure TGLAbstractShaderUniform.SetVec3(const Value: TVector3f);
6170
begin
6171
end;
6172

6173
procedure TGLAbstractShaderUniform.SetVec4(const Value: TVector4f);
6174
begin
6175
end;
6176

6177
procedure TGLAbstractShaderUniform.WriteToFiler(AWriter: TWriter);
6178
begin
6179
end;
6180

6181
{$IFDEF GLS_REGION}{$ENDREGION}{$ENDIF}
6182

6183
{$IFDEF GLS_REGION}{$REGION 'TGLShaderUniform'}{$ENDIF}
6184

6185
function TGLShaderUniform.GetFloat: Single;
6186
begin
6187
  // TODO: Type checking
6188
  GL.GetUniformfv(GetProgram, FLocation, @Result);
6189
end;
6190

6191
function TGLShaderUniform.GetInt: TGLint;
6192
begin
6193
  GL.GetUniformiv(GetProgram, FLocation, @Result);
6194
end;
6195

6196
function TGLShaderUniform.GetIVec2: TVector2i;
6197
begin
6198
  GL.GetUniformiv(GetProgram, FLocation, @Result);
6199
end;
6200

6201
function TGLShaderUniform.GetIVec3: TVector3i;
6202
begin
6203
  GL.GetUniformiv(GetProgram, FLocation, @Result);
6204
end;
6205

6206
function TGLShaderUniform.GetIVec4: TVector4i;
6207
begin
6208
  GL.GetUniformiv(GetProgram, FLocation, @Result);
6209
end;
6210

6211
function TGLShaderUniform.GetMat2: TMatrix2f;
6212
begin
6213
  GL.GetUniformfv(GetProgram, FLocation, @Result);
6214
end;
6215

6216
function TGLShaderUniform.GetMat3: TMatrix3f;
6217
begin
6218
  GL.GetUniformfv(GetProgram, FLocation, @Result);
6219
end;
6220

6221
function TGLShaderUniform.GetMat4: TMatrix4f;
6222
begin
6223
  GL.GetUniformfv(GetProgram, FLocation, @Result);
6224
end;
6225

6226
function TGLShaderUniform.GetProgram: TGLuint;
6227
begin
6228
  Result := TGLBaseShaderModel(Owner).FHandle.Handle;
6229
end;
6230

6231
procedure TGLShaderUniform.Apply(var ARci: TGLRenderContextInfo);
6232
begin
6233
  if Assigned(FAutoSet) then
6234
    FAutoSet(Self, ARci);
6235
end;
6236

6237
procedure TGLShaderUniform.Assign(Source: TPersistent);
6238
var
6239
  LUniform: TGLShaderUniform;
6240
begin
6241
  if Source is TGLShaderUniform then
6242
  begin
6243
    LUniform := TGLShaderUniform(Source);
6244
    FName := LUniform.Name;
6245
    FNameHashCode := LUniform.FNameHashCode;
6246
    FType := LUniform.FType;
6247
    FSamplerType := LUniform.FSamplerType;
6248
    FAutoSet := LUniform.FAutoSet;
6249
  end;
6250
  inherited;
6251
end;
6252

6253
function TGLShaderUniform.GetAutoSetMethod: string;
6254
begin
6255
  Result := GetUniformAutoSetMethodName(FAutoSet);
6256
end;
6257

6258
function TGLShaderUniform.GetUInt: TGLuint;
6259
begin
6260
  GL.GetUniformuiv(GetProgram, FLocation, @Result);
6261
end;
6262

6263
function TGLShaderUniform.GetUVec2: TVector2ui;
6264
begin
6265
  GL.GetUniformuiv(GetProgram, FLocation, @Result);
6266
end;
6267

6268
function TGLShaderUniform.GetUVec3: TVector3ui;
6269
begin
6270
  GL.GetUniformuiv(GetProgram, FLocation, @Result);
6271
end;
6272

6273
function TGLShaderUniform.GetUVec4: TVector4ui;
6274
begin
6275
  GL.GetUniformuiv(GetProgram, FLocation, @Result);
6276
end;
6277

6278
function TGLShaderUniform.GetVec2: TVector2f;
6279
begin
6280
  GL.GetUniformfv(GetProgram, FLocation, @Result);
6281
end;
6282

6283
function TGLShaderUniform.GetVec3: TVector3f;
6284
begin
6285
  GL.GetUniformfv(GetProgram, FLocation, @Result);
6286
end;
6287

6288
function TGLShaderUniform.GetVec4: TVector;
6289
begin
6290
  GL.GetUniformfv(GetProgram, FLocation, @Result);
6291
end;
6292

6293
procedure TGLShaderUniform.PopProgram;
6294
begin
6295
  CurrentGLContext.GLStates.CurrentProgram := FStoreProgram;
6296
end;
6297

6298
procedure TGLShaderUniform.PushProgram;
6299
begin
6300
  with CurrentGLContext.GLStates do
6301
  begin
6302
    FStoreProgram := CurrentProgram;
6303
    CurrentProgram := GetProgram;
6304
  end;
6305
end;
6306

6307
procedure TGLShaderUniform.ReadFromFiler(AReader: TReader);
6308
begin
6309
  with AReader do
6310
  begin
6311
    FName := ReadWideString;
6312
    FNameHashCode := ComputeNameHashKey(FName);
6313
    FType := TGLSLDataType(ReadInteger);
6314
    FSamplerType := TGLSLSamplerType(ReadInteger);
6315
    SetAutoSetMethod(ReadWideString);
6316
  end;
6317
end;
6318

6319
procedure TGLShaderUniform.SetFloat(const Value: TGLFloat);
6320
begin
6321
  PushProgram;
6322
  GL.Uniform1f(FLocation, Value);
6323
  PopProgram;
6324
end;
6325

6326
procedure TGLShaderUniform.SetFloatArray(const Values: PGLFloat;
6327
  Count: Integer);
6328
begin
6329
  PushProgram;
6330
  GL.Uniform1fv(FLocation, Count, Values);
6331
  PopProgram;
6332
end;
6333

6334
procedure TGLShaderUniform.SetInt(const Value: Integer);
6335
begin
6336
  PushProgram;
6337
  GL.Uniform1i(FLocation, Value);
6338
  PopProgram;
6339
end;
6340

6341
procedure TGLShaderUniform.SetIntArray(const Values: PGLInt; Count: Integer);
6342
begin
6343
  PushProgram;
6344
  GL.Uniform1iv(FLocation, Count, Values);
6345
  PopProgram;
6346
end;
6347

6348
procedure TGLShaderUniform.SetIVec2(const Value: TVector2i);
6349
begin
6350
  PushProgram;
6351
  GL.Uniform2i(FLocation, Value.V[0], Value.V[1]);
6352
  PopProgram;
6353
end;
6354

6355
procedure TGLShaderUniform.SetIVec3(const Value: TVector3i);
6356
begin
6357
  PushProgram;
6358
  GL.Uniform3i(FLocation, Value.V[0], Value.V[1], Value.V[2]);
6359
  PopProgram;
6360
end;
6361

6362
procedure TGLShaderUniform.SetIVec4(const Value: TVector4i);
6363
begin
6364
  PushProgram;
6365
  GL.Uniform4i(FLocation, Value.V[0], Value.V[1], Value.V[2], Value.V[3]);
6366
  PopProgram;
6367
end;
6368

6369
procedure TGLShaderUniform.SetMat2(const Value: TMatrix2f);
6370
begin
6371
  PushProgram;
6372
  GL.UniformMatrix2fv(FLocation, 1, False, @Value);
6373
  PopProgram;
6374
end;
6375

6376
procedure TGLShaderUniform.SetMat3(const Value: TMatrix3f);
6377
begin
6378
  PushProgram;
6379
  GL.UniformMatrix2fv(FLocation, 1, False, @Value);
6380
  PopProgram;
6381
end;
6382

6383
procedure TGLShaderUniform.SetMat4(const Value: TMatrix4f);
6384
begin
6385
  PushProgram;
6386
  GL.UniformMatrix4fv(FLocation, 1, False, @Value);
6387
  PopProgram;
6388
end;
6389

6390
procedure TGLShaderUniform.SetAutoSetMethod(const AValue: string);
6391
begin
6392
  FAutoSet := GetUniformAutoSetMethod(AValue);
6393
end;
6394

6395
procedure TGLShaderUniform.SetUInt(const Value: GLuint);
6396
begin
6397
  PushProgram;
6398
  GL.Uniform1ui(FLocation, Value);
6399
  PopProgram;
6400
end;
6401

6402
procedure TGLShaderUniform.SetUIntArray(const Values: PGLUInt; Count: Integer);
6403
begin
6404
  PushProgram;
6405
  GL.Uniform1uiv(FLocation, Count, Values);
6406
  PopProgram;
6407
end;
6408

6409
procedure TGLShaderUniform.SetUVec2(const Value: TVector2ui);
6410
begin
6411
  PushProgram;
6412
  GL.Uniform2ui(FLocation, Value.V[0], Value.V[1]);
6413
  PopProgram;
6414
end;
6415

6416
procedure TGLShaderUniform.SetUVec3(const Value: TVector3ui);
6417
begin
6418
  PushProgram;
6419
  GL.Uniform3ui(FLocation, Value.V[0], Value.V[1], Value.V[2]);
6420
  PopProgram;
6421
end;
6422

6423
procedure TGLShaderUniform.SetUVec4(const Value: TVector4ui);
6424
begin
6425
  PushProgram;
6426
  GL.Uniform4ui(FLocation, Value.V[0], Value.V[1], Value.V[2], Value.V[3]);
6427
  PopProgram;
6428
end;
6429

6430
procedure TGLShaderUniform.SetVec2(const Value: TVector2f);
6431
begin
6432
  PushProgram;
6433
  GL.Uniform2f(FLocation, Value.V[0], Value.V[1]);
6434
  PopProgram;
6435
end;
6436

6437
procedure TGLShaderUniform.SetVec3(const Value: TVector3f);
6438
begin
6439
  PushProgram;
6440
  GL.Uniform3f(FLocation, Value.V[0], Value.V[1], Value.V[2]);
6441
  PopProgram;
6442
end;
6443

6444
procedure TGLShaderUniform.SetVec4(const Value: TVector4f);
6445
begin
6446
  PushProgram;
6447
  GL.Uniform4f(FLocation, Value.V[0], Value.V[1], Value.V[2], Value.V[3]);
6448
  PopProgram;
6449
end;
6450

6451
procedure TGLShaderUniform.WriteToFiler(AWriter: TWriter);
6452
begin
6453
  with AWriter do
6454
  begin
6455
    WriteWideString(FName);
6456
    WriteInteger(Integer(FType));
6457
    WriteInteger(Integer(FSamplerType));
6458
    WriteWideString(GetAutoSetMethod);
6459
  end;
6460
end;
6461

6462
{$IFDEF GLS_REGION}{$ENDREGION}{$ENDIF}
6463

6464
{$IFDEF GLS_REGION}{$REGION 'TGLShaderUniformDSA'}{$ENDIF}
6465

6466
procedure TGLShaderUniformDSA.SetFloat(const Value: TGLFloat);
6467
begin
6468
  GL.ProgramUniform1f(GetProgram, FLocation, Value);
6469
end;
6470

6471
procedure TGLShaderUniformDSA.SetFloatArray(const Values: PGLFloat;
6472
  Count: Integer);
6473
begin
6474
  GL.ProgramUniform1fv(GetProgram, FLocation, Count, Values);
6475
end;
6476

6477
procedure TGLShaderUniformDSA.SetInt(const Value: Integer);
6478
begin
6479
  GL.ProgramUniform1i(GetProgram, FLocation, Value);
6480
end;
6481

6482
procedure TGLShaderUniformDSA.SetIntArray(const Values: PGLInt; Count: Integer);
6483
begin
6484
  GL.ProgramUniform1iv(GetProgram, FLocation, Count, Values);
6485
end;
6486

6487
procedure TGLShaderUniformDSA.SetIVec2(const Value: TVector2i);
6488
begin
6489
  GL.ProgramUniform2i(GetProgram, FLocation, Value.V[0], Value.V[1]);
6490
end;
6491

6492
procedure TGLShaderUniformDSA.SetIVec3(const Value: TVector3i);
6493
begin
6494
  GL.ProgramUniform3i(GetProgram, FLocation, Value.V[0], Value.V[1], Value.V[2]);
6495
end;
6496

6497
procedure TGLShaderUniformDSA.SetIVec4(const Value: TVector4i);
6498
begin
6499
  GL.ProgramUniform4i(GetProgram, FLocation, Value.V[0], Value.V[1], Value.V[2],
6500
    Value.V[3]);
6501
end;
6502

6503
procedure TGLShaderUniformDSA.SetMat2(const Value: TMatrix2f);
6504
begin
6505
  GL.ProgramUniformMatrix2fv(GetProgram, FLocation, 1, False, @Value);
6506
end;
6507

6508
procedure TGLShaderUniformDSA.SetMat3(const Value: TMatrix3f);
6509
begin
6510
  GL.ProgramUniformMatrix3fv(GetProgram, FLocation, 1, False, @Value);
6511
end;
6512

6513
procedure TGLShaderUniformDSA.SetMat4(const Value: TMatrix4f);
6514
begin
6515
  GL.ProgramUniformMatrix4fv(GetProgram, FLocation, 1, False, @Value);
6516
end;
6517

6518
procedure TGLShaderUniformDSA.SetUInt(const Value: GLuint);
6519
begin
6520
  GL.ProgramUniform1ui(GetProgram, FLocation, Value);
6521
end;
6522

6523
procedure TGLShaderUniformDSA.SetUIntArray(const Values: PGLUInt;
6524
  Count: Integer);
6525
begin
6526
  GL.ProgramUniform1uiv(GetProgram, FLocation, Count, Values);
6527
end;
6528

6529
procedure TGLShaderUniformDSA.SetUVec2(const Value: TVector2ui);
6530
begin
6531
  GL.ProgramUniform2ui(GetProgram, FLocation, Value.V[0], Value.V[1]);
6532
end;
6533

6534
procedure TGLShaderUniformDSA.SetUVec3(const Value: TVector3ui);
6535
begin
6536
  GL.ProgramUniform3ui(GetProgram, FLocation, Value.V[0], Value.V[1], Value.V[2]);
6537
end;
6538

6539
procedure TGLShaderUniformDSA.SetUVec4(const Value: TVector4ui);
6540
begin
6541
  GL.ProgramUniform4ui(GetProgram, FLocation, Value.V[0], Value.V[1], Value.V[2],
6542
    Value.V[3]);
6543
end;
6544

6545
procedure TGLShaderUniformDSA.SetVec2(const Value: TVector2f);
6546
begin
6547
  GL.ProgramUniform2f(GetProgram, FLocation, Value.V[0], Value.V[1]);
6548
end;
6549

6550
procedure TGLShaderUniformDSA.SetVec3(const Value: TVector3f);
6551
begin
6552
  GL.ProgramUniform3f(GetProgram, FLocation, Value.V[0], Value.V[1], Value.V[2]);
6553
end;
6554

6555
procedure TGLShaderUniformDSA.SetVec4(const Value: TVector4f);
6556
begin
6557
  GL.ProgramUniform4f(GetProgram, FLocation, Value.V[0], Value.V[1], Value.V[2],
6558
    Value.V[3]);
6559
end;
6560

6561
{$IFDEF GLS_REGION}{$ENDREGION}{$ENDIF}
6562

6563
{$IFDEF GLS_REGION}{$REGION 'TGLTextureSwizzling'}{$ENDIF}
6564

6565
procedure TGLTextureSwizzling.Assign(Source: TPersistent);
6566
var
6567
  LSwizzling: TGLTextureSwizzling;
6568
begin
6569
  if Source is TGLTextureSwizzling then
6570
  begin
6571
    LSwizzling := TGLTextureSwizzling(Source);
6572
    FSwizzles[0] := LSwizzling.FSwizzles[0];
6573
    FSwizzles[1] := LSwizzling.FSwizzles[1];
6574
    FSwizzles[2] := LSwizzling.FSwizzles[2];
6575
    FSwizzles[3] := LSwizzling.FSwizzles[3];
6576
  end;
6577
  inherited;
6578
end;
6579

6580
constructor TGLTextureSwizzling.Create(AOwner: TPersistent);
6581
begin
6582
  inherited;
6583
  FSwizzles := cDefaultSwizzleVector;
6584
end;
6585

6586
function TGLTextureSwizzling.GetSwizzle(AIndex: Integer): TGLTextureSwizzle;
6587
begin
6588
  Result := FSwizzles[AIndex];
6589
end;
6590

6591
procedure TGLTextureSwizzling.ReadFromFiler(AReader: TReader);
6592
begin
6593
  with AReader do
6594
  begin
6595
    ReadInteger;
6596
    FSwizzles[0] := TGLTextureSwizzle(ReadInteger);
6597
    FSwizzles[1] := TGLTextureSwizzle(ReadInteger);
6598
    FSwizzles[2] := TGLTextureSwizzle(ReadInteger);
6599
    FSwizzles[3] := TGLTextureSwizzle(ReadInteger);
6600
  end;
6601
end;
6602

6603
procedure TGLTextureSwizzling.SetSwizzle(AIndex: Integer;
6604
  AValue: TGLTextureSwizzle);
6605
begin
6606
  if AValue <> FSwizzles[AIndex] then
6607
  begin
6608
    FSwizzles[AIndex] := AValue;
6609
    NotifyChange(Self);
6610
  end;
6611
end;
6612

6613
function TGLTextureSwizzling.StoreSwizzle(AIndex: Integer): Boolean;
6614
begin
6615
  Result := (FSwizzles[AIndex] <> cDefaultSwizzleVector[AIndex]);
6616
end;
6617

6618
procedure TGLTextureSwizzling.WriteToFiler(AWriter: TWriter);
6619
begin
6620
  with AWriter do
6621
  begin
6622
    WriteInteger(0);
6623
    WriteInteger(Integer(FSwizzles[0]));
6624
    WriteInteger(Integer(FSwizzles[1]));
6625
    WriteInteger(Integer(FSwizzles[2]));
6626
    WriteInteger(Integer(FSwizzles[3]));
6627
  end;
6628
end;
6629

6630
{$IFDEF GLS_REGION}{$ENDREGION}{$ENDIF}
6631

6632
{$IFDEF GLS_REGION}{$REGION 'TGLFrameBufferAttachment'}{$ENDIF}
6633

6634
procedure TGLFrameBufferAttachment.Apply(var ARci: TGLRenderContextInfo);
6635
begin
6636
  if FIsValid and not FOnlyWrite then
6637
  begin
6638
    // Just bind
6639
    with ARci.GLStates do
6640
    begin
6641
      ActiveTextureEnabled[FHandle.Target] := True;
6642
      TextureBinding[ActiveTexture, FHandle.Target] := FHandle.Handle;
6643
    end;
6644
  end
6645
  else
6646
    ARci.GLStates.TextureBinding[ARci.GLStates.ActiveTexture, FHandle.Target] :=
6647
      0;
6648
end;
6649

6650
procedure TGLFrameBufferAttachment.Assign(Source: TPersistent);
6651
var
6652
  LAttachment: TGLFrameBufferAttachment;
6653
begin
6654
  if Source is TGLFrameBufferAttachment then
6655
  begin
6656
    LAttachment := TGLFrameBufferAttachment(Source);
6657
    FLayered := LAttachment.Layered;
6658
    FCubeMap := LAttachment.CubeMap;
6659
    FSamples := LAttachment.Samples;
6660
    FOnlyWrite := LAttachment.OnlyWrite;
6661
    FFixedSamplesLocation := LAttachment.FixedSamplesLocation;
6662
    FWidth := LAttachment.InternalWidth;
6663
    FHeight := LAttachment.InternalHeight;
6664
    FDepth := LAttachment.InternalDepth;
6665
    FInternalFormat := LAttachment.InternalFormat;
6666
    NotifyChange(Self);
6667
  end;
6668
  inherited;
6669
end;
6670

6671
constructor TGLFrameBufferAttachment.Create(AOwner: TGLXCollection);
6672
begin
6673
  inherited;
6674
  FDefferedInit := False;
6675
  FHandle := TGLTextureHandle.Create;
6676
  FHandle.OnPrapare := DoOnPrepare;
6677
  FRenderBufferHandle := TGLRenderbufferHandle.Create;
6678
  FRenderBufferHandle.OnPrapare := DoOnPrepare;
6679
  FInternalFormat := tfRGBA8;
6680
  FWidth := 256;
6681
  FHeight := 256;
6682
  FDepth := 0;
6683
  FSamples := -1;
6684
  FLayered := False;
6685
  FCubeMap := False;
6686
  FOnlyWrite := False;
6687
  FFixedSamplesLocation := False;
6688
  Name := TGLMatLibComponents(AOwner).MakeUniqueName('Attachment');
6689
end;
6690

6691
destructor TGLFrameBufferAttachment.Destroy;
6692
begin
6693
  FHandle.Destroy;
6694
  FRenderBufferHandle.Destroy;
6695
  inherited;
6696
end;
6697

6698
procedure TGLFrameBufferAttachment.DoOnPrepare(Sender: TGLContext);
6699
var
6700
  LTarget: TGLTextureTarget;
6701
  w, h, d, s, Level, MaxLevel: Integer;
6702
  glTarget, glFormat, glFace: TGLEnum;
6703
begin
6704
  if IsDesignTime and FDefferedInit then
6705
    exit;
6706

6707
  FHandle.AllocateHandle;
6708
  FRenderBufferHandle.AllocateHandle;
6709
  if not (FHandle.IsDataNeedUpdate or FRenderBufferHandle.IsDataNeedUpdate) then
6710
    exit;
6711

6712
  // Target
6713

6714
  if FSamples < 0 then
6715
  begin
6716
    LTarget := ttTexture2D;
6717
    if FHeight = 1 then
6718
      LTarget := ttTexture1D;
6719
    if FCubeMap then
6720
      LTarget := ttTextureCube;
6721
    if FDepth > 0 then
6722
      LTarget := ttTexture3D;
6723
    if FLayered then
6724
    begin
6725
      if FDepth < 2 then
6726
        LTarget := ttTexture1DArray
6727
      else
6728
        LTarget := ttTexture2DArray;
6729
      if FCubeMap then
6730
        LTarget := ttTextureCubeArray;
6731
    end;
6732
  end
6733
  else
6734
  begin
6735
    if FDepth > 0 then
6736
      LTarget := ttTexture2DMultisampleArray
6737
    else
6738
      LTarget := ttTexture2DMultisample;
6739
  end;
6740

6741
  // Check target support
6742
  if FOnlyWrite and (LTarget = ttTexture2DMultisample)
6743
    and not Sender.GL.EXT_framebuffer_multisample then
6744
  begin
6745
    FIsValid := False;
6746
    exit;
6747
  end;
6748
  if not IsTargetSupported(LTarget) then
6749
  begin
6750
    FIsValid := False;
6751
    exit;
6752
  end;
6753

6754
  // Adjust dimension
6755
  w := FWidth;
6756
  h := FHeight;
6757
  d := FDepth;
6758
  s := FSamples;
6759
  if FCubeMap then
6760
  begin
6761
    if w > Integer(Sender.GLStates.MaxCubeTextureSize) then
6762
      w := Sender.GLStates.MaxCubeTextureSize;
6763
    h := w;
6764
    if FLayered then
6765
    begin
6766
      if d < 6 then
6767
        d := 6
6768
      else if (d mod 6) > 0 then
6769
        d := 6 * (d div 6 + 1);
6770
    end;
6771
  end
6772
  else if w > Integer(Sender.GLStates.MaxTextureSize) then
6773
    w := Sender.GLStates.MaxTextureSize;
6774
  if h > Integer(Sender.GLStates.MaxTextureSize) then
6775
    h := Sender.GLStates.MaxTextureSize;
6776
  if FLayered then
6777
  begin
6778
    if d > Integer(Sender.GLStates.MaxArrayTextureSize) then
6779
      d := Sender.GLStates.MaxArrayTextureSize;
6780
  end
6781
  else if d > Integer(Sender.GLStates.Max3DTextureSize) then
6782
    d := Sender.GLStates.Max3DTextureSize;
6783
  if (s > -1) and (s > Integer(Sender.GLStates.MaxSamples)) then
6784
    s := Sender.GLStates.MaxSamples;
6785

6786
  glTarget := DecodeGLTextureTarget(LTarget);
6787

6788
  if (FHandle.Target <> LTarget)
6789
    and (FHandle.Target <> ttNoShape) then
6790
  begin
6791
    FHandle.DestroyHandle;
6792
    FHandle.AllocateHandle;
6793
  end;
6794
  FHandle.Target := LTarget;
6795

6796
  glFormat := InternalFormatToOpenGLFormat(FInternalFormat);
6797

6798
  if FOnlyWrite and ((LTarget = ttTexture2D) or (LTarget =
6799
    ttTexture2DMultisample))
6800
    and FRenderBufferHandle.IsSupported then
6801
  begin
6802
    if LTarget = ttTexture2D then
6803
      FRenderBufferHandle.SetStorage(glFormat, w, h)
6804
    else
6805
      FRenderBufferHandle.SetStorageMultisample(glFormat, s, w, h);
6806
  end
6807
  else
6808
    with Sender do
6809
    begin
6810
      GLStates.ActiveTextureEnabled[FHandle.Target] := True;
6811
      GLStates.TextureBinding[GLStates.ActiveTexture, FHandle.Target] :=
6812
        FHandle.Handle;
6813
      MaxLevel := CalcTextureLevelNumber(LTarget, w, h, d);
6814

6815
      case glTarget of
6816

6817
        GL_TEXTURE_1D:
6818
          for Level := 0 to MaxLevel - 1 do
6819
          begin
6820
            GL.TexImage1D(glTarget, Level, glFormat, w, 0, GL_RGBA,
6821
              GL_UNSIGNED_BYTE, nil);
6822
            Div2(w);
6823
          end;
6824

6825
        GL_TEXTURE_2D:
6826
          for Level := 0 to MaxLevel - 1 do
6827
          begin
6828
            GL.TexImage2D(glTarget, Level, glFormat, w, h, 0, GL_RGBA,
6829
              GL_UNSIGNED_BYTE, nil);
6830
            Div2(w);
6831
            Div2(h);
6832
          end;
6833

6834
        GL_TEXTURE_RECTANGLE:
6835
          begin
6836
            GL.TexImage2D(glTarget, 0, glFormat, w, h, 0, GL_RGBA,
6837
              GL_UNSIGNED_BYTE, nil);
6838
          end;
6839

6840
        GL_TEXTURE_3D:
6841
          for Level := 0 to MaxLevel - 1 do
6842
          begin
6843
            GL.TexImage3D(glTarget, Level, glFormat, w, h, d, 0, GL_RGBA,
6844
              GL_UNSIGNED_BYTE, nil);
6845
            Div2(w);
6846
            Div2(h);
6847
            Div2(d);
6848
          end;
6849

6850
        GL_TEXTURE_CUBE_MAP:
6851
          for Level := 0 to MaxLevel - 1 do
6852
          begin
6853
            for glFace := GL_TEXTURE_CUBE_MAP_POSITIVE_X to
6854
              GL_TEXTURE_CUBE_MAP_NEGATIVE_Z do
6855
              GL.TexImage2D(glFace, Level, glFormat, w, w, 0, GL_RGBA,
6856
                GL_UNSIGNED_BYTE, nil);
6857
            Div2(w);
6858
          end;
6859

6860
        GL_TEXTURE_1D_ARRAY:
6861
          for Level := 0 to MaxLevel - 1 do
6862
          begin
6863
            GL.TexImage2D(glTarget, Level, glFormat, w, h, 0, GL_RGBA,
6864
              GL_UNSIGNED_BYTE, nil);
6865
            Div2(w);
6866
          end;
6867

6868
        GL_TEXTURE_2D_ARRAY:
6869
          for Level := 0 to MaxLevel - 1 do
6870
          begin
6871
            GL.TexImage3D(glTarget, Level, glFormat, w, h, d, 0, GL_RGBA,
6872
              GL_UNSIGNED_BYTE, nil);
6873
            Div2(w);
6874
            Div2(h);
6875
          end;
6876

6877
        GL_TEXTURE_CUBE_MAP_ARRAY:
6878
          for Level := 0 to MaxLevel - 1 do
6879
          begin
6880
            GL.TexImage3D(glTarget, Level, glFormat, w, w, d, 0, GL_RGBA,
6881
              GL_UNSIGNED_BYTE, nil);
6882
            Div2(w);
6883
          end;
6884
      end; // of case
6885

6886
      GLStates.ActiveTextureEnabled[FHandle.Target] := False;
6887
      FOnlyWrite := False;
6888
    end; // of texture
6889

6890
  if GL.GetError <> GL_NO_ERROR then
6891
  begin
6892
    GL.ClearError;
6893
    GLSLogger.LogErrorFmt('Unable to create attachment "%s"', [Self.Name]);
6894
    exit;
6895
  end
6896
  else
6897
    FIsValid := True;
6898

6899
  FHandle.NotifyDataUpdated;
6900
  FRenderBufferHandle.NotifyDataUpdated;
6901
end;
6902

6903
class function TGLFrameBufferAttachment.FriendlyName: string;
6904
begin
6905
  Result := 'Framebuffer Attachment';
6906
end;
6907

6908
procedure TGLFrameBufferAttachment.NotifyChange(Sender: TObject);
6909
begin
6910
  FHandle.NotifyChangesOfData;
6911
  FRenderBufferHandle.NotifyChangesOfData;
6912
  inherited;
6913
end;
6914

6915
procedure TGLFrameBufferAttachment.ReadFromFiler(AReader: TReader);
6916
var
6917
  archiveVersion: Integer;
6918
begin
6919
  with AReader do
6920
  begin
6921
    archiveVersion := ReadInteger;
6922
    if archiveVersion = 0 then
6923
    begin
6924
      Name := ReadWideString;
6925
      FDefferedInit := ReadBoolean;
6926
      FLayered := ReadBoolean;
6927
      FCubeMap := ReadBoolean;
6928
      FSamples := ReadInteger;
6929
      FOnlyWrite := ReadBoolean;
6930
      FFixedSamplesLocation := ReadBoolean;
6931
      FWidth := ReadInteger;
6932
      FHeight := ReadInteger;
6933
      FDepth := ReadInteger;
6934
      FInternalFormat := TGLInternalFormat(ReadInteger);
6935
    end
6936
    else
6937
      RaiseFilerException(archiveVersion);
6938
  end;
6939
end;
6940

6941
procedure TGLFrameBufferAttachment.SetCubeMap(AValue: Boolean);
6942
begin
6943
  if FCubeMap <> AValue then
6944
  begin
6945
    FCubeMap := AValue;
6946
    NotifyChange(Self);
6947
  end;
6948
end;
6949

6950
procedure TGLFrameBufferAttachment.SetDepth(AValue: Integer);
6951
begin
6952
  if FDepth < 0 then
6953
    FDepth := 0
6954
  else if FDepth > 256 then
6955
    FDepth := 256;
6956
  if FDepth <> AValue then
6957
  begin
6958
    FDepth := AValue;
6959
    NotifyChange(Self);
6960
  end;
6961
end;
6962

6963
procedure TGLFrameBufferAttachment.SetFixedSamplesLocation(AValue: Boolean);
6964
begin
6965
  if FFixedSamplesLocation <> AValue then
6966
  begin
6967
    FFixedSamplesLocation := AValue;
6968
    NotifyChange(Self);
6969
  end;
6970
end;
6971

6972
procedure TGLFrameBufferAttachment.SetHeight(AValue: Integer);
6973
begin
6974
  if FHeight < 1 then
6975
    FHeight := 1
6976
  else if FHeight > 8192 then
6977
    FHeight := 8192;
6978
  if FHeight <> AValue then
6979
  begin
6980
    FHeight := AValue;
6981
    NotifyChange(Self);
6982
  end;
6983
end;
6984

6985
procedure TGLFrameBufferAttachment.SetInternalFormat(
6986
  const AValue: TGLInternalFormat);
6987
begin
6988
  if FInternalFormat <> AValue then
6989
  begin
6990
    FInternalFormat := AValue;
6991
    NotifyChange(Self);
6992
  end;
6993
end;
6994

6995
procedure TGLFrameBufferAttachment.SetLayered(AValue: Boolean);
6996
begin
6997
  if FLayered <> AValue then
6998
  begin
6999
    FLayered := AValue;
7000
    NotifyChange(Self);
7001
  end;
7002
end;
7003

7004
procedure TGLFrameBufferAttachment.SetOnlyWrite(AValue: Boolean);
7005
begin
7006
  if FOnlyWrite <> AValue then
7007
  begin
7008
    if AValue
7009
      and ((FDepth > 0) or FLayered or FFixedSamplesLocation or FCubeMap) then
7010
      exit;
7011
    FOnlyWrite := AValue;
7012
    NotifyChange(Self);
7013
  end;
7014
end;
7015

7016
procedure TGLFrameBufferAttachment.SetSamples(AValue: Integer);
7017
begin
7018
  if AValue < -1 then
7019
    AValue := -1;
7020
  if FSamples <> AValue then
7021
  begin
7022
    FSamples := AValue;
7023
    NotifyChange(Self);
7024
  end;
7025
end;
7026

7027
procedure TGLFrameBufferAttachment.SetWidth(AValue: Integer);
7028
begin
7029
  if FWidth < 1 then
7030
    FWidth := 1
7031
  else if FWidth > 8192 then
7032
    FWidth := 8192;
7033
  if FWidth <> AValue then
7034
  begin
7035
    FWidth := AValue;
7036
    NotifyChange(Self);
7037
  end;
7038
end;
7039

7040
procedure TGLFrameBufferAttachment.UnApply(var ARci: TGLRenderContextInfo);
7041
begin
7042
  ARci.GLStates.ActiveTextureEnabled[FHandle.Target] := False;
7043
end;
7044

7045
procedure TGLFrameBufferAttachment.WriteToFiler(AWriter: TWriter);
7046
begin
7047
  with AWriter do
7048
  begin
7049
    WriteInteger(0); // archive version
7050
    WriteWideString(Name);
7051
    WriteBoolean(FDefferedInit);
7052
    WriteBoolean(FLayered);
7053
    WriteBoolean(FCubeMap);
7054
    WriteInteger(FSamples);
7055
    WriteBoolean(FOnlyWrite);
7056
    WriteBoolean(FFixedSamplesLocation);
7057
    WriteInteger(FWidth);
7058
    WriteInteger(FHeight);
7059
    WriteInteger(FDepth);
7060
    WriteInteger(Integer(FInternalFormat));
7061
  end;
7062
end;
7063

7064
{$IFDEF GLS_REGION}{$ENDREGION}{$ENDIF}
7065

7066
{$IFDEF GLS_REGION}{$REGION 'TStandartUniformAutoSetExecutor'}{$ENDIF}
7067

7068
constructor TStandartUniformAutoSetExecutor.Create;
7069
begin
7070
  RegisterUniformAutoSetMethod('Camera world position', GLSLType4F,
7071
    SetCameraPosition);
7072
  RegisterUniformAutoSetMethod('LightSource[0] world position', GLSLType4F,
7073
    SetLightSource0Position);
7074
  RegisterUniformAutoSetMethod('World (model) matrix', GLSLTypeMat4F,
7075
    SetModelMatrix);
7076
  RegisterUniformAutoSetMethod('WorldView matrix', GLSLTypeMat4F,
7077
    SetModelViewMatrix);
7078
  RegisterUniformAutoSetMethod('WorldNormal matrix', GLSLTypeMat3F,
7079
    SetNormalModelMatrix);
7080
  RegisterUniformAutoSetMethod('Inverse World matrix', GLSLTypeMat4F,
7081
    SetInvModelMatrix);
7082
  RegisterUniformAutoSetMethod('View matrix', GLSLTypeMat4F, SetViewMatrix);
7083
  RegisterUniformAutoSetMethod('Inverse WorldView matrix', GLSLTypeMat4F,
7084
    SetInvModelViewMatrix);
7085
  RegisterUniformAutoSetMethod('Projection matrix', GLSLTypeMat4F,
7086
    SetProjectionMatrix);
7087
  RegisterUniformAutoSetMethod('ViewProjection matrix', GLSLTypeMat4F,
7088
    SetViewProjectionMatrix);
7089
  RegisterUniformAutoSetMethod('WorldViewProjection matrix', GLSLTypeMat4F,
7090
    SetWorldViewProjectionMatrix);
7091
  RegisterUniformAutoSetMethod('Material front face emission', GLSLType4F,
7092
    SetMaterialFrontEmission);
7093
  RegisterUniformAutoSetMethod('Material front face ambient', GLSLType4F,
7094
    SetMaterialFrontAmbient);
7095
  RegisterUniformAutoSetMethod('Material front face diffuse', GLSLType4F,
7096
    SetMaterialFrontDiffuse);
7097
  RegisterUniformAutoSetMethod('Material front face specular', GLSLType4F,
7098
    SetMaterialFrontSpecular);
7099
  RegisterUniformAutoSetMethod('Material front face shininess', GLSLType1F,
7100
    SetMaterialFrontShininess);
7101
  RegisterUniformAutoSetMethod('Material back face emission', GLSLType4F,
7102
    SetMaterialBackEmission);
7103
  RegisterUniformAutoSetMethod('Material back face ambient', GLSLType4F,
7104
    SetMaterialBackAmbient);
7105
  RegisterUniformAutoSetMethod('Material back face diffuse', GLSLType4F,
7106
    SetMaterialBackDiffuse);
7107
  RegisterUniformAutoSetMethod('Material back face specular', GLSLType4F,
7108
    SetMaterialBackSpecular);
7109
  RegisterUniformAutoSetMethod('Material back face shininess', GLSLType1F,
7110
    SetMaterialBackShininess)
7111
end;
7112

7113
procedure TStandartUniformAutoSetExecutor.SetCameraPosition(Sender:
7114
  IShaderParameter; var ARci: TGLRenderContextInfo);
7115
begin
7116
  Sender.vec4 := ARci.cameraPosition;
7117
end;
7118

7119
procedure TStandartUniformAutoSetExecutor.SetInvModelMatrix(Sender:
7120
  IShaderParameter; var ARci: TGLRenderContextInfo);
7121
begin
7122
  Sender.mat4 := ARci.PipelineTransformation.InvModelMatrix;
7123
end;
7124

7125
procedure TStandartUniformAutoSetExecutor.SetInvModelViewMatrix(Sender:
7126
  IShaderParameter; var ARci: TGLRenderContextInfo);
7127
begin
7128
  Sender.mat4 := ARci.PipelineTransformation.InvModelViewMatrix;
7129
end;
7130

7131
procedure TStandartUniformAutoSetExecutor.SetLightSource0Position(Sender:
7132
  IShaderParameter; var ARci: TGLRenderContextInfo);
7133
begin
7134
  Sender.vec4 := ARci.GLStates.LightPosition[0];
7135
end;
7136

7137
procedure TStandartUniformAutoSetExecutor.SetMaterialBackAmbient(Sender:
7138
  IShaderParameter; var ARci: TGLRenderContextInfo);
7139
begin
7140
  Sender.vec4 := ARci.GLStates.MaterialAmbient[cmBack];
7141
end;
7142

7143
procedure TStandartUniformAutoSetExecutor.SetMaterialBackDiffuse(Sender:
7144
  IShaderParameter; var ARci: TGLRenderContextInfo);
7145
begin
7146
  Sender.vec4 := ARci.GLStates.MaterialDiffuse[cmBack];
7147
end;
7148

7149
procedure TStandartUniformAutoSetExecutor.SetMaterialBackEmission(Sender:
7150
  IShaderParameter; var ARci: TGLRenderContextInfo);
7151
begin
7152
  Sender.vec4 := ARci.GLStates.MaterialEmission[cmBack];
7153
end;
7154

7155
procedure TStandartUniformAutoSetExecutor.SetMaterialBackShininess(Sender:
7156
  IShaderParameter; var ARci: TGLRenderContextInfo);
7157
begin
7158
  Sender.float := ARci.GLStates.MaterialShininess[cmBack];
7159
end;
7160

7161
procedure TStandartUniformAutoSetExecutor.SetMaterialBackSpecular(Sender:
7162
  IShaderParameter; var ARci: TGLRenderContextInfo);
7163
begin
7164
  Sender.vec4 := ARci.GLStates.MaterialSpecular[cmBack];
7165
end;
7166

7167
procedure TStandartUniformAutoSetExecutor.SetMaterialFrontAmbient(Sender:
7168
  IShaderParameter; var ARci: TGLRenderContextInfo);
7169
begin
7170
  Sender.vec4 := ARci.GLStates.MaterialAmbient[cmFront];
7171
end;
7172

7173
procedure TStandartUniformAutoSetExecutor.SetMaterialFrontDiffuse(Sender:
7174
  IShaderParameter; var ARci: TGLRenderContextInfo);
7175
begin
7176
  Sender.vec4 := ARci.GLStates.MaterialDiffuse[cmFront];
7177
end;
7178

7179
procedure TStandartUniformAutoSetExecutor.SetMaterialFrontEmission(Sender:
7180
  IShaderParameter; var ARci: TGLRenderContextInfo);
7181
begin
7182
  Sender.vec4 := ARci.GLStates.MaterialEmission[cmFront];
7183
end;
7184

7185
procedure TStandartUniformAutoSetExecutor.SetMaterialFrontShininess(Sender:
7186
  IShaderParameter; var ARci: TGLRenderContextInfo);
7187
begin
7188
  Sender.float := ARci.GLStates.MaterialShininess[cmFront];
7189
end;
7190

7191
procedure TStandartUniformAutoSetExecutor.SetMaterialFrontSpecular(Sender:
7192
  IShaderParameter; var ARci: TGLRenderContextInfo);
7193
begin
7194
  Sender.vec4 := ARci.GLStates.MaterialSpecular[cmFront];
7195
end;
7196

7197
procedure TStandartUniformAutoSetExecutor.SetModelMatrix(Sender:
7198
  IShaderParameter; var ARci: TGLRenderContextInfo);
7199
begin
7200
  Sender.mat4 := ARci.PipelineTransformation.ModelMatrix;
7201
end;
7202

7203
procedure TStandartUniformAutoSetExecutor.SetModelViewMatrix(Sender:
7204
  IShaderParameter; var ARci: TGLRenderContextInfo);
7205
begin
7206
  Sender.mat4 := ARci.PipelineTransformation.ModelViewMatrix;
7207
end;
7208

7209
procedure TStandartUniformAutoSetExecutor.SetNormalModelMatrix(Sender:
7210
  IShaderParameter; var ARci: TGLRenderContextInfo);
7211
begin
7212
  Sender.mat3 := ARci.PipelineTransformation.NormalModelMatrix;
7213
end;
7214

7215
procedure TStandartUniformAutoSetExecutor.SetProjectionMatrix(Sender:
7216
  IShaderParameter; var ARci: TGLRenderContextInfo);
7217
begin
7218
  Sender.mat4 := ARci.PipelineTransformation.ProjectionMatrix;
7219
end;
7220

7221
procedure TStandartUniformAutoSetExecutor.SetViewMatrix(Sender:
7222
  IShaderParameter; var ARci: TGLRenderContextInfo);
7223
begin
7224
  Sender.mat4 := ARci.PipelineTransformation.ViewMatrix;
7225
end;
7226

7227
procedure TStandartUniformAutoSetExecutor.SetViewProjectionMatrix(Sender:
7228
  IShaderParameter; var ARci: TGLRenderContextInfo);
7229
begin
7230
  Sender.mat4 := ARci.PipelineTransformation.ViewProjectionMatrix;
7231
end;
7232

7233
procedure TStandartUniformAutoSetExecutor.SetWorldViewProjectionMatrix(Sender:
7234
  IShaderParameter; var ARci: TGLRenderContextInfo);
7235
begin
7236
  Sender.mat4 := MatrixMultiply(
7237
    ARci.PipelineTransformation.ModelViewMatrix,
7238
    ARci.PipelineTransformation.ProjectionMatrix);
7239
end;
7240

7241
{$IFDEF GLS_REGION}{$ENDREGION}{$ENDIF}
7242

7243
{$IFDEF GLS_REGION}{$REGION 'TGLASMVertexProgram'}{$ENDIF}
7244

7245
procedure TGLASMVertexProgram.Assign(Source: TPersistent);
7246
var
7247
  LProg: TGLASMVertexProgram;
7248
begin
7249
  if Source is TGLASMVertexProgram then
7250
  begin
7251
    LProg := TGLASMVertexProgram(Source);
7252
    FSource.Assign(LProg.FSource);
7253
  end;
7254
  inherited;
7255
end;
7256

7257
constructor TGLASMVertexProgram.Create(AOwner: TGLXCollection);
7258
begin
7259
  inherited;
7260
  FHandle := TGLARBVertexProgramHandle.Create;
7261
  FHandle.OnPrapare := DoOnPrepare;
7262
  FSource := TStringList.Create;
7263
  FSource.OnChange := NotifyChange;
7264
  Name := TGLMatLibComponents(AOwner).MakeUniqueName('VertexProg');
7265
end;
7266

7267
destructor TGLASMVertexProgram.Destroy;
7268
begin
7269
  FHandle.Destroy;
7270
  FSource.Destroy;
7271
  inherited;
7272
end;
7273

7274
procedure TGLASMVertexProgram.DoOnPrepare(Sender: TGLContext);
7275
begin
7276
  if FDefferedInit and not IsDesignTime then
7277
    exit;
7278
  try
7279
    if FHandle.IsSupported then
7280
    begin
7281
      FHandle.AllocateHandle;
7282
      if FHandle.IsDataNeedUpdate then
7283
      begin
7284
        SetExeDirectory;
7285
        if (Length(FSourceFile) > 0) and FileStreamExists(FSourceFile) then
7286
          FSource.LoadFromFile(FSourceFile);
7287
        if FSource.Count > 0 then
7288
        begin
7289
          FHandle.LoadARBProgram(FSource.Text);
7290
          FIsValid := FHandle.Ready;
7291
          if IsDesignTime then
7292
          begin
7293
            FInfoLog := FHandle.InfoLog;
7294
            if (Length(FInfoLog) = 0) and FIsValid then
7295
              FInfoLog := 'Compilation successful';
7296
          end
7297
          else if FIsValid then
7298
            GLSLogger.LogInfoFmt('Program "%s" compilation successful - %s',
7299
              [Name, FHandle.InfoLog])
7300
          else
7301
            GLSLogger.LogErrorFmt('Program "%s" compilation failed - %s',
7302
              [Name, FHandle.InfoLog]);
7303
          FHandle.NotifyDataUpdated;
7304
        end
7305
        else
7306
        begin
7307
          if IsDesignTime then
7308
            FInfoLog := 'No source'
7309
          else
7310
            GLSLogger.LogInfoFmt('Program "%s" has no source code', [Name]);
7311
          FIsValid := False;
7312
        end;
7313
      end;
7314
    end
7315
    else
7316
    begin
7317
      FIsValid := False;
7318
      if IsDesignTime then
7319
        FInfoLog := 'Not supported by hardware';
7320
    end;
7321
  except
7322
    on E: Exception do
7323
    begin
7324
      FIsValid := False;
7325
      if IsDesignTime then
7326
        InformationDlg(E.ClassName + ': ' + E.Message)
7327
      else
7328
        GLSLogger.LogError(E.ClassName + ': ' + E.Message);
7329
    end;
7330
  end;
7331
end;
7332

7333
class function TGLASMVertexProgram.FriendlyName: string;
7334
begin
7335
  Result := 'ASM Vertex Program';
7336
end;
7337

7338
function TGLASMVertexProgram.GetHandle: TGLARBVertexProgramHandle;
7339
begin
7340
  Result := FHandle;
7341
end;
7342

7343
procedure TGLASMVertexProgram.NotifyChange(Sender: TObject);
7344
begin
7345
  FHandle.NotifyChangesOfData;
7346
  inherited;
7347
end;
7348

7349
procedure TGLASMVertexProgram.ReadFromFiler(AReader: TReader);
7350
var
7351
  archiveVersion: Integer;
7352
begin
7353
  with AReader do
7354
  begin
7355
    archiveVersion := ReadInteger;
7356
    if archiveVersion = 0 then
7357
    begin
7358
      Name := ReadWideString;
7359
      FDefferedInit := ReadBoolean;
7360
      FSource.Text := ReadWideString;
7361
      FSourceFile := ReadWideString;
7362
    end
7363
    else
7364
      RaiseFilerException(archiveVersion);
7365
  end;
7366
end;
7367

7368
procedure TGLASMVertexProgram.SetSource(AValue: TStringList);
7369
begin
7370
  FSource.Assign(AValue);
7371
end;
7372

7373
procedure TGLASMVertexProgram.SetSourceFile(AValue: string);
7374
begin
7375
  FixPathDelimiter(AValue);
7376
  if FSourceFile <> AValue then
7377
  begin
7378
    FSourceFile := AValue;
7379
    NotifyChange(Self);
7380
  end;
7381
end;
7382

7383
procedure TGLASMVertexProgram.WriteToFiler(AWriter: TWriter);
7384
begin
7385
  with AWriter do
7386
  begin
7387
    WriteInteger(0); // archive version
7388
    WriteWideString(Name);
7389
    WriteBoolean(FDefferedInit);
7390
    if Length(FSourceFile) = 0 then
7391
      WriteWideString(FSource.Text)
7392
    else
7393
      WriteWideString('');
7394
    WriteWideString(FSourceFile);
7395
  end;
7396
end;
7397

7398
{$IFDEF GLS_REGION}{$ENDREGION}{$ENDIF}
7399

7400
initialization
7401

7402
  RegisterClasses(
7403
    [
7404
    TGLTextureImageEx,
7405
      TGLFrameBufferAttachment,
7406
      TGLTextureSampler,
7407
      TGLTextureCombiner,
7408
      TGLShaderEx,
7409
      TGLASMVertexProgram,
7410
      TGLMaterialLibraryEx,
7411
      TGLShaderUniform,
7412
      TGLShaderUniformDSA,
7413
      TGLShaderUniformTexture
7414
      ]);
7415

7416
  RegisterXCollectionItemClass(TGLTextureImageEx);
7417
  RegisterXCollectionItemClass(TGLTextureSampler);
7418
  RegisterXCollectionItemClass(TGLFrameBufferAttachment);
7419
  RegisterXCollectionItemClass(TGLTextureCombiner);
7420
  RegisterXCollectionItemClass(TGLShaderEx);
7421
  RegisterXCollectionItemClass(TGLASMVertexProgram);
7422

7423
  vStandartUniformAutoSetExecutor := TStandartUniformAutoSetExecutor.Create;
7424

7425
finalization
7426

7427
  vStandartUniformAutoSetExecutor.Destroy;
7428

7429
end.
7430

7431

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

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

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

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