LZScene

Форк
0
/
GLSLDiffuseSpecularShader.pas 
846 строк · 28.5 Кб
1
//
2
// This unit is part of the GLScene Engine https://github.com/glscene
3
//
4
{
5
    This is a collection of GLSL diffuse-specular shaders.
6

7
	 History :  
8
       09/03/13 - Yar - Added point, parallel, spot and parallel spot light's style support to TGLSLMLDiffuseSpecularShader
9
                           Deleted TGLSLDiffuseSpecularShaderAM, TGLSLDiffuseSpecularShaderAM
10
       17/02/13 - Yar - Added fog support to TGLSLMLDiffuseSpecularShader
11
       16/03/11 - Yar - Fixes after emergence of GLMaterialEx
12
       23/10/10 - Yar - Bugfixed memory leak
13
       23/08/10 - Yar - Replaced OpenGL1x to OpenGLTokens
14
       07/01/10 - DaStr - Bugfixed all DoInitialize() calls
15
                              (thanks YarUnderoaker)  
16
       25/07/09 - DaStr - Fixed a bug with "dot(reflect_vec, LightVector)" clamping
17
                              which occured on all GeForce 8x and later graphic cards
18
       24/07/09 - DaStr - Added Fog support for single-light shaders and fixed
19
                              a bug with material Alpha (thanks Controller)
20
       02/09/07 - LC - Fixed texture bug in TGLSLMLDiffuseSpecularShader.
21
                          (Bugtracker ID = 1786286)
22
       03/04/07 - LC - Shader didn't respect the texture matrix. Changed
23
                          vertex shader to fix this. (Bugtracker ID = 1693389)
24
       20/03/07 - DaStr - Made changes related to the new parameter passing model
25
       06/03/07 - DaStr - Again replaced DecimalSeparator stuff with
26
                              a single Str procedure (thanks Uwe Raabe)
27
       03/03/07 - DaStr - Made compatible with Delphi6
28
                             Added more stuff to RegisterClasses()
29
       21/02/07 - DaStr - Initial version (contributed to GLScene)
30

31

32
    This is a collection of GLSL Diffuse Specular shaders, comes in these variaties
33
              (to know what these suffixes and prefixes mean see GLCustomShader.pas):
34
      - TGLSLDiffuseSpecularShader
35
      - TGLSLDiffuseSpecularShaderMT
36

37
      - TGLSLMLDiffuseSpecularShader
38
      - TGLSLMLDiffuseSpecularShaderMT
39

40
    Notes:
41
     1) TGLSLDiffuseSpecularShader takes all Material parameters directly
42
      from OpenGL (that includes TGLMaterial's)
43
     2) TGLSLDiffuseSpecularShader takes all Light parameters directly
44
      from OpenGL (that includes TGLLightSource's)
45

46

47
    Previous version history:
48
      v1.0    01 November  '2006  Creation
49
      v1.1    19 December  '2006  TGLBaseCustomGLSLDiffuseSpecular[MT] abstracted
50
                                  5 different versions of this shader added
51
      v1.1.2  06 February  '2007  IGLMaterialLibrarySupported renamed to
52
                                   IGLMaterialLibrarySupported
53
      v1.2    16 February  '2007  Updated to the latest CVS version of GLScene
54

55
}
56
unit GLSLDiffuseSpecularShader;
57

58
interface
59

60
{$I GLScene.inc}
61

62
uses
63
  Classes, SysUtils,
64

65
  GLTexture, GLScene, GLVectorGeometry, OpenGLTokens, GLStrings, GLCustomShader,
66
  GLSLShader, GLColor, GLRenderContextInfo, GLMaterial;
67

68
type
69
  EGLSLDiffuseSpecularShaderException = class(EGLSLShaderException);
70

71
  // Abstract class.
72
  TGLBaseCustomGLSLDiffuseSpecular = class(TGLCustomGLSLShader)
73
  private
74
    FLightPower: Single;
75
    FRealisticSpecular: Boolean;
76
    FFogSupport: TGLShaderFogSupport;
77
    procedure SetRealisticSpecular(const Value: Boolean);
78
    procedure SetFogSupport(const Value: TGLShaderFogSupport);
79
  protected
80
    procedure DoApply(var rci : TGLRenderContextInfo; Sender : TObject); override;
81
    function DoUnApply(var rci: TGLRenderContextInfo): Boolean; override;
82
  public
83
    constructor Create(AOwner : TComponent); override;
84
    property LightPower: Single read FLightPower write FLightPower;
85
    property RealisticSpecular: Boolean read FRealisticSpecular write SetRealisticSpecular;
86

87
    // User can disable fog support and save some FPS if he doesn't need it.
88
    property FogSupport: TGLShaderFogSupport read FFogSupport write SetFogSupport default sfsAuto;
