日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android OpenGL ES 离屏渲染(offscreen render)

發(fā)布時間:2025/7/14 Android 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android OpenGL ES 离屏渲染(offscreen render) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

通常在Android上使用OpenGL ES,都是希望把渲染后的結果顯示在屏幕上,例如圖片處理、模型顯示等。這種情況下,只需要使用Android API中提供的GLSurfaceView類和Renderer類,在這兩個類提供的初始化、回調函數(shù)中設置/編寫相應的代碼即可。不過,如果不希望把渲染結果顯示在屏幕上,也就是所說的離屏渲染(offscreen render),這兩個類就幫不上忙了。在此介紹一下如何在Android系統(tǒng)上做OpenGL ES 的離屏渲染。

?

1.基礎知識

要想使用OpenGL ES,一般包括如下幾個步驟:

  (1)EGL初始化

  (2)OpenGL ES初始化

  (3)OpenGL ES設置選項&繪制

  (4)OpenGL ES資源釋放(可選)

  (5)EGL資源釋放

Android提供的GLSurfaceView和Renderer自動完成了(1)(5)兩個部分,這部分只需要開發(fā)者做一些簡單配置即可。另外(4)這一步是可選的,因為隨著EGL中上下文的銷毀,openGL ES用到的資源也跟著釋放了。因此只有(2)(3)是開發(fā)者必須做的。這大大簡化了開發(fā)過程,但是靈活性也有所降低,利用這兩個類是無法完成offscreen render的。要想完成offscreen render其實也很簡單,相信大家也都猜到了,只要我們把(1)~(5)都自己完成就可以了。后續(xù)部分的代碼大部分都是C/C++,少部分是Java。

?

2.EGL初始化

EGL的功能是將OpenGL ES API和設備當前的窗口系統(tǒng)粘合在一起,起到了溝通橋梁的作用。不同設備的窗口系統(tǒng)千變?nèi)f化,但是OpenGL ES提供的API卻是統(tǒng)一的,所以EGL需要協(xié)調當前設備的窗口系統(tǒng)和OpenGL ES。下面EGL初始化的代碼我是用C++寫的,然后通過jni調用。Android在Java層面上也提供了對應的Java接口函數(shù)。

