공부 중 메모/DirectX

3. VertexBuffer, IndexBuffer

라이피 (Lypi) 2018. 12. 18. 19:35
반응형

Vertex Buffer

  일단 아래와 같은 쉐이더 파일을 라이브러리 혹은 샘플 폴더에 만들자.
  # 쉐이더 코드는 txt로 적어도 아무런 상관이 없다. 
  # 구문 강조 기능을 위해서 확장자를 hlsl로 했다면 설정에서 빌드에서 제외를 해주는 것이 정신건강에 이롭다.
  # 픽셀 쉐이더에서 하얀색으로 지정했다.

VS.txt

float4 VS(in float4 p : POSITION) : SV_POSITION
{
	return p;
}

PS.txt

float4 PS(in float4 p : SV_POSITION) : SV_Target
{
	return float4(1.0f, 1.0f, 1.0f, 1.0f);
}


# 아래와 같이 코드를 작성하면 화면에 사각형이 그려진다.
  #쉐이더 파일의 경로에 주의할 것.
  #T를 누르면 토폴로지가 바뀌도록 해뒀다.

sample.h 업데이트

#pragma once
#pragma comment(lib, "TLib.lib")

#include "zCore.h"

namespace Lypi
{
	struct Point3
	{
		float x;
		float y;
		float z;
	};


	class Sample : public zCore
	{
		//--------------------------------------------------------------------------------------
		// 버텍스 버퍼 및 레이아웃
		//--------------------------------------------------------------------------------------
		ID3D11Buffer*         m_pVertexBuffer;    //정점 버퍼 인터페이스
		ID3D11InputLayout*	  m_pVertexLayout;    //정점 레이아웃 인터페이스
		
		//--------------------------------------------------------------------------------------
		 // 버텍스 및 픽셀 쉐이더
		 //--------------------------------------------------------------------------------------
		ID3D11VertexShader*     m_pVS;   //정점 쉐이더 인터페이스
		ID3D11PixelShader*      m_pPS;	 //픽셀 쉐이더 인터페이스

	public:
		//--------------------------------------------------------------------------------------
		// 정점 버퍼 생성
		//--------------------------------------------------------------------------------------
		HRESULT		CreateVertexBuffer();
		//--------------------------------------------------------------------------------------
		// 정점 및 픽쉘 쉐이더 로딩 및 생성
		//--------------------------------------------------------------------------------------
		HRESULT		LoadShaderAndInputLayout();

	public:
		bool Init();
		bool Frame();
		bool Render();
		bool Release();

	public:
		Sample(LPCTSTR LWndName);
		virtual ~Sample();
	};

}

sample.cpp 업데이트

#include "sample.h"

namespace Lypi
{
	Sample::Sample(LPCTSTR LWndName) : zCore(LWndName)
	{
		m_pVertexLayout = NULL;
		m_pVertexBuffer = NULL;
		m_pVS = NULL;
		m_pPS = NULL;

		m_PrimType = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
	}

	HRESULT Sample::CreateVertexBuffer()
	{
		HRESULT hr = S_OK;

		//시계 방향으로 지정할 것.
		Point3 vertices[] =
		{
			{ -0.5f, +0.5f, 0.5f },
			{ +0.5f, +0.5f, 0.5f },
			{ +0.5f, -0.5f, 0.5f },

			{ +0.5f, -0.5f, 0.5f },
			{ -0.5f, -0.5f, 0.5f },
			{ -0.5f, +0.5f, 0.5f },
		};

		D3D11_BUFFER_DESC bd;
		ZeroMemory(&bd, sizeof(D3D11_BUFFER_DESC));
		bd.ByteWidth = sizeof(Point3) * (sizeof(vertices) / sizeof(vertices[0]));	  // 버퍼 크기 지정
		bd.Usage = D3D11_USAGE_DEFAULT;					                              // GPU에서만 읽고쓰기 가능
		bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;	                                  // 버퍼의 용도를 정점 버퍼로 지정

		D3D11_SUBRESOURCE_DATA InitData;
		ZeroMemory(&InitData, sizeof(D3D11_SUBRESOURCE_DATA));
		InitData.pSysMem = vertices;

		return g_pD3dDevice->CreateBuffer(&bd, &InitData, &m_pVertexBuffer);
	}

