我正在尝试编写一些代码来渲染任意多边形上的任意图像 . 该程序需要支持图像透明度 . 我选择使用OpenGL来渲染所述多边形 . 当我在Windows机器上开发时,我正在使用glew来处理在OpenGL 1.1之后发生的OpenGL函数 . 我的图形硬件支持OpenGL 2.1 . 我正在使用stb_image将我的图像从磁盘加载到RAM . 我从绘图中得到了一些相当奇怪的结果 .

当我使用glTexEnv中的GL_DECAL将图像渲染到多边形上时,纹理's alpha channel dictates its blending between the color of the texture and the color of the polygon it'被绘制到 . 这是我所期望的,但是当与颜色缓冲区混合时,它是's not the behavior I would like. So, I changed from GL_DECAL to GL_REPLACE, which is said to use the texture'的alpha值 . 启用混合后,我得到了上面提到的奇怪结果 . 当我想要绘制的图像的alpha值等于0时,我在(据称)完全透明的部分中得到随机颜色 . 我的问题实际上与Transparent png texture in cocos2d using opengl iphone中提到的问题完全相同,但在Windows 7而不是iOS上 .

有谁知道为什么我得到这些结果以及我能做些什么来得不到这些结果?

glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL ); 渲染的图像:http://www.majhost.com/gallery/DagonEcelstraun/Others/HelpNeeded/gl_decal.png注意小猫图像上的红色文字和红色背景 . 这是应该的 .

使用 glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); 呈现的图像:http://www.majhost.com/gallery/DagonEcelstraun/Others/HelpNeeded/gl_replace.png请注意,文本不再是红色 . 奇 . 还要注意小猫的背景没有意义 .

初始化代码,在Graphics2D.cpp中:

Graphics2D::Graphics2D()
{
glEnable( GL_TEXTURE_2D );
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
}

图形加载代码,在Graphics2D.cpp中:

int Graphics2D::loadImage( std::string imageName ) {
FILE *file = fopen( imageName.c_str(), "rb" );  //open filename as a read-only binary file
GLuint texture = 0;
int x, y, comp; //actual x-dimension, y-dimension, and number of byter per pixel in the actual file
GLubyte *data = stbi_load_from_file( file, &x, &y, &comp, 0 );
fclose( file );

glEnable( GL_TEXTURE_2D );

glGenTextures( 1, &texture );
glBindTexture( GL_TEXTURE_2D, texture );
glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );

if( comp == 3 ) {
    glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, x, y, 0, GL_RGB, GL_UNSIGNED_BYTE, data );
} else if( comp == 4 ) {
    glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data );
}

ImageData d;
d.id = texture;
d.x = x;
d.y = y;
d.a = comp == 4;
images.push_back( d );

return texture;
}

图形绘制代码,在Graphics2D.cpp中:

void Graphics2D::drawImage( int imageID, int x, int y ) {
ImageData curData;
for( ImageData &id : images ) {
    if( id.id == imageID ) {
        curData = id;
    }
}
int maxX = x + curData.x;
int maxY = y + curData.y;

if( curData.a ) {       
    glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
} else { 
    glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL );
}

glBindTexture( GL_TEXTURE_2D, imageID );
glBegin( GL_QUADS );
    glTexCoord2i( 0, 0 );
    glVertex3i( x, -y, -1 );
    glTexCoord2i( 1, 0 );
    glVertex3i( maxX, -y, -1 );
    glTexCoord2i( 1, 1 );
    glVertex3i( maxX, -maxY, -1 );
    glTexCoord2i( 0, 1 );
    glVertex3i( x, -maxY, -1 );
glEnd();
}

最后,主程序在Main.cpp中调用的代码:

void paint( HDC hDC )
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glMatrixMode( GL_MODELVIEW );
glPushMatrix();
glLoadIdentity();

//graphics.drawImage( catJPG, 0, 0 );
graphics.setColor( 255, 0, 0 );    //graphics is an object of type Graphics2D
graphics.drawImage( catPNG, 250, 250 );
graphics.drawText( "Hello World", 50, 50 );

glPopMatrix();
SwapBuffers( hDC );
}

让我解释一下我使用的数据结构: ImageData 是一个结构,其中一个int用于OpenGL纹理id,一个int用于纹理's width (stored in x), an int for the texture'的高度(存储在y中),还有一个bool来告诉我纹理是否是否有alpha通道(存储在a中) . 因此,如果纹理具有alpha通道,则语句 if( curData.a ) 的计算结果为true .

值得注意的是,我在第一和第二张图像之间唯一改变的是,在图像绘制功能中,我改变了'glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE);' (现在是什么以及第二张图片中的内容)'glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);' (过去是什么以及第一张图片中的内容) .