89
  end;
90

91
  // Abstract class.
92
  TGLBaseGLSLDiffuseSpecularShaderMT = class(TGLBaseCustomGLSLDiffuseSpecular, IGLMaterialLibrarySupported)
93
  private
94
    FMaterialLibrary: TGLMaterialLibrary;
95
    FMainTexture: TGLTexture;
96
    FMainTextureName: TGLLibMaterialName;
97
    function GetMainTextureName: TGLLibMaterialName;
98
    procedure SetMainTextureName(const Value: TGLLibMaterialName);
99
    // Implementing IGLMaterialLibrarySupported.
100
    function GetMaterialLibrary: TGLAbstractMaterialLibrary;
101
  protected
102
    procedure SetMaterialLibrary(const Value: TGLMaterialLibrary); virtual;
103
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
104
    procedure DoApply(var rci : TGLRenderContextInfo; Sender : TObject); override;
105
  public
106
    property MainTexture: TGLTexture read FMainTexture write FMainTexture;
107
    property MainTextureName: TGLLibMaterialName read GetMainTextureName write SetMainTextureName;
108
    property MaterialLibrary: TGLMaterialLibrary read FMaterialLibrary write SetMaterialLibrary;
109
  end;
110

111
                     {********  Single Light  ************}
112

113
  TGLCustomGLSLDiffuseSpecularShader = class(TGLBaseCustomGLSLDiffuseSpecular)
114
  protected
115
    procedure DoInitialize(var rci: TGLRenderContextInfo; Sender: TObject); override;
116
    procedure DoApply(var rci : TGLRenderContextInfo; Sender : TObject); override;
117
  end;
118

119

120
  TGLCustomGLSLDiffuseSpecularShaderMT = class(TGLBaseGLSLDiffuseSpecularShaderMT)
121
  protected
122
    procedure DoInitialize(var rci: TGLRenderContextInfo; Sender: TObject); override;
123
  end;
124

125
                     {********  Multi Light  ************}
126

127
  { Note: probably LightCount should be replaced by LightSources, like in
128
     GLSLBumpShader.pas }
129

130
  TLightRecord = record
131
    Enabled: Boolean;
132
    Style: TLightStyle;
133
  end;
134

135
  TGLCustomGLSLMLDiffuseSpecularShader = class(TGLBaseCustomGLSLDiffuseSpecular)
136
  private
137
    FLightTrace: array[0..7] of TLightRecord;
138
  protected
139
    procedure DoInitialize(var rci: TGLRenderContextInfo; Sender: TObject); override;
140
    procedure DoApply(var rci: TGLRenderContextInfo; Sender: TObject); override;
141
  public
142
    constructor Create(AOwner : TComponent); override;
143
  end;
144

145
  TGLCustomGLSLMLDiffuseSpecularShaderMT = class(TGLBaseGLSLDiffuseSpecularShaderMT)
146
  private
147
    FLightTrace: array[0..7] of TLightRecord;
148
  protected
149
    procedure DoInitialize(var rci: TGLRenderContextInfo; Sender: TObject); override;
150
    procedure DoApply(var rci: TGLRenderContextInfo; Sender: TObject); override;
151
  public
152
    constructor Create(AOwner : TComponent); override;
153
  end;
154

155

156
                     {********  Published Stuff  ************}
157

158
  TGLSLDiffuseSpecularShaderMT = class(TGLCustomGLSLDiffuseSpecularShaderMT)
159
  published
160
    property MainTextureName;
161

162
    property LightPower;
163
    property FogSupport;
164
  end;
165

166
  TGLSLDiffuseSpecularShader = class(TGLCustomGLSLDiffuseSpecularShader)
167
  published
168
    property LightPower;
169
    property FogSupport;
170
  end;
171

172

173
  TGLSLMLDiffuseSpecularShaderMT = class(TGLCustomGLSLMLDiffuseSpecularShaderMT)
174
  published
175
    property MainTextureName;
176

177
    property LightPower;
178
    property FogSupport;
179
  end;
180

181
  TGLSLMLDiffuseSpecularShader = class(TGLCustomGLSLMLDiffuseSpecularShader)
182
  published
183
    property LightPower;
184
    property FogSupport;
185
  end;
186

187
implementation
188

189
procedure GetVertexProgramCode(const Code: TStrings;
190
  AFogSupport: Boolean; var rci: TGLRenderContextInfo);
191
begin
192
  with Code do
193
  begin
194
    Clear;
195
    Add('varying vec3 Normal; ');
196
    Add('varying vec4 Position; ');
197
    if AFogSupport then
198
    begin
199
      Add('varying float fogFactor; ');
200
    end;
201
    Add(' ');
202
    Add(' ');
