source: trunk/Packages/bgrabitmap/bgrarenderer3d.pas

Last change on this file was 2, checked in by chronos, 5 years ago
File size: 27.5 KB
Line 
1unit BGRARenderer3D;
2
3{$mode objfpc}{$H+}
4
5interface
6
7uses BGRABitmapTypes,
8 BGRASceneTypes, BGRASSE,
9 BGRAPolygon, BGRAColorInt,
10 Classes, BGRAMatrix3D,
11 BGRAPolygonAliased;
12
13type
14 TInt65536ShaderFunction3D = function (Context: PBasicLightingContext; Color: TBGRAPixel): TColorInt65536 of object;
15
16 { TBGRAShader3D }
17
18 TBGRAShader3D = class
19 protected
20 FAmbiantLightness: integer;
21 FAmbiantLightColor: TColorInt65536;
22 FUseAmbiantColor: boolean;
23 FLights: TList;
24 FContextBlock: TMemoryBlockAlign128;
25 FShaderFunc: TShaderFunction3D;
26 FInt65536ShaderFunc: TInt65536ShaderFunction3D;
27 FContext: PBasicLightingContext;
28 FOnlyDirectionalLights: boolean;
29 FWhiteMaterial: boolean;
30
31 procedure ComputeDiffuseLightness(Context: PSceneLightingContext); inline;
32 procedure ComputeDiffuseLight(Context: PSceneLightingContext); inline;
33 procedure ComputeDiffuseAndSpecularLight(Context: PSceneLightingContext); inline;
34
35 function ApplyNoLighting(Context: PSceneLightingContext; Color: TBGRAPixel): TBGRAPixel;
36 function ApplyLightingWithAmbiantLightnessOnly(Context: PSceneLightingContext; Color: TBGRAPixel): TBGRAPixel;
37 function ApplyLightingWithLightness(Context: PSceneLightingContext; Color: TBGRAPixel): TBGRAPixel;
38 function ApplyLightingWithDiffuseColor(Context: PSceneLightingContext; Color: TBGRAPixel): TBGRAPixel;
39 function ApplyLightingWithDiffuseAndSpecularColor(Context: PSceneLightingContext; Color: TBGRAPixel): TBGRAPixel;
40
41 function Int65536ApplyNoLighting(Context: PSceneLightingContext; Color: TBGRAPixel): TColorInt65536;
42 function Int65536ApplyLightingWithAmbiantLightnessOnly(Context: PSceneLightingContext; Color: TBGRAPixel): TColorInt65536;
43 function Int65536ApplyLightingWithLightness(Context: PSceneLightingContext; Color: TBGRAPixel): TColorInt65536;
44 function Int65536ApplyLightingWithDiffuseColor(Context: PSceneLightingContext; Color: TBGRAPixel): TColorInt65536;
45 function Int65536ApplyLightingWithDiffuseAndSpecularColor(Context: PSceneLightingContext; Color: TBGRAPixel): TColorInt65536;
46 public
47 constructor Create(const AAmbiantLightColorF: TColorF; ALights: TList);
48 destructor Destroy; override;
49 function Apply(APosition: TPoint3D_128; ANormal: TPoint3D_128; AColor: TBGRAPixel): TBGRAPixel;
50 function Int65536Apply(APosition: TPoint3D_128; ANormal: TPoint3D_128; AColor: TBGRAPixel): TColorInt65536;
51 procedure Prepare(constref ADescription: TFaceRenderingDescription);
52 property ShaderFunction: TShaderFunction3D read FShaderFunc;
53 property Int65536ShaderFunction: TInt65536ShaderFunction3D read FInt65536ShaderFunc;
54 property Context: PBasicLightingContext read FContext;
55 property OnlyDirectionalLights: boolean read FOnlyDirectionalLights;
56 end;
57
58 { TBGRARenderer3D }
59
60 TBGRARenderer3D = class(TCustomRenderer3D)
61 protected
62 FColorGradientTempBmp: TBGRACustomBitmap;
63 FZBuffer: PSingle;
64 FOutputSurface, FRenderSurface: TBGRACustomBitmap;
65 FRenderSurfaceMultisample: Integer;
66 FMultishapeFiller: TBGRAMultishapeFiller;
67 FOptions: TRenderingOptions;
68 FShader: TBGRAShader3D;
69 FDepths: array of single;
70 FLightings: array of word;
71
72 FShadedColors: array of TBGRAPixel;
73 FSameShadedColors: boolean;
74
75 FCenter: record
76 proj: TPointF;
77 pos3D,normal3D: TPoint3D_128;
78 color: TBGRAPixel;
79 end;
80
81 function GetHasZBuffer: boolean; override;
82 function GetGlobalScale: single; override;
83 function GetSurfaceWidth: integer; override;
84 function GetSurfaceHeight: integer; override;
85 function GetHandlesNearClipping: boolean; override;
86 function GetHandlesFaceCulling: boolean; override;
87 public
88 constructor Create(AOutputSurface: TBGRACustomBitmap;
89 ARenderingOptions: TRenderingOptions;
90 AAmbiantLightColorF: TColorF;
91 ALights: TList);
92 function RenderFace(var ADescription: TFaceRenderingDescription;
93 AComputeCoordinate: TComputeProjectionFunc): boolean; override;
94 destructor Destroy; override;
95 end;
96
97implementation
98
99uses SysUtils, BGRAResample;
100
101{ TBGRAShader3D }
102
103constructor TBGRAShader3D.Create(const AAmbiantLightColorF: TColorF;
104 ALights: TList);
105var
106 j: Integer;
107begin
108 FAmbiantLightColor := ColorFToColorInt65536(AAmbiantLightColorF);
109 FAmbiantLightness := round((AAmbiantLightColorF[1]+AAmbiantLightColorF[2]+AAmbiantLightColorF[3])/3*32768);
110 FUseAmbiantColor:= (FAmbiantLightColor.r <> FAmbiantLightColor.g) or (FAmbiantLightColor.g <> FAmbiantLightColor.b);
111 FLights := ALights;
112 FContextBlock := TMemoryBlockAlign128.Create(sizeof(TSceneLightingContext));
113 FOnlyDirectionalLights:= true;
114 for j := 0 to FLights.Count-1 do
115 if not TBGRALight3D(FLights[j]).IsDirectional then FOnlyDirectionalLights := false;
116end;
117
118destructor TBGRAShader3D.Destroy;
119begin
120 FreeAndNil(FContextBlock);
121 inherited Destroy;
122end;
123
124function TBGRAShader3D.Apply(APosition: TPoint3D_128; ANormal: TPoint3D_128;
125 AColor: TBGRAPixel): TBGRAPixel;
126begin
127 with Context^ do
128 begin
129 Position := APosition;
130 Normal := ANormal;
131 end;
132 result := ShaderFunction(Context,AColor);
133end;
134
135function TBGRAShader3D.Int65536Apply(APosition: TPoint3D_128;
136 ANormal: TPoint3D_128; AColor: TBGRAPixel): TColorInt65536;
137begin
138 with Context^ do
139 begin
140 Position := APosition;
141 Normal := ANormal;
142 end;
143 result := Int65536ShaderFunction(Context,AColor);
144end;
145
146procedure TBGRAShader3D.Prepare(constref
147 ADescription: TFaceRenderingDescription);
148var
149 UseDiffuseColor: Boolean;
150 j: Integer;
151 ctx: PSceneLightingContext;
152begin
153 with ADescription do
154 begin
155 FWhiteMaterial:= Texture <> nil;
156 if Material.GetSpecularOn then
157 begin
158 FShaderFunc := TShaderFunction3D(@ApplyLightingWithDiffuseAndSpecularColor);
159 FInt65536ShaderFunc := TInt65536ShaderFunction3D(@Int65536ApplyLightingWithDiffuseAndSpecularColor);
160 end else
161 begin
162 UseDiffuseColor := FUseAmbiantColor;
163 if not UseDiffuseColor then
164 begin
165 with Material.GetDiffuseColorInt do
166 UseDiffuseColor := (r <> g) or (g <> b);
167 if not UseDiffuseColor and Material.GetAutoDiffuseColor then
168 begin
169 for j := 0 to FLights.Count-1 do
170 if TBGRALight3D(FLights[j]).GetColoredLight then
171 begin
172 UseDiffuseColor := true;
173 break;
174 end;
175 end;
176 end;
177 if UseDiffuseColor then
178 begin
179 FShaderFunc := TShaderFunction3D(@ApplyLightingWithDiffuseColor);
180 FInt65536ShaderFunc := TInt65536ShaderFunction3D(@Int65536ApplyLightingWithDiffuseColor);
181 end else
182 begin
183 if FLights.Count = 0 then
184 begin
185 if FAmbiantLightness = 32768 then
186 begin
187 FShaderFunc := TShaderFunction3D(@ApplyNoLighting);
188 FInt65536ShaderFunc := TInt65536ShaderFunction3D(@Int65536ApplyNoLighting);
189 end else
190 begin
191 FShaderFunc := TShaderFunction3D(@ApplyLightingWithAmbiantLightnessOnly);
192 FInt65536ShaderFunc := TInt65536ShaderFunction3D(@Int65536ApplyLightingWithAmbiantLightnessOnly);
193 end;
194 end else
195 begin
196 FShaderFunc := TShaderFunction3D(@ApplyLightingWithLightness);
197 FInt65536ShaderFunc := TInt65536ShaderFunction3D(@Int65536ApplyLightingWithLightness);
198 end;
199 end;
200 end;
201
202 ctx := PSceneLightingContext( FContextBlock.Data );
203 ctx^.material := Material;
204 ctx^.LightThroughFactor := LightThroughFactor;
205 ctx^.LightThrough := ctx^.LightThroughFactor > 0;
206 ctx^.SaturationHighF := Material.GetSaturationHigh;
207 ctx^.SaturationLowF := Material.GetSaturationLow;
208 ctx^.SaturationHigh := round(Material.GetSaturationHigh*32768);
209 ctx^.SaturationLow := round(Material.GetSaturationLow*32768);
210 FContext := PBasicLightingContext(ctx);
211 end;
212end;
213
214procedure TBGRAShader3D.ComputeDiffuseLightness(
215 Context: PSceneLightingContext);
216var i: NativeInt;
217begin
218 Context^.lightness := FAmbiantLightness;
219
220 i := FLights.Count-1;
221 while i >= 0 do
222 begin
223 TBGRALight3D(FLights[i]).ComputeDiffuseLightness(Context);
224 dec(i);
225 end;
226end;
227
228procedure TBGRAShader3D.ComputeDiffuseLight(Context: PSceneLightingContext);
229var i: NativeInt;
230 m: TBGRAMaterial3D;
231begin
232 m := TBGRAMaterial3D(Context^.material);
233
234 if FWhiteMaterial or m.GetAutoAmbiantColor then
235 Context^.diffuseColor := FAmbiantLightColor
236 else
237 Context^.diffuseColor := FAmbiantLightColor*m.GetAmbiantColorInt;
238
239 i := FLights.Count-1;
240 while i >= 0 do
241 begin
242 TBGRALight3D(FLights[i]).ComputeDiffuseColor(Context);
243 dec(i);
244 end;
245
246 Context^.diffuseColor.a := 65536;
247end;
248
249procedure TBGRAShader3D.ComputeDiffuseAndSpecularLight(
250 Context: PSceneLightingContext);
251var i: NativeInt;
252 m: TBGRAMaterial3D;
253begin
254 m := TBGRAMaterial3D(Context^.material);
255
256 if FWhiteMaterial or m.GetAutoAmbiantColor then
257 Context^.diffuseColor := FAmbiantLightColor
258 else
259 Context^.diffuseColor := FAmbiantLightColor*m.GetAmbiantColorInt;
260 Context^.specularColor := ColorInt65536(0,0,0,0);
261
262 i := FLights.Count-1;
263 while i >= 0 do
264 begin
265 TBGRALight3D(FLights[i]).ComputeDiffuseAndSpecularColor(Context);
266 dec(i);
267 end;
268
269 Context^.diffuseColor.a := 65536;
270end;
271
272function TBGRAShader3D.ApplyNoLighting(Context: PSceneLightingContext;
273 Color: TBGRAPixel): TBGRAPixel;
274var
275 m: TBGRAMaterial3D;
276begin
277 m := TBGRAMaterial3D(Context^.material);
278
279 if FWhiteMaterial or m.GetAutoAmbiantColor then
280 result := Color
281 else
282 result := ColorIntToBGRA(BGRAToColorInt(Color,True)*m.GetAmbiantColorInt,True);
283end;
284
285function TBGRAShader3D.ApplyLightingWithAmbiantLightnessOnly(
286 Context: PSceneLightingContext; Color: TBGRAPixel): TBGRAPixel;
287var
288 m: TBGRAMaterial3D;
289begin
290 m := TBGRAMaterial3D(Context^.material);
291
292 if not FWhiteMaterial and not m.GetAutoAmbiantColor then
293 Color := ColorIntToBGRA(BGRAToColorInt(Color,True)* m.GetAmbiantColorInt,True);
294
295 if FAmbiantLightness <= 0 then
296 result := BGRA(0,0,0,color.alpha)
297 else
298 result := ApplyIntensityFast(Color, FAmbiantLightness);
299end;
300
301function TBGRAShader3D.ApplyLightingWithLightness(Context: PSceneLightingContext;
302 Color: TBGRAPixel): TBGRAPixel;
303var
304 m: TBGRAMaterial3D;
305begin
306 ComputeDiffuseLightness(Context);
307
308 m := TBGRAMaterial3D(Context^.material);
309 if not FWhiteMaterial and not m.GetAutoSimpleColor then
310 Color := ColorIntToBGRA(BGRAToColorInt(Color,True)*m.GetSimpleColorInt,True);
311
312 with Context^ do
313 if Lightness <= 0 then
314 result := BGRA(0,0,0,color.alpha)
315 else
316 begin
317 if Lightness <= SaturationLow then
318 result := ApplyIntensityFast(Color, Lightness)
319 else if Lightness >= SaturationHigh then
320 result := BGRA(255,255,255,color.alpha)
321 else
322 result := ApplyLightnessFast( ApplyIntensityFast(Color, SaturationLow),
323 (Lightness - SaturationLow)*32767 div (SaturationHigh-SaturationLow)+32768 );
324 end;
325end;
326
327function TBGRAShader3D.ApplyLightingWithDiffuseColor(Context: PSceneLightingContext;
328 Color: TBGRAPixel): TBGRAPixel;
329begin
330 ComputeDiffuseLight(Context);
331 result := ColorIntToBGRA(BGRAToColorInt(Color,True)*Context^.diffuseColor,True);
332end;
333
334function TBGRAShader3D.ApplyLightingWithDiffuseAndSpecularColor(Context: PSceneLightingContext;
335 Color: TBGRAPixel): TBGRAPixel;
336begin
337 ComputeDiffuseAndSpecularLight(Context);
338 result := ColorIntToBGRA(BGRAToColorInt(Color,True)*Context^.diffuseColor + Context^.specularColor,True);
339end;
340
341function TBGRAShader3D.Int65536ApplyNoLighting(Context: PSceneLightingContext;
342 Color: TBGRAPixel): TColorInt65536;
343var
344 m: TBGRAMaterial3D;
345begin
346 m := TBGRAMaterial3D(Context^.material);
347
348 if not FWhiteMaterial and not m.GetAutoAmbiantColor then
349 result := BGRAToColorInt(Color,True)* m.GetAmbiantColorInt
350 else
351 result := BGRAToColorInt(Color,True);
352end;
353
354function TBGRAShader3D.Int65536ApplyLightingWithAmbiantLightnessOnly(
355 Context: PSceneLightingContext; Color: TBGRAPixel): TColorInt65536;
356var
357 m: TBGRAMaterial3D;
358 MaterialColor: TColorInt65536;
359begin
360 m := TBGRAMaterial3D(Context^.material);
361
362 if not FWhiteMaterial and not m.GetAutoAmbiantColor then
363 MaterialColor := BGRAToColorInt(Color,True)* m.GetAmbiantColorInt
364 else
365 MaterialColor := BGRAToColorInt(Color,True);
366
367 if FAmbiantLightness <= 0 then
368 result := ColorInt65536(0,0,0,MaterialColor.a)
369 else
370 result := MaterialColor *
371 ColorInt65536(FAmbiantLightness shl 1,FAmbiantLightness shl 1,FAmbiantLightness shl 1,65536);
372end;
373
374function TBGRAShader3D.Int65536ApplyLightingWithLightness(
375 Context: PSceneLightingContext; Color: TBGRAPixel): TColorInt65536;
376var
377 MaterialColor: TColorInt65536;
378 m: TBGRAMaterial3D;
379 Extra: NativeInt;
380begin
381 ComputeDiffuseLightness(Context);
382
383 m := TBGRAMaterial3D(Context^.material);
384 if not FWhiteMaterial and not m.GetAutoSimpleColor then
385 MaterialColor := BGRAToColorInt(Color,True)*m.GetSimpleColorInt
386 else
387 MaterialColor := BGRAToColorInt(Color,True);
388
389 with Context^ do
390 if Lightness <= 0 then
391 result := ColorInt65536(0,0,0,MaterialColor.a)
392 else
393 begin
394 if Lightness <= SaturationLow then
395 result := MaterialColor * ColorInt65536(Lightness shl 1,Lightness shl 1,Lightness shl 1,65536)
396 else if Lightness >= SaturationHigh then
397 result := ColorInt65536(65536,65536,65536,MaterialColor.a)
398 else
399 begin
400 result := MaterialColor * ColorInt65536(Lightness shl 1,Lightness shl 1,Lightness shl 1,65536);
401 Extra := (Lightness - SaturationLow)*65536 div (SaturationHigh-SaturationLow);
402 result.r += Extra;
403 result.g += Extra;
404 result.b += Extra;
405 end;
406 end;
407end;
408
409function TBGRAShader3D.Int65536ApplyLightingWithDiffuseColor(
410 Context: PSceneLightingContext; Color: TBGRAPixel): TColorInt65536;
411begin
412 ComputeDiffuseLight(Context);
413 result := BGRAToColorInt(Color,True)*Context^.diffuseColor;
414end;
415
416function TBGRAShader3D.Int65536ApplyLightingWithDiffuseAndSpecularColor(
417 Context: PSceneLightingContext; Color: TBGRAPixel): TColorInt65536;
418begin
419 ComputeDiffuseAndSpecularLight(Context);
420 result := BGRAToColorInt(Color,True)*Context^.diffuseColor + Context^.specularColor;
421end;
422
423{ TBGRARenderer3D }
424
425function TBGRARenderer3D.GetHasZBuffer: boolean;
426begin
427 result := Assigned(FZBuffer);
428end;
429
430function TBGRARenderer3D.GetGlobalScale: single;
431begin
432 result := FRenderSurfaceMultisample;
433end;
434
435function TBGRARenderer3D.GetSurfaceWidth: integer;
436begin
437 result := FOutputSurface.Width;
438end;
439
440function TBGRARenderer3D.GetSurfaceHeight: integer;
441begin
442 result := FOutputSurface.Height;
443end;
444
445function TBGRARenderer3D.GetHandlesNearClipping: boolean;
446begin
447 result := false;
448end;
449
450function TBGRARenderer3D.GetHandlesFaceCulling: boolean;
451begin
452 result := false;
453end;
454
455constructor TBGRARenderer3D.Create(AOutputSurface: TBGRACustomBitmap;
456 ARenderingOptions: TRenderingOptions;
457 AAmbiantLightColorF: TColorF;
458 ALights: TList);
459begin
460 if AOutputSurface = nil then
461 raise exception.Create('No surface specified');
462 FOutputSurface := AOutputSurface;
463 FOptions := ARenderingOptions;
464
465 if (FOptions.AntialiasingMode = am3dResample)
466 and (FOptions.AntialiasingResampleLevel > 1) then
467 begin
468 FRenderSurface := FOutputSurface.NewBitmap(FOutputSurface.Width*FOptions.AntialiasingResampleLevel,
469 FOutputSurface.Height*FOptions.AntialiasingResampleLevel);
470 FRenderSurfaceMultisample := FOptions.AntialiasingResampleLevel;
471 end else
472 begin
473 FRenderSurface := FOutputSurface;
474 FRenderSurfaceMultisample := 1;
475 end;
476
477 FColorGradientTempBmp := FRenderSurface.NewBitmap(2,2);
478 FColorGradientTempBmp.ScanInterpolationFilter := rfLinear;
479
480 if FOptions.PerspectiveMode = pmZBuffer then
481 begin
482 Getmem(FZBuffer, FRenderSurface.NbPixels*sizeof(single));
483 FillDWord(FZBuffer^, FRenderSurface.NbPixels, dword(single(0)));
484 end
485 else
486 FZBuffer := nil;
487
488 if (FOptions.AntialiasingMode = am3dMultishape) and
489 (FOptions.PerspectiveMode <> pmZBuffer) then
490 begin
491 FMultishapeFiller := TBGRAMultishapeFiller.Create;
492 FMultishapeFiller.PolygonOrder := poLastOnTop;
493 end
494 else
495 FMultishapeFiller := nil;
496
497 FShader := TBGRAShader3D.Create(AAmbiantLightColorF, ALights);
498end;
499
500function TBGRARenderer3D.RenderFace(var ADescription: TFaceRenderingDescription;
501 AComputeCoordinate: TComputeProjectionFunc): boolean;
502
503 procedure ComputeCenter;
504 var j: NativeInt;
505 begin
506 with ADescription do
507 begin
508 with FCenter do
509 begin
510 ClearPoint3D_128(pos3D);
511 ClearPoint3D_128(normal3D);
512 color := MergeBGRA(slice(Colors,NbVertices));
513 end;
514 for j := 0 to NbVertices-1 do
515 begin
516 FCenter.pos3D += Positions3D[j];
517 FCenter.normal3D += Normals3D[j];
518 end;
519 with FCenter do
520 begin
521 pos3D *= (1/NbVertices);
522 Normalize3D_128(normal3D);
523 end;
524 end;
525 FCenter.proj := AComputeCoordinate(FCenter.pos3D);
526 end;
527
528 procedure DrawFaceWithShader;
529 var
530 j,k: NativeInt;
531 SameColor: boolean;
532 begin
533 with ADescription do
534 begin
535 if Texture <> nil then
536 begin
537 BGRAPolygonAliased.PolygonPerspectiveMappingShaderAliased(FRenderSurface,
538 slice(Projections,NbVertices),slice(Positions3D,NbVertices),slice(Normals3D,NbVertices),
539 Texture,slice(TexCoords,NbVertices),FOptions.TextureInterpolation,
540 FShader.ShaderFunction,True, BGRAPixelTransparent,FZBuffer,FShader.Context);
541 exit;
542 end;
543
544 SameColor := True;
545 for j := 1 to NbVertices-1 do
546 if (Colors[j]<>Colors[j-1]) then SameColor := False;
547
548 if SameColor then
549 begin
550 BGRAPolygonAliased.PolygonPerspectiveMappingShaderAliased(FRenderSurface,
551 slice(Projections,NbVertices),slice(Positions3D,NbVertices),slice(Normals3D,NbVertices),nil,
552 slice(TexCoords,NbVertices),False,FShader.ShaderFunction,True,Colors[0],FZBuffer,FShader.Context);
553 end else
554 if NbVertices = 3 then
555 begin
556 FColorGradientTempBmp.SetPixel(0,0,Colors[0]);
557 FColorGradientTempBmp.SetPixel(1,0,Colors[1]);
558 FColorGradientTempBmp.SetPixel(0,1,Colors[2]);
559 FColorGradientTempBmp.SetPixel(1,1,MergeBGRA(Colors[1],Colors[2]));
560 BGRAPolygonAliased.PolygonPerspectiveMappingShaderAliased(FRenderSurface,
561 slice(Projections,NbVertices),slice(Positions3D,NbVertices),slice(Normals3D,NbVertices),FColorGradientTempBmp,
562 [PointF(0,0),PointF(1,0),PointF(0,1)],True,FShader.ShaderFunction,True, BGRAPixelTransparent,FZBuffer,FShader.Context);
563 end else
564 if NbVertices = 4 then
565 begin
566 FColorGradientTempBmp.SetPixel(0,0,Colors[0]);
567 FColorGradientTempBmp.SetPixel(1,0,Colors[1]);
568 FColorGradientTempBmp.SetPixel(1,1,Colors[2]);
569 FColorGradientTempBmp.SetPixel(0,1,Colors[3]);
570 BGRAPolygonAliased.PolygonPerspectiveMappingShaderAliased(FRenderSurface,
571 slice(Projections,NbVertices),slice(Positions3D,NbVertices),slice(Normals3D,NbVertices),FColorGradientTempBmp,
572 [PointF(0,0),PointF(1,0),PointF(1,1),PointF(0,1)],True,FShader.ShaderFunction,True, BGRAPixelTransparent,FZBuffer,FShader.Context);
573 end else
574 if NbVertices >= 3 then
575 begin //split into triangles
576 ComputeCenter;
577 k := NbVertices-1;
578 for j := 0 to NbVertices-1 do
579 begin
580 FColorGradientTempBmp.SetPixel(0,0,Colors[k]);
581 FColorGradientTempBmp.SetPixel(1,0,Colors[j]);
582 FColorGradientTempBmp.SetPixel(0,1,FCenter.color);
583 FColorGradientTempBmp.SetPixel(1,1,MergeBGRA(Colors[j],FCenter.color));
584 BGRAPolygonAliased.PolygonPerspectiveMappingShaderAliased(FRenderSurface,
585 [Projections[k],Projections[j],FCenter.proj], [Positions3D[k],Positions3D[j],FCenter.pos3D],
586 [Normals3D[k],Normals3D[j],FCenter.normal3D], FColorGradientTempBmp,
587 [PointF(0,0),PointF(1,0),PointF(0,1)],True,FShader.ShaderFunction,True, BGRAPixelTransparent,FZBuffer,FShader.Context);
588 k := j;
589 end;
590 end;
591 end;
592 end;
593
594 procedure ComputeShadedColors;
595 var
596 j: NativeInt;
597 begin
598 with ADescription do
599 begin
600 //Vertex lighting interpolation (low-quality Gouraud, low-quality Phong)
601 if length(FShadedColors) < NbVertices then
602 setlength(FShadedColors, NbVertices);
603
604 for j := 0 to NbVertices-1 do
605 FShadedColors[j] := FShader.Apply(Positions3D[j],Normals3D[j],Colors[j]);
606
607 FSameShadedColors := True;
608 for j := 1 to NbVertices-1 do
609 if (FShadedColors[j]<>FShadedColors[j-1]) then
610 begin
611 FSameShadedColors := False;
612 break;
613 end;
614 end;
615 end;
616
617 procedure DrawWithMultishape;
618 var shadedCenter: TBGRAPixel;
619 j,k: NativeInt;
620 begin
621 with ADescription do
622 begin
623 if Texture <> nil then
624 begin
625 if (FOptions.PerspectiveMode <> pmLinearMapping) and (NbVertices=4) then
626 FMultishapeFiller.AddQuadPerspectiveMapping(
627 Projections[0],Projections[1],Projections[2],Projections[3],
628 Texture,TexCoords[0],TexCoords[1],TexCoords[2],TexCoords[3])
629 else
630 if NbVertices>=3 then
631 begin
632 for j := 0 to NbVertices-3 do
633 FMultishapeFiller.AddTriangleLinearMapping(
634 Projections[j],Projections[j+1],Projections[j+2],
635 Texture,TexCoords[j],TexCoords[j+1],TexCoords[j+2]);
636 end;
637 end
638 else
639 begin
640 ComputeShadedColors;
641
642 if FSameShadedColors then
643 FMultishapeFiller.AddPolygon(slice(Projections,NbVertices),FShadedColors[0])
644 else
645 if NbVertices=3 then
646 FMultishapeFiller.AddTriangleLinearColor(
647 Projections[0],Projections[1],Projections[2],
648 FShadedColors[0],FShadedColors[1],FShadedColors[2])
649 else
650 if NbVertices>=3 then
651 begin //split into triangles
652 ComputeCenter;
653 shadedCenter := FShader.Apply(FCenter.pos3D,FCenter.normal3D,FCenter.color);
654 k := NbVertices-1;
655 for j := 0 to NbVertices-1 do
656 begin
657 FMultishapeFiller.AddTriangleLinearColor(
658 Projections[k],Projections[j],FCenter.proj,
659 FShadedColors[k],FShadedColors[j],shadedCenter);
660 k := j;
661 end;
662 end;
663 end;
664 end;
665 end;
666
667 procedure DrawAliasedColoredFace;
668 var j,k: integer;
669 shadedCenter: TBGRAPixel;
670 begin
671 with ADescription do
672 begin
673 ComputeShadedColors;
674
675 if FSameShadedColors then
676 begin
677 if FOptions.PerspectiveMode = pmZBuffer then
678 BGRAPolygonAliased.PolygonPerspectiveColorGradientAliased(FRenderSurface, slice(Projections,NbVertices),
679 slice(FDepths,NbVertices), slice(FShadedColors,NbVertices),True,FZBuffer)
680 else
681 FRenderSurface.FillPoly(slice(Projections,NbVertices),FShadedColors[0],dmDrawWithTransparency);
682 end
683 else
684 begin
685 if NbVertices > 4 then
686 begin //split into triangles
687 ComputeCenter;
688 shadedCenter := FShader.Apply(FCenter.pos3D,FCenter.normal3D,FCenter.color);
689 k := NbVertices-1;
690 if FOptions.PerspectiveMode = pmLinearMapping then
691 begin
692 for j := 0 to NbVertices-1 do
693 begin
694 FRenderSurface.FillPolyLinearColor([Projections[k],Projections[j],FCenter.proj],[FShadedColors[k],FShadedColors[j],shadedCenter]);
695 k := j;
696 end;
697 end else
698 begin
699 for j := 0 to NbVertices-1 do
700 begin
701 BGRAPolygonAliased.PolygonPerspectiveColorGradientAliased(FRenderSurface, [Projections[k],Projections[j],FCenter.proj],
702 [FDepths[k],FDepths[j],FCenter.pos3D.z], [FShadedColors[k],FShadedColors[j],shadedCenter],True,FZBuffer);
703 k := j;
704 end;
705 end;
706 end else
707 begin
708 if FOptions.PerspectiveMode = pmLinearMapping then
709 FRenderSurface.FillPolyLinearColor(slice(Projections,NbVertices),slice(FShadedColors,NbVertices))
710 else
711 BGRAPolygonAliased.PolygonPerspectiveColorGradientAliased(FRenderSurface, slice(Projections,NbVertices),
712 slice(FDepths,NbVertices), slice(FShadedColors,NbVertices),True,FZBuffer);
713 end;
714 end;
715 end;
716 end;
717
718 procedure DrawWithoutShader;
719 var
720 noLighting: Boolean;
721 j: NativeInt;
722 begin
723 with ADescription do
724 begin
725 if length(FDepths) < NbVertices then
726 setlength(FDepths, NbVertices);
727 for j := 0 to NbVertices-1 do
728 FDepths[j] := Positions3D[j].z;
729
730 if Texture <> nil then
731 begin
732 noLighting := True;
733 if length(FLightings) < NbVertices then
734 setlength(FLightings, NbVertices);
735 for j := 0 to NbVertices-1 do
736 begin
737 FLightings[j] := FShader.Int65536Apply(Positions3D[j],Normals3D[j],BGRAWhite).g div 2;
738 if abs(FLightings[j]-32768) > 1 then noLighting := false;
739 end;
740
741 if noLighting then
742 begin
743 if FOptions.PerspectiveMode <> pmLinearMapping then
744 FRenderSurface.FillPolyPerspectiveMapping(slice(Projections,NbVertices),
745 slice(FDepths,NbVertices),Texture,slice(TexCoords,NbVertices),
746 FOptions.TextureInterpolation, FZBuffer)
747 else
748 FRenderSurface.FillPolyLinearMapping(slice(Projections,NbVertices),
749 Texture,slice(TexCoords,NbVertices),FOptions.TextureInterpolation);
750 end else
751 begin
752 if FOptions.PerspectiveMode <> pmLinearMapping then
753 FRenderSurface.FillPolyPerspectiveMappingLightness(
754 slice(Projections,NbVertices),slice(FDepths,NbVertices),Texture,
755 slice(TexCoords,NbVertices),slice(FLightings,NbVertices),
756 FOptions.TextureInterpolation, FZBuffer)
757 else
758 FRenderSurface.FillPolyLinearMappingLightness(
759 slice(Projections,NbVertices),Texture,slice(TexCoords,NbVertices),
760 slice(FLightings,NbVertices),FOptions.TextureInterpolation);
761 end;
762 end
763 else
764 DrawAliasedColoredFace; //already low-quality shaded
765 end;
766 end;
767
768var
769 j: integer;
770 SkipShader: boolean;
771begin
772 result := true;
773 FShader.Prepare(ADescription);
774 with ADescription do
775 begin
776 //high-quality lighting interpolation, necessary for Phong and high-quality Gouraud
777 if ( (FOptions.LightingInterpolation = liAlwaysHighQuality) or
778 ((FOptions.LightingInterpolation = liSpecularHighQuality) and Material.GetSpecularOn) )
779 and (NormalsMode <> lnNone) then
780 begin
781 //if there are only directional lights and all the normals are the same,
782 //then the lighting will be uniform so we can skip the shader
783 if FShader.OnlyDirectionalLights then
784 begin
785 SkipShader := true;
786 for j := 1 to NbVertices-1 do
787 if Normals3D[j] <> Normals3D[j-1] then
788 begin
789 SkipShader := false;
790 break;
791 end;
792 end else
793 SkipShader := false;
794
795 if not SkipShader then
796 begin
797 DrawFaceWithShader;
798 exit;
799 end;
800 end;
801
802 if Assigned(FMultishapeFiller) then //high-quality antialiasing
803 DrawWithMultishape
804 else
805 DrawWithoutShader;
806 end;
807end;
808
809destructor TBGRARenderer3D.Destroy;
810begin
811 FreeAndNil(FShader);
812
813 if Assigned(FMultishapeFiller) then
814 begin
815 FMultishapeFiller.Draw(FRenderSurface);
816 FreeAndNil(FMultishapeFiller);
817 end;
818
819 if FZBuffer <> nil then
820 begin
821 FreeMem(FZBuffer);
822 FZBuffer := nil;
823 end;
824
825 FreeAndNil(FColorGradientTempBmp);
826
827 if FRenderSurfaceMultisample > 1 then
828 begin
829 BGRAResample.DownSamplePutImage(FRenderSurface,
830 FRenderSurfaceMultisample,FRenderSurfaceMultisample,
831 FOutputSurface, 0,0, dmDrawWithTransparency);
832 FreeAndNil(FRenderSurface);
833 FRenderSurfaceMultisample := 1;
834 end
835 else
836 FRenderSurface := nil;
837
838 inherited Destroy;
839end;
840
841end.
Note: See TracBrowser for help on using the repository browser.