답변:
예, 게임 엔진에는 일반적으로 다양한 쉐이더가 있습니다. 일반적인 패턴은 다음과 같습니다.
엔진을 초기화하고 게임 월드를로드하는 동안 렌더링에 사용할 모든 셰이더를 준비하십시오. "준비"란 메모리에로드하고 필요한 경우 컴파일 한 ID3D11Device::CreatePixelShader
다음 D3D 셰이더 객체를 할당하고 준비 할 수 있도록 모든 호출을 수행합니다 . 객체를 배열 또는 다른 데이터 구조로 유지하십시오.
일반적으로 정점 셰이더와 함께 작동하도록 설계된 픽셀 셰이더 사이에는 일대일 관계가 있습니다. 나는 그것들이 하나의 객체라고 생각하는데, 그것은 실제로 버텍스 쉐이더와 픽셀 쉐이더 (그리고 아마도 지오메트리 / 헐 / 도메인 쉐이더도 포함하고 있음)를 포함하고 있지만 "쉐이더"라고 부릅니다.
각 프레임은 렌더링 할 객체 (메시) 목록을 찾았 으면 셰이더별로 정렬합니다. 주어진 쉐이더로 모든 객체를 함께 그려서 프레임에서 쉐이더를 전환하는 횟수를 최소화하는 것이 좋습니다. 이는 셰이더 전환이 다소 비싼 작업이기 때문입니다 (프레임 당 수백 또는 천 번 수행 할 수는 있지만 실제로 그렇게 비싸지는 않습니다 ).
실제로 한 단계 더 나아가 메쉬를 먼저 쉐이더로 정렬하고 머티리얼을 둘째로 정렬 할 수 있습니다. "소재"란 셰이더와 텍스처 및 매개 변수의 조합을 의미합니다. 셰이더에는 일반적으로 텍스처와 숫자 매개 변수 (상수 버퍼에 저장 됨)가 포함되어 있으므로 벽돌 재질과 아스팔트 재질은 다른 재질의 텍스처와 동일한 셰이더 코드를 사용할 수 있습니다.
그리려면 셰이더를 반복하고에 각 셰이더를 ID3D11DeviceContext
설정하고 매개 변수 (일정한 버퍼, 텍스처 등)를 설정 한 다음 객체를 그립니다. 내가 언급 한 쉐이더 / 재질 구별을 포함한 의사 코드에서 :
for each shader:
// Set the device context to use this shader
pContext->VSSetShader(shader.pVertexShader);
pContext->PSSetShader(shader.pPixelShader);
for each material that uses this shader:
// Set the device context to use any constant buffers, textures, samplers,
// etc. needed for this material
pContext->VSSetConstantBuffers(...);
pContext->PSSetConstantBuffers(...);
pContext->PSSetShaderResources(...);
pContext->PSSetSamplers(...);
for each mesh that uses this material:
// Set any constant buffers containing parameters specific to the mesh
// (e.g. world matrix)
pContext->VSSetConstantBuffers(...);
// Set the context to use the vertex & index buffers for this mesh
pContext->IASetInputLayout(mesh.pInputLayout);
pContext->IASetVertexBuffers(...);
pContext->IASetIndexBuffer(...);
pContext->IASetPrimitiveTopology(...)
// Draw it
pContext->DrawIndexed(...)
객체, 메시, 셰이더, 입력 레이아웃, 상수 버퍼 등 관리에 대해 말할 수있는 것이 더 많지만 시작하기에 충분해야합니다. :)