Dibuja una textura en OpenGL ignorando su canal alfa
-
13-09-2020 - |
Pregunta
Tengo una textura cargada en la memoria que es de formato RGBA con varios valores alfa.
La imagen se carga así:
GLuint texture = 0;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
self.texNum = texture;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, self.imageWidth, self.imageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, [self.imageData bytes]);
Quiero saber cómo puedo dibujar esta textura para que el canal alfa de la imagen se trate como todos unos y la textura se dibuje como una imagen RGB.
Considere la imagen base:
Esta imagen es una progresión de 0 a 255 alfa y tiene un valor RGB de 255,0,0 en todo momento.
Sin embargo, si lo dibujo con la combinación desactivada, obtengo una imagen similar a la siguiente:www.ldeo.columbia.edu/~jcoplan/alpha/no_alpha.png
Cuando lo que realmente quiero es una imagen como esta:www.ldeo.columbia.edu/~jcoplan/alpha/correct.png
Realmente agradecería algunos consejos para que ignore el canal alfa por completo.Tenga en cuenta que inicialmente no puedo cargar la imagen como RGB porque necesito el canal alfa en otros puntos.
Editar:Intenté usar GL_COMBINE para resolver mi problema como tal:
glColorf(1,1,1,1);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PRIMARY_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
[self drawTexture];
Pero aún así no hubo suerte, todavía dibuja de negro a rojo.
Solución
Tengo una textura cargada en la memoria que es del formato RGBA con varios valores alfa
gldisable (gl_blend)
Sin embargo, si lo dibujo con la mezcla deshabilitada, obtengo una imagen que parece: www.ldeo.columbia.edu/~jcoplan/alpha/no_alpha.png
Esto sucede porque en su imagen de origen, todos los píxeles transparentes son negros.Es un problema con su textura / imagen, o tal vez con la función del cargador, pero no es un problema de OpenGL.
probablemente podría intentar solucionarlo usando GLTEXENV (GL_COMBINE ...) (es decir, mezcle el color de la textura con un color subyacente basado en el canal alfa), pero como no he hecho algo así, no estoy completamente seguro,y no puedo darte operandos exactos.Fue posible en Direct3D9 (usando D3DTOP_MODULATATEALPHA_ADDCOLOR), lo más probable es que haya una manera de hacerlo en OpenGL.
Otros consejos
No debe deshabilitar la mezcla, sino que use la glblendfunc con el correctoParámetros:
glBlendFunc(GL_ONE, GL_ZERO);
O podría decirle a OpenGL que cargue solo los canales RGB de su imagen usando
glPixelStorei(GL_UNPACK_ALIGNMENT, 4)
antes de llamar glTexImage2D
con el formato establecido en GL_RGB
.Hará que se salte el cuarto byte de cada píxel, es decir.el canal alfa.
Tuve un problema similar, y descubrí que fue porque IOS Image Loading estaba haciendo un valor premultivo en los valores de RBG (como se discutió en algunas de las otras respuestas y comentarios aquí).Me encantaría saber si hay una forma de deshabilitar la multiplicación previa, pero mientras tanto, estoy "des-multiplicando" usando el código derivado de este hilo y este hilo .
// un pre-multiply
uint8_t *imageBytes = (uint8_t *)imageData ;
int byteCount = width*height*4 ;
for (int i=0; i < byteCount; i+= 4) {
uint8_t a = imageBytes[i+3] ;
if (a!=255 && a!=0 ){
float alphaFactor = 255.0/a ;
imageBytes[i] *= alphaFactor ;
imageBytes[i+1] *= alphaFactor ;
imageBytes[i+2] *= alphaFactor ;
}
}