DirectX11 初始化(2) 框架搭建

我们定义一个DirectX11的类

头文件的定义:

#pragma once
#ifndef __DIRECT3DCLASS_H_
#define __DIRECT3DCLASS_H_

#pragma comment(lib, "dxgi.lib")  
#pragma comment(lib, "d3d11.lib")  
#pragma comment(lib, "d3dx11.lib")  
#pragma comment(lib, "d3dx10.lib")  
#pragma comment(lib, "dxerr.lib")
#pragma comment(lib, "legacy_stdio_definitions.lib")    


#include<d3d11.h>
#include<D3DX11.h>
#include<DxErr.h>


class DIrect3DClass
{
public:
	DIrect3DClass();
	virtual ~DIrect3DClass();   //在子类中被重写
	bool initialize(HINSTANCE hInstance, HWND hwnd);   //初始化函数
	void shutdown();            //释放在开始时创建的Direct3D对象

	virtual bool LoadContent();    //提供一方式载入具体Demo内容
	virtual void UnLoadContent();  //提供卸载具体Demo内容的方式

	virtual void Update(float dt) = 0;   //提供每帧更新具体Demo的能力
	virtual void Render() = 0;           //提供可重写的具体Demo的渲染函数

protected:
	HINSTANCE hInstance_;
	HWND hwnd_;

	D3D_DRIVER_TYPE driverType_;    //驱动类型
	D3D_FEATURE_LEVEL featureLevel_;   //特征性等级
	 
	ID3D11Device* d3dDevice_;           //设备类
	ID3D11DeviceContext* d3dContext_;   //环境渲染类
	IDXGISwapChain* swapChain_;         //交换链
	ID3D11RenderTargetView* backBufferTarget_;  //渲染目标视图
};

#endif


源文件:

#include "DIrect3DClass.h"


DIrect3DClass::DIrect3DClass()
{
}


DIrect3DClass::~DIrect3DClass()
{
	shutdown();    //每个析构函数有自己独特的关闭内容
}

bool DIrect3DClass::LoadContent() {

	return true;   //调用内容
}

void DIrect3DClass::UnLoadContent() {

	//根据不同的内容进行重写
}

//初始内容
void DIrect3DClass::shutdown() {

	//释放内容:
	UnLoadContent();

	//释放指针对象
	if (backBufferTarget_) backBufferTarget_->Release();
	if (swapChain_)swapChain_->Release();
	if (d3dContext_)d3dContext_->Release();
	if (d3dDevice_)d3dDevice_->Release();

	backBufferTarget_ = 0;
	swapChain_ = 0;
	d3dContext_ = 0;
	d3dDevice_ = 0;

}

