수업
주제
- DirectX11 기반 사각형(Quad) 렌더링 구현
- VertexColorData 구조를 이용한 색상 렌더링
- GeometryHelper를 통한 정점/인덱스 버퍼 구성
- FX11 기반 .fx 셰이더 파일을 이용한 technique/pass 셋업
- Wireframe 렌더링을 위한 RasterizerState 사용
개념
- Quad(사각형) 는 두 개의 삼각형으로 구성되며, 인덱스 버퍼를 사용하면 정점 네 개로 효율적으로 표현할 수 있다.
- 정점 구조(VertexColorData) 는 위치와 색상 정보를 함께 갖는 구조체이며, 셰이더를 통해 렌더링에 반영된다.
- FX11 기반 Shader 구성은 technique과 pass를 활용하여 다양한 렌더링 상태를 정의할 수 있다.
- RasterizerState 는 FillMode 설정을 통해 Wireframe 모드로 출력할 수 있게 해준다.
- GeometryHelper 클래스는 정점 및 인덱스 정보를 Geometry 객체에 자동으로 세팅하는 헬퍼 유틸리티이다.
- 정점 버퍼(VertexBuffer)와 인덱스 버퍼(IndexBuffer)는 GPU 자원으로 설정되어 DrawIndexed 호출로 최적화된 렌더링이 가능하다.
용어정리
| 용어 | 설명 |
|---|
| Quad | 네 개의 꼭짓점으로 이루어진 사각형 |
| VertexColorData | 위치(Vec3)와 색상(Color)를 가진 정점 데이터 구조체 |
| Geometry | 정점(Vertex)과 인덱스(Index)를 포함하는 제너릭 렌더링 데이터 클래스 |
| IndexBuffer | 정점을 조합하여 도형을 구성하는 인덱스 순서를 저장하는 GPU 자원 |
| VertexBuffer | 정점 정보를 저장하고 GPU에 전달하는 버퍼 |
| FX11 | Microsoft에서 제공하는 HLSL 기반의 Shader 효과 처리 시스템 |
| technique / pass | FX11에서 셰이더의 상태 묶음 (pass는 실행 단위, technique는 그룹) |
| RasterizerState | 삼각형을 채우는 방식(FillMode)을 지정하는 상태 객체 |
| Wireframe | 메시의 외곽선을 선으로만 렌더링하는 방식 |
| DC | DeviceContext. 렌더링 명령을 GPU에 전달하는 DirectX 객체 |
코드 분석
GeometryHelper 구현
void GeometryHelper::CreateQuad(shared_ptr<Geometry<VertexColorData>> geometry, Color color)
{
vector<VertexColorData> vtx(4);
vtx[0].position = Vec3(-0.5f, -0.5f, 0.f); vtx[0].color = color;
vtx[1].position = Vec3(-0.5f, 0.5f, 0.f); vtx[1].color = color;
vtx[2].position = Vec3(0.5f, -0.5f, 0.f); vtx[2].color = color;
vtx[3].position = Vec3(0.5f, 0.5f, 0.f); vtx[3].color = color;
geometry->SetVertices(vtx);
vector<uint32> idx = { 0, 1, 2, 2, 1, 3 };
geometry->SetIndices(idx);
}
Quad.fx Shader 구성
struct VertexInput {
float4 position : POSITION;
float4 color : COLOR;
};
struct VertexOutput {
float4 position : SV_POSITION;
float4 color : COLOR;
};
VertexOutput VS(VertexInput input) {
VertexOutput output;
output.position = input.position;
output.color = input.color;
return output;
}
float4 PS(VertexOutput input) : SV_TARGET {
return input.color;
}
RasterizerState FillModeWireFrame {
FillMode = Wireframe;
};
technique11 T0 {
pass P0 {
SetVertexShader(CompileShader(vs_5_0, VS()));
SetPixelShader(CompileShader(ps_5_0, PS()));
}
pass P1 {
SetRasterizerState(FillModeWireFrame);
SetVertexShader(CompileShader(vs_5_0, VS()));
SetPixelShader(CompileShader(ps_5_0, PS()));
}
};
QuadDemo.h 핵심 멤버
class QuadDemo : public IExecute {
public:
void Init() override;
void Update() override;
void Render() override;
shared_ptr<Shader> _shader;
shared_ptr<Geometry<VertexColorData>> _geometry;
shared_ptr<VertexBuffer> _vertexBuffer;
shared_ptr<IndexBuffer> _indexBuffer;
};
QuadDemo.cpp 렌더링 구성
void QuadDemo::Init() {
_shader = make_shared<Shader>(L"02. Quad.fx");
_geometry = make_shared<Geometry<VertexColorData>>();
GeometryHelper::CreateQuad(_geometry, Color(1.f, 0.f, 0.f, 1.f));
_vertexBuffer = make_shared<VertexBuffer>();
_vertexBuffer->Create(_geometry->GetVertices());
_indexBuffer = make_shared<IndexBuffer>();
_indexBuffer->Create(_geometry->GetIndices());
}
void QuadDemo::Render() {
uint32 stride = _vertexBuffer->GetStride();
uint32 offset = _vertexBuffer->GetOffset();
DC->IASetVertexBuffers(0, 1, _vertexBuffer->GetComPtr().GetAddressOf(), &stride, &offset);
DC->IASetIndexBuffer(_indexBuffer->GetComPtr().Get(), DXGI_FORMAT_R32_UINT, 0);
_shader->DrawIndexed(0, 0, _indexBuffer->GetCount(), 0, 0);
}
Main.cpp 실행 단위 설정
int WINAPI WinMain(...) {
GameDesc desc;
desc.app = make_shared<QuadDemo>();
GAME->Run(desc);
return 0;
}
핵심
- GeometryHelper를 사용하여 Quad의 정점(Vertex)과 인덱스(Index)를 자동 생성한다.
- VertexColorData를 통해 정점별 색상 정보를 전달하고 Shader에서 처리한다.
- FX11 기반의 .fx 파일을 활용하여 Vertex/Pixel Shader를 한 파일에서 구성하고, pass별로 렌더링 상태를 제어한다.
- pass P1을 통해 Wireframe 모드를 출력할 수 있으며 RasterizerState로 설정 가능하다.
- DrawIndexed 함수는 GPU에 정점 및 인덱스를 기반으로 도형을 효율적으로 그리도록 명령을 전달한다.
- Shader 클래스 내부에서 pipeline과 material 기능을 통합적으로 관리하며 사용자는 로직 구현에 집중할 수 있다.
- Main에서 실행 단위를 QuadDemo로 설정하여 실습 단위 프로그램을 교체해가며 테스트 가능하다.