Direct3D:尝试绘制三角形,但没有显示任何内容

时间:2017-10-29 10:11:28

标签: c++ directx directx-11

我正在学习Direct3D11并且我正在尝试显示一个三角形,我遵循了所有必要的步骤,但没有显示任何内容。 这是我的代码:

#include <Windows.h>
#include <dxgi1_4.h>
#include <d3d11.h>
#include <d3dcompiler.h>
#include "Game.h"

Game *Game::game = nullptr;

Game *Game::GetInstance()
{
    if (Game::game == nullptr)
        Game::game = new Game();
    return game;
}

Game::Game()
{
}

Game::~Game()
{
}

bool Game::Initialize(HINSTANCE hInstance)
{
    if (InitializeWindow(hInstance))
        return InitializeDirect3D();
    return false;
}

bool Game::InitializeWindow(HINSTANCE hInstance)
{
    WNDCLASS windowClass = {};
    windowClass.hInstance = hInstance;
    windowClass.lpfnWndProc = &WndProc;
    windowClass.lpszClassName = L"wndClass";
    windowClass.lpszMenuName = NULL;
    windowClass.style = CS_HREDRAW | CS_VREDRAW;
    windowClass.cbClsExtra = 0;
    windowClass.cbWndExtra = 0;
    windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    windowClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    windowClass.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);
    RegisterClass(&windowClass);

    mWindow = CreateWindow(L"wndClass", L"DirectX 12 Engine", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, hInstance, 0);
    if (!mWindow)
    {
        MessageBox(0, L"window creation failed", L"ERROR", MB_OK);
        return false;
    }
    ShowWindow(mWindow, SW_SHOW);
    UpdateWindow(mWindow);

    return true;
}

bool Game::InitializeDirect3D()
{
    HRESULT hr;

    // create the device and the device context
    const D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_11_0 };
    D3D_FEATURE_LEVEL featureLevel;
    hr = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, 0, D3D11_CREATE_DEVICE_DEBUG, featureLevels, 1, D3D11_SDK_VERSION, &mDevice, &featureLevel, &mDeviceContext);
    if (FAILED(hr))
    {
        MessageBox(mWindow, L"device creation failed", L"ERROR", MB_OK);
        return false;
    }
    if (featureLevel != D3D_FEATURE_LEVEL_11_0)
    {
        MessageBox(mWindow, L"DirectX 11 not supported", L"ERROR", MB_OK);
        return false;
    }

    // query 4X MSAA support
    mDevice->CheckMultisampleQualityLevels(DXGI_FORMAT_R8G8B8A8_UNORM, 4, &m4xMsaaQuality);
    if (m4xMsaaQuality <= 0)
    {
        MessageBox(mWindow, L"4X MSAA not supported", L"ERROR", MB_OK);
        return false;
    }

    // describe and create the swap chain
    DXGI_MODE_DESC modeDesc = {};
    modeDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    modeDesc.Width = mClientWidth;
    modeDesc.Height = mClientHeight;
    modeDesc.RefreshRate.Denominator = 1;
    modeDesc.RefreshRate.Numerator = 60;
    modeDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
    modeDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
    DXGI_SWAP_CHAIN_DESC swapChainDesc = {};
    swapChainDesc.BufferDesc = modeDesc;
    swapChainDesc.BufferCount = 1;
    swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    swapChainDesc.Flags = 0;
    swapChainDesc.OutputWindow = mWindow;
    swapChainDesc.Windowed = true;
    swapChainDesc.SampleDesc.Count = 4;
    swapChainDesc.SampleDesc.Quality = m4xMsaaQuality - 1;
    swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;

    IDXGIDevice *device = nullptr;
    mDevice->QueryInterface(IID_PPV_ARGS(&device));
    IDXGIAdapter *adapter = nullptr;
    device->GetParent(IID_PPV_ARGS(&adapter));
    IDXGIFactory *factory = nullptr;
    adapter->GetParent(IID_PPV_ARGS(&factory));
    hr = factory->CreateSwapChain(mDevice, &swapChainDesc, &mSwapChain);
    if (FAILED(hr))
    {
        MessageBox(mWindow, L"swap chain creation failed", L"ERROR", MB_OK);
        return false;
    }

    device->Release();
    adapter->Release();
    factory->Release();

    // create the render target view
    ID3D11Texture2D *texture = nullptr;
    mSwapChain->GetBuffer(0, IID_PPV_ARGS(&texture));
    mDevice->CreateRenderTargetView(texture, nullptr, &mRenderTargetView);
    texture->Release();

    // bind render target views to output merger stage of graphics pipeline
    mDeviceContext->OMSetRenderTargets(1, &mRenderTargetView, nullptr);

    // set the viewport
    D3D11_VIEWPORT viewport;
    viewport.TopLeftX = 0.0f;
    viewport.TopLeftY = 0.0f;
    viewport.Width = static_cast<float>(mClientWidth);
    viewport.Height = static_cast<float>(mClientHeight);
    viewport.MinDepth = 0.0f;
    viewport.MaxDepth = 1.0f;
    mDeviceContext->RSSetViewports(1, &viewport);

    CreateShaders();
    CreateBuffers();
    CreateInputLayout();

    return true;
}

