2
// This unit is part of the GLScene Engine https://github.com/glscene
5
A shader that applies bump mapping.
8
The normal map is expected to be the primary texture.
10
The secondary texture is used for the diffuse texture,
11
to enable set boDiffuseTexture2 in the BumpOptions property.
13
The tertiary texture is used for the specular texture,
14
to enable set boSpecularTexture3 in the BumpOptions property.
15
The SpecularMode determines the specular highlight calculation
16
(Blinn or Phong), smOff disables specular highlights in the
19
External tangent bump space expects tangent data under
20
GL_TEXTURE1_ARB and binormal data under GL_TEXTURE2_ARB.
22
The boUseSecondaryTexCoords bump option tells the shader to use
23
the secondary texture coordinates for the diffuse and specular
27
23/08/10 - Yar - Upgraded program hadles
28
22/04/10 - Yar - Fixes after GLState revision
29
05/03/10 - DanB - More state added to TGLStateCache
30
06/06/07 - DaStr - Added GLColor to uses (BugtrackerID = 1732211)
31
31/03/07 - DaStr - Added $I GLScene.inc
32
25/02/07 - DaStr - Moved registration to GLSceneRegister.pas
33
15/04/05 - SG - Added parallax offset mapping for the BasicARBfp bump method (experimental)
34
Height data is expected in the normal map alpha channel.
35
21/12/04 - SG - Added light attenutation support through the
36
boLightAttenutation option in the BumpOptions property.
37
27/10/04 - SG - Added boUseSecondaryTexCoords option to BumpOptions
38
11/10/04 - SG - Added SpecularMode to define the specular highlight equation,
39
Removed the boDisableSpecular bump option (depricated).
40
06/10/04 - SG - Added special functions for generating the ARB programs
41
which replace the string constants.
42
02/10/04 - SG - Changed render order a little, minimum texture units
43
is now 2 for dot3 texcombiner bump method.
44
Changed vertex programs to accept local program
45
params, now only 1 vertex and 1 fragment program is
46
required for all lights.
47
Vertex programs now apply the primary texture matrix.
48
30/09/04 - SG - Added fragment program logic,
49
Added bmBasicARBFP bump method, bsTangentExternal
50
bump space and associated ARB programs,
51
Various name changes and fixes
52
28/09/04 - SG - Vertex programs now use ARB_position_invariant option.
53
29/06/04 - SG - Quaternion tangent space fix in tangent bump vertex
55
23/06/04 - SG - Added bsTangent option to TBumpSpace,
56
Added tangent space light vector vertex program.
57
22/06/04 - SG - Creation.
69
GLMaterial, GLGraphics, GLUtils, GLVectorGeometry, OpenGLTokens,
70
GLContext, GLVectorLists, GLColor, GLRenderContextInfo, GLState,
74
TBumpMethod = (bmDot3TexCombiner, bmBasicARBFP);
76
TBumpSpace = (bsObject, bsTangentExternal, bsTangentQuaternion);
78
TBumpOption = (boDiffuseTexture2, // Use secondary texture as diffuse
79
boSpecularTexture3, // Use tertiary texture as specular
80
boUseSecondaryTexCoords, // Pass through secondary texcoords
81
boLightAttenuation, // Use light attenuation
82
boParallaxMapping // Enable parallax offset mapping
84
TBumpOptions = set of TBumpOption;
86
TSpecularMode = (smOff, smBlinn, smPhong);
90
{ A generic bump shader. }
91
TGLBumpShader = class(TGLShader)
93
FVertexProgramHandle: TGLARBVertexProgramHandle;
94
FFragmentProgramHandle: TGLARBFragmentProgramHandle;
95
FLightIDs: TIntegerList;
96
FLightsEnabled: Integer;
97
FBumpMethod: TBumpMethod;
98
FBumpSpace: TBumpSpace;
99
FBumpOptions: TBumpOptions;
100
FSpecularMode: TSpecularMode;
101
FDesignTimeEnabled: Boolean;
102
FAmbientPass: Boolean;
103
FDiffusePass: Boolean;
104
FVertexProgram: TStringList;
105
FFragmentProgram: TStringList;
106
FParallaxOffset: Single;
108
function GenerateVertexProgram: string;
109
function GenerateFragmentProgram: string;
110
procedure DoLightPass(var rci: TGLRenderContextInfo; lightID: Cardinal);
113
procedure SetBumpMethod(const Value: TBumpMethod);
114
procedure SetBumpSpace(const Value: TBumpSpace);
115
procedure SetBumpOptions(const Value: TBumpOptions);
116
procedure SetSpecularMode(const Value: TSpecularMode);
117
procedure SetDesignTimeEnabled(const Value: Boolean);
118
procedure SetParallaxOffset(const Value: Single);
119
procedure Loaded; override;
120
procedure DeleteVertexPrograms;
121
procedure DeleteFragmentPrograms;
124
constructor Create(AOwner: TComponent); override;
125
destructor Destroy; override;
127
procedure DoApply(var rci: TGLRenderContextInfo; Sender: TObject); override;
128
function DoUnApply(var rci: TGLRenderContextInfo): Boolean; override;
131
property BumpMethod: TBumpMethod read FBumpMethod write SetBumpMethod;
132
property BumpSpace: TBumpSpace read FBumpSpace write SetBumpSpace;
133
property BumpOptions: TBumpOptions read FBumpOptions write SetBumpOptions;
134
property SpecularMode: TSpecularMode read FSpecularMode write
136
property DesignTimeEnabled: Boolean read FDesignTimeEnabled write
137
SetDesignTimeEnabled;
138
property ParallaxOffset: Single read FParallaxOffset write
143
// ------------------------------------------------------------------
144
// ------------------------------------------------------------------
145
// ------------------------------------------------------------------
147
// ------------------------------------------------------------------
148
// ------------------------------------------------------------------
149
// ------------------------------------------------------------------
152
// ------------------ TGLBumpShader ------------------
158
constructor TGLBumpShader.Create(AOwner: TComponent);
161
FLightIDs := TIntegerList.Create;
162
FBumpMethod := bmDot3TexCombiner;
163
FBumpSpace := bsObject;
165
FSpecularMode := smOff;
166
ShaderStyle := ssLowLevel;
167
FParallaxOffset := 0.04;
169
FVertexProgram := TStringList.Create;
170
FFragmentProgram := TStringList.Create;
176
destructor TGLBumpShader.Destroy;
178
DeleteVertexPrograms;
179
DeleteFragmentPrograms;
182
FFragmentProgram.Free;
189
procedure TGLBumpShader.Loaded;
194
// GenerateVertexProgram
197
function TGLBumpShader.GenerateVertexProgram: string;
200
DoTangent, DoSpecular, DoParallaxOffset: Boolean;
203
DoSpecular := (BumpMethod = bmBasicARBFP) and not (SpecularMode = smOff);
204
DoTangent := (BumpSpace = bsTangentExternal) or (BumpSpace =
205
bsTangentQuaternion);
206
DoParallaxOffset := (BumpMethod = bmBasicARBFP) and (boParallaxMapping in
207
BumpOptions) and DoTangent;
209
VP := TStringList.Create;
211
VP.Add('!!ARBvp1.0');
212
VP.Add('OPTION ARB_position_invariant;');
214
VP.Add('PARAM mv[4] = { state.matrix.modelview };');
215
VP.Add('PARAM mvinv[4] = { state.matrix.modelview.inverse };');
216
VP.Add('PARAM mvit[4] = { state.matrix.modelview.invtrans };');
217
VP.Add('PARAM tex[4] = { state.matrix.texture[0] };');
218
if boUseSecondaryTexCoords in BumpOptions then
219
VP.Add('PARAM tex2[4] = { state.matrix.texture[1] };');
220
VP.Add('PARAM lightPos = program.local[0];');
221
VP.Add('PARAM lightAtten = program.local[1];');
222
if BumpSpace = bsTangentExternal then
224
VP.Add('ATTRIB tangent = vertex.texcoord[1];');
225
VP.Add('ATTRIB binormal = vertex.texcoord[2];');
226
VP.Add('ATTRIB normal = vertex.normal;');
228
VP.Add('TEMP temp, temp2, light, eye, atten;');
230
if (boLightAttenuation in BumpOptions) then
233
VP.Add(' DP4 temp.x, mv[0], vertex.position;');
234
VP.Add(' DP4 temp.y, mv[1], vertex.position;');
235
VP.Add(' DP4 temp.z, mv[2], vertex.position;');
236
VP.Add(' ADD light, lightPos, -temp;');
238
VP.Add(' DP3 atten.y, light, light;');
239
VP.Add(' RSQ atten.y, atten.y;');
240
if BumpMethod = bmDot3TexCombiner then
242
VP.Add(' RCP atten.y, atten.y;');
243
VP.Add(' MUL atten.z, atten.y, atten.y;');
244
VP.Add(' MAD atten.x, lightAtten.y, atten.y, lightAtten.x;');
245
VP.Add(' MAD atten.x, lightAtten.z, atten.z, atten.x;');
246
VP.Add(' RCP atten.x, atten.x;');
248
else if BumpMethod = bmBasicARBFP then
250
// Store the distance in atten.x for ARBFP,
251
// fragment program will calculate attenutation
252
VP.Add(' RCP atten.x, atten.y;');
255
VP.Add(' DP3 temp.x, mvinv[0], light;');
256
VP.Add(' DP3 temp.y, mvinv[1], light;');
257
VP.Add(' DP3 temp.z, mvinv[2], light;');
258
VP.Add(' MOV light, temp;');
262
VP.Add(' DP4 light.x, mvinv[0], lightPos;');
263
VP.Add(' DP4 light.y, mvinv[1], lightPos;');
264
VP.Add(' DP4 light.z, mvinv[2], lightPos;');
265
VP.Add(' ADD light, light, -vertex.position;');
268
if DoSpecular or DoParallaxOffset then
269
VP.Add(' ADD eye, mvit[3], -vertex.position;');
273
if BumpSpace = bsTangentExternal then
276
VP.Add(' DP3 temp.x, light, tangent;');
277
VP.Add(' DP3 temp.y, light, binormal;');
278
VP.Add(' DP3 temp.z, light, normal;');
279
VP.Add(' MOV light, temp;');
280
if DoSpecular or DoParallaxOffset then
282
VP.Add(' DP3 temp.x, eye, tangent;');
283
VP.Add(' DP3 temp.y, eye, binormal;');
284
VP.Add(' DP3 temp.z, eye, normal;');
285
VP.Add(' MOV eye, temp;');
289
else if BumpSpace = bsTangentQuaternion then
292
VP.Add(' DP3 temp.x, light, light;');
293
VP.Add(' RSQ temp.x, temp.x;');
294
VP.Add(' MUL light, temp.x, light;');
296
VP.Add(' MOV temp2.x, vertex.normal.y;');
297
VP.Add(' ADD temp2.y, 0.0, -vertex.normal.x;');
298
VP.Add(' MOV temp2.z, 0.0;');
300
VP.Add(' DP3 temp.x, temp2, light;');
301
VP.Add(' MUL temp.x, temp2.y, light.z;');
302
VP.Add(' MAD temp.y, vertex.normal.z, light.x, temp.x;');
303
VP.Add(' MUL temp.x, vertex.normal.y, light.z;');
304
VP.Add(' MAD temp.z, vertex.normal.z, light.y, -temp.x;');
305
VP.Add(' MUL temp.x, vertex.normal.y, light.y;');
306
VP.Add(' MAD temp.x, vertex.normal.z, light.z, temp.x;');
307
VP.Add(' MAD temp.w, -temp2.y, light.x, temp.x;');
308
VP.Add(' MOV light, temp.yzwy;');
310
if DoSpecular or DoParallaxOffset then
312
VP.Add(' DP3 temp.x, temp2, eye;');
313
VP.Add(' MUL temp.x, temp2.y, eye.z;');
314
VP.Add(' MAD temp.y, vertex.normal.z, eye.x, temp.x;');
315
VP.Add(' MUL temp.x, vertex.normal.y, eye.z;');
316
VP.Add(' MAD temp.z, vertex.normal.z, eye.y, -temp.x;');
317
VP.Add(' MUL temp.x, vertex.normal.y, eye.y;');
318
VP.Add(' MAD temp.x, vertex.normal.z, eye.z, temp.x;');
319
VP.Add(' MAD temp.w, -temp2.y, eye.x, temp.x;');
320
VP.Add(' MOV eye, temp.yzwy;');
326
if BumpMethod = bmDot3TexCombiner then
329
if BumpSpace <> bsTangentQuaternion then
331
VP.Add(' DP3 temp.x, light, light;');
332
VP.Add(' RSQ temp, temp.x;');
333
VP.Add(' MUL light, temp.x, light;');
336
if boLightAttenuation in BumpOptions then
337
VP.Add(' MUL light, atten.x, light;');
339
VP.Add(' MAD result.color, light, 0.5, 0.5;');
340
VP.Add(' MOV result.color.w, 1.0;');
343
else if BumpMethod = bmBasicARBFP then
346
if boLightAttenuation in BumpOptions then
347
VP.Add(' MOV light.w, atten.x;')
349
VP.Add(' MOV light.w, 0.0;');
350
if DoSpecular or DoParallaxOffset then
351
VP.Add(' MOV eye.w, 0.0;');
357
VP.Add(' DP4 temp.x, vertex.texcoord[0], tex[0];');
358
VP.Add(' DP4 temp.y, vertex.texcoord[0], tex[1];');
359
VP.Add(' DP4 temp.z, vertex.texcoord[0], tex[2];');
360
VP.Add(' DP4 temp.w, vertex.texcoord[0], tex[3];');
361
VP.Add(' MOV result.texcoord[' + IntToStr(texcoord) + '], temp;');
364
if boUseSecondaryTexCoords in BumpOptions then
366
VP.Add(' DP4 temp.x, vertex.texcoord[1], tex2[0];');
367
VP.Add(' DP4 temp.y, vertex.texcoord[1], tex2[1];');
368
VP.Add(' DP4 temp.z, vertex.texcoord[1], tex2[2];');
369
VP.Add(' DP4 temp.w, vertex.texcoord[1], tex2[3];');
370
VP.Add(' MOV result.texcoord[' + IntToStr(texcoord) + '], temp;');
374
if BumpMethod = bmDot3TexCombiner then
376
if (boDiffuseTexture2 in BumpOptions)
377
and not (boUseSecondaryTexCoords in BumpOptions) then
378
VP.Add(' MOV result.texcoord[' + IntToStr(texcoord) + '], temp;');
382
VP.Add(' MOV result.texcoord[' + IntToStr(texcoord) + '], light;');
385
VP.Add(' MOV result.texcoord[' + IntToStr(texcoord) + '], eye;');
390
FVertexProgram.Assign(VP);
395
// GenerateFragmentProgram
398
function TGLBumpShader.GenerateFragmentProgram: string;
403
DoParallaxOffset: Boolean;
409
eyeTexCoords: Integer;
411
DoSpecular := not (SpecularMode = smOff);
412
DoTangent := (BumpSpace = bsTangentExternal) or (BumpSpace =
413
bsTangentQuaternion);
414
DoParallaxOffset := (boParallaxMapping in BumpOptions) and DoTangent;
417
normalTexCoords := texcoord;
418
if boUseSecondaryTexCoords in BumpOptions then
420
diffTexCoords := texcoord;
421
specTexCoords := texcoord;
423
lightTexCoords := texcoord;
425
eyeTexCoords := texcoord;
427
FP := TStringList.Create;
429
FP.Add('!!ARBfp1.0');
431
FP.Add('PARAM lightDiffuse = program.local[0];');
432
FP.Add('PARAM lightSpecular = program.local[1];');
433
FP.Add('PARAM lightAtten = program.local[2];');
434
FP.Add('PARAM materialDiffuse = state.material.diffuse;');
435
FP.Add('PARAM materialSpecular = state.material.specular;');
436
FP.Add('PARAM shininess = state.material.shininess;');
437
FP.Add('TEMP temp, tex, light, eye, normal, col, diff, spec;');
438
FP.Add('TEMP textureColor, reflect, atten, offset, texcoord;');
440
if DoSpecular or DoParallaxOffset then
442
// Get the eye vector
443
FP.Add(' DP3 eye, fragment.texcoord[' + IntToStr(eyeTexCoords) +
444
'], fragment.texcoord[' + IntToStr(eyeTexCoords) + '];');
445
FP.Add(' RSQ eye, eye.x;');
446
FP.Add(' MUL eye, fragment.texcoord[' + IntToStr(eyeTexCoords) +
450
if DoParallaxOffset then
452
// Get the parallax offset
453
FP.Add(' TEX textureColor, fragment.texcoord[' + IntToStr(normalTexCoords)
454
+ '], texture[0], 2D;');
455
FP.Add(Format(' MAD offset.x, textureColor.a, %f, %f;', [FParallaxOffset,
456
-0.5 * FParallaxOffset]));
457
FP.Add(' MUL offset, eye, offset.x;');
458
FP.Add(' ADD texcoord, fragment.texcoord[' + IntToStr(normalTexCoords) +
462
FP.Add(' MOV texcoord, fragment.texcoord[' + IntToStr(normalTexCoords) +
465
// Get the normalized normal vector
466
FP.Add(' TEX textureColor, texcoord, texture[0], 2D;');
467
FP.Add(' ADD normal, textureColor, -0.5;');
468
FP.Add(' DP3 temp, normal, normal;');
469
FP.Add(' RSQ temp, temp.x;');
470
FP.Add(' MUL normal, normal, temp.x;');
472
// Get the normalized light vector
473
FP.Add(' MOV light, fragment.texcoord[' + IntToStr(lightTexCoords) + '];');
474
if boLightAttenuation in BumpOptions then
475
FP.Add(' MOV atten.x, light.w;');
476
FP.Add(' DP3 light, light, light;');
477
FP.Add(' RSQ light, light.x;');
478
FP.Add(' MUL light, fragment.texcoord[' + IntToStr(lightTexCoords) +
481
// Calculate the diffuse color
482
FP.Add(' DP3 diff, normal, light;');
483
FP.Add(' MUL diff, diff, lightDiffuse;');
484
FP.Add(' MUL diff, diff, materialDiffuse;');
485
if boDiffuseTexture2 in BumpOptions then
487
if DoParallaxOffset then
489
FP.Add(' ADD temp, fragment.texcoord[' + IntToStr(diffTexCoords) +
491
FP.Add(' TEX textureColor, temp, texture[1], 2D;');
494
FP.Add(' TEX textureColor, fragment.texcoord[' + IntToStr(diffTexCoords)
495
+ '], texture[1], 2D;');
496
FP.Add(' MUL diff, diff, textureColor;');
504
FP.Add(' ADD eye, eye, light;');
505
FP.Add(' DP3 temp, eye, eye;');
506
FP.Add(' RSQ temp, temp.x;');
507
FP.Add(' MUL eye, eye, temp.x;');
508
FP.Add(' DP3_SAT spec, normal, eye;');
512
FP.Add(' DP3 reflect, normal, light;');
513
FP.Add(' MUL reflect, reflect.x, normal;');
514
FP.Add(' MUL reflect, 2.0, reflect;');
515
FP.Add(' ADD reflect, reflect, -light;');
516
FP.Add(' DP3_SAT spec, reflect, eye;');
519
Assert(False, 'Invalid specular mode!');
522
FP.Add(' POW spec, spec.x, shininess.x;');
523
FP.Add(' MUL spec, spec, materialSpecular;');
524
FP.Add(' MUL spec, spec, lightSpecular;');
525
if boSpecularTexture3 in BumpOptions then
527
if DoParallaxOffset then
529
FP.Add(' ADD temp, fragment.texcoord[' + IntToStr(specTexCoords) +
531
FP.Add(' TEX textureColor, temp, texture[2], 2D;');
534
FP.Add(' TEX textureColor, fragment.texcoord[' +
535
IntToStr(specTexCoords) + '], texture[2], 2D;');
536
FP.Add(' MUL spec, spec, textureColor;');
542
FP.Add(' ADD temp, diff, spec;')
544
FP.Add(' MOV temp, diff;');
546
if boLightAttenuation in BumpOptions then
548
FP.Add(' MUL atten.y, atten.x, atten.x;');
549
FP.Add(' MAD atten.x, lightAtten.y, atten.x, lightAtten.x;');
550
FP.Add(' MAD atten.x, lightAtten.z, atten.y, atten.x;');
551
FP.Add(' RCP atten.x, atten.x;');
552
FP.Add(' MUL temp, temp, atten.x;');
555
FP.Add(' MOV_SAT result.color, temp;');
556
FP.Add(' MOV result.color.w, 1.0;');
560
FFragmentProgram.Assign(FP);
568
procedure TGLBumpShader.DoLightPass(var rci: TGLRenderContextInfo;
571
dummyHandle, tempHandle: Integer;
572
lightPos, lightAtten,
573
materialDiffuse, lightDiffuse, lightSpecular: TVector;
575
FVertexProgramHandle.Enable;
576
FVertexProgramHandle.Bind;
578
// Set the light position to program.local[0]
579
GL.GetLightfv(GL_LIGHT0 + FLightIDs[0], GL_POSITION, @lightPos.V[0]);
580
GL.ProgramLocalParameter4fv(GL_VERTEX_PROGRAM_ARB, 0, @lightPos.V[0]);
582
// Set the light attenutation to program.local[1]
583
lightAtten.V[0] := rci.GLStates.LightConstantAtten[FLightIDs[0]];
584
lightAtten.V[1] := rci.GLStates.LightLinearAtten[FLightIDs[0]];
585
lightAtten.V[2] := rci.GLStates.LightQuadraticAtten[FLightIDs[0]];
586
GL.ProgramLocalParameter4fv(GL_VERTEX_PROGRAM_ARB, 1, @lightAtten.V[0]);
591
rci.GLStates.ActiveTexture := 0;
592
dummyHandle := rci.GLStates.TextureBinding[0, ttTexture2D];
593
GL.TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
594
GL.TexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_DOT3_RGB_ARB);
595
GL.TexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE0_ARB);
596
GL.TexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB);
598
rci.GLStates.ActiveTexture := 1;
599
rci.GLStates.ActiveTextureEnabled[ttTexture2D] := True;
600
tempHandle := rci.GLStates.TextureBinding[1, ttTexture2D];
601
if tempHandle = 0 then
602
rci.GLStates.TextureBinding[1, ttTexture2D] := dummyHandle;
603
lightDiffuse := rci.GLStates.LightDiffuse[FLightIDs[0]];
604
GL.GetMaterialfv(GL_FRONT, GL_DIFFUSE, @materialDiffuse);
605
lightDiffuse.V[0] := lightDiffuse.V[0] * materialDiffuse.V[0];
606
lightDiffuse.V[1] := lightDiffuse.V[1] * materialDiffuse.V[1];
607
lightDiffuse.V[2] := lightDiffuse.V[2] * materialDiffuse.V[2];
608
lightDiffuse.V[3] := lightDiffuse.V[3] * materialDiffuse.V[3];
609
GL.TexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, @lightDiffuse);
610
GL.TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
611
GL.TexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
612
GL.TexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB);
613
GL.TexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_CONSTANT_COLOR_ARB);
618
ActiveTextureEnabled[ttTexture2D] := False;
625
FFragmentProgramHandle.Enable;
626
FFragmentProgramHandle.Bind;
627
lightDiffuse := rci.GLStates.LightDiffuse[FLightIDs[0]];
628
lightSpecular := rci.GLStates.LightSpecular[FLightIDs[0]];
629
lightAtten.V[0] := rci.GLStates.LightConstantAtten[FLightIDs[0]];
631
GL.ProgramLocalParameter4fv(GL_FRAGMENT_PROGRAM_ARB, 0,
633
GL.ProgramLocalParameter4fv(GL_FRAGMENT_PROGRAM_ARB, 1,
634
@lightSpecular.V[0]);
635
GL.ProgramLocalParameter4fv(GL_FRAGMENT_PROGRAM_ARB, 2,
640
Assert(False, 'Invalid bump method!');
647
procedure TGLBumpShader.DoApply(var rci: TGLRenderContextInfo; Sender: TObject);
649
maxTextures, i: Integer;
650
ambient, LMaterialAmbient: TColorVector;
653
if (csDesigning in ComponentState) and not DesignTimeEnabled then
658
GL.GetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, @maxTextures);
662
if not GL.ARB_multitexture then
663
raise Exception.Create('This shader requires GL_ARB_multitexture.');
665
and ((BumpMethod <> bmDot3TexCombiner) or (BumpSpace = bsTangentExternal)) then
667
Exception.Create('The current shader settings require 3 or more texture units.');
669
and (BumpMethod <> bmDot3TexCombiner)
670
and (boUseSecondaryTexCoords in BumpOptions)
671
and (SpecularMode <> smOff) then
673
Exception.Create('The current shader settings require 4 or more texture units.');
675
if not Assigned(FVertexProgramHandle) then
677
FVertexProgramHandle := TGLARBVertexProgramHandle.CreateAndAllocate;
678
FVertexProgramHandle.LoadARBProgram(GenerateVertexProgram);
681
if not Assigned(FFragmentProgramHandle) then
682
if FBumpMethod = bmBasicARBFP then
684
FFragmentProgramHandle := TGLARBFragmentProgramHandle.CreateAndAllocate;
685
FFragmentProgramHandle.LoadARBProgram(GenerateFragmentProgram);
694
DesignTimeEnabled := False;
699
rci.GLStates.ActiveTexture := 0;
700
if rci.GLStates.ActiveTextureEnabled[ttTexture2D] then
701
for i := 0 to rci.GLStates.MaxLights - 1 do
703
if rci.GLStates.LightEnabling[i] then
706
FLightsEnabled := FLightIDs.Count;
708
FAmbientPass := False;
709
FDiffusePass := False;
711
if FLightIDs.Count > 0 then
714
rci.GLStates.DepthFunc := cfLEqual;
715
rci.GLStates.Disable(stBlend);
716
DoLightPass(rci, FLightIDs[0]);
725
ActiveTextureEnabled[ttTexture2D] := False;
727
ActiveTextureEnabled[ttTexture2D] := False;
729
ActiveTextureEnabled[ttTexture2D] := False;
732
GL.GetFloatv(GL_LIGHT_MODEL_AMBIENT, @ambient);
733
GL.GetMaterialfv(GL_FRONT, GL_AMBIENT, @LMaterialAmbient);
734
ambient.V[0] := ambient.V[0] * LMaterialAmbient.V[0];
735
ambient.V[1] := ambient.V[1] * LMaterialAmbient.V[1];
736
ambient.V[2] := ambient.V[2] * LMaterialAmbient.V[2];
737
GL.Color3fv(@ambient);
739
FAmbientPass := True;
747
function TGLBumpShader.DoUnApply(var rci: TGLRenderContextInfo): Boolean;
749
ambient, LMaterialAmbient: TVector;
752
if (csDesigning in ComponentState) and not DesignTimeEnabled then
757
if FLightIDs.Count > 0 then
761
DepthFunc := cfLEqual;
763
SetBlendFunc(bfOne, bfOne);
765
DoLightPass(rci, FLightIDs[0]);
771
else if not FDiffusePass and (FLightsEnabled <> 0)
772
and (boDiffuseTexture2 in BumpOptions)
773
and (BumpMethod = bmDot3TexCombiner) then
778
SetBlendFunc(bfDstColor, bfZero);
781
ActiveTextureEnabled[ttTexture2D] := False;
783
ActiveTextureEnabled[ttTexture2D] := True;
784
GL.TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
786
ActiveTextureEnabled[ttTexture2D] := False;
789
FDiffusePass := True;
794
else if not FAmbientPass then
798
FVertexProgramHandle.Disable;
799
if BumpMethod = bmBasicARBFP then
800
FFragmentProgramHandle.Disable;
804
ActiveTextureEnabled[ttTexture2D] := False;
806
ActiveTextureEnabled[ttTexture2D] := False;
808
ActiveTextureEnabled[ttTexture2D] := False;
811
DepthFunc := cfLEqual;
813
SetBlendFunc(bfOne, bfOne);
815
GL.GetFloatv(GL_LIGHT_MODEL_AMBIENT, @ambient);
816
GL.GetMaterialfv(GL_FRONT, GL_AMBIENT, @LMaterialAmbient);
817
ambient.V[0] := ambient.V[0] * LMaterialAmbient.V[0];
818
ambient.V[1] := ambient.V[1] * LMaterialAmbient.V[1];
819
ambient.V[2] := ambient.V[2] * LMaterialAmbient.V[2];
820
GL.Color3fv(@ambient);
822
FAmbientPass := True;
828
FVertexProgramHandle.Disable;
829
if BumpMethod = bmBasicARBFP then
830
FFragmentProgramHandle.Disable;
833
// DeleteVertexPrograms
836
procedure TGLBumpShader.DeleteVertexPrograms;
838
FVertexProgramHandle.Free;
839
FVertexProgramHandle := nil;
840
FVertexProgram.Clear;
843
// DeleteFragmentPrograms
846
procedure TGLBumpShader.DeleteFragmentPrograms;
848
FFragmentProgramHandle.Free;
849
FFragmentProgramHandle := nil;
850
FFragmentProgram.Clear;
856
procedure TGLBumpShader.SetBumpMethod(const Value: TBumpMethod);
858
if Value <> FBumpMethod then
860
FBumpMethod := Value;
861
DeleteVertexPrograms;
862
DeleteFragmentPrograms;
870
procedure TGLBumpShader.SetBumpSpace(const Value: TBumpSpace);
872
if Value <> FBumpSpace then
875
DeleteVertexPrograms;
876
DeleteFragmentPrograms;
884
procedure TGLBumpShader.SetBumpOptions(const Value: TBumpOptions);
886
if Value <> FBumpOptions then
888
FBumpOptions := Value;
889
DeleteVertexPrograms;
890
DeleteFragmentPrograms;
898
procedure TGLBumpShader.SetSpecularMode(const Value: TSpecularMode);
900
if Value <> FSpecularMode then
902
FSpecularMode := Value;
903
DeleteVertexPrograms;
904
DeleteFragmentPrograms;
909
// SetDesignTimeEnabled
912
procedure TGLBumpShader.SetDesignTimeEnabled(const Value: Boolean);
914
if Value <> FDesignTimeEnabled then
916
FDesignTimeEnabled := Value;
924
procedure TGLBumpShader.SetParallaxOffset(const Value: Single);
926
if Value <> FParallaxOffset then
928
FParallaxOffset := Value;
929
DeleteVertexPrograms;
930
DeleteFragmentPrograms;