我有一个绑定到简单四边形的OpenGL纹理。
我的问题是:我的纹理是128x128像素的图像。我只在该图像上填充大约100x60像素,其他像素是透明的。我把它保存在.png文件中。当我绘图时,绑定纹理的透明部分是白色的。
假设我有背景。当我在这个背景上绘制这个新的四边形时,我看不到透过纹理的透明部分。
有什么建议吗?
代码:
// Init code...
gl.glEnable(gl.GL_TEXTURE_2D);
gl.glDisable(gl.GL_DITHER);
gl.glDisable(gl.GL_LIGHTING);
gl.glDisable(gl.GL_DEPTH_TEST);
gl.glTexEnvi(gl.GL_TEXTURE_ENV, gl.GL_TEXTURE_ENV_MODE, gl.GL_MODULATE);
// Drawing code...
gl.glBegin(gl.GL_QUADS);
gl.glTexCoord2d(0.0, 0.0);
gl.glVertex3f(0.0f, 0.0f, 0.0f);
gl.glTexCoord2d(1.0, 0.0);
gl.glVertex3f(1.0f, 0.0f, 0.0f);
gl.glTexCoord2d(1.0, 1.0);
gl.glVertex3f(1.0f, 1.0f, 0.0f);
gl.glTexCoord2d(0.0, 1.0);
gl.glVertex3f(0.0f, 1.0f, 0.0f);
gl.glEnd();
我已尝试过几乎所有内容,从启用混合到更改为GL_REPLACE,但是我无法让它工作。
编辑:
// Texture. Have tested both gl.GL_RGBA and gl.GL_RGB8.
gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, (int)gl.GL_RGBA, imgWidth, imgHeight,
0, gl.GL_BGR_EXT, gl.GL_UNSIGNED_BYTE, bitmapdata.Scan0);
答案 0 :(得分:32)
检查您的纹理是否为RGBA格式,并启用混合并设置混合功能:
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
绘制纹理。如果你的纹理不是RGBA,那么就没有alpha,混合也不会做任何事情。
编辑:既然您发布了代码,我可能会发现一个严重的错误:glTexImage2D(gl.GL_TEXTURE_2D, 0, (int)gl.GL_RGBA, imgWidth, imgHeight, 0, gl.GL_BGR_EXT, gl.GL_UNSIGNED_BYTE, bitmapdata.Scan0);
你告诉GL纹理有internalFormat RGBA,但是位图数据有BGR格式,所以纹理数据没有alpha。假设alpha = 1.0。
要更正它,请使用RGBA格式加载PNG,并使用GL_RGBA作为glTexImage2D的internalFormat和format参数。
答案 1 :(得分:1)
When I'm drawing, the transparent part of the binded texture is white.
这意味着您的PNG解析器将透明区域转换为白色值。如果要使用OpenGL渲染透明图层,通常不依赖纹理文件来保持透明度,而是使用GLBlendFunc()
。更多信息:
http://www.opengl.org/resources/faq/technical/transparency.htm
答案 2 :(得分:1)
此外,如果渲染到帧缓冲区并将结果复制到纹理中,请检查帧缓冲区是否已打开alpha。例如,当使用osgViewer时,可以通过(在调用setUpViewInWindow之前执行此操作)来实现:
osg::DisplaySettings *pSet = myviewer.getDisplaySettings();
if(pSet == NULL)
pSet = new osg::DisplaySettings();
pSet->setMinimumNumAlphaBits(8);
myviewer.setDisplaySettings(pSet);
并且在qt下它应该与(来自http://forum.openscenegraph.org/viewtopic.php?t=6411):
一起使用QGLFormat f;
f.setAlpha( true ); //enables alpha channel for this format
QGLFormat::setDefaultFormat( f ); //set it as default before instantiations
setupUi(this); //instantiates QGLWidget (ViewerQT)
通常情况下,最好直接渲染到帧缓冲区中,但是在准备一些遗留代码的过程中,我总是这样做,而且在开始时很难找到它。