fForestD.pas 22 KB

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