| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423 |
- {
- Vampyre Imaging Library Demo
- D3D9 Demo (D3D9 extension)
- Demo that shows how to create Direct3D 9 textures from files
- and Imaging's images and vice versa. This sample uses SDL to create
- window and process messages. Background and sprite textures are loaded from
- files and rendered. Sprite is rendered in each corner of the window
- using various texture stage and blending settings.
- You can change sprite's texture format by pressing SPACE key
- (it cycles trough all TImageFormat values). Background texture
- can be saved to file by pressing S key and sprite texture
- can be saved by pressing D key.
- }
- unit DemoUnit;
- {$I ImagingOptions.inc}
- {$R ..\Common\MainIcon.res}
- interface
- procedure RunDemo;
- implementation
- uses
- Windows,
- SysUtils,
- ImagingTypes,
- Imaging,
- ImagingUtility,
- sdl,
- Direct3D9,
- ImagingDirect3D9,
- ImagingSdl,
- DemoUtils;
- type
- TVector2 = record
- X, Y: Single;
- end;
- TVector4 = record
- X, Y, Z, W: Single;
- end;
- TVertex = record
- Position: TVector4;
- TexCoord1: TVector2;
- TexCoord2: TVector2;
- end;
- TRect = array[0..3] of TVertex;
- const
- SWindowTitle = 'Vampyre Imaging Library (%s) - Direct3D9 Demo (format: %s)';
- SWindowIconTitle = 'Direct3D9 Demo';
- SBackImageFile = 'Tigers.jpg';
- SSpriteImageFile = 'Vezyr.png';
- SOutScreenFile = 'D3DScreen.png';
- SOutSpriteFile = 'D3DSprite.dds';
- SIconFile = 'Icon.png';
- DisplayWidth = 800;
- DisplayHeight = 600;
- SpriteWidth = 256.0;
- SpriteHeight = 192.0;
- FVF_VERTEX = D3DFVF_XYZRHW or D3DFVF_TEX2;
- var
- WindowHandle: THandle;
- Direct3D: IDirect3D9 = nil;
- Device: IDirect3DDevice9 = nil;
- BackTex: IDirect3DTexture9 = nil;
- SpriteTex: IDirect3DTexture9 = nil;
- PresentParams: TD3DPresentParameters;
- DisplaySurface: PSDL_Surface = nil;
- SpriteImage: TImageData;
- SpriteFormat: TImageFormat = ifA8R8G8B8;
- BackRect: TRect;
- Rects: array[0..3] of TRect;
- Event : TSDL_Event;
- Running: Boolean = True;
- Frames: LongInt = 0;
- FPS: LongInt = 0;
- LastTime: LongInt = 0;
- TextureCaps: TD3DTextureCaps;
- function Vector2(X, Y: Single): TVector2;
- begin
- Result.X := X;
- Result.Y := Y;
- end;
- function Vector4(X, Y, Z, W: Single): TVector4;
- begin
- Result.X := X;
- Result.Y := Y;
- Result.Z := Z;
- Result.W := W;
- end;
- procedure PlaceRect(Index: LongInt; X, Y: Single);
- begin
- Rects[Index, 0].Position.X := X;
- Rects[Index, 0].Position.Y := Y;
- Rects[Index, 1].Position.X := X + SpriteWidth;
- Rects[Index, 1].Position.Y := Y;
- Rects[Index, 2].Position.X := X;
- Rects[Index, 2].Position.Y := Y + SpriteHeight;
- Rects[Index, 3].Position.X := X + SpriteWidth;
- Rects[Index, 3].Position.Y := Y + SpriteHeight;
- end;
- procedure MessageOut(Window: THandle; const Msg: string; const Args: array of const);
- begin
- MessageBox(Window, PChar(Format(Msg, Args)), 'Message',
- MB_ICONINFORMATION or MB_OK);
- end;
- procedure MessageOutAndHalt(Window: THandle; const Msg: string; const Args: array of const);
- begin
- MessageBox(Window, PChar(Format(Msg, Args)), 'Error',
- MB_ICONERROR or MB_OK);
- SDL_Quit;
- Halt(1);
- end;
- procedure UpdateCaption;
- begin
- SDL_WM_SetCaption(PAnsiChar(AnsiString(Format(SWindowTitle + ' FPS: %d',
- [Imaging.GetVersionStr, GetFormatName(SpriteFormat), FPS]))),
- SWindowIconTitle);
- end;
- procedure CreateSpriteTexture(const Device: IDirect3DDevice9; Format: TImageFormat);
- var
- D3DFormat: TD3DFormat;
- ConvTo: TImageFormat;
- ConvImage: TImageData;
- begin
- // Find D3D format that matches given TImageFormat
- D3DFormat := ImagingDirect3D9.ImageFormatToD3DFormat(Format, ConvTo);
- if D3DFormat <> D3DFMT_UNKNOWN then
- begin
- // Free old texture and create new one in the different format
- SpriteTex := nil;
- Imaging.InitImage(ConvImage);
- Imaging.CloneImage(SpriteImage, ConvImage);
- // Create texture from image
- ImagingDirect3D9.CreateD3DTextureFromImage(ConvImage, Device, SpriteTex,
- SpriteImage.Width, SpriteImage.Height, 0, 0, D3DFormat, D3DPOOL_MANAGED);
- Imaging.FreeImage(ConvImage);
- end;
- end;
- procedure Initialize;
- var
- Caption, Icon: PAnsiChar;
- Mode: TD3DDisplayMode;
- I: LongInt;
- begin
- // Get SDL app window
- SDL_WM_GetCaption(Caption, Icon);
- WindowHandle := FindWindowA('SDL_app', Caption);
- if WindowHandle = 0 then
- MessageOutAndHalt(GetActiveWindow, 'Cannot get SDL window handle', []);
- // Place window to the center of the screen
- SetWindowPos(WindowHandle, 0, (GetSystemMetrics(SM_CXSCREEN) - DisplayWidth) div 2,
- (GetSystemMetrics(SM_CYSCREEN) - DisplayHeight - 20) div 2, 0, 0, SWP_NOSIZE or SWP_NOZORDER);
- // Create IDirect3D interface
- Direct3D := Direct3DCreate9(D3D_SDK_VERSION);
- if Direct3D = nil then
- MessageOutAndHalt(WindowHandle, 'Cannot create Direct3D interface', []);
- // Get the current display mode and fill presentation parameters
- Direct3D.GetAdapterDisplayMode(D3DADAPTER_DEFAULT, Mode);
- FillChar(PresentParams, SizeOf(PresentParams), 0);
- PresentParams.hDeviceWindow := WindowHandle;
- PresentParams.Windowed := True;
- PresentParams.BackBufferCount := 1;
- PresentParams.BackBufferFormat := Mode.Format;
- PresentParams.SwapEffect := D3DSWAPEFFECT_DISCARD;
- PresentParams.PresentationInterval := D3DPRESENT_INTERVAL_IMMEDIATE;
- // Create Direct3D device
- if Failed(Direct3D.CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, PresentParams.hDeviceWindow,
- D3DCREATE_SOFTWARE_VERTEXPROCESSING, @PresentParams, Device)) then
- MessageOutAndHalt(WindowHandle, 'Cannot create Direct3D device', []);
- // Get texture caps
- ImagingDirect3D9.GetDeviceTextureCaps(Device, TextureCaps);
- // Load background texture from file
- ImagingDirect3D9.LoadD3DTextureFromFile(GetDataDir + PathDelim + SBackImageFile, Device, BackTex);
- Imaging.InitImage(SpriteImage);
- // Load sprite image from file
- Imaging.LoadImageFromFile(GetDataDir + PathDelim + SSpriteImageFile, SpriteImage);
- // Create sprite texture from image
- CreateSpriteTexture(Device, SpriteFormat);
- // Set render states
- Device.SetRenderState(D3DRS_LIGHTING, 0);
- Device.SetRenderState(D3DRS_ALPHABLENDENABLE, 1);
- Device.SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
- Device.SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
- // Set texture stage states
- Device.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
- Device.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
- Device.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
- Device.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
- Device.SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
- Device.SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
- Device.SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
- Device.SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT);
- Device.SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
- Device.SetTextureStageState(1, D3DTSS_ALPHAARG2, D3DTA_CURRENT);
- Device.SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
- Device.SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
- Device.SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
- // Set size of the background
- BackRect[0].Position := Vector4(0.0, 0.0, 0.0, 1.0);
- BackRect[1].Position := Vector4(DisplayWidth, 0.0, 0.0, 1.0);
- BackRect[2].Position := Vector4(0.0, DisplayHeight, 0.0, 1.0);
- BackRect[3].Position := Vector4(DisplayWidth, DisplayHeight, 0.0, 1.0);
- // Set background's tex coords
- BackRect[0].TexCoord1 := Vector2(0.0, 0.0);
- BackRect[1].TexCoord1 := Vector2(1.0, 0.0);
- BackRect[2].TexCoord1 := Vector2(0.0, 1.0);
- BackRect[3].TexCoord1 := Vector2(1.0, 1.0);
- // Set sprites' tex coords and default position
- for I := 0 to 3 do
- begin
- Rects[I, 0].Position := Vector4(0.0, 0.0, 0.0, 1.0);
- Rects[I, 1].Position := Vector4(0.0, 0.0, 0.0, 1.0);
- Rects[I, 2].Position := Vector4(0.0, 0.0, 0.0, 1.0);
- Rects[I, 3].Position := Vector4(0.0, 0.0, 0.0, 1.0);
- Rects[I, 0].TexCoord1 := Vector2(0.0, 0.0);
- Rects[I, 1].TexCoord1 := Vector2(1.0, 0.0);
- Rects[I, 2].TexCoord1 := Vector2(0.0, 1.0);
- Rects[I, 3].TexCoord1 := Vector2(1.0, 1.0);
- Rects[I, 0].TexCoord2 := Vector2(0.0, 1.0);
- Rects[I, 1].TexCoord2 := Vector2(1.0, 1.0);
- Rects[I, 2].TexCoord2 := Vector2(0.0, 0.0);
- Rects[I, 3].TexCoord2 := Vector2(1.0, 0.0);
- end;
- // Place sprites
- PlaceRect(0, 0, 0);
- PlaceRect(1, DisplayWidth - SpriteWidth, 0);
- PlaceRect(2, 0, DisplayHeight - SpriteHeight);
- PlaceRect(3, DisplayWidth - SpriteWidth, DisplayHeight - SpriteHeight);
- end;
- procedure Present;
- begin
- Device.Clear(0, nil, D3DCLEAR_TARGET, $FFCCFFFF, 1.0, 0);
- if Succeeded(Device.BeginScene) then
- begin
- Device.SetFVF(FVF_VERTEX);
- // First render background
- Device.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
- Device.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
- Device.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
- Device.SetTexture(0, BackTex);
- Device.DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, BackRect, SizeOf(TVertex));
- Device.SetTexture(0, SpriteTex);
- Device.SetTexture(1, SpriteTex);
- // Render first sprite
- Device.DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, Rects[0], SizeOf(TVertex));
- // Render second sprite
- Device.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_ADDSIGNED);
- Device.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_ADDSIGNED);
- Device.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
- Device.DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, Rects[1], SizeOf(TVertex));
- // Render third sprite
- Device.SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
- Device.SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
- Device.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
- Device.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
- Device.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_SUBTRACT);
- Device.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
- Device.DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, Rects[2], SizeOf(TVertex));
- Device.SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
- Device.SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
- // Render last sprite
- Device.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DOTPRODUCT3);
- Device.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DOTPRODUCT3);
- Device.DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, Rects[3], SizeOf(TVertex));
- Device.SetTexture(0, nil);
- Device.SetTexture(1, nil);
- Device.EndScene;
- end;
- // Copy backbuffer to window
- Device.Present(nil, nil, 0, nil);
- end;
- procedure Finalize;
- begin
- BackTex := nil;
- SpriteTex := nil;
- Device := nil;
- Direct3D := nil;
- Imaging.FreeImage(SpriteImage);
- end;
- procedure TakeScreenShot;
- var
- RenderTarget, OldRenderTarget: IDirect3DSurface9;
- ScreenImg: TImageData;
- begin
- // Create new render target and activate it
- Device.CreateRenderTarget(DisplayWidth, DisplayHeight, D3DFMT_A8R8G8B8,
- D3DMULTISAMPLE_NONE, 0, True, RenderTarget, nil);
- Device.GetRenderTarget(0, OldRenderTarget);
- Device.SetRenderTarget(0, RenderTarget);
- // Render to new target
- Present;
- // Activate old target
- Device.SetRenderTarget(0, OldRenderTarget);
- // Convert reder target surface to Imaging image and save it to file
- ImagingDirect3D9.CreateImageFromD3DSurface(RenderTarget, ScreenImg);
- Imaging.SaveImageToFile(SOutScreenFile, ScreenImg);
- // Free all
- Imaging.FreeImage(ScreenImg);
- RenderTarget := nil;
- OldRenderTarget := nil;
- end;
- procedure RunDemo;
- begin
- // Initialize SDL
- if (SDL_Init(SDL_INIT_VIDEO) < 0) then
- MessageOutAndHalt(GetActiveWindow, 'SDL initialization failed: %s', [SDL_GetError]);
- SDL_WM_SetCaption(PAnsiChar(AnsiString(Format(SWindowTitle, [Imaging.GetVersionStr,
- GetFormatName(SpriteFormat)]))), SWindowIconTitle);
- SDL_WM_SetIcon(LoadSDLSurfaceFromFile(GetDataDir + PathDelim + SIconFile), 0);
- // Initialize video mode
- DisplaySurface := SDL_SetVideoMode(DisplayWidth, DisplayHeight, 32, 0);
- if DisplaySurface = nil then
- MessageOutAndHalt(GetActiveWindow, 'SDL SetVideoMode failed: %s', [SDL_GetError]);
- // Initialize surfaces and enter main loop
- Initialize;
- LastTime := SDL_GetTicks;
- while Running do
- begin
- while SDL_PollEvent(@Event) = 1 do
- begin
- case Event.type_ of
- SDL_QUITEV:
- begin
- Running := False;
- end;
- SDL_KEYDOWN:
- begin
- with Event.key.keysym do
- if ((sym = SDLK_F4) and ((modifier and KMOD_ALT) <> 0)) or
- (Event.key.keysym.sym = SDLK_ESCAPE) then
- Running := False;
- // Using S and D keys you can take screen shots and texture
- // shots easily
- // SPACE key can be used to cycle sprite image formats
- case Event.key.keysym.sym of
- SDLK_S: TakeScreenShot;
- SDLK_D: ImagingDirect3D9.SaveD3DTextureToFile(SOutSpriteFile, SpriteTex);
- SDLK_SPACE:
- begin
- SpriteFormat := NextFormat(SpriteFormat);
- CreateSpriteTexture(Device, SpriteFormat);
- UpdateCaption;
- end;
- end;
- end;
- end;
- end;
- // Calculate FPS
- if LongInt(SDL_GetTicks) - LastTime > 1000 then
- begin
- FPS := Frames;
- UpdateCaption;
- Frames := 0;
- LastTime := SDL_GetTicks;
- end;
- Inc(Frames);
- // Renders background and sprites to the window
- Present;
- end;
- // Frees all textures, images, and D3D objects
- Finalize;
- SDL_Quit;
- end;
- {
- File Notes:
- -- 0.77.1 ---------------------------------------------------
- - Refactored the demo (moved stuff to unit from dpr) and
- added Lazarus project files.
- -- 0.26.1 Changes/Bug Fixes ---------------------------------
- - Delphi 2009 compatibility pchar/string changes.
- -- 0.17 Changes/Bug Fixes -----------------------------------
- - S key now saves screenshot to file
- }
- end.
|