ShaderLab 语法:纹理组合器 (Texture Combiners)

基础顶点光照经计算后可应用纹理。在 ShaderLab 中,这是通过使用 设置纹理 (SetTexture) 命令完成的。

当使用片元程序时,SetTexture 命令无效;因为在此情况下,像素操作在着色器中被全部描述。

贴图 (Texturing) 可以用来实现老风格的组合器效果。在一个通道中可使用多个 SetTexture 命令 - 所有纹理都按顺序应用,如同绘图程序中的图层一样。SetTexture 命令必须放置在通道的末尾。

Syntax

SetTexture [TexturePropertyName] { Texture Block }
分配纹理。必须将 TextureName 定义为纹理属性。TextureBlock 中定义了如何应用纹理。

纹理块控制如何应用纹理。纹理块中有三种命令:combinematrixconstantColor.

纹理块 combine 命令

combine src1 * src2
将 src1 和 src2 相乘。结果比会比单独输入任何一个都要暗。
combine src1 + src2
将 src1 和 src2 相加。结果比会比单独输入任何一个都要亮。
combine src1 - src2
src1 减去 src2。
combine src1 +- src2
src1 加 src2,然后减去 0.5(带正负号的加法)。
combine src1 lerp (src2) src3
使用 src2 的 alpha 在 src3 和 src1 之间进行插值。注意插值是反向的:当 alpha 是 1 时使用 src1,alpha 为 0 时使用 src3。
combine src1 * src2 + src3
将 src1 与 src2 的 alpha 分量相乘,然后加上 src3。
combine src1 * src2 +- src3
将 src1 与 src2 的 alpha 分量相乘,然后加上带正负号的 src3。
combine src1 * src2 - src3
将 src1 与 src2 的 alpha 分量相乘,然后减去 src3。

所有的 src 属性可以是前一个 (previous)不变 (constant)主要 (primary) 或者纹理 (texture)中的一个。

修改器:

纹理块 constantColor 命令

ConstantColor color
定义一个可以在组合命令中使用的不变色。

纹理块 matrix 命令

matrix [MatrixPropertyName]
使用给定矩阵变换该命令中使用的纹理坐标。

详细信息

片元程序出现前,较老的显卡对纹理使用分层方案。逐个应用纹理,以修改写到屏幕的颜色。一般来说,每一个纹理都与上一次操作结果相组合。

请注意,在“真正实固定功能”设备(OpenGL、OpenGL ES 1.1、Wii)上,每个 SetTexture 阶段的值被限制在 0..1 范围内。在别处 (Direct3D、OpenGL ES 2.0),该范围可能会更高,但也可能不会。这可能会影响能产生的值高于 1.0 的 SetTexture 阶段。

独立的 Alpha 和颜色计算

默认情况下,组合器公式用于计算颜色的 RGB 和 alpha 分量。另外,您可以为 alpha 计算指定一个单独的公式。如下所示:

SetTexture [_MainTex] { combine previous * texture, previous + texture }

我们对 RGB 颜色做乘法运算并对 alpha 做加法运算。

高光亮点

默认情况下,primary 颜色是散射光、环境光和反射光颜色(如光照计算中定义的)的总和。如果您在通道选项中指定 SeparateSpecular On,则反射光颜色将在组合器计算之后(而不是之前)被加入。这就是内置顶点光照 (VertexLit) 着色器的默认行为。

图形硬件支持

片元着色器支持(桌面平台上为“shader model 2.0”,移动平台上为 OpenGL ES 2.0)的现代显卡支持所有 SetTexture 模式,而且至少是 4 个纹理阶段(其中很多支持 8 个)。如果在比较老的硬件上运行(2003 年前的 PC,或 iPhone3GS 之前的移动设备),您应该有 2 个纹理阶段得到支持。着色器的制作者应该会为他或她想要支持的显卡编写独立的子着色器

示例

混合两种纹理的 Alpha

