OpenGL镂空贴图可以使用AlphaTest来完成,也可以使用Blend。
在载入bmp材质时,如果该bmp具有alpha通道,那么可以直接使用它创建纹理。如果只有rgb数据,想使用某种颜色作为镂空色,那么则需要手工创建一个unsigned char [width][height][4] 的空间,先将RGB按 [x][y][0], [x][y][1], [x][y][2] 对应拷贝到这个RGBA缓冲中,然后遍历它,对需要镂空的颜色,将其位置的 [x][y][3] 设置为 0 (对应alpha通道float表示方式的0.0f),否则为255 (对应alpha通道float表示方式的1.0f)。
之后,按RGBA, 4字节的方式创建纹理贴图
参考代码片段:
//---------------------------------------------------------------------------
bool Material::Open(const String& bmpFile)
{
if (this->IsOpen())
return false;
if (!File::IsExist(bmpFile))
return false;
AUX_RGBImageRec* textureImage = auxDIBImageLoad(bmpFile.ToLocal().Data());
if (!textureImage)
return false;
int handleId = -1;
glGenTextures(1, (GLuint*)&handleId); // 限制不超过signed int, 并且要成功
if (handleId < 0)
{
glDeleteTextures(1, (GLuint*)&handleId);
if (textureImage->data)
free(textureImage->data);//注意要用free
free(textureImage); //这里也要free
return false;
}
const int img_size = textureImage->sizeX * textureImage->sizeY;
unsigned char* buffer = new unsigned char[img_size * 4];
gt_assert(buffer);
for (int i = 0; i < img_size; ++i)
{
buffer[i * 4 + 0] = textureImage->data[i * 3];
buffer[i * 4 + 1] = textureImage->data[i * 3 + 1];
buffer[i * 4 + 2] = textureImage->data[i * 3 + 2];
if (buffer[i * 4 + 0] == MASK_RED && buffer[i * 4 + 1] == MASK_GREEN && buffer[i * 4 + 2] == MASK_BLUE)
buffer[i * 4 + 3] = 0;
else
buffer[i * 4 + 3] = 255;
}
glBindTexture(GL_TEXTURE_2D, handleId);
glTexImage2D(GL_TEXTURE_2D, 0, 4, textureImage->sizeX, textureImage->sizeY, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_2D, 0);
delete buffer; buffer = NULL;
if (textureImage->data)
free(textureImage->data);//注意要用free
free(textureImage); //这里也要free
m_handle = handleId;
return true;
}
//---------------------------------------------------------------------------
现在有2种显示镂空的方法:
(1) AlphaTest方式:
绘制前设置:
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0.0f); // GL_GREATER表示大于的意思,这里指:当源的Alpha通道>0.0f时,画出这个象素,否则不画。
(2) Blend方式:
绘制前设置:
glEnable(GL_BLEND); // 启用混合
glDisable(GL_DEPTH_TEST); // 禁用深度测试
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // 表示按源元素Alpha处理,不改变Alpha亮度进行混合。
两种方式中,第一种方法专用与镂空,第二种方法可以实现半透明+镂空,具体效果可以调整alpha值自己体会。
注意,第一种方式会明显快与第二种,因为openGL中,alpha test是先于alpha blend的,首先要通过检测的pix才进入管线再进行颜色混合的。