GLS.zBuffer.pas 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321
  1. //
  2. // The multimedia graphics platform GLScene https://github.com/glscene
  3. //
  4. unit GLS.zBuffer;
  5. (*
  6. ZBuffer retrieval and computations.
  7. See readme.txt in the Demos/SpecialsFX/Shadows directory.
  8. By René Lindsay.
  9. *)
  10. //--------These formulas are the key to making use of the z-Buffer--------
  11. //
  12. // dst (d): world distance
  13. // dov : depth of view (distance between Far-plane and Near-plane)
  14. // np : near plane
  15. // fp : far plane (dov+np)
  16. //
  17. //------------------------
  18. //dst:=(fp*np)/(fp-z*dov); //calc from z-buffer value to frustrum depth
  19. //z :=(1-np/d)/(1-np/fp); //calc from frustrum depth to z-buffer value
  20. //------------------------ z:=1-(fp/d-1)/(fp/np-1); //old FtoZ
  21. //------------------------------------------------------------------------
  22. interface
  23. {$I GLScene.inc}
  24. uses
  25. Winapi.OpenGL,
  26. System.Classes,
  27. System.SysUtils,
  28. System.Math,
  29. GLS.OpenGLTokens,
  30. GLS.XOpenGL,
  31. GLS.Scene,
  32. GLS.VectorGeometry,
  33. GLS.Graphics,
  34. GLS.Objects,
  35. GLS.Context,
  36. GLS.SceneViewer,
  37. GLS.Color,
  38. GLS.RenderContextInfo,
  39. GLS.State,
  40. GLS.TextureFormat,
  41. GLS.VectorTypes,
  42. GLS.Coordinates,
  43. GLS.PersistentClasses;
  44. type
  45. EZBufferException = class(Exception);
  46. TZArray = array[0..MaxInt shr 3] of Single;
  47. PZArray = ^TZArray;
  48. TZArrayIdx = array of PZArray;
  49. TAArray = array[0..MaxInt shr 3] of Byte;
  50. PAArray = ^TAArray;
  51. TAArrayIdx = array of PAArray;
  52. TOptimise = (opNone, op4in1, op9in1, op16in1);
  53. TGLzBuffer = class(TPersistent)
  54. private
  55. FData: PZArray;
  56. FDataIdx, FDataInvIdx: TZArrayIdx;
  57. FWidth, FHeight: Integer;
  58. FDataSize: Integer;
  59. //VectorToScreen variables;
  60. Ang1, Ang2, Scal, C1, S1, C2, S2, Vw, Vh: single;
  61. //ScreenToVector corner vectors;
  62. Lt, Rt, Lb, Rb: TAffineVector;
  63. UpVec, RiVec: TAffineVector;
  64. //ScreenToVector corner vectors;(Warped)
  65. LtW, RtW, LbW, RbW: TAffineVector;
  66. UpVecW, RiVecW: TAffineVector;
  67. OrthInvDov, OrthAddX, OrthMulX, OrthAddY, OrthMulY: single;
  68. //Calc Variables;
  69. Dov, Np, Fp, NpFp, OneMinNp_Fp, InvOneMinNp_Fp: single;
  70. Cam: TGLCamera;
  71. procedure DoCalcVectors;
  72. protected
  73. procedure PrepareBufferMemory;
  74. procedure SetWidth(val: Integer);
  75. procedure SetHeight(const val: Integer);
  76. public
  77. SceneViewer: TGLSceneViewer;
  78. MemoryViewer: TGLMemoryViewer;
  79. Buffer: TGLSceneBuffer;
  80. Normal: TAffineVector; //Absolute direction of camera
  81. constructor Create;
  82. destructor Destroy; override;
  83. procedure LinkToViewer(viewer: TGLSceneViewer); overload;
  84. procedure LinkToViewer(viewer: TGLMemoryViewer); overload;
  85. function GetDepthBuffer(CalcVectors: Boolean; ContextIsActive: boolean): PZArray;
  86. function GetPixelzDepth(x, y: integer): Single;
  87. function PixelToDistance_OLD(x, y: integer): Single;
  88. function PixelToDistance(x, y: integer): Single;
  89. property Width: Integer read FWidth write SetWidth;
  90. property Height: Integer read FHeight write SetHeight;
  91. property DataSize: Integer read FDataSize;
  92. property Data: PZArray read FData;
  93. property DataIdx: TZArrayIdx read FDataIdx;
  94. property DataInvIdx: TZArrayIdx read FDataIdx;
  95. procedure Refresh;
  96. function FastScreenToVector(x, y: Integer): TAffineVector;
  97. function FastVectorToScreen(const vec: TAffineVector): TAffineVector;
  98. function PixelToWorld(const x, y: Integer): TAffineVector;
  99. function WorldToPixel(const aPoint: TAffineVector; out pixX, pixY: integer; out pixZ: single): boolean;
  100. function WorldToPixelZ(const aPoint: TAffineVector; out pixX, pixY: integer; out pixZ: single): boolean; overload;
  101. function WorldToPixelZ(const aPoint: TAffineVector; out pixX, pixY: single; out pixZ: single): boolean; overload;
  102. function OrthWorldToPixelZ(const aPoint: TAffineVector; out pixX, pixY: single; out pixZ: single): boolean;
  103. end;
  104. TGLZShadows = class(TGLBaseSceneObject)
  105. private
  106. FViewer: TGLSceneViewer;
  107. FCaster: TGLMemoryViewer;
  108. FDepthFade: Boolean;
  109. FFrustShadow: Boolean;
  110. FSkyShadow: Boolean;
  111. FOptimise: TOptimise;
  112. FData: PAArray;
  113. FDataIdx, FDataInvIdx: TAArrayIdx;
  114. FDataSize: Integer;
  115. FWidth: integer;
  116. FHeight: integer;
  117. FXRes: integer;
  118. FYRes: integer;
  119. Fsoft: boolean;
  120. FTolerance: single;
  121. FColor: TGLColor;
  122. SCol: TGLPixel32;
  123. //stepX, stepY :single;
  124. FTexturePrepared: Boolean;
  125. FTexHandle: TGLTextureHandle;
  126. protected
  127. procedure PrepareAlphaMemory;
  128. function GetViewer: TGLSceneViewer;
  129. procedure SetViewer(const val: TGLSceneViewer);
  130. function GetCaster: TGLMemoryViewer;
  131. procedure SetCaster(const val: TGLMemoryViewer);
  132. procedure CalcShadowTexture(var rci: TGLRenderContextInfo);
  133. function HardSet(const x, y: integer): Byte;
  134. function SoftTest(const x, y: integer): Byte;
  135. procedure SetWidth(const val: integer);
  136. procedure SetHeight(const val: integer);
  137. procedure SetXRes(const val: integer);
  138. procedure SetYRes(const val: integer);
  139. procedure SetSoft(const val: boolean);
  140. procedure BindTexture;
  141. public
  142. ViewerZBuf: TGLzBuffer;
  143. CasterZBuf: TGLzBuffer;
  144. constructor Create(AOwner: TComponent); override;
  145. destructor Destroy; override;
  146. procedure DoRender(var ARci: TGLRenderContextInfo; ARenderSelf, ARenderChildren: Boolean); override;
  147. published
  148. property Viewer: TGLSceneViewer read GetViewer write SetViewer;
  149. property Caster: TGLMemoryViewer read GetCaster write SetCaster;
  150. property FrustShadow: Boolean read FFrustShadow write FFrustShadow;
  151. property SkyShadow: Boolean read FSkyShadow write FSkyShadow;
  152. property Optimise: TOptimise read FOptimise write FOptimise;
  153. property Width: integer read FWidth write SetWidth;
  154. property Height: integer read FHeight write SetHeight;
  155. property Color: TGLColor read FColor write FColor;
  156. // property Xres :integer read FXRes write SetXRes;// default 64;
  157. // property Yres :integer read FYRes write SetYRes;// default 64;
  158. property Soft: Boolean read Fsoft write SetSoft;
  159. property Tolerance: single read FTolerance write FTolerance;
  160. // property Material;
  161. property ObjectsSorting;
  162. property Visible;
  163. property DepthFade: Boolean read FDepthFade write FDepthFade;
  164. function CastShadow: boolean;
  165. end;
  166. //--------------------------------------------------------------------
  167. implementation
  168. //--------------------------------------------------------------------
  169. constructor TGLzBuffer.Create;
  170. begin
  171. inherited Create;
  172. self.FWidth := 0;
  173. self.FHeight := 0;
  174. self.FDataSize := 0;
  175. self.cam := nil;
  176. self.SceneViewer := nil;
  177. self.MemoryViewer := nil;
  178. self.buffer := nil;
  179. // self.DoCalcVectors;
  180. end;
  181. procedure TGLzBuffer.LinkToViewer(viewer: TGLSceneViewer); // overload;
  182. begin
  183. if ((FWidth <> Viewer.width) or (FHeight <> Viewer.height)) then
  184. begin
  185. FWidth := Viewer.width;
  186. FHeight := Viewer.height;
  187. PrepareBufferMemory;
  188. end;
  189. cam := Viewer.camera;
  190. SceneViewer := Viewer;
  191. Buffer := Viewer.Buffer;
  192. self.DoCalcVectors;
  193. end;
  194. procedure TGLzBuffer.LinkToViewer(viewer: TGLMemoryViewer); // overload;
  195. begin
  196. if ((FWidth <> Viewer.width) or (FHeight <> Viewer.height)) then
  197. begin
  198. FWidth := Viewer.width;
  199. FHeight := Viewer.height;
  200. PrepareBufferMemory;
  201. end;
  202. Cam := Viewer.camera;
  203. MemoryViewer := Viewer;
  204. Buffer := Viewer.Buffer;
  205. self.DoCalcVectors;
  206. end;
  207. //---Destroy---
  208. destructor TGLzBuffer.Destroy;
  209. begin
  210. FreeMem(FData);
  211. inherited Destroy;
  212. end;
  213. procedure TGLzBuffer.PrepareBufferMemory;
  214. var
  215. i: Integer;
  216. begin
  217. FDataSize := FWidth * FHeight * 4;
  218. ReallocMem(FData, FDataSize);
  219. SetLength(FDataIdx, FHeight + 2);
  220. SetLength(FDataInvIdx, FHeight + 2);
  221. for i := 0 to FHeight - 1 do
  222. begin
  223. FDataIdx[i] := @FData[i * FWidth]; // range: [0..height-1]
  224. FDataInvIdx[i] := @FData[(FHeight - i - 1) * FWidth]; // range: [0..height-1]
  225. end;
  226. FDataIdx[FHeight] := FDataIdx[FHeight - 1];
  227. FDataInvIdx[FHeight] := FDataInvIdx[FHeight - 1];
  228. end;
  229. //---Width---
  230. procedure TGLzBuffer.SetWidth(val: Integer);
  231. begin
  232. if val <> FWidth then
  233. begin
  234. Assert(val >= 0);
  235. FWidth := val;
  236. PrepareBufferMemory;
  237. end;
  238. end;
  239. //---Height---
  240. procedure TGLzBuffer.SetHeight(const val: Integer);
  241. begin
  242. if val <> FHeight then
  243. begin
  244. Assert(val >= 0);
  245. FHeight := val;
  246. PrepareBufferMemory;
  247. end;
  248. end;
  249. function TGLzBuffer.GetDepthBuffer(CalcVectors: Boolean; ContextIsActive:
  250. boolean): PZArray;
  251. begin
  252. if ContextIsActive then
  253. begin
  254. gl.ReadPixels(0, 0, FWidth, FHeight, GL_DEPTH_COMPONENT, GL_FLOAT, FData);
  255. end
  256. else
  257. begin
  258. Buffer.RenderingContext.Activate;
  259. try
  260. gl.ReadPixels(0, 0, FWidth, FHeight, GL_DEPTH_COMPONENT, GL_FLOAT, FData);
  261. finally
  262. Buffer.RenderingContext.Deactivate;
  263. end;
  264. end;
  265. if CalcVectors then
  266. DoCalcVectors;
  267. Result := FData;
  268. end;
  269. function TGLzBuffer.GetPixelzDepth(x, y: integer): Single;
  270. begin
  271. if (Cardinal(x) < Cardinal(FWidth)) and (Cardinal(y) < Cardinal(FHeight)) then
  272. Result := FDataInvIdx[y]^[x]
  273. else
  274. Result := 0;
  275. end;
  276. function TGLzBuffer.PixelToDistance_OLD(x, y: integer): Single;
  277. var
  278. z, dst, camAng, wrpdst: single;
  279. vec: TAffineVector;
  280. begin
  281. if ((x < 0) or (x > FWidth) or (y < 0) or (y > FWidth)) then
  282. result := 0
  283. else
  284. begin
  285. z := FData^[x + (FHeight - y) * FWidth]; //fetch pixel z-depth
  286. dst := (NpFp) / (fp - z * dov); //calc from z-buffer value to frustrum depth
  287. vec := FastScreenToVector(x, y);
  288. camAng := VectorAngleCosine(normal, vec);
  289. wrpdst := dst / camAng; //compensate for flat frustrum face
  290. result := wrpdst;
  291. end;
  292. end;
  293. function TGLzBuffer.PixelToDistance(x, y: integer): Single;
  294. var
  295. z, dst: single;
  296. xx, yy, zz: single;
  297. fy: integer;
  298. begin
  299. if ((x < 0) or (x >= FWidth) or (y < 0) or (y >= FHeight)) then
  300. result := 0
  301. else
  302. begin
  303. fy := FHeight - y;
  304. z := FData^[x + fy * FWidth]; //fetch pixel z-depth
  305. if z < 1 then
  306. begin
  307. dst := (NpFp) / (fp - z * dov);
  308. //calc from z-buffer value to frustrum depth
  309. xx := (lbW.X + riVecW.X * x + UpVecW.X * fy);
  310. yy := (lbW.Y + riVecW.Y * x + UpVecW.Y * fy);
  311. zz := (lbW.Z + riVecW.Z * x + UpVecW.Z * fy);
  312. result := sqrt(xx * xx + yy * yy + zz * zz) * dst;
  313. end
  314. else
  315. result := 0;
  316. end;
  317. end;
  318. procedure TGLzBuffer.Refresh;
  319. begin
  320. if assigned(Buffer) then
  321. GetDepthBuffer(True, False);
  322. end;
  323. procedure TGLzBuffer.DoCalcVectors;
  324. var
  325. axs: TAffineVector;
  326. Hnorm, hcvec: TGLVector;
  327. vec: TAffineVector;
  328. w, h: integer;
  329. wrp: single;
  330. begin
  331. if not (assigned(Buffer) and Buffer.RCInstantiated) then
  332. exit;
  333. if not assigned(cam) then
  334. raise EZBufferException.Create('No Camera!');
  335. //-----------For ScreenToVector-------------
  336. w := FWidth;
  337. h := FHeight;
  338. setVector(vec, 0, 0, 0);
  339. lb := buffer.ScreenToVector(vec); // same as cvec...optimise?
  340. setVector(vec, w, 0, 0);
  341. rb := buffer.ScreenToVector(vec);
  342. setVector(vec, 0, h, 0);
  343. lt := buffer.ScreenToVector(vec);
  344. setVector(vec, w, h, 0);
  345. rt := buffer.ScreenToVector(vec);
  346. //------------Set Camera values-------------
  347. normal := VectorLerp(lb, rt, 0.5);
  348. upVec := VectorSubtract(lt, lb);
  349. riVec := VectorSubtract(rb, lb);
  350. // cam:=viewer.Camera;
  351. dov := Cam.DepthOfView;
  352. np := Cam.NearPlane;
  353. fp := Cam.NearPlane + dov;
  354. NpFp := np * fp;
  355. OneMinNp_Fp := 1 - np / fp;
  356. invOneMinNp_Fp := 1 / OneMinNp_Fp;
  357. //-----------For VectorToScreen-------------
  358. {
  359. cam :=Viewer.Camera.Position.AsAffineVector;
  360. targ:=Viewer.Camera.TargetObject.Position.AsAffineVector;
  361. norm:=VectorSubtract(targ,cam); //---Camera Normal vector---
  362. MakeVector(hnorm,norm);
  363. }
  364. MakeVector(hnorm, normal);
  365. MakeVector(hcVec, lb); //---Corner Vector---
  366. ang1 := ArcTan2(Hnorm.X, Hnorm.Z);
  367. SetVector(axs, 0, 1, 0);
  368. RotateVector(hnorm, axs, ang1);
  369. RotateVector(hcvec, axs, ang1);
  370. ang2 := ArcTan2(Hnorm.Y, Hnorm.Z);
  371. SetVector(axs, 1, 0, 0);
  372. RotateVector(hcvec, axs, -ang2);
  373. hcvec.X := hcvec.X / hcvec.Z;
  374. vw := Fwidth / 2;
  375. vh := Fheight / 2;
  376. scal := vw / hcvec.X;
  377. SinCosine(-ang1, s1, c1);
  378. SinCosine(-ang2, s2, c2);
  379. //------------------------------------------
  380. //--------------------2-----------------
  381. vec := self.FastScreenToVector(0, 1);
  382. wrp := VectorAngleCosine(normal, vec);
  383. ltW := VectorNormalize(lt);
  384. rtW := VectorNormalize(rt);
  385. lbW := VectorNormalize(lb);
  386. rbW := VectorNormalize(rb);
  387. ltW := VectorScale(ltW, 1 / wrp);
  388. rtW := VectorScale(rtW, 1 / wrp);
  389. lbW := VectorScale(lbW, 1 / wrp);
  390. rbW := VectorScale(rbW, 1 / wrp);
  391. upVecW := VectorSubtract(ltW, lbW);
  392. upVecW := VectorScale(upVecW, 1 / Fheight);
  393. riVecW := VectorSubtract(rbW, lbW);
  394. riVecW := VectorScale(riVecW, 1 / Fwidth);
  395. // UpVecW[0]:=-UpVecW[0];
  396. // UpVecW[1]:=-UpVecW[1];
  397. // UpVecW[2]:=-UpVecW[2];
  398. //--------------------------------------
  399. //-------orth---------
  400. // OrthAdd:=2;
  401. // OrthMul:=64;
  402. orthAddX := rt.X;
  403. OrthMulX := FWidth / (OrthAddX * 2);
  404. orthAddY := rt.Z;
  405. OrthMulY := FHeight / (OrthAddY * 2);
  406. OrthInvDov := 1 / dov;
  407. //--------------------
  408. end;
  409. function TGLzBuffer.FastScreenToVector(x, y: integer): TAffineVector;
  410. var
  411. w, h: integer;
  412. Rlerp, Ulerp: single;
  413. begin
  414. w := FWidth;
  415. h := FHeight;
  416. Rlerp := x / w;
  417. Ulerp := (h - y) / h;
  418. result.X := lb.X + riVec.X * Rlerp + UpVec.X * Ulerp;
  419. result.Y := lb.Y + riVec.Y * Rlerp + UpVec.Y * Ulerp;
  420. result.Z := lb.Z + riVec.Z * Rlerp + UpVec.Z * Ulerp;
  421. end;
  422. function TGLzBuffer.FastVectorToScreen(const Vec: TAffineVector): TAffineVector;
  423. var
  424. v0, v1, x, y, z: Single;
  425. begin
  426. x := vec.X;
  427. y := vec.Y;
  428. z := vec.Z;
  429. v0 := x;
  430. x := c1 * v0 + s1 * z;
  431. z := c1 * z - s1 * v0; //Rotate around Y-axis
  432. v1 := y;
  433. y := c2 * v1 + s2 * z;
  434. z := c2 * z - s2 * v1; //Rotate around X-axis
  435. Result.X := Round(-x / z * scal + vw);
  436. Result.Y := Round(y / z * scal + vh);
  437. end;
  438. function TGLzBuffer.PixelToWorld(const x, y: Integer): TAffineVector;
  439. var
  440. z, dst: single;
  441. fy: integer;
  442. camvec: TGLVector;
  443. begin
  444. // if (Cardinal(x)<Cardinal(FWidth)) and (Cardinal(y)<Cardinal(FWidth)) then begin //xres,yres?
  445. if (x < FWidth) and (y < FHeight) then
  446. begin
  447. z := FDataInvIdx[y]^[x];
  448. dst := (NpFp) / (fp - z * dov); //calc from z-buffer value to frustrum depth
  449. camvec := cam.AbsolutePosition;
  450. fy := FHeight - y;
  451. result.X := (lbW.X + riVecW.X * x + UpVecW.X * fy) * dst + camvec.X;
  452. result.Y := (lbW.Y + riVecW.Y * x + UpVecW.Y * fy) * dst + camvec.Y;
  453. result.Z := (lbW.Z + riVecW.Z * x + UpVecW.Z * fy) * dst + camvec.Z;
  454. end
  455. else
  456. begin
  457. result.X := 0;
  458. result.Y := 0;
  459. result.Z := 0;
  460. end;
  461. end;
  462. function TGLzBuffer.WorldToPixel(const aPoint: TAffineVector; out pixX, pixY:
  463. integer; out pixZ: single): boolean;
  464. var
  465. camPos: TGLVector;
  466. x, y, z, v0, v1, zscal: single;
  467. begin
  468. //---Takes x,y,z world coordinate.
  469. //---Result is true if pixel lies within view frustrum
  470. //---returns canvas pixel x,y coordinate, and the world distance
  471. result := false;
  472. campos := cam.AbsolutePosition;
  473. x := apoint.X - camPos.X;
  474. y := apoint.Y - camPos.Y;
  475. z := apoint.Z - camPos.Z; //get vector from camera to world point
  476. v0 := x;
  477. x := c1 * v0 + s1 * z;
  478. z := c1 * z - s1 * v0; //Rotate around Y-axis
  479. v1 := y;
  480. y := c2 * v1 + s2 * z;
  481. z := c2 * z - s2 * v1; //Rotate around X-axis
  482. if z > 0 then
  483. begin
  484. zscal := scal / z;
  485. pixX := Round(-x * zscal + vw);
  486. pixY := Round(y * zscal + vh);
  487. pixZ := sqrt(x * x + y * y + z * z);
  488. if (pixX >= 0) and (pixX < FWidth) and (pixY >= 0) and (pixY < FHeight) then
  489. Result := true;
  490. end
  491. else
  492. begin //ignore anything that is behind the camera
  493. pixX := 0;
  494. pixY := 0;
  495. pixZ := 0;
  496. end;
  497. end;
  498. function TGLzBuffer.WorldToPixelZ(const aPoint: TAffineVector; out pixX, pixY:
  499. integer; out pixZ: single): boolean; //OVERLOAD
  500. var
  501. camPos: TGLVector;
  502. x, y, z, v0, v1, zscal: single;
  503. begin
  504. //---Takes x,y,z world coordinate.
  505. //---Result is true if pixel lies within view frustrum
  506. //---returns canvas pixel x,y coordinate, and CALCULATES the z-buffer distance
  507. campos := cam.AbsolutePosition;
  508. x := apoint.X - camPos.X;
  509. y := apoint.Y - camPos.Y;
  510. z := apoint.Z - camPos.Z; //get vector from camera to world point
  511. v0 := x;
  512. x := c1 * v0 + s1 * z;
  513. z := c1 * z - s1 * v0; //Rotate around Y-axis
  514. v1 := y;
  515. y := c2 * v1 + s2 * z;
  516. z := c2 * z - s2 * v1; //Rotate around X-axis
  517. if z > 0 then
  518. begin
  519. zscal := scal / z;
  520. pixX := Round(-x * zscal + vw);
  521. pixY := Round(y * zscal + vh);
  522. //------z:=(1-np/z)/(1-np/fp);------
  523. // pixZ:=(1-np/z)/(1-np/fp);
  524. pixZ := (1 - np / z) * invOneMinNp_Fp;
  525. Result := (Cardinal(pixX) < Cardinal(FWidth)) and (Cardinal(pixY) <
  526. Cardinal(FHeight));
  527. end
  528. else
  529. begin //ignore anything that is behind the camera
  530. Result := false;
  531. pixX := 0;
  532. pixY := 0;
  533. pixZ := 0;
  534. end;
  535. end;
  536. function TGLzBuffer.WorldToPixelZ(const aPoint: TAffineVector; out pixX, pixY:
  537. single; out pixZ: single): boolean; //OVERLOAD
  538. var
  539. camPos: TGLVector;
  540. x, y, z, invZ, v0, v1, zscal: single;
  541. begin
  542. //---Takes x,y,z world coordinate. (aPoint)
  543. //---Result is true if pixel lies within view frustrum
  544. //---returns canvas pixel x,y coordinate, and CALCULATES the z-buffer distance
  545. campos := cam.AbsolutePosition;
  546. x := apoint.X - camPos.X;
  547. y := apoint.Y - camPos.Y;
  548. z := apoint.Z - camPos.Z; //get vector from camera to world point
  549. v0 := x;
  550. x := c1 * v0 + s1 * z;
  551. z := c1 * z - s1 * v0; //Rotate around Y-axis
  552. v1 := y;
  553. y := c2 * v1 + s2 * z;
  554. z := c2 * z - s2 * v1; //Rotate around X-axis
  555. if z > 0 then
  556. begin
  557. invZ := 1 / z;
  558. zscal := scal * invZ;
  559. pixX := vw - x * zscal;
  560. pixY := vh + y * zscal;
  561. //------z:=(1-np/z)/(1-np/fp);------
  562. // pixZ:=(1-np/z)/(1-np/fp);
  563. pixZ := (1 - np * invZ) * invOneMinNp_Fp;
  564. Result := (pixX >= 0) and (pixX < FWidth) and (pixY >= 0) and (pixY <
  565. FHeight);
  566. end
  567. else
  568. begin //ignore anything that is behind the camera
  569. result := false;
  570. pixX := 0;
  571. pixY := 0;
  572. pixZ := 0;
  573. end;
  574. end;
  575. function TGLzBuffer.OrthWorldToPixelZ(const aPoint: TAffineVector; out pixX,
  576. pixY: single; out pixZ: single): boolean;
  577. var
  578. camPos: TGLVector;
  579. x, y, z: single;
  580. begin
  581. campos := cam.AbsolutePosition;
  582. x := apoint.X - camPos.X;
  583. y := apoint.Y - camPos.Y;
  584. z := apoint.Z - camPos.Z; //get vector from camera to world point
  585. pixX := (x + OrthAddX) * OrthMulX;
  586. pixY := (z + OrthAddY) * OrthMulY;
  587. pixZ := (-y - np) * OrthInvDov; //(-y-np)/dov
  588. Result := (pixX >= 0) and (pixX < FWidth) and (pixY >= 0) and (pixY <
  589. FHeight);
  590. end;
  591. // ------------------
  592. // ------------------ TGLZShadows ------------------
  593. // ------------------
  594. //
  595. constructor TGLZShadows.Create(AOwner: TComponent);
  596. begin
  597. inherited;
  598. ObjectStyle := ObjectStyle + [osDirectDraw, osNoVisibilityCulling];
  599. FColor := TGLColor.Create(Self);
  600. self.FDataSize := 0;
  601. self.FXRes := 64;
  602. self.FYRes := 64;
  603. self.Tolerance := 0.015;
  604. FTexHandle := TGLTextureHandle.Create;
  605. end;
  606. //---Destroy---
  607. destructor TGLZShadows.Destroy;
  608. begin
  609. ViewerZBuf.Free;
  610. CasterZBuf.Free;
  611. FColor.Free;
  612. FTexHandle.Free;
  613. FreeMem(FData);
  614. inherited Destroy;
  615. end;
  616. // BindTexture
  617. //
  618. procedure TGLZShadows.BindTexture;
  619. begin
  620. if FTexHandle.Handle = 0 then
  621. with FTexHandle do
  622. begin
  623. AllocateHandle;
  624. with RenderingContext.GLStates do
  625. begin
  626. TextureBinding[0, ttTexture2D] := Handle;
  627. gl.Hint(GL_PERSPECTIVE_CORRECTION_HINT, GL_Fastest);
  628. UnpackAlignment := 1;
  629. UnpackRowLength := 0;
  630. UnpackSkipRows := 0;
  631. UnpackSkipPixels := 0;
  632. gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  633. gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  634. ActiveTextureEnabled[ttTexture2D] := True;
  635. SetBlendFunc(bfSRCALPHA, bfONEMINUSSRCALPHA);
  636. gl.TexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  637. Enable(stBlend);
  638. PrepareAlphaMemory;
  639. end;
  640. end
  641. else
  642. with FTexHandle do
  643. RenderingContext.GLStates.TextureBinding[0, ttTexture2D] := Handle;
  644. end;
  645. procedure TGLZShadows.PrepareAlphaMemory;
  646. var
  647. i: Integer;
  648. begin
  649. // ShowMessage(IntToStr(FWidth)+' '+IntToStr(FXRes));
  650. FDataSize := FXRes * FYRes * 1;
  651. ReallocMem(FData, FDataSize);
  652. SetLength(FDataIdx, FYRes);
  653. SetLength(FDataInvIdx, FYRes);
  654. for i := 0 to FYres - 1 do
  655. begin
  656. FDataIdx[i] := @FData[i * FXRes]; // range: [0..height-1]
  657. FDataInvIdx[i] := @FData[(FYRes - i - 1) * FXRes]; // range: [0..height-1]
  658. end;
  659. end;
  660. // DoRender
  661. //
  662. procedure TGLZShadows.DoRender(var ARci: TGLRenderContextInfo;
  663. ARenderSelf, ARenderChildren: Boolean);
  664. var
  665. vx, vy, vx1, vy1: Single;
  666. xtex, ytex: single;
  667. begin
  668. if not assigned(FViewer) then
  669. exit;
  670. if not assigned(FCaster) then
  671. exit;
  672. if not assigned(CasterZBuf) then
  673. exit; //only render if a shadow has been cast
  674. //only render in view-camera
  675. if TGLSceneBuffer(ARci.buffer).Camera <> FViewer.Camera then
  676. exit;
  677. if not assigned(ViewerZBuf) then
  678. begin //Create viewer zbuffer
  679. ViewerZBuf := TGLZBuffer.Create;
  680. ViewerZBuf.LinkToViewer(FViewer);
  681. Bindtexture;
  682. FTexturePrepared := False;
  683. end;
  684. ViewerZBuf.Refresh;
  685. ARci.GLStates.ActiveTextureEnabled[ttTexture2D] := True;
  686. ARci.GLStates.Enable(stBlend);
  687. ARci.GLStates.SetBlendFunc(bfSrcAlpha, bfOneMinusSrcAlpha);
  688. if FWidth > ARci.viewPortSize.cx then
  689. Fwidth := ARci.viewPortSize.cx;
  690. if FHeight > ARci.viewPortSize.cy then
  691. FHeight := ARci.viewPortSize.cy;
  692. //-----------------------
  693. CalcShadowTexture(ARci);
  694. //-----------------------
  695. ARci.GLStates.TextureBinding[0, ttTexture2D] := FTexHandle.Handle;
  696. //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  697. gl.Color3f(SCol.r, SCol.g, SCol.b);
  698. if not FTexturePrepared then
  699. begin
  700. gl.TexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, FXRes, FYRes, 0, GL_ALPHA,
  701. GL_UNSIGNED_BYTE, @FData[0]);
  702. FTexturePrepared := True;
  703. end
  704. else
  705. gl.TexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, FXRes, FYRes, GL_ALPHA,
  706. GL_UNSIGNED_BYTE, @FData[0]);
  707. // NotifyChange(Self);
  708. //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  709. // Prepare matrices
  710. gl.MatrixMode(GL_MODELVIEW);
  711. gl.PushMatrix;
  712. gl.LoadMatrixf(@TGLSceneBuffer(ARci.buffer).BaseProjectionMatrix);
  713. gl.Scalef(2 / ARci.viewPortSize.cx, 2 / ARci.viewPortSize.cy, 1);
  714. gl.Translatef(Position.X - ARci.viewPortSize.cx * 0.5,
  715. ARci.viewPortSize.cy * 0.5 - Position.Y, Position.Z);
  716. gl.MatrixMode(GL_PROJECTION);
  717. gl.PushMatrix;
  718. gl.LoadIdentity;
  719. ARci.GLStates.Disable(stDepthTest);
  720. ARci.GLStates.Disable(stLighting);
  721. vx := 0;
  722. vx1 := vx + FWidth;
  723. vy := 0;
  724. vy1 := vy - FHeight;
  725. Xtex := FWidth / FXres; //1
  726. Ytex := 1 - (FHeight / FYres); //0
  727. // issue quad
  728. gl.Begin_(GL_QUADS);
  729. gl.Normal3fv(@YVector);
  730. gl.TexCoord2f(0, ytex);
  731. gl.Vertex2f(vx, vy1);
  732. gl.TexCoord2f(xtex, ytex);
  733. gl.Vertex2f(vx1, vy1);
  734. gl.TexCoord2f(xtex, 1);
  735. gl.Vertex2f(vx1, vy);
  736. gl.TexCoord2f(0, 1);
  737. gl.Vertex2f(vx, vy);
  738. gl.End_;
  739. // restore state
  740. gl.PopMatrix;
  741. gl.MatrixMode(GL_MODELVIEW);
  742. gl.PopMatrix;
  743. if Count > 0 then
  744. Self.RenderChildren(0, Count - 1, ARci);
  745. end;
  746. procedure TGLZShadows.CalcShadowTexture(var rci: TGLRenderContextInfo);
  747. var
  748. pix, p0, p1, p2, p3, p4: Byte;
  749. pM, pL, pT: Byte;
  750. pixa: PAArray;
  751. x, y, w, h: integer;
  752. xy: integer;
  753. begin
  754. pixa := FData;
  755. w := fXres;
  756. h := fYres;
  757. SCol.r := Round(FColor.Red * 255);
  758. SCol.g := Round(FColor.green * 255);
  759. SCol.b := Round(FColor.Blue * 255);
  760. SCol.a := Round(FColor.Alpha * 255);
  761. //-----------No optimising-----------
  762. if FOptimise = opNone then
  763. begin
  764. y := 0;
  765. while y < FHeight do
  766. begin
  767. x := 0;
  768. while x < fWidth do
  769. begin
  770. HardSet(x, y);
  771. x := x + 1;
  772. end;
  773. y := y + 1;
  774. end;
  775. end
  776. else
  777. if FOptimise = op4in1 then
  778. begin
  779. for x := 0 to fXres - 1 do
  780. HardSet(x, 0);
  781. for x := 0 to fXres - 1 do
  782. HardSet(x, fYres - 1);
  783. for y := 1 to fYres - 1 do
  784. HardSet(0, y);
  785. for y := 1 to fYres - 1 do
  786. HardSet(fXres - 1, y);
  787. y := 2;
  788. while y < fYres do
  789. begin
  790. x := 2;
  791. p1 := HardSet(x - 1, y - 2);
  792. HardSet(x - 1, y - 1);
  793. p0 := HardSet(x - 1, y);
  794. while x < fXres do
  795. begin
  796. pix := HardSet(x, y);
  797. if (pix = p1) and (pix = p0) then
  798. begin
  799. FDataInvIdx[y]^[x - 1] := pix;
  800. FDataInvIdx[y - 1]^[x - 1] := pix;
  801. end
  802. else
  803. begin
  804. HardSet(x - 1, y);
  805. HardSet(x - 1, y - 1);
  806. end;
  807. p2 := SoftTest(x + 1, y - 2);
  808. if (pix = p2) then
  809. FDataInvIdx[y - 1]^[x] := pix
  810. else
  811. HardSet(x, y - 1);
  812. p1 := p2;
  813. p0 := pix;
  814. x := x + 2;
  815. end;
  816. y := y + 2;
  817. end;
  818. end
  819. else
  820. if FOptimise = op9in1 then
  821. begin
  822. for x := 0 to fXres - 1 do
  823. HardSet(x, 0);
  824. for x := 0 to fXres - 1 do
  825. HardSet(x, fYres - 1);
  826. for y := 0 to fYres - 1 do
  827. HardSet(fXres - 1, y);
  828. // for y:=1 to fYres-1 do HardSet(fXres-2,y);
  829. y := 3;
  830. while y < fYres do
  831. begin
  832. x := 3;
  833. p1 := HardSet(x - 3, y - 3);
  834. // p2:=HardSet(x ,y-3);
  835. p3 := HardSet(x - 3, y);
  836. while x < fXres do
  837. begin
  838. p2 := SoftTest(x, y - 3);
  839. p4 := HardSet(x, y);
  840. if ((p1 = p2) and (p3 = p4) and (p2 = p4)) then
  841. begin
  842. xy := x + (fYres - (y - 3) - 1) * fXres;
  843. pixa^[xy - 2] := p4;
  844. pixa^[xy - 1] := p4;
  845. xy := xy - w; //xy:=x+(fYres-(y-2)-1)*fXres;
  846. pixa^[xy - 3] := p4;
  847. pixa^[xy - 2] := p4;
  848. pixa^[xy - 1] := p4;
  849. xy := xy - w; //xy:=x+(fYres-(y-1)-1)*fXres;
  850. pixa^[xy - 3] := p4;
  851. pixa^[xy - 2] := p4;
  852. pixa^[xy - 1] := p4;
  853. end
  854. else
  855. begin
  856. HardSet(x - 2, y - 3);
  857. HardSet(x - 1, y - 3);
  858. HardSet(x - 3, y - 2);
  859. HardSet(x - 2, y - 2);
  860. HardSet(x - 1, y - 2);
  861. HardSet(x - 3, y - 1);
  862. HardSet(x - 2, y - 1);
  863. HardSet(x - 1, y - 1);
  864. end;
  865. p1 := p2;
  866. p3 := p4;
  867. x := x + 3;
  868. end;
  869. y := y + 3;
  870. end;
  871. end
  872. else
  873. if FOptimise = op16in1 then
  874. begin
  875. y := 4;
  876. while (y <> FHeight + 3) do
  877. begin
  878. if y >= FHeight then
  879. y := FHeight - 1;
  880. repeat
  881. x := 4;
  882. p1 := HardSet(x - 4, y - 4);
  883. // HardSet(x ,y-4); //p2
  884. p3 := HardSet(x - 4, y);
  885. while (x <> fWidth + 3) do
  886. begin
  887. if x >= FWidth then
  888. x := FWidth - 1;
  889. repeat
  890. p2 := SoftTest(x, y - 4);
  891. p4 := HardSet(x, y);
  892. //p4.r:=255;
  893. if ((p1 = p2) and (p3 = p4) and (p2 = p4)) then
  894. begin
  895. xy := x + (h - (y - 4) - 1) * w;
  896. pixa^[xy - 3] := p4;
  897. pixa^[xy - 2] := p4;
  898. pixa^[xy - 1] := p4;
  899. xy := xy - w;
  900. pixa^[xy - 4] := p4;
  901. pixa^[xy - 3] := p4;
  902. pixa^[xy - 2] := p4;
  903. pixa^[xy - 1] := p4;
  904. xy := xy - w;
  905. pixa^[xy - 4] := p4;
  906. pixa^[xy - 3] := p4;
  907. pixa^[xy - 2] := p4;
  908. pixa^[xy - 1] := p4;
  909. xy := xy - w;
  910. pixa^[xy - 4] := p4;
  911. pixa^[xy - 3] := p4;
  912. pixa^[xy - 2] := p4;
  913. pixa^[xy - 1] := p4;
  914. end
  915. else
  916. begin
  917. //--------------------------------------------
  918. pM := HardSet(x - 2, y - 2);
  919. pL := HardSet(x - 4, y - 2);
  920. pT := HardSet(x - 2, y - 4);
  921. xy := x + (h - (y - 4) - 1) * w;
  922. if (p1 = pT) then
  923. pixa^[xy - 3] := pT
  924. else
  925. HardSet(x - 3, y - 4);
  926. if (p2 = pT) then
  927. pixa^[xy - 1] := pT
  928. else
  929. HardSet(x - 1, y - 4);
  930. xy := xy - w; //down
  931. if (pL = p1) then
  932. pixa^[xy - 4] := pL
  933. else
  934. HardSet(x - 4, y - 3);
  935. if (p1 = pM) then
  936. pixa^[xy - 3] := pM
  937. else
  938. HardSet(x - 3, y - 3);
  939. if (p2 = pM) then
  940. pixa^[xy - 1] := pM
  941. else
  942. HardSet(x - 1, y - 3); //p2m
  943. if (pT = pM) then
  944. pixa^[xy - 2] := pM
  945. else
  946. HardSet(x - 2, y - 3);
  947. xy := xy - w; //down
  948. if (pL = pM) then
  949. pixa^[xy - 3] := pM
  950. else
  951. HardSet(x - 3, y - 2);
  952. xy := xy - w; //down
  953. if (p3 = pL) then
  954. pixa^[xy - 4] := pL
  955. else
  956. HardSet(x - 4, y - 1);
  957. if (p3 = pM) then
  958. pixa^[xy - 3] := pM
  959. else
  960. HardSet(x - 3, y - 1); //p3m
  961. if (p4 = pM) then
  962. begin
  963. pixa^[xy - 1] := pM;
  964. if (pM = p2) then
  965. pixa^[xy + w - 1] := pM
  966. else
  967. HardSet(x - 1, y - 2);
  968. if (pM = p3) then
  969. pixa^[xy - 2] := pM
  970. else
  971. HardSet(x - 2, y - 1);
  972. end
  973. else
  974. begin
  975. HardSet(x - 1, y - 1); //p4m
  976. HardSet(x - 1, y - 2);
  977. HardSet(x - 2, y - 1);
  978. end;
  979. end;
  980. p1 := p2;
  981. p3 := p4;
  982. x := x + 4;
  983. until x >= FWidth;
  984. end; //while
  985. y := y + 4;
  986. until y > (FHeight - 2);
  987. end; //while
  988. for x := 0 to FWidth - 1 do
  989. FDataIdx[0][x] := FDataIdx[1][x];
  990. for y := 0 to FHeight - 1 do
  991. FDataIdx[y][FWidth - 1] := FDataIdx[y][FWidth - 2];
  992. end;
  993. end;
  994. function TGLZShadows.HardSet(const x, y: integer): Byte;
  995. var
  996. pix: Byte;
  997. coord: TAffineVector;
  998. ipixX, ipixY: integer;
  999. pixX, pixY: single;
  1000. pixZ: single;
  1001. IsInFrust: Boolean;
  1002. ilum: Integer;
  1003. shad: single;
  1004. Tol: Single;
  1005. modx, mody: single;
  1006. d2, d4, d5, d6, d8: single;
  1007. shad2, shad4, shad5, shad6, shad8: single;
  1008. function ComputeIlum: Integer; //PALOFF
  1009. begin
  1010. //---Lighting---
  1011. if FDepthFade then
  1012. begin
  1013. Result := Round(SCol.a * (pixZ * 10 - 9));
  1014. if Result < 0 then
  1015. Result := 0;
  1016. //if ilum>255 then ilum:=255;
  1017. if Result > SCol.a then
  1018. Result := SCol.a;
  1019. end
  1020. else
  1021. Result := 0;
  1022. end;
  1023. begin
  1024. //---test pixel for shadow---
  1025. if ViewerZBuf.GetPixelzDepth(x, y) < 1 then
  1026. begin
  1027. coord := ViewerZBuf.PixelToWorld(x, y);
  1028. IsInFrust := CasterZBuf.WorldToPixelZ(coord, pixX, pixY, pixZ);
  1029. //if caster.Camera.CameraStyle=csOrthogonal then IsInFrust:=CasterZBuf.OrthWorldToPixelZ(coord,pixX,pixY,pixZ);
  1030. //--- Tolerance scaling - reduces shadow-creeping at long-range and self-shadowing at short-range ---
  1031. tol := FTolerance * (1.0 - pixZ);
  1032. //--- ilum=light ------ SCol.a=shade ------
  1033. if not isInFrust then
  1034. begin
  1035. if FFrustShadow then
  1036. pix := SCol.a //dark outside frustrum
  1037. else
  1038. pix := ComputeIlum; //light outside frustrum
  1039. end
  1040. else
  1041. begin
  1042. ipixX := Trunc(pixX);
  1043. ipixY := Trunc(pixY);
  1044. if (FSoft ) and (ipixY > 0) then
  1045. begin //---soft shadows---
  1046. modx := Frac(pixX);
  1047. //extract the fraction part only - used to interpolate soft shadow edges
  1048. mody := Frac(pixY);
  1049. if ipixX > 0 then
  1050. d4 := CasterZBuf.DataIdx[ipixY]^[ipixX - 1]
  1051. else
  1052. d4 := CasterZBuf.DataIdx[ipixY]^[0];
  1053. d5 := CasterZBuf.DataIdx[ipixY]^[ipixX];
  1054. d6 := CasterZBuf.DataIdx[ipixY]^[ipixX + 1];
  1055. d8 := CasterZBuf.DataIdx[ipixY + 1]^[ipixX];
  1056. // if ipixY<1 then d2:=d5 else
  1057. d2 := CasterZBuf.DataIdx[ipixY - 1]^[ipixX];
  1058. ilum := ComputeIlum;
  1059. if ((pixZ - d2) > Tol) then
  1060. Shad2 := SCol.a
  1061. else
  1062. Shad2 := ilum;
  1063. if ((pixZ - d4) > Tol) then
  1064. Shad4 := SCol.a
  1065. else
  1066. Shad4 := ilum;
  1067. if ((pixZ - d5) > Tol) then
  1068. Shad5 := SCol.a
  1069. else
  1070. Shad5 := ilum;
  1071. if ((pixZ - d6) > Tol) then
  1072. Shad6 := SCol.a
  1073. else
  1074. Shad6 := ilum;
  1075. if ((pixZ - d8) > Tol) then
  1076. Shad8 := SCol.a
  1077. else
  1078. Shad8 := ilum;
  1079. shad := shad2 + (shad8 - shad2) * mody +
  1080. shad4 + (shad6 - shad4) * modx + shad5;
  1081. pix := Round(Shad / 3);
  1082. end
  1083. else
  1084. begin //---hard shadows---
  1085. if pixZ - Tol > CasterZBuf.DataIdx[ipixY]^[ipixX] then
  1086. pix := SCol.a //dark
  1087. else
  1088. pix := ComputeIlum; //light
  1089. end;
  1090. end;
  1091. end
  1092. else
  1093. begin // if z=1 ... i.e. nothing was drawn at this pixel (sky)
  1094. if FSkyShadow then
  1095. pix := SCol.a // dark
  1096. else
  1097. pix := 0; //ComputeIlum; // light
  1098. end;
  1099. FDataInvIdx[y]^[x] := pix; //Write pixel
  1100. result := pix;
  1101. end;
  1102. function TGLZShadows.SoftTest(const x, y: integer): Byte;
  1103. begin
  1104. result := FDataInvIdx[y]^[x];
  1105. end;
  1106. function TGLZShadows.GetViewer: TGLSceneViewer;
  1107. begin
  1108. result := FViewer;
  1109. end;
  1110. procedure TGLZShadows.SetViewer(const val: TGLSceneViewer);
  1111. begin
  1112. FViewer := Val;
  1113. Width := FViewer.Width;
  1114. Height := FViewer.Height;
  1115. end;
  1116. function TGLZShadows.GetCaster: TGLMemoryViewer;
  1117. begin
  1118. result := FCaster;
  1119. end;
  1120. procedure TGLZShadows.SetCaster(const val: TGLMemoryViewer);
  1121. begin
  1122. FCaster := Val;
  1123. end;
  1124. function TGLZShadows.CastShadow: Boolean;
  1125. begin
  1126. if Caster <> nil then
  1127. begin
  1128. if not assigned(CasterZBuf) then
  1129. begin
  1130. CasterZBuf := TGLZBuffer.Create;
  1131. CasterZBuf.LinkToViewer(FCaster);
  1132. end;
  1133. if FCaster.Camera.CameraStyle = csOrthogonal then
  1134. begin
  1135. if assigned(FCaster.Camera.TargetObject) then
  1136. begin
  1137. FCaster.Camera.Position.x := FCaster.Camera.TargetObject.Position.x;
  1138. FCaster.Camera.Position.z := FCaster.Camera.TargetObject.Position.z;
  1139. end;
  1140. with FCaster.Camera.direction do
  1141. begin
  1142. x := 0;
  1143. y := -1;
  1144. z := 0;
  1145. end;
  1146. end;
  1147. try
  1148. FCaster.Render;
  1149. except
  1150. Caster := nil; // prevents further attempts
  1151. raise;
  1152. end;
  1153. CasterZBuf.Refresh;
  1154. Result := False;
  1155. end
  1156. else
  1157. Result := True;
  1158. end;
  1159. procedure TGLZShadows.SetWidth(const val: integer);
  1160. begin
  1161. FWidth := val;
  1162. SetXRes(val);
  1163. end;
  1164. procedure TGLZShadows.SetHeight(const val: integer);
  1165. begin
  1166. FHeight := val;
  1167. SetYRes(val);
  1168. end;
  1169. procedure TGLZShadows.SetXRes(const val: integer);
  1170. var
  1171. i: integer;
  1172. begin
  1173. i := 2;
  1174. while val > i do
  1175. i := i * 2; //
  1176. FXRes := i; //calculate the closest power of 2, smaller than val
  1177. FTexturePrepared := False;
  1178. PrepareAlphaMemory;
  1179. end;
  1180. procedure TGLZShadows.SetYRes(const val: integer);
  1181. var
  1182. i: integer;
  1183. begin
  1184. i := 2;
  1185. while val > i do
  1186. i := i * 2; //
  1187. FYRes := i; //calculate the closest power of 2, larger than val
  1188. FTexturePrepared := False;
  1189. PrepareAlphaMemory;
  1190. end;
  1191. procedure TGLZShadows.SetSoft(const val: boolean);
  1192. begin
  1193. FSoft := val;
  1194. NotifyChange(Self);
  1195. end;
  1196. // ------------------------------------------------------------------
  1197. initialization
  1198. // ------------------------------------------------------------------
  1199. RegisterClasses([TGLZShadows]);
  1200. end.