본문 바로가기

Graphics

[GLUT/openGL] 그래픽스 프로그램의 흐름

cf. 서강대 [기초컴퓨터그래픽스] 수업의 실습자료1 기준으로 흐름을 따라가보았다.

 

일반적인 프로그램과 동일하게 

entry point는 main 함수이다.

main 에서는 각종 초기화 후 main loop를 돌리면서 사용자의 명령에 의한 event를 기다린다.

또한 입력된 event는 callbacks 함수를 통해 처리되는 구조이다.

ex)

입력된 event 작동하는 callbacks
렌더링 glutDisplayFunc
마우스 입력 glutMouseFunc
키보드 입력 glutKeyboardFunc
윈도우의 크기 변경 glutReshapeFunc
아무 입력이 없다 glutIdleFunc

 

▶ main 함수의 흐름

각종 초기화 후 콜백함수를 등록한다. 콜백함수가 등록되었다는 것은 내가 입력받을 모든 event에 대해 처리담당

callbacks가 준비되었다는 뜻이다. 따라서 mainloop로 진입하여 event를 기다리게 된다.

즉 가장 중요한 흐름은 콜백함수 등록->mainloop 진입 이다.

main 함수의 핵심 코드 일부

몇가지 내용을 잠시 확인하고 가자.

컴퓨터 그래픽스 분야에서 렌더링(rendering)이란 일반적으로 가상의 3D 세상에서 가상 카메라로 영상을 찍음으로써 (현실의) 2D 영상을 생성하는 작업을 뜻한다.

윈도우 시스템(window system)은 아이콘, 창 등 그래픽을 통해 사용자와 소통하는 GUI(그래픽 사용자 인터페이스)이다. 이때 이 윈도우 시스템은 운영체제(operating system)과 긴밀하게 연결된 하나의 시스템 프로그램이라 생각해도 되고, 운영체제의 일부라고 봐도 된다. 또한 윈도우 시스템의 서버는 모니터, 마우스, 키보드 등의 장치를 제어하고 있다.

윈도우 응용 프로그램의 수행 메커니즘도 살펴보자. 

ex) 사용자가 마우스로 화면에 그림을 그렸더니 화면에 마우스를 따라 그림이 그려졌다
사용자가 마우스로 화면에 그림을 그림 -> 윈도우 시스템의 서버가 이를 인지하고 응용프로그램에게 알려줌 -> 응용프로그램이 윈도우 서버에게 마우스를 따라 그림을 그려 화면에 나타내줄 것을 요청 -> 윈도우 서버가 화면에 그림을 그려줌

이때 응용프로그램은 사용자가 그림을 그렸으니 그것을 화면에 나타내야한다는 판단을 하고 윈도우 서버에게 요청을 했다. 이를 응용프로그램 입장에서 보면 event가 발생하여 그에 대한 처리를 해준 것이다.

 

▶ display 함수는 대체 누가 호출하는 거냐?

main에서 호출되는 함수 중에 initialize_renderer()가 있는데, 여기서부터 따라가야한다.

main - initialize_renderer - register_callbacks

- glutDisplayFunc - display!!!

정말 복잡하당^_ㅠ

 

차근히 살펴보자.

glutDisplayFunc(RenderScene) 함수는 register_callbacks 내부의 함수들 중 하나이므로,

사용자 명령에 의한 event를 처리하도록 등록한 함수일 것이다.

더 자세히는, event 발생시 인자로 있는 RenderScene 함수를 실행함으로써 event를 처리한다.

내 코드에서 RenderScene은 display 함수이다. 

 

▶ display 함수는 처음에 딱한번 호출되는건가? -> NO!

전체 프로그램을 실행하여 각종 event를 발생시키면 

각 event에 따른 처리 함수에서 r, g, b값을 변경시키는 것을 확인하였다.

그런데 위 사진처럼 r, g, b변수가 인자인 glClearColor 를 지우고

숫자를 그냥 대입한 glClearColor로 바꿔보았더니 아무리 event를 발생시켜도

색이 변하지 않았다. (r, g, b 변수는 값이 업뎃되는데도 불구하고!)

즉 event에 따라 업뎃되는 r, g, b로 윈도우 색깔까지 업뎃시켜주는 것은 

바로 이 display 함수로 보인다. 

그러니까 display 함수는 계속 호출되는 것!!

근데 이 함수가 register_callbacks에 있던 걸 생각하면 사실 당연한 걸지도..ㅎ?

 

▶ glutPostRedisplay 와 display는 무슨 관계일까?

무슨 event 처리 함수마다 죄다 glutPostRedisplay를 마지막에 붙혀놓았다.

display 가 그때그때 호출될텐데 glutPostRedisplay는 또 뭐냐..?

흠.. 

glutPostRedisplay 는 윈도우를 다시 그리도록 요청할 뿐이고,

display는 register_callbacks 내부의 glutDisplayFunc(display) 로 있다.

즉 display는 윈도우를 그리는 것과 관련된 event 처리 함수의 일부라 할 수 있다.

glutPostRedisplay에 의해 다시 그리라는 event가 생기는 것!

glutDisplayFunc - display 에 의해 그 event를 처리하는 것! 이라 정리해볼 수 있다.

그 event를 받고 처리할 시점을 결정하는 등의 일을 하는 것이 main loop인 것이다.

위 코드는 키보드에서 r, g를 누르면 각각 red, green으로 윈도우의 배경색을 바꿔준다는 내용이다.

4번째 줄과 같이 case r의 glutPostRedisplay()를 주석처리하였더니,

r을 누르면 윈도우 색이 바뀌지 않고, g를 누르면 올바르게 초록색으로 바뀐다!

또한 r을 누르고 좌클릭을 하는 등 색과 무관한 다른 event를 주었더니

갑자기 색이 빨강색으로 업데이트된다!!! (다른 event에도 대부분 glutPostRedisplay가 끝에 붙어있다.)

따라서 glutPostRedisplay는 화면을 다시 그리라는 event를 발생시켜 main에 요청하는 함수임을 알 수 있다.

 

cf) 방금 대부분의 event 처리 함수의 끝에 glutPostRedisplay가 붙어있다고 했는데..

아래 사진처럼 reshape이 하나의 반례가 되겠다.

reshape은 glutReshapeFunc이 reshape event를 처리하기 위해 인자로 호출하는 함수이다.

( glutReshapeFunc(reshape) 과 같이!! )

이러한 경우는 display event를 처리하는 콜백함수인 glutDisplayFunc이 자동으로 호출되는 상황이다.

따라서 glutDisplayFunc 호출을 위해 event를 생성해버리는 glutPostRedisplay 코드가 붙어있지 않은 것!

 

▶ 프로그램을 실행시켰을때 처음 뜨는 윈도우는 누가 event를 발생시켜서 glutDisplayFunc이 처리한 걸까?

아직은 잘 모르겠지만, 누군가 event를 발생시켜 mainloop의 event 처리 queue에 가장 먼저 들어갔을 것이다.

그럼 mainloop가 돌며 event를 순차적으로 처리할때 glutDisplayFunc을 통해 화면이 띄워질 수 있었겠지!!