d3d.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 819 行 · 第 1/2 页

C
819
字号
//---------------------------------------------------------------------------------------
//
// Simple Windows Direct3D Example Code
//
// Jim Shaw 12/3/2004
//
//---------------------------------------------------------------------------------------

//---------------------------------------------------------------------------------------
// always include windows.h for windows programs
//---------------------------------------------------------------------------------------
#include <windows.h>
#include <d3d9.h>
#include <d3dx9math.h>

#include <stdlib.h>
#include <string.h>
#include <math.h>

#include <assert.h>

//---------------------------------------------------------------------------------------
// Screen dimensions and other options
//---------------------------------------------------------------------------------------
#define SCREEN_X   640
#define SCREEN_Y   480
#define RUN_WINDOWED 1
#define USE_ZBUFFER  1

//---------------------------------------------------------------------------------------
// Variable to hold the address of the Windows window
//---------------------------------------------------------------------------------------
HWND game_window;

//---------------------------------------------------------------------------------------
// Name of our window class.  every class has a name.  every window is one of a class.
// this can be pretty much anything
//---------------------------------------------------------------------------------------
char game_class[]="D3DCWindow";
static int quit = 0;

//---------------------------------------------------------------------------------------
// function prototypes
//---------------------------------------------------------------------------------------
void draw(void);
void flip(void);
int init_d3d(int, int);
int init_cube(void);
void init_textures(void);
void animate(void);
void set_view(void);
void shutdown_d3d(void);

//---------------------------------------------------------------------------------------
// Direct3D Variables
//---------------------------------------------------------------------------------------
IDirect3D9 *d3d=NULL;
IDirect3DDevice9 *d3d_dev=NULL;
IDirect3DVertexBuffer9 *vertex_buffer=NULL;
IDirect3DTexture9 *texture[6]={0};
int textures_dynamic;
int zbuffer_enabled;
D3DFORMAT texture_format;

// Our custom FVF, which describes our custom vertex structure
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1)

typedef struct
{
    D3DXVECTOR3 position; // The position
    D3DCOLOR    color;    // The color
    FLOAT       tu, tv;   // The texture coordinates
} CUSTOMVERTEX;

//---------------------------------------------------------------------------------------
// Cube animation parameters
//---------------------------------------------------------------------------------------
float yaw=0.0f, pitch=0.0f, roll=0.0f, scale=20.0f;
float x=0.0f, y=0.0f, z=100.0f;
float xr=0.0f, yr=0.0f, zr=0.0f;
int animating=1;

//---------------------------------------------------------------------------------------
// Every window has a WindowProc which handles messages Windows sends to them.  These
// are things like key presses, mouse clicks, and thousands of other things you might
// be interested in.
//---------------------------------------------------------------------------------------
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch (uMsg)
	{
		//this message gets sent to the window when you click the close box on it
		case WM_DESTROY:
			//tell Windows to close the app
			PostQuitMessage(0);
			quit = 1;
			break;

		//this message gets sent when you press a key
		case WM_KEYDOWN:
			switch (wParam)
			{
				//pressed Escape key?
				case VK_ESCAPE:
					//tell Windows to close the app
					PostQuitMessage(0);
					quit = 1;
					break;

				//keyboard controls
				case 'A':		animating ^= 1; break;
				case 'R':
					yaw = 0.0f;
					pitch = 0.0f;
					roll = 0.0f;
					x=0.0f;
					y=0.0f;
					z=100.0f;
					scale=20.0f;
					xr=0.0f;
					yr=0.0f;
					zr=0.0f;
					break;
				case VK_UP: 	y += 10.0f; break;
				case VK_DOWN:	y -= 10.0f; break;
				case VK_LEFT:	x -= 10.0f; break;
				case VK_RIGHT:	x += 10.0f; break;
				case VK_PRIOR:	z += 10.0f; break;
				case VK_NEXT:	z -= 10.0f; break;

				case VK_NUMPAD7: yaw += 0.1f; break;
				case VK_NUMPAD4: yaw -= 0.1f; break;
				case VK_NUMPAD8: pitch += 0.1f; break;
				case VK_NUMPAD5: pitch -= 0.1f; break;
				case VK_NUMPAD9: roll += 0.1f; break;
				case VK_NUMPAD6: roll -= 0.1f; break;

				case VK_ADD:	  scale = scale + 10.0f; break;
				case VK_SUBTRACT: scale = scale - 10.0f; if (scale < 0.0f) scale = 0.0f; break;

			}
			break;

		//any message you don't process gets passed to this function inside Windows.
		default:
			return DefWindowProc(hwnd, uMsg, wParam, lParam);
	}
	//any message you do process, return 0 (unless the message documentation says otherwise)
return 0;
}

