204 lines
5.6 KiB
ObjectPascal

unit ex2;
{$mode objfpc}{$H+}
interface
{ This example draws a box. It comes with different flavors :
- e2lNone : without lighting but with water
- e2lLightness : with lighting and water
- e2lColored : with two lights of different colors, but without water
In this example, faces are textured. Each texture is generated with utexture unit.
Because we want to have a shiny effect on the box, we need to create different material.
The parameter of CreateMaterial is the exponent of the specular light, which is the
concentration of the reflected beam. The lamps are not shiny, but we must see some of the
light through them, that's why the LightThroughFactor is set to a small non zero number.
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. The example 3 show the difference
between these modes.
}
uses
Classes, SysUtils, BGRAScene3D, BGRABitmap, BGRABitmapTypes
{$IFNDEF NO_OPENGL_SURFACE}, BGRAOpenGL3D{$ENDIF};
type
TExample2Lighting = (e2lNone,e2lLightness,e2lColored);
{ TExample2 }
TExample2 = class({$IFNDEF NO_OPENGL_SURFACE}TBGLScene3D{$ELSE}TBGRAScene3D{$ENDIF})
private
water,wood,vWood: TBGRABitmap;
box,ground,light1,light2: IBGRAObject3D;
alpha: integer;
cury: single;
FLighting: TExample2Lighting;
procedure CreateScene;
procedure ApplyTexCoord(face: IBGRAFace3D; Times: integer = 1);
procedure SetLighting(AValue: TExample2Lighting);
public
constructor Create(ALighting: TExample2Lighting);
procedure Elapse;
destructor Destroy; override;
property Lighting: TExample2Lighting read FLighting write SetLighting;
end;
implementation
uses utexture;
const texSize = 256;
{ TExample2 }
constructor TExample2.Create(ALighting: TExample2Lighting);
begin
inherited Create;
//create textures
water := CreateWaterTexture(texSize,texSize);
vWood := CreateVerticalWoodTexture(texSize,texSize);
wood := CreateWoodTexture(texSize,texSize);
FLighting:= ALighting;
CreateScene;
end;
procedure TExample2.Elapse;
var dy: single;
begin
if light1 <> nil then light1.MainPart.RotateYDeg(1,False);
if light2 <> nil then light2.MainPart.RotateYDeg(-1.3,False);
if ground <> nil then
begin
dy := cos(alpha*Pi/180)*0.05;
cury += dy;
ground.MainPart.Translate(0,dy,0,False);
ViewPoint := Point3D(ViewPoint.x,-40+cury,ViewPoint.z);
LookAt(Point3D(0,cury,0),Point3D(0,-1,0));
inc(alpha);
if alpha = 360 then alpha := 0;
end;
end;
procedure TExample2.CreateScene;
var
base,v: array of IBGRAVertex3D;
lamp,shiny: IBGRAMaterial3D;
begin
Clear;
shiny := CreateMaterial(500);
lamp := CreateMaterial;
lamp.LightThroughFactor := 0.01;
//create wooden box
box := CreateObject(vWood);
with box do
begin
v := MainPart.Add([-1,-1,-1, 1,-1,-1, 1,1,-1, -1,1,-1,
-1,-1,+1, 1,-1,+1, 1,1,+1, -1,1,+1]);
ApplyTexCoord(AddFace([v[0],v[1],v[2],v[3]]));
ApplyTexCoord(AddFace([v[4],v[5],v[1],v[0]],wood));
ApplyTexCoord(AddFace([v[5],v[4],v[7],v[6]]));
ApplyTexCoord(AddFace([v[3],v[2],v[6],v[7]],wood));
ApplyTexCoord(AddFace([v[1],v[5],v[6],v[2]]));
ApplyTexCoord(AddFace([v[4],v[0],v[3],v[7]]));
MainPart.Scale(20);
end;
DefaultLightingNormal:= lnFace;
if Lighting = e2lColored then
begin
ViewPoint := Point3D(0,0,-150);
AmbiantLightColor := BGRA(192,192,192);
box.Material := shiny;
//lights
light1 := CreateHalfSphere(10, BGRA(255,128,0), 8,8);
with light1 do
begin
AddPointLight(MainPart.Add(0,0,-5),60,BGRA(255,128,0),0);
MainPart.Translate(-100,-50,0);
MainPart.LookAt(Point3D(0,0,0),Point3D(0,-1,0));
Material := lamp;
LightingNormal := lnVertex;
end;
light2 := CreateHalfSphere(10, BGRA(0,128,255), 8,8);
with light2 do
begin
AddPointLight(MainPart.Add(0,0,-5),100,BGRA(0,128,255),0);
MainPart.Translate(50,0,-100);
MainPart.LookAt(Point3D(0,0,0),Point3D(0,-1,0));
Material := lamp;
LightingNormal := lnVertex;
end;
end else
begin
//create ground
ground := CreateObject(water);
if Lighting = e2lLightness then
begin
with ground do
begin
base := MainPart.Add([-50,0,-50, -50,0,50, 50,0,50, 50,0,-50]);
ApplyTexCoord(AddFace(base,True),2);
end;
ViewPoint := Point3D(-40,-40,-100);
AmbiantLightness := 0.25;
with CreateObject do
AddPointLight(MainPart.Add(-100,-80,0),100,1.25, -0.15);
end else
begin
AmbiantLightness := 1;
with ground do
begin
base := MainPart.Add([-50,0,-50, -50,0,50, 50,0,50, 50,0,-50]);
MainPart.Scale(2);
ApplyTexCoord(AddFace(base,True),2);
end;
ViewPoint := Point3D(0,-40,-120);
end;
RenderingOptions.PerspectiveMode:= pmZBuffer;
end;
RenderingOptions.TextureInterpolation := false;
end;
procedure TExample2.ApplyTexCoord(face: IBGRAFace3D; Times: integer);
begin
with face do
begin
TexCoord[0] := PointF(0,0);
TexCoord[1] := PointF(texSize*Times-1,0);
TexCoord[2] := PointF(texSize*Times-1,texSize*Times-1);
TexCoord[3] := PointF(0,texSize*Times-1);
end;
end;
procedure TExample2.SetLighting(AValue: TExample2Lighting);
begin
if FLighting=AValue then Exit;
FLighting:=AValue;
CreateScene;
end;
destructor TExample2.Destroy;
begin
water.free;
wood.free;
vWood.free;
inherited Destroy;
end;
end.