Direct3D 11的初始化

因为比较看不惯商店应用使用的C++/CX,所以用win32的项目来学习,起名为D3DFirst。

项目模板会生成一堆默认的代码,用于显示一个最简单的Windows窗口,这个窗口会作为D3D画面的输出窗口。

生成的代码虽然很多,但我只关心图形绘制相关的代码,所以直接定位到

RESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

回调函数的

case WM_PAINT:
    break;

所有的绘制都是在这里进行的,我的D3D代码也是写在这里。

为了不和这个默认生成的代码文件搅和在一起,自己新建一个类专门用于操作D3D,叫做D3DRender。将绘制的代码写在WM_PAINT后面。

可以声明一个全局的变量

D3DRender pD3dRender;

然后在InitInstance函数里初始化,主要是初始化D3D需要的资源,并且将窗口做为参数传入。

pD3dRender.Init(hWnd);

然后在WM_PAINT后面绘制:

	case WM_PAINT:
		//hdc = BeginPaint(hWnd, &ps);
		 TODO: Add any drawing code here...
		//EndPaint(hWnd, &ps);
		pD3dRender.OnRender();
		break;

当然还有D3DRender类的头文件需要include。


下面介绍D3DRender类的声明:

头文件和using namespace:

#pragma once

#include "D3D11_1.h"
#include "d3dx11.h"
#include "directxmath.h"
#include "DirectXPackedVector.h"
#include "d3dCompiler.h"
using namespace DirectX;
using namespace DirectX::PackedVector;

前两个是D3D的一些核心接口。

DirectXMath.h和DirectXPackedVector.h是向量和矩阵的相关接口。

d3dCompiler.h是用于读取shader的接口。


下面是类的主要内容,基本上就是渲染流水线所需要的所有东西。

struct Vertex1  
{  
	XMFLOAT3 pos;
        XMFLOAT4 color;
};  
struct Vertex2 
{  
XMFLOAT3 pos;
XMFLOAT3 normal;
XMFLOAT2 Tex0;
XMFLOAT2 Tex1;
};  
struct ConstantBuffer
{
XMMATRIX mWorld;
XMMATRIX mView;
XMMATRIX mProjection;
};


class D3DRender
{
public:
D3DRender(void);
~D3DRender(void);
void CreateDeviceAndSwapChain(HWND);//创建设备接口和双缓冲交换接口
void Check4XMsaa();//检测多重采样的质量级别
void CreateRenderTargetView();//创建渲染目标视图(双缓冲的其中一个Buffer)
void CreateDepthView();//创建深度视图(检测遮挡)
void BindView();//绑定视图(将渲染目标视图和深度视图绑定到output stage)
void SetViewport();//绑定一组视口到Rasterizer Stage
void SetInputLayout();//绑定输入格式到input-assembler stage.
HRESULT CompileShaderFromFile( WCHAR* szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3DBlob** ppBlobOut);//从文件读取shader或effect
void CreateVertexBuffer();//绑定一组顶点Buffer到input-assembler stage.
void CreateIndexBuffer();//绑定一组索引Buffer到input-assembler stage.
void CreateVertexShader();//用文件中读取的编译过的shader创建一个顶点shader对象
void CreateConstantBuffer();//创建一个Buffer(类型可以是顶点,索引,shader常量buffer)
void SetPrimitive();//设置图元类型,数据的输入顺序,绑定到input-assembler stage.
void CreatePixelShader();//用文件中读取的编译过的shader创建一个索引shader对象
void InitWorldMatrix();
void InitViewMatrix();
void InitProjectionMatrix();


void Init(HWND);//初始化
void OnRender();//绘制
void OnResize();


private:
ID3D11Device* pDevice;
ID3D11DeviceContext* pDeviceContext;
IDXGISwapChain* pSwapChain;


ID3D11Texture2D* pDepthStencilBuffer;
ID3D11DepthStencilView* pDepthStencilView;
ID3D11Texture2D* pBackBuffer;
ID3D11RenderTargetView* pRenderTargetView;


ID3DBlob* pVSBlob;
ID3DBlob* pPSBlob;
ID3D11InputLayout* pInputLayout;
ID3D11Buffer* pVertexBuffer;
ID3D11Buffer* pIndexBuffer;
ID3D11Buffer* pConstantBuffer;
ID3D11VertexShader* pVertexShader;
ID3D11PixelShader* pPixelShader;


UINT m4xMsaaQuality;
HRESULT hr;
RECT rect;
UINT width;
UINT height;


XMMATRIX  worldMatrix;
XMMATRIX  viewMatrix;
XMMATRIX  projectionMatrix;
};

下面是这些函数的实现:

#include "stdafx.h"
#include "D3DRender.h"


