GLzBuffer.pas 37 KB

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