9. Instancing 구현
Instancing이란?
- 3D 공간상의 물체를 화면에 그리기 위해서 렌더링 파이프라인을 거쳐야 한다.
- 같은 메쉬와 같은 머티리얼을 가진 물체가 여러 개 존재한다면, 각 물체들의 행렬값만 가져올 수 있으면 Input Assembler 단계를 거치지 않고 나머지 단계를 이어서 수행할 수 있지 않을까?
- Instancing의 원리는 Input Assembler 단계에서 Vertex Buffer를 넘길 때 물체들의 행렬값을 담은 Instancing용 버퍼를 같이 넘겨서 그 버퍼를 통해 다른 물체들을 그리는 것이다.
https://dev-treadmill.tistory.com/132
28. Instancing
붓 그리기로 치면, 전체적인 그림을 알고 있으면 빨간 붓을 들었을 때 이 참에 빨간 색이 들어간 모든 부분을 칠하는 것 이전에 DrawIndexedInstanced 함수에서 인스턴싱하는 방법과 별개로 IASetVertexBuf
dev-treadmill.tistory.com
- 이 부분은 이전에 학습했던 Dx12의 인스턴싱 강의를 참고해서 작업했다.
- 실제로 Dx11과 Dx12가 다른 부분들이 있어서 개념만 이해하고 코드로 옮기는 작업이 필요했기 때문에 6시간 정도 걸린 것 같다. (이 중 1시간은 디버깅 시간..ㅠㅠ)
- 구현할 때 실수한 부분이 있었는데, 아무래도 특별한 경우가 아니라면 Dx에서 에러메시지를 띄워주지 않기 떄문에 그래픽 디버깅을 통해 찾아야 했다.
- 분명 행렬값을 CPU에서 InstancingBuffer에 기록하는 부분은 문제가 없었다. (여기서 GPU에 넘겨주는 부분을 확인했어야 했다..ㅠㅠ)
- 지금은 해결했지만 당시에 저 두번째 버텍스 버퍼에 값이 2바이트밖에 기록되어있지 않은 것이었다..
여기서 비로소 캐치를 하고 다시 되돌아가 CPU에서 GPU로 넘겨주는 부분을 체크해서 문제를 해결할 수 있었다.
void InstancingBuffer::PushData()
{
D3D11_MAPPED_SUBRESOURCE mappedSubResource = {};
HRESULT hr = CONTEXT->Map(mpInstancingBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedSubResource);
AssertEx(SUCCEEDED(hr), L"InstancingBuffer::PushData() - 데이터를 집어넣는 과정에서 에러 발생");
memcpy(mappedSubResource.pData, mData.data(), mData.size() * sizeof(InstancingParams));
CONTEXT->Unmap(mpInstancingBuffer.Get(), 0);
}
- memcpy 부분에서 mData.size() 이후 sizeof(InstancingParams) 부분이 누락되어 있었다.
- 사소하다고 생각할 수 있는 부분이지만 좀 더 꼼꼼하게 작업할 필요성을 느꼈다.
내일 할 일
- FBX로 불러온 모델의 메쉬들을 Instancing할 수 있도록 별도 처리