	HRESULT Sample::LoadShaderAndInputLayout()
	{
		HRESULT hr = S_OK;

		DWORD dwShaderFlags = D3DCOMPILE_ENABLE_STRICTNESS;

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

		ID3DBlob* pVSBuf = NULL;
		V_FRETURN(D3DX11CompileFromFile(L"../../INPUT/DATA/Shader/sample/VS.hlsl", NULL, NULL, 
                                        "VS", "vs_5_0", dwShaderFlags, NULL, NULL, &pVSBuf, NULL, NULL));
		V_FRETURN(g_pD3dDevice->CreateVertexShader((DWORD*)pVSBuf->GetBufferPointer(), pVSBuf->GetBufferSize(), NULL, &m_pVS));

		SIZE_T vsSize = pVSBuf->GetBufferSize();

		ID3DBlob* pPSBuf = NULL;
		V_FRETURN(D3DX11CompileFromFile(L"../../INPUT/DATA/Shader/sample/PS.hlsl", NULL, NULL, 
                                        "PS", "ps_5_0", dwShaderFlags, NULL, NULL, &pPSBuf, NULL, NULL));
		V_FRETURN(g_pD3dDevice->CreatePixelShader((DWORD*)pPSBuf->GetBufferPointer(), pPSBuf->GetBufferSize(), NULL, &m_pPS));

		SIZE_T psSize = pPSBuf->GetBufferSize();


		const D3D11_INPUT_ELEMENT_DESC layout[] =
		{
			//정점쉐이더안의 POSITION시멘틱의 의미를 지정.
			{ "POSITION",  0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0,  D3D11_INPUT_PER_VERTEX_DATA, 0 },
		};

		V_FRETURN(g_pD3dDevice->CreateInputLayout(layout, 1, pVSBuf->GetBufferPointer(), vsSize, &m_pVertexLayout));

		SAFE_RELEASE(pVSBuf);
		SAFE_RELEASE(pPSBuf);
		return hr;
	}

	bool Sample::Init()
	{
		if (FAILED(CreateVertexBuffer()))
		{
			MessageBox(0, _T("CreateTrangle1  실패"), _T("Fatal error"), MB_OK);
			return false;
		}
		if (FAILED(LoadShaderAndInputLayout()))
		{
			MessageBox(0, _T("CreateTrangle2  실패"), _T("Fatal error"), MB_OK);
			return false;
		}
		return true;
	}

	bool Sample::Frame()
	{
		if (I_Input.IsKeyDownOnce(DIK_T)) { 
			(m_PrimType+1 > 5) ? (m_PrimType = 1) : (m_PrimType += 1);
		}
		return true;
	}

	bool Sample::Render()
	{
		m_Font.SetAlignment(DWRITE_TEXT_ALIGNMENT_CENTER, DWRITE_PARAGRAPH_ALIGNMENT_NEAR);
		m_Font.SetTextColor(ColorF(1.0f, 1.0f, 1.0f, 1.0f));
		m_Font.SetlayoutRt(0, 0, (FLOAT)g_rtClient.right, (FLOAT)g_rtClient.bottom);

		TCHAR TopologyBuffer[256];
		ZeroMemory(TopologyBuffer, sizeof(TCHAR) * 256);
		
		switch (m_PrimType) {
			case 1: { _tcscpy_s(TopologyBuffer, L"POINTLIST"); } break;
			case 2: { _tcscpy_s(TopologyBuffer, L"LINELIST"); } break;
			case 3: { _tcscpy_s(TopologyBuffer, L"LINESTRIP"); } break;
			case 4: { _tcscpy_s(TopologyBuffer, L"TRIANGLELIST"); } break;
			case 5: { _tcscpy_s(TopologyBuffer, L"TRIANGLESTRIP"); } break;
		}

		TCHAR pBuffer[256];
		ZeroMemory(pBuffer, sizeof(TCHAR) * 256);

		_stprintf_s(pBuffer, L"%s", TopologyBuffer);

		m_Font.DrawText(pBuffer);

		// Set the input layout
		g_pD3dContext->IASetInputLayout(m_pVertexLayout);

		// Shaders
		g_pD3dContext->VSSetShader(m_pVS, NULL, 0);
		g_pD3dContext->PSSetShader(m_pPS, NULL, 0);

		// // Set vertex buffer
		UINT stride = sizeof(Point3);
		UINT offset = 0;

		//IASetVertexBuffers : 1개 정점의 메모리 크기
		g_pD3dContext->IASetVertexBuffers(0, 1, &m_pVertexBuffer, &stride, &offset);

		g_pD3dContext->IASetPrimitiveTopology((D3D_PRIMITIVE_TOPOLOGY)m_PrimType);
		g_pD3dContext->Draw(6, 0);

		return true;
	}

	bool Sample::Release()
	{
		SAFE_RELEASE(m_pVertexLayout); // 정정레이아웃 소멸
		SAFE_RELEASE(m_pVertexBuffer); // 정점버퍼 소멸	
		SAFE_RELEASE(m_pVS);           // 정점쉐이더 소멸
		SAFE_RELEASE(m_pPS);           // 픽쉘쉐이더 소멸 
		return true;
	}
	
