Главная » Статьи » » -=Програмирование=-

Уроки по програмированию в С+ OpenGL_GLSL часть пятая.
\-Базовые знания
    \- Шейдеры
        \-Урок5: Вершинный шейдер

Урок5: Вершинный шейдер

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

Примечание1: вопреки распространенному мнению, операция интерполяции зачастую не является
линейной, поэтому в ряде случаев приходится переносить многие вычисления в
пиксельный шейдер. Это связано с тем, что система координат при наличии перспективы
не является ортогональной, и в ней не выполняется линейность векторных операций.

Примечание2: вершинный шейдер обрабатывает вершины до отсечения их областью видимости,
так что избежание обработки лишних вершин лежит целиком на программисте. Это сделано в
связи с тем, что OpenGL заранее неизвестно, попадет ли вершина в область отсечения
после трансформаций в вершинном шейдере.

Вот пример простого вершинного шейдера:

void main(void)
{
    gl_Position     = gl_ModelViewProjectionMatrix * gl_Vertex;
    gl_TexCoord [0] = gl_TextureMatrix * gl_MultiTexCoord0;
}

gl_TexCoord [0...7] это заранее заданные varying (?) переменные, которые используются
для передачи обработанных текстурных координат в пиксельный шейдер.
Довольно часто не требуется трансформация текстурных координат(при текстурной матрицы, равной матрице идентичности), поэтому в таких случаях их стоит передавать без трансформации. Например, при отрисовке травы желательно избежать лишних операций.

gl_TexCoord [0] = gl_MultiTexCoord0;

Пример шейдера для просчета освещенности направленного источника:

uniform vec3 LightDir; //переданный шейдеру извне вектор направления источника света
varying float Light; //эту переменную мы передаем на пиксельный шейдер

void main(void)
{
    Light=max(0.0,dot(gl_NormalMatrix *gl_Normal,LightDir);
    gl_Position     = gl_ModelViewProjectionMatrix * gl_Vertex;
    gl_TexCoord [0] = gl_TextureMatrix * gl_MultiTexCoord0;
}

Теперь, объявив в пиксельном шейдере varying float Light; можно использовать интерполированное
значение освещения (для направленного источника это значение будет точным).

Еще один простой пример:

uniform float time; //время, передаваемое шейдеру программой

void main(void)
{
    vec4 pos_delta=vec3(0.0,2.5*sin(time),0.0,0.0);
    gl_Position     = gl_ModelViewProjectionMatrix * (gl_Vertex+pos_delta);
    gl_TexCoord [0] = gl_MultiTexCoord0;
}

В результате этого примера получим колебание всех вершин по оси y

А в этом примере фаза колебания будет зависеть еще и от координаты x

uniform float time; //время, передаваемое шейдеру программой

void main(void)
{
    vec4 pos_delta=vec3(0.0,2.5*sin(time+gl_Vertex.x*5.0),0.0,0.0);
    gl_Position     = gl_ModelViewProjectionMatrix * (gl_Vertex+pos_delta);
    gl_TexCoord [0] = gl_MultiTexCoord0;
}

Результат можно использовать для колблющихся на ветру флагов.

Это лишь общие принципы работы с вершинным шейдером, в следующих уроках будут
рассмотренны и более интерестные примеры.



Источник:
Категория: -=Програмирование=- | Добавил: spirit (15.08.2008) | Автор:
Просмотров: 1309 | Комментарии: 2 | Рейтинг: 0.0/0 |

Всего комментариев: 0

Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]

Форма входа

Категории каталога
-=SEO=- [8]
Раскрутка сайта в поисковиках
-=Дизайн=- [3]
Статьи по дизайну
-=CMS=- [3]
Статьи по работе с CMS
-=Програмирование=- [7]
Статьи по WEB и OS програмированию

Поиск