2
// This unit is part of the GLScene Engine https://github.com/glscene
5
An ARBvp1.0 + ARBfp1.0 shader that implements phong shading.
8
23/08/10 - Yar - Added OpenGLTokens to uses, replaced OpenGL1x functions to OpenGLAdapter
9
22/04/10 - Yar - Fixes after GLState revision
10
05/03/10 - DanB - More state added to TGLStateCache
11
28/07/09 - DaStr - Small changes and simplifications
12
24/07/09 - DaStr - TGLShader.DoInitialize() now passes rci
13
(BugTracker ID = 2826217)
14
20/03/07 - DaStr - Moved some of the stuff from TGLCustomAsmShader back here
15
25/02/07 - DaStr - Completely replaced with a descendant of TGLCustomAsmShader.
16
11/10/04 - SG - Creation.
29
GLTexture, GLVectorGeometry, GLVectorLists, OpenGLTokens, GLContext,
30
GLAsmShader, GLRenderContextInfo, GLCustomShader, GLState;
33
TGLPhongShader = class(TGLCustomAsmShader)
35
FLightIDs: TIntegerList;
36
FDesignTimeEnabled: Boolean;
37
FAmbientPass: Boolean;
38
procedure SetDesignTimeEnabled(const Value: Boolean);
41
procedure DoLightPass(lightID: Cardinal); virtual;
42
procedure DoAmbientPass(var rci: TGLRenderContextInfo); virtual;
43
procedure UnApplyLights(var rci: TGLRenderContextInfo); virtual;
45
procedure DoApply(var rci: TGLRenderContextInfo; Sender: TObject); override;
46
function DoUnApply(var rci: TGLRenderContextInfo): Boolean; override;
47
procedure DoInitialize(var rci : TGLRenderContextInfo; Sender : TObject); override;
50
constructor Create(AOwner: TComponent); override;
51
destructor Destroy; override;
52
function ShaderSupported: Boolean; override;
55
property DesignTimeEnabled: Boolean read FDesignTimeEnabled write SetDesignTimeEnabled default False;
62
procedure TGLPhongShader.DoApply(var rci: TGLRenderContextInfo; Sender: TObject);
64
if (csDesigning in ComponentState) and not DesignTimeEnabled then Exit;
66
GetActiveLightsList(FLightIDs);
67
FAmbientPass := False;
69
if FLightIDs.Count > 0 then
71
rci.GLStates.DepthFunc := cfLEqual;
72
rci.GLStates.Disable(stBlend);
73
DoLightPass(FLightIDs[0]);
85
function TGLPhongShader.DoUnApply(var rci: TGLRenderContextInfo): Boolean;
88
if (csDesigning in ComponentState) and not DesignTimeEnabled then Exit;
90
if FLightIDs.Count > 0 then
97
if not FAmbientPass then
99
Self.UnApplyShaderPrograms();
101
rci.GLStates.Enable(stBlend);
102
rci.GLStates.SetBlendFunc(bfOne, bfOne);
104
FAmbientPass := True;
109
rci.GLStates.DepthFunc := cfLEqual;
114
procedure TGLPhongShader.DoInitialize(var rci : TGLRenderContextInfo; Sender : TObject);
116
if (csDesigning in ComponentState) and not DesignTimeEnabled then Exit;
120
// SetDesignTimeEnabled
122
procedure TGLPhongShader.SetDesignTimeEnabled(const Value: Boolean);
124
if Value <> FDesignTimeEnabled then
126
FDesignTimeEnabled := Value;
133
constructor TGLPhongShader.Create(AOwner: TComponent);
136
with VertexProgram.Code do
139
Add('OPTION ARB_position_invariant;');
141
Add('PARAM mvinv[4] = { state.matrix.modelview.inverse };');
142
Add('PARAM mvit[4] = { state.matrix.modelview.invtrans };');
143
Add('PARAM lightPos = program.local[0];');
144
Add('TEMP light, normal, eye;');
146
Add(' ADD eye, mvit[3], -vertex.position;');
147
Add(' MOV eye.w, 0.0;');
149
Add(' DP4 light.x, mvinv[0], lightPos;');
150
Add(' DP4 light.y, mvinv[1], lightPos;');
151
Add(' DP4 light.z, mvinv[2], lightPos;');
152
Add(' ADD light, light, -vertex.position;');
153
Add(' MOV light.w, 0.0;');
155
Add(' MOV result.texcoord[0], vertex.normal;');
156
Add(' MOV result.texcoord[1], light;');
157
Add(' MOV result.texcoord[2], eye;');
162
with FragmentProgram.Code do
166
Add('PARAM lightDiff = program.local[0];');
167
Add('PARAM lightSpec = program.local[1];');
168
Add('PARAM materialDiff = state.material.diffuse;');
169
Add('PARAM materialSpec = state.material.specular;');
170
Add('PARAM shininess = state.material.shininess;');
171
Add('TEMP temp, light, normal, eye, R, diff, spec;');
173
Add(' DP3 temp, fragment.texcoord[0], fragment.texcoord[0];');
174
Add(' RSQ temp, temp.x;');
175
Add(' MUL normal, temp.x, fragment.texcoord[0];');
176
Add(' DP3 temp, fragment.texcoord[1], fragment.texcoord[1];');
177
Add(' RSQ temp, temp.x;');
178
Add(' MUL light, temp.x, fragment.texcoord[1];');
179
Add(' DP3 temp, fragment.texcoord[2], fragment.texcoord[2];');
180
Add(' RSQ temp, temp.x;');
181
Add(' MUL eye, temp.x, fragment.texcoord[2];');
183
Add(' DP3_SAT diff, normal, light;');
184
Add(' MUL diff, diff, lightDiff;');
185
Add(' MUL diff, diff, materialDiff;');
187
Add(' DP3 R, normal, light;');
188
Add(' MUL R, R.x, normal;');
189
Add(' MUL R, 2.0, R;');
190
Add(' ADD R, R, -light;');
192
Add(' DP3_SAT spec, R, eye;');
193
Add(' POW spec, spec.x, shininess.x;');
194
Add(' MUL spec, spec, lightDiff;');
195
Add(' MUL spec, spec, materialDiff;');
197
Add(' ADD_SAT result.color, diff, spec;');
198
Add(' MOV result.color.w, 1.0;');
202
FLightIDs := TIntegerList.Create;
207
function TGLPhongShader.ShaderSupported: Boolean;
209
MaxTextures: Integer;
211
Result := inherited ShaderSupported and GL.ARB_multitexture;
213
GL.GetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, @MaxTextures);
214
Result := Result and (maxTextures > 2);
219
procedure TGLPhongShader.UnApplyLights(var rci: TGLRenderContextInfo);
221
rci.GLStates.DepthFunc := cfLEqual;
222
rci.GLStates.Enable(stBlend);
223
rci.GLStates.SetBlendFunc(bfOne, bfOne);
224
DoLightPass(FLightIDs[0]);
228
destructor TGLPhongShader.Destroy;
234
procedure TGLPhongShader.DoAmbientPass(var rci: TGLRenderContextInfo);
236
ambient, materialAmbient: TVector;
238
rci.GLStates.Disable(stLighting);
240
GL.GetFloatv(GL_LIGHT_MODEL_AMBIENT, @ambient);
241
GL.GetMaterialfv(GL_FRONT, GL_AMBIENT, @materialAmbient);
242
ScaleVector(ambient, materialAmbient);
243
GL.Color3fv(@ambient);
246
procedure TGLPhongShader.DoLightPass(lightID: Cardinal);
250
Self.ApplyShaderPrograms();
252
with CurrentGLContext.GLStates do
254
GL.GetLightfv(GL_LIGHT0+lightID, GL_POSITION, @LightParam);
255
LightParam := LightParam;
256
GL.ProgramLocalParameter4fv(GL_VERTEX_PROGRAM_ARB, 0, @LightParam);
257
LightParam := LightDiffuse[lightID];
258
GL.ProgramLocalParameter4fv(GL_FRAGMENT_PROGRAM_ARB, 0, @LightParam);
259
LightParam := LightSpecular[lightID];
260
GL.ProgramLocalParameter4fv(GL_FRAGMENT_PROGRAM_ARB, 1, @LightParam);
265
RegisterClasses([TGLPhongShader]);