3D그래픽2011. 6. 29. 23:13
Android 2.2 ApiDemo에는 OpenGL ES 2.0을 이용하여 Textured Triangle을 회전시키는 예제가 들어있다.

그냥 막연하게 OpenGL ES 1.1을 가지고 뭔가를 해 보려고 했었는데, GLSurfaceView.Renderer interface method 들의 argument가 GL10으로 되어 있어, 그걸 GL11로 casting 해서 사용해 보려고도 했었는데 (당연히) 실패했다(하하^^;). 그래서, "아... OpenGL ES 2.0은 커녕 OpenGL ES 1.1도 사용하기 어렵구나..." 라고만 생각하고 있었는데, 바보 같은 생각 이었다. (역시 사람은 모르면 찾아보고 물어봐야 한다! -_-;)

GLSurfaceView는 하나의 Activity에서 하나의 instance만 사용이 가능하기 때문에, (아마도 OpenGL이 state machine 기반이기 때문이 아닐까 짐작) GLES11 또는 GLES20 class의 static method로 이용이 가능했던 것이다. GLES11 or GLES20 reference document만 차분히 확인 했어도 짐작할 수 있었던 내용인데, GLSurfaceView.Renderer interface method 들의 argument로 넘겨주는 GL10 instance에 낚여 버렸다. (javax.microedition.khronos.opengles.GLnx와 android.opengl.GLESnx의 차이는 또 다시 확인 해 봐야 할 사항이다. License 때문에 Java Micro Edition은 Android에서 빠졌다고 알고 있는데, 이건 왜 넣어 놓은걸까? 궁금!)

어쨌든, Android 2.2 이상에서 OpenGL ES 2.0을 이용하는 방법(순서?)를 ApiDemo를 기준으로 정리하면 다음과 같다.

[[[ Activity ]]]
1. GLSurfaceView instance를 생성
2. ActivityManager service에서 device configuration info(android.content.pm.ConfigurationInfo)를 획득하여 OpenGL ES 버전을 확인
3. (1)에서 생성한 GLSurfaceView가 사용할 EGL의 Version을 2(아마도 2.0?)로 설정
4. OpenGL ES 2.0으로 작성 된 Renderer instance를 (1)에서 생성한 GLSurfaceView의 renderer로 설정
5. 선택적으로 rendering overhead를 줄이기 위해, (1)에서 생성한 GLSurfaceView의 setRenderMode method를 호출하여 렌더링 모드를 RENDERMODE_WHEN_DIRTY로 설정할 수 있다. (기본은 RENDERMODE_CONTINUOSLY)

[[[ GLSurfaceView.Renderer ]]]
(onSurfaceCreated)
1. Vertex Shader를 생성하고, Vertext Shader 코드를 로드 & 컴파일
    glCreateShader(), glShaderSource(), glCompileShader()
2. Fragment Shader를 생성하고, Fragment Shader  코드를 로드 & 컴파일
    glCreateShader()glShaderSource()glCompileShader()
3. Program을 생성 (Vertext Shader 및 Fragment Shader를 묶는 단위)
3-1. Vertext Shader를 Program에 attach glCreateProgram()
3-2. Fragment Shader를 Program에 attach glAttachShader()
3-3. Vertext Shader와 Fragment Shader가 추가된 Program을 링크 glLinkProgram()
4. Program으로부터 attribute와 uniform을 참조할 수 있는 handle을 획득
    glGetAttribLocation(), glGetUniformLocation()
5. Rendering에 사용 될 Texture를 준비
5-1. Texture object 생성
5-2. 생성된 Texture의 ID를 GL_TEXTURE_2D로 바인딩
5-3. GL_TEXTURE_2D의 옵션(속성)을 설정
5-4. Bitmap data를 GL_TEXTURE_2D로 전송
6. Matrix class를 이용해 View Matrix를 초기화 (Camera 설정이라고 생각하면 될 듯)
    Matrix.setLootAtM()

(onSurfaceChanged)

7. View 영역(View port)를 설정 glViewport()
8. Matrix class를 이용해 Projection Matrix를 초기화 Matrix.frustumM()

(onDrawFrame)
9. Clear 색상 설정 glClearColor()
10. Depth buffer와 Color buffer를 초기화 glClear()
11. 사용할 Program을 지정 glUseProgram()
12. Texture를 활성화 하고, (5-4)에서 전송 해 둔 Texture ID와 연결
13. Vertex 좌표가 저장된 buffer의 포인터를 attribute로 설정 glVertexAttribPointer()
     - glVertexAttribPointer() 사용 시 주의할 점은, 5th argument인 stride는 byte 기준이라는 것!
     - 즉, float 형 x, y, z 세 개씩 건너 뛰어야 할 경우, stride 값은 3 * float 변수의 byte 크기(4) = 12
        (stride 값을 3으로 주고, 안보여서 한참 삽질 했네-_-;)
14. Vertex attribute array를 활성화 glEnableVertexAttribArray()
15. Texture 좌표가 저장된 buffer의 포인터를 attribute로 설정
16. Model Matrix 설정(여기서는 회전) Matrix.setRotateM()
17. MVP Matrix를 계산(MVPMatrix = mProjMatrix * VMatrix * MMatrix) Matrix.multiplyMM()
18. MVP Matrix를 uniform으로 설정 glUniformMatrix4fv()
19. 삼각형을 출력 glDrawArrays()

'3D그래픽' 카테고리의 다른 글

Transforms (변환 행렬)  (0) 2011.09.06
Goraud shading vs. Phong shading  (0) 2011.09.02
Normal Transform(법선벡터 변환)  (0) 2011.09.02
COLLADA (3D Asset Exchange Schema)  (0) 2011.08.31
OpenGL ES 2.0 Q&A by myself  (5) 2011.07.12
Posted by 세월의돌