	Sample::~Sample() { }
}


IndexBuffer

  # 인덱스 버퍼를 사용하는 예제. 위의 예제에서 몇 부분만 추가, 변경 되었다.

sample.h 업데이트

   
        ID3D11Buffer*         m_pIndexBuffer;    //인덱스 버퍼 인터페이스    - 추가된 변수
        HRESULT	             CreateIndexBuffer();   // 인덱스 버퍼 생성  - 추가된 함수

sample.cpp 업데이트

	
        // 추가된 함수
        HRESULT Sample::CreateIndexBuffer()
	{
		HRESULT hr = S_OK;

		WORD indices[] =
		{
			0,1,2,
			0,2,3,
		};

		UINT iNumIndex = sizeof(indices) / sizeof(indices[0]);

		// Create an Index Buffer
		D3D11_BUFFER_DESC ib;
		ZeroMemory(&ib, sizeof(D3D11_BUFFER_DESC));
		ib.ByteWidth = iNumIndex * sizeof(WORD);
		ib.Usage = D3D11_USAGE_DEFAULT;
		ib.BindFlags = D3D11_BIND_INDEX_BUFFER;

		D3D11_SUBRESOURCE_DATA ibInitData;
		ZeroMemory(&ibInitData, sizeof(D3D11_SUBRESOURCE_DATA));
		ibInitData.pSysMem = indices;
		V_FRETURN(g_pD3dDevice->CreateBuffer(&ib, &ibInitData, &m_pIndexBuffer));

		return hr;
	}

        // 변경된 내용
	bool Sample::Init()
	{
		if (FAILED(CreateVertexBuffer()))
		{
			MessageBox(0, _T("CreateTrangle1  실패"), _T("Fatal error"), MB_OK);
			return false;
		}

		if (FAILED(CreateIndexBuffer()))
		{
			MessageBox(0, _T("CreateTrangle2  실패"), _T("Fatal error"), MB_OK);
			return false;
		}

		if (FAILED(LoadShaderAndInputLayout()))
		{
			MessageBox(0, _T("CreateTrangle3  실패"), _T("Fatal error"), MB_OK);
			return false;
		}
		return true;
	}

	bool Sample::Render()
	{
		m_Font.SetAlignment(DWRITE_TEXT_ALIGNMENT_CENTER, DWRITE_PARAGRAPH_ALIGNMENT_NEAR);
		m_Font.SetTextColor(ColorF(1.0f, 1.0f, 1.0f, 1.0f));
		m_Font.SetlayoutRt(0, 0, (FLOAT)g_rtClient.right, (FLOAT)g_rtClient.bottom);

		TCHAR TopologyBuffer[256];
		ZeroMemory(TopologyBuffer, sizeof(TCHAR) * 256);
		
		switch (m_PrimType) {
			case 1: { _tcscpy_s(TopologyBuffer, L"POINTLIST"); } break;
			case 2: { _tcscpy_s(TopologyBuffer, L"LINELIST"); } break;
			case 3: { _tcscpy_s(TopologyBuffer, L"LINESTRIP"); } break;
			case 4: { _tcscpy_s(TopologyBuffer, L"TRIANGLELIST"); } break;
			case 5: { _tcscpy_s(TopologyBuffer, L"TRIANGLESTRIP"); } break;
		}

		TCHAR pBuffer[256];
		ZeroMemory(pBuffer, sizeof(TCHAR) * 256);

		_stprintf_s(pBuffer, L"%s", TopologyBuffer);

		m_Font.DrawText(pBuffer);

		// Set the input layout
		g_pD3dContext->IASetInputLayout(m_pVertexLayout);

		// Shaders
		g_pD3dContext->VSSetShader(m_pVS, NULL, 0);
		g_pD3dContext->PSSetShader(m_pPS, NULL, 0);

		// // Set vertex buffer
		UINT stride = sizeof(Point3);
		UINT offset = 0;

		//IASetVertexBuffers : 1개 정점의 메모리 크기
		g_pD3dContext->IASetVertexBuffers(0, 1, &m_pVertexBuffer, &stride, &offset);
		g_pD3dContext->IASetIndexBuffer(m_pIndexBuffer, DXGI_FORMAT_R16_UINT, 0); //WORD는 R16, DWORD는 R32

		g_pD3dContext->IASetPrimitiveTopology((D3D_PRIMITIVE_TOPOLOGY)m_PrimType);
		g_pD3dContext->DrawIndexed(6, 0, 0); //정점 버퍼와 인덱스 버퍼를 모두 사용해서 뿌리는 거

		return true;
	}


반응형