1、颜色混合

使用混合的原因:

我们把OpenGL渲染时会把颜⾊值存在颜⾊缓存区中,每个⽚段的深度值也是放在深度缓冲区。当深度缓冲区被关闭时,新的颜⾊将简单的覆盖原来颜⾊缓存区存在的颜⾊值;当深度缓冲区再次打开时,新的颜⾊⽚段只是当它们⽐原来的值更接近邻近的裁剪平⾯才会替换原来的颜⾊⽚段。

那么如果开启深度测试后,当出现2个重叠的图层情况,有⼀个图层是半透明的,另⼀个图层是⾮半透明的,那么此时就不能进⾏单纯的⽐较深度值,然后进⾏覆盖。⽽是需要将2个图层的颜⾊进⾏计算后得到应该显示颜色,这个过程叫“混合”。

通常使用场景:

  • 如果只是单纯的2个图层重叠时进⾏混合,只需要开启混合,设置混合方式(设置后在固定着⾊器或可编程着⾊器中它会自动混合)。
  • 比如一些滤镜效果的制作,需要在可编程管线的⽚元着⾊器的着色时,套⽤公式或自定义进⾏颜⾊混合⽅程式计算,得到新的颜色值。例如将处理图⽚原图颜⾊加上薄薄的绿⾊,可以得到更好的视觉效果。

混合的具体使用:

⽬标颜⾊: 已经存储在颜⾊缓存区的颜⾊值。

源颜⾊: 作为当前渲染命令结果进⼊颜⾊缓存区的颜⾊值。


// 在OpenGL中默认是关闭的,需要开启GL_BLEND来启用混合功能:
glEnable(GL_BlEND); // 设置混合因⼦。S:源混合因⼦;D:⽬标混合因⼦。
glBlendFunc(GLenum S,GLenum D);
OpenGL混合计算方程式:

开启混合后,我们通过glBlendFunc函数告诉OpenGL使用什么混合因子来进行计算,而默认计算方程式是固定的,只需要改变因子来变换计算参数,得到不同的使用效果。


// 当混合功能被启动时,源颜⾊和⽬标颜⾊的组合⽅式是混合⽅程式控制的。
// 在默认情况下,混合⽅程式如下所示:Cf = (Cs * S) + (Cd * D)Cf :最终计算参数的颜⾊
Cs : 源颜⾊
Cd :⽬标颜⾊
S:源混合因⼦
D:⽬标混合因⼦
OpenGL混合因子表:

表中表示的都是计算方程式中参数的计算规则。
表中R、G、B、A 分别代表 红、绿、蓝、alpha。
表中下标S、D,分别代表源、⽬标。
表中C 代表常量颜⾊(默认⿊⾊)。

混合计算例子:

下⾯通过⼀个常⻅的混合函数组合来说明问题:
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);


如果颜⾊缓存区已经有⼀种颜⾊红⾊(1.0f,0.0f,0.0f,1.0f),这个⽬标颜⾊Cd;
如果在这上⾯⽤⼀种alpha为0.6的蓝⾊(0.0f,0.0f,1.0f,0.6f)。 Cd (⽬标颜⾊) = (1.0f,0.0f,0.0f,1.0f);
Cs (源颜⾊) = (0.0f,0.0f,1.0f,0.6f);
S = 源alpha值 = 0.6f
D = 1 - 源alpha值= 1-0.6f = 0.4f ⽅程式 Cf = (Cs * S) + (Cd * D)
等价于 = (Blue * 0.6f) + (Red * 0.4f)

修改混合⽅程式:

默认混合⽅程式为:Cf = (Cs * S) + (Cd * D)
实际上远不⽌这⼀种混合⽅程式,我们可以从5个不同的⽅程式中进⾏选择:


//选择混合⽅程式的函数:
glbBlendEquation(GLenum mode);
模式 函数
GL_FUNC_ADD Cf = (Cs * S) + (Cd * D)
GL_FUNC_SUBTRACT Cf = (Cs * S) - (Cd * D)
GL_FUNC_REVERSE_SUBTRACT Cf = (Cd * D) - (Cs * S)
GL_MIN Cf = min (Cs, Cd)
GL_MAX Cf = max (Cs, Cd)
修改常量混合颜⾊:

在混合因⼦表中,GL_CONSTANT_COLOR, GL_ONE_MINUS_CONSTANT_COLOR, GL_CONSTANT_ALPHA, GL
_ONE_MINUS_CONSTANT值允许混合⽅程式中引⼊⼀个常量混合颜⾊。默认初始化为⿊⾊(0.0f,0.0f,0.0f,1.0f),但是还是可以修改这个常量混合颜⾊。


常量混合颜⾊,默认初始化为⿊⾊(0.0f,0.0f,0.0f,1.0f),但是还是可以修改这个常量混合颜⾊。
void glBlendColor(GLclampf red ,GLclampf green ,GLclampf blue ,GLclam pf alpha );
设置混合因子:
  • glBlendFunc函数可以指定源和⽬标RGBA值的混合因子。
  • glBlendFuncSeparate函数则允许为RGB和Alpha成分单独指定混合因子。

glBlendFunc (GLenum sfactor, GLenum dfactor) sfactor:源混合因⼦;
dfactor:⽬标混合因⼦。

// 相对glBlendFunc来设置混合因子,glBlendFuncSeparate更灵活:
void glBlendFuncSeparate(GLenum strRGB,GLenum dstRGB ,GLenum strAlpha,GLenum dstAlpha);strRGB: 源颜色的混合因子
dstRGB: ⽬标颜色的混合因子=
strAlpha: 源颜色的Alpha因子
dstAlpha: ⽬标颜色的Alpha因子

反走样

为什么走样:

我们都知道,在数学的定义中一条线段是由两个端点确定的,而线段是没有宽度和面积的。但在计算机图形领域中,为了让人的肉眼能够看到,必须给线段一定的宽度,所以我们的线段通常是由两个端点和一个宽度参数确定的,而我们计算机中图形的宽度通常都是以像素为单位的,因此我们的线段宽度有可能是1像素也有可能是n像素。

使用OpenGL进行渲染后,我们很容易发现渲染图像的线存在锯齿问题。之所以产生这种锯齿,是因为一条理想的直线是通过像素网格上的一系列像素点去逼近的。由此产生的锯齿问题叫做走样(sliasing),而消除这种锯齿的过程就是我们所说的反走样。

反走样方式一:

上图所示为两条相交的线,分别是走样的情形和反走样的情形。图像进行了适当放大处理以突出显示效果。右侧宽度为1个像素的对角线段覆盖了比一般线段更多的像素块。事实上,当我们实现反走样的时候,OpenGL会根据屏幕上每个像素块所覆盖的范围来计算每个片元的覆盖值。OpenGL会将片元alpha值与这个覆盖值相乘。然后我们就可以使用alpha值来实现片元与帧缓存中已有像素的融混操作了。

覆盖值计算的细节是非常复杂的,很难概要地进行讲述。事实上,不同的 OpenGL实现中的计算方法也是存在细微差别的。我们可以使用gIHint()来进行进一步的控制,在图像质量和速度上做出权衡,不过并不是所有的设备实现都会受到这个函数的影响。


// glHint控制OpenGL的一些具体特性。
// hint参数的解析方式是与平台相关的,有些OpenGL的实现可能会完全忽略它们的影响。void glHint(GLenum target, GLenum hint);

glHint的参数target用来设置要控制的特性类型:

target参数 描述
GL_POINT_SMOOTH_HINT 点的反走样质量
GL_LINE_SMOOTH_HINT 线的反走样质量
GL_POLYGON_SMOOTH_HINT 多边形边的反走样质量
GL_TEXTURE_COMPRESSION_HINT 纹理图像压缩的质量和性能
GL_FRAGMENT_SHADER_DERIVATIVE_HINT 片元处理内置函数的导数精度,包括 dFdx、dFdx 以及 fwidth

glHint的参数hint用来设置要控制的质量最高类型:

hint参数 描述
GL_FASTEST 使用效率最高的方式
GL_NICEST 使用质量最高的方式
GL_DONT_CARE 表示没有偏好
反走样方式二

