SlideShare ist ein Scribd-Unternehmen logo
1 von 12
Downloaden Sie, um offline zu lesen
Temporal Anti-Aliasing 1
Temporal Anti-Aliasing
목차
1. Temporal Anti-Aliasing 이란
2. 구현방식
3. 할톤수열(Halton Sequence)
4. Jittering 적용
5. 혼합
6. Ghosting
7. 동적씬에서의아티팩트해결
8. 마치며
9. Reference
Temporal Anti-Aliasing 이란
Tmporal Anti-Aliasing(이하TAA)은공간축선안티에일리어싱(Spatial anti-aliasing)의일종으로과거프레임
의이미지를현재프레임의이미지에결합하여이미지의계단현상을제거하는기법입니다. TAA는다른AA기
법들과비교했을때적은비용을사용하여안티에일리어싱효과를얻을수있다는장점이있지만이전프레임
의이미지와결합하는과정에서흐릿한이미지를얻게되는경우가있습니다. ( 이를해결하기위해서추가로
Sharpen 필터를적용하는경우가있습니다. ) 여기서는간단한TAA의구현방식을살펴보도록하겠습니다.
구현방식
TAA는다음과같은순서로구현됩니다.
1. 매프레임에씬을그릴때마다스크린평면의각기다른방향으로위치를살짝이동하여씬을그립니다. (
Jittering 적용)
2. 이렇게렌더링된현재프레임의이미지와이전프레임들의이미지(= History buffer )를조합합니다. ( 혼
합)
3. 조합한이미지를Frame Buffer에복사합니다.
이후로각단계를좀더자세히살펴보도록하겠습니다.
할톤수열(Halton Sequence)
매프레임마다씬의위치를조금씩이동시키기위해TAA에서는할톤수열이라는것사용합니다. 할톤수열은
몬테카를로시뮬레이션등에서사용되는공간상의점을생성하는데사용되는수열로결정론적(= 같은입력에
항상같은출력값을가짐) 이며저불일치(low discrepancy)인수열입니다. 저불일치수열은기존숫자로부터
가능한멀리떨어져있는숫자를연속하여생성하기때문에군집화를방지합니다. 아래도표는할톤수열로생
성한2차원점과랜덤하게생성한2차원의점216개를서로비교한결과로저불일치수열의특징을보여줍니
다.
Temporal Anti-Aliasing 2
랜덤하게생성한2차원점은다음과같은코드를통해생성하였습니다.
std::random_device rd;
std::mt19937 mt( rd() );
std::uniform_real_distribution<float> ud( 0.f, 1.f );
std::ofstream random( "random.txt" );
for ( int i = 0; i < 216; ++i )
{
random << ud( mt ) << "t" << ud( mt ) << "n";
}
이제할톤수열을어떻게생성하는지살펴보겠습니다. 할톤수열은Radical inverse라는것에기초하여생성할
수있습니다. Radical inverse이무엇인지알아보기전에양의정수를특정기수(=기저, 밑, base)로나타내는
방법을살펴보겠습니다.
양의정수 는특정기수 를사용하여다음과같이나타낼수있습니다.
여기서 는 에서 사이의숫자입니다.
수식보다좀더알기쉬운예시를보자면2진수가있겠습니다. 양의정수13을2진수로표현하면( )
가됩니다. 이를위의수식으로표현하면
가됩니다. 이식에 인것을확인할수있습니다.
Radical inverse 함수 는기수 를통해나타낸양의정수 를소수점을기준으로반전시키는것으로[0,
1) 범위의분수로변환합니다.
즉양의정수13을기수2를통해Radical inverse를적용하면다음과같습니다.
a b
a = d (a)b
i=1
∑
m
i
i−1
d (a)
i 0 b − 1
b = 2
11012
a = 1 ∗ 2 +
0
0 ∗ 2 +
1
1 ∗ 2 +
2
1 ∗ 23
d (a) =
0 1,d (a) =
1 0,d (a) =
2 1,d (a) =
3 1
ϕb b a
ϕ (a) =
b 0.d (a)d (a)...d (a)
1 2 m
Temporal Anti-Aliasing 3
이를이용해 차원의할톤수열을만들려면각차원마다서로다른기수 를사용하면됩니다. 여기서 는반드
시서로소여야하므로소수를사용하게됩니다.
TAA에서는스크린평면상에서물체를이동시킬것이므로2차원할톤수열을통해2차원의점을생성하면됩
니다. 즉 인쌍을생성합니다.
여기서 는좀더효율적으로계산할수있는데컴퓨터에서정수를이미2진수로표현하고있기때문에비
트를뒤집어주기만하면됩니다.
uint32 ReverseBits( uint32 n )
{
n = ( n << 16 ) | ( n >> 16 );
n = ( ( n & 0x00ff00ff ) << 8 ) | ( ( n & 0xff00ff00 ) >> 8 );
n = ( ( n & 0x0f0f0f0f ) << 4 ) | ( ( n & 0xf0f0f0f0 ) >> 4 );
n = ( ( n & 0x33333333 ) << 2 ) | ( ( n & 0xcccccccc ) >> 2 );
n = ( ( n & 0x55555555 ) << 1 ) | ( ( n & 0xaaaaaaaa ) >> 1 );
return n;
}
uint64 ReverseBits( uint64 n )
{
uint64 hi = ReverseBits( static_cast<uint32>( n ) );
uint64 lo = ReverseBits( static_cast<uint32>( n >> 32 ) );
return ( hi << 32 ) | lo;
}
float Halton::RadicalInverse( uint32 baseIndex, uint64 a ) const
{
switch ( baseIndex )
{
case 0:
return static_cast<float>( ReverseBits( a ) * 0x1p-64 );
case 1:
return ::RadicalInverse<3>( a );
default:
assert( false );
break;
}
return 0.5f;
}
부터는이방법을사용할수없기때문에정수를기수 로나눠가면서직접생성해줍니다.
template <uint64 base>
float RadicalInverse( uint64 a )
{
constexpr float invBase = 1.f / base;
uint64 reversedDigits = 0;
float invBaseN = 1;
while ( a )
{
uint64 next = a / base;
uint64 digit = a % base;
reversedDigits = reversedDigits * base + digit;
0.1011 =
2
16
11
10
n b b
x =
a (ϕ (a),ϕ (a),ϕ (a),...ϕ (a))
2 3 5 pn
p = (ϕ (a),ϕ (a))
2 3
ϕ (a)
2
ϕ (a)
3 b
Temporal Anti-Aliasing 4
invBaseN *= invBase;
a = next;
}
return std::min( reversedDigits * invBaseN, (float)0x1.fffffep-1 );
}
해당코드를통해생성한점은다음과같습니다.
0.5 0.333333
0.25 0.666667
0.75 0.111111
0.125 0.444444
0.625 0.777778
0.375 0.222222
0.875 0.555556
0.0625 0.888889
0.5625 0.037037
0.3125 0.37037
0.8125 0.703704
0.1875 0.148148
0.6875 0.481482
0.4375 0.814815
0.9375 0.259259
.
.
.
Jittering 적용
생성한2차원할톤수열을이용해매프레임마다지터링을적용하여씬을그리도록합니다. 할톤수열은다음
과같이앞에서16개를골라상수로사용하도록하였습니다.
static const int MAX_HALTON_SEQUENCE = 16;
static const float2 HALTON_SEQUENCE[MAX_HALTON_SEQUENCE] = {
float2( 0.5, 0.333333 ),
float2( 0.25, 0.666667 ),
float2( 0.75, 0.111111 ),
float2( 0.125, 0.444444 ),
float2( 0.625, 0.777778 ),
float2( 0.375, 0.222222 ),
float2( 0.875, 0.555556 ) ,
float2( 0.0625, 0.888889 ),
float2( 0.5625, 0.037037 ),
float2( 0.3125, 0.37037 ),
float2( 0.8125, 0.703704 ),
float2( 0.1875, 0.148148 ),
float2( 0.6875, 0.481482 ),
float2( 0.4375, 0.814815 ),
float2( 0.9375, 0.259259 ),
float2( 0.03125, 0.592593 )
};
지터링은투영변환까지적용한위치에아래와같이적용합니다. 할톤수열은[0, 1)의구간을가지므로[-1, 1)
의구간으로변경한다음픽셀하나의크기가될수있도록프레임버퍼의크기로나눠줍니다.
Temporal Anti-Aliasing 5
float4 ApplyTAAJittering( float4 clipSpace )
{
#if TAA == 1
int idx = FrameCount % MAX_HALTON_SEQUENCE;
// [0, 1) -> [-1, 1) -> 픽셀 하나 크기의 uv 좌표로 변경
float2 jitter = HALTON_SEQUENCE[idx];
jitter.x = ( jitter.x - 0.5f ) / ViewportDimensions.x * 2.f;
jitter.y = ( jitter.y - 0.5f ) / ViewportDimensions.y * 2.f;
clipSpace.xy += jitter * clipSpace.w; // Pixel Shader로 전달시 w로 나뉘므로 곱해준다.
#endif
return clipSpace;
}
혼합
이제지터링이적용된이미지를과거프레임의이미지와섞어주면됩니다. A Survey of Temporal
Antialiasing Techniques(behindthepixels.io/assets/files/TemporalAA.pdf) 에따르면TAA의혼합은다음과
같은단순한선형보간식에의해서이뤄집니다.
는 프레임의픽셀 에대한색상출력이며 는블렌딩가중치. 는 프레임에새롭게계산된색
상, 는지금까지혼합된이전프레임의색상입니다.
가중치수치 는과거색상과현재색상간의균형을맞추는데대부분의TTA 구현은고정된 를사용하며대체
로0.1이사용된다고합니다. 따라서다음과같이간단하게혼합할수있습니다.
float4 main( PS_INPUT input ) : SV_Target0
{
float3 historyColor = HistoryTex.Sample( HistoryTexSampler, input.uv ).rgb;
float4 sceneColor = SceneTex.Sample( SceneTexSampler, input.uv );
// sceneColor.rgb * ( 1 - 0.9 ) + historyColor * 0.9
// sceneColor.rgb * 1.0 + historyColor * 0.9
float3 resolveColor = lerp( sceneColor.rgb, historyColor, 0.9 );
return float4( resolveColor, sceneColor.a );
}
f (p) =
n a ∗ s (p) +
n (1 − a) ∗ f (π(p))
n−1
f (p)
n n p a s (p)
n n
f (π(p))
n−1
a a
Temporal Anti-Aliasing 6
TAA On TAA Off
적용전과비교했을때에일리어싱현상이개선된것을확인할수있습니다. 그런데이상태에서카메라를움직
여보면문제가발생합니다.
Temporal Anti-Aliasing 7
Ghosting
Temporal Anti-Aliasing 8
고스팅현상은이전프레임의이미지를섞음으로인해서잔상과같은효과가생기는아티팩트를의미합니다.
이전프레임의이미지가유령처럼남아있다는의미로이렇게불립니다. 지금까지의방법은정적인씬에서는
잘동작하지만카메라나물체의위치변환이있는동적인씬에서는이전프레임의색상위치가변경되었는데
이를적절하게처리하지못하기때문에고스팅현상을방지할수없습니다. 고스팅현상을처리하는방식은다
양한데여기서는이를해결하기위한2가지방식을보겠습니다.
동적씬에서아티팩트해결
Velocity Buffer
첫번째는Velocity Buffer를도입하는것입니다. Velocity Buffer는현재프레임과이전프레임의픽셀간위치
차이를저장하고있는버퍼로이를이용하여현재프레임의픽셀에대한알맞는과거프레임의픽셀을샘플링
할수있도록텍스쳐uv를조정합니다.
Velocity Buffer를구성해보겠습니다. 준비해야할것은이전프레임의월드, 카메라, 투영변환행렬입니다. 정
점셰이더에는해당행렬을가지고이전프레임의위치와현재프레임의위치를계산하여픽셀셰이더로전달
합니다.
VS_OUTPUT main( VS_INPUT input )
{
Temporal Anti-Aliasing 9
VS_OUTPUT output = (VS_OUTPUT)0;
PrimitiveSceneData primitiveData = GetPrimitiveData( input.primitiveId );
output.curFramePosition = mul( float4( input.position, 1.0f ), primitiveData.m_worldMatrix );
output.curFramePosition = mul( float4( output.curFramePosition.xyz, 1.0f ), ViewMatrix );
output.curFramePosition = mul( float4( output.curFramePosition.xyz, 1.0f ), ProjectionMatrix );
output.worldNormal = mul( float4( input.normal, 0.f ), transpose( primitiveData.m_invWorldMatrix ) ).xyz;
output.prevFramePosition = mul( float4( input.position, 1.0f ), primitiveData.m_prevWorldMatrix );
output.prevFramePosition = mul( float4( output.prevFramePosition.xyz, 1.0f ), PrevViewMatrix );
output.prevFramePosition = mul( float4( output.prevFramePosition.xyz, 1.0f ), PrevProjectionMatrix );
output.position = ApplyTAAJittering( output.curFramePosition );
return output;
}
픽셀셰이더는전달받은위치를스크린의uv좌표로변경하여저장합니다.
float2 CalcVelocity( float4 curFramePosition, float4 prevFramePosition )
{
float2 curFrameUV = curFramePosition.xy / curFramePosition.w;
curFrameUV = curFrameUV * 0.5f + 0.5f;
curFrameUV.y = 1.f - curFrameUV.y;
float2 prevFrameUV = prevFramePosition.xy / prevFramePosition.w;
prevFrameUV = prevFrameUV * 0.5f + 0.5f;
prevFrameUV.y = 1.f - prevFrameUV.y;
return curFrameUV - prevFrameUV;
}
Output main( PS_INPUT input )
{
Output output = (Output)0;
output.depth = input.position.w / FarPlaneDist;
float3 enc = SignedOctEncode( normalize( input.worldNormal ) );
output.packedNormal = float4( 0.f, enc );
output.velocity = CalcVelocity( input.curFramePosition, input.prevFramePosition );
return output;
}
이제TAA 셰이더는Velocity Buffer에저장된uv값을사용하여현재프레임의픽셀에알맞는이전프레임의픽
셀을샘플링합니다.
float4 main( PS_INPUT input ) : SV_Target0
{
float2 velocity = VelocityTex.Sample( VelocityTexSampler, input.uv );
float2 previousUV = input.uv - velocity;
float3 historyColor = HistoryTex.Sample( HistoryTexSampler, previousUV ).rgb;
float4 sceneColor = SceneTex.Sample( SceneTexSampler, input.uv );
float3 resolveColor = lerp( sceneColor.rgb, historyColor, BlendWeight );
return float4( resolveColor, sceneColor.a );
}
Velocity Buffer를적용한결과다음과같은결과를얻을수있습니다.
Temporal Anti-Aliasing 10
붉은네모부분을보면고스팅현상이사라진것을확인할수있습니다. 하지만여전히잔상이발생하는부분
이있습니다.
색상Clamp
두번째는색상Clamp입니다. 만약이전프레임의픽셀색상이현재프레임의픽셀색상과유사하다면잔상현
상이발생할까요? 파란색에( R : 0, G : 0, B : 255 ) 약간흐린파란색( R : 0, G : 0, B : 240 )을섞는다고해
도그리티가나지않을거라예상할수있습니다. 색상Clamp는현재프레임의색상을기준으로이전프레임의
색상을조정하는방법입니다.
여기서는색상Clamp을위해현재프레임의상하좌우로이웃하는4픽셀을추가로샘플링하여색상의최소최
대범위를계산합니다.
float3 left = SceneTex.Sample( SceneTexSampler, input.uv, int2( -1, 0 ) ).rgb;
float3 right = SceneTex.Sample( SceneTexSampler, input.uv, int2( 1, 0 ) ).rgb;
float3 top = SceneTex.Sample( SceneTexSampler, input.uv, int2( 0, -1 ) ).rgb;
float3 bottom = SceneTex.Sample( SceneTexSampler, input.uv, int2( 0, 1 ) ).rgb;
float3 lower = min( sceneColor, min( min( left, right ), min( top, bottom ) ) );
float3 upper = max( sceneColor, max( max( left, right ), max( top, bottom ) ) );
그리고이lower, upper 색상범위로이전프레임의색상을조정합니다.
historyColor = clamp( historyColor, lower, upper );
Temporal Anti-Aliasing 11
색상Clamp를적용한TAA 셰이더의전체모습은다음과같습니다.
float4 main( PS_INPUT input ) : SV_Target0
{
float2 velocity = VelocityTex.Sample( VelocityTexSampler, input.uv );
float2 previousUV = input.uv - velocity;
float3 historyColor = HistoryTex.Sample( HistoryTexSampler, previousUV ).rgb;
float4 sceneColor = SceneTex.Sample( SceneTexSampler, input.uv );
float3 left = SceneTex.Sample( SceneTexSampler, input.uv, int2( -1, 0 ) ).rgb;
float3 right = SceneTex.Sample( SceneTexSampler, input.uv, int2( 1, 0 ) ).rgb;
float3 top = SceneTex.Sample( SceneTexSampler, input.uv, int2( 0, -1 ) ).rgb;
float3 bottom = SceneTex.Sample( SceneTexSampler, input.uv, int2( 0, 1 ) ).rgb;
float3 lower = min( sceneColor, min( min( left, right ), min( top, bottom ) ) );
float3 upper = max( sceneColor, max( max( left, right ), max( top, bottom ) ) );
historyColor = clamp( historyColor, lower, upper );
float3 resolveColor = lerp( sceneColor.rgb, historyColor, BlendWeight );
return float4( resolveColor, sceneColor.a );
}
이를적용하면다음과같이고스팅현상을개선할수있습니다.
https://s3-us-west-2.amazonaws.com/secure.notion-static.com/4fbdd80c-15a1-4dea-9bff-2016
42823616/2022-10-12_23_12_55.mp4
올바르지않은과거프레임의픽셀을조정하는방식은이외에도다양한데게임‘인사이드’의GDC 자료를보면
3x3 범위의이웃픽셀에대해서과거프레임의픽셀을clipping하는방법을사용한것을볼수있습니다.
마치며…
준비한내용은여기까지입니다. 이내용은훌륭한TAA 튜토리얼글인
https://sugulee.wordpress.com/2021/06/21/temporal-anti-aliasingtaa-tutorial/ 를참고하여Direct3D11
을사용한개인프로젝트의코드를기반으로작성되었습니다.
전체코드는아래의변경점에서
https://github.com/xtozero/SSR/commit/8f732f29d23063c914e0285120abaed024f9bba3
Source/RenderCore/Private/Renderer/TemporalAntiAliasingRendering.cpp
Source/Shaders/Private/TemporalAntiAliasing/PS_TAAResolve.fx
Source/Shaders/Private/VS_DepthWrite.fx
Source/Shaders/Private/PS_DepthWrite.fx
등의파일을참고하시면됩니다.
Temporal Anti-Aliasing 12
Reference
behindthepixels.io/assets/files/TemporalAA.pdf
https://sugulee.wordpress.com/2021/06/21/temporal-anti-aliasingtaa-tutorial/
https://en.wikipedia.org/wiki/Temporal_anti-aliasing
https://pbr-book.org/3ed-2018/Sampling_and_Reconstruction/The_Halton_Sampler
https://ziyadbarakat.wordpress.com/2020/07/28/temporal-anti-aliasing-step-by-step/
http://s3.amazonaws.com/arena-attachments/655504/c5c71c5507f0f8bf344252958254fb7d.pdf?
1468341463