//---------------------------------------------------------------------------------------
// WinMain
//---------------------------------------------------------------------------------------
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	WNDCLASSEX clas;
	MSG msg;
	int style;
	RECT rect;
	int time;
	int elapsed;

	//Here we create the Class we named above
	clas.cbSize = sizeof(WNDCLASSEX);
	clas.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
	clas.lpfnWndProc = WindowProc;//<- tell it where the WindowProc is
	clas.cbClsExtra = 0;
	clas.cbWndExtra = 0;
	clas.hInstance = hInstance;
	clas.hIcon = NULL;
	clas.hCursor = NULL;
	clas.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);//<- background colour of window
	clas.lpszMenuName = NULL;
	clas.lpszClassName = game_class;//<- the class name
	clas.hIconSm = 0;
	//do it!
	RegisterClassEx(&clas);

	//style of the window - what boxes do we need (close minimised etc)
	style = WS_CAPTION|WS_SYSMENU|WS_MAXIMIZEBOX|WS_MINIMIZEBOX;
	//create the window
	game_window = CreateWindowEx(0, game_class, "Direct3D", style, CW_USEDEFAULT, CW_USEDEFAULT, 1,1, NULL, NULL, hInstance, 0);

	//adjust the window size so that a SCREEN_X x SCREEN_Y window will fit inside its frame
	rect.left = rect.top = 0;
	rect.right = SCREEN_X;
	rect.bottom = SCREEN_Y;
	AdjustWindowRectEx(&rect, style , FALSE, 0);
	SetWindowPos(game_window, NULL, 0,0, rect.right - rect.left, rect.bottom - rect.top, SWP_NOMOVE|SWP_NOZORDER);

	if (init_d3d(RUN_WINDOWED, USE_ZBUFFER) == 0)
	{
		MessageBox(NULL, "A problem occurred creating the Direct3D Device.\nCheck your video drivers and "
							"DirectX version.\nThis demo requires DirectX9.0 or better.", "DirectX Initialisation Error", MB_ICONWARNING|MB_OK);
		shutdown_d3d();
		return 0;
	}

	//show the window on the desktop
	ShowWindow(game_window, nCmdShow);

	//message processing loop
	//all Windows programs have one of these.  It receives the messages Windows sends to the program and
	//passes them to the WindowProc in the Class we registered for the window.
	quit = 0;
	do
	{
		//Are there any messages waiting?
		while (PeekMessage(&msg, game_window, 0, 0, PM_NOREMOVE))
		{
			//yes!  read it.
			if (GetMessage(&msg, game_window, 0,0) < 0)
				break;

			//pass the message to WindowProc
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}

		//get the current time
		time = GetTickCount();

		//draw my game!
		animate();
		draw();
		flip();
		//find out how long the frame took to draw
		elapsed = GetTickCount()-time;

	} while (!quit);

	shutdown_d3d();

	return 0;
}

//---------------------------------------------------------------------------------------
// Animate the cube
//---------------------------------------------------------------------------------------
void animate(void)
{
	if (animating)
	{
		yaw   += 0.01f;
		pitch += 0.02f;
		roll  += 0.03f;

		xr += 0.1f;
		yr += 0.2f;
		zr += 0.3f;

		x = (float)sin((double)xr)*10.0f;
		y = (float)sin((double)yr)*10.0f;
		z = (float)sin((double)zr)*10.0f+100.0f;
	}
}

