서피스 뷰에서 터치 이벤트 리스너를 등록하고 JNI로 이벤트를 내려주자.
TouchEventStart : 첫 터치 이벤트
TouchEventMove : 드래그 이벤트
TouchEventRelease : 마지막 터치 이벤트
GLESView.java
class GLESView extends GLSurfaceView {
....
public boolean onTouchEvent( final MotionEvent event )
{
//Log.w(TAG, "OnTouchEvent");
switch( event.getAction() )
{
case MotionEvent.ACTION_DOWN:
{
GLESNativeLib.TouchEventStart( event.getX(0), event.getY(0));
break;
}
case MotionEvent.ACTION_MOVE:
{
GLESNativeLib.TouchEventMove( event.getX(0), event.getY(0) );
break;
}
case MotionEvent.ACTION_UP:
{
GLESNativeLib.TouchEventRelease( event.getX(0), event.getY(0) );
break;
}
}
return true;
}
}
GLESNativeLib.java
package cookbook.gles;
public class GLESNativeLib {
static {
System.loadLibrary("glNative");
}
/**
* @param width the current opengl view window width
* @param height the current opengl view window view height
*/
public static native void init( String apkFilePath );
public static native void resize(int width, int height );
public static native void step();
public static native void TouchEventStart( float x, float y );
public static native void TouchEventMove( float x, float y );
public static native void TouchEventRelease( float x, float y );
}
NativeTemplate.cpp
#include "NativeTemplate.h"
#include "../Scene/renderer.h"
bool GraphicsInit()
{
Renderer::Instance().initializeRenderer();
return true;
}
bool GraphicsResize( int width, int height )
{
Renderer::Instance().resize(width, height);
return true;
}
bool GraphicsRender()
{
Renderer::Instance().setUpProjection();
Renderer::Instance().render();
return true;
}
void TouchEventDown( float x, float y )
{
Renderer::Instance().TouchEventDown( x, y );
}
void TouchEventMove( float x, float y )
{
Renderer::Instance().TouchEventMove( x, y );
}
void TouchEventRelease( float x, float y )
{
Renderer::Instance().TouchEventRelease( x, y );
}
#ifdef __ANDROID__
JNIEXPORT void JNICALL Java_cookbook_gles_GLESNativeLib_init( JNIEnv *env, jobject obj, jstring FilePath )
{
setenv( "FILESYSTEM", env->GetStringUTFChars( FilePath, NULL ), 1 );
GraphicsInit();
}
JNIEXPORT void JNICALL Java_cookbook_gles_GLESNativeLib_resize( JNIEnv *env, jobject obj, jint width, jint height)
{
GraphicsResize( width, height );
}
JNIEXPORT void JNICALL Java_cookbook_gles_GLESNativeLib_step(JNIEnv * env, jobject obj)
{
GraphicsRender();
//renderFrame();
}
JNIEXPORT void JNICALL Java_cookbook_gles_GLESNativeLib_TouchEventStart(JNIEnv * env, jobject obj, float x, float y )
{
TouchEventDown(x ,y);
}
JNIEXPORT void JNICALL Java_cookbook_gles_GLESNativeLib_TouchEventMove(JNIEnv * env, jobject obj, float x, float y )
{
TouchEventMove(x ,y);
}
JNIEXPORT void JNICALL Java_cookbook_gles_GLESNativeLib_TouchEventRelease(JNIEnv * env, jobject obj, float x, float y )
{
TouchEventRelease(x ,y);
}
#endif
여기까지가 앱에서 터치이벤트를 받아서 JNI를 통하여 네이티브로 전달을 했다.
앱이 실행되면 GraphicsInit() 가 실행되고
프레임마다 GraphicsRender() 실행되고,
마우스를 누를때마다 Touch Api () 실행 된다.
GraphicsInit() 과정에서
Triangle 객체를 생성 후 InitModel() 실행해 준다.
렌더 과정에는 Render() 실행해 준다.
InitModel() 에서는 앱이 실행하고 최초 1번 실행하니
셰이더 객체 생성, 셰이더 객체에 셰이더 코드 전달, 컴파일, Attach, 링킹 과 같은 작업을 진행한다.
Render() 에서는 프레임마다 실행되니
어트리뷰트 index 가져오고, 버퍼 데이터를 어트리뷰트에 연결, 셰이더 어트리뷰트 활성화 같은 작업을 진행 후
draw 한다.
터치 이벤트 down, move, release 발생할때마다 color 값을 바꾸어준다.
down 하면 빨강, move 하면 초록, release 하면 파랑으로 설정된다.
Triangle.cpp
Triangle::Triangle( Renderer* parent )
{
if (!parent)
return;
MapRenderHandler = parent;
ProgramManagerObj = parent->RendererProgramManager();
TransformObj = parent->RendererTransform();
modelType = TriangleType;
colors[0] = 0.0; colors[1] = 1.0; colors[2] = 0.0;
colors[3] = 1.0; colors[4] = 0.0; colors[5] = 0.0;
colors[6] = 0.0; colors[7] = 0.0; colors[8] = 1.0;
}
void Triangle::InitModel()
{
if (!(program = ProgramManagerObj->Program( ( char * )"Triangle" ))) {
program = ProgramManagerObj->ProgramInit( ( char * )"Triangle" );
ProgramManagerObj->AddProgram( program );
}
program->VertexShader = ShaderManager::ShaderInit( VERTEX_SHADER_PRG, GL_VERTEX_SHADER );
program->FragmentShader = ShaderManager::ShaderInit( FRAGMENT_SHADER_PRG, GL_FRAGMENT_SHADER );
//////////////////////////////////////////////////////
/////////// Vertex shader //////////////////////////
//////////////////////////////////////////////////////
CACHE *m = reserveCache( VERTEX_SHADER_PRG, true );
if( m ) {
if( !ShaderManager::ShaderCompile( program->VertexShader, ( char * )m->buffer, 1 ) ) exit( 1 );
freeCache( m );
}
m = reserveCache( FRAGMENT_SHADER_PRG, true );
if( m ) {
if( !ShaderManager::ShaderCompile( program->FragmentShader, ( char * )m->buffer, 1 ) ) exit( 2 );
freeCache( m );
}
if( !ProgramManagerObj->ProgramLink( program, 1 ) ) exit( 3 );
glUseProgram( program->ProgramID );
return;
}
void Triangle::Render()
{
glUseProgram( program->ProgramID );
const GLfloat gTriangleVertices[] = { 0.0f, 0.5f, -0.5f, -0.5f, 0.5f, -0.5f };
char attrib = ProgramManagerObj->ProgramGetVertexAttribLocation(program, (char*)"VertexPosition");
glVertexAttribPointer(attrib, 2, GL_FLOAT, GL_FALSE, 0, gTriangleVertices);
glEnableVertexAttribArray(attrib);
char attribColor = ProgramManagerObj->ProgramGetVertexAttribLocation(program, (char*)"VertexColor");
glVertexAttribPointer(attribColor, 3, GL_FLOAT, GL_FALSE, 0, colors);
glEnableVertexAttribArray(attribColor);
glDrawArrays(GL_TRIANGLES, 0, 3);
}
void Triangle::TouchEventDown( float x, float y )
{
colors[0] = 1.0; colors[1] = 0.0; colors[2] = 0.0;
colors[3] = 1.0; colors[4] = 0.0; colors[5] = 0.0;
colors[6] = 1.0; colors[7] = 0.0; colors[8] = 0.0;
}
void Triangle::TouchEventMove( float x, float y )
{
colors[0] = 0.0; colors[1] = 1.0; colors[2] = 0.0;
colors[3] = 0.0; colors[4] = 1.0; colors[5] = 0.0;
colors[6] = 0.0; colors[7] = 1.0; colors[8] = 0.0;
}
void Triangle::TouchEventRelease( float x, float y )
{
colors[0] = 0.0; colors[1] = 0.0; colors[2] = 1.0;
colors[3] = 0.0; colors[4] = 0.0; colors[5] = 1.0;
colors[6] = 0.0; colors[7] = 0.0; colors[8] = 1.0;
}
자주 실수하는 에러
1)
Android.mk에 Shared Library 를 빌드하도록 설정했으면
Application.mk 에서도 APP_STL := c++_shared로 설정하자.
include $(BUILD_SHARED_LIBRARY)
2)
glAttachShader에서 에러가 나면 셰이더 컴파일이 제대로 동작하는지 확인하자.
보통은 셰이더 경로를 잘못써서 발생.
셰이더 폴더는 assets 폴더 내부에 보통 넣는다.
device/generic/goldfish-opengl/system/GLESv2_enc/GL2Encoder.cpp:s_glAttachShader:2155 GL error 0x501 condition [!shaderIsShaderOrProgram]
3) JNI cpp 코드에서 타입이 있는데, 리턴을 안하면 해당 함수에서 이유 없이 죽는다.
조심
00 pc 000000000000d061 /data/app/~~TeEzxj5I-
coAEqvSmqG0hA==/cookbook.opengles-0l8YZGEJFO1U5XJCcZLYjQ==/base.apk!libglNative.so (offset 0x6ba000) (GraphicsInit()+17)
'Opengles 3.0 with Android' 카테고리의 다른 글
Chapter 2.2 (Vertex Array object) 사용한 Cube 렌더링 (1) | 2024.10.22 |
---|---|
Chapter 2.1 VBO(Vertex Buffer Object) 사용하여 정사각형 렌더링. 해본다. (0) | 2024.10.17 |
Chapter 1.2 Vertex Buffer 사용해보기 (0) | 2024.10.12 |
Chapter 1.1 Shader Build (0) | 2024.10.12 |
Chapter 1.0 EGL Context 생성하여 GLSurfaceView 에 적용하기 (0) | 2024.10.10 |