fFluidsD.pas 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. unit fFluidsD;
  2. interface
  3. uses
  4. System.SysUtils,
  5. System.Classes,
  6. Vcl.Controls,
  7. Vcl.Forms,
  8. Vcl.StdCtrls,
  9. Vcl.Graphics,
  10. GLS.Scene,
  11. GLScene.VectorGeometry,
  12. GLScene.VectorTypes,
  13. GLS.Cadencer,
  14. GLS.SceneViewer,
  15. GLS.BaseClasses,
  16. GLS.Coordinates,
  17. GLS.Context,
  18. GLS.Gui,
  19. GLS.BitmapFont,
  20. GLS.WindowsFont,
  21. GLSL.CustomShader,
  22. GLS.RenderContextInfo,
  23. GLS.State,
  24. GLS.Material,
  25. GLSL.Shader,
  26. GLS.Windows,
  27. GLSL.ShaderCombiner,
  28. CUDA.Context,
  29. CUDA.APIComps,
  30. CUDA.Compiler,
  31. CUDA.FFTPlan,
  32. CUDA.Graphics,
  33. CUDA.DataAccess;
  34. type
  35. TForm1 = class(TForm)
  36. GLScene1: TGLScene;
  37. GLSceneViewer1: TGLSceneViewer;
  38. GLCadencer1: TGLCadencer;
  39. GLCamera1: TGLCamera;
  40. GLCUDADevice1: TGLCUDADevice;
  41. GLCUDA1: TGLCUDA;
  42. GLCUDACompiler1: TGLCUDACompiler;
  43. procedure FormCreate(Sender: TObject);
  44. procedure GLSceneViewer1MouseDown(Sender: TObject; Button: TMouseButton;
  45. Shift: TShiftState; X, Y: Integer);
  46. procedure GLSceneViewer1MouseMove(Sender: TObject; Shift: TShiftState; X,
  47. Y: Integer);
  48. procedure GLSceneViewer1MouseUp(Sender: TObject; Button: TMouseButton;
  49. Shift: TShiftState; X, Y: Integer);
  50. procedure GLCadencer1Progress(Sender: TObject; const deltaTime,
  51. newTime: Double);
  52. private
  53. Path: TFileName;
  54. clicked: Boolean;
  55. lastx: Integer;
  56. lasty: Integer;
  57. ComplexPadWidth: Integer;
  58. RealPadWidth: Integer;
  59. PaddedDomainSize: Integer;
  60. SpeedX: Integer;
  61. SpeedY: Integer;
  62. ForceX: Single;
  63. ForceY: Single;
  64. public
  65. MainModule: TCUDAModule;
  66. ArrayOfTexture: TCUDAMemData;
  67. TextureOfVelocityField: TCUDATexture;
  68. VelocityField: TCUDAMemData;
  69. ComplexVXField: TCUDAMemData;
  70. ComplexVYField: TCUDAMemData;
  71. InitialPosition: TCUDAMemData;
  72. FluidShader: TGLSLShader;
  73. GLMaterialLibrary1: TGLMaterialLibrary;
  74. ForwardFFT: TCUDAFFTPlan;
  75. InverseFFT: TCUDAFFTPlan;
  76. ParticleMapper: TCUDAGeometryResource;
  77. ResetButton: TGLButton;
  78. GLWindowsBitmapFont1: TGLWindowsBitmapFont;
  79. GLGuiLayout1: TGLGuiLayout;
  80. ParticleRenderer: TCUDAFeedbackMesh;
  81. addForces: TCUDAFunction;
  82. advectVelocity: TCUDAFunction;
  83. diffuseProject: TCUDAFunction;
  84. updateVelocity: TCUDAFunction;
  85. advectParticles: TCUDAFunction;
  86. addForces_k_v: TCUDAFuncParam;
  87. addForces_k_dx: TCUDAFuncParam;
  88. addForces_k_dy: TCUDAFuncParam;
  89. addForces_k_spx: TCUDAFuncParam;
  90. addForces_k_spy: TCUDAFuncParam;
  91. addForces_k_fx: TCUDAFuncParam;
  92. addForces_k_fy: TCUDAFuncParam;
  93. addForces_k_r: TCUDAFuncParam;
  94. addForces_k_pitch: TCUDAFuncParam;
  95. advectVelocity_k_vx: TCUDAFuncParam;
  96. advectVelocity_k_vy: TCUDAFuncParam;
  97. advectVelocity_k_dx: TCUDAFuncParam;
  98. advectVelocity_k_pdx: TCUDAFuncParam;
  99. advectVelocity_k_dy: TCUDAFuncParam;
  100. advectVelocity_k_dt: TCUDAFuncParam;
  101. advectVelocity_k_lb: TCUDAFuncParam;
  102. diffuseProject_k_vx: TCUDAFuncParam;
  103. diffuseProject_k_vy: TCUDAFuncParam;
  104. diffuseProject_k_dx: TCUDAFuncParam;
  105. diffuseProject_k_dy: TCUDAFuncParam;
  106. diffuseProject_k_dt: TCUDAFuncParam;
  107. diffuseProject_k_visc: TCUDAFuncParam;
  108. diffuseProject_k_lb: TCUDAFuncParam;
  109. updateVelocity_k_v: TCUDAFuncParam;
  110. updateVelocity_k_vx: TCUDAFuncParam;
  111. updateVelocity_k_vy: TCUDAFuncParam;
  112. updateVelocity_k_dx: TCUDAFuncParam;
  113. updateVelocity_k_pdx: TCUDAFuncParam;
  114. updateVelocity_k_dy: TCUDAFuncParam;
  115. updateVelocity_k_lb: TCUDAFuncParam;
  116. updateVelocity_k_pitch: TCUDAFuncParam;
  117. updateVelocity_k_scale: TCUDAFuncParam;
  118. advectParticles_k_part: TCUDAFuncParam;
  119. advectParticles_k_v: TCUDAFuncParam;
  120. advectParticles_k_dx: TCUDAFuncParam;
  121. advectParticles_k_dy: TCUDAFuncParam;
  122. advectParticles_k_dt: TCUDAFuncParam;
  123. advectParticles_k_lb: TCUDAFuncParam;
  124. advectParticles_k_pitch: TCUDAFuncParam;
  125. ParticlesDim: Integer;
  126. DeltaTime: Single;
  127. ViscosityConst: Single;
  128. ForceScaleFactor: Single;
  129. ForceUpdateRadius: Integer;
  130. ParticlesPerThread: Integer;
  131. procedure addForcesParameterSetup(Sender: TObject);
  132. procedure advectParticlesParameterSetup(Sender: TObject);
  133. procedure advectVelocityParameterSetup(Sender: TObject);
  134. procedure updateVelocityParameterSetup(Sender: TObject);
  135. procedure diffuseProjectParameterSetup(Sender: TObject);
  136. procedure FluidShaderApply(Shader: TGLCustomGLSLShader);
  137. procedure ResetButtonButtonClick(Sender: TObject);
  138. procedure BeforeKernelLaunch(Sender: TGLVertexAttribute);
  139. procedure GLCUDA1OpenGLInteropInit(out Context: TGLContext);
  140. end;
  141. var
  142. Form1: TForm1;
  143. implementation
  144. {$R *.dfm}
  145. var
  146. InitPosition : Boolean = False;
  147. procedure TForm1.FormCreate(Sender: TObject);
  148. var
  149. i, j: Integer;
  150. pos: FloatElement.TVector2;
  151. begin
  152. ParticlesDim := 512;
  153. ComplexPadWidth := ParticlesDim div 2 + 1;
  154. RealPadWidth := 2 * ComplexPadWidth;
  155. PaddedDomainSize := ParticlesDim * ComplexPadWidth;
  156. ViscosityConst := 0.0025;
  157. ForceScaleFactor := 5.8 * ParticlesDim;
  158. ForceUpdateRadius := 4;
  159. ParticlesPerThread := 16;
  160. ComplexVXField.Width := PaddedDomainSize;
  161. ComplexVYField.Width := PaddedDomainSize;
  162. advectVelocity.BlockShape.SizeX := 64;
  163. advectVelocity.BlockShape.SizeY := 4;
  164. advectVelocity.Grid.SizeX := 8;
  165. advectVelocity.Grid.SizeY := 8;
  166. diffuseProject.BlockShape.SizeX := 64;
  167. diffuseProject.BlockShape.SizeY := 4;
  168. diffuseProject.Grid.SizeX := 8;
  169. diffuseProject.Grid.SizeY := 8;
  170. updateVelocity.BlockShape.SizeX := 64;
  171. updateVelocity.BlockShape.SizeY := 4;
  172. updateVelocity.Grid.SizeX := 8;
  173. updateVelocity.Grid.SizeY := 8;
  174. advectParticles.BlockShape.SizeX := 64;
  175. advectParticles.BlockShape.SizeY := 4;
  176. advectParticles.Grid.SizeX := 8;
  177. advectParticles.Grid.SizeY := 8;
  178. // Create initial position data at host side
  179. for i := 0 to InitialPosition.Height - 1 do
  180. for j := 0 to InitialPosition.Width - 1 do
  181. begin
  182. pos[0] := ((j + 0.5) / InitialPosition.Width) + (random - 0.5) /
  183. InitialPosition.Width;
  184. pos[1] := ((i + 0.5) / InitialPosition.Height) + (random - 0.5) /
  185. InitialPosition.Height;
  186. InitialPosition.Data<Single>(j, i).Vector2 := pos;
  187. end;
  188. ParticleRenderer.VertexNumber := ParticlesDim * ParticlesDim;
  189. clicked := false;
  190. end;
  191. procedure TForm1.GLSceneViewer1MouseDown(Sender: TObject; Button: TMouseButton;
  192. Shift: TShiftState; X, Y: Integer);
  193. begin
  194. lastX := X;
  195. lastY := Y;
  196. clicked := true;
  197. ResetButton.MouseDown(Sender, TMouseButton(Button), Shift, X, Y);
  198. end;
  199. procedure TForm1.GLSceneViewer1MouseMove(Sender: TObject; Shift: TShiftState; X,
  200. Y: Integer);
  201. var
  202. nx, ny: Integer;
  203. ddx, ddy: Integer;
  204. begin
  205. // Convert motion coordinates to domain
  206. ForceX := lastx / GLSceneViewer1.Width;
  207. ForceY := lasty / GLSceneViewer1.Height;
  208. nx := Round(ForceX * InitialPosition.Width);
  209. ny := Round(ForceY * InitialPosition.Height);
  210. if clicked and (nx < InitialPosition.Width - ForceUpdateRadius)
  211. and (nx > ForceUpdateRadius - 1)
  212. and (ny < InitialPosition.Height - ForceUpdateRadius)
  213. and (ny > ForceUpdateRadius - 1) then
  214. begin
  215. ddx := X - lastx;
  216. ddy := Y - lasty;
  217. SpeedX := nx - ForceUpdateRadius;
  218. SpeedY := ny - ForceUpdateRadius;
  219. ForceX := DeltaTime * ForceScaleFactor * (ddx / GLSceneViewer1.Width);
  220. ForceY := DeltaTime * ForceScaleFactor * (ddy / GLSceneViewer1.Height);
  221. addForces.Launch(false);
  222. lastx := X;
  223. lasty := Y;
  224. end;
  225. ResetButton.MouseMove(Sender, Shift, X, Y);
  226. end;
  227. procedure TForm1.GLSceneViewer1MouseUp(Sender: TObject; Button: TMouseButton;
  228. Shift: TShiftState; X, Y: Integer);
  229. begin
  230. clicked := false;
  231. ResetButton.MouseUp(Sender, TMouseButton(Button), Shift, X, Y);
  232. end;
  233. procedure TForm1.GLCUDA1OpenGLInteropInit(out Context: TGLContext);
  234. begin
  235. Context := GLSceneViewer1.Buffer.RenderingContext;
  236. end;
  237. procedure TForm1.BeforeKernelLaunch(
  238. Sender: TGLVertexAttribute);
  239. begin
  240. if not InitPosition then
  241. begin
  242. InitialPosition.CopyTo(
  243. ParticleMapper,
  244. ParticleRenderer.Attributes[0].Name);
  245. VelocityField.FillMem(NullVector);
  246. InitPosition := true;
  247. end;
  248. // Simulate fluid
  249. advectVelocity.Launch;
  250. ForwardFFT.Execute(ComplexVXField, ComplexVXField);
  251. ForwardFFT.Execute(ComplexVYField, ComplexVYField);
  252. diffuseProject.Launch;
  253. InverseFFT.Execute(ComplexVXField, ComplexVXField);
  254. InverseFFT.Execute(ComplexVYField, ComplexVYField);
  255. updateVelocity.Launch;
  256. // advectParticles will be launched automaticaly by ParticleRenderer
  257. // Look at ParticleRenderer.VertexAttributes[0].KernelFunction
  258. end;
  259. procedure TForm1.addForcesParameterSetup(Sender: TObject);
  260. begin
  261. with addForces do
  262. begin
  263. BlockShape.SizeX := 2 * ForceUpdateRadius + 1;
  264. BlockShape.SizeY := 2 * ForceUpdateRadius + 1;
  265. SetParam(VelocityField);
  266. SetParam(ParticlesDim);
  267. SetParam(ParticlesDim);
  268. SetParam(SpeedX);
  269. SetParam(SpeedY);
  270. SetParam(ForceX);
  271. SetParam(ForceY);
  272. SetParam(ForceUpdateRadius);
  273. SetParam(VelocityField.Pitch);
  274. end;
  275. end;
  276. procedure TForm1.advectVelocityParameterSetup(Sender: TObject);
  277. begin
  278. VelocityField.CopyTo(ArrayOfTexture);
  279. with advectVelocity do
  280. begin
  281. SetParam(ComplexVXField);
  282. SetParam(ComplexVYField);
  283. SetParam(ParticlesDim);
  284. SetParam(RealPadWidth);
  285. SetParam(ParticlesDim);
  286. SetParam(DeltaTime);
  287. SetParam(ParticlesPerThread);
  288. // For texture parameter order does not matter
  289. SetParam(TextureOfVelocityField);
  290. end;
  291. end;
  292. procedure TForm1.diffuseProjectParameterSetup(Sender: TObject);
  293. begin
  294. with diffuseProject do
  295. begin
  296. SetParam(ComplexVXField);
  297. SetParam(ComplexVYField);
  298. SetParam(ComplexPadWidth);
  299. SetParam(ParticlesDim);
  300. SetParam(DeltaTime);
  301. SetParam(ViscosityConst);
  302. SetParam(ParticlesPerThread);
  303. end;
  304. end;
  305. procedure TForm1.updateVelocityParameterSetup(Sender: TObject);
  306. begin
  307. with updateVelocity do
  308. begin
  309. SetParam(VelocityField);
  310. SetParam(ComplexVXField);
  311. SetParam(ComplexVYField);
  312. SetParam(ParticlesDim);
  313. SetParam(RealPadWidth);
  314. SetParam(ParticlesDim);
  315. SetParam(ParticlesPerThread);
  316. SetParam(VelocityField.Pitch);
  317. SetParam(1.0 / (ParticlesDim * ParticlesDim));
  318. end;
  319. end;
  320. procedure TForm1.advectParticlesParameterSetup(Sender: TObject);
  321. begin
  322. with advectParticles do
  323. begin
  324. SetParam(ParticleMapper.AttributeDataAddress[ParticleRenderer.Attributes[0].Name]);
  325. SetParam(VelocityField);
  326. SetParam(ParticlesDim);
  327. SetParam(ParticlesDim);
  328. SetParam(DeltaTime);
  329. SetParam(ParticlesPerThread);
  330. SetParam(VelocityField.Pitch);
  331. end;
  332. end;
  333. procedure TForm1.ResetButtonButtonClick(Sender: TObject);
  334. begin
  335. InitPosition := false;
  336. end;
  337. procedure TForm1.GLCadencer1Progress(Sender: TObject; const DeltaTime,
  338. newTime: Double);
  339. begin
  340. Self.DeltaTime := 5*DeltaTime;
  341. GLSceneViewer1.Invalidate;
  342. end;
  343. procedure TForm1.FluidShaderApply(Shader: TGLCustomGLSLShader);
  344. begin
  345. with CurrentGLContext.GLStates do
  346. begin
  347. Enable(stPointSmooth);
  348. Enable(stBlend);
  349. Disable(stCullFace);
  350. Disable(stDepthTest);
  351. PointSize := 1;
  352. SetBlendFunc(bfSrcAlpha, bfOneMinusSrcAlpha);
  353. end;
  354. end;
  355. end.