static EGLConfig eglConf; static EGLSurface eglSurface; static EGLContext eglCtx; static EGLDisplay eglDisp;JNIEXPORT void JNICALL Java_com_handspeaker_offscreentest_MyGles_init (JNIEnv*env,jobject obj) {// EGL config attributesconst EGLint confAttr[] ={EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,// very important!EGL_SURFACE_TYPE,EGL_PBUFFER_BIT,//EGL_WINDOW_BIT EGL_PBUFFER_BIT we will create a pixelbuffer surfaceEGL_RED_SIZE, 8,EGL_GREEN_SIZE, 8,EGL_BLUE_SIZE, 8,EGL_ALPHA_SIZE, 8,// if you need the alpha channelEGL_DEPTH_SIZE, 8,// if you need the depth bufferEGL_STENCIL_SIZE,8,EGL_NONE};// EGL context attributesconst EGLint ctxAttr[] = {EGL_CONTEXT_CLIENT_VERSION, 2,// very important! EGL_NONE};// surface attributes// the surface size is set to the input frame sizeconst EGLint surfaceAttr[] = {EGL_WIDTH,512,EGL_HEIGHT,512,EGL_NONE};EGLint eglMajVers, eglMinVers;EGLint numConfigs;eglDisp = eglGetDisplay(EGL_DEFAULT_DISPLAY);if(eglDisp == EGL_NO_DISPLAY){//Unable to open connection to local windowing systemLOGI("Unable to open connection to local windowing system");}if(!eglInitialize(eglDisp, &eglMajVers, &eglMinVers)){// Unable to initialize EGL. Handle and recoverLOGI("Unable to initialize EGL");}LOGI("EGL init with version %d.%d", eglMajVers, eglMinVers);// choose the first config, i.e. best configif(!eglChooseConfig(eglDisp, confAttr, &eglConf, 1, &numConfigs)){LOGI("some config is wrong");}else{LOGI("all configs is OK");}// create a pixelbuffer surfaceeglSurface = eglCreatePbufferSurface(eglDisp, eglConf, surfaceAttr);if(eglSurface == EGL_NO_SURFACE){switch(eglGetError()){case EGL_BAD_ALLOC:// Not enough resources available. Handle and recoverLOGI("Not enough resources available");break;case EGL_BAD_CONFIG:// Verify that provided EGLConfig is validLOGI("provided EGLConfig is invalid");break;case EGL_BAD_PARAMETER:// Verify that the EGL_WIDTH and EGL_HEIGHT are// non-negative valuesLOGI("provided EGL_WIDTH and EGL_HEIGHT is invalid");break;case EGL_BAD_MATCH:// Check window and EGLConfig attributes to determine// compatibility and pbuffer-texture parametersLOGI("Check window and EGLConfig attributes");break;}}eglCtx = eglCreateContext(eglDisp, eglConf, EGL_NO_CONTEXT, ctxAttr);if(eglCtx == EGL_NO_CONTEXT){EGLint error = eglGetError();if(error == EGL_BAD_CONFIG){// Handle error and recoverLOGI("EGL_BAD_CONFIG");}}if(!eglMakeCurrent(eglDisp, eglSurface, eglSurface, eglCtx)){LOGI("MakeCurrent failed");}LOGI("initialize success!"); }

代碼比較長,不過大部分都是檢測當前函數(shù)調用是否出錯的,核心的函數(shù)只有6個,只要它們的調用沒有問題即可:

eglGetDisplay(EGL_DEFAULT_DISPLAY)

eglInitialize(eglDisp, &eglMajVers, &eglMinVers)

eglChooseConfig(eglDisp, confAttr, &eglConf, 1, &numConfigs)

eglCreatePbufferSurface(eglDisp, eglConf, surfaceAttr)

eglCreateContext(eglDisp, eglConf, EGL_NO_CONTEXT, ctxAttr)

eglMakeCurrent(eglDisp, eglSurface, eglSurface, eglCtx)

這些函數(shù)中參數(shù)的具體定義可以在這個網(wǎng)站找到: ?https://www.khronos.org/registry/egl/sdk/docs/man/

需要說明的是,eglChooseConfig(eglDisp, confAttr, &eglConf, 1, &numConfigs)中confAttr參數(shù)一定要有EGL_SURFACE_TYPE,EGL_PBUFFER_BIT這個配置,它決定了是渲染surface的類型,是屏幕還是內(nèi)存。另外,還有一些選項和OpenGL ES版本有關,具體選用1.x還是2.x,這個視個人情況而定,我使用的是2.x。

?

3.OpenGL ES部分

為了方便說明,我把OpenGL ES部分都寫在一起了,代碼如下:

JNIEXPORT void JNICALL Java_com_handspeaker_offscreentest_MyGles_draw (JNIEnv*env,jobject obj) {const char*vertex_shader=vertex_shader_fix;const char*fragment_shader=fragment_shader_simple;glPixelStorei(GL_UNPACK_ALIGNMENT,1);glClearColor(0.0,0.0,0.0,0.0);glEnable(GL_DEPTH_TEST);glDepthFunc(GL_LESS);glCullFace(GL_BACK);glViewport(0,0,512,512);GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);glShaderSource(vertexShader,1,&vertex_shader,NULL);glCompileShader(vertexShader);GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);glShaderSource(fragmentShader,1,&fragment_shader,NULL);glCompileShader(fragmentShader);GLuint program = glCreateProgram();glAttachShader(program, vertexShader);glAttachShader(program, fragmentShader);glLinkProgram(program);glUseProgram(program);GLuint aPositionLocation =glGetAttribLocation(program, "a_Position");glVertexAttribPointer(aPositionLocation,2,GL_FLOAT,GL_FALSE,0,tableVerticesWithTriangles);glEnableVertexAttribArray(aPositionLocation);//draw somethingglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);glDrawArrays(GL_TRIANGLES,0,6);eglSwapBuffers(eglDisp,eglSurface); }

需要說明的是,繪制完成后,需要調用eglSwapBuffers(eglDisp,eglSurface)函數(shù),因為在初始化EGL時默認設置的是雙緩沖模式,即一份緩沖用于繪制圖像,一份緩沖用于顯示圖像,每次顯示時需要交換兩份緩沖,把繪制好的圖像顯示出來。

上面openGL繪制需要的兩個shader在此不寫了,可供下載的demo里會有。

?

4.EGL資源釋放

最后還差一個函數(shù),用于EGL資源釋放,代碼如下:

JNIEXPORT void JNICALL Java_com_handspeaker_offscreentest_MyGles_release (JNIEnv*env,jobject obj) {eglMakeCurrent(eglDisp, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);eglDestroyContext(eglDisp, eglCtx);eglDestroySurface(eglDisp, eglSurface);eglTerminate(eglDisp);eglDisp = EGL_NO_DISPLAY;eglSurface = EGL_NO_SURFACE;eglCtx = EGL_NO_CONTEXT; }

?

5.總結

大功告成,其實吃透了openGL ES的原理后,整個過程還是很簡單的。為了測試是否真的做到了offscreen render,我們把framebuffer中的圖片保存成圖片,來檢測結果。代碼如下:

