【问题标题】:How to pass a EGLSurface to a Surface in Kotlin (better) or Java?如何将 EGLSurface 传递给 Kotlin(更好)或 Java 中的 Surface?
【发布时间】:2020-07-27 15:32:03
【问题描述】:

我有一个像这样来自 RendererThread 的流(它只是作为测试)

class RendererThread(val surface: SurfaceTexture, mSurface: Surface?) : Thread() {

    var isStopped = false
    var color = 0f
    private lateinit var eglSurface:EGLSurface

    val config = intArrayOf(
        EGL10.EGL_RENDERABLE_TYPE, EGL14.EGL_OPENGL_ES2_BIT,
        EGL10.EGL_RED_SIZE, 8,
        EGL10.EGL_GREEN_SIZE, 8,
        EGL10.EGL_BLUE_SIZE, 8,
        EGL10.EGL_ALPHA_SIZE, 8,
        EGL10.EGL_DEPTH_SIZE, 0,
        EGL10.EGL_STENCIL_SIZE, 0,
        EGL10.EGL_NONE
    )
    var surfacePlane = mSurface
    var surfaceTexImported:SurfaceTexture? = null

    fun getSurfaceTexture(surfaceTexture: SurfaceTexture){
        this.surfaceTexImported = surfaceTexture
    }

    fun getSurface(surface: Surface){
        this.surfacePlane = surface
    }

    fun  chooseEglConfig(egl: EGL10, eglDisplay: EGLDisplay) : EGLConfig {
        val configsCount = intArrayOf(0);
        val configs = arrayOfNulls<EGLConfig>(1);
        egl.eglChooseConfig(eglDisplay, config, configs, 1, configsCount)
        return configs[0]!!
    }

    override fun run() {
        super.run()

        val egl = EGLContext.getEGL() as EGL10
        var eglDisplay = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY)
        egl.eglInitialize(eglDisplay, intArrayOf(0, 0))   // getting OpenGL ES 2
        val eglConfig = chooseEglConfig(egl, eglDisplay);
        val eglContext = egl.eglCreateContext(eglDisplay, eglConfig,
            EGL10.EGL_NO_CONTEXT, intArrayOf(
                EGL14.EGL_CONTEXT_CLIENT_VERSION, 2,
                EGL10.EGL_NONE
            ));
        if(this.surfacePlane == null){
            eglSurface = egl.eglCreateWindowSurface(eglDisplay, eglConfig, surface, null)
        } else {
            eglSurface = egl.eglCreateWindowSurface(eglDisplay, eglConfig, surfacePlane, null)
        }

        var colorVelocity = 0.31f

        print(egl.eglGetError())
        while (!isStopped && egl.eglGetError() == EGL10.EGL_SUCCESS) {
           
            egl.eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext)
            colorVelocity *= if (color > 1 && color < 1.6 || color < 0) {
                +1
            } else {
                -1
            }
            color += colorVelocity

            GLES20.glClearColor(color / 2, color, color, 0.5f)
            GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT)
            egl.eglSwapBuffers(eglDisplay, eglSurface)

            Thread.sleep((1f / 60f * 1000f).toLong()) // in real life this sleep is more complicated
        }

        surface.release()
        egl.eglDestroyContext(eglDisplay, eglContext)
        egl.eglDestroySurface(eglDisplay, eglSurface)
    }
}

它应该在绿色上产生类似频闪的效果,即使它被卡在黑色上,但没关系,因为我可以看到它正在工作。 可以很方便的渲染成TextureView,但是ViewRenderable中的Sceneform不支持​​TextureView。

我的想法是将流通过管道传输到提供给 ModelRenderable 的 ExternalTexture 中,这与在增强图像上播放来自 MediaPlayer 的视频相同。

所以我尝试将 ExternalTexture 的 SurfaceTexture(甚至是“绝望”的 Surface)传递给 EGLSurface 构造函数。

在这两种情况下,作为最佳结果,我都获得了渲染的整个屏幕颜色,而不是渲染到我的 modelRenderable 的 Surface 中,像这样构建

ModelRenderable.builder()
        
        .build()
        .thenAccept { liquidRenderable ->
            liquidViewRenderable = liquidRenderable
            liquidRenderable.isShadowCaster = false
            liquidRenderable.isShadowReceiver = false
            liquidRenderable.material.setExternalTexture("videoPlane", externalTexture)
        }
        .exceptionally { throwable ->
            Log.e(TAG, "Could not create renderable", throwable)
            return@exceptionally null
        }

注意: 我更改了以前的代码部分。 我在 TextureView 类可用的 onSurfaceTextureAvailable 方法中初始化渲染器

    override fun onSurfaceTextureAvailable(surface: SurfaceTexture, width: Int, height: Int) {
       renderer = RendererThread(surface)
    } // here the "surface" passed is actually the SurfaceTexture and        not the Surface

【问题讨论】:

    标签: opengl-es arcore sceneform egl


    【解决方案1】:

    我找到了一个非常简单的解决方案:

    1. 在 OnCreate 方法中创建一个 TextureView

      override fun onCreate(savedInstanceState: Bundle?) {
      
          ...
          mTextureView = TextureView(this.context)
          ...
      }
      
    2. 在 OnViewCreated 方法中将 TextureView 链接到 View

      override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
          ...
          val mViewGroup = view.parent as ViewGroup
          mViewGroup.addView(mTextureView)
          ...
      
    3. 创建

      externalTexture = ExternalTexture()
      

      TextureView 完全初始化后

    4. 获取与 egl 一起使用的渲染器并传递

      externalTexture.surface
      

      作为参数

      eglSurface = egl.eglCreateWindowSurface(eglDisplay, eglConfig, injectedSurface, null) 
      //injectedSurface is the externalTexture.surface
      

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-07
      • 1970-01-01
      • 2018-08-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多