Normal 벡터를 저장하는 GBuffer 포맷
1. 문제
아래와 같이 Normal이 이상하게 저장되어 라이팅 계산이 제대로 되지 않는 문제가 있었다.
Normal 이상

정상

원인으로 GBuffer중 Normal을 저장하는 버퍼를 기존의 백버퍼에서 사용하는 포맷인 DXGI_FORMAT_R8G8B8A8_UNORM을 사용하였더니, -1~1의 값을 가지는 Normal이 0~1의 값으로 클램핑되어 일어난 일이였다.
2. 시도
방법 1.
-1~1값을 가지는 Normal을 0~1값으로 인코딩하여 저장하는 것이다. 반대로 사용할 때 다시 -1~1값으로 디코딩을 해주어야 한다.
// 벡터를 normalize하고 0 ~ 1값으로 인코딩
float3 EncodeVector(float3 Vector)
{
return (normalize(Vector) + 1.0f) / 2.0f;
}
// 0 ~ 1로 인코딩된 벡터를 -1 ~ 1로 디코딩
float3 DecodeVector(float3 EncodedVector)
{
return EncodedVector * 2 - 1.0f;
}
float3 EncodedNormalW = EncodeVector(NormalW);
GBufferA = float4(EncodedNormalW, 1.0f);
float3 WorldNormal = gTexture[gGBufferATextureIndex].Sample(gsamLinearWrap, TexC).rgb;
WorldNormal = DecodeVector(WorldNormal);

라이팅 계산 자체는 되었지만, Specular부분에 물결무늬가 발생한 것을 알 수 있다. 이것은 Normal이 각 채널 8비트의 낮은 정밀도에 인코딩, 디코딩되면서 발생한 값 손실 때문이다.
방법 2.
DXGI_FORMAT_R16G16B16A16_FLOAT 포맷을 사용하여 Normal을 저장해 준다.

정상적으로 라이팅 계산이 되었음을 알 수 있다.
3. 결과
- 정상적인 라이팅 계산 가능
- 메모리 사용량 증가