203
    Add('void main(void) ');
204
    Add('{ ');
205
    Add('  gl_Position = ftransform(); ');
206
    Add('  gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; ');
207
    Add('  Normal = normalize(gl_NormalMatrix * gl_Normal); ');
208
    Add('  Position = gl_ModelViewMatrix * gl_Vertex; ');
209

210
    if AFogSupport then
211
    begin
212
    Add('  const float LOG2 = 1.442695; ');
213
    Add('  gl_FogFragCoord = length(Position.xyz); ');
214

215
    case TGLSceneBuffer(rci.buffer).FogEnvironment.FogMode of
216
      fmLinear:
217
        Add('  fogFactor = (gl_Fog.end - gl_FogFragCoord) * gl_Fog.scale; ');
218
      fmExp, // Yep, I don't know about this type, so I use fmExp2.
219
      fmExp2:
220
      begin
221
        Add('  fogFactor = exp2( -gl_Fog.density * ');
222
        Add('  				   gl_Fog.density * ');
223
        Add('  				   gl_FogFragCoord * ');
224
        Add('  				   gl_FogFragCoord * ');
225
        Add('  				   LOG2 ); ');
226
      end;
227
    else
228
      Assert(False, glsUnknownType);
229
    end;
230

231
      Add('  fogFactor = clamp(fogFactor, 0.0, 1.0); ');
232
    end;
233

234
    Add('} ');
235
  end;
236
end;
237

238
procedure AddLightSub(const Code: TStrings);
239
begin
240
  with Code do
241
  begin
242
    Add('void pointLight(in int i, in vec3 normal, in vec3 eye, in vec3 ecPosition3)');
243
    Add('{');
244
    Add('   float nDotVP;       // normal . light direction');
245
    Add('   float nDotHV;       // normal . light half vector');
246
    Add('   float pf;           // power factor');
247
    Add('   float attenuation;  // computed attenuation factor');
248
    Add('   float d;            // distance from surface to light source');
249
    Add('   vec3  VP;           // direction from surface to light position');
250
    Add('   vec3  halfVector;   // direction of maximum highlights');
251
    Add(' ');
252
    Add('   // Compute vector from surface to light position');
253
    Add('   VP = vec3 (gl_LightSource[i].position) - ecPosition3;');
254
    Add(' ');
255
    Add('   // Compute distance between surface and light position');
256
    Add('   d = length(VP);');
257
    Add(' ');
258
    Add('   // Normalize the vector from surface to light position');
259
    Add('   VP = normalize(VP);');
260
    Add(' ');
261
    Add('   // Compute attenuation');
262
    Add('   attenuation = 1.0 / (gl_LightSource[i].constantAttenuation +');
263
    Add('       gl_LightSource[i].linearAttenuation * d +');
264
    Add('       gl_LightSource[i].quadraticAttenuation * d * d);');
265
    Add(' ');
266
    Add('   halfVector = normalize(VP + eye);');
267
    Add(' ');
268
    Add('   nDotVP = max(0.0, dot(normal, VP));');
269
    Add('   nDotHV = max(0.0, dot(normal, halfVector));');
270
    Add(' ');
271
    Add('   if (nDotVP == 0.0)');
272
    Add('   {');
273
    Add('       pf = 0.0;');
274
    Add('   }');
275
    Add('   else');
276
    Add('   {');
277
    Add('       pf = pow(nDotHV, gl_FrontMaterial.shininess);');
278
    Add(' ');
279
    Add('   }');
280
    Add('   Ambient  += gl_LightSource[i].ambient * attenuation;');
281
    Add('   Diffuse  += gl_LightSource[i].diffuse * nDotVP * attenuation;');
282
    Add('   Specular += gl_LightSource[i].specular * pf * attenuation;');
283
    Add('}');
284
    Add(' ');
285
    Add('void directionalLight(in int i, in vec3 normal)');
286
    Add('{');
287
    Add('   float nDotVP;         // normal . light direction');
288
    Add('   float nDotHV;         // normal . light half vector');
289
    Add('   float pf;             // power factor');
290
    Add(' ');
291
    Add('   nDotVP = max(0.0, dot(normal, normalize(vec3 (gl_LightSource[i].position))));');
292
    Add('   nDotHV = max(0.0, dot(normal, vec3 (gl_LightSource[i].halfVector)));');
293
    Add(' ');
294
    Add('   if (nDotVP == 0.0)');
295
    Add('   {');
296
    Add('       pf = 0.0;');
297
    Add('   }');
298
    Add('   else');
299
    Add('   {');
300
    Add('       pf = pow(nDotHV, gl_FrontMaterial.shininess);');
301
    Add(' ');
302
    Add('   }');
303
    Add('   Ambient  += gl_LightSource[i].ambient;');
