GLSL 编程/Blender/独立于顺序的透明度
本教程涵盖 **独立于顺序的混合**。
它继续讨论 关于透明度的教程,并解决了标准透明度的一些问题。如果您还没有阅读过该教程,建议您先阅读。
正如 关于透明度的教程 中所述,混合的结果通常(特别是对于标准 alpha 混合)取决于三角形渲染的顺序,因此如果三角形没有从后到前排序(通常不会),就会导致渲染伪像。术语“独立于顺序的透明度”描述了各种避免此问题的技术。其中一项技术是独立于顺序的混合,即使用不依赖于三角形光栅化顺序的混合方程。有两种基本可能性:叠加混合和相乘混合。
叠加混合的标准示例是本页中的双重曝光:颜色被叠加,因此无法(或至少很难)说出照片拍摄的顺序。叠加混合可以用 关于透明度的教程 中介绍的混合方程来表征
vec4 result = SrcFactor * gl_FragColor + DstFactor * pixel_color;
其中 SrcFactor
和 DstFactor
由 Blender 的 Python API 函数设置
bge.types.KX_BlenderMaterial.setBlending(
{code for SrcFactor
},{code for DstFactor
})
对于叠加混合,DstFactor
的代码必须为 bge.logic.BL_ONE
,而 SrcFactor
的代码不能依赖于帧缓冲区中的像素颜色;也就是说,它可以是 bge.logic.BL_ONE
、bge.logic.BL_SRC_COLOR
、bge.logic.BL_SRC_ALPHA
、bge.logic.BL_ONE_MINUS_SRC_COLOR
或 bge.logic.BL_ONE_MINUS_SRC_ALPHA
。
示例如下
import bge
cont = bge.logic.getCurrentController()
VertexShader = """
void main()
{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
"""
FragmentShader = """
void main()
{
gl_FragColor = vec4(1.0, 0.0, 0.0, 0.3);
}
"""
mesh = cont.owner.meshes[0]
for mat in mesh.materials:
shader = mat.getShader()
if shader != None:
if not shader.isValid():
shader.setSource(VertexShader, FragmentShader, 1)
mat.setBlending(bge.logic.BL_SRC_ALPHA, bge.logic.BL_ONE)
请记住,您必须在 **3D 视图** 菜单中将 **视口着色** 设置为 **纹理** 以激活混合。此外,您还应该激活 **Z 透明度** 并停用 **背面剔除**,如 关于透明度的教程 中所述。
摄影中相乘混合的一个示例是使用多个均匀的灰色滤镜:滤镜叠加到相机上的顺序对图像的最终衰减没有影响。就三角形的光栅化而言,图像对应于三角形光栅化之前帧缓冲区的内容,而滤镜对应于三角形。
在 Python 中使用以下代码指定相乘混合
bge.types.KX_BlenderMaterial.setBlending(
{code for SrcFactor
},{code for DstFactor
})
SrcFactor
的代码必须为 bge.logic.BL_ZERO
,而 DstFactor
的代码必须依赖于片段颜色;也就是说,它可以是 bge.logic.BL_SRC_COLOR
、bge.logic.BL_SRC_ALPHA
、bge.logic.BL_ONE_MINUS_SRC_COLOR
或 bge.logic.BL_ONE_MINUS_SRC_ALPHA
。使用 bge.logic.BL_ONE_MINUS_SRC_ALPHA
作为 DstFactor
的代码,可以衰减由片段的 alpha 分量指定的背景,这是一种典型的示例。
import bge
cont = bge.logic.getCurrentController()
VertexShader = """
void main()
{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
"""
FragmentShader = """
void main()
{
gl_FragColor = vec4(1.0, 0.0, 0.0, 0.3);
}
"""
mesh = cont.owner.meshes[0]
for mat in mesh.materials:
shader = mat.getShader()
if shader != None:
if not shader.isValid():
shader.setSource(VertexShader, FragmentShader, 1)
mat.setBlending(bge.logic.BL_ZERO,
bge.logic.BL_ONE_MINUS_SRC_ALPHA)
恭喜您,您已经完成了本教程。我们已经了解了以下内容:
- 什么是独立于顺序的透明度和独立于顺序的混合。
- 两种最重要的独立于顺序的混合类型是什么(叠加和相乘)。
- 如何实现叠加和相乘混合。
如果您想了解更多
- 关于着色器代码的信息,请阅读 关于透明度的教程.
- 关于另一种独立于顺序的透明度技术,即深度剥离,您可以阅读 Cass Everitt 的技术报告:“交互式独立于顺序的透明度”,该报告可以在 网上 获取。