C++

[강의] 2월 10일 수업정리

k-codestudy 2025. 2. 10. 17:12

오늘 api환경에 directX를 옮기는 작업을 하였다.

 

실행 파일과 리소스 경로 설정 정리

C++ 프로젝트에서 실행 파일(EXE)이 데이터를 찾을 때 EXE가 포함된 디렉터리를 기준으로 탐색한다

즉, 실행 파일과 리소스 파일(예: 이미지, 사운드, 설정 파일 등)이 같은 폴더에 있어야 정상적으로 로드된다

 

실행 방식에 따른 리소스 경로 차이

  1. Ctrl + F5 (독립 실행)
    • 실행 중인 EXE 파일이 있는 디렉터리에서 데이터를 찾는다
    • 그러나 리소스 파일은 Visual Studio 내부의 경로를 참조할 수도 있어 불일치 문제가 발생할 수 있음.
  2. EXE 파일을 직접 실행 (더블 클릭)
    • 실행 파일과 동일한 폴더에 있는 리소스를 정상적으로 로드함
    • 따라서 최종적으로 배포할 때는 EXE와 리소스를 같은 디렉터리에 두어야 함

 

리소스 경로를 설정하는 방법

 

1. 출력 디렉터리 설정

  • 속성 → 일반 → 출력 디렉터리 → bin 폴더로 변경
  • 실행 파일이 생성되는 위치를 bin 폴더로 설정하여, 다른 파일과 통일된 경로를 유지

2. 디버그 모드에서 실행 파일 이름 변경

  • 속성 → 일반 → 대상 이름 → game_D.exe (디버그 모드에서 실행할 EXE 이름)
  • 디버그와 릴리스 버전의 EXE 파일을 명확히 구분할 수 있음

 

3. 작업 디렉터리 설정

  • 속성 → 디버깅 → 작업 디렉터리
  • 출력 디렉터리와 동일한 경로로 설정 (복사 & 붙여넣기)
  • 이렇게 하면 Visual Studio에서 실행할 때도 리소스 경로가 실제 실행 파일과 일치하여 경로 불일치 문제를 방지

 

요약

  • EXE 파일은 동일한 디렉터리에 있는 데이터 파일을 로드함
  • Visual Studio에서 실행할 때 리소스 경로가 어긋나는 문제를 방지하려면 출력 디렉터리와 작업 디렉터리를 동일하게 설정
  • 디버그/릴리스 실행 파일을 구분하기 위해 EXE 이름을 변경 (예: game_D.exe)
  • 배포 시에는 EXE와 리소스를 같은 폴더에 둬야 정상 동작
  • 이렇게 설정하면 어떤 방식으로 실행해도 리소스 경로가 일치하여 실행 시 리소스를 찾지 못하는 오류를 방지할 수 있다

 

api.h

#pragma once

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

#include "graphic.h"

class C_API
{
private:
	C_GRAPHIC m_cGraphic;
	static C_API* m_pApi;
	HINSTANCE	m_hInstance;
	HWND		m_hWnd;

private:
	static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
	LRESULT CALLBACK apiProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
	C_API() = default;

public:
	static void createApi();
	static C_API* getApi();
	static void releaseApi();

	bool init(HINSTANCE hInstance);
	void updateMsg();
};

api.cpp

#include "api.h"

C_API* C_API::m_pApi = nullptr;

void C_API::createApi()
{
    if (!m_pApi)
        m_pApi = new C_API{};
}

C_API* C_API::getApi()
{
    return m_pApi;
}

void C_API::releaseApi()
{
    if (m_pApi)
    {
        m_pApi->m_cGraphic.release();

        delete m_pApi;
        m_pApi = nullptr;
    }
}

bool C_API::init(HINSTANCE hInstance)
{
    m_hInstance = hInstance;

    WNDCLASSEXW wcex;
    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc = WndProc;
    wcex.cbClsExtra = 0;
    wcex.cbWndExtra = 0;
    wcex.hInstance = m_hInstance;
    wcex.hIcon = LoadIcon(m_hInstance, MAKEINTRESOURCE(IDI_API));
    wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
    wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wcex.lpszMenuName = 0;
    wcex.lpszClassName = L"name";
    wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

    RegisterClassExW(&wcex);

    m_hWnd = CreateWindowW(L"name", nullptr, WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, m_hInstance, nullptr);

    if (!m_hWnd)
        return FALSE;

    ShowWindow(m_hWnd, SW_SHOWDEFAULT);

    m_cGraphic.init();
    C_DX::getDx()->init(m_hWnd);
    
    return true;
}

