2011-08-22 5 views
0

Xna Framework Game 클래스의 소스 코드를 살펴 보았습니다. 구체적으로 어떻게 그리기 호출을하는지, GraphicsDeviceManager.EndDraw()에서 GraphicsDevice.Present() 호출을 볼 수있었습니다. GraphicsDevice.BeginScene() 또는 GraphicsDevice.EndScene()에 대한 호출을 찾지 마십시오. GraphicsDevice 클래스 자체는 아닙니다. 누구나이 상황을 어떻게 처리하는지 알 수 있습니다.Xna Framework 질문

+0

그럼 뭐가 문제입니까? –

답변

7

GraphicsDevice.Begin/EndScene()에 대한 참조를 찾지 못한 이유는 이러한 방법이 없기 때문입니다. GraphicsDevice 클래스는 XNA 프레임 워크 사용자가 필요로하는 그래픽 기능을 캡슐화하는 데 사용되는 관리되는 클래스입니다. 네이티브 IDirect3DDevice9 인터페이스의 1 대 1 매핑이 아닙니다.

Reflector와 같은 것을 사용한다는 것을 의미하는 소스 코드를 살펴보고, C# 코드로 코드를보고 있다고 가정합니다. 명심해야 할 중요한 점 중 하나는 XNA 프레임 워크의 상당 부분이 C++/CLI로 작성되고 결과적으로 C#에 반영 될 때 결과가 예측할 수 없다는 점입니다.

IDirect3DDevice9::BeginScene()IDirect3DDevice9::EndScene() 네이티브 호출에 대한 구체적인 사례는 조금 알아봐야합니다.

다음은 모두 XNA 4.0을 전제로합니다. 3.1은 여전히 ​​유사해야합니다. 리플 렉터에는 GraphicsDevice 클래스에 전용 bool_insideScene이 있습니다. 이것을 분석하면 GraphicsDevice.DrawPrimitives() 호출과 같은 다양한 위치에서 설정이 표시됩니다. 이 방법의 C#을 반사 다음 코드로이 멤버를 설정해야합니다

if (!this._insideScene) 
{ 
    **(((int*) this.pComPtr))[0xa4](this.pComPtr); 
    this._insideScene = true; 
} 

여기서 핵심 라인은 **(((int*) this.pComPtr))[0xa4](this.pComPtr);입니다. C++/CLI 어셈블리를 작성하고 적절한 DirectX 헤더 (d3d9.h)를 포함하고 IDirect3DDevice9 (즉, pDevice->BeginScene())의 인스턴스에 BeginScene()을 호출 한 다음 C#에서 어셈블리를 분해하면 위와 동일한 행이됩니다. 이것은 네이티브 호출을위한 일리노이가 C# 으로 다시 매핑되는 방법이지만 C#에서 해당 라인을 작성하고을 컴파일하는 것은 불가능합니다.

코드 줄은 기본적으로 원시 가상 메서드 호출입니다. 가상 메서드 테이블 here에 대한 자세한 정보를 읽을 수 있지만이 상황에 대한 기본 개념은 다음과 같습니다. 개체의 가상 테이블 포인터는 (컴파일러에 따라 다르지만이 경우 true) 네이티브 개체의 첫 번째 요소입니다. pComPtr은 기본 COM IDirect3DDevice9 개체에 대한 안전하지 않은 포인터입니다. 따라서 역 참조 pComPtr (*pComPtr)은 가상 메소드 테이블에 대한 포인터를 제공합니다. 해체는 여기서 다소 모호하지만 IL은 상당히 명확합니다. 다음은 가상 메소드 테이블 포인터에 0xa4이 추가됩니다. 이를 이해하려면 원시 배열은 배열의 첫 번째 요소에 대한 포인터 일뿐입니다. 객체의 가상 메소드 테이블은 함수 포인터의 배열입니다. 0xa4은 십진수로 164이며, 이는 포인터가 164 바이트 앞으로 이동 함을 의미합니다. 라이브러리는 x86 라이브러리이므로 포인터는 4 바이트 길이입니다. 이는 가상 메소드 테이블 (164/4 = 41)의 41 번째 메소드로 이동했음을 의미합니다. d3d9.h (DirectX SDK의 일부)에서 IDirect3DDevice9 인터페이스 선언을 보면 41 번째 방법이 BeginScene임을 알 수 있습니다. 그런 다음이 포인터를 역 참조하여 실제 BeginScene 메서드를 제공 한 다음 첫 번째 (및 유일한) 매개 변수 (보통 호출의 경우 thisthis.pComPtr 포인터)로 (일반적으로 숨겨진) this 포인터를 전달합니다.

개인 안전하지 않은 GraphicsDevice.Present() 메서드에서 유사한 코드를 볼 수 있습니다. 이번에는 0xa8으로 오프셋되거나, 기능 42는 IDirect3DDevice9::EndScene()입니다.

따라서 GraphicsDevice가 제대로 모든 도면이 완료되기 전에 BeginScene가 호출되었고, 네이티브 IDirect3DDevice9::Present() 메소드가 호출되기 전에 EndScene가 호출되는 것을 보장 볼 수 있지만, 의도적으로 XNA 프레임 워크의 사용자에서이 기능을 숨 깁니다.

+0

괴짜. 좋은 대답. –

+0

Impresive, 그게 전부입니다. 나는 네게 묻고 싶다. 네이티브 C++로 게임 프로그래밍 프레임 워크를 만들려고하는데, xna가 작동하는 방식을 좋아한다. 그래서 내가하고있는 일은 내 프레임웍에 같은 기능을 코딩하려고하는 것이다. 그것은 틀린가? 어떤 법적 의미가 있는가? 그리고 네, DotNetReflector를 사용하고 있습니다. – Yoss