简体   繁体   中英

triangle not showing up direct3d11

I am trying to draw a triangle as the first step in a game engine I am developing, here is the code for the graphics system:

graphics.hpp

#pragma once

#include "Engine.hpp"

#include <type_traits>
#include <codecvt>

#include "Window.hpp"
#include "Shader.hpp"

namespace engine::graphics
{
    class GraphicsData final
    {
    public:
        logger::Logger* logger;

        Window* window;
        const std::string engineName;
        bool fullScreen;
    };

    class Graphics
    {
    public:
        virtual bool createGraphics(const GraphicsData& data) = 0;
        virtual void destroyGraphics() = 0;

        virtual void clearFrame() = 0;
        virtual void drawVertexes(const std::vector<std::any>& vertexes) = 0;
        virtual void presentFrame() = 0;

        virtual Graphics& loadShader(const std::string& shaderName, GraphicsShader* shader) = 0;
    };

#ifdef _WIN32
    struct DxVertex
    {
        DirectX::XMFLOAT3 m_Pos;
    };

    class DxGraphics final : public Graphics
    {
        ID3D11Device* m_Device;
        ID3D11DeviceContext* m_Context;
        IDXGISwapChain* m_Swapchain;
        ID3D11RasterizerState* m_RState;
        ID3D11RenderTargetView* m_RenderTargetView;
        ID3D11InputLayout* m_InputLayout;

        D3D_FEATURE_LEVEL m_FeatureLevel;
        D3D11_VIEWPORT m_Viewport;

        std::map<std::string, GraphicsShader*> m_GraphicsShaders;

        std::shared_ptr<logger::Logger> m_Logger;
        
        DXGI_SWAP_CHAIN_DESC GetDesc(
            Window* window,
            bool windowed
        );

    public:
        bool createGraphics(const GraphicsData& data) override;
        void destroyGraphics() override;

        void clearFrame() override;
        void drawVertexes(const std::vector<std::any>& vertexes) override;
        void presentFrame() override;

        Graphics& loadShader(const std::string& shaderName, GraphicsShader* shader) override;
    };
#endif
}

graphics.cpp

#include "Graphics.hpp"

DXGI_SWAP_CHAIN_DESC engine::graphics::DxGraphics::GetDesc(Window* window, bool windowed)
{
    RECT rect{};
    GetClientRect(std::any_cast<HWND>(window->getWindowHandle()), &rect);

    DXGI_SWAP_CHAIN_DESC desc{
        .BufferDesc = DXGI_MODE_DESC{
            .Width = static_cast<unsigned int>(rect.right - rect.left),
            .Height = static_cast<unsigned int>(rect.bottom - rect.top),
            .RefreshRate = DXGI_RATIONAL{
                .Numerator = 60, // TODO: fix this
                .Denominator = 1
            },
            .Format = DXGI_FORMAT::DXGI_FORMAT_R8G8B8A8_UNORM,
            .ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER::DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE,
            .Scaling = DXGI_MODE_SCALING::DXGI_MODE_SCALING_CENTERED
        },
        .SampleDesc = DXGI_SAMPLE_DESC{
            .Count = 1,
            .Quality = 0
        },
        .BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT,
        .BufferCount = 2,
        .OutputWindow = std::any_cast<HWND>(window->getWindowHandle()),
        .Windowed = windowed,
        .SwapEffect = DXGI_SWAP_EFFECT::DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL,
        .Flags = 0
    };

    return desc;
}

