📄 3dtut.cpp
字号:
//This is a fully functional DX app that draws a triangle in fullscreen mode and rotates it (like the triangle sample in the SDK)
//e-mail me at wulf@ignmail.com for suggestions/requests/criticizims (no flames please, i'll just block you)
//Code Copyright (c) 2000, by Albert Chaulk
//Stuff: add winmm.lib ddraw.lib d3dim.lib d3dframe.lib & dxguid.lib to the project's link (and add/change directories
//to search, etc) If you still get errors, try adding #define INITGUID. If that doesn't work, add every lib in the SDK lib dir
#define D3D_OVERLOADS
#include <windows.h>
#include <mmsystem.h>
#include <ddraw.h>
#include <d3d.h>
#include <d3dtypes.h>
#include "d3dutil.h"
#include "d3dmath.h"//probably not needed for this
#include "d3dtextr.h"//probably not needed
LPDIRECT3D7 lp_D3D=NULL;
LPDIRECTDRAW7 lp_DD=NULL;
LPDIRECT3DDEVICE7 lpDevice=NULL;
LPDIRECTDRAWSURFACE7 lpPrimary=NULL;
LPDIRECTDRAWSURFACE7 lpBack=NULL;
LPDIRECTDRAWSURFACE7 lpZBuf=NULL;
#define Release(x) if(x){ x->Release(); /*delete x;*/ x=NULL; };
#define Delete(x) if(x){ /*x->Release();*/ delete x; x=NULL; };
#define ReleaseDelete(x) if(x){ x->Release(); delete x; x=NULL; };
struct ScreenProp{
UINT x;
UINT y;
UINT bpp;
ScreenProp::ScreenProp() { x=640; y=480; bpp=8; };//640x480x8 is universal
ScreenProp::ScreenProp(UINT nx,UINT ny,UINT nbpp) { x=nx; y=ny; bpp=nbpp; };
};
HWND m_hWnd;
BOOL InitGlobal(HRESULT &hr,ScreenProp scr);
void Render(LPDIRECTDRAWSURFACE7 lpSurf,LPDIRECTDRAWSURFACE7,LPDIRECT3DDEVICE7 lpDev,float elapsed,float);
LRESULT CALLBACK WindowProc(HWND hWnd,unsigned uMsg,WPARAM wParam,LPARAM lParam);
void Cleanup();
int WINAPI WinMain(HINSTANCE hInst,HINSTANCE hPrevInst,LPSTR lpCmd,int Show)
{
DWORD current_time;
DWORD last_time;
float time_elapsed;
float time_scale;
time_scale=0.001f;//constant 1ms in win95
const char class_name[]="Tutorial";
const char app_name[]="Albert Chaulk's Tutorial";
WNDCLASS wc;
wc.style=CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc=(WNDPROC)WindowProc;
wc.cbClsExtra=0;
wc.cbWndExtra=sizeof(DWORD);
wc.hInstance=hInst;
wc.hIcon=NULL;
wc.hCursor=LoadCursor(NULL,IDC_ARROW);
wc.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH);
wc.lpszMenuName=NULL;
wc.lpszClassName=class_name;
if(!RegisterClass(&wc))
return 0;
m_hWnd=CreateWindow(class_name,app_name,WS_VISIBLE|WS_POPUP,0,0,GetSystemMetrics(SM_CXSCREEN)
,GetSystemMetrics(SM_CYSCREEN),NULL,NULL,hInst,NULL);
if(!m_hWnd)
return 0;
ShowWindow(m_hWnd,SW_SHOW);
UpdateWindow(m_hWnd);
HRESULT hr;
InitGlobal(hr,ScreenProp(640,480,16));
BOOL bGotMsg;
MSG msg;
PeekMessage(&msg,NULL,0,0,PM_NOREMOVE);
while(msg.message!=WM_QUIT)
{
bGotMsg=PeekMessage(&msg,NULL,0,0,PM_REMOVE);
if(bGotMsg)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else{
current_time=timeGetTime();
time_elapsed=(current_time-last_time)*time_scale;
last_time=current_time;
Render(lpPrimary,lpBack,lpDevice,time_elapsed,current_time*time_scale);
}
}
// return final message
return msg.wParam;
}
LRESULT CALLBACK WindowProc(HWND hWnd,unsigned uMsg,WPARAM wParam,LPARAM lParam)
{
switch(uMsg){
case WM_KEYDOWN:
switch(wParam){
case VK_ESCAPE:
DestroyWindow(hWnd);
break;
}
break;
case WM_DESTROY:
Cleanup();
PostQuitMessage(0);
break;
}
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
void Render(LPDIRECTDRAWSURFACE7 lpSurf,LPDIRECTDRAWSURFACE7 lpBackBuf,LPDIRECT3DDEVICE7 lpDev,float elapsed,float total)
{
D3DMATRIX mat;
D3DVERTEX g_pvTriangleVertices[6];
D3DVECTOR p1( 0.0f, 3.0f, 0.0f );
D3DVECTOR p2( 3.0f,-3.0f, 0.0f );
D3DVECTOR p3(-3.0f,-3.0f, 0.0f );
D3DVECTOR vNormal( 0.0f, 0.0f, 1.0f );
// Initialize the 3 vertices for the front of the triangle
g_pvTriangleVertices[0] = D3DVERTEX( p1, vNormal, 0.0f, 0.0f );
g_pvTriangleVertices[1] = D3DVERTEX( p2, vNormal, 0.0f, 0.0f );
g_pvTriangleVertices[2] = D3DVERTEX( p3, vNormal, 0.0f, 0.0f );
// Initialize the 3 vertices for the back of the triangle
g_pvTriangleVertices[3] = D3DVERTEX( p1, -vNormal, 0.0f, 0.0f );
g_pvTriangleVertices[4] = D3DVERTEX( p3, -vNormal, 0.0f, 0.0f );
g_pvTriangleVertices[5] = D3DVERTEX( p2, -vNormal, 0.0f, 0.0f );
D3DMATERIAL7 mtrl;
ZeroMemory( &mtrl, sizeof(mtrl) );
mtrl.ambient.r = 1.0f;
mtrl.ambient.g = 1.0f;
mtrl.ambient.b = 0.0f;
if(FAILED(lpDev->BeginScene()))
return;
D3DUtil_SetViewMatrix(mat,D3DVECTOR(0.0f,0.0f,-15.0f),D3DVECTOR(0.0f,0.0f,1.0f),D3DVECTOR(0.0f,1.0f,0.0f));
lpDev->SetTransform(D3DTRANSFORMSTATE_VIEW,&mat);
D3DUtil_SetRotateYMatrix(mat,total);
lpDev->SetTransform(D3DTRANSFORMSTATE_WORLD,&mat);
lpDev->SetMaterial( &mtrl );
lpDev->SetRenderState( D3DRENDERSTATE_AMBIENT, 0xffffffff );
lpDev->Clear(0,NULL,D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET,0,1.0f,0);
lpDev->DrawPrimitive( D3DPT_TRIANGLELIST, D3DFVF_VERTEX,g_pvTriangleVertices, 6, NULL );
lpDev->EndScene();
lpSurf->Flip(lpBackBuf,0);
}
void Cleanup()
{
Release(lpDevice);
Release(lp_D3D);
Release(lpZBuf);
Release(lpBack);
Release(lpPrimary);
Release(lp_DD);
}
BOOL InitInterfaces(HRESULT& hr)
{
if(FAILED(hr=DirectDrawCreateEx(NULL,(VOID**)&lp_DD,IID_IDirectDraw7,NULL)))
return FALSE;
if(FAILED(hr=lp_DD->QueryInterface(IID_IDirect3D7,(VOID**)&lp_D3D)))
return FALSE;
return TRUE;
}
BOOL InitDDraw(HRESULT& hr,UINT x,UINT y,UINT bpp)
{
//set coop to exclusive, fullscreen mode. DDSCL_FPUSETUP is optional
if(FAILED(hr=lp_DD->SetCooperativeLevel(m_hWnd,DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN)))
return FALSE;
//set to x by y by bpp screen mode
if(FAILED(hr=lp_DD->SetDisplayMode(x,y,bpp,0,0)))
return FALSE;
//create primary surf, attach backbuffer
DDSURFACEDESC2 ddsd;
ZeroMemory(&ddsd,sizeof(ddsd));
ddsd.dwSize=sizeof(ddsd);
ddsd.dwFlags=DDSD_CAPS|DDSD_BACKBUFFERCOUNT;
ddsd.ddsCaps.dwCaps=DDSCAPS_PRIMARYSURFACE|DDSCAPS_FLIP|DDSCAPS_3DDEVICE|DDSCAPS_COMPLEX;
ddsd.dwBackBufferCount=1;
if(FAILED(hr=lp_DD->CreateSurface(&ddsd,&lpPrimary,NULL)))
return FALSE;
//get the backbuffer
DDSCAPS2 ddscaps;
ZeroMemory(&ddscaps,sizeof(ddscaps));
ddscaps.dwCaps=DDSCAPS_BACKBUFFER;
if(FAILED(hr=lpPrimary->GetAttachedSurface(&ddscaps,&lpBack)))
return FALSE;
return TRUE;
}
BOOL use_ZBuffer;
static HRESULT WINAPI EnumZBufferFormatsCallback(DDPIXELFORMAT *pddpf,VOID *pddpfDesired)
{
// if parameters==NULL, don't enumerate more
use_ZBuffer=FALSE;
if(pddpf==NULL||pddpfDesired==NULL)
return D3DENUMRET_CANCEL;
// if the current pixel format's match the desired ones (DDPF_ZBUFFER and
// possibly DDPF_STENCILBUFFER),lets copy it and return. This function is
// not choosy... it accepts the first valid format that comes along.
if(pddpf->dwFlags==((DDPIXELFORMAT*)pddpfDesired)->dwFlags)
{
memcpy(pddpfDesired,pddpf,sizeof(DDPIXELFORMAT));
use_ZBuffer=TRUE;
return D3DENUMRET_CANCEL;
}
return D3DENUMRET_OK;
}
BOOL InitD3D(HRESULT& hr,UINT x,UINT y)
{
DDPIXELFORMAT m_ddpfZBuffer;
ZeroMemory(&m_ddpfZBuffer,sizeof(m_ddpfZBuffer));
m_ddpfZBuffer.dwSize=sizeof(m_ddpfZBuffer);
m_ddpfZBuffer.dwFlags=DDPF_ZBUFFER;
int zbuf_format;
//get best format, from hardware to software
lp_D3D->EnumZBufferFormats(IID_IDirect3DTnLHalDevice,EnumZBufferFormatsCallback,(VOID*)&m_ddpfZBuffer);
if(use_ZBuffer){
zbuf_format=1;
}
else{
lp_D3D->EnumZBufferFormats(IID_IDirect3DHALDevice,EnumZBufferFormatsCallback,(VOID*)&m_ddpfZBuffer);
if(use_ZBuffer){
zbuf_format=2;
}
else{
lp_D3D->EnumZBufferFormats(IID_IDirect3DMMXDevice,EnumZBufferFormatsCallback,(VOID*)&m_ddpfZBuffer);
if(use_ZBuffer){
zbuf_format=3;
}
else{
lp_D3D->EnumZBufferFormats(IID_IDirect3DRGBDevice,EnumZBufferFormatsCallback,(VOID*)&m_ddpfZBuffer);
if(use_ZBuffer)
zbuf_format=4;
}
}
}
DDSURFACEDESC2 ddsd;
ZeroMemory(&ddsd,sizeof(ddsd));
ddsd.dwSize=sizeof(ddsd);
ddsd.dwFlags=DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT|DDSD_PIXELFORMAT;
if(use_ZBuffer){
if(zbuf_format<3)
ddsd.ddsCaps.dwCaps=DDSCAPS_ZBUFFER|DDSCAPS_VIDEOMEMORY;
else
ddsd.ddsCaps.dwCaps=DDSCAPS_ZBUFFER|DDSCAPS_SYSTEMMEMORY;
//set to res
ddsd.dwWidth=x;
ddsd.dwHeight=y;
ddsd.ddpfPixelFormat.dwSize=sizeof(DDPIXELFORMAT);
ddsd.ddpfPixelFormat.dwFlags=DDPF_ZBUFFER;
memcpy(&ddsd.ddpfPixelFormat,&m_ddpfZBuffer,sizeof(DDPIXELFORMAT));
if(FAILED(hr=lp_DD->CreateSurface(&ddsd,&lpZBuf,NULL)))
return FALSE;;
lpBack->AddAttachedSurface(lpZBuf);//add zbuf to surface
}
//get best device, from full t&l to software
if((hr=lp_D3D->CreateDevice(IID_IDirect3DTnLHalDevice,lpBack,&lpDevice))!=D3D_OK)
if((hr=lp_D3D->CreateDevice(IID_IDirect3DHALDevice,lpBack,&lpDevice))!=D3D_OK)
if((hr=lp_D3D->CreateDevice(IID_IDirect3DMMXDevice,lpBack,&lpDevice))!=D3D_OK)
if((hr=lp_D3D->CreateDevice(IID_IDirect3DRGBDevice,lpBack,&lpDevice))!=D3D_OK)
return FALSE;
//setup viewport
D3DVIEWPORT7 view;
view.dwX=0;
view.dwY=0;
view.dwWidth=x;
view.dwHeight=y;
view.dvMinZ=0.0f;
view.dvMaxZ=1.0f;
if(lpDevice->SetViewport(&view)!=D3D_OK)
return FALSE;
D3DMATRIX proj;
//Set projection matrix.
D3DUtil_SetProjectionMatrix(proj,0.8f,(float)((float)x/(float)y)/*1.333 is standard*/,10.0f,2000.0f/*min/max clipping*/);
lpDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION,&proj);
//linear tex filtering
lpDevice->SetTextureStageState(0,D3DTSS_MAGFILTER,D3DTFG_LINEAR|D3DTFG_ANISOTROPIC);
//Enable z-buffering.
lpDevice->SetRenderState(D3DRENDERSTATE_ZENABLE,TRUE);
//Set ambient light color
lpDevice->SetRenderState(D3DRENDERSTATE_AMBIENT,D3DRGBA(0.1f,0.1f,0.1f,0.1f));
return TRUE;
}
BOOL InitGlobal(HRESULT &hr,ScreenProp scr)
{
if(!InitInterfaces(hr))
return FALSE;
if(!InitDDraw(hr,scr.x,scr.y,scr.bpp))
return FALSE;
if(!InitD3D(hr,scr.x,scr.y))
return FALSE;
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -