在二维绘图里面的半透明很简单,把alpha通道的值不设置为1或者255就能看见后面的物体;后面物体的清晰度根据设置值的大小来决定。而在opengl中要实现半透明效果也很简单,但相比二维绘图还是要麻烦一些了。
其方法为启用GL_BLEND混合功能,设置混合因子;这样opengl就会用混合因子将前、后两个物体颜色进行混合;这里有很多种混合方式,可以只显示前面物体,也可以只显示后面物体,也可以像素叠加(分为rgb叠加,alpha叠加)等待。
我实现的效果如下
实现相比以前简单得多,就设置了下启用GL_BLEND功能,和设置混合因子。其它的渲染器我是用的前面的现成的
这里我只介绍绿色图片的混合实现,其渲染器很简单就是一个普通的纹理2d图片
#ifndef IMAGERENDER_H
#define IMAGERENDER_H
#include <QOpenGLShaderProgram>
#include <QOpenGLBuffer>
#include <QOpenGLTexture>
#include <QOpenGLExtraFunctions>
class ImageRender
{
public:
ImageRender() = default;
~ImageRender();
void initsize(QString fileName);
void render(QOpenGLExtraFunctions *f,QMatrix4x4 &pMatrix,QMatrix4x4 &vMatrix,QMatrix4x4 &mMatrix);
private:
QOpenGLShaderProgram program_;
QOpenGLTexture *texture_{nullptr};
QOpenGLBuffer vbo_;
};
#endif // IMAGERENDER_H
#include "imagerender.h"
ImageRender::~ImageRender()
{
texture_->destroy();
delete texture_;
}
void ImageRender::initsize(QString fileName)
{
program_.addCacheableShaderFromSourceFile(QOpenGLShader::Vertex,"vsrc.vert");
program_.addCacheableShaderFromSourceFile(QOpenGLShader::Fragment,"fsrc.frag");
program_.link();
texture_ = new QOpenGLTexture(QImage(fileName));
texture_->setMinificationFilter(QOpenGLTexture::LinearMipMapNearest);
texture_->setMagnificationFilter(QOpenGLTexture::LinearMipMapLinear);
texture_->setWrapMode(QOpenGLTexture::DirectionS,QOpenGLTexture::ClampToEdge);
texture_->setWrapMode(QOpenGLTexture::DirectionT,QOpenGLTexture::ClampToEdge);
GLfloat points[4 * 3 + 8]{
-1.0,-1.0,0.0,
+1.0,-1.0,0.0,
+1.0,+1.0,0.0,
-1.0,+1.0,0.0,
0.0,1.0,
1.0,1.0,
1.0,0.0,
0.0,0.0
};
vbo_.create();
vbo_.bind();
vbo_.allocate(points, sizeof points);
}
void ImageRender::render(QOpenGLExtraFunctions *f, QMatrix4x4 &pMatrix, QMatrix4x4 &vMatrix, QMatrix4x4 &mMatrix)
{
f->glEnable(GL_DEPTH_TEST);
f->glEnable(GL_CULL_FACE);
program_.bind();
vbo_.bind();
f->glActiveTexture(GL_TEXTURE0 + 0);
program_.setUniformValue("sTexture",0);
program_.setUniformValue("uPMatrix",pMatrix);
program_.setUniformValue("uVMatrix",vMatrix);
program_.setUniformValue("uMMatrix",mMatrix);
program_.enableAttributeArray(0);
program_.enableAttributeArray(1);
program_.setAttributeBuffer(0,GL_FLOAT,0,3,3 * sizeof GLfloat);
program_.setAttributeBuffer(1,GL_FLOAT,4 * 3 * sizeof GLfloat, 2, 2 * sizeof GLfloat);
texture_->bind(0);
f->glDrawArrays(GL_TRIANGLE_FAN,0,4);
program_.disableAttributeArray(0);
program_.disableAttributeArray(1);
texture_->release();
vbo_.release();
program_.release();
f->glDisable(GL_DEPTH_TEST);
f->glDisable(GL_CULL_FACE);
}
其shader如下
#version 330
uniform mat4 uPMatrix,uVMatrix,uMMatrix;
layout (location = 0) in vec3 aPosition;
layout (location = 1) in vec2 aTexture;
smooth out vec2 vTextureCood;
void main(void)
{
gl_Position = uPMatrix * uVMatrix * uMMatrix * vec4(aPosition,1);
vTextureCood = aTexture;
}
#version 330
uniform sampler2D sTexture;
in vec2 vTextureCood;
out vec4 fragColor;
void main(void)
{
fragColor = texture2D(sTexture,vTextureCood);
}
其它的还用到了mipmap纹理渲染器,和一个obj模型渲染器,在前面有就不介绍了。在使用时根据需要打开混合功能。
mMatrix.setToIdentity();
mMatrix.translate(3,1,10);
imageRender_.render(f,pMatrix,vMatrix,mMatrix); //不启用混合
f->glEnable(GL_BLEND); //启用混合
mMatrix.setToIdentity();
mMatrix.translate(-1.2,1.6,10);
mMatrix.scale(1.2);
f->glBlendFunc(GL_SRC_COLOR,GL_ONE_MINUS_SRC_COLOR); //用前物体因子用rgba、后物体因子为前物体rgba的1-前物体的rgba值(opengl中颜色值为0-1)。实现的效果类似于透过有色玻璃看物体
imageRender_.render(f,pMatrix,vMatrix,mMatrix);
mMatrix.setToIdentity();
mMatrix.translate(1.0,2.6,10);
f->glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); //以前物体的透明度为基准,前物体全透明,就只能看见后面的物体;前物体半透明,就能看见后面物体。
imageRender1_.render(f,pMatrix,vMatrix,mMatrix);
f->glDisable(GL_BLEND);//关闭混合
源码到此下载https://download.csdn.net/download/wanghualin033/10854601