Direct3D 9에서 셰이더 사용

특정 하드웨어용 셰이더 컴파일

셰이더는 DirectX 8.0에서 Microsoft DirectX에 처음 추가되었습니다. 그 당시 여러 가상 셰이더 컴퓨터가 정의되었으며, 각각은 상위 3D 그래픽 공급업체에서 생산한 특정 그래픽 프로세서에 대략적으로 해당합니다. 이러한 각 가상 셰이더 컴퓨터에 대해 어셈블리 언어가 설계되었습니다. 셰이더 모델에 작성된 프로그램(vs_1_1 및 ps_1_1 - ps_1_4로 명명)은 상대적으로 짧았으며 일반적으로 개발자가 적절한 어셈블리 언어로 직접 작성했습니다. 애플리케이션은 D3DXAssembleShader를 사용하여 인간이 읽을 수 있는 어셈블리 언어 코드를 D3DX 라이브러리에 전달하고 셰이더의 이진 파일 표현을 다시 가져와서 CreateVertexShader 또는 CreatePixelShader를 사용하여 전달합니다. 자세한 내용은 SDK(소프트웨어 개발 키트)를 참조하세요.

Direct3D 9의 상황도 비슷합니다. 애플리케이션은 D3DXCompileShader를 사용하여 HLSL 셰이더를 D3DX로 전달하고 컴파일된 셰이더의 이진 파일 표현을 다시 가져옵니다. 그러면 CreatePixelShader 또는 CreateVertexShader를 사용하여 Microsoft Direct3D로 전달됩니다. 런타임은 HLSL에 대해 아무것도 모르고 이진 어셈블리 셰이더 모델만 알 수 있습니다. 이는 HLSL 컴파일러가 Direct3D 런타임과 독립적으로 업데이트될 수 있음을 의미하기 때문에 좋습니다. fxc를 사용하여 셰이더를 오프라인으로 컴파일할 수도 있습니다.

HLSL 컴파일러의 개발 외에도 Direct3D 9는 어셈블리 수준 셰이더 모델을 도입하여 최신 그래픽 하드웨어의 기능을 노출했습니다. 애플리케이션 개발자는 이러한 새 모델(vs_2_0, vs_3_0, ps_2_0, ps_3_0)에 대한 어셈블리에서 작업할 수 있지만 대부분의 개발자는 셰이더 개발을 위해 HLSL로 이동할 것으로 예상됩니다.

물론 특정 음영 알고리즘을 표현하기 위해 HLSL 프로그램을 작성하는 기능이 지정된 하드웨어에서 자동으로 실행되도록 하는 것은 아닙니다. 애플리케이션은 D3DX를 호출하여 D3DXCompileShader를 사용하여 셰이더를 이진 파일 어셈블리 코드로 컴파일합니다. 이 진입점의 제한 사항 중 하나는 HLSL 컴파일러가 최종 셰이더 코드를 표현하는 데 사용해야 하는 어셈블리 수준 모델(또는 컴파일 대상)을 정의하는 매개 변수입니다. 애플리케이션이 런타임에 HLSL 셰이더 컴파일을 수행하는 경우(컴파일 시간이나 오프라인이 아닌) 애플리케이션은 Direct3D 디바이스의 기능을 검사하고 일치시킬 컴파일 대상을 선택할 수 있습니다. HLSL 셰이더에 표현된 알고리즘이 선택한 컴파일 대상에서 실행하기에 너무 복잡하면 컴파일이 실패합니다. 즉, HLSL은 셰이더 개발에 큰 이점이 있지만 다양한 기능의 그래픽 디바이스를 사용하여 대상 그룹 고객에게 게임을 제공하는 현실에서 개발자를 자유롭게 하지는 못합니다. 게임 개발자는 여전히 비주얼에 대한 계층화된 방식을 관리해야 합니다. 이는 더 많은 기능을 갖춘 그래픽 카드를 위해 더 나은 셰이더를 작성하고 구형 카드를 위해 더 기본적인 버전을 작성한다는 것을 의미합니다. 그러나 잘 작성된 HLSL을 사용하면 이러한 부담을 크게 줄일 수 있습니다.

애플리케이션 로드 시 또는 처음 사용할 때 고객의 컴퓨터에서 D3DX를 사용하여 HLSL 셰이더를 컴파일하는 대신, 많은 개발자는 셰이더를 배송하기도 전에 HLSL에서 이진 파일 어셈블리 코드로 컴파일하도록 선택합니다. 이렇게 하면 HLSL 소스 코드가 눈에 띄지 않고 애플리케이션이 실행될 모든 셰이더가 내부 품질 보증 프로세스를 거쳤는지 확인할 수 있습니다. 셰이더를 오프라인으로 컴파일하기 위한 편리한 유틸리티는 fxc입니다. 이 도구에는 지정된 컴파일 대상에 대한 코드를 컴파일하는 데 사용할 수 있는 여러 옵션이 있습니다. 디스어셈블된 출력을 연구하는 것은 셰이더를 최적화하려는 경우 또는 일반적으로 가상 셰이더 컴퓨터의 기능을 보다 자세한 수준에서 알아보려는 경우 개발 중에 매우 교육적일 수 있습니다. 이러한 옵션은 아래에 요약되어 있습니다.

셰이더 상수 초기화

셰이더 상수는 상수 테이블에 포함되어 있습니다. ID3DXConstantTable 인터페이스로 액세스할 수 있습니다. 전역 셰이더 변수는 셰이더 코드에서 초기화할 수 있습니다. 이는 SetDefaults를 호출하여 런타임 시 초기화됩니다.

셰이더 매개 변수를 특정 레지스터에 바인딩

컴파일러는 레지스터를 전역 변수에 자동으로 할당합니다. 컴파일러는 다음 세 전역 변수에 대해 Environment를 샘플러 레지스터 s0에, SparkleNoise를 샘플러 레지스터 s1에, k_s를 상수 레지스터 c0에 할당합니다(다른 샘플러 또는 상수 레지스터가 이미 할당되지 않았다고 가정).

sampler Environment;
sampler SparkleNoise;
float4 k_s;

변수를 특정 레지스터에 바인딩하는 것도 가능합니다. 컴파일러가 특정 레지스터에 할당하도록 하려면 다음 구문을 사용합니다.

register(RegisterName)

여기서 RegisterName은 특정 레지스터의 이름입니다. 다음 예에서는 샘플러 환경이 샘플러 레지스터 s1에 바인딩되고 SparkleNoise가 샘플러 레지스터 s0에 바인딩되고 k_s가 상수 레지스터 c12에 바인딩되는 특정 레지스터 할당 구문을 보여 줍니다.

sampler Environment : register(s1);
sampler SparkleNoise : register(s0);
float4 k_s : register(c12);

프로그래밍 가능한 셰이더 렌더링

셰이더는 디바이스에서 현재 셰이더를 설정하고, 셰이더 상수를 초기화하고, 다양한 입력 데이터가 어디에서 오는지 디바이스에 알리고, 마지막으로 기본 형식을 렌더링하여 렌더링됩니다. 이들 각각은 다음 메서드를 각각 호출하여 수행할 수 있습니다.

셰이더 디버깅

Microsoft Visual Studio .NET용 DirectX 확장은 Visual Studio .NET IDE(통합 개발 환경) 내에서 완전히 통합된 HLSL 디버거를 제공합니다. 셰이더 디버깅을 준비하려면 컴퓨터에 올바른 도구를 설치해야 합니다(Visual Studio에서 셰이더 디버깅(Direct3D 9) 참조).

HLSL에 대한 프로그래밍 지침