本文正在参加「金石方案」
OpenGL混合根底
OpenGL中的混合简略了解便是两个色彩的中和色,比如常见的通明色,咱们有一块玻璃,玻璃后面有个物体,那么要显示一种通明的作用,就需求运用到混合的概念。
通明物体可所以彻底通明(它使色彩彻底穿透)或者半通明的(它使色彩穿透的同时也显示本身色彩)。一个物体的通明度,被定义为它的色彩的alpha值,alpha色彩值运用色彩向量的第四个元素。
混合方程
OpenGL中有两种混合方法:
- 第一种:能够简略的给定一个通明度alpha的阈值,关于低于阈值alpha的片段进行丢掉,高于阈值的片段进行保存,能够得到一个混合后的作用。可是这种混合方法会使得部分区域彻底保存,部分区域彻底丢掉,不适合通明下的场景。
- 第二种:采用一个混合公式对片段色彩进行混合。
OpenGL以下面的方程进行混合:
这里简略阐明下源向量和方针向量的概念:
源向量:便是将要运用的掩盖方针向量的色彩。
方针向量:将要被源向量掩盖的色彩向量。
经过定义也能够看出,咱们在制作的时候需求先制作方针向量,再制作源向量。
如果次序搞反了,先制作了源向量,再制作了方针向量,那么在制作源向量的过程中,由于方针向量还不存在,就会呈现方针向量被彻底掩盖的状况(假定敞开了深度测试)。
混合API详解
-
敞开混合
glEnable(GL_BLEND);
GL_BLEND
用来启用混合(Blending) 功用。
-
混合函数因子设置:
void glBlendFunc(GLenum sfactor, GLenum dfactor)
glBlendFunc接纳两个参数:用来设置源和方针因子。
OpenGL为咱们定义了许多选项,咱们把最常用的列在下面:
选项 值 GL_ZERO 00 GL_ONE 11 GL_SRC_COLOR 源色彩向量C_source GL_ONE_MINUS_SRC_COLOR 1−C_source GL_DST_COLOR 方针色彩向量C_destination GL_ONE_MINUS_DST_COLOR 1−C_destination GL_SRC_ALPHA C_source alpha值 GL_ONE_MINUS_SRC_ALPHA 1−C_source alpha值 GL_DST_ALPHA C_destination的alpha值 GL_ONE_MINUS_DST_ALPHA 1−C_destination的alpha值 GL_CONSTANT_COLOR 常色彩向量C_constant GL_ONE_MINUS_CONSTANT_COLOR 1−C_constant GL_CONSTANT_ALPHA C_constant的alpha值 GL_ONE_MINUS_CONSTANT_ALPHA 1−C_constant的alpha值 注意,色彩常数向量能够用
glBlendColor
函数分开来设置。为了将两个色彩按alpha通明度进行混合,咱们需求把源色彩的alpha给源因子,1−alpha给方针因子,如下设置:
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
当然你也能够运用
glBlendFuncSeparate
函数来分别对RGB和alpha因子设置:glBlendFuncSeparate (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
-
设置混合形式是相加还是相减
void glBlendEquation(GLenum mode)
有三种形式可选:
- GL_FUNC_ADD:默许的,互相元素相加:result = Src+Dst;
- GL_FUNC_SUBTRACT:互相元素相减:result = Src−Dst;
- GL_FUNC_REVERSE_SUBTRACT:互相元素相减,但次序相反:result = Dst−Src;
一般咱们运用默许的GL_FUNC_ADD即可,如果需求完成一些其他作用,能够选择其他形式、
了解了以上api之后,下面咱们来写个demo
混合操作实践
下面咱们在之前代码根底上,给模型加上一个通明窗户的作用:渲染半通明纹路
代码如下:
- 极点着色器代码:
"#version 300 es \n"
"layout(location = 0) in vec3 vPosition;\n"
"layout(location = 1) in vec2 texCords;\n"
"out vec2 TexCords;\n"
"uniform mat4 model;\n"
"uniform mat4 view;\n"
"uniform mat4 projection;\n"
"void main()"
"{ \n"
" gl_Position = projection*view*model*vec4(vPosition,1.0f); \n"
" TexCords = texCords; \n"
"} \n";
- 片段着色器代码:
"#version 300 es \n"
"precision mediump float;\n"
"uniform sampler2D cubeTexture;"
"in vec2 TexCords;"
"out vec4 outColor;\n"
"void main()"
"{ \n"
" vec3 _texture = vec3(texture(cubeTexture,TexCords));\n"
" outColor = vec4(_texture, 0.6f); \n"
"} \n";
- 制作代码:
void MyGLRenderContext::OnDrawFrame() {
isDrawing = true;
beforeDraw();
if(programObj == 0){
return;
}
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//清除buffer
glEnable(GL_DEPTH_TEST);
glEnable(GL_STENCIL_TEST);
glStencilOp(GL_KEEP,GL_KEEP,GL_REPLACE);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
//part1:制作立方体
{
//总是写入模板缓冲区,并让模板缓冲区可写
glStencilFunc(GL_ALWAYS,1,0xff);
glStencilMask(0xff);
//运用立方体程序着色器目标
useProgram(programObj);
//绑定VAO
glBindVertexArray(VAO);
//观察者位置
setCordder(model);
//绑定纹路
setUniformTexture("textureColor",textureID);
//开端制作
glDrawArrays(GL_TRIANGLES,0,36);
//解绑VAO
glBindVertexArray(GL_NONE);
}
//part2:制作物体概括
{
//制作模板缓冲区中不等于1的部分,并让模板缓冲区不可写,且屏蔽深度测试
glStencilFunc(GL_NOTEQUAL,1,0xff);
glStencilMask(0x00);
glDisable(GL_DEPTH_TEST);
//运用物体概括制作的着色器目标
useProgram(singleColorShader);
glBindVertexArray(VAO);
GLfloat scale = 1.1f;
//第一次制作时缩放到1.1倍
if(isFirstDraw){
modelScale = glm::scale(modelScale, glm::vec3(scale, scale, scale));
isFirstDraw = false;
}
//设置坐标系的变换矩阵
setCordder(modelScale);
//开端制作
glDrawArrays(GL_TRIANGLES,0,36);
//重置模板缓冲区参数并敞开深度测试,开释资源
glStencilMask(0xFF);
glStencilFunc(GL_ALWAYS, 0, 0xFF);
glEnable(GL_DEPTH_TEST);
glBindVertexArray(GL_NONE);
//解绑程序着色器目标
glUseProgram(GL_NONE);
}
//part3:制作窗户
{
//运用一个新的着色器目标
useProgram(cubeProObj);
//绑定窗户极点数据
glBindVertexArray(cubeVAO);
//设置坐标系
setCordder(modelCube);
//设置纹路坐标:窗户
setUniformTexture("cubeTexture",cubeTextureID);
//制作正方形
glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_INT,0);
isDrawing = false;
glBindVertexArray(GL_NONE);
//解绑程序着色器目标
useProgram(GL_NONE);
}
}
- 最后作用:
最后:完整代码现已贴到github上了,我们能够自行下载查看。我是小余,咱们下期见》》》