watamochi517221
@watamochi517221

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

文字が描画できない

解決したいこと

文字をマップの上に描画したい

visualstudioでDirectXを使って2Dゲームを作っています。
文字が描画されず見えません。
解決方法を教えてください

発生している問題・エラー

文字が描画されない

例)

エラーコードは特にないです。

該当するソースコード

#include <windows.h>
#include <iostream>
#include <tchar.h>
#include <d3d11.h>
#include <d3dcompiler.h>
#include <d2d1.h>
#include <dwrite.h>

#pragma comment(lib, "d3d11.lib")
#pragma comment(lib, "D3DCompiler.lib")
#pragma comment(lib, "d2d1.lib")
#pragma comment(lib, "dwrite.lib")

#include "Game.h"

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void DrawTile(int x, int y, float w, float h, float r, float g, float b);

void InitializeDirect2D(HWND hwnd);
void RenderText();
void Text(const wchar_t* text, float x, float y, float size);

// DirectX 関連のグローバル変数
ID3D11Device* g_pd3dDevice = nullptr;
ID3D11DeviceContext* g_pImmediateContext = nullptr;
IDXGISwapChain* g_pSwapChain = nullptr;
ID3D11RenderTargetView* g_pRenderTargetView = nullptr;
ID3D11InputLayout* g_pVertexLayout = nullptr;
ID3D11Buffer* g_pVertexBuffer = nullptr;
ID3D11VertexShader* g_pVertexShader = nullptr;
ID3D11PixelShader* g_pPixelShader = nullptr;

// グローバル変数
ID2D1Factory* pFactory = nullptr;
IDWriteFactory* pWriteFactory = nullptr;
ID2D1HwndRenderTarget* pRenderTarget = nullptr;
IDWriteTextFormat* pTextFormat = nullptr;
ID2D1SolidColorBrush* pBrush = nullptr;


// ウィンドウのサイズに関するグローバル変数
int windowWidth = 1980; // 初期値
int windowHeight = 1280; // 初期値

// 頂点データ構造体
struct SimpleVertex
{
    float x, y, z;
    float r, g, b;
};

// 頂点シェーダーのソースコード
const char* g_VS =
"struct VS_INPUT { float4 pos : POSITION; float4 color : COLOR; };"
"struct PS_INPUT { float4 pos : SV_POSITION; float4 color : COLOR; };"
"PS_INPUT main(VS_INPUT input) {"
"    PS_INPUT output;"
"    output.pos = input.pos;"
"    output.color = input.color;"
"    return output;"
"}";

// ピクセルシェーダーのソースコード
const char* g_PS =
"struct PS_INPUT { float4 pos : SV_POSITION; float4 color : COLOR; };"
"float4 main(PS_INPUT input) : SV_Target {"
"    return input.color;"
"}";

// マップデータ
const int MAP_WIDTH = 10;
const int MAP_HEIGHT = 10;

int map[MAP_WIDTH][MAP_HEIGHT] = {
    {1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
    {1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
    {1, 0, 2, 2, 0, 0, 0, 2, 0, 1},
    {1, 0, 2, 2, 0, 0, 0, 2, 0, 1},
    {1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
    {1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
    {1, 0, 0, 0, 0, 0, 2, 0, 0, 1},
    {1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
    {1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
    {1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
};

const float tileSize = 0.1f;

// Direct3D の初期化関数
HRESULT InitD3D(HWND hWnd)
{
    HRESULT hr = S_OK;

    // スワップチェインの設定
    DXGI_SWAP_CHAIN_DESC sd = {};
    sd.BufferCount = 1;
    sd.BufferDesc.Width = windowWidth;
    sd.BufferDesc.Height = windowHeight;
    sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    sd.OutputWindow = hWnd;
    sd.SampleDesc.Count = 1;
    sd.SampleDesc.Quality = 0;
    sd.Windowed = FALSE;
    sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;

    // デバイス、スワップチェイン、コンテキストの作成
    hr = D3D11CreateDeviceAndSwapChain(
        nullptr,
        D3D_DRIVER_TYPE_HARDWARE,
        nullptr,
        0,
        nullptr,
        0,
        D3D11_SDK_VERSION,
        &sd,
        &g_pSwapChain,
        &g_pd3dDevice,
        nullptr,
        &g_pImmediateContext
    );
    if (FAILED(hr))
        return hr;

    // レンダーターゲットビューの作成
    ID3D11Texture2D* pBackBuffer = nullptr;
    hr = g_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
    if (FAILED(hr))
        return hr;

    hr = g_pd3dDevice->CreateRenderTargetView(pBackBuffer, nullptr, &g_pRenderTargetView);
    pBackBuffer->Release();
    if (FAILED(hr))
        return hr;

    g_pImmediateContext->OMSetRenderTargets(1, &g_pRenderTargetView, nullptr);

    // ビューポートの設定
    D3D11_VIEWPORT vp = {};
    vp.Width = static_cast<float>(windowWidth);
    vp.Height = static_cast<float>(windowHeight);
    vp.MinDepth = 0.0f;
    vp.MaxDepth = 1.0f;
    g_pImmediateContext->RSSetViewports(1, &vp);

    // 頂点シェーダーのコンパイルと作成
    ID3DBlob* pVSBlob = nullptr;
    hr = D3DCompile(g_VS, strlen(g_VS), nullptr, nullptr, nullptr, "main", "vs_4_0", 0, 0, &pVSBlob, nullptr);
    if (FAILED(hr))
        return hr;

    hr = g_pd3dDevice->CreateVertexShader(pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), nullptr, &g_pVertexShader);
    if (FAILED(hr))
    {
        pVSBlob->Release();
        return hr;
    }

    // 入力レイアウトの作成
    D3D11_INPUT_ELEMENT_DESC layout[] =
    {
        { "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 }
    };
    UINT numElements = ARRAYSIZE(layout);

    hr = g_pd3dDevice->CreateInputLayout(layout, numElements, pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), &g_pVertexLayout);
    pVSBlob->Release();
    if (FAILED(hr))
        return hr;

    g_pImmediateContext->IASetInputLayout(g_pVertexLayout);

    // ピクセルシェーダーのコンパイルと作成
    ID3DBlob* pPSBlob = nullptr;
    hr = D3DCompile(g_PS, strlen(g_PS), nullptr, nullptr, nullptr, "main", "ps_4_0", 0, 0, &pPSBlob, nullptr);
    if (FAILED(hr))
        return hr;

    hr = g_pd3dDevice->CreatePixelShader(pPSBlob->GetBufferPointer(), pPSBlob->GetBufferSize(), nullptr, &g_pPixelShader);
    pPSBlob->Release();
    if (FAILED(hr))
        return hr;

    // 初期描画用のバッファを作成
    return S_OK;
}

// 描画関数
void Render()
{
    // バックバッファのクリア
    float ClearColor[4] = { 0.0f, 0.125f, 0.3f, 1.0f };
    g_pImmediateContext->ClearRenderTargetView(g_pRenderTargetView, ClearColor);

    // 頂点シェーダーとピクセルシェーダーのセット
    g_pImmediateContext->VSSetShader(g_pVertexShader, nullptr, 0);
    g_pImmediateContext->PSSetShader(g_pPixelShader, nullptr, 0);

    // ウィンドウのアスペクト比を計算
    float aspectRatio = static_cast<float>(windowWidth) / static_cast<float>(windowHeight);

    // 正方形を保つためにタイルサイズを調整
    float adjustedTileWidth = tileSize;
    float adjustedTileHeight = tileSize;

    if (aspectRatio > 1.0f) {
        adjustedTileWidth = tileSize / aspectRatio;
    }
    else {
        adjustedTileHeight = tileSize * aspectRatio;
    }

    // マップのタイルを描画
    for (int y = 0; y < MAP_HEIGHT; ++y)
    {
        for (int x = 0; x < MAP_WIDTH; ++x)
        {
            float r = 0.0f, g = 0.0f, b = 0.0f;
            if (map[x][y] == 0) b = 1.0f;  // 青
            else if (map[x][y] == 1) g = 1.0f;  // 緑
            else if (map[x][y] == 2) r = 1.0f;  // 赤

            DrawTile(x, y, adjustedTileWidth, adjustedTileHeight, r, g, b);
        }
    }


    Player(adjustedTileWidth, adjustedTileHeight);

    // バックバッファを前面に表示
    g_pSwapChain->Present(0, 0);
}


// 頂点バッファをセットアップし、タイルを描画する関数
void DrawTile(int x, int y, float w, float h, float r, float g, float b)
{
    float adjustedX = (x * w) - 1.0f;
    float adjustedY = 1.0f - (y * h);

    SimpleVertex vertices[] =
    {
        { adjustedX, adjustedY - h, 0.0f, r, g, b },  // 左下
        { adjustedX, adjustedY, 0.0f, r, g, b },  // 左上
        { adjustedX + w, adjustedY - h, 0.0f, r, g, b },  // 右下
        { adjustedX + w, adjustedY, 0.0f, r, g, b },  // 右上
    };

    // バッファの設定
    D3D11_BUFFER_DESC bd = {};
    bd.Usage = D3D11_USAGE_DEFAULT;
    bd.ByteWidth = sizeof(vertices);
    bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
    bd.CPUAccessFlags = 0;

    D3D11_SUBRESOURCE_DATA InitData = {};
    InitData.pSysMem = vertices;
    ID3D11Buffer* pVertexBuffer = nullptr;
    g_pd3dDevice->CreateBuffer(&bd, &InitData, &pVertexBuffer);

    // バッファをセット
    UINT stride = sizeof(SimpleVertex);
    UINT offset = 0;
    g_pImmediateContext->IASetVertexBuffers(0, 1, &pVertexBuffer, &stride, &offset);
    g_pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);

    // タイルの描画
    g_pImmediateContext->Draw(4, 0);

    // バッファを解放
    pVertexBuffer->Release();
}

// メイン関数
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    // ウィンドウクラスの設定
    WNDCLASSEX wc = {};
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WndProc;
    wc.hInstance = hInstance;
    wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wc.lpszClassName = _T("D3DWindowClass");

    RegisterClassEx(&wc);

    // ウィンドウの作成
    HWND hWnd = CreateWindow(
        _T("D3DWindowClass"),
        _T("Direct3D Sample"),
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT,
        windowWidth, windowHeight,
        nullptr, nullptr, hInstance, nullptr
    );

    if (!hWnd)
        return 0;

    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);

    // Direct3D の初期化
    if (FAILED(InitD3D(hWnd)))
        return 0;
 

    // メインループ
    MSG msg = {};
    while (WM_QUIT != msg.message)
    {
        if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        else
        {
            Render();
            RenderText();
            Intervar();
        }
    }

    // クリーンアップ
    if (g_pImmediateContext) g_pImmediateContext->ClearState();
    if (g_pRenderTargetView) g_pRenderTargetView->Release();
    if (g_pSwapChain) g_pSwapChain->Release();
    if (g_pd3dDevice) g_pd3dDevice->Release();
    if (g_pImmediateContext) g_pImmediateContext->Release();
    if (g_pVertexLayout) g_pVertexLayout->Release();
    if (g_pVertexBuffer) g_pVertexBuffer->Release();
    if (g_pVertexShader) g_pVertexShader->Release();
    if (g_pPixelShader) g_pPixelShader->Release();

    if (pBrush) pBrush->Release();
    if (pTextFormat) pTextFormat->Release();
    if (pRenderTarget) pRenderTarget->Release();
    if (pWriteFactory) pWriteFactory->Release();
    if (pFactory) pFactory->Release();

    return static_cast<int>(msg.wParam);
}

// ウィンドウプロシージャ
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
    case WM_SIZE:
        windowWidth = LOWORD(lParam);
        windowHeight = HIWORD(lParam);

        // ビューポートのサイズを更新
        if (g_pImmediateContext)
        {
            D3D11_VIEWPORT vp = {};
            vp.Width = static_cast<float>(windowWidth);
            vp.Height = static_cast<float>(windowHeight);
            vp.MinDepth = 0.0f;
            vp.MaxDepth = 1.0f;
            g_pImmediateContext->RSSetViewports(1, &vp);
        }
        break;
    case WM_KEYDOWN:

        Key(wParam);
        break;
    case WM_CREATE:
        InitializeDirect2D(hWnd);
        break;
    case WM_PAINT:

        ValidateRect(hWnd, nullptr);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hWnd, msg, wParam, lParam);
}

void InitializeDirect2D(HWND hwnd)
{
    D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &pFactory);
    DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), reinterpret_cast<IUnknown**>(&pWriteFactory));

    RECT rc;
    GetClientRect(hwnd, &rc);

    D2D1_SIZE_U size = D2D1::SizeU(static_cast<UINT32>(rc.right - rc.left), static_cast<UINT32>(rc.bottom - rc.top));

    HRESULT hr = pFactory->CreateHwndRenderTarget(
        D2D1::RenderTargetProperties(),
        D2D1::HwndRenderTargetProperties(hwnd, size),
        &pRenderTarget
    );

    if (SUCCEEDED(hr))
    {
        pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Black), &pBrush);
    }
}

