android - Problemas con GLUtils.texImage2D y Alpha en Textures
opengl-es bitmap (5)
Hay un problema en GLUtils con alpha premultiplicado. La única solución alternativa que puedo proponer es usar:
gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA)
En caso de que necesite otras funciones de mezcla, deberá usar gl.glTexImage2D
.
Estoy generando con éxito mis texturas usando GLUtils.texImage2D, pero cuando uso las texturas generadas, tengo problemas con mi alfa: son más oscuras de lo deseado.
Después de haber verificado varias cosas, finalmente obtuve las conclusiones de que el problema proviene de GLUtils.texImage2D (GL10.GL_TEXTURE_2D, level, bmp, 0);
Creé una segunda función que usa gl.glTexImage2D (GL10.GL_TEXTURE_2D, nivel, GL10.GL_RGBA, ancho, alto, 0, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, pixels2);
pero es costoso en el proceso crear pixels2, que es un bytebuffer en el que tengo que volver a copiar los bytes mientras cambio los valores desde el mapa de bits ARGB a la textura RGBA.
¿Alguien ha notado eso? y si es así, ¿cómo resolviste esto ...
jason
Gracias por tu respuesta, ya estoy usando
gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
y estoy obteniendo este problema
mi problema es que el alfa generado por GLUtils no es el de la textura, es más oscuro.
la diferencia es como mirar un color en el sol y en la sombra (si eso le da algún sentido).
Ya probé gl.gltextimage2d, pero la creación del búfer tarda demasiado, a menos que haya una herramienta para convertir un mapa de bits en un búfer de bytes que no conozco ...
GLUtils.texImage2D genera una textura alfa premultiplicada. En esta textura generada, todos los píxeles se multiplican por el valor alfa, por lo que no es necesario multiplicar el valor alfa una vez más. Intentemos
gl.glBlendFunc (GL10.GL_ONE, GL10.GL_ONE_MINUS_SRC_ALPHA);
El canal alfa es el hijastro maltratado y maltratado de una gran cantidad de programadores es todo lo que puedo decir ... pero la carga funciona bastante eficiente si haces eso:
Calcule su textura más grande (como 1024x1024) y cree una matriz int de ese tamaño (1024 * 1024) que almacene en alguna variable estática o en algún lugar donde pueda acceder a ella para no tener que volver a crear esa matriz (el tiempo de asignación es precioso aquí)
entonces haz esto:
bitmap.getPixels(pixels, 0, width, 0, 0, width, height); gl.glTexImage2D(GL10.GL_TEXTURE_2D, 0, GL10.GL_RGBA, width, height, 0, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, IntBuffer.wrap(pixels));
Lamento no haber encontrado una solución diferente ... el problema original es que el implementador de la función GLUtils.texImage2D ha maltratado el canal alfa de alguna manera, dando como resultado bordes negros cuando la imagen se muestra más grande de lo que es (el filtro bilineal calcula el color entre cuatro píxeles y cuando los valores de rgb de los píxeles con alfas transparentes han sido mutilados (como si estuvieran en negro), el resultado es que ocurre una especie de "sangrado de color" sobre el borde transparente que se está formando allí. Muy feo. Tal vez se hizo para mejorar la relación de compresión ya que los valores RGB en áreas alfa transparentes en PSD contienen una gran cantidad de basura que cuando se eliminan producen mucho margen de mejora para los algoritmos de compresión.
Editar: Lamentablemente, este enfoque solo funcionaba correctamente para las imágenes grises, ya que el canal rojo y azul se intercambia cuando se buscan los píxeles del mapa de bits. Al menos en MI dispositivo. No estoy seguro de qué tan correcto es esto para otros dispositivos, pero en mi caso, este fue el truco:
for (int i=0;i<pixels.length;i+=1) {
int argb = pixels[i];
pixels[i] = argb&0xff00ff00 | ((argb&0xff)<<16) | ((argb>>16)&0xff);
}
Android Bitmap
almacena imágenes cargadas desde PNG con colores premultiplicados. GLUtils.texImage2D
también utiliza colores premultiplicados por alfa, por lo que no puede obtener los colores originales de esta manera.
Para cargar imágenes PNG sin canales RGB que se premultiplican uso el PNGDecoder
terceros y la textura de carga con glTexImage2D
. Puede obtener la biblioteca PNGDecoder para decodificar PNG desde aquí: http://twl.l33tlabs.org/#downloads
La solución se encuentra aquí . Se relaciona como lo afirman otros con alfa premultiplicado.
En el SurfaceView Constructor
setEGLConfigChooser(8, 8, 8, 8, 0, 0);
getHolder().setFormat(PixelFormat.RGBA_8888);
En View.Renderer onSurfaceCreated
gl.glEnable(GL10.GL_BLEND);
gl.glBlendFunc(GL10.GL_ONE, GL10.GL_ONE_MINUS_SRC_ALPHA);