LZScene

Форк
0
/
GLPhongShader.pas 
267 строк · 7.5 Кб
1
//
2
// This unit is part of the GLScene Engine https://github.com/glscene
3
//
4
{
5
   An ARBvp1.0 + ARBfp1.0 shader that implements phong shading.
6

7
    History :  
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.
17
    
18
}
19
unit GLPhongShader;
20

21
interface
22

23
{$I GLScene.inc }
24

25
uses
26
  // VCL
27
  Classes, SysUtils,
28

29
  GLTexture, GLVectorGeometry, GLVectorLists, OpenGLTokens, GLContext,
30
  GLAsmShader, GLRenderContextInfo, GLCustomShader, GLState;
31

32
type
33
  TGLPhongShader = class(TGLCustomAsmShader)
34
  private
35
    FLightIDs: TIntegerList;
36
    FDesignTimeEnabled: Boolean;
37
    FAmbientPass: Boolean;
38
    procedure SetDesignTimeEnabled(const Value: Boolean);
39
  protected
40
     
41
    procedure DoLightPass(lightID: Cardinal); virtual;
42
    procedure DoAmbientPass(var rci: TGLRenderContextInfo); virtual;
43
    procedure UnApplyLights(var rci: TGLRenderContextInfo); virtual;
44

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;
48
  public
49
     
50
    constructor Create(AOwner: TComponent); override;
51
    destructor Destroy; override;
52
    function ShaderSupported: Boolean; override;
53
  published
54
     
55
    property DesignTimeEnabled: Boolean read FDesignTimeEnabled write SetDesignTimeEnabled default False;
56
  end;
57

58
implementation
59

60
// DoApply
61
//
62
procedure TGLPhongShader.DoApply(var rci: TGLRenderContextInfo; Sender: TObject);
63
begin
64
  if (csDesigning in ComponentState) and not DesignTimeEnabled then Exit;
65

66
  GetActiveLightsList(FLightIDs);
67
  FAmbientPass := False;
68

69
  if FLightIDs.Count > 0 then
70
  begin
71
    rci.GLStates.DepthFunc := cfLEqual;
72
    rci.GLStates.Disable(stBlend);
73
    DoLightPass(FLightIDs[0]);
74
    FLightIDs.Delete(0);
75
  end
76
  else
77
  begin
78
    DoAmbientPass(rci);
79
    FAmbientPass := True;
80
  end;
81
end;
82

83
// DoUnApply
84
//
85
function TGLPhongShader.DoUnApply(var rci: TGLRenderContextInfo): Boolean;
86
begin
87
  Result := False;
88
  if (csDesigning in ComponentState) and not DesignTimeEnabled then Exit;
89

90
  if FLightIDs.Count > 0 then
91
  begin
92
    UnApplyLights(rci);
93
    Result := True;
94
    Exit;
95
  end
96
  else
97
  if not FAmbientPass then
98
  begin
99
    Self.UnApplyShaderPrograms();
100

101
    rci.GLStates.Enable(stBlend);
102
    rci.GLStates.SetBlendFunc(bfOne, bfOne);
103
    DoAmbientPass(rci);
104
    FAmbientPass := True;
105

106
    Result := True;
107
    Exit;
108
  end;
109
  rci.GLStates.DepthFunc := cfLEqual;
110
end;
111

112
// DoInitialize
113
//
114
procedure TGLPhongShader.DoInitialize(var rci : TGLRenderContextInfo; Sender : TObject);
115
begin
116
  if (csDesigning in ComponentState) and not DesignTimeEnabled then Exit;
117
  inherited;
118
end;
119

120
// SetDesignTimeEnabled
121
//
122
procedure TGLPhongShader.SetDesignTimeEnabled(const Value: Boolean);
123
begin
124
  if Value <> FDesignTimeEnabled then
125
  begin
126
    FDesignTimeEnabled := Value;
127
    NotifyChange(Self);
128
  end;
129
end;
130

131
// Create
132
//
133
constructor TGLPhongShader.Create(AOwner: TComponent);
134
begin
135
  inherited;
136
  with VertexProgram.Code do
137
  begin
138
    Add('!!ARBvp1.0');
139
    Add('OPTION ARB_position_invariant;');
140

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;');
145

146
    Add('   ADD eye, mvit[3], -vertex.position;');
147
    Add('   MOV eye.w, 0.0;');
148

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;');
154

155
    Add('   MOV result.texcoord[0], vertex.normal;');
156
    Add('   MOV result.texcoord[1], light;');
157
    Add('   MOV result.texcoord[2], eye;');
158

159
    Add('END');
160
  end;
161

162
  with FragmentProgram.Code do
163
  begin
164
    Add('!!ARBfp1.0');
165

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;');
172

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];');
182

183
    Add('   DP3_SAT diff, normal, light;');
184
    Add('   MUL diff, diff, lightDiff;');
185
    Add('   MUL diff, diff, materialDiff;');
186

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;');
191

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;');
196

197
    Add('   ADD_SAT result.color, diff, spec;');
198
    Add('   MOV result.color.w, 1.0;');
199

200
    Add('END');
201
  end;
202
  FLightIDs := TIntegerList.Create;
203
end;
204

205
// ShaderSupported
206
//
207
function TGLPhongShader.ShaderSupported: Boolean;
208
var
209
  MaxTextures: Integer;
210
begin
211
  Result := inherited ShaderSupported and GL.ARB_multitexture;
212

213
  GL.GetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, @MaxTextures);
214
  Result := Result and (maxTextures > 2);
215
end;
216

217
// UnApplyLights
218
//
219
procedure TGLPhongShader.UnApplyLights(var rci: TGLRenderContextInfo);
220
begin
221
  rci.GLStates.DepthFunc := cfLEqual;
222
  rci.GLStates.Enable(stBlend);
223
  rci.GLStates.SetBlendFunc(bfOne, bfOne);
224
  DoLightPass(FLightIDs[0]);
225
  FLightIDs.Delete(0);
226
end;
227

228
destructor TGLPhongShader.Destroy;
229
begin
230
  FLightIDs.Free;
231
  inherited;
232
end;
233

234
procedure TGLPhongShader.DoAmbientPass(var rci: TGLRenderContextInfo);
235
var
236
  ambient, materialAmbient: TVector;
237
begin
238
  rci.GLStates.Disable(stLighting);
239

240
  GL.GetFloatv(GL_LIGHT_MODEL_AMBIENT, @ambient);
241
  GL.GetMaterialfv(GL_FRONT, GL_AMBIENT, @materialAmbient);
242
  ScaleVector(ambient, materialAmbient);
243
  GL.Color3fv(@ambient);
244
end;
245

246
procedure TGLPhongShader.DoLightPass(lightID: Cardinal);
247
var
248
  LightParam: TVector;
249
begin
250
  Self.ApplyShaderPrograms();
251

252
  with CurrentGLContext.GLStates do
253
  begin
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);
261
  end;
262
end;
263

264
initialization
265
  RegisterClasses([TGLPhongShader]);
266

267
end.
268

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

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

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

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