我想要能够改变代码颜色的粒子,因此可以使用任何颜色。所以我只有一个基本上具有亮度的纹理。
我一直在使用glColor4f(1f, 0f, 0f, 1f);
来应用颜色。
我试过的每一个blendfunc都已经接近工作了,就像下面的最后一张图片一样。我仍然希望保留亮度,就像在中间的图片中一样。 (如果颜色图层位于纹理图层的顶部,则类似于Photoshop中的叠加或柔光滤镜。)
如果没有可编程着色器,如何做到这一点的任何想法?此外,由于这些是粒子,我不想在它后面有一个黑盒子,我想把它添加到场景中。
答案 0 :(得分:9)
这是一个可能接近您正在寻找的解决方案:
glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
glActiveTexture( GL_TEXTURE0 );
glEnable( GL_TEXTURE_2D );
glBindTexture(GL_TEXTURE_2D, spriteTexture);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
glActiveTexture( GL_TEXTURE1 );
glEnable( GL_TEXTURE_2D );
glBindTexture(GL_TEXTURE_2D, spriteTexture);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD );
它的作用是将原始纹理乘以指定的颜色,然后在顶部添加原始纹理的像素值:
final_color.rgba = original_color.rgba * color.rgba + original_color.rgba;
这会产生比你要求的更亮的图像,但可能会有一些调整。
如果要保留纹理的alpha值,则需要使用GL_COMBINE而不是GL_ADD(+正确设置GL_COMBINE_RGB和GL_COMBINE_ALPHA)。
以下是在纹理上使用此技术的一些结果。
答案 1 :(得分:2)
无义!您不必使用多纹理。只是预先计算你的alpha。
如果你在加载它之后和之前为图像预加倍alpha,那么你只需要一个纹理单元用于GL_ADD纹理环境模式。
如果你在iOS上,那么Apple的libs可以为你预乘。请参阅示例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
搜索“预乘alpha”