GXS.Blur.pas 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885
  1. //
  2. // The graphics engine GLXEngine. The unit of GXScene for Delphi
  3. //
  4. unit GXS.Blur;
  5. (* Applies a blur effect over the viewport *)
  6. interface
  7. {$I Stage.Defines.inc}
  8. uses
  9. Winapi.OpenGL,
  10. Winapi.OpenGLext,
  11. System.Classes,
  12. System.SysUtils,
  13. System.UITypes,
  14. FMX.Graphics,
  15. Stage.VectorTypes,
  16. GXS.PersistentClasses,
  17. GXS.Scene,
  18. GXS.Coordinates,
  19. Stage.VectorGeometry,
  20. GXS.Objects,
  21. GXS.BitmapFont,
  22. GXS.Texture,
  23. GXS.Material,
  24. GXS.HudObjects,
  25. GXS.Color,
  26. GXS.Graphics,
  27. GXS.Context,
  28. GXS.State,
  29. Stage.Strings,
  30. Stage.TextureFormat,
  31. GXS.BaseClasses,
  32. GXS.RenderContextInfo;
  33. type
  34. TgxBlurPreset = (pNone, pGlossy, pBeastView, pOceanDepth, pDream, pOverBlur,
  35. pAdvancedBlur);
  36. TgxBlurkind = (bNone, bSimple, bAdvanced);
  37. TRGBPixel = record
  38. R, G, B: GLubyte;
  39. end;
  40. TRGBPixelBuffer = array of TRGBPixel;
  41. TgxAdvancedBlurImagePrepareEvent = procedure(Sender: TObject;
  42. BMP32: TgxBitmap32; var DoBlur: boolean) of object;
  43. EGLMotionBlurException = class(Exception);
  44. TgxBlur = class(TgxHUDSprite)
  45. private
  46. FViewer: TgxMemoryViewer;
  47. OldTime: Double;
  48. FDoingMemView: boolean;
  49. FBlurDeltaTime: Double;
  50. FBlurTop: Single;
  51. FBlurBottom: Single;
  52. FBlurLeft: Single;
  53. FBlurRight: Single;
  54. FRenderHeight: Integer;
  55. FRenderWidth: Integer;
  56. FPreset: TgxBlurPreset;
  57. FTargetObject: TgxbaseSceneObject;
  58. FOnAdvancedBlurImagePrepareEvent: TgxAdvancedBlurImagePrepareEvent;
  59. FBlur: TgxBlurkind;
  60. Pixelbuffer: TRGBPixelBuffer;
  61. FAdvancedBlurPasses: Integer;
  62. FOnAfterTargetRender: TNotifyEvent;
  63. FOnBeforeTargetRender: TNotifyEvent;
  64. FAdvancedBlurAmp: Single;
  65. FBlurSelf: boolean;
  66. FAdvancedBlurLowClamp: byte;
  67. FAdvancedBlurHiClamp: byte;
  68. FRenderBackgroundColor: TColor;
  69. procedure DoMemView(baseObject: TgxbaseSceneObject);
  70. procedure SetRenderHeight(const Value: Integer);
  71. procedure SetRenderWidth(const Value: Integer);
  72. procedure UpdateImageSettings;
  73. procedure SetPreset(const Value: TgxBlurPreset);
  74. function StoreBlurBottom: boolean;
  75. function StoreBlurDeltaTime: boolean;
  76. function StoreBlurRight: boolean;
  77. function StoreBlurTop: boolean;
  78. function StoreBlurLeft: boolean;
  79. procedure SetTargetObject(const Value: TgxbaseSceneObject);
  80. procedure SetOnAdvancedBlurImagePrepareEvent(const Value
  81. : TgxAdvancedBlurImagePrepareEvent);
  82. procedure SetBlur(const Value: TgxBlurkind);
  83. procedure SetAdvancedBlurPasses(const Value: Integer);
  84. procedure SetOnAfterTargetRender(const Value: TNotifyEvent);
  85. procedure SetOnBeforeTargetRender(const Value: TNotifyEvent);
  86. procedure SetAdvancedBlurAmp(const Value: Single);
  87. procedure SetBlurSelf(const Value: boolean);
  88. procedure SetAdvancedBlurLowClamp(const Value: byte);
  89. procedure SetAdvancedBlurHiClamp(const Value: byte);
  90. procedure SetRenderBackgroundColor(const Value: TColor);
  91. public
  92. constructor Create(AOwner: TComponent); override;
  93. destructor Destroy; override;
  94. procedure DoProgress(const progressTime: TgxProgressTimes); override;
  95. procedure DoRender(var ARci: TgxRenderContextInfo;
  96. ARenderSelf, ARenderChildren: boolean); override;
  97. procedure Notification(AComponent: TComponent;
  98. Operation: TOperation); override;
  99. published
  100. property Blur: TgxBlurkind read FBlur write SetBlur;
  101. property BlurDeltaTime: Double read FBlurDeltaTime write FBlurDeltaTime
  102. stored StoreBlurDeltaTime;
  103. property BlurLeft: Single read FBlurLeft write FBlurLeft
  104. stored StoreBlurLeft;
  105. property BlurTop: Single read FBlurTop write FBlurTop stored StoreBlurTop;
  106. property BlurRight: Single read FBlurRight write FBlurRight
  107. stored StoreBlurRight;
  108. property BlurBottom: Single read FBlurBottom write FBlurBottom
  109. stored StoreBlurBottom;
  110. property RenderWidth: Integer read FRenderWidth write SetRenderWidth
  111. default 256;
  112. property RenderHeight: Integer read FRenderHeight write SetRenderHeight
  113. default 256;
  114. property Preset: TgxBlurPreset read FPreset write SetPreset stored false;
  115. property TargetObject: TgxbaseSceneObject read FTargetObject
  116. write SetTargetObject;
  117. property AdvancedBlurPasses: Integer read FAdvancedBlurPasses
  118. write SetAdvancedBlurPasses;
  119. property AdvancedBlurAmp: Single read FAdvancedBlurAmp
  120. write SetAdvancedBlurAmp;
  121. property AdvancedBlurLowClamp: byte read FAdvancedBlurLowClamp
  122. write SetAdvancedBlurLowClamp;
  123. property AdvancedBlurHiClamp: byte read FAdvancedBlurHiClamp
  124. write SetAdvancedBlurHiClamp;
  125. property BlurSelf: boolean read FBlurSelf write SetBlurSelf;
  126. property RenderBackgroundColor: TColor read FRenderBackgroundColor
  127. write SetRenderBackgroundColor;
  128. property OnAdvancedBlurImagePrepareEvent: TgxAdvancedBlurImagePrepareEvent
  129. read FOnAdvancedBlurImagePrepareEvent
  130. write SetOnAdvancedBlurImagePrepareEvent;
  131. property OnBeforeTargetRender: TNotifyEvent read FOnBeforeTargetRender
  132. write SetOnBeforeTargetRender;
  133. property OnAfterTargetRender: TNotifyEvent read FOnAfterTargetRender
  134. write SetOnAfterTargetRender;
  135. end;
  136. (* This component blurs everything thatis rendered BEFORE it. So if you want part
  137. of your scene blured, the other not blured, make sure that the other part is
  138. rendered after this component. It is fast and does not require shaders.
  139. Note: it is FPS-dependant. Also also can produce a "blury trail effect", which
  140. stays on the screen until something new is rendered over it. It can be overcome
  141. by changing the Material.FrontProperties.Diffuse property. This, however, also
  142. has a drawback - the picture becomes more blured altogether. For example, if
  143. your backgroud color is Black, set the Material.FrontProperties.Diffuse to White.
  144. If it is White, set Material.FrontProperties.Diffuse to Black. I haven't tried
  145. any others, but I hope you get the idea ;)
  146. I've seen this effect in different Bruring components, even in shaders, but if
  147. anyone knows another way to fix this issue - please post it on the glscene newsgroup *)
  148. TgxMotionBlur = class(TgxCustomSceneObject, IgxInitializable)
  149. private
  150. FIntensity: Single;
  151. function StoreIntensity: boolean;
  152. protected
  153. procedure DoOnAddedToParent; override;
  154. procedure InitializeObject(ASender: TObject;
  155. const ARci: TgxRenderContextInfo); virtual;
  156. public
  157. { This function is only valid AFTER OpenGL has been initialized. }
  158. function SupportsRequiredExtensions: boolean;
  159. procedure DoRender(var ARci: TgxRenderContextInfo;
  160. ARenderSelf, ARenderChildren: boolean); override;
  161. constructor Create(AOwner: TComponent); override;
  162. procedure Assign(Source: TPersistent); override;
  163. published
  164. // The more the intensity, the more blur you have.
  165. property Intensity: Single read FIntensity write FIntensity
  166. stored StoreIntensity;
  167. // From TgxBaseSceneObject.
  168. property Visible;
  169. property OnProgress;
  170. property Behaviours;
  171. property Effects;
  172. property Hint;
  173. end;
  174. // ------------------------------------------------------------------------
  175. implementation
  176. // ------------------------------------------------------------------------
  177. const
  178. EPS = 0.001;
  179. constructor TgxBlur.Create(AOwner: TComponent);
  180. begin
  181. inherited;
  182. FBlurDeltaTime := 0.02;
  183. FBlurTop := 0.01;
  184. FBlurLeft := 0.01;
  185. FBlurRight := 0.01;
  186. FBlurBottom := 0.01;
  187. FRenderHeight := 256;
  188. FRenderWidth := 256;
  189. FViewer := TgxMemoryViewer.Create(Self);
  190. FPreset := pNone;
  191. Material.Texture.Disabled := false;
  192. FAdvancedBlurPasses := 1;
  193. FAdvancedBlurAmp := 1.1;
  194. FBlurSelf := true;
  195. FAdvancedBlurLowClamp := 0;
  196. FAdvancedBlurHiClamp := 255;
  197. FRenderBackgroundColor := TColors.Black;
  198. end;
  199. destructor TgxBlur.Destroy;
  200. begin
  201. FViewer.Free;
  202. inherited;
  203. end;
  204. procedure TgxBlur.UpdateImageSettings;
  205. var
  206. B: TBitmap;
  207. begin
  208. if Material.Texture.Image is TgxBlankImage then
  209. with TgxBlankImage(Material.Texture.Image) do
  210. begin
  211. Width := RenderWidth;
  212. Height := RenderHeight;
  213. end
  214. else if Material.Texture.Image is TgxPersistentImage then
  215. begin
  216. B := TgxPersistentImage(Material.Texture.Image).Picture.Bitmap;
  217. B.Width := 0;
  218. B.Height := 0;
  219. B.Width := RenderWidth;
  220. B.Height := RenderHeight;
  221. end;
  222. with FViewer do
  223. begin
  224. Width := RenderWidth;
  225. Height := RenderHeight;
  226. end;
  227. SetLength(Pixelbuffer, RenderWidth * RenderHeight);
  228. end;
  229. procedure TgxBlur.DoProgress(const progressTime: TgxProgressTimes);
  230. begin
  231. inherited;
  232. if Self.Visible and (progressTime.newTime - OldTime > FBlurDeltaTime) then
  233. begin
  234. OldTime := progressTime.newTime;
  235. if TargetObject <> nil then
  236. DoMemView(TargetObject);
  237. end;
  238. end;
  239. procedure TgxBlur.DoMemView(baseObject: TgxbaseSceneObject);
  240. var
  241. OldFocalLength: Single;
  242. refsiz: Single;
  243. BMP: TgxBitmap32;
  244. x, y: Integer;
  245. line: PgxPixel32Array;
  246. by: Integer;
  247. bp: Integer;
  248. DoBlur: boolean;
  249. procedure ApplyBlur(const passes: Integer);
  250. var
  251. t: Integer;
  252. x, y: Integer;
  253. lin, linu, lind, linuu, lindd: PgxPixel32Array;
  254. R, G, B: Single;
  255. ir, ig, ib: Smallint;
  256. procedure ApplyBlurClampAndSetPixel;
  257. begin
  258. // 0.1111 = 1/7 (where 7 is the times each pixel is summed with neighbours or self)
  259. ir := round(R * FAdvancedBlurAmp * 0.1111);
  260. ig := round(G * FAdvancedBlurAmp * 0.1111);
  261. ib := round(B * FAdvancedBlurAmp * 0.1111);
  262. // Hi Clamp
  263. if ir > FAdvancedBlurHiClamp then
  264. ir := FAdvancedBlurHiClamp;
  265. if ig > FAdvancedBlurHiClamp then
  266. ig := FAdvancedBlurHiClamp;
  267. if ib > FAdvancedBlurHiClamp then
  268. ib := FAdvancedBlurHiClamp;
  269. lin^[x].R := ir;
  270. lin^[x].G := ig;
  271. lin^[x].B := ib;
  272. end;
  273. begin
  274. for t := 0 to passes do
  275. begin
  276. for y := 2 to BMP.Height - 3 do
  277. begin
  278. linuu := BMP.ScanLine[y - 2];
  279. linu := BMP.ScanLine[y - 1];
  280. lin := BMP.ScanLine[y];
  281. lind := BMP.ScanLine[y + 1];
  282. lindd := BMP.ScanLine[y + 2];
  283. by := y * BMP.Height;
  284. // X = 0 PART:
  285. x := 0;
  286. R := lin^[x].R + lin^[x + 1].R + lin^[x + 2].R + linu^[x].R + lind^[x].R
  287. + linuu^[x].R + lindd^[x].R;
  288. G := lin^[x].G + lin^[x + 1].G + lin^[x + 2].G + linu^[x].G + lind^[x].G
  289. + linuu^[x].G + lindd^[x].G;
  290. B := lin^[x].B + lin^[x + 1].B + lin^[x + 2].B + linu^[x].B + lind^[x].B
  291. + linuu^[x].B + lindd^[x].B;
  292. ApplyBlurClampAndSetPixel;
  293. // X = 1 PART:
  294. x := 1;
  295. R := lin^[x].R + lin^[x + 1].R + lin^[x - 1].R + lin^[x + 2].R +
  296. linu^[x].R + lind^[x].R + linuu^[x].R + lindd^[x].R;
  297. G := lin^[x].G + lin^[x + 1].G + lin^[x - 1].G + lin^[x + 2].G +
  298. linu^[x].G + lind^[x].G + linuu^[x].G + lindd^[x].G;
  299. B := lin^[x].B + lin^[x + 1].B + lin^[x - 1].B + lin^[x + 2].B +
  300. linu^[x].B + lind^[x].B + linuu^[x].B + lindd^[x].B;
  301. ApplyBlurClampAndSetPixel;
  302. // ALL X IN MIDDLE PART:
  303. for x := 2 to BMP.Width - 3 do
  304. begin
  305. R := lin^[x].R + lin^[x + 1].R + lin^[x - 1].R + lin^[x + 2].R +
  306. lin^[x - 2].R + linu^[x].R + lind^[x].R + linuu^[x].R + lindd^[x].R;
  307. G := lin^[x].G + lin^[x + 1].G + lin^[x - 1].G + lin^[x + 2].G +
  308. lin^[x - 2].G + linu^[x].G + lind^[x].G + linuu^[x].G + lindd^[x].G;
  309. B := lin^[x].B + lin^[x + 1].B + lin^[x - 1].B + lin^[x + 2].B +
  310. lin^[x - 2].B + linu^[x].B + lind^[x].B + linuu^[x].B + lindd^[x].B;
  311. ApplyBlurClampAndSetPixel;
  312. end;
  313. // X = NEXT TO LAST PART:
  314. x := BMP.Width - 2;
  315. R := lin^[x].R + lin^[x + 1].R + lin^[x - 1].R + lin^[x - 2].R +
  316. linu^[x].R + lind^[x].R + linuu^[x].R + lindd^[x].R;
  317. G := lin^[x].G + lin^[x + 1].G + lin^[x - 1].G + lin^[x - 2].G +
  318. linu^[x].G + lind^[x].G + linuu^[x].G + lindd^[x].G;
  319. B := lin^[x].B + lin^[x + 1].B + lin^[x - 1].B + lin^[x - 2].B +
  320. linu^[x].B + lind^[x].B + linuu^[x].B + lindd^[x].B;
  321. ApplyBlurClampAndSetPixel;
  322. // X = LAST PART:
  323. x := BMP.Width - 1;
  324. R := lin^[x].R + lin^[x - 1].R + lin^[x - 2].R + linu^[x].R + lind^[x].R
  325. + linuu^[x].R + lindd^[x].R;
  326. G := lin^[x].G + lin^[x - 1].G + lin^[x - 2].G + linu^[x].G + lind^[x].G
  327. + linuu^[x].G + lindd^[x].G;
  328. B := lin^[x].B + lin^[x - 1].B + lin^[x - 2].B + linu^[x].B + lind^[x].B
  329. + linuu^[x].B + lindd^[x].B;
  330. ApplyBlurClampAndSetPixel;
  331. end;
  332. end;
  333. end;
  334. begin
  335. if FViewer.Camera <> Scene.CurrentCamera then
  336. FViewer.Camera := Scene.CurrentCamera;
  337. if FViewer.Camera <> nil then
  338. begin
  339. FDoingMemView := true;
  340. // Scene.RenderScene(FViewer.Buffer,FViewer.Width,FViewer.Height,dsRendering,baseObject);
  341. FViewer.Camera.BeginUpdate;
  342. OldFocalLength := FViewer.Camera.FocalLength;
  343. // CALCULATE SCALED FOCAL LENGTH FOR VIEWER
  344. if Scene.CurrentBuffer.Width > Scene.CurrentBuffer.Height then
  345. refsiz := Scene.CurrentBuffer.Width
  346. else
  347. refsiz := Scene.CurrentBuffer.Height;
  348. FViewer.Camera.FocalLength := FViewer.Camera.FocalLength *
  349. FViewer.Buffer.Width / refsiz;
  350. if FViewer.Buffer.BackgroundColor <> FRenderBackgroundColor then
  351. FViewer.Buffer.BackgroundColor := FRenderBackgroundColor;
  352. try
  353. case FBlur of
  354. bNone:
  355. begin
  356. // do nothing
  357. end;
  358. bSimple:
  359. begin
  360. if Assigned(FOnBeforeTargetRender) then
  361. FOnBeforeTargetRender(Self);
  362. // RENDER
  363. FViewer.Render(baseObject);
  364. // Copy to texture (unfortunatelly, after this, the bitmap cannot be red back from the hardware.. i think)
  365. FViewer.CopyToTexture(Material.Texture);
  366. if Assigned(FOnAfterTargetRender) then
  367. FOnAfterTargetRender(Self);
  368. end;
  369. bAdvanced:
  370. begin
  371. if Assigned(FOnBeforeTargetRender) then
  372. FOnBeforeTargetRender(Self);
  373. // RENDER
  374. FViewer.Render(baseObject);
  375. // Read pixels from buffer. This is slow, but ok with reasonably small render size.
  376. FViewer.Buffer.RenderingContext.Activate;
  377. try
  378. glReadPixels(0, 0, FViewer.Buffer.Width, FViewer.Buffer.Height,
  379. GL_RGB, GL_UNSIGNED_BYTE, Pixelbuffer);
  380. except
  381. FViewer.Buffer.RenderingContext.Deactivate;
  382. end;
  383. if Assigned(FOnAfterTargetRender) then
  384. FOnAfterTargetRender(Self);
  385. BMP := Material.Texture.Image.GetBitmap32;
  386. BMP.Narrow;
  387. FViewer.Buffer.RenderingContext.Deactivate;
  388. // FILLS THE BITMAP with the pixelbuffer captured from the internal memoryViewer
  389. for y := 0 to RenderHeight - 1 do
  390. begin
  391. line := BMP.ScanLine[y];
  392. by := y * RenderHeight;
  393. for x := 0 to RenderWidth - 1 do
  394. begin
  395. bp := x + by;
  396. line^[x].R := Pixelbuffer[bp].R;
  397. line^[x].G := Pixelbuffer[bp].G;
  398. line^[x].B := Pixelbuffer[bp].B;
  399. // Low clamp
  400. if line^[x].R < FAdvancedBlurLowClamp then
  401. line^[x].R := 0;
  402. if line^[x].G < FAdvancedBlurLowClamp then
  403. line^[x].G := 0;
  404. if line^[x].B < FAdvancedBlurLowClamp then
  405. line^[x].B := 0;
  406. end;
  407. end;
  408. DoBlur := true;
  409. if Assigned(FOnAdvancedBlurImagePrepareEvent) then
  410. begin
  411. FOnAdvancedBlurImagePrepareEvent(Self, BMP, DoBlur);
  412. end;
  413. if DoBlur then
  414. ApplyBlur(FAdvancedBlurPasses);
  415. Material.Texture.Image.NotifyChange(Self);
  416. end;
  417. end;
  418. finally
  419. FViewer.Camera.FocalLength := OldFocalLength;
  420. FViewer.Camera.EndUpdate;
  421. FDoingMemView := false;
  422. end;
  423. end;
  424. end;
  425. {$WARNINGS Off} // Suppress "unsafe" warning
  426. procedure TgxBlur.DoRender(var ARci: TgxRenderContextInfo;
  427. ARenderSelf, ARenderChildren: boolean);
  428. var
  429. vx, vy, vx1, vy1, f: Single;
  430. offsx, offsy: Single;
  431. MaxMeasure: Integer;
  432. begin
  433. if FDoingMemView and (FBlurSelf = false) then
  434. Exit;
  435. if (csDesigning in ComponentState) then
  436. begin
  437. if Count > 0 then
  438. Self.RenderChildren(0, Count - 1, ARci);
  439. Exit;
  440. end;
  441. if ARci.ignoreMaterials then
  442. Exit;
  443. Material.Apply(ARci);
  444. repeat
  445. if AlphaChannel <> 1 then
  446. ARci.gxStates.SetMaterialAlphaChannel(GL_FRONT, AlphaChannel);
  447. // Prepare matrices
  448. glMatrixMode(GL_MODELVIEW);
  449. glPushMatrix;
  450. glLoadMatrixf(@TgxSceneBuffer(ARci.Buffer).BaseProjectionMatrix);
  451. if ARci.renderDPI = 96 then
  452. f := 1
  453. else
  454. f := ARci.renderDPI / 96;
  455. glScalef(2 / ARci.viewPortSize.cx, 2 / ARci.viewPortSize.cy, 1);
  456. // center of viewport:
  457. glTranslatef(0, 0, Position.Z);
  458. if Rotation <> 0 then
  459. glRotatef(Rotation, 0, 0, 1);
  460. glMatrixMode(GL_PROJECTION);
  461. glPushMatrix;
  462. glLoadIdentity;
  463. ARci.gxStates.Disable(stDepthTest);
  464. ARci.gxStates.DepthWriteMask := false;
  465. // calculate offsets in order to keep the quad a square centered in the view
  466. if ARci.viewPortSize.cx > ARci.viewPortSize.cy then
  467. begin
  468. offsx := 0;
  469. offsy := (ARci.viewPortSize.cx - ARci.viewPortSize.cy) * 0.5;
  470. MaxMeasure := ARci.viewPortSize.cx;
  471. end
  472. else
  473. begin
  474. offsx := (ARci.viewPortSize.cy - ARci.viewPortSize.cx) * 0.5;
  475. offsy := 0;
  476. MaxMeasure := ARci.viewPortSize.cy;
  477. end;
  478. // precalc coordinates
  479. vx := -ARci.viewPortSize.cx * 0.5 * f;
  480. vx1 := vx + ARci.viewPortSize.cx * f;
  481. vy := +ARci.viewPortSize.cy * 0.5 * f;
  482. vy1 := vy - ARci.viewPortSize.cy * f;
  483. vx := vx - offsx;
  484. vx1 := vx1 + offsx;
  485. vy := vy + offsy;
  486. vy1 := vy1 - offsy;
  487. // Cause the radial scaling
  488. if FDoingMemView then
  489. begin
  490. vx := vx - FBlurLeft * MaxMeasure;
  491. vx1 := vx1 + FBlurRight * MaxMeasure;
  492. vy := vy + FBlurTop * MaxMeasure;
  493. vy1 := vy1 - FBlurBottom * MaxMeasure;
  494. end;
  495. // issue quad
  496. glBegin(GL_QUADS);
  497. glNormal3fv(@YVector);
  498. glTexCoord2f(0, 0);
  499. glVertex2f(vx, vy1);
  500. glTexCoord2f(XTiles, 0);
  501. glVertex2f(vx1, vy1);
  502. glTexCoord2f(XTiles, YTiles);
  503. glVertex2f(vx1, vy);
  504. glTexCoord2f(0, YTiles);
  505. glVertex2f(vx, vy);
  506. glEnd;
  507. // restore state
  508. glPopMatrix;
  509. glMatrixMode(GL_MODELVIEW);
  510. glPopMatrix;
  511. until not Material.UnApply(ARci);
  512. if Count > 0 then
  513. Self.RenderChildren(0, Count - 1, ARci);
  514. end;
  515. procedure TgxBlur.Notification(AComponent: TComponent; Operation: TOperation);
  516. begin
  517. inherited;
  518. if Operation = opRemove then
  519. if AComponent = FTargetObject then
  520. FTargetObject := nil;
  521. inherited;
  522. end;
  523. {$WARNINGS On}
  524. procedure TgxBlur.SetRenderBackgroundColor(const Value: TColor);
  525. begin
  526. FRenderBackgroundColor := Value;
  527. end;
  528. procedure TgxBlur.SetRenderHeight(const Value: Integer);
  529. begin
  530. FRenderHeight := Value;
  531. UpdateImageSettings;
  532. end;
  533. procedure TgxBlur.SetRenderWidth(const Value: Integer);
  534. begin
  535. FRenderWidth := Value;
  536. UpdateImageSettings;
  537. end;
  538. procedure TgxBlur.SetTargetObject(const Value: TgxbaseSceneObject);
  539. begin
  540. FTargetObject := Value;
  541. end;
  542. procedure TgxBlur.SetAdvancedBlurAmp(const Value: Single);
  543. begin
  544. FAdvancedBlurAmp := Value;
  545. end;
  546. procedure TgxBlur.SetAdvancedBlurHiClamp(const Value: byte);
  547. begin
  548. FAdvancedBlurHiClamp := Value;
  549. end;
  550. procedure TgxBlur.SetAdvancedBlurLowClamp(const Value: byte);
  551. begin
  552. FAdvancedBlurLowClamp := Value;
  553. end;
  554. procedure TgxBlur.SetAdvancedBlurPasses(const Value: Integer);
  555. begin
  556. FAdvancedBlurPasses := Value;
  557. end;
  558. procedure TgxBlur.SetBlur(const Value: TgxBlurkind);
  559. begin
  560. if FBlur <> Value then
  561. begin
  562. case Value of
  563. bNone:
  564. begin
  565. // do Nothing
  566. end;
  567. bSimple:
  568. begin
  569. Material.Texture.ImageClassName := TgxBlankImage.ClassName;
  570. end;
  571. bAdvanced:
  572. begin
  573. Material.Texture.ImageClassName := TgxPersistentImage.ClassName;
  574. end;
  575. end;
  576. UpdateImageSettings;
  577. end;
  578. FBlur := Value;
  579. end;
  580. procedure TgxBlur.SetBlurSelf(const Value: boolean);
  581. begin
  582. FBlurSelf := Value;
  583. end;
  584. procedure TgxBlur.SetOnAdvancedBlurImagePrepareEvent
  585. (const Value: TgxAdvancedBlurImagePrepareEvent);
  586. begin
  587. FOnAdvancedBlurImagePrepareEvent := Value;
  588. end;
  589. procedure TgxBlur.SetOnAfterTargetRender(const Value: TNotifyEvent);
  590. begin
  591. FOnAfterTargetRender := Value;
  592. end;
  593. procedure TgxBlur.SetOnBeforeTargetRender(const Value: TNotifyEvent);
  594. begin
  595. FOnBeforeTargetRender := Value;
  596. end;
  597. procedure TgxBlur.SetPreset(const Value: TgxBlurPreset);
  598. begin
  599. FPreset := Value;
  600. case FPreset of
  601. pNone:
  602. begin
  603. // do nothing
  604. end;
  605. pAdvancedBlur:
  606. begin
  607. Blur := bAdvanced;
  608. Material.BlendingMode := bmAdditive;
  609. Material.FrontProperties.Diffuse.SetColor(1, 1, 1, 1);
  610. BlurTop := 0;
  611. BlurLeft := 0;
  612. BlurRight := 0;
  613. BlurBottom := 0;
  614. BlurDeltaTime := 0;
  615. BlurSelf := false;
  616. AdvancedBlurPasses := 1;
  617. AdvancedBlurAmp := 1.2;
  618. RenderWidth := 64;
  619. RenderHeight := 64;
  620. end;
  621. pGlossy:
  622. begin
  623. Material.BlendingMode := bmAdditive;
  624. Material.FrontProperties.Diffuse.SetColor(1, 1, 1, 0.7);
  625. BlurTop := 0.02;
  626. BlurLeft := 0.02;
  627. BlurRight := 0.02;
  628. BlurBottom := 0.02;
  629. BlurDeltaTime := 0.02;
  630. BlurSelf := true;
  631. end;
  632. pBeastView:
  633. begin
  634. Blur := bSimple;
  635. Material.BlendingMode := bmAdditive;
  636. Material.FrontProperties.Diffuse.SetColor(1, 0, 0, 0.8);
  637. BlurTop := 0.001;
  638. BlurLeft := 0.03;
  639. BlurRight := 0.03;
  640. BlurBottom := 0.001;
  641. BlurDeltaTime := 0.02;
  642. BlurSelf := true;
  643. end;
  644. pOceanDepth:
  645. begin
  646. Blur := bSimple;
  647. Material.BlendingMode := bmTransparency;
  648. Material.FrontProperties.Diffuse.SetColor(0.2, 0.2, 1, 0.99);
  649. BlurTop := 0.04;
  650. BlurLeft := 0.02;
  651. BlurRight := 0.02;
  652. BlurBottom := 0.04;
  653. BlurDeltaTime := 0.02;
  654. BlurSelf := true;
  655. end;
  656. pDream:
  657. begin
  658. Blur := bSimple;
  659. Material.BlendingMode := bmTransparency;
  660. Material.FrontProperties.Diffuse.SetColor(1, 1, 1, 0.992);
  661. BlurTop := 0.02;
  662. BlurLeft := 0.02;
  663. BlurRight := 0.02;
  664. BlurBottom := 0.02;
  665. BlurDeltaTime := 0.1;
  666. BlurSelf := true;
  667. end;
  668. pOverBlur:
  669. begin
  670. Blur := bSimple;
  671. Material.BlendingMode := bmAdditive;
  672. Material.FrontProperties.Diffuse.SetColor(0.95, 0.95, 0.95, 0.98);
  673. BlurTop := 0.01;
  674. BlurLeft := 0.01;
  675. BlurRight := 0.01;
  676. BlurBottom := 0.01;
  677. BlurDeltaTime := 0.02;
  678. BlurSelf := true;
  679. end;
  680. end;
  681. end;
  682. function TgxBlur.StoreBlurBottom: boolean;
  683. begin
  684. Result := Abs(FBlurBottom - 0.01) > EPS;
  685. end;
  686. function TgxBlur.StoreBlurDeltaTime: boolean;
  687. begin
  688. Result := Abs(FBlurDeltaTime - 0.02) > EPS;
  689. end;
  690. function TgxBlur.StoreBlurLeft: boolean;
  691. begin
  692. Result := Abs(FBlurLeft - 0.01) > EPS;
  693. end;
  694. function TgxBlur.StoreBlurRight: boolean;
  695. begin
  696. Result := Abs(FBlurRight - 0.01) > EPS;
  697. end;
  698. function TgxBlur.StoreBlurTop: boolean;
  699. begin
  700. Result := Abs(FBlurTop - 0.01) > EPS;
  701. end;
  702. // -------------------------------------------------
  703. // TgxMotionBlur
  704. // -------------------------------------------------
  705. procedure TgxMotionBlur.Assign(Source: TPersistent);
  706. begin
  707. inherited;
  708. if Source is TgxMotionBlur then
  709. begin
  710. FIntensity := TgxMotionBlur(Source).FIntensity;
  711. end;
  712. end;
  713. constructor TgxMotionBlur.Create(AOwner: TComponent);
  714. begin
  715. inherited Create(AOwner);
  716. Material.FrontProperties.Diffuse.Initialize(clrBlack);
  717. Material.MaterialOptions := [moNoLighting, moIgnoreFog];
  718. Material.Texture.Disabled := false;
  719. Material.BlendingMode := bmTransparency;
  720. FIntensity := 0.975;
  721. end;
  722. procedure TgxMotionBlur.DoOnAddedToParent;
  723. begin
  724. inherited;
  725. // Request to be initialized on next render.
  726. if Scene <> nil then
  727. Scene.InitializableObjects.Add(Self);
  728. end;
  729. procedure TgxMotionBlur.DoRender(var ARci: TgxRenderContextInfo;
  730. ARenderSelf, ARenderChildren: boolean);
  731. begin
  732. if not(ARci.ignoreMaterials or (csDesigning in ComponentState) or
  733. (ARci.drawState = dsPicking)) then
  734. with ARci.gxStates do
  735. begin
  736. ARci.ignoreDepthRequests := true;
  737. Material.Apply(ARci);
  738. ActiveTextureEnabled[ttTextureRect] := true;
  739. glMatrixMode(GL_PROJECTION);
  740. glPushMatrix;
  741. glLoadIdentity;
  742. glOrtho(0, ARci.viewPortSize.cx, ARci.viewPortSize.cy, 0, 0, 1);
  743. glMatrixMode(GL_MODELVIEW);
  744. glPushMatrix;
  745. glLoadIdentity;
  746. Disable(stDepthTest);
  747. DepthWriteMask := false;
  748. glBegin(GL_QUADS);
  749. glTexCoord2f(0.0, ARci.viewPortSize.cy);
  750. glVertex2f(0, 0);
  751. glTexCoord2f(0.0, 0.0);
  752. glVertex2f(0, ARci.viewPortSize.cy);
  753. glTexCoord2f(ARci.viewPortSize.cx, 0.0);
  754. glVertex2f(ARci.viewPortSize.cx, ARci.viewPortSize.cy);
  755. glTexCoord2f(ARci.viewPortSize.cx, ARci.viewPortSize.cy);
  756. glVertex2f(ARci.viewPortSize.cx, 0);
  757. glEnd;
  758. glPopMatrix;
  759. glMatrixMode(GL_PROJECTION);
  760. glPopMatrix;
  761. glMatrixMode(GL_MODELVIEW);
  762. ActiveTextureEnabled[ttTextureRect] := false;
  763. Material.UnApply(ARci);
  764. ARci.ignoreDepthRequests := false;
  765. glCopyTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGB, 0, 0,
  766. ARci.viewPortSize.cx, ARci.viewPortSize.cy, 0);
  767. Material.FrontProperties.Diffuse.Alpha := FIntensity;
  768. end;
  769. if Count <> 0 then
  770. Self.RenderChildren(0, Count - 1, ARci);
  771. end;
  772. procedure TgxMotionBlur.InitializeObject(ASender: TObject;
  773. const ARci: TgxRenderContextInfo);
  774. begin
  775. // If extension is not supported, silently disable this component.
  776. if not(csDesigning in ComponentState) then
  777. if not SupportsRequiredExtensions then
  778. Visible := false;
  779. end;
  780. function TgxMotionBlur.StoreIntensity: boolean;
  781. begin
  782. Result := Abs(FIntensity - 0.975) > EPS;
  783. end;
  784. function TgxMotionBlur.SupportsRequiredExtensions: boolean;
  785. begin
  786. Result := true;
  787. // (GL_TEXTURE_RECTANGLE or GL_TEXTURE_RECTANGLE_ARB or GL_TEXTURE_RECTANGLE_NV);
  788. end;
  789. // ------------------------------------------------------------------
  790. initialization
  791. // ------------------------------------------------------------------
  792. RegisterClass(TgxBlur);
  793. RegisterClass(TgxMotionBlur);
  794. end.