D3D11.0绘制简单图元

本文介绍了一个使用Direct3D 11 (D3D11) 创建基本图形应用程序的例子,包括初始化窗口和设备、编译着色器、创建顶点缓冲区等关键步骤。

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

1. main.cpp文件

#include <windows.h>
#include <d3d11.h>
#include <DirectXColors.h>
#include <d3dcompiler.h>

using namespace DirectX;

HINSTANCE g_hInstance = nullptr;
HWND g_hWnd = nullptr;
LPCWSTR g_name = L"D3D11Demo";
D3D_DRIVER_TYPE g_driverType = D3D_DRIVER_TYPE_NULL;                	//驱动类型
D3D_FEATURE_LEVEL g_featureLevel = D3D_FEATURE_LEVEL_11_0;            	//特征等级    
ID3D11Device *g_pd3dDevice = nullptr;                              	//设备
ID3D11DeviceContext *g_pImmediateContext = nullptr;                    	//设备上下文
IDXGISwapChain *g_pSwapChain = nullptr;                               	//交换链
ID3D11RenderTargetView *g_pRenderTargetView = nullptr;                  //要创建的视图
ID3D11VertexShader *g_pVertexShader = nullptr;				//顶点着色器
ID3D11PixelShader *g_pPixelShader = nullptr;				//像素着色器
ID3D11InputLayout *g_pVertexLayout = nullptr;				//输入布局(顶点布局)
ID3D11Buffer *g_pVertexBuffer = nullptr;				//D3D11缓冲区

HRESULT InitWindow(HINSTANCE hInstance, int nCmdShow);
HRESULT InitDevice();
void CleanupDevice();
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void Render();

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd)
{
    if (FAILED(InitWindow(hInstance, nShowCmd)))
        return 0;
    if (FAILED(InitDevice()))
    {
        CleanupDevice();
        return 0;
    }
    MSG msg;
    ZeroMemory(&msg, sizeof(MSG));
	while (msg.message != WM_QUIT)
    {
        if (PeekMessage(&msg, nullptr, 0, 0,PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        else//渲染
        {
			Render();
        }
    }
    CleanupDevice();
    return (int)msg.wParam;
}

HRESULT InitWindow(HINSTANCE hInstance, int nCmdShow)
{
    WNDCLASSEX wcex;
    wcex.cbClsExtra = 0;
    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.cbWndExtra = 0;
    wcex.hbrBackground = (HBRUSH)COLOR_WINDOWFRAME;
    wcex.hCursor = LoadCursor(nullptr,IDC_ARROW);
    wcex.hIcon = LoadIcon(nullptr, IDI_WINLOGO);
    wcex.hIconSm = wcex.hIcon;
    wcex.hInstance = hInstance;
    wcex.lpfnWndProc = WndProc;
    wcex.lpszClassName = g_name;
    wcex.lpszMenuName = nullptr;
    wcex.style = CS_HREDRAW | CS_VREDRAW;
    if (!RegisterClassEx(&wcex))
        return E_FAIL;

    g_hInstance = hInstance;
    RECT rc = {0, 0, 800, 800};
    AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE);
    g_hWnd = CreateWindowEx(WS_EX_APPWINDOW, g_name, g_name, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
        rc.right - rc.left, rc.bottom - rc.top, nullptr, nullptr, g_hInstance, nullptr);
    if (!g_hWnd)
        return E_FAIL;

    ShowWindow(g_hWnd, nCmdShow);

    return S_OK;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wPararm, LPARAM lParam)
{
    switch (message)
    {
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wPararm, lParam);
    }
    return 0;
}

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

    DWORD dwShaderFlags = D3DCOMPILE_ENABLE_STRICTNESS;
#ifdef _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;

    // Disable optimizations to further improve shader debugging
    dwShaderFlags |= D3DCOMPILE_SKIP_OPTIMIZATION;
#endif

    ID3DBlob* pErrorBlob = nullptr;
    hr = D3DCompileFromFile( szFileName, nullptr, nullptr, szEntryPoint, szShaderModel, 
        dwShaderFlags, 0, ppBlobOut, &pErrorBlob );
    if( FAILED(hr) )
    {
        if( pErrorBlob )
        {
            OutputDebugStringA( reinterpret_cast<const char*>( pErrorBlob->GetBufferPointer() ) );
            pErrorBlob->Release();
        }
        return hr;
    }
    if( pErrorBlob ) pErrorBlob->Release();

    return S_OK;
}

