외국 게임회사 면접시 질문

Game Dev./General 2009/10/25 22:08 Posted by sonee

외국 게임 회사 면접시 질문 내용은 인터넷에서 거의 찾아볼 수가 없어서 외국으로 취업을 처음 준비하는 사람에게는 참고할만한 자료가 없어서 준비하는데 참 힘들더군요. 프로그래밍 시험 내용은 각 회사에서 비밀로 하는 내용이기 때문에 이 포스팅에서는 다루지 않겠습니다.

보통 외국 게임 회사와 연락이 닿으면 동네에 살지 않는이상 보통은 전화 면접을 먼저 보게 됩니다. 저의 경우에는 짧게는 15분 부터 길게는 1시간까지 전화면접을 보게 되었습니다.
4군데 정도 전화면접을 보게 되었는데, 보통 이경우 HR 팀에서 면접을 진행하게 됩니다. 면접 절차는 일반적으로,

1. Human Resources Department 와 면접
2. 프로그래밍 테스트
3. 실무자 테스트
4. 최종 인터뷰

이렇게 진행됩니다. 중간에 3번등은 상황에 따라 생략될 수 있습니다.

중요한게 1번은 보통 전화면접이 이루어지고, 아시다시피 전화 면접은 상당히 힘듭니다. 그냥 대면해서 하는 면접도 힘든데 전화니 아무래도 더 힘들겠죠. 예상 문제에 대한 답을 미리 외워두는게 좋습니다. 전화 인터뷰라해서 질문에 맞춰서 줄줄줄 읽는방식은 개인적으로 비추입니다.

면접시 질문 내용은 다음과 같았습니다.

1. 너 자신에 대해 간략히 설명해봐라. (Can you tell me a little about yourself?)
2. 너의 최대 장점이 무엇인가? (What is your greatest strength?)
3. 왜 우리가 너를 고용해야 하는가? (Why should we hire you?)
4. 왜 우리회사에 끌렸는가? (Why do you like this company, what attracted you to us?)
5. 너의 미래의 목적은 무엇인가? (What are your goals for the future?)
6. 너의 최대 단점은 무엇인가? (What is your biggest weakness?)

네. 아시다시피 국내 면접 질문과 크게 다른것이 없습니다.
그러나 말을 하실때에는 그냥 생각과 사실을 그대로 설명하기 보다는 항상 예를 들어 설명해야 합니다. 주관적인 것보다는 항상 객관적 사실과 근거가 뒷받침 되어야 합니다. 그리고 아주 겸손하실 필요는 없고, 그렇다고 너무 자만해서도 안됩니다.
대답을 할때에는 단답식은 무조건 피하도록 합니다. 어느정도 재치, 유머로써 전화 면접을 이끄는것도 좋은 방법인것 같습니다.(당연히 너무 장난스럽게 이끌어가면 면접 자체가 너무 가벼워지겠죠.)
또한 전화 면접 자체가 갖는 특수한 환경 및 제약을 해당 담당자도 어느정도 인지 하고 있는것으로 알고 있습니다. 그러니 sorry? pardon me? 등을 적당히 쓰셔도 상대방이 그렇게 불쾌해 하지 않을 겁니다.

한국 면접 방식과 비교해볼때 아주 큰 차이점은 없는 것 같으나 그 세부 내용에 있어 차이는 꽤 있습니다. 한국 면접시에는 대체로 추상적이거나 뭉뚱그려서 설명을 하는 경우에 적당히 면접관이 이해하고 넘어가는 부분이 있지만, 외국 게임회사 면접을 볼때에는 모두 세세한 내용이나 객관적 근거들을 물어봤습니다. 따라서 좀더 구체적이고, 객관적인 답을 준비하셔야 합니다. 저의 경우에는 대략적인 특정 알고리즘의 시간복잡도나 수학에서 특정 법칙등을 예를들어가며 설명해었는데, 시간 복잡도가 그렇게 되는 이유라던가, 해당 법칙이 활용되는 분야라던가.. 참으로 여러가지 질문을 받아서 조금 당황했습니다.

그리고 질문 있냐고 면접관이 물었을 경우에는 당연히. 질문을 하시는게 맞습니다. 이건 한국이나 외국이나 공통점이네요.
근무 시간, 연월차, 그밖의 benefit, 개발 인원, iteration 등등 미리 준비해놓으세요 ^^

