fForest.pas 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778
  1. unit fForest;
  2. interface
  3. uses
  4. Winapi.Windows,
  5. Winapi.OpenGL,
  6. Winapi.OpenGLext,
  7. System.SysUtils,
  8. System.Classes,
  9. System.Math,
  10. System.Types,
  11. Vcl.Graphics,
  12. Vcl.Controls,
  13. Vcl.Forms,
  14. Vcl.Dialogs,
  15. Vcl.Imaging.Jpeg,
  16. Vcl.ExtCtrls,
  17. GLS.OpenGLTokens,
  18. GLS.SceneViewer,
  19. GLS.Cadencer,
  20. GLS.Texture,
  21. GLS.VectorTypes,
  22. GLS.VectorGeometry,
  23. GLS.Scene,
  24. GLS.Objects,
  25. GLS.Tree,
  26. GLS.Keyboard,
  27. GLS.VectorLists,
  28. GLS.BitmapFont,
  29. GLS.Context,
  30. GLS.WindowsFont,
  31. GLS.HUDObjects,
  32. GLS.SkyDome,
  33. GLS.Imposter,
  34. GLS.ParticleFX,
  35. GLS.Graphics,
  36. GLS.PersistentClasses,
  37. GLS.PipelineTransformation,
  38. GLS.XOpenGL,
  39. GLS.BaseClasses,
  40. GLS.TextureCombiners,
  41. GLS.TextureFormat,
  42. GLS.Material,
  43. GLS.Coordinates,
  44. GLS.TerrainRenderer,
  45. GLS.HeightData,
  46. GLS.HeightTileFileHDS,
  47. GLS.RenderContextInfo,
  48. GLS.Screen,
  49. GLS.State,
  50. GLS.FileTGA,
  51. GLS.Utils;
  52. type
  53. TForm1 = class(TForm)
  54. SceneViewer: TGLSceneViewer;
  55. GLScene: TGLScene;
  56. MLTrees: TGLMaterialLibrary;
  57. MLTerrain: TGLMaterialLibrary;
  58. GLCadencer: TGLCadencer;
  59. Terrain: TGLTerrainRenderer;
  60. Camera: TGLCamera;
  61. Light: TGLLightSource;
  62. GLHUDText1: TGLHUDText;
  63. GLWindowsBitmapFont1: TGLWindowsBitmapFont;
  64. EarthSkyDome: TGLEarthSkyDome;
  65. GLRenderPoint: TGLRenderPoint;
  66. SIBTree: TGLStaticImposterBuilder;
  67. DOTrees: TGLDirectOpenGL;
  68. PFXTrees: TGLCustomPFXManager;
  69. RenderTrees: TGLParticleFXRenderer;
  70. Timer1: TTimer;
  71. MLWater: TGLMaterialLibrary;
  72. DOInitializeReflection: TGLDirectOpenGL;
  73. DOGLSLWaterPlane: TGLDirectOpenGL;
  74. DOClassicWaterPlane: TGLDirectOpenGL;
  75. GLHeightTileFileHDS: TGLHeightTileFileHDS;
  76. procedure FormCreate(Sender: TObject);
  77. procedure FormDestroy(Sender: TObject);
  78. procedure TerrainGetTerrainBounds(var l, t, r, b: Single);
  79. procedure GLCadencerProgress(Sender: TObject; const deltaTime,
  80. newTime: Double);
  81. procedure FormKeyDown(Sender: TObject; var Key: Word;
  82. Shift: TShiftState);
  83. procedure DOTreesRender(Sender: TObject; var rci: TGLRenderContextInfo);
  84. procedure PFXTreesBeginParticles(Sender: TObject;
  85. var rci: TGLRenderContextInfo);
  86. procedure PFXTreesCreateParticle(Sender: TObject; aParticle: TGLParticle);
  87. procedure PFXTreesEndParticles(Sender: TObject; var rci: TGLRenderContextInfo);
  88. procedure PFXTreesRenderParticle(Sender: TObject;
  89. aParticle: TGLParticle; var rci: TGLRenderContextInfo);
  90. procedure SIBTreeImposterLoaded(Sender: TObject;
  91. impostoredObject: TGLBaseSceneObject; destImposter: TImposter);
  92. function SIBTreeLoadingImposter(Sender: TObject;
  93. impostoredObject: TGLBaseSceneObject;
  94. destImposter: TImposter): TGLBitmap32;
  95. procedure Timer1Timer(Sender: TObject);
  96. procedure PFXTreesProgress(Sender: TObject;
  97. const progressTime: TGLProgressTimes; var defaultProgress: Boolean);
  98. function PFXTreesGetParticleCountEvent(Sender: TObject): Integer;
  99. procedure FormResize(Sender: TObject);
  100. procedure DOInitializeReflectionRender(Sender: TObject;
  101. var rci: TGLRenderContextInfo);
  102. procedure DOGLSLWaterPlaneRender(Sender: TObject;
  103. var rci: TGLRenderContextInfo);
  104. procedure DOClassicWaterPlaneRender(Sender: TObject;
  105. var rci: TGLRenderContextInfo);
  106. procedure FormDeactivate(Sender: TObject);
  107. procedure FormShow(Sender: TObject);
  108. private
  109. // hscale, mapwidth, mapheight : Single;
  110. lmp: TPoint;
  111. camPitch, camTurn, camTime, curPitch, curTurn: Single;
  112. function GetTextureReflectionMatrix: TGLMatrix;
  113. public
  114. TestTree: TGLTree;
  115. TreesShown: Integer;
  116. nearTrees: TPersistentObjectList;
  117. imposter: TImposter;
  118. densityBitmap: TBitmap;
  119. mirrorTexture: TGLTextureHandle;
  120. mirrorTexType: TGLTextureTarget;
  121. reflectionProgram: TGLProgramHandle;
  122. supportsGLSL: Boolean;
  123. enableGLSL: Boolean;
  124. enableRectReflection, enableTex2DReflection: Boolean;
  125. end;
  126. var
  127. Form1: TForm1;
  128. //-----------------------------------------------
  129. implementation
  130. //-----------------------------------------------
  131. {$R *.dfm}
  132. const
  133. cImposterCacheFile: string = 'imposters.bmp';
  134. cMapWidth: Integer = 1024;
  135. cMapHeight: Integer = 1024;
  136. cBaseSpeed: Single = 50;
  137. procedure TForm1.FormCreate(Sender: TObject);
  138. var
  139. density: TPicture;
  140. DataPath : TFileName;
  141. begin
  142. // go to 1024x768x32
  143. // SetFullscreenMode(GetIndexFromResolution(1024, 768, 32), 85);
  144. Application.OnDeactivate := FormDeactivate;
  145. DataPath := ExtractFilePath(ParamStr(0));
  146. Delete(DataPath, Length(DataPath) - 12, 12);
  147. DataPath := DataPath + 'Data\';
  148. SetCurrentDir(DataPath);
  149. // Load volcano textures
  150. MLTerrain.AddTextureMaterial('Terrain', 'volcano_TX_low.jpg').Texture2Name := 'Detail';
  151. MLTerrain.AddTextureMaterial('Detail', 'detailmap.jpg').Material.Texture.TextureMode := tmModulate;
  152. MLTerrain.AddTextureMaterial('Detail', 'detailmap.jpg').TextureScale.SetPoint(128, 128, 128);
  153. Terrain.Material.MaterialLibrary := MLTerrain;
  154. Terrain.Material.LibMaterialName := 'Terrain';
  155. // Load tree textures
  156. MLTrees.AddTextureMaterial('Leaf', 'leaf.tga').Material.Texture.TextureFormat := tfRGBA;
  157. MLTrees.AddTextureMaterial('Leaf', 'leaf.tga').Material.Texture.TextureMode := tmModulate;
  158. MLTrees.AddTextureMaterial('Leaf', 'leaf.tga').Material.Texture.MinFilter := miNearestMipmapNearest;
  159. MLTrees.AddTextureMaterial('Leaf', 'leaf.tga').Material.BlendingMode := bmAlphaTest50;
  160. MLTrees.AddTextureMaterial('Bark', 'zbark_016.jpg').Material.Texture.TextureMode := tmModulate;
  161. // Create test tree
  162. Randomize;
  163. TestTree := TGLTree(GLScene.Objects.AddNewChild(TGLTree));
  164. with TestTree do
  165. begin
  166. Visible := False;
  167. MaterialLibrary := MLTrees;
  168. LeafMaterialName := 'Leaf';
  169. LeafBackMaterialName := 'Leaf';
  170. BranchMaterialName := 'Bark';
  171. Up.SetVector(ZHmgVector);
  172. Direction.SetVector(YHmgVector);
  173. Depth := 9;
  174. BranchFacets := 6;
  175. LeafSize := 0.50;
  176. BranchAngle := 0.65;
  177. BranchTwist := 135;
  178. ForceTotalRebuild;
  179. end;
  180. SIBTree.RequestImposterFor(TestTree);
  181. densityBitmap := TBitmap.Create;
  182. try
  183. densityBitmap.PixelFormat := pf24bit;
  184. Density := TPicture.Create;
  185. try
  186. Density.LoadFromFile('volcano_trees.jpg');
  187. densityBitmap.Width := Density.Width;
  188. densityBitmap.Height := Density.Height;
  189. densityBitmap.Canvas.Draw(0, 0, Density.Graphic);
  190. finally
  191. Density.Free;
  192. end;
  193. PFXTrees.CreateParticles(10000);
  194. finally
  195. densityBitmap.Free;
  196. end;
  197. TreesShown := 2000;
  198. Light.Pitch(30);
  199. Camera.Position.Y := Terrain.InterpolatedHeight(Camera.Position.AsVector) + 10;
  200. lmp := ClientToScreen(Point(Width div 2, Height div 2));
  201. SetCursorPos(lmp.X, lmp.Y);
  202. ShowCursor(False);
  203. nearTrees := TPersistentObjectList.Create;
  204. camTurn := -60;
  205. enableRectReflection := False;
  206. enableTex2DReflection := False;
  207. end;
  208. procedure TForm1.FormDestroy(Sender: TObject);
  209. begin
  210. // RestoreDefaultMode;
  211. ShowCursor(True);
  212. nearTrees.Free;
  213. end;
  214. procedure TForm1.FormResize(Sender: TObject);
  215. begin
  216. Camera.FocalLength := Width * 50 / 800;
  217. end;
  218. procedure TForm1.FormDeactivate(Sender: TObject);
  219. begin
  220. Close;
  221. end;
  222. procedure TForm1.FormShow(Sender: TObject);
  223. begin
  224. SetFocus;
  225. end;
  226. procedure TForm1.GLCadencerProgress(Sender: TObject; const deltaTime,
  227. newTime: Double);
  228. var
  229. speed, z: Single;
  230. nmp: TPoint;
  231. begin
  232. // Camera movement
  233. if IsKeyDown(VK_SHIFT) then
  234. speed := deltaTime * cBaseSpeed * 10
  235. else
  236. speed := deltaTime * cBaseSpeed;
  237. if IsKeyDown(VK_UP) or IsKeyDown('W') or IsKeyDown('Z') then
  238. Camera.Move(speed)
  239. else if IsKeyDown(VK_DOWN) or IsKeyDown('S') then
  240. Camera.Move(-speed);
  241. if IsKeyDown(VK_LEFT) or IsKeyDown('A') or IsKeyDown('Q') then
  242. Camera.Slide(-speed)
  243. else if IsKeyDown(VK_RIGHT) or IsKeyDown('D') then
  244. Camera.Slide(speed);
  245. z := Terrain.Position.Y + Terrain.InterpolatedHeight(Camera.Position.AsVector);
  246. if z < 0 then
  247. z := 0;
  248. z := z + 10;
  249. if Camera.Position.Y < z then
  250. Camera.Position.Y := z;
  251. GetCursorPos(nmp);
  252. camTurn := camTurn - (lmp.X - nmp.X) * 0.2;
  253. camPitch := camPitch + (lmp.Y - nmp.Y) * 0.2;
  254. camTime := camTime + deltaTime;
  255. while camTime > 0 do
  256. begin
  257. curTurn := Lerp(curTurn, camTurn, 0.2);
  258. curPitch := Lerp(curPitch, camPitch, 0.2);
  259. Camera.Position.Y := Lerp(Camera.Position.Y, z, 0.2);
  260. camTime := camTime - 0.01;
  261. end;
  262. Camera.ResetRotations;
  263. Camera.Turn(curTurn);
  264. Camera.Pitch(curPitch);
  265. SetCursorPos(lmp.X, lmp.Y);
  266. SceneViewer.Invalidate;
  267. end;
  268. procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
  269. Shift: TShiftState);
  270. begin
  271. case key of
  272. VK_ESCAPE: Form1.Close;
  273. VK_ADD: if TreesShown < PFXTrees.Particles.ItemCount then
  274. TreesShown := TreesShown + 100;
  275. VK_SUBTRACT: if TreesShown > 0 then
  276. TreesShown := TreesShown - 100;
  277. Word('R'): enableTex2DReflection := not enableTex2DReflection;
  278. Word('G'): if supportsGLSL then
  279. begin
  280. enableGLSL := not enableGLSL;
  281. enableTex2DReflection := True;
  282. end;
  283. end;
  284. end;
  285. procedure TForm1.Timer1Timer(Sender: TObject);
  286. var
  287. hud: string;
  288. begin
  289. hud := Format('%.1f FPS - %d trees'#13#10'Tree sort: %f ms',
  290. [SceneViewer.FramesPerSecond, TreesShown, RenderTrees.LastSortTime]);
  291. if enableTex2DReflection then
  292. begin
  293. hud := hud + #13#10 + 'Water reflections';
  294. if enableRectReflection then
  295. hud := hud + ' (RECT)';
  296. end;
  297. if enableGLSL and enableTex2DReflection then
  298. hud := hud + #13#10 + 'GLSL water';
  299. GLHUDText1.Text := hud;
  300. SceneViewer.ResetPerformanceMonitor;
  301. Caption := Format('%.2f', [RenderTrees.LastSortTime]);
  302. end;
  303. procedure TForm1.PFXTreesCreateParticle(Sender: TObject;
  304. aParticle: TGLParticle);
  305. var
  306. u, v, p: Single;
  307. // x, y, i, j, dark : Integer;
  308. pixelX, pixelY: Integer;
  309. begin
  310. repeat
  311. repeat
  312. u := Random * 0.88 + 0.06;
  313. v := Random * 0.88 + 0.06;
  314. pixelX := Round(u * densityBitmap.Width);
  315. pixelY := Round(v * densityBitmap.Height);
  316. p := ((densityBitmap.Canvas.Pixels[pixelX, pixelY] shr 8) and 255) / 255;
  317. until p > Random;
  318. aParticle.PosX := (0.5 - u) * Terrain.Scale.X * cMapWidth;
  319. aParticle.PosY := 0;
  320. aParticle.PosZ := (0.5 - (1 - v)) * Terrain.Scale.Y * cMapHeight;
  321. aParticle.PosY := Terrain.Position.Y + Terrain.InterpolatedHeight(aParticle.Position);
  322. until aParticle.PosY >= 0;
  323. aParticle.Tag := Random(360);
  324. end;
  325. procedure TForm1.PFXTreesBeginParticles(Sender: TObject;
  326. var rci: TGLRenderContextInfo);
  327. begin
  328. imposter := SIBTree.ImposterFor(TestTree);
  329. imposter.BeginRender(rci);
  330. end;
  331. procedure TForm1.PFXTreesRenderParticle(Sender: TObject;
  332. aParticle: TGLParticle; var rci: TGLRenderContextInfo);
  333. const
  334. cTreeCenteringOffset: TAffineVector = (X:0; Y:30; Z:0);
  335. var
  336. d: Single;
  337. camPos: TGLVector;
  338. begin
  339. if not IsVolumeClipped(VectorAdd(aParticle.Position, cTreeCenteringOffset), 30, rci.rcci.frustum)
  340. then
  341. begin
  342. ;
  343. VectorSubtract(rci.cameraPosition, aParticle.Position, camPos);
  344. d := VectorNorm(camPos);
  345. if d > Sqr(180) then
  346. begin
  347. RotateVectorAroundY(PAffineVector(@camPos)^, aParticle.Tag * cPIdiv180);
  348. imposter.Render(rci, VectorMake(aParticle.Position), camPos, 10);
  349. end
  350. else
  351. begin
  352. nearTrees.Add(aParticle);
  353. end;
  354. end;
  355. end;
  356. procedure TForm1.PFXTreesEndParticles(Sender: TObject;
  357. var rci: TGLRenderContextInfo);
  358. var
  359. aParticle: TGLParticle;
  360. camPos: TGLVector;
  361. begin
  362. // Only 20 trees max rendered at full res, force imposter'ing the others
  363. while nearTrees.Count > 20 do
  364. begin
  365. aParticle := TGLParticle(nearTrees.First);
  366. VectorSubtract(rci.cameraPosition, aParticle.Position, camPos);
  367. RotateVectorAroundY(PAffineVector(@camPos)^, aParticle.Tag * cPIdiv180);
  368. imposter.Render(rci, VectorMake(aParticle.Position), camPos, 10);
  369. nearTrees.Delete(0);
  370. end;
  371. imposter.EndRender(rci);
  372. end;
  373. procedure TForm1.DOTreesRender(Sender: TObject;
  374. var rci: TGLRenderContextInfo);
  375. var
  376. i: Integer;
  377. particle: TGLParticle;
  378. TreeModelMatrix: TGLMatrix;
  379. begin
  380. rci.GLStates.Disable(stBlend);
  381. for i := 0 to nearTrees.Count - 1 do
  382. begin
  383. particle := TGLParticle(nearTrees[i]);
  384. TreeModelMatrix := MatrixMultiply(CreateTranslationMatrix(particle.Position),
  385. rci.PipelineTransformation.ViewMatrix^);
  386. TreeModelMatrix := MatrixMultiply(CreateScaleMatrix(VectorMake(10, 10, 10)),
  387. TreeModelMatrix);
  388. TreeModelMatrix := MatrixMultiply(CreateRotationMatrixY(DegToRad(-particle.Tag)),
  389. TreeModelMatrix);
  390. TreeModelMatrix := MatrixMultiply(CreateRotationMatrixX(DegToRad(Cos(GLCadencer.CurrentTime + particle.ID * 15) * 0.2)),
  391. TreeModelMatrix);
  392. TreeModelMatrix := MatrixMultiply(CreateRotationMatrixZ(DegToRad(Cos(GLCadencer.CurrentTime * 1.3 + particle.ID * 15) * 0.2)),
  393. TreeModelMatrix);
  394. TestTree.AbsoluteMatrix := TreeModelMatrix;
  395. TestTree.Render(rci);
  396. end;
  397. nearTrees.Clear;
  398. end;
  399. procedure TForm1.TerrainGetTerrainBounds(var l, t, r, b: Single);
  400. begin
  401. l := 0;
  402. t := cMapHeight;
  403. r := cMapWidth;
  404. b := 0;
  405. end;
  406. function TForm1.SIBTreeLoadingImposter(Sender: TObject;
  407. impostoredObject: TGLBaseSceneObject;
  408. destImposter: TImposter): TGLBitmap32;
  409. var
  410. bmp: TBitmap;
  411. cacheAge, exeAge: TDateTime;
  412. begin
  413. Tag := 1;
  414. Result := nil;
  415. if not FileExists(cImposterCacheFile) then
  416. Exit;
  417. FileAge(cImposterCacheFile, cacheAge, True);
  418. FileAge(ParamStr(0), exeAge, True);
  419. if cacheAge < exeAge then
  420. Exit;
  421. Tag := 0;
  422. bmp := TBitmap.Create;
  423. bmp.LoadFromFile(cImposterCacheFile);
  424. Result := TGLBitmap32.Create;
  425. Result.Assign(bmp);
  426. bmp.Free;
  427. end;
  428. procedure TForm1.SIBTreeImposterLoaded(Sender: TObject;
  429. impostoredObject: TGLBaseSceneObject; destImposter: TImposter);
  430. var
  431. bmp32: TGLBitmap32;
  432. bmp: TBitmap;
  433. begin
  434. if Tag = 1 then
  435. begin
  436. bmp32 := TGLBitmap32.Create;
  437. bmp32.AssignFromTexture2D(SIBTree.ImposterFor(TestTree).Texture);
  438. bmp := bmp32.Create32BitsBitmap;
  439. bmp.SaveToFile(cImposterCacheFile);
  440. bmp.Free;
  441. bmp32.Free;
  442. end;
  443. end;
  444. function TForm1.PFXTreesGetParticleCountEvent(Sender: TObject): Integer;
  445. begin
  446. Result := TreesShown;
  447. end;
  448. procedure TForm1.PFXTreesProgress(Sender: TObject;
  449. const progressTime: TGLProgressTimes; var defaultProgress: Boolean);
  450. begin
  451. defaultProgress := False;
  452. end;
  453. procedure TForm1.DOInitializeReflectionRender(Sender: TObject;
  454. var rci: TGLRenderContextInfo);
  455. var
  456. w, h: Integer;
  457. refMat: TGLMatrix;
  458. cameraPosBackup, cameraDirectionBackup: TGLVector;
  459. frustumBackup: TFrustum;
  460. clipPlane: TDoubleHmgPlane;
  461. glTarget: GLEnum;
  462. begin
  463. supportsGLSL := GL.ARB_shader_objects and GL.ARB_fragment_shader and GL.ARB_vertex_shader;
  464. enableRectReflection := GL.NV_texture_rectangle and ((not enableGLSL) or GL.EXT_Cg_shader);
  465. if not enableTex2DReflection then
  466. Exit;
  467. if not Assigned(mirrorTexture) then
  468. mirrorTexture := TGLTextureHandle.Create;
  469. rci.PipelineTransformation.Push;
  470. // Mirror coordinates
  471. refMat := MakeReflectionMatrix(NullVector, YVector);
  472. rci.PipelineTransformation.ViewMatrix^ :=
  473. MatrixMultiply(refMat, rci.PipelineTransformation.ViewMatrix^);
  474. rci.GLStates.FrontFace := fwClockWise;
  475. GL.Enable(GL_CLIP_PLANE0);
  476. SetPlane(clipPlane, PlaneMake(AffineVectorMake(0, 1, 0), VectorNegate(YVector)));
  477. GL.ClipPlane(GL_CLIP_PLANE0, @clipPlane);
  478. cameraPosBackup := rci.cameraPosition;
  479. cameraDirectionBackup := rci.cameraDirection;
  480. frustumBackup := rci.rcci.frustum;
  481. rci.cameraPosition := VectorTransform(rci.cameraPosition, refMat);
  482. rci.cameraDirection := VectorTransform(rci.cameraDirection, refMat);
  483. with rci.rcci.frustum do
  484. begin
  485. pLeft := VectorTransform(pLeft, refMat);
  486. pRight := VectorTransform(pRight, refMat);
  487. pTop := VectorTransform(pTop, refMat);
  488. pBottom := VectorTransform(pBottom, refMat);
  489. pNear := VectorTransform(pNear, refMat);
  490. pFar := VectorTransform(pFar, refMat);
  491. end;
  492. rci.PipelineTransformation.ViewMatrix^ := IdentityHmgMatrix;
  493. Camera.Apply;
  494. rci.PipelineTransformation.ViewMatrix^ :=
  495. MatrixMultiply(refMat, rci.PipelineTransformation.ViewMatrix^);
  496. EarthSkyDome.DoRender(rci, True, False);
  497. rci.PipelineTransformation.ModelMatrix^ := Terrain.AbsoluteMatrix;
  498. Terrain.DoRender(rci, True, False);
  499. rci.cameraPosition := cameraPosBackup;
  500. rci.cameraDirection := cameraDirectionBackup;
  501. rci.rcci.frustum := frustumBackup;
  502. // Restore to "normal"
  503. rci.PipelineTransformation.Pop;
  504. GLScene.SetupLights(TGLSceneBuffer(rci.buffer).LimitOf[limLights]);
  505. rci.GLStates.FrontFace := fwCounterClockWise;
  506. if enableRectReflection then
  507. begin
  508. mirrorTexType := ttTextureRect;
  509. w := SceneViewer.Width;
  510. h := SceneViewer.Height;
  511. end
  512. else
  513. begin
  514. mirrorTexType := ttTexture2D;
  515. w := RoundUpToPowerOf2(SceneViewer.Width);
  516. h := RoundUpToPowerOf2(SceneViewer.Height);
  517. end;
  518. glTarget := DecodeTextureTarget(mirrorTexType);
  519. mirrorTexture.AllocateHandle;
  520. if mirrorTexture.IsDataNeedUpdate then
  521. begin
  522. rci.GLStates.TextureBinding[0, mirrorTexType] := mirrorTexture.Handle;
  523. GL.TexParameteri(glTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  524. GL.TexParameteri(glTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  525. GL.TexParameteri(glTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  526. GL.TexParameteri(glTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  527. GL.CopyTexImage2d(glTarget, 0, GL_RGBA8, 0, 0, w, h, 0);
  528. mirrorTexture.NotifyDataUpdated;
  529. end
  530. else
  531. begin
  532. rci.GLStates.TextureBinding[0, mirrorTexType] := mirrorTexture.Handle;
  533. GL.CopyTexSubImage2D(glTarget, 0, 0, 0, 0, 0, w, h);
  534. end;
  535. GL.Clear(GL_COLOR_BUFFER_BIT + GL_DEPTH_BUFFER_BIT + GL_STENCIL_BUFFER_BIT);
  536. end;
  537. procedure TForm1.DOClassicWaterPlaneRender(Sender: TObject;
  538. var rci: TGLRenderContextInfo);
  539. const
  540. cWaveScale = 7;
  541. cWaveSpeed = 0.02;
  542. cSinScale = 0.02;
  543. var
  544. tex0Matrix, tex1Matrix: TGLMatrix;
  545. tWave: Single;
  546. pos: TAffineVector;
  547. tex: TTexPoint;
  548. x, y: Integer;
  549. begin
  550. if enableGLSL and enableTex2DReflection then
  551. Exit;
  552. tWave := GLCadencer.CurrentTime * cWaveSpeed;
  553. rci.GLStates.ActiveTexture := 0;
  554. rci.GLStates.TextureBinding[0, ttTexture2D] := MLWater.Materials[0].Material.Texture.Handle;
  555. rci.GLStates.ActiveTextureEnabled[ttTexture2D] := True;
  556. tex0Matrix := IdentityHmgMatrix;
  557. tex0Matrix.X.X := 3 * cWaveScale;
  558. tex0Matrix.Y.Y := 4 * cWaveScale;
  559. tex0Matrix.W.X := tWave * 1.1;
  560. tex0Matrix.W.Y := tWave * 1.06;
  561. rci.GLStates.SetGLTextureMatrix(tex0Matrix);
  562. rci.GLStates.ActiveTexture := 1;
  563. rci.GLStates.TextureBinding[0, ttTexture2D] := MLWater.Materials[0].Material.Texture.Handle;
  564. rci.GLStates.ActiveTextureEnabled[ttTexture2D] := True;
  565. tex1Matrix := IdentityHmgMatrix;
  566. tex1Matrix.X.X := cWaveScale;
  567. tex1Matrix.Y.Y := cWaveScale;
  568. tex1Matrix.W.X := tWave * 0.83;
  569. tex1Matrix.W.Y := tWave * 0.79;
  570. rci.GLStates.SetGLTextureMatrix(tex1Matrix);
  571. if enableTex2DReflection then
  572. begin
  573. rci.GLStates.ActiveTexture := 2;
  574. rci.GLStates.TextureBinding[2, mirrorTexType] := mirrorTexture.Handle;
  575. rci.GLStates.ActiveTextureEnabled[ttTexture2D] := True;
  576. rci.GLStates.SetGLTextureMatrix(GetTextureReflectionMatrix);
  577. end;
  578. rci.GLStates.ActiveTexture := 0;
  579. {
  580. if enableTex2DReflection then
  581. begin
  582. //SetupTextureCombiners('Tex0:=Tex1*Tex0;'#13#10
  583. GetTextureCombiners('Tex0:=Tex1*Tex0;'#13#10
  584. + 'Tex1:=Tex0+Col;'#13#10
  585. + 'Tex2:=Tex1+Tex2-0.5;');
  586. GL.Color4f(0.0, 0.3, 0.3, 1);
  587. end
  588. else
  589. begin
  590. //SetupTextureCombiners('Tex0:=Tex1*Tex0;'#13#10
  591. GetTextureCombiners('Tex0:=Tex1*Tex0;'#13#10
  592. + 'Tex1:=Tex0+Col;');
  593. GL.Color4f(0.0, 0.4, 0.7, 1);
  594. end;
  595. }
  596. GL.Color4f(0.0, 0.4, 0.7, 1);
  597. rci.GLStates.Disable(stCullFace);
  598. for y := -10 to 10 - 1 do
  599. begin
  600. GL.Begin_(GL_QUAD_STRIP);
  601. for x := -10 to 10 do
  602. begin
  603. SetVector(pos, x * 1500, 0, y * 1500);
  604. tex := TexPointMake(x, y);
  605. GL.MultiTexCoord2fv(GL_TEXTURE0, @tex);
  606. GL.MultiTexCoord2fv(GL_TEXTURE1, @tex);
  607. GL.MultiTexCoord3fv(GL_TEXTURE2, @pos);
  608. GL.Vertex3fv(@pos);
  609. SetVector(pos, x * 1500, 0, (y + 1) * 1500);
  610. tex := TexPointMake(x, (y + 1));
  611. GL.MultiTexCoord3fv(GL_TEXTURE0, @tex);
  612. GL.MultiTexCoord3fv(GL_TEXTURE1, @tex);
  613. GL.MultiTexCoord3fv(GL_TEXTURE2, @pos);
  614. GL.Vertex3fv(@pos);
  615. end;
  616. GL.End_;
  617. end;
  618. rci.GLStates.ResetGLTextureMatrix;
  619. end;
  620. procedure TForm1.DOGLSLWaterPlaneRender(Sender: TObject;
  621. var rci: TGLRenderContextInfo);
  622. var
  623. x, y: Integer;
  624. begin
  625. if not (enableGLSL and enableTex2DReflection) then
  626. Exit;
  627. if not Assigned(reflectionProgram) then
  628. begin
  629. reflectionProgram := TGLProgramHandle.CreateAndAllocate;
  630. reflectionProgram.AddShader(TGLVertexShaderHandle, string(LoadAnsiStringFromFile('water_vp.glsl')),True);
  631. reflectionProgram.AddShader(TGLFragmentShaderHandle, string(LoadAnsiStringFromFile('water_fp.glsl')),True);
  632. if not reflectionProgram.LinkProgram then
  633. raise Exception.Create(reflectionProgram.InfoLog);
  634. if not reflectionProgram.ValidateProgram then
  635. raise Exception.Create(reflectionProgram.InfoLog);
  636. end;
  637. reflectionProgram.UseProgramObject;
  638. reflectionProgram.Uniform1f['Time'] := GLCadencer.CurrentTime;
  639. reflectionProgram.Uniform4f['EyePos'] := Camera.AbsolutePosition;
  640. rci.GLStates.TextureBinding[0, mirrorTexType] := mirrorTexture.Handle;
  641. rci.GLStates.SetGLTextureMatrix(GetTextureReflectionMatrix);
  642. reflectionProgram.Uniform1i['ReflectionMap'] := 0;
  643. rci.GLStates.TextureBinding[1, ttTexture2D] := MLWater.Materials[1].Material.Texture.Handle;
  644. reflectionProgram.Uniform1i['WaveMap'] := 1;
  645. for y := -10 to 10 - 1 do
  646. begin
  647. GL.Begin_(GL_QUAD_STRIP);
  648. for x := -10 to 10 do
  649. begin
  650. GL.Vertex3f(x * 1500, 0, y * 1500);
  651. GL.Vertex3f(x * 1500, 0, (y + 1) * 1500);
  652. end;
  653. GL.End_;
  654. end;
  655. reflectionProgram.EndUseProgramObject;
  656. end;
  657. // SetupReflectionMatrix
  658. //
  659. function TForm1.GetTextureReflectionMatrix: TGLMatrix;
  660. const
  661. cBaseMat: TGLMatrix =
  662. (V:((X:0.5; Y:0; Z:0; W:0),
  663. (X:0; Y:0.5; Z:0; W:0),
  664. (X:0; Y:0; Z:1; W:0),
  665. (X:0.5; Y:0.5; Z:0; W:1)));
  666. var
  667. w, h: Single;
  668. begin
  669. if mirrorTexType = ttTexture2D then
  670. begin
  671. w := 0.5 * SceneViewer.Width / RoundUpToPowerOf2(SceneViewer.Width);
  672. h := 0.5 * SceneViewer.Height / RoundUpToPowerOf2(SceneViewer.Height);
  673. end
  674. else
  675. begin
  676. w := 0.5 * SceneViewer.Width;
  677. h := 0.5 * SceneViewer.Height;
  678. end;
  679. Result := CreateTranslationMatrix(VectorMake(w, h, 0));
  680. Result := MatrixMultiply(CreateScaleMatrix(VectorMake(w, h, 0)), Result);
  681. with CurrentGLContext.PipelineTransformation do
  682. Result := MatrixMultiply(ViewProjectionMatrix^, Result);
  683. // Camera.ApplyPerspective(SceneViewer.Buffer.ViewPort, SceneViewer.Width, SceneViewer.Height, 96);
  684. // Camera.Apply;
  685. Result := MatrixMultiply(CreateScaleMatrix(VectorMake(1, -1, 1)), Result);
  686. end;
  687. end.