GXS.TexLensFlare.pas 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. //
  2. // The graphics engine GXScene https://github.com/glscene
  3. //
  4. unit GXS.TexLensFlare;
  5. (* Texture-based Lens flare object *)
  6. interface
  7. {$I Stage.Defines.inc}
  8. uses
  9. Winapi.OpenGL,
  10. System.Classes,
  11. GXS.Scene,
  12. Stage.VectorGeometry,
  13. GXS.PersistentClasses,
  14. GXS.Objects,
  15. GXS.Texture,
  16. GXS.Context,
  17. GXS.RenderContextInfo,
  18. GXS.BaseClasses,
  19. GXS.State,
  20. Stage.VectorTypes;
  21. type
  22. TgxTextureLensFlare = class(TgxBaseSceneObject)
  23. private
  24. FSize: integer;
  25. FCurrSize: Single;
  26. FNumSecs: integer;
  27. FAutoZTest: boolean;
  28. //used for internal calculation
  29. FDeltaTime: Double;
  30. FImgSecondaries: TgxTexture;
  31. FImgRays: TgxTexture;
  32. FImgRing: TgxTexture;
  33. FImgGlow: TgxTexture;
  34. FSeed: Integer;
  35. procedure SetImgGlow(const Value: TgxTexture);
  36. procedure SetImgRays(const Value: TgxTexture);
  37. procedure SetImgRing(const Value: TgxTexture);
  38. procedure SetImgSecondaries(const Value: TgxTexture);
  39. procedure SetSeed(const Value: Integer);
  40. protected
  41. procedure SetSize(aValue: integer);
  42. procedure SetNumSecs(aValue: integer);
  43. procedure SetAutoZTest(aValue: boolean);
  44. public
  45. constructor Create(AOwner: TComponent); override;
  46. destructor Destroy; override;
  47. procedure BuildList(var rci: TgxRenderContextInfo); override;
  48. procedure DoProgress(const progressTime: TgxProgressTimes); override;
  49. published
  50. // MaxRadius of the flare.
  51. property Size: integer read FSize write SetSize default 50;
  52. // Random seed
  53. property Seed: Integer read FSeed write SetSeed;
  54. // Number of secondary flares.
  55. property NumSecs: integer read FNumSecs write SetNumSecs default 8;
  56. // Number of segments used when rendering circles.
  57. //property Resolution: integer read FResolution write SetResolution default 64;
  58. property AutoZTest: boolean read FAutoZTest write SetAutoZTest default True;
  59. // The Textures
  60. property ImgGlow: TgxTexture read FImgGlow write SetImgGlow;
  61. property ImgRays: TgxTexture read FImgRays write SetImgRays;
  62. property ImgRing: TgxTexture read FImgRing write SetImgRing;
  63. property ImgSecondaries: TgxTexture read FImgSecondaries write SetImgSecondaries;
  64. property ObjectsSorting;
  65. property Position;
  66. property Visible;
  67. property OnProgress;
  68. property Behaviours;
  69. property Effects;
  70. end;
  71. //------------------------------------------------------------------
  72. implementation
  73. //------------------------------------------------------------------
  74. // ------------------
  75. // ------------------ TgxTextureLensFlare ------------------
  76. // ------------------
  77. constructor TgxTextureLensFlare.Create(AOwner: TComponent);
  78. begin
  79. inherited;
  80. Randomize;
  81. FSeed := Random(2000) + 465;
  82. // Set default parameters:
  83. ObjectStyle := ObjectStyle + [osDirectDraw, osNoVisibilityCulling];
  84. FSize := 50;
  85. FCurrSize := FSize;
  86. FNumSecs := 8;
  87. FAutoZTest := True;
  88. FImgRays := TgxTexture.Create(Self);
  89. FImgSecondaries := TgxTexture.Create(Self);
  90. FImgRing := TgxTexture.Create(Self);
  91. FImgGlow := TgxTexture.Create(Self);
  92. end;
  93. procedure TgxTextureLensFlare.SetSize(aValue: integer);
  94. begin
  95. if FSize <> aValue then
  96. begin
  97. FSize := aValue;
  98. FCurrSize := FSize;
  99. StructureChanged;
  100. end;
  101. end;
  102. procedure TgxTextureLensFlare.SetNumSecs(aValue: integer);
  103. begin
  104. if FNumSecs <> aValue then
  105. begin
  106. FNumSecs := aValue;
  107. StructureChanged;
  108. end;
  109. end;
  110. procedure TgxTextureLensFlare.SetAutoZTest(aValue: boolean);
  111. begin
  112. if FAutoZTest <> aValue then
  113. begin
  114. FAutoZTest := aValue;
  115. StructureChanged;
  116. end;
  117. end;
  118. procedure TgxTextureLensFlare.BuildList(var rci: TgxRenderContextInfo);
  119. var
  120. v, rv, screenPos, posVector: TAffineVector;
  121. depth, rnd: Single;
  122. flag: Boolean;
  123. i: Integer;
  124. CurrentBuffer: TgxSceneBuffer;
  125. begin
  126. CurrentBuffer := TgxSceneBuffer(rci.buffer);
  127. SetVector(v, AbsolutePosition);
  128. // are we looking towards the flare?
  129. rv := VectorSubtract(v, PAffineVector(@rci.cameraPosition)^);
  130. if VectorDotProduct(rci.cameraDirection, rv) > 0 then
  131. begin
  132. // find out where it is on the screen.
  133. screenPos := CurrentBuffer.WorldToScreen(v);
  134. if (screenPos.X < rci.viewPortSize.cx) and (screenPos.X >= 0)
  135. and (screenPos.Y < rci.viewPortSize.cy) and (screenPos.Y >= 0) then
  136. begin
  137. if FAutoZTest then
  138. begin
  139. depth := CurrentBuffer.GetPixelDepth(Round(ScreenPos.X),
  140. Round(rci.viewPortSize.cy - ScreenPos.Y));
  141. // but is it behind something?
  142. if screenPos.Z >= 1 then
  143. flag := (depth >= 1)
  144. else
  145. flag := (depth >= screenPos.Z);
  146. end
  147. else
  148. flag := True;
  149. end
  150. else
  151. flag := False;
  152. end
  153. else
  154. flag := False;
  155. MakeVector(posVector,
  156. screenPos.X - rci.viewPortSize.cx / 2,
  157. screenPos.Y - rci.viewPortSize.cy / 2, 0);
  158. // make the glow appear/disappear progressively
  159. if Flag then
  160. if FCurrSize < FSize then
  161. FCurrSize := FCurrSize + FDeltaTime * 200 {FSize * 4};
  162. if not Flag then
  163. if FCurrSize > 0 then
  164. FCurrSize := FCurrSize - FDeltaTime * 200 {FSize * 4};
  165. if FCurrSize <= 0 then
  166. Exit;
  167. // Prepare matrices
  168. glMatrixMode(GL_MODELVIEW);
  169. glPushMatrix;
  170. glLoadMatrixf(@CurrentBuffer.BaseProjectionMatrix);
  171. glMatrixMode(GL_PROJECTION);
  172. glPushMatrix;
  173. glLoadIdentity;
  174. glScalef(2 / rci.viewPortSize.cx, 2 / rci.viewPortSize.cy, 1);
  175. rci.gxStates.Disable(stLighting);
  176. rci.gxStates.Disable(stDepthTest);
  177. rci.gxStates.Enable(stBlend);
  178. rci.gxStates.SetBlendFunc(bfOne, bfOne);
  179. //Rays and Glow on Same Position
  180. glPushMatrix;
  181. glTranslatef(posVector.X, posVector.Y, posVector.Z);
  182. if not ImgGlow.Disabled and Assigned(ImgGlow.Image) then
  183. begin
  184. ImgGlow.Apply(rci);
  185. glBegin(GL_QUADS);
  186. glTexCoord2f(0, 0);
  187. glVertex3f(-FCurrSize, -FCurrSize, 0);
  188. glTexCoord2f(1, 0);
  189. glVertex3f(FCurrSize, -FCurrSize, 0);
  190. glTexCoord2f(1, 1);
  191. glVertex3f(FCurrSize, FCurrSize, 0);
  192. glTexCoord2f(0, 1);
  193. glVertex3f(-FCurrSize, FCurrSize, 0);
  194. glEnd;
  195. ImgGlow.UnApply(rci);
  196. end;
  197. if not ImgRays.Disabled and Assigned(ImgRays.Image) then
  198. begin
  199. ImgRays.Apply(rci);
  200. glBegin(GL_QUADS);
  201. glTexCoord2f(0, 0);
  202. glVertex3f(-FCurrSize, -FCurrSize, 0);
  203. glTexCoord2f(1, 0);
  204. glVertex3f(FCurrSize, -FCurrSize, 0);
  205. glTexCoord2f(1, 1);
  206. glVertex3f(FCurrSize, FCurrSize, 0);
  207. glTexCoord2f(0, 1);
  208. glVertex3f(-FCurrSize, FCurrSize, 0);
  209. glEnd;
  210. ImgRays.UnApply(rci);
  211. end;
  212. glPopMatrix;
  213. if not ImgRing.Disabled and Assigned(ImgRing.Image) then
  214. begin
  215. glPushMatrix;
  216. glTranslatef(posVector.X * 1.1, posVector.Y * 1.1, posVector.Z);
  217. ImgRing.Apply(rci);
  218. glBegin(GL_QUADS);
  219. glTexCoord2f(0, 0);
  220. glVertex3f(-FCurrSize, -FCurrSize, 0);
  221. glTexCoord2f(1, 0);
  222. glVertex3f(FCurrSize, -FCurrSize, 0);
  223. glTexCoord2f(1, 1);
  224. glVertex3f(FCurrSize, FCurrSize, 0);
  225. glTexCoord2f(0, 1);
  226. glVertex3f(-FCurrSize, FCurrSize, 0);
  227. glEnd;
  228. ImgRing.UnApply(rci);
  229. glPopMatrix;
  230. end;
  231. if not ImgSecondaries.Disabled and Assigned(ImgSecondaries.Image) then
  232. begin
  233. RandSeed := FSeed;
  234. glPushMatrix;
  235. ImgSecondaries.Apply(rci);
  236. for i := 1 to FNumSecs do
  237. begin
  238. rnd := 2 * Random - 1;
  239. v := PosVector;
  240. if rnd < 0 then
  241. ScaleVector(V, rnd)
  242. else
  243. ScaleVector(V, 0.8 * rnd);
  244. glPushMatrix;
  245. glTranslatef(v.X, v.Y, v.Z);
  246. rnd := random * 0.5 + 0.1;
  247. glBegin(GL_QUADS);
  248. glTexCoord2f(0, 0);
  249. glVertex3f(-FCurrSize * rnd, -FCurrSize * rnd, 0);
  250. glTexCoord2f(1, 0);
  251. glVertex3f(FCurrSize * rnd, -FCurrSize * rnd, 0);
  252. glTexCoord2f(1, 1);
  253. glVertex3f(FCurrSize * rnd, FCurrSize * rnd, 0);
  254. glTexCoord2f(0, 1);
  255. glVertex3f(-FCurrSize * rnd, FCurrSize * rnd, 0);
  256. glEnd;
  257. glPopMatrix
  258. end;
  259. ImgSecondaries.UnApply(rci);
  260. glPopMatrix;
  261. end;
  262. // restore state
  263. glPopMatrix;
  264. glMatrixMode(GL_MODELVIEW);
  265. glPopMatrix;
  266. if Count > 0 then
  267. Self.RenderChildren(0, Count - 1, rci);
  268. end;
  269. procedure TgxTextureLensFlare.DoProgress(const progressTime: TgxProgressTimes);
  270. begin
  271. FDeltaTime := progressTime.deltaTime;
  272. inherited;
  273. end;
  274. procedure TgxTextureLensFlare.SetImgGlow(const Value: TgxTexture);
  275. begin
  276. FImgGlow.Assign(Value);
  277. StructureChanged;
  278. end;
  279. procedure TgxTextureLensFlare.SetImgRays(const Value: TgxTexture);
  280. begin
  281. FImgRays.Assign(Value);
  282. StructureChanged;
  283. end;
  284. procedure TgxTextureLensFlare.SetImgRing(const Value: TgxTexture);
  285. begin
  286. FImgRing.Assign(Value);
  287. StructureChanged;
  288. end;
  289. procedure TgxTextureLensFlare.SetImgSecondaries(const Value: TgxTexture);
  290. begin
  291. FImgSecondaries.Assign(Value);
  292. StructureChanged;
  293. end;
  294. destructor TgxTextureLensFlare.Destroy;
  295. begin
  296. FImgRays.Free;
  297. FImgSecondaries.Free;
  298. FImgRing.Free;
  299. FImgGlow.Free;
  300. inherited;
  301. end;
  302. procedure TgxTextureLensFlare.SetSeed(const Value: Integer);
  303. begin
  304. FSeed := Value;
  305. StructureChanged;
  306. end;
  307. // ------------------------------------------------------------------
  308. initialization
  309. // ------------------------------------------------------------------
  310. RegisterClasses([TgxTextureLensFlare]);
  311. end.