Direct3D 10에서 셰이더 사용
파이프라인에는 3개의 셰이더 단계가 있으며 각 단계는 HLSL 셰이더로 프로그래밍됩니다. 모든 Direct3D 10 셰이더는 셰이더 모델 4를 대상으로 HLSL로 작성됩니다.
Direct3D 9와 Direct3D 10의 차이점:
- 중간 어셈블리 언어로 작성될 수 있는 Direct3D 9 셰이더 모델과 달리 셰이더 모델 4.0 셰이더는 HLSL로만 작성됩니다. 디바이스에서 사용할 수 있는 바이트 코드로의 셰이더 오프라인 컴파일은 계속 지원되며 대부분의 시나리오에 권장됩니다.
이 예에서는 꼭짓점 셰이더만 사용합니다. 모든 셰이더는 공통 셰이더 코어에서 빌드되기 때문에 꼭짓점 셰이더 사용 방법을 배우는 것은 기하 도형 또는 픽셀 셰이더를 사용하는 것과 매우 유사합니다.
HLSL 셰이더를 작성했으면(이 예에서는 꼭짓점 셰이더 HLSLWithoutFX.vsh를 사용함) 이를 사용할 특정 파이프라인 단계에 대해 준비해야 합니다. 이렇게 하려면 다음을 수행해야 합니다.
파이프라인의 각 셰이더에 대해 이러한 단계를 반복해야 합니다.
셰이더 컴파일
첫 번째 단계는 셰이더를 컴파일하여 HLSL 문을 올바르게 코딩했는지 확인하는 것입니다. 이는 D3D10CompileShader를 호출하고 여기에 표시된 대로 여러 매개 변수를 제공하여 수행됩니다.
IPD3D10Blob * pBlob;
// Compile the vertex shader from the file
D3D10CompileShader( strPath, strlen( strPath ), "HLSLWithoutFX.vsh",
NULL, NULL, "Ripple", "vs_4_0", dwShaderFlags, &pBlob, NULL );
이 함수는 다음 매개 변수를 사용합니다.
셰이더가 포함된 파일의 이름(및 바이트 단위의 이름 문자열 길이)입니다. 이 예에서는 꼭짓점 셰이더만 사용합니다(파일 확장자 .vsh가 꼭짓점 셰이더의 약어인 HLSLWithoutFX.vsh 파일에서).
셰이더 함수 이름입니다. 이 예는 단일 입력을 받고 출력 구조체를 반환하는 Ripple 함수에서 꼭짓점 셰이더를 컴파일합니다(함수는 HLSLWithoutFX 샘플에서 가져옴).
VS_OUTPUT Ripple( in float2 vPosition : POSITION )
셰이더에서 사용하는 모든 매크로에 대한 포인터입니다. 매크로를 정의하는 데 도움이 되도록 D3D10_SHADER_MACRO를 사용합니다. 모든 매크로 이름(공백으로 구분된 각 이름 포함)과 정의 문자열(공백으로 구분된 각 매크로 본문 포함)을 포함하는 이름 문자열을 만들기만 하면 됩니다. 두 문자열 모두 NULL로 종료되어야 합니다.
셰이더를 컴파일하기 위해 포함해야 하는 다른 파일에 대한 포인터입니다. 이는 두 가지 사용자 구현 메서드인 열기 및 닫기가 있는 ID3D10Include 인터페이스를 사용합니다. 이 작업을 수행하려면 Open 및 Close 메서드의 본문을 구현해야 합니다. Open 메서드에서 원하는 포함 파일을 여는 데 사용할 코드를 추가하고, Close 함수에서 파일 작업이 완료되면 파일을 닫는 코드를 추가합니다.
컴파일할 셰이더 함수의 이름입니다. 이 셰이더는 Ripple 함수를 컴파일합니다.
컴파일할 때 대상으로 지정할 셰이더 프로필입니다. 함수를 꼭짓점, 기하 도형 또는 픽셀 셰이더로 컴파일할 수 있으므로 프로필은 코드를 비교할 셰이더 형식과 셰이더 모델을 컴파일러에 알려 줍니다.
셰이더 컴파일러 플래그입니다. 이러한 플래그는 컴파일된 출력에 입력할 정보와 속도, 디버그 등 출력 코드를 최적화하는 방법을 컴파일러에 알려 줍니다. 사용 가능한 플래그 목록은 효과 상수(Direct3D 10)를 참조하세요. 샘플에는 프로젝트에 대한 컴파일러 플래그 값을 설정하는 데 사용할 수 있는 일부 코드가 포함되어 있습니다. 이는 주로 디버그 정보를 생성할지 여부에 대한 질문입니다.
컴파일된 셰이더 코드가 포함된 버퍼에 대한 포인터입니다. 버퍼에는 컴파일러 플래그에서 요청한 포함 디버그 및 기호 테이블 정보도 포함되어 있습니다.
셰이더를 컴파일하는 동안 디버거를 실행하는 경우 디버그 출력에 표시되는 것과 동일한 메시지인 컴파일 중에 발생한 오류 및 경고 목록이 포함된 버퍼에 대한 포인터입니다. NULL은 오류를 버퍼로 반환하지 않으려는 경우 허용되는 값입니다.
셰이더가 성공적으로 컴파일되면 셰이더 코드에 대한 포인터가 ID3D10Blob 인터페이스로 반환됩니다. 포인터가 DWORD 배열로 구성된 메모리 위치를 가리키기 때문에 Blob 인터페이스라고 합니다. 다음 단계에서 필요한 컴파일된 셰이더에 대한 포인터를 가져올 수 있도록 인터페이스가 제공됩니다.
2006년 12월 SDK부터 DirectX 10 HLSL 컴파일러는 이제 DirectX 9 및 DirectX 10 모두에서 기본 컴파일러입니다. 자세한 내용은 효과 컴파일러 도구를 참조하세요.
컴파일된 셰이더에 대한 포인터 가져오기
여러 API 메서드에는 컴파일된 셰이더에 대한 포인터가 필요합니다. 이 인수는 일련의 바이트 코드로 표시되는 컴파일된 셰이더를 가리키기 때문에 일반적으로 pShaderBytecode라고 합니다. 컴파일된 셰이더에 대한 포인터를 가져오려면 먼저 D3D10CompileShader 또는 유사한 함수를 호출하여 셰이더를 컴파일합니다. 컴파일에 성공하면 컴파일된 셰이더가 ID3D10Blob 인터페이스에 반환됩니다. 마지막으로 GetBufferPointer 메서드를 사용하여 포인터를 반환합니다.
셰이더 개체 만들기
셰이더가 컴파일되면 CreateVertexShader를 호출하여 셰이더 개체를 만듭니다.
ID3D10VertexShader ** ppVertexShader
ID3D10Blob pBlob;
// Create the vertex shader
hr = pd3dDevice->CreateVertexShader( (DWORD*)pBlob->GetBufferPointer(),
pBlob->GetBufferSize(), &ppVertexShader );
// Release the pointer to the compiled shader once you are done with it
pBlob->Release();
셰이더 개체를 만들려면 컴파일된 셰이더에 대한 포인터를 CreateVertexShader에 전달합니다. 먼저 셰이더를 성공적으로 컴파일해야 했기 때문에 컴퓨터에 메모리 문제가 없는 한 이 호출은 거의 확실히 통과할 것입니다.
셰이더 개체를 원하는 만큼 만들고 해당 개체에 대한 포인터를 유지할 수 있습니다. 셰이더 프로필(compile 메서드를 호출할 때)을 인터페이스 이름(create 메서드를 호출할 때)과 일치시킨다고 가정하면 기하 도형 및 픽셀 셰이더에 대해 동일한 메커니즘이 작동합니다.
셰이더 개체 설정
마지막 단계는 셰이더를 파이프라인 단계로 설정하는 것입니다. 파이프라인에는 3개의 셰이더 단계가 있으므로 각 단계마다 하나씩 3개의 API 호출을 수행해야 합니다.
// Set a vertex shader
pd3dDevice->VSSetShader( g_pVS10 );
VSSetShader에 대한 호출은 1단계에서 만들어진 꼭짓점 셰이더에 대한 포인터를 사용합니다. 그러면 디바이스의 셰이더가 설정됩니다. 이제 꼭짓점 셰이더 단계가 해당 꼭짓점 셰이더 코드로 초기화되었으며 남은 것은 셰이더 변수를 초기화하는 것뿐입니다.
3개의 셰이더 단계 모두에 대해 반복합니다.
이와 동일한 일련의 단계를 반복하여 꼭짓점 또는 픽셀 셰이더 또는 픽셀 셰이더로 출력되는 기하 도형 셰이더를 빌드합니다.