먼저, 해당 프로젝트는 2D를 기준으로 진행합니다.
또한, 잘못알고있는 부분이나 틀린점이 있을 수 있습니다.
잘못된 부분에대해서는 코멘트해주시면 감사하겠습니다 ^^ 

Android NDK를 이용하여 OpenGL을 사용하기전에 ndk환경을 마련해야합니다.
ndk개발환경 구축방법은 따로 설명드리지 않겠습니다.

그럼, 프로젝트 생성부터 시작하겠습니다.
1. Android Project 생성


쭈욱 입력해줍니다.
프로젝트 버전은 2.1이상으로 작성하였습니다.






























2. GLView.java 생성
package pe.berabue.opengl;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.content.Context;
import android.opengl.GLSurfaceView;
import android.opengl.GLSurfaceView.Renderer;

public class GLView extends GLSurfaceView implements Renderer {

	public GLView(Context context) {
		super(context);
		// GLSurfaceView extends시 생성하여야함
	}

	@Override
	public void onDrawFrame(GL10 gl) {
		// Renderer implements시 생성하여야함
	}

	@Override
	public void onSurfaceChanged(GL10 gl, int width, int height) {
		// Renderer implements시 생성하여야함		
	}

	@Override
	public void onSurfaceCreated(GL10 gl, EGLConfig config) {
		// Renderer implements시 생성하여야함		
	}

}
새로 만들어준 GLView class에 GLSurfaceView를 extends하고 Renderer를 implements해줍니다.
위와같이 하나의 생성자와 3개의 함수를 구현해주어야합니다.

public void onDrawFrame(GL10 gl) {}
public void onSurfaceChanged(GL10 gl, int w, int h) {}
public void onSurfaceCreated(GL10 gl, EGLConfig config) {}
 onSurfaceChanged()와 onSurfaceCreated()는 일반 SurfaceView와 같습니다.
 onDrawFrame() 이함수를 호출하여 실질적으로 그림을 그리게됩니다. 


3. GLView 생성자 부분을 작성합니다.
public GLView(Context context) {
		super(context);
		this.setRenderer(this);
		this.requestFocus();
		this.setRenderMode(RENDERMODE_WHEN_DIRTY);
		this.setFocusableInTouchMode(true);
	}
setRenderer(this);
 렌더러를 세팅합니다. ( 뭐라고 설명해야될지 모르겠습니다. )
setRenderMode(RENDERMODE_WHEN_DIRTY);
 렌더러모드를 ( 1회 그리기 )모드로 세팅합니다. onDrawFrame이 1회 불림  


4. C로 작성된 함수를 호출할 native함수를 작성하고 적절한 위치에서 함수를 호출합니다.
package pe.berabue.opengl;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.content.Context;
import android.opengl.GLSurfaceView;
import android.opengl.GLSurfaceView.Renderer;
import android.view.MotionEvent;

public class GLView extends GLSurfaceView implements Renderer {

	private static native void nativeCreated(); 
    private static native void nativeChanged(int w, int h);
    private static native void nativeUpdateGame();
	private static native void nativeOnTouchEvent(int x, int y, int touchFlag);
	
	public GLView(Context context) {
		super(context);
		this.setRenderer(this);
		this.requestFocus();
		this.setRenderMode(RENDERMODE_WHEN_DIRTY);
		this.setFocusableInTouchMode(true);
	}

	public void onDrawFrame(GL10 gl) {
		nativeUpdateGame();
	}

	public void onSurfaceChanged(GL10 gl, int w, int h) {
		nativeChanged(w, h); 
	}

	public void onSurfaceCreated(GL10 gl, EGLConfig config) {
		nativeCreated();
	} 
	
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		nativeOnTouchEvent((int)event.getX(), (int)event.getY(), event.getAction());
		return true;
	}
}
GLView에서 해주어야할 일이 끝났습니다!


5. GLView를 메인View에 연결해볼 차례입니다. MainActivity로 가서..
package pe.berabue.opengl;

import android.app.Activity;
import android.opengl.GLSurfaceView;
import android.os.Bundle;

public class MainActivity extends Activity {
	
	private GLSurfaceView mGLView;
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        mGLView = new GLView(getApplicationContext());
        setContentView(mGLView);
    }

    static {
    	System.loadLibrary("berabueLib");
    }
}
mGLView = new GLView(getApplicationContext());
setContentView(mGLView);

 GLSurfaceView를 만들고 메인View로 지정해줍니다. 
