SkyBox
스카이박스의 기본 원리
// SkyBox.hlsl 중요 부분
float4 viewPos = mul(float4(input.position.xyz, 0), viewMatrix);
output.position.z = output.position.w * 0.999999f;
큐브 메시 사용: 플레이어를 감싸는 큰 정육면체 메시를 생성
큐브맵 텍스처: 6개 방향(+X, -X, +Y, -Y, +Z, -Z)의 이미지로 구성된 특수 텍스처 사용
카메라 중심 배치: 스카이박스는 항상 카메라를 중심으로 이동
깊이 값 최대화: 다른 모든 객체 뒤에 그려지도록 깊이 값을 최대치(0.999999)로 설정
쉐이더 구현
// SkyBox.hlsl
VS_OUTPUT VS(VS_INPUT input)
{
VS_OUTPUT output;
// 위치를 뷰 행렬로 변환하되, w=0으로 설정하여 이동 성분 제거
float4 viewPos = mul(float4(input.position.xyz, 0), viewMatrix);
float4 clipSpacePos = mul(viewPos, projectionMatrix);
output.position = clipSpacePos.xyzw;
// 깊이 값을 최대치로 설정 (항상 가장 뒤에 그려지도록)
output.position.z = output.position.w * 0.999999f;
// 로컬 위치를 텍스처 좌표로 사용
output.PosL = input.position.xyz;
return output;
}
float4 PS(VS_OUTPUT input) : SV_Target
{
// 입력된 방향으로 큐브맵 샘플링
float4 textureColor = texture0.Sample(sampler0, input.PosL);
return textureColor;
}
핵심 기술 설명:
깊이 값 조정
output.position.z = output.position.w * 0.999999f;
Z 값을 w와 거의 같게 설정하여 정규화된 깊이 값이 1에 매우 가까워짐
이는 스카이박스가 항상 다른 객체보다 뒤에 그려지도록 함
0.999999를 곱하는 이유는 정확히 1.0이 되면 일부 그래픽 하드웨어에서 깊이 버퍼 정밀도 문제가 발생할 수 있기 때문
큐브맵 샘플링
float4 textureColor = texture0.Sample(sampler0, input.PosL);
큐브 정점의 로컬 위치(input.PosL)를 직접 텍스처 좌표로 사용
이 벡터는 중심에서 큐브의 각 정점으로 향하는 방향 벡터가 됨
큐브맵 텍스처는 이 방향 벡터를 기반으로 적절한 텍셀 값을 반환
Last updated