void C_API::updateMsg()
{
    MSG msg = { 0 };
    while (WM_QUIT != msg.message)
    {
        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        else
        {
           C_DX::getDx()->Render();
        }
    }
}


LRESULT CALLBACK C_API::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    return m_pApi->apiProc(hWnd, message, wParam, lParam);
}

LRESULT C_API::apiProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_PAINT:
    {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hWnd, &ps);
        EndPaint(hWnd, &ps);
    }
    break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

dx.h

#pragma once

#include <windows.h>
#include <d3d11.h>
#include <d3dx11.h>
#include <d3dcompiler.h>
#include <xnamath.h>

#include "mesh.h"

class C_DX
{
private:
    static C_DX* m_pDx;

public:
    static void createDx();
    static C_DX* getDx();
    static void releaseDx();

private:

    struct CBNeverChanges
    {
        XMMATRIX mView;
    };

    struct CBChangeOnResize
    {
        XMMATRIX mProjection;
    };

    struct CBChangesEveryFrame
    {
        XMMATRIX mWorld;
        XMFLOAT4 vMeshColor;
    };

    HWND                                g_hWnd;
    D3D_DRIVER_TYPE                     g_driverType ;
    D3D_FEATURE_LEVEL                   g_featureLevel;
    ID3D11Device*                       g_pd3dDevice ;
    ID3D11DeviceContext*                g_pImmediateContext;
    IDXGISwapChain*                     g_pSwapChain;
    ID3D11RenderTargetView*             g_pRenderTargetView;
    ID3D11Texture2D*                    g_pDepthStencil;
    ID3D11DepthStencilView*             g_pDepthStencilView;
    ID3D11VertexShader*                 g_pVertexShader;
    ID3D11PixelShader*                  g_pPixelShader;
    ID3D11InputLayout*                  g_pVertexLayout;
    ID3D11Buffer*                       g_pCBNeverChanges;
    ID3D11Buffer*                       g_pCBChangeOnResize;
    ID3D11Buffer*                       g_pCBChangesEveryFrame;
    ID3D11SamplerState*                 g_pSamplerLinear;
    XMMATRIX                            g_World;
    XMMATRIX                            g_View;
    XMMATRIX                            g_Projection;
    XMFLOAT4                            g_vMeshColor;

    C_MESH                              m_cMesh;

private:
    C_DX() = default;
    HRESULT InitDevice();
    HRESULT CompileShaderFromFile(LPCWSTR szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3DBlob** ppBlobOut);

public:
    HRESULT createBuffer(D3D11_USAGE usage, UINT byteWidth, UINT bindFlags, const void* initData, ID3D11Buffer** ppBuffer);
    void init(HWND hWnd);
    void CleanupDevice();
    void Render();

    ID3D11Device* getDevice();
    ID3D11DeviceContext* getContext();
};

dx.cpp

#include "dx.h"

C_DX* C_DX::m_pDx = nullptr;

void C_DX::createDx()
{
    if (!m_pDx)
        m_pDx = new C_DX{};
}

C_DX* C_DX::getDx()
{
    return m_pDx;
}

void C_DX::releaseDx()
{
    if (m_pDx)
    {
        delete m_pDx;
        m_pDx = nullptr;
    }
}

void C_DX::init(HWND hWnd)
{
    g_hWnd = hWnd;
    g_driverType = D3D_DRIVER_TYPE_NULL;
    g_featureLevel = D3D_FEATURE_LEVEL_11_0;
    g_World = XMMatrixIdentity();
    g_View = XMMatrixIdentity();;
    g_Projection = XMMatrixIdentity();;
    g_vMeshColor = XMFLOAT4(0.7f, 0.7f, 0.7f, 1.0f);

    InitDevice();
}

HRESULT C_DX::CompileShaderFromFile(LPCWSTR szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3DBlob** ppBlobOut)
{
    HRESULT hr = S_OK;

    DWORD dwShaderFlags = D3DCOMPILE_ENABLE_STRICTNESS;
#if defined( DEBUG ) || defined( _DEBUG )
    dwShaderFlags |= D3DCOMPILE_DEBUG;
#endif

    ID3DBlob* pErrorBlob;
    hr = D3DX11CompileFromFile(szFileName, NULL, NULL, szEntryPoint, szShaderModel,
        dwShaderFlags, 0, NULL, ppBlobOut, &pErrorBlob, NULL);
    if (FAILED(hr))
    {
        if (pErrorBlob != NULL)
            OutputDebugStringA((char*)pErrorBlob->GetBufferPointer());
        if (pErrorBlob) pErrorBlob->Release();
        return hr;
    }
    if (pErrorBlob) pErrorBlob->Release();

    return S_OK;
}

