博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Direct3D 11的初始化
阅读量:2503 次
发布时间:2019-05-11

本文共 12621 字,大约阅读时间需要 42 分钟。

因为比较看不惯商店应用使用的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 Stagevoid SetInputLayout();//绑定输入格式到input-assembler stage.HRESULT CompileShaderFromFile( WCHAR* szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3DBlob** ppBlobOut);//从文件读取shader或effectvoid 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
(width); viewport.Height = static_cast
(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 ); }
最后运行的效果如下:

你可能感兴趣的文章
Android批量图片加载经典系列——使用二级缓存、异步网络负载形象
查看>>
Cookie/Session机制具体解释
查看>>
ATMEGA16 IOport相关汇总
查看>>
有意思的cmd命令
查看>>
js正則表達式语法
查看>>
Xcode 5.1安装插件:规范凝视生成器VVDocumenter
查看>>
Python学习笔记(一):基本数据类型
查看>>
QT-自定义信号和槽
查看>>
破天荒头一篇
查看>>
spring validator 注解
查看>>
C#根据淘宝接口网址获取客户端访问IP和网络运营商
查看>>
PAT乙级1008. 数组元素循环右移问题 (20)
查看>>
VBA中两个整数相除返回向下取整的整数结果?
查看>>
JVM-垃圾回收
查看>>
python中的多继承
查看>>
ubuntu-14.04.1-desktop上安装配置JDK1.8的环境变量
查看>>
VS2013 添加已有文件夹
查看>>
摄影扫盲
查看>>
POJ 2388 - Who's in the Middle
查看>>
python 计时程序运行时间
查看>>