bool DIrect3DClass::initialize(HINSTANCE hInstance, HWND hwnd) {

	HRESULT result;   //检测是否生成成功

	hInstance_ = hInstance;
	hwnd_ = hwnd;
	

	//生成驱动和特性等级//
	RECT dimensions;
	GetClientRect(hwnd, &dimensions);

	unsigned int Width = dimensions.right - dimensions.left;
	unsigned int height = dimensions.bottom - dimensions.top;

	D3D_DRIVER_TYPE driverTypes[] = {        //四种驱动类型,选择最合适的驱动类型
		D3D_DRIVER_TYPE_HARDWARE, D3D_DRIVER_TYPE_WARP,
		D3D_DRIVER_TYPE_REFERENCE, D3D_DRIVER_TYPE_SOFTWARE
	};

	unsigned int totalDriverTypes = ARRAYSIZE(driverTypes);   //得出类型数

	D3D_FEATURE_LEVEL featureLeverls[] = {   //三种版本依赖 迭代选择最合适的版本依赖
		D3D_FEATURE_LEVEL_11_0,
		D3D_FEATURE_LEVEL_10_1,
		D3D_FEATURE_LEVEL_10_0
	};

	unsigned int totalFeatureLevels = ARRAYSIZE(featureLeverls);  //得出版本数
	
	//生成交换链//:
	DXGI_SWAP_CHAIN_DESC swapChainDesc;

	ZeroMemory(&swapChainDesc, sizeof(swapChainDesc));
	swapChainDesc.BufferCount = 1;    //缓存页的数量
	swapChainDesc.BufferDesc.Width = Width;   //宽度
	swapChainDesc.BufferDesc.Height = height; //高度
	swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;  //缓存格式
	swapChainDesc.BufferDesc.RefreshRate.Numerator = 60;      //刷新率
	swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;      //使用60/1表示60Hz的刷新率
	swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;      //交换链中的缓存用法,能够用于输出以及渲染
	swapChainDesc.OutputWindow = hwnd;    //窗口句柄
	swapChainDesc.Windowed = true;        //是全屏还是原来的尺寸resize?
	swapChainDesc.SampleDesc.Count = 1;    //取样描述:数量
	swapChainDesc.SampleDesc.Quality = 0;   //取样描述:质量
	

     //测试并选择驱动和特征级别//:
	 //创建渲染环境//
	unsigned int creationFlags = 0;
#ifndef _DEBUG
	creationFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif 
	
	
	for (unsigned int driver = 0; driver < totalDriverTypes; ++driver) {
		result = D3D11CreateDeviceAndSwapChain(0, driverTypes[driver], 0, creationFlags, featureLeverls, totalFeatureLevels, D3D11_SDK_VERSION, &swapChainDesc, &swapChain_,
			&d3dDevice_, &featureLevel_, &d3dContext_);

		if (SUCCEEDED(result)) {
			driverType_ = driverTypes[driver];
			break;
		}
	}

	if (FAILED(result))
	{
		DXTRACE_MSG("Failed to create the Direct3D device!");
		return false;
	}


	//获取后置内存指针//
	ID3D11Texture2D* backBufferTexture;
	result = swapChain_->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&backBufferTexture);

	if (FAILED(result)) {
		DXTRACE_MSG("Failed to get the swap chain back buffer");
		return false;
	}
	
	
	//创建渲染目标视图//
	result = d3dDevice_->CreateRenderTargetView(backBufferTexture, 0, &backBufferTarget_);
	
	//释放贴图
	if (backBufferTexture) {
		backBufferTexture->Release();   //释放内容
	}
	if (FAILED(result)) {
		DXTRACE_MSG("FAILED To Create the render target view!");
		return false;
	}


	//创建视口//
	D3D11_VIEWPORT viewport;
	
	viewport.Width = static_cast<float>(Width);
	viewport.Height = static_cast<float>(height);
	viewport.MinDepth = 0.0f;
	viewport.MaxDepth = 1.0f;
	viewport.TopLeftX = 0.0f;
	viewport.TopLeftY = 0.0f;
	
	d3dContext_->RSSetViewports(1, &viewport);


	//返回//
	return LoadContent();
}

然后创建一个demo类 继承DirectX11类

头文件:

#pragma once

#ifndef __BLAMLDEMO_H_
#define __BLAMLDEMO_H_
#include "DIrect3DClass.h"

class BlamlDemo :
	public DIrect3DClass
{
public:
	BlamlDemo();
	virtual ~BlamlDemo();


	//重写函数
	bool LoadContent();
	void UnLoadContent();

	void Update(float dt);
	void Render();
	
};

#endif





源文件:

#include "BlamlDemo.h"



BlamlDemo::BlamlDemo()
{
}


BlamlDemo::~BlamlDemo()
{
}

bool BlamlDemo::LoadContent()
{

	return true;
}

void BlamlDemo::UnLoadContent(){


}

void BlamlDemo::Update(float dt) {


}

void BlamlDemo::Render() {

	if (d3dContext_ == 0)
		return;

	float clearColor[4] = { 0.0f, 0.0f, 0.25f, 1.0f };
	d3dContext_->ClearRenderTargetView(backBufferTarget_, clearColor);

	swapChain_->Present(0, 0);

}



窗口文件(winmain入口定义):

#include<iostream>
#include<memory>
#include "BlamlDemo.h"
using namespace std;

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);    //用来处理消息队列

																					//wWinMain 和 WinMain的区别 可以解决Unicode和ANSI之间的切换问题
