반응형

앱을 만들어 실제 빌드 후 자바로 빌드된 소스 코드를 디컴파일로 봤을 때 (코틀린도 JVM 기반이라 자바에 종속되어 있습니다.)  Canvas로 비트맵을 그릴 때마다 Null 검사를 하고 있었습니다. 만일 화면에 타일을 20개 정도 그린다면 그때마다 20번의 If.. Null 검사를 합니다. 게다가 JVM 자체가 인터 프린터 방식입니다.(요즘은 실행속도가 많이 상승했다고 합니다), Canvas가 기본적으로 클리핑(비트맵이 화면 밖으로 나갔을 때 잘린 부분 처리)도 해주는 걸 봐도 내부적으로 속도 저하를 유발하는  많은  코드들이 존재한다는 게 대충 느껴집니다.

 

어느 정도 타협이 된다면 Canvas를 사용하면 됩니다.(편하니까...^^; 하드웨어 가속 옵션을 사용하면 쓸만한 것 같아요) 많은 비트맵을 빠르게 그려야 하는 게임 등을 제작할 때 그리는 속도가 생각보다 많이 떨어진다면 게임 툴을 쓰시거나   OpenGl를 배울 필요성이 느껴집니다.

 

OpenGl 자바 예제는 많지만 기초  코틀린 예제는 찾기가 힘듭니다. 난해한 코드가 많아서 안드로이드 스튜디오에서 자바 코드가 코틀린으로 변화가 안 되는 부분도 많았습니다.

 

요즘은 챗GPT를 참조하는 걸 추천합니다. 실제 질답 해보면 코드가  복잡해 질수록 실행 안 되는 코드들을 많이 뿜어 댑니다, 그래도 간단한 코드 들은 즉답을 해줘서상당히 쓸만합니다

https://chat.openai.com/

 

 

공식 홈페이지에서 코틀린 Opengl ES  기초 설명이 가장 잘 되어 있는 것 같습니다.

OpenGl ES 설명 및 예제 (코틀린/자바)

developer.android.com/training/graphics/opengl/index.html


OPENGL context surface 설정에 대한 도움 되는 글들...

 

OpenGL이 비트맵등을 읽거나 그리거나 로드 저장등을 할 때 전부 render를 거쳐야 합니다. 외부에선 함수에서는 처리가 안됨. 그래서 context를 공유해야 할 필요가 생기는데 그에 도움이 되는 글들을 모아봤습니다.

 

OPEN GL ES 2.0 (1.4) Gl context 코틀린 코드 예

https://stackoverflow.com/questions/65562689/how-to-render-bitmap-off-screen-in-android-using-opengl

 

예제가 좋은  페이지 중 하나(자바,중국어)

https://github.com/WangYantao/android-opengles-demos/blob/master/android-opengles3.0%E5%BC%80%E5%8F%91%E3%80%904%E3%80%91%E4%BD%BF%E7%94%A8EGL%E7%BB%98%E5%88%B6%E5%9B%BE%E5%BD%A2.md

 

이 페이지도 예제가 좋은 것 같습니다.(자바)

https://stackoverflow.com/questions/66929292/how-to-use-imagereader-to-read-opengl-surface

 

https://stackoverflow.com/questions/36312209/opengls-eglcreatewindowsurface-gl-error-egl-bad-alloc


openGL context를 만들어 공유하지 않는다면 surfaceview에서 

