1 | unit BGRAOpenGL3D;
|
---|
2 |
|
---|
3 | {$mode objfpc}{$H+}
|
---|
4 |
|
---|
5 | interface
|
---|
6 |
|
---|
7 | uses BGRABitmapTypes,
|
---|
8 | BGRASceneTypes, BGRASSE,
|
---|
9 | Classes, BGRAMatrix3D,
|
---|
10 | BGRACanvasGL,
|
---|
11 | BGRAScene3D,
|
---|
12 | BGRAOpenGLType,
|
---|
13 | BGRATransform,
|
---|
14 | BGRARenderer3D;
|
---|
15 |
|
---|
16 | type
|
---|
17 | TAttributeVariable = BGRACanvasGL.TAttributeVariable;
|
---|
18 |
|
---|
19 | TBGLShader3D = class;
|
---|
20 |
|
---|
21 | { TBGLLighting3D }
|
---|
22 |
|
---|
23 | TBGLLighting3D = class
|
---|
24 | private
|
---|
25 | procedure SetUseBuiltIn(AValue: boolean);
|
---|
26 | protected
|
---|
27 | FCanvas: TBGLCustomCanvas;
|
---|
28 | FLights: TList;
|
---|
29 | FAmbiantLight: TColorF;
|
---|
30 | FShaderLightingCode: string;
|
---|
31 | FUseBuiltIn: boolean;
|
---|
32 | procedure Init;
|
---|
33 | public
|
---|
34 | constructor Create(ACanvas: TBGLCustomCanvas; AAmbiantLight: TColorF; ALights: TList);
|
---|
35 | procedure SetSpecularIndex(AIndex: Integer);
|
---|
36 | destructor Destroy; override;
|
---|
37 | property ShaderLightingCode: string read FShaderLightingCode;
|
---|
38 | property UseOpenGLBuiltInLighting: boolean read FUseBuiltIn write SetUseBuiltIn;
|
---|
39 | end;
|
---|
40 |
|
---|
41 | { TBGLRenderer3D }
|
---|
42 |
|
---|
43 | TBGLRenderer3D = class(TCustomRenderer3D)
|
---|
44 | protected
|
---|
45 | FCanvas: TBGLCustomCanvas;
|
---|
46 | FHasZBuffer: Boolean;
|
---|
47 | FGlobalScale: single;
|
---|
48 | FOptions: TRenderingOptions;
|
---|
49 | FFactorZ, FAddZ: single;
|
---|
50 | FLightingGL: TBGLLighting3D;
|
---|
51 | FLights: TList;
|
---|
52 | FAmbiantLight: TColorF;
|
---|
53 | FFar: single;
|
---|
54 | FOldCulling: TFaceCulling;
|
---|
55 | FOldMatrix: TAffineMatrix;
|
---|
56 | FOldProjection, FProjectionMatrix: TMatrix4D;
|
---|
57 | FShader, FShaderWithTexture: TBGLCustomShader;
|
---|
58 | FBGRAShader: TBGRAShader3D;
|
---|
59 | FShadedColorsF: array of TColorF;
|
---|
60 | FShadedColors: array of TBGRAPixel;
|
---|
61 | function GetHasZBuffer: boolean; override;
|
---|
62 | function GetGlobalScale: single; override;
|
---|
63 | function GetSurfaceWidth: integer; override;
|
---|
64 | function GetSurfaceHeight: integer; override;
|
---|
65 | procedure SetProjection(const AValue: TProjection3D); override;
|
---|
66 | function GetHandlesNearClipping: boolean; override;
|
---|
67 | function GetHandlesFaceCulling: boolean; override;
|
---|
68 | procedure InitLighting(AUseOpenGLBuiltInLighting: boolean);
|
---|
69 | public
|
---|
70 | constructor Create(ACanvas: TBGLCustomCanvas;
|
---|
71 | AScene: TBGRAScene3D; AFar: single);
|
---|
72 | function RenderFace(var ADescription: TFaceRenderingDescription;
|
---|
73 | {%H-}AComputeCoordinate: TComputeProjectionFunc): boolean; override;
|
---|
74 | destructor Destroy; override;
|
---|
75 | property Canvas: TBGLCustomCanvas read FCanvas;
|
---|
76 | end;
|
---|
77 |
|
---|
78 | { TBGLScene3D }
|
---|
79 |
|
---|
80 | TBGLScene3D = class(TBGRAScene3D)
|
---|
81 | protected
|
---|
82 | function LoadBitmapFromFileUTF8(AFilenameUTF8: string): TBGRACustomBitmap; override;
|
---|
83 | public
|
---|
84 | procedure RenderGL(ACanvas: TBGLCustomCanvas; AMaxZ: single = 1000); virtual;
|
---|
85 | end;
|
---|
86 |
|
---|
87 | { TUniformVariable }
|
---|
88 |
|
---|
89 | TUniformVariable = object
|
---|
90 | private
|
---|
91 | FProgram: TBGLShader3D;
|
---|
92 | FVariable: DWord;
|
---|
93 | procedure Init(AProgram: TBGLShader3D; AVariable: DWord);
|
---|
94 | end;
|
---|
95 |
|
---|
96 | { TUniformVariableSingle }
|
---|
97 |
|
---|
98 | TUniformVariableSingle = object(TUniformVariable)
|
---|
99 | private
|
---|
100 | FValue: single;
|
---|
101 | procedure SetValue(const AValue: single);
|
---|
102 | public
|
---|
103 | procedure Update;
|
---|
104 | property Value: single read FValue write SetValue;
|
---|
105 | end;
|
---|
106 |
|
---|
107 | { TUniformVariablePointF }
|
---|
108 |
|
---|
109 | TUniformVariablePointF = object(TUniformVariable)
|
---|
110 | private
|
---|
111 | FValue: TPointF;
|
---|
112 | procedure SetValue(const AValue: TPointF);
|
---|
113 | public
|
---|
114 | procedure Update;
|
---|
115 | property Value: TPointF read FValue write SetValue;
|
---|
116 | end;
|
---|
117 |
|
---|
118 | { TUniformVariablePoint3D }
|
---|
119 |
|
---|
120 | TUniformVariablePoint3D = object(TUniformVariable)
|
---|
121 | private
|
---|
122 | FValue: TPoint3D;
|
---|
123 | procedure SetValue(const AValue: TPoint3D);
|
---|
124 | public
|
---|
125 | procedure Update;
|
---|
126 | property Value: TPoint3D read FValue write SetValue;
|
---|
127 | end;
|
---|
128 |
|
---|
129 | { TUniformVariableInteger }
|
---|
130 |
|
---|
131 | TUniformVariableInteger = object(TUniformVariable)
|
---|
132 | private
|
---|
133 | FValue: Integer;
|
---|
134 | procedure SetValue(const AValue: Integer);
|
---|
135 | public
|
---|
136 | procedure Update;
|
---|
137 | property Value: Integer read FValue write SetValue;
|
---|
138 | end;
|
---|
139 |
|
---|
140 | { TUniformVariablePoint }
|
---|
141 |
|
---|
142 | TUniformVariablePoint = object(TUniformVariable)
|
---|
143 | private
|
---|
144 | FValue: TPoint;
|
---|
145 | procedure SetValue(const AValue: TPoint);
|
---|
146 | public
|
---|
147 | procedure Update;
|
---|
148 | property Value: TPoint read FValue write SetValue;
|
---|
149 | end;
|
---|
150 |
|
---|
151 | { TUniformVariableMatrix4D }
|
---|
152 |
|
---|
153 | TUniformVariableMatrix4D = object(TUniformVariable)
|
---|
154 | private
|
---|
155 | FValue: TMatrix4D;
|
---|
156 | procedure SetValue(const AValue: TMatrix4D);
|
---|
157 | public
|
---|
158 | procedure Update;
|
---|
159 | property Value: TMatrix4D read FValue write SetValue;
|
---|
160 | end;
|
---|
161 |
|
---|
162 | { TAttributeVariableSingle }
|
---|
163 |
|
---|
164 | TAttributeVariableSingle = object(TAttributeVariable)
|
---|
165 | protected
|
---|
166 | procedure Init(AProgram: TObject; AAttribute: DWord);
|
---|
167 | end;
|
---|
168 |
|
---|
169 | { TAttributeVariablePointF }
|
---|
170 |
|
---|
171 | TAttributeVariablePointF = object(TAttributeVariable)
|
---|
172 | protected
|
---|
173 | procedure Init(AProgram: TObject; AAttribute: DWord);
|
---|
174 | end;
|
---|
175 |
|
---|
176 | { TAttributeVariablePoint3D }
|
---|
177 |
|
---|
178 | TAttributeVariablePoint3D = object(TAttributeVariable)
|
---|
179 | protected
|
---|
180 | procedure Init(AProgram: TObject; AAttribute: DWord);
|
---|
181 | end;
|
---|
182 |
|
---|
183 | { TAttributeVariableInteger }
|
---|
184 |
|
---|
185 | TAttributeVariableInteger = object(TAttributeVariable)
|
---|
186 | protected
|
---|
187 | procedure Init(AProgram: TObject; AAttribute: DWord);
|
---|
188 | end;
|
---|
189 |
|
---|
190 | { TAttributeVariablePoint }
|
---|
191 |
|
---|
192 | TAttributeVariablePoint = object(TAttributeVariable)
|
---|
193 | protected
|
---|
194 | procedure Init(AProgram: TObject; AAttribute: DWord);
|
---|
195 | end;
|
---|
196 |
|
---|
197 | { TBGLShader3D }
|
---|
198 |
|
---|
199 | TBGLShader3D = class(TBGLCustomShader)
|
---|
200 | protected
|
---|
201 | FUsed: boolean;
|
---|
202 | FCanvas: TBGLCustomCanvas;
|
---|
203 | FLighting: TBGLCustomLighting;
|
---|
204 | FVertexShaderSource,
|
---|
205 | FFragmentShaderSource: string;
|
---|
206 | FVertexShader,
|
---|
207 | FFragmentShader,
|
---|
208 | FProgram: DWord;
|
---|
209 | function GetUniformVariableSingle(AName: string): TUniformVariableSingle;
|
---|
210 | function GetUniformVariablePointF(AName: string): TUniformVariablePointF;
|
---|
211 | function GetUniformVariablePoint3D(AName: string): TUniformVariablePoint3D;
|
---|
212 | function GetUniformVariableInteger(AName: string): TUniformVariableInteger;
|
---|
213 | function GetUniformVariablePoint(AName: string): TUniformVariablePoint;
|
---|
214 | function GetUniformVariableMatrix4D(AName: string): TUniformVariableMatrix4D;
|
---|
215 | function GetAttributeVariableInteger(AName: string): TAttributeVariableInteger;
|
---|
216 | function GetAttributeVariablePoint(AName: string): TAttributeVariablePoint;
|
---|
217 | function GetAttributeVariableSingle(AName: string): TAttributeVariableSingle;
|
---|
218 | function GetAttributeVariablePointF(AName: string): TAttributeVariablePointF;
|
---|
219 | function GetAttributeVariablePoint3D(AName: string): TAttributeVariablePoint3D;
|
---|
220 | procedure SetUniformSingle(AVariable: DWord; const AValue; AElementCount: integer; AComponentCount: integer);
|
---|
221 | procedure SetUniformInteger(AVariable: DWord; const AValue; AElementCount: integer; AComponentCount: integer);
|
---|
222 | procedure CheckUsage(AUsing: boolean);
|
---|
223 | procedure StartUse; override;
|
---|
224 | procedure EndUse; override;
|
---|
225 | property Canvas: TBGLCustomCanvas read FCanvas;
|
---|
226 | public
|
---|
227 | constructor Create(ACanvas: TBGLCustomCanvas; AVertexShaderSource: string;
|
---|
228 | AFragmentShaderSource: string; AVaryingVariables: string = '';
|
---|
229 | AVersion: string = '120');
|
---|
230 | destructor Destroy; override;
|
---|
231 | property UniformSingle[AName: string]: TUniformVariableSingle read GetUniformVariableSingle;
|
---|
232 | property UniformPointF[AName: string]: TUniformVariablePointF read GetUniformVariablePointF;
|
---|
233 | property UniformPoint3D[AName: string]: TUniformVariablePoint3D read GetUniformVariablePoint3D;
|
---|
234 | property UniformInteger[AName: string]: TUniformVariableInteger read GetUniformVariableInteger;
|
---|
235 | property UniformPoint[AName: string]: TUniformVariablePoint read GetUniformVariablePoint;
|
---|
236 | property UniformMatrix4D[AName: string]: TUniformVariableMatrix4D read GetUniformVariableMatrix4D;
|
---|
237 | property AttributeSingle[AName: string]: TAttributeVariableSingle read GetAttributeVariableSingle;
|
---|
238 | property AttributePointF[AName: string]: TAttributeVariablePointF read GetAttributeVariablePointF;
|
---|
239 | property AttributePoint3D[AName: string]: TAttributeVariablePoint3D read GetAttributeVariablePoint3D;
|
---|
240 | property AttributeInteger[AName: string]: TAttributeVariableInteger read GetAttributeVariableInteger;
|
---|
241 | property AttributePoint[AName: string]: TAttributeVariablePoint read GetAttributeVariablePoint;
|
---|
242 | property IsUsed: boolean read FUsed;
|
---|
243 | end;
|
---|
244 |
|
---|
245 | function ProjectionToOpenGL(AProj: TProjection3D; ANear, AFar: Single): TMatrix4D;
|
---|
246 |
|
---|
247 | implementation
|
---|
248 |
|
---|
249 | uses SysUtils, BGRAColorInt;
|
---|
250 |
|
---|
251 | type
|
---|
252 |
|
---|
253 | { TShaderWithTexture }
|
---|
254 |
|
---|
255 | TShaderWithTexture = class(TBGLShader3D)
|
---|
256 | private
|
---|
257 | function GetTexture: integer;
|
---|
258 | procedure SetTexture(AValue: integer);
|
---|
259 | protected
|
---|
260 | FTextureUniform: TUniformVariableInteger;
|
---|
261 | procedure StartUse; override;
|
---|
262 | public
|
---|
263 | class function GetCodeForTextureColor: string;
|
---|
264 | constructor Create(ACanvas: TBGLCustomCanvas; AFragmentShader: string; ATexture: integer = 0);
|
---|
265 | property Texture: integer read GetTexture write SetTexture;
|
---|
266 | end;
|
---|
267 |
|
---|
268 | function ProjectionToOpenGL(AProj: TProjection3D; ANear, AFar: Single): TMatrix4D;
|
---|
269 | begin
|
---|
270 | result[1,1] := AProj.Zoom.X; result[2,1] := 0; result[3,1] := -(AProj.Center.x + 0.5); result[4,1] := 0;
|
---|
271 | result[1,2] := 0; result[2,2] := AProj.Zoom.Y; result[3,2] := -(AProj.Center.y + 0.5); result[4,2] := 0;
|
---|
272 | result[1,3] := 0; result[2,3] := 0; result[3,3] := -2/(AFar-ANear); result[4,3] := -1 - AFar*result[3,3];
|
---|
273 | result[1,4] := 0; result[2,4] := 0; result[3,4] := -1; result[4,4] := 0;
|
---|
274 | end;
|
---|
275 |
|
---|
276 | { TUniformVariableMatrix4D }
|
---|
277 |
|
---|
278 | procedure TUniformVariableMatrix4D.SetValue(const AValue: TMatrix4D);
|
---|
279 | begin
|
---|
280 | if CompareMem(@AValue, @FValue, sizeof(FValue)) then Exit;
|
---|
281 | FValue:=AValue;
|
---|
282 | if FProgram.IsUsed then Update;
|
---|
283 | end;
|
---|
284 |
|
---|
285 | procedure TUniformVariableMatrix4D.Update;
|
---|
286 | begin
|
---|
287 | FProgram.SetUniformSingle(FVariable, FValue, 1, 16);
|
---|
288 | end;
|
---|
289 |
|
---|
290 | { TShaderWithTexture }
|
---|
291 |
|
---|
292 | function TShaderWithTexture.GetTexture: integer;
|
---|
293 | begin
|
---|
294 | result := FTextureUniform.Value;
|
---|
295 | end;
|
---|
296 |
|
---|
297 | procedure TShaderWithTexture.SetTexture(AValue: integer);
|
---|
298 | begin
|
---|
299 | FTextureUniform.Value := AValue;
|
---|
300 | end;
|
---|
301 |
|
---|
302 | procedure TShaderWithTexture.StartUse;
|
---|
303 | begin
|
---|
304 | inherited StartUse;
|
---|
305 | FTextureUniform.Update;
|
---|
306 | end;
|
---|
307 |
|
---|
308 | class function TShaderWithTexture.GetCodeForTextureColor: string;
|
---|
309 | begin
|
---|
310 | result := 'texture2D(texture, texture_coordinate)';
|
---|
311 | end;
|
---|
312 |
|
---|
313 | constructor TShaderWithTexture.Create(ACanvas: TBGLCustomCanvas;
|
---|
314 | AFragmentShader: string; ATexture: integer);
|
---|
315 | begin
|
---|
316 | inherited Create(ACanvas,
|
---|
317 | 'void main(void) ' +
|
---|
318 | '{ ' +
|
---|
319 | ' gl_Position = gl_ProjectionMatrix * gl_Vertex; ' +
|
---|
320 | ' texture_coordinate = vec2(gl_MultiTexCoord0); ' +
|
---|
321 | ' N = gl_Normal; ' +
|
---|
322 | ' V = vec3(gl_Vertex); ' +
|
---|
323 | '} ',
|
---|
324 |
|
---|
325 | 'uniform sampler2D texture; ' +
|
---|
326 | AFragmentShader,
|
---|
327 |
|
---|
328 | 'varying vec2 texture_coordinate; ' +
|
---|
329 | 'varying vec3 N; ' +
|
---|
330 | 'varying vec3 V; ');
|
---|
331 | FTextureUniform := UniformInteger['texture'];
|
---|
332 | Texture := ATexture;
|
---|
333 | end;
|
---|
334 |
|
---|
335 | { TAttributeVariablePoint3D }
|
---|
336 |
|
---|
337 | procedure TAttributeVariablePoint3D.Init(AProgram: TObject; AAttribute: DWord);
|
---|
338 | begin
|
---|
339 | inherited Init(AProgram,AAttribute,3,True);
|
---|
340 | end;
|
---|
341 |
|
---|
342 | { TAttributeVariablePointF }
|
---|
343 |
|
---|
344 | procedure TAttributeVariablePointF.Init(AProgram: TObject; AAttribute: DWord);
|
---|
345 | begin
|
---|
346 | inherited Init(AProgram,AAttribute,2,True);
|
---|
347 | end;
|
---|
348 |
|
---|
349 | { TAttributeVariableInteger }
|
---|
350 |
|
---|
351 | procedure TAttributeVariableInteger.Init(AProgram: TObject; AAttribute: DWord);
|
---|
352 | begin
|
---|
353 | inherited Init(AProgram,AAttribute,1,False);
|
---|
354 | end;
|
---|
355 |
|
---|
356 | { TAttributeVariablePoint }
|
---|
357 |
|
---|
358 | procedure TAttributeVariablePoint.Init(AProgram: TObject; AAttribute: DWord);
|
---|
359 | begin
|
---|
360 | inherited Init(AProgram,AAttribute,2,False);
|
---|
361 | end;
|
---|
362 |
|
---|
363 | { TAttributeVariableSingle }
|
---|
364 |
|
---|
365 | procedure TAttributeVariableSingle.Init(AProgram: TObject; AAttribute: DWord);
|
---|
366 | begin
|
---|
367 | inherited Init(AProgram,AAttribute,1,True);
|
---|
368 | end;
|
---|
369 |
|
---|
370 | { TUniformVariablePoint }
|
---|
371 |
|
---|
372 | procedure TUniformVariablePoint.SetValue(const AValue: TPoint);
|
---|
373 | begin
|
---|
374 | if (FValue.x=AValue.x) and (FValue.y=AValue.y) then Exit;
|
---|
375 | FValue:=AValue;
|
---|
376 | if FProgram.IsUsed then Update;
|
---|
377 | end;
|
---|
378 |
|
---|
379 | procedure TUniformVariablePoint.Update;
|
---|
380 | begin
|
---|
381 | FProgram.SetUniformInteger(FVariable, FValue, 1, 2);
|
---|
382 | end;
|
---|
383 |
|
---|
384 | { TUniformVariableInteger }
|
---|
385 |
|
---|
386 | procedure TUniformVariableInteger.SetValue(const AValue: Integer);
|
---|
387 | begin
|
---|
388 | if FValue=AValue then Exit;
|
---|
389 | FValue:=AValue;
|
---|
390 | if FProgram.IsUsed then Update;
|
---|
391 | end;
|
---|
392 |
|
---|
393 | procedure TUniformVariableInteger.Update;
|
---|
394 | begin
|
---|
395 | FProgram.SetUniformInteger(FVariable, FValue, 1, 1);
|
---|
396 | end;
|
---|
397 |
|
---|
398 | { TUniformVariablePoint3D }
|
---|
399 |
|
---|
400 | procedure TUniformVariablePoint3D.SetValue(const AValue: TPoint3D);
|
---|
401 | begin
|
---|
402 | if (FValue.x=AValue.x) and (FValue.y=AValue.y) and (FValue.z=AValue.z) then Exit;
|
---|
403 | FValue:=AValue;
|
---|
404 | if FProgram.IsUsed then Update;
|
---|
405 | end;
|
---|
406 |
|
---|
407 | procedure TUniformVariablePoint3D.Update;
|
---|
408 | begin
|
---|
409 | FProgram.SetUniformSingle(FVariable, FValue, 1, 3);
|
---|
410 | end;
|
---|
411 |
|
---|
412 | { TUniformVariablePointF }
|
---|
413 |
|
---|
414 | procedure TUniformVariablePointF.SetValue(const AValue: TPointF);
|
---|
415 | begin
|
---|
416 | if (FValue.x=AValue.x) and (FValue.y=AValue.y) then Exit;
|
---|
417 | FValue:=AValue;
|
---|
418 | if FProgram.IsUsed then Update;
|
---|
419 | end;
|
---|
420 |
|
---|
421 | procedure TUniformVariablePointF.Update;
|
---|
422 | begin
|
---|
423 | FProgram.SetUniformSingle(FVariable, FValue, 1, 2);
|
---|
424 | end;
|
---|
425 |
|
---|
426 | { TUniformVariableSingle }
|
---|
427 |
|
---|
428 | procedure TUniformVariableSingle.SetValue(const AValue: single);
|
---|
429 | begin
|
---|
430 | if FValue=AValue then Exit;
|
---|
431 | FValue:=AValue;
|
---|
432 | if FProgram.IsUsed then Update;
|
---|
433 | end;
|
---|
434 |
|
---|
435 | procedure TUniformVariableSingle.Update;
|
---|
436 | begin
|
---|
437 | FProgram.SetUniformSingle(FVariable, FValue, 1, 1);
|
---|
438 | end;
|
---|
439 |
|
---|
440 | { TUniformVariable }
|
---|
441 |
|
---|
442 | procedure TUniformVariable.Init(AProgram: TBGLShader3D; AVariable: DWord);
|
---|
443 | begin
|
---|
444 | FProgram := AProgram;
|
---|
445 | FVariable := AVariable;
|
---|
446 | end;
|
---|
447 |
|
---|
448 | { TBGLShader3D }
|
---|
449 |
|
---|
450 | function TBGLShader3D.GetUniformVariableSingle(AName: string): TUniformVariableSingle;
|
---|
451 | begin
|
---|
452 | {$push}{$hints off}
|
---|
453 | fillchar(result,sizeof(result),0);
|
---|
454 | result.Init(self, FCanvas.Lighting.GetUniformVariable(FProgram, AName));
|
---|
455 | {$pop}
|
---|
456 | end;
|
---|
457 |
|
---|
458 | function TBGLShader3D.GetUniformVariablePointF(AName: string): TUniformVariablePointF;
|
---|
459 | begin
|
---|
460 | {$push}{$hints off}
|
---|
461 | fillchar(result,sizeof(result),0);
|
---|
462 | result.Init(self, FCanvas.Lighting.GetUniformVariable(FProgram, AName));
|
---|
463 | {$pop}
|
---|
464 | end;
|
---|
465 |
|
---|
466 | function TBGLShader3D.GetUniformVariablePoint3D(AName: string): TUniformVariablePoint3D;
|
---|
467 | begin
|
---|
468 | {$push}{$hints off}
|
---|
469 | fillchar(result,sizeof(result),0);
|
---|
470 | result.Init(self, FCanvas.Lighting.GetUniformVariable(FProgram, AName));
|
---|
471 | {$pop}
|
---|
472 | end;
|
---|
473 |
|
---|
474 | function TBGLShader3D.GetUniformVariableInteger(AName: string): TUniformVariableInteger;
|
---|
475 | begin
|
---|
476 | {$push}{$hints off}
|
---|
477 | fillchar(result,sizeof(result),0);
|
---|
478 | result.Init(self, FCanvas.Lighting.GetUniformVariable(FProgram, AName));
|
---|
479 | {$pop}
|
---|
480 | end;
|
---|
481 |
|
---|
482 | function TBGLShader3D.GetUniformVariablePoint(AName: string): TUniformVariablePoint;
|
---|
483 | begin
|
---|
484 | {$push}{$hints off}
|
---|
485 | fillchar(result,sizeof(result),0);
|
---|
486 | result.Init(self, FCanvas.Lighting.GetUniformVariable(FProgram, AName));
|
---|
487 | {$pop}
|
---|
488 | end;
|
---|
489 |
|
---|
490 | function TBGLShader3D.GetUniformVariableMatrix4D(AName: string): TUniformVariableMatrix4D;
|
---|
491 | begin
|
---|
492 | {$push}{$hints off}
|
---|
493 | fillchar(result,sizeof(result),0);
|
---|
494 | result.Init(self, FCanvas.Lighting.GetUniformVariable(FProgram, AName));
|
---|
495 | {$pop}
|
---|
496 | end;
|
---|
497 |
|
---|
498 | procedure TBGLShader3D.CheckUsage(AUsing: boolean);
|
---|
499 | begin
|
---|
500 | if AUsing <> FUsed then
|
---|
501 | begin
|
---|
502 | if FUsed then raise exception.Create('Shader is in use') else
|
---|
503 | raise exception.Create('Shader is not in use');
|
---|
504 | end;
|
---|
505 | end;
|
---|
506 |
|
---|
507 | function TBGLShader3D.GetAttributeVariableSingle(AName: string): TAttributeVariableSingle;
|
---|
508 | begin
|
---|
509 | {$push}{$hints off}
|
---|
510 | fillchar(result,sizeof(result),0);
|
---|
511 | result.Init(self, FCanvas.Lighting.GetAttribVariable(FProgram, AName));
|
---|
512 | {$pop}
|
---|
513 | end;
|
---|
514 |
|
---|
515 | function TBGLShader3D.GetAttributeVariablePointF(AName: string): TAttributeVariablePointF;
|
---|
516 | begin
|
---|
517 | {$push}{$hints off}
|
---|
518 | fillchar(result,sizeof(result),0);
|
---|
519 | result.Init(self, FCanvas.Lighting.GetAttribVariable(FProgram, AName));
|
---|
520 | {$pop}
|
---|
521 | end;
|
---|
522 |
|
---|
523 | function TBGLShader3D.GetAttributeVariablePoint3D(AName: string): TAttributeVariablePoint3D;
|
---|
524 | begin
|
---|
525 | {$push}{$hints off}
|
---|
526 | fillchar(result,sizeof(result),0);
|
---|
527 | result.Init(self, FCanvas.Lighting.GetAttribVariable(FProgram, AName));
|
---|
528 | {$pop}
|
---|
529 | end;
|
---|
530 |
|
---|
531 | function TBGLShader3D.GetAttributeVariableInteger(AName: string): TAttributeVariableInteger;
|
---|
532 | begin
|
---|
533 | {$push}{$hints off}
|
---|
534 | fillchar(result,sizeof(result),0);
|
---|
535 | result.Init(self, FCanvas.Lighting.GetAttribVariable(FProgram, AName));
|
---|
536 | {$pop}
|
---|
537 | end;
|
---|
538 |
|
---|
539 | function TBGLShader3D.GetAttributeVariablePoint(AName: string): TAttributeVariablePoint;
|
---|
540 | begin
|
---|
541 | {$push}{$hints off}
|
---|
542 | fillchar(result,sizeof(result),0);
|
---|
543 | result.Init(self, FCanvas.Lighting.GetAttribVariable(FProgram, AName));
|
---|
544 | {$pop}
|
---|
545 | end;
|
---|
546 |
|
---|
547 | procedure TBGLShader3D.SetUniformSingle(AVariable: DWord; const AValue; AElementCount: integer; AComponentCount: integer);
|
---|
548 | begin
|
---|
549 | CheckUsage(True);
|
---|
550 | FCanvas.Lighting.SetUniformSingle(AVariable, AValue, AElementCount, AComponentCount);
|
---|
551 | end;
|
---|
552 |
|
---|
553 | procedure TBGLShader3D.SetUniformInteger(AVariable: DWord; const AValue; AElementCount: integer; AComponentCount: integer);
|
---|
554 | begin
|
---|
555 | CheckUsage(True);
|
---|
556 | FCanvas.Lighting.SetUniformInteger(AVariable, AValue, AElementCount, AComponentCount);
|
---|
557 | end;
|
---|
558 |
|
---|
559 | constructor TBGLShader3D.Create(ACanvas: TBGLCustomCanvas;
|
---|
560 | AVertexShaderSource: string; AFragmentShaderSource: string;
|
---|
561 | AVaryingVariables: string; AVersion: string);
|
---|
562 | begin
|
---|
563 | FCanvas := ACanvas;
|
---|
564 | FLighting := FCanvas.Lighting;
|
---|
565 | FVertexShaderSource:= '#version ' + AVersion + #10 + AVaryingVariables + #10 + AVertexShaderSource;
|
---|
566 | FFragmentShaderSource:= '#version ' + AVersion + #10 + AVaryingVariables + #10 + AFragmentShaderSource;
|
---|
567 | FVertexShader := 0;
|
---|
568 | FFragmentShader := 0;
|
---|
569 | FProgram := 0;
|
---|
570 | try
|
---|
571 | FVertexShader := FLighting.MakeVertexShader(FVertexShaderSource);
|
---|
572 | FFragmentShader := FLighting.MakeFragmentShader(FFragmentShaderSource);
|
---|
573 | FProgram := FLighting.MakeShaderProgram(FVertexShader,FFragmentShader);
|
---|
574 | except on ex:Exception do
|
---|
575 | begin
|
---|
576 | FLighting.DeleteShaderProgram(FProgram);
|
---|
577 | FLighting.DeleteShaderObject(FFragmentShader);
|
---|
578 | FLighting.DeleteShaderObject(FVertexShader);
|
---|
579 | raise ex;
|
---|
580 | end;
|
---|
581 | end;
|
---|
582 | end;
|
---|
583 |
|
---|
584 | destructor TBGLShader3D.Destroy;
|
---|
585 | begin
|
---|
586 | if IsUsed then raise exception.Create('Shader is still in use');
|
---|
587 | inherited Destroy;
|
---|
588 | end;
|
---|
589 |
|
---|
590 | procedure TBGLShader3D.StartUse;
|
---|
591 | begin
|
---|
592 | CheckUsage(False);
|
---|
593 | FLighting.UseProgram(FProgram);
|
---|
594 | FUsed:= True;
|
---|
595 | end;
|
---|
596 |
|
---|
597 | procedure TBGLShader3D.EndUse;
|
---|
598 | begin
|
---|
599 | CheckUsage(True);
|
---|
600 | FLighting.UseProgram(0);
|
---|
601 | FUsed:= False;
|
---|
602 | end;
|
---|
603 |
|
---|
604 | { TBGLLighting3D }
|
---|
605 |
|
---|
606 | procedure TBGLLighting3D.SetUseBuiltIn(AValue: boolean);
|
---|
607 | begin
|
---|
608 | if FUseBuiltIn=AValue then Exit;
|
---|
609 | FUseBuiltIn:=AValue;
|
---|
610 | FCanvas.Lighting.BuiltInLightingEnabled := FUseBuiltIn;
|
---|
611 | end;
|
---|
612 |
|
---|
613 | procedure TBGLLighting3D.Init;
|
---|
614 | var
|
---|
615 | i: Integer;
|
---|
616 | v: TPoint3D;
|
---|
617 | int: single;
|
---|
618 | num: string;
|
---|
619 | minInt: string;
|
---|
620 | colorMult: TColorF;
|
---|
621 | begin
|
---|
622 | FShaderLightingCode:=
|
---|
623 | 'void main(void) ' +
|
---|
624 | '{ ' +
|
---|
625 | ' vec3 L, H; float d; float sat, sumUnsat; vec4 color, clampedColor; vec4 unsat; ' +
|
---|
626 | ' vec3 Idiff = vec3(gl_LightModel.ambient); ' +
|
---|
627 | ' vec4 Ispec = vec4(0,0,0,0); ' +
|
---|
628 | ' vec3 NN = normalize(N); ';
|
---|
629 | with FCanvas.Lighting do
|
---|
630 | begin
|
---|
631 | AmbiantLightF := FAmbiantLight;
|
---|
632 | for i := 0 to FLights.Count-1 do
|
---|
633 | with TBGRALight3D(FLights[i]) do
|
---|
634 | begin
|
---|
635 | str(GetMinIntensity,minInt);
|
---|
636 | if IsDirectional then
|
---|
637 | begin
|
---|
638 | v := -GetDirection;
|
---|
639 | v.z := -v.z;
|
---|
640 | num := IntToStr(AddDirectionalLight(GetColorF, v));
|
---|
641 | str(GetMinIntensity,minInt);
|
---|
642 | FShaderLightingCode +=
|
---|
643 | ' L = gl_LightSource['+num+'].position.xyz; ' +
|
---|
644 | ' Idiff += vec3(gl_LightSource['+num+'].diffuse * max(dot(NN,L), '+minInt+') ); ' +
|
---|
645 | ' if (gl_FrontMaterial.shininess > 0) { ' +
|
---|
646 | ' H = normalize(L + vec3(0,0,1)); ' +
|
---|
647 | ' Ispec += gl_LightSource['+num+'].specular * pow(abs(dot(NN,H)), gl_FrontMaterial.shininess*2); ' +
|
---|
648 | ' } ';
|
---|
649 | end
|
---|
650 | else
|
---|
651 | begin
|
---|
652 | int := GetIntensity*0.75;
|
---|
653 | if int > 0 then
|
---|
654 | begin
|
---|
655 | v := GetPosition;
|
---|
656 | v.z := -v.z;
|
---|
657 | colorMult := GetColorF * ColorF(int,int,int,1);
|
---|
658 | num := IntToStr(AddPointLight(colorMult, v, 0,1));
|
---|
659 | str(GetMinIntensity/int,minInt);
|
---|
660 | FShaderLightingCode +=
|
---|
661 | ' L = (gl_LightSource['+num+'].position.xyz - V).xyz; ' +
|
---|
662 | ' d = length(L); ' +
|
---|
663 | ' L *= 1/d; ' +
|
---|
664 | ' Idiff += vec3(gl_LightSource['+num+'].diffuse * max(dot(NN,L)/(d*d), '+minInt+') ); ' +
|
---|
665 | ' if (gl_FrontMaterial.shininess > 0) { ' +
|
---|
666 | ' H = normalize(L + vec3(0,0,1)); ' +
|
---|
667 | ' Ispec += gl_LightSource['+num+'].specular * pow(abs(dot(NN,H))/(d*d), gl_FrontMaterial.shininess*2); ' +
|
---|
668 | ' } ';
|
---|
669 | end;
|
---|
670 | end;
|
---|
671 |
|
---|
672 | end;
|
---|
673 | end;
|
---|
674 | FShaderLightingCode +=
|
---|
675 | ' color = #color# * vec4(Idiff,1) + Ispec; ' +
|
---|
676 | ' clampedColor = clamp(color,0,1); ' +
|
---|
677 | ' sat = dot( color - clampedColor, vec4(1) ); ' +
|
---|
678 | ' if (sat > 0) { ' +
|
---|
679 | ' unsat = vec4(1) - clampedColor; ' +
|
---|
680 | ' sumUnsat = unsat[0]+unsat[1]+unsat[2]; ' +
|
---|
681 | ' if (sumUnsat > 0) { ' +
|
---|
682 | ' sat *= max(max(unsat[0],unsat[1]),unsat[2]) / sumUnsat; ' +
|
---|
683 | ' gl_FragColor = clamp(color + vec4(sat,sat,sat,0),0,1); ' +
|
---|
684 | ' } ' +
|
---|
685 | ' else gl_FragColor = clampedColor; ' +
|
---|
686 | ' } ' +
|
---|
687 | ' else gl_FragColor = clampedColor; ' +
|
---|
688 | '} ';
|
---|
689 | end;
|
---|
690 |
|
---|
691 | constructor TBGLLighting3D.Create(ACanvas: TBGLCustomCanvas; AAmbiantLight: TColorF; ALights: TList);
|
---|
692 | begin
|
---|
693 | FCanvas := ACanvas;
|
---|
694 | FLights := ALights;
|
---|
695 | FAmbiantLight := AAmbiantLight;
|
---|
696 | Init;
|
---|
697 | end;
|
---|
698 |
|
---|
699 | procedure TBGLLighting3D.SetSpecularIndex(AIndex: Integer);
|
---|
700 | begin
|
---|
701 | FCanvas.Lighting.SetSpecularIndex(AIndex);
|
---|
702 | end;
|
---|
703 |
|
---|
704 | destructor TBGLLighting3D.Destroy;
|
---|
705 | begin
|
---|
706 | FCanvas.Lighting.SetSpecularIndex(0);
|
---|
707 | FCanvas.Lighting.ClearLights;
|
---|
708 | UseOpenGLBuiltInLighting := false;
|
---|
709 | inherited Destroy;
|
---|
710 | end;
|
---|
711 |
|
---|
712 | { TBGLScene3D }
|
---|
713 |
|
---|
714 | function TBGLScene3D.LoadBitmapFromFileUTF8(AFilenameUTF8: string
|
---|
715 | ): TBGRACustomBitmap;
|
---|
716 | begin
|
---|
717 | if BGLBitmapFactory <> nil then
|
---|
718 | Result:= BGLBitmapFactory.Create(AFilenameUTF8,True)
|
---|
719 | else
|
---|
720 | result := inherited LoadBitmapFromFileUTF8(AFilenameUTF8);
|
---|
721 | end;
|
---|
722 |
|
---|
723 | procedure TBGLScene3D.RenderGL(ACanvas: TBGLCustomCanvas; AMaxZ: single);
|
---|
724 | var
|
---|
725 | renderer: TBGLRenderer3D;
|
---|
726 | begin
|
---|
727 | renderer := TBGLRenderer3D.Create(ACanvas, self, AMaxZ);
|
---|
728 | Render(renderer);
|
---|
729 | renderer.Free;
|
---|
730 | end;
|
---|
731 |
|
---|
732 | { TBGLRenderer3D }
|
---|
733 |
|
---|
734 | function TBGLRenderer3D.GetHasZBuffer: boolean;
|
---|
735 | begin
|
---|
736 | result := FHasZBuffer;
|
---|
737 | end;
|
---|
738 |
|
---|
739 | function TBGLRenderer3D.GetGlobalScale: single;
|
---|
740 | begin
|
---|
741 | result := FGlobalScale;
|
---|
742 | end;
|
---|
743 |
|
---|
744 | function TBGLRenderer3D.GetSurfaceWidth: integer;
|
---|
745 | begin
|
---|
746 | result := FCanvas.Width;
|
---|
747 | end;
|
---|
748 |
|
---|
749 | function TBGLRenderer3D.GetSurfaceHeight: integer;
|
---|
750 | begin
|
---|
751 | result := FCanvas.Height;
|
---|
752 | end;
|
---|
753 |
|
---|
754 | {$PUSH}{$OPTIMIZATION OFF} //avoid internal error 2012090607
|
---|
755 | procedure TBGLRenderer3D.SetProjection(const AValue: TProjection3D);
|
---|
756 | begin
|
---|
757 | inherited SetProjection(AValue);
|
---|
758 | FProjectionMatrix := ProjectionToOpenGL(AValue, FOptions.MinZ, FFar) *
|
---|
759 | OrthoProjectionToOpenGL(0,0,FCanvas.Width,FCanvas.Height);
|
---|
760 | FCanvas.ProjectionMatrix := FProjectionMatrix;
|
---|
761 | end;
|
---|
762 | {$POP}
|
---|
763 |
|
---|
764 | function TBGLRenderer3D.GetHandlesNearClipping: boolean;
|
---|
765 | begin
|
---|
766 | result := true;
|
---|
767 | end;
|
---|
768 |
|
---|
769 | function TBGLRenderer3D.GetHandlesFaceCulling: boolean;
|
---|
770 | begin
|
---|
771 | result := FShader <> nil;
|
---|
772 | end;
|
---|
773 |
|
---|
774 | procedure TBGLRenderer3D.InitLighting(AUseOpenGLBuiltInLighting: boolean);
|
---|
775 | var
|
---|
776 | fragmentShaderCode: string;
|
---|
777 | begin
|
---|
778 | if not Assigned(FLightingGL) then
|
---|
779 | begin
|
---|
780 | FLightingGL := TBGLLighting3D.Create(FCanvas, FAmbiantLight, FLights);
|
---|
781 |
|
---|
782 | if (FOptions.LightingInterpolation <> liLowQuality) and FCanvas.Lighting.SupportShaders then
|
---|
783 | begin
|
---|
784 | fragmentShaderCode := StringReplace(FLightingGL.ShaderLightingCode, '#color#', 'gl_Color', []);
|
---|
785 | FShader := FCanvas.Lighting.Shader[fragmentShaderCode];
|
---|
786 | if (FShader = nil) and FCanvas.Lighting.SupportShaders then
|
---|
787 | begin
|
---|
788 | FShader := TBGLShader3D.Create(FCanvas,
|
---|
789 | 'void main(void) ' +
|
---|
790 | '{ ' +
|
---|
791 | ' gl_Position = gl_ProjectionMatrix * gl_Vertex; ' +
|
---|
792 | ' gl_FrontColor = gl_Color; ' +
|
---|
793 | ' gl_BackColor = gl_Color; ' +
|
---|
794 | ' N = gl_Normal; ' +
|
---|
795 | ' V = vec3(gl_Vertex); ' +
|
---|
796 | '} ',
|
---|
797 |
|
---|
798 | fragmentShaderCode,
|
---|
799 |
|
---|
800 | 'varying vec3 N; ' +
|
---|
801 | 'varying vec3 V; ');
|
---|
802 | FCanvas.Lighting.Shader[fragmentShaderCode] := FShader;
|
---|
803 | end;
|
---|
804 |
|
---|
805 | fragmentShaderCode := StringReplace(FLightingGL.ShaderLightingCode, '#color#', TShaderWithTexture.GetCodeForTextureColor, []);
|
---|
806 | FShaderWithTexture := FCanvas.Lighting.Shader[fragmentShaderCode];
|
---|
807 | if (FShaderWithTexture = nil) and FCanvas.Lighting.SupportShaders then
|
---|
808 | begin
|
---|
809 | FShaderWithTexture := TShaderWithTexture.Create(FCanvas, fragmentShaderCode, 0);
|
---|
810 | FCanvas.Lighting.Shader[fragmentShaderCode] := FShaderWithTexture;
|
---|
811 | end;
|
---|
812 | end else
|
---|
813 | begin
|
---|
814 | FLightingGL.UseOpenGLBuiltInLighting := AUseOpenGLBuiltInLighting;
|
---|
815 | if not AUseOpenGLBuiltInLighting then
|
---|
816 | FBGRAShader := TBGRAShader3D.Create(FAmbiantLight, FLights);
|
---|
817 | end;
|
---|
818 | end;
|
---|
819 | end;
|
---|
820 |
|
---|
821 | constructor TBGLRenderer3D.Create(ACanvas: TBGLCustomCanvas;
|
---|
822 | AScene: TBGRAScene3D; AFar: single);
|
---|
823 | begin
|
---|
824 | FCanvas := ACanvas;
|
---|
825 | FOptions := AScene.RenderingOptions;
|
---|
826 | FLights := AScene.MakeLightList;
|
---|
827 | FAmbiantLight := AScene.AmbiantLightColorF;
|
---|
828 | FGlobalScale:= 1;
|
---|
829 | FHasZBuffer := FOptions.PerspectiveMode = pmZBuffer;
|
---|
830 | FFactorZ := -2/(FFar-FOptions.MinZ);
|
---|
831 | FAddZ := -1 - FFar*FFactorZ;
|
---|
832 | FFar := AFar;
|
---|
833 | if FHasZBuffer then ACanvas.StartZBuffer;
|
---|
834 | FOldCulling:= FCanvas.FaceCulling;
|
---|
835 | FOldMatrix := FCanvas.Matrix;
|
---|
836 | FCanvas.ResetTransform;
|
---|
837 | FOldProjection := FCanvas.ProjectionMatrix;
|
---|
838 | FCanvas.ProjectionMatrix := MatrixIdentity4D;
|
---|
839 |
|
---|
840 | FShader := nil;
|
---|
841 | FShaderWithTexture := nil;
|
---|
842 |
|
---|
843 | InitLighting(False);
|
---|
844 | end;
|
---|
845 |
|
---|
846 | function TBGLRenderer3D.RenderFace(var ADescription: TFaceRenderingDescription;
|
---|
847 | AComputeCoordinate: TComputeProjectionFunc): boolean;
|
---|
848 | var
|
---|
849 | NormalCenter3D,PtCenter3D: TPoint3D_128;
|
---|
850 | ColorCenter: TBGRAPixel;
|
---|
851 |
|
---|
852 | procedure ComputeCenter;
|
---|
853 | var j: NativeInt;
|
---|
854 | begin
|
---|
855 | with ADescription do
|
---|
856 | begin
|
---|
857 | PtCenter3D := Point3D_128_Zero;
|
---|
858 | NormalCenter3D := Point3D_128_Zero;
|
---|
859 | for j := 0 to NbVertices-1 do
|
---|
860 | begin
|
---|
861 | PtCenter3D += Positions3D[j];
|
---|
862 | NormalCenter3D += Normals3D[j];
|
---|
863 | end;
|
---|
864 | PtCenter3D *= (1/NbVertices);
|
---|
865 | Normalize3D_128(NormalCenter3D);
|
---|
866 | ColorCenter := MergeBGRA(slice(Colors,NbVertices));
|
---|
867 | end;
|
---|
868 | end;
|
---|
869 |
|
---|
870 | var tex: IBGLTexture;
|
---|
871 | i,j: NativeInt;
|
---|
872 | begin
|
---|
873 | result := true;
|
---|
874 |
|
---|
875 | if not ProjectionDefined then
|
---|
876 | raise exception.Create('Projection must be defined before drawing faces');
|
---|
877 |
|
---|
878 | If ADescription.Texture <> nil then
|
---|
879 | tex := ADescription.Texture.GetTextureGL as IBGLTexture
|
---|
880 | else
|
---|
881 | tex := nil;
|
---|
882 |
|
---|
883 | with ADescription do
|
---|
884 | begin
|
---|
885 | if ADescription.Biface then
|
---|
886 | FCanvas.FaceCulling := fcNone
|
---|
887 | else
|
---|
888 | FCanvas.FaceCulling := fcKeepCW;
|
---|
889 |
|
---|
890 | if ADescription.Material.GetSpecularOn then
|
---|
891 | FLightingGL.SetSpecularIndex(ADescription.Material.GetSpecularIndex)
|
---|
892 | else
|
---|
893 | FLightingGL.SetSpecularIndex(0);
|
---|
894 |
|
---|
895 | if tex <> nil then
|
---|
896 | begin
|
---|
897 | FCanvas.Lighting.ActiveShader := FShaderWithTexture;
|
---|
898 |
|
---|
899 | if Assigned(FBGRAShader) then
|
---|
900 | begin
|
---|
901 | FBGRAShader.Prepare(ADescription);
|
---|
902 |
|
---|
903 | if length(FShadedColorsF) < NbVertices then
|
---|
904 | setlength(FShadedColorsF, NbVertices);
|
---|
905 | for i := 0 to NbVertices-1 do
|
---|
906 | FShadedColorsF[i] := BGRAToColorF(ColorIntToBGRA(FBGRAShader.Int65536Apply(Positions3D[i],Normals3D[i],BGRAWhite), true), false);
|
---|
907 |
|
---|
908 | for i := 0 to NbVertices-1 do
|
---|
909 | Positions3D[i].z := -Positions3D[i].z;
|
---|
910 |
|
---|
911 | if NbVertices = 3 then
|
---|
912 | tex.DrawTriangle(slice(Positions3D,3),slice(TexCoords,3),slice(FShadedColorsF,3))
|
---|
913 | else if NbVertices = 4 then
|
---|
914 | tex.DrawQuad(slice(Positions3D,4),slice(TexCoords,4),slice(FShadedColorsF,4));
|
---|
915 | end else
|
---|
916 | begin
|
---|
917 | for i := 0 to NbVertices-1 do
|
---|
918 | begin
|
---|
919 | Positions3D[i].z := -Positions3D[i].z;
|
---|
920 | Normals3D[i].z := -Normals3D[i].z;
|
---|
921 | end;
|
---|
922 |
|
---|
923 | if NbVertices = 3 then
|
---|
924 | tex.DrawTriangle(slice(Positions3D,3),slice(Normals3D,3),slice(TexCoords,3))
|
---|
925 | else if NbVertices = 4 then
|
---|
926 | tex.DrawQuad(slice(Positions3D,4),slice(Normals3D,4),slice(TexCoords,4));
|
---|
927 | end;
|
---|
928 | end
|
---|
929 | else
|
---|
930 | begin
|
---|
931 | FCanvas.Lighting.ActiveShader := FShader;
|
---|
932 |
|
---|
933 | if Assigned(FBGRAShader) then
|
---|
934 | begin
|
---|
935 | FBGRAShader.Prepare(ADescription);
|
---|
936 |
|
---|
937 | if length(FShadedColors) < NbVertices then
|
---|
938 | setlength(FShadedColors, NbVertices);
|
---|
939 | for i := 0 to NbVertices-1 do
|
---|
940 | FShadedColors[i] := FBGRAShader.Apply(Positions3D[i],Normals3D[i],Colors[i]);
|
---|
941 |
|
---|
942 | if NbVertices > 4 then
|
---|
943 | begin
|
---|
944 | ComputeCenter;
|
---|
945 | ColorCenter := FBGRAShader.Apply(PtCenter3D,NormalCenter3D,MergeBGRA(slice(Colors,NbVertices)));
|
---|
946 |
|
---|
947 | for i := 0 to NbVertices-1 do
|
---|
948 | Positions3D[i].z := -Positions3D[i].z;
|
---|
949 | PtCenter3D.z := -PtCenter3D.z;
|
---|
950 |
|
---|
951 | i := NbVertices-1;
|
---|
952 | for j := 0 to NbVertices-1 do
|
---|
953 | begin
|
---|
954 | FCanvas.FillTrianglesLinearColor(
|
---|
955 | [Positions3D[i],Positions3D[j],PtCenter3D],
|
---|
956 | [FShadedColors[i],FShadedColors[j],ColorCenter]);
|
---|
957 | i := j;
|
---|
958 | end;
|
---|
959 | end else
|
---|
960 | begin
|
---|
961 | for i := 0 to NbVertices-1 do
|
---|
962 | Positions3D[i].z := -Positions3D[i].z;
|
---|
963 |
|
---|
964 | if NbVertices = 3 then
|
---|
965 | FCanvas.FillTrianglesLinearColor(slice(Positions3D,3),slice(FShadedColors,3))
|
---|
966 | else if NbVertices = 4 then
|
---|
967 | FCanvas.FillQuadsLinearColor(slice(Positions3D,4),slice(FShadedColors,4));
|
---|
968 | end;
|
---|
969 | end else
|
---|
970 | begin
|
---|
971 | for i := 0 to NbVertices-1 do
|
---|
972 | begin
|
---|
973 | Positions3D[i].z := -Positions3D[i].z;
|
---|
974 | Normals3D[i].z := -Normals3D[i].z;
|
---|
975 | end;
|
---|
976 |
|
---|
977 | if NbVertices > 4 then
|
---|
978 | begin
|
---|
979 | ComputeCenter;
|
---|
980 |
|
---|
981 | i := NbVertices-1;
|
---|
982 | for j := 0 to NbVertices-1 do
|
---|
983 | begin
|
---|
984 | FCanvas.FillTrianglesLinearColor(
|
---|
985 | [Positions3D[i],Positions3D[j],PtCenter3D],
|
---|
986 | [Normals3D[i],Normals3D[j],NormalCenter3D],
|
---|
987 | [Colors[i],Colors[j],ColorCenter]);
|
---|
988 | i := j;
|
---|
989 | end;
|
---|
990 | end else
|
---|
991 | begin
|
---|
992 | if NbVertices = 3 then
|
---|
993 | FCanvas.FillTrianglesLinearColor(slice(Positions3D,3),slice(Normals3D,3),slice(Colors,3))
|
---|
994 | else if NbVertices = 4 then
|
---|
995 | FCanvas.FillQuadsLinearColor(slice(Positions3D,4),slice(Normals3D,4),slice(Colors,4));
|
---|
996 | end;
|
---|
997 | end;
|
---|
998 | end;
|
---|
999 | end;
|
---|
1000 | end;
|
---|
1001 |
|
---|
1002 | destructor TBGLRenderer3D.Destroy;
|
---|
1003 | begin
|
---|
1004 | FreeAndNil(FBGRAShader);
|
---|
1005 | FCanvas.Lighting.ActiveShader := nil;
|
---|
1006 | FCanvas.ProjectionMatrix := FOldProjection;
|
---|
1007 | FCanvas.Matrix := FOldMatrix;
|
---|
1008 | FCanvas.FaceCulling := FOldCulling;
|
---|
1009 | FreeAndNil(FLightingGL);
|
---|
1010 | if FHasZBuffer then FCanvas.EndZBuffer;
|
---|
1011 | FLights.Free;
|
---|
1012 | inherited Destroy;
|
---|
1013 | end;
|
---|
1014 |
|
---|
1015 |
|
---|
1016 | end.
|
---|