http://blog.csdn.net/shenzi/article/details/4395155Direct3D立体显示实现
这是根据上篇文章而写的基于Direct3D的立体显示:
// include the basic windows header files and the Direct3D header file
#include <windows.h>
#include <windowsx.h>
#include <d3d9.h>
#include <d3dx9.h>
// include the Direct3D Library files
#pragma comment (lib , "d3d9.lib" )
#pragma comment (lib , "d3dx9.lib" )
// define the screen resolution and keyboard macros
#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480
#define KEY_DOWN (vk_code ) ((GetAsyncKeyState (vk_code ) & 0x8000) ? 1 : 0)
#define KEY_UP (vk_code ) ((GetAsyncKeyState (vk_code ) & 0x8000) ? 0 : 1)
// global declarations
LPDIRECT3D9 d3d ; // the pointer to our Direct3D interface
LPDIRECT3DDEVICE9 d3ddev ; // the pointer to the device class
// mesh declarations
LPD3DXMESH meshSpaceship ; // define the mesh pointer
D3DMATERIAL9 * material ; // define the material object
LPDIRECT3DTEXTURE9 * texture ; // a pointer to a texture
DWORD numMaterials ; // stores the number of materials in the mesh
double StereoCameraOffset ; // half the overall camera separation
double Xrange ;//the horizontal range of the scene along the plane of zero parallax
// adjust the strength of the stereo effect to suit their preference.
double UserOffsetAdjustment = 1.0;
double ZeroParallaxDistance = 7.0; // zero parallax distance
double n_over_d ; // NearClipDistance / ZeroParallaxDistance;
double UserBalanceAdjustment = 1.0; // adjust the parallax balance to their liking
double FrustumAsymmetry ; // the desired amount of frustum asymmetry
// are the arguments of the original symmetric frustum projection
double FrustumLeft = -0.5;
double FrustumRight = 0.5;
double NearClipDistance = 1.0;
double FarClipDistance = 100.0;
double FrustumBottom = -0.5;
double FrustumTop = 0.5;
double ObjectDistance = ZeroParallaxDistance ;
float g_fSpinX = 0.0f;
float g_fSpinY = 0.0f;
// function prototypes
void initD3D (HWND hWnd ); // sets up and initializes Direct3D
void render_frame (void ); // renders a single frame
void cleanD3D (void ); // closes Direct3D and releases memory
void init_graphics (void ); // 3D declarations
// the WindowProc function prototype
LRESULT CALLBACK WindowProc (HWND hWnd , UINT message , WPARAM wParam , LPARAM lParam );
// the entry point for any Windows program
int WINAPI WinMain (HINSTANCE hInstance ,
HINSTANCE hPrevInstance ,
LPSTR lpCmdLine ,
int nCmdShow )
{
HWND hWnd ;
WNDCLASSEX wc ;
ZeroMemory (&wc , sizeof (WNDCLASSEX ));
wc .cbSize = sizeof (WNDCLASSEX );
wc .style = CS_HREDRAW | CS_VREDRAW ;
wc .lpfnWndProc = (WNDPROC )WindowProc ;
wc .hInstance = hInstance ;
wc .hCursor = LoadCursor (NULL , IDC_ARROW );
wc .lpszClassName = L "WindowClass1" ;
RegisterClassEx (&wc );
hWnd = CreateWindowEx (NULL ,
L "WindowClass1" ,
L "Our Direct3D Program" ,
WS_EX_TOPMOST | WS_POPUP ,
0, 0,
SCREEN_WIDTH , SCREEN_HEIGHT ,
NULL ,
NULL ,
hInstance ,
NULL );
ShowWindow (hWnd , nCmdShow );
// set up and initialize Direct3D
initD3D (hWnd );
// enter the main loop:
MSG msg ;
while (TRUE )
{
DWORD starting_point = GetTickCount ();
if (PeekMessage (&msg , NULL , 0, 0, PM_REMOVE ))
{
if (msg .message == WM_QUIT )
break ;
TranslateMessage (&msg );
DispatchMessage (&msg );
}
render_frame ();
// check the 'escape' key
if (KEY_DOWN (VK_ESCAPE ))
PostMessage (hWnd , WM_DESTROY , 0, 0);
while ((GetTickCount () - starting_point ) < 25);
}
// clean up DirectX and COM
cleanD3D ();
return msg .wParam ;
}
// this is the main message handler for the program
LRESULT CALLBACK WindowProc (HWND hWnd , UINT message , WPARAM wParam , LPARAM lParam )
{
static POINT ptLastMousePosit ;
static POINT ptCurrentMousePosit ;
static bool bMousing ;
switch (message )
{
case WM_DESTROY :
{
PostQuitMessage (0);
return 0;
} break ;
case WM_KEYDOWN :
{
switch (wParam )
{
case VK_F1 :
if (UserOffsetAdjustment <= 2.0)
{
UserOffsetAdjustment += 0.1;
}
break ;
case VK_F2 :
if (UserOffsetAdjustment > 0.0)
{
UserOffsetAdjustment -= 0.1;
}
break ;
case VK_F3 :
if (UserBalanceAdjustment <= 2.0)
{
UserBalanceAdjustment += 0.1;
}
break ;
case VK_F4 :
if (UserBalanceAdjustment > 0.0)
{
UserBalanceAdjustment -= 0.1;
}
break ;
case VK_UP :
ObjectDistance += 0.1;
break ;
case VK_DOWN :
ObjectDistance -= 0.1;
break ;
}
}
break ;
case WM_LBUTTONDOWN :
{
ptLastMousePosit .x = ptCurrentMousePosit .x = LOWORD (lParam );
ptLastMousePosit .y = ptCurrentMousePosit .y = HIWORD (lParam );
bMousing = true ;
}
break ;
case WM_LBUTTONUP :
{
bMousing = false ;
}
break ;
case WM_MOUSEMOVE :
{
ptCurrentMousePosit .x = LOWORD (lParam );
ptCurrentMousePosit .y = HIWORD (lParam );
if ( bMousing )
{
g_fSpinX -= (ptCurrentMousePosit .x - ptLastMousePosit .x );
g_fSpinY -= (ptCurrentMousePosit .y - ptLastMousePosit .y );
}
ptLastMousePosit .x = ptCurrentMousePosit .x ;
ptLastMousePosit .y = ptCurrentMousePosit .y ;
}
break ;
}
return DefWindowProc (hWnd , message , wParam , lParam );
}
// this function initializes and prepares Direct3D for use
void initD3D (HWND hWnd )
{
d3d = Direct3DCreate9 (D3D_SDK_VERSION );
D3DPRESENT_PARAMETERS d3dpp ;
ZeroMemory (&d3dpp , sizeof (d3dpp ));
d3dpp .Windowed = FALSE ;
d3dpp .SwapEffect = D3DSWAPEFFECT_DISCARD ;
d3dpp .hDeviceWindow = hWnd ;
d3dpp .BackBufferFormat = D3DFMT_X8R8G8B8 ;
d3dpp .BackBufferWidth = SCREEN_WIDTH ;
d3dpp .BackBufferHeight = SCREEN_HEIGHT ;
d3dpp .EnableAutoDepthStencil = TRUE ; // automatically run the z-buffer for us
d3dpp .AutoDepthStencilFormat = D3DFMT_D16 ; // 16-bit pixel format for the z-buffer
// create a device class using this information and the info from the d3dpp stuct
d3d ->CreateDevice (D3DADAPTER_DEFAULT ,
D3DDEVTYPE_HAL ,
hWnd ,
D3DCREATE_HARDWARE_VERTEXPROCESSING ,
&d3dpp ,
&d3ddev );
// create the z-buffer
d3ddev ->CreateDepthStencilSurface (SCREEN_WIDTH ,
SCREEN_HEIGHT ,
D3DFMT_D16 ,
D3DMULTISAMPLE_NONE ,
0,
TRUE ,
&z_buffer ,
NULL );
init_graphics (); // call the function to initialize the triangle
d3ddev ->SetRenderState (D3DRS_LIGHTING , FALSE ); // turn on the 3D lighting
d3ddev ->SetRenderState (D3DRS_ZENABLE , TRUE ); // turn on the z-buffer
d3ddev ->SetRenderState (D3DRS_AMBIENT , D3DCOLOR_XRGB (50, 50, 50));// ambient light
return ;
}
// this is the function used to render a single frame
void render_frame (void )
{
n_over_d = NearClipDistance / ZeroParallaxDistance ;
Xrange = (FrustumRight - FrustumLeft ) / n_over_d ;
StereoCameraOffset = Xrange * 0.035 * UserOffsetAdjustment ;
FrustumAsymmetry = StereoCameraOffset * UserBalanceAdjustment ;
FrustumAsymmetry *= n_over_d ;
d3ddev ->Clear (0, NULL , D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER , D3DCOLOR_XRGB (20, 20, 20), 1.0f, 0);
D3DXMATRIX matProjection ; // the projection transform matrix
D3DXMATRIX matLeftTrans ; // the left-eye transform matrix
D3DXMATRIX matRightTrans ; // the right-eye transform matrix
D3DXMATRIX matRot ; //the rotation matrix
D3DXMATRIX matScale ; //the scale matrix
D3DXMatrixScaling (&matScale , 0.4f, 0.4f, 0.4f);
d3ddev ->BeginScene ();
D3DXMatrixPerspectiveOffCenterLH (&matProjection , FrustumLeft + FrustumAsymmetry , FrustumRight + FrustumAsymmetry , FrustumBottom , FrustumTop , NearClipDistance , FarClipDistance );
d3ddev ->SetTransform (D3DTS_PROJECTION , &matProjection ); // set the projection
D3DXMatrixRotationYawPitchRoll ( &matRot ,
D3DXToRadian (g_fSpinX ),
D3DXToRadian (g_fSpinY ),
0.0f );
// Draw left eye view
D3DXMatrixTranslation (&matLeftTrans , StereoCameraOffset , 0.0f, ObjectDistance );
d3ddev ->SetTransform (D3DTS_WORLD , &(matScale *matRot *matLeftTrans ));
d3ddev ->SetRenderState (D3DRS_COLORWRITEENABLE ,D3DCOLORWRITEENABLE_RED );
// draw the spaceship
for (DWORD i = 0; i < numMaterials ; i ++) // loop through each subset
{
d3ddev ->SetMaterial (&material [i ]); // set the material for the subset
if (texture [i ] != NULL ) // if the subset has a texture (if texture is not NULL)
d3ddev ->SetTexture (0, texture [i ]); // ...then set the texture
meshSpaceship ->DrawSubset (i ); // draw the subset
}
// Draw right eye view
d3ddev ->Clear (0, NULL , D3DCLEAR_ZBUFFER , D3DCOLOR_XRGB (20, 20, 20), 1.0f, 0); D3DXMatrixTranslation (&matRightTrans , -StereoCameraOffset , 0.0f,ObjectDistance );
d3ddev ->SetTransform (D3DTS_WORLD , &(matScale *matRot *matRightTrans ));
D3DXMatrixPerspectiveOffCenterLH (&matProjection , FrustumLeft - FrustumAsymmetry , FrustumRight - FrustumAsymmetry , FrustumBottom , FrustumTop , NearClipDistance , FarClipDistance );
d3ddev ->SetTransform (D3DTS_PROJECTION , &matProjection ); // set the projection
d3ddev ->SetRenderState (D3DRS_COLORWRITEENABLE , D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE );
// draw the spaceship
for (DWORD i = 0; i < numMaterials ; i ++) // loop through each subset
{
d3ddev ->SetMaterial (&material [i ]); // set the material for the subset
if (texture [i ] != NULL ) // if the subset has a texture (if texture is not NULL)
d3ddev ->SetTexture (0, texture [i ]); // ...then set the texture
meshSpaceship ->DrawSubset (i ); // draw the subset
}
d3ddev ->EndScene ();
d3ddev ->Present (NULL , NULL , NULL , NULL );
return ;
}
// this is the function that cleans up Direct3D and COM
void cleanD3D (void )
{
meshSpaceship ->Release (); // close and release the spaceship mesh
d3ddev ->Release (); // close and release the 3D device
d3d ->Release (); // close and release Direct3D
return ;
}
// this is the function that puts the 3D models into video RAM
void init_graphics (void )
{
LPD3DXBUFFER bufShipMaterial ;
D3DXLoadMeshFromX (L "airplane 2.x" , // load this file
D3DXMESH_SYSTEMMEM , // load the mesh into system memory
d3ddev , // the Direct3D Device
NULL , // we aren't using adjacency
&bufShipMaterial , // put the materials here
NULL , // we aren't using effect instances
&numMaterials , // the number of materials in this model
&meshSpaceship ); // put the mesh here
// retrieve the pointer to the buffer containing the material information
D3DXMATERIAL * tempMaterials = (D3DXMATERIAL *)bufShipMaterial ->GetBufferPointer ();
// create a new material buffer and texture for each material in the mesh
material = new D3DMATERIAL9 [numMaterials ];
texture = new LPDIRECT3DTEXTURE9 [numMaterials ];
for (DWORD i = 0; i < numMaterials ; i ++) // for each material...
{
material [i ] = tempMaterials [i ].MatD3D ; // get the material info
material [i ].Ambient = material [i ].Diffuse ; // make ambient the same as diffuse
// if there is a texture to load, load it
if (FAILED (D3DXCreateTextureFromFileA (d3ddev ,
tempMaterials [i ].pTextureFilename ,
&texture [i ])))
texture [i ] = NULL ; // if there is no texture, set the texture to NULL
}
return ;
}
当然需要带上红绿眼镜才能看得到立体效果哦~~