Fri 01 Sep 06 @ 2:56 pm
The video engine of VirtualDJ is based on 3 different engines:
- For Windows 32-bit, it uses Direct3D 9
- For Windows 64-bit, it uses Direct3D 11
- For Mac OS, it uses OpenGL
This topic is dedicated to Direct3D only.
1) Direct3D deviceFirst we advise you to define the following lines in your CMyPlugin class (for easier compatibility):
#if (defined(VDJ_WIN))
#if (defined(_M_X64) || defined(__amd64__))
#define VDJ_D3D11
#include <D3D11_4.h>
#pragma comment (lib, "D3D11.lib")
#else
#define VDJ_D3D9
#include <d3dx9.h>
#pragma comment(lib, "d3dx9.lib")
#endif
#ifndef SAFE_RELEASE
#define SAFE_RELEASE(x) { if (x!=NULL) { x->Release(); x=NULL; } }
#endif
#elif (defined(VDJ_MAC))
#define VDJ_OPENGL
#include <OpenGL/OpenGL.h> // you have to import OpenGL.framework in the XCode project
#endif
class CMyPlugin : public IVdjPluginVideoXXXXXX
{
public:
//…………...
private:
#if (defined(VDJ_D3D9))
static const EVdjVideoEngine VDJVIDEOENGINE = VdjVideoEngineDirectX9;
typedef IDirect3DDevice9 VDJVIDEODEVICE;
typedef IDirect3DTexture9 VDJVIDEOTEXTURE;
VDJVIDEODEVICE *pVDJDevice;
VDJVIDEOTEXTURE *pVDJTexture;
#elif (defined(VDJ_D3D11))
static const EVdjVideoEngine VDJVIDEOENGINE = VdjVideoEngineDirectX11;
typedef ID3D11Device VDJVIDEODEVICE;
typedef ID3D11ShaderResourceView VDJVIDEOTEXTURE;
VDJVIDEODEVICE *pVDJDevice;
VDJVIDEOTEXTURE *pVDJTexture;
ID3D11DeviceContext* pDeviceContext;
// ID3D11RenderTargetView* pRenderTargetView;
// ID3D11DepthStencilView* pDepthStencilView;
// ID3D11Resource* texResource ;
// ID3D11Texture2D* pTexture;
#elif (defined(VDJ_OPENGL))
static const EVdjVideoEngine VDJVIDEOENGINE = VdjVideoEngineOpenGL;
#endif
};
As VDJVIDEODEVICE is defined inside of VirtualDJ, you have to use the following function from the VirtualDJ video plugins SDK to get a pointer to it:
HRESULT VDJ_API CMyPlugin::OnDeviceInit()
{
#if (defined(VDJ_D3D9) || defined(VDJ_D3D11))
HRESULT hr = S_FALSE;
void *device = NULL;
hr = GetDevice(VDJVIDEOENGINE, &device);
if(hr!=S_OK || device==NULL) return S_FALSE;
pVDJDevice = reinterpret_cast<VDJVIDEODEVICE*>(device);
#endif
return S_OK;
}
Each time you want to use a Direct3D functions "xxxx", you have to use "pVDJDevice->xxxxxx"
You don't need to delete/release the pVDJDevice pointer.
2) VertexA vertex is a dot in the space defined by a struct TVertex
(NB: one vertex, two vertices)
3D models in Direct3D are based on triangles:
To define a triangle, you need 3 Vertices: vertices[0], vertices[1], vertices[2]
To define a square so 4 Vertices: vertices[0], vertices[1], vertices[2], vertices[3], you need 2 triangles :
{vertices[0], vertices[1], vertices[2]} and {vertices[1], vertices[3], vertices[2]}
struct TVertex
{
struct {float x,y,z;} position; // The 3D position (coordinates) for the vertex
DWORD color; // The vertex color
float tu,tv; // The texture coordinates
};
TVertex Vertex[4];
// for video fx plugins:
hr = GetTexture(VDJVIDEOENGINE,(void **)&pVDJTexture, &Vertex);
// for video transitions:
int iDeck = 1; // iDeck = 1 (left), 2 (right), ...
memcpy(Vertex,GetVertices(iDeck), 4*sizeof(TVertex));
- For SDK8:
Vertex[0].position.x=0.0f;
Vertex[0].position.y=0.0f;
Vertex[0].position.z=0.5f;
Vertex[0].color=D3DCOLOR_RGBA(255,255,255,255);
Vertex[0].tu=0.0f;
Vertex[0].tv=0.0f;
Vertex[1].position.x=1.0f * width;
Vertex[1].position.y=0.0f;
Vertex[1].position.z=0.5f
Vertex[1].color=D3DCOLOR_RGBA(255,255,255,255);
Vertex[1].tu=1.0f;
Vertex[1].tv=0.0f;
Vertex[2].position.x=1.0f * width;
Vertex[2].position.y=1.0f * height;
Vertex[2].position.z=0.5f;
Vertex[2].color=D3DCOLOR_RGBA(255,255,255,255);
Vertex[2].tu=1.0f;
Vertex[2].tv=1.0f;
Vertex[3].position.x=0.0f;
Vertex[3].position.y=1.0f * height;
Vertex[3].position.z=0.5f;
Vertex[3].color=D3DCOLOR_RGBA(255,255,255,255);
Vertex[3].tu=0.0f;
Vertex[3].tv=1.0f;
you can also define your own vertex to be used with pixel shaders (for Video FX):
struct D3DXCOLOR
{
public:
D3DXCOLOR() = default;
D3DXCOLOR(float r, float g, float b, float a)
{
this->r = r;
this->g = g;
this->b = b;
this->a = a;
}
operator FLOAT* ()
{
return &r;
}
float r, g, b, a;
};
struct TLVERTEX
{
struct { float x, y, z; } position;
D3DXCOLOR color;
float tu, tv;
};
- For SDK6 and previous: [deprecated in SDK8]
Vertex[0].position.x=-1.0f;
Vertex[0].position.y=1.0f;
Vertex[0].position.z=0.5f;
Vertex[0].color=D3DCOLOR_RGBA(255,255,255,255);
Vertex[0].tu=0.0f;
Vertex[0].tv=0.0f;
Vertex[1].position.x=1.0f;
Vertex[1].position.y=1.f;
Vertex[1].position.z=0.5f;
Vertex[1].color=D3DCOLOR_RGBA(255,255,255,255);
Vertex[1].tu=1.0f;
Vertex[1].tv=0.0f;
Vertex[2].position.x=-1.0f;
Vertex[2].position.y=-1.0f;
Vertex[2].position.z=0.5f;
Vertex[2].color=D3DCOLOR_RGBA(255,255,255,255);
Vertex[2].tu=0.0f;
Vertex[2].tv=1.0f;
Vertex[3].position.x=1.0f;
Vertex[3].position.y=-1.0f;
Vertex[3].position.z=0.5f;
Vertex[3].color=D3DCOLOR_RGBA(255,255,255,255);
Vertex[3].tu=1.0f;
Vertex[3].tv=1.0f;
// Color definition
#ifndef D3DCOLOR_DEFINED
#define D3DCOLOR_DEFINED
typedef DWORD D3DCOLOR;
#endif
#define D3DCOLOR_ARGB(a,r,g,b) \
((D3DCOLOR)((((a)&0xFF)<<24)|(((r)&0xFF)<<16)|(((g)&0xFF)<<8)|((b)&0xFF)))
#define D3DCOLOR_RGBA(r,g,b,a) D3DCOLOR_ARGB(a,r,g,b)
// Color definition (0xFF = 255)
#define GetRValue_D3DColor(d3dcolor) ((d3dcolor>>16)&255 )
#define GetGValue_D3DColor(d3dcolor) ((d3dcolor>>8)&255 )
#define GetBValue_D3DColor(d3dcolor) ((d3dcolor)&255 )
#define GetAValue_D3DColor(d3dcolor) ((d3dcolor>>24)&255 )
// Some colors
#define COLOR_BLACK D3DCOLOR_RGBA(0,0,0,255)
#define COLOR_WHITE D3DCOLOR_RGBA(255,255,255,255)
#define COLOR_RED D3DCOLOR_RGBA(255,0,0,255)
#define COLOR_GREEN D3DCOLOR_RGBA(0,255,0,255)
#define COLOR_BLUE D3DCOLOR_RGBA(0,0,255,255)
#define COLOR_YELLOW D3DCOLOR_RGBA(255,255,0,255)
#define COLOR_MAGENTA D3DCOLOR_RGBA(255,0,255,255)
#define COLOR_CYAN D3DCOLOR_RGBA(0,255,255,255)
3) Renderering: HRESULT VDJ_API CMyPlugin::OnDrawXXXX(xxxxx,yyyyyy)
{
HRESULT hr;
hr = DrawDeck(iDeck, Vertex);
return S_OK;
}
or
HRESULT VDJ_API CMyPlugin::OnDraw()
{
HRESULT hr;
#if (defined(VDJ_D3D11))
if (pVDJDevice)
{
pVDJDevice->GetImmediateContext(&pDeviceContext);
}
#endif
hr = DrawDeck();
return S_OK;
}
return S_FALSE; will automatically render the video for you
if you want to render by yourself, you can use for example the following function:
pVDJDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,(LPVOID)Vertex,sizeof(Vertex[0]));
and in this case, use return S_OK;
D3D11_PRIMITIVE_TOPOLOGY PrimitiveTypology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
D3D11_BUFFER_DESC.D3D11_CPU_ACCESS_FLAG CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
D3D11_BUFFER_DESC.D3D11_USAGE Usage = D3D11_USAGE_DYNAMIC;
D3D11_BUFFER_DESC.D3D11_BIND_FLAG BindFlags = D3D11_BIND_VERTEX_BUFFER;
D3D11_RASTERIZER_DESC.D3D11_FILL_MODE FillMode = D3D11_FILL_SOLID;
D3D11_RASTERIZER_DESC.D3D11_CULL_MODE CullMode = D3D11_CULL_NONE;
4) Texturing:D
#if (defined(VDJ_D3D9))
VDJVIDEOTEXTURE *texture;
//IDirect3DSurface9 *surface;
#elif
VDJVIDEOTEXTURE *texture;
#elif (defined(VDJ_OPENGL))
GLuint GLTexture;
#endif
Format = DGXI_FORMAT_B8G8R8A8_UNORM
in the function OnDraw() is the current video texture
Then you apply the texture (video,bitmap,...) on this square with the following function:
pVDJDevice->SetTexture(0,texture);
NB: in this case "0" means the first stage of the video