HRESULT C_DX::InitDevice()
{
    HRESULT hr = S_OK;

    RECT rc;
    GetClientRect(g_hWnd, &rc);
    UINT width = rc.right - rc.left;
    UINT height = rc.bottom - rc.top;

    UINT createDeviceFlags = 0;
#ifdef _DEBUG
    createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif

    D3D_DRIVER_TYPE driverTypes[] =
    {
        D3D_DRIVER_TYPE_HARDWARE,
        D3D_DRIVER_TYPE_WARP,
        D3D_DRIVER_TYPE_REFERENCE,
    };
    UINT numDriverTypes = ARRAYSIZE(driverTypes);

    D3D_FEATURE_LEVEL featureLevels[] =
    {
        D3D_FEATURE_LEVEL_11_0,
        D3D_FEATURE_LEVEL_10_1,
        D3D_FEATURE_LEVEL_10_0,
    };
    UINT numFeatureLevels = ARRAYSIZE(featureLevels);

    DXGI_SWAP_CHAIN_DESC sd;
    ZeroMemory(&sd, sizeof(sd));
    sd.BufferCount = 1;
    sd.BufferDesc.Width = width;
    sd.BufferDesc.Height = height;
    sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    sd.BufferDesc.RefreshRate.Numerator = 60;
    sd.BufferDesc.RefreshRate.Denominator = 1;
    sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    sd.OutputWindow = g_hWnd;
    sd.SampleDesc.Count = 1;
    sd.SampleDesc.Quality = 0;
    sd.Windowed = TRUE;

    for (UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++)
    {
        g_driverType = driverTypes[driverTypeIndex];
        hr = D3D11CreateDeviceAndSwapChain(NULL, g_driverType, NULL, createDeviceFlags, featureLevels, numFeatureLevels,
            D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &g_featureLevel, &g_pImmediateContext);
        if (SUCCEEDED(hr))
            break;
    }
    if (FAILED(hr))
        return hr;

    ID3D11Texture2D* pBackBuffer = NULL;
    hr = g_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
    if (FAILED(hr))
        return hr;

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

    D3D11_TEXTURE2D_DESC descDepth;
    ZeroMemory(&descDepth, sizeof(descDepth));
    descDepth.Width = width;
    descDepth.Height = height;
    descDepth.MipLevels = 1;
    descDepth.ArraySize = 1;
    descDepth.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
    descDepth.SampleDesc.Count = 1;
    descDepth.SampleDesc.Quality = 0;
    descDepth.Usage = D3D11_USAGE_DEFAULT;
    descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL;
    descDepth.CPUAccessFlags = 0;
    descDepth.MiscFlags = 0;
    hr = g_pd3dDevice->CreateTexture2D(&descDepth, NULL, &g_pDepthStencil);
    if (FAILED(hr))
        return hr;
    
    D3D11_DEPTH_STENCIL_VIEW_DESC descDSV;
    ZeroMemory(&descDSV, sizeof(descDSV));
    descDSV.Format = descDepth.Format;
    descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
    descDSV.Texture2D.MipSlice = 0;
    hr = g_pd3dDevice->CreateDepthStencilView(g_pDepthStencil, &descDSV, &g_pDepthStencilView);
    if (FAILED(hr))
        return hr;

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

    D3D11_VIEWPORT vp;
    vp.Width = (FLOAT)width;
    vp.Height = (FLOAT)height;
    vp.MinDepth = 0.0f;
    vp.MaxDepth = 1.0f;
    vp.TopLeftX = 0;
    vp.TopLeftY = 0;
    g_pImmediateContext->RSSetViewports(1, &vp);

    ID3DBlob* pVSBlob = NULL;
    hr = CompileShaderFromFile(L"data\\Tutorial07.fx", "VS", "vs_4_0", &pVSBlob);
    if (FAILED(hr))
    {
        MessageBox(NULL,
            L"The FX file cannot be compiled.  Please run this executable from the directory that contains the FX file.", L"Error", MB_OK);
        return hr;
    }

    hr = g_pd3dDevice->CreateVertexShader(pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), NULL, &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 },
        { "TEXCOORD", 0, DXGI_FORMAT_R32G32_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 = NULL;
    hr = CompileShaderFromFile(L"data\\Tutorial07.fx", "PS", "ps_4_0", &pPSBlob);
    if (FAILED(hr))
    {
        MessageBox(NULL,
            L"The FX file cannot be compiled.  Please run this executable from the directory that contains the FX file.", L"Error", MB_OK);
        return hr;
    }

    // Create the pixel shader
    hr = g_pd3dDevice->CreatePixelShader(pPSBlob->GetBufferPointer(), pPSBlob->GetBufferSize(), NULL, &g_pPixelShader);
    pPSBlob->Release();
    if (FAILED(hr))
        return hr;

    if (FAILED(createBuffer(D3D11_USAGE_DEFAULT, sizeof(CBNeverChanges), D3D11_BIND_CONSTANT_BUFFER, nullptr, &g_pCBNeverChanges)))
        return hr;
    if (FAILED(createBuffer(D3D11_USAGE_DEFAULT, sizeof(CBChangeOnResize), D3D11_BIND_CONSTANT_BUFFER, nullptr, &g_pCBChangeOnResize)))
        return hr;
    if (FAILED(createBuffer(D3D11_USAGE_DEFAULT, sizeof(CBChangesEveryFrame), D3D11_BIND_CONSTANT_BUFFER, nullptr, &g_pCBChangesEveryFrame)))
        return hr;

    if (FAILED(hr))
        return hr;

    D3D11_SAMPLER_DESC sampDesc;
    ZeroMemory(&sampDesc, sizeof(sampDesc));
    sampDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
    sampDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
    sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
    sampDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
    sampDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
    sampDesc.MinLOD = 0;
    sampDesc.MaxLOD = D3D11_FLOAT32_MAX;
    hr = g_pd3dDevice->CreateSamplerState(&sampDesc, &g_pSamplerLinear);
    if (FAILED(hr))
        return hr;

    g_World = XMMatrixIdentity();

    XMVECTOR Eye = XMVectorSet(0.0f, 3.0f, -6.0f, 0.0f);
    XMVECTOR At = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);
    XMVECTOR Up = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);
    g_View = XMMatrixLookAtLH(Eye, At, Up);

    CBNeverChanges cbNeverChanges;
    cbNeverChanges.mView = XMMatrixTranspose(g_View);
    g_pImmediateContext->UpdateSubresource(g_pCBNeverChanges, 0, NULL, &cbNeverChanges, 0, 0);

    g_Projection = XMMatrixPerspectiveFovLH(XM_PIDIV4, width / (FLOAT)height, 0.01f, 100.0f);

    CBChangeOnResize cbChangesOnResize;
    cbChangesOnResize.mProjection = XMMatrixTranspose(g_Projection);
    g_pImmediateContext->UpdateSubresource(g_pCBChangeOnResize, 0, NULL, &cbChangesOnResize, 0, 0);

    m_cMesh.load(L"cube.data");
    m_cMesh.setMesh();

    return S_OK;
}