如果程序中十分需要多重采样的效果,那么对线段和多边形反走样的另一种方法就是通过gIEnable()开启反走样,然后将GL_LINE_SMOOTH或者 GL_POLYGON_SMOOTH作为参数传入。你可能也需要通过gIHint()来设置一个质量参考值。

点的反走样:


glEnable(GL_POINT_SMOOTH);
glHint(GL_POINT_SMOOTH,GL_NICEST);

线段的反走样:

首先,需要开启融混。融混参数通常可以设置为 GL_SRC_ALPHA(源)和GL ONE_MINUS_SRC_ALPHA(目标)。或者也可以使用GL_ONE作为目标参数,这样线段相交的地方会显得更亮。现在我们可以使用反走样的方式来绘制点和线段了。如果用的alpha值足够高,那么反走样效果是非常明显的。注意当你设置使用融混时,需要考虑好渲染的顺序。不过大多数情况下,忽略顺序也不会带来很明显的问题。


glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glHint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE);

多边形的反走样
:


glEnable(GL_POLYGON_SMOOTH);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA_SATURATE, GL_ONE);
glHint(GL_POLYGON_SMOOTH_HINT, GL_DONT_CARE);

填充多边形的边的反走样与线段的反走样过程相似。由于不同的多边形的边之间存在着交叠,因此我们需要适当地对颜色值进行融混。

为了对多边形进行反走样,需要使用alpha值来表达多边形边的覆盖值。通过glIEnable()设置参数GL_POLYGON_SMOOTH来开启多边形的反走样功能。这样多边形边上的像素就会根据覆盖率来设置alpha值,这一点与线段的反走样是一致的。当然,如果需要的话,我们也可以设置 GL_POLYGON_SMOOTH_HINT的质量值。

为了确保边的融混方式恰当,我们可以设置颜色混合参数为 GL_SRC_ALPHA_SATURATE(源)和 GL_ONE(目标)。通过这个特定的融混函数,得到的最终颜色将是目标颜色和成比例的源颜色的总和;比例系数其实就是以下两者中的较小者:输入源的alpha值、1减去目标alpha值。这也就是说,对于一个alpha值很大的像素,连续输入像素对于最终颜色的影响很小,因为1减去目标alpha几乎为0。通过这种方式,多边形边的像素就可以与之后绘制的其他多边形的颜色很好地融合在一起了。

最后,还需要对场景中的所有多边形进行排序,保证它们按照从前往后的顺序排列后再渲染。

深度缓存对于反走样的使用有一定的负面影响,因为某些像素可能本来需要融混,但是却在深度测试后被抛弃了。如果要保证融混和反走样的正确性,那么我们也许需要禁止深度缓存。