// テキストの描画
void RenderText()
{
    // テキストの描画を行うために必要な初期化があるか確認
    if (!pRenderTarget) {
        return;
    }

    // レンダーターゲットの開始
    pRenderTarget->BeginDraw();

    // 描画するテキストの指定
    Text(L"Hello, DirectX 11!", 100, 100, 32.0f); // カスタム関数で描画
    Text(L"This is a second line!", 100, 150, 32.0f); // カスタム関数で描画

    // 描画の終了
    pRenderTarget->EndDraw();
}


// テキストを描画するカスタム関数
void Text(const wchar_t* text, float x, float y, float size)
{
    // フォントの設定
    if (!pTextFormat) {
        // フォント形式の作成
        pWriteFactory->CreateTextFormat(
            L"Arial",
            nullptr,
            DWRITE_FONT_WEIGHT_NORMAL,
            DWRITE_FONT_STYLE_NORMAL,
            DWRITE_FONT_STRETCH_NORMAL,
            size,
            L"ja-JP", // ロケール
            &pTextFormat);
    }

    // ブラシの設定
    if (!pBrush) {
        pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::White), &pBrush);
    }

    // テキストの描画
    pRenderTarget->DrawText(
        text,
        wcslen(text),
        pTextFormat,
        D2D1::RectF(x, y, windowWidth, windowHeight),
        pBrush);
}

自分で試したこと

ほとんどがchatGptで出力しながらダメなところを修正していました。
描画の順番を変えたりしてみました。

0

1Answer

Direct3DSample.png
C#で同じコードを書いてみましたが、添付画像と紺一色の表示を交互に行っているように見えました。
今のコードだとRenderとRenderTextで描画している対象が別ものになっているように見えます。

0Like

Your answer might help someone💌