RGBABuffer = IntBuffer.allocate(512 * 512);MyGles.release();MyGles.init();MyGles.draw();RGBABuffer.position(0);GLES20.glReadPixels(0, 0, 512, 512,GLES20.GL_RGBA,GLES20.GL_UNSIGNED_BYTE,RGBABuffer);int[] modelData=RGBABuffer.array();int[] ArData=new int[modelData.length];int offset1, offset2;for (int i = 0; i < 512; i++) {offset1 = i * 512;offset2 = (512 - i - 1) * 512;for (int j = 0; j < 512; j++) {int texturePixel = modelData[offset1 + j];int blue = (texturePixel >> 16) & 0xff;int red = (texturePixel << 16) & 0x00ff0000;int pixel = (texturePixel & 0xff00ff00) | red | blue;ArData[offset2 + j] = pixel;}}Bitmap modelBitmap = Bitmap.createBitmap(ArData,512,512,Bitmap.Config.ARGB_8888);saveBitmap(modelBitmap);

要注意的是,因為openGL ES framebuffer和圖像通道的存儲順序不同,需要做一次ABGR到ARGB的轉換。

一般來說,offscreen render的用處主要是做GPU加速,如果你的算法是計算密集型的,可以通過一些方法將其轉化成位圖形式,作為紋理(texture)載入到GPU顯存中,再利用GPU的并行計算能力,對其進行處理,最后利用glReadPixels將計算結果讀取到內(nèi)存中。就說這么多吧,更多的用法還需要大家的發(fā)掘。

?

這里是demo下載鏈接

轉載于:https://www.cnblogs.com/hrlnw/p/4642272.html

總結

以上是生活随笔為你收集整理的Android OpenGL ES 离屏渲染(offscreen render)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 黑人玩弄人妻一区二区三区 | brazzers猛女系列 | 三级全黄做爰龚玥菲在线 | 9cao| 日本免费一区二区三区最新 | 国产a精品 | 天堂影视在线观看 | 久久久久久无码精品大片 | 国产精品三级在线 | 青娱网电信一区电信二区电信三区 | 91叼嘿视频| 欧美中文字幕在线观看 | 无码任你躁久久久久久久 | 国产亚洲一区二区三区四区 | 美女隐私无遮挡免费 | 顶弄h校园1v1| www.jizz国产 | 日韩精品免费一区二区三区竹菊 | 黄片毛片av | 在线免费观看污 | 一级成人免费 | 成人黄色免费网 | 久艹在线播放 | 成年人爱爱视频 | 先锋资源一区 | 免费看美女隐私网站 | 国产美女在线精品 | 久久亚洲精少妇毛片午夜无码 | 国产欧美一区二区视频 | 嫩草社区 | 国产精品色综合 | 91资源站 | 欧美日韩精品一区二区在线观看 | 免费中文视频 | 久久夜色精品亚洲 | 国产麻豆交换夫妇 | 欧美变态网站 | 国产suv精品一区二区 | 办公室荡乳欲伦交换bd电影 | 亚洲最新av在线 | 美女网站在线 | 久99热 | 9人人澡人人爽人人精品 | 日本污视频在线观看 | 日韩高清黄色 | 超碰在线中文 | 日韩理论视频 | 99精品视频在线观看 | 99久久婷婷国产综合精品青牛牛 | 玩偶姐姐在线观看免费 | 久草av在线播放 | 欧美日韩亚洲视频 | 国产婷婷色一区二区三区在线 | 欧美12--15处交性娇小 | 最新视频 - 88av| 不卡的一区二区 | 中文字幕久久网 | 黄色的毛片 | 美美女高清毛片视频免费观看 | 亚洲精品免费av | 精品人人人| 国产黄色片在线 | 一区黄色| 免费欧美一区 | 黑人导航 | 午夜av毛片 | 日韩v在线| 综合激情在线 | 97超碰伊人 | 色多多黄色 | 欧美伦理片网站 | 中文字幕欧美日韩 | 国产精品久久久久蜜臀 | 国产五月| 亚洲视频在线免费 | www日本高清视频 | 日夜夜操 | 四虎国产在线观看 | 欧洲熟妇的性久久久久久 | 成人精品视频99在线观看免费 | 深爱五月激情五月 | 日本福利视频导航 | 国产微拍一区 | 美女扒开让男人桶爽 | 人人人人干 | 秋霞影院午夜丰满少妇在线视频 | 污视频网站免费在线观看 | 亚洲福利电影 | 免费av大全 | 成人国产精品久久 | 岛国片免费在线观看 | 国产男女猛烈无遮挡免费观看网站 | 国产成人无码www免费视频播放 | 欧美成人高潮一二区在线看 | 国产精品拍拍 | 国产精选自拍 | 日本黄色视屏 | 欧美精品一 | 日韩黄色成人 |