unit ex1; {$mode objfpc}{$H+} interface { This is a simple 3D objet, a pyramid with a hexagonal base. The object is designed in the constructor. The CreateObject method returns an interface to an empty object. An interface is similar to a class except you don't have to call Free. A 3D object has a MainPart property, which contains the vertices describing the objet. It can contains subparts, but here it is not the case. Parts can be rotated and scaled relative to their container. The MainPart is rotated and scaled relative to the whole scene. Faces are created using vertices, so that they will follow the movements of these vertices. Here the default color SandColor is defined for the whole object. In order to make it attractive, a lighting is defined. The simplest way is to use a directional light, so that you don't have to bother with the coordinates of the light source. The background is filled with a gradient. Note that it is a vertical gradient which is very fast to draw, because each scanline is filled with one color. } uses Classes, SysUtils, BGRAScene3D, BGRABitmapTypes {$IFNDEF NO_OPENGL_SURFACE}, BGRAOpenGL, BGRAOpenGL3D{$ENDIF}; type { TExample1 } TExample1 = class({$IFNDEF NO_OPENGL_SURFACE}TBGLScene3D{$ELSE}TBGRAScene3D{$ENDIF}) SandColor: TBGRAPixel; constructor Create; procedure Render; override; {$IFNDEF NO_OPENGL_SURFACE} procedure RenderGL(ACanvas: TBGLCustomCanvas; AMaxZ: single=1000); override; {$ENDIF} end; implementation { TExample1 } constructor TExample1.Create; var base: array of IBGRAVertex3D; top: IBGRAVertex3D; begin inherited Create; SandColor := BGRA(255,240,128); //create a pyramid with CreateObject(SandColor) do begin top := MainPart.Add(0,-15,0); //pyramid base is in a clockwise order if we look the pyramid from under base := MainPart.Add([-20,15,-20, 0,15,-30, 20,15,-20, 20,15,20, 0,15,30, -20,15,20]); AddFace(base); //add four faces, the three vertices are in a clockwise order AddFace([base[0],top,base[1]]); AddFace([base[1],top,base[2]]); AddFace([base[2],top,base[3]]); AddFace([base[3],top,base[4]]); AddFace([base[4],top,base[5]]); AddFace([base[5],top,base[0]]); MainPart.Scale(1.3); MainPart.RotateYDeg(30); MainPart.RotateXDeg(20); MainPart.Translate(0,-5,0); end; //set ambiant lightness to dark (1 is normal lightness, 2 is complete whiteness) AmbiantLightness := 0.5; //add a directional light from top-left, maximum lightness will be 0.5 + 1 = 1.5 AddDirectionalLight(Point3D(1,1,1),0.5); //we can have high quality antialiasing because it is a simple scene RenderingOptions.PerspectiveMode := pmLinearMapping; end; procedure TExample1.Render; begin //fill background Surface.GradientFill(0,0,Surface.Width,Surface.Height, MergeBGRA(SandColor,1,BGRABlack,1), MergeBGRA(SandColor,1,BGRABlack,2), gtLinear,PointF(0,0),PointF(0,Surface.Height),dmSet); inherited Render; end; {$IFNDEF NO_OPENGL_SURFACE} procedure TExample1.RenderGL(ACanvas: TBGLCustomCanvas; AMaxZ: single); begin //fill background ACanvas.FillRectLinearColor(0,0,BGLCanvas.Width,BGLCanvas.Height, MergeBGRA(SandColor,1,BGRABlack,1),MergeBGRA(SandColor,1,BGRABlack,1), MergeBGRA(SandColor,1,BGRABlack,2),MergeBGRA(SandColor,1,BGRABlack,2), False); inherited RenderGL(ACanvas, AMaxZ); end; {$ENDIF} end.