//创建设备及交换链
HRESULT InitDevice()
{
    HRESULT hResult = S_OK;//返回结果

    RECT rc;
    GetClientRect(g_hWnd, &rc);//获取窗口客户区大小
    UINT width = rc.right - rc.left;
    UINT height = rc.bottom - rc.top;

    UINT createDeviceFlags = 0;
#ifdef _DEBUG
    createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;//创建标志,0用于游戏发布,一般D3D11_CREATE_DEVICE_DEBUG允许我们创建可供调试的设备,在开发中比较有用
#endif

    //驱动类型数组,性能从强到弱排序
    D3D_DRIVER_TYPE driverTypes[] = 
    {
        D3D_DRIVER_TYPE_HARDWARE,
        D3D_DRIVER_TYPE_WARP,
        D3D_DRIVER_TYPE_REFERENCE
    };
    UINT numDriverTypes = ARRAYSIZE(driverTypes);

    //特征级别数组,从高到低排序
    D3D_FEATURE_LEVEL featureLevels[] =
    {
        D3D_FEATURE_LEVEL_11_0,
        D3D_FEATURE_LEVEL_10_1,
        D3D_FEATURE_LEVEL_10_0
    };
    UINT numFeatureLevels = ARRAYSIZE(featureLevels);

    //交换链
    DXGI_SWAP_CHAIN_DESC sd;
    ZeroMemory(&sd, sizeof(DXGI_SWAP_CHAIN_DESC));//填充
    sd.BufferCount = 1;                              //我们只创建一个后缓冲(双缓冲)因此为1
    sd.BufferDesc.Width = width;
    sd.BufferDesc.Height = height;
    sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    sd.BufferDesc.RefreshRate.Numerator = 60;
    sd.BufferDesc.RefreshRate.Denominator = 1;
    sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    sd.OutputWindow = g_hWnd;
    sd.SampleDesc.Count = 1;                      //1重采样
    sd.SampleDesc.Quality = 0;                      //采样等级,Count = 1, Quality = 0禁止了重采样
    sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;      //常用参数
    sd.Windowed = TRUE;                              //是否全屏

    for (UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; ++driverTypeIndex)
    {
        g_driverType = driverTypes[driverTypeIndex];
        hResult = D3D11CreateDeviceAndSwapChain(
            nullptr,                                //默认图形适配器
            g_driverType,                        //驱动类型
            nullptr,                                //实现软件渲染设备的动态库句柄,如果使用的驱动设备类型是软件设备则不能为nullptr
            createDeviceFlags,                    //创建标志,0用于游戏发布,一般D3D11_CREATE_DEVICE_DEBUG允许我们创建可供调试的设备,在开发中比较有用
            featureLevels,                        //特征等级
            numFeatureLevels,                    //特征等级数量
            D3D11_SDK_VERSION,                    //sdk版本号
            &sd,
            &g_pSwapChain,
            &g_pd3dDevice,
            &g_featureLevel,
            &g_pImmediateContext
            );
        if (SUCCEEDED(hResult))
            break;
    }
    if (FAILED(hResult))
        return hResult;

    //创建渲染目标视图
    ID3D11Texture2D *pBackBuffer = nullptr;
    //获取后缓冲区地址
    hResult = g_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
    if (FAILED(hResult))
        return hResult;

    //创建目标视图
    hResult = g_pd3dDevice->CreateRenderTargetView(pBackBuffer, nullptr, &g_pRenderTargetView);
    //释放后缓冲
    pBackBuffer->Release();
    if (FAILED(hResult))
        return hResult;

    //绑定到渲染管线
    g_pImmediateContext->OMSetRenderTargets(1, &g_pRenderTargetView, nullptr);

    //设置viewport
    D3D11_VIEWPORT vp;
    vp.Height = (FLOAT)height;
    vp.Width = (FLOAT)width;
    vp.MinDepth = 0.0f;
    vp.MaxDepth = 1.0f;
    vp.TopLeftX = 0;
    vp.TopLeftY = 0;
    g_pImmediateContext->RSSetViewports(1, &vp);

	// Compile the vertex shader
	ID3DBlob *pVSBlob = nullptr;
	hResult = CompileShaderFromFile(L"sample.fx", "VS", "vs_4_0", &pVSBlob);
	if( FAILED(hResult) )
    {
        MessageBox( nullptr,
                    L"The FX file cannot be compiled.  Please run this executable from the directory that contains the FX file.", L"Error", MB_OK );
        return hResult;
    }

	// Create the vertex shader
	hResult = g_pd3dDevice->CreateVertexShader(pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), nullptr, &g_pVertexShader);
	if (FAILED(hResult))
	{
		pVSBlob->Release();
		return hResult;
	}

	// 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);

	// Create the input layout传递到设备了
	hResult = g_pd3dDevice->CreateInputLayout(layout, numElements, pVSBlob->GetBufferPointer(),
		pVSBlob->GetBufferSize(), &g_pVertexLayout);
	pVSBlob->Release();
	if (FAILED(hResult))
	{
		return hResult;
	}

	// Set the input layout
	g_pImmediateContext->IASetInputLayout(g_pVertexLayout);// 激活layout

	// Compile the pixel shader
	ID3DBlob *pPSBlob = nullptr;
	hResult = CompileShaderFromFile(L"sample.fx", "PS", "ps_4_0", &pPSBlob);
	if( FAILED( hResult ) )
    {
        MessageBox( nullptr,
                    L"The FX file cannot be compiled.  Please run this executable from the directory that contains the FX file.", L"Error", MB_OK );
        return hResult;
    }

	// Create the pixel shader
	hResult = g_pd3dDevice->CreatePixelShader(pPSBlob->GetBufferPointer(), pPSBlob->GetBufferSize(), nullptr, &g_pPixelShader);
	pPSBlob->Release();
	if (FAILED(hResult))
	{
		return hResult;
	}

	// Create vertex buffer
	struct SimpleVertex
	{
		XMFLOAT3 Pos;
	};

	SimpleVertex vertices[] =
    {
        XMFLOAT3( -0.25f, 0.25f, 0.5f ),
        XMFLOAT3( 0.25f, 0.25f, 0.5f ),
        XMFLOAT3( -0.25f, -0.25f, 0.5f ),
		XMFLOAT3( 0.25f, -0.25f, 0.5f ),
    };

	
    D3D11_BUFFER_DESC bd;
	ZeroMemory( &bd, sizeof(bd) );
    bd.Usage = D3D11_USAGE_DEFAULT;
    bd.ByteWidth = sizeof( SimpleVertex ) * 4;
    bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
	bd.CPUAccessFlags = 0;
    D3D11_SUBRESOURCE_DATA InitData;
	ZeroMemory( &InitData, sizeof(InitData) );
    InitData.pSysMem = vertices;
    hResult = g_pd3dDevice->CreateBuffer( &bd, &InitData, &g_pVertexBuffer );
    if( FAILED( hResult) )
        return hResult;

	// Set vertex buffer设置成被激活的顶点缓冲
    UINT stride = sizeof( SimpleVertex );
    UINT offset = 0;
    g_pImmediateContext->IASetVertexBuffers( 0, 1, &g_pVertexBuffer, &stride, &offset );

    // Set primitive topology
    g_pImmediateContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP );
    
	
	return S_OK;
}