304
    Add('   Diffuse  += gl_LightSource[i].diffuse * nDotVP;');
305
    Add('   Specular += gl_LightSource[i].specular * pf;');
306
    Add('}');
307
    Add('void spotLight(in int i, in vec3 normal, in vec3 eye, in vec3 ecPosition3)');
308
    Add('{');
309
    Add('   float nDotVP;            // normal . light direction');
310
    Add('   float nDotHV;            // normal . light half vector');
311
    Add('   float pf;                // power factor');
312
    Add('   float spotDot;           // cosine of angle between spotlight');
313
    Add('   float spotAttenuation;   // spotlight attenuation factor');
314
    Add('   float attenuation;       // computed attenuation factor');
315
    Add('   float d;                 // distance from surface to light source');
316
    Add('   vec3  VP;                // direction from surface to light position');
317
    Add('   vec3  halfVector;        // direction of maximum highlights');
318
    Add(' ');
319
    Add('   // Compute vector from surface to light position');
320
    Add('   VP = vec3 (gl_LightSource[i].position) - ecPosition3;');
321
    Add(' ');
322
    Add('   // Compute distance between surface and light position');
323
    Add('   d = length(VP);');
324
    Add(' ');
325
    Add('   // Normalize the vector from surface to light position');
326
    Add('   VP = normalize(VP);');
327
    Add(' ');
328
    Add('   // Compute attenuation');
329
    Add('   attenuation = 1.0 / (gl_LightSource[i].constantAttenuation +');
330
    Add('       gl_LightSource[i].linearAttenuation * d +');
331
    Add('       gl_LightSource[i].quadraticAttenuation * d * d);');
332
    Add(' ');
333
    Add('   // See if point on surface is inside cone of illumination');
334
    Add('   spotDot = dot(-VP, normalize(gl_LightSource[i].spotDirection));');
335
    Add(' ');
336
    Add('   if (spotDot < gl_LightSource[i].spotCosCutoff)');
337
    Add('   {');
338
    Add('       spotAttenuation = 0.0; // light adds no contribution');
339
    Add('   }');
340
    Add('   else');
341
    Add('   {');
342
    Add('       spotAttenuation = pow(spotDot, gl_LightSource[i].spotExponent);');
343
    Add(' ');
344
    Add('   }');
345
    Add('   // Combine the spotlight and distance attenuation.');
346
    Add('   attenuation *= spotAttenuation;');
347
    Add(' ');
348
    Add('   halfVector = normalize(VP + eye);');
349
    Add(' ');
350
    Add('   nDotVP = max(0.0, dot(normal, VP));');
351
    Add('   nDotHV = max(0.0, dot(normal, halfVector));');
352
    Add(' ');
353
    Add('   if (nDotVP == 0.0)');
354
    Add('   {');
355
    Add('       pf = 0.0;');
356
    Add('   }');
357
    Add('   else');
358
    Add('   {');
359
    Add('       pf = pow(nDotHV, gl_FrontMaterial.shininess);');
360
    Add(' ');
361
    Add('   }');
362
    Add('   Ambient  += gl_LightSource[i].ambient * attenuation;');
363
    Add('   Diffuse  += gl_LightSource[i].diffuse * nDotVP * attenuation;');
364
    Add('   Specular += gl_LightSource[i].specular * pf * attenuation;');
365
    Add(' ');
366
    Add('}');
367
    Add('void infiniteSpotLight(in int i, in vec3 normal)');
368
    Add('{');
369
    Add('   float nDotVP;         // normal . light direction');
370
    Add('   float nDotHV;         // normal . light half vector');
371
    Add('   float pf;             // power factor');
372
    Add('   float spotAttenuation;');
373
    Add('   vec3  Ppli;');
374
    Add('   vec3  Sdli;');
375
    Add(' ');
376
    Add('   nDotVP = max(0.0, dot(normal, normalize(vec3 (gl_LightSource[i].position))));');
377
    Add('   nDotHV = max(0.0, dot(normal, vec3 (gl_LightSource[i].halfVector)));');
378
    Add(' ');
379
    Add('   Ppli = -normalize(vec3(gl_LightSource[i].position));');
380
    Add('   Sdli = normalize(vec3(gl_LightSource[i].spotDirection));');
381
    Add(' ');
382
    Add('   spotAttenuation = pow(dot(Ppli, Sdli), gl_LightSource[i].spotExponent);');
383
    Add('   if (nDotVP == 0.0)');
384
    Add('   {');
385
    Add('       pf = 0.0;');
386
    Add('   }');
387
    Add('   else');
388
    Add('   {');
389
    Add('       pf = pow(nDotHV, gl_FrontMaterial.shininess);');
390
    Add(' ');
391
    Add('   }');
