I've been trying to port some DBP code over to C++ for a plugin (keep reading
), and I thought I'd take the plunge and try some DirectX programming.
I'm trying to find a fast way of pasting an image on screen, using the DirectX libraries (can't use GDK unfortunately as I want a plugin for DBPro).
//Custom vertex
typedef struct tlVertex
{
float x;
float y;
float z;
float rhw;
D3DCOLOR colour;
float u;
float v;
tlVertex() : x(0.0f), y(0.0f), z(0.0f), rhw(1.0f), colour(0xFF000000), u(0.0f), v(0.0f) {};
} TLVERTEX, *LPTLVERTEX;
TLVERTEX Vertices[4];
// Coming up...
void SetVertex(TLVERTEX &V, float x, float y, DWORD Color, float u, float v);
void RenderImage(LPDIRECT3DDEVICE9 pD3D, LPDIRECT3DTEXTURE9 &Img, LPDIRECT3DSURFACE9 &ToImg,
float x1, float y1, DWORD Color1, float u1, float v1,
float x2, float y2, DWORD Color2, float u2, float v2,
float x3, float y3, DWORD Color3, float u3, float v3,
float x4, float y4, DWORD Color4, float u4, float v4);
EXPORT void MyPasteImage(int ImgID, int X, int Y)
{
// if (!dbGetPointer) return;
// MessageBox(NULL, "One", "DarkGUI Error!", MB_OK);
// Get image
LPDIRECT3DTEXTURE9 Texture;
LPDIRECT3DSURFACE9 Surface;
D3DSURFACE_DESC SurfaceDesc;
// Get access to image data from DBP - this gives a pointer to the texture
Texture = dbGetPointer(ImgID);
if (!Texture) return;
if (Texture->GetSurfaceLevel(0, &Surface) != D3D_OK) return;
if (Surface->GetDesc(&SurfaceDesc) != D3D_OK)
{
Surface->Release();
Surface = NULL;
return;
}
// MessageBox(NULL, "Two", "DarkGUI Error!", MB_OK);
LPDIRECT3DDEVICE9 pD3D = dbGetD3DDevice();
// MessageBox(NULL, "Got device", "DarkGUI Error!", MB_OK);
// Setup Render states???
pD3D->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
pD3D->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
pD3D->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
//Alpha value algorithm
pD3D->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
pD3D->SetRenderState(D3DRS_SRCBLENDALPHA, D3DBLEND_ONE);
pD3D->SetRenderState(D3DRS_DESTBLENDALPHA, D3DBLEND_ONE);
DWORD MinFilter = 0;
DWORD MagFilter = 0;
DWORD MipFilter = 0;
DWORD AddressU = 0;
DWORD AddressV = 0;
pD3D->SetSamplerState( 0, D3DSAMP_MINFILTER, MinFilter );
pD3D->SetSamplerState( 0, D3DSAMP_MAGFILTER, MagFilter );
pD3D->SetSamplerState( 0, D3DSAMP_MIPFILTER, MipFilter );
pD3D->SetSamplerState( 0, D3DSAMP_ADDRESSU, AddressU );
pD3D->SetSamplerState( 0, D3DSAMP_ADDRESSV, AddressV );
int Top = 200;
int Left = 200;
int Right = 250;
int Bottom = 250;
// MessageBox(NULL, "Trying to render image...", "DarkGUI Error!", MB_OK);
// Render
RenderImage(pD3D, Texture, g_pGlob->pCurrentBitmapSurface,
(float)Left, (float)Top, 0xFFFFFFFF, 0.0f, 0.0f,
(float)Right, (float)Top, 0xFFFFFFFF, 1.0f, 0.0f,
(float)Right, (float)Bottom, 0xFFFFFFFF, 1.0f, 1.0f,
(float)Left, (float)Bottom, 0xFFFFFFFF, 0.0f, 1.0f);
}
void RenderImage(LPDIRECT3DDEVICE9 pD3D, LPDIRECT3DTEXTURE9 &Img, LPDIRECT3DSURFACE9 &ToImg,
float x1, float y1, DWORD Color1, float u1, float v1,
float x2, float y2, DWORD Color2, float u2, float v2,
float x3, float y3, DWORD Color3, float u3, float v3,
float x4, float y4, DWORD Color4, float u4, float v4)
{
//Set new values
pD3D->SetRenderTarget(0, ToImg);
pD3D->SetTexture (0, Img);
pD3D->SetDepthStencilSurface(NULL);
//Set render states
pD3D->SetRenderState ( D3DRS_FILLMODE, D3DFILL_SOLID );
pD3D->SetRenderState ( D3DRS_DITHERENABLE, FALSE );
pD3D->SetRenderState ( D3DRS_LIGHTING, FALSE);
pD3D->SetRenderState ( D3DRS_CULLMODE, D3DCULL_NONE );
pD3D->SetRenderState ( D3DRS_FOGENABLE, FALSE );
pD3D->SetRenderState ( D3DRS_ZWRITEENABLE, FALSE );
pD3D->SetRenderState ( D3DRS_ZENABLE, FALSE );
// Set texture stage states
pD3D->SetTextureStageState ( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
pD3D->SetTextureStageState ( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
pD3D->SetTextureStageState ( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
pD3D->SetTextureStageState ( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
pD3D->SetTextureStageState ( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
pD3D->SetTextureStageState ( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
//Lock the vertex buffer
SetVertex(Vertices[0], x1, y1, Color1, u1, v1);
SetVertex(Vertices[1], x2, y2, Color2, u2, v2);
SetVertex(Vertices[2], x3, y3, Color3, u3, v3);
SetVertex(Vertices[3], x4, y4, Color4, u4, v4);
//Draw image
pD3D->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1);
pD3D->DrawPrimitiveUP (D3DPT_TRIANGLEFAN, 2, Vertices, sizeof(TLVERTEX));
//Reset for DBP
pD3D->SetRenderTarget(0, g_pGlob->pCurrentBitmapSurface);
pD3D->SetDepthStencilSurface(g_pGlob->pHoldDepthBufferPtr);
pD3D->SetRenderState ( D3DRS_ALPHABLENDENABLE, FALSE );
pD3D->SetRenderState ( D3DRS_ZENABLE, TRUE );
pD3D->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
}
void SetVertex(TLVERTEX &V, float x, float y, DWORD Color, float u, float v)
{
V.colour = Color;
V.x = (float)x - 0.5f;
V.y = (float)y - 0.5f;
V.z = 0.0f;
V.u = u;
V.v = v;
}
This code works
but:
1) a 50x50 pixel image is pasted as 64x64 - a suspicious "power of two". How do I paste it at actual size, and not stretched up to a texture size?
2) The code runs slower than DBP's own PasteImage command. I thought the whole point of C++ was that it would be faster than DBP itself - so what have I done wrong?
3) most importantly - most of this code came from SvenB's image kit plugin. I don't really know what the render state settings/flags actually mean. Help??
We spend our lives chasing dreams. Dark Basic lets us catch some of them.