Direct3D的初始化

(1)获取接口IDirect3D9的指针,该接口用于获取系统中物理硬件设备的信息并创建接口IDirect3DDevice9,该接口是一个C++对象,代表了我们用来显示3D图形的物理硬件设备。
使用Direct3DCreate9可获得该指针,它的参数必须是D3D_SDK_VERSION,只有如此才能保证程序使用正确头文件,如果函数调用失败,将返回一个NULL指针

(2)检查设备性能(D3DCAPS9),判断主显卡是否支持硬件顶点运算,为了创建接口IDirect3DDevice9,我们必须明确显卡是否支持该功能

HRESULT IDirect3D9::GetDeviceCaps(
		UINT Adapter,				//指定物理显卡的序号
		D3DDEVTYPE DeviceType,		//指定设备类型 硬件设备D3DDEVTYPE_HAL  软件设备D3DDEVTYPE_REF
		D3DCAPS9 * pCaps			//设备性能结构
	);

(3)初始化D3DPRESENT_PARAMETERS结构示例,我们可以通过这些变量来指定即将创建接口IDirect3DDevice9的特性

(4)利用已初始化的D3DPRESENT_PARAMETERS结构创建一个IDirect3DDevice9对象

d3dUtility.h

#pragma once
#include <d3d9.h>

namespace d3d
{
	//初始化Direct3D
	bool InitD3D(
		HINSTANCE hInstance,
		int width,
		int height,
		bool windowed,
		D3DDEVTYPE deviceType,
		IDirect3DDevice9** device);

	//封装应用程序的消息循环,参数为实现绘制功能的函数指针,在空闲处理期间显示场景
	int EnterMsgLoop(
		bool(*ptr_display)(float timeDelta));

	LRESULT CALLBACK WndProc(
		HWND hwnd,
		UINT msg,
		WPARAM wParam,
		LPARAM lParam);

	template<class T> 
	void Release(T t)
	{
		if (t)
		{
			t->Release();
			t = 0;
		}
	}

	template<class T>
	void Delete(T t)
	{
		if (t)
		{
			delete t;
			t = 0;
		}
	}
}

d3dUtility.cpp

#include "d3dUtility.h"

bool d3d::InitD3D(HINSTANCE hInstance, int width, int height, bool windowed, D3DDEVTYPE deviceType, IDirect3DDevice9 ** device)
{
	//定义窗口样式
	WNDCLASS wc;
	wc.style = CS_HREDRAW | CS_VREDRAW;
	wc.lpfnWndProc = WndProc;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hInstance = hInstance;
	wc.hIcon = LoadIcon(0, IDI_APPLICATION);
	wc.hCursor = LoadCursor(0, IDC_ARROW);
	wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	wc.lpszMenuName = 0;
	wc.lpszClassName = L"Direct3D9App";

	//窗口注册
	if (!RegisterClass(&wc))
	{
		MessageBox(0, L"RegisterClass() - FAILED", 0, 0);
		return false;
	}

	//创建窗口
	HWND hwnd = 0;
	hwnd = CreateWindow(L"Direct3D9App", L"Direct3D9App", WS_OVERLAPPEDWINDOW, 0, 0, width, height, 0, 0, hInstance, 0);
	if (!hwnd)
	{
		MessageBox(0, L"CreateWindow() - FAILED", 0, 0);
		return false;
	}
	//绘制更新窗口
	ShowWindow(hwnd, SW_SHOW);
	UpdateWindow(hwnd);

	//--------以下为初始化IDirect3D------------

	//获取IDirect3D9指针
	IDirect3D9* d3d9;
	d3d9 = Direct3DCreate9(D3D_SDK_VERSION);

	if (!d3d9)
	{
		MessageBox(0, L"Direct3DCreate9() - FAILED", 0, 0);
		return false;
	}

	//校验硬件性能(顶点运算)
	D3DCAPS9 caps;
	d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, deviceType, &caps);

	int vp = 0;
	if (caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
		vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;
	else
		vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;

	//填充D3DPRESENT_PARAMETERS结构
	D3DPRESENT_PARAMETERS d3dpp;
	d3dpp.BackBufferWidth = width;								//后台缓存中表面的宽度,单位为像素
	d3dpp.BackBufferHeight = height;							
	d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;					//后台缓存的像素格式
	d3dpp.BackBufferCount = 1;									//所需使用的后台缓存个数,通常指定为1
	d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;				//后台缓存所使用的多重采样类型
	d3dpp.MultiSampleQuality = 0;								//多重采样的质量水平
	d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;					//交换链中缓存的页面置换方式,D3DSWAPEFFECT_DISCARD时最高
	d3dpp.hDeviceWindow = hwnd;									//所要进行绘制的应用程序窗口
	d3dpp.Windowed = windowed;									//true为窗口模式,false为全屏模式
	d3dpp.EnableAutoDepthStencil = true;						//设为true则Direct3D自动创建并维护深度缓存或模板缓存
	d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;				//深度缓存或模板缓存的像素格式 D3DFMT_D24S8 24位表示深度,8位保留模板缓存使用
	d3dpp.Flags = 0;											//附加特性   D3DPRESENTFLAG_LOCKABLE_BACKBUFFER指定可锁定后台缓存,使用一个可锁定的后台缓存会降低性能   D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL  	
	d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; //刷新频率
	d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; //提交频率 D3DPRESENT_INTERVAL_IMMEDIATE立即提交   D3DPRESENT_INTERVAL_DEFAULT由Direct3D来选择提交频率
	
	//创建IDirectDevice9接口
	d3d9->CreateDevice(D3DADAPTER_DEFAULT, deviceType, hwnd, vp, &d3dpp, device);
	d3d9->Release();
	return true;
}


