반응형
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; }
반응형