저작자 표시 비영리 변경 금지

D3DBook is available on GDWiki

Game Dev./General 2009/02/19 01:57 Posted by sonee

I found a D3DBook webpage on GDWiki. It is kind of site that is very helpful to programmers who are studying D3D10. Even though I haven't read it entirely, I'm sure that it helps programmers who have been using DX9 adapt to D3D10 easily.

 

Wolfgang Engel, well known as an author of game programming books, is a person of authors who joined to make the site. So the fact that he joined is enough to be worthy of attention because books that he wrote so far are very helpful.

I think most programmers might not have had any opportunity to use D3D10 at their project, because all of customers don’t have a graphic card that D3D10 is available. However, D3D10 have been being already used at development environment of XBOX360, and cheap graphic cards that support D3D10 will be spread more and more as time passed by. So I think game programmers have to get accustomed to use D3D10 to develop games that have greater graphic qualities than before and compete with other programmers in same area.

 

In fact, I didn’t also have the opportunity at my project, and I’m not used to D3D10. So lately I’m studying hard about D3D10 in order to be accustomed to handle D3D10. I guess most 3D programmers who are used to D3D9 can adapt to D3D10 easily if they study D3D10 a little bit.

 

http://wiki.gamedev.net/index.php/D3DBook:Book_Cover

 

Productivity of C#

Game Dev./General 2008/12/30 18:37 Posted by sonee

최근에는 집에서 쉬면서 부모님 가게의 전산화를 도와드리고 있습니다.
부모님 가게의 전산화를 위해 유료로 판매되는 모 판매재고관리 프로그램을 구입하여 전산화 작업중인데요.
이게 참 맘에 안드는게 많습니다. 워낙 범용적으로 만들어서 판매하는 제품인지라, 부모님이 운영하시는 가게를 전산화하여 사용하기에는 부족한 점이 너무 많네요.

특히나 대부분 부족한 기능들은 단가 관리 입니다. 환율등에 영향을 받는 품목인 경우 최근처럼 널뛰기 환율에 의하여 가격변동이 심한데, 대부분의 프로그램들은 이렇게 변동된 단가들을 일일이 수작업으로 수정해줘야 하는 번거로움이 있습니다. 그냥 간단히 올릴 품목들을 선택해서 10% 만 입력하면 자동으로 도매가, 소매가, 오도매가 등이 자동으로 계산되면 편할텐데 말입니다.

어쨌건 한 두 달전에 친구랑 밤새서 열심히 입력했던 수천개의 단가들이 변동되었고, 이걸 다시 입력하자니 정말-_- 난감하더군요. 그래서 뭔가 툴을 만들어야겠다.. 라는 생각에 일단 작업에 착수했습니다.

전에 자료를 입력할 때 단순 반복되는 품목들이 많아서(예를들어 규격만 조금씩 규칙적으로 바뀐다거나..) 자동으로 품목과 단가를 입력하는 프로그램을 만들어서 입력했었는데 그때 DB 를 분석했던 기억을 되살려서 진행을 해보았습니다.

많은 분들이 이러한 툴이나 판매재고 관리 프로그램을 만드실 때 Visual Basic이나 Delphi 등을 많이 이용하시는 것 같은데 그걸 쓰면 얼마나 편할지는 잘 모르겠습니다만, 전에 C#을 공부하면서 간단한 윈도우 어플리케이션과 Direct3D 어플리케이션을 만든기억이 있는데 무지하게 편했던 기억이 있어서 C#을 선택하였습니다.

사실 DB 쪽때문에 이거 C++ 을 써야하는거 아닌가 싶었는데 뭐 걱정할 필요도 없이 바로 -_- 되는군요.



DB연동작업도 있고 해서 MFC를 썼다면 대략 작업시간으로 2~3일 분량이었는데, 하루도 안되서 작업이 끝나버렸습니다.
GRID CONTROL 만해도 MFC 를 썼다면 코드프로젝트등에서 이래저래 찾아보고, 삽질하는데도 시간이 좀 걸렸을 텐데 쓸만한 콘트롤들이 기본으로 내장되어 있고, 쓰기도 편해서 개발 시간이 대폭 감소한 것 같습니다.


