Vertex Shader에 대해서 알아보자. 이전글에서 정점 버퍼를 만들었다. 이 정점 버퍼의 내용으로 렌더링을 걸었을 때 가장 처음 가공을 시작하는 렌더링 파이프라인의 스테이지가 바로 이 Vertex Shader Stage
이다. 이번글에는 HLSL
로 작성된 1.쉐이더 파일을 컴파일한 후, 2. 컴파일된 내용을 쉐이더 객체로 생성하여 3. 렌더링 파이프라인에 연결하는 과정에 대해 알아볼 것이다.
Shader Code 작성
우선 아주 간단한 형태의 정점 쉐이더 코드를 작성해보도록 하자.
struct PixelIn
{
float4 position : SV_POSITION;
float4 color : COLOR;
};
PixelIn VS( float4 position : SV_POSITION, float4 color : COLOR )
{
PixelIn output;
output.position = position;
output.color = color;
return output;
}
코드를 보면 정점 쉐이더에서는 아무런 가공도 하지 않고 일단 들어오는 정점 데이터를 픽셀 쉐이더 입력 데이터로 바로 반환한다.
Vertex Shader에서 반환되는 데이터의 이후 가공
렌더링 파이프라인에서는 이후 스테이지들을 통해 렌더링 과정을 거치게 된다. Pixel Shader
에서는 이 정점들로 이루어진 도형의 내부 픽셀에 대해 처리를 한다. Pixel Shader
에서는 처리될 데이터로 Vertex Shader
에서 반환한 데이터들간에 자동으로 보간된 값을 입력 파라메터로 받게 된다. 그리고 최종적으로 픽셀에 대한 가공처리가 된 후 저장이 된다.
HLSL 빌드에서 제외하기
쉐이더 파일을 프로젝트에 포함시키면 빌드시 컴파일러가 포함된 쉐이더 파일까지 컴파일을 시도한다. 당연히 많은 에러가 발생하게 된다. HLSL파일을 우리가 따로 컴파일 시키므로 컴파일 대상에서 제외시켜주도록 한다.

라이더에서는 위와 같이 파일의 속성에서 Build Action을 None
으로 설정하면 된다.
Shader Compile 하기
쉐이더도 하나의 프로그램이라고 보면 된다. 우리가 코드를 작성하고 컴파일 과정을 거쳐 기계어로 바뀌듯이 쉐이더도 작성한 코드를 컴파일해서 GPU가 해석할 수 있는 쉐이더 프로그램으로 바꾸어야 한다. 컴파일된 쉐이더 프로그램은 ID3DBlob
객체로 캐슁할 수 있다. 다음은 쉐이더를 컴파일 하는 코드이다.
ID3DBlob* compiledShader = nullptr;
ID3DBlob* error = nullptr;
D3DCompileFromFile( Path, nullptr, nullptr, EntryPoint, ShaderModel, 0, 0, &compiledShader, &error );
d3dcompiler.lib 추가하기
D3DCompileFromFile
함수는 d3dcompiler
라는 독립된 라이브러리를 사용하므로 lib
파일을 포함하지 않으면 링크 에러가 발생한다. 따라서 올바르게 사용하기 위해서는 #pragma comment( lib, "d3dcompiler.lib" )
를 통해 라이브러리를 포함시켜주어야 한다.
Path
D3DCompileFromFile
함수는 파일로부터 쉐이더를 컴파일하기 때문에 먼저 작성했던 쉐이더 코드를 파일로 저장해야 한다. 저장된 파일의 경로를 첫번째 파라메터로 넘겨준다.
EntryPoint
컴파일할 쉐이더 함수를 넣어준다. 지금은 정점 쉐이더를 컴파일하려 하므로 쉐이더 코드중에서 버택스 쉐이더 함수의 이름을 넣어준다. 위 쉐이더 코드에 따르면 VS
를 넣어주면 된다.
ShaderModel
쉐이더도 추가되는 하드웨어의 기능에 따라 혹은 코드의 발전에 따라 여러 버전이 있다. 이 버전을 지정해주는 것이다.
레퍼런스는 마이크로 소프트를 참고하면 된다. 쉐이더 내용에 문제가 있어 컴파일을 제대로 못한 경우 내용을 ID3DBlob* error
에서 받을 수 있다. 이를 문자열로 전환하여 에러 메세지를 확인할 수 있다.
HRESULT hr = D3DCompileFromFile( Path, nullptr, nullptr, EntryPoint, ShaderModel, 0, 0, &compiledShader, &error )
if ( FAILED( hr ) )
{
char* msg = (char * )error->GetBufferPointer();
}
Shader 만들기
정상적으로 컴파일된 쉐이더를 반환받았다면 이제 이것을 가지고 쉐이더를 생성하면 된다.
ID3D11VertexShader* VertexShader = nullptr;
D3D11Device->CreateVertexShader( compiledShader->GetBufferPointer(), compiledShader->GetBufferSize(), nullptr, &VertexShader );
Shader 연결하기
만들어진 쉐이더 객체를 렌더링에 사용하려면 렌더링 파이프라인에 연결해줘야 한다.
D3D11DeviceContext->VSSetShader( VertexShader, nullptr, 0 );
이전글 : [DirectX11] 5. 삼각형 – Vertex Buffer에 대해 알아보자.
다음글 : [DirectX11] 7. 삼각형 – Input Layout에 대해 알아보자.