|
program Lightsbb;
uses
Windows,
Messages,
MMSystem,
Direct3D9,SysUtils,
D3DX9;
type
PD3DMaterial9Array = ^TD3DMaterial9Array;
TD3DMaterial9Array = array[0..0] of TD3DMaterial9;
PIDirect3DTexture9Array = ^IDirect3DTexture9Array;
IDirect3DTexture9Array = array[0..0] of IDirect3DTexture9;
//-----------------------------------------------------------------------------
// Global variables
//-----------------------------------------------------------------------------
var
g_pD3D: IDirect3D9 = nil; // Used to create the D3DDevice
g_pd3dDevice: IDirect3DDevice9 = nil; // Our rendering device
g_pVB: IDirect3DVertexBuffer9 = nil; // Buffer to hold vertices
g_pTexture: IDirect3DTexture9 = nil; // Our texture
// A structure for our custom vertex type. We added a normal, and omitted the
// color (which is provided by the material)
g_pMesh: ID3DXMesh = nil; // Our mesh object in sysmem
g_pMeshMaterials: PD3DMaterial9Array = nil; // Materials for our mesh
g_pMeshTextures: PIDirect3DTexture9Array = nil; // Textures for our mesh
g_dwNumMaterials: DWORD = 0; // Number of mesh materials
type
PCustomVertex = ^TCustomVertex;
TCustomVertex = packed record
position: TD3DXVector3; // The position
normal: TD3DVector;
color: TD3DColor; // The color
{$IFNDEF SHOW_HOW_TO_USE_TCI}
tu, tv: Single; // The texture coordinates
{$ENDIF}
end;
PCustomVertexArray = ^TCustomVertexArray;
TCustomVertexArray = array [0..0] of TCustomVertex;
const
// Our custom FVF, which describes our custom vertex structure
{$IFDEF SHOW_HOW_TO_USE_TCI}
D3DFVF_CUSTOMVERTEX = D3DFVF_XYZ or D3DFVF_DIFFUSE or D3DFVF_NORMAL;
{$ELSE}
D3DFVF_CUSTOMVERTEX = D3DFVF_XYZ or D3DFVF_NORMAL or D3DFVF_TEX1 or D3DFVF_DIFFUSE ;
{$ENDIF}
function InitD3D(hWnd: HWND): HRESULT;
var
d3dpp: TD3DPresentParameters;
begin
Result:= E_FAIL;
// Create the D3D object.
g_pD3D := Direct3DCreate9(D3D_SDK_VERSION);
if (g_pD3D = nil) then Exit;
// Set up the structure used to create the D3DDevice. Since we are now
// using more complex geometry, we will create a device with a zbuffer.
FillChar(d3dpp, SizeOf(d3dpp), 0);
d3dpp.Windowed := True;
d3dpp.SwapEffect := D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat := D3DFMT_UNKNOWN;
d3dpp.EnableAutoDepthStencil := True;
d3dpp.AutoDepthStencilFormat := D3DFMT_D16;
// Create the D3DDevice
Result:= g_pD3D.CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
@d3dpp, g_pd3dDevice);
if FAILED(Result) then
begin
Result:= E_FAIL;
Exit;
end;
// Turn off culling
g_pd3dDevice.SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
// Turn on the zbuffer
g_pd3dDevice.SetRenderState(D3DRS_ZENABLE, iTrue);
g_pd3dDevice.SetRenderState(D3DRS_AMBIENT, $ffffffff);
Result:= S_OK;
end;
function InitGeometry: HRESULT;
type
PD3DXMaterialArray = ^TD3DXMaterialArray;
TD3DXMaterialArray = array[0..0] of TD3DXMaterial;
const
strPrefix = '..\';
lenPrefix = Length(strPrefix);
var
i,r: DWORD; rr,rr1, y0,y1:real;
theta,thetb: Single;
pVertices: PCustomVertexArray;
pD3DXMtrlBuffer: ID3DXBuffer;
d3dxMaterials: PD3DXMaterialArray;
strTexture: array[0..MAX_PATH-1] of Char;
begin
Result:= E_FAIL;
// Use D3DX to create a texture from a file based image
if FAILED(D3DXCreateTextureFromFile(g_pd3dDevice, 'banana.bmp', g_pTexture)) then
begin
// If texture is not in current folder, try parent folder
if FAILED(D3DXCreateTextureFromFile(g_pd3dDevice, '..\banana.bmp', g_pTexture)) then
begin
MessageBox(0, 'Could not find banana.bmp', 'Textures.exe', MB_OK);
Exit;
end;
end;
// Create the vertex buffer.
if FAILED(g_pd3dDevice.CreateVertexBuffer((2500)*2*SizeOf(TCustomVertex),
0, D3DFVF_CUSTOMVERTEX,
D3DPOOL_DEFAULT, g_pVB, nil))
then Exit;
if FAILED(g_pVB.Lock(0, 0, Pointer(pVertices), 0))
then Exit;
theta := (D3DX_PI)/(50-1);
thetb := (2*D3DX_PI)/(50-1);
for i:=0 to 48 do
begin
rr:= 0.2*sin((i+0) * theta );
rr1 :=0.2* sin((i+1) * theta);
y0 := cos((i+0) * theta );
y1 := cos((i+1) * theta );
for r:=0 to 49 do
begin
pVertices[2*(50*i+r)+0].position := D3DXVector3(rr*sin((r)*thetb),y0, rr*cos((r)*thetb));
pVertices[2*(50*i+r)+0].normal := D3DXVector3(rr*sin((r)*thetb),y0, rr*cos((r)*thetb));
pVertices[2*(50*i+r)+0].color := $ff000080;
{$IFNDEF SHOW_HOW_TO_USE_TCI}
pVertices[2*(50*i+r)+0].tu :=(r)/50;
pVertices[2*(50*i+r)+0].tv := 1-(i)/50;
{$ENDIF}
pVertices[2*(50*i+r)+1].position := D3DXVector3(rr1*sin((r)*thetb),y1, rr1*cos((r)*thetb));
pVertices[2*(50*i+r)+1].normal := D3DXVector3(rr1*sin((r)*thetb),y1, rr1*cos((r)*thetb));
pVertices[2*(50*i+r)+1].color := $ff000080;
{$IFNDEF SHOW_HOW_TO_USE_TCI}
pVertices[2*(50*i+r)+1].tu := ((r)/50);
pVertices[2*(50*i+r)+1].tv := 1-((i+1)/50);
{$ENDIF}
end;
end;
g_pVB.Unlock;
if FAILED(D3DXLoadMeshFromX('Tiger.x', D3DXMESH_SYSTEMMEM,
g_pd3dDevice, nil,
@pD3DXMtrlBuffer, nil, @g_dwNumMaterials,
g_pMesh)) then
begin
// If model is not in current folder, try parent folder
if FAILED(D3DXLoadMeshFromX('..\Tiger.x', D3DXMESH_SYSTEMMEM,
g_pd3dDevice, nil,
@pD3DXMtrlBuffer, nil, @g_dwNumMaterials,
g_pMesh)) then
begin
MessageBox(0, 'Could not find tiger.x', 'Meshes.exe', MB_OK);
Exit;
end;
end;
// We need to extract the material properties and texture names from the
// pD3DXMtrlBuffer
d3dxMaterials := pD3DXMtrlBuffer.GetBufferPointer;
GetMem(g_pMeshMaterials, SizeOf(TD3DMaterial9)*g_dwNumMaterials);
GetMem(g_pMeshTextures, SizeOf(IDirect3DTexture9)*g_dwNumMaterials);
ZeroMemory(g_pMeshTextures, SizeOf(IDirect3DTexture9)*g_dwNumMaterials);
i:= 0;
while (i < g_dwNumMaterials) do
begin
// Copy the material
g_pMeshMaterials := d3dxMaterials.MatD3D;
// Set the ambient color for the material (D3DX does not do this)
g_pMeshMaterials.Ambient := g_pMeshMaterials.Diffuse;
g_pMeshTextures := nil;
if (d3dxMaterials.pTextureFilename <> nil) and
(StrLen(d3dxMaterials.pTextureFilename) > 0) then
begin
if FAILED(D3DXCreateTextureFromFile(g_pd3dDevice,
d3dxMaterials.pTextureFilename,
g_pMeshTextures)) then
begin
// If texture is not in current folder, try parent folder
StrLCopy(strTexture, strPrefix, MAX_PATH);
StrLCopy(strTexture + lenPrefix, d3dxMaterials.pTextureFilename, MAX_PATH - lenPrefix);
// If texture is not in current folder, try parent folder
if FAILED(D3DXCreateTextureFromFile(g_pd3dDevice,
strTexture,
g_pMeshTextures)) then
begin
MessageBox(0, 'Could not find texture map', 'Meshes.exe', MB_OK);
end;
end;
end;
Inc(i);
end;
// Done with the material buffer
pD3DXMtrlBuffer:= nil;
Result:= S_OK;
end;
procedure Cleanup;
var
i: DWORD;
begin
if (g_pMeshMaterials <> nil) then
FreeMem(g_pMeshMaterials);
if (g_pMeshTextures <> nil) then
begin
i:= 0;
while(i < g_dwNumMaterials) do
begin
if (g_pMeshTextures <> nil) then
g_pMeshTextures:= nil;
Inc(i);
end;
FreeMem(g_pMeshTextures);
end;
if (g_pMesh <> nil) then
g_pMesh:= nil;
if (g_pVB <> nil) then
g_pVB:= nil;
if (g_pd3dDevice <> nil) then
g_pd3dDevice:= nil;
if (g_pD3D <> nil) then
g_pD3D:= nil;
end;
procedure SetupMatrices;
var
matWorld, matView, matProj: TD3DMatrix;
vEyePt, vLookatPt, vUpVec: TD3DVector;
begin
D3DXMatrixIdentity(matWorld);
D3DXMatrixRotationAxis(matWorld, D3DXVector3(2.0, 3.0,-1.0), timeGetTime/1000.0);
D3DXMatrixRotationy(matWorld, timeGetTime/500.0);
g_pd3dDevice.SetTransform(D3DTS_WORLD, matWorld);
vEyePt:= D3DXVector3(0.0, 0.0,-8.0);
vLookatPt:= D3DXVector3Zero;
vUpVec:= D3DXVector3(0.0, 1.0, 0.0);
D3DXMatrixLookAtLH(matView, vEyePt, vLookatPt, vUpVec);
g_pd3dDevice.SetTransform(D3DTS_VIEW, matView);
D3DXMatrixPerspectiveFovLH(matProj, D3DX_PI/4, 1.0, 1.0, 100.0);
g_pd3dDevice.SetTransform(D3DTS_PROJECTION, matProj);
end;
procedure SetupLights;
var
mtrl: TD3DMaterial9;
vecDir: TD3DXVector3;
light,light1: TD3DLight9;
begin
ZeroMemory(@mtrl, SizeOf(TD3DMaterial9));
mtrl.Diffuse.r := 255.0; mtrl.Ambient.r := 55.0;
mtrl.Diffuse.g := 255.0; mtrl.Ambient.g := 255.0;
mtrl.Diffuse.b := 0.0; mtrl.Ambient.b := 0.0;
mtrl.Diffuse.a := 1.0; mtrl.Ambient.a := 1.0;
g_pd3dDevice.SetMaterial(mtrl);
ZeroMemory(@light, SizeOf(TD3DLight9));
light._Type := D3DLIGHT_SPOT;
light.Diffuse.r := 255.0;
light.Diffuse.g := 255.0;
light.Diffuse.b := 10.0;
vecDir:= D3DXVector3(Cos(timeGetTime/1000.0),
-1.0,
Sin(timeGetTime/1000.0) );
D3DXVec3Normalize(light.Direction, vecDir);
light.Range := 1000.0;
g_pd3dDevice.SetLight(0, light);
g_pd3dDevice.LightEnable(0, True);
g_pd3dDevice.SetRenderState(D3DRS_LIGHTING, iTrue);
ZeroMemory(@light1, SizeOf(TD3DLight9));
light1._Type := D3DLIGHT_DIRECTIONAL;
light1.Diffuse.r := 1.0;
light1.Diffuse.g := 1.0;
light1.Diffuse.b := 1.0;
vecDir:= D3DXVector3(-5,
5.0,
0 );
D3DXVec3Normalize(light1.Direction, vecDir);
light1.Range := 1000.0;
g_pd3dDevice.SetLight(1, light1);
g_pd3dDevice.LightEnable(1, True);
g_pd3dDevice.SetRenderState(D3DRS_LIGHTING, iTrue);
// Finally, turn on some ambient light.
g_pd3dDevice.SetRenderState(D3DRS_AMBIENT, $ffffffff);
end;
procedure Render;
var
i: DWORD;
begin
g_pd3dDevice.Clear(0, nil, D3DCLEAR_TARGET or D3DCLEAR_ZBUFFER,
D3DCOLOR_XRGB(0,0,0), 1.0, 0);
// Begin the scene
if SUCCEEDED(g_pd3dDevice.BeginScene) then
begin
// Setup the world, view, and projection matrices
SetupMatrices;
// Meshes are divided into subsets, one for each material. Render them in
// a loop
i:= 0;
while(i < g_dwNumMaterials) do
begin
// Set the material and texture for this subset
g_pd3dDevice.SetMaterial(g_pMeshMaterials);
g_pd3dDevice.SetTexture(0, g_pMeshTextures);
// Draw the mesh subset
g_pMesh.DrawSubset(i);
Inc(i);
end;
// End the scene
g_pd3dDevice.EndScene;
end;
if SUCCEEDED(g_pd3dDevice.BeginScene) then
begin
// Setup the lights and materials
SetupLights;
// Setup the world, view, and projection matrices
SetupMatrices;
g_pd3dDevice.SetTexture(0, g_pTexture);
// Set up the default texture states.
g_pd3dDevice.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
g_pd3dDevice.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
g_pd3dDevice.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
g_pd3dDevice.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
// Set up the default sampler states.
g_pd3dDevice.SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
g_pd3dDevice.SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
g_pd3dDevice.SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR );
g_pd3dDevice.SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP );
g_pd3dDevice.SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP );
{$IFDEF SHOW_HOW_TO_USE_TCI}
// tu = 0.5*x + 0.5
// tv = -0.5*y + 0.5
mat._11 := 0.25; mat._12 := 0.00; mat._13 := 0.00; mat._14 := 0.00;
mat._21 := 0.00; mat._22 :=-0.25; mat._23 := 0.00; mat._24 := 0.00;
mat._31 := 0.00; mat._32 := 0.00; mat._33 := 1.00; mat._34 := 0.00;
mat._41 := 0.50; mat._42 := 0.50; mat._43 := 0.00; mat._44 := 1.00;
g_pd3dDevice.SetTransform(D3DTS_TEXTURE0, mat);
g_pd3dDevice.SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
g_pd3dDevice.SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION);
{$ENDIF}
// Render the vertex buffer contents
g_pd3dDevice.SetStreamSource(0, g_pVB, 0, SizeOf(TCustomVertex));
g_pd3dDevice.SetFVF(D3DFVF_CUSTOMVERTEX);
g_pd3dDevice.DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2*2500-2);
// End the scene
g_pd3dDevice.EndScene;
end;
// Present the backbuffer contents to the display
g_pd3dDevice.Present(nil, nil, 0, nil);
end;
function MsgProc(hWnd: HWND; uMsg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
begin
case uMsg of
WM_DESTROY:
begin
Cleanup;
PostQuitMessage(0);
Result:= 0;
Exit;
end;
end;
Result:= DefWindowProc(hWnd, uMsg, wParam, lParam);
end;
var
wc: TWndClassEx = (
cbSize: SizeOf(TWndClassEx);
style: CS_CLASSDC;
lpfnWndProc: @MsgProc;
cbClsExtra: 0;
cbWndExtra: 0;
hInstance: 0; // - filled later
hIcon: 0;
hCursor: 0;
hbrBackground: 0;
lpszMenuName: nil;
lpszClassName: 'D3D Tutorial';
hIconSm: 0);
var
hWindow: HWND;
msg: TMsg;
begin
wc.hInstance:= GetModuleHandle(nil);
RegisterClassEx(wc);
// Create the application's window
hWindow := CreateWindow('D3D Tutorial', 'D3D Tutorial 04: Lights',
WS_OVERLAPPEDWINDOW, 100, 100, 800, 800,
GetDesktopWindow, 0, wc.hInstance, nil);
// Initialize Direct3D
if SUCCEEDED(InitD3D(hWindow)) then
begin
// Create the scene geometry
if SUCCEEDED(InitGeometry) then
begin
// Show the window
ShowWindow(hWindow, SW_SHOWDEFAULT);
UpdateWindow(hWindow);
// Enter the message loop
FillChar(msg, SizeOf(msg), 0);
while (msg.message <> WM_QUIT) do
begin
if PeekMessage(msg, 0, 0, 0, PM_REMOVE) then
begin
TranslateMessage(msg);
DispatchMessage(msg);
end else
Render;
end;
end;
end;
UnregisterClass('D3D Tutorial', wc.hInstance);
end.
|
|