1
// This unit is part of the GLScene Engine https://github.com/glscene
4
SEM shader : Spherical Environment Mapping
5
The main idea of SEM is to get the UV coordinates (which are used to lookup the matCap texture)
6
from the normal vector on the fragment instead of the original texture coordinates from the object.
8
A material using SEM is very useful to highlight variations in the mesh: creases, bumps, even slow ondulations.
9
It doesn't work that well on a cube, for instance. And does absolutely nothing on a sphere:
10
SEM on a sphere is exactly the same as a planar projection of the matCap texture.
12
At this time only one light source is supported
15
11/12/15 - J.Delauney - Creation
29
GLScene, GLCrossPlatform, OpenGLTokens, OpenGL1x, GLContext, GLRenderContextInfo,
30
GLVectorGeometry, GLCoordinates,
31
GLColor, GLTexture, GLMaterial,
32
GLSLShader, GLCustomShader;
34
//TGLCustomGLSLSimpleWaterShader
36
{ Custom class for GLSLWaterShader. Very simple water shader }
38
TGLCustomGLSLWaterShader = class(TGLCustomGLSLShader)
41
FMaterialLibrary: TGLAbstractMaterialLibrary;
43
FWaterTexture: TGLTexture;
44
FWaterTexName : TGLLibMaterialName;
46
FWaterRefTexture: TGLTexture;
47
FWaterRefTexName : TGLLibMaterialName;
50
// FSpecularPower: Single;
51
// FLightPower: Single;
53
function GetMaterialLibrary: TGLAbstractMaterialLibrary;
55
procedure SetWaterTexTexture(const Value: TGLTexture);
56
function GetWaterTexName: TGLLibMaterialName;
57
procedure SetWaterTexName(const Value: TGLLibMaterialName);
59
procedure SetWaterRefTexture(const Value: TGLTexture);
60
function GetWaterRefTexName: TGLLibMaterialName;
61
procedure SetWaterRefTexName(const Value: TGLLibMaterialName);
65
procedure DoApply(var rci : TGLRenderContextInfo; Sender : TObject); override;
66
function DoUnApply(var rci: TGLRenderContextInfo): Boolean; override;
68
procedure SetMaterialLibrary(const Value: TGLAbstractMaterialLibrary); virtual;
69
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
71
constructor Create(AOwner : TComponent); override;
72
destructor Destroy; override;
74
property WaveTime : Single Read FWaveTime Write FWaveTime;
75
property MaterialLibrary: TGLAbstractMaterialLibrary read getMaterialLibrary write SetMaterialLibrary;
76
property WaterTexture: TGLTexture read FWaterTexture write SetWaterTexTexture;
77
property WaterTextureName: TGLLibMaterialName read GetWaterTexName write SetWaterTexName;
78
property WaterRefTexture: TGLTexture read FWaterRefTexture write SetWaterRefTexture;
79
property WaterRefTextureName: TGLLibMaterialName read GetWaterRefTexName write SetWaterRefTexName;
83
TGLSLWaterShader = class(TGLCustomGLSLWaterShader)
86
property MaterialLibrary;
87
property WaterTexture;
88
property WaterTextureName;
89
property WaterRefTexture;
90
property WaterRefTextureName;
95
constructor TGLCustomGLSLWaterShader.Create(AOwner: TComponent);
98
with VertexProgram.Code do
101
Add('uniform float waveTime; ');
102
Add('varying vec3 vTexCoord; ');
104
Add('void main() { ');
105
Add(' gl_TexCoord[0] = gl_MultiTexCoord0; ');
106
Add(' gl_TexCoord[1] = gl_MultiTexCoord1;');
108
Add('gl_TexCoord[0].x += waveTime*0.25; ');
109
Add('gl_TexCoord[0].y += waveTime-4.0; '); //Make the water move direction vary a little.
110
// Normal in Eye Space
111
Add('vec3 vEyeNormal = gl_NormalMatrix * gl_Normal; ');
112
// Vertex position in Eye Space
113
Add('vec4 vVert4 = gl_ModelViewMatrix * gl_Vertex; ');
114
Add('vec3 vEyeVertex = normalize(vVert4.xyz / vVert4.w); ');
115
Add('vec4 vCoords = vec4(reflect(vEyeVertex, vEyeNormal), 0.0); ');
116
// Rotate by flipped camera
117
Add('//vCoords = gl_ModelViewMatrixInverse * vCoords; ');
118
Add('vTexCoord.xyz =normalize(vCoords.xyz); ');
119
Add(' gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; ');
123
with FragmentProgram.Code do
126
Add('uniform sampler2D waveTextureId; ');
127
Add('uniform sampler2D waveTextureIdRef; ');
128
Add('uniform float waveTime; ');
129
Add('varying vec3 vTexCoord; ');
131
Add('void main() { ');
132
Add(' vec4 color1 = texture2D(waveTextureId, vec2(gl_TexCoord[0])); ');
133
Add(' vec4 color2 = texture2D(waveTextureIdRef, vec2(vTexCoord)); ');
136
Add(' gl_FragColor = 0.6 * vec4(color1 + color2) * vec4(0.0, 1.0, 1.0, 0.50); ');
144
destructor TGLCustomGLSLWaterShader.Destroy;
150
procedure TGLCustomGLSLWaterShader.DoApply(var rci: TGLRenderContextInfo; Sender: TObject);
153
GetGLSLProg.UseProgramObject;
156
// Param['SpecPower'].AsVector1f := FSpecularPower;
157
// Param['LightIntensity'].AsVector1f := FLightPower;
158
Param['waveTime'].AsVector1f := FWaveTime;
159
Param['waveTextureId'].AsTexture2D[0] := FWaterTexture;
160
Param['waveTextureIdRef'].AsTexture2D[1] := FWaterRefTexture;
164
function TGLCustomGLSLWaterShader.DoUnApply(var rci: TGLRenderContextInfo): Boolean;
166
gl.ActiveTexture(GL_TEXTURE0_ARB);
167
//gl.ActiveTexture(GL_TEXTURE1_ARB);
168
GetGLSLProg.EndUseProgramObject;
173
function TGLCustomGLSLWaterShader.GetMaterialLibrary: TGLAbstractMaterialLibrary;
175
Result := FMaterialLibrary;
178
procedure TGLCustomGLSLWaterShader.SetMaterialLibrary(const Value: TGLAbstractMaterialLibrary);
180
if FMaterialLibrary <> nil then FMaterialLibrary.RemoveFreeNotification(Self);
181
FMaterialLibrary := Value;
182
if (FMaterialLibrary <> nil)
183
and (FMaterialLibrary is TGLAbstractMaterialLibrary) then
184
FMaterialLibrary.FreeNotification(Self);
187
procedure TGLCustomGLSLWaterShader.SetWaterTexTexture(const Value: TGLTexture);
189
if FWaterTexture = Value then Exit;
190
FWaterTexture := Value;
194
function TGLCustomGLSLWaterShader.GetWaterTexName: TGLLibMaterialName;
196
Result := TGLMaterialLibrary(FMaterialLibrary).GetNameOfTexture(FWaterTexture);
197
if Result = '' then Result := FWaterTexName;
200
procedure TGLCustomGLSLWaterShader.SetWaterTexName(const Value: TGLLibMaterialName);
202
// Assert(not(assigned(FMaterialLibrary)),'You must set Material Library Before');
203
if FWaterTexName = Value then Exit;
204
FWaterTexName := Value;
206
FWaterTexture := TGLMaterialLibrary(FMaterialLibrary).TextureByName(FWaterTexName);
210
procedure TGLCustomGLSLWaterShader.SetWaterRefTexture(const Value: TGLTexture);
212
if FWaterRefTexture = Value then Exit;
213
FWaterRefTexture := Value;
217
function TGLCustomGLSLWaterShader.GetWaterRefTexName: TGLLibMaterialName;
219
Result := TGLMaterialLibrary(FMaterialLibrary).GetNameOfTexture(FWaterRefTexture);
220
if Result = '' then Result := FWaterRefTexName;
223
procedure TGLCustomGLSLWaterShader.SetWaterRefTexName(const Value: TGLLibMaterialName);
225
// Assert(not(assigned(FMaterialLibrary)),'You must set Material Library Before');
226
if FWaterRefTexName = Value then Exit;
227
FWaterRefTexName := Value;
229
FWaterRefTexture := TGLMaterialLibrary(FMaterialLibrary).TextureByName(FWaterRefTexName);
235
procedure TGLCustomGLSLWaterShader.Notification(AComponent: TComponent; Operation: TOperation);
240
if Operation = opRemove then
241
if AComponent = FMaterialLibrary then
242
if FMaterialLibrary <> nil then
245
if FWaterTexture <> nil then
247
Index := TGLMaterialLibrary(FMaterialLibrary).Materials.GetTextureIndex(FWaterTexture);
249
SetWaterTexTexture(nil);
252
if FWaterRefTexture <> nil then
254
Index := TGLMaterialLibrary(FMaterialLibrary).Materials.GetTextureIndex(FWaterRefTexture);
256
SetWaterRefTexture(nil);
259
FMaterialLibrary := nil;