2017-11-06 23 views
0

저는 DirectX9를 사용하여 간단한 2D 게임을 제작하려고합니다. 스케일링을 적용하지 않고 스프라이트 치수와 좌표를 사용할 수 있기를 원합니다.DirectX 9 - 정확한 치수로 2D 스프라이트 그리기

Frank Luna의 "DirectX 9.0c로 3D 게임 프로그래밍 입문"책자는 Direct3D의 스프라이트 기능을 사용하여 그래픽을 2D로 렌더링하는 트릭을 보여 주지만 책 코드는 여전히 다음을 사용하여 카메라를 설정합니다. D3DXMatrixLookAtLH 및 D3DXMatrixPerspectiveFovLH를 사용하면 스프라이트 이미지가 원근감있게 확대됩니다. 스프라이트가 원래 크기로 렌더링되는 위치에 대한 뷰 및 투영을 설정하고 X-Y 좌표를 윈도우 내의 실제 픽셀 위치로 지정할 수 있습니까?

이 이상적인 솔루션이 아닐 수도 있지만 UPDATE, 나는 해결 방법을 마련했다. 나는 투영 행렬을 90 도의 field-of-view로 설정하고 z = 0에서 가까운 평면을 설정하면 D3DXMatrixLookAtRH로 원점 (0, 0, 0)을보고 단계 만 수행하면됩니다. 화면 너비의 절반만큼 뒤로 이동합니다 (Isosceles Right Triangle의 높이는 기준의 절반입니다).

그래서 X 400 (400) 인 내 클라이언트 영역에 대해 다음 설정은 나를 위해 일한 :

// get client rect 
RECT R; 
GetClientRect(hWnd, &R); 
float width = (float)R.right; 
float height = (float)R.bottom; 

// step back by 400/2=200 and look at the origin 
D3DXMATRIX V; 
D3DXVECTOR3 pos(0.0f, 0.0f, (-width*0.5f)/(width/height)); // see "UPDATE 2" below 
D3DXVECTOR3 up(0.0f, 1.0f, 0.0f); 
D3DXVECTOR3 target(0.0f, 0.0f, 0.0f); 
D3DXMatrixLookAtLH(&V, &pos, &target, &up); 
d3dDevice->SetTransform(D3DTS_VIEW, &V); 

// PI x 0.5 -> 90 degrees, set the near plane to z=0 
D3DXMATRIX P; 
D3DXMatrixPerspectiveFovLH(&P, D3DX_PI * 0.5f, width/height, 0.0f, 5000.0f); 
d3dDevice->SetTransform(D3DTS_PROJECTION, &P); 

모든 텍스처 필터를 해제 (또는 D3DTEXF_POINT로 설정하면) 최고의 픽셀 정확한 느낌을 얻을 것으로 보인다.

요청한 400x400 크기의 CreateWindowEx()가 387x362와 같은 클라이언트 영역을 반환 했으므로 GetClientRect()를 사용하여 차이점을 계산하고 다음을 사용하여 창 크기를 재조정해야한다는 점도 주목해야합니다. 초기 생성 후 SetWindowPos().

아래 스크린 샷은 위에서 언급 한 단계를 수행 한 결과를 보여줍니다. 원래 비트 맵 (오른쪽)은 응용 프로그램 (왼쪽)에 적용된 비율 조정/늘이기없이 렌더링됩니다 ... 마침내!

enter image description here

I의 종횡비가 1 대 없을 때, 상기 방법을 시험하지 않았다 2

UPDATE : 1. 코드를 조정했는데 카메라 위치를 뒤로 물러나는 양은 ... window_width * 0.5/aspect_ratio (또는 width/height) 여야합니다.

+0

왜 15 년 전 레거시 Direct3D 9를 사용하고 있습니까? DirectX 11을 사용하십시오. –

+0

XP를 실행하는 컴퓨터 중 하나에서이 작업을 실행할 수 있기를 원합니다. 단지 실험을 위해 :-) – morezoom

답변

0

DirectX Tool KitSpriteBatch 클래스는 사용자가 설명하는 것과 정확히 일치하도록 설계되었습니다. Direct3D를 사용하여 그리는 경우 화면 오른쪽 위 모서리의 (-1, -1)에서 (1,1)까지의 화면 좌표가 (-1, -1)입니다.

이렇게하면 오른쪽 위의 (0,0)이있는 화면 좌표에서 지정할 수있는 행렬이 설정됩니다. 센터는 다르게 Direct3D를 10/11/12보다 조금 정의 된 Direct3D를 9 픽셀에서

// Compute the matrix. 
float xScale = (mViewPort.Width > 0) ? 2.0f/mViewPort.Width : 0.0f; 
float yScale = (mViewPort.Height > 0) ? 2.0f/mViewPort.Height : 0.0f; 

switch(rotation) 
{ 
case DXGI_MODE_ROTATION_ROTATE90: 
    return XMMATRIX 
    (
     0,  -yScale, 0, 0, 
     -xScale, 0,  0, 0, 
     0,  0,  1, 0, 
     1,  1,  0, 1 
    ); 

case DXGI_MODE_ROTATION_ROTATE270: 
    return XMMATRIX 
    (
     0,  yScale, 0, 0, 
     xScale, 0,  0, 0, 
     0,  0,  1, 0, 
     -1,  -1,  0, 1 
    ); 

case DXGI_MODE_ROTATION_ROTATE180: 
    return XMMATRIX 
    (
     -xScale, 0,  0, 0, 
     0,  yScale, 0, 0, 
     0,  0,  1, 0, 
     1,  -1,  0, 1 
    ); 

default: 
    return XMMATRIX 
    (
     xScale, 0,  0, 0, 
     0,  -yScale, 0, 0, 
     0,  0,  1, 0, 
     -1,  1,  0, 1 
    ); 
} 

때문에 레거시 API의 일반적인 솔루션은 모든 위치에 오프셋 0.5,0.5 반 센터를 추가했다 . Direct3D 10/11/12에서는이 작업을 수행 할 필요가 없습니다.

+0

답장을 보내 주셔서 감사합니다.이 도구 키트를 살펴 보겠습니다. 2D 드로잉을 할 때 도움이 될 것 같습니다. – morezoom