Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
billboard [2020/01/10 12:22] – [Example: Grass Billboard] adminbillboard [Unknown date] (current) – removed - external edit (Unknown date) 127.0.0.1
Line 1: Line 1:
-====== Billboard ====== 
  
-A billboard controls proxy instances of a basis mesh (source object). 
- 
-The billboard component is a mesh itself, into which proxies are merged. Much faster rendering is possible if proxy meshes are merge into one mesh, instead of rendering each mesh. 
- 
-We typically use this technique for grass or trees. 
-It is not suitable for animated meshes. 
- 
-===== Example: Grass Billboard ===== 
- 
-In this example we will display grass on multiplied planes inside of the billboard component. 
-After applying the TGorillaGrassMaterial we are able to render different textures onto those planes and to manipulate vertices. 
- 
-The result should be a varying grass landscape with waving grass. 
- 
-<file pascal Form1.pas> 
-procedure TForm1.FormCreate(Sender: TObject); 
-var LBillboard : TPlane; 
-    LPoolE : TGorillaBitmapPoolEntry; 
-    LGrassMat : TGorillaGrassMaterialSource; 
-    LAlg : TGorillaBillboardRectFilling; 
-begin 
-  // creating the source object - here a plane 
-  LBillboard := TPlane.Create(fGorilla); 
-  LBillboard.Scale.Point := Point3D(4, 4, 4); 
-   
-  // creating the grass material source 
-  FGrassMat := TGorillaGrassMaterialSource.Create(FGorilla); 
-  FGrassMat.Parent := FGorilla; 
-   
-  // now we load a pool of grass textures, the material shader 
-  // randomly chooses from 
-  with FGrassMat do 
-  begin 
-    LPoolE := Bitmaps.Add() as TGorillaBitmapPoolEntry; 
-    LPoolE.DisplayName := 'Grass1'; 
-    LPoolE.Bitmap.LoadFromFile('grass1.png'); 
- 
-    LPoolE := Bitmaps.Add() as TGorillaBitmapPoolEntry; 
-    LPoolE.DisplayName := 'Grass2'; 
-    LPoolE.Bitmap.LoadFromFile('grass2.png'); 
- 
-    LPoolE := Bitmaps.Add() as TGorillaBitmapPoolEntry; 
-    LPoolE.DisplayName := 'Grass3'; 
-    LPoolE.Bitmap.LoadFromFile('grass3.png'); 
- 
-    LPoolE := Bitmaps.Add() as TGorillaBitmapPoolEntry; 
-    LPoolE.DisplayName := 'Grass4'; 
-    LPoolE.Bitmap.LoadFromFile('grass4.png'); 
-  end;   
- 
-  // creating the billboard control 
-  FGrass := TGorillaBillboard.Create(FGorilla); 
-  FGrass .Parent := FGorilla; 
-  FGrass.AddSourceObject(LBillboard); 
-  FGrass.MaterialSource := LGrassMat; 
-  FGrass.SetSize(GORILLA_BILLBOARD_SIZE, GORILLA_BILLBOARD_SIZE, GORILLA_BILLBOARD_SIZE); 
- 
-  // create an individual filling algorithm to multiply the grass planes 
-  // on elder Gorilla3D version TGorillaBillboardRectFilling 
-  LAlg := TGorillaBillboardFlatFilling.Create(FGrass); 
-  try 
-    LAlg.Count := 1000; 
-    FGrass.Fill(LAlg, true); 
-  finally 
-    FreeAndNil(LAlg); 
-  end; 
-</file> 
- 
-==== Interact with grass shader ==== 
- 
-The default grass shader provides functionality to bend the grass planes at a certain point. 
-To enable interaction, f.e. at mouse position, we can simply configure the TGorillaGrassMaterialSource: 
- 
-<file pascal Form1.pas> 
-  FGrassMat.SpotRadius := 0.5; 
-  FGrassMat.SpotEnabled := true; 
-</file> 
- 
-And in the OnMouseMove event we can set the current interaction point like this: 
- 
-<file pascal Form1.pas> 
-procedure TForm1.DoOnViewportMouseMove(ASender : TObject; AShiftState : TShiftState; 
-  X, Y : Single); 
-var LPt3D : TPoint3D; 
-    LRayPos, LRayDir : TVector3D; 
-begin 
-  if FMove then 
-  begin 
-    if (ssLeft in AShiftState) then 
-    begin 
-      FGorilla.BeginUpdate(); 
-      try 
-        LPt3D := FGorilla.ScreenToWorld(PointF(X, Y)); 
-        FGorilla.Context.Pick(X, Y, TProjection.Camera, LRayPos, LRayDir); 
-        FGrass.RayCastIntersect(LRayPos, LRayDir, LPt3D); 
- 
-        // apply scaled light position 
-        FGrassMat.Spot := TPoint3D(LPt3D); 
-      finally 
-        FGorilla.EndUpdate(); 
-      end; 
-    end; 
- 
-    FLatest := PointF(X, Y); 
-  end; 
-end; 
-</file> 
- 
-===== Example: Terrain Grass Billboard ===== 
- 
-Since v0.8.1+ we've implemented a lot of new backend features (bounding volume hierarchy for TMeshDef, multiple billboard source objects, TGorillaModel support), which allows to multiple meshes and place those onto a terrain surface. 
- 
-The following example will create 64 billboards, filled up with 64 copies of a grass template model. The billboards will be attached as childs to the terrain and rendered above. 
-All billboards will be placed as grid above the complete terrain. 
- 
-__Notice:__ We could multiply the template model into a single billboard component, but the idea behind it, is to use the performance optimization of frustum culling. 
-By frustum culling only the visible billboard chunks will be rendered, therefore we can reduce vertex rendering a lot. 
- 
-So at first we will load a grass template model. //Keep the mesh as simple as possible, because vertex count will increase fastly.// 
- 
-To place a grass model copy in correct y-position on the terrain, we need to know vertices of the terrain. The new feature of bounding volume hierarchy (BVH) computation for TMeshDef's helps here a lot. It is 1000 times faster, than iterating of all vertices to find the correct position. 
- 
-For template model multiplication we use the new TGorillaBillboardTerrainFilling class, which automatically reads y-position from BVH. 
- 
-<file pascal> 
-const 
-  MAP_SIZE = 900; // terrain size (quadratic) 
-  MAP_HEIGHT = MAP_SIZE / 4; 
-   
-var FGrassTemps : Array[0..0] of TGorillaModel; 
- 
-procedure TForm1.CreateGrass(ATerrain : TGorillaTerrain; const AAssetsPath : String); 
-const  GORILLA_BILLBOARD_SIZE = 1; 
-      GORILLA_MODEL_GRASS_1 = 'lowpoly-grass-planes.obj'; 
- 
-var LTexPath      : String; 
-    LGrass        : TGorillaBillboard; 
-    LFillAlg      : TGorillaBillboardTerrainFilling; 
-    LChunks       : Integer; 
-    LChunksPerRow : Integer; 
-    i             : Integer; 
-    LChunkSize    : TPoint3D; 
-    LX, LZ        : Single; 
-begin 
-  if not Assigned(ATerrain) then 
-    raise Exception.Create('terrain not available - grass will be as child of the terrain'); 
- 
-  // load the grass templates 
-  LTexPath := IncludeTrailingPathDelimiter(AAssetsPath + 'grass'); 
-  FGrassTemps[0] := TGorillaModel.LoadNewModelFromFile(FViewport, nil, 
-    LTexPath + GORILLA_MODEL_GRASS_1, []); 
-  FGrassTemps[0].Visible := false; // it do not need to be shown 
- 
-  // create a list for all 64 billboard chunks 
-  FGrassBillboards := TList<TGorillaBillboard>.Create(); 
- 
-  // acquire a bounding volume hierarchy for much faster raytracing 
-  // after usage, it will be destroyed, because it consumes a lot memory 
-  // and we only need it for the moment 
-  TMeshDef(ATerrain.Def).AcquireBVH(); 
-  try 
-    LChunks := 64; 
-    LChunksPerRow := Ceil(Sqrt(LChunks)); 
- 
-    LChunkSize.X := (MAP_SIZE / LChunksPerRow); 
-    LChunkSize.Y := MAP_HEIGHT; 
-    LChunkSize.Z := (MAP_SIZE / LChunksPerRow); 
- 
-    for i := 0 to LChunks - 1 do 
-    begin 
-      // create multiple grass billboards to use frustum culling 
-      LGrass := TGorillaBillboard.Create(FViewport); 
-      LGrass.Parent := FViewport; 
-      LGrass.Opaque := false; // allow translucent rendering 
-      LGrass.TwoSide := true; 
-      LGrass.Name := 'Grass' + IntToStr(i + 1); 
- 
-      // add the grass model as source object 
-      // multiple source objects are possible and will be chosen randomly 
-      LGrass.AddSourceObject(FGrassTemps[0]); 
-       
-      // set the size of billboard chunk 
-      LGrass.SetSize(LChunkSize.X, LChunkSize.Y, LChunkSize.Z); 
- 
-      LX := -(MAP_SIZE / 2) + ((i mod LChunksPerRow) * LChunkSize.X); 
-      LZ := (MAP_SIZE / 2) - (Floor(i / LChunksPerRow) * LChunkSize.Z); 
- 
-      // place billboard chunk over terrain 
-      LGrass.Position.Point := Point3D(LX, 0, LZ); 
-      LGrass.MaterialSource := FGrassTemps[0].Meshes[0].MaterialSource; 
-      FGrassBillboards.Add(LGrass); 
- 
-      // fill up billboard chunk with 64 copies of our grass template 
-      LFillAlg := TGorillaBillboardTerrainFilling.Create(LGrass, ATerrain); 
-      try 
-        LFillAlg.Count := 64; 
-        LGrass.Fill(LFillAlg, true); 
-      finally 
-        FreeAndNil(LFillAlg); 
-      end; 
- 
-      // we put grass billboard into terrain model 
-      LGrass.Parent := ATerrain; 
-    end; 
-  finally 
-    // at the end we destroy the bounding volume hierarchy again to free memory 
-    TMeshDef(ATerrain.Def).ReleaseBVH(); 
-  end; 
-end; 
-</file> 
- 
-Next step: [[inventory|Inventory]]