bool engine::graphics::DxGraphics::createGraphics(const GraphicsData& data)
{
    m_Logger.reset(data.logger);

    unsigned int flags = D3D11_CREATE_DEVICE_FLAG::D3D11_CREATE_DEVICE_BGRA_SUPPORT;
#ifdef _DEBUG
    flags |= D3D11_CREATE_DEVICE_FLAG::D3D11_CREATE_DEVICE_DEBUG;
#endif // _DEBUG

    D3D_FEATURE_LEVEL featureLevel[] = {
        D3D_FEATURE_LEVEL::D3D_FEATURE_LEVEL_11_0,
        D3D_FEATURE_LEVEL::D3D_FEATURE_LEVEL_11_1
    };

    DXGI_SWAP_CHAIN_DESC desc = GetDesc(data.window, !data.fullScreen);

    HRESULT hr;

    hr = D3D11CreateDeviceAndSwapChain(
        nullptr,
        D3D_DRIVER_TYPE::D3D_DRIVER_TYPE_HARDWARE,
        nullptr,
        flags,
        featureLevel,
        2,
        D3D11_SDK_VERSION,
        &desc,
        &m_Swapchain,
        &m_Device,
        &m_FeatureLevel,
        &m_Context
    );
    if (FAILED(hr))
    {
        *m_Logger << logger::Message{
            .type = logger::Message::Type::CLIENT,
            .severity = logger::Message::Severity::ERR,
            .data = "Failed to create device and swapchain"
        };
        return false;
    }

    ID3D11Texture2D* texture = nullptr;
    hr = m_Swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&texture));
    if (FAILED(hr))
    {
        *m_Logger << logger::Message{
            .type = logger::Message::Type::CLIENT,
            .severity = logger::Message::Severity::ERR,
            .data = "Failed to collect backbuffer used for rendering"
        };
        return false;
    }

    hr = m_Device->CreateRenderTargetView(texture, nullptr, &m_RenderTargetView);

    if (texture)
        texture->Release();

    if (FAILED(hr))
    {
        *m_Logger << logger::Message{
            .type = logger::Message::Type::CLIENT,
            .severity = logger::Message::Severity::ERR,
            .data = "Failed to set render target view"
        };
        return false;
    }

    m_Context->OMSetRenderTargets(1, &m_RenderTargetView, nullptr);

    m_Viewport = {
        .TopLeftX = 0,
        .TopLeftY = 0,
        .Width = static_cast<float>(desc.BufferDesc.Width),
        .Height = static_cast<float>(desc.BufferDesc.Height),
        .MinDepth = 0,
        .MaxDepth = 1
    };

    D3D11_RASTERIZER_DESC rsDesc{
        .FillMode = D3D11_FILL_MODE::D3D11_FILL_SOLID,
        .CullMode = D3D11_CULL_MODE::D3D11_CULL_BACK,
        .FrontCounterClockwise = true,
        .DepthBias = 0,
        .DepthBiasClamp = 1,
        .SlopeScaledDepthBias = 0,
        .DepthClipEnable = true,
        .ScissorEnable = false,
        .MultisampleEnable = false,
        .AntialiasedLineEnable = false
    };

    m_Device->CreateRasterizerState(
        &rsDesc,
        &m_RState
    );

    m_Context->RSSetState(
        m_RState
    );
    m_Context->RSSetViewports(1, &m_Viewport);

    return true;
}