Weitere ähnliche Inhalte

Was ist angesagt?

State-Based Scripting in Uncharted 2: Among Thieves
State-Based Scripting in Uncharted 2: Among ThievesState-Based Scripting in Uncharted 2: Among Thieves
State-Based Scripting in Uncharted 2: Among Thieves
Naughty Dog
 
Lighting Shading by John Hable
Lighting Shading by John HableLighting Shading by John Hable
Lighting Shading by John Hable
Naughty Dog
 
Terrain Rendering in Frostbite using Procedural Shader Splatting (Siggraph 2007)
Terrain Rendering in Frostbite using Procedural Shader Splatting (Siggraph 2007)Terrain Rendering in Frostbite using Procedural Shader Splatting (Siggraph 2007)
Terrain Rendering in Frostbite using Procedural Shader Splatting (Siggraph 2007)
Johan Andersson
 
High Dynamic Range color grading and display in Frostbite
High Dynamic Range color grading and display in FrostbiteHigh Dynamic Range color grading and display in Frostbite
High Dynamic Range color grading and display in Frostbite
Electronic Arts / DICE
 
multi plaform Full3D MMO 만들기 "삼국지를 품다"의 테크니컬 아트
multi plaform Full3D MMO 만들기 "삼국지를 품다"의 테크니컬 아트multi plaform Full3D MMO 만들기 "삼국지를 품다"의 테크니컬 아트
multi plaform Full3D MMO 만들기 "삼국지를 품다"의 테크니컬 아트
JP Jung
 