D3DRender::D3DRender(void)
{
	pDevice = NULL;
	pDeviceContext = NULL;
	pSwapChain = NULL;
	pBackBuffer= NULL;
	pRenderTargetView= NULL; 
}


D3DRender::~D3DRender(void)
{
	pDevice->Release();
	pDeviceContext->Release();
	pSwapChain->Release();
	pBackBuffer->Release();
	pRenderTargetView->Release();
}

void D3DRender::CreateDeviceAndSwapChain(HWND hwnd)
{
	D3D_DRIVER_TYPE driverTypes[] = 
	{
		D3D_DRIVER_TYPE_HARDWARE,
		D3D_DRIVER_TYPE_WARP,
		D3D_DRIVER_TYPE_SOFTWARE
	};


	D3D_FEATURE_LEVEL featureLevels[] =  
	{  
		D3D_FEATURE_LEVEL_11_0,
		D3D_FEATURE_LEVEL_10_1,
		D3D_FEATURE_LEVEL_10_0,
		D3D_FEATURE_LEVEL_9_3,
		D3D_FEATURE_LEVEL_9_2,
		D3D_FEATURE_LEVEL_9_1,
	};  

	UINT featureLevelsCount = ARRAYSIZE(featureLevels);

	GetClientRect(hwnd, &rect);
	width = rect.right - rect.left;
	height = rect.bottom - rect.top;

	DXGI_SWAP_CHAIN_DESC swapChainDesc = {0,};
	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;  
	swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;  
	swapChainDesc.OutputWindow = hwnd;  
	swapChainDesc.Windowed = TRUE;  
	swapChainDesc.SampleDesc.Count = 1;  
	swapChainDesc.SampleDesc.Quality = 0;

	D3D_FEATURE_LEVEL featureLevel;

	hr = D3D11CreateDeviceAndSwapChain( 
		NULL, 
		driverTypes[0], 
		NULL, 
		D3D11_CREATE_DEVICE_DEBUG, 
		featureLevels, 
		featureLevelsCount,
		D3D11_SDK_VERSION, 
		&swapChainDesc, 
		&pSwapChain, 
		&pDevice,
		&featureLevel,
		&pDeviceContext);

}

void D3DRender::Check4XMsaa()
{
	hr = pDevice->CheckMultisampleQualityLevels(DXGI_FORMAT_B8G8R8A8_UNORM, 4, &m4xMsaaQuality);
}

void D3DRender::CreateRenderTargetView()
{
	// Get a pointer to the back buffer of target view
	hr = pSwapChain->GetBuffer( 0, __uuidof(ID3D11Texture2D ),  ( LPVOID* )&pBackBuffer ); 

	// Create a render-target view
	hr = pDevice->CreateRenderTargetView(pBackBuffer, 0, &pRenderTargetView ); 
}

void D3DRender::CreateDepthView()
{	
	D3D11_TEXTURE2D_DESC depthStencilDesc;
	depthStencilDesc.Width = rect.right-rect.left;
	depthStencilDesc.Height = rect.bottom = rect.top;
	depthStencilDesc.MipLevels = 1;
	depthStencilDesc.ArraySize = 1;
	depthStencilDesc.Format =  DXGI_FORMAT_D24_UNORM_S8_UINT;
	depthStencilDesc.SampleDesc.Count = 1;
	depthStencilDesc.SampleDesc.Quality = m4xMsaaQuality - 1;
	depthStencilDesc.Usage = D3D11_USAGE_DEFAULT;
	depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
	depthStencilDesc.CPUAccessFlags = 0;
	depthStencilDesc.MiscFlags = 0;

	hr = pDevice->CreateTexture2D( &depthStencilDesc, 0, &pDepthStencilBuffer);
	hr = pDevice->CreateDepthStencilView( pDepthStencilBuffer, 0, &pDepthStencilView);
}

void D3DRender::BindView()
{
	// Bind the view
	pDeviceContext->OMSetRenderTargets( 1, &pRenderTargetView, pDepthStencilView);
}

void D3DRender::SetViewport()
{
	// Setup the viewport
	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;  
	pDeviceContext->RSSetViewports( 1, &viewport );
}



