123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778 |
- unit fForest;
- interface
- uses
- Winapi.Windows,
- Winapi.OpenGL,
- Winapi.OpenGLext,
- System.SysUtils,
- System.Classes,
- System.Math,
- System.Types,
- Vcl.Graphics,
- Vcl.Controls,
- Vcl.Forms,
- Vcl.Dialogs,
- Vcl.Imaging.Jpeg,
- Vcl.ExtCtrls,
- GLS.OpenGLTokens,
- GLS.SceneViewer,
- GLS.Cadencer,
- GLS.Texture,
- GLS.VectorTypes,
- GLS.VectorGeometry,
- GLS.Scene,
- GLS.Objects,
- GLS.Tree,
- GLS.Keyboard,
- GLS.VectorLists,
- GLS.BitmapFont,
- GLS.Context,
- GLS.WindowsFont,
- GLS.HUDObjects,
- GLS.SkyDome,
- GLS.Imposter,
- GLS.ParticleFX,
- GLS.Graphics,
- GLS.PersistentClasses,
- GLS.PipelineTransformation,
- GLS.XOpenGL,
- GLS.BaseClasses,
- GLS.TextureCombiners,
- GLS.TextureFormat,
- GLS.Material,
- GLS.Coordinates,
- GLS.TerrainRenderer,
- GLS.HeightData,
- GLS.HeightTileFileHDS,
- GLS.RenderContextInfo,
- GLS.Screen,
- GLS.State,
- GLS.FileTGA,
- GLS.Utils;
- type
- TForm1 = class(TForm)
- SceneViewer: TGLSceneViewer;
- GLScene: TGLScene;
- MLTrees: TGLMaterialLibrary;
- MLTerrain: TGLMaterialLibrary;
- GLCadencer: TGLCadencer;
- Terrain: TGLTerrainRenderer;
- Camera: TGLCamera;
- Light: TGLLightSource;
- GLHUDText1: TGLHUDText;
- GLWindowsBitmapFont1: TGLWindowsBitmapFont;
- EarthSkyDome: TGLEarthSkyDome;
- GLRenderPoint: TGLRenderPoint;
- SIBTree: TGLStaticImposterBuilder;
- DOTrees: TGLDirectOpenGL;
- PFXTrees: TGLCustomPFXManager;
- RenderTrees: TGLParticleFXRenderer;
- Timer1: TTimer;
- MLWater: TGLMaterialLibrary;
- DOInitializeReflection: TGLDirectOpenGL;
- DOGLSLWaterPlane: TGLDirectOpenGL;
- DOClassicWaterPlane: TGLDirectOpenGL;
- GLHeightTileFileHDS: TGLHeightTileFileHDS;
- procedure FormCreate(Sender: TObject);
- procedure FormDestroy(Sender: TObject);
- procedure TerrainGetTerrainBounds(var l, t, r, b: Single);
- procedure GLCadencerProgress(Sender: TObject; const deltaTime,
- newTime: Double);
- procedure FormKeyDown(Sender: TObject; var Key: Word;
- Shift: TShiftState);
- procedure DOTreesRender(Sender: TObject; var rci: TGLRenderContextInfo);
- procedure PFXTreesBeginParticles(Sender: TObject;
- var rci: TGLRenderContextInfo);
- procedure PFXTreesCreateParticle(Sender: TObject; aParticle: TGLParticle);
- procedure PFXTreesEndParticles(Sender: TObject; var rci: TGLRenderContextInfo);
- procedure PFXTreesRenderParticle(Sender: TObject;
- aParticle: TGLParticle; var rci: TGLRenderContextInfo);
- procedure SIBTreeImposterLoaded(Sender: TObject;
- impostoredObject: TGLBaseSceneObject; destImposter: TImposter);
- function SIBTreeLoadingImposter(Sender: TObject;
- impostoredObject: TGLBaseSceneObject;
- destImposter: TImposter): TGLBitmap32;
- procedure Timer1Timer(Sender: TObject);
- procedure PFXTreesProgress(Sender: TObject;
- const progressTime: TGLProgressTimes; var defaultProgress: Boolean);
- function PFXTreesGetParticleCountEvent(Sender: TObject): Integer;
- procedure FormResize(Sender: TObject);
- procedure DOInitializeReflectionRender(Sender: TObject;
- var rci: TGLRenderContextInfo);
- procedure DOGLSLWaterPlaneRender(Sender: TObject;
- var rci: TGLRenderContextInfo);
- procedure DOClassicWaterPlaneRender(Sender: TObject;
- var rci: TGLRenderContextInfo);
- procedure FormDeactivate(Sender: TObject);
- procedure FormShow(Sender: TObject);
- private
-
- // hscale, mapwidth, mapheight : Single;
- lmp: TPoint;
- camPitch, camTurn, camTime, curPitch, curTurn: Single;
- function GetTextureReflectionMatrix: TGLMatrix;
- public
-
- TestTree: TGLTree;
- TreesShown: Integer;
- nearTrees: TPersistentObjectList;
- imposter: TImposter;
- densityBitmap: TBitmap;
- mirrorTexture: TGLTextureHandle;
- mirrorTexType: TGLTextureTarget;
- reflectionProgram: TGLProgramHandle;
- supportsGLSL: Boolean;
- enableGLSL: Boolean;
- enableRectReflection, enableTex2DReflection: Boolean;
- end;
- var
- Form1: TForm1;
- //-----------------------------------------------
- implementation
- //-----------------------------------------------
- {$R *.dfm}
- const
- cImposterCacheFile: string = 'imposters.bmp';
- cMapWidth: Integer = 1024;
- cMapHeight: Integer = 1024;
- cBaseSpeed: Single = 50;
- procedure TForm1.FormCreate(Sender: TObject);
- var
- density: TPicture;
- DataPath : TFileName;
- begin
- // go to 1024x768x32
- // SetFullscreenMode(GetIndexFromResolution(1024, 768, 32), 85);
- Application.OnDeactivate := FormDeactivate;
- DataPath := ExtractFilePath(ParamStr(0));
- Delete(DataPath, Length(DataPath) - 12, 12);
- DataPath := DataPath + 'Data\';
- SetCurrentDir(DataPath);
- // Load volcano textures
- MLTerrain.AddTextureMaterial('Terrain', 'volcano_TX_low.jpg').Texture2Name := 'Detail';
- MLTerrain.AddTextureMaterial('Detail', 'detailmap.jpg').Material.Texture.TextureMode := tmModulate;
- MLTerrain.AddTextureMaterial('Detail', 'detailmap.jpg').TextureScale.SetPoint(128, 128, 128);
- Terrain.Material.MaterialLibrary := MLTerrain;
- Terrain.Material.LibMaterialName := 'Terrain';
- // Load tree textures
- MLTrees.AddTextureMaterial('Leaf', 'leaf.tga').Material.Texture.TextureFormat := tfRGBA;
- MLTrees.AddTextureMaterial('Leaf', 'leaf.tga').Material.Texture.TextureMode := tmModulate;
- MLTrees.AddTextureMaterial('Leaf', 'leaf.tga').Material.Texture.MinFilter := miNearestMipmapNearest;
- MLTrees.AddTextureMaterial('Leaf', 'leaf.tga').Material.BlendingMode := bmAlphaTest50;
- MLTrees.AddTextureMaterial('Bark', 'zbark_016.jpg').Material.Texture.TextureMode := tmModulate;
- // Create test tree
- Randomize;
- TestTree := TGLTree(GLScene.Objects.AddNewChild(TGLTree));
- with TestTree do
- begin
- Visible := False;
- MaterialLibrary := MLTrees;
- LeafMaterialName := 'Leaf';
- LeafBackMaterialName := 'Leaf';
- BranchMaterialName := 'Bark';
- Up.SetVector(ZHmgVector);
- Direction.SetVector(YHmgVector);
- Depth := 9;
- BranchFacets := 6;
- LeafSize := 0.50;
- BranchAngle := 0.65;
- BranchTwist := 135;
- ForceTotalRebuild;
- end;
- SIBTree.RequestImposterFor(TestTree);
- densityBitmap := TBitmap.Create;
- try
- densityBitmap.PixelFormat := pf24bit;
- Density := TPicture.Create;
- try
- Density.LoadFromFile('volcano_trees.jpg');
- densityBitmap.Width := Density.Width;
- densityBitmap.Height := Density.Height;
- densityBitmap.Canvas.Draw(0, 0, Density.Graphic);
- finally
- Density.Free;
- end;
- PFXTrees.CreateParticles(10000);
- finally
- densityBitmap.Free;
- end;
- TreesShown := 2000;
- Light.Pitch(30);
- Camera.Position.Y := Terrain.InterpolatedHeight(Camera.Position.AsVector) + 10;
- lmp := ClientToScreen(Point(Width div 2, Height div 2));
- SetCursorPos(lmp.X, lmp.Y);
- ShowCursor(False);
- nearTrees := TPersistentObjectList.Create;
- camTurn := -60;
- enableRectReflection := False;
- enableTex2DReflection := False;
- end;
- procedure TForm1.FormDestroy(Sender: TObject);
- begin
- // RestoreDefaultMode;
- ShowCursor(True);
- nearTrees.Free;
- end;
- procedure TForm1.FormResize(Sender: TObject);
- begin
- Camera.FocalLength := Width * 50 / 800;
- end;
- procedure TForm1.FormDeactivate(Sender: TObject);
- begin
- Close;
- end;
- procedure TForm1.FormShow(Sender: TObject);
- begin
- SetFocus;
- end;
- procedure TForm1.GLCadencerProgress(Sender: TObject; const deltaTime,
- newTime: Double);
- var
- speed, z: Single;
- nmp: TPoint;
- begin
- // Camera movement
- if IsKeyDown(VK_SHIFT) then
- speed := deltaTime * cBaseSpeed * 10
- else
- speed := deltaTime * cBaseSpeed;
- if IsKeyDown(VK_UP) or IsKeyDown('W') or IsKeyDown('Z') then
- Camera.Move(speed)
- else if IsKeyDown(VK_DOWN) or IsKeyDown('S') then
- Camera.Move(-speed);
- if IsKeyDown(VK_LEFT) or IsKeyDown('A') or IsKeyDown('Q') then
- Camera.Slide(-speed)
- else if IsKeyDown(VK_RIGHT) or IsKeyDown('D') then
- Camera.Slide(speed);
- z := Terrain.Position.Y + Terrain.InterpolatedHeight(Camera.Position.AsVector);
- if z < 0 then
- z := 0;
- z := z + 10;
- if Camera.Position.Y < z then
- Camera.Position.Y := z;
- GetCursorPos(nmp);
- camTurn := camTurn - (lmp.X - nmp.X) * 0.2;
- camPitch := camPitch + (lmp.Y - nmp.Y) * 0.2;
- camTime := camTime + deltaTime;
- while camTime > 0 do
- begin
- curTurn := Lerp(curTurn, camTurn, 0.2);
- curPitch := Lerp(curPitch, camPitch, 0.2);
- Camera.Position.Y := Lerp(Camera.Position.Y, z, 0.2);
- camTime := camTime - 0.01;
- end;
- Camera.ResetRotations;
- Camera.Turn(curTurn);
- Camera.Pitch(curPitch);
- SetCursorPos(lmp.X, lmp.Y);
- SceneViewer.Invalidate;
- end;
- procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
- Shift: TShiftState);
- begin
- case key of
- VK_ESCAPE: Form1.Close;
- VK_ADD: if TreesShown < PFXTrees.Particles.ItemCount then
- TreesShown := TreesShown + 100;
- VK_SUBTRACT: if TreesShown > 0 then
- TreesShown := TreesShown - 100;
- Word('R'): enableTex2DReflection := not enableTex2DReflection;
- Word('G'): if supportsGLSL then
- begin
- enableGLSL := not enableGLSL;
- enableTex2DReflection := True;
- end;
- end;
- end;
- procedure TForm1.Timer1Timer(Sender: TObject);
- var
- hud: string;
- begin
- hud := Format('%.1f FPS - %d trees'#13#10'Tree sort: %f ms',
- [SceneViewer.FramesPerSecond, TreesShown, RenderTrees.LastSortTime]);
- if enableTex2DReflection then
- begin
- hud := hud + #13#10 + 'Water reflections';
- if enableRectReflection then
- hud := hud + ' (RECT)';
- end;
- if enableGLSL and enableTex2DReflection then
- hud := hud + #13#10 + 'GLSL water';
- GLHUDText1.Text := hud;
- SceneViewer.ResetPerformanceMonitor;
- Caption := Format('%.2f', [RenderTrees.LastSortTime]);
- end;
- procedure TForm1.PFXTreesCreateParticle(Sender: TObject;
- aParticle: TGLParticle);
- var
- u, v, p: Single;
- // x, y, i, j, dark : Integer;
- pixelX, pixelY: Integer;
- begin
- repeat
- repeat
- u := Random * 0.88 + 0.06;
- v := Random * 0.88 + 0.06;
- pixelX := Round(u * densityBitmap.Width);
- pixelY := Round(v * densityBitmap.Height);
- p := ((densityBitmap.Canvas.Pixels[pixelX, pixelY] shr 8) and 255) / 255;
- until p > Random;
- aParticle.PosX := (0.5 - u) * Terrain.Scale.X * cMapWidth;
- aParticle.PosY := 0;
- aParticle.PosZ := (0.5 - (1 - v)) * Terrain.Scale.Y * cMapHeight;
- aParticle.PosY := Terrain.Position.Y + Terrain.InterpolatedHeight(aParticle.Position);
- until aParticle.PosY >= 0;
- aParticle.Tag := Random(360);
- end;
- procedure TForm1.PFXTreesBeginParticles(Sender: TObject;
- var rci: TGLRenderContextInfo);
- begin
- imposter := SIBTree.ImposterFor(TestTree);
- imposter.BeginRender(rci);
- end;
- procedure TForm1.PFXTreesRenderParticle(Sender: TObject;
- aParticle: TGLParticle; var rci: TGLRenderContextInfo);
- const
- cTreeCenteringOffset: TAffineVector = (X:0; Y:30; Z:0);
- var
- d: Single;
- camPos: TGLVector;
- begin
- if not IsVolumeClipped(VectorAdd(aParticle.Position, cTreeCenteringOffset), 30, rci.rcci.frustum)
- then
- begin
- ;
- VectorSubtract(rci.cameraPosition, aParticle.Position, camPos);
- d := VectorNorm(camPos);
- if d > Sqr(180) then
- begin
- RotateVectorAroundY(PAffineVector(@camPos)^, aParticle.Tag * cPIdiv180);
- imposter.Render(rci, VectorMake(aParticle.Position), camPos, 10);
- end
- else
- begin
- nearTrees.Add(aParticle);
- end;
- end;
- end;
- procedure TForm1.PFXTreesEndParticles(Sender: TObject;
- var rci: TGLRenderContextInfo);
- var
- aParticle: TGLParticle;
- camPos: TGLVector;
- begin
- // Only 20 trees max rendered at full res, force imposter'ing the others
- while nearTrees.Count > 20 do
- begin
- aParticle := TGLParticle(nearTrees.First);
- VectorSubtract(rci.cameraPosition, aParticle.Position, camPos);
- RotateVectorAroundY(PAffineVector(@camPos)^, aParticle.Tag * cPIdiv180);
- imposter.Render(rci, VectorMake(aParticle.Position), camPos, 10);
- nearTrees.Delete(0);
- end;
- imposter.EndRender(rci);
- end;
- procedure TForm1.DOTreesRender(Sender: TObject;
- var rci: TGLRenderContextInfo);
- var
- i: Integer;
- particle: TGLParticle;
- TreeModelMatrix: TGLMatrix;
- begin
- rci.GLStates.Disable(stBlend);
- for i := 0 to nearTrees.Count - 1 do
- begin
- particle := TGLParticle(nearTrees[i]);
- TreeModelMatrix := MatrixMultiply(CreateTranslationMatrix(particle.Position),
- rci.PipelineTransformation.ViewMatrix^);
- TreeModelMatrix := MatrixMultiply(CreateScaleMatrix(VectorMake(10, 10, 10)),
- TreeModelMatrix);
- TreeModelMatrix := MatrixMultiply(CreateRotationMatrixY(DegToRad(-particle.Tag)),
- TreeModelMatrix);
- TreeModelMatrix := MatrixMultiply(CreateRotationMatrixX(DegToRad(Cos(GLCadencer.CurrentTime + particle.ID * 15) * 0.2)),
- TreeModelMatrix);
- TreeModelMatrix := MatrixMultiply(CreateRotationMatrixZ(DegToRad(Cos(GLCadencer.CurrentTime * 1.3 + particle.ID * 15) * 0.2)),
- TreeModelMatrix);
- TestTree.AbsoluteMatrix := TreeModelMatrix;
- TestTree.Render(rci);
- end;
- nearTrees.Clear;
- end;
- procedure TForm1.TerrainGetTerrainBounds(var l, t, r, b: Single);
- begin
- l := 0;
- t := cMapHeight;
- r := cMapWidth;
- b := 0;
- end;
- function TForm1.SIBTreeLoadingImposter(Sender: TObject;
- impostoredObject: TGLBaseSceneObject;
- destImposter: TImposter): TGLBitmap32;
- var
- bmp: TBitmap;
- cacheAge, exeAge: TDateTime;
- begin
- Tag := 1;
- Result := nil;
- if not FileExists(cImposterCacheFile) then
- Exit;
- FileAge(cImposterCacheFile, cacheAge, True);
- FileAge(ParamStr(0), exeAge, True);
- if cacheAge < exeAge then
- Exit;
- Tag := 0;
- bmp := TBitmap.Create;
- bmp.LoadFromFile(cImposterCacheFile);
- Result := TGLBitmap32.Create;
- Result.Assign(bmp);
- bmp.Free;
- end;
- procedure TForm1.SIBTreeImposterLoaded(Sender: TObject;
- impostoredObject: TGLBaseSceneObject; destImposter: TImposter);
- var
- bmp32: TGLBitmap32;
- bmp: TBitmap;
- begin
- if Tag = 1 then
- begin
- bmp32 := TGLBitmap32.Create;
- bmp32.AssignFromTexture2D(SIBTree.ImposterFor(TestTree).Texture);
- bmp := bmp32.Create32BitsBitmap;
- bmp.SaveToFile(cImposterCacheFile);
- bmp.Free;
- bmp32.Free;
- end;
- end;
- function TForm1.PFXTreesGetParticleCountEvent(Sender: TObject): Integer;
- begin
- Result := TreesShown;
- end;
- procedure TForm1.PFXTreesProgress(Sender: TObject;
- const progressTime: TGLProgressTimes; var defaultProgress: Boolean);
- begin
- defaultProgress := False;
- end;
- procedure TForm1.DOInitializeReflectionRender(Sender: TObject;
- var rci: TGLRenderContextInfo);
- var
- w, h: Integer;
- refMat: TGLMatrix;
- cameraPosBackup, cameraDirectionBackup: TGLVector;
- frustumBackup: TFrustum;
- clipPlane: TDoubleHmgPlane;
- glTarget: GLEnum;
- begin
- supportsGLSL := GL.ARB_shader_objects and GL.ARB_fragment_shader and GL.ARB_vertex_shader;
- enableRectReflection := GL.NV_texture_rectangle and ((not enableGLSL) or GL.EXT_Cg_shader);
- if not enableTex2DReflection then
- Exit;
- if not Assigned(mirrorTexture) then
- mirrorTexture := TGLTextureHandle.Create;
- rci.PipelineTransformation.Push;
- // Mirror coordinates
- refMat := MakeReflectionMatrix(NullVector, YVector);
- rci.PipelineTransformation.ViewMatrix^ :=
- MatrixMultiply(refMat, rci.PipelineTransformation.ViewMatrix^);
- rci.GLStates.FrontFace := fwClockWise;
- GL.Enable(GL_CLIP_PLANE0);
- SetPlane(clipPlane, PlaneMake(AffineVectorMake(0, 1, 0), VectorNegate(YVector)));
- GL.ClipPlane(GL_CLIP_PLANE0, @clipPlane);
- cameraPosBackup := rci.cameraPosition;
- cameraDirectionBackup := rci.cameraDirection;
- frustumBackup := rci.rcci.frustum;
- rci.cameraPosition := VectorTransform(rci.cameraPosition, refMat);
- rci.cameraDirection := VectorTransform(rci.cameraDirection, refMat);
- with rci.rcci.frustum do
- begin
- pLeft := VectorTransform(pLeft, refMat);
- pRight := VectorTransform(pRight, refMat);
- pTop := VectorTransform(pTop, refMat);
- pBottom := VectorTransform(pBottom, refMat);
- pNear := VectorTransform(pNear, refMat);
- pFar := VectorTransform(pFar, refMat);
- end;
- rci.PipelineTransformation.ViewMatrix^ := IdentityHmgMatrix;
- Camera.Apply;
- rci.PipelineTransformation.ViewMatrix^ :=
- MatrixMultiply(refMat, rci.PipelineTransformation.ViewMatrix^);
- EarthSkyDome.DoRender(rci, True, False);
- rci.PipelineTransformation.ModelMatrix^ := Terrain.AbsoluteMatrix;
- Terrain.DoRender(rci, True, False);
- rci.cameraPosition := cameraPosBackup;
- rci.cameraDirection := cameraDirectionBackup;
- rci.rcci.frustum := frustumBackup;
- // Restore to "normal"
- rci.PipelineTransformation.Pop;
- GLScene.SetupLights(TGLSceneBuffer(rci.buffer).LimitOf[limLights]);
- rci.GLStates.FrontFace := fwCounterClockWise;
- if enableRectReflection then
- begin
- mirrorTexType := ttTextureRect;
- w := SceneViewer.Width;
- h := SceneViewer.Height;
- end
- else
- begin
- mirrorTexType := ttTexture2D;
- w := RoundUpToPowerOf2(SceneViewer.Width);
- h := RoundUpToPowerOf2(SceneViewer.Height);
- end;
- glTarget := DecodeTextureTarget(mirrorTexType);
- mirrorTexture.AllocateHandle;
- if mirrorTexture.IsDataNeedUpdate then
- begin
- rci.GLStates.TextureBinding[0, mirrorTexType] := mirrorTexture.Handle;
- GL.TexParameteri(glTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- GL.TexParameteri(glTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- GL.TexParameteri(glTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- GL.TexParameteri(glTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- GL.CopyTexImage2d(glTarget, 0, GL_RGBA8, 0, 0, w, h, 0);
- mirrorTexture.NotifyDataUpdated;
- end
- else
- begin
- rci.GLStates.TextureBinding[0, mirrorTexType] := mirrorTexture.Handle;
- GL.CopyTexSubImage2D(glTarget, 0, 0, 0, 0, 0, w, h);
- end;
- GL.Clear(GL_COLOR_BUFFER_BIT + GL_DEPTH_BUFFER_BIT + GL_STENCIL_BUFFER_BIT);
- end;
- procedure TForm1.DOClassicWaterPlaneRender(Sender: TObject;
- var rci: TGLRenderContextInfo);
- const
- cWaveScale = 7;
- cWaveSpeed = 0.02;
- cSinScale = 0.02;
- var
- tex0Matrix, tex1Matrix: TGLMatrix;
- tWave: Single;
- pos: TAffineVector;
- tex: TTexPoint;
- x, y: Integer;
- begin
- if enableGLSL and enableTex2DReflection then
- Exit;
- tWave := GLCadencer.CurrentTime * cWaveSpeed;
- rci.GLStates.ActiveTexture := 0;
- rci.GLStates.TextureBinding[0, ttTexture2D] := MLWater.Materials[0].Material.Texture.Handle;
- rci.GLStates.ActiveTextureEnabled[ttTexture2D] := True;
- tex0Matrix := IdentityHmgMatrix;
- tex0Matrix.X.X := 3 * cWaveScale;
- tex0Matrix.Y.Y := 4 * cWaveScale;
- tex0Matrix.W.X := tWave * 1.1;
- tex0Matrix.W.Y := tWave * 1.06;
- rci.GLStates.SetGLTextureMatrix(tex0Matrix);
- rci.GLStates.ActiveTexture := 1;
- rci.GLStates.TextureBinding[0, ttTexture2D] := MLWater.Materials[0].Material.Texture.Handle;
- rci.GLStates.ActiveTextureEnabled[ttTexture2D] := True;
- tex1Matrix := IdentityHmgMatrix;
- tex1Matrix.X.X := cWaveScale;
- tex1Matrix.Y.Y := cWaveScale;
- tex1Matrix.W.X := tWave * 0.83;
- tex1Matrix.W.Y := tWave * 0.79;
- rci.GLStates.SetGLTextureMatrix(tex1Matrix);
- if enableTex2DReflection then
- begin
- rci.GLStates.ActiveTexture := 2;
- rci.GLStates.TextureBinding[2, mirrorTexType] := mirrorTexture.Handle;
- rci.GLStates.ActiveTextureEnabled[ttTexture2D] := True;
- rci.GLStates.SetGLTextureMatrix(GetTextureReflectionMatrix);
- end;
- rci.GLStates.ActiveTexture := 0;
- {
- if enableTex2DReflection then
- begin
- //SetupTextureCombiners('Tex0:=Tex1*Tex0;'#13#10
- GetTextureCombiners('Tex0:=Tex1*Tex0;'#13#10
- + 'Tex1:=Tex0+Col;'#13#10
- + 'Tex2:=Tex1+Tex2-0.5;');
- GL.Color4f(0.0, 0.3, 0.3, 1);
- end
- else
- begin
- //SetupTextureCombiners('Tex0:=Tex1*Tex0;'#13#10
- GetTextureCombiners('Tex0:=Tex1*Tex0;'#13#10
- + 'Tex1:=Tex0+Col;');
- GL.Color4f(0.0, 0.4, 0.7, 1);
- end;
- }
- GL.Color4f(0.0, 0.4, 0.7, 1);
- rci.GLStates.Disable(stCullFace);
- for y := -10 to 10 - 1 do
- begin
- GL.Begin_(GL_QUAD_STRIP);
- for x := -10 to 10 do
- begin
- SetVector(pos, x * 1500, 0, y * 1500);
- tex := TexPointMake(x, y);
- GL.MultiTexCoord2fv(GL_TEXTURE0, @tex);
- GL.MultiTexCoord2fv(GL_TEXTURE1, @tex);
- GL.MultiTexCoord3fv(GL_TEXTURE2, @pos);
- GL.Vertex3fv(@pos);
- SetVector(pos, x * 1500, 0, (y + 1) * 1500);
- tex := TexPointMake(x, (y + 1));
- GL.MultiTexCoord3fv(GL_TEXTURE0, @tex);
- GL.MultiTexCoord3fv(GL_TEXTURE1, @tex);
- GL.MultiTexCoord3fv(GL_TEXTURE2, @pos);
- GL.Vertex3fv(@pos);
- end;
- GL.End_;
- end;
- rci.GLStates.ResetGLTextureMatrix;
- end;
- procedure TForm1.DOGLSLWaterPlaneRender(Sender: TObject;
- var rci: TGLRenderContextInfo);
- var
- x, y: Integer;
- begin
- if not (enableGLSL and enableTex2DReflection) then
- Exit;
- if not Assigned(reflectionProgram) then
- begin
- reflectionProgram := TGLProgramHandle.CreateAndAllocate;
- reflectionProgram.AddShader(TGLVertexShaderHandle, string(LoadAnsiStringFromFile('water_vp.glsl')),True);
- reflectionProgram.AddShader(TGLFragmentShaderHandle, string(LoadAnsiStringFromFile('water_fp.glsl')),True);
- if not reflectionProgram.LinkProgram then
- raise Exception.Create(reflectionProgram.InfoLog);
- if not reflectionProgram.ValidateProgram then
- raise Exception.Create(reflectionProgram.InfoLog);
- end;
- reflectionProgram.UseProgramObject;
- reflectionProgram.Uniform1f['Time'] := GLCadencer.CurrentTime;
- reflectionProgram.Uniform4f['EyePos'] := Camera.AbsolutePosition;
- rci.GLStates.TextureBinding[0, mirrorTexType] := mirrorTexture.Handle;
- rci.GLStates.SetGLTextureMatrix(GetTextureReflectionMatrix);
- reflectionProgram.Uniform1i['ReflectionMap'] := 0;
- rci.GLStates.TextureBinding[1, ttTexture2D] := MLWater.Materials[1].Material.Texture.Handle;
- reflectionProgram.Uniform1i['WaveMap'] := 1;
- for y := -10 to 10 - 1 do
- begin
- GL.Begin_(GL_QUAD_STRIP);
- for x := -10 to 10 do
- begin
- GL.Vertex3f(x * 1500, 0, y * 1500);
- GL.Vertex3f(x * 1500, 0, (y + 1) * 1500);
- end;
- GL.End_;
- end;
- reflectionProgram.EndUseProgramObject;
- end;
- // SetupReflectionMatrix
- //
- function TForm1.GetTextureReflectionMatrix: TGLMatrix;
- const
- 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; Z:1; W:0),
- (X:0.5; Y:0.5; Z:0; W:1)));
- var
- w, h: Single;
- begin
- if mirrorTexType = ttTexture2D then
- begin
- w := 0.5 * SceneViewer.Width / RoundUpToPowerOf2(SceneViewer.Width);
- h := 0.5 * SceneViewer.Height / RoundUpToPowerOf2(SceneViewer.Height);
- end
- else
- begin
- w := 0.5 * SceneViewer.Width;
- h := 0.5 * SceneViewer.Height;
- end;
- Result := CreateTranslationMatrix(VectorMake(w, h, 0));
- Result := MatrixMultiply(CreateScaleMatrix(VectorMake(w, h, 0)), Result);
- with CurrentGLContext.PipelineTransformation do
- Result := MatrixMultiply(ViewProjectionMatrix^, Result);
- // Camera.ApplyPerspective(SceneViewer.Buffer.ViewPort, SceneViewer.Width, SceneViewer.Height, 96);
- // Camera.Apply;
- Result := MatrixMultiply(CreateScaleMatrix(VectorMake(1, -1, 1)), Result);
- end;
- end.
|