文字が描画できない
解決したいこと
文字をマップの上に描画したい
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