392
    Add('   Ambient  += gl_LightSource[i].ambient * spotAttenuation;');
393
    Add('   Diffuse  += gl_LightSource[i].diffuse * nDotVP * spotAttenuation;');
394
    Add('   Specular += gl_LightSource[i].specular * pf * spotAttenuation;');
395
    Add('}');
396
  end;
397
end;
398

399
procedure GetMLFragmentProgramCodeMid(const Code: TStrings;
400
  const CurrentLight: Integer; AStyle: TLightStyle);
401
begin
402
  with Code do
403
  begin
404
    case AStyle of
405
      lsOmni: Add(Format('  pointLight(%d, N, eye, Pos); ', [CurrentLight]));
406
      lsSpot: Add(Format('  spotLight(%d, N, eye, Pos); ', [CurrentLight]));
407
      lsParallel: Add(Format('  directionalLight(%d, N); ', [CurrentLight]));
408
      lsParallelSpot: Add(Format('  infiniteSpotLight(%d, N); ', [CurrentLight]));
409
    end;
410
  end;
411
end;
412

413
procedure GetFragmentProgramCode(const Code: TStrings;
414
  const ARealisticSpecular: Boolean; const AFogSupport: Boolean;
415
  aRci: TGLRenderContextInfo);
416
var
417
  scene: TGLScene;
418
begin
419
  with Code do
420
  begin
421
    Clear;
422
    Add('uniform float LightIntensity; ');
423
    Add('uniform sampler2D MainTexture; ');
424
    Add(' ');
425
    Add('varying vec3 Normal; ');
426
    Add('varying vec4 Position; ');
427

428
    if AFogSupport then
429
    begin
430
      Add('varying float fogFactor; ');
431
    end;
432

433
    Add('vec4 Ambient;');
434
    Add('vec4 Diffuse;');
435
    Add('vec4 Specular;');
436

437
    AddLightSub(Code);
438

439
    Add('void main(void) ');
440
    Add('{ ');
441
    Add('  vec4 TextureContrib = texture2D(MainTexture, gl_TexCoord[0].xy); ');
442
    Add('  vec3 eye = vec3(0.0, 0.0, 1.0); ');
443
    Add('  Diffuse = vec4(0.0); ');
444
    Add('  Specular = vec4(0.0); ');
445
    Add('  Ambient = vec4(0.0); ');
446
    Add('  vec3 Pos = Position.xyz; ');
447
    Add('  vec3 N = normalize(Normal); ');
448
    scene := TGLScene(ARci.scene);
449
    if (scene.Lights.Count > 0) then
450
      GetMLFragmentProgramCodeMid(Code, 0,
451
      TGLLightSource(scene.Lights[0]).LightStyle);
452

453
    if ARealisticSpecular then
454
      Add('  gl_FragColor = LightIntensity * (TextureContrib * (gl_FrontLightModelProduct.sceneColor + Ambient * gl_FrontMaterial.ambient + Diffuse * gl_FrontMaterial.diffuse) + Specular * gl_FrontMaterial.specular); ')
455
    else
456
      Add('  gl_FragColor = LightIntensity * TextureContrib * (gl_FrontLightModelProduct.sceneColor + Ambient * gl_FrontMaterial.ambient + Diffuse * gl_FrontMaterial.diffuse + Specular * gl_FrontMaterial.specular); ');
457

458
    if AFogSupport then
459
      Add('  gl_FragColor = mix(gl_Fog.color, gl_FragColor, fogFactor);');
460

461
    Add('  gl_FragColor.a = TextureContrib.a; ');
462
    Add('} ');
463
  end;
464
end;
465

466
procedure GetMLFragmentProgramCodeBeg(const Code: TStrings;
467
  const AFogSupport: Boolean);
468
begin
469
  with Code do
470
  begin
471
    Clear;
472
    Add('uniform sampler2D MainTexture;');
473
    Add('uniform float LightIntensity; ');
474
    Add('uniform float SpecPower; ');
475
    Add('varying vec3 Normal;');
476
    Add('varying vec4 Position;');
477
    if AFogSupport then
478
    begin
479
      Add('varying float fogFactor;');
480
    end;
481
    Add('vec4 Ambient;');
482
    Add('vec4 Diffuse;');
483
    Add('vec4 Specular;');
484
    AddLightSub(Code);
485

486
    Add('void main(void) ');
487
    Add('{ ');
488
    Add('  vec4 TextureContrib = texture2D(MainTexture, gl_TexCoord[0].st); ');
489
    Add('  vec3 eye = vec3(0.0, 0.0, 1.0); ');
490
    Add('  Diffuse = vec4(0.0); ');
491
    Add('  Specular = vec4(0.0); ');
492
    Add('  Ambient = vec4(0.0); ');
