2. Frame Move

engine-1.jpg

목표 :
매프레임 동작하는 동작 원리에 대해 알아본다.
매프레임 호출되는 함수들의 순서와 각 함수들의 원리에대해 이해한다.
multi thread 동작을 위한 방식에대해 간략하게 알아본다. (뒤쪽에 보다 자세한 설명을 한다.)



결과 :
blue screen 을 만든다.



1> 우선 매프레임 호촐되는 함수 두개를 만들자.
; 하나는 각 오브젝트들의 상태를 갱신하기위한 process 함수와 또 하나는 각 오브젝트들의 rendering 을 담당하는 render() 함수
를 만들자.

process()
<< 엔진을 통해 생성된 오브젝트들을 갱신하는 함수. 엔진의 main_pre_process 함수와 main_process 함수 사이에 위치한다.

render()
<< 엔진에 rendering 을 요청한다.

2> 우선 엔진내부의 기본 동작을 위한 몇가지 함수들에 대해 알아본다.
; 설명된 순으로 함수를 호출하면 된다.

g_engine_core.main_pre_process( delta_time );   
<< 엔진으로 생성된 모든 객체들의 시간을 업데이트 하기위한 함수. 위에서 생성된 process 함수의 윗쪽에서 먼저 호출해 준다. 단지 호출만 하면 됨.

process();
<< 위에서 설명 되었음. 실제 rendering 할 오브젝트들을 갱신하는 역할을 한다.

g_engine_core.main_process();
<< 이 함수를 호출하기전 갱신했던 모든 오브젝트들의 실제 계산이 이루어 지는 함수. 예를들어 만약 이 함수를 호출하기전 특정 오브젝트를 갱신해 주었다면, 이번 함수에서 실제 오브젝트에 관련된 계산이 이루어진다.  그러므로 위에서 생성한 process 함수는 이 함수와 main_pre_process 함수 사이에 위치 하여야 한다.

g_engine_core.main_pre_render();
<< process 함수에서 갱신된 오브젝트들을 rendering 하기 전 rendering 하기위한 각종 data 들을 갱신하는 역할을 한다.

g_engine_core.clear();
<< rendering 할 buffer 를 특정 컬러로 clear 한다.

g_engine_core.begin();
<< 실제로 rendering buffer 에 기록을 시작함을 알린다.

g_engine_core.main_render();
<< 이 함수의 호출과 동시에 갱신된 오브젝트들의 정보를 renderer 에 전달한다. 전달된 정보들은 renderer 를 통해 각 render state 에따라 최적화된 렌더링 순서로 sorting 되고 그 순으로 rendering 된다.

g_engine_core.end();
<< main_render 함수의 호출과 함께 rendering 하여야 할 모든 오브젝트들이 rendering buffer 에 render 되었다. 이 함수의 호출로
rendering buffer 에 기록된 정보들이 화면버퍼로 옮겨지게 된다.

g_engine_core.main_post_render();
<< rendering 된 각종 data 들을 초기화 한다.


3> 위에서 설명한 모든 함수들은 단지 호출만을 통해 모든 과정이 자동으로 일어난다.
; 단지 위 함수들의 호출만으로, 내부적으로는 카메라의 계산, 애니메이션의 블랜딩 연산이라던지 상하체 분리 연산, 접근가능한 깊이버퍼를 생성, post effect 를 위한 각종 target rendering , 카메라에대한 가시성 검사, scene 에 대한 각종 연산, 각 render state 에따른 최적화된 rendering, 등 수십가지의 일들이 자동으로 일어나게 된다.
물론 multi thread 용 라이브러리를 링크하였다면 위의 일들은 자동으로 multi thread 환경에 맞게끔 여러 thread 를 생성하여 동작되게 된다.  그러므로 단지 호출만을 통해 복잡하고 힘든 대부분의 작업들은 엔진 내부적으로 처리되게 된다. 클라이언트 프로그래머는 단지 로직에만 열중할 수 있는 환경에 제공된다.


4> 실제 소스코드.

void process()
{
      g_engine_core.main_pre_process();

     // 각종 로직이 위치할 자리.

      g_engine_core.main_process();
      g_engine_core.main_post_process();
}

void render()
{
      // clear color 설정. 차례대로 rgba 순이다.
      float bgcolor[4];
       bgcolor[0] = 0.0f;      // r
       bgcolor[1] = 0.0f;      // g
       bgcolor[2] = 1.0f;      // b
       bgcolor[3] = 1.0f;      // a

      // viewport 설정
       GetClientRect(m_hWnd,&rc);
       sEPP_VIEWPORT vp;
       vp._fWidth = (float)(rc.right);
       vp._fHeight = (float)(rc.bottom);
       vp._fMaxDepth = 1.0f;
       vp._fMinDepth = 0.0f;
       vp._uiTopX = 0;
       vp._uiTopY = 0;
       g_engine_core.set_viewport_by_process(&vp);

      // 실제 렌더링을 위한 클리어 설정
       g_engine_core.clear(bgcolor);

      // 실제 렌더링코드. 단지 호출만 하면 자동으로 갱신된 오브젝트들이 렌더링 된다.
       g_engine_core.begin();
       g_engine_core.main_pre_render();
       g_engine_core.main_render(1);
       g_engine_core.end(&rc,&rc);

      // 렌더링된 오브젝트들을 초기화 한다.
       g_engine_core.main_post_render();
}

Download
epp_engine_frame_move.cpp


* PARAMETER
bool end(RECT* p_pSrc = NULL, RECT* p_pDest = NULL, HWND p_hWnd = NULL, bool p_bEndScene = true);
p_pSrc : rendering 을 갱신할 buffer 의 사각형 영역
p_pDest : rendering 을 갱신할 목적지 buffer 의 사각형 영역
p_hWnd : 갱신된 rendering buffer 를 나타낼 윈도우 핸들

bool clear(const float p_pColorRGBA[4]);
p_pColorRGBA[4] : clear color. 배열의 순서대로 R G B A.

void main_pre_process(DWORD p_dwDeltaTime = 0xffffffff, float p_fSpd = 1.0f);
p_dwDeltaTime : 이전 프레임과 현재 프레임 사이의 시간간격. ( 1초 = 1000 )
p_fSpd : 엔진의 속도 배속. (예를들어 2.0 이면 모든 시간간격이 현재의 2배가 된다. 0 이면 정지.)

void main_render(bool p_bUseScreenBuffer = false, bool p_bInterfaceScreenFilter = false);
p_bUseScreenBuffer : 엔진내부에서 만들어진 rendering buffer 을 사용하지 여부. false 라면 기존 device 에서 제공하는 buffer 사용.
p_bInterfaceScreenFilter : p_bUseScreenBuffer 가 true 인 상태에서 post effect 적용시 interface 까지 적용될지 여부.