void Render()
{
    g_pImmediateContext->ClearRenderTargetView(g_pRenderTargetView, DirectX::Colors::White);// float ClearColor[4] = { 0.5f, 0.1f, 0.2f, 1.0f }; //red,green,blue,alpha
	
	// TODO:
	g_pImmediateContext->VSSetShader(g_pVertexShader, nullptr, 0);
	g_pImmediateContext->PSSetShader(g_pPixelShader, nullptr, 0);
	g_pImmediateContext->Draw(4, 0);

    g_pSwapChain->Present(0, 0);
}

void CleanupDevice()
{
	if (g_pVertexBuffer)
		g_pVertexBuffer->Release();
	if (g_pVertexShader)
		g_pVertexShader->Release();
	if (g_pPixelShader)
		g_pPixelShader->Release();
    if (g_pImmediateContext)
        g_pImmediateContext->ClearState();
    if (g_pSwapChain)
        g_pSwapChain->Release();
    if (g_pRenderTargetView)
        g_pRenderTargetView->Release();
    if (g_pImmediateContext)
        g_pImmediateContext->Release();
    if (g_pd3dDevice)
        g_pd3dDevice->Release();
}

2. fx文件(编译时需要在属性配置中设置为“从生成中排除”)
//--------------------------------------------------------------------------------------
// Vertex Shader
//--------------------------------------------------------------------------------------
float4 VS( float4 Pos : POSITION ) : SV_POSITION
{
    return Pos;
}


//--------------------------------------------------------------------------------------
// Pixel Shader
//--------------------------------------------------------------------------------------
float4 PS( float4 Pos : SV_POSITION ) : SV_Target
{
    return float4( 0.0f, 0.0f, 0.0f, 1.0f );    // Yellow, with Alpha = 1
}

3. 参考

官方:https://msdn.microsoft.com/en-us/library/windows/apps/ff729719.aspx

翻译:http://blog.youkuaiyun.com/jake2012/article/details/24367525

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值