여튼 C#의 이러한 생산성은 게임을 만들때. 특히나 게임 개발에 필요한 툴을 만들때에도 꽤 큰 잇점이 될 수 있는데요.
많은 프로그래머들이 C#의 속도를 신뢰하지 않기 때문에, 당장 쓰기에 많이 망설이시는것 같습니다.
특히나 엔진은 C/C++ 로 개발하고, 툴만 C#으로 만드는게 사실상 현실적으로 힘들기 때문에, 메인 코어도 C#으로 개발해야 할텐데, C#의 속도 문제때문에 무언가 검증된 결과물이 나오질 않는이상 저라도 어쩔 수 없이 C/C++ 을 사용할 것 같습니다. 일단 다른 개발자들을 설득하기도 힘들구요.;

개인적으로는 C#을 공부해보면서 생각이 드는건데, C#을 게임 개발의 메인 언어로 선택하는게 아주 큰 모험이 되진 않을 것 같다라고 판단이 서는데요. 물론 가장 크게 문제되는건 미들웨어와의 연동이겠지만요. 속도는 D3D를 사용한 간단한 지형 렌더링을 테스트 해본바로는 큰 차이는 없었습니다.
물론 게임에서 여러 데이타 및 메모리 관리가 속도에 가장 큰 영향을 미치겠지만 말입니다. 뭐 이것도 GC만 믿고, 날림으로 만들지 않는 이상 크게 문제될 부분은 없어보입니다. 좋은 메모리 메니지먼트 솔루션들이 많으니까요.

여튼 게임 개발 초기 단계의 언어 선택에 있어서, 당연히 C/C++ 이라기보단 한 번쯤은 C#을 생각해보는게 좋을 것 같습니다.
C/C++개발자라면 아주 쉽게 C#에 적응이 될 수 있고, C#이 가진 이러한 생산성은 게임 개발에 있어서 개발 속도뿐만 아니라 게임의 퀄리티를 높여주는데 분명 아주 큰 잇점이 될테니까요.

아마도 이미 국내에서도 여러 게임 회사에서 C#을 이용하여 게임개발을 진행하고 있고, 또 완료한 회사도 있을 텐데, C#을 이용해서 어떤 잇점을 얻었고, 어떤게 문제였는지 이야기를 해주었으면 좋겠네요.

C#에 익숙해지다보니 다시는 MFC를 사용하여 어플리케이션을 만들기가 싫어졌습니다..-_-;
미국 사장님의 허락하에 스샷을 공개 합니다.
회사에서 제가 만든 3D Engine을 사용한 야구 게임입니다.
아쉽게도 회사 사정에 의해 개발이 중단된 상태입니다.
아직 보충할 것도 많고, 다듬어야 할 것도 많은데 정말 아쉽네요.
클릭하시면 확대되고, 사용된 기술은 맨 아래 있습니다.

사용된 기술중에는 제가 독자적으로 개발한것도 몇 개 있는데, 이 부분은 공유 하기 위해 현재 문서로 작성하고 있습니다. 완성되는대로 올리겠습니다.(영어로 작성하고 있어서 언제 완성될지 ..-_-)

중간에 DHL, SAMSUNG, NIKE 이미지는 테스트겸해서 넣어본 것입니다. ^^

사용된 텍스쳐의 최대 크기는 512입니다.

사용자 삽입 이미지사용자 삽입 이미지사용자 삽입 이미지

그리고 이건 보너스
Reiot님의 요청에 의해 TeamFortress2의 느낌을 내보려고 후딱 렌더링 코드를 수정해봤습니다.


사용자 삽입 이미지


Shader Model 2.0

. Scriptable Shader System
. Ball Catching System(날아오는 공의 위치에 정확히 손을 뻗게 하는)
. Swing Animation Solver(날아오는 공의 위치에 방망이를 가져다 대는.정확히 방망이의 sweet position)
. HDR, Glow, Depth Of Field
. Image Based Lighting
. Ambient Occlusion
. 유니폼 커스터마이징 시스템
 - 베이스 색, 줄무늬, 유저가 제작한 엠블렘, 줄무늬 색, 등번호 색, 등 이름 색
. 캐릭터 커스터마이징 시스템
 - 구렛나룻, 콧수염, 턱수염, 눈썹, 머리, 머리색, 피부색, 문신 등..
