<?xml version="1.0" encoding="windows-1251"?>
<rss version="2.0">
<channel>
  <title>Программирование игр</title>
  <link>http://www.gamedev.ru/code/</link>
  <description>Программирование игр</description>
  <language>ru</language>
  <generator>http://skif.qrim.ru/</generator>
<item>
  <guid isPermaLink="true">http://www.gamedev.ru/code/terms/PhotonMapping</guid>
  <pubDate>Sat, 31 Jul 2010 19:10:07 GMT</pubDate>
  <title>Photon mapping</title>
  <link>http://www.gamedev.ru/code/terms/PhotonMapping</link>
  <category>Графика</category>
  <category>caustic</category>
  <category>global illumination</category>
  <category>photon mapping</category>
  <description>
&lt;p&gt;&lt;b&gt;Photon mapping&lt;/b&gt; (техника &lt;b&gt;фотонных карт&lt;/b&gt;) &amp;mdash; алгоритм расчета глобального освещения, используемый в компьютерной графике. Данная техника позволяет рассчитать не только освещение и затенение объектов, но и отраженный и преломленный свет (например &lt;a href=&quot;http://www.gamedev.ru/code/terms/Caustic&quot; title=&quot;Каустика&quot;&gt;каустику&lt;/a&gt;) а так же &lt;a href=&quot;http://www.gamedev.ru/code/terms/SSS&quot; title=&quot;SSS: Subsurface scattering (Подповерхностное рассеивание)&quot;&gt;подповерхностное рассеивание&lt;/a&gt;.&lt;p&gt;Расчет освещения в технике фотонных карт производится путем трассировки лучей от источника света и камеры. Существуют методы расчета фотонных карт в реальном времени и в офлайн режиме. Для просчета освещения в офлайн режиме используется обычная трассировка лучей (метод Монте-Карло и др.). Для использования фотонных карт в реальном времени (в 3D приложениях и &lt;a href=&quot;http://www.gamedev.ru/industry/terms/Games&quot; title=&quot;Игры (games): компьютерные игры&quot;&gt;играх&lt;/a&gt;) можно использовать один из методов трассировки лучей в пространстве изображения (см. ссылки).&lt;/p&gt;
&lt;p&gt;Алгоритм техники фотонных карт обычно состоит из двух частей:
&lt;br /&gt;1) непосредственно расчет фотонной карты &amp;mdash; трассировка лучей и накопление (сохранение) данных;
&lt;br /&gt;2) рендеринг с использованием рассчитанной фотонной карты.&lt;/p&gt;
&lt;p&gt;Пример построения изображения с использованием фотонных карт:
&lt;/p&gt;&lt;p style=&quot;text-align:center&quot;&gt;&lt;img src=&quot;http://www.gamedev.ru/files/images/refractive.jpg&quot; alt=&quot;Изображение&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Ссылки:&lt;/b&gt;
&lt;p&gt;Henrik Wann Jensen. Global Illumination using Photon Maps &lt;a href=&quot;http://graphics.ucsd.edu/~henrik/papers/photon_map/global_illumination_using_photon_maps_egwr96.pdf&quot;&gt;[^]&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Morgan McGuire, Williams College David Luebke. Hardware-Accelerated Global Illumination by Image Space Photon Mapping. &lt;a href=&quot;http://graphics.cs.williams.edu/papers/PhotonHPG09/&quot;&gt;[^]&lt;/a&gt;&lt;/p&gt;</description>
</item>
<item>
  <guid isPermaLink="true">http://www.gamedev.ru/code/news/OpenGL4_1</guid>
  <pubDate>Tue, 27 Jul 2010 20:35:42 GMT</pubDate>
  <title>API OpenGL обновлен до версии 4.1</title>
  <link>http://www.gamedev.ru/code/news/OpenGL4_1</link>
  <category>Графика</category>
  <category>OpenGL</category>
  <description>
&lt;p&gt;Консорциум Khronos Group, который занимается разработкой стандарта &lt;a href=&quot;http://www.gamedev.ru/code/terms/OpenGL&quot; title=&quot;OpenGL: Open Graphics Library&quot;&gt;OpenGL&lt;/a&gt;, анонсировал выпуск новой версии &amp;mdash; OpenGL 4.1. Следует отметить, что финальная спецификация OpenGL 4.0 была представлена всего несколько месяцев назад.&lt;/p&gt;
&lt;p&gt;API OpenGL 4.1 содержит ряд усовершенствований и нововведений, среди которых выделяются следующие моменты:&lt;/p&gt;
&lt;p&gt;&amp;mdash; Реализована полная совместимость с API OpenGL ES 2.0 для более лeгкого портирования между мобильными устройствами и традиционными компьютерными платформами;
&lt;br /&gt;&amp;mdash; Реализована возможность запрашивать и загружать скомпилированную ранее версию объектов &lt;a href=&quot;http://www.gamedev.ru/code/terms/Shader&quot; title=&quot;Шейдер (Shader)&quot;&gt;шейдерных&lt;/a&gt; программ с целью сокращения затрат времени на перекомпиляцию;
&lt;br /&gt;&amp;mdash; Добавлена возможность индивидуального связывания программ с программируемыми этапами для улучшения гибкости их программирования;
&lt;br /&gt;&amp;mdash; Внедрена возможность использования 64-битных компонентов в вершинных шейдерах для реализации более точных геометрических вычислений;
&lt;br /&gt;&amp;mdash; Реализована возможность использования множественных точек обзора поверхности рендеринга для повышения гибкости рендеринга.&lt;/p&gt;
&lt;p&gt;Кроме того, в OpenGL 4.1 реализован ряд новых расширений, которые позволяют: осуществлять синхронизацию объектов OpenGL с событиями &lt;a href=&quot;http://www.gamedev.ru/code/terms/OpenCL&quot; title=&quot;OpenCL: Open Computing Language&quot;&gt;OpenCL&lt;/a&gt;; устанавливать трафаретные значения в фрагментах шейдеров; повысить устойчивость при выполнении приложений WebGL; получать уведомления о возникающих ошибках.&lt;/p&gt;</description>
</item>
<item>
  <guid isPermaLink="true">http://www.gamedev.ru/code/articles/Racing_Simulator</guid>
  <pubDate>Sat, 17 Jul 2010 10:37:05 GMT</pubDate>
  <title>Пишем симулятор гонок</title>
  <link>http://www.gamedev.ru/code/articles/Racing_Simulator</link>
  <comments>http://www.gamedev.ru/code/forum/?id=135833</comments>
  <category>Физика</category>
  <category>физика</category>
  <category>racing</category>
  <category>автомобиль</category>
  <category>симулятор</category>
  <description>
&lt;p&gt;В данной статье представлены методы для создания математической модели автомобиля, позволяющие достаточно точно симулировать физику авто на уровне лучших современных симуляторов гонок.&lt;/p&gt;&lt;p&gt;Суть математической модели автомобиля &amp;mdash; в зависимости от состояний элементов управления автомобилем, таких как педали дросселя (&amp;laquo;газ&amp;raquo;), сцепления, тормозного усилия, руля и переключателя передач, выводить результирующие силы на каждом колесе авто, а также некоторые промежуточные значения, такие как скорость вращения колёс, обороты двигателя и т.п.&lt;/p&gt;
&lt;p style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;http://www.gamedev.ru/files/images/56206_1279190118_1.jpg&quot; alt=&quot;Car sim | Пишем симулятор гонок&quot; /&gt;&lt;/p&gt;
&lt;p&gt;В рамках статьи не рассматривается реализация взаимодействий между твёрдыми телами. Этим может заняться любой &lt;a href=&quot;http://www.gamedev.ru/code/terms/PhysicsEngine&quot; title=&quot;Физический движок (Physics Engine)&quot;&gt;физический движок&lt;/a&gt;, симулирующий физику твёрдых тел. Он должен поддерживать статические тримеши, динамические примитивы и соединения &amp;mdash; этого будет достаточно.&lt;/p&gt;
&lt;p&gt;Основные части, которые необходимо рассмотреть при создании мат. модели автомобиля:&lt;/p&gt;
&lt;p&gt;==Часть 1: Крутящий момент==&lt;/p&gt;
&lt;p&gt;Крутящий момент &amp;mdash; есть вращательное действие силы. Это основа движущей силы автомобиля. Он создаётся в двигателе и передаётся колёсам, где есть рычаг, преобразующий крутящий момент в силу.&lt;/p&gt;
&lt;p&gt;===1.1 Двигатель автомобиля===&lt;/p&gt;
&lt;p style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;http://www.gamedev.ru/files/images/56207_1279190346_2.jpg&quot; alt=&quot;Engine | Пишем симулятор гонок&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Как уже было сказано &amp;mdash; двигатель это источник крутящего момента. Для моделирования работы двигателя достаточно задать следующие характеристики:
&lt;br /&gt;1) зависимость крутящего момента от текущей скорости вращения коленвала;
&lt;br /&gt;2) инертность вращающихся элементов (совокупность маховика, коленвала и проч.)
&lt;br /&gt;3) тип расположения (продольно/поперечно);
&lt;br /&gt;при рассматривании двигателя внутри авто нам понадобится ещё одна характеристика:
&lt;br /&gt;4) масса двигателя.&lt;/p&gt;
&lt;p&gt;Рассмотрим эти характеристики подробнее. Мощность двигателя определяется его крутящим моментом, причем эти две величины меняются в зависимости от &amp;quot;оборотов двигателя&amp;quot;, т.е. от скорости вращения коленвала. Типичный график изображён на следующем рисунке:&lt;/p&gt;
&lt;p style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;http://www.gamedev.ru/files/images/56208_1279190440_3.jpg&quot; alt=&quot;EngineGraph1 | Пишем симулятор гонок&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Необходимо задать график крутящего момента, а мощность рассчитывается следующим образом:&lt;/p&gt;
&lt;div style=&quot;background: #f2f2f2; padding: 5px; margin: 4px;&quot;&gt;&lt;pre&gt;    Power&lt;span style=&quot;color: #a06000&quot;&gt;[&lt;/span&gt;RPM&lt;span style=&quot;color: #a06000&quot;&gt;]&lt;/span&gt; = Torque&lt;span style=&quot;color: #a06000&quot;&gt;[&lt;/span&gt;RPM&lt;span style=&quot;color: #a06000&quot;&gt;]&lt;/span&gt; * RPM / &lt;span style=&quot;color: #F04000; &quot;&gt;7000&lt;/span&gt;;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;
&lt;p&gt;где RPM &amp;mdash; текущие &amp;laquo;обороты двигателя&amp;raquo;. Как видно, при 7000 об/мин мощность равна крутящему моменту, в этой точке графики всегда пересекаются.&lt;/p&gt;
&lt;p&gt;Крутящий момент, развиваемый двигателем, равен:&lt;/p&gt;
&lt;div style=&quot;background: #f2f2f2; padding: 5px; margin: 4px;&quot;&gt;&lt;pre&gt;    &lt;span style=&quot;color: #0030fF; &quot;&gt;float&lt;/span&gt; torq = Torque&lt;span style=&quot;color: #a06000&quot;&gt;[&lt;/span&gt;RPM&lt;span style=&quot;color: #a06000&quot;&gt;]&lt;/span&gt; * Throttle;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;
где Throttle &amp;mdash; значение от 0 до 1 &amp;mdash; дроссель. Чем сильнее жмём на педаль, тем больший процент максимального крутящего момента развивается двигателем.
&lt;p&gt;Куда направлен этот крутящий момент? Это зависит от сцепления, которое мы рассмотрим позже. А сейчас этот момент просто раскручивает наш мотор:&lt;/p&gt;
&lt;div style=&quot;background: #f2f2f2; padding: 5px; margin: 4px;&quot;&gt;&lt;pre&gt;    RPM += torq / Inertia;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;
где Inertia &amp;mdash; инертность вращающихся элементов. 
&lt;p&gt;Вот так работает мотор. Однако эта формула не полная, так как существует так называемый обратный момент, возникающий при сбросе газа и заставляющий мотору снижать свои обороты:&lt;/p&gt;
&lt;div style=&quot;background: #f2f2f2; padding: 5px; margin: 4px;&quot;&gt;&lt;pre&gt;    RPM += torq / Inertia - pow&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #F04000; &quot;&gt;1&lt;/span&gt;.&lt;span style=&quot;color: #F04000; &quot;&gt;0&lt;/span&gt;f - torq, &lt;span style=&quot;color: #F04000; &quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt; * BackTorque;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;
где pow() &amp;mdash; функция возведения в степень, backTorq &amp;mdash; константа, определяющая величину обратного момента. 
&lt;p&gt;Теперь ещё раз дополним этот участок &amp;mdash; здесь заранее необходимо учесть фактор сцепления.&lt;/p&gt;
&lt;div style=&quot;background: #f2f2f2; padding: 5px; margin: 4px;&quot;&gt;&lt;pre&gt;    &lt;span style=&quot;color: #0030fF; &quot;&gt;float&lt;/span&gt; additionRPM = torq / Inertia - pow&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #F04000; &quot;&gt;1&lt;/span&gt;.&lt;span style=&quot;color: #F04000; &quot;&gt;0&lt;/span&gt;f - torq, &lt;span style=&quot;color: #F04000; &quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt; * BackTorque;
    RPM += additionRPM * &lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #F04000; &quot;&gt;1&lt;/span&gt;.&lt;span style=&quot;color: #F04000; &quot;&gt;0&lt;/span&gt;f - Clutch&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;
где Clutch &amp;mdash; значение от 0 до 1 &amp;mdash; педаль сцепления. Часть, равная (1.0f – Clutch) уйдёт на раскрутку мотора, а часть, равная Clutch уйдёт в коробку передач, которую мы рассмотрим позже.
&lt;p&gt;Чуть не забыл упомянуть о холостом ходе. Делается просто &amp;mdash; когда обороты ниже определённого значения &amp;mdash; величина открытия дросселя немного увеличивается.&lt;/p&gt;
&lt;p&gt;Приблизительная структура нашего мотора на языке C++ будет выглядеть так:&lt;/p&gt;
&lt;div style=&quot;background: #f2f2f2; padding: 5px; margin: 4px;&quot;&gt;&lt;pre&gt;&lt;span style=&quot;color: #0030fF; &quot;&gt;struct&lt;/span&gt; Engine
{
    &lt;span style=&quot;color: #808080&quot;&gt;// базовые величины&lt;/span&gt;
    &lt;span style=&quot;color: #0030fF; &quot;&gt;float&lt;/span&gt;* Torque;
    &lt;span style=&quot;color: #0030fF; &quot;&gt;float&lt;/span&gt;* Power;
    &lt;span style=&quot;color: #0030fF; &quot;&gt;float&lt;/span&gt; Inertia, Mass, BackTorque;
    &lt;span style=&quot;color: #0030fF; &quot;&gt;char&lt;/span&gt; Direction;

    &lt;span style=&quot;color: #0030fF; &quot;&gt;float&lt;/span&gt; IdleRPM; &lt;span style=&quot;color: #808080&quot;&gt;// обороты холостого хода&lt;/span&gt;

    &lt;span style=&quot;color: #808080&quot;&gt;// динамические величины&lt;/span&gt;
    &lt;span style=&quot;color: #0030fF; &quot;&gt;float&lt;/span&gt; RPM;

    &lt;span style=&quot;color: #808080&quot;&gt;// функция обновления&lt;/span&gt;
    &lt;span style=&quot;color: #0030fF; &quot;&gt;void&lt;/span&gt; Progress&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #0030fF; &quot;&gt;float&lt;/span&gt; Throttle, &lt;span style=&quot;color: #0030fF; &quot;&gt;float&lt;/span&gt; Clutch&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;
    {
        &lt;span style=&quot;color: #0030fF; &quot;&gt;if&lt;/span&gt; &lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;RPM &lt;span style=&quot;color: #a06000&quot;&gt;&amp;lt;&lt;/span&gt; IdleRPM &amp;amp;&amp;amp; Throttle &lt;span style=&quot;color: #a06000&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&quot;color: #F04000; &quot;&gt;0&lt;/span&gt;.&lt;span style=&quot;color: #F04000; &quot;&gt;3&lt;/span&gt;f&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;
            Throttle += &lt;span style=&quot;color: #F04000; &quot;&gt;0&lt;/span&gt;.&lt;span style=&quot;color: #F04000; &quot;&gt;1&lt;/span&gt;f;

        &lt;span style=&quot;color: #0030fF; &quot;&gt;float&lt;/span&gt; torq = Torque&lt;span style=&quot;color: #a06000&quot;&gt;[&lt;/span&gt; &lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #0030fF; &quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;RPM &lt;span style=&quot;color: #a06000&quot;&gt;]&lt;/span&gt; * Throttle;

        &lt;span style=&quot;color: #0030fF; &quot;&gt;float&lt;/span&gt; additionRPM = torq / Inertia - pow&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #F04000; &quot;&gt;1&lt;/span&gt;.&lt;span style=&quot;color: #F04000; &quot;&gt;0&lt;/span&gt;f - torq, &lt;span style=&quot;color: #F04000; &quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt; * BackTorque;
        RPM += additionRPM * &lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #F04000; &quot;&gt;1&lt;/span&gt;.&lt;span style=&quot;color: #F04000; &quot;&gt;0&lt;/span&gt;f - Clutch&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;;
    }
};&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;
&lt;p&gt;Примечание: я привёл эту структуру только для того, чтобы читатель понял принцип, я советую НЕ использовать эту структуру, а писать свою в соответствии с выбранной вами архитектурой вашего приложения.&lt;/p&gt;
&lt;p&gt;===1.2 КПП===&lt;/p&gt;
&lt;p style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;http://www.gamedev.ru/files/images/56209_1279190597_4.jpg&quot; alt=&quot;GearBox parts | Пишем симулятор гонок&quot; /&gt;&lt;/p&gt;
&lt;p&gt;В коробке переключения передач происходит две вещи &amp;mdash; преобразование и передача крутящего момента. Для моделирования работы КПП достаточно задать следующие характеристики:
&lt;br /&gt;1) передаточные отношения всех передач;
&lt;br /&gt;2) передаточное отношение &amp;quot;главной пары&amp;quot;;
&lt;br /&gt;3) КПД коробки передач.&lt;/p&gt;
&lt;p&gt;Скорость вращения коленвала достаточно высока, например, на холостых оборотах она составляет около 16 полных оборотов в секунду. Поэтому в коробке передач существует так называемая &amp;laquo;главная пара&amp;raquo; &amp;mdash; пара шестерёнок, представляющих базовый редуктор. Главная пара всегда включена. &lt;/p&gt;
&lt;p&gt;Если вы взглянете с умным видом на график мощности, то поймёте, что он достигает маскимальных значений только в некотором диапазоне (особенно у гоночных машин он становится совсем узким). Для этого и нужны все передачи в КПП &amp;mdash; чтобы держать мотор в диапазоне максимальной мощности.&lt;/p&gt;
&lt;p&gt;Посмотрим, что же происходит с крутящим моментом, переданным в коробку передач:&lt;/p&gt;
&lt;div style=&quot;background: #f2f2f2; padding: 5px; margin: 4px;&quot;&gt;&lt;pre&gt;    &lt;span style=&quot;color: #0030fF; &quot;&gt;float&lt;/span&gt; toWheelTorq = torq * Efficiency / &lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;TopGear * Gear&lt;span style=&quot;color: #a06000&quot;&gt;[&lt;/span&gt;CurrentGear&lt;span style=&quot;color: #a06000&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;
где Efficiency &amp;mdash; это КПД нашей коробки передач (в среднем равно 0.9, у заднеприводных меньше, у полноприводных ещё меньше, у &amp;laquo;УАЗика&amp;raquo; может вообще где-то 0.6), TopGear &amp;mdash; коэффициент редукции главной парой, Gear[] &amp;mdash; массив коэффициентов редукции передачами, CurrentGear &amp;mdash; номер включенной передачи. Таким образом мы подсчитали крутящий момент, который передаётся колёсам.
&lt;p&gt;Далее для примера привожу коэффициенты в КПП для &amp;laquo;двенашки&amp;raquo;:&lt;/p&gt;
&lt;div style=&quot;background: #f2f2f2; padding: 5px; margin: 4px;&quot;&gt;&lt;pre&gt;    TopGear = &lt;span style=&quot;color: #F04000; &quot;&gt;3&lt;/span&gt;.&lt;span style=&quot;color: #F04000; &quot;&gt;9&lt;/span&gt;f;

    Gear&lt;span style=&quot;color: #a06000&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #F04000; &quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;]&lt;/span&gt; = -&lt;span style=&quot;color: #F04000; &quot;&gt;4&lt;/span&gt;.&lt;span style=&quot;color: #F04000; &quot;&gt;0&lt;/span&gt;f; &lt;span style=&quot;color: #808080&quot;&gt;// задняя&lt;/span&gt;
    Gear&lt;span style=&quot;color: #a06000&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #F04000; &quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;]&lt;/span&gt; = &lt;span style=&quot;color: #F04000; &quot;&gt;0&lt;/span&gt;.&lt;span style=&quot;color: #F04000; &quot;&gt;0&lt;/span&gt;f; &lt;span style=&quot;color: #808080&quot;&gt;// нейтраль&lt;/span&gt;
    Gear&lt;span style=&quot;color: #a06000&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #F04000; &quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;]&lt;/span&gt; = &lt;span style=&quot;color: #F04000; &quot;&gt;3&lt;/span&gt;.&lt;span style=&quot;color: #F04000; &quot;&gt;64&lt;/span&gt;f; &lt;span style=&quot;color: #808080&quot;&gt;// первая&lt;/span&gt;
    Gear&lt;span style=&quot;color: #a06000&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #F04000; &quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;]&lt;/span&gt; = &lt;span style=&quot;color: #F04000; &quot;&gt;1&lt;/span&gt;.&lt;span style=&quot;color: #F04000; &quot;&gt;95&lt;/span&gt;f; &lt;span style=&quot;color: #808080&quot;&gt;// вторая&lt;/span&gt;
    Gear&lt;span style=&quot;color: #a06000&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #F04000; &quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;]&lt;/span&gt; = &lt;span style=&quot;color: #F04000; &quot;&gt;1&lt;/span&gt;.&lt;span style=&quot;color: #F04000; &quot;&gt;36&lt;/span&gt;f; &lt;span style=&quot;color: #808080&quot;&gt;// третья&lt;/span&gt;
    Gear&lt;span style=&quot;color: #a06000&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #F04000; &quot;&gt;5&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;]&lt;/span&gt; = &lt;span style=&quot;color: #F04000; &quot;&gt;0&lt;/span&gt;.&lt;span style=&quot;color: #F04000; &quot;&gt;94&lt;/span&gt;f; &lt;span style=&quot;color: #808080&quot;&gt;// четвёртая&lt;/span&gt;
    Gear&lt;span style=&quot;color: #a06000&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #F04000; &quot;&gt;6&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;]&lt;/span&gt; = &lt;span style=&quot;color: #F04000; &quot;&gt;0&lt;/span&gt;.&lt;span style=&quot;color: #F04000; &quot;&gt;78&lt;/span&gt;f; &lt;span style=&quot;color: #808080&quot;&gt;// пятая&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;
&lt;p&gt;КПП также действует и в обратном направлении &amp;mdash; колёса раскручивают мотор. Это проще всего описать несколькими уравнений:&lt;/p&gt;
&lt;table&gt;&lt;tr&gt;&lt;td&gt;&lt;div style=&quot;background: #f2f2f2; padding: 5px; margin: 4px;&quot;&gt;&lt;pre&gt;     &lt;span style=&quot;color: #808080&quot;&gt;// вращение колёс &amp;quot;в моторном расчёте&amp;quot;&lt;/span&gt;
     &lt;span style=&quot;color: #0030fF; &quot;&gt;float&lt;/span&gt; wheelRPM = FastestWheelRotation * TopGear * Gear&lt;span style=&quot;color: #a06000&quot;&gt;[&lt;/span&gt;CurrentGear&lt;span style=&quot;color: #a06000&quot;&gt;]&lt;/span&gt;;

     &lt;span style=&quot;color: #0030fF; &quot;&gt;float&lt;/span&gt; baseTorque = &lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;wheelRPM - RPM&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt; * Clutch / &lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;WheelInertia + EngineInertia&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;;

     &lt;span style=&quot;color: #0030fF; &quot;&gt;float&lt;/span&gt; toEngine = WheelInertia * baseTorque;
     &lt;span style=&quot;color: #0030fF; &quot;&gt;float&lt;/span&gt; toWheels = EngineInertia * baseTorque;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;p&gt;Последние две величины крутящего момента должны быть приложены к мотору и к колёсам соответственно. Возможно это не лучший вариант, так как тут явно что-то не так с величинами измерений, но работает это отлично.&lt;/p&gt;
&lt;p&gt;===1.3 Дифференциал===&lt;/p&gt;
&lt;p style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;http://www.gamedev.ru/files/images/56210_1279190692_5.jpg&quot; alt=&quot;Diff | Пишем симулятор гонок&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Это устройство позволяет вращаться колёсам с разными скоростями и при этом передавать на эти колёса крутящий момент. &lt;/p&gt;
&lt;p&gt;Существуют межколёсные и межосевые дифференциалы. Для гоночных автомобилей часто устанавливают самоблокирующиеся дифференциалы, которые блокируются при появлении крутящего момента, а при его отсутствии дают вращаться колёсам независимо друг от друга.&lt;/p&gt;
&lt;p&gt;На кольцевых и раллийных автомобилях эти дифференциалы управляются электронно, то есть задаётся график степени блокировки в зависимости от крутящего момента. Это позволяет значительно улучшить &amp;laquo;управляемость&amp;raquo; машины.&lt;/p&gt;
&lt;p&gt;Простым способом смоделировать блокирующийся дифференциал явлется выравниваение скоростей вращения колёс, пример для двух колёс:&lt;/p&gt;
&lt;div style=&quot;background: #f2f2f2; padding: 5px; margin: 4px;&quot;&gt;&lt;pre&gt;    &lt;span style=&quot;color: #0030fF; &quot;&gt;float&lt;/span&gt; wheelDiff = Wh&lt;span style=&quot;color: #a06000&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #F04000; &quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;]&lt;/span&gt;.Rotation - Wh&lt;span style=&quot;color: #a06000&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #F04000; &quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;]&lt;/span&gt;.Rotation;

    Wh&lt;span style=&quot;color: #a06000&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #F04000; &quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;]&lt;/span&gt;.Rotation -= wheelDiff * &lt;span style=&quot;color: #F04000; &quot;&gt;0&lt;/span&gt;.&lt;span style=&quot;color: #F04000; &quot;&gt;5&lt;/span&gt;f * DiffForce * Throttle * Clutch;
    Wh&lt;span style=&quot;color: #a06000&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #F04000; &quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;]&lt;/span&gt;.Rotation += wheelDiff * &lt;span style=&quot;color: #F04000; &quot;&gt;0&lt;/span&gt;.&lt;span style=&quot;color: #F04000; &quot;&gt;5&lt;/span&gt;f * DiffForce * Throttle * Clutch;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;
&lt;p&gt;где Wh[].Rotation &amp;mdash; скорость вращения определённого колеса, DiffForce &amp;mdash; значение от 0 до 1 &amp;mdash; сила блокировки дифференциала. В этой формуле также присутсвует множитель Throttle * Clutch, благодаря чему эффект блокировки возникает только при наличии крутящего момента. Если этот множитель убрать, то блокировка на заданную величину будет происходить постоянно.&lt;/p&gt;
&lt;p&gt;==Часть 2: Шасси==&lt;/p&gt;
&lt;p style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;http://www.gamedev.ru/files/images/56211_1279190785_6.jpg&quot; alt=&quot;car box | Пишем симулятор гонок&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Теперь рассмотрим сам автомобиль. Несущий каркас, на котором держится мотор и всё остальное, взаимодействует с землёй посредством шасси.&lt;/p&gt;
&lt;p&gt;Здесь стоит сказать о модели авто, которую мы составляем в стороннем физическом движке, моделирующем поведения твёрдых тел. На рисунке выше представлен пример &amp;mdash; колёса это цилиндры, кузов это бокс, соединены они посредством соединения типа слайдер.&lt;/p&gt;
&lt;p&gt;Ограничения движения этого соединения задают максимальный ход колёс в вертикальном направлении относительно кузова. Теперь рассмотрим подробно это движение.&lt;/p&gt;
&lt;p&gt;===2.1 Амортизаторы===&lt;/p&gt;
&lt;p style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;http://www.gamedev.ru/files/images/56212_1279190902_7.jpg&quot; alt=&quot;shock | Пишем симулятор гонок&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Амортизаторы состоят из двух частей &amp;mdash; демпфирующей и пружинящей &amp;mdash; стойка и пружина. Стойка гасит колебания, а пружина плавно передаёт нагрузку.&lt;/p&gt;
&lt;p&gt;Как работает пружина, думаю, никому объяснять не надо:&lt;/p&gt;
&lt;div style=&quot;background: #f2f2f2; padding: 5px; margin: 4px;&quot;&gt;&lt;pre&gt;    &lt;span style=&quot;color: #0030fF; &quot;&gt;float&lt;/span&gt; force = &lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;CurrentLength - RestLength&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt; * SpringForce;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;
где CurrentLength &amp;mdash; текущая длина пружины, RestLength &amp;mdash; базовая длина пружины, SpringForce &amp;mdash; сила упругости пружины.
&lt;p&gt;Полученная величина очень важна &amp;mdash; это первая величина, которую мы передаём физическому движку, моделирующему физику твёрдых тел. По сути &amp;mdash; это вертикальная сила, она передаётся от амортизатора к кузову в точке чуть выше самого колеса (примерно), а также она передаётся и самому колесу, только в другом направлении.&lt;/p&gt;
&lt;p&gt;Теперь демпфер:&lt;/p&gt;
&lt;div style=&quot;background: #f2f2f2; padding: 5px; margin: 4px;&quot;&gt;&lt;pre&gt;    &lt;span style=&quot;color: #0030fF; &quot;&gt;float&lt;/span&gt; dampForce = ShiftSpeed * Damping;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;
где ShiftSpeed &amp;mdash; скорость сближения/отдаления колеса от кузова, величину эту получаем из физического движка (из соединения слайдер), Damping &amp;mdash; коэффициент демпфирования. По сути это добавка к результирующей силе, которую мы считали чуть выше.
&lt;p&gt;===2.2 Распределение массы===&lt;/p&gt;
&lt;p style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;http://www.gamedev.ru/files/images/56309_1279345698_8.jpg&quot; alt=&quot;car_sim2 | Пишем симулятор гонок&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Вертикальное давление на колесо, как будет показано дальше, сильно влияет на поведение автомобиля. Поэтому факт динамического перемещения давления между четырьмя опорами должен быть обязательно рассмотрен.&lt;/p&gt;
&lt;p&gt;Та сила, которую мы нашли в предыдущем пункте, должна быть сохранена для каждого колеса, так как она нам понадобится, когда мы будем считать трение колёс.&lt;/p&gt;
&lt;p&gt;Учтите также, что из-за расположения мотора не по середине мы имеем не равномерное распределение массы в состоянии покоя (на скриншоте выше машина затормаживает, не беспокойтесь). Если мотор спереди (чаще всего, но не всегда), то нагрузка на переднюю ось будет больше. У некоторых машин распределено 65% на переднюю ось и 35% на заднюю. У хороших машин, даже если мотор спереди, нагрузка может быть 50/50, но в большинстве случаев где-то 60/40.&lt;/p&gt;
&lt;p&gt;===2.3 Кинематика подвески===&lt;/p&gt;
&lt;p&gt;Пункт в принципе не обязательный, но если вы пишете серьёзный симулятор, то на это тоже следует обратить внимание.&lt;/p&gt;
&lt;p&gt;Необходимо задать значения углов каждого колеса, таких как сход/развал (см. дальше), в зависимости от текущего положения и поворота колеса. На рисунка далее видно, как в реальности изменяются углы.&lt;/p&gt;
&lt;p style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;http://www.gamedev.ru/files/images/56221_1279192945_16.jpg&quot; alt=&quot;kinematic | Пишем симулятор гонок&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Это даёт ощутимый эффект в управляемости.&lt;/p&gt;
&lt;p style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;http://www.gamedev.ru/files/images/56215_1279191621_10.jpg&quot; alt=&quot;susp kinematic | Пишем симулятор гонок&quot; /&gt;&lt;/p&gt;
&lt;p&gt;==Часть 3: Сцепление шин с дорогой==&lt;/p&gt;
&lt;p&gt;===3.1 Вращательное и поступательное движения колёс===&lt;/p&gt;
&lt;p style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;http://www.gamedev.ru/files/images/56216_1279192066_11.jpg&quot; alt=&quot;wheel | Пишем симулятор гонок&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Отчего вращаются колёса? Ну для начала от нашего мотора. Мы посчитали крутящий момент, который на них передаётся, осталось только его приложить:&lt;/p&gt;
&lt;div style=&quot;background: #f2f2f2; padding: 5px; margin: 4px;&quot;&gt;&lt;pre&gt;    Rotation += Torque / Inerita;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;
где Torque &amp;mdash; приложенный крутящий момент, Inertia &amp;mdash; инерция колеса.
&lt;p&gt;Отчего же двигаются колёса? Двигает их связь с кузовом, то есть исходит это от физического движка. Следует отметить, что рассмотрению подвергнутся продольные и поперечные скорости движения, как показано на рисунке выше.&lt;/p&gt;
&lt;p&gt;===3.2 Тормозные механизмы===&lt;/p&gt;
&lt;p&gt;Тормоза устроены просто, но и тут есть небольшие нюансы. Во-первых, это ручной тормоз, я покажу как правильно его сделать и почему от него &amp;laquo;заносит&amp;raquo;, а во-вторых, это распределение тормозного усилия.&lt;/p&gt;
&lt;p&gt;Обычно при торможении вертикальная нагрузка на передние колёса значительно больше, чем на задние, поэтому передние колёса могут тормозить лучше.&lt;/p&gt;
&lt;div style=&quot;background: #f2f2f2; padding: 5px; margin: 4px;&quot;&gt;&lt;pre&gt;    Rotation -= BrakesForce * BrakesFrontPart * BrakesState / Inertia;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;
где BrakesForce &amp;mdash; сила тормозов, BrakesFrontPart &amp;mdash; процент усилия для передней оси (для задней оси будет 1.0f – BrakesFrontPart, если кто не понял), BrakesState &amp;mdash; процент нажатия тормоза, Inertia &amp;mdash; инерция колеса.
&lt;p&gt;Ручной тормоз устроен аналогично, только действует он исключительно на задние колёса:&lt;/p&gt;
&lt;div style=&quot;background: #f2f2f2; padding: 5px; margin: 4px;&quot;&gt;&lt;pre&gt;    Rotation -= HandBrakeForce * HandBrakeState / Inertia;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;
где HandBrakeForce &amp;mdash; сила ручного тормоза, HandBrakeState &amp;mdash; процент нажатия тормоза, Inertia &amp;mdash; инерция колеса.
&lt;p&gt;Отчего же машины так классно заносит когда дёргаешь ручник? Передние колёса при этом не теряют сцепления, так как ничего не меняется, а задние блокируются, отчего появляется скольжение и задняя ось начинает пытаться обогнать переднюю, что и называется занос.&lt;/p&gt;
&lt;p&gt;Для общего развития &amp;mdash; ещё есть понятие &amp;laquo;снос&amp;raquo; &amp;mdash; это когда передняя ось скользит, а задняя нет, то есть обратная ситуация заносу.&lt;/p&gt;
&lt;p&gt;===3.3 Трение шин===&lt;/p&gt;
&lt;p&gt;Самая важная часть. Я предпочитаю рассматривать продольное и поперечное трение в отдельности, хотя можно работать и с векторами. Просто плоские графики лучше воспринимаются.&lt;/p&gt;
&lt;p&gt;Итак, в зависимости от скорости скольжения двух поверхностей относительно друг друга, сила трения между ними изменяется. Для колёс этот график может выглядеть так:&lt;/p&gt;
&lt;p style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;http://www.gamedev.ru/files/images/56217_1279192229_12.jpg&quot; alt=&quot;tire fric | Пишем симулятор гонок&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Как видим, чем сильнее скольжение, тем меньше сила. Это так для асфальта, но например не так для гравия &amp;mdash; этот график может быть сильно изменён, всё зависит от покрытия и типа шин. С этим приходится экспериментировать.&lt;/p&gt;
&lt;p&gt;Рассмотрим сначала поперечную силу &amp;mdash; с ней всё просто. У нас есть скорость поперечного движения колеса (из физеского движка) &amp;mdash; это и есть скорость скольжения. При помощи графика мы получаем поперечную силу, действующую на колесо:&lt;/p&gt;
&lt;div style=&quot;background: #f2f2f2; padding: 5px; margin: 4px;&quot;&gt;&lt;pre&gt;    &lt;span style=&quot;color: #0030fF; &quot;&gt;float&lt;/span&gt; lateralForce = TireFriction&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;LateralSpeed&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt; * ShiftForce * Friction;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;
где TireFriction() &amp;mdash; наш график трения, ShiftForce &amp;mdash; вертикальная нагрузка на колесе, Friction &amp;mdash; коэффициент трения. 
&lt;br /&gt;Полученную величину передаём физическому движку, пусть приложит её к колесу в поперечном направлении.
&lt;p&gt;Теперь рассмотрим продольную силу. Тут всё немного сложнее, так как необходимо учесть вращение колеса.
&lt;br /&gt;У нас есть продольная и вращательная скорость, найдём скольжение:&lt;/p&gt;
&lt;div style=&quot;background: #f2f2f2; padding: 5px; margin: 4px;&quot;&gt;&lt;pre&gt;    &lt;span style=&quot;color: #0030fF; &quot;&gt;float&lt;/span&gt; longSlip = LongSpeed - Rotation * &lt;span style=&quot;color: #F04000; &quot;&gt;2&lt;/span&gt;.&lt;span style=&quot;color: #F04000; &quot;&gt;0&lt;/span&gt;f * Pi * Radius;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;
где LongSpeed &amp;mdash; продольная скорость колеса, Rotation &amp;mdash; вращение колеса, Radius &amp;mdash; радиус колеса.
&lt;p&gt;Теперь рассчитываем возникающую силу трения в продольном направлении:&lt;/p&gt;
&lt;div style=&quot;background: #f2f2f2; padding: 5px; margin: 4px;&quot;&gt;&lt;pre&gt;    &lt;span style=&quot;color: #0030fF; &quot;&gt;float&lt;/span&gt; longForce = TireFriction&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;longSlip&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt; * ShiftForce * Friction;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;
&lt;p&gt;Две полученые величины &amp;mdash; продольная и поперечная сила не могут быть максимальными одновременно, тут необходимо действует правило &amp;laquo;окружность трения&amp;raquo;, известное среди профессиональных гонщиков:&lt;/p&gt;
&lt;p style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;http://www.gamedev.ru/files/images/56218_1279192555_13.jpg&quot; alt=&quot;firction circle | Пишем симулятор гонок&quot; /&gt;&lt;/p&gt;
&lt;p&gt;В некоторых случаях это может быть эллипс.&lt;/p&gt;
&lt;p&gt;Следует также отметить, что ещё необходимо учесть угол поворота руля, если вы рассматриваете локальную систему координат при получении продольной и поперечной скоростей, а также при приложении таких сил, то проблем не возникнет. Да и в противном случае необходимы лишь некоторые векторные преобразования.&lt;/p&gt;
&lt;p&gt;===3.4 Сход/развал===&lt;/p&gt;
&lt;p style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;http://www.gamedev.ru/files/images/56219_1279192654_14.jpg&quot; alt=&quot;wheel angles | Пишем симулятор гонок&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Со сходом всё просто &amp;mdash; задаём углы при расположении тел в физическом движке. Эффект проявится сам. Если Вы знакомы с такими понятиями и в жизни их ощущали, то сразу заметите, в противном случае можете не моделировать сход.&lt;/p&gt;
&lt;p&gt;В случае развала у нас появляется дополнительная зависимость величины результирующей силы трения от угла наклона колеса.&lt;/p&gt;
&lt;p style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;http://www.gamedev.ru/files/images/56220_1279192747_15.jpg&quot; alt=&quot;wa2 | Пишем симулятор гонок&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Трение максимально, когда колесо стоит перпендикулярно, но в поворотах, когда весь автомобиль кренится и подвеска сжимается &amp;mdash; угол колеса меняется. Именно для этого иногда выставляют небольшой угол развала. У гоночных машин он бывает огромным.&lt;/p&gt;
&lt;p&gt;Не сложно догадаться, что эффект от этого тоже не маленький. Дело в том, что когда мы едем по прямой &amp;mdash; нас не сильно волнует насколько хорошо сцепление с дорогой, а когда мы заезжаем в поворот &amp;mdash; у внешних колёс (на них максимальная нагрузка от распределённой массы) сцепление становится максимальным, потому что они в повороте оказываются перпендикулярно плоскости дороги &amp;mdash; пятно контакта шины с дорогой имеет в данном случае максимальную площадь. И всё это благодаря выставленному развалу.&lt;/p&gt;
&lt;p&gt;===3.5 Давление в шинах, уводы и подламывания===&lt;/p&gt;
&lt;p style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;http://www.gamedev.ru/files/images/56307_1279345626_17.jpg&quot; alt=&quot;car_sim1 | Пишем симулятор гонок&quot; /&gt;&lt;/p&gt;
&lt;p&gt;В жизни шины мягкие. В гонках это редко, но тоже встречается.&lt;/p&gt;
&lt;p&gt;На самом деле смоделировать это очень просто &amp;mdash; представим шину в виде пружины, чем больше она растянута, тем больше силы она передаёт. Чем выше давление, тем жестче пружина. Таким образом достигается эффект подламывания шины, благодаря которому создаётся невероятная реалистичность &amp;mdash; каждый гонщик хорошо знает, что от давления в шинах, от жёсткости их боковины и их профиля сильно зависит поведение машины на дороге.&lt;/p&gt;
&lt;p style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;http://www.gamedev.ru/files/images/56656_1280043318_19.jpg&quot; alt=&quot;Soft tyres | Пишем симулятор гонок&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Сила трения передаётся мнимому (дополнительному телу), возникает разница в поперечном положении двух тел. &lt;/p&gt;
&lt;p&gt;Далее всё просто: находим силу, действующую на основное тело, используя либо линейное уравнение F = kx , либо опять же строим нужный график для пущей реалистичности. Требования к зависимости следующие: сила стремится к нулю, если x стремится к нулю; сила стремится к бесконечности при x большем, чем ширина шины. Конечно на практике бесконечность не применима, поэтому результирующая сила ограничивается сверху силой трения. &lt;/p&gt;
&lt;p&gt;Напомню также, что результирующая сила действует на оба тела.&lt;/p&gt;
&lt;p style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;http://www.gamedev.ru/files/images/56306_1279345599_18.jpg&quot; alt=&quot;car sim | Пишем симулятор гонок&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Это всё, что необходимо знать об автомобиле, если Вы решили написать симулятор гонок.&lt;/p&gt;
&lt;p&gt;Дополнительно выкладываю видео, качество ужасное, но смотреть можно. Если постараться, то можно углядеть мягкие шины :)&lt;/p&gt;
&lt;p style=&quot;text-align: center&quot;&gt;&lt;object width=&quot;640&quot; height=&quot;385&quot;&gt;&lt;param name=&quot;movie&quot; value=&quot;http://www.youtube.com/v/AERHbhHbWc8&amp;amp;color1=0xb1b1b1&amp;amp;color2=0xcfcfcf&amp;amp;hl=ru_RU&amp;amp;feature=player_embedded&amp;amp;fs=1&quot;&gt;&lt;/param&gt;&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot;&gt;&lt;/param&gt;&lt;param name=&quot;allowScriptAccess&quot; value=&quot;always&quot;&gt;&lt;/param&gt;&lt;param name=&quot;wmode&quot; value=&quot;transparent&quot;&gt;&lt;/param&gt;&lt;embed src=&quot;http://www.youtube.com/v/AERHbhHbWc8&amp;amp;color1=0xb1b1b1&amp;amp;color2=0xcfcfcf&amp;amp;hl=ru_RU&amp;amp;feature=player_embedded&amp;amp;fs=1&quot; type=&quot;application/x-shockwave-flash&quot; wmode=&quot;transparent&quot; allowfullscreen=&quot;true&quot; allowScriptAccess=&quot;always&quot; width=&quot;640&quot; height=&quot;385&quot;&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/p&gt;</description>
</item>
<item>
  <guid isPermaLink="true">http://www.gamedev.ru/code/articles/DDS_DXT1_DXT3_DXT5</guid>
  <pubDate>Fri, 16 Jul 2010 16:32:17 GMT</pubDate>
  <title>Графические файлы DDS. Что лучше: DXT1, DXT3, DXT5?</title>
  <link>http://www.gamedev.ru/code/articles/DDS_DXT1_DXT3_DXT5</link>
  <comments>http://www.gamedev.ru/code/forum/?id=135813</comments>
  <category>Графика</category>
  <category>DDS</category>
  <category>графика</category>
  <category>текстуры</category>
  <description>
&lt;p&gt;Файлы DDS. Описание формата DXTn, его возможностей, простые рекомендации по выбору формата компрессии. 
&lt;p&gt;&lt;b&gt;DDS файлы&lt;/b&gt; &amp;mdash; изображения, в которых данные хранятся так же, как в видеопамяти (включая мипмапы). Это позволяет их быстро загружать в игре. В DDS могут храниться объёмные текстуры, куб-мапы и прочие необычные (для графических файлов) вещи.
&lt;p&gt;2D слои в DDS-файле могут храниться в RGBA формате, а могут быть сжаты в форматы DXT1, DXT3, DXT5.&lt;/p&gt;
&lt;p&gt;Это сжатие с потерями, как Jpeg. Оно было специально разработано для того, чтобы видеокарта могла &amp;laquo;расжимать&amp;raquo; гигабайт текстур за секунду, отображая на экране сжатую текстуру сразу из видеопамяти, без промежуточного конвертирования.&lt;/p&gt;
&lt;p&gt;DXT1 &amp;mdash; для RGB картинок c однобитной альфой, четыре бита на пиксел (сжатие в 8 раз по сравнению с RGBX).
&lt;br /&gt;DXT3 и DXT5 &amp;mdash; для картинок с альфа-каналом, типично DXT5 лучше. 8 бит на пиксел, сжатие в четыре раза.&lt;/p&gt;
&lt;h3&gt;Подробней про метод сжатия, на уровне битов:&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;http://www.gamedev.ru/files/images/2010-07-16__15-04-09_9kb.png&quot; alt=&quot;2010-07-16__15-04-09_9kb | Графические файлы DDS. Что лучше: DXT1, DXT3, DXT5?&quot; /&gt; 
&lt;p&gt;Изображение делится на блоки 4x4. Для каждого блока хранится два 16-битных цвета. При распаковке из двух цветов x,y генерится четыре последовательных цвета, палитра [x, &amp;#8532;x + &amp;#8531;y, &amp;#8531;x + &amp;#8532;y, y]. После 2*16 бит цветов хранится 4*4 двухбитых индексов в эту палитру. Порядок двух цветов (цвет_0 &amp;gt; цвет_1 ?) также содержит один бит информации. Если цвет_0 &amp;gt; цвет_1, то в палитре одно из значений используется как нулевая альфа, и остальные 3 цвета [x, &amp;#189;x + &amp;#189;y, y] &amp;mdash; палитра из непрозрачных цветов. Всего получается 64 бита на блок 4x4 пиксела.&lt;/p&gt;
&lt;p&gt;В DXT3 и DXT5 rgb-канал хранится точно так же как в DXT1. Альфа в DXT3 хранится просто как округлённое с 8 битов до 4 битов на пиксел, без сжатия. В DXT5 для альфы используется метод сжатия, похожий на метод для RGB в DXT1. Два значения альфы на блок 4x4. Если цвет_0 &amp;gt; цвет_1, создаётся 6 промежуточных значений альфы в палитре и ещё отдельно два особых значения 0 и 1 для альфы. Если цвет_0 &amp;lt;= цвет_1, то из двух крайних значений альфы создаётся 8 промежуточных. После двух 8-битных граничных значений альфы идёт 16 3-битных индексов.&amp;nbsp; DXT5 обычно гораздо точней сохраняет альфу и рекомендуется вместо DXT3.&lt;/p&gt;
&lt;p&gt;Артефакты после сжатия малозаметны, чаще всего их можно увидеть в блоках, где сходится 3 разных оттенка (3 оттенка в 2-х на один блок не помещаются).&lt;/p&gt;
&lt;p&gt;DXT2 раскодируется так же как DXT3, а DXT4 так же как DXT5, только программа должна интерпретировать RGB как уже умноженный на альфу. В них хранится флажок &amp;laquo;premultiplied alpha&amp;raquo;, который может быть интересен универсальной смотрелке картинок, но не игровому движку.&lt;/p&gt;
&lt;p&gt;Это сжатие с потерями, паковщик должен выбрать два идеальных цвета для квадрата 4x4, поэтому разные инструменты могут конвертировать с разным соотношением время работы/качество результата (см. иллюстрацию в конце). NVidia хвастается, что её nvcompress лучший, не знаю насколько справедливо. На глаз вроде результат лучше, чем у TEXCONV из D3D SDK.&lt;/p&gt;
&lt;p&gt;При сжатии DXT в zip имеет смысл разделить индексы и палитру, хранить приращения. Тогда сожмётся чуть лучше. Увы сам не мерял, только напел. Если вы пробовали &amp;mdash; напишите, интересно.&lt;/p&gt;
&lt;p&gt;Можно чуть-чуть &amp;laquo;подвигать&amp;raquo; ползунок качество/сжатие таким образом: перед DXT-сжатием использовать текстуру которая в 2 раза больше, если такая есть. Например, уменьшить то, что нарисовал художник не с 4096x4096 до 128x128x, а до 256x256.&lt;/p&gt;
&lt;h3&gt;Итого:&lt;/h3&gt;
&lt;p&gt;Если картинка без альфы или достаточно однобитной альфы, используйте DXT1. С альфой &amp;mdash; DXT5. На &amp;laquo;мультяшных&amp;raquo; картинках с мелкими деталями будут артефакты, на реалистичных текстурах с шумом и градиентом компрессия незаметна.&lt;/p&gt;
&lt;h3&gt;Иллюстрация (масштаб 200%):&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;http://www.gamedev.ru/files/images/nya2010-07-17__23-32-40_68kb_1_.png&quot; alt=&quot;dxt1 texture | Графические файлы DDS. Что лучше: DXT1, DXT3, DXT5?&quot; /&gt;</description>
</item>
<item>
  <guid isPermaLink="true">http://www.gamedev.ru/code/terms/Genetic_Algorithm</guid>
  <pubDate>Thu, 15 Jul 2010 17:54:03 GMT</pubDate>
  <title>Генетический алгоритм</title>
  <link>http://www.gamedev.ru/code/terms/Genetic_Algorithm</link>
  <comments>http://www.gamedev.ru/code/forum/?id=136061</comments>
  <category>Игровая логика и ИИ</category>
  <category>ИИ</category>
  <category>algorithms</category>
  <category>genetic</category>
  <description>
&lt;p&gt;&lt;b&gt;Генетический алгоритм&lt;/b&gt; &amp;mdash; это алгоритм поиска решения определённой задачи, основанный на эвристике. Круг решаемых задач несколько узок: в основном, это задачи оптимизации и моделирования. Поиск решения осуществляется путём случайного подбора, комбинирования и вариации искомых параметров с использованием методов, напоминающих биологическую эволюцию.&lt;p&gt;Генетический алгоритм является разновидностью эволюционных вычислений.&lt;/p&gt;
&lt;p&gt;Задача кодируется таким образом, чтобы её решение можно было представить в виде набора коэффициентов &amp;mdash; генов. Это, пожалуй, единственное ограничение, и если это возможно, то задача вполне успешно будет решаться генетическим алгоритмом. То есть основная сложность &amp;mdash; представление (интерпретация) решения задачи в необходимом виде.&lt;/p&gt;
&lt;p&gt;Первоначально создаётся первая популяция (набор решений), гены которой определены случайным образом, в след за этим для каждого варианта решения определяется значение fitness-функции.&lt;/p&gt;
&lt;p&gt;Fitness-функция &amp;mdash; это целевая функция, то есть мера точности решения или мера удовлетворения решению задачи. Увеличением значения fitness-функции и занимается генетический алгоритм.&lt;/p&gt;
&lt;p&gt;Определив fitness-функции и подсчитав их для каждого варианта, отбираются лучшие гены, которые будут переданы следующему поколению вариантов решений. Таким образом, через несколько поколений будет найдено (если это возможно) хорошее решение поставленной задачи.&lt;/p&gt;
&lt;p&gt;В качестве примера привожу график из моей статьи (ИжГТУ 2008) :&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://www.gamedev.ru/files/images/zz_graph.jpg&quot; alt=&quot;GA_graph | Генетический алгоритм&quot; /&gt;
&lt;p&gt;На графике представлены максимальные и средние из всей популяции значения фитнесс-функции для каждой эпохи. Коэффициенты подбирались для нейронной сети, задача была не простая &amp;mdash; обучение механизмов правильному движению. И тем не менее, за небольшое количество эпох уже был найден хороший вариант.&lt;/p&gt;
&lt;p&gt;В качестве дополнения привожу одну из моих реализаций генетического алгоритма, простой и одновременно отличный вариант:&lt;/p&gt;
&lt;div style=&quot;background: #f2f2f2; padding: 5px; margin: 4px;&quot;&gt;&lt;pre&gt;&lt;span style=&quot;color: #0030fF; &quot;&gt;void&lt;/span&gt; GeneticPool::Evolve&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #0030fF; &quot;&gt;int&lt;/span&gt; diversity, &lt;span style=&quot;color: #0030fF; &quot;&gt;float&lt;/span&gt; mutationPower&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;           
{
     SortByFitness&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;; &lt;span style=&quot;color: #808080&quot;&gt;// сортировка генов&lt;/span&gt;

     &lt;span style=&quot;color: #0030fF; &quot;&gt;for&lt;/span&gt; &lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #0030fF; &quot;&gt;int&lt;/span&gt; i = diversity; i &lt;span style=&quot;color: #a06000&quot;&gt;&amp;lt;&lt;/span&gt; genesCount; i++&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;
     {
           Genes&lt;span style=&quot;color: #a06000&quot;&gt;[&lt;/span&gt;i&lt;span style=&quot;color: #a06000&quot;&gt;]&lt;/span&gt; = MutateGenes&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;Genes&lt;span style=&quot;color: #a06000&quot;&gt;[&lt;/span&gt;RandomInt&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;diversity&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;]&lt;/span&gt;, MutationPower&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;;
     }
}&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;
&lt;p&gt;Значение diversity определяет количество особей, гены которых будут переданы следующему поколению. Сами эти особи изменению не подвергнутся, дабы не потерять лучшие решения. Таким образом мы получили отличный вариант генетического алгоритма.&lt;/p&gt;</description>
</item>
<item>
  <guid isPermaLink="true">http://www.gamedev.ru/code/articles/GPU_Global_Illumination</guid>
  <pubDate>Sun, 27 Jun 2010 10:44:02 GMT</pubDate>
  <title>GPU Global Illumination (фейковый)</title>
  <link>http://www.gamedev.ru/code/articles/GPU_Global_Illumination</link>
  <comments>http://www.gamedev.ru/code/forum/?id=135032</comments>
  <category>Графика</category>
  <category>GPU</category>
  <category>indirect illumination</category>
  <description>
&lt;p&gt;В этой статье будет обсуждаться реализация Глобально Освещения (Global Illumination) с использованием GPU, а фейк весь в том, что мы всё-таки будем использовать и CPU – для трассировки &amp;laquo;фотонов&amp;raquo;.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;http://www.gamedev.ru/files/images/images.jpeg&quot; alt=&quot;images | GPU Global Illumination (фейковый)&quot; /&gt;
&lt;p&gt;В этой статье будет больше теории, чем практики, хотя и псевдокода есть немного.&lt;/p&gt;
&lt;p&gt;Итак, приступим. Для начала уясним, что такое Indirect-Illumination (ненаправленный свет). Пока то, что мы сейчас видим в играх &amp;mdash; это Direct Illumination (направленный свет).&lt;/p&gt;
&lt;p&gt;Направленный свет:
&lt;/p&gt;&lt;p style=&quot;text-align:center&quot;&gt;
&lt;br /&gt;&lt;img src=&quot;http://www.gamedev.ru/files/images/direct_illumination.gif&quot; alt=&quot;direct_illumination | GPU Global Illumination (фейковый)&quot; /&gt;
&lt;br /&gt;&lt;i&gt;Направленный свет схематично.&lt;/i&gt;&lt;/p&gt;
&lt;p style=&quot;text-align:center&quot;&gt;
&lt;br /&gt;&lt;img src=&quot;http://www.gamedev.ru/files/images/local_illumination.jpg&quot; alt=&quot;Local_illumination | GPU Global Illumination (фейковый)&quot; /&gt;
&lt;br /&gt;&lt;i&gt;Направленный свет в сцене.&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;Ненаправленный свет:
&lt;/p&gt;&lt;p style=&quot;text-align:center&quot;&gt;
&lt;br /&gt;&lt;img src=&quot;http://www.gamedev.ru/files/images/indirect_illumination.gif&quot; alt=&quot;indirect_illumination | GPU Global Illumination (фейковый)&quot; /&gt;
&lt;br /&gt;&lt;i&gt;Неправленный свет схематично.&lt;/i&gt;&lt;/p&gt;
&lt;p style=&quot;text-align:center&quot;&gt;
&lt;br /&gt;&lt;img src=&quot;http://www.gamedev.ru/files/images/global_illumination.jpg&quot; alt=&quot;Global_illumination | GPU Global Illumination (фейковый)&quot; /&gt;
&lt;br /&gt;&lt;i&gt;Ненаправленный свет в сцене.&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;Как видим по картинкам, при одной направленной иллюминации у нас не идёт отражение света от поверхностей, что физически неправильно, хотя в принципе это можно компенсировать лайтмапами, в которые запечена ненаправленная иллюминация, но это не так качественно как хотелось бы, и нельзя использовать для динамической геометрии.&lt;/p&gt;
&lt;p&gt;Итак, на счёт моей идеи фейкового глобального освещения. Для каждой модели создаём текстуру R8G8B8 произвольного размера (всё зависит от количества видео памяти у видеокарты), но чем текстура больше, тем качественее картинка будет в итоге, делаем вторую uv развёртку для модели под эту текстуру (такую же как и для Lightmap или Ambient Map).&lt;/p&gt;
&lt;p&gt;Далее нам нужен будет специальный источник света, так как всё-таки от всех источников получить ненаправленную иллюминацию не получится ввиду большого кол-ва расчётов.&lt;/p&gt;
&lt;table&gt;&lt;tr&gt;&lt;td&gt;&lt;div style=&quot;background: #f2f2f2; padding: 5px; margin: 4px;&quot;&gt;&lt;pre&gt;&lt;span style=&quot;color: #0030fF; &quot;&gt;class&lt;/span&gt; IndirectLight{
&lt;span style=&quot;color: #0030fF; &quot;&gt;public&lt;/span&gt;:
  &lt;span style=&quot;color: #808080&quot;&gt;// позиция источника&lt;/span&gt;
  float3 position;

  &lt;span style=&quot;color: #808080&quot;&gt;// цвет источника&lt;/span&gt;
  float3 radiant;

  &lt;span style=&quot;color: #808080&quot;&gt;// радиус источника&lt;/span&gt;
  &lt;span style=&quot;color: #0030fF; &quot;&gt;float&lt;/span&gt;  radius;

  &lt;span style=&quot;color: #808080&quot;&gt;// интервал апдейта&lt;/span&gt;
  &lt;span style=&quot;color: #0030fF; &quot;&gt;int&lt;/span&gt;    updateInterval;

  &lt;span style=&quot;color: #808080&quot;&gt;// время прошлого апдейта&lt;/span&gt;
  &lt;span style=&quot;color: #0030fF; &quot;&gt;int&lt;/span&gt;    time;

  IndirectLight&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt; {
    radiant = float3&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #F04000; &quot;&gt;1&lt;/span&gt;.&lt;span style=&quot;color: #F04000; &quot;&gt;0&lt;/span&gt;f,&lt;span style=&quot;color: #F04000; &quot;&gt;1&lt;/span&gt;.&lt;span style=&quot;color: #F04000; &quot;&gt;0&lt;/span&gt;f,&lt;span style=&quot;color: #F04000; &quot;&gt;1&lt;/span&gt;.&lt;span style=&quot;color: #F04000; &quot;&gt;0&lt;/span&gt;f&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;;
    radius = &lt;span style=&quot;color: #F04000; &quot;&gt;1&lt;/span&gt;.&lt;span style=&quot;color: #F04000; &quot;&gt;0&lt;/span&gt;f;
    updateInterval = -&lt;span style=&quot;color: #F04000; &quot;&gt;1&lt;/span&gt;;
  }

  IndirectLight&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt; &lt;span style=&quot;color: #0030fF; &quot;&gt;const&lt;/span&gt; float3&amp;amp; radiant , &lt;span style=&quot;color: #0030fF; &quot;&gt;float&lt;/span&gt; radius , &lt;span style=&quot;color: #0030fF; &quot;&gt;int&lt;/span&gt; updateInterval = -&lt;span style=&quot;color: #F04000; &quot;&gt;1&lt;/span&gt; &lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;{
    &lt;span style=&quot;color: #0030fF; &quot;&gt;this&lt;/span&gt;-&lt;span style=&quot;color: #a06000&quot;&gt;&amp;gt;&lt;/span&gt;radiant = radiant;
    &lt;span style=&quot;color: #0030fF; &quot;&gt;this&lt;/span&gt;-&lt;span style=&quot;color: #a06000&quot;&gt;&amp;gt;&lt;/span&gt;radius = radius;
    &lt;span style=&quot;color: #0030fF; &quot;&gt;this&lt;/span&gt;-&lt;span style=&quot;color: #a06000&quot;&gt;&amp;gt;&lt;/span&gt;updateInterval = updateInterval;
  }

  ~IndirectLight&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;{
  }
};&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;p&gt;Также нам понадобится класс процессора, который будет отвечать за обновление ненаправленной иллюминации.
&lt;div style=&quot;background: #f2f2f2; padding: 5px; margin: 4px;&quot;&gt;&lt;pre&gt;&lt;span style=&quot;color: #0030fF; &quot;&gt;class&lt;/span&gt; IndirectProcessor{
&lt;span style=&quot;color: #0030fF; &quot;&gt;public&lt;/span&gt;:
  std::vector&lt;span style=&quot;color: #a06000&quot;&gt;&amp;lt;&lt;/span&gt; IndirectLight* &lt;span style=&quot;color: #a06000&quot;&gt;&amp;gt;&lt;/span&gt; emiterList;

  IndirectProcessor&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt; {
  }

  ~IndirectProcessor&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;{
  }

  &lt;span style=&quot;color: #808080&quot;&gt;// Добавление нового источника &lt;/span&gt;
  &lt;span style=&quot;color: #0030fF; &quot;&gt;void&lt;/span&gt; addEmiter&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt; IndirectLight* emiter &lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;{
    removeEmiter&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;emiter&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;;
    emiterList.push_back&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;emiter&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;;
  }

  &lt;span style=&quot;color: #808080&quot;&gt;// Удаление источника из списка&lt;/span&gt;
  &lt;span style=&quot;color: #0030fF; &quot;&gt;void&lt;/span&gt; removeEmiter&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt; IndirectLight* emiter &lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;{
    &lt;span style=&quot;color: #0030fF; &quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt; std::vector&lt;span style=&quot;color: #a06000&quot;&gt;&amp;lt;&lt;/span&gt; IndirectLight* &lt;span style=&quot;color: #a06000&quot;&gt;&amp;gt;&lt;/span&gt;::iterator it = emiterList.begin&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;;
         it != emiterList.end&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;; it++ &lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;{
      &lt;span style=&quot;color: #0030fF; &quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt; &lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;*it&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt; == emiter &lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt; {
        emiterList.erase&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;it&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;;
        &lt;span style=&quot;color: #0030fF; &quot;&gt;return&lt;/span&gt;;
      }
    }
  }

  &lt;span style=&quot;color: #808080&quot;&gt;// Обновление источника&lt;/span&gt;
  &lt;span style=&quot;color: #0030fF; &quot;&gt;void&lt;/span&gt; updateEmiter&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt; IndirectLight* emiter &lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;{
    &lt;span style=&quot;color: #808080&quot;&gt;// TODO&lt;/span&gt;
  }

  &lt;span style=&quot;color: #808080&quot;&gt;// Процессинг&lt;/span&gt;
  &lt;span style=&quot;color: #0030fF; &quot;&gt;void&lt;/span&gt; processFrame&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt; &lt;span style=&quot;color: #0030fF; &quot;&gt;int&lt;/span&gt; time &lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;{
    &lt;span style=&quot;color: #0030fF; &quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt; std::vector&lt;span style=&quot;color: #a06000&quot;&gt;&amp;lt;&lt;/span&gt; IndirectLight* &lt;span style=&quot;color: #a06000&quot;&gt;&amp;gt;&lt;/span&gt;::iterator it = emiterList.begin&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;;
         it != emiterList.end&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;; it++ &lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;{
      IndirectLight* emiter = &lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;*it&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;;

      &lt;span style=&quot;color: #808080&quot;&gt;// Проверяем, если апдейт интервал равен -1 или 0,&lt;/span&gt;
      &lt;span style=&quot;color: #808080&quot;&gt;// то значит обнавлять такой источник придётя каждый кадр&lt;/span&gt;
      &lt;span style=&quot;color: #808080&quot;&gt;// что не очень хорошо, но всё же...&lt;/span&gt;
      &lt;span style=&quot;color: #0030fF; &quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt; emiter-&lt;span style=&quot;color: #a06000&quot;&gt;&amp;gt;&lt;/span&gt;updateInterval == -&lt;span style=&quot;color: #F04000; &quot;&gt;1&lt;/span&gt; || emiter-&lt;span style=&quot;color: #a06000&quot;&gt;&amp;gt;&lt;/span&gt;updateInterval == &lt;span style=&quot;color: #F04000; &quot;&gt;0&lt;/span&gt; &lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;{
        updateEmiter&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;emiter&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;;
        &lt;span style=&quot;color: #0030fF; &quot;&gt;continue&lt;/span&gt;;
      }

      &lt;span style=&quot;color: #808080&quot;&gt;// Если текущее время источника равно -1,&lt;/span&gt;
      &lt;span style=&quot;color: #808080&quot;&gt;// то значит источник ещё ни разу не обновлялся&lt;/span&gt;
      &lt;span style=&quot;color: #0030fF; &quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt; emiter-&lt;span style=&quot;color: #a06000&quot;&gt;&amp;gt;&lt;/span&gt;time == -&lt;span style=&quot;color: #F04000; &quot;&gt;1&lt;/span&gt; &lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt; {
        updateEmiter&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;emiter&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;;
        emiter-&lt;span style=&quot;color: #a06000&quot;&gt;&amp;gt;&lt;/span&gt;time = time;
        &lt;span style=&quot;color: #0030fF; &quot;&gt;continue&lt;/span&gt;;
      }

      &lt;span style=&quot;color: #808080&quot;&gt;// Прибавляем к прошлому времени источника апдейт интервал&lt;/span&gt;
      &lt;span style=&quot;color: #808080&quot;&gt;// и если то, что у нас получилось равно текущему времени:&lt;/span&gt;
      &lt;span style=&quot;color: #0030fF; &quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt; emiter-&lt;span style=&quot;color: #a06000&quot;&gt;&amp;gt;&lt;/span&gt;time + emiter-&lt;span style=&quot;color: #a06000&quot;&gt;&amp;gt;&lt;/span&gt;updateInterval == time &lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;{  
        updateEmiter&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;emiter&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;;
        emiter-&lt;span style=&quot;color: #a06000&quot;&gt;&amp;gt;&lt;/span&gt;time = time;
      }
    }
  }
};&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;Итак, все затраты заключаются в том, что нам придётся трассировать лучи от источников, нам придётся трассировать от каждого источника N лучей с рандомным направлением + K отражений каждого луча.&lt;/p&gt;
&lt;p&gt;Обновляем наш класс источника, добавим в него N и K:&lt;/p&gt;
&lt;table&gt;&lt;tr&gt;&lt;td&gt;&lt;div style=&quot;background: #f2f2f2; padding: 5px; margin: 4px;&quot;&gt;&lt;pre&gt;&lt;span style=&quot;color: #0030fF; &quot;&gt;class&lt;/span&gt; IndirectLight{
&lt;span style=&quot;color: #0030fF; &quot;&gt;public&lt;/span&gt;:
  &lt;span style=&quot;color: #808080&quot;&gt;// позиция источника&lt;/span&gt;
  float3 position;
           
  &lt;span style=&quot;color: #808080&quot;&gt;// цвет источника&lt;/span&gt;
  float3 radiant;

  &lt;span style=&quot;color: #808080&quot;&gt;// радиус источника&lt;/span&gt;
  &lt;span style=&quot;color: #0030fF; &quot;&gt;float&lt;/span&gt;  radius;

  &lt;span style=&quot;color: #808080&quot;&gt;// апдейт интервал&lt;/span&gt;
  &lt;span style=&quot;color: #0030fF; &quot;&gt;int&lt;/span&gt;    updateInterval;

  &lt;span style=&quot;color: #808080&quot;&gt;// время прошлого апдейта&lt;/span&gt;
  &lt;span style=&quot;color: #0030fF; &quot;&gt;int&lt;/span&gt;    time;

  &lt;span style=&quot;color: #808080&quot;&gt;// N - кол-во &amp;quot;фотонов&amp;quot;&lt;/span&gt;
  &lt;span style=&quot;color: #0030fF; &quot;&gt;int&lt;/span&gt;    photonCount;

  &lt;span style=&quot;color: #808080&quot;&gt;// K - кол-во отражений фотона&lt;/span&gt;
  &lt;span style=&quot;color: #0030fF; &quot;&gt;int&lt;/span&gt;    photonReflectionCount;


  IndirectLight&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt; {
    radiant = float3&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #F04000; &quot;&gt;1&lt;/span&gt;.&lt;span style=&quot;color: #F04000; &quot;&gt;0&lt;/span&gt;f,&lt;span style=&quot;color: #F04000; &quot;&gt;1&lt;/span&gt;.&lt;span style=&quot;color: #F04000; &quot;&gt;0&lt;/span&gt;f,&lt;span style=&quot;color: #F04000; &quot;&gt;1&lt;/span&gt;.&lt;span style=&quot;color: #F04000; &quot;&gt;0&lt;/span&gt;f&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;;
    radius = &lt;span style=&quot;color: #F04000; &quot;&gt;1&lt;/span&gt;.&lt;span style=&quot;color: #F04000; &quot;&gt;0&lt;/span&gt;f;
    updateInterval = -&lt;span style=&quot;color: #F04000; &quot;&gt;1&lt;/span&gt;;
    time = -&lt;span style=&quot;color: #F04000; &quot;&gt;1&lt;/span&gt;;
    photonCount = &lt;span style=&quot;color: #F04000; &quot;&gt;0&lt;/span&gt;;
    photonReflectionCount = &lt;span style=&quot;color: #F04000; &quot;&gt;0&lt;/span&gt;;
  }

  IndirectLight&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt; &lt;span style=&quot;color: #0030fF; &quot;&gt;const&lt;/span&gt; float3&amp;amp; radiant , &lt;span style=&quot;color: #0030fF; &quot;&gt;float&lt;/span&gt; radius , &lt;span style=&quot;color: #0030fF; &quot;&gt;int&lt;/span&gt; photonCount = &lt;span style=&quot;color: #F04000; &quot;&gt;100&lt;/span&gt; , 
                 &lt;span style=&quot;color: #0030fF; &quot;&gt;int&lt;/span&gt; photonReflectionCount = &lt;span style=&quot;color: #F04000; &quot;&gt;4&lt;/span&gt; , &lt;span style=&quot;color: #0030fF; &quot;&gt;int&lt;/span&gt; updateInterval = -&lt;span style=&quot;color: #F04000; &quot;&gt;1&lt;/span&gt; &lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;{
    &lt;span style=&quot;color: #0030fF; &quot;&gt;this&lt;/span&gt;-&lt;span style=&quot;color: #a06000&quot;&gt;&amp;gt;&lt;/span&gt;radiant = radiant;
    &lt;span style=&quot;color: #0030fF; &quot;&gt;this&lt;/span&gt;-&lt;span style=&quot;color: #a06000&quot;&gt;&amp;gt;&lt;/span&gt;radius = radius;
    &lt;span style=&quot;color: #0030fF; &quot;&gt;this&lt;/span&gt;-&lt;span style=&quot;color: #a06000&quot;&gt;&amp;gt;&lt;/span&gt;updateInterval = updateInterval;
    time = -&lt;span style=&quot;color: #F04000; &quot;&gt;1&lt;/span&gt;;
    &lt;span style=&quot;color: #0030fF; &quot;&gt;this&lt;/span&gt;-&lt;span style=&quot;color: #a06000&quot;&gt;&amp;gt;&lt;/span&gt;photonCount = photonCount;
    &lt;span style=&quot;color: #0030fF; &quot;&gt;this&lt;/span&gt;-&lt;span style=&quot;color: #a06000&quot;&gt;&amp;gt;&lt;/span&gt;photonReflectionCount = photonReflectionCount;
  }

  ~IndirectLight&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;{
  }
};&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;p&gt;Алгоритм трассировки таков:&lt;/p&gt;
&lt;p&gt;1) Забиваем нули в наши текстуры у моделей.
&lt;br /&gt;2) Трассируем текущий фотонный луч. Если попали то переходим к пункту 3, если же нет, трассируем следующий фотонный луч.
&lt;br /&gt;3) Берём UV пересечения (важно, чтобы UV пересечения вычислялось по второй развёртке для нашей текстуры) и добавляем по этим UV в текстуру модели с которой произошло пересечение emiter-&amp;gt;radiant, если, конечно, текущее значение в текстурке равно нулю, если же нет, то смешиваем текущее значение с emiter-&amp;gt;radiant. Далее мы отражаем текущий луч по нормали персечения и возвращаемся к пункту 2 но reflectionIndex уменьшаем на 1, чтобы не получить бесконечный цикл. После окончания обновления всех источников, шлем все текстуры моделей на GPU.&lt;/p&gt;
&lt;table&gt;&lt;tr&gt;&lt;td&gt;&lt;div style=&quot;background: #f2f2f2; padding: 5px; margin: 4px;&quot;&gt;&lt;pre&gt;&lt;span style=&quot;color: #0030fF; &quot;&gt;class&lt;/span&gt; IndirectProcessor{
&lt;span style=&quot;color: #0030fF; &quot;&gt;public&lt;/span&gt;:
  std::vector&lt;span style=&quot;color: #a06000&quot;&gt;&amp;lt;&lt;/span&gt; IndirectLight* &lt;span style=&quot;color: #a06000&quot;&gt;&amp;gt;&lt;/span&gt; emiterList;

  IndirectProcessor&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt; {
  }

  ~IndirectProcessor&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;{
  }

  &lt;span style=&quot;color: #808080&quot;&gt;// Добавление нового источника &lt;/span&gt;
  &lt;span style=&quot;color: #0030fF; &quot;&gt;void&lt;/span&gt; addEmiter&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt; IndirectLight* emiter &lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;{
    removeEmiter&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;emiter&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;;
    emiterList.push_back&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;emiter&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;;
  }

  &lt;span style=&quot;color: #808080&quot;&gt;// Удаление источника из списка&lt;/span&gt;
  &lt;span style=&quot;color: #0030fF; &quot;&gt;void&lt;/span&gt; removeEmiter&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt; IndirectLight* emiter &lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;{
    &lt;span style=&quot;color: #0030fF; &quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt; std::vector&lt;span style=&quot;color: #a06000&quot;&gt;&amp;lt;&lt;/span&gt; IndirectLight* &lt;span style=&quot;color: #a06000&quot;&gt;&amp;gt;&lt;/span&gt;::iterator it = emiterList.begin&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;;
        it != emiterList.end&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;; it++ &lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;{
      &lt;span style=&quot;color: #0030fF; &quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt; &lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;*it&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt; == emiter &lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt; {
        emiterList.erase&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;it&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;;
        &lt;span style=&quot;color: #0030fF; &quot;&gt;return&lt;/span&gt;;
      }
    }
  }

  &lt;span style=&quot;color: #808080&quot;&gt;// Трассировка луча&lt;/span&gt;
  &lt;span style=&quot;color: #0030fF; &quot;&gt;void&lt;/span&gt; traceRadiant&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt; &lt;span style=&quot;color: #0030fF; &quot;&gt;const&lt;/span&gt; float3&amp;amp; orig, &lt;span style=&quot;color: #0030fF; &quot;&gt;const&lt;/span&gt; float3&amp;amp; dir,
                     &lt;span style=&quot;color: #0030fF; &quot;&gt;float&lt;/span&gt; radius , float3&amp;amp; radiant , &lt;span style=&quot;color: #0030fF; &quot;&gt;int&lt;/span&gt; reflectionIdx &lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;{
    Hit hit;

    &lt;span style=&quot;color: #808080&quot;&gt;// Если луч не персёкся ни с чем, то выходим из функции&lt;/span&gt;
    &lt;span style=&quot;color: #0030fF; &quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt; !world-&lt;span style=&quot;color: #a06000&quot;&gt;&amp;gt;&lt;/span&gt;traceRay&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;hit,dir,radius&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt; &lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt; &lt;span style=&quot;color: #0030fF; &quot;&gt;return&lt;/span&gt;;

    &lt;span style=&quot;color: #808080&quot;&gt;// Домножаем текущий цвет на цвет материала&lt;/span&gt;
    radiant = hit.material.color * radiant;

    &lt;span style=&quot;color: #808080&quot;&gt;// Отправляем текущий цвет в нашу текстуру модели&lt;/span&gt;
    hit.model-&lt;span style=&quot;color: #a06000&quot;&gt;&amp;gt;&lt;/span&gt;uploadRadiant&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;hit.u,hit.v,radiant&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;;

    
    &lt;span style=&quot;color: #0030fF; &quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt; reflectionIdx &lt;span style=&quot;color: #a06000&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&quot;color: #F04000; &quot;&gt;0&lt;/span&gt; &lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;
      traceRadiant&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;dir.reflect&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;hit.normal&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;, radius, radiant, reflectionIdx - &lt;span style=&quot;color: #F04000; &quot;&gt;1&lt;/span&gt; &lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;;
  }

  &lt;span style=&quot;color: #808080&quot;&gt;// Обновление источника&lt;/span&gt;
  &lt;span style=&quot;color: #0030fF; &quot;&gt;void&lt;/span&gt; updateEmiter&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt; IndirectLight* emiter &lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;{

    &lt;span style=&quot;color: #808080&quot;&gt;// Цикл от 0 до кол-ва &amp;quot;фотонов&amp;quot; источника&lt;/span&gt;
    &lt;span style=&quot;color: #0030fF; &quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt; &lt;span style=&quot;color: #0030fF; &quot;&gt;int&lt;/span&gt; i = &lt;span style=&quot;color: #F04000; &quot;&gt;0&lt;/span&gt;; i &lt;span style=&quot;color: #a06000&quot;&gt;&amp;lt;&lt;/span&gt; emiter-&lt;span style=&quot;color: #a06000&quot;&gt;&amp;gt;&lt;/span&gt;photonCount; i++ &lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;{
      &lt;span style=&quot;color: #808080&quot;&gt;// Генерируем случайный луч.&lt;/span&gt;
      float3 dir = generateRandomDirection&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;;

      &lt;span style=&quot;color: #808080&quot;&gt;// Трассируем &amp;quot;фотон&amp;quot;&lt;/span&gt;
      traceRadiant&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt; emiter-&lt;span style=&quot;color: #a06000&quot;&gt;&amp;gt;&lt;/span&gt;position, dir, emiter-&lt;span style=&quot;color: #a06000&quot;&gt;&amp;gt;&lt;/span&gt;radius, 
                    emiter-&lt;span style=&quot;color: #a06000&quot;&gt;&amp;gt;&lt;/span&gt;radiant, emiter-&lt;span style=&quot;color: #a06000&quot;&gt;&amp;gt;&lt;/span&gt;photonReflectionCount&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;;
    }
  }

  &lt;span style=&quot;color: #808080&quot;&gt;// Процессинг&lt;/span&gt;
  &lt;span style=&quot;color: #0030fF; &quot;&gt;void&lt;/span&gt; processFrame&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt; &lt;span style=&quot;color: #0030fF; &quot;&gt;int&lt;/span&gt; time &lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;{
    &lt;span style=&quot;color: #0030fF; &quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt; std::vector&lt;span style=&quot;color: #a06000&quot;&gt;&amp;lt;&lt;/span&gt; IndirectLight* &lt;span style=&quot;color: #a06000&quot;&gt;&amp;gt;&lt;/span&gt;::iterator it = emiterList.begin&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;;
         it != emiterList.end&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;; it++ &lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;{
      IndirectLight* emiter = &lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;*it&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;;

      &lt;span style=&quot;color: #808080&quot;&gt;// Проверяем, если апдейт интервал равен -1,&lt;/span&gt;
      &lt;span style=&quot;color: #808080&quot;&gt;// то значит обновлять такой источник придётя каждый кадр&lt;/span&gt;
      &lt;span style=&quot;color: #808080&quot;&gt;// что не чень хорошо, но всё же...&lt;/span&gt;
      &lt;span style=&quot;color: #0030fF; &quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt; emiter-&lt;span style=&quot;color: #a06000&quot;&gt;&amp;gt;&lt;/span&gt;updateInterval == -&lt;span style=&quot;color: #F04000; &quot;&gt;1&lt;/span&gt; &lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;{
        updateEmiter&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;emiter&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;;
        &lt;span style=&quot;color: #0030fF; &quot;&gt;continue&lt;/span&gt;;
      }

      &lt;span style=&quot;color: #808080&quot;&gt;// Если текущее время источника равно -1,&lt;/span&gt;
      &lt;span style=&quot;color: #808080&quot;&gt;// то значит источник ещё ни разу не обновлялся.&lt;/span&gt;
      &lt;span style=&quot;color: #0030fF; &quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt; emiter-&lt;span style=&quot;color: #a06000&quot;&gt;&amp;gt;&lt;/span&gt;time == -&lt;span style=&quot;color: #F04000; &quot;&gt;1&lt;/span&gt; &lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt; {
        updateEmiter&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;emiter&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;;
        emiter-&lt;span style=&quot;color: #a06000&quot;&gt;&amp;gt;&lt;/span&gt;time = time;
        &lt;span style=&quot;color: #0030fF; &quot;&gt;continue&lt;/span&gt;;
      }

      &lt;span style=&quot;color: #808080&quot;&gt;// Прибавляем к прошлому времени источника апдейт интервал&lt;/span&gt;
      &lt;span style=&quot;color: #808080&quot;&gt;// и если то, что у нас получилось равно текущему времени:&lt;/span&gt;
      &lt;span style=&quot;color: #0030fF; &quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt; emiter-&lt;span style=&quot;color: #a06000&quot;&gt;&amp;gt;&lt;/span&gt;time + emiter-&lt;span style=&quot;color: #a06000&quot;&gt;&amp;gt;&lt;/span&gt;updateInterval == time &lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;{  
        updateEmiter&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;emiter&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;;
        emiter-&lt;span style=&quot;color: #a06000&quot;&gt;&amp;gt;&lt;/span&gt;time = time;
      }
    }
  }
};&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;p&gt;Псевдо шейдер на языке NVIDIA Cg:
&lt;table&gt;&lt;tr&gt;&lt;td&gt;&lt;div style=&quot;background: #f2f2f2; padding: 5px; margin: 4px;&quot;&gt;&lt;pre&gt;&lt;span style=&quot;color: #0030fF; &quot;&gt;void&lt;/span&gt; main&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt; in Fragment fragment , out Output target , uniform sampler2D photonMap &lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;{
  float2 texcoord2 = fragment.photonTexcoord;

  float3 indirect = float3&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #F04000; &quot;&gt;0&lt;/span&gt;,&lt;span style=&quot;color: #F04000; &quot;&gt;0&lt;/span&gt;,&lt;span style=&quot;color: #F04000; &quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;;
  &lt;span style=&quot;color: #0030fF; &quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #0030fF; &quot;&gt;float&lt;/span&gt; multipler = &lt;span style=&quot;color: #F04000; &quot;&gt;1&lt;/span&gt;.&lt;span style=&quot;color: #F04000; &quot;&gt;0&lt;/span&gt;f / &lt;span style=&quot;color: #F04000; &quot;&gt;9&lt;/span&gt;.&lt;span style=&quot;color: #F04000; &quot;&gt;0&lt;/span&gt;f;
  &lt;span style=&quot;color: #0030fF; &quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt; &lt;span style=&quot;color: #0030fF; &quot;&gt;int&lt;/span&gt; x = -&lt;span style=&quot;color: #F04000; &quot;&gt;1&lt;/span&gt;; x &lt;span style=&quot;color: #a06000&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&quot;color: #F04000; &quot;&gt;1&lt;/span&gt;; x++ &lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;{
    indirect += tex2D&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;photonMap,texcoord2,int2&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;x,&lt;span style=&quot;color: #F04000; &quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;.rgb;
  }
  &lt;span style=&quot;color: #0030fF; &quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt; &lt;span style=&quot;color: #0030fF; &quot;&gt;int&lt;/span&gt; y = -&lt;span style=&quot;color: #F04000; &quot;&gt;1&lt;/span&gt;; y &lt;span style=&quot;color: #a06000&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&quot;color: #F04000; &quot;&gt;1&lt;/span&gt;; y++ &lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;{
    indirect += tex2D&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;photonMap,texcoord2,int2&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #F04000; &quot;&gt;0&lt;/span&gt;,y&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;.rgb;
  }
  indirect = clamp&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;indirect * multipler,&lt;span style=&quot;color: #F04000; &quot;&gt;0&lt;/span&gt;.&lt;span style=&quot;color: #F04000; &quot;&gt;0&lt;/span&gt;f,&lt;span style=&quot;color: #F04000; &quot;&gt;1&lt;/span&gt;.&lt;span style=&quot;color: #F04000; &quot;&gt;0&lt;/span&gt;f&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;;

  &lt;span style=&quot;color: #808080&quot;&gt;// Далее идёт направленое освещение и в итоге&lt;/span&gt;
  target.color = direct + indirect;
}&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/p&gt;
&lt;p&gt;Некоторые мысли по оптимизации:&lt;/p&gt;
&lt;p&gt;1) Мультипоточная обработка источников: можно, например, сразу обновлять несколько источников в разных потоках.
&lt;br /&gt;2) BSP Tree было бы огромным плюсом для трассировки лучей.
&lt;br /&gt;3) Использования SSE для проверки пересечения луча с треугольником.
&lt;br /&gt;4) Использование &lt;a href=&quot;http://www.gamedev.ru/code/terms/OpenCL&quot; title=&quot;OpenCL: Open Computing Language&quot;&gt;OpenCL&lt;/a&gt;\&lt;a href=&quot;http://www.gamedev.ru/code/terms/CUDA&quot; title=&quot;CUDA&quot;&gt;CUDA&lt;/a&gt; для трассировки лучей.&lt;/p&gt;
&lt;p&gt;Также есть менее затратный вариант в плане видеопамяти. Вместо текстур мы будет использовать Deferred Lighting и так называемые Virtual Point Light (Point Light не имеющий радиуса). И вместо hit.model-&amp;gt;uploadRadiant(hit.u,hit.v,radiant); будем добавлять в список источников света vpl и обрабатывать его с помощью Deferred Lighting.&lt;/p&gt;
&lt;p&gt;Вот и всё, удачи в начинаниях.&lt;/p&gt;
&lt;p&gt;Литература:
&lt;br /&gt; - &lt;a href=&quot;http://en.wikipedia.org/wiki/Global_illumination&quot; rel=&quot;nofollow&quot;&gt;http://en.wikipedia.org/wiki/Global_illumination&lt;/a&gt;
&lt;br /&gt; - &lt;a href=&quot;http://ru.wikipedia.org/wiki/Глобальное_освещение&quot; rel=&quot;nofollow&quot;&gt;http://ru.wikipedia.org/wiki/Глобальное_освещение&lt;/a&gt;
&lt;br /&gt; - &lt;a href=&quot;http://habrahabr.ru/blogs/3d_graphics/77235/&quot;&gt;http://habrahabr.ru/blogs/3d_graphics/77235/&lt;/a&gt;
&lt;br /&gt; - &lt;a href=&quot;http://ru.wikipedia.org/wiki/Трассировка_лучей&quot; rel=&quot;nofollow&quot;&gt;http://ru.wikipedia.org/wiki/Трассировка_лучей&lt;/a&gt;
&lt;br /&gt; - &lt;a href=&quot;http://en.wikipedia.org/wiki/Binary_space_partitioning&quot; rel=&quot;nofollow&quot;&gt;http://en.wikipedia.org/wiki/Binary_space_partitioning&lt;/a&gt;
&lt;br /&gt; - &lt;a href=&quot;http://ru.wikipedia.org/wiki/SSE&quot; rel=&quot;nofollow&quot;&gt;http://ru.wikipedia.org/wiki/SSE&lt;/a&gt;
&lt;br /&gt; - &lt;a href=&quot;http://en.wikipedia.org/wiki/Multithreading&quot; rel=&quot;nofollow&quot;&gt;http://en.wikipedia.org/wiki/Multithreading&lt;/a&gt;&lt;/p&gt;</description>
</item>
<item>
  <guid isPermaLink="true">http://www.gamedev.ru/code/news/ati_stream_sdk_21</guid>
  <pubDate>Wed, 26 May 2010 06:19:44 GMT</pubDate>
  <title>ATI Stream SDK v2.1</title>
  <link>http://www.gamedev.ru/code/news/ati_stream_sdk_21</link>
  <category>Общее</category>
  <category>ATI</category>
  <category>ATI Stream</category>
  <category>SDK</category>
  <description>
&lt;p&gt;Вышел ATI Stream SDK версии 2.1.
&lt;br /&gt;Скачать можно здесь: &lt;a href=&quot;http://developer.amd.com/gpu/ATIStreamSDK/Pages/default.aspx&quot;&gt;http://developer.amd.com/gpu/ATIStreamSDK/Pages/default.aspx&lt;/a&gt;
&lt;br /&gt;По этой же ссылке можно найти список новшеств.&lt;/p&gt;</description>
</item>
<item>
  <guid isPermaLink="true">http://www.gamedev.ru/code/news/opencl-opengl</guid>
  <pubDate>Thu, 20 May 2010 14:36:49 GMT</pubDate>
  <title>OpenCL вместе с OpenGL</title>
  <link>http://www.gamedev.ru/code/news/opencl-opengl</link>
  <category>Графика</category>
  <category>OpenCL</category>
  <category>OpenGL</category>
  <category>OpenTK</category>
  <description>
&lt;p&gt;На сайте CMSoft появилась статья, иллюстрирующая применение связки &lt;a href=&quot;http://www.gamedev.ru/code/terms/OpenCL&quot; title=&quot;OpenCL: Open Computing Language&quot;&gt;OpenCL&lt;/a&gt; и &lt;a href=&quot;http://www.gamedev.ru/code/terms/OpenGL&quot; title=&quot;OpenGL: Open Graphics Library&quot;&gt;OpenGL&lt;/a&gt;. В частности в статье рассматривается манипулирование данными в вершинном буфере OpenGL из OpenCL. Вот что получилось у авторов статьи в результате:&lt;/p&gt;&lt;p&gt;&lt;object width=&quot;640&quot; height=&quot;385&quot;&gt;&lt;param name=&quot;movie&quot; value=&quot;http://www.youtube.com/v/K1FOIhA6ecQ&amp;amp;color1=0xb1b1b1&amp;amp;color2=0xcfcfcf&amp;amp;hl=ru_RU&amp;amp;feature=player_embedded&amp;amp;fs=1&quot;&gt;&lt;/param&gt;&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot;&gt;&lt;/param&gt;&lt;param name=&quot;allowScriptAccess&quot; value=&quot;always&quot;&gt;&lt;/param&gt;&lt;param name=&quot;wmode&quot; value=&quot;transparent&quot;&gt;&lt;/param&gt;&lt;embed src=&quot;http://www.youtube.com/v/K1FOIhA6ecQ&amp;amp;color1=0xb1b1b1&amp;amp;color2=0xcfcfcf&amp;amp;hl=ru_RU&amp;amp;feature=player_embedded&amp;amp;fs=1&quot; type=&quot;application/x-shockwave-flash&quot; wmode=&quot;transparent&quot; allowfullscreen=&quot;true&quot; allowScriptAccess=&quot;always&quot; width=&quot;640&quot; height=&quot;385&quot;&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/p&gt;
&lt;p&gt;Исходный код и объяснения доступны по &lt;a href=&quot;http://www.cmsoft.com.br/index.php?option=com_content&amp;amp;view=category&amp;amp;layout=blog&amp;amp;id=99&amp;amp;Itemid=150&quot;&gt;этой ссылке&lt;/a&gt;.&lt;/p&gt;</description>
</item>
<item>
  <guid isPermaLink="true">http://www.gamedev.ru/code/tip/Titan_Quest_Terrain</guid>
  <pubDate>Tue, 18 May 2010 12:53:59 GMT</pubDate>
  <title>Пример смешивания текстур ландшафта в Titan Quest.</title>
  <link>http://www.gamedev.ru/code/tip/Titan_Quest_Terrain</link>
  <category>Графика</category>
  <category>ландшафт</category>
  <category>текстурирование</category>
  <description>
&lt;p&gt;Для текстурирования местности, построенной на карте высот, наибольшее распространение получил метод, использующий несколько слоев бесшовных (затайленых) текстур. Слои накладываются один поверх другого и смешиваются для получения финального изображения. В дополнение к бесшовной текстуре каждый слой имеет карту прозрачности, определяющую с каким весом текстура слоя смешивается в любой точке местности. В отличие от самой бесшовной текстуры, эта карта прозрачности растягивается на весь ландшафт, и, следовательно, имеет очень низкую детализацию.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;http://www.gamedev.ru/files/images/titanquest_low.jpg&quot; alt=&quot;titanquest_low | Пример смешивания текстур ландшафта в Titan Quest.&quot; /&gt;
&lt;br /&gt;Текстурированный ландшафт в Titan Quest.
&lt;p&gt;Рассмотрим простой пример. Наша местность будет состоять из двух слоев &amp;mdash; травы и песка. В любой точке, где карта прозрачности для слоя травы хранит 1.0 (непрозрачно), мы увидим только траву. Там, где карта прозрачности хранит 0.0, мы увидим песок, и там, где было 0.5, мы увидим промежуточное состояние &amp;mdash; песок, смешанный с травой. Обратите внимание, что самый нижний слой не имеет карты прозрачности, так как основной слой должен быть виден везде. &lt;/p&gt;
&lt;p&gt;Операция для смешивания двух текстур будет выглядеть так:&lt;/p&gt;
&lt;div style=&quot;background: #f2f2f2; padding: 5px; margin: 4px;&quot;&gt;&lt;pre&gt;float4 blend(float4 texture0, float4 texture1, float layerOpacity)
{
    return lerp(texture0, texture1, layerOpacity);
}&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;
&lt;p&gt;Недостаток этой простой техники в том, что если приглядеться поближе, смешивание травы и песка 50/50 выглядит не очень хорошо.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://www.gamedev.ru/files/images/alphablend.jpg&quot; alt=&quot;alphablend | Пример смешивания текстур ландшафта в Titan Quest.&quot; /&gt;
&lt;p&gt;Результат смешивания (внизу) больше напоминает зеленый песок, а не клочок травы в песке. Если бы текстуры лучше соотносились друг с другом, результат выглядел бы лучше. Проблему можно было бы решить дополнительными текстурами переходов, созданными художниками. Однако это добавляет художникам работы, и требует отрисовки дополнительного текстурного слоя. Наконец, для каждой комбинации текстур, которые мы собираемся использовать на местности, нам понадобятся разные текстуры переходов. И в конечном итоге нам понадобится несколько таких текстур.&lt;/p&gt;
&lt;p&gt;Существует способ c простым решением, который использовался в Titan Quest. Идея в том, чтобы вместо рисования 50% текстуры в каждом пикселе, рисовать одну текстуру в 50% пикселей, и другую текстуру в других 50%.&lt;/p&gt;
&lt;p&gt;Вот как выглядит результат в этом случае:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://www.gamedev.ru/files/images/selectblend.jpg&quot; alt=&quot;selectblend | Пример смешивания текстур ландшафта в Titan Quest.&quot; /&gt;
&lt;p&gt;Чтобы реализовать это метод, мы храним маску в альфа-канале каждой бесшовной текстуры. Эта маска использует полный диапазон значений, и определяет, будет ли виден тексель, если текстурный слой местности имеет определенную прозрачность. Иными словами, тексель отрисовывается, если значение маски меньше, чем значение непрозрачности слоя. 
&lt;br /&gt;Эта новая &amp;laquo;пятнистая&amp;raquo; техника смешивания просто реализуется так:&lt;/p&gt;
&lt;div style=&quot;background: #f2f2f2; padding: 5px; margin: 4px;&quot;&gt;&lt;pre&gt;float4 blend(float4 texture0, float4 texture1, float layerOpacity)
{
    if (texture1.a &amp;lt; layerOpacity)
    {
        return texture1;
    }
    else
    {
        return texture0;
    }
}&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;
&lt;p&gt;Результат выглядит более естественно, и структура пятен может быть подогнана индивидуально для каждого типа текстур. Так, текстура травы использует зашумленный узор. Текстуры с более крупными элементами &amp;mdash; такими как камни &amp;mdash; могут быть настроены таким образом, что смешивание будут следовать структуре. Для камней альфа-маска может хранить большие значения для трещин, и небольшие значения для плоских поверхностей. При смешивании слоя камней поверх слоя травы, трава будет появляться в трещинах в камне по мере роста прозрачности слоя.&lt;/p&gt;
&lt;p&gt;Из-за бинарного характера сравнения, результат будет иметь жесткие границы и показывать сильный алиасинг. Гораздо лучше получается при небольшом смешивании границ между текстурами при помощи обычного альфа-блендинга.
&lt;br /&gt;Вот один из способов сделать это, хотя другие методы определенно могут быть использованы тоже (для Titan Quest использовался более простой метод, чтобы втиснуться в лимит на число инструкций для ps1.0):&lt;/p&gt;
&lt;div style=&quot;background: #f2f2f2; padding: 5px; margin: 4px;&quot;&gt;&lt;pre&gt;float4 blend(float4 texture0, float4 texture1, float layerOpacity)
{
    const float blendRange = 0.1;
 
    if (texture1.a &amp;lt; layerOpacity - blendRange)     
    {
         return texture1;
    }
    else if (texture1.a &amp;gt; layerOpacity + blendRange)
    {
        return texture0;
    }
    else
    {
        float f = (texture1.a - layerOpacity + blendRange) / (2 * blendRange);
        return lerp(texture1, texture0, f);
    }
}&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;
&lt;p&gt;Вот как выглядит финальный результат:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://www.gamedev.ru/files/images/smoothedselectblend.jpg&quot; alt=&quot;smoothedselectblend | Пример смешивания текстур ландшафта в Titan Quest.&quot; /&gt;
&lt;p&gt;Хотя примеры показаны только для случая с двумя текстурами, любое количество слоев может быть смешано таким же образом, как и с простой техникой.&lt;/p&gt;
&lt;p&gt;Этот тип смешивания также не ограничен текстурированием ландшафтов. Интересные эффекты могут быть получены анимированием прозрачности слоя. Например, вот как работает такой же тип смешивания в прототипе динамического заражения для Natural Selection 2:&lt;/p&gt;
&lt;p&gt;&lt;object width=&quot;640&quot; height=&quot;385&quot;&gt;&lt;param name=&quot;movie&quot; value=&quot;http://www.youtube.com/v/mMMiKKv7g7s&amp;amp;color1=0xb1b1b1&amp;amp;color2=0xcfcfcf&amp;amp;hl=ru_RU&amp;amp;feature=player_embedded&amp;amp;fs=1&quot;&gt;&lt;/param&gt;&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot;&gt;&lt;/param&gt;&lt;param name=&quot;allowScriptAccess&quot; value=&quot;always&quot;&gt;&lt;/param&gt;&lt;param name=&quot;wmode&quot; value=&quot;transparent&quot;&gt;&lt;/param&gt;&lt;embed src=&quot;http://www.youtube.com/v/mMMiKKv7g7s&amp;amp;color1=0xb1b1b1&amp;amp;color2=0xcfcfcf&amp;amp;hl=ru_RU&amp;amp;feature=player_embedded&amp;amp;fs=1&quot; type=&quot;application/x-shockwave-flash&quot; wmode=&quot;transparent&quot; allowfullscreen=&quot;true&quot; allowScriptAccess=&quot;always&quot; width=&quot;640&quot; height=&quot;385&quot;&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/p&gt;
&lt;p&gt;Это перевод записи Blending Terrain Textures:
&lt;br /&gt;&lt;a href=&quot;http://www.m4x0r.com/blog/2010/05/blending-terrain-textures/&quot;&gt;http://www.m4x0r.com/blog/2010/05/blending-terrain-textures/&lt;/a&gt;&lt;/p&gt;</description>
</item>
<item>
  <guid isPermaLink="true">http://www.gamedev.ru/code/news/pathengine-5-24</guid>
  <pubDate>Fri, 14 May 2010 18:44:07 GMT</pubDate>
  <title>PathEngine 5.24</title>
  <link>http://www.gamedev.ru/code/news/pathengine-5-24</link>
  <comments>http://www.gamedev.ru/code/forum/?id=133727</comments>
  <category>Общее</category>
  <category>ИИ</category>
  <category>PathEngine</category>
  <description>
&lt;p&gt;Вышла новая версия движка для поиска пути и перемещения агентов PathEngine 5.24. Новая версия включает в себя несколько дополнений и улучшений, а также несколько новых вариантов лицензии. &lt;/p&gt;
&lt;p&gt;Вместе с добавлением поиска пути из нескольких начальных точек, компания завяляет о &amp;laquo;значительном увеличении скорости работы алгоритмов поиска пути и улучшениях в генерировании кривых пути&amp;raquo;, вспомогательных методах и исправлении багов. Поиск пути учитывает трёхмерную модель пространства, размер персонажа и динамические объекты на карте.&lt;/p&gt;
&lt;p&gt;Подробнее можно узнать на сайте компании: &lt;a href=&quot;http://www.pathengine.com/&quot;&gt;pathengine.com&lt;/a&gt;.&lt;/p&gt;</description>
</item>
<item>
  <guid isPermaLink="true">http://www.gamedev.ru/code/news/ati-firepro-rg220</guid>
  <pubDate>Fri, 14 May 2010 18:37:26 GMT</pubDate>
  <title>ATI FirePro RG220</title>
  <link>http://www.gamedev.ru/code/news/ati-firepro-rg220</link>
  <category>Графика</category>
  <category>AMD</category>
  <category>ATI</category>
  <category>Gaikai</category>
  <category>OnLive</category>
  <category>PCoIP</category>
  <description>
&lt;p&gt;С появлением таких систем как OnLive, можно было ожидать ответного шага со стороны производителей аппаратных решений для поддержки нового типа игры по сети. Напомним, что в OnLive по сети от сервера передаётся видеопоток, а от клиента – команды контроллера.&lt;/p&gt;
&lt;p&gt;ATI представила новый продукт &lt;b&gt;ATI FirePro RG220&lt;/b&gt;. Эта видеокарта поддерживает протокол&amp;nbsp; &lt;a href=&quot;http://www.teradici.com/&quot;&gt;Teradici PC-over-IP&lt;/a&gt;, &lt;a href=&quot;http://www.gamedev.ru/code/terms/OpenGL&quot; title=&quot;OpenGL: Open Graphics Library&quot;&gt;OpenGL&lt;/a&gt; 4 и DX 11, а также множество виртуальных машин, каждая из которых может работать со своей видеокартой.&lt;/p&gt;&lt;p&gt;&lt;object width=&quot;640&quot; height=&quot;385&quot;&gt;&lt;param name=&quot;movie&quot; value=&quot;http://www.youtube.com/v/5J9HtEmC6ew&amp;amp;color1=0xb1b1b1&amp;amp;color2=0xcfcfcf&amp;amp;hl=ru_RU&amp;amp;feature=player_embedded&amp;amp;fs=1&quot;&gt;&lt;/param&gt;&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot;&gt;&lt;/param&gt;&lt;param name=&quot;allowScriptAccess&quot; value=&quot;always&quot;&gt;&lt;/param&gt;&lt;param name=&quot;wmode&quot; value=&quot;transparent&quot;&gt;&lt;/param&gt;&lt;embed src=&quot;http://www.youtube.com/v/5J9HtEmC6ew&amp;amp;color1=0xb1b1b1&amp;amp;color2=0xcfcfcf&amp;amp;hl=ru_RU&amp;amp;feature=player_embedded&amp;amp;fs=1&quot; type=&quot;application/x-shockwave-flash&quot; wmode=&quot;transparent&quot; allowfullscreen=&quot;true&quot; allowScriptAccess=&quot;always&quot; width=&quot;640&quot; height=&quot;385&quot;&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/p&gt;</description>
</item>
<item>
  <guid isPermaLink="true">http://www.gamedev.ru/code/news/lua-with-glsl</guid>
  <pubDate>Wed, 12 May 2010 22:16:21 GMT</pubDate>
  <title>Использование Lua для формирования шейдеров на GLSL</title>
  <link>http://www.gamedev.ru/code/news/lua-with-glsl</link>
  <category>Графика</category>
  <category>GLSL</category>
  <category>Lua</category>
  <category>OpenGL</category>
  <description>
&lt;p&gt;В своём блоге Philip Rideout проанализировал, как использовать скрипты &lt;a href=&quot;http://www.gamedev.ru/code/terms/Lua&quot; title=&quot;Lua (Скриптовый язык Lua)&quot;&gt;Lua&lt;/a&gt; для управления строками в &lt;a href=&quot;http://www.gamedev.ru/code/terms/Shader&quot; title=&quot;Шейдер (Shader)&quot;&gt;шейдерах&lt;/a&gt; на &lt;a href=&quot;http://www.gamedev.ru/code/terms/GLSL&quot; title=&quot;GLSL (OpenGL Shading Language)&quot;&gt;GLSL&lt;/a&gt;, с примерами кода. Philip также рассматривает примеры трюков, таких как добавление #line для определения строк при обработке ошибок.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://prideout.net/blog/?p=1&quot;&gt;http://prideout.net/blog/?p=1&lt;/a&gt;&lt;/p&gt;</description>
</item>
<item>
  <guid isPermaLink="true">http://www.gamedev.ru/code/terms/Architecture</guid>
  <pubDate>Mon, 10 May 2010 05:48:07 GMT</pubDate>
  <title>Архитектура игры</title>
  <link>http://www.gamedev.ru/code/terms/Architecture</link>
  <category>Общее</category>
  <category>программирование</category>
  <category>проектирование</category>
  <description>
&lt;p&gt;&lt;strong&gt;Архитектура компьютерной игры&lt;/strong&gt; (движка игры) &amp;mdash; структура &lt;a href=&quot;http://www.gamedev.ru/industry/terms/Games&quot; title=&quot;Игры (games): компьютерные игры&quot;&gt;игры&lt;/a&gt;, как правило, включающая программные компоненты и взаимосвязи между ними. &amp;laquo;Архитектура &amp;mdash; это базовая организация системы, воплощенная в ее компонентах, их отношениях между собой и с окружением, а также принципы, определяющие проектирование и развитие системы&amp;raquo; (Стандарт IEEE 1471).&lt;p&gt;По стандарту UML, Архитектура &amp;mdash; это &amp;laquo;структура организации и связанное с ней поведение системы. Архитектуру можно рекурсивно разобрать на части, взаимодействующие посредством интерфейсов, связи, которые соединяют части, и условия сборки частей. Части, которые взаимодействуют через интерфейсы, включают классы, компоненты и подсистемы.&amp;raquo;&lt;/p&gt;
&lt;p&gt;Любая игра имеет архитектуру независимо от того, проектировалась она или нет. Архитектура может быть восстановлена по уже имеющейся игре. При создании игры не обязательно прорабатывать ее архитектуру заранее, однако ее проработка может существенно уменьшить объем работ при реализации игры, так как исправление архитектуры в общем случае проще исправления кода реализации. Описание архитектуры позволяет скрыть сложность игры при помощи абстракции и разделения ответственности между подсистемами. Наличие описания архитектуры, как правило, упрощает обсуждение и принятие решений, касающихся разрабатываемой игры.&lt;/p&gt;
&lt;p&gt;Архитектура игры определяет из каких элементов состоит игра и как эти элементы взаимодействуют, но при этом описание не обязано быть исчерпывающим, достаточно бывает описания главных структурных элементов, элементов, связанных с основным поведением и элементов, которые определяют значимые свойства игры. Детали реализации как правило отношения к архитектуре не имеют, однако, именно архитектор решает, где заканчивается архитектура и начинается проработка деталей реализации. Таким образом, все описанное архитектором автоматически может считаться архитектурой.&lt;/p&gt;
&lt;p&gt;Архитектуру, как правило, представляют в виде разного рода диаграмм, но Архитектура &amp;mdash; это не только диаграмма, но и ее логическое обоснование. Для правильного понимания архитектуры игры бывает важно понимание тех решений, которые привели к созданию этой архитектуры, и их логические обоснования.&lt;/p&gt;
&lt;p&gt;Литература:
&lt;br /&gt;&lt;a href=&quot;http://www.intuit.ru/department/internet/mwebtech/5/1.html&quot;&gt;http://www.intuit.ru/department/internet/mwebtech/5/1.html&lt;/a&gt;
&lt;br /&gt;&lt;a href=&quot;http://www.ibm.com/developerworks/ru/library/eeles/index.html&quot;&gt;http://www.ibm.com/developerworks/ru/library/eeles/index.html&lt;/a&gt;&lt;/p&gt;</description>
</item>
<item>
  <guid isPermaLink="true">http://www.gamedev.ru/code/news/neoaxis-0-85</guid>
  <pubDate>Tue, 04 May 2010 18:44:16 GMT</pubDate>
  <title>NeoAxis Game Engine 0.85</title>
  <link>http://www.gamedev.ru/code/news/neoaxis-0-85</link>
  <category>Графика</category>
  <category>NeoAxis</category>
  <description>
&lt;p&gt;NeoAxis Group выпустила новую версию движка NeoAxis. Среди новых возможностей ПО присутствует поддержка текстур в формате 3Dc, генерация шрифтов в формате True Type, улучшенные тени (Stencil Shadows) и был улучшен плагин для браузеров. Также инструментарий позволяет экспортировать морфемы. &lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.neoaxisgroup.com/&quot;&gt;http://www.neoaxisgroup.com/&lt;/a&gt;&lt;/p&gt;</description>
</item>
<item>
  <guid isPermaLink="true">http://www.gamedev.ru/code/terms/neuronet</guid>
  <pubDate>Tue, 27 Apr 2010 19:21:48 GMT</pubDate>
  <title>Нейросеть</title>
  <link>http://www.gamedev.ru/code/terms/neuronet</link>
  <comments>http://www.gamedev.ru/code/forum/?id=132900</comments>
  <category>Игровая логика и ИИ</category>
  <category>ИИ</category>
  <category>нейросети</category>
  <description>
