[关闭]
@cybercser 2015-11-20T06:36:59.000000Z 字数 1729 阅读 55

第十课:透明

OpenGL 教程

alpha通道

alpha通道的概念很简单。我们以前的计算结果是RGB值,现在则是RGBA值:

  1. // Ouput data : it's now a vec4
  2. out vec4 color;

前三个分量仍可以通过重组操作符(swizzle operator).xyz访问,最后一个分量通过.a访问:

  1. color.a = 0.3;

与直觉相反,alpha代表的是不透明度;因此alpha = 1代表完全不透明,alpha = 0为完全透明。

这里我们简单地将alpha硬编码为0.3;但更常见的做法是用一个uniform变量表示它,或从RGBA纹理中读取(TGA格式支持alpha通道,而GLFW支持TGA格式)。

结果如下。既然我们能“看透”模型表面,请确保关闭背面剔除(glDisable(GL_CULL_FACE))。否则我们就发现模型没有了“背”面。

transparencyok

顺序很重要!

上一个截图看上去还行,但这仅仅是运气好罢了。

问题所在

这里我画了一红一绿两个alpha值为50%的正方形。从中可以看出顺序的重要性,最终的颜色显著影响了眼睛对深度的感知。

transparencyorder

我们的场景中也出现了同样的现象。试着稍稍改变一下观察点:

原来这还是个十分棘手的问题。您在游戏中也没怎么见过透明的东西,是吧?

常见解决方案

常见解决方案即对所有的透明三角形排序。是的,所有的透明三角形。

可以用C语言的qsort函数或者C++的std::sort函数来排序。细节就不多说了,因为……

警告

这么做可以解决问题(下一节还会介绍它),但是:

一个足够好的解决方案是:

顺序无关透明

如果您的引擎确实需要顶级的透明效果,这里有一些值得研究的技术:

注意,即便是《小小大星球》(Little Big Planet)这种刚出炉的、运行在高端主机上的游戏,也只用了一层透明。

混合函数

要让上述代码运行起来,得设置好混合函数。

  1. // Enable blending
  2. glEnable(GL_BLEND);
  3. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

这意味着

New color in framebuffer = 
           current alpha in framebuffer * current color in framebuffer + 
           (1 - current alpha in framebuffer) * shader's output color

上图红色方块居上的效果由如下等式得来:

new color = 0.5*(0,1,0) + (1-0.5)*(1,0.5,0.5); // (the red was already blended with the white background)
new color = (1, 0.75, 0.25) = the same orange

© http://www.opengl-tutorial.org/

Written with Cmd Markdown.

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注