. Instancing(폴리곤 관중)
. Self Shadow(TSM, VSM)
. Stadium Tool, Character Tool, Customizing Tool
. 입체감이 있는 잔디 바닥
. 흙바닥의 흙정리 한 느낌의 입체감

더 있을 법도 한데 기억이... ㅠㅠ

UBO, UBO2008, RBO, RBO2008, RBO2009, RIPKEN BASEBALL ONLINE, PLAYREALBASEBALL
2004년에 제가 작성했던 글입니다. ㅎㅎ 당시 위키에 기록했었는데 위키는 어디로 사라진거지..-_-


마우스로 드래그해서 삼각형들 선택하기

당연히 정밀도는 높은 편이고, 필요한 함수는 AABB와 삼각형 교차/포함 판정 정도이겠군요.

1. 먼저 체크할 폴리곤들을 추립니다. 경우에 따라 안추리고 죄다 검사 해도 상관없겠죠-_-
2. 화면을 비추던 카메라의 정보를 가지고 해당 삼각형들을 projection 해버립니다.
3. 삼각형의 세 점을 다 projection 했으면 그 값으로 다시 삼각형을 만듭니다.
4. 현재 화면에 드래그 한 시작 포지션과 끝 포지션을 가지고, x는 -1부터 1, y 는 -1부터 1까지 적당히 비율 계산해서 넣습니다. z 값은 min 이 0, max 가 1일껍니다. DX라면..
5. 그 삼각형과 4번에서 만든 AABB 와 교차/포함 판정합니다.

조금만 더 개조하면 다른 폴리곤에 의해 가려진 삼각형은 선택 안하게 만들수도 있구요. 속도를 요하는 거라면 적당히 프러스텀도 써주고 샤바샤바 해주면 빨라질듯.

ShaderX 5

Game Dev./General 2007/01/25 23:21 Posted by sonee

사용자 삽입 이미지

ShaderX4 에도 볼 내용이 많앗는데
ShaderX5에는 더 볼만한 내용이 많다.
역시나 패럴럭스 매핑이 대세인가;;

일단 Device 차원의 최적화를 이야기할까 한다. 나머지는 프로그래머의 역량에 따라 충분히 개선될 수 있기 때문이다. 그렇지만 지금 이 글에 나오는 내용은 단순히 프로그래머의 역량에 의존적이지 않기 때문에 필히 알아두어야 하겠다.

1. 자주 업데이트 되는 VertexBuffer와 IndexBuffer는 일반적으로 D3DPOOL_DEFAULT 에 생성해야 한다.
D3DPOOL_MANAGED메모리풀을 사용하면 보통 두 번의 메모리 복사가 일어나므로 퍼포먼스 향상에 도움이 되지 않는다.

2. 가능하면 생성된 버퍼로부터 값들을 읽지 말아야 한다.
일반적으로 AGP나 비디오 메모리로부터 값을 읽는것은 매우 느리다. 이것은 옛날 2D 때부터도 그랬다. 그래서 만일 값들을 많이 읽어야 한다면 차라리 D3DPOOL_SYSTEMMEM 에 버퍼를 생성하고 읽는게 낫다.
아니면 System 에 따로 Buffer의 복사본을 두고 쓰는게 낫다.

3. 오직 쓰기만하는 버퍼는 D3DUSAGE_WRITEONLY 와 D3DPOOL_MANAGED를 사용하라.
DirectX Software Development Kit Document에는 D3DUSAGE_WRITEONLY flag 를 사용하면 버퍼에 쓰고 화면에 렌더링하는데 가장 효율적인 메모리 위치를 찾아 할당해준다고 나와있다.

그렇다면 메로리 할당 순서는?
1. 렌더타겟
2. D3DPOOL_DEFAULT
3. D3DPOOL_MANAGED
이 순서를 반드시 지키는 것이 큰 규모의 게임을 만드는데 큰 도움이 될 것이다. 나중에 비디오 메모리가 부족하다고 난리치지말자.
TAG 3d, 최적화

옛날에 썼던 FadeIN/OUT 자료

Game Dev./General 2006/08/03 19:11 Posted by sonee
헐;; 거의 7년전에 올렸던-_- 강좌;;;

2000/01/31 00:04 | sonee ( 손희승 ) | 조회 1222  

안녕하세요.