void engine::graphics::DxGraphics::clearFrame()
{
    float color[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
    m_Context->ClearRenderTargetView(m_RenderTargetView, color);

    m_Context->RSSetState(m_RState);
    m_Context->RSSetViewports(1, &m_Viewport);

    m_Context->OMSetRenderTargets(1, &m_RenderTargetView, nullptr);
}

void engine::graphics::DxGraphics::drawVertexes(const std::vector<std::any>& vertexes)
{
    HRESULT hr;

    ID3D11Buffer* buffer;

    D3D11_INPUT_ELEMENT_DESC shaderInputLayout[] = {
        D3D11_INPUT_ELEMENT_DESC{
            .SemanticName = "POSITION",
            .SemanticIndex = 0,
            .Format = DXGI_FORMAT::DXGI_FORMAT_R32G32B32_FLOAT,
            .InputSlot = 0,
            .AlignedByteOffset = 0,
            .InputSlotClass = D3D11_INPUT_CLASSIFICATION::D3D11_INPUT_PER_VERTEX_DATA,
            .InstanceDataStepRate = 0
        }
    };
    UINT numLayoutElements = ARRAYSIZE(shaderInputLayout);

    hr = m_Device->CreateInputLayout(
        shaderInputLayout,
        numLayoutElements,
        m_GraphicsShaders.at("vertex")->getShaderCode(),
        m_GraphicsShaders.at("vertex")->getShaderCodeSize(),
        &m_InputLayout
    );
    if (FAILED(hr))
    {
        *m_Logger << logger::Message{
            .type = logger::Message::Type::CLIENT,
            .severity = logger::Message::Severity::ERR,
            .data = "Failed to create input layout"
        };
        return;
    }

    m_Context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY::D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
    m_Context->IASetInputLayout(m_InputLayout);

    UINT byteWidth = sizeof(DxVertex) * vertexes.size();

    D3D11_BUFFER_DESC desc{};
    desc.Usage = D3D11_USAGE::D3D11_USAGE_DEFAULT;
    desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
    desc.ByteWidth = byteWidth;
    desc.StructureByteStride = sizeof(DxVertex);

    D3D11_SUBRESOURCE_DATA resource{};
    resource.pSysMem = vertexes.data();

    hr = m_Device->CreateBuffer(
        &desc,
        &resource,
        &buffer
    );
    if (FAILED(hr))
    {
        if (buffer)
            buffer->Release();

        *m_Logger << logger::Message{
               .type = logger::Message::Type::CLIENT,
               .severity = logger::Message::Severity::ERR,
               .data = "Failed to create vertex buffer"
        };
        return;
    }

    UINT strides = sizeof(DxVertex);
    UINT offset = 0;

    m_Context->IASetVertexBuffers(0, 1, &buffer, &strides, &offset);

    m_Context->VSSetShader(static_cast<ID3D11VertexShader*>(m_GraphicsShaders.at("vertex")->getShader()), nullptr, 0);
    m_Context->PSSetShader(static_cast<ID3D11PixelShader*>(m_GraphicsShaders.at("pixel")->getShader()), nullptr, 0);

    UINT numVertexes = vertexes.size();

    m_Context->Draw(numVertexes, 0);

    if (buffer)
        buffer->Release();

    if (m_InputLayout)
        m_InputLayout->Release();
}

void engine::graphics::DxGraphics::presentFrame()
{
    m_Swapchain->Present(0, 0);
}

engine::graphics::Graphics& engine::graphics::DxGraphics::loadShader(const std::string& shaderName, GraphicsShader* shader)
{
    DxGraphicsShaderData data{
        .device = m_Device,
        .context = m_Context
    };
    data.logger = m_Logger.get();
    shader->createShader(data);
    m_GraphicsShaders.insert(std::make_pair(shaderName, shader));

    return *this;
}

void engine::graphics::DxGraphics::destroyGraphics()
{
    for (auto& shader : m_GraphicsShaders)
    {
        shader.second->destroyShader();
        delete shader.second;
    }
    if (m_RenderTargetView)
    {
        m_RenderTargetView->Release();
    }
    if (m_Swapchain)
    {
        m_Swapchain->Release();
    }
    if (m_Context)
    {
        m_Context->Release();
    }
    if (m_Device)
    {
        m_Device->Release();
    }
}

shader.hpp

#pragma once

#include "Engine.hpp"

#include "Logger.hpp"

namespace engine::graphics
{
    struct GraphicsShaderData
    {
        logger::Logger* logger;
    };

    class GraphicsShader
    {
    public:
        virtual bool createShader(const GraphicsShaderData& data) = 0;
        virtual void destroyShader() = 0;

        virtual const char* getShaderCode() = 0;
        virtual size_t getShaderCodeSize() = 0;

        virtual void* getShader() = 0;
    };

#ifdef _WIN32
    struct DxGraphicsShaderData final : public GraphicsShaderData
    {
        ID3D11Device* device;
        ID3D11DeviceContext* context;
    };

    template<typename T>
    class DxGraphicsShader final : public GraphicsShader
    {
    };

    template<>
    class DxGraphicsShader<ID3D11VertexShader> final : public GraphicsShader
    {
        ID3DBlob* m_Code;
        ID3D11VertexShader* m_Shader;

    public:
        bool createShader(const GraphicsShaderData& data) override
        {
            const DxGraphicsShaderData& dxdata = static_cast<const DxGraphicsShaderData&>(data);

            int flags = D3DCOMPILE_ENABLE_STRICTNESS;
#ifdef _DEBUG
            flags |= D3DCOMPILE_DEBUG;
#endif // _DEBUG
            HRESULT hr;
            ID3DBlob* errBuff;

            hr = D3DCompileFromFile(
                std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>>().from_bytes(
                    "vertex.hlsl" // TODO: fix with resource manager
                ).c_str(),
                nullptr,
                nullptr,
                "VMain",
                "vs_5_0",
                flags,
                0,
                &m_Code,
                &errBuff
            );

            if (FAILED(hr))
            {
                if (errBuff)
                {
                    *dxdata.logger << logger::Message{
                        .type = logger::Message::Type::CLIENT,
                        .severity = logger::Message::Severity::ERR,
                        .data = static_cast<char*>(errBuff->GetBufferPointer())
                    };
                    errBuff->Release();
                }

                return false;
            }

            if (errBuff)
                errBuff->Release();

            hr = dxdata.device->CreateVertexShader(
                m_Code->GetBufferPointer(),
                m_Code->GetBufferSize(),
                0,
                &m_Shader
            );
            if (FAILED(hr))
            {
                if (m_Code)
                    m_Code->Release();

                return false;
            }

            dxdata.context->VSSetShader(
                m_Shader,
                nullptr,
                0
            );

            return true;
        }
        void destroyShader() override
        {
            if (m_Shader)
                m_Shader->Release();

            if (m_Code)
                m_Code->Release();
        }

        const char* getShaderCode()
        {
            return static_cast<char*>(m_Code->GetBufferPointer());
        }
        size_t getShaderCodeSize()
        {
            return m_Code->GetBufferSize();
        }

        void* getShader() override
        {
            return m_Shader;
        }
    };

    template<>
    class DxGraphicsShader<ID3D11PixelShader> final : public GraphicsShader
    {
        ID3DBlob* m_Code;
        ID3D11PixelShader* m_Shader;

    public:
        bool createShader(const GraphicsShaderData& data) override
        {
            const DxGraphicsShaderData& dxdata = static_cast<const DxGraphicsShaderData&>(data);

            int flags = D3DCOMPILE_ENABLE_STRICTNESS;
#ifdef _DEBUG
            flags |= D3DCOMPILE_DEBUG;
#endif // _DEBUG
            HRESULT hr;
            ID3DBlob* errBuff;

            hr = D3DCompileFromFile(
                std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>>().from_bytes(
                    "pixel.hlsl" // TODO: fix with resource manager
                ).c_str(),
                nullptr,
                nullptr,
                "PMain",
                "ps_5_0",
                flags,
                0,
                &m_Code,
                &errBuff
            );

            if (FAILED(hr))
            {
                if (errBuff)
                {
                    *dxdata.logger << logger::Message{
                        .type = logger::Message::Type::CLIENT,
                        .severity = logger::Message::Severity::ERR,
                        .data = static_cast<char*>(errBuff->GetBufferPointer())
                    };
                    errBuff->Release();
                }

                return false;
            }

            if (errBuff)
                errBuff->Release();

            hr = dxdata.device->CreatePixelShader(
                m_Code->GetBufferPointer(),
                m_Code->GetBufferSize(),
                0,
                &m_Shader
            );
            if (FAILED(hr))
            {
                if (m_Code)
                    m_Code->Release();

                return false;
            }

            dxdata.context->PSSetShader(
                m_Shader,
                nullptr,
                0
            );

            return true;
        }
        void destroyShader() override
        {
            if (m_Shader)
                m_Shader->Release();

            if (m_Code)
                m_Code->Release();
        }

        const char* getShaderCode()
        {
            return static_cast<char*>(m_Code->GetBufferPointer());
        }
        size_t getShaderCodeSize()
        {
            return m_Code->GetBufferSize();
        }

        void* getShader() override
        {
            return m_Shader;
        }
    };
#endif // _WIN32
}

This is just a template before abstraction, it has a hardware based renderer, and a default rasterizer for later specification

I have already checked the memory data of the vertex buffer in gpu memory and it does indeed contain data, i get no errors from function outputs, and have tried flipping the order of triangle vertexes in source.

First of all, you should rename "vertexes" to "vertices". There's weird stuff in your code, but the problems I could notice that won't let you see your triangle as you asked are two: Your polygon description(DxVertex) don't have color data and your input layout cannot receive color data, your input assembler needs it so it can send this data to the shaders to be able to paint your model so you can see it. I also see that you created a buffer by pointing it to your polygon data using vertexes.data() , I should assume this returns a pointer to your polygon data, but I don't see you declaring the coordinates anywhere. I see you compiled a file called pixel.hlsl and assigned it as your pixel shader so you may have some clue of what it is about. For readability purposes, try to name everything properly in your program and don't create functions inside classes or headers, do it inside a cpp file.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM