<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/css" href="http://wiki2.linuxformat.ru/skins/common/feed.css?97"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
	<channel>
		<title>LXF109:Игрострой - История изменений</title>
		<link>http://wiki2.linuxformat.ru/index.php?title=LXF109:%D0%98%D0%B3%D1%80%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B9&amp;action=history</link>
		<description>История изменений этой страницы в вики</description>
		<language>ru</language>
		<generator>MediaWiki 1.11.1</generator>
		<lastBuildDate>Wed, 13 May 2026 21:10:32 GMT</lastBuildDate>
		<item>
			<title>Crazy Rebel в 11:06, 15 января 2010</title>
			<link>http://wiki2.linuxformat.ru/index.php?title=LXF109:%D0%98%D0%B3%D1%80%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B9&amp;diff=9510&amp;oldid=prev</link>
			<description>&lt;p&gt;&lt;/p&gt;

			&lt;table style=&quot;background-color: white; color:black;&quot;&gt;
			&lt;col class='diff-marker' /&gt;
			&lt;col class='diff-content' /&gt;
			&lt;col class='diff-marker' /&gt;
			&lt;col class='diff-content' /&gt;
			&lt;tr&gt;
				&lt;td colspan='2' style=&quot;background-color: white; color:black;&quot;&gt;← Предыдущая&lt;/td&gt;
				&lt;td colspan='2' style=&quot;background-color: white; color:black;&quot;&gt;Версия 11:06, 15 января 2010&lt;/td&gt;
			&lt;/tr&gt;
		&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Строка 1:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Строка 1:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;: '''Игрострой'''&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;: '''Игрострой'''&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;background: #cfc; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;background: #cfc; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;{{Цикл/Ни строчки кода}}&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;==Нереальная реальность==&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;==Нереальная реальность==&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</description>
			<pubDate>Fri, 15 Jan 2010 11:06:09 GMT</pubDate>			<dc:creator>Crazy Rebel</dc:creator>			<comments>http://wiki2.linuxformat.ru/index.php/%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5:LXF109:%D0%98%D0%B3%D1%80%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B9</comments>		</item>
		<item>
			<title>Crazy Rebel в 08:28, 9 декабря 2009</title>
			<link>http://wiki2.linuxformat.ru/index.php?title=LXF109:%D0%98%D0%B3%D1%80%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B9&amp;diff=9387&amp;oldid=prev</link>
			<description>&lt;p&gt;&lt;/p&gt;

			&lt;table style=&quot;background-color: white; color:black;&quot;&gt;
			&lt;col class='diff-marker' /&gt;
			&lt;col class='diff-content' /&gt;
			&lt;col class='diff-marker' /&gt;
			&lt;col class='diff-content' /&gt;
			&lt;tr&gt;
				&lt;td colspan='2' style=&quot;background-color: white; color:black;&quot;&gt;← Предыдущая&lt;/td&gt;
				&lt;td colspan='2' style=&quot;background-color: white; color:black;&quot;&gt;Версия 08:28, 9 декабря 2009&lt;/td&gt;
			&lt;/tr&gt;
		&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Строка 32:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Строка 32:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;процессор просто не годится. Благодаря шейдерам появляется возможность освободить его для более интересных задач, скажем, просчета AI.&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;процессор просто не годится. Благодаря шейдерам появляется возможность освободить его для более интересных задач, скажем, просчета AI.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;-&lt;/td&gt;&lt;td style=&quot;background: #ffa; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;{{Врезка | Содержание=[[Изображение: LXF109_101_1.jpg|300px|Рис. 1]] &lt;del style=&quot;color: red; font-weight: bold; text-decoration: none;&quot;&gt;  &lt;/del&gt;Рис. 1. Стандартный конвейер операций OpenGL с программируемыми процессорами шейдеров.| Ширина=300px}}&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;background: #cfc; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;{{Врезка | Содержание=[[Изображение: LXF109_101_1.jpg|300px|Рис. 1]] Рис. 1. Стандартный конвейер операций OpenGL с программируемыми процессорами шейдеров.| Ширина=300px}}&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;Выделяют два вида шейдеров: вершинный и фрагментный. Каждый из них выполняет определенные операции на соответствующем процессоре. Запомните! При изменении стандартной программы обработки какого-либо шейдера необходимо выполнить весь «затертый» функционал в своей реализации кода. Например, невозможно одновременно использовать стандартные функции преобразования вершины и нормали и свой код для вычисления освещения. Написанный вами шейдер должен уметь выполнять все три перечисленные операции. К счастью, в ''GLSL'' существуют команды-эквиваленты для замещения стандартных действий. Для более полного понимания происходящего обратите внимание на '''рис. 1''', где схематично представлен конвейер обработки данных OpenGL.&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;Выделяют два вида шейдеров: вершинный и фрагментный. Каждый из них выполняет определенные операции на соответствующем процессоре. Запомните! При изменении стандартной программы обработки какого-либо шейдера необходимо выполнить весь «затертый» функционал в своей реализации кода. Например, невозможно одновременно использовать стандартные функции преобразования вершины и нормали и свой код для вычисления освещения. Написанный вами шейдер должен уметь выполнять все три перечисленные операции. К счастью, в ''GLSL'' существуют команды-эквиваленты для замещения стандартных действий. Для более полного понимания происходящего обратите внимание на '''рис. 1''', где схематично представлен конвейер обработки данных OpenGL.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Строка 132:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Строка 132:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;можно было написать так:&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;можно было написать так:&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;-&lt;/td&gt;&lt;td style=&quot;background: #ffa; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;{{Врезка | Содержание=[[Изображение: LXF109_102_1.jpg|300px|Рис. 2]]&lt;del style=&quot;color: red; font-weight: bold; text-decoration: none;&quot;&gt;|&lt;/del&gt;Рис. 2. Без теней, без света, но зато с использованием шейдеров (слева – стандартный рендеринг в ''Blender'', справа – результат работы фрагментного шейдера)!| Ширина=300px}}&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;background: #cfc; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;{{Врезка | Содержание=[[Изображение: LXF109_102_1.jpg|300px|Рис. 2]]Рис. 2. Без теней, без света, но зато с использованием шейдеров (слева – стандартный рендеринг в ''Blender'', справа – результат работы фрагментного шейдера)!| Ширина=300px}}&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&amp;lt;source lang=c&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&amp;lt;source lang=c&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Строка 150:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Строка 150:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;на произвольную точку поверхности, равномерно рассеивается по всем направлениям (в рассматриваемом примере расчетная функция сознательно упрощена). Все необходимые вычисления будет производить вершинный шейдер.&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;на произвольную точку поверхности, равномерно рассеивается по всем направлениям (в рассматриваемом примере расчетная функция сознательно упрощена). Все необходимые вычисления будет производить вершинный шейдер.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;-&lt;/td&gt;&lt;td style=&quot;background: #ffa; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;{{Врезка | Содержание=[[Изображение: LXF109_102_2.jpg|300px|Рис. 3]]&lt;del style=&quot;color: red; font-weight: bold; text-decoration: none;&quot;&gt;| &lt;/del&gt;Рис. 3. Векторы для расчета освещения с помощью диффузной модели.| Ширина=300px}}&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;background: #cfc; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;{{Врезка | Содержание=[[Изображение: LXF109_102_2.jpg|300px|Рис. 3]] Рис. 3. Векторы для расчета освещения с помощью диффузной модели.| Ширина=300px}}&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;Вначале необходимо вычислить координаты вершины в пространстве обзора. Для этого берем локальные координаты из переменной '''gl_Vertex'''&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;Вначале необходимо вычислить координаты вершины в пространстве обзора. Для этого берем локальные координаты из переменной '''gl_Vertex'''&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Строка 193:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Строка 193:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;И вот что в итоге у нас получилось:&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;И вот что в итоге у нас получилось:&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;-&lt;/td&gt;&lt;td style=&quot;background: #ffa; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;{{Врезка | Содержание=[[Изображение: LXF109_103_1.jpg|300px|Рис. 4]]&lt;del style=&quot;color: red; font-weight: bold; text-decoration: none;&quot;&gt;|&lt;/del&gt;Рис. 4. Диффузная модель освещения в действии.| Ширина=300px}}&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;background: #cfc; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;{{Врезка | Содержание=[[Изображение: LXF109_103_1.jpg|300px|Рис. 4]]Рис. 4. Диффузная модель освещения в действии.| Ширина=300px}}&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&amp;lt;source lang=c&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&amp;lt;source lang=c&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Строка 320:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Строка 320:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;Для создания и управления шейдерами в OpenGL имеется специальный набор функций, предоставляемый расширениями '''ARB_shader_objects, ARB_vertex_shader, ARB_fragment_shader'''. В целом, последовательный механизм действий выглядит следующим образом:&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;Для создания и управления шейдерами в OpenGL имеется специальный набор функций, предоставляемый расширениями '''ARB_shader_objects, ARB_vertex_shader, ARB_fragment_shader'''. В целом, последовательный механизм действий выглядит следующим образом:&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;background: #cfc; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;'''1''' Создание пустого шейдерного объекта функцией '''glCreateShaderObjectARB''' (Glenum тип шейдера). Пример:&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;'''1''' Создание пустого шейдерного объекта функцией '''glCreateShaderObjectARB''' (Glenum тип шейдера). Пример:&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</description>
			<pubDate>Wed, 09 Dec 2009 08:28:37 GMT</pubDate>			<dc:creator>Crazy Rebel</dc:creator>			<comments>http://wiki2.linuxformat.ru/index.php/%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5:LXF109:%D0%98%D0%B3%D1%80%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B9</comments>		</item>
		<item>
			<title>Crazy Rebel: викификация, оформление, иллюстрация</title>
			<link>http://wiki2.linuxformat.ru/index.php?title=LXF109:%D0%98%D0%B3%D1%80%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B9&amp;diff=9386&amp;oldid=prev</link>
			<description>&lt;p&gt;викификация, оформление, иллюстрация&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Новая статья&lt;/b&gt;&lt;/p&gt;&lt;div&gt;: '''Игрострой'''&lt;br /&gt;
&lt;br /&gt;
==Нереальная реальность==&lt;br /&gt;
&lt;br /&gt;
: '''ЧАСТЬ 1''' Пластмасса, сталь, огонь, вода, облака, свет и процедурные текстуры – что объединяет все эти понятия? Оказывается, шейдеры – и '''Андрей Прахов''' сейчас расскажет о них подробнее.&lt;br /&gt;
&lt;br /&gt;
Шейдер! Многочисленная армия поклонников игр так или иначе знакома с этим термином. Строго говоря, программы на шейдерах используются не только в играх, но и в системах 3D-моделирования, визуализации, спецэффектах. Для обычного игрока это слово вызывает&lt;br /&gt;
разве что ассоциации с чем-то загадочным, непостижимым и, отчасти, крутым. Но мы же с&lt;br /&gt;
вами не только игроки, а поэтому давайте вместе разбираться, что это за зверь.&lt;br /&gt;
&lt;br /&gt;
Не секрет, что возможности трехмерных ускорителей (GPU) в своей области на порядок выше программных эквивалентов. Это и понятно, так как процессоры современных видеоплат представляют собой специализированные чипы, ориентированные на выполнение задач,&lt;br /&gt;
связанных с просчетом выводимой графики и только (правда, в последнее время инженерами компании NVIDIA ведутся интенсивные исследования по привлечению мощностей GPU к вычислениям игровой ['''и неигровой, – прим. ред.'''] физики). Однако для задействования этих функций необходимо писать код, понятный конкретным GPU. Ранее для этого использовался низкоуровневый язык, чем-то похожий на ассемблер. К&lt;br /&gt;
счастью, в настоящее время необходимость в нем отпала, и разработчики различных графических API предоставили пользователям свои&lt;br /&gt;
версии высокоуровневых шейдерных языков. Так как в Linux применяется исключительно OpenGL, то и мы будем изучать созданный для него&lt;br /&gt;
язык ''GLSL'' [OpenGL Shading Language]. Естественно, это не единственный язык подобного рода: так, для DirectX существует ''HLSL'', компания NVIDIA предлагает свой вариант – ''Cg'', а Pixar – ''RenderMan''.&lt;br /&gt;
&lt;br /&gt;
Прежде чем приступить к работе над шейдерами, необходимо оговорить ту программную среду, в которой мы будем ваять свои шедевры. После недолгого размышления я откинул идею об использовании «чистого» API OpenGL, так как тогда нам пришлось бы изучать не столько&lt;br /&gt;
шейдеры, сколько саму библиотеку. Поэтому для тестирования и прогона наших программ мы возьмем систему моделирования ''Blender''. В этом&lt;br /&gt;
случае мы получаем ощутимые плюсы в виде легкости написания кода и мощной базы для эффективного отображения задуманных эффектов.&lt;br /&gt;
Для любителей «чистого» OpenGL будут предусмотрены специальные сноски с необходимыми пояснениями. Обратите внимание! Эти уроки&lt;br /&gt;
'''только о ''GLSL'''''; информация о ''Blender'' и OpenGL будет в рамках, строго необходимых для работы (см. врезки).&lt;br /&gt;
&lt;br /&gt;
Что может дать использование шейдеров в наших программах? Вот небольшой список для ознакомления:&lt;br /&gt;
* Реалистичность отображения материалов (дерево, металл, пластик, краски);&lt;br /&gt;
* Природные явления (огонь, вода, облака, дым);&lt;br /&gt;
* Процедурные текстуры;&lt;br /&gt;
* Способы обработки изображений (яркость, контрастность, сепии, сглаживание, искривления и т.п.);&lt;br /&gt;
* Анимация;&lt;br /&gt;
* Реалистичность эффектов освещения, преломления.&lt;br /&gt;
&lt;br /&gt;
Перечень далеко не полный. Не забывайте о том, что для вычисления и демонстрации подобных эффектов с хорошей скоростью центральный&lt;br /&gt;
процессор просто не годится. Благодаря шейдерам появляется возможность освободить его для более интересных задач, скажем, просчета AI.&lt;br /&gt;
&lt;br /&gt;
{{Врезка | Содержание=[[Изображение: LXF109_101_1.jpg|300px|Рис. 1]]   Рис. 1. Стандартный конвейер операций OpenGL с программируемыми процессорами шейдеров.| Ширина=300px}}&lt;br /&gt;
&lt;br /&gt;
Выделяют два вида шейдеров: вершинный и фрагментный. Каждый из них выполняет определенные операции на соответствующем процессоре. Запомните! При изменении стандартной программы обработки какого-либо шейдера необходимо выполнить весь «затертый» функционал в своей реализации кода. Например, невозможно одновременно использовать стандартные функции преобразования вершины и нормали и свой код для вычисления освещения. Написанный вами шейдер должен уметь выполнять все три перечисленные операции. К счастью, в ''GLSL'' существуют команды-эквиваленты для замещения стандартных действий. Для более полного понимания происходящего обратите внимание на '''рис. 1''', где схематично представлен конвейер обработки данных OpenGL.&lt;br /&gt;
&lt;br /&gt;
* '''Вершинный шейдер [vertex shader]''' – это программа, выполняемая графическим процессором и обрабатывающая данные вершин конкретного примитива. Заметьте, что vertex shader работает исключительно с одной из вершин, не подозревая о существовании других. Таким образом, вы не можете добавлять или удалять вершины из существующего примитива. Для ускорения обработки современные GPU имеют до нескольких сотен соответствующих логических блоков.&lt;br /&gt;
&lt;br /&gt;
Список возможных операций вершинного шейдера:&lt;br /&gt;
** Преобразование вершин и нормалей;&lt;br /&gt;
** Генерирование и преобразование текстурных координат;&lt;br /&gt;
** Настройки освещения;&lt;br /&gt;
** Взаимодействие с цветом материала.&lt;br /&gt;
&lt;br /&gt;
После обработки данных всех вершин происходит сборка геометрических примитивов и их растеризация. Следующим этапом является работа фрагментного шейдера.&lt;br /&gt;
&lt;br /&gt;
* '''Фрагментный шейдер [fragment shader]''' – это программа, выполняемая графическим процессором и обрабатывающая отдельные фрагменты, полученные при растеризации фигур. Подобно вершинным, фрагментные шейдеры также могут быть запущены параллельно.&lt;br /&gt;
&lt;br /&gt;
Список возможных операций фрагментного шейдера:&lt;br /&gt;
** Доступ к текстурам и их наложение на модель;&lt;br /&gt;
** Наложение цветов;&lt;br /&gt;
** Масштабирование и смещение пиксела;&lt;br /&gt;
** Создание эффекта тумана.&lt;br /&gt;
&lt;br /&gt;
===Особенности ''GLSL''===&lt;br /&gt;
&lt;br /&gt;
Программистам на ''C/C++'', наверное, будет приятно узнать, что создатели ''GLSL'' отталкивались именно от их любимцев. Действительно, большинство правил синтаксиса, равно как и построения логических конструкций, напоминают указанные выше языки. Константы, операторы,&lt;br /&gt;
выражения и предложения – понятия одинаковые и для ''С''и, и для ''GLSL''.&lt;br /&gt;
Естественно, не стоит забывать, что шейдерный язык создавался исключительно для реализации графических алгоритмов и имеет свои характерные особенности.&lt;br /&gt;
&lt;br /&gt;
Во-первых, забудьте об использовании строковых и символьных значений. ''GLSL'' – язык работы только с числами! Не поддерживаются короткие и длинные целые, а также беззнаковые. При указании значения переменной необходимо следить за соответствием типов. Так, выражение&lt;br /&gt;
'''float a=0'''; является неверным и вызовет ошибку компилятора. Правильно будет: '''float a=0.0''';.&lt;br /&gt;
&lt;br /&gt;
В языке шейдеров отсутствуют какие-либо функции для работы с файлами и побитовые операции. Зато, по сравнению с ''C/C++'', появились новые типы данных. Для векторов могут использоваться числа с плавающей запятой, булевы и целые. Так, для первых они называются:&lt;br /&gt;
'''vec2, vec3, vec4''' (два, три, четыре числа). Имеется доступ к отдельным значениям вектора – либо с помощью индексации, либо по именованным полям. К примеру, значения отдельных координат можно получить, присоединив к переменной '''.x, .y, .z'''. Допускается и смешивание: '''.xy'''.&lt;br /&gt;
&lt;br /&gt;
Для работы с текстурной памятью был создан специальный тип переменной (дискретизатор), характерный для конкретного типа текстурной&lt;br /&gt;
карты: '''sampler1D''' – доступ к одномерной текстурной карте; '''sampler2D''' – доступ к двухмерной текстурной карте, и т.д.&lt;br /&gt;
&lt;br /&gt;
Существуют особые спецификаторы для управления входными и выходными данными шейдеров:&lt;br /&gt;
* '''attribute''' – переменные этого типа хранят часто изменяющиеся значения и используются для передачи данных от приложения к вершинному шейдеру. Доступны только для чтения. Массивы и структуры описывать ими нельзя;&lt;br /&gt;
* '''uniform''' – может содержать относительно редко изменяющиеся данные и использоваться для обоих типов шейдеров. В отличие от атрибутов, данный описатель можно задействовать для переменных всех типов. Заметьте, что имеется некоторое ограничение на количество имеющихся '''uniform'''-переменных, накладываемое реализацией ''GLSL'' и конкретным графическим ускорителем;&lt;br /&gt;
* '''varying''' – служат исключительно для передачи интерполированных данных от вершинного шейдера к фрагментному, причем фрагментный шейдер (в отличие от вершинного) не может изменять значение полученной '''varying'''-переменной. Эти описатели должны быть объявлены в обоих шейдерах и иметь одинаковые типы. Таким образом, как и '''uniform''', они являются глобальными и объявляются до первого использования.&lt;br /&gt;
&lt;br /&gt;
Естественно, предоставляется возможность работы с матрицами – наиболее удобным типом при выполнения линейных преобразований&lt;br /&gt;
для чисел с плавающей запятой. Поддерживаются таблицы от 2х2 до 4х4 с соответствующим обозначением '''mat2...mat4'''. Работать с ними можно&lt;br /&gt;
как с массивом, выбирая столбцы с помощью индексации.&lt;br /&gt;
&lt;br /&gt;
Помимо сказанного, ''GLSL'' имеет встроенные переменные для доступа к состояниям OpenGL. Все они начинаются с префикса '''gl_'''. Так, для&lt;br /&gt;
вершинного шейдера имеются переменные, позволяющие, к примеру, отследить текущее состояние источника света – '''gl_LightSource[номер источника]''', '''gl_Fog.color''' – цвета тумана, и т.д.&lt;br /&gt;
&lt;br /&gt;
Язык шейдеров предоставляет в помощь программисту большой набор встроенных функций, таких как: тригонометрические (синус, косинус, тангенс...); геометрические (нормализация, нахождения расстояния и длины и др.); общие математические операции (округление, модуль&lt;br /&gt;
числа и т.д.); специализированные для фрагментного шейдера; функции доступа к текстурной памяти и многие другие. Пользоваться ими не&lt;br /&gt;
только можно, но и нужно. Дело в том, что большинство предлагаемых функций могут обрабатываться на аппаратном уровне GPU и существен-&lt;br /&gt;
но ускорить вычисления. К сожалению, не всем функциям обеспечена такая поддержка, но их применение является хорошим тоном, хотя бы&lt;br /&gt;
потому, что производители оборудования не стоят на месте, а значит,&lt;br /&gt;
можно ожидать появления этой поддержки в будущем.&lt;br /&gt;
&lt;br /&gt;
===Первые шаги в неизведанное===&lt;br /&gt;
&lt;br /&gt;
Начнем с того, что каждый шейдер должен иметь свою функцию '''main()''',&lt;br /&gt;
объявленную как тип '''void''' – стандартная конструкция Си:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=c&amp;gt;&lt;br /&gt;
  void main ()&lt;br /&gt;
  {&lt;br /&gt;
              ...&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Попробуем написать простейший шейдер, который будет выводить объект и закрашивать его в красный цвет. Распределим задачи:&lt;br /&gt;
# '''Вершинный шейдер''' – трансформация вершины и запись полученного значения в глобальную переменную '''gl_Position''';&lt;br /&gt;
# '''Фрагментный шейдер''' – заливка цветом полученного пикселя через переменную '''gl_FragColor'''.&lt;br /&gt;
&lt;br /&gt;
Таким образом, получается, что вершинный шейдер у нас должен выполнять стандартный функционал, а вот фрагментный подвергается&lt;br /&gt;
необходимым изменениям. Займемся сначала первым.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=c&amp;gt;&lt;br /&gt;
 //GLSL vertex shader&lt;br /&gt;
  void main ()&lt;br /&gt;
  {&lt;br /&gt;
            gl_Position = ftransform();&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Ftransform()''' как раз и является той функцией, что позволяет частично замещать «затертый» функционал стандартного шейдера. Она возвращает результат трансформации вершин, выполняя операции того же плана, что и базовый функционал. Учтите, что все остальные преобразования – скажем, такие, как обработка освещения – произведены не будут. Но использование '''ftransform()''' гарантирует, по крайней мере, выполнение стандартного потока операций с использованием оптимизации на уровне GPU.&lt;br /&gt;
&lt;br /&gt;
Для записи цвета обработанного пикселя во фрагментном шейдере служит переменная '''gl_FragColor''', которая, так же как и '''gl_Position''', является заранее объявленной. Тип переменной – '''vec4'''. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=c&amp;gt;&lt;br /&gt;
 //GLSL fragment shader&lt;br /&gt;
  void main ()&lt;br /&gt;
  {&lt;br /&gt;
            gl_FragColor = vec4 (1.0,0.0,0.0,1.0);&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Обратите внимание на значения, передаваемые переменной. Это не что иное, как раскладка цветовой палитры RGBA (red, green, blue, alpha)&lt;br /&gt;
[красный, зеленый, синий, прозрачность]. Как уже говорилось ранее, ''GLSL'' позволяет получить доступ к отдельным значениям вектора с&lt;br /&gt;
помощью именованных полей. Для этой цели, в данном случае, имеются зарезервированные буквы r, g, b, a. Например, фрагментный шейдер&lt;br /&gt;
можно было написать так:&lt;br /&gt;
&lt;br /&gt;
{{Врезка | Содержание=[[Изображение: LXF109_102_1.jpg|300px|Рис. 2]]|Рис. 2. Без теней, без света, но зато с использованием шейдеров (слева – стандартный рендеринг в ''Blender'', справа – результат работы фрагментного шейдера)!| Ширина=300px}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=c&amp;gt;&lt;br /&gt;
 //GLSL fragment shader&lt;br /&gt;
  void main ()&lt;br /&gt;
  {&lt;br /&gt;
 gl_FragColor.r = 1.0;&lt;br /&gt;
 gl_FragColor.gba = vec3 (1.0, 0.0, 1.0);&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Вот и все! Для проверки написанного кода просто загрузите с '''LXFDVD''' файл '''les1_1.blend''' и запустите движок клавишей '''P''' ('''рис. 2''').&lt;br /&gt;
&lt;br /&gt;
Действительно очень просто; но не очень зрелищно. Картинка будет смотреться гораздо выигрышнее, если научить шейдер реагировать на&lt;br /&gt;
освещение модели. Существует немало способов и алгоритмов расчета освещения, и в дальнейшем этой теме будет посвящена целая статья.&lt;br /&gt;
Сейчас же давайте рассмотрим самый простой способ работы со светом, а именно – диффузную модель освещения, когда луч, падающий&lt;br /&gt;
на произвольную точку поверхности, равномерно рассеивается по всем направлениям (в рассматриваемом примере расчетная функция сознательно упрощена). Все необходимые вычисления будет производить вершинный шейдер.&lt;br /&gt;
&lt;br /&gt;
{{Врезка | Содержание=[[Изображение: LXF109_102_2.jpg|300px|Рис. 3]]| Рис. 3. Векторы для расчета освещения с помощью диффузной модели.| Ширина=300px}}&lt;br /&gt;
&lt;br /&gt;
Вначале необходимо вычислить координаты вершины в пространстве обзора. Для этого берем локальные координаты из переменной '''gl_Vertex'''&lt;br /&gt;
и умножаем их на текущую матрицу объекта. Заметьте, так как один из операндов – матрица, а другой – вектор, то происходит математическое,&lt;br /&gt;
а не покомпонентное умножение:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=c&amp;gt;&lt;br /&gt;
 vec3 position = vec3 (gl_ModelViewMatrix * gl_Vertex);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для вычисления самого рассеивания света нужно определить угол между нормалью к поверхности и лучом света (рис. 3). Добиться этого&lt;br /&gt;
можно, если взять значения нормали и преобразовать их с помощью матрицы '''gl_NormalMatrix'''. Полученный вектор необходимо привести к&lt;br /&gt;
единичной длине с помощью встроенной функции '''normalize''':&lt;br /&gt;
&amp;lt;source lang=c&amp;gt;&lt;br /&gt;
  vec3 norm = normalize (gl_NormalMatrix * gl_Normal);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Осталось только построить вектор из заданной точки до источника освещения:&lt;br /&gt;
&amp;lt;source lang=c&amp;gt;&lt;br /&gt;
  vec3 lightvec = normalize (vec3 (lightPos) - position);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для окончательного результата вычисления введем переменную&lt;br /&gt;
'''varying outColor''', которая будет хранить интерполированное значение&lt;br /&gt;
цвета для фрагментного шейдера. Переменные этого типа должны быть&lt;br /&gt;
определенны в обоих шейдерах одинаково. Помимо нее, нам еще понадобится константа '''inColor''' для хранения оригинального цвета объекта и&lt;br /&gt;
'''uniform'''-переменная – для координат источника света. Следующая строка выполняет необходимые нам вычисления:&lt;br /&gt;
&amp;lt;source lang=c&amp;gt;&lt;br /&gt;
  outColor = inColor * (max (dot (norm, lightvec), 0.0));&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Так как может сложиться ситуация, когда источник света расположен за самим объектом, то применяется функция max для обеспечения нулевого значения рассеянного отражения при угле больше 90 градусов между&lt;br /&gt;
направлением освещения и нормалью к поверхности. Вторая неизвестная&lt;br /&gt;
вам функция '''dot''' выполняет скалярное произведения двух векторов.&lt;br /&gt;
&lt;br /&gt;
Осталось выполнить трансформацию вершины, но на этот раз мы не будем вызывать функцию '''ftransform()''', а выполним непосредственное перемножение координат вершины на проектную матрицу OpenGL (результат практически тот же):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=c&amp;gt;&lt;br /&gt;
  gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
И вот что в итоге у нас получилось:&lt;br /&gt;
&lt;br /&gt;
{{Врезка | Содержание=[[Изображение: LXF109_103_1.jpg|300px|Рис. 4]]|Рис. 4. Диффузная модель освещения в действии.| Ширина=300px}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=c&amp;gt;&lt;br /&gt;
 //GLSL vertex shader&lt;br /&gt;
  void main ()&lt;br /&gt;
 const vec4 inColor = vec4 (1.0, 0.0, 0.0, 1.0);&lt;br /&gt;
 uniform vec3 lightPos;&lt;br /&gt;
 varying vec4 outColor;&lt;br /&gt;
 {&lt;br /&gt;
             vec3 position = vec3 (gl_ModelViewMatrix * gl_Vertex);&lt;br /&gt;
             vec3 lightvec = normalize (vec3 (lightPos) – position);&lt;br /&gt;
             vec3 norm = normalize (gl_NormalMatrix * gl_Normal);&lt;br /&gt;
             outColor = inColor * (max (dot (norm, lightvec), 0.0));&lt;br /&gt;
             gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;&lt;br /&gt;
             gl_Position = ftransform();&lt;br /&gt;
 }&lt;br /&gt;
 //GLSL fragment shader&lt;br /&gt;
  varying vec4 outColor;&lt;br /&gt;
  void main ()&lt;br /&gt;
  {&lt;br /&gt;
 gl_FragColor= outColor;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Как видите, ничего сложного в работе с шейдерами нет, особенно когда многими учеными мужами уже были выведены необходимые нам&lt;br /&gt;
формулы. Однако на следующем уроке мы займемся по-настоящему тяжелой и интересной работой с так называемыми процедурными текстурами. До встречи! '''LXF'''&lt;br /&gt;
&lt;br /&gt;
===А как это в ''Blender''?===&lt;br /&gt;
&lt;br /&gt;
В большинстве случаев для программирования шейдеров можно обойтись предлагаемой ниже заготовкой:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
  ##----------------------------------------------------------------&lt;br /&gt;
  ## Shader Template.py&lt;br /&gt;
  ##----------------------------------------------------------------&lt;br /&gt;
  import GameLogic&lt;br /&gt;
  ObjectList = GameLogic.getCurrentScene().getObjectList()&lt;br /&gt;
  # -------------------------------------&lt;br /&gt;
  ShaderObjects = [ObjectList[‘OBCube’]]&lt;br /&gt;
 MaterialIndexList = [0]&lt;br /&gt;
  ##---------------------------------------------------------------&lt;br /&gt;
  # ----------------------------------------------------------------&lt;br /&gt;
 VertexShader = &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
  void main() {&lt;br /&gt;
      //shader&lt;br /&gt;
  }&lt;br /&gt;
  &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
  FragmentShader = &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
  void main() {&lt;br /&gt;
      //shader&lt;br /&gt;
  }&lt;br /&gt;
  &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
  def MainLoop ():&lt;br /&gt;
         for obj in ShaderObjects:&lt;br /&gt;
               mesh_index = 0&lt;br /&gt;
               mesh = obj.getMesh(mesh_index)&lt;br /&gt;
               while mesh != None:&lt;br /&gt;
                     # for each material in the mesh&lt;br /&gt;
                     for mat in mesh.materials:&lt;br /&gt;
                           if not hasattr(mat, &amp;quot;getMaterialIndex&amp;quot;):&lt;br /&gt;
                                  return&lt;br /&gt;
                           mat_index = mat.getMaterialIndex()&lt;br /&gt;
                           # find an index from the list&lt;br /&gt;
                           found = 0&lt;br /&gt;
                           for i in range(len(MaterialIndexList)):&lt;br /&gt;
                                  if mat_index == MaterialIndexList[i]:&lt;br /&gt;
                                        found=1&lt;br /&gt;
                                        break&lt;br /&gt;
                     if not found: continue&lt;br /&gt;
                     shader = mat.getShader()&lt;br /&gt;
                     if shader != None:&lt;br /&gt;
                            if not shader.isValid():&lt;br /&gt;
                                   shader.setSource(VertexShader,FragmentShader,1)&lt;br /&gt;
                            # set uniforms&lt;br /&gt;
                mesh_index += 1&lt;br /&gt;
                mesh = obj.getMesh(mesh_index)&lt;br /&gt;
  ## call it&lt;br /&gt;
  MainLoop()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Рассмотрим ее подробнее. Первые две строки подключают необходимую библиотеку BGE и загружают в переменную '''ObjectList''' список существующих объектов в сцене. Все это стандартно, но обратите внимание на третью строку в листинге. Именно в ней указывается объект, для которого будет применяться шейдер. В моем тексте это ‘OBCube’. Необходимое имя объекта вы можете взять из меню ‘Object and Link ‘, нажав '''F7'''.&lt;br /&gt;
&lt;br /&gt;
Строки ‘VertexShader’ и ‘FragmentShader’ указывают на начало программных блоков, написанных на ''GLSL''. Все передаваемые в шейдер переменные '''uniform''' располагаются после строки ‘# set uniforms’. Список функций для имеющихся переменных ''GLSL'' таков:&lt;br /&gt;
&lt;br /&gt;
{|class=wikitable border=1 cellpadding=5|-&lt;br /&gt;
! Тип переменной &lt;br /&gt;
! Функция инициализации &lt;br /&gt;
! Комментарий&lt;br /&gt;
|-&lt;br /&gt;
| uniform vec1 (float) &lt;br /&gt;
| setUniform1f (name, a)&lt;br /&gt;
| Целочисленное значение&lt;br /&gt;
|-&lt;br /&gt;
| uniform vec2 (float) &lt;br /&gt;
| setUniform2f (name, a,b)&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| uniform vec3 (float) &lt;br /&gt;
| setUniform3f (name, a,b,c)&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| uniform vec4 (float) &lt;br /&gt;
| setUniform4f (name, a,b,c,d)&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| uniform vec1 (int) &lt;br /&gt;
| setUniform1i (name, a)&lt;br /&gt;
| Число с плавающей запятой&lt;br /&gt;
|-&lt;br /&gt;
| uniform vec2 (int) &lt;br /&gt;
| setUniform2i (name, a,b)&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| uniform vec3 (int) &lt;br /&gt;
| setUniform3i (name, a,b,c)&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| uniform vec4 (int) &lt;br /&gt;
| setUniform4i (name, a,b,c,d)&lt;br /&gt;
| &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Приведу пример. Пусть в вершинном шейдере используется переменная '''uniform vec3 lightPos'''. Соответственно, для ее установки служит следующая строка на ''Python'': '''shader.setUniform3f(‘lightPos’, 0.2,0.2,0.2)'''.&lt;br /&gt;
&lt;br /&gt;
===А как это в OpenGL?===&lt;br /&gt;
&lt;br /&gt;
Для создания и управления шейдерами в OpenGL имеется специальный набор функций, предоставляемый расширениями '''ARB_shader_objects, ARB_vertex_shader, ARB_fragment_shader'''. В целом, последовательный механизм действий выглядит следующим образом:&lt;br /&gt;
'''1''' Создание пустого шейдерного объекта функцией '''glCreateShaderObjectARB''' (Glenum тип шейдера). Пример:&lt;br /&gt;
&lt;br /&gt;
  testVS = glCreateShaderObjectARB (GL_VERTEX_SHADER_ARB);&lt;br /&gt;
  testFS = glCreateShaderObjectARB (GL_FRAGMENT_SHADER_ARB);&lt;br /&gt;
&lt;br /&gt;
'''2''' Передача исходного кода шейдеров функцией '''glShaderSourceARB'''. Пример:&lt;br /&gt;
&lt;br /&gt;
  glShaderSourceARB(testVS, 1, &amp;amp;testvertex, NULL);&lt;br /&gt;
  glShaderSourceARB(testFS, 1, &amp;amp;testfragment, NULL);&lt;br /&gt;
&lt;br /&gt;
'''3''' Компиляция каждого из шейдеров:&lt;br /&gt;
&lt;br /&gt;
 glCompileShaderARB(testVS);&lt;br /&gt;
 glCompileShaderARB(testFS);&lt;br /&gt;
&lt;br /&gt;
'''4''' Создание программного объекта и присоединение шейдеров к нему:&lt;br /&gt;
&lt;br /&gt;
 shaderProg = glCreateProgramObjectARB();&lt;br /&gt;
 glAttachObjectARB(shaderProg, testVS);&lt;br /&gt;
 glAttachObjectARB(shaderProg, testFS);&lt;br /&gt;
&lt;br /&gt;
'''5''' Компоновка функцией '''glLinkProgramARB''':&lt;br /&gt;
&lt;br /&gt;
 glLinkProgramARB(shaderProg);&lt;br /&gt;
&lt;br /&gt;
'''6''' Установка программного объекта как текущего:&lt;br /&gt;
&lt;br /&gt;
 glUseProgramObjectARB(shaderProg);&lt;br /&gt;
&lt;br /&gt;
'''7''' Установка, если нужно, начальных значений переменных '''uniform''':&lt;br /&gt;
&lt;br /&gt;
 glUniform3fARB(getUniLoc(shaderProg, ‘name’), первое значение, второе значение, третье значение);&lt;/div&gt;</description>
			<pubDate>Wed, 09 Dec 2009 08:26:09 GMT</pubDate>			<dc:creator>Crazy Rebel</dc:creator>			<comments>http://wiki2.linuxformat.ru/index.php/%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5:LXF109:%D0%98%D0%B3%D1%80%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B9</comments>		</item>
	</channel>
</rss>