第十课:透明 === alpha通道 alpha通道的概念很简单。之前是写RGB结果,现在改为写RGBA: 前三个分量仍可以通过混合操作符(swizzle operator).xyz访问,最后一个分量通过.a访问: 不太直观,但alpha = 不透明度;因此alpha = 1代表完全不透明,alpha = 0为完全透明。 这里我们简单地将alpha硬编码为0.3;但更常见的做法是用一个uniform变量表示它,或从RGBA纹理中读取(TGA格式支持alpha通道,而GLFW支持TGA)。 结果如下。既然我们能“看透”模型表面,请确保关闭隐面消除( )。否则就发现模型没有了“背”面。 transparencyok-1024x793 顺序很重要! 上一个截图看上去还行,但这仅仅是运气好罢了。
alpha通道的概念很简单。之前是写RGB结果,现在改为写RGBA:
// Ouput data : it's now a vec4 out vec4 color;
前三个分量仍可以通过混合操作符(swizzle operator).xyz访问,最后一个分量通过.a访问:
color.a = 0.3;
不太直观,但alpha = 不透明度;因此alpha = 1代表完全不透明,alpha = 0为完全透明。
这里我们简单地将alpha硬编码为0.3;但更常见的做法是用一个uniform变量表示它,或从RGBA纹理中读取(TGA格式支持alpha通道,而GLFW支持TGA)。
结果如下。既然我们能“看透”模型表面,请确保关闭隐面消除(glDisable(GL_CULL_FACE) )。否则就发现模型没有了“背”面。
上一个截图看上去还行,但这仅仅是运气好罢了。
###问题所在###
这里我画了一红一绿两个alpha值为50%的正方形。从中可以看出顺序的重要性,最终的颜色显著影响了眼睛对深度的感知。

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

事实证明这个问题十分棘手。游戏中透明的东西不多,对吧?
###常见解决方案###
常见解决方案即对所有的透明三角形排序。是的,所有的透明三角形。
可以用C语言的qsort函数或者C++的std::sort函数来排序。细节就不多说了,因为……
###警告###
这么做可以解决问题(下一节还会介绍它),但:
一个足够好的解决方案是:
###顺序无关透明
如果你的引擎确实需要顶尖的透明效果,这有一些技术值得研究一番:
注意,即便是《小小大星球》(Little Big Planet)这种最新的端游,也只用了一层透明。
要让之前的代码运行,得设置好混合函数。In order for the previous code to work, you need to setup your blend function.
// Enable blending glEnable(GL_BLEND); 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