interface
uses Microsoft.DirectX, Microsoft.DirectX.Direct3D, System.Drawing,
System.Windows.Forms;
type
TPaintDirectX9 =
class
private
Fdevice: Device;
// Our rendering device
FVertexBuffer: VertexBuffer;
procedure InitializeGraphics(OutControl: System.Windows.Forms.Control);
procedure OnCreateDevice(sender: TObject; e: EventArgs);
procedure OnResetDevice(sender: TObject; e: EventArgs);
procedure OnCreateVertexBuffer(sender: TObject; e: EventArgs);
procedure SetupMatrices;
procedure SetupLights;
public
constructor Create(OutControl: System.Windows.Forms.Control);
procedure Render;
end;
implementation
constructor TPaintDirectX9.Create(OutControl: System.Windows.Forms.Control);
begin
inherited Create;
try
InitializeGraphics(OutControl);
except
on e: DirectXException
do Raise Exception.Create('
Fehler beim Zugriff auf DirectX 9: ' + e.
Message);
end;
end;
procedure TPaintDirectX9.InitializeGraphics(OutControl: System.Windows.Forms.Control);
var
FPresentParams: PresentParameters;
begin
FPresentParams := PresentParameters.Create;
FPresentParams.Windowed := true;
// We don't want to run fullscreen
FPresentParams.SwapEffect := SwapEffect.Discard;
// Discard the frames
FPresentParams.EnableAutoDepthStencil := true;
// Turn on a Depth stencil
FPresentParams.AutoDepthStencilFormat := DepthFormat.D16;
// And the stencil format
Fdevice := Device.Create(0, DeviceType.Hardware, OutControl, CreateFlags.SoftwareVertexProcessing, [FPresentParams]);
//Create a device
Borland.Delphi.System.Include(Fdevice.DeviceReset, Self.OnResetDevice);
self.OnCreateDevice(Fdevice,
NIL);
self.OnResetDevice(Fdevice,
NIL);
end;
procedure TPaintDirectX9.OnCreateVertexBuffer(sender: TObject; e: EventArgs);
var
vb: VertexBuffer;
verts: System.&
Array;
//of CustomVertex.PositionNormal;
i: Integer;
theta: Single;
begin
vb := VertexBuffer(sender);
// Create a vertex buffer (100 customervertex)
verts := vb.Lock(0,LockFlags.None);
// Lock the buffer (which will return our structs)
try
for i := 0
to 49
do
begin
// Fill up our structs
theta := (2 * Math.PI * i) / 49;
verts.SetValue(CustomVertex.PositionNormal.Create(
Vector3.Create(Math.Sin(theta), -1, Math.Cos(theta)),
Vector3.Create(Math.Sin(theta), 0, Math.Cos(theta))),
2*i);
verts.SetValue(CustomVertex.PositionNormal.Create(
Vector3.Create(Math.Sin(theta), 1, Math.Cos(theta)),
Vector3.Create(Math.Sin(theta), 0, Math.Cos(theta))),
2*i+1);
end;
finally
vb.Unlock;
end;
end;
procedure TPaintDirectX9.OnCreateDevice(sender: TObject; e: EventArgs);
var
dev: Microsoft.DirectX.Direct3D.Device;
begin
dev := Device(sender);
// Hier wird der Puffer für die Dreiecke erzeugt
FvertexBuffer := VertexBuffer.Create(typeof(CustomVertex.PositionNormal), 100, dev, Usage.
WriteOnly, CustomVertex.PositionNormal.Format, Pool.
Default);
Borland.Delphi.System.Include(FvertexBuffer.Created, Self.OnCreateVertexBuffer);
Self.OnCreateVertexBuffer(FvertexBuffer,
NIL);
end;
procedure TPaintDirectX9.OnResetDevice(sender: TObject; e: EventArgs);
var
dev: Device;
begin
dev := Device(sender);
// Turn off culling, so we see the front and back of the triangle
dev.RenderState.CullMode := Microsoft.DirectX.Direct3D.Cull.None;
// Turn on the ZBuffer
dev.RenderState.ZBufferEnable := true;
dev.RenderState.Lighting := true;
//make sure lighting is enabled
end;
procedure TPaintDirectX9.SetupLights;
var
col: System.Drawing.Color;
mtrl: Material;
begin
col := System.Drawing.Color.White;
//Set up a material. The material here just has the diffuse and ambient
//colors set to yellow. Note that only one material can be used at a time.
mtrl := Microsoft.DirectX.Direct3D.Material.Create;
mtrl.Diffuse := col;
mtrl.Ambient := col;
Fdevice.Material := mtrl;
//Set up a white, directional light, with an oscillating direction.
//Note that many lights may be active at a time (but each one slows down
//the rendering of our scene). However, here we are just using one. Also,
//we need to set the D3DRS_LIGHTING renderstate to enable lighting
Fdevice.Lights[0].&
Type := LightType.Directional;
Fdevice.Lights[0].Diffuse := System.Drawing.Color.DarkTurquoise;
Fdevice.Lights[0].Direction := Vector3.Create(Math.Cos(Environment.TickCount / 250.0), 1.0, Math.Sin(Environment.TickCount / 250.0));
Fdevice.Lights[0].Enabled := true;
//turn it on
//Finally, turn on some ambient light.
//Ambient light is light that scatters and lights all objects evenly
Fdevice.RenderState.Ambient := System.Drawing.Color.FromArgb(32,32,32);
end;
procedure TPaintDirectX9.SetupMatrices;
begin
// For our world matrix, we will just rotate the object about the y-axis.
Fdevice.Transform.World := Matrix.RotationAxis(Vector3.Create(Math.Cos(Environment.TickCount / 250.0),1, Math.Sin(Environment.TickCount / 250.0)), Environment.TickCount / 3000.0 );
// Set up our view matrix. A view matrix can be defined given an eye point,
// a point to lookat, and a direction for which way is up. Here, we set the
// eye five units back along the z-axis and up three units, look at the
// origin, and define "up" to be in the y-direction.
Fdevice.Transform.View := Matrix.LookAtLH(Vector3.Create( 0.0, 3.0,-5.0 ), Vector3.Create( 0.0, 0.0, 0.0), Vector3.Create( 0.0, 1.0, 0.0 ) );
// For the projection matrix, we set up a perspective transform (which
// transforms geometry from 3D view space to 2D viewport space, with
// a perspective divide making objects smaller in the distance). To build
// a perpsective transform, we need the field of view (1/4 pi is common),
// the aspect ratio, and the near and far clipping planes (which define at
// what distances geometry should be no longer be rendered).
Fdevice.Transform.Projection := Matrix.PerspectiveFovLH( Math.PI / 4.0, 1.0, 1.0, 100.0);
end;
procedure TPaintDirectX9.Render;
begin
//Clear the backbuffer to a blue color
Fdevice.Clear(ClearFlags.Target
or ClearFlags.ZBuffer, System.Drawing.Color.Blue, 1.0, 0);
//Begin the scene
Fdevice.BeginScene();
// Setup the lights and materials
SetupLights();
// Setup the world, view, and projection matrices
SetupMatrices();
Fdevice.SetStreamSource(0, FVertexBuffer, 0);
Fdevice.VertexFormat := CustomVertex.PositionNormal.Format;
Fdevice.DrawPrimitives(PrimitiveType.TriangleStrip, 0, (4*25)-2);
//End the scene
Fdevice.EndScene();
// Update the screen
Fdevice.Present();
end;