//---------------------------------------------------------------------------------------
// Initialise all the direct3d structures we need
//---------------------------------------------------------------------------------------
int init_d3d(int windowed, int zbuffered)
{
	D3DCAPS9 d3dcaps9;
	D3DDISPLAYMODE d3ddm;
	D3DPRESENT_PARAMETERS d3dpp;
	D3DCAPS9 caps;
	HRESULT hr;
	D3DFORMAT depth_format;

	// Create the D3D device
    d3d = Direct3DCreate9(D3D_SDK_VERSION);
	if (d3d == NULL)
		return 0;

	// Get some information about the device and display adapter
	hr = IDirect3D9_GetDeviceCaps(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &d3dcaps9);

	if (windowed)
		hr = IDirect3D9_GetAdapterDisplayMode(d3d, D3DADAPTER_DEFAULT, &d3ddm);
	else
		d3ddm.Format = D3DFMT_X8R8G8B8;

	// Work out a depth format
	depth_format = D3DFMT_D32;
	hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, d3ddm.Format, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D32);
	if (hr != D3D_OK)
	{
		depth_format = D3DFMT_D16;
		hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, d3ddm.Format, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D16);
		if (hr != D3D_OK)
			return 0;
	}

	// Work out a texture format
	texture_format = D3DFMT_A8R8G8B8;
	hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, d3ddm.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_A8R8G8B8);
	if (hr != D3D_OK)
	{
		texture_format = D3DFMT_X8R8G8B8;
		hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, d3ddm.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_X8R8G8B8);
		if (hr != D3D_OK)
		{
			texture_format = D3DFMT_A1R5G5B5;
			hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, d3ddm.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_A1R5G5B5);
			if (hr != D3D_OK)
			{
				texture_format = D3DFMT_R5G6B5;
				hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, d3ddm.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_R5G6B5);
				if (hr != D3D_OK)
					return 0;
			}
		}
	}

	// Fill in the Presentation Parameters
    memset(&d3dpp, 0, sizeof d3dpp);

	if (windowed)
	{
		d3dpp.Windowed              = TRUE;
	}
	else
	{
		d3dpp.Windowed				= FALSE;
		d3dpp.BackBufferWidth		= SCREEN_X;
		d3dpp.BackBufferHeight		= SCREEN_Y;
		d3dpp.BackBufferCount		= 1;
		d3dpp.PresentationInterval	= D3DPRESENT_INTERVAL_ONE;
		d3dpp.FullScreen_RefreshRateInHz = 60;
	}

	if (zbuffered)
	{
	    d3dpp.EnableAutoDepthStencil = TRUE;
	    d3dpp.AutoDepthStencilFormat = depth_format;
	}
	else
	{
	    d3dpp.EnableAutoDepthStencil = FALSE;
		d3dpp.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
	}

    d3dpp.SwapEffect				= D3DSWAPEFFECT_FLIP;
    d3dpp.BackBufferFormat			= d3ddm.Format;
	d3dpp.hDeviceWindow				= game_window;

    // Create the D3DDevice (make sure we take a T&L device if it's available)
	if (d3dcaps9.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
	{
		hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, game_window,
									  D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED,
									  &d3dpp, &d3d_dev);
	}
	else
	{
		hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, game_window,
									  D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED,
									  &d3dpp, &d3d_dev);
	}
	if (hr != D3D_OK)
		return 0;

	// Get the capabilities of the device
    memset(&caps, 0, sizeof caps);
    hr = IDirect3DDevice9_GetDeviceCaps(d3d_dev, &caps);

	//Set texture address mode to clamp
    hr = IDirect3DDevice9_SetSamplerState(d3d_dev, 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
    hr = IDirect3DDevice9_SetSamplerState(d3d_dev, 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);

    // Set filtering
	// Give us the best filtering available
	hr = IDirect3DDevice9_SetSamplerState(d3d_dev, 0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
	hr = IDirect3DDevice9_SetSamplerState(d3d_dev, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
	if (caps.TextureFilterCaps & D3DPTFILTERCAPS_MINFLINEAR)
		hr = IDirect3DDevice9_SetSamplerState(d3d_dev, 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
	if (caps.TextureFilterCaps & D3DPTFILTERCAPS_MAGFLINEAR)
		hr = IDirect3DDevice9_SetSamplerState(d3d_dev, 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
	if (caps.TextureFilterCaps & D3DPTFILTERCAPS_MINFANISOTROPIC)
		hr = IDirect3DDevice9_SetSamplerState(d3d_dev, 0, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC);
	if (caps.TextureFilterCaps & D3DPTFILTERCAPS_MAGFANISOTROPIC)
		hr = IDirect3DDevice9_SetSamplerState(d3d_dev, 0, D3DSAMP_MAGFILTER, D3DTEXF_ANISOTROPIC);

    // set maximum ambient light
    hr = IDirect3DDevice9_SetRenderState(d3d_dev, D3DRS_AMBIENT, RGB(255,255,255));

    // Turn on backface culling
    hr = IDirect3DDevice9_SetRenderState(d3d_dev, D3DRS_CULLMODE, D3DCULL_CW);

    // Turn off D3D lighting
    hr = IDirect3DDevice9_SetRenderState(d3d_dev, D3DRS_LIGHTING, FALSE);

	if (zbuffered)
	{
	    // Turn on the zbuffer
	    hr = IDirect3DDevice9_SetRenderState(d3d_dev, D3DRS_ZENABLE, D3DZB_TRUE);
	    hr = IDirect3DDevice9_SetRenderState(d3d_dev, D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
		zbuffer_enabled = TRUE;
	}
	else
	{
	    // Turn off the zbuffer
	    hr = IDirect3DDevice9_SetRenderState(d3d_dev, D3DRS_ZENABLE, D3DZB_FALSE);
	    hr = IDirect3DDevice9_SetRenderState(d3d_dev, D3DRS_ZFUNC, D3DCMP_ALWAYS);
		zbuffer_enabled = FALSE;
	}

	// Turn off alpga blending
	hr = IDirect3DDevice9_SetRenderState(d3d_dev, D3DRS_ALPHABLENDENABLE, FALSE);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?