нонсенс! Вам не нужно использовать несколько текстур. Просто умножьте свою альфу.
Если вы предварительно умножаете альфа на изображение после того, как загрузите его и до того, как создадите для него текстуру GL, тогда вам понадобится только одна единица текстуры для режима env текстуры GL_ADD.
Если вы работаете на iOS, то библиотеки Apple могут быть предварительно умножены для вас. См. Пример класса Texture2D и найдите флаг kCGImageAlphaPremultipliedLast.
Если вы не используете загрузчик изображений, который поддерживает предварительное умножение, вам придется делать это вручную после загрузки изображения. Псевдокод:
uint8* LoadRGBAImage(const char* pImageFileName) {
Image* pImage = LoadImageData(pImageFileName);
if (pImage->eFormat != FORMAT_RGBA)
return NULL;
// allocate a buffer to store the pre-multiply result
// NOTE that in a real scenario you'll want to pad pDstData to a power-of-2
uint8* pDstData = (uint8*)malloc(pImage->rows * pImage->cols * 4);
uint8* pSrcData = pImage->pBitmapBytes;
uint32 bytesPerRow = pImage->cols * 4;
for (uint32 y = 0; y < pImage->rows; ++y) {
byte* pSrc = pSrcData + y * bytesPerRow;
byte* pDst = pDstData + y * bytesPerRow;
for (uint32 x = 0; x < pImage->cols; ++x) {
// modulate src rgb channels with alpha channel
// store result in dst rgb channels
uint8 srcAlpha = pSrc[3];
*pDst++ = Modulate(*pSrc++, srcAlpha);
*pDst++ = Modulate(*pSrc++, srcAlpha);
*pDst++ = Modulate(*pSrc++, srcAlpha);
// copy src alpha channel directly to dst alpha channel
*pDst++ = *pSrc++;
}
}
// don't forget to free() the pointer!
return pDstData;
}
uint8 Modulate(uint8 u, uint8 uControl) {
// fixed-point multiply the value u with uControl and return the result
return ((uint16)u * ((uint16)uControl + 1)) >> 8;
}
Лично я использую libpng и предварительно умножаю вручную.
В любом случае, после предварительного умножения просто свяжите байтовые данные как текстуру RGBA OpenGL. Использование glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD); с одним текстурным блоком должно быть все, что вам нужно после этого. Вы должны получить точно (или чертовски близко) к тому, что вы хотите. Возможно, вам придется использовать glBlendFunc (GL_SRC_ALPHA, GL_ONE); а также, если вы действительно хотите, чтобы вещь выглядела блестящей между прочим.
Это немного отличается от метода Ozirus. Он никогда не «уменьшает» значения RGB текстуры путем предварительного умножения, поэтому каналы RGB добавляются слишком сильно и выглядят как размытые / слишком яркие.
Полагаю, что метод предварительного умножения больше похож на Overlay, тогда как метод Ozirus - Soft Light.
Подробнее см .:
http://en.wikipedia.org/wiki/Alpha_compositing
Поиск "предварительно умноженная альфа"