493
    Add('  vec3 Pos = Position.xyz; ');
494
    Add('  vec3 N = normalize(Normal); ');
495
  end;
496
end;
497

498
procedure GetMLFragmentProgramCodeEnd(const Code: TStrings;
499
  const ARealisticSpecular: Boolean;
500
  AFogSupport: Boolean);
501
begin
502
  with Code do
503
  begin
504
    if ARealisticSpecular then
505
      Add('  gl_FragColor = LightIntensity * (TextureContrib * (gl_FrontLightModelProduct.sceneColor + Ambient * gl_FrontMaterial.ambient + Diffuse * gl_FrontMaterial.diffuse) + Specular * gl_FrontMaterial.specular); ')
506
    else
507
      Add('  gl_FragColor = LightIntensity * TextureContrib * (gl_FrontLightModelProduct.sceneColor + Ambient * gl_FrontMaterial.ambient + Diffuse * gl_FrontMaterial.diffuse + Specular * gl_FrontMaterial.specular); ');
508

509
    if AFogSupport then
510
      Add('  gl_FragColor = mix(gl_Fog.color, gl_FragColor, fogFactor);');
511

512
    Add('  gl_FragColor.a = TextureContrib.a; ');
513
    Add('} ');
514
  end;
515
end;
516

517

518
{ TGLBaseCustomGLSLDiffuseSpecular }
519

520
constructor TGLBaseCustomGLSLDiffuseSpecular.Create(
521
  AOwner: TComponent);
522
begin
523
  inherited;
524

525
  FLightPower     := 1;
526
  FFogSupport := sfsAuto;
527
  TStringList(VertexProgram.Code).OnChange := nil;
528
  TStringList(FragmentProgram.Code).OnChange := nil;
529
  VertexProgram.Enabled := true;
530
  FragmentProgram.Enabled := true;
531
end;
532

533
procedure TGLBaseCustomGLSLDiffuseSpecular.DoApply(
534
  var rci: TGLRenderContextInfo; Sender: TObject);
535
begin
536
  GetGLSLProg.UseProgramObject;
537
  Param['LightIntensity'].AsVector1f := FLightPower;
538
end;
539

540
function TGLBaseCustomGLSLDiffuseSpecular.DoUnApply(
541
  var rci: TGLRenderContextInfo): Boolean;
542
begin
543
  Result := False;
544
  GetGLSLProg.EndUseProgramObject;
545
end;
546

547
procedure TGLBaseCustomGLSLDiffuseSpecular.SetFogSupport(
548
  const Value: TGLShaderFogSupport);
549
begin
550
  if FFogSupport <> Value then
551
  begin
552
    FFogSupport := Value;
553
    Self.FinalizeShader;
554
  end;
555
end;
556

557
procedure TGLBaseCustomGLSLDiffuseSpecular.SetRealisticSpecular(
558
  const Value: Boolean);
559
begin
560
  if FRealisticSpecular <> Value then
561
  begin
562
    FRealisticSpecular := Value;
563
    Self.FinalizeShader;
564
  end;
565
end;
566

567

568
{ TGLBaseGLSLDiffuseSpecularShaderMT }
569

570
procedure TGLBaseGLSLDiffuseSpecularShaderMT.DoApply(
571
  var rci: TGLRenderContextInfo; Sender: TObject);
572
begin
573
  inherited;
574
  Param['MainTexture'].AsTexture2D[0] := FMainTexture;
575
end;
576

577
function TGLBaseGLSLDiffuseSpecularShaderMT.GetMainTextureName: TGLLibMaterialName;
578
begin
579
  Result := FMaterialLibrary.GetNameOfTexture(FMainTexture);
580
end;
581

582
function TGLBaseGLSLDiffuseSpecularShaderMT.GetMaterialLibrary: TGLAbstractMaterialLibrary;
583
begin
584
  Result := FMaterialLibrary;
585
end;
586

587
procedure TGLBaseGLSLDiffuseSpecularShaderMT.Notification(
588
  AComponent: TComponent; Operation: TOperation);
589
var
590
  Index: Integer;
591
begin
592
  inherited;
593
  if Operation = opRemove then
594
    if AComponent = FMaterialLibrary then
595
      if FMaterialLibrary <> nil then
596
      begin
597
        //need to nil the textures that were ownned by it
598
        if FMainTexture <> nil then
599
        begin
600
          Index := FMaterialLibrary.Materials.GetTextureIndex(FMainTexture);
601
          if Index <> -1 then
602
            FMainTexture := nil;
603
        end;
604
        FMaterialLibrary := nil;
605
      end;
606
end;
607

608
procedure TGLBaseGLSLDiffuseSpecularShaderMT.SetMainTextureName(
609
  const Value: TGLLibMaterialName);
