2
// This unit is part of the GLScene Engine https://github.com/glscene
5
TGLSLShader is a wrapper for GLS shaders.
8
09/02/13 - Yar - Added OnApplyEx, OnInitializeEx events where is TGLLibMaterial as Sender (thanks to Dmitriy Buharin)
9
10/11/12 - PW - Added CPP compatibility: changed vector arrays to records
10
18/02/11 - Yar - Fixed transform feedback varyings activation
11
23/08/10 - Yar - Replaced OpenGL1x to OpenGLTokens
12
02/06/10 - Yar - Replace OpenGL functions to OpenGLAdapter
13
Added unsigned integer uniforms
14
22/04/10 - Yar - Fixes after GLState revision
15
02/04/10 - Yar - Added GetActiveAttribs to TGLCustomGLSLShader
16
04/11/09 - DaStr - Added default value to TGLCustomGLSLShader.TransformFeedBackMode
17
26/10/09 - DaStr - Updated GeometryShader support (thanks YarUnderoaker)
18
24/08/09 - DaStr - Added GeometryShader support (thanks YarUnderoaker)
19
24/07/09 - DaStr - Added support for TGLCustomShader.DebugMode
20
Fixed spelling mistake in TGLShaderUnAplyEvent
21
TGLShader.DoInitialize() now passes rci
22
(BugTracker ID = 2826217)
23
Bugfixed TGLCustomGLSLShader.DoInitialize() - now
24
shader cleanes up correctly if failed to initialize
25
15/03/08 - DaStr - Fixups for vIgnoreContextActivationFailures mode
26
(BugTracker ID = 1914782)
27
25/12/07 - DaStr - Fix-up for previous update (BugtrackerID = 1772477)
28
12/08/07 - LC - TGLSLShaderParameter.SetAsCustomTexture now restores
29
the active texture unit (BugtrackerID = 1772477)
30
12/07/07 - DaStr - TGLSLInitializedShaderParameters removed because
31
even if implemented, it could not give
32
a significant performance increase
33
30/03/07 - fig - Changed OnInitialize event to be fired after
34
linking, but before validation. This can now be
35
used to set texture units for different sampler
36
types (1D/2D/3D) before validation, which fixes
37
a bug (or complies to strict validation) with ATI
39
30/03/07 - DaStr - Bugfixed TGLCustomGLSLShader.DoUnApply
40
(Result was not initialized)
41
20/03/07 - DaStr - TGLCustomGLSLShader now generates its own events
42
Added TGLSLShaderParameter
43
Added TGLCustomGLSLShader.DoInitialPass
44
Added TGLCustomGLSLShader.Param[]
45
21/02/07 - DaStr - Initial version (contributed to GLScene)
49
Previous version history:
50
v1.0 11 March '2006 Creation
51
v1.1 06 August '2006 TGLCustomGLSLShader.DoInitialize bugfixed
52
v1.1.2 24 August '2006 TGLCustomShader.SetParameterTexture[1-3]D added
53
v1.1.4 09 September '2006 Fixed a memory leak which occured when
54
enabling / disabling the shader several times
55
v1.1.6 22 September '2006 DoUnApply fixed (suggested by Nelsol Chu)
56
v1.2 04 November '2006 function GetGLSLProg added (just in case)
57
TGLSLShader has more published properties
58
Bugfix in DoInitialize (when no shader is active)
59
(Get/Set)ParameterTexture[1/2/3]DHandle added
60
(Get/Set)ParameterCustomTextureHandle support added
61
v1.2.4 22 November '2006 TGLProgramHandle.Name is now used
63
Fixed a possible bug in DoInitialize
64
(Handle was freed, but not nil'ed)
76
GLVectorGeometry, GLVectorTypes, GLTexture, OpenGLTokens, GLContext, GLCustomShader,
77
GLRenderContextInfo, GLTextureFormat, GLSLParameter;
80
TGLSLShaderParameter = class;
81
TGLCustomGLSLShader = class;
82
EGLSLShaderException = class(EGLCustomShaderException);
84
TGLSLShaderEvent = procedure(Shader: TGLCustomGLSLShader) of object;
85
TGLSLShaderUnApplyEvent = procedure(Shader: TGLCustomGLSLShader;
86
var ThereAreMorePasses: Boolean) of object;
87
TGLSLShaderEventEx = procedure(Shader: TGLCustomGLSLShader;
88
Sender: TObject) of object;
90
TGLActiveAttrib = record
97
TGLActiveAttribArray = array of TGLActiveAttrib;
99
TGLCustomGLSLShader = class(TGLCustomShader)
101
FGLSLProg: TGLProgramHandle;
102
FParam: TGLSLShaderParameter;
103
FActiveVarying: TStrings;
104
FTransformFeedBackMode: TGLTransformFeedBackMode;
106
FOnInitialize: TGLSLShaderEvent;
107
FOnApply: TGLSLShaderEvent;
108
FOnUnApply: TGLSLShaderUnApplyEvent;
109
FOnInitializeEx: TGLSLShaderEventEx;
110
FOnApplyEx: TGLSLShaderEventEx;
112
function GetParam(const Index: string): TGLSLShaderParameter;
113
function GetDirectParam(const Index: Cardinal): TGLSLShaderParameter;
114
procedure OnChangeActiveVarying(Sender: TObject);
116
property OnApply: TGLSLShaderEvent read FOnApply write FOnApply;
117
property OnUnApply: TGLSLShaderUnApplyEvent read FOnUnApply write FOnUnApply;
118
property OnInitialize: TGLSLShaderEvent read FOnInitialize write FOnInitialize;
119
property OnInitializeEx: TGLSLShaderEventEx read FOnInitializeEx write FOnInitializeEx;
120
property OnApplyEx: TGLSLShaderEventEx read FOnApplyEx write FOnApplyEx;
122
function GetGLSLProg: TGLProgramHandle; virtual;
123
function GetCurrentParam: TGLSLShaderParameter; virtual;
124
procedure SetActiveVarying(const Value: TStrings);
125
procedure SetTransformFeedBackMode(const Value: TGLTransformFeedBackMode);
126
procedure DoInitialize(var rci: TGLRenderContextInfo; Sender: TObject); override;
127
procedure DoFinalize; override;
128
procedure DoApply(var rci: TGLRenderContextInfo; Sender: TObject); override;
129
function DoUnApply(var rci: TGLRenderContextInfo): Boolean; override;
131
constructor Create(AOwner: TComponent); override;
132
destructor Destroy; override;
133
procedure Assign(Source: TPersistent); override;
134
function ShaderSupported: Boolean; override;
135
function GetActiveAttribs: TGLActiveAttribArray;
137
property Param[const Index: string]: TGLSLShaderParameter read GetParam;
138
property DirectParam[const Index: Cardinal]: TGLSLShaderParameter read GetDirectParam;
139
property ActiveVarying: TStrings read FActiveVarying write SetActiveVarying;
140
property TransformFeedBackMode: TGLTransformFeedBackMode read FTransformFeedBackMode write SetTransformFeedBackMode default tfbmInterleaved;
144
{ Wrapper around a parameter of a GLSL program. }
145
TGLSLShaderParameter = class(TGLCustomShaderParameter)
148
FGLSLProg: TGLProgramHandle;
152
function GetAsVector1f: Single; override;
153
function GetAsVector2f: TVector2f; override;
154
function GetAsVector3f: TVector3f; override;
155
function GetAsVector4f: TVector; override;
157
function GetAsVector1i: Integer; override;
158
function GetAsVector2i: TVector2i; override;
159
function GetAsVector3i: TVector3i; override;
160
function GetAsVector4i: TVector4i; override;
162
function GetAsVector1ui: GLuint; override;
163
function GetAsVector2ui: TVector2ui; override;
164
function GetAsVector3ui: TVector3ui; override;
165
function GetAsVector4ui: TVector4ui; override;
167
procedure SetAsVector1f(const Value: Single); override;
168
procedure SetAsVector2f(const Value: TVector2f); override;
169
procedure SetAsVector3f(const Value: TVector3f); override;
170
procedure SetAsVector4f(const Value: TVector4f); override;
172
procedure SetAsVector1i(const Value: Integer); override;
173
procedure SetAsVector2i(const Value: TVector2i); override;
174
procedure SetAsVector3i(const Value: TVector3i); override;
175
procedure SetAsVector4i(const Value: TVector4i); override;
177
procedure SetAsVector1ui(const Value: GLuint); override;
178
procedure SetAsVector2ui(const Value: TVector2ui); override;
179
procedure SetAsVector3ui(const Value: TVector3ui); override;
180
procedure SetAsVector4ui(const Value: TVector4ui); override;
182
function GetAsMatrix2f: TMatrix2f; override;
183
function GetAsMatrix3f: TMatrix3f; override;
184
function GetAsMatrix4f: TMatrix4f; override;
185
procedure SetAsMatrix2f(const Value: TMatrix2f); override;
186
procedure SetAsMatrix3f(const Value: TMatrix3f); override;
187
procedure SetAsMatrix4f(const Value: TMatrix4f); override;
189
function GetAsCustomTexture(const TextureIndex: Integer;
190
TextureTarget: TGLTextureTarget): Cardinal; override;
191
procedure SetAsCustomTexture(const TextureIndex: Integer;
192
TextureTarget: TGLTextureTarget; const Value: Cardinal); override;
194
function GetAsUniformBuffer: GLenum; override;
195
procedure SetAsUniformBuffer( UBO: GLenum); override;
198
// Nothing here ...yet.
201
TGLSLShader = class(TGLCustomGLSLShader)
203
property FragmentProgram;
204
property VertexProgram;
205
property GeometryProgram;
210
property OnInitialize;
211
property OnInitializeEx;
213
property ShaderStyle;
214
property FailedInitAction;
216
property ActiveVarying;
217
property TransformFeedBackMode;
226
{ TGLCustomGLSLShader }
228
procedure TGLCustomGLSLShader.DoApply(var rci: TGLRenderContextInfo; Sender: TObject);
230
FGLSLProg.UseProgramObject;
231
if Assigned(FOnApply) then
233
if Assigned(FOnApplyEx) then
234
FOnApplyEx(Self, Sender);
238
procedure TGLCustomGLSLShader.DoInitialize(var rci: TGLRenderContextInfo; Sender: TObject);
240
cBufferMode: array[tfbmInterleaved..tfbmSeparate] of GLenum = (
241
GL_INTERLEAVED_ATTRIBS_EXT, GL_SEPARATE_ATTRIBS_EXT);
243
i, NumVarying: Integer;
244
sVaryings: array of AnsiString;
245
pVaryings: array of PGLChar;
248
if not ShaderSupported then
249
HandleFailedInitialization
252
FGLSLProg.AllocateHandle;
253
if FGLSLProg.IsDataNeedUpdate then
256
FGLSLProg.Name := Name
258
FGLSLProg.Name := ClassName;
260
FGLSLProg.DetachAllObject;
261
if VertexProgram.Enabled then
262
FGLSLProg.AddShader(TGLVertexShaderHandle, VertexProgram.Code.Text, FDebugMode);
263
if FragmentProgram.Enabled then
264
FGLSLProg.AddShader(TGLFragmentShaderHandle, FragmentProgram.Code.Text, FDebugMode);
265
if GeometryProgram.Enabled then
266
FGLSLProg.AddShader(TGLGeometryShaderHandle, GeometryProgram.Code.Text, FDebugMode);
268
if VertexProgram.Enabled or FragmentProgram.Enabled or GeometryProgram.Enabled then
270
if GeometryProgram.Enabled then
272
GL.ProgramParameteri(FGLSLProg.Handle, GL_GEOMETRY_INPUT_TYPE_EXT,
273
cGLgsInTypes[GeometryProgram.InputPrimitiveType]);
274
GL.ProgramParameteri(FGLSLProg.Handle, GL_GEOMETRY_OUTPUT_TYPE_EXT,
275
cGLgsOutTypes[GeometryProgram.OutputPrimitiveType]);
276
GL.ProgramParameteri(FGLSLProg.Handle, GL_GEOMETRY_VERTICES_OUT_EXT,
277
GeometryProgram.VerticesOut);
280
NumVarying := FActiveVarying.Count;
281
if NumVarying > 0 then
284
SetLength(sVaryings, NumVarying);
285
SetLength(pVaryings, NumVarying);
286
for i := 0 to NumVarying - 1 do
288
sVaryings[i] := AnsiString(FActiveVarying.Strings[i]) + #0;
289
pVaryings[i] := PAnsiChar( sVaryings[i] );
291
GL.TransformFeedbackVaryings(
292
FGLSLProg.Handle, NumVarying, @pVaryings[0],
293
cBufferMode[FTransformFeedBackMode] );
296
if (not FGLSLProg.LinkProgram) then
297
raise EGLSLShaderException.Create(FGLSLProg.InfoLog);
299
FGLSLProg.NotifyDataUpdated;
305
HandleFailedInitialization(E.Message);
312
if Assigned(FOnInitialize) then
314
FGLSLProg.UseProgramObject;
316
FGLSLProg.EndUseProgramObject;
318
if Assigned(FOnInitializeEx) then
320
FGLSLProg.UseProgramObject;
321
FOnInitializeEx(Self, Sender);
322
FGLSLProg.EndUseProgramObject;
324
if (not FGLSLProg.ValidateProgram) then
325
raise EGLSLShaderException.Create(FGLSLProg.InfoLog);
330
HandleFailedInitialization(E.Message);
337
function TGLCustomGLSLShader.DoUnApply(var rci: TGLRenderContextInfo): Boolean;
340
if Assigned(FOnUnApply) then
341
FOnUnApply(Self, Result);
343
FGLSLProg.EndUseProgramObject;
347
function TGLCustomGLSLShader.ShaderSupported: Boolean;
349
Result := (GL.ARB_shader_objects and GL.ARB_vertex_program and
350
GL.ARB_vertex_shader and GL.ARB_fragment_shader);
353
function TGLCustomGLSLShader.GetActiveAttribs: TGLActiveAttribArray;
355
LRci: TGLRenderContextInfo;
357
buff: array[0..127] of AnsiChar;
362
DoInitialize(LRci, Self);
364
SetLength(Result, 16);
366
if FGLSLProg.Handle<>0 then
368
GL.GetProgramiv(FGLSLProg.Handle, GL_ACTIVE_ATTRIBUTES, @max);
369
for i := 0 to 16 - 1 do
372
GL.GetActiveAttrib(FGLSLProg.Handle, i, Length(buff), @len, @Result[j].Size,
378
GL_FLOAT: AType := GLSLType1F;
379
GL_FLOAT_VEC2: AType := GLSLType2F;
380
GL_FLOAT_VEC3: AType := GLSLType3F;
381
GL_FLOAT_VEC4: AType := GLSLType4F;
382
GL_INT: AType := GLSLType1I;
383
GL_INT_VEC2: AType := GLSLType2I;
384
GL_INT_VEC3: AType := GLSLType3I;
385
GL_INT_VEC4: AType := GLSLType4I;
386
GL_UNSIGNED_INT: AType := GLSLType1UI;
387
GL_UNSIGNED_INT_VEC2: AType := GLSLType2UI;
388
GL_UNSIGNED_INT_VEC3: AType := GLSLType3UI;
389
GL_UNSIGNED_INT_VEC4: AType := GLSLType4UI;
390
GL_BOOL: AType := GLSLType1I;
391
GL_BOOL_VEC2: AType := GLSLType2I;
392
GL_BOOL_VEC3: AType := GLSLType3I;
393
GL_BOOL_VEC4: AType := GLSLType4I;
394
GL_FLOAT_MAT2: AType := GLSLTypeMat2F;
395
GL_FLOAT_MAT3: AType := GLSLTypeMat3F;
396
GL_FLOAT_MAT4: AType := GLSLTypeMat4F;
398
Name := Copy(string(buff), 0, len);
404
SetLength(Result, j);
407
procedure TGLCustomGLSLShader.Assign(Source: TPersistent);
409
inherited Assign(Source);
411
if Source is TGLCustomGLSLShader then
413
FreeAndNil(FGLSLProg); //just free the handle for it to be recreated on next initialization
417
procedure TGLCustomGLSLShader.DoFinalize;
420
if Assigned(FGLSLProg) then
421
FGLSLProg.NotifyChangesOfData;
424
function TGLCustomGLSLShader.GetGLSLProg: TGLProgramHandle;
429
function TGLCustomGLSLShader.GetParam(
430
const Index: string): TGLSLShaderParameter;
432
FParam.FParameterID := FGLSLProg.GetUniformLocation(Index);
436
function TGLCustomGLSLShader.GetDirectParam(
437
const Index: Cardinal): TGLSLShaderParameter;
439
FParam.FParameterID := Index;
443
function TGLCustomGLSLShader.GetCurrentParam: TGLSLShaderParameter;
448
constructor TGLCustomGLSLShader.Create(AOwner: TComponent);
451
FGLSLProg := TGLProgramHandle.Create;
452
FParam := TGLSLShaderParameter.Create;
453
FParam.FGLSLProg := FGLSLProg;
454
FActiveVarying := TStringList.Create;
455
TStringList(FActiveVarying).OnChange := OnChangeActiveVarying;
456
FTransformFeedBackMode := tfbmInterleaved;
459
destructor TGLCustomGLSLShader.Destroy;
461
FreeAndNil(FGLSLProg);
463
FreeAndNil(FActiveVarying);
467
procedure TGLCustomGLSLShader.SetActiveVarying(const Value: TStrings);
469
FActiveVarying.Assign(Value);
473
procedure TGLCustomGLSLShader.SetTransformFeedBackMode(const Value: TGLTransformFeedBackMode);
475
if Value <> FTransformFeedBackMode then
477
FTransformFeedBackMode := Value;
482
procedure TGLCustomGLSLShader.OnChangeActiveVarying(Sender: TObject);
487
{ TGLSLShaderParameter }
489
function TGLSLShaderParameter.GetAsCustomTexture(
490
const TextureIndex: Integer; TextureTarget: TGLTextureTarget): Cardinal;
492
GL.GetUniformiv(FGLSLProg.Handle, TextureIndex, @Result);
495
function TGLSLShaderParameter.GetAsMatrix2f: TMatrix2f;
497
GL.GetUniformfv(FGLSLProg.Handle, FParameterID, @Result);
500
function TGLSLShaderParameter.GetAsMatrix3f: TMatrix3f;
502
GL.GetUniformfv(FGLSLProg.Handle, FParameterID, @Result);
505
function TGLSLShaderParameter.GetAsMatrix4f: TMatrix4f;
507
GL.GetUniformfv(FGLSLProg.Handle, FParameterID, @Result);
510
function TGLSLShaderParameter.GetAsVector1f: Single;
512
GL.GetUniformfv(FGLSLProg.Handle, FParameterID, @Result);
515
function TGLSLShaderParameter.GetAsVector1i: Integer;
517
GL.GetUniformiv(FGLSLProg.Handle, FParameterID, @Result);
520
function TGLSLShaderParameter.GetAsVector2f: TVector2f;
522
GL.GetUniformfv(FGLSLProg.Handle, FParameterID, @Result);
525
function TGLSLShaderParameter.GetAsVector2i: TVector2i;
527
GL.GetUniformiv(FGLSLProg.Handle, FParameterID, @Result);
530
function TGLSLShaderParameter.GetAsVector3f: TVector3f;
532
GL.GetUniformfv(FGLSLProg.Handle, FParameterID, @Result);
535
function TGLSLShaderParameter.GetAsVector3i: TVector3i;
537
GL.GetUniformiv(FGLSLProg.Handle, FParameterID, @Result);
540
function TGLSLShaderParameter.GetAsVector4f: TVector;
542
GL.GetUniformfv(FGLSLProg.Handle, FParameterID, @Result);
545
function TGLSLShaderParameter.GetAsVector4i: TVector4i;
547
GL.GetUniformiv(FGLSLProg.Handle, FParameterID, @Result);
550
procedure TGLSLShaderParameter.SetAsCustomTexture(
551
const TextureIndex: Integer; TextureTarget: TGLTextureTarget;
552
const Value: Cardinal);
554
CurrentGLContext.GLStates.TextureBinding[TextureIndex, TextureTarget] := Value;
555
GL.Uniform1i(FParameterID, TextureIndex);
558
procedure TGLSLShaderParameter.SetAsMatrix2f(const Value: TMatrix2f);
560
GL.UniformMatrix2fv(FParameterID, 1, False, @Value);
563
procedure TGLSLShaderParameter.SetAsMatrix3f(const Value: TMatrix3f);
565
GL.UniformMatrix3fv(FParameterID, 1, False, @Value);
568
procedure TGLSLShaderParameter.SetAsMatrix4f(const Value: TMatrix4f);
570
GL.UniformMatrix4fv(FParameterID, 1, False, @Value);
573
procedure TGLSLShaderParameter.SetAsVector1f(const Value: Single);
575
GL.Uniform1f(FParameterID, Value);
578
procedure TGLSLShaderParameter.SetAsVector1i(const Value: Integer);
580
GL.Uniform1i(FParameterID, Value);
583
procedure TGLSLShaderParameter.SetAsVector2f(const Value: TVector2f);
585
GL.Uniform2f(FParameterID, Value.V[0], Value.V[1]);
588
procedure TGLSLShaderParameter.SetAsVector2i(const Value: TVector2i);
590
GL.Uniform2i(FParameterID, Value.V[0], Value.V[1]);
593
procedure TGLSLShaderParameter.SetAsVector3f(const Value: TVector3f);
595
GL.Uniform3f(FParameterID, Value.V[0], Value.V[1], Value.V[2]);
598
procedure TGLSLShaderParameter.SetAsVector3i(const Value: TVector3i);
600
GL.Uniform3i(FParameterID, Value.V[0], Value.V[1], Value.V[2]);
603
procedure TGLSLShaderParameter.SetAsVector4f(const Value: TVector4f);
605
GL.Uniform4f(FParameterID, Value.V[0], Value.V[1], Value.V[2], Value.V[3]);
608
procedure TGLSLShaderParameter.SetAsVector4i(const Value: TVector4i);
610
GL.Uniform4i(FParameterID, Value.V[0], Value.V[1], Value.V[2], Value.V[3]);
613
function TGLSLShaderParameter.GetAsUniformBuffer: GLenum;
615
GL.GetUniformiv(FGLSLProg.Handle, FParameterID, @Result);
618
function TGLSLShaderParameter.GetAsVector1ui: GLuint;
620
GL.GetUniformuiv(FGLSLProg.Handle, FParameterID, @Result);
623
procedure TGLSLShaderParameter.SetAsVector1ui(const Value: GLuint);
625
GL.Uniform1ui(FParameterID, Value);
628
function TGLSLShaderParameter.GetAsVector2ui: TVector2ui;
630
GL.GetUniformiv(FGLSLProg.Handle, FParameterID, @Result);
633
procedure TGLSLShaderParameter.SetAsVector2ui(const Value: TVector2ui);
635
GL.Uniform2ui(FParameterID, Value.V[0], Value.V[1]);
638
function TGLSLShaderParameter.GetAsVector3ui: TVector3ui;
640
GL.GetUniformiv(FGLSLProg.Handle, FParameterID, @Result);
643
procedure TGLSLShaderParameter.SetAsVector3ui(const Value: TVector3ui);
645
GL.Uniform3ui(FParameterID, Value.V[0], Value.V[1], Value.V[2]);
648
function TGLSLShaderParameter.GetAsVector4ui: TVector4ui;
650
GL.GetUniformiv(FGLSLProg.Handle, FParameterID, @Result);
653
procedure TGLSLShaderParameter.SetAsVector4ui(const Value: TVector4ui);
655
GL.Uniform4ui(FParameterID, Value.V[0], Value.V[1], Value.V[2], Value.V[3]);
658
procedure TGLSLShaderParameter.SetAsUniformBuffer(UBO: Cardinal);
660
CurrentGLContext.GLStates.UniformBufferBinding := UBO;
661
GL.UniformBuffer(FGLSLProg.Handle, FParameterID, UBO);
665
RegisterClasses([TGLCustomGLSLShader, TGLSLShader]);