Was ist angesagt? (20)

DirectX 11 Rendering in Battlefield 3
DirectX 11 Rendering in Battlefield 3DirectX 11 Rendering in Battlefield 3
DirectX 11 Rendering in Battlefield 3
 
smallpt: Global Illumination in 99 lines of C++
smallpt:  Global Illumination in 99 lines of C++smallpt:  Global Illumination in 99 lines of C++
smallpt: Global Illumination in 99 lines of C++
 
State-Based Scripting in Uncharted 2: Among Thieves
State-Based Scripting in Uncharted 2: Among ThievesState-Based Scripting in Uncharted 2: Among Thieves
State-Based Scripting in Uncharted 2: Among Thieves
 
Gcm#4 アメリカの長編アニメーションの 色とライティング
Gcm#4  アメリカの長編アニメーションの 色とライティングGcm#4  アメリカの長編アニメーションの 色とライティング
Gcm#4 アメリカの長編アニメーションの 色とライティング
 
Forts and Fights Scaling Performance on Unreal Engine*
Forts and Fights Scaling Performance on Unreal Engine*Forts and Fights Scaling Performance on Unreal Engine*
Forts and Fights Scaling Performance on Unreal Engine*
 
NPRキャラクターレンダリング総結集!今こそ更なる高みを目指して | UNREAL FEST EXTREME 2020 WINTER
NPRキャラクターレンダリング総結集!今こそ更なる高みを目指して | UNREAL FEST EXTREME 2020 WINTERNPRキャラクターレンダリング総結集!今こそ更なる高みを目指して | UNREAL FEST EXTREME 2020 WINTER
NPRキャラクターレンダリング総結集!今こそ更なる高みを目指して | UNREAL FEST EXTREME 2020 WINTER
 