610
begin
611
  if FMaterialLibrary = nil then
612
  begin
613
    FMainTextureName := Value;
614
    if not (csLoading in ComponentState) then
615
      raise EGLSLDiffuseSpecularShaderException.Create(glsErrorEx + glsMatLibNotDefined);
616
  end
617
  else
618
  begin
619
    FMainTexture := FMaterialLibrary.TextureByName(Value);
620
    FMainTextureName := '';
621
  end;
622
end;
623

624
procedure TGLBaseGLSLDiffuseSpecularShaderMT.SetMaterialLibrary(
625
  const Value: TGLMaterialLibrary);
626
begin
627
  if FMaterialLibrary <> nil then
628
    FMaterialLibrary.RemoveFreeNotification(Self);
629
  FMaterialLibrary := Value;
630

631
  if FMaterialLibrary <> nil then
632
  begin
633
    FMaterialLibrary.FreeNotification(Self);
634

635
    if FMainTextureName <> '' then
636
      SetMainTextureName(FMainTextureName);
637
  end
638
  else
639
    FMainTextureName := '';
640
end;
641

642
{ TGLCustomGLSLDiffuseSpecularShaderMT }
643

644
procedure TGLCustomGLSLDiffuseSpecularShaderMT.DoInitialize(var rci: TGLRenderContextInfo; Sender: TObject);
645
begin
646
  GetVertexProgramCode(VertexProgram.Code, IsFogEnabled(FFogSupport, rci), rci);
647
  GetFragmentProgramCode(FragmentProgram.Code, FRealisticSpecular, IsFogEnabled(FFogSupport, rci), rci);
648
  VertexProgram.Enabled := True;
649
  FragmentProgram.Enabled := True;
650
  inherited;
651
end;
652

653
{ TGLCustomGLSLDiffuseSpecularShader }
654

655
procedure TGLCustomGLSLDiffuseSpecularShader.DoApply(
656
  var rci: TGLRenderContextInfo; Sender: TObject);
657
begin
658
  inherited;
659
  Param['MainTexture'].AsVector1i := 0;  // Use the current texture.
660
end;
661

662
procedure TGLCustomGLSLDiffuseSpecularShader.DoInitialize(var rci: TGLRenderContextInfo; Sender: TObject);
663
begin
664
  GetVertexProgramCode(VertexProgram.Code, IsFogEnabled(FFogSupport, rci), rci);
665
  GetFragmentProgramCode(FragmentProgram.Code, FRealisticSpecular, IsFogEnabled(FFogSupport, rci), rci);
666
  VertexProgram.Enabled := True;
667
  FragmentProgram.Enabled := True;
668
  inherited;
669
end;
670

671
{ TGLCustomGLSLMLDiffuseSpecularShader }
672

673
constructor TGLCustomGLSLMLDiffuseSpecularShader.Create(
674
  AOwner: TComponent);
675
begin
676
  inherited;
677
end;
678

679
procedure TGLCustomGLSLMLDiffuseSpecularShader.DoApply(var rci: TGLRenderContextInfo; Sender: TObject);
680
var
681
  I: Integer;
682
  scene: TGLScene;
683
  needRecompile: Boolean;
684
begin
685
  scene := TGLScene(rci.scene);
686
  needRecompile := False;
687
  for I := 0 to scene.Lights.Count - 1 do
688
  begin
689
    if Assigned(scene.Lights[I]) then
690
    begin
691
      if FLightTrace[I].Enabled <> TGLLightSource(scene.Lights[I]).Shining then
692
      begin
693
        needRecompile := True;
694
        break;
695
      end;
696
      if FLightTrace[I].Style <> TGLLightSource(scene.Lights[I]).LightStyle then
697
      begin
698
        needRecompile := True;
699
        break;
700
      end;
701
    end
702
    else
703
      if FLightTrace[I].Enabled then
704
      begin
705
        needRecompile := True;
706
        break;
707
      end;
708
  end;
709
  if needRecompile then
710
  begin
711
    FinalizeShader;
712
    InitializeShader(rci, Sender);
713
  end;
714

715
  inherited;
716
  Param['MainTexture'].AsVector1i := 0;  // Use the current texture.
717
end;
718

719
procedure TGLCustomGLSLMLDiffuseSpecularShader.DoInitialize(var rci: TGLRenderContextInfo; Sender: TObject);
720
var
721
  I: Integer;
722
  scene: TGLScene;
723
begin
724
  GetVertexProgramCode(VertexProgram.Code, IsFogEnabled(FFogSupport, rci), rci);
725
  with FragmentProgram.Code do
726
  begin
727
    GetMLFragmentProgramCodeBeg(FragmentProgram.Code, IsFogEnabled(FFogSupport, rci));
