2013년 8월 11일 일요일

GTK+-3.0과 OpenGL을 같이 사용할 수 있는 방법

GTK+-2.x 버전에서는 gtkglext이라는 것이 있어서 사용하기 편했는데

GTK+-3.0을 위한 gtkglext3은 아직 개발 중에 있다.

하지만, 3가지 정도의 회피 방법이 있다.

1. 아직 개발 중인 gtkglext3을 따로 얻어서 사용하는 방법

https://github.com/tdz/gtkglext

조금 불편하고 불안정 하지만 가장 손쉬운 방법이 아닌가 싶다.

사용 방법은 다음과 같다. 우선 소스코드를 다운 받고

기본적으로 libgtk-3.0-dev, libgtk-3.0-doc, gtk-doc-tools 등의 패키지가 설치 되어 있어야 한다.

그럼 다운 로드한 gtkglext의 디렉토리로 이동하자.

# cd ~/gtkglext-VERSION

README 파일을 읽어 보면 autogen.sh 스크립트를 이용해서 설치할 것을 권고한다.

하지만, bootstrap을 이용해서 설치용 스크립트를 생성하자.

# env ACLOCAL_FLAGS='-I /pkgconfig/share/aclocal -I /gtk/share/aclocal' ./bootstrap --prefix=${HOME}/gtkglext --enable-debug=yes

기본적인 준비는 갖추어 졌다. 다음과 같이 설정하고, 컴파일하고 설치하면 된다.

# ./configure
# make
# make install

마지막으로 /usr/local/include에서 잘 설치가 되어 있는지 확인하자.

참조 문서 : http://spectrum3d.sourceforge.net/documentation.html

2. OpenGL을 지원하는 libsdl을 사용하여 GTK+에 심어 넣는 방법.

이 방법은 두 종류의 용도가 겹치는 이종 라이브러리를 결합해야 하기 때문에 코드가 지져분해진다.

사용 예는 Gtk+-2.x 버전에 libsdl을 사용하는 방법이긴 하지만 거의 동일할 것으로 여겨진다.

출처 : http://sdl.5483.n7.nabble.com/SDL-WINDOWID-embedding-SDL-into-gtkmm-td13354.html

 #include <gtk/gtk.h>   
 #include <SDL.h>   
   
 /*   
  * GTK+ SDL Window reparenting test   
  * written by Mikael Eriksson <[hidden email]>   
  *   
  * Compile with:   
  * cc -g -o gtk-sdl-test gtk-sdl-test.c `pkg-config --cflags --libs gtk+-2.0 sdl`   
  */   
   
 gboolean do_sdl_stuff( gpointer data ) {   
     SDL_Event event;   
     SDL_Surface *display = data;   
   
     while ( SDL_PollEvent( &event ) ) {   
         /* Handle quit event, not sure if this will ever appear */   
         if ( event.type == SDL_QUIT ) return FALSE;   
         /* Handle clear userevent */   
         if ( event.type == SDL_USEREVENT && event.user.code == 0 ) {   
             SDL_FillRect( display, NULL, 0 );   
             SDL_Flip( display );   
         }   
         /* Handle draw rect userevent */   
         if ( event.type == SDL_USEREVENT && event.user.code == 1 ) {   
             SDL_Rect rect;   
               
             rect.x = rand() % 320;   
             rect.y = rand() % 240;   
             rect.w = rand() % 100 + 10;   
             rect.h = rand() % 100 + 10;   
   
             printf( "%ux%u+%u+%u\n", rect.w, rect.h, rect.x, rect.y );   
   
             SDL_FillRect( display, &rect, SDL_MapRGB( display->format, rand()%255, rand()%255, rand()%255 ) );   
             SDL_Flip( display );   
         }   
     }   
   
     return TRUE;   
 }   
   
 void button_clicked( GtkButton *button, gpointer data ) {   
     /* Put draw rect userevent on queue */   
     SDL_Event event;   
     event.type = SDL_USEREVENT;   
     event.user.code = 1;   
     SDL_PushEvent( &event );   
 }   
   
 void clear(void) {   
     /* Put clear userevent on queue */   
     SDL_Event event;   
     event.type = SDL_USEREVENT;   
     event.user.code = 0;   
     SDL_PushEvent( &event );   
 }   
   
 int main( int argc, char **argv ) {   
     GtkWidget *window, *sock, *box, *button;   
     char winhack[1024];   
     SDL_Surface *display;   
   
     gtk_init( &argc, &argv );   
   
     /* Create widgets */   
     window = gtk_window_new( GTK_WINDOW_TOPLEVEL );   
     sock = gtk_socket_new();   
     box = gtk_vbox_new( FALSE, 0 );   
     button = gtk_button_new_with_label( "Press me!" );   
   
     /* Setup socket widget */   
     gtk_widget_set_size_request( sock, 320, 240 );   
     gtk_box_pack_start( GTK_BOX(box), sock, TRUE, FALSE, 0 );   
   
     /* Setup button */   
     gtk_container_set_border_width( GTK_CONTAINER(button), 5 );   
     g_signal_connect( G_OBJECT(button), "clicked", G_CALLBACK(button_clicked), display );   
     gtk_box_pack_start( GTK_BOX(box), button, FALSE, FALSE, 0 );   
   
     /* Setup window */   
     gtk_container_add( GTK_CONTAINER(window), box );   
     g_signal_connect( G_OBJECT(window), "delete-event", G_CALLBACK(gtk_main_quit), NULL );   
     gtk_widget_show_all( window );   
   
     /* Make SDL windows appear inside socket window */   
     snprintf( winhack, sizeof winhack, "SDL_WINDOWID=%i", gtk_socket_get_id( GTK_SOCKET(sock) ) );   
     SDL_putenv( winhack );   
   
     /* Init SDL */   
     if ( SDL_Init( SDL_INIT_VIDEO ) < 0 ) {   
         fprintf( stderr, "%s.\n", SDL_GetError() );   
         return EXIT_FAILURE;   
     }   
   
     /* Create SDL window */   
     if ( !( display = SDL_SetVideoMode( 320, 240, 0, 0 ) ) ) {   
         fprintf( stderr, "%s.\n", SDL_GetError() );   
         return EXIT_FAILURE;   
     }   
   
     /* Clear the SDL window */   
     clear();   
   
     /* Setup SDL event handlig timer */   
     g_timeout_add( 100, do_sdl_stuff, display );   
   
     /* Start main loop */   
     gtk_main();   
   
     return 0;   
 }   

3. 마지막으로 새로운 Gtk+-3.0 을 위한 opengl binding을 새로 만드는 방법.

이 방법도 이미 구현되어져 있다. 조금만 시간이 많다면 시도해 볼만한 방법이 있다.

https://github.com/andrepiske/tegtkgl

위의 링크를 찾아 가보면 소스 코드를 받아 볼 수 있다.

그리고 마지막으로 위의 두 가지의 방법을 사용한 예로 spectrum3D라는 프로젝트가 있다.

http://spectrum3d.sourceforge.net/

마찬가지로 시간이 많다면 살펴보고 시도해 볼만 하다.

무엇보다도 gtkglext이 debian 패키지로 빨리 나오길 바란다.

댓글 없음:

댓글 쓰기