这个小示例采用两种纹理。首先,Alpha 使第一个组合器只采用 _MainTex,然后使用 _BlendTex 的 alpha 通道淡入 _BlendTex 的 RGB 颜色

Shader "Examples/2 Alpha Blended Textures" {
    Properties {
        _MainTex ("Base (RGB)", 2D) = "white" {}
        _BlendTex ("Alpha Blended (RGBA) ", 2D) = "white" {}
    }
    SubShader {
        Pass {
            // 应用基础纹理
            SetTexture [_MainTex] {
                combine texture
            }
            // 使用 lerp 操作符混合 alpha 纹理
            SetTexture [_BlendTex] {
                combine texture lerp (texture) previous
            }
        }
    }
} 

Alpha 控制的自发光

此着色器使用 _MainTex 的 alpha 分量来决定在何处应用光照。通过两个阶段应用纹理来实现;在第一个阶段,使用纹理的 alpha 值在顶点颜色和纯白色之间进行调和。第二个阶段,乘以纹理的 RGB 值。

Shader "Examples/Self-Illumination" {
    Properties {
        _MainTex ("Base (RGB) Self-Illumination (A)", 2D) = "white" {}
    }
    SubShader {
        Pass {
            // 设置基础白色顶点光照
            Material {
                Diffuse (1,1,1,1)
                Ambient (1,1,1,1)
            }
            Lighting On

            // 使用纹理 alpha 调和至白色(= 完全发光)
            SetTexture [_MainTex] {
                constantColor (1,1,1,1)
                combine constant lerp(texture) previous
            }
            // 乘以纹理
            SetTexture [_MainTex] {
                combine previous * texture
            }
        }
    }
} 

我们还可以在这里做点别的事情,除了混合至纯白色,我们还能添加自发光颜色然后再混合至纯白色。使用 ConstantColor 从属性获取 _SolidColor 并应用到纹理混合中时要注意。

Shader "Examples/Self-Illumination 2" {
    Properties {
        _IlluminCol ("Self-Illumination color (RGB)", Color) = (1,1,1,1)
        _MainTex ("Base (RGB) Self-Illumination (A)", 2D) = "white" {}
    }
    SubShader {
        Pass {
            // 设置基础白色顶点光照
            Material {
                Diffuse (1,1,1,1)
                Ambient (1,1,1,1)
            }
            Lighting On

            // 使用纹理 alpha 调和至白色(= 完全发光)
            SetTexture [_MainTex] {
                // 将颜色属性拉至该混合器中
                constantColor [_IlluminCol]
                // 并且使用纹理的 alpha 在纹理和
                // 顶点颜色之间混合
                combine constant lerp(texture) previous
            }
            // 乘以纹理
            SetTexture [_MainTex] {
                combine previous * texture
            }
        }
    }
} 

最后,我们采用顶点光照着色器的所有的光照属性并将其拉入:

Shader "Examples/Self-Illumination 3" {
    Properties {
        _IlluminCol ("Self-Illumination color (RGB)", Color) = (1,1,1,1)
        _Color ("Main Color", Color) = (1,1,1,0)
        _SpecColor ("Spec Color", Color) = (1,1,1,1)
        _Emission ("Emmisive Color", Color) = (0,0,0,0)
        _Shininess ("Shininess", Range (0.01, 1)) = 0.7
        _MainTex ("Base (RGB)", 2D) = "white" {}
    }

    SubShader {
        Pass {
            // 设置基础顶点光照
            Material {
                Diffuse [_Color]
                Ambient [_Color]
                Shininess [_Shininess]
                Specular [_SpecColor]
                Emission [_Emission]
            }
            Lighting On

            // 使用纹理 alpha 调和至白色(= 完全发光)
            SetTexture [_MainTex] {
                constantColor [_IlluminCol]
                combine constant lerp(texture) previous
            }
            // 乘以纹理
            SetTexture [_MainTex] {
                combine previous * texture
            }
        }
    }
} 

Page last updated: 2013-06-28