2. CRYTEK의 GDC2005 자료
• 개인적으로 공부하다 적은 것이므로 영어&이해 부족으로 인한 오역을 감안하세요
• 틀린 부분이나 혹 문제가 될 부분이 있다면 해강(questionname@naver.com)으로
알려주시면 감사하겠습니다
• 붉은 색은 개인적으로 적어놓은 메모입니다 틀릴 수도 있어요
• 원본은 여기입니다
• http://www.crytek.com/cryengine/presentations/far-cry-and-dx9
3. Far Cry는 최신 DX9 기능을 사용한다
• Shader Models 2.x / 3.0
- vertex textures와 dynamic flow control은 제외
• Geometry Instancing
• Floating-point render targets
4. Dynamic flow control* in PS
• 우리는 궁극적으로 하나의 패스에 여러개의 조명을
통합하기를 원한다…
float3 finalCol = 0;
float3 diffuseCol = tex2D( diffuseMap, IN.diffuseUV.xy );
float3 normal = mul( IN.tangentToWorldSpace,
tex2D( normalMap, IN.bumpUV.xy ).xyz );
for( int i = 0; i < cNumLights; i++ )
{
float3 lightCol = LightColor[ i ];
float3 lightVec = normalize( cLightPos[ i ].xyz –
IN.pos.xyz );
// …
// Attenuation, Specular, etc. calculated via if(
const_boolean )
// …
float nDotL = saturate( dot( lightVec.xyz, normal ) );
final += lightCol.xyz * diffuseCol.xyz * nDotL * atten;
}
return( float4( finalCol, 1 ) );
* Dynamic flow control는 동적 코드 분기(ex : break)
Shader3.0에서 24, 4.0부터 완전지원
5. Dynamic flow control in PS
• 현실 세계에 온 것을 환영한다…
– Dynamic indexing은 오직input registers에서만허용;
상수레지스터와루프안의인덱스를통해라이트
데이터가 통과하는것을방지
– 입력레지스터를통해라이트정보가 통과되면,
그것들은 충분하지않기때문에 제대로실현
불가능하다(오직 10개* )
– 동적분기는무료가아니다
*3.0 기준 레지스터 제한 10
http://msdn.microsoft.com/en-us/
library/bb172920%28v=VS.85%29.aspx
6. Loop unrolling*
• 우리는 동적 분기와 루프를 사용하지 않기로 선택했다
• 대신 정적 분기를 사용하고, 루프를 풀어서 대신했다
• Far Cry의 기존 쉐이더 프레임워크와 잘 작동한다
• 쉐이더는 다른 light masks를 위해 미리 컴파일 한다
– 0-4개의패스당동적라이트
– 3개의다른라이트타입(spot, omni(ex:전구), directional)
– 2개의라이트당수정타입(specular only, occlusion map(물체가빛을막아생김)
• 4개의 조명을 사용할 때 loop unrolling 후 160지침
(지나치게 긴 쉐이더)이 발생할 수 있다
– ps_2_0에서너무길게작성
– ps_2_a, ps_2_b and ps_3_0에서는괜찮다!
• 런타임에 뻑나는걸 방지하기 위해, 쉐이더 캐쉬를 미리 확보
* 루프를 풀어쓰는 기법 (예 : for(int i = 0; i < 100; ++I) -> for(int i = 0; i < 50; i += 2)
분기를 줄이고, cache hit 비율을 높여주는 효과가 있다
레지스터 사용량이 증가하는건 단점
정상적인 코드에 대한 최적화로 고려되는 작업이므로 무분별한 사용은 금물
http://en.wikipedia.org/wiki/Loop_unrolling
7. 어떻게 쉐이더 캐쉬를 작업했나
• 특정 쉐이더에 따라 다르다:
1) 재질 종류
(e.g. skin, phong, metal)
2) 재질 사용 항목
(e.g. bump-mapped, specular)
3) 특정 환경
(e.g. light mask, fog)
8. 어떻게 쉐이더 캐쉬를 작업했나
• Cache access:
– 객체가 랜더링할때이미 쉐이더핸들을 가지고 있나? 그것들을사용해라!
– 그렇지 않다면메모리에서쉐이더를찾아봐라
– 만약 하드디스크에서로드에실패하면,(다음)
– 만약 하드디스크에저장된백업에서VS/PS 생성에 실패한다면, (다음)
– 마지막으로객체의 쉐이더핸들을 저장한다
• 이상적인 해결책은 아니다, 그러나
– 기존의 하드웨어에서꽤 잘 작동한다
– assets의 변경 없이 손쉽게 통합시킬수 있었다
• 캐쉬를 효율적으로 써야…
– HD에 미리 캐쉬된 파일 같은 것들이 존재해야모든 쉐이더의통합이가능
• 즉시사용할경우쉐이더컴파일에필요한시간때문에맛이간다!
– 그러나, 캐쉬를 계속 유지하는것은 번거로운일이다
10. Geometry Instancing
• 오브젝트의 인스턴스를 n만큼 랜더링할 때 n-1의 드로우콜
비용이 절약될 가능성이 있다*
• Far Cry는 식물의 랜더링 속도를 올리기 위해 주로 사용했다
• 인스턴스 속성당:
– Position
– Size
– Bending info
– Rotation (필요할때만)
• 인스턴스 속성의 수를 줄이는! 두가지 방법:
– 버텍스쉐이더상수
• 100개 이상의폴리곤을가지고있는 오브젝트에사용
– 속성을연속된열 (stream) 로 만든다
• 작은 오브젝트에사용 (sprites, impostors)
* 인스턴싱은 동일한 데이터를 가지고 여러 사본을 만들어 랜더링
하는 방법이다. n-1의 비용이 절약된다는 말은 10개의 오브젝트를
찍는다고 했을 때 10번의 호출이 인스턴싱을 통해 최초 1번만 들 수
있다는 이야기다
11. VS 상수안의 인스턴스 속성
• 많은 숫자의 폴리곤을 가진 오브젝트를 위한
최고의 방법
• 인스턴스 인덱스를 연속적인 열(stream)로 넣어
덧붙인다
• SetStreamSourceFrequency를 사용하여 다음과
같이 지오메트리 인스턴싱에 설정한다…
SetStreamSourceFrequency( geomStream,
D3DSTREAMSOURCE_INDEXEDDATA | numInstances );
SetStreamSourceFrequency( instStream,
D3DSTREAMSOURCE_INSTANCEDATA | 1 );
• SSSF(위함수)가 완료되면 당신은 버텍스 스트림의
빈도를 재설정 해야 한다 ( strNum, 1 )!
12. VS 상수로 만들어낸
matMVP와 변환된 버텍스로부터
VS 속성 (위치 & 크기) 들을 분석해낸다
const float4x4 cMatViewProj;
const float4 cPackedInstanceData[ numInstances ];
float4x4 matWorld;
float4x4 matMVP;
int i = IN.InstanceIndex;
matWorld[ 0 ] = float4( cPackedInstanceData[ i ].w, 0, 0,
cPackedInstanceData[ i ].x );
matWorld[ 1 ] = float4( 0, cPackedInstanceData[ i ].w, 0,
cPackedInstanceData[ i ].y );
matWorld[ 2 ] = float4( 0, 0, cPackedInstanceData[ i ].w,
cPackedInstanceData[ i ].z );
matWorld[ 3 ] = float4( 0, 0, 0, 1 );
matMVP = mul( cMatViewProj, matWorld );
OUT.HPosition = mul( matMVP, IN.Position );
13. 인스턴스 속성 stream(열)
• 폴리곤이 많지 않은 오브젝트를 위한 최고의 방법
• 인스턴스 데이터를 stream에 추가해 넣는다
• 버텍스 스트림 설정이 완료되면 다시 이전으로
되돌린다
19. High Dynamic Range Rendering*
• A16B16G16R16F 랜더 타겟 포멧 사용
• Alpha blending과 filtering은 필수다
• 후처리를 위한 통합 솔루션
• 후처리에 큰 영향을 주는 것들의
전체범위를 대체
(glare(눈부심), flares(불꽃))
* HDR 참고
http://www.slideshare.net/agebreak/ndc12-hdr
20. HDR – 구현
• Far Cry의 HDR 표준 접근 방법
– Kawase’s bloom filters*
– Reinhard’s tone mapping operator
– See DXSDK sample
• Performance hint
– 후처리를 위해컬러를RG, BA로 색을나눈뒤,
G16R16F포멧의 두MRT로읽어들여라. 일부
카드에서 더 효율적으로캐시를 처리한다
*GDC2004 - Practical Implementation of High Dynamic Range Rendering
GDC2003도 있다 뒤에 기록
21. Bloom from [Kawase03]
• 반복적으로 작은 블러 필터를 적용한다*
• 원본 이미지와 bloom을 합성한다
– 이상적으로는 HDR 공간에서 바로 tone mapping
*전체를 blur하기엔 부하가 크기에 축소 버퍼를 반복적으로 사용한다
이 방법으로 넓은 범위를 더 빠르고, 높은 품질로 blur 할 수 있다
22. 필터 크기가 각 패스마다 증가
픽셀이 랜더링 되는 지점
텍스처 샘플링 지점
1st pass
2nd pass
3rd pass
From [Kawase03]
25. [Reinhard02] – Tone Mapping*
1) scene 휘도를 계산
GPU에서 log()값을 샘플링 완료
1X1 다운스케일링, exp()(지수함수)로 계산
2) 평균 휘도 α를 목표로 확장
3) 톤맵핑 연산자 적용
• 휘도값을 Lumavg 의 값으로 천천히 맞춰가면서 2와 3의 단계에 따라 Lumavg
으로 대체해 빛의 적응을 시뮬레이션 한다
• 자세한 내용은 “Tone Reproduction In Interactive Applications” 라는
Reinhard의 세션에 참석해 봐라
*HDR값을 LDR 영역 값으로 돌려주는 것이 톤맵핑이다
LDR의 부족한 출력영역을 보정해 보다 리얼한 표현이 가능해진다
http://www.cs.utah.edu/~reinhard/cdrom/
26. HDR – 주의사항
• 현재 FSAA(Full Screen Anti-Aliasing)는 사용하지 않는다
• 매우 느린 채우기 속도
• float buffer blending 지원 필요
• HDR관련 제작1 :
– Light maps
– Skybox
1) 프로토 타입을 위해 우리는 실제로 라이트맵 생성기 를
수정해 HDR맵과 HDR 스카이박스를 생성하도록 시도했다.
그들은 좋아 보인다. 그러나 우리는 패치에 포함하지 않았다
(아래 이유 때문에)…
– HDR light map textures 압축에 도전중이다
– 대역폭(사양) 요구사항이더 커졌을 것이다
– Far Cry 패치 크기가 거대했을것이다
– 모든 레벨을 조정하고테스트하기엔시간이없었다
27. 결론
• Dynamic flow control in ps_3_0
• Geometry Instancing
• High Dynamic Range Rendering
28. References
• [Kawase03] Masaki Kawase, “Frame
Buffer Postprocessing Effects in
DOUBLE-S.T.E.A.L (Wreckless),” Game
Developer’s Conference 2003
• [Reinhard02] Erik Reinhard, Michael
Stark, Peter Shirley and James
Ferwerda, “Photographic Tone
Reproduction for Digital Images,”
SIGGRAPH 2002.