unit ex3; {$mode objfpc}{$H+} interface { This example is a cylinder. It aims at showing the difference between lighting normals modes. The lighting normals are the direction considered to be orthogonal to the surface. The box uses lnFace, which means that each face is considered to be flat. On the contrary, lamps are rounded, so their lighting normals are lnVertex, which means that the surface is considered to be rounded between faces, using vertices as a reference. Depending on the value of DefaultLightingNormal, the cylinder will look polygonal or rounded. The value lnFaceVertexMix is an intermediate between Face and Vertex, which allows to have some light diffusion effect while keeping an angle between faces. The SaturationLow and SaturationHigh properties of the material allows to create a shiny effect without actually computing reflected light. Simply when a pixel is very bright, it turns into white, as if we could see the reflection of some white beam. } uses Classes, SysUtils, BGRAScene3D, BGRABitmapTypes {$IFNDEF NO_OPENGL_SURFACE}, BGRAOpenGL3D{$ENDIF}; type { TExample3 } TExample3 = class({$IFNDEF NO_OPENGL_SURFACE}TBGLScene3D{$ELSE}TBGRAScene3D{$ENDIF}) constructor Create; end; implementation uses BGRAMatrix3D; { TExample3 } constructor TExample3.Create; const radius = 20; topY = -20; bottomY = 20; precision = 40; var bottom,top: array[1..precision] of IBGRAVertex3D; topCoord,bottomCoord: TPoint3D; rotateMatrix: TMatrix3D; i,j: Integer; begin inherited Create; DefaultMaterial.SpecularIndex := 50; DefaultMaterial.AutoSpecularColor:= true; //create a cylinder with CreateObject(BGRA(0,0,255)) do begin for j := 1 to 2 do begin //top and bottom coordinates topCoord := Point3D(radius,topY,0); bottomCoord := Point3D(radius,bottomY,0); //rotating around the Y axis rotateMatrix := MatrixRotateY(2*Pi/precision); //create the vertices for i := 1 to precision do begin //store in reverse order the second time if j = 2 then begin top[precision+1-i] := MainPart.Add(topCoord); bottom[precision+1-i] := MainPart.Add(bottomCoord); end else begin top[i] := MainPart.Add(topCoord); bottom[i] := MainPart.Add(bottomCoord); end; topCoord := rotateMatrix*topCoord; bottomCoord := rotateMatrix*bottomCoord; end; //add faces : the second time, there will be in the opposite direction because of the reverse order for i := 1 to precision do AddFace([top[i],top[(i mod precision)+1],bottom[(i mod precision)+1],bottom[i]]); end; //apply a rotation to show the top of the cylinder MainPart.RotateXDeg(30); 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),1,-0.5); end; end.