第08课 OpenGL 混合
混合:
在这一课里,我们在纹理的基础上加上了混合,它看起具有透明的效果,当然解释它不是那么容易,当希望你喜欢它。
简单的透明
OpenGL中的绝大多数特效都与某些类型的(色彩)混合有关。混色的定义为,将某个象素的颜色和已绘制在屏幕上与其对应的象素颜色相互结合。至于如何结合这两个颜色则依赖于颜色的alpha通道的分量值,以及/或者所使用的混色函数。Alpha通常是位于颜色值末尾的第4个颜色组成分量。前面这些课我们都是用GL_RGB来指定颜色的三个分量。相应的GL_RGBA可以指定alpha分量的值。更进一步,我们可以使用glColor4f()来代替glColor3f()。
绝大多数人都认为Alpha分量代表材料的透明度。这就是说,alpha值为0.0时所代表的材料是完全透明的。alpha值为1.0时所代表的材料则是完全不透明的。
混色的公式 若您对数学不感冒,而只想看看如何实现透明,请跳过这一节。若您想深入理解(色彩)混合的工作原理,这一节应该适合您吧。『译者注:其实并不难^-^。原文中的公式如下,CKER再唠叨一下吧。其实混合的基本原理是就将要分色的图像各象素的颜色以及背景颜色均按照RGB规则各自分离之后,根据-图像的RGB颜色分量*alpha值+背景的RGB颜色分量*(1-alpha值)-这样一个简单公式来混合之后,最后将混合得到的RGB分量重新合并。』 公式如下: (Rs Sr + Rd Dr, Gs Sg + Gd Dg, Bs Sb + Bd Db, As Sa + Ad Da) OpenGL按照上面的公式计算这两个象素的混色结果。小写的s和r分别代表源象素和目标象素。大写的S和D则是相应的混色因子。这些决定了您如何对这些象素混色。绝大多数情况下,各颜色通道的alpha混色值大小相同,这样对源象素就有 (As, As, As, As),目标象素则有1, 1, 1, 1) - (As, As, As, As)。上面的公式就成了下面的模样: (Rs As + Rd (1 - As), Gs As + Gd (1 - As), Bs As + Bs (1 - As), As As + Ad (1 - As)) 这个公式会生成透明/半透明的效果。
OpenGL中的混色 在OpenGL中实现混色的步骤类似于我们以前提到的OpenGL过程。接着设置公式,并在绘制透明对象时关闭写深度缓存。因为我们想在半透明的图形背后绘制 对象。这不是正确的混色方法,但绝大多数时候这种做法在简单的项目中都工作的很好。 Rui Martins 的补充: 正确的混色过程应该是先绘制全部的场景之后再绘制透明的图形。并且要按照与深度缓存相反的次序来绘制(先画最远的物体)。 考虑对两个多边形(1和2)进行alpha混合,不同的绘制次序会得到不同的结果。(这里假定多边形1离观察者最近,那么正确的过程应该先画多边形2,再画多边形1。正如您再现实中所见到的那样,从这两个<透明的>多边形背后照射来的光线总是先穿过多边形2,再穿过多边形1,最后才到达观察者的眼睛。) 在深度缓存启用时,您应该将透明图形按照深度进行排序,并在全部场景绘制完毕之后再绘制这些透明物体。否则您将得到不正确的结果。我知道某些时候这样做是很令人痛苦的,但这是正确的方法。 我们将使用第七课的代码。一开始先在代码开始处增加两个新的变量。出于清晰起见,我重写了整段代码。
bool blend; // 是否混合? bool bp; // B 键按下了么?
然后往下移动到 LoadGLTextures() 这里。找到" if (TextureImage[0]=LoadBMP("Data/Crate.bmp")) "这一行。我们现在使用有色玻璃纹理来代替上一课中的木箱纹理。
if (TextureImage[0]=LoadBMP("Data/glass.bmp")) // 载入玻璃位图
在InitGL()代码段加入以下两行。第一行以全亮度绘制此物体,并对其进行50%的alpha混合(半透明)。当混合选项打开时,此物体将会产生50%的透明效果。第二行设置所采用的混合类型。
Rui Martins 的补充: alpha通道的值为 0.0意味着物体材质是完全透明的。1.0 则意味着完全不透明。
glColor4f(1.0f,1.0f,1.0f,0.5f); // 全亮度, 50% Alpha 混合 glBlendFunc(GL_SRC_ALPHA,GL_ONE); // 基于源象素alpha通道值的半透明混合函数
在接近第七课结尾处的地方找到下面的代码段。
if (keys[VK_LEFT]) // Left方向键按下了么?
{
yspeed-=0.01f; // 若是, 减少yspeed
}
接着上面的代码,我们增加如下的代码。这几行监视B键是否按下。如果是的话,计算机检查混合选项是否已经打开。然后将其置为相反的状态。
if (keys['B'] && !bp) // B 健按下且bp为 FALSE么?
{
bp=TRUE; // 若是, bp 设为 TRUE blend = !blend; // 切换混合选项的 TRUE / FALSE if(blend) // 混合打开了么?
{
glEnable(GL_BLEND); // 打开混合 glDisable(GL_DEPTH_TEST); // 关闭深度测试
}
else // 否则
{
glDisable(GL_BLEND); // 关闭混合 glEnable(GL_DEPTH_TEST); // 打开深度测试
}
}
if (!keys['B']) // B 键松开了么?
{
bp=FALSE; // 若是, bp设为 FALSE
}
但是怎样才能在使用纹理贴图的时候指定混合时的颜色呢?很简单,在调整贴图模式时,文理贴图的每个象素点的颜色都是由alpha通道参数与当前地象素颜色相乘所得到的。比如,绘制的颜色是 (0.5, 0.6, 0.4),我们会把颜色相乘得到(0.5, 0.6, 0.4, 0.2) (alpha参数在没有指定时,缺省为零)。 就是如此!OpenGL实现Alpha混合的确很简单!
原文注 (11/13/99) 我(NeHe)混色代码进行了修改,以使显示的物体看起来更逼真。同时对源象素和目的象素使用alpha参数来混合,会导致物体的人造痕迹看起来很明显。 会使得物体的背面沿着侧面的地方显得更暗。基本上物体会看起来很怪异。我所用的混色方法也许不是最好的,但的确能够工作。启用光源之后,物体看起来很逼真。感谢Tom提供的原始代码,他采用的混色方法是正确的,但物体看起来并不象所期望的那样吸引人:) 代码所作的再次修改是因为在某些显卡上glDepthMask()函数存在寻址问题。这条命令在某些卡上启用或关闭深度缓冲测试时似乎不是很有效,所以我已经将启用或关闭深度缓冲测试的代码转成老式的glEnable和glDisable。
纹理贴图的Alpha混合 用于纹理贴图的alpha参数可以象颜色一样从问题贴图中读取。方法如下,您需要在载入所需的材质同时取得其的alpha参数。然后在调用glTexImage2D()时使用GL_RGBA的颜色格式。
第08课 OpenGL 混合的更多相关文章
- OpenGL———混合的基本知识
混合是一种常用的技巧,通常可以用来实现半透明.但其实它也是十分灵活的,你可以通过不同的设置得到不同的混合结果,产生一些有趣或者奇怪的图象.混合是什么呢?混合就是把两种颜色混在一起.具体一点,就是把某一 ...
- (转)OpenGL混合的基本知识
今天介绍关于OpenGL混合的基本知识.混合是一种常用的技巧,通常可以用来实现半透明.但其实它也是十分灵活的,你可以通过不同的设置得到不同的混合结果,产生一些有趣或者奇怪的图象. 混合是什么呢?混合就 ...
- Qt移动应用开发(八):实现跨平台的QML和OpenGL混合渲染
Qt移动应用开发(八):实现跨平台的QML和OpenGL混合渲染 上一篇文章讲到了利用C++这个桥梁,我们实现了QML和Java的交互.Qt 5大力推崇的QML/JS开发,让轻量.高速开发的QML/J ...
- CUDA+OpenGL混合编程
CUDA+OpenGL混合编程示例: #include <stdio.h> #include <stdlib.h> #include "GL\glew.h" ...
- NeHe OpenGL教程 第八课:混合
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- 第11课 OpenGL 飘动的旗帜
飘动的旗帜: 这一课从第六课的代码开始,创建一个飘动的旗帜.我相信在这课结束的时候,你可以掌握纹理映射和混合操作. 大家好!对那些想知道我在这里作了些什么的朋友,您可以先按文章的末尾所列出的链接,下载 ...
- 第09课 OpenGL 移动图像
3D空间中移动图像: 你想知道如何在3D空间中移动物体,你想知道如何在屏幕上绘制一个图像,而让图像的背景色变为透明,你希望有一个简单的动画.这一课将教会你所有的一切.前面的课程涵盖了基础的OpenGL ...
- 第05课 OpenGL 3D空间
3D空间: 我们使用多边形和四边形创建3D物体,在这一课里,我们把三角形变为立体的金子塔形状,把四边形变为立方体. 在上节课的内容上作些扩展,我们现在开始生成真正的3D对象,而不是象前两节课中那样3D ...
- 第03课 OpenGL 添加颜色
添加颜色: 作为第二课的扩展,我将叫你如何使用颜色.你将理解两种着色模式,在下图中,三角形用的是光滑着色,四边形用的是平面着色 上一课中我教给您三角形和四边形的绘制方法.这一课我将教您给三角形和四边形 ...
随机推荐
- 密码学系列之:Argon2加密算法详解
目录 简介 密钥推导函数key derivation function Password Hashing Competition Argon2算法 Argon2的输入参数 处理流程 简介 Argon2 ...
- PHP的Hash信息摘要扩展框架
今天我们主要学习的是 PHP 中一些 Hash 散列加密相关的扩展函数的使用,而不是 Hash 算法,这种加密其实也只是一种更复杂一些的密钥算法,与 Hash 算法类似的是,我们输入的一串字符串,就像 ...
- Shell系列(4)- 历史命令
格式:history [选项] [历史命令保存文件] 选项: -c:清空历史命令 -w:把缓存中的历史命令写入到历史命令保存文件~ /.bash_history;用户的家目录下 例子: [root@l ...
- javascript 分时函数 分批次添加DOM节点 timeChunk
创建1000个webqq的qq好友列表, 一个好友用一个节点来表示 * timeChunk var timeChunk = function(a, fn, sz, done) { var obj, t ...
- 鸿蒙内核源码分析(寄存器篇) | 小强乃宇宙最忙存储器 | 百篇博客分析OpenHarmony源码 | v38.02
百篇博客系列篇.本篇为: v38.xx 鸿蒙内核源码分析(寄存器篇) | 小强乃宇宙最忙存储器 | 51.c.h .o 硬件架构相关篇为: v22.xx 鸿蒙内核源码分析(汇编基础篇) | CPU在哪 ...
- windows kubectl 远程操作k8s
在windows 电脑上配置kubectl远程操作kubernetes 一.下载windows版的kubectl可执行文件 下载地址 二.创建.kube 建议使用git bash cd ~ mkdir ...
- Mysql explain中key_len的作用及计算规则
key_len表示索引使用的字节数,根据这个值可以判断索引的使用情况,特别是在组合索引的时候,判断该索引有多少部分被使用到非常重要. 在计算key_len时,下面是一些需要考虑的点: 索引字段的附加信 ...
- Apache Struts2 S2-013远程代码执行漏洞复现
墨者学院开的靶场 进入环境 Struts2-013好家伙,框架直接写脸上,怕人看不出来= = 看了看源码什么的啥都没发现= = 去了解了一下这个漏洞,爬回来继续做 漏洞原理 struts2的标签中&l ...
- MySQL where子句的使用
MySQL WHERE 子句 我们知道从 MySQL 表中使用 SQL SELECT 语句来读取数据. 如需有条件地从表中选取数据,可将 WHERE 子句添加到 SELECT 语句中. 语法 以下是 ...
- iframe、SameSite与CEF
iframe.SameSite与CEF 背景 本人使用CEF(或是Chrome)来加载开发的前端页面,其中使用iframe嵌入了第三方页面,在第三方页面中需要发送cookie到后端,然而加载会报错,第 ...