2018년 1월 16일 화요일

Vertex Shader and Pixel Shader (HLSL)

Vertex Shader and Pixel Shader (HLSL)


Direct3D 의 Shader 프로그램은 HLSL (High Level Shading Language) 언어로 작성 된다.
HLSL 은 OpenGL 의 GLSL 과 전체적으로는 유사한 언어구조를 갖는다. 그러나 다른점이 많다.


가정 먼저 나타나는 차이는 바로 main 함수의 존재이다.


GLSL 에서는 Shader의 진입 함수로 main() 함수가 사용되었다. 그러나 HLSL은 이러한 역할을 수행하는 함수가 있지만 그 함수 이름이 main으로 고정되지는 않는다.


즉 진입 함수를 프로그램적으로 정의 할 수 있다는 것이다.


이렇게 진입 함수 이름을 다르게 정할 수 있는데에는 나름대로 장점이 있다.


우리는 Vertex Shader와 Pixel Shader를 모두 작성하게 된다.
GLSL에서는 이 두개의 쉐이더에 각각 main 함수가 있어야 하기 때문에 이 두 파일을 따로 컴파일 하여야 한다. 쉐이더 코드를 각각 준비해야 된다는 것이다.


그러나 이렇게 진입호출 함수를 직접 정할 수 있다면, 하나의 파일로 Vertex Shader 와 Pixel Shader를 관리 할 수 있다는 것이다.


GLSL 과 또다른 차이는 Semantics 가 있고 없고의 차이 이다.
GLSL 에서는 Semantics 이 없다. 그러나 HLSL 에서는 Semantics 가 있어야 한다.


그러면 Semantics가 과연 무엇인지를 알아야 GLSL 의 지식에 기반하여 HLSL 프로그램을 이해할 수 있게 된다. GLSL 은 Semantic 이라는 것이 필요가 없다.


struct VOut
{
   float4 position : SV_POSITION;
};

VOut VShader(float4 position : POSITION)
{
   VOut output;
   output.position = position;
   return output;
}

float4 PShader(float4 position : SV_POSITION) : SV_TARGET
{
   return float4(1.0,1.0,1.0,1.0);
}


위의 코드는 HLSL 로 작성한 버텍스 쉐이어와 픽셀쉐이더이다. 두개의 서로다른 쉐이더를  같은 파일에 작성 할 수 있는 것은 앞서 말했듯이 main가 없고, 직접 쉐이더 프로그램을 C/C++ 코드에서 직접 지정할 수 있기 때문이다.


GLSL 의 코드와 차이가 있음을 알 수 있다.


우선 쉐이더 main 함수가 없고, 직접 이름을 지정하여 호출하게 되는데, 이 함수들이 입력 파라미터를 갖고 있고 또한 return 값도 갖고 있다.


우리가 GLSL 의 main 함수는 void main(); 으로 return 값이 없었다는 것과 입력 파라미터가 없었다는 것을 기억하기 바란다.


또한 변수의 선언에 차이를 보인다.


float4 position : POSITION


와 같이 선언 된것을 볼 수 있다.


HLSL에서 변수의 선언(함수의 선언도 비슷하다) 구조는 다음과 같다.


[Storage_Class] [Type_Modifier] Type Name[Index]
   [: Semantic]
   [: Packoffset]
   [: Register];
   [Annotations]
   [= Initial_Value]


좀 복잡하기도 하다.. 생략 가능한 몇가지를 제거하고 좀 단순화 시켜보자.


Type Name [: Semantic];


Type Name 은 GLSL 과 같은 모습이다. 물론 C 언어와도 같은 모습이다.


여기에 이어서  : (콜론 기호) 를 입력한 후 Semantic 을 추가 할 수 있다.
시멘틱에 대해서는 다음 링크를 읽어보기 바란다.




시멘틱은 해당 변수의 성격을 정해준다. POSITION 이라는 것은 시멘특에서 보면 버텍스 쉐이더에서 사용하는 input 값중 하나로 object 의 버텍스 위치를 의미한다고 되어 있다.


POSITION[n]
Vertex position in object space.


VOut VShader(float4 position : POSITION)
버텍스 쉐이더 이다. 버텍스 버퍼의 위치정보가 position 인수로 전달되어 온다.
VOut 이라는 구조체를 return 하게 된다.


VOut 은 float4 position : SV_POSITION 정보를 갖도록 선언된 구조체이다.


여기서 SV_POSITION 도 시멘틱이다.

float4 PShader(float4 position : SV_POSITION) : SV_TARGET
픽셀쉐이더 이다.

위의 쉐이더에 의하여 출력되는 화면은 다음과 같다.





이또한 픽셀쉐이더에서 색상을 변경할 수 있다.


float4 PShader(float4 position : VPOS) : SV_Target
{
   return float4(1.0,.0,.0,1.0);
}




위의 경우 버텍스 쉐이더에서 픽셀쉐이더로 position이 전달되고 있는데 쉐이더 코드에서는 직접 사용하지 않고 있기는 하다.


댓글 없음:

댓글 쓰기

Vertex , 정점 정보의 확장

Vertex , 정점 정보의 확장 그동안의 설명에 있어서 우리는 VERTEX 정보에 대하여 3 차원의 위치 정보만 사용하였다. struct VERTEX {float x,y,z;}; 이제 이를 확장하여 색상을...