흑백 처리

포스트이펙트에 대해서 알아보자.

파일 가져오기

shader_basic02.html 페이지에서 EnvironmentMapping.rfx  렌더몽키 파일을 수정할 것이다.

렌더몽키 이펙트 이름은 ColorConversion으로 바꾼다.

포스트이펙트 이펙트는 첫 번째 패스에서 렌더타겟에 렌더링한다.
두 번째 패스에서 사각형에 렌더타겟을 그린다.

사각형을 투영좌표의 (-1, -1, 0) ~ (1, 1, 0)으로 하여 셰이더에서 공간변환을 하지 않을 것이다.

셰이더에서 공간 변환의 불필요

투영공간 좌표 영역은  (-1, -1, 0) ~ (1, 1, 0)이다.
스크린을 덮을 화면의 사각형의 좌표를 다음과 같이 하면 공간변환을 할 필요가 없다.
투영공간과 사각형 평면 공간 변환이 일치한다.

v0 = ( -1, 1, 0)
v1 = (-1, -1, 0)
v2 = (1, 1, 0)
v3 = (1, -1, 0)

렌더 타겟 설정

화면을 렌더타겟에 그려주기 위해 [ Add Texture ] - [ Add Renderable Texture ]를 선택한다.
이름은 renderTexture에서 SceneTexture로 바꾼다.

SceneTexture를 더블 클릭하여 화면 크기를 설정한다.

렌더타겟을 화면에 꽉 채우기 위해 "Use viewport dimensions"을 체크한다.

Pass0의 이름을 EnvironmentMapping으로 바꾼다.

EnvironmentMapping 패스에서 오른쪽 버튼을 눌러 RenderTarget을 설정한다.

"Add Render Target" / "SceneTexture"
를 선택하면 패스의 결과가 렌더타겟에 그려지므로 화면에는 아무것도 그려지지 않을것이다..

무효과 셰이더

두 번째 패스에서 어떤 효과도 없이 그대로 보여주는 셰이더를 먼저 만들어 보자.
렌더타겟을 화면에 그대로 보여주는 패스를 추가한다.

ColorConversion 이펙트에서 오른쪽 마우스 버튼을 눌러 패스를 추가한다.

패스 이름은 NoEffect로 한다.

ColorConversion 이펙트 / Add Model / ScreenAlignedQuad.3ds를 선택한다.

NoEffect 패스의 Model에서 오른쪽 마우스 버튼을 누른다.

Reference Node / ScreenAlignedQuad를 선택하여 모델을 지정한다.

렌더타겟을 그리기 위해서 NoEffect 패스의 Model을 ScreenAlignedQuad.3ds로 바꾼다.

EnvironmentMapping 패스의  최종 결과물인 렌더러 텍스처를 Texture Object로 추가한다.

NoEffect 패스에서
Add Texture Object / Scene Texture를 선택한다.

변수명은 SceneSampler로 한다.

정점 셰이더

사각형 평면이 투영공간과 일치 하기 때문에 별도의 공간 변환은 하지 않는다.
그래서 전역 변수도 사용하지 않는다.

struct VS_INPUT
{
   float4 pos : POSITION0;
   float2 uv : TEXCOORD0;
};

struct VS_OUTPUT
{
   float4 pos : POSITION0;
   float2 uv : TEXCOORD0;
};

VS_OUTPUT vs_main( VS_INPUT input )
{
   VS_OUTPUT output;

   output.pos = input.pos;
   output.uv = input.uv;
   
   return( output );
}

픽셀 셰이더

렌더타겟 텍스쳐를 불러와서 렌더링한다.

struct PS_INPUT
{
   float2 uv : TEXCOORD0;
};

sampler2D SceneSampler;

float4 ps_main( PS_INPUT input) : COLOR0
{   
   float4 rgb = tex2D( SceneSampler, input.uv);
   return rgb;
}

셰이더를 컴파일 하면 아무것도 그려지지 않는다.
사각형 메시의 감기가 반대로 되어 있어서 뒷면으로 인식하기 때문이다.
이때는 Back-Face Culling을 꺼줄 필요가 있다.

NoEffect 패스에서 "Add Render State Block"을 선택한다.

NoEffect 패스의 "Render State"를 더블 클릭한다.
D3DRS_CULLMODE의 Value 값을 D3DCULL_NONE으로 설정한다.

이제 화면에 정상적으로 나온다.

 

GrayScale 패스( 흑백 패스)

NoEffet 패스에서 마우스 오른쪽 버튼을 눌러 Copy를 선택한다.
ColorConversion 패스에서 마우스 오른쪽 버튼을 눌러 Paste를 선택한다.
패스 이름은 GrayScale로 바꾼다.
NOEffect 패스에서 마우스 오른쪽 버튼을 눌러 Disable 시킨다.

픽셀 셰이더의 전체 코드이다.

struct PS_INPUT
{
   float2 uv : TEXCOORD0;
};

sampler2D SceneSampler;

float4 ps_main( PS_INPUT input) : COLOR
{   
   float4 tex = tex2D( SceneSampler, input.uv);
   tex.rgb = dot(tex.rgb, float3(0.3, 0.59, 0.11));
   return tex;
}

흑백은 RGB 값이 모두 동일한 값이다. 그래서 RGB 값의 평균값을 구하면 된다.

tex.rgb = (tex.r + tex.g + tex.b) /3;

인간의 눈은 RGB에 따라서 명암을 지각하는 정도가 다르기 때문에 빨강 30%, 녹색 59%, 파랑 11% 비율로 한다. 위의 코드를 바꾸면 다음과 같다.

tex.rgb = tex.r * 0.3 + tex.g * 0.59 + tex.b * 0.11

벡터의 각 성분을 다른 값으로 곱한뒤 더하는 연산이므로 내적을 사용해서 다음과 같이 수정한다.

tex.rgb = dot(tex.rgb, float3(0.3, 0.59, 0.11));

다운로드 : ColorConversion.rfx(무효과 셰이더)

다운로드 : ColorConversion2.rfx(흑백 셰이더)