10.8 안개
안개 효과를 이용하면 먼거리의 렌더링 결함과 파핑 현상을 숨길 수 있다
파핑 현상이란 물체가 카메라 이동함에 따라 절두체 안으로 들어 오면서 갑자기 화면에 튀어나오는 현상
안개를 구현 하는데는 안개 색상, 안개 시작점, 안개의 범위
렌더링 도중에는 삼각형의 한점의 색상을 원래 색상과 안개 색상의 가중 평균으로 구한다
$$ foggedColor = litColor + s(fogColor - litColor)\\
foggedColor =(1-s) \cdot litColor + s \cdot fogColor$$
매개 변수 s 는 카메라 위치와 점 사이의 함수 ( 0이상 1이하의 치역)
매개 변수 s 구하는 식
$s = saturate(\frac{dist(p,E) - fogStart}{fogRange})$
dist(p,E) 은 표면 p 점과 카메라 E 의 사이의 거리, saturate 주어진 인수를 [0, 1] 구간으로 한정 하는 함수
안개 예시
$ dist(p,E) <= fogStart , s = 0 $ : fogstart 이하인 표면 점은 안개 색에 영향을 받지 않는다
$ dist(p,E) >= fogStart + fogRange , s = 1 $ : 안개 색만 보이게 된다
$ fogStart < dist(p, E) < fogStart + fogRange $ : 거리에 증가 함에 안개 색 가중치 커지고, 색상 가중치는 낮아 진다
cbuffer cbPass : register(b1)
{
//...
// Allow application to change fog parameters once per frame.
// For example, we may only use fog for certain times of day.
float4 gFogColor;
float gFogStart;
float gFogRange;
float2 cbPerObjectPad2;
//...
}
float4 PS(VertexOut pin) : SV_Target
{
//...
// Vector from point being lit to eye.
float3 toEyeW = gEyePosW - pin.PosW;
float distToEye = length(toEyeW);
toEyeW /= distToEye; // normalize
#ifdef FOG
float fogAmount = saturate((distToEye - gFogStart) / gFogRange);
litColor = lerp(litColor, gFogColor, fogAmount);
#endif
//...
}
void BlendApp::BuildShadersAndInputLayout()
{
const D3D_SHADER_MACRO defines[] =
{
"FOG", "1",
NULL, NULL
};
const D3D_SHADER_MACRO alphaTestDefines[] =
{
"FOG", "1",
"ALPHA_TEST", "1",
NULL, NULL
};
mShaders["standardVS"] = d3dUtil::CompileShader(L"Shaders\\Default.hlsl", nullptr, "VS", "vs_5_0");
mShaders["opaquePS"] = d3dUtil::CompileShader(L"Shaders\\Default.hlsl", defines, "PS", "ps_5_0");
mShaders["alphaTestedPS"] = d3dUtil::CompileShader(L"Shaders\\Default.hlsl", alphaTestDefines, "PS", "ps_5_0");
}
컴파일 시 FOG 가 정의 되어 있을 때만 안개 관련 코드가 컴파일 된다, 안개를 적용 하지 않을 때는 계산 하지 않는다
참고 및 내용 인용
프랭크 D 루나 지음, 류광 옮김
한빛 미디어
Directx 12를 이용한 3D 게임 프로그래밍 입문(2017)