在 Visual Studio 中实现三维图形的坐标系之间的变换和三维图形几何变换,可以使用 DirectX API。以下是修改示例图形为给定的三棱锥模型的代码示例:
```c++
#include <Windows.h>
#include <d3d11.h>
#include <d3dcompiler.h>
#include <DirectXMath.h>
#include <iostream>
#pragma comment(lib, "d3d11.lib")
#pragma comment(lib, "d3dcompiler.lib")
using namespace DirectX;
// 定义三棱锥顶点数据类型
struct Vertex
{
XMFLOAT3 position;
XMFLOAT4 color;
};
// 定义矩阵缓冲区数据类型
struct MatrixBuffer
{
XMMATRIX world;
XMMATRIX view;
XMMATRIX projection;
};
// 定义全局变量
HWND hwnd = NULL;
const int Width = 800;
const int Height = 600;
IDXGISwapChain* swapChain;
ID3D11Device* d3d11Device;
ID3D11DeviceContext* d3d11DeviceContext;
ID3D11RenderTargetView* renderTargetView;
ID3D11DepthStencilView* depthStencilView;
ID3D11Texture2D* depthStencilBuffer;
ID3D11InputLayout* inputLayout;
ID3D11VertexShader* vertexShader;
ID3D11PixelShader* pixelShader;
ID3D11Buffer* vertexBuffer;
ID3D11Buffer* indexBuffer;
ID3D11Buffer* matrixBuffer;
XMMATRIX worldMatrix;
XMMATRIX viewMatrix;
XMMATRIX projectionMatrix;
// 创建交换链
bool CreateSwapChain()
{
DXGI_SWAP_CHAIN_DESC swapChainDesc = {};
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.SampleDesc.Count = 1;
swapChainDesc.SampleDesc.Quality = 0;
swapChainDesc.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, &swapChainDesc, &swapChain, &d3d11Device, NULL, &d3d11DeviceContext);
if (FAILED(hr))
{
std::cout << "Failed to create swap chain" << std::endl;
return false;
}
return true;
}
// 创建渲染目标视图
bool CreateRenderTargetView()
{
ID3D11Texture2D* backBuffer;
HRESULT hr = swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&backBuffer);
if (FAILED(hr))
{
std::cout << "Failed to get back buffer" << std::endl;
return false;
}
hr = d3d11Device->CreateRenderTargetView(backBuffer, NULL, &renderTargetView);
if (FAILED(hr))
{
std::cout << "Failed to create render target view" << std::endl;
return false;
}
backBuffer->Release();
return true;
}
// 创建深度模板缓冲区和深度模板视图
bool CreateDepthStencilBufferAndView()
{
D3D11_TEXTURE2D_DESC depthStencilDesc = {};
depthStencilDesc.Width = Width;
depthStencilDesc.Height = Height;
depthStencilDesc.MipLevels = 1;
depthStencilDesc.ArraySize = 1;
depthStencilDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
depthStencilDesc.SampleDesc.Count = 1;
depthStencilDesc.SampleDesc.Quality = 0;
depthStencilDesc.Usage = D3D11_USAGE_DEFAULT;
depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
depthStencilDesc.CPUAccessFlags = 0;
depthStencilDesc.MiscFlags = 0;
HRESULT hr = d3d11Device->CreateTexture2D(&depthStencilDesc, NULL, &depthStencilBuffer);
if (FAILED(hr))
{
std::cout << "Failed to create depth stencil buffer" << std::endl;
return false;
}
hr = d3d11Device->CreateDepthStencilView(depthStencilBuffer, NULL, &depthStencilView);
if (FAILED(hr))
{
std::cout << "Failed to create depth stencil view" << std::endl;
return false;
}
return true;
}
// 创建顶点着色器
bool CreateVertexShader()
{
ID3DBlob* vertexShaderBlob;
HRESULT hr = D3DCompileFromFile(L"VertexShader.hlsl", NULL, NULL, "main", "vs_5_0", 0, 0, &vertexShaderBlob, NULL);
if (FAILED(hr))
{
std::cout << "Failed to compile vertex shader" << std::endl;
return false;
}
hr = d3d11Device->CreateVertexShader(vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), NULL, &vertexShader);
if (FAILED(hr))
{
std::cout << "Failed to create vertex shader" << std::endl;
return false;
}
// 定义顶点输入布局
D3D11_INPUT_ELEMENT_DESC inputElementDesc[] =
{
{"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 = d3d11Device->CreateInputLayout(inputElementDesc, 2, vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), &inputLayout);
if (FAILED(hr))
{
std::cout << "Failed to create input layout" << std::endl;
return false;
}
vertexShaderBlob->Release();
return true;
}
// 创建像素着色器
bool CreatePixelShader()
{
ID3DBlob* pixelShaderBlob;
HRESULT hr = D3DCompileFromFile(L"PixelShader.hlsl", NULL, NULL, "main", "ps_5_0", 0, 0, &pixelShaderBlob, NULL);
if (FAILED(hr))
{
std::cout << "Failed to compile pixel shader" << std::endl;
return false;
}
hr = d3d11Device->CreatePixelShader(pixelShaderBlob->GetBufferPointer(), pixelShaderBlob->GetBufferSize(), NULL, &pixelShader);
if (FAILED(hr))
{
std::cout << "Failed to create pixel shader" << std::endl;
return false;
}
pixelShaderBlob->Release();
return true;
}
// 创建顶点缓冲区
bool CreateVertexBuffer()
{
// 定义三棱锥的顶点数据
Vertex vertices[] =
{
{XMFLOAT3(0.0f, 0.0f, 0.0f), XMFLOAT4(1.0f, 0.0f, 0.0f, 1.0f)}, // A
{XMFLOAT3(1.0f, 0.0f, 0.0f), XMFLOAT4(0.0f, 1.0f, 0.0f, 1.0f)}, // B
{XMFLOAT3(1.0f, 0.0f, 1.0f), XMFLOAT4(0.0f, 0.0f, 1.0f, 1.0f)}, // C
{XMFLOAT3(0.0f, 0.0f, 1.0f), XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f)}, // D
{XMFLOAT3(0.5f, 1.0f, 0.5f), XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f)} // E
};
D3D11_BUFFER_DESC vertexBufferDesc = {};
vertexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
vertexBufferDesc.ByteWidth = sizeof(Vertex) * 5;
vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vertexBufferDesc.CPUAccessFlags = 0;
vertexBufferDesc.MiscFlags = 0;
D3D11_SUBRESOURCE_DATA vertexBufferData = {};
vertexBufferData.pSysMem = vertices;
HRESULT hr = d3d11Device->CreateBuffer(&vertexBufferDesc, &vertexBufferData, &vertexBuffer);
if (FAILED(hr))
{
std::cout << "Failed to create vertex buffer" << std::endl;
return false;
}
return true;
}
// 创建索引缓冲区
bool CreateIndexBuffer()
{
// 定义三棱锥的索引数据
unsigned int indices[] =
{
0, 1, 2, // 底面三角形 ABC
0, 2, 3, // 底面三角形 ACD
0, 1, 4, // 侧面三角形 ABE
1, 2, 4, // 侧面三角形 BCE
2, 3, 4, // 侧面三角形 CDE
3, 0, 4 // 侧面三角形 DAE
};
D3D11_BUFFER_DESC indexBufferDesc = {};
indexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
indexBufferDesc.ByteWidth = sizeof(unsigned int) * 18;
indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
indexBufferDesc.CPUAccessFlags = 0;
indexBufferDesc.MiscFlags = 0;
D3D11_SUBRESOURCE_DATA indexBufferData = {};
indexBufferData.pSysMem = indices;
HRESULT hr = d3d11Device->CreateBuffer(&indexBufferDesc, &indexBufferData, &indexBuffer);
if (FAILED(hr))
{
std::cout << "Failed to create index buffer" << std::endl;
return false;
}
return true;
}
// 创建矩阵缓冲区
bool CreateMatrixBuffer()
{
D3D11_BUFFER_DESC matrixBufferDesc = {};
matrixBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
matrixBufferDesc.ByteWidth = sizeof(MatrixBuffer);
matrixBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
matrixBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
matrixBufferDesc.MiscFlags = 0;
HRESULT hr = d3d11Device->CreateBuffer(&matrixBufferDesc, NULL, &matrixBuffer);
if (FAILED(hr))
{
std::cout << "Failed to create matrix buffer" << std::endl;
return false;
}
return true;
}
// 初始化 DirectX
bool InitDirectX()
{
if (!CreateSwapChain())
{
return false;
}
if (!CreateRenderTargetView())
{
return false;
}
if (!CreateDepthStencilBufferAndView())
{
return false;
}
d3d11DeviceContext->OMSetRenderTargets(1, &renderTargetView, depthStencilView);
D3D11_VIEWPORT viewport = {};
viewport.TopLeftX = 0;
viewport.TopLeftY = 0;
viewport.Width = Width;
viewport.Height = Height;
viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f;
d3d11DeviceContext->RSSetViewports(1, &viewport);
if (!CreateVertexShader())
{
return false;
}
if (!CreatePixelShader())
{
return false;
}
if (!CreateVertexBuffer())
{
return false;
}
if (!CreateIndexBuffer())
{
return false;
}
if (!CreateMatrixBuffer())
{
return false;
}
return true;
}
// 渲染场景
void RenderScene()
{
// 设置顶点缓冲区和索引缓冲区
unsigned int stride = sizeof(Vertex);
unsigned int offset = 0;
d3d11DeviceContext->IASetVertexBuffers(0, 1, &vertexBuffer, &stride, &offset);
d3d11DeviceContext->IASetIndexBuffer(indexBuffer, DXGI_FORMAT_R32_UINT, 0);
// 设置输入布局
d3d11DeviceContext->IASetInputLayout(inputLayout);
// 设置基本图元类型
d3d11DeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
// 更新矩阵缓冲区
MatrixBuffer matrixBufferData = {};
matrixBufferData.world = worldMatrix;
matrixBufferData.view = viewMatrix;
matrixBufferData.projection = projectionMatrix;
D3D11_MAPPED_SUBRESOURCE mappedResource = {};
HRESULT hr = d3d11DeviceContext->Map(matrixBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if (FAILED(hr))
{
std::cout << "Failed to map matrix buffer" << std::endl;
return;
}
memcpy(mappedResource.pData, &matrixBufferData, sizeof(MatrixBuffer));
d3d11DeviceContext->Unmap(matrixBuffer, 0);
d3d11DeviceContext->VSSetConstantBuffers(0, 1, &matrixBuffer);
// 设置顶点着色器和像素着色器
d3d11DeviceContext->VSSetShader(vertexShader, NULL, 0);
d3d11DeviceContext->PSSetShader(pixelShader, NULL, 0);
// 绘制图形
d3d11DeviceContext->DrawIndexed(18, 0, 0);
// 切换缓冲区,显示渲染结果
swapChain->Present(0, 0);
}
// 释放资源
void Release()
{
if (matrixBuffer)
{
matrixBuffer->Release();
}
if (indexBuffer)
{
indexBuffer->Release();
}
if (vertexBuffer)
{
vertexBuffer->Release();
}
if (pixelShader)
{
pixelShader->Release();
}
if (vertexShader)
{
vertexShader->Release();
}
if (inputLayout)
{
inputLayout->Release();
}
if (depthStencilView)
{
depthStencilView->Release();
}
if (depthStencilBuffer)
{
depthStencilBuffer->Release();
}
if (renderTargetView)
{
renderTargetView->Release();
}
if (swapChain)
{
swapChain->Release();
}
if (d3d11DeviceContext)
{
d3d11DeviceContext->Release();
}
if (d3d11Device)
{
d3d11Device->Release();
}
}
// 窗口过程函数
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
int main()
{
// 注册窗口类
HINSTANCE hInstance = GetModuleHandle(NULL);
WNDCLASSEX wc = {};
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.lpszClassName = L"DirectXWindowClass";
RegisterClassEx(&wc);
// 创建窗口
hwnd = CreateWindowEx(0, L"DirectXWindowClass", L"DirectX Window", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, Width, Height, NULL, NULL, hInstance, NULL);
if (hwnd == NULL)
{
std::cout << "Failed to create window" << std::endl;
return 0;
}
ShowWindow(hwnd, SW_SHOW);
// 初始化 DirectX
if (!InitDirectX())
{
Release();
return 0;
}
// 设置世界坐标系、物坐标系和屏幕坐标系的变换矩阵
worldMatrix = XMMatrixIdentity();
viewMatrix = XMMatrixLookAtLH(XMVectorSet(0.0f, 1.5f, -3.0f, 0.0f), XMVectorSet(0.0f, 0.0f, 0.0f, 0.0f), XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f));
projectionMatrix = XMMatrixPerspectiveFovLH(XM_PIDIV4,