원래는 타일 스크롤에 대한 강좌를 쓸려구 그랬는데..
이걸 먼저 쓰게 되었네요.
16비트 칼라를 중심으로 설명하겠습니다.

이번에 설명 드릴것은 Fade IN, Fade OUT 이라는건데요.

Fade IN 은 화면이 점점 밝아지는것을 말하고,
Fade OUT 은 화면이 점점 어두워 지는것을 말합니다.

모니터에서 발산하는 건 가산혼합이기 때문에.. 색을 섞을 수록 밝아집니다.
어둡게 찍기 위해서는 R,G,B 값을 줄여야 어두워지고 다시 밝게 찍기 위해서
는 R,G,B 값을 늘려야 밝아집니다.
이제 원리는 알았으니.. 그걸 구현만 하면 되겠지요?

서론은 줄이고 본론부터 들어가겠습니다^^;


구현 방법은 각각의 r,g,b 값을 얻어다가 백분율로 환산해서
계산해주면 되는데요.. 저는 여기서 64 단계를 사용했습니다.
백분율이 아닌 육십사분율--; 이 되겠군요.

한점한점 처리할때에는 r,g,b 값을 마스크를 통해 얻어온다음에
r=r*depth>>6;
g=g*depth>>6;
b=b*depth>>6;
이렇게 계산을 하면 됩니다.
계산한 후에 다시 마스크를 씌운담에, 필요없는부분들을 제거해야
합니다.

한점한점 처리하면 처리속도가 많이 늦어지는데요.. 이를 위해서 2점 처리를
사용하도록 하겠습니다. 음.. 처리 방법은 다 아실듯 싶습니다. WORD 값두개
를 DWORD 로 합친후에 마스크도 DWORD 크기로 하셔서 한점한점 처리하는것과
같이 처리하면 됩니다.

먼저 소스부터 써보겠습니다.

