Foundation of game engine development에서는 Structure Buffer 를 소개합니다. 이 책에서는 Structure Buffer라고 이름 붙여서 그 뒤 과정에서 이 버퍼를 계속 그렇게 부릅니다. 이름이 DirectX의 Structured Buffer 기능과 혼동 될 수 있지만 신경쓰지 마시고, 이 Buffer를 통해 여러가지 효과를 구현하는데 활용하는데에 집중해주세요. 오늘은 Structure Buffer가 무엇인지 어떻게 구성했는지에 대해 알아봅시다.
Structure Buffer에는 메인씬을 그릴때 쓰기위해서 카메라 공간에서의 깊이 값을 저장합니다. 렌더링 패스 초기에 DepthBuffer와 Structure Buffer 둘을 모두 채워주고 이 후에 여러가지 용도로 사용하게 됩니다. Structure Buffer는 16 bit 포맷 4 채널로 구성되어집니다. 각각의 채널은 아래와 같은 내용이 담깁니다.
x | y | z | w |
z값의 x 축 기준 변화량. 즉, ddx(z) | z값의 y 축 기준 변화량. 즉, ddy(z) | Depth 값을 일부 (h = z & 0xFFFFE000) | Depth 값을 일부 (z - h) |
z값은 정밀도를 더 높게 사용하기 위해서 32 bit 의 z값을 z 채널과, w 채널으로 분리하여 저장합니다. 이 버퍼가 16 bit floating point 버퍼라는 점을 고려하면서, 최대한 정밀도를 살려 z, w를 저장하기 위해서 아래와 같은 방법을 사용합니다.
float4 CalculateStructureOutput(float z) { float h = asfloat(asuint(z) & 0xFFFFE000U); return (float4(ddx(z), ddy(z), h, z - h); }
32bit floating point는 아래와 같이 구성됩니다.
Sign bit | Exponent bit | Mantissa |
1 | 8 | 23 |

16bit floating point는 아래와 같이 구성됩니다.
Sign bit | Exponent bit | Mantissa |
1 | 5 | 10 |

위의 코드에서 h= z & 0xFFFFE000 이었습니다. (z & 0xFFFFE000)를 하면, 32비트 floating point 에서 뒤에 13자리를 제외하고 앞의 19비트를만 남긴다는 의미입니다. 이렇게 되면 32Bit의 Mantissa의 뒤의 부분이 잘리고 아래와 같이 됩니다.
Sign 1 bit, Exponent 8 bit, Mantissa 10 bit. Mantissa의 정밀도는 10비트가 유지됩니다. 이 값은 16 bit floating point와 비교해볼때 Exponent 의 비트수만 다르고 모두 똑같습니다.
이 값을 그대로 16 bit floating point로 z 채널에 저장한다고 합시다(16 bit floating point 채널 텍스쳐에 저장하기 때문 이렇게 고려). 만약 Exponent가 [-15~15] 범위 라면, 1개의 16 bit floating point에 그대로 잘 저장 될 것입니다. (그렇지 않다면 문제가 발생하겠죠. Z값이 상당히 큰경우는 이 부분에 문제가 있을 수 있습니다). 그리고 z - h를 하여 Mantissa 의 뒤쪽 13비트를 다른 16bit floating w 채널에 저장합니다.
추후에 Structure Buffer에서 z값을 복원하는 방법은 간단합니다. z와 w채널의 값을 읽어와 그냥 더해주기만 하면 됩니다.
Structure Buffer가 주로 쓰이는 곳은 Ambient Occlusion 혹은 Depth Fade에 사용하게 됩니다.
DepthFade는 안개와 같은 반투명 빌보드 텍스쳐가 지면과 만나게 될때, DepthTest가 갑자기 특정 지점(빌보드와 지면이 만나는 곳)에서 부터 실패하게 되면서, 그 만나는 지점에 선이 나타나는 Artifacts 입니다. 이 부분을 해결하기 위해서 아래와 같은 아이디어를 사용합니다.
Structure Buffer에 이미 쓰여진 Z 값과 현재 그리고 있는 반투명 빌보드의 Z 값의 차이가 적으면 알파값을 줄여서 투명도를 더 높여 주는 것입니다.
s = 조정 가능한 scale factor
za = Structured Buffer의 Z와 현재 그리는 반투명 빌보드의 Z의 차이
New Alpha = saturate(s * za) * alpha
uniform TextureRect structureBuffer; float CalcaulateDepthFade(float2 pixelCoord, float z, float scale) { float2 depth = texture(structureBuffer, pixelCoord).zw; float delta = depth.x + depth.y - z; return saturate(scale * delta); }
Reference
'Graphics > Graphics' 카테고리의 다른 글
VGPR, SGPR 사용여부 확인 (0) | 2020.09.24 |
---|---|
Physically-Based Cosmetic Rendering (0) | 2020.09.09 |
Accurate atmospheric scattering (0) | 2020.09.01 |
Absorption and Scattering (흡수와 산란) (0) | 2020.08.11 |
Perspective Shadow Map (PSM) (0) | 2020.08.05 |