Combinación Android de OpenGL de SurfaceTexture (imagen externa) y textura ordinaria

Me gustaría mezclar la vista previa de la cámara SurfaceTexture con una textura de superposición. Estoy utilizando estos shaders para procesamiento:

private final String vss = "attribute vec2 vPosition;\n" + "attribute vec2 vTexCoord;\n" + "varying vec2 texCoord;\n" + "void main() {\n" + " texCoord = vTexCoord;\n" + " gl_Position = vec4 ( vPosition.x, vPosition.y, 0.0, 1.0 );\n" + "}"; private final String fss = "#extension GL_OES_EGL_image_external : require\n" + "precision mediump float;\n" + "uniform samplerExternalOES sTexture;\n" + "uniform sampler2D filterTexture;\n" + "varying vec2 texCoord;\n" + "void main() {\n" +" vec4 t_camera = texture2D(sTexture,texCoord);\n" //+" vec4 t_overlayer = texture2D(filterTexture, texCoord);\n" //+ " gl_FragColor = t_overlayer;\n" + "}"; + " gl_FragColor = t_camera;\n" + "}"; 

Mi objetivo es mezclar t_camera y t_overlayer. Cuando muestro t_camera o t_overlayer por separado, funciona (muestra la vista previa de la cámara o textura). Pero cuando descomente t_overlayer, entonces t_camera se convirtió en negro (de alguna manera mal muestreado). Mi textura de superposición es 512×512 y CLAMPT_TO_EDGE. Este problema se produce sólo por ejemplo en: Emulador de Android, HTC Evo 3D. Pero en SGS3, HTC One X, funciona muy bien.

¿Qué está mal? ¿Es Evo 3D falta alguna extensión o qué?

Tengo el mismo problema en mi Nexus 7 y me volvió loco. El acceso a un samplerExternalOES o un sampler2D funcionó totalmente bien, pero acceder a ambos en el mismo shader dio resultados inesperados. A veces la salida sería negra. A veces la salida de una de las búsquedas tendría malos artefactos de cuantificación. El comportamiento también varía dependiendo de la unidad de textura a la que se unen los samplers. Comprobé cada error de opengl y validateProgram resultados.

Eventualmente, lo que funcionó fue usar un shader independiente para simplemente acceder a la salida de la cámara y convertirla en una textura. A continuación, la textura resultante se puede acceder a través de un sampler2D regular y todo funciona exactamente como se espera. Sospecho que hay un error en algún lugar relacionado con samplerExternalOES.

Me imagino que tiene este problema porque no está configurando la ID de textura correcta en su código. Este es un error típico en suposiciones que parecen lógicas, pero en realidad no se define así en la documentación. Si comprueba la documentación de esta extensión, verá lo siguiente (editado) TEXT:

Cada objeto de textura TEXTURE_EXTERNAL_OES puede requerir hasta 3 unidades de imagen de textura para cada unidad de textura a la que está enlazada. Cuando se establece en TEXTURE_EXTERNAL_OES este valor estará entre 1 y 3 (inclusive). Para otros objetivos de textura válidos, este valor siempre será 1. Tenga en cuenta que cuando un objeto de textura TEXTURE_EXTERNAL_OES está enlazado, el número de unidades de imagen de textura requerido por una unidad de textura única puede ser 1, 2 ó 3 , mientras que para otros objetos de textura cada uno La unidad de textura requiere exactamente 1 unidad de imagen de textura.

Esto significa que al menos un adicional funcionará, siempre que utilice id 0 para ello. En tu caso:

 GLES20.glUniform1i(sTextureHandle, 1); GLES20.glActiveTexture(GLES20.GL_TEXTURE1); GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, sTextureId); 

Para su textura 2D:

 GLES20.glUniform1i(filterTextureHandle, 0); GLES20.glActiveTexture(GLES20.GL_TEXTURE0); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, filterTextureID); 

Estoy seguro de que esto funcionará para usted.

El método en el anterior ahorrar mucho de mi tiempo. Gracias gurú:

 GLES20.glUniform1i(sTextureHandle, 1); GLES20.glActiveTexture(GLES20.GL_TEXTURE1); GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, sTextureId); 

Para su textura 2D:

 GLES20.glUniform1i(filterTextureHandle, 0); GLES20.glActiveTexture(GLES20.GL_TEXTURE0); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, filterTextureID); 

Cambiar el índice de textura es una buena manera de resolver esto.

Parece ser un error en la implementación de OpenGl. El mismo código funcionó bien en Samsung Nota y no en el nexo 4. Parece que getUniformLocation se rompe en algunos dispositivos para todas las variables que se encuentran más allá de samplerExternalOES.