HRESULT D3DRender::CompileShaderFromFile( WCHAR* szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3DBlob** ppBlobOut )
{
	HRESULT hr = S_OK;

	DWORD dwShaderFlags = D3DCOMPILE_ENABLE_STRICTNESS;
#if defined( DEBUG ) || defined( _DEBUG )
	// Set the D3DCOMPILE_DEBUG flag to embed debug information in the shaders.
	// Setting this flag improves the shader debugging experience, but still allows 
	// the shaders to be optimized and to run exactly the way they will run in 
	// the release configuration of this program.
	dwShaderFlags |= D3DCOMPILE_DEBUG;
#endif

	ID3DBlob* pErrorBlob;
	hr = D3DX11CompileFromFile( szFileName, NULL, NULL, szEntryPoint, szShaderModel, 
		dwShaderFlags, 0, NULL, ppBlobOut, &pErrorBlob, NULL );
	if( FAILED(hr) )
	{
		if( pErrorBlob != NULL )
			OutputDebugStringA( (char*)pErrorBlob->GetBufferPointer() );
		if( pErrorBlob ) pErrorBlob->Release();
		return hr;
	}
	if( pErrorBlob ) pErrorBlob->Release();

	return S_OK;
}

void D3DRender::CreateVertexShader()
{
	// Compile the vertex shader
	hr = CompileShaderFromFile( L"vs1.hlsl", "main", "vs_4_0", &pVSBlob );

	//create vertex shader
	hr = pDevice->CreateVertexShader( pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), NULL, &pVertexShader );
	//pVSBlob->Release();
}

void D3DRender::SetInputLayout()
{
	// Define the input layout
	D3D11_INPUT_ELEMENT_DESC layout[] =
	{
		{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },  
	};
	UINT numElements = ARRAYSIZE(layout);

	hr= pDevice->CreateInputLayout(layout, numElements, pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), &pInputLayout);

	pDeviceContext->IASetInputLayout(pInputLayout);
}

void D3DRender::CreatePixelShader()
{
	pPSBlob = NULL;
	// Compile the pixel shader
	hr = CompileShaderFromFile( L"ps1.hlsl", "main", "ps_4_0", &pPSBlob );

	// Create the pixel shader
	hr = pDevice->CreatePixelShader( pPSBlob->GetBufferPointer(), pPSBlob->GetBufferSize(), NULL, &pPixelShader );
	pPSBlob->Release();
}

void D3DRender::CreateVertexBuffer()
{
	// Create vertex buffer
	Vertex vertices[] =
	{
		XMFLOAT3( 0.0f, 0.5f, 0.5f ),
		XMFLOAT3( 0.5f, -0.5f, 0.5f ),
		XMFLOAT3( -0.5f, -0.5f, 0.5f ),
	};

	Vertex1 vertices1[] =
	{
		{ XMFLOAT3( -1.0f, 1.0f, -1.0f ), XMFLOAT4( 0.0f, 0.0f, 1.0f, 1.0f ) },
		{ XMFLOAT3( 1.0f, 1.0f, -1.0f ), XMFLOAT4( 0.0f, 1.0f, 0.0f, 1.0f ) },
		{ XMFLOAT3( 1.0f, 1.0f, 1.0f ), XMFLOAT4( 0.0f, 1.0f, 1.0f, 1.0f ) },
		{ XMFLOAT3( -1.0f, 1.0f, 1.0f ), XMFLOAT4( 1.0f, 0.0f, 0.0f, 1.0f ) },
		{ XMFLOAT3( -1.0f, -1.0f, -1.0f ), XMFLOAT4( 1.0f, 0.0f, 1.0f, 1.0f ) },
		{ XMFLOAT3( 1.0f, -1.0f, -1.0f ), XMFLOAT4( 1.0f, 1.0f, 0.0f, 1.0f ) },
		{ XMFLOAT3( 1.0f, -1.0f, 1.0f ), XMFLOAT4( 1.0f, 1.0f, 1.0f, 1.0f ) },
		{ XMFLOAT3( -1.0f, -1.0f, 1.0f ), XMFLOAT4( 0.0f, 0.0f, 0.0f, 1.0f ) },
	};

	D3D11_BUFFER_DESC bd;
	ZeroMemory( &bd, sizeof(bd) );
	bd.Usage = D3D11_USAGE_DEFAULT;
	bd.ByteWidth = sizeof( Vertex ) * 3;
	bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
	bd.CPUAccessFlags = 0;
	bd.MiscFlags = 0;

	D3D11_SUBRESOURCE_DATA InitData; 
	ZeroMemory( &InitData, sizeof(InitData) );
	InitData.pSysMem = vertices;
	hr = pDevice->CreateBuffer( &bd, &InitData, &pVertexBuffer );

	// Set vertex buffer
	UINT stride = sizeof( Vertex );
	UINT offset = 0;
	pDeviceContext->IASetVertexBuffers( 0, 1, &pVertexBuffer, &stride, &offset );

}