OpenGL 颜色混合、图元的反走样(五)相关推荐

  1. opengl 反走样 混合 多重采样 blend multisample

    1. 反走样         在光栅图形显示器上绘制非水平且非垂直的直线或多边形边界时,或多或少会呈现锯齿状或台阶状外观.这是因为直线.多边形.色彩边界等是连续的,而光栅则是由离散的点组成,在光栅显示 ...

  2. 【转】OpenGL反走样

    反走样:        在光栅图形显示器上绘制非水平且非垂直的直线或多边形边界时,或多或少会呈现锯齿状或台阶状外观.这是因为直线.多边形.色彩边界等是连续的,而光栅则是由离散的点组成,在光栅显示设备上 ...

  3. 反走样和OpenGL多重采样

    1. 反走样 在计算机图形学中,在屏幕上显示对象时,可能会出现许多的"锯齿",这些锯齿是由顶点数据像素化之后成为片段的方式所引起的,由于将数学意义上的坐标转换到物理的显示器硬件上进 ...

  4. OPENGL简介---反走样

    由于计算机以离散点生成图形,生成图形必然与真实景物存在差距,这种差距表现为:直线或光滑曲面的锯齿.花纹失去原有色彩形状.细小物体在画面的消失等.统统叫做走样(aliasing).反走样可以减少这种情况 ...

  5. NeHe OpenGL第四十六课:全屏反走样

    NeHe OpenGL第四十六课:全屏反走样 全屏反走样 当今显卡的强大功能,你几乎什么都不用做,只需要在创建窗口的时候该一个数据.看看吧,驱动程序为你做完了一切.   在图形的绘制中,直线的走样是非 ...

  6. 计算机图形学【GAMES-101】2、光栅化(反走样、傅里叶变换、卷积)

    快速跳转: 1.矩阵变换原理Transform(旋转.位移.缩放.正交投影.透视投影) 2.光栅化(反走样.傅里叶变换.卷积) 3.着色计算(深度缓存.着色模型.着色频率) 4.纹理映射(重心坐标插值 ...

  7. WuxioLin 反锯齿算法(反走样算法,Xiaolin Wu Anti-aliasing algorithm) C# 代码实现

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一.锯齿和反锯齿 二.Xiaolin Wu 算法代码 1.C#完整代码如下 2.举例和测试 总结 前言 笔者前几日自己 ...

  8. QT QPainter::antialiasing QPainter::textAntialiasing 反走样、抗锯齿探究

    QT中使用QPainter 进行自行绘图的时候,为了防止"锯齿"的出现,我们会经常使用抗锯齿属性,也叫反走样, 既: QPainter::Antialiasing //绘图抗锯齿 ...

  9. GPU Gems1 - 11 阴影贴图反走样

    这章介绍了如何通过邻近百分比过滤方法(Percentage-Closer Filtering , PCF)有效减少阴影贴图的反走样,并描述了如何实现一个简化版本,并对PCF方法进行了一定改进.关于阴影 ...

  10. IOS – OpenGL ES 调节图像反色 GPUImageColorInvertFilter

    目录 一.简介 二.效果演示 三.源码下载 四.猜你喜欢 零基础 OpenGL (ES) 学习路线推荐 : OpenGL (ES) 学习目录 >> OpenGL ES 基础 零基础 Ope ...

最新文章

  1. 如何到达永生?揭示科学之美
  2. 在winform嵌入外部应用程序
  3. 技术部门Leader是不是一定要技术大牛担任?
  4. 【kafka】kafka消费者报错INVALID_FETCH_SESSION_EPOCH
  5. C++生成指定范围内随机数封装
  6. 【实践】数据科学在搜索、广告、推荐系统的应用实践.pdf(附下载链接)
  7. windows查看端口占用指令
  8. Xtreme Report为windows开发者提供一个完善的类似于Outlook 2003报表的风格
  9. 掌握 需求过程阅读笔记02
  10. NetSuite 设置库存盘点
  11. 数字时代的中国支付体系现代化——DC/EP与数字人民币
  12. 3.23早间BTC/ETH急剧回踩,短暂拉升等机会
  13. 计算机浏览器应用程序,电脑打开IE浏览器显示找不到应用程序如何解决
  14. 使用晨曦记账本,个人有效记账
  15. 基于OpenWrt的PPTP插件开启防火墙转发
  16. #今日论文推荐# 速递:机器学习帮助构建人类肠道微生物群体感应网络
  17. replace、replaceAll、replaceFirst的区别
  18. hbase数据库连接池 未设置最大链接数导致数据库操作异常频发
  19. Rancher k8s 资源管理
  20. 个人网页中嵌入新浪微博

热门文章

  1. win2003桌面图标蓝底去除
  2. iTOP-4418开发板RS85模块ioctl操作时间间隔修改
  3. OMV搭建系列教程[5] – 安装Aria2
  4. 背景音乐默认播放css,可以通过CSS改变背景音乐播放器的颜色吗?
  5. 空军资深战略研究员:房地产支撑不起大国崛起
  6. 全球最最可爱的的10种著名小型犬
  7. FIRST集 FOLLOW集和SELECT集
  8. 远程服务器下载百度网盘中的内容
  9. frp内网穿透疑难杂症【1】do http proxy request [host:www.xxx.xxx] error: no root found: www.xxx.xxx
  10. 阿里云centos 7下kubeadm方式安装kubernetes 1.14.1集群(包含解决墙以及各种坑的问题)