HRESULT C_DX::createBuffer(D3D11_USAGE usage, UINT byteWidth, UINT bindFlags, const void* initData, ID3D11Buffer** ppBuffer)
{
    D3D11_BUFFER_DESC bd{ byteWidth  , usage  , bindFlags  , 0,0,0};
    D3D11_SUBRESOURCE_DATA subResource{ initData ,0,0 };
    D3D11_SUBRESOURCE_DATA* pInit{};
    if (initData)
        pInit = &subResource;

    return g_pd3dDevice->CreateBuffer(&bd, pInit, ppBuffer);
}

ID3D11Device* C_DX::getDevice()
{
    return g_pd3dDevice;
}

ID3D11DeviceContext* C_DX::getContext()
{
    return g_pImmediateContext;
}

void C_DX::CleanupDevice()
{
    m_cMesh.release();
    if (g_pImmediateContext) g_pImmediateContext->ClearState();
    if (g_pSamplerLinear) g_pSamplerLinear->Release();
    if (g_pCBNeverChanges) g_pCBNeverChanges->Release();
    if (g_pCBChangeOnResize) g_pCBChangeOnResize->Release();
    if (g_pCBChangesEveryFrame) g_pCBChangesEveryFrame->Release();
    if (g_pVertexLayout) g_pVertexLayout->Release();
    if (g_pVertexShader) g_pVertexShader->Release();
    if (g_pPixelShader) g_pPixelShader->Release();
    if (g_pDepthStencil) g_pDepthStencil->Release();
    if (g_pDepthStencilView) g_pDepthStencilView->Release();
    if (g_pRenderTargetView) g_pRenderTargetView->Release();
    if (g_pSwapChain) g_pSwapChain->Release();
    if (g_pImmediateContext) g_pImmediateContext->Release();
    if (g_pd3dDevice) g_pd3dDevice->Release();
}

