zoukankan      html  css  js  c++  java
  • 安卓下多线程OpenGL共享Context (三)

          在上一节中我们介绍了多线程OpenGL绘制方案,但是如果需要在Java线程不断修改纹理数据,会由于并发访问导致Unity线程出现访问非法内存而崩溃。因此,考虑在Java线程加载数据,然后在unity线程调用OpenGL操作更新纹理。这样所有的OpenGL操作都在Unity绘制线程完成,从而避免了多线程OpenGL引入的各种问题。为了能够从Java线程切换到Unity线程执行,我们获取到Unity线程的Looper,然后使用该Looper实例化一个Handler,这样就可以通过往上发送消息或者Runnable在Unity线程执行任务了。Java代码如下:

     1 package com.thornbirds.unity;
     2 
     3 import android.graphics.Bitmap;
     4 import android.graphics.BitmapFactory;
     5 import android.opengl.GLES10;
     6 import android.opengl.GLES11Ext;
     7 import android.opengl.GLES20;
     8 import android.opengl.GLUtils;
     9 import android.os.Handler;
    10 import android.os.Looper;
    11 import android.util.Log;
    12 
    13 import java.util.concurrent.ExecutorService;
    14 import java.util.concurrent.Executors;
    15 
    16 public class PluginTexture {
    17     private static final String TAG = "PluginTexture";
    18 
    19     private int mTextureID = 0;
    20     private int mTextureWidth = 0;
    21     private int mTextureHeight = 0;
    22 
    23     // 创建单线程池,用于加载图片资源
    24     private final ExecutorService mJavaThread = Executors.newSingleThreadExecutor();
    25     // 使用Unity线程Looper的Handler,用于执行Java层的OpenGL操作
    26     private Handler mUnityRenderHandler;
    27 
    28     public int getStreamTextureWidth() {
    29         return mTextureWidth;
    30     }
    31 
    32     public int getStreamTextureHeight() {
    33         return mTextureHeight;
    34     }
    35 
    36     public int getStreamTextureID() {
    37         return mTextureID;
    38     }
    39 
    40     public PluginTexture() {
    41     }
    42 
    43     private void glLogE(String msg) {
    44         Log.e(TAG, msg + ", err=" + GLES10.glGetError());
    45     }
    46 
    47     public void setupOpenGL() {
    48         // 注意:该调用一定是从Unity绘制线程发起
    49         if (Looper.myLooper() == null) {
    50             Looper.prepare();
    51         }
    52         mUnityRenderHandler = new Handler(Looper.myLooper());
    53         // 生成OpenGL纹理ID
    54         int textures[] = new int[1];
    55         GLES20.glGenTextures(1, textures, 0);
    56         if (textures[0] == 0) {
    57             glLogE("glGenTextures failed");
    58             return;
    59         }
    60         mTextureID = textures[0];
    61         mTextureWidth = 640;
    62         mTextureHeight = 360;
    63     }
    64 
    65     public void updateTexture() {
    66         mJavaThread.execute(new Runnable() {
    67             @Override
    68             public void run() {
    69                 // 加载图片资源
    70                 String imageFilePath = "/sdcard/test/image.png";
    71                 final Bitmap bitmap = BitmapFactory.decodeFile(imageFilePath);
    72                 // 切换到Unity绘制线程更新纹理
    73                 mUnityRenderHandler.post(new Runnable() {
    74                     @Override
    75                     public void run() {
    76                         GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureID);
    77                         GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
    78                         GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
    79                         GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
    80                         GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
    81                         bitmap.recycle();
    82                     }
    83                 });
    84             }
    85         });
    86     }
    87 
    88     public void destroy() {
    89         mJavaThread.shutdownNow();
    90         mUnityRenderHandler.removeCallbacksAndMessages(null);
    91     }
    92 }

         至此,我们完整介绍了Unity3D开发中在Android Java Plugin中进行纹理更新的方案和实现方法。基于相同的原理,我们可以很方便地给出iOS Object-C Plugin的实现,此处不在赘述。

  • 相关阅读:
    Chino 操作系统开发日志 (1)
    将Asp.Net Core和corefx移植到.Net 4.0
    C++编写操作系统(1):基于 EFI 的 Bootloader
    第二次作业:支付宝手机软件分析
    第一次作业:以人为鉴 可以明得失
    个人附加作业
    个人作业3---个人总结
    结对编程2---单元测试
    个人作业2---必应词典案例分析
    结对编程作业1
  • 原文地址:https://www.cnblogs.com/moderate-fish/p/6902817.html
Copyright © 2011-2022 走看看