티스토리 뷰
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 정도 더 빨랐다
- Total
- Today
- Yesterday