void CBMP::Fade(int depth)
{
DWORD Mask_G,Mask_B,Mask_R;
DWORD r,g,b;
DWORD temp;


if(bColorMode) // 5:6:5 모드인경우
{
Mask_R=0xf800f800;
Mask_G=0x07e007e0;
Mask_B=0x001f001f;
} else
{
Mask_R=0x7c007c00;
Mask_G=0x03e003e0;
Mask_B=0x001f001f;
}
if(depth>64) depth=64;

int next;
WORD *src=Lock(next);
for(int i=0;i {
WORD *pw=src+(next*i);
for(int j=0;j {
// 2점을 한번에 처리하기 위한..
DWORD dwsrc=*((DWORD*)pw);
temp=dwsrc;
r=temp&Mask_R;
r>>=6;
r*=depth;
r=r&Mask_R;
g=temp&Mask_G;
g>>=6;
g*=depth;

g=g&Mask_G;
b=temp&Mask_B;
b*=depth;
b>>=6;

b=b&Mask_B;
*((DWORD*)pw)=r|g|b;
pw+=2;
}
}
Unlock();
}

이렇게 되는데요.
한줄한줄 분석해보면


void CBMP::Fade(int depth)
이건 제가 화면 클래스로 사용하는 CBMP 에서 Fade 라는 함수입니다.
depth 는 0부터 64까지의 단계로 이루어져 있습니다.
{
DWORD Mask_G,Mask_B,Mask_R;
각 컬러 모드에 맞게 마스크 값을 정합니다.

DWORD r,g,b;
여기다가 r,g,b 값을 얻어서 저장해놓구요.

DWORD temp;
이건 현재 컬러값이 저장되는곳입니다.


if(bColorMode) // 5:6:5 모드인경우
말 그대루 5:6:5 모드이면

{
Mask_R=0xf800f800;
마스크 R 값을 두점을 처리할 수 있도록 정합니다.상위 5바이트를 얻어오는
거죠.

Mask_G=0x07e007e0;
마스크 G 값을 정합니다.

Mask_B=0x001f001f;
마스크 B 값을 정하구요.

} else
{
이건 5:5:5 모드일때 사용하는 마스크 값입니다.

Mask_R=0x7c007c00;
Mask_G=0x03e003e0;
Mask_B=0x001f001f;
}
depth 가 64이상이 되면 화면이 이상하게 바뀔테니.. 보정해주구요.
(음수도 보정해야겠죠^^)
if(depth>64) depth=64;

int next;
여기에는 락을하면 얻는 ddsd.lPitch/2 값이 들어갑니다.

WORD *src=Lock(next);
현재 서피스를 락을 한담에

for(int i=0;i {
화면 세로 크기만큼 반복합니다.

WORD *pw=src+(next*i);
현재의 위치를 pw 에 기억해놓구요.

for(int j=0;j두점을 한번에 처리하기 때문에 j+=2 라고 했습니다.

{
// 2점을 한번에 처리하기 위한..
DWORD dwsrc=*((DWORD*)pw);
두점을 얻어오고
temp=dwsrc;
그 값을 temp 에 넣습니다.
r=temp&Mask_R;
r 값을 마스크로 얻어온후에
r>>=6;
그냥 먼저 곱해버리면.. 표현 수의 범위가 넘어가기 때문에 먼저 나눕니다
상위 비트이기 때문에 상관 없죠.. ^^
r*=depth;
밝기를 곱하고
r=r&Mask_R;
다시 마스크를 씌어서 쓰레기값을 청소합니다.

g=temp&Mask_G;
g>>=6;
g*=depth;

g=g&Mask_G;
b=temp&Mask_B;
b*=depth;
b>>=6;

b=b&Mask_B;
*((DWORD*)pw)=r|g|b;
r,g,b 값을 더한후에 대입을 합니다.

pw+=2;
두점 뒤로 갑니다.
}
}
Unlock();
락을 풀어줘야죠.. ^^
}


이상입니다.
사용 방법은

for(int i=64;i>0;i--)
{
back->Fade(i);
Flip();
}

이렇게 쓰시구요. 저기 중간에 동기화를 넣어서 처리하면되겠군요.^^

위는 어둡게 하는거고
밝게하는건

for(int i=0;i<64;i++)
{
back->Fade(i);
Flip();
}

이렇게 하면 됩니다.

제가 글솜씨가 없어서..
이해가 잘 되셨는지 모르겠네요.
그럼.^^

----------------

g 값을 쉬프트 시킬때 한번에 6개를 해주면....
약간 색이 이상해지는군요.
그부분을
g=temp&Mask_G;
g>>=3;
g*=depth;
g>>=3;
g=g&Mask_G;

바꿔주면 됩니다.
두번 쉬프트 하는 과정을 거치는데...
따로 계산해주면 해결되지만.... 위의 소스 사용시 이렇게 변형하시면
괜찮을듯^^  
TAG 2D

GPU Skinning

Game Dev./General 2006/08/01 19:10 Posted by sonee
기존에 캐릭터 애니메이션을 CPU 에서 처리 하던것을 GPU 로 옮겼다.
하루 종일 삽질끝에 완성-_-v
그러나.. 속도는 많이 빨라 졌지만 문제가 생겼다.-_-

만들고 있는 게임에선 렌더타겟이 많은데-_-;;;
렌더타겟 별로 그려줄 때 계속 GPU 에서 애니메이션 계산을 해야 한다는 것. ;;;

결국 속도는 비슷하게 나온다.. 렌더타겟이 화면에 출력되지 않을땐 빠르고..-_-
흐으으으;;;;

여튼 쉐이더 코드만 기하급수적으로 늘어나고 있다-_-;
라이팅 1개 일때, 2개일때-_-, 스페큘러 맵, 환경 맵, 노멀맵, 라이트맵-_-, 디스플래이스먼트맵-_-, 쉐도우맵, GPU 스키닝 여부, 그림자 렌더링;;; 등
경우의 수만큼 Technique 가 증가하고 있다.
OTL
TAG 3d, SHADER

NVPerfHUD 4

Game Dev./General 2006/07/31 17:10 Posted by sonee
NVPerfHUD 2 를 -_- 마지막으로 사용했었는데;;
얼마전 회사 컴퓨터 비디오카드를 ATI 에서 NVIDIA 계열로 교체 후 다시 NVPerfHUD 를 받아서 사용해봤다.
-_- NVPerfHUD 2랑은 엄청나게 많은 변화가;; 게다가 2는 Registered developers 만 받을 수 있었는데 이젠 공개;
(사실 공개된지는 좀 된듯..)

여튼 Game/Application의 graphics 최적화를 위해서라면 반드시 한 번쯤은 돌려봐야할 툴.

link : http://developer.nvidia.com/object/nvperfhud_home.html