#if 0
GetMessage的主要功能是从消息队列中“取出”消息,消息被取出以后,就从消息队列中将其删除;而PeekMessage的主要功能是“窥视”消息,
如果有消息,就返回true,否则返回false。也可以使用PeekMessage从消息队列中取出消息,这要用到它的一个参数(UINT wRemoveMsg),
如果设置为PM_REMOVE,消息则被取出并从消息队列中删除;如果设置为PM_NOREMOVE,消息就不会从消息队列中取出
#endif


int d3d::EnterMsgLoop(bool(*ptr_display)(float timeDelta))
{
	MSG msg;
	::ZeroMemory(&msg, sizeof(MSG));

	static float lastTime = (float)timeGetTime();

	while (msg.message != WM_QUIT)
	{
		if (::PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
		{
			::TranslateMessage(&msg);
			::DispatchMessage(&msg);
		}
		else
		{
			float currTime = (float)timeGetTime();
			float timeDelta = (currTime - lastTime)*0.001f;
			ptr_display(timeDelta);
			lastTime = currTime;
		}
	}

	return msg.wParam;
}


LRESULT CALLBACK d3d::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch (msg)
	{
	case WM_DESTROY: //销毁
		PostQuitMessage(0); //终止请求
		break;
	case WM_KEYDOWN: //键按下
		if (wParam == VK_ESCAPE) //Esc键
			DestroyWindow(hwnd);
		break;
	default:
		break;
	}

	//调用缺省的窗口过程来为应用程序没有处理的任何窗口信息提供缺省的处理
	//该函数确保每一个消息得到处理
	return DefWindowProc(hwnd, msg, wParam, lParam);
}

D3DPractice.cpp

#include <windows.h>
#include "d3dUtility.h"
#include <d3dx9math.h>

IDirect3DDevice9* Device = NULL;

bool DisPlay(float timeDelta)
{
	if (Device)
	{
		Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
/*
	STDMETHOD(Clear)(THIS_ DWORD Count, CONST D3DRECT* pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) PURE;
	Count: pRects数组中矩形的数目
	pRects:要执行清除操作的屏幕矩形数组,该参数允许我们只对表面的部分区域进行清除操作
	Flags:指定所要清除的表面
	D3DCLEAR_TARGET 绘制目标表面,通常指后台缓存
	D3DCLEAR_ZBUFFER 深度缓存
	D3DCLEAR_STENCIL 模板缓存
	Color:指定将绘制目标体设置为何种颜色
	Z:深度缓存所需要设定的值
	Stencil:模板缓存所需要设定的值
*/
		Device->Present(0, 0, 0, 0);  //提交后台缓存
	}
	return true;
}

bool SetUp()
{
	return true;
}

void CleanUp()
{
}

