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