ex:       class MyGLSurfaceView(context: Context) : GLSurfaceView(context){

 

class 내부에 게임 메인 루프를 만들고, 텍스처 읽기 변경 작업등이 필요할 때마다 requestRender()로 랜더를 호출해서, 텍스처를 만든다거나 픽셀 작업을 하거나,  화면 그림 등의 입출력을 모두 한개의 랜더 함수에서  처리하는 방법을 사용해야 합니다. 그와 동시에 어떤 작업을 했든 간에  랜더 후 반드시 화면 출력도 같이 완료해야 합니다. 그냥 return 하면 화면 버퍼링 오류 생김

여기에서 그래픽에 관련된 모든 함수를 처리...ㅠㅠ

지금 저는 앱을 만들때 텍스처 매핑을 하거나, 그래픽 정보 관련 입출력 모든 것을 한개의 랜더 함수에서 처리하고 있습니다 .


아래 소스는 제가 연구하다 만든 코틀린 open gl context 구현 소슨데...
open gl surface에서 texture 캡처하는 걸 구현했는데
texture가 어쩔된 캡처 됐다 어쩔 땐 안됐다 완벽하지 않습니다. 

opengl context 구현 참고만하세요

import android.opengl.EGL14
import android.opengl.EGLContext
import android.opengl.EGLDisplay
import android.opengl.EGLSurface
import android.util.Log

  val omglctx=Mglctx()
  class Mglctx(){
   
   private lateinit var cOrgDisplay: EGLDisplay
   private lateinit var vsurface: EGLSurface
   private lateinit var veglContext: EGLContext
   
   private lateinit var cOrgSurface: EGLSurface
   private lateinit var cOrgContext: EGLContext
   
   //외부 호출
   //override fun onSurfaceCreated(gl: GL10, config: EGLConfig)
   //에서 초기에
   
   fun initCtx(){
    
    cOrgContext = EGL14.eglGetCurrentContext()
    cOrgSurface = EGL14.eglGetCurrentSurface(EGL14.EGL_READ) //EGL14.EGL_DRAW , EGL_READ
    cOrgDisplay=EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY)
    
    //------------------------------------------------------------------------
    
    val versions = IntArray(2)
    EGL14.eglInitialize(cOrgDisplay, versions, 0, versions, 1)
    
    val configAttr = intArrayOf(EGL14.EGL_BUFFER_SIZE, 32,EGL14.EGL_ALPHA_SIZE,
     8,EGL14.EGL_BLUE_SIZE, 8, EGL14.EGL_GREEN_SIZE, 8, EGL14.EGL_RED_SIZE, 8,
     EGL14.EGL_RENDERABLE_TYPE,EGL14.EGL_OPENGL_ES2_BIT,EGL14.EGL_SURFACE_TYPE,
     EGL14.EGL_PBUFFER_BIT, //캡처작업,  일반작업은 EGL_WINDOW_BIT
     EGL14.EGL_NONE)
    
    val numConfig = IntArray(1)
    val configs: Array<android.opengl.EGLConfig?> = arrayOfNulls(1)
    EGL14.eglChooseConfig(cOrgDisplay, configAttr, 0, configs, 0, 1, numConfig, 0)
    
    //--------------------------------------------------------------------------------------
    val config2: android.opengl.EGLConfig? = configs[0]
    
    val contextAttrib = intArrayOf(EGL14.EGL_CONTEXT_CLIENT_VERSION, 2, EGL14.EGL_NONE)
    veglContext = EGL14.eglCreateContext(cOrgDisplay, config2, EGL14.EGL_NO_CONTEXT, contextAttrib, 0)
    
    //--------------------------------------------------------------------------------------
    val surfAttr = intArrayOf(EGL14.EGL_WIDTH, famscrx, EGL14.EGL_HEIGHT, famscry, EGL14.EGL_NONE)
    vsurface = EGL14.eglCreatePbufferSurface(cOrgDisplay, config2, surfAttr, 0)
    
   }
   fun free(){ //앱 종료시
    // surface와의 연결을 끊어 버린다
    EGL14.eglMakeCurrent(cOrgDisplay,EGL14.EGL_NO_SURFACE,EGL14.EGL_NO_SURFACE,EGL14.EGL_NO_CONTEXT)
    EGL14.eglDestroySurface(cOrgDisplay, vsurface)
    EGL14.eglDestroyContext(cOrgDisplay, veglContext)
    EGL14.eglTerminate(cOrgDisplay)
   }
   
   fun getTouch(){
    EGL14.eglMakeCurrent(cOrgDisplay, cOrgSurface, cOrgSurface, cOrgContext)
    
    //opengl 캡처 작업.
    
    EGL14.eglMakeCurrent(cOrgDisplay,EGL14.EGL_NO_SURFACE,EGL14.EGL_NO_SURFACE,EGL14.EGL_NO_CONTEXT)
   }
   
  }
//------------------------------------------------------------------------
 
반응형

+ Recent posts