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