728

729
    // Repeat for all lights.
730
    scene := TGLScene(rci.scene);
731
    for I := 0 to scene.Lights.Count - 1 do
732
    begin
733
      if Assigned(scene.Lights[I]) then
734
      begin
735
        FLightTrace[I].Enabled := TGLLightSource(scene.Lights[I]).Shining;
736
        FLightTrace[I].Style := TGLLightSource(scene.Lights[I]).LightStyle;
737
        if FLightTrace[I].Enabled then
738
          GetMLFragmentProgramCodeMid(FragmentProgram.Code, I, FLightTrace[I].Style);
739
      end
740
      else
741
        FLightTrace[I].Enabled := False;
742
    end;
743

744
    GetMLFragmentProgramCodeEnd(FragmentProgram.Code,
745
      FRealisticSpecular, IsFogEnabled(FFogSupport, rci));
746
  end;
747
  VertexProgram.Enabled := True;
748
  FragmentProgram.Enabled := True;
749
  inherited DoInitialize(rci, Sender);
750
end;
751

752
{ TGLCustomGLSLMLDiffuseSpecularShaderMT }
753

754
constructor TGLCustomGLSLMLDiffuseSpecularShaderMT.Create(
755
  AOwner: TComponent);
756
begin
757
  inherited;
758
end;
759

760
procedure TGLCustomGLSLMLDiffuseSpecularShaderMT.DoApply(
761
  var rci: TGLRenderContextInfo; Sender: TObject);
762
var
763
  I: Integer;
764
  scene: TGLScene;
765
  needRecompile: Boolean;
766
begin
767
  scene := TGLScene(rci.scene);
768
  needRecompile := False;
769
  for I := 0 to scene.Lights.Count - 1 do
770
  begin
771
    if Assigned(scene.Lights[I]) then
772
    begin
773
      if FLightTrace[I].Enabled <> TGLLightSource(scene.Lights[I]).Shining then
774
      begin
775
        needRecompile := True;
776
        break;
777
      end;
778
      if FLightTrace[I].Style <> TGLLightSource(scene.Lights[I]).LightStyle then
779
      begin
780
        needRecompile := True;
781
        break;
782
      end;
783
    end
784
    else
785
      if FLightTrace[I].Enabled then
786
      begin
787
        needRecompile := True;
788
        break;
789
      end;
790
  end;
791
  if needRecompile then
792
  begin
793
    FinalizeShader;
794
    InitializeShader(rci, Sender);
795
  end;
796

797
  inherited;
798
end;
799

800
procedure TGLCustomGLSLMLDiffuseSpecularShaderMT.DoInitialize(var rci: TGLRenderContextInfo; Sender: TObject);
801
var
802
  I: Integer;
803
  scene: TGLScene;
804
begin
805
  GetVertexProgramCode(VertexProgram.Code, IsFogEnabled(FFogSupport, rci), rci);
806
  with FragmentProgram.Code do
807
  begin
808
    GetMLFragmentProgramCodeBeg(FragmentProgram.Code, IsFogEnabled(FFogSupport, rci));
809

810
    // Repeat for all lights.
811
    scene := TGLScene(rci.scene);
812
    for I := 0 to scene.Lights.Count - 1 do
813
    begin
814
      if Assigned(scene.Lights[I]) then
815
      begin
816
        FLightTrace[I].Enabled := TGLLightSource(scene.Lights[I]).Shining;
817
        FLightTrace[I].Style := TGLLightSource(scene.Lights[I]).LightStyle;
818
        if FLightTrace[I].Enabled then
819
          GetMLFragmentProgramCodeMid(FragmentProgram.Code, I, FLightTrace[I].Style);
820
      end
821
      else
822
        FLightTrace[I].Enabled := False;
823
    end;
824

825
    GetMLFragmentProgramCodeEnd(FragmentProgram.Code,
826
      FRealisticSpecular, IsFogEnabled(FFogSupport, rci));
827
  end;
828
  VertexProgram.Enabled := True;
829
  FragmentProgram.Enabled := True;
830
  inherited;
831
end;
832

833
initialization
834
  RegisterClasses([
835
                  TGLCustomGLSLDiffuseSpecularShader,
836
                  TGLCustomGLSLDiffuseSpecularShaderMT,
837
                  TGLCustomGLSLMLDiffuseSpecularShader,
838
                  TGLCustomGLSLMLDiffuseSpecularShaderMT,
839

840
                  TGLSLDiffuseSpecularShader,
841
                  TGLSLDiffuseSpecularShaderMT,
842
                  TGLSLMLDiffuseSpecularShader,
843
                  TGLSLMLDiffuseSpecularShaderMT
844
                  ]);
845

846
end.
847

848

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

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

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

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