void D3DRender::CreateIndexBuffer()
{
	// Create index buffer
	WORD indices[] =
	{
		3,1,0,
		2,1,3,

		0,5,4,
		1,5,0,

		3,4,7,
		0,4,3,

		1,6,5,
		2,6,1,

		2,7,6,
		3,7,2,

		6,4,5,
		7,4,6,
	};
	D3D11_BUFFER_DESC bd;
	ZeroMemory( &bd, sizeof(bd) );
	bd.Usage = D3D11_USAGE_DEFAULT;
	bd.ByteWidth = sizeof( WORD ) * 36;        // 36 vertices needed for 12 triangles in a triangle list
	bd.BindFlags = D3D11_BIND_INDEX_BUFFER;
	bd.CPUAccessFlags = 0;

	D3D11_SUBRESOURCE_DATA InitData; 
	ZeroMemory( &InitData, sizeof(InitData) );
	InitData.pSysMem = indices;
	hr = pDevice->CreateBuffer( &bd, &InitData, &pIndexBuffer );

	// Set index buffer
	pDeviceContext->IASetIndexBuffer( pIndexBuffer, DXGI_FORMAT_R16_UINT, 0 );
}

void D3DRender::SetPrimitive()
{
	// Set primitive topology
	pDeviceContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST );
}
void D3DRender::CreateConstantBuffer()
{
	// Create the constant buffer
	D3D11_BUFFER_DESC bd;
	ZeroMemory( &bd, sizeof(bd) );
	bd.Usage = D3D11_USAGE_DEFAULT;
	bd.ByteWidth = sizeof(ConstantBuffer);
	bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
	bd.CPUAccessFlags = 0;
	hr = pDevice->CreateBuffer( &bd, NULL, &pConstantBuffer );
}

void D3DRender::InitWorldMatrix()
{
	worldMatrix = XMMatrixIdentity();
}
void D3DRender::InitViewMatrix()
{
	XMVECTOR Eye = XMVectorSet( 0.0f, 1.0f, -5.0f, 0.0f );
	XMVECTOR At = XMVectorSet( 0.0f, 1.0f, 0.0f, 0.0f );
	XMVECTOR Up = XMVectorSet( 0.0f, 1.0f, 0.0f, 0.0f );
	viewMatrix = XMMatrixLookAtLH( Eye, At, Up );
}
void D3DRender::InitProjectionMatrix()
{
	projectionMatrix = XMMatrixPerspectiveFovLH( XM_PIDIV2, width / (FLOAT)height, 0.01f, 100.0f );
}
void D3DRender::Init(HWND hwnd)
{
	CreateDeviceAndSwapChain(hwnd);
	Check4XMsaa();
	CreateRenderTargetView();
	//CreateDepthView();
	BindView();
	SetViewport();
	CreateVertexShader();
	SetInputLayout();
	CreatePixelShader();
	CreateVertexBuffer();
	CreateIndexBuffer();
	SetPrimitive();
	CreateConstantBuffer();
	InitWorldMatrix();
	InitViewMatrix();
	InitProjectionMatrix();

}

void D3DRender::OnRender()
{
	// Update our time
	static float t = 0.0f;

	static DWORD dwTimeStart = 0;
	DWORD dwTimeCur = GetTickCount();
	if( dwTimeStart == 0 )
		dwTimeStart = dwTimeCur;
	t = ( dwTimeCur - dwTimeStart ) / 1000.0f;

	//
	// Animate the cube
	//
	worldMatrix = XMMatrixRotationY( t );

	float clearColor[4] = { 0.0f, 0.0f, 0.25f, 1.0f };  
	pDeviceContext->ClearRenderTargetView( pRenderTargetView, clearColor );
	//pDeviceContext->ClearDepthStencilView( pDepthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0 );

	//
    // Update variables
    //
    ConstantBuffer cb;
	cb.mWorld = XMMatrixTranspose( worldMatrix );
	cb.mView = XMMatrixTranspose( viewMatrix );
	cb.mProjection = XMMatrixTranspose( projectionMatrix );
	pDeviceContext ->UpdateSubresource( pConstantBuffer, 0, NULL, &cb, 0, 0 );

    //
    // Renders a triangle
    //
	//pDeviceContext->VSSetShader(pVertexShader, NULL, 0 );
	//pDeviceContext->VSSetConstantBuffers( 0, 1, &pConstantBuffer );
	//pDeviceContext->PSSetShader( pPixelShader, NULL, 0 );
	//pDeviceContext->DrawIndexed( 36, 0, 0 );        // 36 vertices needed for 12 triangles in a triangle list

	// Render a triangle
	pDeviceContext->VSSetShader( pVertexShader, NULL, 0 );
	pDeviceContext->PSSetShader( pPixelShader, NULL, 0 );
    pDeviceContext->Draw( 3, 0 );


	pSwapChain->Present( 0, 0 );  


}

最后运行的效果如下:


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值