&lt;p&gt;&lt;b&gt;Искусственная нейросеть (neuronet)&lt;/b&gt; &amp;mdash; математическая модель, а также программная или аппаратная реализация, построенная по принципу функционирования нервных клеток. Нейросеть состоит из нейронов.&lt;p&gt;&lt;b&gt;Искусственный нейрон (neuron)&lt;/b&gt; &amp;mdash; математическая модель или программная реализация нервной клетки.
&lt;p&gt;&lt;img src=&quot;http://www.gamedev.ru/files/images/180px-artificial_neuron_scheme.png&quot; alt=&quot;Нейрон | Нейросеть&quot; /&gt;
&lt;p&gt;Искусственный нейрон состоит из:
&lt;br /&gt;1) Входной вектор I = (i1, ... , in) &amp;mdash; фактически являются &amp;laquo;рецепторами&amp;raquo; нейрона,
&lt;br /&gt;2) Вектор весов W = (w1, ... ,wn) &amp;mdash; веса &amp;laquo;рецепторов&amp;raquo;,
&lt;br /&gt;3) Вектор выходов O = (o1, ... , 0k) &amp;mdash; каждый нейрон имеет свою собственную вычислительную способность, в этом векторе хранится результат его вычисления,
&lt;br /&gt;4) Порог c &amp;mdash; эмуляция биологического порога активации нейрона.&lt;/p&gt;
&lt;p&gt;Выходы искуственного нейрона считаются следующим образом:&lt;/p&gt;
&lt;p&gt;&amp;nbsp; oj = Fa(i1*w1+ ... +in*wn - c), 1&amp;lt;j&amp;lt;k , где Fa(x) &amp;mdash; сигмоидальная функция.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Сигмоидальная функция &lt;/b&gt; &amp;mdash; тип передаточной функции, позволяющий расширить использование нейронных сетей.
&lt;br /&gt;В качестве сигмоидальной функции рекомендуется использовать функцию вида:
&lt;p&gt;&amp;nbsp; &lt;b&gt;Fa(x) = 1/(1+exp(-c*x)) &lt;/b&gt;, где c - константа влияющая на кривизну функции.
&lt;p&gt;Также стоит отметить, что приоритет выбора этой функции обусловлен простым нахождением ее производной&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &lt;b&gt;Fa`(x) = c*Fa(x)*(1-Fa(x))&lt;/b&gt;, что является очень полезным свойством при обучении нейросети.
&lt;p&gt;&lt;b&gt;Пример 1:&lt;/b&gt;
&lt;p&gt;Простейшая и наглядная нейросеть состоит из одного нейрона, у которого два входа, один выход, и он способен вычислять простейшие бинарные функции, такие как коньюнкция, дизьюнкция, эквивалентность, и другие.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Пример 2:&lt;/b&gt;
&lt;p&gt;&lt;img src=&quot;http://www.gamedev.ru/files/images/300px-perceptron_xor_task_v2_svg.png&quot; alt=&quot;Нейросеть | Нейросеть&quot; /&gt;
&lt;br /&gt;S &amp;mdash; это входной слой нейросети, на него подаются значения x и y.
&lt;br /&gt;A &amp;mdash; скрытый слой.
&lt;br /&gt;R &amp;mdash; выходной слой.
&lt;p&gt;Эта нейросеть вычисляет XOR(x,y), у всех нейронов порог = 0. Следует также обратить внимание на то, что все нейроны из следующего слоя связаны со всеми нейронами предыдущего, и не стоит пренебрегать этим, при формировании своей сети, так как, если связь между двумя нейронами не важна в конечной нейросети, то в процессе обучение ее вес станет = 0.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Прямой проход нейросети&lt;/b&gt; &amp;mdash; вычисление нейросетью выходного результата. Прямой проход происходит &amp;laquo;сверху вниз, слева направо&amp;raquo;, то есть, сначала вычисляются все выходы всех нейронов в текущем слое, затем в следующем, и так далее. Стоит обратить внимание, что в нейросети выходы нейронов текущего слоя являются входами нейронов следующего.
&lt;p&gt;Одним из важных особенностей нейросетей является быстрое вычисление результата (линейная сложность) и способность к переобучению.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Ссылки:&lt;/b&gt;
&lt;br /&gt;&lt;a href=&quot;http://neuropro.ru/neu1.shtml&quot;&gt;http://neuropro.ru/neu1.shtml&lt;/a&gt;
&lt;br /&gt;&lt;a href=&quot;http://ru.wikipedia.org/wiki/Искусственная_нейронная_сеть&quot; rel=&quot;nofollow&quot;&gt;http://ru.wikipedia.org/wiki/Искусственная_нейронная_сеть&lt;/a&gt;
&lt;br /&gt;&lt;a href=&quot;http://www.ai-junkie.com/ann/evolved/nnt1.html&quot;&gt;http://www.ai-junkie.com/ann/evolved/nnt1.html&lt;/a&gt;</description>
</item>
<item>
  <guid isPermaLink="true">http://www.gamedev.ru/code/terms/RangeFog</guid>
  <pubDate>Tue, 20 Apr 2010 22:48:04 GMT</pubDate>
  <title>Range Fog</title>
  <link>http://www.gamedev.ru/code/terms/RangeFog</link>
  <category>Графика</category>
  <category>туман</category>
  <description>
&lt;p&gt;&lt;strong&gt;Range Fog&lt;/strong&gt; &amp;mdash; техника отображения тумана, когда степень эффекта тумана зависит от расстояния от точки в пространстве сцены до положения наблюдателя. Эта техника является альтернативной классической техники отрисовки тумана Plane Fog.&lt;p&gt;Разницу между Range Fog и Plane Fog легко почувствовать, вращая камеру из стороны в сторону. Если приглядеться, то объекты, находящиеся ближе к краю экрана при приближении к центру становятся более затуманенными, хотя фактически расстояние до них остаётся неизменным.&lt;/p&gt;
&lt;p&gt;Классические техники отрисовки тумана основываются на Z-координате, получаемой в результате проекции пространства. Однако получаемая Z координата является не расстоянием до точки, в которой расположена камера, а расстоянием между плоскостью камеры и проецируемой точкой в пространстве.&lt;/p&gt;
&lt;p&gt;Задача правильного расчёта тумана в &lt;a href=&quot;http://www.gamedev.ru/code/terms/OpenGL&quot; title=&quot;OpenGL: Open Graphics Library&quot;&gt;OpenGL&lt;/a&gt; решалась расширениями. Можно было передавать координаты для вычисления затуманивания для каждой вершины сетки. Позже появился вариант от компании NVIDIA – расширение GL_NV_fog_distance и параметра EYE_RADIAL_NV. С переходом от фиксированного конвейера к &lt;a href=&quot;http://www.gamedev.ru/code/terms/Shader&quot; title=&quot;Шейдер (Shader)&quot;&gt;шейдерам&lt;/a&gt; стало возможно вычислять правильное значение цвета пикселей с учётом тумана в шейдере.&lt;/p&gt;</description>
</item>
<item>
  <guid isPermaLink="true">http://www.gamedev.ru/community/delphinarium/articles/texture_and_uniform_buf</guid>
  <pubDate>Tue, 20 Apr 2010 21:24:04 GMT</pubDate>
  <title>Буферы данных в OpenGL через расширения texture_buffer_object и uniform_buffer_object</title>
  <link>http://www.gamedev.ru/community/delphinarium/articles/texture_and_uniform_buf</link>
  <comments>http://www.gamedev.ru/community/delphinarium/forum/?id=132647</comments>
  <category>Графика</category>
  <category>Delphi</category>
  <category>расширения OpenGL</category>
  <category>OpenGL</category>
  <description>
&lt;p&gt;На сегодняшний день GPU обладают памятью такого же объёма (если не большего), что и оперативная память на ПК. Поэтому сейчас есть возможность хранить больше данных в памяти непосредственно на GPU, чем можно было ранее. &lt;a href=&quot;http://www.gamedev.ru/code/terms/OpenGL&quot; title=&quot;OpenGL: Open Graphics Library&quot;&gt;OpenGL&lt;/a&gt; 3 дал возможность использовать расширения, позволяющие хранить, к примеру, большую информацию о геометрии. С выходом новой версии этого API расширения texture_buffer_object и uniform_buffer_object стали чуть ли не основными способами хранения данных.&lt;/p&gt;&lt;p&gt;==Texture Buffers==&lt;/p&gt;
&lt;p&gt;Текстурные буферы стали доступны в OpenGL 3.1 через расширение &lt;a href=&quot;http://www.opengl.org/registry/specs/ARB/texture_buffer_object.txt&quot;&gt;GL_ARB_texture_buffer_object&lt;/a&gt; (ранее доступные через расширение &lt;a href=&quot;http://www.opengl.org/registry/specs/EXT/texture_buffer_object.txt&quot;&gt;GL_EXT_texture_buffer_object&lt;/a&gt;). Данная технология позволяет считывать в вершинном шейдере данные из буфера, используя тексели текстуры как ячейки хранения данных. Поэтому, чтобы использовать такой буфер, нужно преобразовать его в формат текстуры. И для большей эффективности лучше использовать все 4 компонента текстуры.&lt;/p&gt;
&lt;p&gt;Ниже приведён абстрактный пример заполнения буфера данных для использования TextureBuffers.&lt;/p&gt;
&lt;div style=&quot;background: #f2f2f2; padding: 5px; margin: 4px;&quot;&gt;&lt;pre&gt;&lt;span style=&quot;color: #0030fF; &quot;&gt;var&lt;/span&gt;
   Data: &lt;span style=&quot;color: #0030fF; &quot;&gt;array&lt;/span&gt; &lt;span style=&quot;color: #a06000&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #F04000; &quot;&gt;0&lt;/span&gt;..&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;VertexCount – &lt;span style=&quot;color: #F04000; &quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;]&lt;/span&gt; &lt;span style=&quot;color: #0030fF; &quot;&gt;of&lt;/span&gt; TVec4f;
&lt;span style=&quot;color: #0030fF; &quot;&gt;begin&lt;/span&gt;
    &lt;span style=&quot;color: #808080&quot;&gt;//…&lt;/span&gt;
    glGenBuffers&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #F04000; &quot;&gt;1&lt;/span&gt;, @FTexBuffer&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;;
    glBindBuffer&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;GL_TEXTURE_BUFFER, FTexBuffer&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;;
    glBufferData&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;GL_TEXTURE_BUFFER, VertexCount * SizeOf&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;TVec4f&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;, @Data&lt;span style=&quot;color: #a06000&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #F04000; &quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;]&lt;/span&gt;,
                    GL_STREAM_DRAW&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;;

    glGenTextures&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #F04000; &quot;&gt;1&lt;/span&gt;, @FBuffer&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;;
    glBindTexture&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;GL_TEXTURE_BUFFER, FBuffer&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;;
    glPixelStorei&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;GL_UNPACK_ALIGNMENT, &lt;span style=&quot;color: #F04000; &quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;; 

    glTexBuffer&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;GL_TEXTURE_BUFFER, GL_RGBA32F, FTexBuffer&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;;

    glBindBuffer&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;GL_TEXTURE_BUFFER, &lt;span style=&quot;color: #F04000; &quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;;
    glBindTexture&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;GL_TEXTURE_BUFFER, &lt;span style=&quot;color: #F04000; &quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;;
&lt;span style=&quot;color: #0030fF; &quot;&gt;end&lt;/span&gt;;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;
&lt;p&gt;Далее текстурный буфер используется как обычная текстура.
&lt;div style=&quot;background: #f2f2f2; padding: 5px; margin: 4px;&quot;&gt;&lt;pre&gt;    glActiveTexture&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;GL_TEXTURE0 + Channel&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;;
    glBindTexture&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;GL_TEXTURE_BUFFER, FBuffer&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;Для получения конкретных данных нам нужно использовать смещения от начала массива данных. Эти смещения можно записывать в &lt;a href=&quot;http://www.gamedev.ru/code/terms/VertexBuffer&quot; title=&quot;Буфер вершин (Vertex Buffer)&quot;&gt;вершинный буфер&lt;/a&gt; данных (или &lt;a href=&quot;http://www.gamedev.ru/code/terms/IndexBuffer&quot; title=&quot;Буфер индексов (Index Buffer)&quot;&gt;буфер индексов&lt;/a&gt;), или же передавать в качестве вершинных атрибутов.&lt;/p&gt;
&lt;p&gt;Пример чтения данных из подобного буфера данных.&lt;/p&gt;
&lt;div style=&quot;background: #f2f2f2; padding: 5px; margin: 4px;&quot;&gt;&lt;pre&gt; 
#version &lt;span style=&quot;color: #F04000; &quot;&gt;150&lt;/span&gt;
precision highp &lt;span style=&quot;color: #0030fF; &quot;&gt;float&lt;/span&gt;;
precision highp &lt;span style=&quot;color: #0030fF; &quot;&gt;int&lt;/span&gt;;

uniform mat4 MatrixViewProjection;
uniform samplerBuffer VertexSampler0;
in &lt;span style=&quot;color: #0030fF; &quot;&gt;float&lt;/span&gt; ID;

&lt;span style=&quot;color: #0030fF; &quot;&gt;void&lt;/span&gt; main&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #0030fF; &quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;
{
     &lt;span style=&quot;color: #0030fF; &quot;&gt;int&lt;/span&gt; offset = &lt;span style=&quot;color: #0030fF; &quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;ID&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;;
     vec4 inVertex = texelFetch&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;VertexSampler0, offset&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;;

     gl_Position = MatrixViewProjection * inVertex;
}&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;
&lt;p&gt;===Дополнительная информация===
&lt;br /&gt;Максимальный объём: 128Мб (или более).
&lt;br /&gt;Максимальный объём в байтах можно получить используя константу 
&lt;div style=&quot;background: #f2f2f2; padding: 5px; margin: 4px;&quot;&gt;&lt;pre&gt;GL_MAX_TEXTURE_BUFFER_SIZE = $8C2B;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;
&amp;nbsp; 
&lt;br /&gt;Метод доступа: произвольный доступ.
&lt;br /&gt;Используемая память: локальный тип памяти.&lt;/p&gt;
&lt;p&gt;Данное расширение удобно использовать для передачи вершинных атрибутов в &lt;a href=&quot;http://www.gamedev.ru/code/terms/Shader&quot; title=&quot;Шейдер (Shader)&quot;&gt;шейдер&lt;/a&gt; без постоянного отправления в память GPU. Например, использование в статичной геометрии, где обновление данных минимально. В противном случае лучше подойдёт Uniform Buffer.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://www.gamedev.ru/community/delphinarium/articles/texture_and_uniform_buf?page=2&quot;&gt;Продолжение&lt;/a&gt;&lt;/p&gt;</description>
</item>
<item>
  <guid isPermaLink="true">http://www.gamedev.ru/code/news/scaleform-ue3</guid>
  <pubDate>Tue, 20 Apr 2010 20:55:09 GMT</pubDate>
  <title>Scaleform теперь будет встроена в Unreal Engine</title>
  <link>http://www.gamedev.ru/code/news/scaleform-ue3</link>
  <comments>http://www.gamedev.ru/code/forum/?id=132693</comments>
  <category>Графика</category>
  <category>Epic</category>
  <category>flash</category>
  <category>Scaleform</category>
  <category>UDK</category>
  <category>Unreal Engine</category>
  <description>
&lt;p&gt;Популярная система построения пользовательского интерфейса &lt;a href=&quot;http://www.scaleform.com/&quot;&gt;Scaleform&lt;/a&gt; на базе Flash популярна среди разработчиков игр. Так, например, она используется для интерфейсов пользователя в CryEngine 2 (игра Crysis), в Mass Effect 2 и во множестве других продуктов. Теперь эта технология будет поставляться вместе с Unreal Engine 3 и даже c бесплатным UDK.&lt;/p&gt;</description>
</item>
<item>
  <guid isPermaLink="true">http://www.gamedev.ru/code/articles/psp_helloworld</guid>
  <pubDate>Tue, 20 Apr 2010 19:31:57 GMT</pubDate>
  <title>Hello World приложение для Sony PSP</title>
  <link>http://www.gamedev.ru/code/articles/psp_helloworld</link>
  <comments>http://www.gamedev.ru/code/forum/?id=132642</comments>
  <category>Общее</category>
  <category>Hello World</category>
  <category>mobile</category>
  <category>PSP</category>
  <description>
&lt;p&gt;В этой статье я раскажу как написать ваше первое приложение для портативной консоли Sony PSP.&lt;/p&gt;&lt;p&gt;Нам понадобятся:
&lt;ul&gt;- Minimallist PSP SDK (&lt;a href=&quot;http://sourceforge.net/projects/minpspw/&quot;&gt;http://sourceforge.net/projects/minpspw/&lt;/a&gt;),
&lt;br /&gt;- Microsoft Visual Studio 2005-2008, можно конечно и напрямую юзать psp gcc.
&lt;br /&gt;- Ну и для тестирования сам девайс или его эмулятор (JPCSP, например, &lt;a href=&quot;http://www.jpcsp.org&quot;&gt;www.jpcsp.org&lt;/a&gt;).&lt;/ul&gt;&lt;/p&gt;
&lt;p&gt;Допустим, всё перечисленное у вас есть, продолжим.&lt;/p&gt;
&lt;p&gt;Устанавливаем SDK в любое место, если вы будете использовать Visual Studio IDE, то при установке поставьте галочку напротив Visual Studio Integration.&lt;/p&gt;
&lt;p&gt;Установили, запускаем Visual Studio, и Жмем File-&amp;gt;New-&amp;gt;Project, далее во вкладке Visual C++ ищем PSP:
&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;img src=&quot;http://www.gamedev.ru/files/images/newproject_psp.jpg&quot; alt=&quot;NewProject_Psp | Hello World приложение для Sony PSP&quot; /&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Выбераем &amp;laquo;Empty Project&amp;raquo;, прописываем пути и жмем Ok. Появится окно визарда, жмем Finish. Вуаля:
&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;img src=&quot;http://www.gamedev.ru/files/images/project_psp.jpg&quot; alt=&quot;Project_Psp | Hello World приложение для Sony PSP&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Теперь жмем в меню Build-&amp;gt;Build Solution. Процесс компиляции пройдет быстро, и в итоге мы получим EBOOT.pbp.
&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;img src=&quot;http://www.gamedev.ru/files/images/project_psp_bulid.jpg&quot; alt=&quot;Project_Psp_Bulid | Hello World приложение для Sony PSP&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Идем в папку проекта и ищем там EBOOT.pbp:
&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;img src=&quot;http://www.gamedev.ru/files/images/eboot.jpg&quot; alt=&quot;EBOOT | Hello World приложение для Sony PSP&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Теперь запуск нашего детища:&lt;/p&gt;
&lt;p&gt;1) Если у вас есть девайс:
&lt;ul&gt;a) Подключаем PSP через USB Transfer к компьютеру.
&lt;br /&gt;b) Заходим X(где X - буква диска вашего устройства, у меня F):\PSP\GAME\
&lt;br /&gt;c) Создаем папку GDPSP
&lt;br /&gt;d) Помещаем в папку EBOOT.pbp
&lt;br /&gt;e) Отключем USB Transfer
&lt;br /&gt;f) Запускаем GDPSP из Игра-&amp;gt;Memory Stick
&lt;/ul&gt;
&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;img src=&quot;http://www.gamedev.ru/files/images/memstick.jpg&quot; alt=&quot;memstick | Hello World приложение для Sony PSP&quot; /&gt;&lt;/p&gt;
&lt;p align=&quot;center&quot;&gt;&lt;img src=&quot;http://www.gamedev.ru/files/images/gdpsp.jpg&quot; alt=&quot;GDPSP | Hello World приложение для Sony PSP&quot; /&gt;&lt;/p&gt;
&lt;p&gt;2) Если вы используете JPCSP:
&lt;ul&gt;a) Жмем File-&amp;gt;Load file-&amp;gt;выбираем наш EBOOT.pbp.
&lt;br /&gt;b) Жмем Run.&lt;/ul&gt;
&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;img src=&quot;http://www.gamedev.ru/files/images/jpcsp.jpg&quot; alt=&quot;JPCSP | Hello World приложение для Sony PSP&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Пример: &lt;b&gt;&lt;a href=&quot;http://www.gamedev.ru/files/?id=53475&quot;&gt;EBOOT&lt;/a&gt;&lt;/b&gt;.&lt;/p&gt;
&lt;p&gt;Удачи в начинаниях.&lt;/p&gt;
&lt;p&gt;PS :Уже есть такие порты для PSP как:
&lt;br /&gt;- Quake
&lt;br /&gt;- Quake 2
&lt;br /&gt;- Quake 3 от нашего соотечественника&amp;nbsp; 
&lt;br /&gt;- Bochs &amp;mdash; PC x86 Emulator (для запуска Linux,Windows на PSP)&lt;/p&gt;
&lt;p&gt;Может и вы внесёте свою лепту ;)&lt;/p&gt;</description>
</item>
<item>
  <guid isPermaLink="true">http://www.gamedev.ru/code/news/parallel-nsight</guid>
  <pubDate>Sun, 18 Apr 2010 12:05:53 GMT</pubDate>
  <title>NVIDIA® Parallel Nsight™ для Visual Studio 2008</title>
  <link>http://www.gamedev.ru/code/news/parallel-nsight</link>
  <comments>http://www.gamedev.ru/code/forum/?id=132526</comments>
  <category>Графика</category>
  <category>CUDA</category>
  <category>NVIDIA</category>
  <description>
&lt;p&gt;NVIDIA® Parallel Nsight™ - среда разработки компании NVIDIA, ориентированная на программирование в условиях массового параллелизма. Этот продукт позволяет отлаживать программы, исполняющиеся на GPU не выходя за пределы привычной Visual Studio, при этом работает просмотр локальных переменных, памяти и работают break point&apos;ы.&amp;nbsp; Кроме общих вычислений Parallel Nsight позволяет отлаживать шейдеры всех видов. Базовая версия программы бесплатна, профессиональная версия оплачивается по годам – 349$ в первый год за рабочее место и 299$ за последующие.&amp;nbsp; За эти деньги программист получит возможность профилирования ядер &lt;a href=&quot;http://www.gamedev.ru/code/terms/CUDA&quot; title=&quot;CUDA&quot;&gt;CUDA&lt;/a&gt;, отслеживать вызовы различных API, получать информацию о событиях на единой шкале времени, ставить break point&apos;ы на данные и улучшенную поддержку от NVIDIA.&lt;/p&gt;
&lt;p&gt;Более подробную информацию можно получить на &lt;a href=&quot;http://developer.nvidia.com/object/nsight.html&quot;&gt;сайте компании&lt;/a&gt;.&lt;/p&gt;</description>
</item>
<item>
  <guid isPermaLink="true">http://www.gamedev.ru/code/news/vs-2010</guid>
  <pubDate>Thu, 15 Apr 2010 08:15:36 GMT</pubDate>
  <title>Visual Studio 2010</title>
  <link>http://www.gamedev.ru/code/news/vs-2010</link>
  <category>Общее</category>
  <category>C#</category>
  <category>Microsoft</category>
  <category>Visual Studio</category>
  <category>.NET</category>
  <description>
&lt;p&gt;Компания Microsoft с размахом запустила Visual Studio 2010. С 12 Апреля в крупных промышленных городах идёт презентация возможностей новой среды для разработки ПО, с которой многие уже могли ознакомиться ранее в формате предварительных версий и технологических превью.&lt;/p&gt;
&lt;p&gt;Скачать ознакомительную версию студии можно на этой &lt;a href=&quot;http://www.microsoft.com/visualstudio/en-us/download&quot;&gt;странице&lt;/a&gt;. Бесплатная Express редакция доступна всем по &lt;a href=&quot;http://www.microsoft.com/express/downloads/&quot;&gt;этой ссылке&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;В новой интегрированной среде разработки был переделан интерфейс. Это коснулось как пользовательского опыта работы с окнами и инструментами, так и изменения коснулись кода интерфейса – теперь он основан на Windows Presentation Foundation. Кроме косметических изменений переделке подверглись IntelliSense и другие части среды. Так, в новой версии, можно отслеживать граф вызовов метода. Среда содержит встроенные средства поддержки разработки с юнит-тестированием.&lt;/p&gt;
&lt;p&gt;Для быстрого освоения новых фич можно воспользоваться тренировочным набором по этой &lt;a href=&quot;http://www.microsoft.com/downloads/details.aspx?FamilyID=752CB725-969B-4732-A383-ED5740F02E93&amp;amp;displaylang=en&quot;&gt;ссылке&lt;/a&gt;. В набор входят презентации и примеры использования новых возможностей.&lt;/p&gt;
&lt;p&gt;Вместе с Visual Studio 2010 сменяет свою версию и .NET Framework. Новая, четвёртая версия фреймворка снова не совместима с предыдущими версиями (версии 3.0 и 3.5 были расширениями версии 2.0). Скачать новый фреймворк можно по этой &lt;a href=&quot;http://www.microsoft.com/downloads/details.aspx?displaylang=en&amp;amp;FamilyID=0a391abd-25c1-4fc0-919f-b21f31ab88b7&quot;&gt;ссылке&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;</description>
</item>
<item>
  <guid isPermaLink="true">http://www.gamedev.ru/code/news/nvidia-opengl-4-ext</guid>
  <pubDate>Wed, 14 Apr 2010 12:15:36 GMT</pubDate>
  <title>Новые возможности OpenGL от NVIDIA</title>
  <link>http://www.gamedev.ru/code/news/nvidia-opengl-4-ext</link>
  <category>Графика</category>
  <category>NVIDIA</category>
  <category>OpenGL</category>
  <description>
&lt;p&gt;NVIDIA представила новые драйвера &lt;a href=&quot;http://www.gamedev.ru/code/terms/OpenGL&quot; title=&quot;OpenGL: Open Graphics Library&quot;&gt;OpenGL 4&lt;/a&gt; для Linux и Windows. Кроме того в них добавлена поддержка восьми расширений:
&lt;br /&gt;•&amp;nbsp; ARB_texture_compression_bptc – новый формат сжатых текстур (аналог BC7 и BC6H в &lt;a href=&quot;http://www.gamedev.ru/code/terms/DirectX&quot; title=&quot;DirectX&quot;&gt;DirectX&lt;/a&gt; 11).
&lt;br /&gt;•&amp;nbsp; EXT_shader_image_load_store – добавляет инструкции в &lt;a href=&quot;http://www.gamedev.ru/code/terms/GLSL&quot; title=&quot;GLSL (OpenGL Shading Language)&quot;&gt;GLSL&lt;/a&gt;, позволяющие читать и писать в текстуры. 
&lt;br /&gt;•&amp;nbsp; EXT_vertex_attrib_64bit – 64-битные параметры вершинных шейдеров в формате с плавающей запятой.
&lt;br /&gt;•&amp;nbsp; NV_vertex_attrib_integer_64bit - 64-битные параметры вершинных шейдеров в целочисленном формате.
&lt;br /&gt;•&amp;nbsp; NV_gpu_program5 – набор инструкций пятого поколения для видеокарт NVIDIA.
&lt;br /&gt;•&amp;nbsp; NV_tesssellation_program5 – предоставляет доступ к шейдерам тесселяции.
&lt;br /&gt;•&amp;nbsp; NV_gpu_shader5 - аналогично ARB_gpu_shader5. Добавляет возможность отправлять patch’и, созданные на этапе тесселяции, в геометрический шейдер или на растеризацию фиксированного конвейера.
&lt;br /&gt;•&amp;nbsp; NV_shader_buffer_store – позволяет писать в буферы (ранее с расширением NV_shader_buffer_load дозволялось только читать).&lt;/p&gt;
&lt;p&gt;Драйвера и документация к ним доступны на странице &lt;a href=&quot;http://developer.nvidia.com/object/opengl_driver.html&quot;&gt;developer.nvidia.com&lt;/a&gt;.&lt;/p&gt;</description>
</item>
<item>
  <guid isPermaLink="true">http://www.gamedev.ru/code/tip/advfloat</guid>
  <pubDate>Wed, 14 Apr 2010 12:01:53 GMT</pubDate>
  <title>Трюки с float: быстрое вычисление логарифмов.</title>
  <link>http://www.gamedev.ru/code/tip/advfloat</link>
  <comments>http://www.gamedev.ru/code/forum/?id=132465</comments>
  <category>Общее</category>
  <description>
&lt;p&gt;Алгоритм быстрого вычисления логарифма, исходя из представления чисел с плавающей точкой
&lt;p&gt;Для быстрого приближенного вычисления некоторых математических функций можно использовать знания о внутреннем устройстве типа float:
&lt;div style=&quot;background: #f2f2f2; padding: 5px; margin: 4px;&quot;&gt;&lt;pre&gt;&lt;span style=&quot;color: #0030fF; &quot;&gt;union&lt;/span&gt; ADVFLOAT
{
  &lt;span style=&quot;color: #0030fF; &quot;&gt;float&lt;/span&gt; x;
  &lt;span style=&quot;color: #0030fF; &quot;&gt;struct&lt;/span&gt;
  {
    &lt;span style=&quot;color: #0030fF; &quot;&gt;unsigned&lt;/span&gt; &lt;span style=&quot;color: #0030fF; &quot;&gt;int&lt;/span&gt; mant : &lt;span style=&quot;color: #F04000; &quot;&gt;23&lt;/span&gt;; &lt;span style=&quot;color: #808080&quot;&gt;/* Mantissa without leading one */&lt;/span&gt; 
    &lt;span style=&quot;color: #0030fF; &quot;&gt;unsigned&lt;/span&gt; &lt;span style=&quot;color: #0030fF; &quot;&gt;int&lt;/span&gt; exp  : &lt;span style=&quot;color: #F04000; &quot;&gt;8&lt;/span&gt;;  &lt;span style=&quot;color: #808080&quot;&gt;/* Exponential part */&lt;/span&gt;
    &lt;span style=&quot;color: #0030fF; &quot;&gt;unsigned&lt;/span&gt; &lt;span style=&quot;color: #0030fF; &quot;&gt;int&lt;/span&gt; sign : &lt;span style=&quot;color: #F04000; &quot;&gt;1&lt;/span&gt;;  &lt;span style=&quot;color: #808080&quot;&gt;/* Indicator of the negative number */&lt;/span&gt;
  };
};&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;
Согласно стандарту IEEE 754, число с плавающей точкой будет представлено следующим образом: &lt;i&gt;x&lt;/i&gt; = (1 + &lt;i&gt;mant&lt;/i&gt;) * 2 ^ (&lt;i&gt;exp&lt;/i&gt; - 127). Таким образом, чтобы, например, удвоить число, достаточно сделать следующую операцию:
&lt;div style=&quot;background: #f2f2f2; padding: 5px; margin: 4px;&quot;&gt;&lt;pre&gt;AdvFloat.exp++;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;
Модуль числа можно получить, наложив AND&apos;ом маску 0x7FFFFFFF.
&lt;br /&gt;Более интересный случай представляет вычисление более сложных математических функций, например, логарифма. Однако, воспользовавшись свойствами логарифма и первым членом &amp;quot;волшебного&amp;quot; ряда Тейлора, легко получить достаточно точный результат:
&lt;br /&gt;&lt;tt&gt;
&lt;br /&gt;log2(&lt;b&gt;x&lt;/b&gt;) = log2((1 + &lt;b&gt;mant&lt;/b&gt;) * 2 ^ (&lt;b&gt;exp&lt;/b&gt; - 127)) = log2(1 + &lt;b&gt;mant&lt;/b&gt;) + log2(2 ^ (&lt;b&gt;exp&lt;/b&gt; - 127)) =
&lt;br /&gt; = ln(1 + &lt;b&gt;mant&lt;/b&gt;) / ln(2) + (&lt;b&gt;exp&lt;/b&gt; - 127) = ln(1 + &lt;b&gt;mant&lt;/b&gt;) / ln(2) + (&lt;b&gt;exp&lt;/b&gt; - 127) 
&lt;br /&gt; = &lt;b&gt;mant&lt;/b&gt; * log2(e) + (&lt;b&gt;exp&lt;/b&gt; - 127).
&lt;br /&gt;&lt;/tt&gt;&lt;/p&gt;
&lt;p&gt;Таким образом, функция для вычисления логаримфма выглядит так:
&lt;div style=&quot;background: #f2f2f2; padding: 5px; margin: 4px;&quot;&gt;&lt;pre&gt;&lt;span style=&quot;color: #0030fF; &quot;&gt;#define&lt;/span&gt; LOG2E &lt;span style=&quot;color: #F04000; &quot;&gt;1&lt;/span&gt;.&lt;span style=&quot;color: #F04000; &quot;&gt;44269504088896340736&lt;/span&gt;f

&lt;span style=&quot;color: #0030fF; &quot;&gt;float&lt;/span&gt; fastLog2&lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt; &lt;span style=&quot;color: #0030fF; &quot;&gt;float&lt;/span&gt; x &lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt;
{
  ADVFLOAT ax;
  &lt;span style=&quot;color: #0030fF; &quot;&gt;int&lt;/span&gt; exp;

  ax.x = x;
  exp = ax.exp - &lt;span style=&quot;color: #F04000; &quot;&gt;127&lt;/span&gt;;
  ax.sign = &lt;span style=&quot;color: #F04000; &quot;&gt;0&lt;/span&gt;;
  ax.exp = &lt;span style=&quot;color: #F04000; &quot;&gt;127&lt;/span&gt;;

  &lt;span style=&quot;color: #0030fF; &quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #a06000&quot;&gt;(&lt;/span&gt;ax.x - &lt;span style=&quot;color: #F04000; &quot;&gt;1&lt;/span&gt;.&lt;span style=&quot;color: #F04000; &quot;&gt;0&lt;/span&gt;f&lt;span style=&quot;color: #a06000&quot;&gt;)&lt;/span&gt; * LOG2E + exp;
}&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;Ошибка обычно появляется лишь во втором-третьем знаке, что весьма неплохо для такой примитивной аппроксимации. Однако, проведя более тщательный математический анализ, можно найти добиться и более высокой точности, если найти менее тривиальные коэффициенты, чем 1.0f и LOG2E. Важно, однако, сохранить линейный или по крайней мере квадратичный характер приближения, иначе весь смысл такой аппроксимации сойдёт на нет.
&lt;br /&gt;Приведёную функцию можно использовать и в готовом виде, или же можно ещё более её ускорить, использую побитовые операции. Наконец, логарифм - не единственное, что посчитать приближенно. Например, очень полезно использовать функцию fastSqrt(), построенную на том же принципе приближенного вычисления.&lt;/p&gt;</description>
</item>
<item>
  <guid isPermaLink="true">http://www.gamedev.ru/code/news/geg2-authors</guid>
  <pubDate>Tue, 13 Apr 2010 21:05:20 GMT</pubDate>
  <title>Game Engine Gems 2 ищет авторов</title>
  <link>http://www.gamedev.ru/code/news/geg2-authors</link>
  <comments>http://www.gamedev.ru/code/forum/?id=132441</comments>
  <category>Общее</category>
  <category>книги</category>
  <description>
&lt;p&gt;Издательская компания Jones and Bartlett Publishers собирается издавать новую книгу серии Game Engine Gems. В книгу войдут статьи связанные с проектированием и разработкой игровых движков, в том числе о способах рендеринга, шейдерах, OpenGL и DirectX, о расчёте физики и столкновений, техниках программирования в целом, архитектурах движков, организации ресурсов, звуке и о многом другом. Для участия в книге необходимо оформить заявку до 15 Июня 2010 года. Заявки можно оставлять на сайте &lt;a href=&quot;http://www.gameenginegems.com/&quot;&gt;gameenginegems.com&lt;/a&gt;.&lt;/p&gt;</description>
</item>
<item>
  <guid isPermaLink="true">http://www.gamedev.ru/code/terms/lobby</guid>
  <pubDate>Mon, 12 Apr 2010 13:33:10 GMT</pubDate>
  <title>Лобби-сервер</title>
  <link>http://www.gamedev.ru/code/terms/lobby</link>
  <category>Сеть</category>
  <description>
&lt;p&gt;&lt;b&gt;Лобби-сервер&lt;/b&gt;: запущенное на сервере приложение, которое служит для централизации игровых сеансов и где пользователи могут находить друг друга и взаимодействовать. Одни создают сервер игры на своем компьютере с заданными параметрами, другие подключаются к нему и играют. Лобби-сервер помогает организовать турниры, подобрать равных по силе игроков или например говорящих на одном языке, выбрать сервер с наименьшим пингом и т.д. Также он может вести статистику побед и поражений, различных наград, предоставлять чат (в том числе и голосовой) и новостную ленту.
&lt;p&gt;&lt;b&gt;Внешний лобби-клиент&lt;/b&gt;: приложение, предназначенное только для подключения к лобби-серверу и взаимодействия к ним. Если будет выбран подходящий сеанс, приложение запустит игру и передаст в нее необходимые данные. Примером может служить GameSpy Arcade, которая работает с несколькими популярными играми.
&lt;p&gt;&lt;b&gt;Внутренний лобби-клиент&lt;/b&gt;: функционал лобби встроен в саму игру, при этом нет необходимости запускать сторонние утилиты.
&lt;p&gt;&lt;/p&gt;</description>
</item>
</channel>
</rss>
