티스토리 뷰

Game/Graphics

Upsampler and downsampler

newpolaris 2017. 12. 2. 16:39

Color 의 경우 Blur를 넣고 downsampling 해야 한다.

근거로는 scale theory 어쩌구 저쩌구. 눈으로 봐도 결과 차이가 난다

그러나 position/depth/normal 은 어떠한가?

다들 자연스럽게 0.5 빵을 하였다.

DS2x[DTid.xy] = Depth[DTix.xy<<1]

당황스러워서 소스에서 좀 더 찾아봤는데

MSSAO 에서는 median을 쓴다. 좀더 정확히는 'downsample.frag'

if (d < 1.0)
{
  Pos = (pos[median.x] + pos[median.y]) / 2.0;
  Norm = (norm[median.x] + norm[median.y]) / 2.0;
}
else
{
  Pos = pos[median.x];
  Norm = norm[median.x];
}

위와 같은 식이다. median은 특별한 방법 없다. 4개중 최대 최소가 아닌 3번째 값이다.

if문에 break 없으니 3번째가 선택되것다

저게 효과는 어느정도는 있었으니까 논문에 썻을거 같은데

nvidia HBAO나 MiniEngine 에서는 안썼으니, 그냥 0.5 배 하기로 했다.

여기서 끝났으면 좋은데...

Generate SSAO 란 부분이 LinearDepth & 0.5 배 depth 생성하는 부분이다

0.9 ms 나왔는데 numthread를 16x16 으로 하면 0.6 ms 가 나온다.

방법은 무식하게 linear 한번하고 0.5 로 dispatch 했다.

Linearize(DTid.xy);

DS2x[DTid.xy] = LinearZ[DTid.xy<<1];

소스 짜는사람도 쉽고, 보는 사람도 이해하기 편하다.

linearize 단독으로 0.45 ms 가 나온다.

그런데 MiniEngine의 PrepareDepthBuffers를 보면, 요상하게 해놓았다.

uint2 startST = Gid.xy << 4 | GTid.xy;
uint destIdx = GTid.y << 4 | GTid.x;

g_CacheW[ destIdx +  0  ] = Linearize(startST | uint2(0, 0));
g_CacheW[ destIdx +  8  ] = Linearize(startST | uint2(8, 0));
g_CacheW[ destIdx + 128 ] = Linearize(startST | uint2(0, 8));
g_CacheW[ destIdx + 136 ] = Linearize(startST | uint2(8, 8));

GroupMemoryBarrierWithGroupSync();

xx ----> xxxx xx

가로 세로 8칸인 x를 직선으로 풀어서 저장하는 거다 그냥 호출하면 크기가 안맞으니 가로세로 0.5배 한 이미지크기로 dispatch 한다

이 경우 DTid는 바로 D2x 와 1:1 대응이다

속도는 0.35 ms 이다

이게 interlaced texture fetch랑 관계가 있는가 찾아봤는데; 몰것다.

Upsampling 이건 많다.

우선 간단한건

Peter-Pike Sloan, Sloan07

http://developer.amd.com/wordpress/media/2012/10/ShopfMixedResolutionRendering.pdf

좀더 자세한건 http://d.hatena.ne.jp/hanecci/20131030/p1

문제가 되는 건, loRes depth, normal, ao 4개가 필요하다는 거

대략 아래와 같다. (MSSAO 슬라이드에서 가져왔다)

저 그림에서는 9/16, 3/16, 3/16, 1/16 써놨는데

2배 scale의 경우 딱 맞춰서 떨어지기에 9로 배수를 줘도 아주 약간 밀린 느낌이 나게된다.

고치려면 그냥 bilinear weight 를 주면된다.

MSSAO 에서는 그때문에 아래와 같이 처리했다.

float weight = normWeight[i] * depthWeight[i] * (9.0 / 16.0) /
  (abs((gl_FragCoord.x - loResCoord[i].x * 2.0) * (gl_FragCoord.y - loResCoord[i].y * 2.0)) * 4.0);    

MiniEngine 에서는

    float4 weights = float4(9, 3, 1, 3) / ( abs(HiDepth - LowDepths) + kUpsampleTolerance );
float TotalWeight = dot(weights, 1) + NoiseFilterStrength;
float WeightedSum = dot(LowAO, weights) + NoiseFilterStrength;// * HiAO;
return HiAO * WeightedSum / TotalWeight;

그리고 Load를 4번 사용한 것 보다, gather 가 0.1 ms 정도 더 빨랐다

'Game > Graphics' 카테고리의 다른 글

디버거에서 같은 값이 보일때,  (0) 2017.12.06
Re:SSAO  (0) 2017.12.02
MSAAO (2)  (0) 2017.12.02
LSAO  (0) 2017.12.02
MSSAO (1)  (0) 2017.12.01
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크