fShadedTerrainD.pas 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. unit fShadedTerrainD;
  2. interface
  3. uses
  4. Winapi.Windows,
  5. Winapi.OpenGL,
  6. System.SysUtils,
  7. System.UITypes,
  8. System.Classes,
  9. System.Math,
  10. Vcl.Graphics,
  11. Vcl.Controls,
  12. Vcl.Forms,
  13. Vcl.Imaging.Jpeg,
  14. Vcl.ExtCtrls,
  15. Vcl.ComCtrls,
  16. Vcl.StdCtrls,
  17. GLS.Scene,
  18. GLS.BaseClasses,
  19. GLS.Objects,
  20. GLS.Keyboard,
  21. GLS.TerrainRenderer,
  22. GLS.ROAMPatch,
  23. GLS.HeightData,
  24. GLS.Cadencer,
  25. GLS.Texture,
  26. GLS.SkyDome,
  27. GLS.SceneViewer,
  28. GLScene.VectorTypes,
  29. GLScene.VectorGeometry,
  30. GLS.LensFlare,
  31. GLS.BumpMapHDS,
  32. GLSL.TextureShaders,
  33. GLS.Material,
  34. GLS.Coordinates,
  35. GLS.State,
  36. GLScene.Utils;
  37. type
  38. TFormShadedTerrain = class(TForm)
  39. GLSceneViewer1: TGLSceneViewer;
  40. GLBitmapHDS1: TGLBitmapHDS;
  41. GLScene1: TGLScene;
  42. GLCamera1: TGLCamera;
  43. DummyCube1: TGLDummyCube;
  44. TerrainRenderer1: TGLTerrainRenderer;
  45. Timer1: TTimer;
  46. GLCadencer1: TGLCadencer;
  47. GLMaterialLibrary1: TGLMaterialLibrary;
  48. SkyDome1: TGLSkyDome;
  49. SPSun: TGLSprite;
  50. GLLensFlare: TGLLensFlare;
  51. GLDummyCube1: TGLDummyCube;
  52. GLTexCombineShader1: TGLTexCombineShader;
  53. GLBumpmapHDS1: TGLBumpmapHDS;
  54. Panel1: TPanel;
  55. Label1: TLabel;
  56. TBSubSampling: TTrackBar;
  57. LASubFactor: TLabel;
  58. Label2: TLabel;
  59. TBIntensity: TTrackBar;
  60. LABumpIntensity: TLabel;
  61. TBContourInterval: TTrackBar;
  62. TBScaleZ: TTrackBar;
  63. LaScaleZ: TLabel;
  64. LabelZ: TLabel;
  65. LabelContInterval: TLabel;
  66. CBContourIntervals: TCheckBox;
  67. procedure GLSceneViewer1MouseDown(Sender: TObject; Button: TMouseButton;
  68. Shift: TShiftState; X, Y: Integer);
  69. procedure GLSceneViewer1MouseMove(Sender: TObject; Shift: TShiftState;
  70. X, Y: Integer);
  71. procedure Timer1Timer(Sender: TObject);
  72. procedure GLCadencer1Progress(Sender: TObject;
  73. const deltaTime, newTime: Double);
  74. procedure FormCreate(Sender: TObject);
  75. procedure FormKeyPress(Sender: TObject; var Key: Char);
  76. procedure GLSceneViewer1BeforeRender(Sender: TObject);
  77. procedure GLBumpmapHDS1NewTilePrepared(Sender: TGLBumpmapHDS;
  78. heightData: TGLHeightData; normalMapMaterial: TGLLibMaterial);
  79. procedure TBSubSamplingChange(Sender: TObject);
  80. procedure FormShow(Sender: TObject);
  81. procedure TBIntensityChange(Sender: TObject);
  82. procedure FormMouseWheel(Sender: TObject; Shift: TShiftState;
  83. WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
  84. procedure TBScaleZChange(Sender: TObject);
  85. procedure TBContourIntervalChange(Sender: TObject);
  86. procedure CBContourIntervalsClick(Sender: TObject);
  87. public
  88. mx, my: Integer;
  89. fullScreen: Boolean;
  90. FCamHeight: Single;
  91. end;
  92. var
  93. FormShadedTerrain: TFormShadedTerrain;
  94. implementation
  95. {$R *.DFM}
  96. procedure TFormShadedTerrain.FormCreate(Sender: TObject);
  97. begin
  98. var Path: TFileName := GetCurrentAssetPath();
  99. SetCurrentDir(Path + '\texture');
  100. // Load Terrain in 8 MB height data cache
  101. // Note this is the data size in terms of elevation samples, it does not
  102. // take into account all the data required/allocated by the renderer
  103. GLBitmapHDS1.MaxPoolSize := 8 * 1024 * 1024;
  104. // specify a map for height field data
  105. GLBitmapHDS1.Picture.LoadFromFile('terrain.bmp');
  106. GLMaterialLibrary1.LibMaterialByName('details').Material.Texture.Image.LoadFromFile('detailmap.jpg');
  107. // GLMaterialLibrary1.LibMaterialByName('texture').Material.Texture.Image.LoadFromFile('snow512.jpg');
  108. SPSun.Material.Texture.Image.LoadFromFile('flare1.bmp');
  109. // Could've been done at design time, but then it hurts the eyes ;)
  110. GLSceneViewer1.Buffer.BackgroundColor := clWhite;
  111. // Initial camera height offset (controled with pageUp/pageDown)
  112. FCamHeight := 20;
  113. // apply texture map scale (our heightmap size is 256)
  114. TerrainRenderer1.TilesPerTexture := 4; // 256/TerrainRenderer1.TileSize;
  115. // TerrainRenderer1.MaterialLibrary := GLMaterialLibrary1;
  116. TerrainRenderer1.ContourWidth := 2;
  117. TBIntensityChange(Self);
  118. TBScaleZChange(Self);
  119. end;
  120. procedure TFormShadedTerrain.FormShow(Sender: TObject);
  121. begin
  122. TBSubSamplingChange(Self);
  123. TBContourIntervalChange(Self);
  124. end;
  125. procedure TFormShadedTerrain.GLBumpmapHDS1NewTilePrepared(Sender: TGLBumpmapHDS;
  126. heightData: TGLHeightData; normalMapMaterial: TGLLibMaterial);
  127. var
  128. Vec: TGLVector;
  129. begin
  130. heightData.MaterialName := normalMapMaterial.Name;
  131. normalMapMaterial.Texture2Name := 'contrast';//'details', 'texture' or 'contrast';
  132. normalMapMaterial.Shader := GLTexCombineShader1;
  133. normalMapMaterial.Material.MaterialOptions := [moNoLighting];
  134. Vec := VectorNormalize(SPSun.AbsolutePosition);
  135. ScaleVector(Vec, 0.5);
  136. Vec.Y := -Vec.Y;
  137. Vec.Z := -Vec.Z;
  138. AddVector(Vec, 0.5);
  139. normalMapMaterial.Material.FrontProperties.Diffuse.Color := Vec;
  140. end;
  141. procedure TFormShadedTerrain.GLCadencer1Progress(Sender: TObject;
  142. const deltaTime, newTime: Double);
  143. var
  144. speed: Single;
  145. begin
  146. // handle keypresses
  147. if IsKeyDown(VK_SHIFT) then
  148. speed := 10 * deltaTime
  149. else
  150. speed := deltaTime;
  151. with GLCamera1.Position do
  152. begin
  153. if IsKeyDown(VK_UP) then
  154. DummyCube1.Translate(-X * speed, 0, -Z * speed);
  155. if IsKeyDown(VK_DOWN) then
  156. DummyCube1.Translate(X * speed, 0, Z * speed);
  157. if IsKeyDown(VK_LEFT) then
  158. DummyCube1.Translate(-Z * speed, 0, X * speed);
  159. if IsKeyDown(VK_RIGHT) then
  160. DummyCube1.Translate(Z * speed, 0, -X * speed);
  161. if IsKeyDown(VK_PRIOR) then
  162. FCamHeight := FCamHeight + 10 * speed;
  163. if IsKeyDown(VK_NEXT) then
  164. FCamHeight := FCamHeight - 10 * speed;
  165. if IsKeyDown(VK_ESCAPE) then
  166. Close;
  167. end;
  168. // don't drop through terrain!
  169. with DummyCube1.Position do
  170. Y := TerrainRenderer1.InterpolatedHeight(AsVector) + FCamHeight;
  171. end;
  172. // Standard mouse rotation & FPS code below
  173. procedure TFormShadedTerrain.GLSceneViewer1MouseDown(Sender: TObject; Button: TMouseButton;
  174. Shift: TShiftState; X, Y: Integer);
  175. begin
  176. GLSceneViewer1.SetFocus;
  177. mx := X;
  178. my := Y;
  179. end;
  180. procedure TFormShadedTerrain.GLSceneViewer1MouseMove(Sender: TObject; Shift: TShiftState;
  181. X, Y: Integer);
  182. begin
  183. if ssLeft in Shift then
  184. begin
  185. GLCamera1.MoveAroundTarget((my - Y) * 0.5, (mx - X) * 0.5);
  186. mx := X;
  187. my := Y;
  188. end;
  189. end;
  190. procedure TFormShadedTerrain.Timer1Timer(Sender: TObject);
  191. begin
  192. Caption := 'Shaded Terrain ' + GLSceneViewer1.FramesPerSecondText;
  193. GLSceneViewer1.ResetPerformanceMonitor;
  194. end;
  195. procedure TFormShadedTerrain.FormKeyPress(Sender: TObject; var Key: Char);
  196. begin
  197. case Key of
  198. 'w', 'W':
  199. with GLMaterialLibrary1.Materials[0].Material do
  200. begin
  201. if PolygonMode = pmLines then
  202. PolygonMode := pmFill
  203. else
  204. PolygonMode := pmLines;
  205. end;
  206. '+':
  207. if GLCamera1.DepthOfView < 2000 then
  208. begin
  209. GLCamera1.DepthOfView := GLCamera1.DepthOfView * 1.2;
  210. with GLSceneViewer1.Buffer.FogEnvironment do
  211. begin
  212. FogEnd := FogEnd * 1.2;
  213. FogStart := FogStart * 1.2;
  214. end;
  215. end;
  216. '-':
  217. if GLCamera1.DepthOfView > 300 then
  218. begin
  219. GLCamera1.DepthOfView := GLCamera1.DepthOfView / 1.2;
  220. with GLSceneViewer1.Buffer.FogEnvironment do
  221. begin
  222. FogEnd := FogEnd / 1.2;
  223. FogStart := FogStart / 1.2;
  224. end;
  225. end;
  226. '*':
  227. with TerrainRenderer1 do
  228. if CLODPrecision > 10 then
  229. CLODPrecision := Round(CLODPrecision * 0.8);
  230. '/':
  231. with TerrainRenderer1 do
  232. if CLODPrecision < 1000 then
  233. CLODPrecision := Round(CLODPrecision * 1.2);
  234. 'l':
  235. with GLLensFlare do
  236. Visible := (not Visible) and SPSun.Visible;
  237. end;
  238. Key := #0;
  239. end;
  240. procedure TFormShadedTerrain.FormMouseWheel(Sender: TObject; Shift: TShiftState;
  241. WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
  242. begin
  243. if GLSceneViewer1.Focused then
  244. GLCamera1.AdjustDistanceToTarget(Power(1.02, WheelDelta / 120));
  245. end;
  246. procedure TFormShadedTerrain.GLSceneViewer1BeforeRender(Sender: TObject);
  247. var
  248. TexUnits: Cardinal;
  249. begin
  250. if GLTexCombineShader1.Enabled then
  251. begin
  252. GLSceneViewer1.Buffer.RenderingContext.Activate;
  253. TexUnits := GLSceneViewer1.Buffer.LimitOf[limNbTextureUnits];
  254. GLSceneViewer1.Buffer.RenderingContext.Deactivate;
  255. if TexUnits < 4 then
  256. begin
  257. Application.MessageBox
  258. ('Not enough texture units! The shader will be disabled.',
  259. 'Error', MB_OK);
  260. GLTexCombineShader1.Enabled := False;
  261. end;
  262. end;
  263. GLLensFlare.PreRender(Sender as TGLSceneBuffer);
  264. end;
  265. procedure TFormShadedTerrain.TBSubSamplingChange(Sender: TObject);
  266. begin
  267. GLBumpmapHDS1.SubSampling := (1 shl TBSubSampling.Position);
  268. LASubFactor.Caption := Format('(%d) -> %dx%1:d', [GLBumpmapHDS1.SubSampling,
  269. TerrainRenderer1.TileSize div GLBumpmapHDS1.SubSampling]);
  270. // don't leave the focus to the trackbar, otherwise it'll keep some keystrokes
  271. // for itself, like the arrow keys
  272. SetFocus;
  273. end;
  274. procedure TFormShadedTerrain.TBIntensityChange(Sender: TObject);
  275. var
  276. i: Integer;
  277. bmp: TBitmap;
  278. begin
  279. with GLMaterialLibrary1.LibMaterialByName('contrast').Material do
  280. begin
  281. bmp := TBitmap.Create;
  282. try
  283. bmp.PixelFormat := pf24bit;
  284. bmp.Width := 1;
  285. bmp.Height := 1;
  286. i := 255;
  287. bmp.Canvas.Pixels[0, 0] := RGB(i, i, i);
  288. Texture.Image.Assign(bmp);
  289. finally
  290. bmp.Free;
  291. end;
  292. i := (TBIntensity.Position * 255) div 100;
  293. Texture.EnvColor.AsWinColor := RGB(i, i, i);
  294. end;
  295. LABumpIntensity.Caption := IntToStr(TBIntensity.Position) + ' %';
  296. end;
  297. procedure TFormShadedTerrain.TBContourIntervalChange(Sender: TObject);
  298. begin
  299. TerrainRenderer1.ContourInterval := TBContourInterval.Position;
  300. LabelContInterval.Caption := IntToStr(TerrainRenderer1.ContourInterval);
  301. end;
  302. procedure TFormShadedTerrain.TBScaleZChange(Sender: TObject);
  303. begin
  304. TerrainRenderer1.Scale.Z := TBScaleZ.Position / 20;
  305. LabelZ.Caption := FloatToStrF(TerrainRenderer1.Scale.Z, ffFixed, 5, 2);
  306. end;
  307. procedure TFormShadedTerrain.CBContourIntervalsClick(Sender: TObject);
  308. begin
  309. if CBContourIntervals.Checked = True then
  310. TerrainRenderer1.ContourInterval := TBContourInterval.Position
  311. else
  312. TerrainRenderer1.ContourInterval := 0;
  313. TBContourinterval.SetFocus;
  314. end;
  315. end.