GXSL.PostShaders.pas 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262
  1. //
  2. // The graphics engine GLXEngine. The unit of GXScene for Delphi
  3. //
  4. unit GXSL.PostShaders;
  5. (* Post shaders that simulate shader visions for a mask or the entire scene *)
  6. interface
  7. {$I Stage.Defines.inc}
  8. uses
  9. System.Classes,
  10. GXS.Texture,
  11. GXS.Scene,
  12. Stage.VectorTypes,
  13. Stage.VectorGeometry,
  14. GXS.Context,
  15. GXS.Material,
  16. GXSL.Shader,
  17. GXSL.CustomShader,
  18. GXS.RenderContextInfo,
  19. Stage.TextureFormat;
  20. // Custom class for GLSLxPostBlurShader. A shader that blurs the entire scene }
  21. type
  22. TgxslCustomPostBlurShader = class(TgxslCustomShader, IgxPostShader)
  23. private
  24. FThreshold: Single;
  25. // Implementing IPostShader.
  26. procedure DoUseTempTexture(const TempTexture: TgxTextureHandle;
  27. TextureTarget: TglTextureTarget);
  28. function GetTextureTarget: TglTextureTarget;
  29. function StoreThreshold: Boolean;
  30. protected
  31. procedure DoApply(var rci: TgxRenderContextInfo; Sender: TObject); override;
  32. function DoUnApply(var rci: TgxRenderContextInfo): Boolean; override;
  33. public
  34. constructor Create(AOwner: TComponent); override;
  35. property Threshold: Single read FThreshold write FThreshold stored StoreThreshold;
  36. end;
  37. TgxslPostBlurShader = class(TgxslCustomPostBlurShader)
  38. published
  39. property Threshold;
  40. end;
  41. // A shader that simulate a Thermal Vision of the entire scene
  42. TgxslCustomPostThermalVisionShader = class(TgxslCustomShader, IgxPostShader)
  43. private
  44. FThreshold : Single;
  45. Fintensity : Single;
  46. // Implementing IPostShader.
  47. procedure DoUseTempTexture(const TempTexture: TgxTextureHandle;TextureTarget: TglTextureTarget);
  48. function GetTextureTarget: TglTextureTarget;
  49. function StoreThreshold: Boolean;
  50. function StoreIntensity: Boolean;
  51. protected
  52. procedure DoApply(var rci: TgxRenderContextInfo; Sender: TObject); override;
  53. function DoUnApply(var rci: TgxRenderContextInfo): Boolean; override;
  54. public
  55. constructor Create(AOwner: TComponent); override;
  56. property Threshold: Single read FThreshold write FThreshold stored StoreThreshold;
  57. property Intensity: Single read FIntensity write FIntensity stored StoreIntensity;
  58. end;
  59. TgxslPostThermalVisionShader = class(TgxslCustomPostThermalVisionShader)
  60. published
  61. property Threshold;
  62. property Intensity;
  63. end;
  64. // A shader that simulate a grayscale threshold vision (aka dream) of the entire scene
  65. TgxslCustomPostDreamVisionShader = class(TgxslCustomShader, IgxPostShader)
  66. private
  67. FThreshold : Single; // In percent 0..100;
  68. // Implementing IPostShader.
  69. procedure DoUseTempTexture(const TempTexture: TgxTextureHandle;TextureTarget: TglTextureTarget);
  70. function GetTextureTarget: TglTextureTarget;
  71. function StoreThreshold: Boolean;
  72. protected
  73. procedure DoApply(var rci: TgxRenderContextInfo; Sender: TObject); override;
  74. function DoUnApply(var rci: TgxRenderContextInfo): Boolean; override;
  75. public
  76. constructor Create(AOwner: TComponent); override;
  77. property Threshold: Single read FThreshold write FThreshold stored StoreThreshold;
  78. end;
  79. TgxSLPostDreamVisionShader = class(TgxslCustomPostDreamVisionShader)
  80. published
  81. property Threshold;
  82. end;
  83. (* Custom shader that simulate a Night Vision of the scene throw a mask if enabled,
  84. or of the entire scene *)
  85. TgxslCustomPostNightVisionShader = class(TgxslCustomShader, IgxPostShader)
  86. private
  87. FMaterialLibrary: TgxAbstractMaterialLibrary;
  88. FLuminanceThreshold: Single;
  89. FColorAmplification:Single;
  90. FElapsedTime : Single;
  91. FUseMask : Integer;
  92. FNoiseTex : TgxTexture;
  93. FMaskTex : TgxTexture;
  94. FNoiseTexName : TgxLibMaterialName;
  95. FMaskTexName : TgxLibMaterialName;
  96. procedure DoUseTempTexture(const TempTexture: TgxTextureHandle;TextureTarget: TglTextureTarget);
  97. function GetTextureTarget: TglTextureTarget;
  98. function StoreLuminanceThreshold: Boolean;
  99. function StoreColorAmplification: Boolean;
  100. procedure SetMaskTexTexture(const Value: TgxTexture);
  101. procedure SetNoiseTexTexture(const Value: TgxTexture);
  102. function GetNoiseTexName: TgxLibMaterialName;
  103. procedure SetNoiseTexName(const Value: TgxLibMaterialName);
  104. function GetMaskTexName: TgxLibMaterialName;
  105. procedure SetMaskTexName(const Value: TgxLibMaterialName);
  106. function GetMaterialLibrary: TgxAbstractMaterialLibrary;
  107. protected
  108. procedure DoApply(var rci: TgxRenderContextInfo; Sender: TObject); override;
  109. function DoUnApply(var rci: TgxRenderContextInfo): Boolean; override;
  110. procedure SetMaterialLibrary(const Value: TgxAbstractMaterialLibrary); virtual;
  111. procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  112. public
  113. constructor Create(AOwner: TComponent); override;
  114. property LuminanceThreshold: Single read FLuminanceThreshold write FLuminanceThreshold stored StoreLuminanceThreshold;
  115. property ColorAmplification: Single read FColorAmplification write FColorAmplification stored StoreColorAmplification;
  116. property ElapsedTime: Single read FElapsedTime write FElapsedTime stored false;
  117. property MaterialLibrary: TgxAbstractMaterialLibrary read getMaterialLibrary write SetMaterialLibrary;
  118. property NoiseTex: TgxTexture read FNoiseTex write SetNoiseTexTexture;
  119. property NoiseTexName: TgxLibMaterialName read GetNoiseTexName write SetNoiseTexName;
  120. property MaskTex: TgxTexture read FMaskTex write SetMaskTexTexture;
  121. property MaskTexName: TgxLibMaterialName read GetMaskTexName write SetMaskTexName;
  122. property UseMask : Integer read FUseMask write FUseMask;
  123. end;
  124. TgxslPostNightVisionShader = class(TgxslCustomPostNightVisionShader)
  125. published
  126. property LuminanceThreshold;
  127. property ColorAmplification;
  128. property ElapsedTime;
  129. property MaterialLibrary;
  130. property NoiseTexName;
  131. property MaskTexName;
  132. property UseMask;
  133. end;
  134. // Custom shader that pixelate of the entire scene
  135. TgxslCustomPostPixelateShader = class(TgxslCustomShader, IgxPostShader)
  136. private
  137. FPixelWidth : Single;
  138. FPixelHeight : Single;
  139. procedure DoUseTempTexture(const TempTexture: TgxTextureHandle;TextureTarget: TglTextureTarget);
  140. function GetTextureTarget: TglTextureTarget;
  141. function StorePixelWidth: Boolean;
  142. function StorePixelHeight: Boolean;
  143. protected
  144. procedure DoApply(var rci: TgxRenderContextInfo; Sender: TObject); override;
  145. function DoUnApply(var rci: TgxRenderContextInfo): Boolean; override;
  146. public
  147. constructor Create(AOwner: TComponent); override;
  148. property PixelWidth: Single read FPixelWidth write FPixelWidth stored StorePixelWidth;
  149. property PixelHeight: Single read FPixelHeight write FPixelHeight stored StorePixelHeight;
  150. end;
  151. TgxslPostPixelateShader = class(TgxslCustomPostPixelateShader)
  152. published
  153. property PixelWidth;
  154. property PixelHeight;
  155. end;
  156. // Custom shader that posterize of the entire scene
  157. TgxslCustomPostPosterizeShader = class(TgxslCustomShader, IgxPostShader)
  158. private
  159. FGamma : Single;
  160. FNumColors : Single;
  161. procedure DoUseTempTexture(const TempTexture: TgxTextureHandle;TextureTarget: TglTextureTarget);
  162. function GetTextureTarget: TglTextureTarget;
  163. function StoreGamma: Boolean;
  164. function StoreNumColors: Boolean;
  165. protected
  166. procedure DoApply(var rci: TgxRenderContextInfo; Sender: TObject); override;
  167. function DoUnApply(var rci: TgxRenderContextInfo): Boolean; override;
  168. public
  169. constructor Create(AOwner: TComponent); override;
  170. property Gamma: Single read FGamma write FGamma stored StoreGamma;
  171. property NumColors: Single read FNumColors write FNumColors stored StoreNumColors;
  172. end;
  173. TgxslPostPosterizeShader = class(TgxslCustomPostPosterizeShader)
  174. published
  175. property Gamma;
  176. property NumColors;
  177. end;
  178. // Custom class for shader that frost of the entire scene
  179. TgxslCustomPostFrostShader = class(TgxslCustomShader, IgxPostShader)
  180. private
  181. FRandScale : Single;
  182. FRandFactor : Single;
  183. procedure DoUseTempTexture(const TempTexture: TgxTextureHandle;TextureTarget: TglTextureTarget);
  184. function GetTextureTarget: TglTextureTarget;
  185. function StoreRandScale: Boolean;
  186. function StoreRandFactor: Boolean;
  187. protected
  188. procedure DoApply(var rci: TgxRenderContextInfo; Sender: TObject); override;
  189. function DoUnApply(var rci: TgxRenderContextInfo): Boolean; override;
  190. public
  191. constructor Create(AOwner: TComponent); override;
  192. property RandScale: Single read FRandScale write FRandScale stored StoreRandScale;
  193. property RandFactor: Single read FRandFactor write FRandFactor stored StoreRandFactor;
  194. end;
  195. TgxslPostFrostShader = class(TgxslCustomPostFrostShader)
  196. published
  197. property RandScale;
  198. property RandFactor;
  199. end;
  200. (* Custom class for GLSLPostTroubleShader.
  201. A shader that trouble of the entire scene. v2
  202. This Shader is experimental it can do smooth the scene or double the scene and it's
  203. depends of PixelX, PixelY and Freq values if they are less than 1 or greater
  204. the effects will be very different *)
  205. TgxslCustomPostTroubleShader = class(TgxslCustomShader, IgxPostShader)
  206. private
  207. FPixelX : Single;
  208. FPixelY : Single;
  209. FFreq : Single;
  210. FMaterialLibrary: TgxAbstractMaterialLibrary;
  211. FNoiseTex : TgxTexture;
  212. FNoiseTexName : TgxLibMaterialName;
  213. procedure DoUseTempTexture(const TempTexture: TgxTextureHandle;TextureTarget: TglTextureTarget);
  214. function GetTextureTarget: TglTextureTarget;
  215. procedure SetNoiseTexTexture(const Value: TgxTexture);
  216. function GetNoiseTexName: TgxLibMaterialName;
  217. procedure SetNoiseTexName(const Value: TgxLibMaterialName);
  218. function GetMaterialLibrary: TgxAbstractMaterialLibrary;
  219. function StorePixelX: Boolean;
  220. function StorePixelY: Boolean;
  221. function StoreFreq: Boolean;
  222. protected
  223. procedure DoApply(var rci: TgxRenderContextInfo; Sender: TObject); override;
  224. function DoUnApply(var rci: TgxRenderContextInfo): Boolean; override;
  225. procedure SetMaterialLibrary(const Value: TgxAbstractMaterialLibrary); virtual;
  226. procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  227. public
  228. constructor Create(AOwner: TComponent); override;
  229. property PixelX: Single read FPixelX write FPixelX stored StorePixelX;
  230. property PixelY: Single read FPixelY write FPixelY stored StorePixelY;
  231. property Freq: Single read FFreq write FFreq stored StoreFreq;
  232. property MaterialLibrary: TgxAbstractMaterialLibrary read getMaterialLibrary write SetMaterialLibrary;
  233. property NoiseTex: TgxTexture read FNoiseTex write SetNoiseTexTexture;
  234. property NoiseTexName: TgxLibMaterialName read GetNoiseTexName write SetNoiseTexName;
  235. end;
  236. TgxslPostTroubleShader = class(TgxslCustomPostTroubleShader)
  237. published
  238. property PixelX;
  239. property PixelY;
  240. property Freq;
  241. property MaterialLibrary;
  242. property NoiseTexName;
  243. end;
  244. //----------------------------------------------------------------------
  245. implementation
  246. //----------------------------------------------------------------------
  247. //-------------------------------------
  248. // TgxslCustomPostBlurShader
  249. //-------------------------------------
  250. constructor TgxslCustomPostBlurShader.Create(
  251. AOwner: TComponent);
  252. begin
  253. inherited;
  254. with VertexProgram.Code do
  255. begin
  256. Add('varying vec2 vTexCoord; ');
  257. Add(' ');
  258. Add('void main(void) ');
  259. Add('{ ');
  260. Add(' ');
  261. Add(' // Clean up inaccuracies ');
  262. Add(' vec2 Position; ');
  263. Add(' Position.xy = sign(gl_Vertex.xy); ');
  264. Add(' ');
  265. Add(' gl_Position = vec4(Position.xy, 0.0, 1.0); ');
  266. Add(' vTexCoord = Position.xy *.5 + .5; ');
  267. Add(' ');
  268. Add('} ');
  269. end;
  270. with FragmentProgram.Code do
  271. begin
  272. Add('uniform float threshold; ');
  273. Add('uniform vec2 ScreenExtents; ');
  274. Add('uniform sampler2DRect Image; ');
  275. Add(' ');
  276. Add('varying vec2 vTexCoord; ');
  277. Add(' ');
  278. Add('void main() ');
  279. Add('{ ');
  280. Add(' ');
  281. Add(' vec2 samples[8]; ');
  282. Add(' vec2 vTexCoordScr = vTexCoord * ScreenExtents; ');
  283. Add(' ');
  284. Add(' samples[0] = vTexCoordScr + vec2(-1.0, -1.0); ');
  285. Add(' samples[1] = vTexCoordScr + vec2( 0.0, -1.0); ');
  286. Add(' samples[2] = vTexCoordScr + vec2( 1.0, -1.0); ');
  287. Add(' samples[3] = vTexCoordScr + vec2(-1.0, 0.0); ');
  288. Add(' samples[4] = vTexCoordScr + vec2( 1.0, 0.0); ');
  289. Add(' samples[5] = vTexCoordScr + vec2(-1.0, 1.0); ');
  290. Add(' samples[6] = vTexCoordScr + vec2( 0.0, 1.0); ');
  291. Add(' samples[7] = vTexCoordScr + vec2( 1.0, 1.0); ');
  292. Add(' ');
  293. Add(' vec4 sample = texture2DRect(Image, vTexCoordScr); ');
  294. Add(' ');
  295. Add(' // Neighborhood average ');
  296. Add(' vec4 avg = sample; ');
  297. Add(' for (int i = 0; i < 8; i++) ');
  298. Add(' { ');
  299. Add(' avg += texture2DRect(Image, samples[i]); ');
  300. Add(' } ');
  301. Add(' ');
  302. Add(' ');
  303. Add(' avg /= 9.0; ');
  304. Add(' ');
  305. Add(' // If the difference between the average and the sample is ');
  306. Add(' // large, we''ll assume it''s noise. ');
  307. Add(' vec4 diff = abs(sample - avg); ');
  308. Add(' float sel = float(dot(diff, vec4(0.25)) > threshold); ');
  309. Add(' ');
  310. Add(' gl_FragColor = mix(sample, avg, sel); ');
  311. Add('} ');
  312. end;
  313. FThreshold := 0.1;
  314. end;
  315. procedure TgxslCustomPostBlurShader.DoApply(
  316. var rci: TgxRenderContextInfo; Sender: TObject);
  317. begin
  318. GetGXSLProg.UseProgramObject;
  319. GetGXSLProg.Uniform1f['threshold'] := FThreshold;
  320. GetGXSLProg.Uniform2f['ScreenExtents'] := Vector2fMake(rci.viewPortSize.cx, rci.viewPortSize.cy);
  321. end;
  322. function TgxslCustomPostBlurShader.DoUnApply(
  323. var rci: TgxRenderContextInfo): Boolean;
  324. begin
  325. rci.gxStates.ActiveTexture := 0;
  326. GetGXSLProg.EndUseProgramObject;
  327. Result := False;
  328. end;
  329. procedure TgxslCustomPostBlurShader.DoUseTempTexture(
  330. const TempTexture: TgxTextureHandle; TextureTarget: TglTextureTarget);
  331. begin
  332. Param['Image'].AsCustomTexture[2, TextureTarget] := TempTexture.Handle;
  333. end;
  334. function TgxslCustomPostBlurShader.GetTextureTarget: TglTextureTarget;
  335. begin
  336. Result := ttTextureRect;
  337. end;
  338. function TgxslCustomPostBlurShader.StoreThreshold: Boolean;
  339. begin
  340. Result := Abs(FThreshold - 0.1) > 0.00001;
  341. end;
  342. //-------------------------------------------
  343. // TgxslCustomPostThermalVisionShader
  344. //-------------------------------------------
  345. constructor TgxslCustomPostThermalVisionShader.Create(
  346. AOwner: TComponent);
  347. begin
  348. inherited;
  349. with VertexProgram.Code do
  350. begin
  351. Add('varying vec2 vTexCoord; ');
  352. Add(' ');
  353. Add('void main(void) ');
  354. Add('{ ');
  355. Add(' ');
  356. Add(' // Clean up inaccuracies ');
  357. Add(' vec2 Position; ');
  358. Add(' Position.xy = sign(gl_Vertex.xy); ');
  359. Add(' ');
  360. Add(' gl_Position = vec4(Position.xy, 0.0, 1.0); ');
  361. Add(' vTexCoord = Position.xy *.5 + .5; ');
  362. Add(' ');
  363. Add('} ');
  364. end;
  365. with FragmentProgram.Code do
  366. begin
  367. Add('uniform float Threshold; ');
  368. Add('uniform float Intensity; ');
  369. Add('uniform vec2 ScreenExtents; ');
  370. Add('uniform sampler2DRect ScreenTex; ');
  371. Add(' ');
  372. Add('varying vec2 vTexCoord; ');
  373. Add(' ');
  374. Add('void main() ');
  375. Add('{ ');
  376. Add(' vec2 uv = vTexCoord * ScreenExtents; ');
  377. Add(' vec3 tc = vec3(1.0, 0.0, 0.0);');
  378. Add(' vec3 pixcol = texture2DRect(ScreenTex, uv).rgb; ');
  379. Add(' vec3 colors[3];');
  380. Add(' colors[0] = vec3(0.,0.,1.); ');
  381. Add(' colors[1] = vec3(1.,1.,0.); ');
  382. Add(' colors[2] = vec3(1.,0.,0.); ');
  383. Add(' float lum = dot(vec3(0.30, 0.59, 0.11), pixcol.rgb); ');
  384. Add('// float lum = (pixcol.r+pixcol.g+pixcol.b)/3.;');
  385. Add(' tc = (lum < 0.5)? mix(colors[0],colors[1],lum/Threshold): mix(colors[1],colors[2],(lum-Intensity)/Threshold); ');
  386. Add(' gl_FragColor = vec4(tc, 1); ');
  387. Add('} ');
  388. end;
  389. FThreshold := 0.5;
  390. FIntensity := 0.5;
  391. end;
  392. procedure TgxslCustomPostThermalVisionShader.DoApply(
  393. var rci: TgxRenderContextInfo; Sender: TObject);
  394. begin
  395. GetGXSLProg.UseProgramObject;
  396. GetGXSLProg.Uniform1f['Threshold'] := FThreshold;
  397. GetGXSLProg.Uniform1f['Intensity'] := FIntensity;
  398. GetGXSLProg.Uniform2f['ScreenExtents'] := Vector2fMake(rci.viewPortSize.cx, rci.viewPortSize.cy);
  399. end;
  400. function TgxslCustomPostThermalVisionShader.DoUnApply(
  401. var rci: TgxRenderContextInfo): Boolean;
  402. begin
  403. rci.gxStates.ActiveTexture := 0;
  404. GetGXSLProg.EndUseProgramObject;
  405. Result := False;
  406. end;
  407. procedure TgxslCustomPostThermalVisionShader.DoUseTempTexture(
  408. const TempTexture: TgxTextureHandle; TextureTarget: TglTextureTarget);
  409. begin
  410. Param['ScreenTex'].AsCustomTexture[3, TextureTarget] := TempTexture.Handle;
  411. end;
  412. function TgxslCustomPostThermalVisionShader.GetTextureTarget: TglTextureTarget;
  413. begin
  414. Result := ttTextureRect; //ttTexture2D;
  415. end;
  416. function TgxslCustomPostThermalVisionShader.StoreThreshold: Boolean;
  417. begin
  418. Result := (Abs(FThreshold) > 0) and (Abs(FThreshold) <= 1.0);
  419. end;
  420. function TgxslCustomPostThermalVisionShader.StoreIntensity: Boolean;
  421. begin
  422. Result := (Abs(FIntensity) >= 0) and (Abs(FIntensity) <= 2.0);
  423. end;
  424. { TgxslCustomPostThermalVisionShader }
  425. constructor TgxslCustomPostDreamVisionShader.Create(
  426. AOwner: TComponent);
  427. begin
  428. inherited;
  429. with VertexProgram.Code do
  430. begin
  431. Add('varying vec2 vTexCoord; ');
  432. Add(' ');
  433. Add('void main(void) ');
  434. Add('{ ');
  435. Add(' ');
  436. Add(' // Clean up inaccuracies ');
  437. Add(' vec2 Position; ');
  438. Add(' Position.xy = sign(gl_Vertex.xy); ');
  439. Add(' ');
  440. Add(' gl_Position = vec4(Position.xy, 0.0, 1.0); ');
  441. Add(' vTexCoord = Position.xy *.5 + .5; ');
  442. Add(' ');
  443. Add('} ');
  444. end;
  445. with FragmentProgram.Code do
  446. begin
  447. Add('uniform float Threshold; ');
  448. Add('uniform vec2 ScreenExtents; ');
  449. Add('uniform sampler2DRect ScreenTex; ');
  450. Add(' ');
  451. Add('varying vec2 vTexCoord; ');
  452. Add(' ');
  453. Add('void main() ');
  454. Add('{ ');
  455. Add(' vec2 uv = vTexCoord * ScreenExtents; ');
  456. Add(' vec3 c = texture2DRect(ScreenTex, uv).rgb; ');
  457. Add(' c += texture2DRect(ScreenTex, uv+0.001).rgb; ');
  458. Add(' c += texture2DRect(ScreenTex, uv+0.003).rgb; ');
  459. Add(' c += texture2DRect(ScreenTex, uv+0.005).rgb; ');
  460. Add(' c += texture2DRect(ScreenTex, uv+0.007).rgb; ');
  461. Add(' c += texture2DRect(ScreenTex, uv+0.009).rgb; ');
  462. Add(' c += texture2DRect(ScreenTex, uv+0.011).rgb; ');
  463. Add(' ');
  464. Add(' c += texture2DRect(ScreenTex, uv-0.001).rgb; ');
  465. Add(' c += texture2DRect(ScreenTex, uv-0.003).rgb; ');
  466. Add(' c += texture2DRect(ScreenTex, uv-0.005).rgb; ');
  467. Add(' c += texture2DRect(ScreenTex, uv-0.007).rgb; ');
  468. Add(' c += texture2DRect(ScreenTex, uv-0.009).rgb; ');
  469. Add(' c += texture2DRect(ScreenTex, uv-0.011).rgb; ');
  470. Add(' ');
  471. Add(' c.rgb = vec3((c.r+c.g+c.b)/3.0); ');
  472. Add(' c = c / Threshold; ');
  473. Add(' gl_FragColor = vec4(c,1.0); ');
  474. Add('} ');
  475. end;
  476. FThreshold := 5;
  477. end;
  478. procedure TgxslCustomPostDreamVisionShader.DoApply(
  479. var rci: TgxRenderContextInfo; Sender: TObject);
  480. begin
  481. GetGXSLProg.UseProgramObject;
  482. GetGXSLProg.Uniform1f['Threshold'] := (FThreshold*255)/100;
  483. GetGXSLProg.Uniform2f['ScreenExtents'] := Vector2fMake(rci.viewPortSize.cx, rci.viewPortSize.cy);
  484. end;
  485. function TgxslCustomPostDreamVisionShader.DoUnApply(
  486. var rci: TgxRenderContextInfo): Boolean;
  487. begin
  488. rci.gxStates.ActiveTexture := 0;
  489. GetGXSLProg.EndUseProgramObject;
  490. Result := False;
  491. end;
  492. procedure TgxslCustomPostDreamVisionShader.DoUseTempTexture(
  493. const TempTexture: TgxTextureHandle; TextureTarget: TglTextureTarget);
  494. begin
  495. Param['ScreenTex'].AsCustomTexture[2, TextureTarget] := TempTexture.Handle;
  496. end;
  497. function TgxslCustomPostDreamVisionShader.GetTextureTarget: TglTextureTarget;
  498. begin
  499. Result := ttTextureRect; //ttTexture2D;
  500. end;
  501. function TgxslCustomPostDreamVisionShader.StoreThreshold: Boolean;
  502. begin
  503. Result := (Abs(FThreshold) > 0) and (Abs(FThreshold) <= 100);
  504. end;
  505. // TgxslCustomPostThermalVisionShader
  506. constructor TgxslCustomPostNightVisionShader.Create(
  507. AOwner: TComponent);
  508. begin
  509. inherited;
  510. with VertexProgram.Code do
  511. begin
  512. Add('varying vec2 vTexCoord; ');
  513. Add(' ');
  514. Add('void main(void) ');
  515. Add('{ ');
  516. Add(' ');
  517. Add(' // Clean up inaccuracies ');
  518. Add(' vec2 Position; ');
  519. Add(' Position.xy = sign(gl_Vertex.xy); ');
  520. Add(' ');
  521. Add(' gl_Position = vec4(Position.xy, 0.0, 1.0); ');
  522. Add(' vTexCoord = Position.xy *.5 + .5; ');
  523. Add(' ');
  524. Add('} ');
  525. end;
  526. with FragmentProgram.Code do
  527. begin
  528. Add('uniform float luminanceThreshold; ');
  529. Add('uniform float colorAmplification; ');
  530. Add('uniform float elapsedTime; ');
  531. Add('uniform int useMask;');
  532. Add('uniform vec2 ScreenExtents; ');
  533. Add('uniform sampler2D noiseTex; ');
  534. Add('uniform sampler2D maskTex; ');
  535. Add('uniform sampler2DRect ScreenTex; ');
  536. Add(' ');
  537. Add('varying vec2 vTexCoord; ');
  538. Add(' ');
  539. Add('void main () ');
  540. Add('{ ');
  541. Add(' vec2 uv = vTexCoord * ScreenExtents; ');
  542. Add(' vec4 finalColor; ');
  543. Add(' vec2 uvv; ');
  544. Add(' uvv.x = 0.4*sin(elapsedTime*50.0); ');
  545. Add(' uvv.y = 0.4*cos(elapsedTime*50.0); ');
  546. Add(' float m = 1; ');
  547. Add(' if (useMask==1) { m = texture2D(maskTex, vTexCoord.st).r; } '); // Problem Here I don't know how to solve ????
  548. Add(' vec3 n = texture2D(noiseTex,(uv.st*3.5) + uvv).rgb; ');
  549. Add(' vec3 c = texture2DRect(ScreenTex, uv.st+(n.xy*0.005)).rgb; ');
  550. Add(' float lum = dot(vec3(0.30, 0.59, 0.11), c); ');
  551. Add(' if (lum < luminanceThreshold) ');
  552. Add(' c *= colorAmplification; ');
  553. Add(' vec3 visionColor = vec3(0.1, 0.95, 0.2); ');
  554. Add(' finalColor.rgb = (c + (n*0.2)) * visionColor * m; ');
  555. Add(' ');
  556. Add(' gl_FragColor.rgb = finalColor.rgb; ');
  557. Add(' gl_FragColor.a = 1.0; ');
  558. Add('} ');
  559. end;
  560. FLuminanceThreshold := 0.2;
  561. FColorAmplification := 4.0;
  562. FElapsedTime:=0.1;
  563. FUseMask:=0; // Shader not working if we want to use mask
  564. end;
  565. procedure TgxslCustomPostNightVisionShader.DoApply(var rci: TgxRenderContextInfo; Sender: TObject);
  566. begin
  567. GetGXSLProg.UseProgramObject;
  568. param['luminanceThreshold'].AsVector1f := FLuminanceThreshold;
  569. param['colorAmplification'].AsVector1f := FColorAmplification;
  570. param['elapsedTime'].AsVector1f := FElapsedTime;
  571. param['useMask'].AsVector1i := FUseMask;
  572. param['ScreenExtents'].AsVector2f := Vector2fMake(rci.viewPortSize.cx, rci.viewPortSize.cy);
  573. param['noiseTex'].AsTexture2D[1]:= FNoiseTex;
  574. param['maskTex'].AsTexture2D[2]:= FMaskTex;
  575. end;
  576. function TgxslCustomPostNightVisionShader.DoUnApply(
  577. var rci: TgxRenderContextInfo): Boolean;
  578. begin
  579. rci.gxStates.ActiveTexture := 0;
  580. GetGXSLProg.EndUseProgramObject;
  581. Result := False;
  582. end;
  583. procedure TgxslCustomPostNightVisionShader.DoUseTempTexture(
  584. const TempTexture: TgxTextureHandle; TextureTarget: TglTextureTarget);
  585. begin
  586. Param['ScreenTex'].AsCustomTexture[7, TextureTarget] := TempTexture.Handle;
  587. end;
  588. function TgxslCustomPostNightVisionShader.GetTextureTarget: TglTextureTarget;
  589. begin
  590. Result := ttTextureRect; //ttTexture2D;
  591. end;
  592. function TgxslCustomPostNightVisionShader.StoreLuminanceThreshold: Boolean;
  593. begin
  594. Result := Abs(FLuminanceThreshold - 0.1) > 0.00001;
  595. end;
  596. function TgxslCustomPostNightVisionShader.StoreColorAmplification: Boolean;
  597. begin
  598. Result := Abs(FColorAmplification - 0.1) > 0.00001;
  599. end;
  600. procedure TgxslCustomPostNightVisionShader.SetMaskTexTexture(const Value: TgxTexture);
  601. begin
  602. if FMaskTex = Value then Exit;
  603. MaskTex := Value;
  604. NotifyChange(Self)
  605. end;
  606. procedure TgxslCustomPostNightVisionShader.SetNoiseTexTexture(const Value: TgxTexture);
  607. begin
  608. if FNoiseTex = Value then Exit;
  609. NoiseTex := Value;
  610. NotifyChange(Self);
  611. end;
  612. function TgxslCustomPostNightVisionShader.GetNoiseTexName: TgxLibMaterialName;
  613. begin
  614. Result := TgxMaterialLibrary(FMaterialLibrary).GetNameOfTexture(FNoiseTex);
  615. if Result = '' then Result := FNoiseTexName;
  616. end;
  617. procedure TgxslCustomPostNightVisionShader.SetNoiseTexName(const Value: TgxLibMaterialName);
  618. begin
  619. //Assert(not(assigned(FMaterialLibrary)),'You must set Material Library Before');
  620. if FNoiseTexName = Value then Exit;
  621. FNoiseTexName := Value;
  622. FNoiseTex := TgxMaterialLibrary(FMaterialLibrary).TextureByName(FNoiseTexName);
  623. NotifyChange(Self);
  624. end;
  625. function TgxslCustomPostNightVisionShader.GetMaskTexName: TgxLibMaterialName;
  626. begin
  627. Result := TgxMaterialLibrary(FMaterialLibrary).GetNameOfTexture(FMaskTex);
  628. if Result = '' then Result := FMaskTexName;
  629. end;
  630. procedure TgxslCustomPostNightVisionShader.SetMaskTexName(const Value: TgxLibMaterialName);
  631. begin
  632. // Assert(not(assigned(FMaterialLibrary)),'You must set Material Library Before');
  633. if FMaskTexName = Value then Exit;
  634. FMaskTexName := Value;
  635. FMaskTex := TgxMaterialLibrary(FMaterialLibrary).TextureByName(FMaskTexName);
  636. NotifyChange(Self);
  637. end;
  638. function TgxslCustomPostNightVisionShader.GetMaterialLibrary: TgxAbstractMaterialLibrary;
  639. begin
  640. Result := FMaterialLibrary;
  641. end;
  642. procedure TgxslCustomPostNightVisionShader.SetMaterialLibrary(const Value: TgxAbstractMaterialLibrary);
  643. begin
  644. if FMaterialLibrary <> nil then FMaterialLibrary.RemoveFreeNotification(Self);
  645. FMaterialLibrary := Value;
  646. if (FMaterialLibrary <> nil)
  647. and (FMaterialLibrary is TgxAbstractMaterialLibrary) then
  648. FMaterialLibrary.FreeNotification(Self);
  649. end;
  650. procedure TgxslCustomPostNightVisionShader.Notification(AComponent: TComponent; Operation: TOperation);
  651. var
  652. Index: Integer;
  653. begin
  654. inherited;
  655. if Operation = opRemove then
  656. if AComponent = FMaterialLibrary then
  657. if FMaterialLibrary <> nil then
  658. begin
  659. // Need to nil the textures that were owned by it
  660. if FNoiseTex <> nil then
  661. begin
  662. Index := TgxMaterialLibrary(FMaterialLibrary).Materials.GetTextureIndex(FNoiseTex);
  663. if Index <> -1 then
  664. SetNoiseTexTexture(nil);
  665. end;
  666. if FMaskTex <> nil then
  667. begin
  668. Index := TgxMaterialLibrary(FMaterialLibrary).Materials.GetTextureIndex(FMaskTex);
  669. if Index <> -1 then
  670. SetMaskTexTexture(nil);
  671. end;
  672. FMaterialLibrary := nil;
  673. end;
  674. end;
  675. //----------------------------------------
  676. // TgxslCustomPostPixelateShader
  677. //----------------------------------------
  678. constructor TgxslCustomPostPixelateShader.Create(
  679. AOwner: TComponent);
  680. begin
  681. inherited;
  682. with VertexProgram.Code do
  683. begin
  684. Add('varying vec2 vTexCoord; ');
  685. Add(' ');
  686. Add('void main(void) ');
  687. Add('{ ');
  688. Add(' ');
  689. Add(' // Clean up inaccuracies ');
  690. Add(' vec2 Position; ');
  691. Add(' Position.xy = sign(gl_Vertex.xy); ');
  692. Add(' ');
  693. Add(' gl_Position = vec4(Position.xy, 0.0, 1.0); ');
  694. Add(' vTexCoord = Position.xy *.5 + .5; ');
  695. Add(' ');
  696. Add('} ');
  697. end;
  698. with FragmentProgram.Code do
  699. begin
  700. Add('uniform float pixel_w; // 8.0 ');
  701. Add('uniform float pixel_h; // 8.0 ');
  702. Add('uniform vec2 ScreenExtents; ');
  703. Add('uniform sampler2DRect ScreenTex; ');
  704. Add(' ');
  705. Add('varying vec2 vTexCoord; ');
  706. Add(' ');
  707. Add('void main() ');
  708. Add('{ ');
  709. Add(' vec2 uv = vTexCoord * ScreenExtents; ');
  710. Add(' vec3 tc = vec3(1.0, 0.0, 0.0); ');
  711. Add(' vec2 coord = vec2(pixel_w*floor(uv.x/pixel_w),pixel_h*floor(uv.y/pixel_h)); ');
  712. Add(' tc = texture2DRect(ScreenTex, coord).rgb; ');
  713. Add(' gl_FragColor = vec4(tc, 1); ');
  714. Add('} ');
  715. end;
  716. FPixelWidth := 8;
  717. FPixelHeight := 12;
  718. end;
  719. procedure TgxslCustomPostPixelateShader.DoApply(
  720. var rci: TgxRenderContextInfo; Sender: TObject);
  721. begin
  722. GetGXSLProg.UseProgramObject;
  723. GetGXSLProg.Uniform1f['pixel_w'] := FPixelWidth;
  724. GetGXSLProg.Uniform1f['pixel_h'] := FPixelHeight;
  725. GetGXSLProg.Uniform2f['ScreenExtents'] := Vector2fMake(rci.viewPortSize.cx, rci.viewPortSize.cy);
  726. end;
  727. function TgxslCustomPostPixelateShader.DoUnApply(
  728. var rci: TgxRenderContextInfo): Boolean;
  729. begin
  730. rci.gxStates.ActiveTexture := 0;
  731. GetGXSLProg.EndUseProgramObject;
  732. Result := False;
  733. end;
  734. procedure TgxslCustomPostPixelateShader.DoUseTempTexture(
  735. const TempTexture: TgxTextureHandle; TextureTarget: TglTextureTarget);
  736. begin
  737. Param['ScreenTex'].AsCustomTexture[3, TextureTarget] := TempTexture.Handle;
  738. end;
  739. function TgxslCustomPostPixelateShader.GetTextureTarget: TglTextureTarget;
  740. begin
  741. Result := ttTextureRect; //ttTexture2D;
  742. end;
  743. function TgxslCustomPostPixelateShader.StorePixelWidth: Boolean;
  744. begin
  745. Result := (Abs(FPixelWidth) > 0) and (Abs(FPixelWidth) <= 64);
  746. end;
  747. function TgxslCustomPostPixelateShader.StorePixelHeight: Boolean;
  748. begin
  749. Result := (Abs(FPixelHeight) > 0) and (Abs(FPixelHeight) <= 64);
  750. end;
  751. { TgxslCustomPostPosterizeShader }
  752. constructor TgxslCustomPostPosterizeShader.Create(
  753. AOwner: TComponent);
  754. begin
  755. inherited;
  756. with VertexProgram.Code do
  757. begin
  758. Add('varying vec2 vTexCoord; ');
  759. Add(' ');
  760. Add('void main(void) ');
  761. Add('{ ');
  762. Add(' ');
  763. Add(' // Clean up inaccuracies ');
  764. Add(' vec2 Position; ');
  765. Add(' Position.xy = sign(gl_Vertex.xy); ');
  766. Add(' ');
  767. Add(' gl_Position = vec4(Position.xy, 0.0, 1.0); ');
  768. Add(' vTexCoord = Position.xy *.5 + .5; ');
  769. Add(' ');
  770. Add('} ');
  771. end;
  772. with FragmentProgram.Code do
  773. begin
  774. Add('uniform float gamma; // 8.0 ');
  775. Add('uniform float numColors; // 8.0 ');
  776. Add('uniform vec2 ScreenExtents; ');
  777. Add('uniform sampler2DRect ScreenTex; ');
  778. Add(' ');
  779. Add('varying vec2 vTexCoord; ');
  780. Add(' ');
  781. Add('void main() ');
  782. Add('{ ');
  783. Add(' vec2 uv = vTexCoord * ScreenExtents; ');
  784. Add(' vec3 c = texture2DRect(ScreenTex, uv.xy).rgb; ');
  785. Add(' c = pow(c, vec3(gamma, gamma, gamma)); ');
  786. Add(' c = c * numColors; ');
  787. Add(' c = floor(c); ');
  788. Add(' c = c / numColors; ');
  789. Add(' c = pow(c, vec3(1.0/gamma)); ');
  790. Add(' gl_FragColor = vec4(c, 1.0); ');
  791. Add('} ');
  792. end;
  793. FGamma := 0.6;
  794. FNumColors := 8;
  795. end;
  796. procedure TgxslCustomPostPosterizeShader.DoApply(
  797. var rci: TgxRenderContextInfo; Sender: TObject);
  798. begin
  799. GetGXSLProg.UseProgramObject;
  800. GetGXSLProg.Uniform1f['gamma'] := FGamma;
  801. GetGXSLProg.Uniform1f['numColors'] := FNumColors;
  802. GetGXSLProg.Uniform2f['ScreenExtents'] := Vector2fMake(rci.viewPortSize.cx, rci.viewPortSize.cy);
  803. end;
  804. function TgxslCustomPostPosterizeShader.DoUnApply(
  805. var rci: TgxRenderContextInfo): Boolean;
  806. begin
  807. rci.gxStates.ActiveTexture := 0;
  808. GetGXSLProg.EndUseProgramObject;
  809. Result := False;
  810. end;
  811. procedure TgxslCustomPostPosterizeShader.DoUseTempTexture(
  812. const TempTexture: TgxTextureHandle; TextureTarget: TglTextureTarget);
  813. begin
  814. Param['ScreenTex'].AsCustomTexture[3, TextureTarget] := TempTexture.Handle;
  815. end;
  816. function TgxslCustomPostPosterizeShader.GetTextureTarget: TglTextureTarget;
  817. begin
  818. Result := ttTextureRect; //ttTexture2D;
  819. end;
  820. function TgxslCustomPostPosterizeShader.StoreGamma: Boolean;
  821. begin
  822. Result := (Abs(FGamma) > 0) and (Abs(FGamma) <= 3.0);
  823. end;
  824. function TgxslCustomPostPosterizeShader.StoreNumColors: Boolean;
  825. begin
  826. Result := (Abs(FNumColors) > 0) and (Abs(FNumColors) <= 255);
  827. end;
  828. { TgxslCustomPostFrostShader }
  829. constructor TgxslCustomPostFrostShader.Create(
  830. AOwner: TComponent);
  831. begin
  832. inherited;
  833. with VertexProgram.Code do
  834. begin
  835. Add('varying vec2 vTexCoord; ');
  836. Add(' ');
  837. Add('void main(void) ');
  838. Add('{ ');
  839. Add(' ');
  840. Add(' // Clean up inaccuracies ');
  841. Add(' vec2 Position; ');
  842. Add(' Position.xy = sign(gl_Vertex.xy); ');
  843. Add(' ');
  844. Add(' gl_Position = vec4(Position.xy, 0.0, 1.0); ');
  845. Add(' vTexCoord = Position.xy *.5 + .5; ');
  846. Add(' ');
  847. Add('} ');
  848. end;
  849. with FragmentProgram.Code do
  850. begin
  851. Add('uniform float rnd_scale; // 250 ');
  852. Add('uniform float rnd_factor; // 50 ');
  853. // Add('uniform vec2 v1; ');
  854. // Add('uniform vec2 v2; ');
  855. Add('uniform vec2 ScreenExtents; ');
  856. Add('uniform sampler2DRect ScreenTex; ');
  857. Add(' ');
  858. Add('varying vec2 vTexCoord; ');
  859. Add(' ');
  860. Add('float rand(vec2 co) ');
  861. Add('{ ');
  862. Add(' vec2 v1 = vec2(92.,80.); ');
  863. Add(' vec2 v2 = vec2(41.,62.); ');
  864. Add(' return fract(sin(dot(co.xy ,v1)) + cos(dot(co.xy ,v2)) * rnd_scale); ');
  865. Add('} ');
  866. Add(' ');
  867. Add('void main() ');
  868. Add('{ ');
  869. Add(' vec2 uv = vTexCoord * ScreenExtents; ');
  870. Add(' vec3 tc = vec3(1.0, 0.0, 0.0); ');
  871. Add(' vec2 rnd = vec2(rand(uv.xy),rand(uv.yx)); ');
  872. Add(' tc = texture2DRect(ScreenTex, uv+rnd*rnd_factor).rgb; ');
  873. Add(' gl_FragColor = vec4(tc, 1.0); ');
  874. Add('} ');
  875. end;
  876. FRandScale := 50;
  877. FRandFactor := 50;
  878. end;
  879. procedure TgxslCustomPostFrostShader.DoApply(
  880. var rci: TgxRenderContextInfo; Sender: TObject);
  881. begin
  882. GetGXSLProg.UseProgramObject;
  883. GetGXSLProg.Uniform1f['rnd_scale'] := FRandScale;
  884. GetGXSLProg.Uniform1f['rnd_factor'] := FRandFactor;
  885. GetGXSLProg.Uniform2f['ScreenExtents'] := Vector2fMake(rci.viewPortSize.cx, rci.viewPortSize.cy);
  886. end;
  887. function TgxslCustomPostFrostShader.DoUnApply(
  888. var rci: TgxRenderContextInfo): Boolean;
  889. begin
  890. rci.gxStates.ActiveTexture := 0;
  891. GetGXSLProg.EndUseProgramObject;
  892. Result := False;
  893. end;
  894. procedure TgxslCustomPostFrostShader.DoUseTempTexture(
  895. const TempTexture: TgxTextureHandle; TextureTarget: TglTextureTarget);
  896. begin
  897. Param['ScreenTex'].AsCustomTexture[3, TextureTarget] := TempTexture.Handle;
  898. end;
  899. function TgxslCustomPostFrostShader.GetTextureTarget: TglTextureTarget;
  900. begin
  901. Result := ttTextureRect; //ttTexture2D;
  902. end;
  903. function TgxslCustomPostFrostShader.StoreRandScale: Boolean;
  904. begin
  905. Result := (Abs(FRandScale) > 0) and (Abs(FRandScale) <= 1000);
  906. end;
  907. function TgxslCustomPostFrostShader.StoreRandFactor: Boolean;
  908. begin
  909. Result := (Abs(FRandFactor) > 0) and (Abs(FRandFactor) <= 1000);
  910. end;
  911. //----------------------------------------
  912. // TgxslCustomPostTroubleShader
  913. //----------------------------------------
  914. constructor TgxslCustomPostTroubleShader.Create( AOwner: TComponent);
  915. begin
  916. inherited;
  917. with VertexProgram.Code do
  918. begin
  919. Add('varying vec2 vTexCoord; ');
  920. Add(' ');
  921. Add('void main(void) ');
  922. Add('{ ');
  923. Add(' ');
  924. Add(' // Clean up inaccuracies ');
  925. Add(' vec2 Position; ');
  926. Add(' Position.xy = sign(gl_Vertex.xy); ');
  927. Add(' ');
  928. Add(' gl_Position = vec4(Position.xy, 0.0, 1.0); ');
  929. Add(' vTexCoord = Position.xy *.5 + .5; ');
  930. Add(' ');
  931. Add('} ');
  932. end;
  933. with FragmentProgram.Code do
  934. begin
  935. Add('uniform float PixelX; // = 2.0; ');
  936. Add('uniform float PixelY; // = 2.0; ');
  937. Add('uniform float Freq; // = 0.115; ');
  938. Add('uniform vec2 ScreenExtents; ');
  939. Add('uniform sampler2D noiseTex; '); // 1
  940. Add('uniform sampler2DRect ScreenTex; ');
  941. Add(' ');
  942. Add('varying vec2 vTexCoord; ');
  943. Add(' ');
  944. Add('vec4 spline(float x, vec4 c1, vec4 c2, vec4 c3, vec4 c4, vec4 c5, vec4 c6, vec4 c7, vec4 c8, vec4 c9) ');
  945. Add('{ ');
  946. Add(' float w1, w2, w3, w4, w5, w6, w7, w8, w9; ');
  947. Add(' w1 = 0.0; ');
  948. Add(' w2 = 0.0; ');
  949. Add(' w3 = 0.0; ');
  950. Add(' w4 = 0.0; ');
  951. Add(' w5 = 0.0; ');
  952. Add(' w6 = 0.0; ');
  953. Add(' w7 = 0.0; ');
  954. Add(' w8 = 0.0; ');
  955. Add(' w9 = 0.0; ');
  956. Add(' float tmp = x * 8.0; ');
  957. Add(' if (tmp<=1.0) { ');
  958. Add(' w1 = 1.0 - tmp; ');
  959. Add(' w2 = tmp; ');
  960. Add(' } ');
  961. Add(' else if (tmp<=2.0) { ');
  962. Add(' tmp = tmp - 1.0; ');
  963. Add(' w2 = 1.0 - tmp; ');
  964. Add(' w3 = tmp; ');
  965. Add(' } ');
  966. Add(' else if (tmp<=3.0) { ');
  967. Add(' tmp = tmp - 2.0; ');
  968. Add(' w3 = 1.0-tmp; ');
  969. Add(' w4 = tmp; ');
  970. Add(' } ');
  971. Add(' else if (tmp<=4.0) { ');
  972. Add(' tmp = tmp - 3.0; ');
  973. Add(' w4 = 1.0-tmp; ');
  974. Add(' w5 = tmp; ');
  975. Add(' } ');
  976. Add(' else if (tmp<=5.0) { ');
  977. Add(' tmp = tmp - 4.0; ');
  978. Add(' w5 = 1.0-tmp; ');
  979. Add(' w6 = tmp; ');
  980. Add(' } ');
  981. Add(' else if (tmp<=6.0) { ');
  982. Add(' tmp = tmp - 5.0; ');
  983. Add(' w6 = 1.0-tmp; ');
  984. Add(' w7 = tmp; ');
  985. Add(' } ');
  986. Add(' else if (tmp<=7.0) { ');
  987. Add(' tmp = tmp - 6.0; ');
  988. Add(' w7 = 1.0 - tmp; ');
  989. Add(' w8 = tmp; ');
  990. Add(' } ');
  991. Add(' else ');
  992. Add(' { ');
  993. Add(' //tmp = saturate(tmp - 7.0); ');
  994. // http://www.ozone3d.net/blogs/lab/20080709/saturate-function-in-glsl/
  995. Add(' tmp = clamp(tmp - 7.0, 0.0, 1.0); ');
  996. Add(' w8 = 1.0-tmp; ');
  997. Add(' w9 = tmp; ');
  998. Add(' } ');
  999. Add(' return w1*c1 + w2*c2 + w3*c3 + w4*c4 + w5*c5 + w6*c6 + w7*c7 + w8*c8 + w9*c9; ');
  1000. Add('} ');
  1001. Add(' ');
  1002. Add('vec3 NOISE2D(vec2 p) ');
  1003. Add(' { return texture2D(noiseTex,p).xyz; } ');
  1004. Add(' ');
  1005. Add('void main() ');
  1006. Add('{ ');
  1007. Add(' vec2 uv = vTexCoord * ScreenExtents; ');
  1008. Add(' vec3 tc = vec3(1.0, 0.0, 0.0); ');
  1009. Add(' float DeltaX = PixelX; ');
  1010. Add(' float DeltaY = PixelY; ');
  1011. Add(' vec2 ox = vec2(DeltaX,0.0); ');
  1012. Add(' vec2 oy = vec2(0.0,DeltaY); ');
  1013. Add(' vec2 PP = uv - oy; ');
  1014. Add(' vec4 C00 = texture2DRect(ScreenTex,PP - ox); ');
  1015. Add(' vec4 C01 = texture2DRect(ScreenTex,PP); ');
  1016. Add(' vec4 C02 = texture2DRect(ScreenTex,PP + ox); ');
  1017. Add(' PP = uv; ');
  1018. Add(' vec4 C10 = texture2DRect(ScreenTex,PP - ox); ');
  1019. Add(' vec4 C11 = texture2DRect(ScreenTex,PP); ');
  1020. Add(' vec4 C12 = texture2DRect(ScreenTex,PP + ox); ');
  1021. Add(' PP = uv + oy; ');
  1022. Add(' vec4 C20 = texture2DRect(ScreenTex,PP - ox); ');
  1023. Add(' vec4 C21 = texture2DRect(ScreenTex,PP); ');
  1024. Add(' vec4 C22 = texture2DRect(ScreenTex,PP + ox); ');
  1025. Add(' float n = NOISE2D(Freq*uv).x; ');
  1026. Add(' n = mod(n, 0.111111)/0.111111; ');
  1027. Add(' vec4 result = spline(n,C00,C01,C02,C10,C11,C12,C20,C21,C22); ');
  1028. Add(' tc = result.rgb; ');
  1029. Add(' gl_FragColor = vec4(tc, 1.0); ');
  1030. Add('} ');
  1031. end;
  1032. FPixelX := 0.5;
  1033. FPixelY := 0.5;
  1034. FFreq:= 2.115;
  1035. end;
  1036. procedure TgxslCustomPostTroubleShader.DoApply(
  1037. var rci: TgxRenderContextInfo; Sender: TObject);
  1038. begin
  1039. GetGXSLProg.UseProgramObject;
  1040. GetGXSLProg.Uniform1f['PixelX'] := FPixelX;
  1041. GetGXSLProg.Uniform1f['PixelY'] := FPixelY;
  1042. GetGXSLProg.Uniform1f['Freq'] := FFreq;
  1043. GetGXSLProg.Uniform2f['ScreenExtents'] := Vector2fMake(rci.viewPortSize.cx, rci.viewPortSize.cy);
  1044. param['noiseTex'].AsTexture2D[1]:= FNoiseTex;
  1045. end;
  1046. function TgxslCustomPostTroubleShader.DoUnApply(
  1047. var rci: TgxRenderContextInfo): Boolean;
  1048. begin
  1049. rci.gxStates.ActiveTexture := 0;
  1050. GetGXSLProg.EndUseProgramObject;
  1051. Result := False;
  1052. end;
  1053. procedure TgxslCustomPostTroubleShader.DoUseTempTexture(
  1054. const TempTexture: TgxTextureHandle; TextureTarget: TglTextureTarget);
  1055. begin
  1056. Param['ScreenTex'].AsCustomTexture[5, TextureTarget] := TempTexture.Handle;
  1057. end;
  1058. function TgxslCustomPostTroubleShader.GetTextureTarget: TglTextureTarget;
  1059. begin
  1060. Result := ttTextureRect; //ttTexture2D;
  1061. end;
  1062. function TgxslCustomPostTroubleShader.StorePixelX: Boolean;
  1063. begin
  1064. Result := (Abs(FPixelX) > 0) and (Abs(FPixelX) <= 1000);
  1065. end;
  1066. function TgxslCustomPostTroubleShader.StorePixelY: Boolean;
  1067. begin
  1068. Result := (Abs(FPixelY) > 0) and (Abs(FPixelY) <= 1000);
  1069. end;
  1070. function TgxslCustomPostTroubleShader.StoreFreq: Boolean;
  1071. begin
  1072. Result := (Abs(FPixelY) > 0) and (Abs(FPixelY) <= 5.0);
  1073. end;
  1074. procedure TgxslCustomPostTroubleShader.SetNoiseTexTexture(const Value: TgxTexture);
  1075. begin
  1076. if FNoiseTex = Value then Exit;
  1077. NoiseTex := Value;
  1078. NotifyChange(Self);
  1079. end;
  1080. function TgxslCustomPostTroubleShader.GetNoiseTexName: TgxLibMaterialName;
  1081. begin
  1082. Result := TgxMaterialLibrary(FMaterialLibrary).GetNameOfTexture(FNoiseTex);
  1083. if Result = '' then Result := FNoiseTexName;
  1084. end;
  1085. procedure TgxslCustomPostTroubleShader.SetNoiseTexName(const Value: TgxLibMaterialName);
  1086. begin
  1087. //Assert(not(assigned(FMaterialLibrary)),'You must set Material Library Before');
  1088. if FNoiseTexName = Value then Exit;
  1089. FNoiseTexName := Value;
  1090. FNoiseTex := TgxMaterialLibrary(FMaterialLibrary).TextureByName(FNoiseTexName);
  1091. NotifyChange(Self);
  1092. end;
  1093. function TgxslCustomPostTroubleShader.GetMaterialLibrary: TgxAbstractMaterialLibrary;
  1094. begin
  1095. Result := FMaterialLibrary;
  1096. end;
  1097. procedure TgxslCustomPostTroubleShader.SetMaterialLibrary(const Value: TgxAbstractMaterialLibrary);
  1098. begin
  1099. if FMaterialLibrary <> nil then FMaterialLibrary.RemoveFreeNotification(Self);
  1100. FMaterialLibrary := Value;
  1101. if (FMaterialLibrary <> nil)
  1102. and (FMaterialLibrary is TgxAbstractMaterialLibrary) then
  1103. FMaterialLibrary.FreeNotification(Self);
  1104. end;
  1105. procedure TgxslCustomPostTroubleShader.Notification(AComponent: TComponent; Operation: TOperation);
  1106. var
  1107. Index: Integer;
  1108. begin
  1109. inherited;
  1110. if Operation = opRemove then
  1111. if AComponent = FMaterialLibrary then
  1112. if FMaterialLibrary <> nil then
  1113. begin
  1114. // Need to nil the textures that were owned by it
  1115. if FNoiseTex <> nil then
  1116. begin
  1117. Index := TgxMaterialLibrary(FMaterialLibrary).Materials.GetTextureIndex(FNoiseTex);
  1118. if Index <> -1 then
  1119. SetNoiseTexTexture(nil);
  1120. end;
  1121. FMaterialLibrary := nil;
  1122. end;
  1123. end;
  1124. end.