Version: 2019.4
ShaderLab: Legacy Texture Combiners
Синтаксис ShaderLab: туман

Синтакс ShaderLab: Альфа тестинг (Alpha testing)

Процесс альфа тестинга — это последний шанс проверить, будет ли пиксель отрисован на экране.

Note: AlphaTest commands have no effect when fragment programs are used; on most platforms alpha testing is done in the shader using HLSL clip() function. It is advisable to use programmable shaders these days instead of SetTexture commands.

После вычисления конечного значения цвета пикселя, можно дополнительно сравнить значение его альфа канала с заранее определенным значением. Если пиксель не проходит этот тест, он не будет выведен на экран.

Синтаксис

AlphaTest Off

Отрисовка всех пикселей (по умолчанию) или…

AlphaTest comparison AlphaValue

Настроить процесс альфа тестинга, чтобы отрисовывались только пиксели, значение альфа канала которых попадает в определенный диапазон.

Сравнение

Вместо слова comparison нужно поставить одно из следующих:

Greater Отрисовывать только пиксели, значение которых строго больше значения AlphaValue.
GEqual Отрисовывать только пиксели, значение которых больше или равно значению AlphaValue.
Less Отрисовывать только пиксели, значение которых строго меньше значения AlphaValue.
LEqual Отрисовывать только пиксели, значение которых меньше или равно значению AlphaValue.
Equal Отрисовывать только пиксели, значение которых равно значению AlphaValue.
NotEqual Отрисовывать только пиксели, значение которых не равно значению AlphaValue.
Always Отрисовывать все пиксели. Функциональный эквивалент AlphaTest Off.
Never Не отрисовывать пиксели.

AlphaValue

Число с плавающей точкой в диапазоне от 0 до 1. Это значение также можно определить как переменную из свойства float или range. В этом случае имя переменной нужно писать с использованием обычной нотации с квадратными скобками ([VariableName]).

Детали

Альфа тест часто используется при отрисовке не выпуклых объектов с прозрачными элементами. Графическая карта хранит значение глубины каждого пикселя, выводимого на экран. Если новый пиксель находится дальше от камеры, чем тот, что уже был отрисован, он не выводится на экран. В этом случае даже с Blending объект не будет просвечивать.

На этом рисунке дерево слева отрисовано с использованием AlphaTest. Обратите внимание, что пиксели либо полностью прозрачны, либо полностью непрозрачны. Дерево в центре отрисовано с использованием Alpha Blending. Из-за буфера глубины, прозрачные части ближайших к камере веток перекрывают ветки, которые находятся дальше. Дерево справа отрисовано с помощью шейдера, описанного ниже. Он реализован с помощью комбинации альфа тестинга и блендинга, что позволяет полностью избавиться от артефактов.

Примеры

Простейший пример — присвойте объекту текстуру с альфа каналом. Объект будет видимым только в тех местах, где значение альфа канала текстуры будет больше 0.5.

Shader "Simple Alpha Test" {
    Properties {
        _MainTex ("Base (RGB) Transparency (A)", 2D) = "" {}
    }
    SubShader {
        Pass {
            // Only render pixels with an alpha larger than 50%
            AlphaTest Greater 0.5
            SetTexture [_MainTex] { combine texture }
        }
    }
}

Сам по себе шейдер не очень полезен. Нужно добавить освещение и позволить пользователю настраивать значение отсечения по альфа каналу:

Shader "Cutoff Alpha" {
    Properties {
        _MainTex ("Base (RGB) Transparency (A)", 2D) = "" {}
        _Cutoff ("Alpha cutoff", Range (0,1)) = 0.5
    }
    SubShader {
        Pass {
            // Use the Cutoff parameter defined above to determine
            // what to render.
            AlphaTest Greater [_Cutoff]
            Material {
                Diffuse (1,1,1,1)
                Ambient (1,1,1,1)
            }
            Lighting On
            SetTexture [_MainTex] { combine texture * primary }
        }
    }
}

Во многих играх, при отрисовке деревьев и травы можно увидеть резкие границы. Это характерно для альфа тестинга. Однако можно обойти это ограничение, отрисовав объект в два подхода (пасса). При первой отрисовке с помощью альфа тестинга отсекаются пиксели, значение альфа канала которых меньше 0.5. При второй отрисовке используется блендинг для тех частей, которые были отсечены, без запоминания значения глубины пикселя. При таком подходе более дальние ветки могут быть отрисованы поверх ближних, но на практике это сложно заметить, поскольку листья обычно состоят из большого количества мелких деталей.

Shader "Vegetation" {
    Properties {
        _Color ("Main Color", Color) = (.5, .5, .5, .5)
        _MainTex ("Base (RGB) Alpha (A)", 2D) = "white" {}
        _Cutoff ("Base Alpha cutoff", Range (0,.9)) = .5
    }
    SubShader {
        // Set up basic lighting
        Material {
            Diffuse [_Color]
            Ambient [_Color]
        }
        Lighting On

        // Render both front and back facing polygons.
        Cull Off

        // first pass:
        // render any pixels that are more than [_Cutoff] opaque
        Pass {
            AlphaTest Greater [_Cutoff]
            SetTexture [_MainTex] {
                combine texture * primary, texture
            }
        }

        // Second pass:
        // render in the semitransparent details.
        Pass {
            // Dont write to the depth buffer
            ZWrite off
            // Don't write pixels we have already written.
            ZTest Less
            // Only render pixels less or equal to the value
            AlphaTest LEqual [_Cutoff]

            // Set up alpha blending
            Blend SrcAlpha OneMinusSrcAlpha

            SetTexture [_MainTex] {
                combine texture * primary, texture
            }
        }
    }
}

Стоит отметить, что в данном случае настройки материалов заданы в SubShader, а не в отдельных пассах. Это позволяет пассам наследовать текущие настройки в SubShader как значения по умолчанию.

ShaderLab: Legacy Texture Combiners
Синтаксис ShaderLab: туман