无法在 Direct3D 应用程序中显示立方体

问题描述 投票:0回答:1

我目前正在开发一个 Direct3D 应用程序,在该应用程序中我面临着在屏幕上显示立方体的挑战。尽管检查了各个方面,立方体仍未出现。以下是我到目前为止已验证的内容:

为立方体的顶点和索引定义并创建缓冲区。 编译着色器(VShader 和 PShader),没有遇到任何错误。 确保视口和渲染目标视图的正确设置。 调用 Present() 函数在屏幕上渲染帧。 然而,尽管做出了这些努力,立方体在运行应用程序时仍然不可见。

感谢您为解决此问题提供的任何见解或帮助。感谢您的关注!

主要.cpp

#include "ExtroEngine.h"
#include <Windows.h>

using namespace ExtroEngine;

ID3D11Device* gp_Device;
ID3D11DeviceContext* gp_DeviceContext;

IDXGIDevice* gp_DXGI_Device;
IDXGIAdapter* gp_DXGI_Adapter;
IDXGIFactory* gp_DXGI_Factory;
IDXGISwapChain* gp_DXGI_SwapChain;

ID3D11VertexShader* gp_VS;
ID3D11PixelShader* gp_PS;
ID3D11InputLayout* gp_InputLayout;
ID3D11Buffer* gp_VBuffer;

ID3D11RenderTargetView* gp_BackBuffer;

void InitD3D(HWND hwnd,RECT wr);
void InitPipeline();
void InitGraphics();
void Render();
void CleanD3D();

Vertex Triangle[] = {
    { XMFLOAT3(-0.5f, -0.5f, -0.5f), XMFLOAT4(1.0f, 0.0f, 0.0f, 1.0f) },
    { XMFLOAT3(-0.5f, 0.5f, -0.5f), XMFLOAT4(0.0f, 1.0f, 0.0f, 1.0f) },
    { XMFLOAT3(0.5f, 0.5f, -0.5f), XMFLOAT4(0.0f, 0.0f, 1.0f, 1.0f) },
    { XMFLOAT3(0.5f, -0.5f, -0.5f), XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f) },
    // Back face
    { XMFLOAT3(-0.5f, -0.5f, 0.5f), XMFLOAT4(1.0f, 0.0f, 0.0f, 1.0f) },
    { XMFLOAT3(0.5f, -0.5f, 0.5f), XMFLOAT4(0.0f, 1.0f, 0.0f, 1.0f) },
    { XMFLOAT3(0.5f, 0.5f, 0.5f), XMFLOAT4(0.0f, 0.0f, 1.0f, 1.0f) },
    { XMFLOAT3(-0.5f, 0.5f, 0.5f), XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f) }
};
WORD CubeIndices[] = {
    // Front face
    0, 1, 2,
    0, 2, 3,
    // Back face
    4, 5, 6,
    4, 6, 7,
    // Left face
    4, 7, 1,
    4, 1, 0,
    // Right face
    3, 2, 6,
    3, 6, 5,
    // Top face
    1, 7, 6,
    1, 6, 2,
    // Bottom face
    4, 0, 3,
    4, 3, 5
};
LRESULT CALLBACK WinProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    HWND hwnd;

    WNDCLASSEXW Wnd = {};
    Wnd.cbSize = sizeof(WNDCLASSEXW);
    Wnd.cbClsExtra = 0;
    Wnd.hInstance = hInstance;
    Wnd.lpszClassName = L"Scene";
    Wnd.lpfnWndProc = WinProc;
    Wnd.style = CS_HREDRAW | CS_VREDRAW;
    Wnd.hCursor = LoadCursorW(hInstance, IDC_ARROW);

    RegisterClassExW(&Wnd);

    RECT wr = { 0, 0, SCENE_WIDTH, SCENE_HEIGHT };
    AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);

    hwnd = CreateWindowExW(NULL, L"Scene", L"Scene", WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, wr.right - wr.left, wr.bottom - wr.top,
        NULL, NULL, hInstance, NULL);
    ShowWindow(hwnd, nCmdShow);
    InitD3D(hwnd, wr);

    MSG msg = { 0 };
    while (TRUE)
    {
        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
            if (msg.message == WM_QUIT)
                break;
        }
        Render();
    }
    CleanD3D();
    return 0;
}
//-------------------KHỞI TẠO DIRECTX 3D-------------------//
void InitD3D(HWND hwnd, RECT wr)
{
    HRESULT hr = 0;
    GetClientRect(hwnd, &wr);
    D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_10_1 };
    D3D_DRIVER_TYPE DriveType[] = {D3D_DRIVER_TYPE_HARDWARE, D3D_DRIVER_TYPE_WARP, D3D_DRIVER_TYPE_REFERENCE};

    DXGI_SWAP_CHAIN_DESC swpDesc;
    ZeroMemory(&swpDesc, sizeof(DXGI_SWAP_CHAIN_DESC));
    swpDesc.BufferCount = 1;
    swpDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    swpDesc.BufferDesc.Width = SCENE_WIDTH_MAX_HD;
    swpDesc.BufferDesc.Height = SCENE_HEIGHT_MAX_HD;
    swpDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    swpDesc.OutputWindow = hwnd;
    swpDesc.SampleDesc.Count = 1;
    swpDesc.SampleDesc.Quality = 0;
    swpDesc.Windowed = TRUE;

    for (auto DeviceSelect : DriveType)
    {
        hr = D3D11CreateDeviceAndSwapChain(NULL, DeviceSelect, NULL, NULL, NULL, NULL,
            D3D11_SDK_VERSION, &swpDesc, &gp_DXGI_SwapChain, &gp_Device, featureLevels, &gp_DeviceContext);
        if (SUCCEEDED(hr))
        {
            break;
        }
    }
    if (FAILED(hr)){
        MessageBox(NULL, L"Error Create Device And Swap Chain", L"Error", MB_OK);
        CleanD3D();
        return;
    }

    ID3D11Texture2D* pBackBuffer;
    gp_DXGI_SwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);

    gp_Device->CreateRenderTargetView(pBackBuffer, NULL, &gp_BackBuffer);
    pBackBuffer->Release();

    gp_DeviceContext->OMSetRenderTargets(1, &gp_BackBuffer, NULL);

    D3D11_VIEWPORT viewport;
    ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT));

    viewport.TopLeftX = 0;
    viewport.TopLeftY = 0;
    viewport.Width = SCENE_WIDTH_MAX_HD;
    viewport.Height = SCENE_HEIGHT_MAX_HD;

    gp_DeviceContext->RSSetViewports(1, &viewport);

    InitPipeline();
    InitGraphics();
}

