204 lines
5.6 KiB
ObjectPascal
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.
|
|
|