본문 바로가기

프로그래밍/Android

OpenGL 사용하기

 

음..  오픈지엘은 직관적인 api 구조를 가지고 있어서 사용하기에 그다지 어렵지 않다.

다이렉트x 5, 6 대의 느낌과 같다는 생각이 들기도 하는데,

윈도우에선 오픈지엘을 실제로 사용해보질 않아서 정확히 어떻다 이야길 하긴 그렇다.

 

사실 3D쪽은 api 외적으로 이해해야 하는 것들이 있는데, 뷰포트, 모델, 프로젝션, 월드 , 행렬, 픽킹, 필터, 각종 쉐이더까정.. api 제외하면 다이렉트x 관련 서적에 많이들 설명되어있다.

다른점도 있는데 다이렉트X는 월드,뷰, 프로젝션 순서의 파이프라인을 사용하지만

오픈지엘은 모델뷰, 프로젝션으로 단순화 되어 있다.

 

이 포스트에선 뭐 아는게 쥐뿔도 없으므로, 당연 api 만 다룬다.

 

1. 네모를 그리자!! -_-;;

튜토리얼에 언제나 나오는 내용.

 

1-1. 서피스뷰 선언

private GLSurfaceView glSurface;

 

glSurface = new GLSurfaceView( this );

glSurface.setRenderer( 렌더러 );

setContentView( glSurface );

 

1-2. 렌더러 만들기

Renderer 를 상속받을 클래스를 생성한다.

아래 세개의 함수를 오버라이드

 

public abstract void onSurfaceCreated(GL10 arg0, EGLConfig arg1);

public abstract void onSurfaceChanged(GL10 arg0, int arg1, int arg2);

public abstract void onDrawFrame(GL10 arg0);

 

 

1-3. 사각형 정의

 

일단 사각형의 각 정점을 정의한다.

private float vertices[] = { -1.0f , -1.0f , 0.0f ,

                                     1.0f , -1.0f, 0.0f ,

                                     -1.0f, 1.0f, 0.0f,

                                     1.0f, 1.0f, 0.0f };

 

1-4. 버퍼에 담기

오픈지엘에서는 버텍스나 칼라처리를 위해 Buffer 객체를 사용한다.

따라서, 위 정의된 버텍스 데이터를 FloatBuffer 에 넣는다.

 

ByteBuffer byteBuffer = ByteBuffer.allocateDirect( vertices.length * 4 );

byteBuffer.order( ByteOrder.nativeOrder() );

 

FloatBuffer vertexBuffer = byteBuffer.asFloatBuffer();

vertexBuffer.put(vertices);

vertexBuffer.position(0);

 

1-5. onSurfaceCreated : 서피스 초기화

gl.glShadeModel( GL10.GL_SMOOTH ); // 쉐이더 모델

gl.glClearColor( 0.0f, 0.0f, 0.0f, 0.5f ); // 배경색

gl.glClearDepth( 1.0f ); // 깊이 버퍼 크기

gl.glEnable( GL10.GL_DEPTH_TEST );

gl.glDepthFunc( GL10.GL_LEQUAL );

gl.glHint( GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST );

 

1-6. onSurfaceChanged : 서비스 변경, 리셋

gl.glViewport( 0, 0, width, height ) ; // 뷰포트를 다시 설정한다.

gl.glMatrixMode( GL10.GL_PROJECTION );  // 프로젝션 변환

gl.glLoadIdentity(); // 단위행렬로 리셋

 

GLU.gluPerspective( gl, 45.0f, (float)width / (float)height, 0.1f, 100.0f); // 화면좌표계로 변환

 

gl.glMatrixMode( GL10.GL_MODELVIEW );

gl.glLoadIdentity();

 

1-7. onDrawFrame

gl.glClear( GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT );

gl.glLoadIdentity(); // 모델뷰 행렬 초기화

 

gl.glTranslatef( 0.0f, -1.0f, -5.0f); // 이동

gl.glFrontFace( GL10.GL_CW );  // 앞면이 표시되는 버텍스 순서

gl.glVertexPointer( 3, GL10.GL_FLOAT, 0, vertexBuffer );

gl.glEnableClientState( GL10.GL_VERTEX_ARRAY );

gl.glColor4f( 0.5f, 0.5f, 1.0f, 1.0f); // 버텍스 색상을 파란색으로 변경

gl.glDrawArrays( GL10.GL_TRIANGLE_STRIP, 0, vertices.length / 3 ); // 각 버텍스를 연결하는 방법으로 그림

gl.glDisableClientState( GL10.GL_VERTEX_ARRARY);

 

// 별도의 색상 버퍼가 있는 경우 동일하게 해당 버퍼를 지정하고, 사용가능하게 한다.

gl.glColorPointer( 4, GL10.GL_FLOAT, 0, colorBuffer );

gl.glEnableClientState( GL10.GL_COLOR_ARRAY );

.

.

gl.glDisableClientState( GL10.GL_COLOR_ARRAY );

 

요럼 일단 사각형 출력은 완료~

1-8. 회전 시키기

gl.glTranslatef() 는 이동 메쏘드 라고 했는데, 회전은 당연 회전 메쏘드 사용하면 된다 -_-;;

버텍스회전, 이동은 모두 4X4 행렬 곱에 의해 처리되는데, 이와 관련한 행렬값을 제공하는 api들이

존재한다.

 

float rot = 0.0f;

 

onDrawFrame()

.

.

rot += 0.1f;

gl.glRotatef( rot , 1.0f, 0.0f, 0.0f ); // x축을 기준으로 회전

.

 

 

음 이러면 회전도 끝났다.

 

정리하자면~

 

>변환할 뷰를 선택한다.

gl.glMatrixMode(  GL10.GL_MODELVIEW );

 

>초기화

gl.glLoadIdentity();

 

>처리할 행렬 셋팅

gl.glTranslatef( 0.0f, -1.0f, -5.0f);

gl.glRotatef( rot , 1.0f, 0.0f, 0.0f );

 

>버텍스 버퍼 활성화

gl.glVertexPointer( 3, GL10.GL_FLOAT, 0, vertexBuffer );

gl.glEnableClientState( GL10.GL_VERTEX_ARRAY );

 

>그리기

gl.glDrawArrays( GL10.GL_TRIANGLE_STRIP, 0, vertices.length / 3 );

 

>버텍스 버퍼 비활성화

gl.glDisableClientState( GL10.GL_VERTEX_ARRARY);

 

오늘은 요것만...ㅎㅎ