void C_DX::Render()
{
    static float t = 0.0f;
    if (g_driverType == D3D_DRIVER_TYPE_REFERENCE)
    {
        t += (float)XM_PI * 0.0125f;
    }
    else
    {
        static DWORD dwTimeStart = 0;
        DWORD dwTimeCur = GetTickCount();
        if (dwTimeStart == 0)
            dwTimeStart = dwTimeCur;
        t = (dwTimeCur - dwTimeStart) / 1000.0f;
    }

    g_World = XMMatrixRotationY(t);

    g_vMeshColor.x = (sinf(t * 1.0f) + 1.0f) * 0.5f;
    g_vMeshColor.y = (cosf(t * 3.0f) + 1.0f) * 0.5f;
    g_vMeshColor.z = (sinf(t * 5.0f) + 1.0f) * 0.5f;

    float ClearColor[4] = { 0.0f, 0.125f, 0.3f, 1.0f }; // red, green, blue, alpha
    g_pImmediateContext->ClearRenderTargetView(g_pRenderTargetView, ClearColor);
    
    g_pImmediateContext->ClearDepthStencilView(g_pDepthStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0);

    CBChangesEveryFrame cb;
    cb.mWorld = XMMatrixTranspose(g_World);
    cb.vMeshColor = g_vMeshColor;
    g_pImmediateContext->UpdateSubresource(g_pCBChangesEveryFrame, 0, NULL, &cb, 0, 0);

    g_pImmediateContext->VSSetShader(g_pVertexShader, NULL, 0);
    g_pImmediateContext->VSSetConstantBuffers(0, 1, &g_pCBNeverChanges);
    g_pImmediateContext->VSSetConstantBuffers(1, 1, &g_pCBChangeOnResize);
    g_pImmediateContext->VSSetConstantBuffers(2, 1, &g_pCBChangesEveryFrame);
    g_pImmediateContext->PSSetShader(g_pPixelShader, NULL, 0);
    g_pImmediateContext->PSSetConstantBuffers(2, 1, &g_pCBChangesEveryFrame);
    g_pImmediateContext->PSSetSamplers(0, 1, &g_pSamplerLinear);
    m_cMesh.render();

    g_pSwapChain->Present(0, 0);
}

graphic.h

#pragma once

#include "dx.h"

class C_GRAPHIC
{
private:


public:
	void init();
	void release();
};

graphic.cpp

#include "graphic.h"

void C_GRAPHIC::init()
{
	C_DX::createDx();
}

void C_GRAPHIC::release()
{
	C_DX::getDx()->CleanupDevice();
	C_DX::releaseDx();
}

mesh.h

#pragma once

#include <d3d11.h>
#include <d3dx11.h>
#include <xnamath.h>

class C_MESH
{
private:
	struct SimpleVertex
	{
		XMFLOAT3 Pos;
		XMFLOAT2 Tex;
	};

private:
	ID3D11Buffer* g_pVertexBuffer;
	ID3D11Buffer* g_pIndexBuffer;
	ID3D11ShaderResourceView* g_pTextureRV;

public:
	HRESULT load(LPCWSTR strFileName);
	void setMesh();
	void release();
	void render();
};

mesh.cpp

#include "dx.h"
#include "mesh.h"

