본문 바로가기

Today I Learned

23.06.12 - Cube Mapping, Skybox

Skybox는 게임에서 하늘을 볼 때 현실처럼 모든 면이 자연스럽게 이어져 보이게 해준다.

카메라 주위를 하나의 박스로 감싸는 것이다. 구로 감쌀 수도 있지만

이번에는 cube로 감싸는 cube mapping에 대해 알아보자.

 

 

큐브 매핑에 사용되는 텍스쳐는 위와 같이 정육면체 전개도처럼 되어있다. 

6개면의 텍스쳐를 한번에 바인딩한다. 정점의 TextureCoord는 기존에는 텍스쳐의 어떤 부분을 표현할지

좌표를 저장했지만, 큐브 매핑에서는 큐브의 중앙 기준으로 어떤 방향인지 방향벡터를 가진다.

 

	pVertices[0].vPosition = m_pVerticesPos[0] = _float3(-0.5f, 0.5f, -0.5f);
	pVertices[0].vTexcoord = pVertices[0].vPosition;
    ...

 

pVerticles[0]은 중앙 기준 x축으로 -0.5, y축으로 0.5f, z축으로 -0.5f만큼 이동했을 때 위치한 정점이다.

TextureCoord에도 position과 같이 중앙기준 방향벡터를 저장한다.

이렇게 Buffer_Cube에 큐브의 정점정보를 저장하고 SkyBox는 Buffer_Cube를 가지고 있을 것이다.

 

void CSky::Late_Tick(_float fTimeDelta)
{
	__super::Late_Tick(fTimeDelta);

	_float4x4			ViewMatrix;
	m_pGraphic_Device->GetTransform(D3DTS_VIEW, &ViewMatrix);
	D3DXMatrixInverse(&ViewMatrix, nullptr, &ViewMatrix);

	m_pTransformCom->Set_State(CTransform::STATE_POSITION, *(_float3*)&ViewMatrix.m[3][0]);
	m_pRendererCom->Add_RenderGroup(CRenderer::RENDER_PRIORITY, this);	
}

 

이제 스카이박스를 카메라의 위치로 옮겨줘야 한다. SkyBox의 Late_Tick에서  현재 뷰행렬의 역행렬을 구한다.

그럼 현재 카메라의 월드 행렬을 구할 수 있다. 카메라의 월드 행렬의 위치값을 그대로 SkyBox의 위치로 설정해주면 된다.

그러면 SkyBox가 Camera의 Transform과 같이 움직이면서 주위에 SkyBox로 가득차게 보인다.

Late_Tick에서 계산하는 이유는 Tick에서 뷰행렬을 계산하기 때문에 그 이후에 계산해야 하기 때문이다.

마지막의 RENDER_PRIORITY에 그려 가장 먼저 Skybox를 그리고 이후에 물체들을 그려 물체들이가려지지 않게 한다.

 

	m_pGraphic_Device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);

 

그리고 SkyBox를 Render할 때 ZWRITEENABLE를 FALSE로 설정해줘야 한다.

그래야 Z버퍼가 갱신되지 않기 때문에 SkyBox가 렌더링할 지형이나 물체들을 가리지 않게 된다.