레스터라이저 스테이트 타입
cull_back -> 아무것도 설정하지 않으면 뒷면을 컬링 (디폴트 옵션)
// 뒷면 기준 -> 레스터라이저에게 전달된 면의 정점 접근하는 순서가 반시계방향으로 접근
cull_front -> 시계방향을 안 그리고 반시계를 그린다.
cull_none -> 컬링을 안함 앞면이든 뒷면이든 상관없이 무조건 그림
wire_frame -> topololy를 다 무시하고 정점과 정점을 잇는 라인만 그리도록 한다 (안에가 안채워짐)
레스터라이저 문제점
디바이스에 단계별로 어떤 레스터라이저 옵션을 사용할 것인지 한 번 셋팅을 해놓으면,
다음 쉐이더가 다른 옵션으로 바꾸지 않으면 계속 동일한 옵션을 사용하게 된다.
그래서 디폴트 옵션인 cull back으로 다시 돌려두려면 이미 셋팅해두었던 레스터라이저의 옵션을 빼는 기능이 있어야한다.
m_arrRS[(UINT)RS_TYPE::CULL_BACK] = nullptr;
디폴트 옵션이 cull back 이기 때문에 nullptr을 넣으면 디폴트로 돌아간다.
레스터라이저는 VS가 끝나고 진행되는 단계이다.
레스터라이저가 호출할 픽셀들을 찾아내면 그 다음 단계인 VS 에서 그 픽셀들에 한하여 호출하게 된다.
레스터라이저 단계에서 어떻게 동작할 것인지 상태값들을 미리 만들어놓고 설정하는 것이다.
레스터라이저 스테이트는 GS 에서 사용한다.
GS 에는 랜더링을 위한 파이프라인 단계가 다 담겨있기 때문에 각 단계마다 어떤 동작을 수행할 것인지 있기 때문이다.
PNG 이미지
PNG 이미지는 알파값을 조절하여 같은 이미지라도 투명도를 조절해서 표현할 수 있다.
원점에서 벗어날수록 흐려진다.
why ? 알파값이 0에 가까워지기 때문이다.
알파(투명도)가 적용되지 않은 상태로 같은 사진을 출력한 것이다.
모든 픽셀이 전부 알파값이 1로 처리됐다는 의미이다.
검은색 모서리 부분도 투명 처리가 된 것이 아니라 채워져 있는 상태이다.
픽셀 쉐이더에서 본인의 투명한 색상을 정할 수가 없다.
투명하다는 것은 본인의 색이 투명하다는 것이 아니다.
반투명하다는 것은 블랜딩(섞어주는)작업이 필요하다.
픽셀쉐이더는 최종적으로 완성된 색상을 정확하게 알 수 없다.
픽셀쉐이더에서 출력하는 색상은 블랜딩을 하기 위한 재료이다.
출력시키려는 그자리에 먼저 그려져있던 색상과 픽셀쉐이더에서 호출하려는 색상을 블랜딩해서 최종 결과를 출력하는 것이다.
내가 출력하려는 곳에 랜더 타겟에 그려져 있던 색상이 뭔줄 알아내야하는데,
이걸 잡아주는게 블랜드 스테이트 이다.
랜더링 파이프라인 구조를 보면,
버텍스 쉐이더 -> 레스터라이저 -> 픽셀쉐이더가 끝나고 출력 병합기 단계가 있는데
출력 병합기 단계는
Depth Stensil State
Blend Stensil State 로 나눌 수 있다.
Depth Stensil State는 픽셀쉐이더에서 출력하려고 하는 색상을 출력하기 전에 깊이 값을 따진다.
투영해서 물체들을 ndc 좌표계에 갖고 오면 위치가 최종적으로 잡히고 거기에 픽셀쉐이더가 호출된다.
픽셀쉐이더를 호출시켜도 먼저 그려져있던 깊이보다 판정에서 지면? 출력을 할 수 없다.
화면에 먼저 세모를 그려놨는데. 네모가 세모 뒤에 있었다고 한다면
좌측의 그림처럼 네모가 그려져야한다.
네모를 그려낸 정점도 깊이가 0 ~ 1 범위 안으로 들어왔기 때문에
이 네모를 구성하고 있는 모든 픽셀에 대해 픽셀쉐이더를 호출 시켰지만
색칠해둔 세모와 네모의 겹치는 영역에 있는 픽셀들은
Depth Stensil State에서 걸러져서 랜더타겟에 최종적으로 출력이 안된 것이다.
랜더타겟과 동일한 해상도로 있는 Depth Stensil texture가 있기 때문에
먼저 세모가 깊이 텍스쳐에 자신의 깊이 값을 기록해놨을 것이다.
그 후, 네모도 자기가 그려질 영역에 깊이 텍스쳐를 확인하고
네모의 깊이 값도 0 ~ 1 사이로 정해져 있을 것이다.
카메라로부터 얼마나 멀리있는지 투영하고 나면 깊이값이 0 -> 1 로 온다.
네모의 깊이가 0.7 이고 세모의 깊이가 0.3인데,
ndc좌표로 가지고 와봤더니 세모는 앞에 있고 그 뒤에 네모가 있게 된 것이다.
네모 입장에서는 Depth Stensil State 에서 실패가 뜨면서
최종적으로 랜더타겟에 픽셀쉐이더에서 출력시키기로 했던 색상의 계산이 다 끝났어도 출력을 할 수 없게 된다.
why? 자기 자리에 자신보다 더 깊이가 가까운 다른 것의 깊이 값이 기록이 되어있기 때문이다.
Depth Stensil State을 통과하면 픽셀쉐이더에서 출력한 색상이 찍힐 위치에 출력이 되어야한다.
출력되기 전에 Blend Stensil State 를 거쳐야 하는데,
Blend Stensil State는 사전검문? 같은 단계이다.
픽셀쉐이더에서는 빨간색으로 출력하라고 했지만 블랜딩 공식에서
출력하는 색상은 0.5, 먼저 그려져 있던 색상에 0.5 곱해서 두 개를 합치라고 하면..
빨간색을 출력하려고 했지만 원래 렌더타겟에 먼저 그려져있던 색상과 반반 섞인 색이 최종색으로 출력이 되게 된다.
Blend Stensil State 디폴트 옵션은
픽셀쉐이더에서 출력하라는 컬러에 1을 곱하고 원래 이미 목적지에 그려져있던 색상에다는 0을 곱해서 둘이 더한다.
즉, 내가 출력하려는 색상은 무조건 덮어씌워진 색상이 나가게 된다.
픽셀쉐이더 코드에서 색상의 알파값을 0으로 설정해놔도 색상이 마치 알파값이 1인것처럼 나와서 의미가 없어질 수도 있다.
rgb에 1을 곱하고, 목적지 색상인 rgb에 0을 곱해서 둘을 더하면 내가 출력하는 색상이 무조건 나간다.
알파값이 몇이든 rgb에 아무런 영향을 주지 못하는 것이다.
우리가 사용할 이미지에는 알파값이 무조건 1이 아니라 투명한 부분도 있다.
그런 알파값으로 적용을 시키려면
선형 합성
최종색 = ( 1 - a ) * dest + a * src
을 이용해야한다.
src 에서 rgb 에다 알파값이 0.3이면 출력하려는 색상을 30% 약화시키는 것이다.
곱해지는 값의 디폴트값이 1이기 때문이다.
dest (이미 출력되어 있는) rgb에는 30%로 투명해지기 때문에 원래 있던 색상에
알파값을 뒤집어서 0.7인 70% 색상으로 합쳐준다.
원래 있던 색상을 안 줄여주면 원래 있던 색상에 내 값이 덧씌워져 더해지는 거라 섞이는게 아니라 진해진다.
본인을 70% 낮추고 더해지는 색상에 30% 낮춘 색상값을 더해서 최종적으로 블랜딩 된 색상으로 픽셀 자리에 찍히게 된다.
아까 위의 세모 네모로 예를 들자면,
세모의 알파가 0.4 정도라면 겹치는 영역에서
원래 세모의 색상이 0.4, 그리고 먼저 그려져 있던 네모의 색상이 0.6 정도가 합쳐지면서
겹치는 영역은 마치 삼각형이 반투명해져서 그 뒤에 있는 네모를 비추는 느낌의 색상이 최종적으로 출력되는 것이다.
블랜드 스테이트 타입
Default
픽셀쉐이더에서 출력하라는 색상을 무조건 출력시킨다.
디폴트 타입이기 때문에 nullptr 로 둔다.
ALPHABLEND
반투명
BlendOp -> D3D11_BLEND_OP_ADD
src + dest
SrcBlend -> D3D11_BLEND_SRC_ALPHA
픽셀쉐이더에서 리턴하는 색상 값 뒤에 곱한다.
DestBlend -> D3D11_BLEND_INV_SRC_ALPHA
랜더타겟에 이미 있는 색상에 곱하는 것이다.
1-알파 를 곱해줘야해서 알파값을 inverse해야해서 inv 를 넣어준다.
RenderTargetWriteMask -> D3D11_COLOR_WRITE_ENABLE_ALL
마스크는 기본적으로 가린다는 의미이다.
rgb 중 일부를 출력되지 않게 할 수 있는데, 우리는 전부 그대로 출력되게 하는 것을 사용할 것이다.
ONE_ONE
블랜딩 알파값을 src, dest에 각각 1로 곱하는 것.
가운데 화려한 이펙트가 있고 테두리는 알파값이 없는 검정색 텍스쳐일 경우 검은색을 빼는 용도로 사용한다.
BlendOp -> D3D11_BLEND_OP_ADD
SrcBlend -> D3D11_BLEND_ONE
DestBlend -> D3D11_BLEND_ONE
RenderTargetWriteMask -> D3D11_COLOR_WRITE_ENABLE_ALL