int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nShowCmd)
{

	//四个参数:
	//hInstance:当前应用的句柄
	//hprevious instance:上一个应用的句柄 通常设为NULL
	//LPSTR cmdLine:用户和窗体之间的交互

	UNREFERENCED_PARAMETER(hPrevInstance);   //告诉编译器已经使用了这个变量
	UNREFERENCED_PARAMETER(lpCmdLine);       //告诉编译器已经使用了该变量

	WNDCLASSEX wndClass = { 0 };
	wndClass.cbSize = sizeof(WNDCLASSEX);     //窗体类的大小,可以用sizeof来获取
	wndClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;   //窗体的风格
	wndClass.lpfnWndProc = WndProc;    //窗口函数处理指针
	wndClass.cbClsExtra = 0;     //指定紧跟在窗口类结构后的附加字数
	wndClass.cbWndExtra = 0;     //指定紧跟在窗口类结构后的附加字节数
	wndClass.hInstance = hInstance;   //本模块的实例句柄
	wndClass.hIcon = LoadIcon(NULL, IDI_WINLOGO);    //图标的句柄
	wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);      //光标的句柄
	wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);    //背景画刷的句柄
	wndClass.lpszMenuName = NULL;        //指向菜单的指针
	wndClass.lpszClassName = TEXT("DX11BookWindowClass");    //指向类名称的指针
	wndClass.hIconSm = LoadIcon(NULL, IDI_WINLOGO);    //和窗口关联的小图标

													   //提交注册表单
	if (!RegisterClassEx(&wndClass)) {
		MessageBox(NULL, TEXT("Register Window failed!"), TEXT("Warning"), MB_OK);
		return -1;
	}

	//设置窗体的大小
	RECT rc = { 0, 0, 1024, 768 };  //窗口规模   左上角坐标 宽度 高度
	AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE);

	//创建一个标准的窗体
	HWND hwnd = CreateWindowEx(WS_EX_APPWINDOW, "DX11BookWindowClass", "BLACK WIN32 Window", WS_OVERLAPPED, CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left,
		rc.bottom - rc.top, NULL, NULL, hInstance, NULL);
	//参数说明:
	//(1)窗口类名:这里有个坑 这里填写的类名必须与上面注册的类名一致
	//(2)窗体标题
	//(3)窗体风格
	//(4)坐标x
	//(5)坐标y
	//(6)宽度
	//(7)高度
	//(8)父类窗体的句柄
	//(9)lpParam--

	if (!hwnd) {
		MessageBox(NULL, TEXT("Register Window failed!"), TEXT("Warning"), MB_OK);
		return -1;
	}

	ShowWindow(hwnd, nShowCmd);

	//初始化对象//
	auto_ptr<DIrect3DClass> Demo(new BlamlDemo());
	

	bool result = Demo->initialize(hInstance, hwnd);   //传入当前窗口的句柄
	if (result == false) {
		MessageBox(hwnd, TEXT("DX3d Initialize error!"), TEXT("eror"), MB_OK);
		return -1;
	}


	//窗体创建完毕后 开始消息循环
	MSG msg = { 0 };
	while (msg.message != WM_QUIT)    //如果不退出的话 则一直循环
	{
		if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
			TranslateMessage(&msg);     //获取新的消息
			DispatchMessage(&msg);      //派遣消息
		}
		else {

			//更新
			Demo->Update(0.0f);
			//渲染
			Demo->Render();
		}
	}

	Demo->shutdown();    //关闭实例
	return static_cast<int>(msg.wParam); //把expression转换为type-id
}


//消息队列
//每当消息循环获取到新消息后 开始处理消息
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
	PAINTSTRUCT ps;
	HDC hdc;

	switch (message)    //选择消息类型进行处理
	{
	case WM_PAINT: {    //窗体绘制
		hdc = BeginPaint(hWnd, &ps);
		EndPaint(hWnd, &ps);
	}break;

	case WM_CLOSE: {     //窗体关闭
		PostQuitMessage(0);
		DestroyWindow(hWnd);
	}break;

	case WM_DESTROY: {
		PostQuitMessage(0);
		break;
	}

	default: {
		return DefWindowProc(hWnd, message, wParam, lParam);  //确保每个消息都得到处理
	}
	}
}







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值