Extended cartoon shading model

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

Обычно cartoon-шейдер использует диффузную освещенность объекта для получения итогового цвета. Простейший пример такого шейдера приводится ниже.

varying	vec3 l;
varying	vec3 h;
varying vec3 v;
varying vec3 n;

void main (void)
{
    const vec4 diffColor = vec4 ( 0.5, 0.0, 0.0, 1.0 );
	
    vec3  n2   = normalize ( n );
    vec3  l2   = normalize ( l );
    float diff = 0.2 + max ( dot ( n2, l2 ), 0.0 );
    vec4  clr;

    if ( diff < 0.4 )
        clr = diffColor * 0.3;
    else
    if ( diff < 0.7 )
        clr = diffColor ;
    else
        clr = diffColor * 1.3;

    gl_FragColor = clr;
}

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

cartoon rendered teapot

Рис 1. Изображение, получаемое при помощи классического cartoon-шейдера

Иногда вместо явного задания нескольких уровней яркости (которым соответствуют определенные цвета) используется одномерная текстура. В этом случае найденное значение диффузной освещенности используется для индексирования в эту текстуру и получения из нее результирующего цвета.

Как легко заметить подобный подход не всегда дает желаемое изображение - довольно часто он оказывается слишком простым и скрывает ряд деталей, которые хочется показать.

Так одним из его недостатков является то, что получаемые при его использовании цвета, не зависят от положения наблюдателя (т.к. диффузное освещенность определяется только углом между нормалью к поверхности и направлением на источник света).

В статье "X-Toon: An Extended Toon Shader" авторами был предложен интересный способ, позволяющий расширить возможности традиционного cartoon-шейдера.

С этой целью вводится дополнительный параметр, влияющий на выбор цвета, - т.н. уровень абстракции (LOA, Level Of Abstraction).

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

На следующем рисунке приведены примеры подобных текстур.

sample textures for shading sample textures for shading sample textures for shading

sample textures for shading sample textures for shading sample textures for shading

sample textures for shading sample textures for shading sample textures for shading

Рис 2. Двухмерные текстуры, используемые при закрашивании объектов.

В качестве уровня абстракции могут выступать самые различные параметры, но мы рассмотрим только несколько простейших случаев.

Использование глубины фрагмента в качестве уровня абстракции

Приведенная глубина объекта (доступная в фрагментном шейдера как gl_FragCoord.z) может выступать в качестве уровня абстракции. Возможно использование не самой глубины, а некоторой ее функции (обычно - линейной), в качестве уровня абстракции.

Такой выбор уровня абстракции позволяет по-разному раскрашивать близко расположенные и удаленные объекты.

Например, можно взять обычную одномерную текстуру, соответствующую классическому cartoon-шейдеру и "вытянуть" ее во второе измерение (превратив в двухмерную текстуру). После этого к это текстуре применяется операция размытия (blur) так, чтобы удаленным объектам соответствовала большая степень размытия, нежели близким.

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

varying	vec3 l;
varying	vec3 h;
varying vec3 v;
varying vec3 n;
uniform sampler2D	toonMap;

void main (void)
{
    vec3  n2   = normalize ( n );
    vec3  l2   = normalize ( l );
    float diff = 0.2 + max ( dot ( n2, l2 ), 0.0 );

    gl_FragColor = texture2D ( toonMap, vec2 ( diff, gl_FragCoord.z ) );
}

extended toon depth-dependent shading

extended toon depth-dependent shading

Рис 3. Изображения, получающиеся при использовании LOA, зависящего от глубины.

Использование бликового освещения в качестве уровня абстракции

В качестве LOA можно также использовать и бликовую освещенность фрагмента (вычисляемую по модели Фонга или Блинна).

Это позволяет получать отчетливые блики на поверхности объекта, сохраняя при этом общий "мультяшный" вид.

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

varying vec3 l;
varying vec3 h;
varying vec3 v;
varying vec3 n;
uniform sampler2D toonMap;

void main (void)
{
    const float	specPower = 10.0;
    
    vec3  n2   = normalize ( n );
    vec3  l2   = normalize ( l );
    vec3  h2   = normalize ( h );
    float diff = 0.2 + max ( dot ( n2, l2 ), 0.0 );
    float spec = pow ( max ( dot ( n2, h2 ), 0.0 ), specPower );

    gl_FragColor = texture2D ( toonMap, vec2 ( diff, spec ) );
}

extended toon specular-dependent shading

extended toon specular-dependent shading

Рис 4. Изображения, получающиеся при использовании LOA, зависящего от бликовой освещенности.

Использование близости к силуэту в качестве уровня абстракции

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

В качестве такого параметра обычно используется следующая величина:

r = pow ( 1.0 - abs ( dot ( n, v ) ), p )

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

Соответствующий шейдер приводится ниже.

varying vec3 l;
varying vec3 h;
varying vec3 v;
varying vec3 n;
uniform sampler2D toonMap;

void main (void)
{
    const float edgePower = 3.0;

    vec3  n2   = normalize ( n );
    vec3  l2   = normalize ( l );
    vec3  h2   = normalize ( h );
    vec3  v2   = normalize ( v );
    float diff = 0.1 + max ( dot ( n2, l2 ), 0.0 );
    float edge = pow ( abs ( dot ( n2, v2 ) ), edgePower );

    gl_FragColor = texture2D ( toonMap, vec2 ( diff, edge ) );
}

На следующих рисунках приводятся получаемые при этом изображения.

extended toon edge-dependent shading

Рис. 5. Изображение, получающееся при использовании LOA, зависящего от близости к силуэту.

По этой ссылке можно скачать весь исходный код к этой статье. Также доступны для скачивания откомпилированные версии для M$ Windows, Linux и Mac OS X.

Valid HTML 4.01 Transitional

Напиши мне
Используются технологии uCoz