System.loadLibrary("berabueLib"); 
 jni폴더를 컴파일하였을때 나오는 berabueLib.so 라이브러리파일을 사용하겠다고 알려줍니다. 

여기까지가 자바에서 해야할 일입니다!


6. 이제 프로젝트 폴더에 jni 폴더를 생성해줍시다.

7. Android.mk 스크립트 파일을 작성합니다.
Android.mk
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := berabueLib
LOCAL_CFLAGS := -DANDROID_NDK
LOCAL_SRC_FILES := jni-ndk.c
LOCAL_LDLIBS := -lGLESv1_CM\
				-llog

include $(BUILD_SHARED_LIBRARY)

LOCAL_PATH := $(call my-dir)
 컴파일하고자 하는 소스파일 위치를 알려줍니다. Android.mk를 jni에 놔두었으니 프로젝트/jni폴더가 됩니다.
include $(CLEAR_VARS)
 
  LOCAL로 시작하는것들을 초기화시킨다고합니다. LOCAL_PATH는 제외.
LOCAL_MODULE := berabueLib
 
  생성될 so파일명입니다.
LOCAL_CFLAGS := -DANDROID_NDK
 
  컴파일 옵션설정. 자세히 모름.
LOCAL_SRC_FILES := jni-ndk.c
 
  컴파일할 소스파일을 추가합니다.  
LOCAL_LDLIBS := -lGLESv1_CM\ -llog
 해당 라이브러리를 사용합니다.
include $(BUILD_SHARED_LIBRARY)
 공유 라이브러리를 생성합니다.

  
8. Application.mk 파일을 작성합니다.
APP_PLATFORM	:= android-7
APP_PLATFORM := android-7
 프로젝트 버전을 입력해줍니다.


9. jni-ndk.c 작성
실질적으로 Java에서 작성한 native 함수가 있는곳입니다.
#include <jni.h>
#include <GLES/gl.h>
#include <GLES/glext.h>

void Java_pe_berabue_opengl_GLView_nativeCreated(JNIEnv*  env)
{	
	glClearColor(0.4f, 0.4f, 0.4f, 0.4f);
}

void Java_pe_berabue_opengl_GLView_nativeChanged(JNIEnv* env, jobject thiz, jint w, jint h)
{
}
   
void Java_pe_berabue_opengl_GLView_nativeUpdateGame(JNIEnv* env)
{
	glClear(GL_COLOR_BUFFER_BIT);
}

void Java_pe_berabue_opengl_GLView_nativeOnTouchEvent(JNIEnv* env, jobject thiz, jint x, jint y, jint touchFlag)
{
}
먼저 jni헤더와 OpenGL에 사용할 헤더파일을 include합니다.

jni을 사용하여 함수명을 작성하는방법은 아래와같습니다.
Java_패키지명_native함수원형을적은클래스명_함수명();

c -> java함수를 호출하거나 데이터를 보내는것은 다음에 설명해드리겠습니다.
우선 OpenGL 함수들을 봅시다.

nativeCreated() 함수를 먼저 보겠습니다.
glClearColor(0.4f, 0.4f, 0.4f, 0.4f);
 RGBA 색상으로 화면을 칠합니다. 0.0 ~ 1.0f
glClear(GL_COLOR_BUFFER_BIT);
 위에서 입력한 색상으로 화면을 초기화합니다. 

c소스를 빌드 후 어플을 실행시키면 아래와같이 회색화면의 화면을 가득채울 것입니다. 



이것으로 프로젝트 준비단계가 끝이났습니다.


간단한 프로젝트 설명.


src 폴더
현재 MainActivity와 GLView 두개의 클래스로만 되어있습니다.
추후 Thread와 JNI를 이용해 Java와 C가 통신을할 별도의 클래스를 두개정도를 더 추가할 예정입니다.

jni 폴더
Android.mk : native lib을 생성하기위한 정보를 담고있는 스크립트 파일
Application.mk : native 모듈 생성파일
jni-ndk.c : GLView클래서에서 c소스를 호출할때 사용할 c파일

libs, obj 폴더
jni폴더 빌드시 libs, obj폴더가 만들어지고 so파일이 생성됩니다.















+ Recent posts