HRESULT C_MESH::load(LPCWSTR strFileName)
{
   SimpleVertex vertices[] =
    {
        { XMFLOAT3(-1.0f, 1.0f, -1.0f), XMFLOAT2(0.0f, 0.0f) },
        { XMFLOAT3(1.0f, 1.0f, -1.0f), XMFLOAT2(1.0f, 0.0f) },
        { XMFLOAT3(1.0f, 1.0f, 1.0f), XMFLOAT2(1.0f, 1.0f) },
        { XMFLOAT3(-1.0f, 1.0f, 1.0f), XMFLOAT2(0.0f, 1.0f) },

        { XMFLOAT3(-1.0f, -1.0f, -1.0f), XMFLOAT2(0.0f, 0.0f) },
        { XMFLOAT3(1.0f, -1.0f, -1.0f), XMFLOAT2(1.0f, 0.0f) },
        { XMFLOAT3(1.0f, -1.0f, 1.0f), XMFLOAT2(1.0f, 1.0f) },
        { XMFLOAT3(-1.0f, -1.0f, 1.0f), XMFLOAT2(0.0f, 1.0f) },

        { XMFLOAT3(-1.0f, -1.0f, 1.0f), XMFLOAT2(0.0f, 0.0f) },
        { XMFLOAT3(-1.0f, -1.0f, -1.0f), XMFLOAT2(1.0f, 0.0f) },
        { XMFLOAT3(-1.0f, 1.0f, -1.0f), XMFLOAT2(1.0f, 1.0f) },
        { XMFLOAT3(-1.0f, 1.0f, 1.0f), XMFLOAT2(0.0f, 1.0f) },

        { XMFLOAT3(1.0f, -1.0f, 1.0f), XMFLOAT2(0.0f, 0.0f) },
        { XMFLOAT3(1.0f, -1.0f, -1.0f), XMFLOAT2(1.0f, 0.0f) },
        { XMFLOAT3(1.0f, 1.0f, -1.0f), XMFLOAT2(1.0f, 1.0f) },
        { XMFLOAT3(1.0f, 1.0f, 1.0f), XMFLOAT2(0.0f, 1.0f) },

        { XMFLOAT3(-1.0f, -1.0f, -1.0f), XMFLOAT2(0.0f, 0.0f) },
        { XMFLOAT3(1.0f, -1.0f, -1.0f), XMFLOAT2(1.0f, 0.0f) },
        { XMFLOAT3(1.0f, 1.0f, -1.0f), XMFLOAT2(1.0f, 1.0f) },
        { XMFLOAT3(-1.0f, 1.0f, -1.0f), XMFLOAT2(0.0f, 1.0f) },

        { XMFLOAT3(-1.0f, -1.0f, 1.0f), XMFLOAT2(0.0f, 0.0f) },
        { XMFLOAT3(1.0f, -1.0f, 1.0f), XMFLOAT2(1.0f, 0.0f) },
        { XMFLOAT3(1.0f, 1.0f, 1.0f), XMFLOAT2(1.0f, 1.0f) },
        { XMFLOAT3(-1.0f, 1.0f, 1.0f), XMFLOAT2(0.0f, 1.0f) },
    };
    WORD indices[] =
    {
        3,1,0,
        2,1,3,

        6,4,5,
        7,4,6,

        11,9,8,
        10,9,11,

        14,12,13,
        15,12,14,

        19,17,16,
        18,17,19,

        22,20,21,
        23,20,22
    };


    if (FAILED(D3DX11CreateShaderResourceViewFromFile(C_DX::getDx()->getDevice(), L"data\\seafloor.dds", NULL, NULL, &g_pTextureRV, NULL)))
        return S_FALSE;

    if (FAILED(C_DX::getDx()->createBuffer(D3D11_USAGE_DEFAULT, sizeof(SimpleVertex) * 24, D3D11_BIND_VERTEX_BUFFER, vertices, &g_pVertexBuffer)))
        return S_FALSE;

    if (FAILED(C_DX::getDx()->createBuffer(D3D11_USAGE_DEFAULT, sizeof(WORD) * 36, D3D11_BIND_INDEX_BUFFER, indices, &g_pIndexBuffer)))
        return S_FALSE;

    return S_OK;

}

void C_MESH::setMesh()
{
    UINT stride = sizeof(SimpleVertex);
    UINT offset = 0;
    C_DX::getDx()->getContext()->IASetVertexBuffers(0, 1, &g_pVertexBuffer, &stride, &offset);

    // Set index buffer
    C_DX::getDx()->getContext()->IASetIndexBuffer(g_pIndexBuffer, DXGI_FORMAT_R16_UINT, 0);

    // Set primitive topology
    C_DX::getDx()->getContext()->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
}

void C_MESH::release()
{
    if (g_pTextureRV) g_pTextureRV->Release();
    if (g_pVertexBuffer) g_pVertexBuffer->Release();
    if (g_pIndexBuffer) g_pIndexBuffer->Release();

}

void C_MESH::render()
{
    C_DX::getDx()->getContext()->PSSetShaderResources(0, 1, &g_pTextureRV);
    C_DX::getDx()->getContext()->DrawIndexed(36, 0, 0);
}

main.cpp

#include "framework.h"
#include "api.h"

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);
    UNREFERENCED_PARAMETER(nCmdShow);

    C_API::createApi();
    C_API::getApi()->init(hInstance);
    C_API::getApi()->updateMsg();
    C_API::releaseApi();
}