2. Frame Move
목표 :
매프레임 동작하는 동작 원리에 대해 알아본다.
매프레임 호출되는 함수들의 순서와 각 함수들의 원리에대해 이해한다.
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 까지 적용될지 여부.
