Qt OpenGL - 纹理透明度问题
Qt OpenGL - Texture Transparency issue
我目前正在尝试学习 OpenGL,但遇到纹理透明度方面的问题。
我有 2 个 planes/rectangles 有纹理,第一个离相机最近,第二个更靠后,在第一个后面。两者都带有背景不透明度为 50% 的图像纹理。
我应该能够看到第一个平面后面的第二个平面的纹理,因为第一个平面在某种程度上是透明的 - 但我没有。我正在使用的图像实际上是独立出现的(如果我旋转相机可以看到它们),并且它们上面有文字(我希望它能从前面图像的半透明背景中渗出).
有办法解决这个问题吗?
这是我的初始化和 paintGL 方法(它们可能经过了可怕的优化)
void oglWidget::initializeGL()
{
glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glEnable(GL_CULL_FACE);
qglClearColor(QColor(Qt::white));
shaderProgram.addShaderFromSourceFile(QGLShader::Vertex, ":/vertexShader.vsh");
shaderProgram.addShaderFromSourceFile(QGLShader::Fragment, ":/fragmentShader.fsh");
shaderProgram.link();
// vertices[1] << QVector3D(-xAmt, -1, 0) << QVector3D( xAmt, -1, 0) << QVector3D( xAmt, 1, 0) // Front
// << QVector3D( xAmt, 1, 0) << QVector3D(-xAmt, 1, 0) << QVector3D(-xAmt, -1, 0);
float xAmt = 16.00/9.00;
vertices << QVector3D(-xAmt, -1, 0) << QVector3D( xAmt, -1, 0) << QVector3D( xAmt, 1, 0) // Midground
/*<< QVector3D( xAmt, 1, 0) << QVector3D(-xAmt, 1, 0) << QVector3D(-xAmt, -1, 0)*/
<< QVector3D(-xAmt, -1, -1) << QVector3D( xAmt, -1, -1) << QVector3D( xAmt, 1, -1) // Background
<< QVector3D( xAmt, 1, -1) << QVector3D(-xAmt, 1, -1) << QVector3D(-xAmt, -1, -1);
textureCoordinates << QVector2D(0, 0) << QVector2D(1, 0) << QVector2D(1, 1) // Front
<< QVector2D(1, 1) << QVector2D(0, 1) << QVector2D(0, 0)
<< QVector2D(0, 0) << QVector2D(1, 0) << QVector2D(1, 1) // Front
<< QVector2D(1, 1) << QVector2D(0, 1) << QVector2D(0, 0);
}
void oglWidget::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
QMatrix4x4 mMatrix;
QMatrix4x4 vMatrix;
QMatrix4x4 cameraTransformation;
cameraTransformation.rotate(alpha, 0, 1, 0);
cameraTransformation.rotate(beta, 1, 0, 0);
QVector3D cameraPosition = cameraTransformation * QVector3D(0, 0, distance);
QVector3D cameraUpDirection = cameraTransformation * QVector3D(0, 1, 0);
vMatrix.lookAt(cameraPosition, QVector3D(0, 0, 0), cameraUpDirection);
shaderProgram.bind();
shaderProgram.setUniformValue("mvpMatrix", pMatrix * vMatrix * mMatrix);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
shaderProgram.setUniformValue("texture", 0);
shaderProgram.setAttributeArray("vertex", vertices.constData());
shaderProgram.enableAttributeArray("vertex");
shaderProgram.setAttributeArray("textureCoordinate", textureCoordinates.constData());
shaderProgram.enableAttributeArray("textureCoordinate");
glGenTextures(0, &texture); glBindTexture(GL_TEXTURE_2D, texture);
QImage tempTexture = QGLWidget::convertToGLFormat(QImage(ImgManager::getImg("/Textures/Editor/m.png")));
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, tempTexture.width(), tempTexture.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, tempTexture.bits() );
glDrawArrays(GL_TRIANGLES, 0, vertices.size());
shaderProgram.release();
}
即使启用了混合,新几何体也会执行深度测试以检查当前片段是否可见并且用新值填充深度缓冲区。
修复它的一个简单方法是使用 glDisable(GL_DEPTH_TEST);
完全禁用深度测试,但更好的方法如下:
- 设置
glDepthMask(GL_TRUE);
- 绘制不透明对象
- 设置
glDepthMask(GL_FALSE);
- 绘制透明对象
glDepthMask(GL_FALSE);
将在深度测试本身仍处于启用状态时禁用对深度缓冲区的写入。因此,不透明物体只有在透明物体真正在它们前面时才会遮挡透明物体。
我目前正在尝试学习 OpenGL,但遇到纹理透明度方面的问题。
我有 2 个 planes/rectangles 有纹理,第一个离相机最近,第二个更靠后,在第一个后面。两者都带有背景不透明度为 50% 的图像纹理。
我应该能够看到第一个平面后面的第二个平面的纹理,因为第一个平面在某种程度上是透明的 - 但我没有。我正在使用的图像实际上是独立出现的(如果我旋转相机可以看到它们),并且它们上面有文字(我希望它能从前面图像的半透明背景中渗出).
有办法解决这个问题吗? 这是我的初始化和 paintGL 方法(它们可能经过了可怕的优化)
void oglWidget::initializeGL()
{
glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glEnable(GL_CULL_FACE);
qglClearColor(QColor(Qt::white));
shaderProgram.addShaderFromSourceFile(QGLShader::Vertex, ":/vertexShader.vsh");
shaderProgram.addShaderFromSourceFile(QGLShader::Fragment, ":/fragmentShader.fsh");
shaderProgram.link();
// vertices[1] << QVector3D(-xAmt, -1, 0) << QVector3D( xAmt, -1, 0) << QVector3D( xAmt, 1, 0) // Front
// << QVector3D( xAmt, 1, 0) << QVector3D(-xAmt, 1, 0) << QVector3D(-xAmt, -1, 0);
float xAmt = 16.00/9.00;
vertices << QVector3D(-xAmt, -1, 0) << QVector3D( xAmt, -1, 0) << QVector3D( xAmt, 1, 0) // Midground
/*<< QVector3D( xAmt, 1, 0) << QVector3D(-xAmt, 1, 0) << QVector3D(-xAmt, -1, 0)*/
<< QVector3D(-xAmt, -1, -1) << QVector3D( xAmt, -1, -1) << QVector3D( xAmt, 1, -1) // Background
<< QVector3D( xAmt, 1, -1) << QVector3D(-xAmt, 1, -1) << QVector3D(-xAmt, -1, -1);
textureCoordinates << QVector2D(0, 0) << QVector2D(1, 0) << QVector2D(1, 1) // Front
<< QVector2D(1, 1) << QVector2D(0, 1) << QVector2D(0, 0)
<< QVector2D(0, 0) << QVector2D(1, 0) << QVector2D(1, 1) // Front
<< QVector2D(1, 1) << QVector2D(0, 1) << QVector2D(0, 0);
}
void oglWidget::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
QMatrix4x4 mMatrix;
QMatrix4x4 vMatrix;
QMatrix4x4 cameraTransformation;
cameraTransformation.rotate(alpha, 0, 1, 0);
cameraTransformation.rotate(beta, 1, 0, 0);
QVector3D cameraPosition = cameraTransformation * QVector3D(0, 0, distance);
QVector3D cameraUpDirection = cameraTransformation * QVector3D(0, 1, 0);
vMatrix.lookAt(cameraPosition, QVector3D(0, 0, 0), cameraUpDirection);
shaderProgram.bind();
shaderProgram.setUniformValue("mvpMatrix", pMatrix * vMatrix * mMatrix);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
shaderProgram.setUniformValue("texture", 0);
shaderProgram.setAttributeArray("vertex", vertices.constData());
shaderProgram.enableAttributeArray("vertex");
shaderProgram.setAttributeArray("textureCoordinate", textureCoordinates.constData());
shaderProgram.enableAttributeArray("textureCoordinate");
glGenTextures(0, &texture); glBindTexture(GL_TEXTURE_2D, texture);
QImage tempTexture = QGLWidget::convertToGLFormat(QImage(ImgManager::getImg("/Textures/Editor/m.png")));
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, tempTexture.width(), tempTexture.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, tempTexture.bits() );
glDrawArrays(GL_TRIANGLES, 0, vertices.size());
shaderProgram.release();
}
即使启用了混合,新几何体也会执行深度测试以检查当前片段是否可见并且用新值填充深度缓冲区。
修复它的一个简单方法是使用 glDisable(GL_DEPTH_TEST);
完全禁用深度测试,但更好的方法如下:
- 设置
glDepthMask(GL_TRUE);
- 绘制不透明对象
- 设置
glDepthMask(GL_FALSE);
- 绘制透明对象
glDepthMask(GL_FALSE);
将在深度测试本身仍处于启用状态时禁用对深度缓冲区的写入。因此,不透明物体只有在透明物体真正在它们前面时才会遮挡透明物体。