2
// This unit is part of the GLScene Engine https://github.com/glscene
5
Erosion shader Erode surface object and render with Anisotropic Specular Reflection
7
At this time one light source is supported
10
08/12/15 - J.Delauney - Improved and Made compatible with the latest SVN version of GLScene
11
02/11/06 - Da Stranger - Creation
13
unit GLSLErosionShader;
22
GLScene, GLCrossPlatform, GLBaseClasses, GLState, OpenGLTokens, OpenGL1x, GLContext, GLRenderContextInfo,
23
GLCoordinates, GLVectorGeometry, GLVectorTypes,
24
GLTextureFormat,GLColor, GLTexture, GLMaterial,
25
GLSLShader, GLCustomShader;
27
//TGLCustomGLSLSimpleErosionShader
29
{ Custom class for GLSLSimpleErosionShader.
30
A shader that Erode surface object }
32
TGLCustomGLSLSimpleErosionShader = class(TGLCustomGLSLShader)
36
FMaterialLibrary: TGLAbstractMaterialLibrary;
38
FMainTex : TGLTexture;
39
FNoiseTex : TGLTexture;
40
FErosionTex : TGLTexture;
42
FMainTexName : TGLLibMaterialName;
43
FNoiseTexName : TGLLibMaterialName;
44
FErosionTexName : TGLLibMaterialName;
46
FErosionScale: Single;
47
FErosionFactor: Single;
48
FIntensityFactor1: Single;
49
FIntensityFactor2: Single;
51
FSpecularColor : TGLColor;
52
FAmbientColor : TGLColor;
53
FAmbientFactor : Single;
54
FDiffuseFactor : Single;
55
FSpecularFactor : Single;
56
FSpecularRoughness : Single;
57
FAnisotropicRoughness : Single;
59
function GetMaterialLibrary: TGLAbstractMaterialLibrary;
61
procedure SetMainTexTexture(const Value: TGLTexture);
62
procedure SetNoiseTexTexture(const Value: TGLTexture);
63
procedure SetErosionTexTexture(const Value: TGLTexture);
65
function GetMainTexName: TGLLibMaterialName;
66
procedure SetMainTexName(const Value: TGLLibMaterialName);
67
function GetNoiseTexName: TGLLibMaterialName;
68
procedure SetNoiseTexName(const Value: TGLLibMaterialName);
69
function GetErosionTexName: TGLLibMaterialName;
70
procedure SetErosionTexName(const Value: TGLLibMaterialName);
72
procedure SetAmbientColor(AValue: TGLColor);
73
procedure SetSpecularColor(AValue: TGLColor);
76
procedure DoApply(var rci : TGLRenderContextInfo; Sender : TObject); override;
77
function DoUnApply(var rci: TGLRenderContextInfo): Boolean; override;
79
procedure SetMaterialLibrary(const Value: TGLAbstractMaterialLibrary); virtual;
80
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
82
constructor Create(AOwner : TComponent); override;
83
destructor Destroy; override;
85
// property Color1: TGLColor read FColor1;
86
// property Color2: TGLColor read FColor2;
88
property MaterialLibrary: TGLAbstractMaterialLibrary read getMaterialLibrary write SetMaterialLibrary;
89
property MainTexture: TGLTexture read FMainTex write SetMainTexTexture;
90
property MainTextureName: TGLLibMaterialName read GetMainTexName write SetMainTexName;
91
property NoiseTexture: TGLTexture read FNoiseTex write SetNoiseTexTexture;
92
property NoiseTextureName: TGLLibMaterialName read GetNoiseTexName write SetNoiseTexName;
93
property ErosionTexture: TGLTexture read FErosionTex write SetErosionTexTexture;
94
property ErosionTextureName: TGLLibMaterialName read GetErosionTexName write SetErosionTexName;
96
property ErosionFactor: Single read FErosionFactor write FErosionFactor;
97
property ErosionScale: Single read FErosionFactor write FErosionFactor;
98
property IntensityFactor1: Single read FIntensityFactor1 write FIntensityFactor1;
99
property IntensityFactor2: Single read FIntensityFactor2 write FIntensityFactor2;
101
property SpecularColor : TGLColor Read FSpecularColor Write setSpecularColor;
102
property AmbientColor : TGLColor Read FAmbientColor Write setAmbientColor;
103
property AmbientFactor : Single Read FAmbientFactor Write FAmbientFactor;
104
property DiffuseFactor : Single Read FDiffuseFactor Write FDiffuseFactor;
105
property SpecularFactor : Single Read FSpecularFactor Write FSpecularFactor;
106
property SpecularRoughness : Single Read FSpecularRoughness Write FSpecularRoughness;
107
property AnisotropicRoughness : Single Read FAnisotropicRoughness Write FAnisotropicRoughness;
111
TGLSLSimpleErosionShader = class(TGLCustomGLSLSimpleErosionShader)
116
property MaterialLibrary;
118
property MainTexture;
119
property MainTextureName;
120
property NoiseTexture;
121
property NoiseTextureName;
122
property ErosionTexture;
123
property ErosionTextureName;
125
property ErosionScale;
126
property ErosionFactor;
127
property IntensityFactor1;
128
property IntensityFactor2;
130
property SpecularColor;
131
property AmbientColor;
132
property AmbientFactor;
133
property DiffuseFactor;
134
property SpecularFactor;
135
property SpecularRoughness;
136
property AnisotropicRoughness;
144
{ TGLCustomGLSLSimpleErosionShader }
146
constructor TGLCustomGLSLSimpleErosionShader.Create(AOwner: TComponent);
149
with VertexProgram.Code do
152
Add('uniform float Scale; ');
154
Add('varying vec3 normal; ');
155
Add('varying vec2 vTexCoord; ');
156
Add('varying vec3 lightVec; ');
157
Add('varying vec3 viewVec; ');
158
Add('varying vec3 Position; ');
161
Add('void main(void) { ');
162
// Add(' mat4 mWorld = gl_ModelViewMatrix; ');
163
Add(' vec3 Normal = gl_Normal; ');
164
Add(' vec4 lightPos = gl_LightSource[0].position;');
165
Add(' vec4 vert = gl_ModelViewMatrix * gl_Vertex; ');
166
Add(' normal = gl_NormalMatrix * gl_Normal; ');
168
Add(' Position = vec3(gl_Vertex)*Scale; ');
169
Add(' vTexCoord = gl_MultiTexCoord0; ');
170
Add(' lightVec = vec3(lightPos - vert); ');
171
Add(' viewVec = -vec3(vert); ');
172
Add(' gl_Position = ftransform(); ');
176
with FragmentProgram.Code do
179
Add('uniform float ErosionFactor; ');
180
Add('uniform float IntensityFactor1; ');
181
Add('uniform float IntensityFactor2; ');
183
Add('uniform sampler2D MainTexture; ');
184
Add('uniform sampler2D Noise2d; ');
185
Add('uniform sampler2D ErosionTexture; ');
187
Add('uniform vec4 SpecularColor; ');
188
Add('uniform vec4 AmbientColor; ');
189
Add('uniform float DiffuseIntensity; ');
190
Add('uniform float AmbientIntensity; ');
191
Add('uniform float SpecularIntensity; ');
192
Add('uniform float SpecularRoughness; ');
193
Add('uniform float AnisoRoughness; ');
195
Add('varying vec3 normal; ');
196
Add('varying vec2 vTexCoord; ');
197
Add('varying vec3 lightVec; ');
198
Add('varying vec3 viewVec; ');
199
Add('varying vec3 Position; ');
201
Add('void main (void) ');
203
Add(' vec3 offset = vec3(- ErosionFactor, - ErosionFactor + 0.06, - ErosionFactor * 0.92); ');
204
Add(' vec4 DiffuseColor; ');
206
Add(' vec4 Color1 = texture2D(MainTexture,vTexCoord); ');
207
Add(' vec4 Color2 = texture2D(ErosionTexture,vTexCoord); ');
209
Add(' // Compute noise ');
210
Add(' vec3 noiseCoord = Position.xyz + offset; ');
211
Add(' vec4 noiseVec = texture2D(Noise2d, noiseCoord.xy); ');
212
Add(' float intensity = (abs(noiseVec[0] - 0.25) + ');
213
Add(' abs(noiseVec[1] - 0.125) + ');
214
Add(' abs(noiseVec[2] - 0.0625) + ');
215
Add(' abs(noiseVec[3] - 0.03125)); ');
216
Add(' // continue noise evaluation');
217
Add(' intensity = IntensityFactor1 * (noiseVec.x + noiseVec.y+ noiseVec.z + noiseVec.w); ');
218
Add(' intensity = IntensityFactor2 * abs(2.0 * intensity -1.0); ');
220
Add(' // discard pixels in a psuedo-random fashion (noise) ');
221
Add(' if (intensity < fract(0.5 - offset.x - offset.y - offset.z)) discard; ');
223
Add(' // color fragments different colors using noise ');
224
Add(' clamp(intensity, 0.0, 1.0); ');
225
Add(' Color2.a =1.0-intensity; ');
226
Add(' Color1.a =1.0; ');
227
Add(' DiffuseColor = mix(Color2, Color1, intensity); ');
228
Add(' DiffuseColor.a = intensity; ');
230
Add(' // Anisotropic Specular Lighting Reflection ');
231
// Anisotropic Specular Reflection
232
// This is useful for depicting surfaces
233
// such as velvet or brushed metal,
234
// it allows you to stretch the highlight along a
235
// SpecDirection vector (in object space)
236
// add new var and replace the follow line
237
// vec3 T = cross(norm,V) by vec3 T = cross(norm,normalize(SpecDirection));
239
Add(' vec3 norm = normalize(normal); ');
240
Add(' vec3 L = normalize(lightVec); ');
241
Add(' vec3 V = normalize(viewVec); ');
242
Add(' vec3 halfAngle = normalize(L + V); ');
243
Add(' vec3 T = cross(norm,V); ');
245
Add(' float NdotL = dot(L, norm); ');
246
Add(' float NdotH = clamp(dot(halfAngle, norm), 0.0, 1.0); ');
248
Add(' // "Half-Lambert" technique for more pleasing diffuse term ');
249
Add(' float diffuse = 0.5 * NdotL + 0.5; ');
250
Add(' float specular = pow(NdotH,1.0/SpecularRoughness); '); //54
251
Add(' // Heidrich-Seidel anisotropic distribution ');
252
Add(' float ldott = dot(L,T); ');
253
Add(' float vdott = dot(V,T); ');
254
Add(' float aniso = pow(sin(ldott)*sin(vdott) + cos(ldott)*cos(vdott),1.0/AnisoRoughness); ');
256
Add(' vec3 FinalColour = AmbientColor*AmbientIntensity + ');
257
Add(' DiffuseColor*diffuse*DiffuseIntensity + ');
258
Add(' SpecularColor*aniso*specular*SpecularIntensity; ');
261
Add(' gl_FragColor = vec4(FinalColour,intensity); ');
265
//setup initial parameters
267
FAmbientColor := TGLColor.Create(self);
268
FAmbientColor.SetColor(0.2,0.2,0.2,1.0);
269
FSpecularColor := TGLColor.Create(self);
270
FSpecularColor.SetColor(0.75,0.75,0.75,1.0);
271
FAmbientFactor := 0.8;
272
FDiffuseFactor :=0.9;
273
FSpecularFactor :=0.8;
274
FSpecularRoughness :=0.45;
275
FAnisotropicRoughness :=0.35;
277
FErosionScale := 0.03;
278
FErosionFactor := 0.35;
279
FIntensityFactor1 := 0.75;
280
FIntensityFactor2 := 1.95;
283
destructor TGLCustomGLSLSimpleErosionShader.Destroy;
290
procedure TGLCustomGLSLSimpleErosionShader.DoApply(var rci : TGLRenderContextInfo; Sender : TObject);
292
GetGLSLProg.UseProgramObject;
294
param['AmbientColor'].AsVector4f := FAmbientColor.Color;
295
param['SpecularColor'].AsVector4f := FSpecularColor.Color;
296
param['AmbientIntensity'].AsVector1f := FAmbientFactor;
297
param['DiffuseIntensity'].AsVector1f := FDiffuseFactor;
298
param['SpecularIntensity'].AsVector1f := FSpecularFactor;
299
param['SpecularRoughness'].AsVector1f := FSpecularRoughness;
300
param['AnisoRoughness'].AsVector1f := FAnisotropicRoughness;
303
param['ErosionFactor'].AsVector1f := FErosionFactor;
304
param['IntensityFactor1'].AsVector1f := FIntensityFactor1;
305
param['IntensityFactor2'].AsVector1f := FIntensityFactor2;
306
param['Scale'].AsVector1f := FErosionScale;
308
param['MainTexture'].AsTexture2D[0] := FMainTex;
309
param['Noise2d'].AsTexture2D[1] := FNoiseTex;
310
param['ErosionTexture'].AsTexture2D[2] := FErosionTex;
311
// GetGLSLProg.UniformTextureHandle['Noise2d', 1, GL_TEXTURE_2D] := FNoiseTexture.Handle;
314
function TGLCustomGLSLSimpleErosionShader.DoUnApply(var rci: TGLRenderContextInfo): Boolean;
316
GetGLSLProg.EndUseProgramObject;
321
function TGLCustomGLSLSimpleErosionShader.GetMaterialLibrary: TGLAbstractMaterialLibrary;
323
Result := FMaterialLibrary;
326
procedure TGLCustomGLSLSimpleErosionShader.SetMaterialLibrary(const Value: TGLAbstractMaterialLibrary);
328
if FMaterialLibrary <> nil then FMaterialLibrary.RemoveFreeNotification(Self);
329
FMaterialLibrary := Value;
330
if (FMaterialLibrary <> nil)
331
and (FMaterialLibrary is TGLAbstractMaterialLibrary) then
332
FMaterialLibrary.FreeNotification(Self);
335
procedure TGLCustomGLSLSimpleErosionShader.SetMainTexTexture(const Value: TGLTexture);
337
if FMainTex = Value then Exit;
342
procedure TGLCustomGLSLSimpleErosionShader.SetNoiseTexTexture(const Value: TGLTexture);
344
if FNoiseTex = Value then Exit;
349
procedure TGLCustomGLSLSimpleErosionShader.SetErosionTexTexture(const Value: TGLTexture);
351
if FErosionTex = Value then Exit;
352
FErosionTex := Value;
356
function TGLCustomGLSLSimpleErosionShader.GetNoiseTexName: TGLLibMaterialName;
358
Result := TGLMaterialLibrary(FMaterialLibrary).GetNameOfTexture(FNoiseTex);
359
if Result = '' then Result := FNoiseTexName;
362
procedure TGLCustomGLSLSimpleErosionShader.SetNoiseTexName(const Value: TGLLibMaterialName);
364
//Assert(not(assigned(FMaterialLibrary)),'You must set Material Library Before');
365
if FNoiseTexName = Value then Exit;
366
FNoiseTexName := Value;
367
FNoiseTex := TGLMaterialLibrary(FMaterialLibrary).TextureByName(FNoiseTexName);
371
function TGLCustomGLSLSimpleErosionShader.GetMainTexName: TGLLibMaterialName;
373
Result := TGLMaterialLibrary(FMaterialLibrary).GetNameOfTexture(FMainTex);
374
if Result = '' then Result := FMainTexName;
377
procedure TGLCustomGLSLSimpleErosionShader.SetMainTexName(const Value: TGLLibMaterialName);
379
// Assert(not(assigned(FMaterialLibrary)),'You must set Material Library Before');
380
if FMainTexName = Value then Exit;
381
FMainTexName := Value;
383
FMainTex := TGLMaterialLibrary(FMaterialLibrary).TextureByName(FMainTexName);
387
function TGLCustomGLSLSimpleErosionShader.GetErosionTexName: TGLLibMaterialName;
389
Result := TGLMaterialLibrary(FMaterialLibrary).GetNameOfTexture(FErosionTex);
390
if Result = '' then Result := FErosionTexName;
393
procedure TGLCustomGLSLSimpleErosionShader.SetErosionTexName(const Value: TGLLibMaterialName);
395
// Assert(not(assigned(FMaterialLibrary)),'You must set Material Library Before');
396
if FErosionTexName = Value then Exit;
397
FErosionTexName := Value;
399
FErosionTex := TGLMaterialLibrary(FMaterialLibrary).TextureByName(FErosionTexName);
403
procedure TGLCustomGLSLSimpleErosionShader.SetAmbientColor(AValue: TGLColor);
405
FAmbientColor.DirectColor := AValue.Color;
408
procedure TGLCustomGLSLSimpleErosionShader.SetSpecularColor(AValue: TGLColor);
410
FSpecularColor.DirectColor := AValue.Color;
414
procedure TGLCustomGLSLSimpleErosionShader.Notification(AComponent: TComponent; Operation: TOperation);
419
if Operation = opRemove then
420
if AComponent = FMaterialLibrary then
421
if FMaterialLibrary <> nil then
423
// Need to nil the textures that were owned by it
424
if FNoiseTex <> nil then
426
Index := TGLMaterialLibrary(FMaterialLibrary).Materials.GetTextureIndex(FNoiseTex);
428
SetNoiseTexTexture(nil);
431
if FMainTex <> nil then
433
Index := TGLMaterialLibrary(FMaterialLibrary).Materials.GetTextureIndex(FMainTex);
435
SetMainTexTexture(nil);
438
if FErosionTex <> nil then
440
Index := TGLMaterialLibrary(FMaterialLibrary).Materials.GetTextureIndex(FErosionTex);
442
SetErosionTexTexture(nil);
445
FMaterialLibrary := nil;