레이블이 OpenGL인 게시물을 표시합니다. 모든 게시물 표시
레이블이 OpenGL인 게시물을 표시합니다. 모든 게시물 표시

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 패키지로 빨리 나오길 바란다.

2011년 8월 16일 화요일

OpenGL 프로그래밍에 대해서

OpenGL은 하드웨어 독립적인 2D/3D 그래픽 라이브러리이다. SGI사의 IRIS GL라이브러리를 기초로 개발되었지만 개방형이다. 그래픽 라이브러리이기 때문에 기본적인 창관리와 입력처리에 대한 부분이 없다. 그래서 GLUT이라는 보조 도구를 이용해서 창을 관리하고 입력을 관리하는 방법을 제공한다. 이것도 역시 시스템 독립적이기 때문에 OpenGL과 GLUT의 조합이면 어떤 시스템에서도 동일한 결과를 갖는 프로그램을 개발 할 수 있다.

GLUT: OpenGL 유틸리티 툴킷을 줄인 말인 것 같다. 내부에 많은 상태 변수들을 관리하고 있단다. 간단히 초기화하고 창에 점과 선만 그릴 수 있었음 만족한다. 간단히 초기화 하는 법은 다음과 같다.


#include  

void MyIdle(void)
{
   /* 사용된 변수값을 다음 프레임의 상태로 수정해 주는부분*/
};

void MyDisplay(void)
{
   /* 프레임에 실제 그림을 그리는 OpenGL명령어들이 들어간다. */
   /* 프레임이 다 그려진 다음 버퍼를 교체한다. */
   glutSwapBuffers();
};

void main(int argcp, char **argv)
{
   /* GLUT상태를 초기화 한다. */
   glutInit(&argcp, argv);
   glutInitWindowSize(640, 480);
   glutInitWindowPosition(0, 0);

   /* 창을 연다. */
   glutCreateWindow("My OpenGL Application");

   /* 디스플레이모드를 선택한다.:
      이중버퍼 & RGBA색상 */
   glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);

   /* 콜백함수들을 등록한다. */
   glutDisplayFunc(MyDisplay)
   glutIdleFunc(MyIdle)

   /* 이벤트 처리엔진을 시작한다 */
   glutMainLoop();
};