Я новичок в Delphi direct3D. Наконец-то получили базовый c фреймворк и запустили рендеринг 2 треугольников на экран. Работает. Однако я бы хотел, чтобы он теперь отображался в Tbitmap. После 2 дней поиска я не нашел ни одного примера в Интернете ... может быть, кто-то здесь может помочь.
Здесь вы найдете код "доказательства концепции". (устранена вся проверка ошибок и т. д. c ..)
в "d3dDevice.Present (nil, nil, 0, nil);" Я хотел бы вывести результат в растровое изображение с именем "frame"
любопытно, если у кого-то есть рабочий код для этого!
grtz Фред
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
// {$IFDEF DXG_COMPAT} DirectXGraphics {$ELSE} Direct3D8 {$ENDIF},
Direct3D8, D3DX8, mmsystem, ExtCtrls ,
System.Variants, Vcl.StdCtrls, Vcl.ComCtrls, types;
type
TForm1 = class(TForm)
Image1: TImage;
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
procedure IdleHandler(Sender: TObject; var Done: Boolean);
public
{ Public declarations }
end;
var
Form1 : TForm1;
frame : Tbitmap;
PointerFrameBuffer : pointer;
screen : hdc;
implementation
{$R *.DFM}
type
CUSTOMVERTEX = record // A structure for our custom vertex type
position : TD3DXVector3; // The untransformed, 3D position for the vertex
color : dword;
end;
PCUSTOMVERTEX = array[0..0] of CUSTOMVERTEX;
const
D3DFVF_CUSTOMVERTEX = (D3DFVF_XYZ or D3DFVF_DIFFUSE {or D3DFVF_NORMAL}); // Our custom FVF, which describes our custom vertex structure
// Global variables
var
D3D : IDirect3D8 = nil; // Used to create the D3DDevice
d3dDevice : IDirect3DDevice8 = nil; // Our rendering device
VertexBuffer : IDirect3DVertexBuffer8 = nil; // Buffer to hold vertices
procedure Render; // Name: Render() // Desc: Draws the scene
var
i,tmpMemP : longint;
begin
d3dDevice.Clear(0, nil, D3DCLEAR_TARGET or D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,55), 1.0, 0); // Clear the backbuffer and the zbuffer
d3dDevice.BeginScene; // Begin the scene
// Render the vertex buffer contents
d3dDevice.SetStreamSource(0, VertexBuffer, SizeOf(CUSTOMVERTEX));
d3dDevice.SetVertexShader(D3DFVF_CUSTOMVERTEX);
d3dDevice.DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 1);
d3dDevice.DrawPrimitive(D3DPT_TRIANGLESTRIP, 3, 1);
d3dDevice.EndScene;
d3dDevice.Present(nil, nil, 0, nil); // Present the backbuffer contents to the display
// IN STEAD OFF PRESENTING THE RESULT TO THE SCREEN I WOULD LIKE IT RENDERED/COPIED INTO MY "FRAME" Tbitmap
tmpMemP := longint(PointerFrameBuffer);
for i:= 0 to 1024*512-1 do begin longint(pointer(TmpMemP)^) := random(256*256*256); inc(tmpMemP,4); end;
form1.Image1.Picture.Assign(frame);
// CornerOfProgram := form1.clienTToScreen(Point(0,0)); // we want to dump our frame at the corner of our program
// StretchBlt(screen, CornerOfProgram.x , CornerOfProgram.y,1024,512, frame.canvas.handle,0,0,frame.Width,frame.Height,srccopy); // should give non blinking update of screen at higher framerates
end;
procedure TForm1.FormCreate(Sender: TObject);
var
d3ddm : TD3DDisplayMode;
d3dpp : TD3DPresentParameters;
pVertices : ^PCUSTOMVERTEX;
i : DWORD;
ViewMatrix, ProjMatrix : TD3DXMatrix;
begin
frame := Tbitmap.Create;
with frame do begin
HandleType :=bmDDB; //DDB?
pixelformat :=pf32bit;
Width :=1024;
Height :=512;
pointerFrameBuffer := ScanLine[frame.height-1]; // OPGELET bitmaps liggen omgekeerd in het geheugen pointer naar laatste scanline = begin onze werkbuffer
end;
screen := getdc(0); // get a direct handle to our hardware screen for fast dump of frame
D3D := Direct3DCreate8(D3D_SDK_VERSION); // Create the D3D object
D3D.GetAdapterDisplayMode(D3DADAPTER_DEFAULT, d3ddm); // Get the current desktop display mode, so we can set up a back buffer of the same format
// 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.
ZeroMemory(@d3dpp, SizeOf(d3dpp));
d3dpp.Windowed := True;
d3dpp.SwapEffect := D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat := d3ddm.Format;
d3dpp.EnableAutoDepthStencil := True;
d3dpp.AutoDepthStencilFormat := D3DFMT_D16;
D3D.CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, handle, D3DCREATE_hardWARE_VERTEXPROCESSING, d3dpp, d3dDevice); // Create the Direct3D device
d3dDevice.SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); // Turn off culling
d3dDevice.SetRenderState(D3DRS_ZENABLE , iTrue); // Turn on the zbuffer
d3dDevice.SetRenderState(D3DRS_LIGHTING, iFalse); // Turn off D3D lighting, since we are providing our own vertex colors
// Setup the view, and projection matrices
D3DXMatrixLookAtLH(ViewMatrix, D3DXVector3(0.0, 0.0, 0.0), // point from where we look
D3DXVector3(0.0, 0.0, 1.0), // to where we look
D3DXVector3(0.0, 1.0, 0.0)); // Y axis is our up direction
d3dDevice.SetTransform(D3DTS_VIEW, ViewMatrix);
D3DXMatrixPerspectiveFovLH(ProjMatrix, 1, 2, 1.0, 1000.0); // 512-1024 res -> 1/2 // 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).
d3dDevice.SetTransform(D3DTS_PROJECTION, ProjMatrix);
// INIT GEOMETRY
d3dDevice.CreateVertexBuffer(50*2*SizeOf(CUSTOMVERTEX), 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, Vertexbuffer); // Create the vertex buffer.
// Fill the vertex buffer. We are algorithmically generating a cylinder here, including the normals, which are used for lighting.
Vertexbuffer.Lock(0, 0, PByte(pVertices), 0);
i:=0; with pVertices[i] do begin position := D3DXVector3(-80, 0,100); color := $ffff0000; end;
i:=1; with pVertices[i] do begin position := D3DXVector3(-80, 40,100); color := $ffff0000; end;
i:=2; with pVertices[i] do begin position := D3DXVector3(-80, 0,140); color := $ffff0000; end;
i:=3; with pVertices[i] do begin position := D3DXVector3( -40, 10, 120); color := $ff00ff00; end;
i:=4; with pVertices[i] do begin position := D3DXVector3( -40, 30, 120); color := $ff00ff00; end;
i:=5; with pVertices[i] do begin position := D3DXVector3( -120, 10, 120); color := $ff00ff00; end;
Vertexbuffer.Unlock;
Application.OnIdle:= IdleHandler;
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
if (VertexBuffer <> nil) then Vertexbuffer:= nil;
if (d3dDevice <> nil) then d3dDevice := nil;
if (D3D <> nil) then D3D := nil;
releaseDC(0, screen)
end;
procedure TForm1.IdleHandler(Sender: TObject; var Done: Boolean);
begin
Render;
Done:= False;
end;
end.