可以让立方体弹出(DirectX 11)。多维数据集未显示,仅清除屏幕

Can get the cube to pop up (DirectX 11). Cube is not showing, only screen is being cleared

我正在尝试制作一个简单的 d3d11 程序来旋转立方体。 但最终立方体似乎并没有出现。 只有屏幕被清除为蓝色,但立方体没有出现。 我一直使用这个作为我的来源:https://docs.microsoft.com/en-us/windows/win32/direct3dgetstarted/getting-started-with-a-directx-game

我的项目结构是 MainClass.cpp、MainClass.h(处理 window 初始化) DeviceResources.cpp、DeviceResources.h(设备资源包括设备、上下文等) Renderer.cpp、Renderer.h(渲染器加载几何体和着色器。很可能这是我出错的地方)

这是我的 Renderer.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);
}

Image of the output

请帮我分析一下哪里错了。 此外,我正在使用 visual studio 2019.

编辑:有些人要求完整复制,所以这里是 visual studio 解决方案 https://drive.google.com/file/d/1jt6fQgbRElpc9AYpbhYOyp-HCQL3WmEF/view?usp=sharing

您在读取顶点和像素缓冲区时进行了无效的内存访问。

另外,在我的电脑上,两个着色器都有十几千字节,而你读取它们的内存缓冲区只有 4096 字节。

要解决您的问题,请增加用于从磁盘读取着色器字节码的内存缓冲区的大小,并且不要忘记更新 fread_s() 中的元素计数。

例如,

Renderer.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
    );

在读取像素着色器的地方执行相同的操作。

专业提示:注意调试输出,您会看到来自 d3d 调试层的重要消息,例如告诉您两个着色器都无法创建的消息:)