Android에는 Open Graphics Library(OpenGL®), 특히 OpenGL ES API를 사용하는 고성능 2D 및 3D 그래픽 지원이 포함되어 있습니다. OpenGL은 3D 그래픽 처리 하드웨어의 표준 소프트웨어 인터페이스를 지정하는 크로스 플랫폼 그래픽 API입니다. OpenGL ES는 임베디드 기기용 OpenGL 사양의 한 버전입니다. Android는 여러 버전의 OpenGL ES API를 지원합니다.
- OpenGL ES 2.0 - 이 API 사양은 Android 2.2 (API 수준 8) 이상에서 지원됩니다.
- OpenGL ES 3.0 - 이 API 사양은 Android 4.3 (API 수준 18) 이상에서 지원됩니다.
- OpenGL ES 3.1 - 이 API 사양은 Android 5.0 (API 수준 21) 이상에서 지원됩니다.
- OpenGL ES 3.2 - 이 API 사양은 Android 7.0 (API 수준 24) 이상에서 지원됩니다.
주의: Android 플랫폼 버전과 관계없이 기기 제조업체에서 이 그래픽 파이프라인의 구현을 제공하지 않으면 기기에서 OpenGL ES 3.0 API를 지원할 수 없습니다. 매니페스트에서 OpenGL ES 3.0이 필요하다고 지정하면 버전이 기기에 있는지 확인할 수 있습니다. 필요한 하위 수준 버전이 필요하다고 지정했지만 가능한 경우 3.0 기능을 사용하려는 경우 런타임에 기기에서 지원하는 OpenGL 버전을 확인해야 합니다. 이 작업을 실행하는 방법에 관한 자세한 내용은 OpenGL ES 버전 확인을 참조하세요.
참고: Android에는 OpenGL ES 1.0 및 1.1 지원 기능이 포함되어 있지만 이 버전의 API는 지원 중단되었으므로 최신 애플리케이션에서 사용하면 안 됩니다.
참고: Android 프레임워크에서 제공하는 특정 API는 J2ME JSR239 OpenGL ES API와 비슷하지만 동일하지는 않습니다. J2ME JSR239 사양에 익숙하다면 변형에 주의하세요.
참고 항목
기본사항
Android는 프레임워크 API와 NDK (Native Development Kit)를 통해 OpenGL을 지원합니다. 이 주제에서는 Android 프레임워크 인터페이스를 집중적으로 다룹니다. NDK에 관한 자세한 내용은 Android NDK를 참고하세요.
Android 프레임워크에는 OpenGL ES API로 그래픽을 만들고 조작할 수 있는 두 가지 기본 클래스, GLSurfaceView
및 GLSurfaceView.Renderer
가 있습니다. Android 애플리케이션에서 OpenGL을 사용하는 것이 목표라면 활동에서 이러한 클래스를 구현하는 방법을 이해해야 합니다.
GLSurfaceView
- 이 클래스는 OpenGL API 호출을 사용하여 객체를 그리고 조작할 수 있는
View
이며SurfaceView
와 기능이 비슷합니다.GLSurfaceView
인스턴스를 만들고 여기에Renderer
를 추가하여 이 클래스를 사용할 수 있습니다. 그러나 터치 스크린 이벤트를 캡처하려면 OpenGL 학습 과정 터치 이벤트에 응답에 표시된 대로GLSurfaceView
클래스를 확장하여 터치 리스너를 구현해야 합니다. GLSurfaceView.Renderer
- 이 인터페이스를 통해서는
GLSurfaceView
에 그래픽을 그리는 데 필요한 메서드를 정의합니다. 이 인터페이스의 구현을 별도의 클래스로 제공하고GLSurfaceView.setRenderer()
를 사용하여GLSurfaceView
인스턴스에 연결해야 합니다.GLSurfaceView.Renderer
인터페이스를 사용하려면 다음 메서드를 구현해야 합니다.-
onSurfaceCreated()
:GLSurfaceView
를 만들 때 시스템에서 이 메서드를 한 번 호출합니다. 이 메서드를 사용하면 OpenGL 환경 매개변수 설정 또는 OpenGL 그래픽 객체 초기화와 같이 한 번만 실행해야 하는 작업을 실행할 수 있습니다. -
onDrawFrame()
: 시스템에서GLSurfaceView
를 다시 그릴 때마다 이 메서드를 호출합니다. 이 메서드를 그래픽 객체를 그리고 다시 그리는 기본 실행 지점으로 사용합니다. -
onSurfaceChanged()
:GLSurfaceView
의 크기 변경이나 기기 화면의 방향 변경을 포함하여GLSurfaceView
도형이 변경될 때 시스템에서 이 메서드를 호출합니다. 예를 들어 기기가 세로 모드에서 가로 모드로 변경될 때 시스템에서 이 메서드를 호출합니다. 이 메서드를 사용하면GLSurfaceView
컨테이너의 변경사항에 대응할 수 있습니다.
-
OpenGL ES 패키지
GLSurfaceView
및 GLSurfaceView.Renderer
를 사용하여 OpenGL ES의 컨테이너 뷰를 설정하고 나면 다음 클래스를 사용하여 OpenGL API 호출을 시작할 수 있습니다.
- OpenGL ES 2.0 API 클래스
android.opengl.GLES20
- 이 패키지는 OpenGL ES 2.0 인터페이스를 제공하며 Android 2.2 (API 수준 8)부터 사용할 수 있습니다.
- OpenGL ES 3.0/3.1/3.2 API 패키지
android.opengl
- 이 패키지는 OpenGL ES 3.0/3.1 클래스에 인터페이스를 제공합니다. 버전 3.0은 Android 4.3(API 레벨 18)부터 사용할 수 있습니다. 버전 3.1은 Android 5.0 (API 수준 21)부터 사용할 수 있습니다. 버전 3.2는 Android 7.0 (API 수준 24)부터 사용할 수 있습니다.
OpenGL ES를 사용하여 즉시 앱 빌드를 시작하려면 OpenGL ES로 그래픽 표시 클래스를 따르세요.
OpenGL 요구사항 선언
애플리케이션에서 일부 기기에서 사용할 수 없는 OpenGL 기능을 사용하는 경우 이러한 요구사항을 AndroidManifest.xml 파일에 포함해야 합니다. 다음은 가장 일반적인 OpenGL manifest 선언입니다.
- OpenGL ES 버전 요구사항 - 애플리케이션에 특정 버전의 OpenGL ES가 필요한 경우 아래와 같이 매니페스트에 다음 설정을 추가하여 요구사항을 선언해야 합니다.
OpenGL ES 2.0:
<!-- Tell the system this app requires OpenGL ES 2.0. --> <uses-feature android:glEsVersion="0x00020000" android:required="true" />
이 선언을 추가하면 Google Play에서 OpenGL ES 2.0을 지원하지 않는 기기에 애플리케이션이 설치되지 않도록 제한합니다. 애플리케이션이 OpenGL ES 3.0을 지원하는 기기 전용인 경우 매니페스트에서 이를 지정할 수도 있습니다.
OpenGL ES 3.0:
<!-- Tell the system this app requires OpenGL ES 3.0. --> <uses-feature android:glEsVersion="0x00030000" android:required="true" />
OpenGL ES 3.1:
<!-- Tell the system this app requires OpenGL ES 3.1. --> <uses-feature android:glEsVersion="0x00030001" android:required="true" />
OpenGL ES 3.2:
<!-- Tell the system this app requires OpenGL ES 3.2. --> <uses-feature android:glEsVersion="0x00030002" android:required="true" />
참고: OpenGL ES 3.x API는 2.0 API와 하위 호환되므로 애플리케이션에서 OpenGL ES를 더욱 유연하게 구현할 수 있습니다. OpenGL ES 2.0 API를 매니페스트에서 요구사항으로 선언하면 이 API 버전을 기본값으로 사용하고 런타임에 3.x API의 사용 가능 여부를 확인한 다음 기기에서 지원하는 경우 OpenGL ES 3.x 기능을 사용할 수 있습니다. 기기에서 지원하는 OpenGL ES 버전을 확인하는 방법에 관한 자세한 내용은 OpenGL ES 버전 확인을 참조하세요.
- 텍스처 압축 요구사항 - 애플리케이션이 텍스처 압축 형식을 사용하는 경우
<supports-gl-texture>
를 사용하여 매니페스트 파일에서 애플리케이션이 지원하는 형식을 선언해야 합니다. 사용 가능한 텍스처 압축 형식에 관한 자세한 내용은 텍스처 압축 지원을 참고하세요.매니페스트에서 텍스처 압축 요구사항을 선언하면 선언된 압축 유형을 하나 이상 지원하지 않는 기기 사용자에게 애플리케이션이 표시되지 않습니다. 텍스처 압축에서 Google Play 필터링이 작동하는 방법에 관한 자세한 내용은
<supports-gl-texture>
문서의 Google Play 및 텍스처 압축 필터링 섹션을 참고하세요.
그린 객체의 좌표 매핑
Android 기기에서 그래픽을 표시할 때 기본적인 문제 중 하나는 화면의 크기와 모양이 다양할 수 있다는 것입니다. OpenGL은 정사각형의 균일 좌표계를 가정하고, 기본적으로 완전히 정사각형인 것처럼 일반적으로 정사각형이 아닌 화면에 이러한 좌표를 그립니다.
![](https://developer.android.com/static/images/opengl/coordinates.png?authuser=9&hl=ko)
그림 1. 일반적인 Android 기기 화면 (오른쪽)에 매핑된 기본 OpenGL 좌표계 (왼쪽)
위의 그림은 OpenGL 프레임에 가정한 균일 좌표계(왼쪽)와 이러한 좌표가 가로 모드 방향(오른쪽)의 일반적인 기기 화면에 실제로 매핑되는 방식을 보여줍니다. 이 문제를 해결하려면 OpenGL 투영 모드와 카메라 뷰를 적용하여 좌표를 변환하여 그래픽 객체가 모든 디스플레이에서 올바른 비율을 갖도록 할 수 있습니다.
투영 및 카메라 보기를 적용하려면 투영 행렬과 카메라 보기 행렬을 만들어 OpenGL 렌더링 파이프라인에 적용합니다. Android 기기 화면에 올바르게 매핑되도록 투영 행렬은 그래픽 좌표를 다시 계산합니다. 카메라 뷰 매트릭스는 특정 눈 위치에서 객체를 렌더링하는 변환을 만듭니다.
OpenGL ES 2.0 이상의 투영 및 카메라 보기
ES 2.0 및 3.0 API에서는 먼저 그래픽 객체의 꼭짓점 셰이더에 행렬 멤버를 추가하여 투영 및 카메라 보기를 적용합니다. 이 행렬 멤버를 추가하면 투영 및 카메라 보기 행렬을 생성하여 객체에 적용할 수 있습니다.
- 꼭짓점 셰이더에 행렬 추가 - 뷰 투영 행렬의 변수를 만들어 셰이더 위치의 승수로 포함합니다. 다음 꼭짓점 셰이더 코드 예에서 포함된
uMVPMatrix
멤버를 사용하면 이 셰이더를 사용하는 객체의 좌표에 투영 및 카메라 보기 행렬을 적용할 수 있습니다.Kotlin
private val vertexShaderCode = // This matrix member variable provides a hook to manipulate // the coordinates of objects that use this vertex shader. "uniform mat4 uMVPMatrix; \n" + "attribute vec4 vPosition; \n" + "void main(){ \n" + // The matrix must be included as part of gl_Position // Note that the uMVPMatrix factor *must be first* in order // for the matrix multiplication product to be correct. " gl_Position = uMVPMatrix * vPosition; \n" + "} \n"
Java
private final String vertexShaderCode = // This matrix member variable provides a hook to manipulate // the coordinates of objects that use this vertex shader. "uniform mat4 uMVPMatrix; \n" + "attribute vec4 vPosition; \n" + "void main(){ \n" + // The matrix must be included as part of gl_Position // Note that the uMVPMatrix factor *must be first* in order // for the matrix multiplication product to be correct. " gl_Position = uMVPMatrix * vPosition; \n" + "} \n";
참고: 위의 예에서는 결합된 투영 행렬과 카메라 뷰 행렬을 적용하는 꼭짓점 셰이더에 단일 변환 행렬 멤버를 정의합니다. 애플리케이션 요구사항에 따라 독립적으로 변경할 수 있도록 꼭짓점 셰이더에 별도의 투영 행렬과 카메라 보기 행렬 멤버를 정의해야 할 수 있습니다.
- 셰이더 행렬 액세스 - 꼭짓점 셰이더에 후크를 만들어 투영과 카메라 뷰를 적용한 후 이 변수에 액세스하여 투영 및 카메라 보기 행렬을 적용할 수 있습니다. 다음 코드는 위의 꼭짓점 셰이더에 정의된 행렬 변수에 액세스하기 위해
GLSurfaceView.Renderer
구현의onSurfaceCreated()
메서드를 수정하는 방법을 보여줍니다.Kotlin
override fun onSurfaceCreated(gl: GL10, config: EGLConfig) { ... muMVPMatrixHandle = GLES20.glGetUniformLocation(program, "uMVPMatrix") ... }
Java
public void onSurfaceCreated(GL10 unused, EGLConfig config) { ... muMVPMatrixHandle = GLES20.glGetUniformLocation(program, "uMVPMatrix"); ... }
- 투영 및 카메라 보기 행렬 만들기 - 그래픽 객체에 적용할 투영 및 보기 행렬을 생성합니다. 다음 코드 예는
GLSurfaceView.Renderer
구현의onSurfaceCreated()
및onSurfaceChanged()
메서드를 수정하여 기기의 화면 가로세로 비율에 따라 카메라 뷰 매트릭스와 투영 매트릭스를 만드는 방법을 보여줍니다.Kotlin
override fun onSurfaceCreated(gl: GL10, config: EGLConfig) { ... // Create a camera view matrix Matrix.setLookAtM(vMatrix, 0, 0f, 0f, -3f, 0f, 0f, 0f, 0f, 1.0f, 0.0f) } override fun onSurfaceChanged(gl: GL10, width: Int, height: Int) { GLES20.glViewport(0, 0, width, height) val ratio: Float = width.toFloat() / height.toFloat() // create a projection matrix from device screen geometry Matrix.frustumM(projMatrix, 0, -ratio, ratio, -1f, 1f, 3f, 7f) }
Java
public void onSurfaceCreated(GL10 unused, EGLConfig config) { ... // Create a camera view matrix Matrix.setLookAtM(vMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f); } public void onSurfaceChanged(GL10 unused, int width, int height) { GLES20.glViewport(0, 0, width, height); float ratio = (float) width / height; // create a projection matrix from device screen geometry Matrix.frustumM(projMatrix, 0, -ratio, ratio, -1, 1, 3, 7); }
- 투영 및 카메라 보기 행렬 적용 - 투영 및 카메라 보기 변환을 적용하려면 행렬을 곱한 다음 꼭짓점 셰이더에 설정합니다. 다음 코드 예에서는
GLSurfaceView.Renderer
구현의onDrawFrame()
메서드를 수정하여 위의 코드에서 만든 투영 행렬과 카메라 보기를 결합한 다음 OpenGL에서 렌더링할 그래픽 객체에 적용하는 방법을 보여줍니다.Kotlin
override fun onDrawFrame(gl: GL10) { ... // Combine the projection and camera view matrices Matrix.multiplyMM(vPMatrix, 0, projMatrix, 0, vMatrix, 0) // Apply the combined projection and camera view transformations GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, vPMatrix, 0) // Draw objects ... }
Java
public void onDrawFrame(GL10 unused) { ... // Combine the projection and camera view matrices Matrix.multiplyMM(vPMatrix, 0, projMatrix, 0, vMatrix, 0); // Apply the combined projection and camera view transformations GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, vPMatrix, 0); // Draw objects ... }
OpenGL ES 2.0에서 투영 및 카메라 보기를 적용하는 방법에 관한 전체 예는 OpenGL ES로 그래픽 표시 클래스를 참고하세요.
도형 면 및 권선
OpenGL에서 도형의 면은 3차원 공간에서 3개 이상의 점으로 정의되는 표면입니다. 3개 이상의 3차원 점 집합 (OpenGL의 꼭짓점이라고 함)에는 앞면과 뒷면이 있습니다. 앞면과 뒷면은 어떻게 구분하나요? 좋은 질문입니다. 답은 권선, 즉 도형의 점을 정의하는 방향과 관련이 있습니다.
![삼각형의 꼭짓점 좌표는](https://developer.android.com/static/images/opengl/ccw-winding.png?authuser=9&hl=ko)
그림 1. 시계 반대 방향 그리기 순서로 변환되는 좌표 목록 그림
이 예에서 삼각형의 점은 시계 반대 방향으로 그려지는 순서로 정의됩니다. 이 좌표를 그리는 순서에 따라 도형의 권선 방향이 정의됩니다. 기본적으로 OpenGL에서는 시계 반대 방향으로 그려지는 면이 앞면입니다. 그림 1에 표시된 삼각형은 사용자가 도형의 앞면을 보고 (OpenGL에서 해석된 대로) 다른 면이 뒷면이 되도록 정의됩니다.
도형의 앞면이 어떤 면인지를 아는 것이 왜 중요한가요? 그 답은 흔히 사용되는 면 선별이라고 하는 OpenGL의 기능과 관련이 있습니다. 면 선별은 렌더링 파이프라인이 도형의 뒷면을 무시 (계산하거나 그리지 않음)할 수 있도록 하여 시간, 메모리, 처리 주기를 절약하는 OpenGL 환경의 옵션입니다.
Kotlin
gl.apply { // enable face culling feature glEnable(GL10.GL_CULL_FACE) // specify which faces to not draw glCullFace(GL10.GL_BACK) }
Java
// enable face culling feature gl.glEnable(GL10.GL_CULL_FACE); // specify which faces to not draw gl.glCullFace(GL10.GL_BACK);
도형의 어느 면이 앞면과 뒷면인지 모르는 상태에서 면 선별 기능을 사용하려고 하면 OpenGL 그래픽이 약간 얇아지거나 전혀 표시되지 않을 수 있습니다. 따라서 항상 시계 반대 방향 그리기 순서로 OpenGL 도형의 좌표를 정의합니다.
참고: 시계 방향 면을 전면으로 취급하도록 OpenGL 환경을 설정할 수 있습니다. 하지만 그렇게 하면 코드가 더 많이 필요하며 숙련된 OpenGL 개발자에게 도움을 요청할 때 혼란을 줄 수 있습니다. 따라서 위와 같이 설정하지 마세요.
OpenGL 버전 및 기기 호환성
OpenGL ES 1.0 및 1.1 API 사양은 Android 1.0부터 지원됩니다. OpenGL ES 1.0/1.1 API를 사용한 그래픽 프로그래밍은 2.0 이상 버전을 사용하는 것과 크게 다릅니다. OpenGL ES 2.0은 Android 2.2 (API 수준 8)부터 모든 Android 기기에서 지원되며 OpenGL ES로 개발 중인 새 애플리케이션에 권장되는 가장 이른 버전입니다. OpenGL ES 3.0은 OpenGL ES 3.0 API 구현을 제공하는 기기에서 Android 4.3 (API 수준 18) 이상에서 지원됩니다. OpenGL ES의 특정 버전을 지원하는 Android 지원 기기의 상대적인 숫자에 관한 자세한 내용은 OpenGL ES 버전 대시보드를 참고하세요.
그래픽 요구사항을 신중하게 고려하고 애플리케이션에 가장 적합한 API 버전을 선택해야 합니다. 자세한 내용은 OpenGL API 버전 선택을 참고하세요.
OpenGL ES 3.0 API는 2.0 API보다 추가 기능과 우수한 성능을 제공하며 이전 버전과도 호환됩니다. 즉, OpenGL ES 2.0을 타겟팅하는 애플리케이션을 작성하고 OpenGL ES 3.0 그래픽 기능이 있는 경우 조건부로 포함할 수 있습니다. 3.0 API를 사용할 수 있는지 확인하는 방법에 관한 자세한 내용은 OpenGL ES 버전 확인을 참고하세요.
텍스처 압축 지원
텍스처 압축은 메모리 요구사항을 줄이고 메모리 대역폭을 더 효율적으로 사용하여 OpenGL 애플리케이션의 성능을 크게 향상시킬 수 있습니다. Android 프레임워크는 ETC1Util
유틸리티 클래스 및 etc1tool
압축 도구 (Android SDK <sdk>/tools/
에 있음)를 포함하여 ETC1 압축 형식을 표준 기능으로 지원합니다. 텍스처 압축을 사용하는 Android 애플리케이션의 예는 Android SDK(<sdk>/samples/<version>/ApiDemos/src/com/example/android/apis/graphics/
)의 CompressedTextureActivity
코드 샘플을 참고하세요.
ETC1 형식은 OpenGL ES 2.0 이상을 지원하는 모든 Android 기기에서 지원됩니다.
참고: ETC1 텍스처 압축 형식은 투명도 (알파 채널) 텍스처를 지원하지 않습니다. 애플리케이션에 투명한 텍스처가 필요하다면 대상 기기에서 사용할 수 있는 다른 텍스처 압축 형식을 조사해야 합니다. ETC1을 사용하여 알파 채널 텍스처를 렌더링하는 방법은 ETC1 텍스처 객체 두 개(첫 번째는 색상 데이터, 두 번째는 알파 채널 데이터)를 결합한 후 프래그먼트 셰이더에서 두 텍스처의 값을 결합하는 것입니다.
ETC2/EAC 텍스처 압축 형식은 OpenGL ES 3.0 API를 사용할 때 사용 가능합니다. 이 텍스처 형식은 높은 시각적 품질과 뛰어난 압축 비율을 제공하며 투명도 (알파 채널)도 지원합니다.
ETC 형식 외에도 Android 기기는 GPU 칩셋과 OpenGL 구현을 기반으로 텍스처 압축을 다양하게 지원합니다. 애플리케이션에서 지원해야 하는 압축 유형을 확인하려면 타겟팅하는 기기에서 텍스처 압축 지원을 조사해야 합니다. 특정 기기에서 지원되는 텍스처 형식을 확인하려면 기기를 쿼리하고 기기에서 지원하는 텍스처 압축 형식 (및 기타 OpenGL 기능)을 식별하는 OpenGL 확장 이름을 검토해야 합니다. 일반적으로 지원되는 텍스처 압축 형식은 다음과 같습니다.
- 적응형 확장 가능한 텍스처 압축 (ASTC) - 이전 형식을 대체하도록 설계된 텍스처 압축 형식입니다. 다양한 블록 크기를 지원하므로 이전 형식보다 더 유연합니다.
GL_KHR_texture_compression_astc_ldr
GL_KHR_texture_compression_astc_hdr
(높은 다이내믹 레인지)
- S3TC(DXTn/DXTC) - S3 텍스처 압축(S3TC)에는 다양한 형식 변형(DXT1 ~ DXT5)이 있으며 덜 광범위하게 사용 가능합니다. 이 형식에서는 4비트 알파 또는 8비트 알파 채널이 있는 RGB 텍스처를 지원합니다. 이러한 형식은 다음 OpenGL 확장 이름으로 표시됩니다.
GL_EXT_texture_compression_s3tc
GL_EXT_texture_compression_dxt1
다음 텍스처 압축 형식은 기존 형식으로 간주되며 새 애플리케이션에 사용하지 않는 것이 좋습니다.
- ATITC (ATC) - ATI 텍스처 압축 (ATITC 또는 ATC)은 다양한 기기에서 사용할 수 있으며 알파 채널이 있거나 없는 RGB 텍스처의 고정 속도 압축을 지원합니다. 이 형식은 여러 OpenGL 확장 이름으로 표시될 수 있습니다. 예를 들면 다음과 같습니다.
GL_AMD_compressed_ATC_texture
GL_ATI_texture_compression_atitc
- PVRTC - PowerVR 텍스처 압축 (PVRTC)은 다양한 기기에서 사용할 수 있으며 알파 채널 유무와 관계없이 픽셀당 2비트 및 4비트 텍스처를 지원합니다.
이 형식은 다음 OpenGL 확장 이름으로 표시됩니다.
GL_IMG_texture_compression_pvrtc
- 3DC - 3DC 텍스처 압축 (3DC)은 알파 채널이 있는 RGB 텍스처를 지원하는 덜 널리 사용되는 형식입니다. 이 형식은 다음 OpenGL 확장 이름으로 표시됩니다.
GL_AMD_compressed_3DC_texture
경고: 이러한 텍스처 압축 형식은 일부 기기에서는 지원되지 않습니다. 이러한 형식에 관한 지원은 제조업체 및 기기에 따라 다를 수 있습니다. 특정 기기에서 텍스처 압축 형식을 확인하는 방법에 관한 자세한 내용은 다음 섹션을 참고하세요.
참고: 애플리케이션에서 지원할 텍스처 압축 형식을 결정한 후에는 <supports-gl-texture> 를 사용하여 매니페스트에서 이를 선언해야 합니다. 이 선언을 사용하면 Google Play와 같은 외부 서비스로 필터링할 수 있으므로 앱에 필요한 형식을 지원하는 기기에만 앱이 설치됩니다. 자세한 내용은 OpenGL 매니페스트 선언을 참고하세요.
OpenGL 확장 판별
OpenGL의 구현은 지원되는 OpenGL ES API의 확장 측면에서 Android 기기에 따라 다릅니다. 이러한 확장에는 텍스처 압축이 포함되지만 일반적으로 OpenGL 기능 세트의 다른 확장도 포함됩니다.
특정 기기에서 지원되는 텍스처 압축 형식 및 기타 OpenGL 확장자를 확인하려면 다음 단계를 따르세요.
- 대상 기기에서 다음 코드를 실행하여 지원되는 텍스처 압축 형식을 확인합니다.
Kotlin
var extensions = gl.glGetString(GL10.GL_EXTENSIONS)
Java
String extensions = gl.glGetString(GL10.GL_EXTENSIONS);
경고: 이 호출 결과는 기기 모델별로 다양합니다! 일반적으로 지원되는 압축 유형을 확인하려면 여러 대상 기기에서 이 호출을 실행해야 합니다.
- 이 메서드의 출력을 검토하여 기기에서 지원되는 OpenGL 확장 프로그램을 확인합니다.
AEP(Android Extension Pack)
AEP를 사용하면 애플리케이션이 OpenGL 3.1 사양에 설명된 핵심 집합 이상의 표준화된 OpenGL 확장 집합을 지원할 수 있습니다. 이러한 확장 프로그램을 함께 패키징하면 여러 기기에서 일관된 기능을 제공할 수 있을 뿐만 아니라 개발자가 최신 모바일 GPU 기기를 최대한 활용할 수 있습니다.
AEP를 사용하면 프래그먼트 셰이더의 이미지, 셰이더 저장소 버퍼 및 원자 카운터 지원도 개선됩니다.
앱에서 AEP를 사용할 수 있으려면 앱 manifest에서 AEP가 필수임을 선언해야 합니다. 플랫폼 버전에서도 지원해야 합니다.
AEP에 지정된 모든 추가 기능은 기본 OpenGL ES 3.2 사양에 포함되어 있습니다. 앱에 OpenGL ES 3.2가 필요한 경우 AEP를 요구하지 않아도 됩니다.
manifest에서 다음과 같이 AEP 요구사항을 선언합니다.
<uses-feature android:name="android.hardware.opengles.aep" android:required="true" />
플랫폼 버전이 AEP를 지원하는지 확인하려면 hasSystemFeature(String)
메서드를 사용하여 FEATURE_OPENGLES_EXTENSION_PACK
를 인수로 전달합니다. 다음 코드 스니펫은 이렇게 하는 방법의 예를 보여줍니다.
Kotlin
var deviceSupportsAEP: Boolean = packageManager.hasSystemFeature(PackageManager.FEATURE_OPENGLES_EXTENSION_PACK)
Java
boolean deviceSupportsAEP = getPackageManager().hasSystemFeature (PackageManager.FEATURE_OPENGLES_EXTENSION_PACK);
메서드에서 true를 반환하면 AEP가 지원되는 것입니다.
AEP에 관한 자세한 내용은 Khronos OpenGL ES 레지스트리 페이지를 참고하세요.
OpenGL ES 버전 확인
Android 기기에서 사용 가능한 OpenGL ES 버전은 여러 가지가 있습니다. 애플리케이션에 필요한 최소 API 버전을 매니페스트에서 지정할 수 있지만 동시에 최신 API의 기능도 활용할 수 있습니다. 예를 들어 OpenGL ES 3.0 API는 API 2.0 버전과 하위 호환되므로 OpenGL ES 3.0 기능을 사용하지만 3.0 API를 사용할 수 없는 경우 2.0 API로 대체하도록 애플리케이션을 작성하는 것이 좋습니다.
애플리케이션 매니페스트에 필요한 최소 버전보다 높은 버전의 OpenGL ES 기능을 사용하려면 먼저 애플리케이션이 기기에서 사용할 수 있는 API 버전을 확인해야 합니다. 다음 두 가지 방법 중 하나로 이 작업을 실행할 수 있습니다.
- 상위 수준 OpenGL ES 컨텍스트 (
EGLContext
)를 만들고 결과를 확인합니다. - 최소 지원 OpenGL ES 컨텍스트를 만들고 버전 값을 확인합니다.
다음 코드 예는 EGLContext
를 만들고 결과를 확인하여 사용 가능한 OpenGL ES 버전을 확인하는 방법을 보여줍니다. 다음 예는 OpenGL ES 3.0 버전을 확인하는 방법을 보여줍니다.
Kotlin
private const val EGL_CONTEXT_CLIENT_VERSION = 0x3098 private const val glVersion = 3.0 private class ContextFactory : GLSurfaceView.EGLContextFactory { override fun createContext(egl: EGL10, display: EGLDisplay, eglConfig: EGLConfig): EGLContext { Log.w(TAG, "creating OpenGL ES $glVersion context") return egl.eglCreateContext( display, eglConfig, EGL10.EGL_NO_CONTEXT, intArrayOf(EGL_CONTEXT_CLIENT_VERSION, glVersion.toInt(), EGL10.EGL_NONE) ) // returns null if 3.0 is not supported } }
Java
private static double glVersion = 3.0; private static class ContextFactory implements GLSurfaceView.EGLContextFactory { private static int EGL_CONTEXT_CLIENT_VERSION = 0x3098; public EGLContext createContext( EGL10 egl, EGLDisplay display, EGLConfig eglConfig) { Log.w(TAG, "creating OpenGL ES " + glVersion + " context"); int[] attrib_list = {EGL_CONTEXT_CLIENT_VERSION, (int) glVersion, EGL10.EGL_NONE }; // attempt to create a OpenGL ES 3.0 context EGLContext context = egl.eglCreateContext( display, eglConfig, EGL10.EGL_NO_CONTEXT, attrib_list); return context; // returns null if 3.0 is not supported; } }
위에 표시된 createContext()
메서드가 null을 반환하면 코드에서 대신 OpenGL ES 2.0 컨텍스트를 만들고 이 API만 사용하도록 대체해야 합니다.
다음 코드 예는 지원되는 최소 컨텍스트를 먼저 만든 다음 버전 문자열을 확인하여 OpenGL ES 버전을 확인하는 방법을 보여줍니다.
Kotlin
// Create a minimum supported OpenGL ES context, then check: gl.glGetString(GL10.GL_VERSION).also { Log.w(TAG, "Version: $it") } // The version format is displayed as: "OpenGL ES <major>.<minor>" // followed by optional content provided by the implementation.
Java
// Create a minimum supported OpenGL ES context, then check: String version = gl.glGetString(GL10.GL_VERSION); Log.w(TAG, "Version: " + version ); // The version format is displayed as: "OpenGL ES <major>.<minor>" // followed by optional content provided by the implementation.
이 접근 방식을 사용할 경우 기기가 상위 수준의 API 버전을 지원한다는 사실을 발견하면 최소 OpenGL ES 컨텍스트를 삭제하고 사용 가능한 더 높은 API 버전으로 새 컨텍스트를 만들어야 합니다.
OpenGL API 버전 선택
OpenGL ES 버전 2.0 및 버전 3.0은 모두 3D 게임, 시각화, 사용자 인터페이스를 만들기 위한 고성능 그래픽 인터페이스를 제공합니다. OpenGL ES 2.0 및 3.0용 그래픽 프로그래밍은 대체로 유사하며 버전 3.0은 추가 기능이 있는 2.0 API의 상위 집합을 나타냅니다. OpenGL ES 1.0/1.1 API와 OpenGL ES 2.0 및 3.0의 프로그래밍은 크게 다르므로 새 애플리케이션에는 권장되지 않습니다. 개발자는 이러한 API를 사용하여 개발을 시작하기 전에 다음 요소를 신중하게 고려해야 합니다.
- 기기 호환성 - 개발자는 기기 유형, Android 버전, 고객이 사용할 수 있는 OpenGL ES 버전을 고려해야 합니다. 기기 간 OpenGL 호환성에 관한 자세한 내용은 OpenGL 버전 및 기기 호환성 섹션을 참조하세요.
- 텍스처 지원 - OpenGL ES 3.0 API는 투명도를 지원하는 ETC2 압축 형식의 가용성을 보장하기 때문에 텍스처 압축을 가장 잘 지원합니다. 2.0 API 구현에는 ETC1 지원이 포함되지만 이 텍스처 형식은 투명도를 지원하지 않습니다. 압축된 텍스처로 투명도를 구현하려면 ETC1 텍스처 두 개 (색상과 알파 간에 분할)를 사용하거나 타겟팅하는 기기에서 지원하는 다른 압축 형식으로 리소스를 제공해야 합니다. 자세한 내용은 텍스처 압축 지원을 참고하세요.
호환성과 텍스처 지원이 결정에 영향을 미칠 수 있지만 사용자에게 최상의 환경을 제공한다고 생각되는 OpenGL API 버전을 선택해야 합니다.