我正在尝试制作一个简单的d3d11程序来旋转立方体。但最终立方体似乎并没有出现。只有屏幕被清除为蓝色,但立方体没有显示。我一直将此作为我的来源:https://learn.microsoft.com/en-us/windows/win32/direct3dgetstarted/getting-started-with-a-directx-game
我的项目结构是MainClass.cpp,MainClass.h(处理窗口初始化(DeviceResources.cpp、DeviceResources.h(设备资源包括设备、上下文等(Renderer.cpp,Renderer.h(渲染器加载几何体和着色器。很可能这就是我出错的地方(
这是我的渲染器。h:
#pragma once
#include <memory>
#include <Windows.h>
#include <DirectXMath.h>
#include "DeviceResources.h"
class Renderer
{
public:
Renderer(std::shared_ptr<DeviceResources> deviceResources);
~Renderer();
void CreateDeviceDependentResources();
void CreateWindowSizeDependentResources();
void Update();
void Render();
private:
HRESULT CreateShaders();
HRESULT CreateCube();
void CreateViewAndPerspective();
bool m_done = false;
std::shared_ptr<DeviceResources> m_deviceResources;
typedef struct _constantBufferStruct {
DirectX::XMFLOAT4X4 world;
DirectX::XMFLOAT4X4 view;
DirectX::XMFLOAT4X4 projection;
} ConstantBufferStruct;
static_assert((sizeof(ConstantBufferStruct) % 16) == 0, "Constant Buffer size must be 16-byte aligned");
typedef struct _vertexPositionColor {
DirectX::XMFLOAT3 pos;
DirectX::XMFLOAT3 color;
} VertexPositionColor;
typedef struct _vertexPositionColorTangent {
DirectX::XMFLOAT3 pos;
DirectX::XMFLOAT3 color;
DirectX::XMFLOAT3 tangent;
} VertexPositionColorTangent;
ConstantBufferStruct m_constantBufferData;
unsigned int m_indexCount;
unsigned int m_frameCount;
Microsoft::WRL::ComPtr<ID3D11Buffer> m_pVertexBuffer;
Microsoft::WRL::ComPtr<ID3D11Buffer> m_pIndexBuffer;
Microsoft::WRL::ComPtr<ID3D11VertexShader> m_pVertexShader;
Microsoft::WRL::ComPtr<ID3D11PixelShader> m_pPixelShader;
Microsoft::WRL::ComPtr<ID3D11InputLayout> m_pInputLayout;
Microsoft::WRL::ComPtr<ID3D11InputLayout> m_pInputLayoutExtended;
Microsoft::WRL::ComPtr<ID3D11Buffer> m_pConstantBuffer;
};
这是我的Renderer.cpp代码:
#include "Renderer.h"
#include <fstream>
#include <ppltasks.h>
#include <stdexcept>
Renderer::Renderer(std::shared_ptr<DeviceResources> deviceResources) :
m_deviceResources(deviceResources),
m_frameCount(0)
{
m_frameCount = 0;
}
Renderer::~Renderer() {}
void Renderer::CreateDeviceDependentResources() {
auto CreateShaderTask = Concurrency::create_task([this]() {CreateShaders();
m_done = true;
});
auto CreateCubeTask = CreateShaderTask.then([this]() {CreateCube(); });
}
void Renderer::CreateWindowSizeDependentResources() {
CreateViewAndPerspective();
}
HRESULT Renderer::CreateShaders() {
HRESULT hr = S_OK;
ID3D11Device* device = m_deviceResources->GetDevice();
FILE* vShader, * pShader;
BYTE* bytes;
size_t destSize = 4096;
size_t bytesRead = 0;
bytes = new BYTE[destSize];
fopen_s(&vShader, "cubeVertexShader.cso", "rb");
bytesRead = fread_s(bytes, destSize, 1, 4096, vShader);
hr = device->CreateVertexShader(
bytes,
bytesRead,
nullptr,
&m_pVertexShader
);
D3D11_INPUT_ELEMENT_DESC iaDesc[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT,
0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R32G32B32_FLOAT,
0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
hr = device->CreateInputLayout(iaDesc,ARRAYSIZE(iaDesc), bytes, bytesRead, &m_pInputLayout);
delete bytes;
bytes = new BYTE[destSize];
bytesRead = 0;
fopen_s(&pShader, "cubePixelShader.cso", "rb");
bytesRead = fread_s(bytes, destSize, 1, 4096, pShader);
hr = device->CreatePixelShader(bytes, bytesRead, nullptr, &m_pPixelShader);
CD3D11_BUFFER_DESC cbDesc(sizeof(ConstantBufferStruct), D3D11_BIND_CONSTANT_BUFFER );
hr = device->CreateBuffer(&cbDesc, nullptr, &m_pConstantBuffer);
if (FAILED(hr))
throw std::exception("Failed to Create Constant Buffer");
fclose(vShader);
fclose(pShader);
return hr;
}
HRESULT Renderer::CreateCube() {
HRESULT hr = S_OK;
ID3D11Device* device = m_deviceResources->GetDevice();
VertexPositionColor CubeVertices[] =
{
{DirectX::XMFLOAT3(-0.5f,-0.5f,-0.5f), DirectX::XMFLOAT3(0, 0, 0),},
{DirectX::XMFLOAT3(-0.5f,-0.5f, 0.5f), DirectX::XMFLOAT3(0, 0, 1),},
{DirectX::XMFLOAT3(-0.5f, 0.5f,-0.5f), DirectX::XMFLOAT3(0, 1, 0),},
{DirectX::XMFLOAT3(-0.5f, 0.5f, 0.5f), DirectX::XMFLOAT3(0, 1, 1),},
{DirectX::XMFLOAT3(0.5f,-0.5f,-0.5f), DirectX::XMFLOAT3(1, 0, 0),},
{DirectX::XMFLOAT3(0.5f,-0.5f, 0.5f), DirectX::XMFLOAT3(1, 0, 1),},
{DirectX::XMFLOAT3(0.5f, 0.5f,-0.5f), DirectX::XMFLOAT3(1, 1, 0),},
{DirectX::XMFLOAT3(0.5f, 0.5f, 0.5f), DirectX::XMFLOAT3(1, 1, 1),},
};
unsigned short CubeIndices[] =
{
0,2,1, // -x
1,2,3,
4,5,6, // +x
5,7,6,
0,1,5, // -y
0,5,4,
2,6,7, // +y
2,7,3,
0,4,6, // -z
0,6,2,
1,3,7, // +z
1,7,5,
};
m_indexCount = ARRAYSIZE(CubeIndices);
CD3D11_BUFFER_DESC vbDesc(sizeof(CubeVertices), D3D11_BIND_VERTEX_BUFFER);
D3D11_SUBRESOURCE_DATA vData;
ZeroMemory(&vData, sizeof(D3D11_SUBRESOURCE_DATA));
vData.pSysMem = CubeVertices;
vData.SysMemPitch = 0;
vData.SysMemSlicePitch = 0;
hr = device->CreateBuffer(&vbDesc, &vData, &m_pVertexBuffer);
CD3D11_BUFFER_DESC ibDesc(sizeof(CubeIndices), D3D11_BIND_INDEX_BUFFER);
D3D11_SUBRESOURCE_DATA iData;
ZeroMemory(&iData, sizeof(D3D11_SUBRESOURCE_DATA));
iData.pSysMem = CubeIndices;
iData.SysMemPitch = 0;
iData.SysMemSlicePitch = 0;
hr = device->CreateBuffer(&ibDesc, &iData, &m_pIndexBuffer);
return hr;
}
void Renderer::CreateViewAndPerspective() {
// Use DirectXMath to create view and perspective matrices.
DirectX::XMVECTOR eye = DirectX::XMVectorSet(0.0f, 0.7f, 1.5f, 0.f);
DirectX::XMVECTOR at = DirectX::XMVectorSet(0.0f, -0.1f, 0.0f, 0.f);
DirectX::XMVECTOR up = DirectX::XMVectorSet(0.0f, 1.0f, 0.0f, 0.f);
DirectX::XMStoreFloat4x4(
&m_constantBufferData.view,
DirectX::XMMatrixTranspose(
DirectX::XMMatrixLookAtRH(
eye,
at,
up
)
)
);
float aspectRatio = m_deviceResources->GetAspectRatio();
DirectX::XMStoreFloat4x4(
&m_constantBufferData.projection,
DirectX::XMMatrixTranspose(
DirectX::XMMatrixPerspectiveFovRH(
DirectX::XMConvertToRadians(70),
aspectRatio,
0.01f,
100.0f
)
)
);
}
void Renderer::Update() {
DirectX::XMStoreFloat4x4(
&m_constantBufferData.world,
DirectX::XMMatrixTranspose(
DirectX::XMMatrixRotationY(
DirectX::XMConvertToRadians(
(float)m_frameCount++
)
)
)
);
if (m_frameCount == MAXUINT) m_frameCount = 0;
}
void Renderer::Render() {
while (!m_done) {
}
ID3D11DeviceContext* context = m_deviceResources->GetDeviceContext();
ID3D11RenderTargetView* renderTarget = m_deviceResources->GetRenderTarget();
ID3D11DepthStencilView* depthStencil = m_deviceResources->GetDepthStencil();
context->UpdateSubresource(m_pConstantBuffer.Get(), 0, nullptr, &m_constantBufferData, 0, 0);
const float blue[4] = { 0.2f, 0.3f, 0.8f, 1.0f};
context->ClearRenderTargetView(renderTarget, blue);
context->ClearDepthStencilView(depthStencil, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
context->OMSetRenderTargets(1, &renderTarget, depthStencil);
UINT stride = sizeof(VertexPositionColor);
UINT offset = 0;
context->IASetVertexBuffers(
0,
1,
m_pVertexBuffer.GetAddressOf(),
&stride,
&offset
);
context->IASetIndexBuffer(m_pIndexBuffer.Get(), DXGI_FORMAT_R16_UINT, 0);
context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
context->IASetInputLayout(m_pInputLayout.Get());
context->VSSetShader(m_pVertexShader.Get(), nullptr, 0);
context->VSSetConstantBuffers(0, 1, m_pConstantBuffer.GetAddressOf());
context->PSSetShader(m_pPixelShader.Get(), nullptr, 0);
//context->DrawIndexed(m_indexCount, 0, 0);
context->Draw(3, 0);
}
有关更多参考,以下是着色器:-顶点着色器
cbuffer ModelViewProjectionBuffer : register(b0)
{
matrix model;
matrix view;
matrix projection;
};
float4 main(float3 Position:POSITION, float3 Color:COLOR) : SV_POSITION// main is the default function name
{
float4 pos = float4(Position, 1.0f);
// Transform the position from object space to homogeneous projection space
pos = mul(pos, model);
pos = mul(pos, view);
pos = mul(pos, projection);
return pos;
}
像素着色器:
float4 main(float4 position:SV_POSITION) : SV_TARGET
{
return float4(0.9f, 0.4f, 0.2f, 1.0f);
}
输出的图像
请帮我分析一下哪里出了问题。此外,我正在使用visual studio 2019。
编辑:有些人要求一个完整的复制品,所以这里是视觉工作室的解决方案https://drive.google.com/file/d/1jt6fQgbRElpc9AYpbhYOyp-HCQL3WmEF/view?usp=sharing
读取顶点和像素缓冲区时,您正在进行无效的内存访问。
此外,在我的计算机上,两个着色器都有十几个千字节,而您正在读取它们的内存缓冲区只有4096个字节。
要解决此问题,请增加用于从磁盘读取着色器字节码的内存缓冲区的大小,并且不要忘记更新fread_s((中的elementcount。
例如
渲染器.cpp@35
size_t destSize = 1024 * 1024; // CHANGE THE SIZE OF YOUR MEMORY BUFFER HERE
size_t bytesRead = 0;
bytes = new BYTE[destSize];
fopen_s(&vShader, "cubeVertexShader.cso", "rb");
bytesRead = fread_s(bytes, destSize * sizeof(BYTE), sizeof(BYTE), destSize, vShader);
hr = device->CreateVertexShader(
bytes,
bytesRead,
nullptr,
&m_pVertexShader
);
在读取像素着色器的位置执行相同操作。
PRO提示:注意调试输出,你会看到来自d3d调试层的重要消息,比如告诉你两个着色器都无法创建的消息:(