Lighting Shading by John Hable
Lighting Shading by John HableLighting Shading by John Hable
Lighting Shading by John Hable
 
An introduction to Realistic Ocean Rendering through FFT - Fabio Suriano - Co...
An introduction to Realistic Ocean Rendering through FFT - Fabio Suriano - Co...An introduction to Realistic Ocean Rendering through FFT - Fabio Suriano - Co...
An introduction to Realistic Ocean Rendering through FFT - Fabio Suriano - Co...
 
Unite 2013 optimizing unity games for mobile platforms
Unite 2013 optimizing unity games for mobile platformsUnite 2013 optimizing unity games for mobile platforms
Unite 2013 optimizing unity games for mobile platforms
 
Physically Based Sky, Atmosphere and Cloud Rendering in Frostbite
Physically Based Sky, Atmosphere and Cloud Rendering in FrostbitePhysically Based Sky, Atmosphere and Cloud Rendering in Frostbite
Physically Based Sky, Atmosphere and Cloud Rendering in Frostbite
 
Future Directions for Compute-for-Graphics
Future Directions for Compute-for-GraphicsFuture Directions for Compute-for-Graphics
Future Directions for Compute-for-Graphics
 
Unity mobile game performance profiling – using arm mobile studio
Unity mobile game performance profiling – using arm mobile studioUnity mobile game performance profiling – using arm mobile studio
Unity mobile game performance profiling – using arm mobile studio
 
Star Ocean 4 - Flexible Shader Managment and Post-processing
Star Ocean 4 - Flexible Shader Managment and Post-processingStar Ocean 4 - Flexible Shader Managment and Post-processing
Star Ocean 4 - Flexible Shader Managment and Post-processing
 
Terrain Rendering in Frostbite using Procedural Shader Splatting (Siggraph 2007)
Terrain Rendering in Frostbite using Procedural Shader Splatting (Siggraph 2007)Terrain Rendering in Frostbite using Procedural Shader Splatting (Siggraph 2007)
Terrain Rendering in Frostbite using Procedural Shader Splatting (Siggraph 2007)
 
Blender で作ったアニメーションを Unreal Engine 4 で利用する
Blender で作ったアニメーションを Unreal Engine 4 で利用するBlender で作ったアニメーションを Unreal Engine 4 で利用する
Blender で作ったアニメーションを Unreal Engine 4 で利用する
 
High Dynamic Range color grading and display in Frostbite
High Dynamic Range color grading and display in FrostbiteHigh Dynamic Range color grading and display in Frostbite
High Dynamic Range color grading and display in Frostbite
 
ガルガンチュア on Oculus Quest - 72FPSへの挑戦 -
ガルガンチュア on Oculus Quest - 72FPSへの挑戦 -ガルガンチュア on Oculus Quest - 72FPSへの挑戦 -
ガルガンチュア on Oculus Quest - 72FPSへの挑戦 -
 
NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기
NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기
NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기
 
multi plaform Full3D MMO 만들기 "삼국지를 품다"의 테크니컬 아트
multi plaform Full3D MMO 만들기 "삼국지를 품다"의 테크니컬 아트multi plaform Full3D MMO 만들기 "삼국지를 품다"의 테크니컬 아트
multi plaform Full3D MMO 만들기 "삼국지를 품다"의 테크니컬 아트
 
A Real-time Radiosity Architecture
A Real-time Radiosity ArchitectureA Real-time Radiosity Architecture
A Real-time Radiosity Architecture
 

Ähnlich wie Temporal Anti-Aliasing

Lock? We don't need no stinkin' locks!
Lock? We don't need no stinkin' locks!Lock? We don't need no stinkin' locks!
Lock? We don't need no stinkin' locks!
Michael Barker
 
fb69b412-97cb-4e8d-8a28-574c09557d35-160618025920
fb69b412-97cb-4e8d-8a28-574c09557d35-160618025920fb69b412-97cb-4e8d-8a28-574c09557d35-160618025920
fb69b412-97cb-4e8d-8a28-574c09557d35-160618025920
Karl Rudeen
 
Fourier series example
Fourier series exampleFourier series example
Fourier series example
Abi finni
 
