如何将 EGLSurface 传递给 Kotlin 中的 Surface(更好)或 Java?
How to pass a EGLSurface to a Surface in Kotlin (better) or Java?
我有一个像这样来自 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,但是 TextureView 在 ViewRenderable 中不受 Sceneform 的支持。
我的想法是将流通过管道传输到提供给 ModelRenderable 的 ExternalTexture,这与在增强图像上播放来自 MediaPlayer 的视频相同。
所以我尝试将 ExternalTexture 的 SurfaceTexture(甚至是非常“绝望”的 Surface)传递给 EGLSurface 构造函数。
在这两种情况下,作为最佳结果,我获得了整个屏幕的颜色渲染,而不是渲染到我的 modelRenderable 的表面,像这样构建
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 class
可用的 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
我找到了一个非常简单的解决方案:
在 OnCreate 方法中创建一个 TextureView
override fun onCreate(savedInstanceState: Bundle?) {
...
mTextureView = TextureView(this.context)
...
}
link OnViewCreated方法中的View的TextureView
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
...
val mViewGroup = view.parent as ViewGroup
mViewGroup.addView(mTextureView)
...
创建
externalTexture = ExternalTexture()
TextureView完全初始化后
采用与egl一起工作的渲染器并传递
externalTexture.surface
作为
中的参数
eglSurface = egl.eglCreateWindowSurface(eglDisplay, eglConfig, injectedSurface, null)
//injectedSurface is the externalTexture.surface
我有一个像这样来自 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,但是 TextureView 在 ViewRenderable 中不受 Sceneform 的支持。
我的想法是将流通过管道传输到提供给 ModelRenderable 的 ExternalTexture,这与在增强图像上播放来自 MediaPlayer 的视频相同。
所以我尝试将 ExternalTexture 的 SurfaceTexture(甚至是非常“绝望”的 Surface)传递给 EGLSurface 构造函数。
在这两种情况下,作为最佳结果,我获得了整个屏幕的颜色渲染,而不是渲染到我的 modelRenderable 的表面,像这样构建
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 class
可用的 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
我找到了一个非常简单的解决方案:
在 OnCreate 方法中创建一个 TextureView
override fun onCreate(savedInstanceState: Bundle?) { ... mTextureView = TextureView(this.context) ... }
link OnViewCreated方法中的View的TextureView
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { ... val mViewGroup = view.parent as ViewGroup mViewGroup.addView(mTextureView) ...
创建
externalTexture = ExternalTexture()
TextureView完全初始化后
采用与egl一起工作的渲染器并传递
externalTexture.surface
作为
中的参数eglSurface = egl.eglCreateWindowSurface(eglDisplay, eglConfig, injectedSurface, null) //injectedSurface is the externalTexture.surface