利用DirectX 11绘制的大致流程(天空盒示例)

本文介绍了使用DirectX 11实现天空盒的详细过程,从基础知识到Direct3D初始化,再到创建几何体数据、设置渲染状态。文章通过实例讲解了如何一步步构建渲染流程,包括顶点缓冲区、索引缓冲区、纹理数据的创建,以及深度模板状态、着色器、常量缓冲区的设置。文中还探讨了顶点着色器和像素着色器如何与C++代码配合工作,展示了如何随着摄像机移动实现天空盒的动态效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文的主要内容

刚开始学习DirectX 11时,看了诸多的资料包括源码后,仍是一头雾水,花费了大量的时间不断地理解代码到底是如何作用于我想要的结果的。本文旨在记录和阐述各个代码在整个程序中扮演的角色。并以天空盒的实现作为了一个小小的例子。本人也是初学这部分内容,若有说的错误之处,还望指正。
源码链接


一、准备知识

想要能上手Direct3D,必然不能是零基础的,在开始学习之前,主要掌握或者了解以下知识:

  • 渲染流水线的大致步骤。
  • 空间几何,线性代数。

掌握上述知识后,就可以开始看别人的代码跟着学了。本文以天空盒的实现为例,大致勾画出一个完整的Direct3D程序应有的步骤。
至于天空盒,是利用立方体映射技术将一个贴着天空纹理的立方体映射到一个球面上,然后通过将天空盒的圆心位置和摄像机坐标同时移动形成天空效果。

效果图如下所示:
在这里插入图片描述


二、项目创建和Direct3D初始化

首先应当创建一个桌面应用或者空项目但子系统指定为窗口(而不是控制台应用),之后只需要少量的Win32代码就可以创建出一个窗口,在处理消息的循环中,我们的程序会不断更新。更新的具体方法可以在MsgProc函数中进行定义。

在这个部分,需要关注的变量和函数有如下:

  • MsgProc函数和MSG messages变量,毋庸置疑,这部分决定了我们的操作带来什么样的效果。至于其中的更多细节,属于Win32编程中的内容,可参考《 windows 程序设计 第五版》一书。
  • HWND MainWnd变量指的是该窗口的句柄,只有拥有该变量的值,我们才能够捕获窗口中的事件以及将场景几何体渲染到该窗口。
LRESULT CALLBACK MsgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);

int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE prevInstance,
	_In_ LPSTR cmdLine, _In_ int showCmd)
{
   
	// 这些参数不使用
	UNREFERENCED_PARAMETER(prevInstance);
	UNREFERENCED_PARAMETER(cmdLine);
	UNREFERENCED_PARAMETER(showCmd);

	WNDCLASS wc;
	wc.style = CS_HREDRAW | CS_VREDRAW;
	wc.lpfnWndProc = MsgProc;
	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(NULL_BRUSH);
	wc.lpszMenuName = 0;
	wc.lpszClassName = L"D3DWndClassName";
	int width = 800, height = 600;

	if (!RegisterClass(&wc))
	{
   
		MessageBox(0, L"RegisterClass Failed.", 0, 0);
		return false;
	}

	RECT R = {
    0, 0, width, height };
	AdjustWindowRect(&R, WS_OVERLAPPEDWINDOW, false);

	HWND MainWnd = CreateWindow(L"D3DWndClassName", L"SkyBox",
		WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, width, height, 0, 0, hInstance, 0);
	if (!MainWnd)
	{
   
		MessageBox(0, L"CreateWindow Failed.", 0, 0);
		return false;
	}

	ShowWindow(MainWnd, SW_SHOW);
	UpdateWindow(MainWnd);
	MSG messages = {
    0 };
	
	/* 在这部分就可以创建并初始化我们的Direct3D程序了*/
	
	//这儿会不断接受并处理消息
	while (messages.message != WM_QUIT)
	{
   
		if (PeekMessage(&messages, 0, 0, 0, PM_REMOVE))
		{
    
			TranslateMessage(&messages);
			DispatchMessage(&messages);
		}
		// 在这里处理消息并更新我们的应用程序
	}

	return messages.wParam;
}

当窗口创建完毕,根据窗口的句柄即可以初始化Direct3D所需的资源,这部分的代码相对变动较小,可以先抄了跑起来再说 之后再细细研究。

初始化Direct3D(D3D)所需的步骤大致如下:

  1. 定义想检查的设备类型和特征级别,这部分也就是检查一下可用的设备(硬件设备,WARP设备,软件驱动设备之类),以及所支持的DirectX类型(D3D11.0,D3D10.1,D3D10.0等)。

    // 驱动类型数组
    D3D_DRIVER_TYPE driverTypes[] =
    {
         
    	D3D_DRIVER_TYPE_HARDWARE,
    	D3D_DRIVER_TYPE_WARP,
    	D3D_DRIVER_TYPE_REFERENCE,
    	D3D_DRIVER_TYPE_SOFTWARE,
    };
    // 特性等级数组
    D3D_FEATURE_LEVEL featureLevels[] =
    {
         
    	D3D_FEATURE_LEVEL_11_1,
    	D3D_FEATURE_LEVEL_11_0,
    	D3D_FEATURE_LEVEL_10_1,
    	D3D_FEATURE_LEVEL_10_0,
    };
    
  2. 创建D3D设备,上下文和交换链,D3D设备(ID3D11Device)和上下文(ID3D11DeviceContext)是用于和硬件交互的接口,也是后续用到的最多的东西。交换链主要是用双缓冲技术保证画面稳定所用。D3D设备和D3D上下文的主要的功能分别为,D3D设备一般用于分配资源(例如创建缓冲区等),而D3D上下文用于将资源绑定到图形管线并产生渲染命令等。下段代码是对这三个创建的示意程序。

    D3D_FEATURE_LEVEL featureLevel;
    ID3D11Device * pd3dDevice;						// D3D设备
    ID3D11DeviceContext * pd3dImmediateContext;		// D3D上下文
    IDXGISwapChain * pSwapChain;					// D3D交换链
    // 在hr中可以得知是否创建成功,这个返回值在之后也会反复出现
    HRESULT hr = D3D11CreateDevice(0, D3D_DRIVER_TYPE_HARDWARE, 0, createDeviceFlags, 0, 0, 
    		D3D11_SDK_VERSION, &d3dDevice, &featureLevel, &d3dImmediateContext);
    // 先对交换链描述结构体进行填充,再调用函数来创建交换链
    DXGI_SWAP_CHAIN_DESC swapChainDesc;							// 交换链描述
    // 填充swapChainDesc
    CreateSwapChain(pd3dDevice, &swapChainDesc, &pSwapChain) 	// 创建交换链
    
  3. 创建渲染目标视图,渲染目标视图主要为了在交换链的辅助缓存(在后面绘画的缓冲区)中联合渲染。

    ID3D11RenderTargetView * pBackBufferTarget;		// 渲染目标视图
    ID3D11Texture2D * pBackBufferTexture;			// 贴图
    HRESULT result;
    // 获取辅助缓存的指针
    result = pSwapChain->GetBuffer(0
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值