public void turnRight(double degrees) {rotationInDegrees + - = deg.pdf
public void turnRight(double degrees) {rotationInDegrees + - = deg.pdfpublic void turnRight(double degrees) {rotationInDegrees + - = deg.pdf
public void turnRight(double degrees) {rotationInDegrees + - = deg.pdf
isenbergwarne4100
 
MuVM: Higher Order Mutation Analysis Virtual Machine for C
MuVM: Higher Order Mutation Analysis Virtual Machine for CMuVM: Higher Order Mutation Analysis Virtual Machine for C
MuVM: Higher Order Mutation Analysis Virtual Machine for C
Susumu Tokumoto
 
Planet of the AOPs
Planet of the AOPsPlanet of the AOPs
Planet of the AOPs
James Ward
 

Ähnlich wie Temporal Anti-Aliasing (20)

Locks? We Don't Need No Stinkin' Locks - Michael Barker
Locks? We Don't Need No Stinkin' Locks - Michael BarkerLocks? We Don't Need No Stinkin' Locks - Michael Barker
Locks? We Don't Need No Stinkin' Locks - Michael Barker
 
Lock? We don't need no stinkin' locks!
Lock? We don't need no stinkin' locks!Lock? We don't need no stinkin' locks!
Lock? We don't need no stinkin' locks!
 
fb69b412-97cb-4e8d-8a28-574c09557d35-160618025920
fb69b412-97cb-4e8d-8a28-574c09557d35-160618025920fb69b412-97cb-4e8d-8a28-574c09557d35-160618025920
fb69b412-97cb-4e8d-8a28-574c09557d35-160618025920
 
Project Paper
Project PaperProject Paper
Project Paper
 
Time Series Analysis with R
Time Series Analysis with RTime Series Analysis with R
Time Series Analysis with R
 
solver (1)
solver (1)solver (1)
solver (1)
 
Fourier series example
Fourier series exampleFourier series example
Fourier series example
 
Implimenting_HJM
Implimenting_HJMImplimenting_HJM
Implimenting_HJM
 
Radio ad blocker
Radio ad blockerRadio ad blocker
Radio ad blocker
 
Optimization Of Fuzzy Bexa Using Nm
Optimization Of Fuzzy Bexa Using NmOptimization Of Fuzzy Bexa Using Nm
Optimization Of Fuzzy Bexa Using Nm
 
Java Performance Puzzlers
Java Performance PuzzlersJava Performance Puzzlers
Java Performance Puzzlers
 
New SPL Features in PHP 5.3 (TEK-X)
New SPL Features in PHP 5.3 (TEK-X)New SPL Features in PHP 5.3 (TEK-X)
New SPL Features in PHP 5.3 (TEK-X)
 
ch08.ppt
ch08.pptch08.ppt
ch08.ppt
 
Clojure concurrency
Clojure concurrencyClojure concurrency
Clojure concurrency
 
Unit 2-data types,Variables,Operators,Conitionals,loops and arrays
Unit 2-data types,Variables,Operators,Conitionals,loops and arraysUnit 2-data types,Variables,Operators,Conitionals,loops and arrays
Unit 2-data types,Variables,Operators,Conitionals,loops and arrays
 
Unit 8
Unit 8Unit 8
Unit 8
 
10.1.1.2.9988
10.1.1.2.998810.1.1.2.9988
10.1.1.2.9988
 
public void turnRight(double degrees) {rotationInDegrees + - = deg.pdf
public void turnRight(double degrees) {rotationInDegrees + - = deg.pdfpublic void turnRight(double degrees) {rotationInDegrees + - = deg.pdf
public void turnRight(double degrees) {rotationInDegrees + - = deg.pdf
 
MuVM: Higher Order Mutation Analysis Virtual Machine for C
MuVM: Higher Order Mutation Analysis Virtual Machine for CMuVM: Higher Order Mutation Analysis Virtual Machine for C
MuVM: Higher Order Mutation Analysis Virtual Machine for C
 
Planet of the AOPs
Planet of the AOPsPlanet of the AOPs
Planet of the AOPs
 

Mehr von Bongseok Cho

Mehr von Bongseok Cho (11)

Light Propagation Volume.pdf
Light Propagation Volume.pdfLight Propagation Volume.pdf
Light Propagation Volume.pdf
 
Spherical Harmonics.pdf
Spherical Harmonics.pdfSpherical Harmonics.pdf
Spherical Harmonics.pdf
 
Reflective Shadow Maps
Reflective Shadow MapsReflective Shadow Maps
Reflective Shadow Maps
 
Volumetric Fog
Volumetric FogVolumetric Fog
Volumetric Fog
 
C++20에서 리플렉션 기능 구현
C++20에서 리플렉션 기능 구현C++20에서 리플렉션 기능 구현
C++20에서 리플렉션 기능 구현
 
멀티스레드 렌더링 (Multithreaded rendering)
멀티스레드 렌더링 (Multithreaded rendering)멀티스레드 렌더링 (Multithreaded rendering)
멀티스레드 렌더링 (Multithreaded rendering)
 
비동기 파일 로딩
비동기 파일 로딩비동기 파일 로딩
비동기 파일 로딩
 
Lock free queue
Lock free queueLock free queue
Lock free queue
 
Precomputed atmospheric scattering(사전 계산 대기 산란)
Precomputed atmospheric scattering(사전 계산 대기 산란)Precomputed atmospheric scattering(사전 계산 대기 산란)
Precomputed atmospheric scattering(사전 계산 대기 산란)
 
Screen space reflection
Screen space reflectionScreen space reflection
Screen space reflection
 
Game Physics Engine Development (게임 물리 엔진 개발)
Game Physics Engine Development (게임 물리 엔진 개발)Game Physics Engine Development (게임 물리 엔진 개발)
Game Physics Engine Development (게임 물리 엔진 개발)
 

Kürzlich hochgeladen

Cara Menggugurkan Sperma Yang Masuk Rahim Biyar Tidak Hamil
Cara Menggugurkan Sperma Yang Masuk Rahim Biyar Tidak HamilCara Menggugurkan Sperma Yang Masuk Rahim Biyar Tidak Hamil
Cara Menggugurkan Sperma Yang Masuk Rahim Biyar Tidak Hamil
Cara Menggugurkan Kandungan 087776558899
 
Standard vs Custom Battery Packs - Decoding the Power Play
Standard vs Custom Battery Packs - Decoding the Power PlayStandard vs Custom Battery Packs - Decoding the Power Play
Standard vs Custom Battery Packs - Decoding the Power Play
Epec Engineered Technologies
 
Integrated Test Rig For HTFE-25 - Neometrix
Integrated Test Rig For HTFE-25 - NeometrixIntegrated Test Rig For HTFE-25 - Neometrix
Integrated Test Rig For HTFE-25 - Neometrix
Neometrix_Engineering_Pvt_Ltd
 
Verification of thevenin's theorem for BEEE Lab (1).pptx
Verification of thevenin's theorem for BEEE Lab (1).pptxVerification of thevenin's theorem for BEEE Lab (1).pptx
Verification of thevenin's theorem for BEEE Lab (1).pptx
chumtiyababu
 
Hospital management system project report.pdf
Hospital management system project report.pdfHospital management system project report.pdf
Hospital management system project report.pdf
Kamal Acharya
 
1_Introduction + EAM Vocabulary + how to navigate in EAM.pdf
1_Introduction + EAM Vocabulary + how to navigate in EAM.pdf1_Introduction + EAM Vocabulary + how to navigate in EAM.pdf
1_Introduction + EAM Vocabulary + how to navigate in EAM.pdf
AldoGarca30
 

Kürzlich hochgeladen (20)

Cara Menggugurkan Sperma Yang Masuk Rahim Biyar Tidak Hamil
Cara Menggugurkan Sperma Yang Masuk Rahim Biyar Tidak HamilCara Menggugurkan Sperma Yang Masuk Rahim Biyar Tidak Hamil
Cara Menggugurkan Sperma Yang Masuk Rahim Biyar Tidak Hamil
 
Moment Distribution Method For Btech Civil
Moment Distribution Method For Btech CivilMoment Distribution Method For Btech Civil
Moment Distribution Method For Btech Civil
 
Block diagram reduction techniques in control systems.ppt
Block diagram reduction techniques in control systems.pptBlock diagram reduction techniques in control systems.ppt
Block diagram reduction techniques in control systems.ppt
 
FEA Based Level 3 Assessment of Deformed Tanks with Fluid Induced Loads
FEA Based Level 3 Assessment of Deformed Tanks with Fluid Induced LoadsFEA Based Level 3 Assessment of Deformed Tanks with Fluid Induced Loads
FEA Based Level 3 Assessment of Deformed Tanks with Fluid Induced Loads
 
Introduction to Serverless with AWS Lambda
Introduction to Serverless with AWS LambdaIntroduction to Serverless with AWS Lambda
Introduction to Serverless with AWS Lambda
 
Standard vs Custom Battery Packs - Decoding the Power Play
Standard vs Custom Battery Packs - Decoding the Power PlayStandard vs Custom Battery Packs - Decoding the Power Play
Standard vs Custom Battery Packs - Decoding the Power Play
 
Integrated Test Rig For HTFE-25 - Neometrix
Integrated Test Rig For HTFE-25 - NeometrixIntegrated Test Rig For HTFE-25 - Neometrix
Integrated Test Rig For HTFE-25 - Neometrix
 
Verification of thevenin's theorem for BEEE Lab (1).pptx
Verification of thevenin's theorem for BEEE Lab (1).pptxVerification of thevenin's theorem for BEEE Lab (1).pptx
Verification of thevenin's theorem for BEEE Lab (1).pptx
 
GEAR TRAIN- BASIC CONCEPTS AND WORKING PRINCIPLE
GEAR TRAIN- BASIC CONCEPTS AND WORKING PRINCIPLEGEAR TRAIN- BASIC CONCEPTS AND WORKING PRINCIPLE
GEAR TRAIN- BASIC CONCEPTS AND WORKING PRINCIPLE
 
Hospital management system project report.pdf
Hospital management system project report.pdfHospital management system project report.pdf
Hospital management system project report.pdf
 
1_Introduction + EAM Vocabulary + how to navigate in EAM.pdf
1_Introduction + EAM Vocabulary + how to navigate in EAM.pdf1_Introduction + EAM Vocabulary + how to navigate in EAM.pdf
1_Introduction + EAM Vocabulary + how to navigate in EAM.pdf
 
DC MACHINE-Motoring and generation, Armature circuit equation
DC MACHINE-Motoring and generation, Armature circuit equationDC MACHINE-Motoring and generation, Armature circuit equation
DC MACHINE-Motoring and generation, Armature circuit equation
 
Unleashing the Power of the SORA AI lastest leap
Unleashing the Power of the SORA AI lastest leapUnleashing the Power of the SORA AI lastest leap
Unleashing the Power of the SORA AI lastest leap
 
HOA1&2 - Module 3 - PREHISTORCI ARCHITECTURE OF KERALA.pptx
HOA1&2 - Module 3 - PREHISTORCI ARCHITECTURE OF KERALA.pptxHOA1&2 - Module 3 - PREHISTORCI ARCHITECTURE OF KERALA.pptx
HOA1&2 - Module 3 - PREHISTORCI ARCHITECTURE OF KERALA.pptx
 
Online food ordering system project report.pdf
Online food ordering system project report.pdfOnline food ordering system project report.pdf
Online food ordering system project report.pdf
 
Computer Networks Basics of Network Devices
Computer Networks  Basics of Network DevicesComputer Networks  Basics of Network Devices
Computer Networks Basics of Network Devices
 
data_management_and _data_science_cheat_sheet.pdf
data_management_and _data_science_cheat_sheet.pdfdata_management_and _data_science_cheat_sheet.pdf
data_management_and _data_science_cheat_sheet.pdf
 
Generative AI or GenAI technology based PPT
Generative AI or GenAI technology based PPTGenerative AI or GenAI technology based PPT
Generative AI or GenAI technology based PPT
 
Thermal Engineering Unit - I & II . ppt
Thermal Engineering  Unit - I & II . pptThermal Engineering  Unit - I & II . ppt
Thermal Engineering Unit - I & II . ppt
 
Thermal Engineering -unit - III & IV.ppt
Thermal Engineering -unit - III & IV.pptThermal Engineering -unit - III & IV.ppt
Thermal Engineering -unit - III & IV.ppt
 

Temporal Anti-Aliasing

  • 1. Temporal Anti-Aliasing 1 Temporal Anti-Aliasing 목차 1. Temporal Anti-Aliasing 이란 2. 구현방식 3. 할톤수열(Halton Sequence) 4. Jittering 적용 5. 혼합 6. Ghosting 7. 동적씬에서의아티팩트해결 8. 마치며 9. Reference Temporal Anti-Aliasing 이란 Tmporal Anti-Aliasing(이하TAA)은공간축선안티에일리어싱(Spatial anti-aliasing)의일종으로과거프레임 의이미지를현재프레임의이미지에결합하여이미지의계단현상을제거하는기법입니다. TAA는다른AA기 법들과비교했을때적은비용을사용하여안티에일리어싱효과를얻을수있다는장점이있지만이전프레임 의이미지와결합하는과정에서흐릿한이미지를얻게되는경우가있습니다. ( 이를해결하기위해서추가로 Sharpen 필터를적용하는경우가있습니다. ) 여기서는간단한TAA의구현방식을살펴보도록하겠습니다. 구현방식 TAA는다음과같은순서로구현됩니다. 1. 매프레임에씬을그릴때마다스크린평면의각기다른방향으로위치를살짝이동하여씬을그립니다. ( Jittering 적용) 2. 이렇게렌더링된현재프레임의이미지와이전프레임들의이미지(= History buffer )를조합합니다. ( 혼 합) 3. 조합한이미지를Frame Buffer에복사합니다. 이후로각단계를좀더자세히살펴보도록하겠습니다. 할톤수열(Halton Sequence) 매프레임마다씬의위치를조금씩이동시키기위해TAA에서는할톤수열이라는것사용합니다. 할톤수열은 몬테카를로시뮬레이션등에서사용되는공간상의점을생성하는데사용되는수열로결정론적(= 같은입력에 항상같은출력값을가짐) 이며저불일치(low discrepancy)인수열입니다. 저불일치수열은기존숫자로부터 가능한멀리떨어져있는숫자를연속하여생성하기때문에군집화를방지합니다. 아래도표는할톤수열로생 성한2차원점과랜덤하게생성한2차원의점216개를서로비교한결과로저불일치수열의특징을보여줍니 다.
  • 2. Temporal Anti-Aliasing 2 랜덤하게생성한2차원점은다음과같은코드를통해생성하였습니다. std::random_device rd; std::mt19937 mt( rd() ); std::uniform_real_distribution<float> ud( 0.f, 1.f ); std::ofstream random( "random.txt" ); for ( int i = 0; i < 216; ++i ) { random << ud( mt ) << "t" << ud( mt ) << "n"; } 이제할톤수열을어떻게생성하는지살펴보겠습니다. 할톤수열은Radical inverse라는것에기초하여생성할 수있습니다. Radical inverse이무엇인지알아보기전에양의정수를특정기수(=기저, 밑, base)로나타내는 방법을살펴보겠습니다. 양의정수 는특정기수 를사용하여다음과같이나타낼수있습니다. 여기서 는 에서 사이의숫자입니다. 수식보다좀더알기쉬운예시를보자면2진수가있겠습니다. 양의정수13을2진수로표현하면( ) 가됩니다. 이를위의수식으로표현하면 가됩니다. 이식에 인것을확인할수있습니다. Radical inverse 함수 는기수 를통해나타낸양의정수 를소수점을기준으로반전시키는것으로[0, 1) 범위의분수로변환합니다. 즉양의정수13을기수2를통해Radical inverse를적용하면다음과같습니다. a b a = d (a)b i=1 ∑ m i i−1 d (a) i 0 b − 1 b = 2 11012 a = 1 ∗ 2 + 0 0 ∗ 2 + 1 1 ∗ 2 + 2 1 ∗ 23 d (a) = 0 1,d (a) = 1 0,d (a) = 2 1,d (a) = 3 1 ϕb b a ϕ (a) = b 0.d (a)d (a)...d (a) 1 2 m
  • 3. Temporal Anti-Aliasing 3 이를이용해 차원의할톤수열을만들려면각차원마다서로다른기수 를사용하면됩니다. 여기서 는반드 시서로소여야하므로소수를사용하게됩니다. TAA에서는스크린평면상에서물체를이동시킬것이므로2차원할톤수열을통해2차원의점을생성하면됩 니다. 즉 인쌍을생성합니다. 여기서 는좀더효율적으로계산할수있는데컴퓨터에서정수를이미2진수로표현하고있기때문에비 트를뒤집어주기만하면됩니다. uint32 ReverseBits( uint32 n ) { n = ( n << 16 ) | ( n >> 16 ); n = ( ( n & 0x00ff00ff ) << 8 ) | ( ( n & 0xff00ff00 ) >> 8 ); n = ( ( n & 0x0f0f0f0f ) << 4 ) | ( ( n & 0xf0f0f0f0 ) >> 4 ); n = ( ( n & 0x33333333 ) << 2 ) | ( ( n & 0xcccccccc ) >> 2 ); n = ( ( n & 0x55555555 ) << 1 ) | ( ( n & 0xaaaaaaaa ) >> 1 ); return n; } uint64 ReverseBits( uint64 n ) { uint64 hi = ReverseBits( static_cast<uint32>( n ) ); uint64 lo = ReverseBits( static_cast<uint32>( n >> 32 ) ); return ( hi << 32 ) | lo; } float Halton::RadicalInverse( uint32 baseIndex, uint64 a ) const { switch ( baseIndex ) { case 0: return static_cast<float>( ReverseBits( a ) * 0x1p-64 ); case 1: return ::RadicalInverse<3>( a ); default: assert( false ); break; } return 0.5f; } 부터는이방법을사용할수없기때문에정수를기수 로나눠가면서직접생성해줍니다. template <uint64 base> float RadicalInverse( uint64 a ) { constexpr float invBase = 1.f / base; uint64 reversedDigits = 0; float invBaseN = 1; while ( a ) { uint64 next = a / base; uint64 digit = a % base; reversedDigits = reversedDigits * base + digit; 0.1011 = 2 16 11 10 n b b x = a (ϕ (a),ϕ (a),ϕ (a),...ϕ (a)) 2 3 5 pn p = (ϕ (a),ϕ (a)) 2 3 ϕ (a) 2 ϕ (a) 3 b
  • 4. Temporal Anti-Aliasing 4 invBaseN *= invBase; a = next; } return std::min( reversedDigits * invBaseN, (float)0x1.fffffep-1 ); } 해당코드를통해생성한점은다음과같습니다. 0.5 0.333333 0.25 0.666667 0.75 0.111111 0.125 0.444444 0.625 0.777778 0.375 0.222222 0.875 0.555556 0.0625 0.888889 0.5625 0.037037 0.3125 0.37037 0.8125 0.703704 0.1875 0.148148 0.6875 0.481482 0.4375 0.814815 0.9375 0.259259 . . . Jittering 적용 생성한2차원할톤수열을이용해매프레임마다지터링을적용하여씬을그리도록합니다. 할톤수열은다음 과같이앞에서16개를골라상수로사용하도록하였습니다. static const int MAX_HALTON_SEQUENCE = 16; static const float2 HALTON_SEQUENCE[MAX_HALTON_SEQUENCE] = { float2( 0.5, 0.333333 ), float2( 0.25, 0.666667 ), float2( 0.75, 0.111111 ), float2( 0.125, 0.444444 ), float2( 0.625, 0.777778 ), float2( 0.375, 0.222222 ), float2( 0.875, 0.555556 ) , float2( 0.0625, 0.888889 ), float2( 0.5625, 0.037037 ), float2( 0.3125, 0.37037 ), float2( 0.8125, 0.703704 ), float2( 0.1875, 0.148148 ), float2( 0.6875, 0.481482 ), float2( 0.4375, 0.814815 ), float2( 0.9375, 0.259259 ), float2( 0.03125, 0.592593 ) }; 지터링은투영변환까지적용한위치에아래와같이적용합니다. 할톤수열은[0, 1)의구간을가지므로[-1, 1) 의구간으로변경한다음픽셀하나의크기가될수있도록프레임버퍼의크기로나눠줍니다.
  • 5. Temporal Anti-Aliasing 5 float4 ApplyTAAJittering( float4 clipSpace ) { #if TAA == 1 int idx = FrameCount % MAX_HALTON_SEQUENCE; // [0, 1) -> [-1, 1) -> 픽셀 하나 크기의 uv 좌표로 변경 float2 jitter = HALTON_SEQUENCE[idx]; jitter.x = ( jitter.x - 0.5f ) / ViewportDimensions.x * 2.f; jitter.y = ( jitter.y - 0.5f ) / ViewportDimensions.y * 2.f; clipSpace.xy += jitter * clipSpace.w; // Pixel Shader로 전달시 w로 나뉘므로 곱해준다. #endif return clipSpace; } 혼합 이제지터링이적용된이미지를과거프레임의이미지와섞어주면됩니다. A Survey of Temporal Antialiasing Techniques(behindthepixels.io/assets/files/TemporalAA.pdf) 에따르면TAA의혼합은다음과 같은단순한선형보간식에의해서이뤄집니다. 는 프레임의픽셀 에대한색상출력이며 는블렌딩가중치. 는 프레임에새롭게계산된색 상, 는지금까지혼합된이전프레임의색상입니다. 가중치수치 는과거색상과현재색상간의균형을맞추는데대부분의TTA 구현은고정된 를사용하며대체 로0.1이사용된다고합니다. 따라서다음과같이간단하게혼합할수있습니다. float4 main( PS_INPUT input ) : SV_Target0 { float3 historyColor = HistoryTex.Sample( HistoryTexSampler, input.uv ).rgb; float4 sceneColor = SceneTex.Sample( SceneTexSampler, input.uv ); // sceneColor.rgb * ( 1 - 0.9 ) + historyColor * 0.9 // sceneColor.rgb * 1.0 + historyColor * 0.9 float3 resolveColor = lerp( sceneColor.rgb, historyColor, 0.9 ); return float4( resolveColor, sceneColor.a ); } f (p) = n a ∗ s (p) + n (1 − a) ∗ f (π(p)) n−1 f (p) n n p a s (p) n n f (π(p)) n−1 a a
  • 6. Temporal Anti-Aliasing 6 TAA On TAA Off 적용전과비교했을때에일리어싱현상이개선된것을확인할수있습니다. 그런데이상태에서카메라를움직 여보면문제가발생합니다.
  • 8. Temporal Anti-Aliasing 8 고스팅현상은이전프레임의이미지를섞음으로인해서잔상과같은효과가생기는아티팩트를의미합니다. 이전프레임의이미지가유령처럼남아있다는의미로이렇게불립니다. 지금까지의방법은정적인씬에서는 잘동작하지만카메라나물체의위치변환이있는동적인씬에서는이전프레임의색상위치가변경되었는데 이를적절하게처리하지못하기때문에고스팅현상을방지할수없습니다. 고스팅현상을처리하는방식은다 양한데여기서는이를해결하기위한2가지방식을보겠습니다. 동적씬에서아티팩트해결 Velocity Buffer 첫번째는Velocity Buffer를도입하는것입니다. Velocity Buffer는현재프레임과이전프레임의픽셀간위치 차이를저장하고있는버퍼로이를이용하여현재프레임의픽셀에대한알맞는과거프레임의픽셀을샘플링 할수있도록텍스쳐uv를조정합니다. Velocity Buffer를구성해보겠습니다. 준비해야할것은이전프레임의월드, 카메라, 투영변환행렬입니다. 정 점셰이더에는해당행렬을가지고이전프레임의위치와현재프레임의위치를계산하여픽셀셰이더로전달 합니다. VS_OUTPUT main( VS_INPUT input ) {
  • 9. Temporal Anti-Aliasing 9 VS_OUTPUT output = (VS_OUTPUT)0; PrimitiveSceneData primitiveData = GetPrimitiveData( input.primitiveId ); output.curFramePosition = mul( float4( input.position, 1.0f ), primitiveData.m_worldMatrix ); output.curFramePosition = mul( float4( output.curFramePosition.xyz, 1.0f ), ViewMatrix ); output.curFramePosition = mul( float4( output.curFramePosition.xyz, 1.0f ), ProjectionMatrix ); output.worldNormal = mul( float4( input.normal, 0.f ), transpose( primitiveData.m_invWorldMatrix ) ).xyz; output.prevFramePosition = mul( float4( input.position, 1.0f ), primitiveData.m_prevWorldMatrix ); output.prevFramePosition = mul( float4( output.prevFramePosition.xyz, 1.0f ), PrevViewMatrix ); output.prevFramePosition = mul( float4( output.prevFramePosition.xyz, 1.0f ), PrevProjectionMatrix ); output.position = ApplyTAAJittering( output.curFramePosition ); return output; } 픽셀셰이더는전달받은위치를스크린의uv좌표로변경하여저장합니다. float2 CalcVelocity( float4 curFramePosition, float4 prevFramePosition ) { float2 curFrameUV = curFramePosition.xy / curFramePosition.w; curFrameUV = curFrameUV * 0.5f + 0.5f; curFrameUV.y = 1.f - curFrameUV.y; float2 prevFrameUV = prevFramePosition.xy / prevFramePosition.w; prevFrameUV = prevFrameUV * 0.5f + 0.5f; prevFrameUV.y = 1.f - prevFrameUV.y; return curFrameUV - prevFrameUV; } Output main( PS_INPUT input ) { Output output = (Output)0; output.depth = input.position.w / FarPlaneDist; float3 enc = SignedOctEncode( normalize( input.worldNormal ) ); output.packedNormal = float4( 0.f, enc ); output.velocity = CalcVelocity( input.curFramePosition, input.prevFramePosition ); return output; } 이제TAA 셰이더는Velocity Buffer에저장된uv값을사용하여현재프레임의픽셀에알맞는이전프레임의픽 셀을샘플링합니다. float4 main( PS_INPUT input ) : SV_Target0 { float2 velocity = VelocityTex.Sample( VelocityTexSampler, input.uv ); float2 previousUV = input.uv - velocity; float3 historyColor = HistoryTex.Sample( HistoryTexSampler, previousUV ).rgb; float4 sceneColor = SceneTex.Sample( SceneTexSampler, input.uv ); float3 resolveColor = lerp( sceneColor.rgb, historyColor, BlendWeight ); return float4( resolveColor, sceneColor.a ); } Velocity Buffer를적용한결과다음과같은결과를얻을수있습니다.
  • 10. Temporal Anti-Aliasing 10 붉은네모부분을보면고스팅현상이사라진것을확인할수있습니다. 하지만여전히잔상이발생하는부분 이있습니다. 색상Clamp 두번째는색상Clamp입니다. 만약이전프레임의픽셀색상이현재프레임의픽셀색상과유사하다면잔상현 상이발생할까요? 파란색에( R : 0, G : 0, B : 255 ) 약간흐린파란색( R : 0, G : 0, B : 240 )을섞는다고해 도그리티가나지않을거라예상할수있습니다. 색상Clamp는현재프레임의색상을기준으로이전프레임의 색상을조정하는방법입니다. 여기서는색상Clamp을위해현재프레임의상하좌우로이웃하는4픽셀을추가로샘플링하여색상의최소최 대범위를계산합니다. float3 left = SceneTex.Sample( SceneTexSampler, input.uv, int2( -1, 0 ) ).rgb; float3 right = SceneTex.Sample( SceneTexSampler, input.uv, int2( 1, 0 ) ).rgb; float3 top = SceneTex.Sample( SceneTexSampler, input.uv, int2( 0, -1 ) ).rgb; float3 bottom = SceneTex.Sample( SceneTexSampler, input.uv, int2( 0, 1 ) ).rgb; float3 lower = min( sceneColor, min( min( left, right ), min( top, bottom ) ) ); float3 upper = max( sceneColor, max( max( left, right ), max( top, bottom ) ) ); 그리고이lower, upper 색상범위로이전프레임의색상을조정합니다. historyColor = clamp( historyColor, lower, upper );
  • 11. Temporal Anti-Aliasing 11 색상Clamp를적용한TAA 셰이더의전체모습은다음과같습니다. float4 main( PS_INPUT input ) : SV_Target0 { float2 velocity = VelocityTex.Sample( VelocityTexSampler, input.uv ); float2 previousUV = input.uv - velocity; float3 historyColor = HistoryTex.Sample( HistoryTexSampler, previousUV ).rgb; float4 sceneColor = SceneTex.Sample( SceneTexSampler, input.uv ); float3 left = SceneTex.Sample( SceneTexSampler, input.uv, int2( -1, 0 ) ).rgb; float3 right = SceneTex.Sample( SceneTexSampler, input.uv, int2( 1, 0 ) ).rgb; float3 top = SceneTex.Sample( SceneTexSampler, input.uv, int2( 0, -1 ) ).rgb; float3 bottom = SceneTex.Sample( SceneTexSampler, input.uv, int2( 0, 1 ) ).rgb; float3 lower = min( sceneColor, min( min( left, right ), min( top, bottom ) ) ); float3 upper = max( sceneColor, max( max( left, right ), max( top, bottom ) ) ); historyColor = clamp( historyColor, lower, upper ); float3 resolveColor = lerp( sceneColor.rgb, historyColor, BlendWeight ); return float4( resolveColor, sceneColor.a ); } 이를적용하면다음과같이고스팅현상을개선할수있습니다. https://s3-us-west-2.amazonaws.com/secure.notion-static.com/4fbdd80c-15a1-4dea-9bff-2016 42823616/2022-10-12_23_12_55.mp4 올바르지않은과거프레임의픽셀을조정하는방식은이외에도다양한데게임‘인사이드’의GDC 자료를보면 3x3 범위의이웃픽셀에대해서과거프레임의픽셀을clipping하는방법을사용한것을볼수있습니다. 마치며… 준비한내용은여기까지입니다. 이내용은훌륭한TAA 튜토리얼글인 https://sugulee.wordpress.com/2021/06/21/temporal-anti-aliasingtaa-tutorial/ 를참고하여Direct3D11 을사용한개인프로젝트의코드를기반으로작성되었습니다. 전체코드는아래의변경점에서 https://github.com/xtozero/SSR/commit/8f732f29d23063c914e0285120abaed024f9bba3 Source/RenderCore/Private/Renderer/TemporalAntiAliasingRendering.cpp Source/Shaders/Private/TemporalAntiAliasing/PS_TAAResolve.fx Source/Shaders/Private/VS_DepthWrite.fx Source/Shaders/Private/PS_DepthWrite.fx 등의파일을참고하시면됩니다.