int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nShowCmd)
{
	
	if (!d3d::InitD3D(hInstance, 800, 600, true, D3DDEVTYPE_HAL, &Device))
	{
		::MessageBox(0, L"InitD3D() - FAILED", 0, 0);
		return 0;
	}

	if (!SetUp())
	{
		::MessageBox(0, L"SetUp() - FAILED", 0, 0);
		return 0;
	}
	

	d3d::EnterMsgLoop(DisPlay);
	CleanUp();
	Device->Release();
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的贪吃蛇游戏示例,使用Panda3D进行渲染和输出: ```python import random from direct.showbase.ShowBase import ShowBase from direct.interval.MetaInterval import Sequence from direct.interval.LerpInterval import LerpFunc from panda3d.core import Point3 # 游戏界面大小 GRID_SIZE = 20 GRID_WIDTH = 10 GRID_HEIGHT = 10 # 定义贪吃蛇类 class Snake: def __init__(self): self.body = [] self.direction = (1, 0) # 初始化贪吃蛇身体 for i in range(3): self.body.append((GRID_WIDTH // 2 - i, GRID_HEIGHT // 2)) # 获取贪吃蛇头部位置 def get_head(self): return self.body[0] # 获取贪吃蛇尾部位置 def get_tail(self): return self.body[-1] # 移动贪吃蛇 def move(self): head = self.get_head() new_head = (head[0] + self.direction[0], head[1] + self.direction[1]) # 判断是否撞墙 if new_head[0] < 0 or new_head[0] >= GRID_WIDTH or new_head[1] < 0 or new_head[1] >= GRID_HEIGHT: return False # 判断是否撞到自己 if new_head in self.body: return False # 判断是否吃到食物 if new_head == food: self.body.insert(0, new_head) return True self.body.insert(0, new_head) self.body.pop() return True # 改变贪吃蛇方向 def set_direction(self, direction): self.direction = direction # 随机生成食物位置 def generate_food(): x = random.randint(0, GRID_WIDTH - 1) y = random.randint(0, GRID_HEIGHT - 1) return (x, y) # 初始化游戏界面 class SnakeGame(ShowBase): def __init__(self): ShowBase.__init__(self) # 添加方格模型 self.grid = self.loader.loadModel("models/grid") self.grid.reparentTo(self.render) # 初始化贪吃蛇和食物 self.snake = Snake() self.food = generate_food() # 添加贪吃蛇模型 self.snake_model = self.loader.loadModel("models/snake") self.snake_model.reparentTo(self.render) # 添加食物模型 self.food_model = self.loader.loadModel("models/food") self.food_model.reparentTo(self.render) # 设置相机位置 self.camera.setPos(0, -20, 10) self.camera.lookAt(0, 0, 0) # 注册键盘事件 self.accept("arrow_left", self.turn_left) self.accept("arrow_right", self.turn_right) self.accept("arrow_up", self.turn_up) self.accept("arrow_down", self.turn_down) # 开始游戏循环 self.taskMgr.add(self.game_loop, "game_loop") # 游戏循环 def game_loop(self, task): # 移动贪吃蛇 if not self.snake.move(): self.game_over() # 更新贪吃蛇模型位置 for i, part in enumerate(self.snake.body): pos = Point3(part[0] - GRID_WIDTH / 2, part[1] - GRID_HEIGHT / 2, 0) self.snake_model.setPos(i, pos) # 更新食物模型位置 pos = Point3(self.food[0] - GRID_WIDTH / 2, self.food[1] - GRID_HEIGHT / 2, 0) self.food_model.setPos(pos) return task.cont # 游戏结束 def game_over(self): self.ignoreAll() print("Game Over") # 处理键盘事件 def turn_left(self): self.snake.set_direction((-1, 0)) def turn_right(self): self.snake.set_direction((1, 0)) def turn_up(self): self.snake.set_direction((0, 1)) def turn_down(self): self.snake.set_direction((0, -1)) # 启动游戏 game = SnakeGame() game.run() ``` 在运行此代码之前,您需要准备一些模型文件,如 `grid.egg`,`snake.egg` 和 `food.egg`。您可以使用Panda3D自带的egg文件导出工具将这些文件从其他3D模型格式转换为egg格式。 运行此代码后,您将看到一个带有贪吃蛇和食物的方格游戏界面。使用方向键来控制贪吃蛇的移动,并尝试让贪吃蛇吃到食物。游戏结束后,控制台将显示 "Game Over"。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值