void InitPipeline()
{
    HRESULT hr;

    ID3DBlob* VS, * PS;
    hr = D3DCompileFromFile(L"Material.hlsl", NULL, D3D_COMPILE_STANDARD_FILE_INCLUDE,
        "VShader", "vs_5_0", 0, 0, &VS, NULL);
    if (FAILED(hr)){
        MessageBox(NULL, L"Compile From File {Material.hlsl} Error With {VShader}",
            L"Error", MB_OK);
        CleanD3D();
        return;
    }

    hr = D3DCompileFromFile(L"Material.hlsl", NULL, D3D_COMPILE_STANDARD_FILE_INCLUDE,
        "PShader", "ps_5_0", 0, 0, &PS, NULL);
    if (FAILED(hr)) {
        MessageBox(NULL, L"Compile From File {Material.hlsl} Error With {PShader}",
            L"Error", MB_OK);
        CleanD3D();
        return;
    }

    hr = gp_Device->CreateVertexShader(VS->GetBufferPointer(), VS->GetBufferSize(), NULL, &gp_VS);
    if (FAILED(hr)) {
        MessageBox(NULL, L"Create Vertex Shader Error With {VS}",
            L"Error", MB_OK);
        CleanD3D();
        return;
    }

    hr = gp_Device->CreatePixelShader(PS->GetBufferPointer(), PS->GetBufferSize(), NULL, &gp_PS);
    if (FAILED(hr)) {
        MessageBox(NULL, L"Create Pixel Shader Error With {PS}",
            L"Error", MB_OK);
        CleanD3D();
        return;
    }

    gp_DeviceContext->VSSetShader(gp_VS, NULL, 0);
    gp_DeviceContext->PSSetShader(gp_PS, NULL, 0);

    D3D11_INPUT_ELEMENT_DESC InputShader[] =
    {
        {"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}
    };
    gp_Device->CreateInputLayout(InputShader, 2, VS->GetBufferPointer(), VS->GetBufferSize(), &gp_InputLayout);
    gp_DeviceContext->IASetInputLayout(gp_InputLayout);
}

void InitGraphics()
{
    HRESULT hr;
    D3D11_BUFFER_DESC bd;
    ZeroMemory(&bd, sizeof(bd));
    bd.Usage = D3D11_USAGE_DYNAMIC;
    bd.ByteWidth = sizeof(Vertex) * ARRAYSIZE(Triangle);
    bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
    bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;

    D3D11_SUBRESOURCE_DATA InitData;
    ZeroMemory(&InitData, sizeof(InitData));
    InitData.pSysMem = Triangle;

    hr = gp_Device->CreateBuffer(&bd, &InitData, &gp_VBuffer);
    if (!SUCCEEDED(hr)){
        MessageBox(NULL, L"Create Buffer Error",
            L"Error", MB_OK);
        CleanD3D();
        return;
    }

    D3D11_MAPPED_SUBRESOURCE map;
    gp_DeviceContext->Map(gp_VBuffer, NULL, D3D11_MAP_WRITE_DISCARD, NULL, &map);
    memcpy(map.pData, Triangle, sizeof(Triangle));
    gp_DeviceContext->Unmap(gp_VBuffer, NULL);
}

//-------------------VẼ CỬA SỔ-------------------//
void Render()
{
    float clearColor[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
    gp_DeviceContext->ClearRenderTargetView(gp_BackBuffer, clearColor);

    UINT stride = sizeof(Vertex);
    UINT offset = 0;
    gp_DeviceContext->IASetVertexBuffers(0, 1, &gp_VBuffer, &stride, &offset);
    gp_DeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

    gp_DeviceContext->DrawIndexed(ARRAYSIZE(CubeIndices), 0, 0);
    gp_DXGI_SwapChain->Present(0, 0);
}
//-------------------GIẢI PHÓNG BỘ NHỚ DIRECTX 3D-------------------//
void CleanD3D()
{
    SafeRelease(gp_Device);
    SafeRelease(gp_DeviceContext);

    SafeRelease(gp_DXGI_Device);
    SafeRelease(gp_DXGI_Adapter);
    SafeRelease(gp_DXGI_Factory);
    SafeRelease(gp_DXGI_SwapChain);

    SafeRelease(gp_VS);
    SafeRelease(gp_PS);
    SafeRelease(gp_InputLayout);

    SafeRelease(gp_BackBuffer);
}
//-------------------GỌI CỬA SỔ-------------------//
LRESULT CALLBACK WinProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_PAINT:
        Render();
        ValidateRect(hwnd, NULL);
        break;

    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
        break;
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}

ExtroEngine.h

#pragma once
#include <d3d11.h>
#include <directxmath.h>
#include <dxgi1_2.h>
#include <d3dcompiler.h>

#define SCENE_HEIGHT 600
#define SCENE_HEIGHT_MAX_HD 3300
#define SCENE_WIDTH_MAX_HD 2240
#define SCENE_WIDTH 600


using namespace DirectX;

namespace ExtroEngine
{
#pragma region Sharder
    struct Vertex
    {
        XMFLOAT3 Position;
        XMFLOAT4 Color;
    };
#pragma endregion
#pragma region Utility
    //Giúp giải phóng tài nguyên an toàn hơn
    template<typename T>
    inline void SafeRelease(T& ptr)
    {
        if (ptr != NULL)
        {
            ptr->Release();
            ptr = NULL;
        }
    }
#pragma endregion
}

和Material.hlsl

cbuffer cbPerObject
{
    float4x4 WVP;
};

struct VOut
{
    float4 position : SV_POSITION;
    float4 color : COLOR;
};

VOut VShader(float4 position : POSITION, float4 color : COLOR)
{
    VOut output;

    output.position = position;
    output.color = color;

    return output;
}

float4 PShader(float4 position : SV_POSITION, float4 color : COLOR) : SV_TARGET
{
    return color;
}

我想了解为什么我会收到此错误以及原因

c++ directx-11 direct3d
1个回答
0
投票

您缺少立方体要显示的很多内容:

  • 您使用 DrawIndexed 但未在渲染管道中设置任何索引缓冲区(启用 DirectX 调试层,您将看到有关此问题的警告)
  • 您必须在管道中设置光栅化器状态

例如,您可以将其添加到您的代码中:

ID3D11Buffer* gp_IBuffer;
ID3D11RasterizerState* gp_rs;

// this goes in InitGraphics/Pipeline

// create an Index Buffer
D3D11_BUFFER_DESC ib{}
ib.Usage = D3D11_USAGE_IMMUTABLE;
ib.ByteWidth = sizeof(WORD) * ARRAYSIZE(CubeIndices);
ib.BindFlags = D3D11_BIND_INDEX_BUFFER;

D3D11_SUBRESOURCE_DATA data{};
data.pSysMem = CubeIndices;
gp_Device->CreateBuffer(&ib, &data, &gp_IBuffer);

// create a Rasterizer State
D3D11_RASTERIZER_DESC rasterizerDesc{};
rasterizerDesc.FillMode = D3D11_FILL_SOLID;
rasterizerDesc.CullMode = D3D11_CULL_NONE; // or something else
gp_Device->CreateRasterizerState(&rasterizerDesc, &gp_rs);

// this goes in Render()

gp_DeviceContext->IASetIndexBuffer(gp_IBuffer, DXGI_FORMAT_R16_UINT, 0);
gp_DeviceContext->RSSetState(gp_rs);

你应该看到这个:

PS:一般来说,你应该在“渲染循环”中设置所有管道操作(VSSetShader、PSSetShader、IASetInputLayout、OMSetRenderTargets 等)。

© www.soinside.com 2019 - 2024. All rights reserved.