También parece que el compilador ordena las variables uniformes alfabéticamente, por lo que la solución que lo hizo funcionar en ambos dispositivos fue cambiar el nombre de su samplerExternalEoz a ser zzzTexture o algo así.

Esto no es una respuesta, sino más bien una elaboración de la pregunta – tal vez ayudará a un experto de OpenGl ES a tener una idea del problema.


Tengo 3 texturas usadas para la superposición, y una textura externa, usada para capturar salida del reproductor multimedia. Si utilizo sólo textura externa, la salida es como se esperaba, frames de MPlayer. El mismo código completo funciona bien en Nexus4, Samsung Galaxy S3, S4, etc. (todos los dispositivos utilizan adreno gpus o Mali400 de Arm) La diferencia en hardware es que Nexus 7 utiliza Nvidia Tegra 3 bordo.


Editar (cómo se resolvió a mi lado) :

Nvidia Tegra 3 requiere que el sampleador externo de textura se llame con un nombre con el orden alfabético más bajo entre los samplers, mientras que el Adreno 220 parece requerir el reverso. Además, T3 requiere que la textura externa se muestre en último lugar. Con dispositivos que utilizan Android 4.3 y versiones posteriores, estos errores pueden resolverse. En el lado de Nvidia, era un error, resuelto hace mucho tiempo, pero los controladores de Nexus se actualizaron sólo más tarde. Así que tuve que comprobar qué gpu estaba presente, y adaptar el código en consecuencia.

Yo podría tener el mismo problema también. Después de días de intentar, estoy proponiendo mis soluciones aquí. Esperando que esto ayudara a otros.

En primer lugar, la declaración del problema. Al igual que Lukáš Jezný, tengo una textura de vista previa y una textura de superposición. Funciona bien para el nexo 4/5 y la mayoría de los otros tipos, pero no muestra nada en OPPO encontrar 5, Lenovo A820, Lenovo A720.

solución:

(1) al igual que Lukáš Jezný, utilizar datos YUV y transformarlos en RGB en el sombreado.

(2) dibujo multipunto, dibujar la textura de vista previa al framebuffer una vez, y leerlo, luego dibujar de nuevo a la pantalla.

(3) utilizar otro programa antes de usar su propio programa,

  GLES20.glUseProgram(another one); GLES20.glUseProgram(your "real" program); 

Y sólo funciona para OPPO encontrar 5, Lenovo A820, Lenovo A720 y otros. Nadie sabe por qué

Haciendo referencia a la publicación de user1924406 ( https://stackoverflow.com/a/14050597/3250829 ) al dividir el acceso a una textura sampler2D y una textura samplerExternalOES, esto es lo que tenía que hacer porque la aplicación que estoy desarrollando es la lectura de un archivo o Streaming desde un servidor en lugar de utilizar la cámara que se encuentra en el dispositivo. El uso de ambas texturas en el mismo sombreado resultó en muy extraños artefactos de coloración (el caso en un Galaxy S3) o problemas de saturación y contraste (el caso en un Nexus 4).

Como tal, la única manera de trabajar alrededor del error de la textura de samplerExternalOES (de lo que he visto hasta ahora) es hacer los dos programas del sombreador: Uno que escribe el contenido contenido en la textura del samplerExternalOES a un FBO y el otro que toma el Contenido de la FBO y lo escribe directamente a la superficie.

Una cosa que usted necesita comprobar es que a veces cuando usted escribe a un FBO, la textura coordina el tirón. En mi caso, se volteó la coordenada V (o T o Y) que dio como resultado una imagen reflejada a través del eje horizontal. Tuve que tener esto en cuenta al escribir el fragmento shader en la segunda etapa.

Esta es una historia de guerra que quería compartir en caso de que haya algunos de ustedes que puedan necesitar leer de un archivo o secuencia de un servidor en lugar de tomar directamente desde la cámara.

  • Compresión de textura de Android OpenGL
  • Cargando texturas en una aplicación de Android OpenGL ES
  • ¿Cómo puedo encontrar el tamaño máximo de textura para diferentes teléfonos?
  • ¿Para qué se utiliza Android TextUtils?
  • Cargando texturas grandes en AndEngine
  • Limitación del tamaño de la textura? Android Open GL ES 2.0
  • Compartir el contexto GLES20 y texturas entre GLSurfaceViews diferentes?
  • LibGDX crea la textura de base64 PNG ByteArrayInputStream
  • Perder las texturas de OpenGL en Android después de un currículum
  • Consejos para mejorar la tasa de llenado de OpenGL ES en Android
  • ¿Cómo escalar sprites en libgdx según las resoluciones de pantalla?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.