색상 기록 금지
원본 픽셀 과 대상 픽셀 섞이게 하지 않고 항상 대상 픽셀이 유지
렌더링 결과를 깊이, 스텐실 버퍼에만 기록 하고 후면 버퍼에는 기록하지 않는 방식
$$C=C_{src} \bigotimes F_{src}\square C_{dst} \bigotimes F_{dis}\\
C=C_{src} \bigotimes (0,0,0)\square C_{dst} \bigotimes (1,1,1)\\
C = C_{dst}$$
D3D12_RENDER_TARGET_BLEND_DESC 구조체의 RenderTargetWriteMask 를 0으로 설정해도 같은 효과 발생
가산 혼합 과 감산 혼합
$$C=C_{src} \bigotimes F_{src}\square C_{dst} \bigotimes F_{dis}\\
C=C_{src} \bigotimes (1,1,1)\square C_{dst} \bigotimes (1,1,1)\\
C = C_{src} + C_{dst}$$
가산 혼합을 할 경우 색이 더해지므로 더 밝은 이미지가 만들어지고,
감산 혼합일 경우 색이 제거 되므로 더 어두운 이미지를 만들수 있다.
위에 식에서 혼합 연산자를 더하면 가산, 빼면 감산 혼합을 만들 수 있다
승상 혼합
성분별로 곱하는 승산 혼합
$$C=C_{src} \bigotimes F_{src}\square C_{dst} \bigotimes F_{dis}\\
C=C_{src} \bigotimes (0,0,0)\square C_{dst} \bigotimes C_{src}\\
C = C_{dst} + C_{src}$$
어두운 부분은 더 어두워지고 밝은 부분은 더 밝아지는 현상
투명도
원본 필셀의 불투명도를 제어하는 a_s 로 지정 후
불투명도가 0일때 완전 투명, 0.4 일때 40% 불투명, 1일때 100% 불투명한 하게 된다
A : 불투명도, T : 투명도 일때 둘의 관계는 T = 1 - A 이다
다음 예는 원본 픽셀의 불투명도에 비례해서 혼합하는 식
$$C=C_{src} \bigotimes F_{src}\square C_{dst} \bigotimes F_{dis}\\
C=C_{src} \bigotimes (a_s, a_s , a_s )\square C_{dst} \bigotimes (1- a_s , 1- a_s , 1-a_s )\\
C = C_{dst} + C_{src}$$
a_s 를 0.25 로 지정하면 원본 픽셀은 25% 만큼 불투명하다가 된다
최종 색상은 원복 픽셀 색상의 25% 와 대상 픽셀 75% 결합 된다
물 처럼 투명( 반투명) 한 물체를 그릴 수 있다.
이처름 혼합 물체를 그릴때에는 그리기 순서가 중요 하며 다음 과 같은 순으로 진행
1. 혼합을 하지 않는 물체 렌더링
2. 혼합을 사용하는 물체들을 카메라 기준으로 정렬
3. 물체들의 뒤에서 앞으로 그린다
비 혼합 기하구조를 모두 후면 버퍼에 깔아둔 후 혼합을 시작
후면 버퍼의 픽셀 색상이 B 이고 가산, 감산, 혼합을 n 수행 할때 어떤 순서로 수행 하든 결과는 동일( 교환 법칙)
혼합과 깊이 버퍼
물체의 집합 S, S의 물체들이 서로를 가리는 것이 아니라 해당 색상들이 모두 누적 되어서 밝은 모습이 된다
파티클 처럼 여러 입자들이 서로에게 영향을 주는 상태, 깊이 판정 하지 않는다
만약 S 물체에 깊이 판정을 실시 하면 깊이 판정으로 인해서 색상들이 누적되지 않는다
렌더링 시 깊이 버퍼 기록을 비활성 후
S 물체의 깊이 값이 버퍼에 기록 되지 않아서 깊이 판정으로 가려지지 않는다
S 물체( 가산 혼합을 적용하는 물체)을 그릴 때 깊이 기록만 비활성화 해야 한다.
알파 채널
분산광 재질의 알파 값을 출력 알파 성분으로 사용 하는데 , 분산광 텍스처에 있는 알파 값이 물체의 투명도 제어
float4 PS(VertexOut pin) : SV_Target
{
float4 diffuseAlbedo =
gDiffuseMap.Sample(gsamAnisotropicWrap, pin.TexC) * gDiffuseAlbedo;
//...
// Common convention to take alpha from diffuse albedo.
litColor.a = diffuseAlbedo.a;
return litColor;
}
픽셀 잘라 내기
픽셀을 기각 해서 더이상 처리 하지 않게 해야 할때 사용
픽셀 잘라내기를 할 떄 HLSL 함수 Clip (x) 사용,
픽셀 셰이더에서만 호출 할 수 있는 이 함수는 x < 0 이면 픽셀 폐기
철망 텍스처 RGB, Alpha 채널을 이용해서 알파 채널의 검은 색인 픽셀을 Clip 함수로 기각
철망에 해당 하는 픽셀만 렌더링 한다
다음은 픽셀 셰이더에서 사용하는 예, 알파 값이 0완전 투명 하다고 간주 한다
float4 PS(VertexOut pin) : SV_Target
{
float4 diffuseAlbedo = gDiffuseMap.Sample(gsamAnisotropicWrap, pin.TexC) * gDiffuseAlbedo;
#ifdef ALPHA_TEST
//텍스처 알파가 0.1 이하이면 폐기, 폐기 시 셰이더의 나머지 코드 실행을 생략,
clip(diffuseAlbedo.a - 0.1f);
#endif
}
ALPHA_TEST 정의가 되어 잇응면 픽셀 잘라내기를 사용 할 수 있다,
혼합을 이용해서도 가능하지만 혼합 계산이 필요하기 때문에 알파 테스트 사용 하는게 효율적 이다.
반투명한 물을 렌더링 후 clip 함수로 알파 판정을 이용해서 철망 상자를 렌더링
철망 상자의 뒷면의 철망이 앞면의 철망을 통해서 보이도록 알파 판정 물체들에 대해서
후면선별을 비활성화 해야 된다.
D3D12_GRAPHICS_PIPELINE_STATE_DESC alphaTestedPsoDesc = opaquePsoDesc;
alphaTestedPsoDesc.PS =
{
reinterpret_cast<BYTE*>(mShaders["alphaTestedPS"]->GetBufferPointer()),
mShaders["alphaTestedPS"]->GetBufferSize()
};
//컬링 모드 변경
alphaTestedPsoDesc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE;
ThrowIfFailed(md3dDevice->CreateGraphicsPipelineState(&alphaTestedPsoDesc,
IID_PPV_ARGS(&mPSOs["alphaTested"])));
참고 및 내용 인용
프랭크 D 루나 지음, 류광 옮김
한빛 미디어
Directx 12를 이용한 3D 게임 프로그래밍 입문(2017)
'Directx12 3D 프로그래밍 입문 > 10. 혼합' 카테고리의 다른 글
10.9 요약 및 연습 문제 (1) | 2023.11.02 |
---|---|
10.8 안개 (1) | 2023.10.28 |
10.1 ~4 혼합 공식, 연산, 계수, 상태 (1) | 2023.10.21 |