-
[week2] Texture RenderingUE5 2025. 3. 20. 23:31
# DirectX 11 렌더링 파이프라인 (함수 호출 기반 정리)
## CPU 준비 단계 (함수 단위)
1. **디바이스 및 스왑 체인 생성**
- `D3D11CreateDeviceAndSwapChain()`
2. **렌더 타겟 및 뎁스 스텐실 준비**
- `SwapChain->GetBuffer()`
- `Device->CreateRenderTargetView()`
- `Device->CreateDepthStencilView()`
3. **자원(Resource) 준비**
- 정점 버퍼: `Device->CreateBuffer()`
- 인덱스 버퍼: `Device->CreateBuffer()`
- 셰이더 컴파일: `D3DCompileFromFile()`
- 셰이더 생성: `Device->CreateVertexShader()`, `Device->CreatePixelShader()`
- 인풋 레이아웃 생성: `Device->CreateInputLayout()`
- 상수 버퍼 생성: `Device->CreateBuffer()` (D3D11_BIND_CONSTANT_BUFFER)
- 텍스처 및 샘플러: `Device->CreateTexture2D()`, `Device->CreateSamplerState()`
## 한 프레임 렌더링 함수 호출 순서
1. Context->ClearRenderTargetView()
2. Context->ClearDepthStencilView()
3. Context->OMSetRenderTargets()
4. Context->IASetVertexBuffers()
5. Context->IASetIndexBuffer()
6. Context->IASetInputLayout()
7. Context->VSSetShader(), PSSetShader(), (필요 시 GS/HS/DS)
8. Context->VSSetConstantBuffers(), PSSetConstantBuffers()
9. Context->RSSetViewports()
10. Context->PSSetSamplers(), PSSetShaderResources()
11. Context->Draw() 또는 DrawIndexed()
12. SwapChain->Present()자원(메모리/성능) 소모가 큰 순서
1️⃣ 텍스처 생성 / 로드 고해상도 텍스처는 VRAM 메모리를 대량 사용하며 압축 및 비압축 처리 비용도 큼 2️⃣ 셰이더 컴파일 (D3DCompileFromFile) 실시간 컴파일은 CPU 부하가 매우 큼 (실제 게임은 보통 미리 컴파일한 *.cso 파일 사용) 3️⃣ 버퍼 생성 (CreateBuffer) 대규모 Vertex / Index / ConstantBuffer 생성 시 메모리 할당 비용 발생 4️⃣ InputLayout 생성 내부 구조 분석과 파싱으로 약간의 자원 소비 (한 번만 생성 후 캐싱 가능) 5️⃣ PSSetShaderResources (텍스처 바인딩) 너무 자주 바인딩하면 드라이버 state change 비용 발생 6️⃣ Draw() / DrawIndexed() 호출 GPU 실행 명령이긴 하지만, 이미 준비된 자원 위에서 실행되므로 상대적으로 비용은 낮음 7️⃣ OMSetRenderTargets / Clear 호출 렌더타겟 & 뎁스 초기화는 GPU 메모리 클리어 작업, 비용 있지만 짧은 편 8️⃣ VSSetShader / PSSetShader 호출 상태 설정 변경 정도이므로 자원 소모는 낮음 자원 소모 최적화 팁
✅ 1️⃣ 텍스처 최적화
DDS(DXT 압축) 텍스처 사용 압축된 텍스처 포맷으로 VRAM 사용량 최소화, 로딩 속도 증가, GPU-Friendly Mipmap 포함 저장 멀리 있는 물체는 낮은 해상도로 자동 렌더링 → 성능 최적화 필요한 해상도만 사용 8K 텍스처 불필요하면 4K / 2K 로 줄여서 메모리 절약 다중 텍스처 통합(Atlas) 여러 작은 텍스처를 한 장으로 묶어 Draw Call & state change 최소화
✅ 2️⃣ 셰이더 최적화
런타임 컴파일 금지 D3DCompileFromFile() 대신 미리 컴파일된 cso 파일 로드 사용 셰이더 캐싱 시스템 구축 동일한 셰이더 재사용 시 재컴파일/재로드 하지 않음, 메모리 절약 불필요한 if / 분기 최소화 GPU 분기 처리는 비싼 연산 → 브랜치 대신 조건 mask 처리 추천
✅ 3️⃣ 버퍼 관리 최적화
큰 정적 버퍼는 한 번 생성 후 재사용 매 프레임 CreateBuffer() 호출하지 말고 초기화 시 생성해서 계속 유지 동적 버퍼는 D3D11_USAGE_DYNAMIC + Map() 사용 CPU 가 자주 업데이트하는 경우 Map/Unmap 으로 효율적 쓰기 가능 Stream Output 또는 Instancing 사용 반복되는 데이터 전송을 줄이고 GPU 내부 인스턴싱으로 성능 향상
✅ 4️⃣ 상태 변화(State Change) 최적화
PSSetShaderResources / VSSetShader / Sampler 최소 변경 매 Draw Call 마다 텍스처, 쉐이더 바꾸면 드라이버 오버헤드 증가 — 유사 상태 묶어 그리기 (Batch) 추천 DrawCall 정리 (Batching) 유사한 메터리얼, 동일 텍스처를 사용하는 객체들을 한 번에 처리해서 상태 전환 비용 최소화 렌더링 순서 정리 (Material sorting) 텍스처나 셰이더 교체가 적은 순서대로 렌더링을 정리하면 GPU 스테이트 변경 비용 절약
✅ 5️⃣ Present & VSync 주의
VSync 끄기(개발 중) 성능 측정 시 GPU 제한 없이 성능 체크 가능 VSync 켜기(출시) 화면 찢어짐 방지, 그러나 GPU 대기 시간이 추가되므로 FPS 제한 확인 필요
✅ 전체 최적화 흐름 추천
- 초기화 시 정적 리소스 전부 로드 & 캐싱
- 렌더링 시 텍스처 & 셰이더 상태 변경 최소화 → 비슷한 메터리얼끼리 묶어서 그리기
- 자주 변경되는 정점 데이터는 동적 버퍼 사용 (Map/Unmap)
- draw 호출 개수 최소화 (인스턴싱 또는 배치)
- 텍스처는 압축 포맷과 mipmap 필수 적용
- Shader 컴파일은 무조건 사전 컴파일 후 cso 파일 로딩
✅ 3️⃣ 정적 버퍼 vs 동적 버퍼 비교 정리
항목 정적 버퍼 (D3D11_USAGE_DEFAULT) 동적 버퍼 (D3D11_USAGE_DYNAMIC) 용도 변경 거의 없는 데이터 (지형, 모델 메쉬 등) 프레임마다 업데이트되는 데이터 (UI, 파티클, 애니메이션 변형 등) CPU 접근 ❌ 없음 (GPU 전용) ✅ CPU 쓰기 가능 (Map/Unmap 사용) 업데이트 방법 변경 시 리소스를 다시 생성해야 함 Map(DISCARD) & memcpy & Unmap 장점 GPU 최적화 / 빠른 렌더링 CPU가 자주 바꾸는 데이터 처리에 최적화 단점 변경 어려움 (매번 리소스 새로 생성 필요) 잘못 설계하면 빈번한 복사 및 GPU Sync 문제가 발생할 수 있음 ✅ 배치 렌더링(Batching) vs 인스턴싱(Instancing) 비교
항목 배치 렌더링 (Batching) 인스턴싱 (Instancing) 방식 CPU 에서 여러 오브젝트 정점 데이터를 월드 변환 후 큰 버퍼로 묶어서 전송 정점 버퍼는 1개, 인스턴스 데이터(월드행렬 등)를 추가로 보내 GPU에서 변환 처리 움직임/변화 불가능 또는 버퍼 재생성 필요 실시간 가능 (인스턴스 버퍼만 매 프레임 업데이트) DrawCall 개수 1회 Draw() 호출 (묶어서 처리) 1회 DrawIndexedInstanced() 호출로 여러 인스턴스 렌더링 CPU 부하 큼 (큰 정점 버퍼 합치고 계산 필요) 적음 (인스턴스 버퍼 갱신만 하면 됨) GPU 효율 중간 (큰 정점량이면 오히려 부담) 높음 (병렬 처리 최적화 가능) 주로 사용하는 상황 고정 지형, 타일맵, 변경 안 되는 배경 나무, 풀, 파티클, 반복되는 작은 오브젝트 대량 렌더링 2주차 배운 것
1. Actor와 ActorComponent
2. 대략적인 생명주기
3. 텍스쳐 렌더링
4. 인덱스 버퍼 사용방법
5. SubUV
'UE5' 카테고리의 다른 글
[week6] Light (1) 2025.04.12 [week5] PixelShader - Fog (1) 2025.04.04 [UE5] Development Editor에서 효과적으로 디버깅하는 방법 (1) 2025.01.17 [CG] 레스터라이저 상태(Rasterizer State) (1) 2025.01.15 [UE5] .uproject, Target.cs, Build.cs (0) 2025.01.13