6. Imaging
lens Plane
d
c
c vn v0
d vn
un vn
v0 v f c vn v0
v0
vf d vn
v p v0 f v0
cd cd 1
vp v0 f vp
초점거리 변수focal length
7. Evolution of the Algorithm
Initial Stochastic Approach
The Scatter-as-Gather Approach
The Blur Approach
8. original texture
Search CoC
모든 픽셀의 CoC 계산.
계산된 CoC를 원본 이미지 샘플링에 사용.
원형 푸아송 분포(Poisson distribution)
주변 픽셀과 현재 계산중인 픽셀의 CoC가 같다는 가정.
이 가정이 아니면 주변 픽셀의 CoC를 따져서 샘플링 해야 한다.
10. Evolution of the Algorithm
Initial Stochastic Approach
주변 픽셀과 현재 계산중인 픽셀의 CoC가 같다는 가정
Sharp shilhouettes, Ring artifact, 텍스쳐 품질 저하.
The Scatter-as-Gather Approach
The Blur Approach
11. 현재 계산중인 픽셀이 CoC 범위에 들지 않으므로 제외
original texture
주변 픽셀과 현재 계산중인 픽셀의 CoC가 같다는 가정.
각자 자신의 CoC를 가진다.
주변 픽셀을 검색할 때 가장 큰 CoC로 검색
주변 픽셀의 CoC가 저마다 다르기 때문.
13. Evolution of the Algorithm
Initial Stochastic Approach
주변 픽셀과 현재 계산중인 픽셀의 CoC가 같다는 가정
Sharp shilhouettes, Ring artifact, 텍스쳐 품질 저하.
The Scatter-as-Gather Approach
각 픽셀마다 자싞의 CoC를 가진다.
첫번째 시도보다는 blur된 텍스쳐 품질은 좋아짐
The Blur Approach
15. focused와 unfocused 경계선이 부드럽지 않다.
최대 blur와 focused 오브젝트의 경계선은 약 50% blur
gradient가 필요.
diameter
DB D0 D1
1
2
D1 2DB D0
D max( D0 ,2DB D0 ) 2 max( D0 , DB ) D0
16. Evolution of the Algorithm
Initial Stochastic Approach
주변 픽셀과 현재 계산중인 픽셀의 CoC가 같다는 가정
Sharp shilhouettes, Ring artifact, 텍스쳐 품질 저하.
The Scatter-as-Gather Approach
각 픽셀마다 자싞의 CoC를 가진다.
첫번째 시도보다는 blur된 텍스쳐 품질은 좋아짐
The Blur Approach
CoC 텍스쳐 ¼ 다운 샘플링 & Blur
gradient로 경계선처리
셋 중 가장 만족스러운 결과물
18. 구현 고려 사항
Depth Information
R32F Texture
Variable-Width Blur
Circle of Confusion Radius
First-Person Weapon Considerations
19. piecewise linear curve로 approximate
서로 다른 blur radius 3개
오리지널 unblurred sample
RGB A
2개의 큰 blur radius 다운 샘플링된 CoC
20. 가장 작은 blur radius
5번의 texture lookup
5X5에서 평균 17 픽셀
가장 작은 blur
실제 blur된 컬러의 approximation
연속된 blur 컬러 표현
21. 구현 고려 사항
Depth Information
R32F Texture
Variable-Width Blur
blur radius 3개 + unblurred sample
가장 작은 blur radius로 실제 컬러 귺사, 연속된 blur 컬러 표현
Circle of Confusion Radius
First-Person Weapon Considerations
22. Depth Texture에 기록된 Depth 값으로 구한
다.
f v0
cd 1
v0 f vp
더 자유로운 표현을 위해
world-near-end distance
world-far-start distance
23. 구현 고려 사항
Depth Information
R32F Texture
Variable-Width Blur
blur radius 3개 + unblurred sample
가장 작은 blur radius로 실제 컬러 귺사, 연속된 blur 컬러 표현
Circle of Confusion Radius
앞에서 구한 공식을 그대로 사용하지 않는다.
자유로운 표현을 위해 변수 추가
First-Person Weapon Considerations
24. FPS(first-person shooter) 게임에서 플레이
어 무기 표현은 매우 중요
특별 처리
view model로 따로 near, far 값을 갖게 한다.
world와 view model의 구분
view model의 경우 depth를 마이너스 값으로
기록
25. 구현 고려 사항
Depth Information
R32F Texture
Variable-Width Blur
blur radius 3개 + unblurred sample
가장 작은 blur radius로 실제 컬러 귺사, 연속된 blur 컬러 표현
Circle of Confusion Radius
앞에서 구한 공식을 그대로 사용하지 않는다.
자유로운 표현을 위해 변수 추가
First-Person Weapon Considerations
특별처리, Depth는 음수값으로 기록
26. The Complete Algorithm
Downsamples the Scene and Initializes the
Near CoC.
soft egde를 표현하기 위한 near CoC 생성
렌더 타겟은 씬의 ¼ 사이즈
Pixel Shader That Calculates the Actual Near
CoC
Blurs the Near CoC and Downsampled Color I
mage Once
Merges the Far CoC with the Near CoC and A
pplies It to the Screen
28. const float2 dofRowDelta;// float2( 0, 0.25 / renderTargetHeight )
half4 DofDownPS( const PixelInput pixel ) : COLOR
{
rowOfs[0] = 0;
rowOfs[1] = dofRowDelta.xy;
rowOfs[2] = dofRowDelta.xy * 2;
rowOfs[3] = dofRowDelta.xy * 3;
// Use bilinear filtering to average 4 color samples for free.
half3 color = 0;
color += tex2D( colorSampler, pixel.tcColor0.xy + rowOfs[0] ).rgb;
color += tex2D( colorSampler, pixel.tcColor1.xy + rowOfs[0] ).rgb;
color += tex2D( colorSampler, pixel.tcColor0.xy + rowOfs[2] ).rgb;
color += tex2D( colorSampler, pixel.tcColor1.xy + rowOfs[2] ).rgb;
color /= 4;
// Process 4 samples at a time to use vector hardware efficiently.
// The CoC will be 1 if the depth is negative, so use "min" to pick
// between "sceneCoc" and "viewCoc".
depth[0] = tex2D( depthSampler, pixel.tcDepth0.xy + rowOfs[0] ).r;
depth[1] = tex2D( depthSampler, pixel.tcDepth1.xy + rowOfs[0] ).r;
depth[2] = tex2D( depthSampler, pixel.tcDepth2.xy + rowOfs[0] ).r;
depth[3] = tex2D( depthSampler, pixel.tcDepth3.xy + rowOfs[0] ).r;
half4 viewCoc = saturate( dofEqWeapon.x * -depth + dofEqWeapon.y );
half4 sceneCoc = saturate( dofEqWorld.x * depth + dofEqWorld.y );
half4 curCoc = min( viewCoc, sceneCoc );
half4 coc = curCoc;
// rowOfs[1], rowOfs[2], rowOfs[3]
half maxCoc = max( max( coc[0], coc[1] ), max( coc[2], coc[3] ) );
return half4( color, maxCoc );
}
29. Color Texture Depth Texture
DofDownTexture
R G B A
max
오리지널 텍스쳐 컬러
CoC
30. The Complete Algorithm
Downsamples the Scene and Initializes the Ne
ar CoC.
soft egde를 표현하기 위한 near CoC 생성
렌더 타겟은 씬의 ¼ 사이즈
Pixel Shader That Calculates the Actual Nea
r CoC
경계선을 부드럽게 할 수 있도록 CoC 계산
Blurs the Near CoC and Downsampled Color I
mage Once
Merges the Far CoC with the Near CoC and A
pplies It to the Screen
31. // These are set by the game engine.
sampler shrunkSampler; // Output of DofDownsample()
sampler blurredSampler; // Blurred version of the shrunk sampler
// This is the pixel shader function that calculates the actual
// value used for the near circle of confusion.
// "texCoords" are 0 at the bottom left pixel and 1 at the top right.
float4 DofNearCoc( const float2 texCoords )
{
half4 shrunk = tex2D( shrunkSampler, texCoords );
half4 blurred = tex2D( blurredSampler, texCoords );
float3 color = shrunk.rgb;
float coc = 2 * max( blurred.a, shrunk.a ) - shrunk.a;
return float4( color, coc );
}
D max( D0 ,2DB D0 ) 2 max( D0 , DB ) D0
shrunkSampler blurredSampler
Gaussian blur blurred
DofDown
DofDown
Texture
Texture
32. The Complete Algorithm
Downsamples the Scene and Initializes the Near C
oC.
soft egde를 표현하기 위한 near CoC 생성
렌더 타겟은 씬의 ¼ 사이즈
Pixel Shader That Calculates the Actual Near CoC
경계선을 부드럽게 할 수 있도록 CoC 계산
Blurs the Near CoC and Downsampled Color Ima
ge Once
3x3 blur를 사용해 실제로 경계선을 부드럽게 한다.
Merges the Far CoC with the Near CoC and Applie
s It to the Screen
33. // This vertex and pixel shader applies a 3 x 3 blur to the image in
// colorMapSampler, which is the same size as the render target.
// The sample weights are 1/16 in the corners, 2/16 on the edges,
// and 4/16 in the center.
sampler colorSampler;// Output of DofNearCoc()
float2 invRenderTargetSize;
struct PixelInput
{
float4 position : POSITION;
float4 texCoords : TEXCOORD0;
};
PixelInput SmallBlurVS( float4 position, float2 texCoords )
{
PixelInput pixel;
const float4 halfPixel = { -0.5, 0.5, -0.5, 0.5 };
pixel.position = Transform_ObjectToClip( position );
pixel.texCoords = texCoords.xxyy + halfPixel * invRenderTargetSize;
return pixel;
}
float4 SmallBlurPS( const PixelInput pixel )
{
float4 color;
color = 0;
color += tex2D( colorSampler, pixel.texCoords.xz );
color += tex2D( colorSampler, pixel.texCoords.yz );
color += tex2D( colorSampler, pixel.texCoords.xw );
color += tex2D( colorSampler, pixel.texCoords.yw );
return color / 4;
}
34. The Complete Algorithm
Downsamples the Scene and Initializes the Near CoC.
soft egde를 표현하기 위한 near CoC 생성
렌더 타겟은 씬의 ¼ 사이즈
Pixel Shader That Calculates the Actual Near CoC
경계선을 부드럽게 할 수 있도록 CoC 계산
Blurs the Near CoC and Downsampled Color Image Once
3x3 blur를 사용해 실제로 경계선을 부드럽게 한다.
Merges the Far CoC with the Near CoC and Applies It to th
e Screen
varialbe-width blur 적용
모든 color sample의 alpha를 1로 가정
읽지 않은 center 샘플을 color가 0이고 alpha가 0인 픽셀로 처리
35. Color Depth
Texture Texture
D max( D0 ,2DB D0 ) 2 max( D0 , DB ) D0
R G B A
DofDown
오리지널 텍스쳐 컬러
max Texture DofNearCoc
CoC
Texture
Gaussian blur
3x3 blur
blurred
DofDown SmallBlur
Texture Texture
largeBlurSampler smallBlurSampler
36. sampler colorSampler; // Original source image
sampler smallBlurSampler; // Output of SmallBlurPS()
sampler largeBlurSampler; // Blurred output of DofDownsample()
half4 ApplyDepthOfField( const float2 texCoords )
{
half coc;
half3 small = GetSmallBlurSample( texCoords );
half4 med = tex2D( smallBlurSampler, texCoords );
half3 large = tex2D( largeBlurSampler, texCoords ).rgb;
half nearCoc = med.a;
half depth = tex2D( depthSampler, texCoords ).r;
if ( depth > 1.0e6 )
{
coc = nearCoc; // We don't want to blur the sky.
}
else
{
// dofEqFar.x and dofEqFar.y specify the linear ramp to convert
// to depth for the distant out-of-focus region.
half farCoc = saturate( dofEqFar.x * depth + dofEqFar.y );
// dofEqFar.z is the ratio of the far to the near blur radius.
coc = max( nearCoc, farCoc * dofEqFar.z );
}
return InterpolateDof( small, med.rgb, large, coc );
}
38. Unblurred Small blur Medium blur Large blur
d0 d1 d2
half4 InterpolateDof( half3 small, half3 med, half3 large, half coc )
{
// Efficiently calculate the cross-blend weights for each sample.
// Let the unblurred sample to small blur fade happen over distance
// d0, the small to medium blur over distance d1, and the medium to
// large blur over distance d2, where d0 + d1 + d2 = 1.
// dofLerpScale = float4( -1 / d0, -1 / d1, -1 / d2, 1 / d2 );
// dofLerpBias = float4( 1, (1 – d2) / d1, 1 / d2, (d2 – 1) / d2 );
half4 weights = saturate( coc * dofLerpScale + dofLerpBias );
weights.yz = min( weights.yz, 1 - weights.xy );
// Unblurred sample with weight "weights.x" done by alpha blending
half3 color = weights.y * small + weights.z * med + weights.w * large;
half alpha = dot( weights.yzw, half3( 16.0 / 17, 1.0, 1.0 ) );
return half4( color, alpha );
}
39. Conclusion
• 픽셀당 8.625 샘플링이 필요.
– large Gaussian blur의 샘플링 카운트를 계산
하지 않았을때
• 오리지널 이미지에 있는 픽셀이 1.3125 번
쓰인다.
– ¼로 다운 샘플링해서 사용
• 렌더타겟 6장
– Gaussian blur가 2패스일때를 가정.
40. Limitations and Future Work
• unfocused 오브젝트의 blur가 focus 오브
젝트를 가린다.
– foreground 오브젝트 렌더링 버퍼를 분리해서
극복 가능
• Transparency를 명확하기 처리 불가능