三角

main.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#include <windows.h>
#include <d3d11.h>
#include <d3dcompiler.h>
#include <iostream>
#include <wrl/client.h>

#pragma comment(lib, "d3d11.lib")
#pragma comment(lib, "dxgi.lib")
#pragma comment(lib, "d3dcompiler.lib")

using Microsoft::WRL::ComPtr;

// 顶点结构
struct Vertex {
float x, y, z;
float r, g, b, a;
};

// HLSL着色器源码
const char* shaderSource = R"(
struct VOut {
float4 pos : SV_POSITION;
float4 col : COLOR;
};
VOut VShader(float4 pos : POSITION, float4 col : COLOR) {
VOut output;
output.pos = pos;
output.col = col;
return output;
}
float4 PShader(float4 pos : SV_POSITION, float4 col : COLOR) : SV_TARGET {
return col;
}
)";

int main() {
// 1. 设置控制台编码,解决输出乱码
system("chcp 65001");
HWND hWnd = GetConsoleWindow();
if (!hWnd) {
std::cout << "无法获取控制台句柄!" << std::endl;
return -1;
}

// 2. 初始化 D3D11 设备与交换链
DXGI_SWAP_CHAIN_DESC sd = {};
sd.BufferCount = 1;
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.OutputWindow = hWnd;
sd.SampleDesc.Count = 1;
sd.Windowed = TRUE;

ComPtr<ID3D11Device> device;
ComPtr<ID3D11DeviceContext> context;
ComPtr<IDXGISwapChain> swapChain;
D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, 0, nullptr, 0, D3D11_SDK_VERSION, &sd, &swapChain, &device, nullptr, &context);

// 3. 创建渲染目标视图 (RTV)
ComPtr<ID3D11RenderTargetView> rtv;
ComPtr<ID3D11Texture2D> backBuffer;
swapChain->GetBuffer(0, IID_PPV_ARGS(&backBuffer));
device->CreateRenderTargetView(backBuffer.Get(), nullptr, &rtv);

// 4. 编译并创建着色器
ComPtr<ID3D11VertexShader> vs;
ComPtr<ID3D11PixelShader> ps;
ComPtr<ID3DBlob> vsBlob, psBlob;
D3DCompile(shaderSource, strlen(shaderSource), nullptr, nullptr, nullptr, "VShader", "vs_4_0", 0, 0, &vsBlob, nullptr);
D3DCompile(shaderSource, strlen(shaderSource), nullptr, nullptr, nullptr, "PShader", "ps_4_0", 0, 0, &psBlob, nullptr);
device->CreateVertexShader(vsBlob->GetBufferPointer(), vsBlob->GetBufferSize(), nullptr, &vs);
device->CreatePixelShader(psBlob->GetBufferPointer(), psBlob->GetBufferSize(), nullptr, &ps);

// 5. 创建输入布局
ComPtr<ID3D11InputLayout> layout;
D3D11_INPUT_ELEMENT_DESC ied[] = {
{"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}
};
device->CreateInputLayout(ied, 2, vsBlob->GetBufferPointer(), vsBlob->GetBufferSize(), &layout);

// 6. 创建顶点缓冲区 (Triangle)
Vertex vertices[] = {
{ 0.0f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f },
{ 0.45f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f },
{-0.45f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f }
};
ComPtr<ID3D11Buffer> vb;
D3D11_BUFFER_DESC bd = { sizeof(vertices), D3D11_USAGE_DEFAULT, D3D11_BIND_VERTEX_BUFFER, 0, 0, 0 };
D3D11_SUBRESOURCE_DATA srd = { vertices, 0, 0 };
device->CreateBuffer(&bd, &srd, &vb);

// 7. 设置视口 (Viewport)
RECT rc; GetClientRect(hWnd, &rc);
D3D11_VIEWPORT vp = { 0, 0, (float)(rc.right - rc.left), (float)(rc.bottom - rc.top), 0.0f, 1.0f };
context->RSSetViewports(1, &vp);

std::cout << "正在控制台渲染彩色三角形... 按下 ESC 键退出。" << std::endl;

// 8. 渲染循环
while (!(GetAsyncKeyState(VK_ESCAPE) & 0x8000)) {
float bgColor[] = { 0.1f, 0.1f, 0.1f, 1.0f };
context->ClearRenderTargetView(rtv.Get(), bgColor);

context->OMSetRenderTargets(1, rtv.GetAddressOf(), nullptr);
context->IASetInputLayout(layout.Get());
context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
UINT stride = sizeof(Vertex), offset = 0;
context->IASetVertexBuffers(0, 1, vb.GetAddressOf(), &stride, &offset);
context->VSSetShader(vs.Get(), nullptr, 0);
context->PSSetShader(ps.Get(), nullptr, 0);

context->Draw(3, 0);
swapChain->Present(1, 0);
}

return 0;
}

CMakeLists.txt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
cmake_minimum_required(VERSION 3.20)

# 项目名称
project(ConsoleD3D11 LANGUAGES CXX)
if(MSVC)
add_compile_options("/utf-8")
endif()
# 设置 C++ 标准
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# 1. 寻找 Windows SDK 中的核心库
# d3d11.lib: 核心 API
# dxgi.lib: 交换链和硬件管理
# d3dcompiler.lib: HLSL 着色器编译
find_library(D3D11_LIB d3d11 REQUIRED)
find_library(DXGI_LIB dxgi REQUIRED)
find_library(D3DCOMPILER_LIB d3dcompiler REQUIRED)

# 2. 扫描源文件 (假设你的文件名是 main.cpp)
add_executable(${PROJECT_NAME} main.cpp)

# 3. 链接库到可执行文件
target_link_libraries(${PROJECT_NAME} PRIVATE
${D3D11_LIB}
${DXGI_LIB}
${D3DCOMPILER_LIB}
)
# 输出到项目下的 bin 文件夹
set_target_properties(${PROJECT_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin")
# 4. (可选) 设置控制台子系统
# 虽然 CMake 默认就是控制台,但这样可以确保链接器行为正确
set_target_properties(${PROJECT_NAME} PROPERTIES
WIN32_EXECUTABLE FALSE
)