AMD의 TressFX The Fast and The Furry by Nicolas Thibieroz 의 한글 번역
원본 http://www.slideshare.net/DevCentralAMD/tress-fx-the-fast-and-the-furry-nicolas-thibieroz
1. TRESSFX
빠르게 진짜 털 같이 만들기
AMD AND MICROSOFT DEVELOPER DAY, JUNE 2014, STOCKHOLM
NICOLAS THIBIEROZ
WORLDWIDE GAMING ENGINEERING MANAGER, AMD
2. 개인적으로 공부하다 적은 것이므로 영어&이해 부족으로 인한 오역을 감안하세요
틀린 부분이나 혹 문제가 될 부분이 있다면 해강(questionname@naver.com) 알려주시면
감사하겠습니다
붉은 색은 개인적으로 적어놓은 메모입니다
원본은 여기입니다
(http://www.slideshare.net/DevCentralAMD/tress-fx-the-fast-and-the-furry-nicolas-thibieroz)
관심이 생기신 분들은 후속 자료도 있으니 더 보셔도 좋을 듯 합니다
(http://www.slideshare.net/DevCentralAMD/grass-fur-and-all-things-hairy-amd-at-gdc14)
3. TRESSFX: 차세대 머리/털 랜더링
지금이 차세대 품질을 위한 시간이다
툼레이더는 차세대 머리털을 개척했다
‒ PS4/XB1 포함
유저들은 차세대 타이틀의 품질 수준을 기대하고 있다
너는 이것에 대해 생각해 볼 필요가 있다!
| TRESSFX THE FAST AND THE FURRY | AMD AND MICROSOFT GAME 3 DEVELOPER DAY - JUNE 2 2014, STOCKHOLM
4. 좋은 머리/털을 만드는 것은 무엇일까?
Basic Rendering Antialiasing Antialiasing
| TRESSFX THE FAST AND THE FURRY | AMD AND MICROSOFT GAME 4 DEVELOPER DAY - JUNE 2 2014, STOCKHOLM
+ Self Shadowing
Antialiasing
+ Self Shadowing
+ Transparency
Demo
세가지 구성 요소들 모두 높은 품질을 보장하기 위해 필요하다
특히 투명성은 차세대 비주얼에 필수다
‒ OIT(반투명 폴리곤을 정렬 없이 랜더링) 솔루션이 필요하다
(http://en.wikipedia.org/wiki/Order-independent_transparency)
5. ISOLINE TESSELLATION FOR HAIR/FUR? 1/2
Isoline 테셀레이션은 두가지 테셀레이션 요소를 가지고 있다
‒ 첫 번째는 라인의 밀도다 (호출 당 라인)
‒ 두 번째는 라인의 세부 사항이다 (라인 당 segments(조각))
이론적으로 쉽게 LOD 시스템을 제공한다
‒ 거리를 기반으로 두 테셀레이션 요소를 증가시킴으로써 라인의 거리와 세부사항을 다양하게 한다
쉽게 말해 주어진 선분에 일정 거리를 두고 복제한 등치선(ISOLINE)을 생성한다
http://blog.naver.com/sorkelf/40190757674
Tess = (1,1) Tess = (2,1) Tess = (2,2) Tess = (2,3) Tess = (3,3)
| TRESSFX THE FAST AND THE FURRY | AMD AND MICROSOFT GAME 5 DEVELOPER DAY - JUNE 2 2014, STOCKHOLM
6. ISOLINE TESSELLATION FOR HAIR/FUR? 2/2
실제 이 시나리오에서 ISOLINE 테셀레이션은 효율성이 낮은 편이다
라인이 항상 1 픽셀 두껍다
‒ 삼각형의 가장자리를 매끄럽게 처리할 지오메트리 쉐이더가 필요하다
‒ 성능에 큰 영향을 준다!
‒ 이에 대한 대안은 MSAA(Multisample anti-aliasing)를 활성화하는 것이다
‒ 대부분의 엔진에서 크게 성능에 영향을 주는 원인이 되어 처리가 지연된다
‒ 부드러운 가장자리를 MSAA 없이 하는건 = 거지같은 퀄리티!
결론 : 순수한 버텍스 셰이더는 빠르다
‒ 곡률은 거의 문제가 되지 않는다 (정점에 의존하고 / 제작 시간 걸려봐야 가닥일 뿐이다)
‒ 만약 버텍스 쉐이더에서 완료할 수 있다면 LOD를 통해 이익을 얻는 것이 필요하다
| TRESSFX THE FAST AND THE FURRY | AMD AND MICROSOFT GAME 6 DEVELOPER DAY - JUNE 2 2014, STOCKHOLM
7. TRESSFX RENDERING PIPELINE
TressFX 2는 최적의 성능을 위해 지연된 접근 방식(디퍼드 랜더링)을 사용
세가지 단계로 이루어진다
STEP 1: 헤어 시뮬레이션
STEP 2: 버퍼에 조각의 성질들을 저장
STEP 3: 조각의 성질들을 가져와서, 정렬하고, 쉐이딩과 랜더할 것을 고른다
‒ K-frontmost Fragment (조각)들은 풀쉐이딩
‒ “Tail“ 조각은 단순한 빛 방정식과 그림자 알고리즘을 사용하여 쉐이드 된다
| TRESSFX THE FAST AND THE FURRY | AMD AND MICROSOFT GAME 7 DEVELOPER DAY - JUNE 2 2014, STOCKHOLM
8. TRESSFX RENDERING PIPELINE
STEP 1: 헤어 시뮬레이션
Simulation
parameters
CS
CCSS
Input Geometry
(SRV)
Post-simulation
geometry (UAV)
Pre-simulation line
segments (model space)
Post-simulation line
segments (world space)
| TRESSFX THE FAST AND THE FURRY | AMD AND MICROSOFT GAME 8 DEVELOPER DAY - JUNE 2 2014, STOCKHOLM
Simulation compute shaders
Edge length 제약
Local shape 제약
Global shape 제약
털을 위해 항상 필요하지는 않다
Model Transform
Collision Shape
털을 위해 항상 필요하지는 않다
외력 (바람, 중력, 등등.)
입력 모델은 line segments (선분)의 집합이다 (각각의 세그먼트는 최대 64 개의 버텍스들로 구성)
최적화 시물레이션 성능을 위해 “master strands(가닥)” 와 “slave strands” 를 선택적으로 나눌 수 있다
‒ 오직 master strands만 시뮬레이션 했다 (예 1:4 비율)
‒ master strand 의 시뮬레이션 결과에 노이즈를 추가해 Slave strands에 사용할 수 있다
‒ 전체를 다 시뮬레이션 하는 것과 거의 차이가 없지만, 훨씬 더 나은 시뮬레이션 성능을 보여준다!
‒ master : Slave 시뮬레이션 비율은 더 나은 성능을 위해 거리를 다르게 할 수 있다
Demo
9. TRESSFX RENDERING PIPELINE
STEP 2: 버퍼에 조각의 성질들을 저장
4
5
3 2
VS
2
1
0 1
0
삼각형으로
뽑아낸다
World
space
Index
Buffer
Indexed triangle list
| TRESSFX THE FAST AND THE FURRY | AMD AND MICROSOFT GAME 9 DEVELOPER DAY - JUNE 2 2014, STOCKHOLM
10. LINE SEGMENT EXTRUSION INTO TRIANGLES
고품질의 머리카락이나 털 렌더링을 위해 정점의 많은 부분들을 조사한다!
‒ 지오메트리 프로세싱은 따라서 상당한 병목이 될 수 있다
이전 버전의 TressFX 출력은 지오메트리 쉐이더에서 수행되었고(하지 마라!) VS에서 draw()(단일)로 그렸다
순수하게 VS 에서 처리하고 미리 계산 된 인덱스 버퍼로 훨씬 빠른 성능을 얻었다
‒ 버텍스 캐쉬 사용을 최대한!
Draw() method
2
1
0
11
7,10
3,5
8,9
6
2,3
0
| TRESSFX THE FAST AND THE FURRY | AMD AND MICROSOFT GAME 10 DEVELOPER DAY - JUNE 2 2014, STOCKHOLM
DrawIndexed() method
2
1
4
5
3 2
0 1
0
Line segments Expanded quads
Indexed triangle list = { ( 0, 1, 2 ), (2, 1, 3 ), ( 2, 3, 4 ), (4, 3, 5 ), ( … ) };
1,4
Line segments Expanded quads
Triangle list = { ( 0, 1, 2 ), ( 3, 4, 5 ), ( 6, 7, 8 ), (9, 10, 11 ), ( … ) };
11. TRESSFX RENDERING PIPELINE
STEP 2: 버퍼에 조각의 성질들을 저장
Antialiasing
동일한
clip space
4
5
3 2
VS PS
2
1
0 1
0
삼각형으로
뽑아낸다
World
space
Index
Buffer
Indexed triangle list
| TRESSFX THE FAST AND THE FURRY | AMD AND MICROSOFT GAME 11 DEVELOPER DAY - JUNE 2 2014, STOCKHOLM
12. ANTIALIASING
안티 엘리어싱 (일명 "적용 범위")에 사용하는 분석 방법이다
‒ 이것은 절대 MSAA가 아니다!
머리카락(가닥) 삼각형과 변환한 알파값을 가지고 가장자리 픽셀
범위를 계산한다
픽셀 중심에서 가닥축까지의 거리에 따라 알파 값을 페이드 아웃한다
에밀 페르손의 Phone-Wire 안티 앨리어싱이랑 유사한 원리다
(Just Cause2)
http://www.humus.name/Articles/Persson_GraphicsGemsForGames.pdf
전선줄 같은 미세한 선도 끊김없이 랜더링 하기 위해 Phone-Wire다
| TRESSFX THE FAST AND THE FURRY | AMD AND MICROSOFT GAME 12 DEVELOPER DAY - JUNE 2 2014, STOCKHOLM
13. TRESSFX RENDERING PIPELINE
STEP 2: 버퍼에 조각의 성질들을 저장
Antialiasing
동일한
clip space
2
0 1
4
| TRESSFX THE FAST AND THE FURRY | AMD AND MICROSOFT GAME 13 DEVELOPER DAY - JUNE 2 2014, STOCKHOLM
depth
tangent
coverage
next
VS PS
World
space
Null RT
Stencil
PPLL
UAV
Head
UAV
Index
Buffer
Indexed triangle list
1
3 2
0
5
삼각형으로
뽑아낸다
14. PER-PIXEL LINKED LISTS
Head UAV
‒ PPLL UAV의 링크드 리스트에 각각의 픽셀 위치가 있는 "헤드 포인터"가 있다
PPLL UAV
‒ 새로운 fragments(조각)가 렌더링되는 동안에, PPLL안에 다음 오픈 위치가 추가된다(UAV 카운터를 사용하여)
‒ 링크로 생성 된 fragments(조각) 포인터는 헤드 포인터에 의해 지시된다
‒ 헤드 포인터는 새로운 fragments (조각)을 가리키게 된다
// 현재의 픽셀 수를 검색하고 카운터를 증가시킨다
uint uPixelCount = LinkedListUAV.IncrementCounter();
uint uOldStartOffset;
// LinkedListHead 텍스쳐에서 인덱스를 확인해 해당하는 픽셀 위치를 교환한다
InterlockedExchange(LinkedListHeadUAV[address], uPixelCount, uOldStartOffset);
// 조각 및 링크 버퍼의 끝부분에 새로운 요소를 추가한다
Element.uNext = uOldStartOffset;
LinkedListUAV[uPixelCount] = Element;
| TRESSFX THE FAST AND THE FURRY | AMD AND MICROSOFT GAME 14 DEVELOPER DAY - JUNE 2 2014, STOCKHOLM
depth
tangent
coverage
next
PPLL
UAV
Head
UAV
메모리 요구 사항은 클 수 있다!
‒ Width * Height * Average overdraw * sizeof (PPLL structure)
‒ 메모리 제약이 있는 상황에서 바둑판 식 배열 방식을 사용할 수 있다
15. TRESSFX RENDERING PIPELINE
STEP 3: 조각의 성질들을 가져와서, 정렬하고, 쉐이딩과 랜더할 것을 고른다
Head
UAV
PPLL
UAV
VS PS
Stencil
Lighting
Full Screen
Quad/Triangle
| TRESSFX THE FAST AND THE FURRY | AMD AND MICROSOFT GAME 15 DEVELOPER DAY - JUNE 2 2014, STOCKHOLM
16. LIGHTING
다른 옵션도 사용 가능하다
‒ Kajiya-Kay hair lighting model
라이팅을 노멀이 아닌 탄젠트 값으로 계산 SIGGRAPH 1989
https://www.cs.drexel.edu/~david/Classes/CS586/Papers/p271-kajiya.pdf
‒ Marshner model
머리카락 내부 산란, 투과나 반사까지 계산 SIGGRAPH 2003
http://www.graphics.stanford.edu/papers/hair/hair-sg03final.pdf
‒ 그 밖의 또 다른 것이라도 좋다!
Fragment (조각) 특성에 대한 저장소의 요구 사항은 네가
선택해 제한할 수 있다!
TressFX 샘플은 두개의 하이라이트를 렌더링 할 때 Marchner
기술의 근사치를 사용한다
‒ 특별한 조각 속성 : 깊이, 접선 벡터
http://www.cs.cornell.edu/~srm/cv.html
이 사람이 발표한 헤어기술인듯 하다 자료 링크
| TRESSFX THE FAST AND THE FURRY | AMD AND MICROSOFT GAME 16 DEVELOPER DAY - JUNE 2 2014, STOCKHOLM
Primary Highlights
Secondary Highlights
17. TRESSFX RENDERING PIPELINE
STEP 3: 조각의 성질들을 가져와서, 정렬하고, 쉐이딩과 랜더할 것을 고른다
Head
UAV
PPLL
UAV
VS PS
Stencil
Lighting Shadows
Full Screen
Quad/Triangle
| TRESSFX THE FAST AND THE FURRY | AMD AND MICROSOFT GAME 17 DEVELOPER DAY - JUNE 2 2014, STOCKHOLM
18. SHADOWS
세가지 다른 경우가 있다
머리카락 자가 그림자(self-shadowing)
‒ 필수적인 요소로 차세대 볼륨메트릭 퀄리티를 보여준다
‒ 간략한 Deep Shadow Map 기법
(테크닉 : 그림자맵과 fragment의 깊이의 차이를 가져온 후,
이 차이가 큰것이 더 어두운 그림자다. 또한 추가 변수를 사용한다)
머리카락 그림자가 몸과 환경에 영향을 주도록
‒ 몸: 매우 부드럽게 보이고, 가까운 거리인 것처럼 보이게 해야 한다(쉐도우맵에 블러)
‒ 환경: cascaded shadow map로부터 헤어 영역을(간단하게 가능) 랜더링
CSM http://msdn.microsoft.com/en-gb/library/windows/desktop/ee416307%28v=vs.85%29.aspx
환경 그림자에 머리카락이 영향을 받도록
‒ 헤어 fragment(조각) 랜더링될 때, 그림자 환경맵 샘플
| TRESSFX THE FAST AND THE FURRY | AMD AND MICROSOFT GAME 18 DEVELOPER DAY - JUNE 2 2014, STOCKHOLM
19. TRESSFX RENDERING PIPELINE
STEP 3: 조각의 성질들을 가져와서, 정렬하고, 쉐이딩과 랜더할 것을 고른다
Head
UAV
PPLL
UAV K frontmost fragment:
VS PS
Stencil
full shading, sorting
and manual blending
Lighting Shadows
Full Screen
Quad/Triangle
| TRESSFX THE FAST AND THE FURRY | AMD AND MICROSOFT GAME 19 DEVELOPER DAY - JUNE 2 2014, STOCKHOLM
Tail fragments:
cheap shading,
no sorting and
manual blending
20. FRAGMENT 쉐이딩 선별
이것이 코드의 핵심적인 부분이다
// 헤드 포인터로부터 링크드리스트의 시작지점을 얻는다
uint pointer = LinkedListHeadSRV[In.vPosition.xy];
// PPLL로부터 KBuffer[]로 첫번째 K fragments를 복사
NODE Kbuffer[KBUFFER_SIZE];
for(int p=0; p<KBUFFER_SIZE; p++)
{
if (pointer != NULLPOINTER)
{
kBuffer[p] = LinkedListSRV[pointer];
pointer = LinkedListSRV[pointer].uNext;
}
}
// 링크드리스트의 나머지 부분으로 이동하고, k fragments의 가장 근접한 부분 유지
// 그러나 정렬하지는 않는다
[allow_uav_condition]
for(int l=0; l < g_iMaxFragments; l++)
{
if(pointer == NULLPOINTER) break;
int id = 0;
float max_depth = 0;
// 배열의 가장 깊은 노드를 찾는다
[unroll]for(int i=0; i<KBUFFER_SIZE; i++)
{
float fDepth = kBuffer[i].depth;
if(max_depth < fDepth)
{
max_depth = fDepth; id = i;
}
}
| TRESSFX THE FAST AND THE FURRY | AMD AND MICROSOFT GAME 20 DEVELOPER DAY - JUNE 2 2014, STOCKHOLM
// 만약 링크드리스트 노드가 지역배열의 깊은 곳보다 가까운 경우
// 링크드 리스트를 지역배열의 노드로 교체
NODE Node = LinkedListSRV[pointer];
if (max_depth > Node.depth)
{
SWAP(Node, Kbuffer[i]);
}
// K closest fragments가 노드에 없다면 간단한 쉐이딩과 그림자를 적용한다
fragmentcolor = ComputeSimpleShading(Node);
// 순서에서 벗어난 것들을 블렌딩
fcolor.xyz = mad(-fcolor.xyz, fragmentColor.w, fcolor.xyz) +
fragmentColor.xyz * fragmentColor.w;
fcolor.w = mad(-fcolor.w, fragmentColor.w, fcolor.w);
// 다음 노드 포인터를 검색한다
pointer = LinkedListSRV[pointer].uNext;
}
// 뒤에서부터 k nearest layers의 fragments을 블랜드(혼합), 여기서 k = KBUFFER_SIZE 다
for(int j=0; j<KBUFFER_SIZE; j++)
{
int id = 0;
float max_depth = 0;
// 배열의 가장 깊은 노드를 찾는다
for(int i=0; i<KBUFFER_SIZE; i++)
{
float fDepth = kBuffer[i].depth;
if(max_depth < fDepth)
{
max_depth = fDepth; id = i;
}
}
// 다음 검색에서 노드에서 벗어난 곳을 가져온다
Node = KBuffer[id]; KBuffer[id] = (NODE)0;
// 높은 품질의 쉐이딩과 그림자 적용
fragmentcolor = ComputeHighQualityshading(Node);
// fragment 색을 블렌드
fcolor.xyz = mad(-fcolor.xyz, fragmentColor.w, fcolor.xyz) +
fragmentColor.xyz * fragmentColor.w;
fcolor.w = mad(-fcolor.w, fragmentColor.w, fcolor.w);
}
return fcolor;
21. TRESSFX RENDERING PIPELINE
STEP 3: 조각의 성질들을 가져와서, 정렬하고, 쉐이딩과 랜더할 것을 고른다
Head
UAV
PPLL
UAV
VS PS
Stencil
| TRESSFX THE FAST AND THE FURRY | AMD AND MICROSOFT GAME 21 DEVELOPER DAY - JUNE 2 2014, STOCKHOLM
Render target
K frontmost fragment:
full shading, sorting
and manual blending
Lighting Shadows
Full Screen
Quad/Triangle
Tail fragments:
cheap shading,
no sorting and
manual blending
22. TRESSFX PERFORMANCE
FAST AND FURRY
높은 수의 fragments는 퀄리티를 위해 요구된다
주요 병목은 모든 fragments를 쉐이딩 할때 나타난다
‒ 픽셀당 링크드 리스트를 모두 방문하지 마라!
선택적 쉐이딩할 경우 상당한 속도를 얻고, 퀄리티와 맞바꿔야할 부분은 드물거나 무시해도 좋을 수준이다
Technique Cost
Out of order, no shading 1.31 ms
Out of order, shading 2.80 ms
Deferred PPLL, selective shading 2.13 ms
거리조정 쉐이딩과 LOD 시뮬레이션은 성능을 더 개선시켜준다
Simulation LOD
Shading LOD
Distance Shading LOD
Disabled
Shading LOD
Enabled
Close range 3.26 ms 3.26 ms
Medium range 3.23 ms 1.77 ms
Long range 2.52 ms 0.64 ms
| TRESSFX THE FAST AND THE FURRY | AMD AND MICROSOFT GAME 22 DEVELOPER DAY - JUNE 2 2014, STOCKHOLM
Shading cost is
~ 1.5 ms
24% faster
Fur model with ~130,000 fur strands
Running on AMD Radeon 7970 @ 1080p
Distance Sim LOD
Disabled
Sim LOD
Enabled
Close range 1.01 ms 1.01 ms
Medium range 1.01 ms 0.70 ms
Long range 1.01 ms 0.37 ms
“K frontmost fragments” 값은 거리에 따라 반비례 한다
23. CONCLUSION AND QUESTIONS?
실시간으로 차세대 머리 / 털을 보는 것이 지금 가능합니다!
Fast:
‒ master/slave 비율을 가변적으로 계산하는 시뮬레이션
‒ 버텍스 쉐이더에서 삼각형 선분을 뽑아낸다 (테셀레이션 + 지오메트리 아님)
‒ 디퍼드 랜더링과 선택적 쉐이딩
‒ 거리 기반의 쉐이딩 및 시뮬레이션 LOD
‒ 최적화 된 쉐이더!
Furry:
TressFX 2 SDK 샘플, 코드와 문서 전체에 자유롭게 사용해볼 수 있다
http://developer.amd.com/tools-and-sdks/graphics-development/amd-radeon-sdk/
| TRESSFX THE FAST AND THE FURRY | AMD AND MICROSOFT GAME 23 DEVELOPER DAY - JUNE 2 2014, STOCKHOLM
nicolas.thibieroz@amd.com @NThibieroz
Simplified Deep Shadow Map technique: take the difference in depth from shadow map depth and fragment depth. The larger this difference the deeper (darker) the shadow. Also uses additional variables.