fForestD.pas 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767
  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. Stage.VectorTypes,
  18. Stage.VectorGeometry,
  19. Stage.OpenGLTokens,
  20. GLS.XCollection,
  21. GLS.VectorLists,
  22. GLS.PersistentClasses,
  23. GLS.BaseClasses,
  24. Stage.TextureFormat,
  25. Stage.Keyboard,
  26. GLS.SceneViewer,
  27. GLS.Cadencer,
  28. GLS.Texture,
  29. GLS.Scene,
  30. GLS.Objects,
  31. GLS.Tree,
  32. GLS.BitmapFont,
  33. GLS.Context,
  34. GLS.WindowsFont,
  35. GLS.HUDObjects,
  36. GLS.SkyDome,
  37. GLS.Imposter,
  38. GLS.ParticleFX,
  39. GLS.Graphics,
  40. GLS.XOpenGL,
  41. Stage.PipelineTransform,
  42. GLS.TextureCombiners,
  43. GLS.Material,
  44. GLS.Coordinates,
  45. GLS.TerrainRenderer,
  46. GLS.HeightData,
  47. GLS.HeightTileFileHDS,
  48. GLS.RenderContextInfo,
  49. GLS.Screen,
  50. GLS.State,
  51. GLS.FileTGA,
  52. Stage.Utils;
  53. type
  54. TFormForest = class(TForm)
  55. SceneViewer: TGLSceneViewer;
  56. GLScene: TGLScene;
  57. MLTrees: TGLMaterialLibrary;
  58. MLTerrain: TGLMaterialLibrary;
  59. GLCadencer: TGLCadencer;
  60. Terrain: TGLTerrainRenderer;
  61. Camera: TGLCamera;
  62. Light: TGLLightSource;
  63. GLHUDText1: TGLHUDText;
  64. GLWindowsBitmapFont1: TGLWindowsBitmapFont;
  65. EarthSkyDome: TGLEarthSkyDome;
  66. GLRenderPoint: TGLRenderPoint;
  67. SIBTree: TGLStaticImposterBuilder;
  68. DOTrees: TGLDirectOpenGL;
  69. PFXTrees: TGLCustomPFXManager;
  70. RenderTrees: TGLParticleFXRenderer;
  71. Timer1: TTimer;
  72. MLWater: TGLMaterialLibrary;
  73. DOInitializeReflection: TGLDirectOpenGL;
  74. DOGLSLWaterPlane: TGLDirectOpenGL;
  75. DOClassicWaterPlane: TGLDirectOpenGL;
  76. GLHeightTileFileHDS: TGLHeightTileFileHDS;
  77. procedure FormCreate(Sender: TObject);
  78. procedure FormDestroy(Sender: TObject);
  79. procedure TerrainGetTerrainBounds(var l, t, r, b: Single);
  80. procedure GLCadencerProgress(Sender: TObject; const deltaTime, newTime: Double);
  81. procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  82. procedure DOTreesRender(Sender: TObject; var rci: TGLRenderContextInfo);
  83. procedure PFXTreesBeginParticles(Sender: TObject; var rci: TGLRenderContextInfo);
  84. procedure PFXTreesCreateParticle(Sender: TObject; aParticle: TGLParticle);
  85. procedure PFXTreesEndParticles(Sender: TObject; var rci: TGLRenderContextInfo);
  86. procedure PFXTreesRenderParticle(Sender: TObject; aParticle: TGLParticle;
  87. var rci: TGLRenderContextInfo);
  88. procedure SIBTreeImposterLoaded(Sender: TObject; impostoredObject: TGLBaseSceneObject;
  89. destImposter: TImposter);
  90. function SIBTreeLoadingImposter(Sender: TObject; impostoredObject: TGLBaseSceneObject;
  91. destImposter: TImposter): TGLBitmap32;
  92. procedure Timer1Timer(Sender: TObject);
  93. procedure PFXTreesProgress(Sender: TObject; const progressTime: TGLProgressTimes;
  94. var defaultProgress: Boolean);
  95. function PFXTreesGetParticleCountEvent(Sender: TObject): Integer;
  96. procedure FormResize(Sender: TObject);
  97. procedure DOInitializeReflectionRender(Sender: TObject; var rci: TGLRenderContextInfo);
  98. procedure DOGLSLWaterPlaneRender(Sender: TObject; var rci: TGLRenderContextInfo);
  99. procedure DOClassicWaterPlaneRender(Sender: TObject; var rci: TGLRenderContextInfo);
  100. procedure FormDeactivate(Sender: TObject);
  101. procedure FormShow(Sender: TObject);
  102. private
  103. // hscale, mapwidth, mapheight : Single;
  104. lmp: TPoint;
  105. camPitch, camTurn, camTime, curPitch, curTurn: Single;
  106. function GetTextureReflectionMatrix: TGLMatrix;
  107. public
  108. Path: TFileName;
  109. TestTree: TGLTree;
  110. TreesShown: Integer;
  111. nearTrees: TGLPersistentObjectList;
  112. Imposter: TImposter;
  113. densityBitmap: TBitmap;
  114. mirrorTexture: TGLTextureHandle;
  115. mirrorTexType: TGLTextureTarget;
  116. reflectionProgram: TGLProgramHandle;
  117. supportsGLSL: Boolean;
  118. enableGLSL: Boolean;
  119. enableRectReflection, enableTex2DReflection: Boolean;
  120. end;
  121. var
  122. FormForest: TFormForest;
  123. implementation // ------------------------------------------------------------
  124. {$R *.dfm}
  125. const
  126. cImposterCacheFile: string = 'imposters.bmp';
  127. cMapWidth: Integer = 1024;
  128. cMapHeight: Integer = 1024;
  129. cBaseSpeed: Single = 50;
  130. procedure TFormForest.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 TFormForest.FormDestroy(Sender: TObject);
  204. begin
  205. // RestoreDefaultMode;
  206. ShowCursor(True);
  207. nearTrees.Free;
  208. end;
  209. procedure TFormForest.FormResize(Sender: TObject);
  210. begin
  211. Camera.FocalLength := Width * 50 / 800;
  212. end;
  213. procedure TFormForest.FormDeactivate(Sender: TObject);
  214. begin
  215. Close;
  216. end;
  217. procedure TFormForest.FormShow(Sender: TObject);
  218. begin
  219. SetFocus;
  220. end;
  221. procedure TFormForest.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 TFormForest.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  263. begin
  264. case Key of
  265. VK_ESCAPE:
  266. FormForest.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 TFormForest.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 TFormForest.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 TFormForest.PFXTreesBeginParticles(Sender: TObject; var rci: TGLRenderContextInfo);
  323. begin
  324. Imposter := SIBTree.ImposterFor(TestTree);
  325. Imposter.BeginRender(rci);
  326. end;
  327. procedure TFormForest.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 TFormForest.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 TFormForest.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 TFormForest.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 TFormForest.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 TFormForest.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 TFormForest.PFXTreesGetParticleCountEvent(Sender: TObject): Integer;
  438. begin
  439. Result := TreesShown;
  440. end;
  441. procedure TFormForest.PFXTreesProgress(Sender: TObject; const progressTime: TGLProgressTimes;
  442. var defaultProgress: Boolean);
  443. begin
  444. defaultProgress := False;
  445. end;
  446. procedure TFormForest.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 TFormForest.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 TFormForest.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 TFormForest.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.