bool Game::CreateShaders()
{
    HRESULT hr;

    // compile shaders
    ID3DBlob *error;
    hr = D3DCompileFromFile(L"shaders/VertexShader.hlsl", nullptr, nullptr, "main", "vs_5_0", 0, 0, &mVertexShaderBlob, &error);
    if (FAILED(hr))
    {
        ErrorBox(L"vertex shader compilation failed");
        OutputDebugStringA((LPCSTR)error->GetBufferPointer());
        return false;
    }
    hr = D3DCompileFromFile(L"shaders/PixelShader.hlsl", nullptr, nullptr, "main", "ps_5_0", 0, 0, &mPixelShaderBlob, &error);
    if (FAILED(hr))
    {
        ErrorBox(L"pixel shader compilation failed");
        OutputDebugStringA((LPCSTR)error->GetBufferPointer());
        return false;
    }

    // create shaders
    hr = mDevice->CreateVertexShader(mVertexShaderBlob->GetBufferPointer(), mVertexShaderBlob->GetBufferSize(), nullptr, &mVertexShader);
    if (FAILED(hr))
    {
        ErrorBox(L"vertex shader creation failed");
        return false;
    }
    hr = mDevice->CreatePixelShader(mPixelShaderBlob->GetBufferPointer(), mPixelShaderBlob->GetBufferSize(), nullptr, &mPixelShader);
    if (FAILED(hr))
    {
        ErrorBox(L"pixel shader creation failed");
        return false;
    }

    return true;
}

bool Game::CreateBuffers()
{
    HRESULT hr;

    // define geometry
    struct Vertex
    {
        float position[3];
    };
    Vertex vertices[] = {
        {-0.5f, -0.5f, 0.0f},
        {-0.5f, 0.5f, 0.0f},
        {0.5f, 0.0f, 0.0f}
    };

    // create vertex buffer
    D3D11_BUFFER_DESC bufferDesc = {};
    bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
    bufferDesc.ByteWidth = sizeof vertices;
    bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
    bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
    bufferDesc.MiscFlags = 0;
    bufferDesc.StructureByteStride = 0;

    D3D11_SUBRESOURCE_DATA data = {};
    data.pSysMem = vertices;

    hr = mDevice->CreateBuffer(&bufferDesc, &data, &mVertexBuffer);
    if (FAILED(hr))
    {
        ErrorBox(L"vertex buffer creation failed");
        return false;
    }

    return true;
}

bool Game::CreateInputLayout()
{
    HRESULT hr;

    // describe input layout
    D3D11_INPUT_ELEMENT_DESC inputLayout[] = {
        {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
    };

    // create input layout
    hr = mDevice->CreateInputLayout(inputLayout, 1, mVertexShaderBlob->GetBufferPointer(), mVertexShaderBlob->GetBufferSize(), &mInputLayout);
    if (FAILED(hr))
    {
        ErrorBox(L"input layout creation failed");
        return false;
    }

    return true;
}

int Game::Run()
{
    MSG msg;
    do
    {
        if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE) != 0)
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        else
            Draw();
    } while (msg.message != WM_QUIT);

    return (int)msg.wParam;
}

// custom vertex format
struct Vertex
{
    float position[3];
    unsigned char color[4];
};

void Game::Draw()
{
    const float color[] = { 0.0f, 1.0f, 0.0f, 1.0f };
    mDeviceContext->ClearRenderTargetView(mRenderTargetView, color);

    // set shaders
    mDeviceContext->VSSetShader(mVertexShader, nullptr, 0);
    mDeviceContext->PSSetShader(mPixelShader, nullptr, 0);

    // set vertex buffer
    UINT stride = sizeof(Vertex);
    UINT offset = 0;
    mDeviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &offset);

    // set input layout
    mDeviceContext->IASetInputLayout(mInputLayout);

    // set primitive topology
    mDeviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

    // draw
    mDeviceContext->Draw(3, 0);
    mSwapChain->Present(0, 0);
}

LRESULT CALLBACK Game::GameWndProc(HWND window, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
        case WM_LBUTTONDOWN:
            MessageBox(mWindow, L"left mouse button clicked", L"CLICK", MB_OK);
            return 0;
        case WM_RBUTTONDOWN:
            MessageBox(mWindow, L"right mouse button clicked", L"CLICK", MB_OK);
            return 0;
        case WM_CLOSE:
            if (MessageBox(mWindow, L"are you sure you want to quit?", L"QUIT", MB_YESNO) == IDYES)
                PostQuitMessage(0);
            return 0;
        default: 
            return DefWindowProc(window, msg, wParam, lParam);
    }
}

LRESULT CALLBACK WndProc(HWND window, UINT msg, WPARAM wParam, LPARAM lParam)
{
    return Game::GetInstance()->GameWndProc(window, msg, wParam, lParam);
}

void ErrorBox(wchar_t *message)
{
    MessageBox(Game::GetInstance()->mWindow, message, L"ERROR", MB_OK);
}

我的WinMain只调用Game :: Initialize()和Game :: Run()。 顶点着色器仅输出顶点的位置,而像素着色器只绘制白色实心像素片段,但我只得到一个绿色屏幕。

我首先尝试使用DirectX12,但我被API的复杂性吓跑了,所以我转向DirectX11学习如何绘制内容然后我会考虑D3D1(我对SDL和OpenGL很熟悉)我设法用它制作简单的游戏,但我坚持使用DirectX初始化。

1 个答案:

答案 0 :(得分:-1)

[翻译] 尝试设置光栅化器状态:

ID3D11RasterizerState* rs = 0;
D3D11_RASTERIZER_DESC r;
r.AntialiasedLineEnable = false;
r.CullMode = D3D11_CULL_BACK;
r.DepthBias = 0;
r.DepthBiasClamp = 0.0f;
r.DepthClipEnable = true;
r.FillMode = D3D11_FILL_MODE::D3D11_FILL_SOLID;
r.FrontCounterClockwise = true;
r.MultisampleEnable = false;
r.ScissorEnable = false;
r.SlopeScaledDepthBias = 0.0f;
/*if (FAILED(*/device->CreateRasterizerState(&r,&rs);
d3dcontext->RSSetState(rs);