This is an old revision of the document!


Billboard

A billboard controls proxy objects of a basis mesh instance (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.

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.Bitmap.LoadFromFile('grass1.png');
 
    LPoolE := Bitmaps.Add() as TGorillaBitmapPoolEntry;
    LPoolE.Bitmap.LoadFromFile('grass2.png');
 
    LPoolE := Bitmaps.Add() as TGorillaBitmapPoolEntry;
    LPoolE.Bitmap.LoadFromFile('grass3.png');
 
    LPoolE := Bitmaps.Add() as TGorillaBitmapPoolEntry;
    LPoolE.Bitmap.LoadFromFile('grass4.png');
  end;  
 
  // creating the billboard control
  FGrass := TGorillaBillboard.Create(FGorilla);
  FGrass .Parent := FGorilla;
  FGrass.SourceObject := 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
  LAlg := TGorillaBillboardRectFilling.Create(FGrass);
  try
    FGrass.Fill(LAlg, true);
  finally
    FreeAndNil(LAlg);
  end;

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:

Form1.pas
  FGrassMat.SpotRadius := 0.5;
  FGrassMat.SpotEnabled := true;

And in the OnMouseMove event we can set the current interaction point like this:

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;

Next step: Inventory