C语言调用D3D11示例
由deepseek-r1创作

#pragma once #include <windows.h> #include <d3d11.h> #include <d3dcompiler.h> #include <d3d9types.h> #include <dxgi.h> #include <math.h> #pragma comment(lib, "d3d11.lib") #pragma comment(lib, "d3dcompiler.lib") #pragma comment(lib, "dxgi.lib") #define WIDTH 800 #define HEIGHT 600 // 常量缓冲结构体 typedef struct { D3DMATRIX mWorld; // 世界矩阵 D3DMATRIX mView; // 视图矩阵 D3DMATRIX mProjection; // 投影矩阵 } ConstantBuffer; // 顶点结构体 typedef struct { float pos[3]; float color[4]; } Vertex; // 全局变量 ID3D11Device* g_pDevice = NULL; ID3D11DeviceContext* g_pContext = NULL; IDXGISwapChain* g_pSwapChain = NULL; ID3D11RenderTargetView* g_pRenderTargetView = NULL; ID3D11VertexShader* g_pVertexShader = NULL; ID3D11PixelShader* g_pPixelShader = NULL; ID3D11InputLayout* g_pInputLayout = NULL; ID3D11Buffer* g_pVertexBuffer = NULL; ID3D11Buffer* g_pIndexBuffer = NULL; ID3D11Buffer* g_pConstantBuffer = NULL; ID3D11DepthStencilView* g_pDepthStencilView = NULL; ID3D11RasterizerState* g_pRasterizerState = NULL; // 矩阵操作函数 void MatrixIdentity(D3DMATRIX* m) { memset(m, 0, sizeof(D3DMATRIX)); m->_11 = m->_22 = m->_33 = m->_44 = 1.0f; } void MatrixRotationY(D3DMATRIX* m, float angle) { float sinA = sinf(angle); float cosA = cosf(angle); MatrixIdentity(m); m->_11 = cosA; m->_31 = sinA; m->_13 = -sinA; m->_33 = cosA; } void MatrixTranslation(D3DMATRIX* m, float x, float y, float z) { MatrixIdentity(m); m->_41 = x; m->_42 = y; m->_43 = z; } void MatrixLookAtLH(D3DMATRIX* m, const float eye[3], const float at[3], const float up[3]) { float zaxis[3] = { at[0] - eye[0], at[1] - eye[1], at[2] - eye[2] }; float len = sqrtf(zaxis[0] * zaxis[0] + zaxis[1] * zaxis[1] + zaxis[2] * zaxis[2]); zaxis[0] /= len; zaxis[1] /= len; zaxis[2] /= len; float xaxis[3]; xaxis[0] = up[1] * zaxis[2] - up[2] * zaxis[1]; xaxis[1] = up[2] * zaxis[0] - up[0] * zaxis[2]; xaxis[2] = up[0] * zaxis[1] - up[1] * zaxis[0]; len = sqrtf(xaxis[0] * xaxis[0] + xaxis[1] * xaxis[1] + xaxis[2] * xaxis[2]); xaxis[0] /= len; xaxis[1] /= len; xaxis[2] /= len; float yaxis[3]; yaxis[0] = zaxis[1] * xaxis[2] - zaxis[2] * xaxis[1]; yaxis[1] = zaxis[2] * xaxis[0] - zaxis[0] * xaxis[2]; yaxis[2] = zaxis[0] * xaxis[1] - zaxis[1] * xaxis[0]; MatrixIdentity(m); m->_11 = xaxis[0]; m->_12 = yaxis[0]; m->_13 = zaxis[0]; m->_21 = xaxis[1]; m->_22 = yaxis[1]; m->_23 = zaxis[1]; m->_31 = xaxis[2]; m->_32 = yaxis[2]; m->_33 = zaxis[2]; m->_41 = -eye[0] * xaxis[0] - eye[1] * xaxis[1] - eye[2] * xaxis[2]; m->_42 = -eye[0] * yaxis[0] - eye[1] * yaxis[1] - eye[2] * yaxis[2]; m->_43 = -eye[0] * zaxis[0] - eye[1] * zaxis[1] - eye[2] * zaxis[2]; } void MatrixPerspectiveFovLH(D3DMATRIX* m, float fov, float aspect, float znear, float zfar) { float yScale = 1.0f / tanf(fov / 2); float xScale = yScale / aspect; MatrixIdentity(m); m->_11 = xScale; m->_22 = yScale; m->_33 = zfar / (zfar - znear); m->_34 = 1.0f; m->_43 = -znear * zfar / (zfar - znear); m->_44 = 0.0f; } // 着色器代码 const char* vsCode = "cbuffer ConstantBuffer : register(b0) {\n" " row_major float4x4 mWorld;\n" " row_major float4x4 mView;\n" " row_major float4x4 mProjection;\n" "};\n" "struct VS_OUTPUT {\n" " float4 pos : SV_POSITION;\n" " float4 color : COLOR;\n" "};\n" "VS_OUTPUT VS(float3 pos : POSITION, float4 color : COLOR) {\n" " VS_OUTPUT output;\n" " float4 pos4 = float4(pos, 1.0f);\n" " pos4 = mul(pos4, mul(mWorld, mul(mView, mProjection)));\n" " output.pos = pos4;\n" " output.color = color;\n" " return output;\n" "}"; const char* psCode = "struct PS_INPUT {\n" " float4 pos : SV_POSITION;\n" " float4 color : COLOR;\n" "};\n" "float4 PS(PS_INPUT input) : SV_TARGET {\n" " return input.color;\n" "}"; // 初始化D3D设备 HRESULT InitD3D(HWND hWnd) { DXGI_SWAP_CHAIN_DESC sd = { 0 }; sd.BufferCount = 1; sd.BufferDesc.Width = WIDTH; sd.BufferDesc.Height = HEIGHT; sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; sd.BufferDesc.RefreshRate.Numerator = 60; sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd.OutputWindow = hWnd; sd.SampleDesc.Count = 1; sd.Windowed = TRUE; D3D_FEATURE_LEVEL featureLevel = D3D_FEATURE_LEVEL_11_0; HRESULT hr = D3D11CreateDeviceAndSwapChain( NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, &featureLevel, 1, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pDevice, NULL, &g_pContext ); if (FAILED(hr)) return hr; // 获取BackBuffer ID3D11Texture2D* pBackBuffer = NULL; hr = g_pSwapChain->lpVtbl->GetBuffer( g_pSwapChain, 0, &IID_ID3D11Texture2D, (void**)&pBackBuffer ); if (FAILED(hr)) return hr; // 创建RenderTargetView hr = g_pDevice->lpVtbl->CreateRenderTargetView( g_pDevice, pBackBuffer, NULL, &g_pRenderTargetView ); pBackBuffer->lpVtbl->Release(pBackBuffer); if (FAILED(hr)) return hr; // 创建深度模板纹理 ID3D11Texture2D* pDepthStencil = NULL; D3D11_TEXTURE2D_DESC descDepth = { 0 }; descDepth.Width = WIDTH; descDepth.Height = HEIGHT; descDepth.MipLevels = 1; descDepth.ArraySize = 1; descDepth.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; descDepth.SampleDesc.Count = 1; descDepth.Usage = D3D11_USAGE_DEFAULT; descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL; hr = g_pDevice->lpVtbl->CreateTexture2D(g_pDevice, &descDepth, NULL, &pDepthStencil); if (FAILED(hr)) return hr; // 创建深度模板视图 D3D11_DEPTH_STENCIL_VIEW_DESC descDSV = { 0 }; descDSV.Format = descDepth.Format; descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; hr = g_pDevice->lpVtbl->CreateDepthStencilView(g_pDevice, pDepthStencil, &descDSV, &g_pDepthStencilView); pDepthStencil->lpVtbl->Release(pDepthStencil); if (FAILED(hr)) return hr; // 绑定RenderTarget和DepthStencil g_pContext->lpVtbl->OMSetRenderTargets(g_pContext, 1, &g_pRenderTargetView, g_pDepthStencilView); // 创建光栅化状态(禁用背面剔除) D3D11_RASTERIZER_DESC rsDesc = { 0 }; rsDesc.FillMode = D3D11_FILL_SOLID; rsDesc.CullMode = D3D11_CULL_NONE; // 禁用剔除 rsDesc.DepthClipEnable = TRUE; hr = g_pDevice->lpVtbl->CreateRasterizerState(g_pDevice, &rsDesc, &g_pRasterizerState); if (FAILED(hr)) return hr; // 设置光栅化状态 g_pContext->lpVtbl->RSSetState(g_pContext, g_pRasterizerState); // 设置视口 D3D11_VIEWPORT vp = { 0 }; vp.Width = WIDTH; vp.Height = HEIGHT; vp.MaxDepth = 1.0f; g_pContext->lpVtbl->RSSetViewports(g_pContext, 1, &vp); return S_OK; } // 初始化图形资源 HRESULT InitGraphics() { // T80坦克顶点数据 Vertex vertices[] = { // 车身(绿色) {{-2.0f,-0.5f,-1.0f}, {0.2f,0.5f,0.2f,1.0f}}, {{ 2.0f,-0.5f,-1.0f}, {0.2f,0.5f,0.2f,1.0f}}, {{ 2.0f, 0.5f,-1.0f}, {0.2f,0.5f,0.2f,1.0f}}, {{-2.0f, 0.5f,-1.0f}, {0.2f,0.5f,0.2f,1.0f}}, {{-2.0f,-0.5f, 1.0f}, {0.2f,0.5f,0.2f,1.0f}}, {{ 2.0f,-0.5f, 1.0f}, {0.2f,0.5f,0.2f,1.0f}}, {{ 2.0f, 0.5f, 1.0f}, {0.2f,0.5f,0.2f,1.0f}}, {{-2.0f, 0.5f, 1.0f}, {0.2f,0.5f,0.2f,1.0f}}, // 炮塔(深绿色) {{-0.8f, 0.5f,-0.8f}, {0.1f,0.3f,0.1f,1.0f}}, {{ 0.8f, 0.5f,-0.8f}, {0.1f,0.3f,0.1f,1.0f}}, {{ 0.8f, 1.2f,-0.8f}, {0.1f,0.3f,0.1f,1.0f}}, {{-0.8f, 1.2f,-0.8f}, {0.1f,0.3f,0.1f,1.0f}}, {{-0.8f, 0.5f, 0.8f}, {0.1f,0.3f,0.1f,1.0f}}, {{ 0.8f, 0.5f, 0.8f}, {0.1f,0.3f,0.1f,1.0f}}, {{ 0.8f, 1.2f, 0.8f}, {0.1f,0.3f,0.1f,1.0f}}, {{-0.8f, 1.2f, 0.8f}, {0.1f,0.3f,0.1f,1.0f}}, // 炮管(黑色) {{-0.2f, 1.0f,-1.5f}, {0.0f,0.0f,0.0f,1.0f}}, {{ 0.2f, 1.0f,-1.5f}, {0.0f,0.0f,0.0f,1.0f}}, {{ 0.2f, 1.0f, 2.0f}, {0.0f,0.0f,0.0f,1.0f}}, {{-0.2f, 1.0f, 2.0f}, {0.0f,0.0f,0.0f,1.0f}}, // 履带(灰色) {{-2.2f,-0.6f,-1.2f}, {0.3f,0.3f,0.3f,1.0f}}, {{ 2.2f,-0.6f,-1.2f}, {0.3f,0.3f,0.3f,1.0f}}, {{ 2.2f,-0.4f,-1.2f}, {0.3f,0.3f,0.3f,1.0f}}, {{-2.2f,-0.4f,-1.2f}, {0.3f,0.3f,0.3f,1.0f}}, {{-2.2f,-0.6f, 1.2f}, {0.3f,0.3f,0.3f,1.0f}}, {{ 2.2f,-0.6f, 1.2f}, {0.3f,0.3f,0.3f,1.0f}}, {{ 2.2f,-0.4f, 1.2f}, {0.3f,0.3f,0.3f,1.0f}}, {{-2.2f,-0.4f, 1.2f}, {0.3f,0.3f,0.3f,1.0f}}, }; // 索引数据 WORD indices[] = { // 车身 0,1,2, 0,2,3, 4,5,6, 4,6,7, 0,4,5, 0,5,1, 1,5,6, 1,6,2, 2,6,7, 2,7,3, 3,7,4, 3,4,0, // 炮塔 8,9,10, 8,10,11, 12,13,14, 12,14,15, 8,12,13, 8,13,9, 9,13,14, 9,14,10, 10,14,15, 10,15,11, 11,15,12, 11,12,8, // 炮管 16,17,18, 16,18,19, 16,19,18, 16,18,17, // 履带 20,21,22, 20,22,23, 24,25,26, 24,26,27, 20,24,25, 20,25,21, 21,25,26, 21,26,22, 22,26,27, 22,27,23, 23,27,24, 23,24,20 }; // 创建顶点缓冲 D3D11_BUFFER_DESC bd = { 0 }; bd.ByteWidth = sizeof(vertices); bd.Usage = D3D11_USAGE_DEFAULT; bd.BindFlags = D3D11_BIND_VERTEX_BUFFER; D3D11_SUBRESOURCE_DATA initData = { 0 }; initData.pSysMem = vertices; HRESULT hr = g_pDevice->lpVtbl->CreateBuffer( g_pDevice, &bd, &initData, &g_pVertexBuffer ); if (FAILED(hr)) return hr; // 创建索引缓冲 bd.ByteWidth = sizeof(indices); bd.BindFlags = D3D11_BIND_INDEX_BUFFER; initData.pSysMem = indices; hr = g_pDevice->lpVtbl->CreateBuffer( g_pDevice, &bd, &initData, &g_pIndexBuffer ); if (FAILED(hr)) return hr; // 编译着色器 ID3DBlob* pVSBlob = NULL, * pPSBlob = NULL; hr = D3DCompile( vsCode, strlen(vsCode), NULL, NULL, NULL, "VS", "vs_4_0", 0, 0, &pVSBlob, NULL ); if (SUCCEEDED(hr)) { hr = g_pDevice->lpVtbl->CreateVertexShader( g_pDevice, pVSBlob->lpVtbl->GetBufferPointer(pVSBlob), pVSBlob->lpVtbl->GetBufferSize(pVSBlob), NULL, &g_pVertexShader ); if (SUCCEEDED(hr)) { D3D11_INPUT_ELEMENT_DESC layout[] = { {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0} }; hr = g_pDevice->lpVtbl->CreateInputLayout( g_pDevice, layout, 2, pVSBlob->lpVtbl->GetBufferPointer(pVSBlob), pVSBlob->lpVtbl->GetBufferSize(pVSBlob), &g_pInputLayout ); } pVSBlob->lpVtbl->Release(pVSBlob); } if (FAILED(hr)) return hr; hr = D3DCompile( psCode, strlen(psCode), NULL, NULL, NULL, "PS", "ps_4_0", 0, 0, &pPSBlob, NULL ); if (SUCCEEDED(hr)) { hr = g_pDevice->lpVtbl->CreatePixelShader( g_pDevice, pPSBlob->lpVtbl->GetBufferPointer(pPSBlob), pPSBlob->lpVtbl->GetBufferSize(pPSBlob), NULL, &g_pPixelShader ); pPSBlob->lpVtbl->Release(pPSBlob); } if (FAILED(hr)) return hr; // 创建常量缓冲 bd.ByteWidth = sizeof(ConstantBuffer); bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER; hr = g_pDevice->lpVtbl->CreateBuffer( g_pDevice, &bd, NULL, &g_pConstantBuffer ); return hr; } // 渲染帧 void RenderFrame() { static float tankRotation = 0.0f; // 车身旋转角度 static float turretRotation = 0.0f; // 炮塔旋转角度 tankRotation += 0.0005f; // 车身缓慢旋转 turretRotation += 0.001f; // 炮塔更快旋转 // 更新矩阵 ConstantBuffer cb; float eye[] = { 0,3,-5 }, at[] = { 0,0,0 }, up[] = { 0,1,0 }; MatrixLookAtLH(&cb.mView, eye, at, up); MatrixPerspectiveFovLH(&cb.mProjection, 3.1415926f / 2, (float)WIDTH / HEIGHT, 0.01f, 100.0f); // 清屏和深度缓冲 float clearColor[4] = { 0,0,0,1 }; g_pContext->lpVtbl->ClearRenderTargetView( g_pContext, g_pRenderTargetView, clearColor ); g_pContext->lpVtbl->ClearDepthStencilView( g_pContext, g_pDepthStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0 ); // 设置渲染管线 g_pContext->lpVtbl->VSSetShader( g_pContext, g_pVertexShader, NULL, 0 ); g_pContext->lpVtbl->PSSetShader( g_pContext, g_pPixelShader, NULL, 0 ); g_pContext->lpVtbl->VSSetConstantBuffers( g_pContext, 0, 1, &g_pConstantBuffer ); g_pContext->lpVtbl->IASetInputLayout( g_pContext, g_pInputLayout ); // 设置顶点缓冲 UINT stride = sizeof(Vertex), offset = 0; g_pContext->lpVtbl->IASetVertexBuffers( g_pContext, 0, 1, &g_pVertexBuffer, &stride, &offset ); g_pContext->lpVtbl->IASetIndexBuffer( g_pContext, g_pIndexBuffer, DXGI_FORMAT_R16_UINT, 0 ); g_pContext->lpVtbl->IASetPrimitiveTopology( g_pContext, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST ); // 绘制车身 MatrixRotationY(&cb.mWorld, tankRotation); g_pContext->lpVtbl->UpdateSubresource( g_pContext, g_pConstantBuffer, 0, NULL, &cb, 0, 0 ); g_pContext->lpVtbl->DrawIndexed( g_pContext, 36, // 车身索引数 0, 0 ); // 绘制履带 g_pContext->lpVtbl->DrawIndexed( g_pContext, 36, // 履带索引数 84, // 起始索引 0 ); // 绘制炮塔 D3DMATRIX turretWorld; MatrixRotationY(&turretWorld, turretRotation); cb.mWorld = turretWorld; // 炮塔独立旋转 g_pContext->lpVtbl->UpdateSubresource( g_pContext, g_pConstantBuffer, 0, NULL, &cb, 0, 0 ); g_pContext->lpVtbl->DrawIndexed( g_pContext, 36, // 炮塔索引数 36, // 起始索引 0 ); // 绘制炮管 g_pContext->lpVtbl->DrawIndexed( g_pContext, 12, // 炮管索引数 72, // 起始索引 0 ); // 呈现 g_pSwapChain->lpVtbl->Present( g_pSwapChain, 0, 0 ); } // 窗口过程 LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { if (msg == WM_DESTROY) { PostQuitMessage(0); return 0; } return DefWindowProc(hWnd, msg, wParam, lParam); } // 主函数 int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow) { WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW, WndProc, 0, 0, hInst, NULL, NULL, (HBRUSH)(COLOR_WINDOW + 1), NULL, L"D3DWindow", NULL }; RegisterClassEx(&wc); HWND hWnd = CreateWindow( wc.lpszClassName, L"T80坦克模型", WS_OVERLAPPEDWINDOW, 100, 100, WIDTH, HEIGHT, NULL, NULL, hInst, NULL ); if (SUCCEEDED(InitD3D(hWnd)) && SUCCEEDED(InitGraphics())) { ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); MSG msg = { 0 }; while (msg.message != WM_QUIT) { if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } else { RenderFrame(); } } } // 释放资源 if (g_pRasterizerState) g_pRasterizerState->lpVtbl->Release(g_pRasterizerState); if (g_pDepthStencilView) g_pDepthStencilView->lpVtbl->Release(g_pDepthStencilView); if (g_pRenderTargetView) g_pRenderTargetView->lpVtbl->Release(g_pRenderTargetView); if (g_pSwapChain) g_pSwapChain->lpVtbl->Release(g_pSwapChain); if (g_pContext) g_pContext->lpVtbl->Release(g_pContext); if (g_pDevice) g_pDevice->lpVtbl->Release(g_pDevice); return 0; }
### **步骤 1:创建新项目**
1. 打开Visual Studio → 选择 **“创建新项目”**
2. 搜索并选择 **“空项目”** → 点击 **“下一步”**
3. 输入项目名称(例如 `D3D11Cube`)→ 指定项目位置 → 点击 **“创建”**
### **步骤 2:配置项目属性**
1. **右键项目 → 属性**
2. **关键配置项**:
- **配置**:`All Configurations`(确保Debug和Release都生效)
- **平台**:`x64`(推荐,D3D11需要64位环境)
| 配置项 | 设置值 |
|---|---|
| **C/C++ → 常规 → 附加包含目录** | `$(WindowsSDK_IncludePath)` |
| **链接器 → 输入 → 附加依赖项** | `d3d11.lib;d3dcompiler.lib;dxguid.lib` |
| **链接器 → 系统 → 子系统** | `Windows (/SUBSYSTEM:WINDOWS)` |
| **C/C++ → 预处理器 → 预处理器定义** | `UNICODE;_UNICODE` |
### **步骤 3:添加源代码**
1. **右键源文件文件夹 → 添加 → 新建项** → 选择 **“C++文件”**
2. 将之前的完整代码粘贴到新文件中(文件名例如 `main.c`)
### **步骤 4:修复代码依赖项**
1. **确保包含头文件**:
```c
#include <windows.h>
#include <d3d11.h>
#include <d3dcompiler.h>
```
### **步骤 5:编译并运行**