<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" >

<channel>
	<title>dev-&gt;harmony</title>
	<atom:link href="http://kirnosenko.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://kirnosenko.com</link>
	<description></description>
	<lastBuildDate>
	Sun, 15 Nov 2020 17:11:29 +0000	</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=5.1.12</generator>
<site xmlns="com-wordpress:feed-additions:1">19155545</site>	<item>
		<title>React &#8211; 7.5 years of code evolution</title>
		<link>http://kirnosenko.com/2020/11/15/react-7-5-years-of-code-evolution/</link>
				<pubDate>Sun, 15 Nov 2020 17:11:28 +0000</pubDate>
		<dc:creator><![CDATA[Semyon Kirnosenko]]></dc:creator>
				<category><![CDATA[Metric Findings]]></category>
		<category><![CDATA[Metrics]]></category>
		<category><![CDATA[MSR]]></category>
		<category><![CDATA[Repositorch]]></category>
		<category><![CDATA[Git]]></category>
		<category><![CDATA[react]]></category>

		<guid isPermaLink="false">http://kirnosenko.com/?p=421</guid>
				<description><![CDATA[Today we use repositorch to look at git repository of react project. React repository is 13700 commits by 1624 authors in 1921 files resulting in&#8230;]]></description>
								<content:encoded><![CDATA[<p>Today we use <a href="https://github.com/kirnosenko/Repositorch" target="_blank" rel="noopener noreferrer">repositorch</a> to look at git repository of <a href="https://github.com/facebook/react" target="_blank" rel="noopener noreferrer">react project</a>.</p>
<p><span id="more-421"></span></p>
<p>React repository is 13700 commits by 1624 authors in 1921 files resulting in 500K lines. Code on JavaScript is about 350K lines.</p>
<p>JavaScript code burndown by year:<a href="http://kirnosenko.com/2020/11/15/react-7-5-years-of-code-evolution/react-js-burndown/" rel="attachment wp-att-422"><img data-attachment-id="422" data-permalink="http://kirnosenko.com/2020/11/15/react-7-5-years-of-code-evolution/react-js-burndown/" data-orig-file="http://kirnosenko.com/wp-content/uploads/2020/11/react-js-burndown.png" data-orig-size="1349,667" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="react-js-burndown" data-image-description="" data-medium-file="http://kirnosenko.com/wp-content/uploads/2020/11/react-js-burndown-300x148.png" data-large-file="http://kirnosenko.com/wp-content/uploads/2020/11/react-js-burndown-1024x506.png" class="aligncenter wp-image-422 size-large" src="http://kirnosenko.com/wp-content/uploads/2020/11/react-js-burndown-1024x506.png" alt="" width="1024" height="506" srcset="http://kirnosenko.com/wp-content/uploads/2020/11/react-js-burndown-1024x506.png 1024w, http://kirnosenko.com/wp-content/uploads/2020/11/react-js-burndown-300x148.png 300w, http://kirnosenko.com/wp-content/uploads/2020/11/react-js-burndown-768x380.png 768w, http://kirnosenko.com/wp-content/uploads/2020/11/react-js-burndown.png 1349w" sizes="(max-width: 1024px) 100vw, 1024px" /></a>JavaScript code ownership by author with 5% threshold:</p>
<p><a href="http://kirnosenko.com/2020/11/15/react-7-5-years-of-code-evolution/react-js-contribution/" rel="attachment wp-att-424"><img data-attachment-id="424" data-permalink="http://kirnosenko.com/2020/11/15/react-7-5-years-of-code-evolution/react-js-contribution/" data-orig-file="http://kirnosenko.com/wp-content/uploads/2020/11/react-js-contribution.png" data-orig-size="1351,663" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="react-js-contribution" data-image-description="" data-medium-file="http://kirnosenko.com/wp-content/uploads/2020/11/react-js-contribution-300x147.png" data-large-file="http://kirnosenko.com/wp-content/uploads/2020/11/react-js-contribution-1024x503.png" class="aligncenter size-large wp-image-424" src="http://kirnosenko.com/wp-content/uploads/2020/11/react-js-contribution-1024x503.png" alt="" width="1024" height="503" srcset="http://kirnosenko.com/wp-content/uploads/2020/11/react-js-contribution-1024x503.png 1024w, http://kirnosenko.com/wp-content/uploads/2020/11/react-js-contribution-300x147.png 300w, http://kirnosenko.com/wp-content/uploads/2020/11/react-js-contribution-768x377.png 768w, http://kirnosenko.com/wp-content/uploads/2020/11/react-js-contribution.png 1351w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>&nbsp;</p>
]]></content:encoded>
									<post-id xmlns="com-wordpress:feed-additions:1">421</post-id>	</item>
		<item>
		<title>A new life for the old idea</title>
		<link>http://kirnosenko.com/2020/09/13/a-new-life-for-the-old-idea/</link>
				<pubDate>Sun, 13 Sep 2020 08:06:31 +0000</pubDate>
		<dc:creator><![CDATA[Semyon Kirnosenko]]></dc:creator>
				<category><![CDATA[Repositorch]]></category>
		<category><![CDATA[Git]]></category>
		<category><![CDATA[Statistics]]></category>

		<guid isPermaLink="false">http://kirnosenko.com/?p=415</guid>
				<description><![CDATA[10 years ago I have created MSR tools: tools for mining software repositories. Its purpose was to solve scientific problems in software defect prediction. Also,&#8230;]]></description>
								<content:encoded><![CDATA[
<p style="text-align: justify;">10 years ago I have created <a href="https://github.com/kirnosenko/msr-tools" target="_blank" rel="noopener noreferrer">MSR tools</a>: tools for mining software repositories. Its purpose was to solve scientific problems in software defect prediction. Also, it was able to get lots of interesting metrics from version control history. Unfortunately, MSR Tools had some issues making it problematic to use. But now I have something better&#8230;</p>
<p><span id="more-415"></span></p>
<p style="text-align: justify;">Initially, MSR Tools was designed for SVN and then poorly adapted for GIT. As a result, it had serious limitations with branch processing which makes it inapplicable for most GIT repositories. Another problem was about infrastructure which requires the installation of MS SQL Server. Project configuration via container XML-files was truly unintuitive and user-unfriendly.</p>
<p style="text-align: justify;">But time does not stand still. Ten years ago there was no .NET Core, Docker or React. Now we have it all and it makes things so different. Using some modern approaches I have reimplemented the core idea of old software to make a new one. Meet <a href="https://github.com/kirnosenko/Repositorch" target="_blank" rel="noopener noreferrer">Repositorch</a>: a version control system analysis engine written in C#.</p>
<p style="text-align: justify;">Right now Repositorch is focused on getting and representing code metrics based on repository evolution. It is easy to use solution, which works on Linux or Windows and allows you to mine some really interesting stuff. Check ten minutes &#8220;how to use&#8221; guide:</p>
<p><iframe class='youtube-player' type='text/html' width='640' height='360' src='http://www.youtube.com/embed/Rd5R0BbFdGA?version=3&#038;rel=1&#038;fs=1&#038;autohide=2&#038;showsearch=0&#038;showinfo=1&#038;iv_load_policy=1&#038;wmode=transparent' allowfullscreen='true' style='border:0;'></iframe></p>
]]></content:encoded>
									<post-id xmlns="com-wordpress:feed-additions:1">415</post-id>	</item>
		<item>
		<title>Реальный опыт использования MonoGame для разработки мобильной игры</title>
		<link>http://kirnosenko.com/2018/08/30/the-real-experience-of-using-monogame-for-mobile-game-development/</link>
				<pubDate>Thu, 30 Aug 2018 08:14:15 +0000</pubDate>
		<dc:creator><![CDATA[Semyon Kirnosenko]]></dc:creator>
				<category><![CDATA[BusyBalls]]></category>
		<category><![CDATA[Games]]></category>
		<category><![CDATA[MonoGame]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://kirnosenko.com/?p=396</guid>
				<description><![CDATA[На протяжении достаточно продолжительного периода, я в свободное от отдыха время занимался разработкой небольшого доморощенного игрового движка на основе MonoGame. По началу было очень интересно&#8230;]]></description>
								<content:encoded><![CDATA[<p style="text-align: justify;">На протяжении достаточно продолжительного периода, я в свободное от отдыха время занимался разработкой небольшого доморощенного игрового движка на основе <a href="http://www.monogame.net/" target="_blank" rel="noopener">MonoGame</a>. По началу было очень интересно попробовать реализовать различные вещи, которые популярные движки позволяют получить сразу из коробки. В процессе пришло понимание, что полный контроль &#8211; это безусловно здорово, но и цена высока. Однажды в процессе изучения Xamarin я наткнулся на простую демку, демонстрирующую использование MonoGame на Android. Тогда и пришла идея адаптировать имеющиеся наработки для мобильной платформы, чтобы сделать наконец что-то, быть может не слишком сложное, но завершённое&#8230;<span id="more-396"></span></p>
<p style="text-align: justify;">За основу была взята идея простой физической симуляции шаров в ящике, управляемой положением мобильного устройства. Этакая пространственная вариация на тему цветных шаров, по мотивам которых существует много так называемых &#8220;тайм-киллеров&#8221;. Периодически безмятежность процесса прерывалась различными тонкими моментами, фичами, багами, с которыми пришлось в разной степени мириться/бороться.</p>
<p><strong>Прежде всего</strong></p>
<p style="text-align: justify;">пришлось обновиться до <a href="https://github.com/MonoGame/MonoGame" target="_blank" rel="noopener">актуальной версии кода</a>. Последняя стабильная версия 3.6 фактически не имеет поддержки OpenGL ES 3 и с поддержкой более ранних версий тоже справляется плохо, демонстрируя стабильные вылеты.</p>
<p><strong>Доступ к ресурсам</strong></p>
<p style="text-align: justify;">по началу может стать причиной неожиданных ошибок в процессе исполнения. Дело в том, что Android основан на ядре Linux и потому обладает свойством чувствительности к регистру символов в именах файлов и путях к ним. Несовпадение регистра символов никак не проявляется при работе в Windows. Но стОит запустить тот же самый код на Android и приложение валится при попытке загрузки ресурсов.</p>
<p><strong>Графика и все что с ней связано</strong></p>
<p style="text-align: justify;">предсказуемо стала источником большинства проблем, как и в случае перехода с XNA на MonoGame. Пришлось довольствоваться возможностями shader model 3 и мириться с большим количеством ограничений. Так например нет возможности использовать floating point render target. А значит для хранения например глубины сцены придется пользоваться какими-нибудь схемами <a href="https://aras-p.info/blog/2009/07/30/encoding-floats-to-rgba-the-final/" target="_blank" rel="noopener">кодирования</a>.</p>
<p style="text-align: justify;">Вертексные и индексные буферы имеют метод GetData. Он позволяет вытащить геометрию из уже созданных буферов, что может быть полезно например для создания модели физики для уже загруженной 3D-модели. Метод хоть и не самый быстрый, но очень удобный. Работая без проблем на десктопе, на мобильной платформе не поддерживается. А без него придется либо править Content Pileline, либо формировать упрощённую физическую модель другими методами.</p>
<p style="text-align: justify;">Среди параметров растеризации есть FillMode, который будучи установленным в значение WireFrame, позволяет отрисовывать только полигональную сетку. Опять же бывает очень удобно в процессе отладки. Однако для Android эта функция не реализована.</p>
<p style="text-align: justify;">Использование семантик COLOR и NORMAL при передаче параметров в пиксельные шейдеры, приводит к невозможности эти параметры использовать. При этом нет ошибок компиляции или исключений в процессе исполнения. Приложение просто намертво зависает. Приходится плодить семантики TEXCOORD1, TEXCOORD2 и т.д.</p>
<p style="text-align: justify;">Для работы различных графических эффектов часто применяются шумы. Чтобы сэкономить время и ресурсы источником шума может быть некая математическая функция. Вот например как выглядит очень типичный код генерации случайной нормали по текстурным координатам:</p>
<p></p><pre class="crayon-plain-tag">float3 randomNormal(float2 tex)
{
  float noiseX = (frac(sin(dot(tex, float2(15.8989f, 76.132f) * 1.0f)) * 46336.23745f));
  float noiseY = (frac(sin(dot(tex, float2(11.9899f, 62.223f) * 2.0f)) * 34748.34744f));
  float noiseZ = (frac(sin(dot(tex, float2(13.3238f, 63.122f) * 3.0f)) * 59998.47362f));
  return normalize(float3(noiseX, noiseY, noiseZ));
}</pre><p></p>
<p style="text-align: justify;">Однако полученная таким образом текстура нормалей на мобильной платформе из-за меньшей точности отличается. Разница между правильным (слева) и неправильным (справа) результатами видна невооруженным глазом. Для решения этой проблемы проще всего пользоваться традиционной готовой текстурой.</p>
<p><a href="http://kirnosenko.com/2018/08/30/the-real-experience-of-using-monogame-for-mobile-game-development/noise/" rel="attachment wp-att-398"><img data-attachment-id="398" data-permalink="http://kirnosenko.com/2018/08/30/the-real-experience-of-using-monogame-for-mobile-game-development/noise/" data-orig-file="http://kirnosenko.com/wp-content/uploads/2018/08/noise.png" data-orig-size="600,400" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="noise" data-image-description="" data-medium-file="http://kirnosenko.com/wp-content/uploads/2018/08/noise-300x200.png" data-large-file="http://kirnosenko.com/wp-content/uploads/2018/08/noise.png" class="aligncenter size-medium wp-image-398" src="http://kirnosenko.com/wp-content/uploads/2018/08/noise-300x200.png" alt="" width="300" height="200" srcset="http://kirnosenko.com/wp-content/uploads/2018/08/noise-300x200.png 300w, http://kirnosenko.com/wp-content/uploads/2018/08/noise.png 600w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>
<p><strong>Производительность</strong></p>
<p style="text-align: justify;">едва ли будет проблемой, если игра достаточно проста и использует спрайтовую анимацию. В моём случае требовалось отрисовывать трехмерную сцену с эффектами и выполнять физическую симуляцию. Не слишком древний аппарат на 4-м Android&#8217;е захлебывался очень быстро. Более свежий аппарат на 7-м Andriod&#8217;е показывал лучшие результаты, но не идеальные. Вынос физики в отдельный поток решил проблему. Остальной код к асинхронной работе физики оказался готов. Почти&#8230; Лишь спустя какое-то время на записи видео игрового процесса удалось разглядеть рассинхрон между геометрией и затенением для неё. Причина была в обновлениях физики, которые вклинивались между формированием двух картинок. Исправить оказалось легче, чем заметить.</p>
<p style="text-align: justify;">Причиной менее очевидных проблем может стать JIT-компиляция. И тут следует зайти из далека. Если не рассматривать различные варианты обфускации, то есть всего три варианта сборки, от выбора которых зависит что в итоге будет содержать результирующий APK-файл:</p>
<p style="text-align: justify;">1. Все ваши библиотеки в неизменном виде. Вариант по умолчанию. Худший вариант ибо и размер APK-файла большой и код абсолютно открыт для исследования/модификации/заимствования.</p>
<p style="text-align: justify;">2. IL-код ваших библиотек интегрированный в нативные бинарники (опция &#8220;Bundle Assemblies into Native Code&#8221;, доступна в Enterprise версии). Позволяет значительно сократить размер APK-файла и усложнить любые манипуляции с кодом.</p>
<p style="text-align: justify;">3. Нативный код (опция &#8220;AOT Compilation&#8221;, доступна в Enterprise версии). Позволяет сократить время запуска и максимально усложнить манипуляции с кодом, но размер APK-файла снова большой.</p>
<p style="text-align: justify;">В первых двух случаях APK-файл содержит IL-код ваших библиотек, который подвергается JIT-компиляции в процессе исполнения. Но не сразу и не весь, а по мере необходимости и частями. Поэтому если так случается, что значительный объем кода до некоторого момента времени не использовался, а потом вдруг понадобился, то его JIT-компиляция может оказаться достаточно продолжительной для того, чтобы привести к заметному притормаживанию. В игровых приложениях это приводит к падению частоты кадров, что конечно крайне нежелательно. Если подобные эффекты слишком заметны, то есть лишь два варианта: либо использовать AOT-компиляцию, либо выполнять прогоны целевого кода на этапе загрузки, чтобы в последствии не тратить время на JIT-компиляцию.</p>
<p><strong>В итоге</strong></p>
<p style="text-align: justify;">каких-то специфичных только для MonoGame трудностей возникло немного. Это лишний раз подтверждает зрелость библиотеки и её готовность для решения подобных задач. Конечно сегодня, учитывая существование и относительную доступность таких движков как <a href="https://unity3d.com/" target="_blank" rel="noopener">Unity</a>, подобные методы можно охарактеризовать как скорее неверные. По крайней мере, если главной целью является быстрое достижение результата. Тем не менее, эти методы все же работают и нашли воплощение в игре <a href="https://play.google.com/store/apps/details?id=com.kirnosenko.BusyBalls" target="_blank" rel="noopener">BusyBalls</a>.</p>
]]></content:encoded>
									<post-id xmlns="com-wordpress:feed-additions:1">396</post-id>	</item>
		<item>
		<title>Пришло время для MonoGame</title>
		<link>http://kirnosenko.com/2015/07/23/it-is-time-for-monogame/</link>
				<pubDate>Thu, 23 Jul 2015 11:27:35 +0000</pubDate>
		<dc:creator><![CDATA[Semyon Kirnosenko]]></dc:creator>
				<category><![CDATA[MonoGame]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://kirnosenko.com/?p=352</guid>
				<description><![CDATA[Очень долгое время MonoGame был не вполне комфортным для использования. Отсутствие собственного Content Pipeline вынуждало устанавливать XNA и Visual Studio 2010, плясать с бубном, а&#8230;]]></description>
								<content:encoded><![CDATA[<p style="text-align: justify;">Очень долгое время <a href="http://www.monogame.net/" target="_blank">MonoGame</a> был не вполне комфортным для использования. Отсутствие собственного <a href="https://msdn.microsoft.com/en-us/library/bb447745.aspx" target="_blank">Content Pipeline</a> вынуждало устанавливать XNA и Visual Studio 2010, плясать с бубном, а в итоге единственным надёжно рабочим решением было добавление в проект уже скомпилированных файлов ресурсов *.xnb. Кроме того, многие возможности XNA оставались нереализованными. Но теперь всё изменилось&#8230;<span id="more-352"></span></p>
<p style="text-align: justify;">Начать проще простого. Идём на <a href="http://www.monogame.net/" target="_blank">официальный сайт</a> и загружаем версию для Visual Studio. Сразу после установки появляются шаблоны проектов MonoGame.</p>
<p style="text-align: justify;"><a href="http://kirnosenko.com/wp-content/uploads/2015/07/monogame-templates.png"><img data-attachment-id="354" data-permalink="http://kirnosenko.com/2015/07/23/it-is-time-for-monogame/monogame-templates/" data-orig-file="http://kirnosenko.com/wp-content/uploads/2015/07/monogame-templates.png" data-orig-size="955,660" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Шаблоны MonoGame" data-image-description="" data-medium-file="http://kirnosenko.com/wp-content/uploads/2015/07/monogame-templates-300x207.png" data-large-file="http://kirnosenko.com/wp-content/uploads/2015/07/monogame-templates.png" class="aligncenter size-medium wp-image-354" src="http://kirnosenko.com/wp-content/uploads/2015/07/monogame-templates-300x207.png" alt="Шаблоны MonoGame" width="300" height="207" srcset="http://kirnosenko.com/wp-content/uploads/2015/07/monogame-templates-300x207.png 300w, http://kirnosenko.com/wp-content/uploads/2015/07/monogame-templates.png 955w" sizes="(max-width: 300px) 100vw, 300px" /></a>Или не появляются&#8230; В этом случае проблема может быть в том, что в настройках Visual Studio был изменён путь к каталогу с шаблонами и придётся скопировать их вручную из каталога где обычно находятся шаблоны проектов C:\Documents and Settings\UserName\Documents\Visual Studio 2013\Templates\ProjectTemplates\Visual C#.</p>
<p style="text-align: justify;">Выбираем проект для той платформы, которая нам нужна и вперёд. Я выбираю Windows Project, т.е. проект для ОС Windows использующий DirectX в качестве графического API. Естественно, вновь созданный пустой проект тут же можно скомпилировать, запустить и узреть пустой экран закрашенный цветом васильков, он же CornflowerBlue.</p>
<p style="text-align: justify;">В последних версиях MonoGame работа с контентом стала наконец такой же удобной как и при использовании XNA. И даже лучше. Больше не нужно никаких Content Project! Прямо в основном проекте теперь есть файл Content.mgcb, при попытке редактирования которого открывается новая утилита MonoGame Pipeline, предназначенная для добавления ресурсов в наше приложение.</p>
<p style="text-align: justify;"><a href="http://kirnosenko.com/wp-content/uploads/2015/07/monogame-pipeline.png"><img data-attachment-id="355" data-permalink="http://kirnosenko.com/2015/07/23/it-is-time-for-monogame/monogame-pipeline/" data-orig-file="http://kirnosenko.com/wp-content/uploads/2015/07/monogame-pipeline.png" data-orig-size="800,599" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Monogame Pipeline" data-image-description="" data-medium-file="http://kirnosenko.com/wp-content/uploads/2015/07/monogame-pipeline-300x225.png" data-large-file="http://kirnosenko.com/wp-content/uploads/2015/07/monogame-pipeline.png" class="aligncenter size-medium wp-image-355" src="http://kirnosenko.com/wp-content/uploads/2015/07/monogame-pipeline-300x225.png" alt="Monogame Pipeline" width="300" height="225" srcset="http://kirnosenko.com/wp-content/uploads/2015/07/monogame-pipeline-300x225.png 300w, http://kirnosenko.com/wp-content/uploads/2015/07/monogame-pipeline.png 800w" sizes="(max-width: 300px) 100vw, 300px" /></a>Добавим какую-нибудь модель в формате .fbx и текстуру для неё. Выполним билд (F6). Утилита должна рапортовать об успехе. Радует, что запускать её придётся только для добавления новых ресурсов. При редактировании ранее добавленных их перекомпиляция выполняется автоматически при построении проекта в Visual Studio, а в случае неудачи причины сразу видны в окне Error List.</p>
<p style="text-align: justify;">Теперь попробуем отрисовать нашу модель. Для этого нам понадобится объявить несколько переменных для модели, текстуры и эффекта.</p>
<p></p><pre class="crayon-plain-tag">Model model;
Texture texture;
Effect modelEffect;</pre><p></p>
<p style="text-align: justify;">Далее в метод LoadContent добавляем код для загрузки необходимых ресурсов. Для эффекта указываем в качестве параметров матрицы мира, вида и проекции, а также текстуру.</p>
<p></p><pre class="crayon-plain-tag">model = Content.Load&amp;lt;Model&amp;gt;(&quot;Statue&quot;);
texture = Content.Load&amp;lt;Texture2D&amp;gt;(&quot;Bronze&quot;);
modelEffect = Content.Load&amp;lt;Effect&amp;gt;(&quot;Model&quot;);
modelEffect.Parameters[&quot;world&quot;].SetValue(Matrix.CreateFromYawPitchRoll(-1,0,0));
modelEffect.Parameters[&quot;projection&quot;].SetValue(Matrix.CreatePerspectiveFieldOfView(
&nbsp;&nbsp; &nbsp;MathHelper.ToRadians(90),
&nbsp;&nbsp; &nbsp;graphics.GraphicsDevice.Viewport.AspectRatio,
&nbsp;&nbsp; &nbsp;0.01f,
&nbsp;&nbsp; &nbsp;100.0f
));
modelEffect.Parameters[&quot;view&quot;].SetValue(Matrix.CreateLookAt(
&nbsp;&nbsp; &nbsp;new Vector3(15, 20, 15),
&nbsp;&nbsp; &nbsp;new Vector3(0, 25, 0),
&nbsp;&nbsp; &nbsp;Vector3.Up
));
modelEffect.Parameters[&quot;colorMap&quot;].SetValue(texture);</pre><p></p>
<p style="text-align: justify;">В метод Draw добавим код для отрисовки модели с нашим кастомным эффектом.</p>
<p></p><pre class="crayon-plain-tag">protected override void Draw(GameTime gameTime)
{
&nbsp;&nbsp; &nbsp;GraphicsDevice.Clear(Color.Black);

&nbsp;&nbsp; &nbsp;modelEffect.CurrentTechnique = modelEffect.Techniques[&quot;Model&quot;];
&nbsp;&nbsp; &nbsp;modelEffect.CurrentTechnique.Passes[0].Apply();
&nbsp;&nbsp; &nbsp;foreach (ModelMesh mesh in model.Meshes)
&nbsp;&nbsp; &nbsp;{
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;foreach (ModelMeshPart meshPart in mesh.MeshParts)
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;{
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;graphics.GraphicsDevice.Indices = meshPart.IndexBuffer;
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;graphics.GraphicsDevice.SetVertexBuffer(meshPart.VertexBuffer);
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;graphics.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, meshPart.NumVertices, meshPart.StartIndex, meshPart.PrimitiveCount);
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}
&nbsp;&nbsp; &nbsp;}&nbsp;&nbsp; &nbsp;
&nbsp;&nbsp; &nbsp;base.Draw(gameTime);
}</pre><p></p>
<p style="text-align: justify;">Далее переходим к коду шейдера на языке HLSL. В нём нам понадобятся переменные для ранее заданных матриц и текстуры.</p>
<p></p><pre class="crayon-plain-tag">float4x4 world;
float4x4 view;
float4x4 projection;

Texture2D colorMap;
SamplerState filter : register(s0);</pre><p></p>
<p style="text-align: justify;">Фильтры для текстур установленные непосредственно в коде шейдера не всегда корректно работают, поэтому лучше устанавливать их в коде программы.</p>
<p></p><pre class="crayon-plain-tag">graphics.GraphicsDevice.SamplerStates[0] = new SamplerState()
{
&nbsp;&nbsp; &nbsp;AddressU = TextureAddressMode.Clamp,
&nbsp;&nbsp; &nbsp;AddressV = TextureAddressMode.Clamp,
&nbsp;&nbsp; &nbsp;Filter = TextureFilter.Anisotropic,
&nbsp;&nbsp; &nbsp;MaxAnisotropy = 8
};</pre><p></p>
<p style="text-align: justify;">Далее структуры для входа и выхода вершинного шейдера.</p>
<p></p><pre class="crayon-plain-tag">struct VSInput
{
&nbsp;&nbsp;&nbsp; float3 Position : SV_POSITION;
&nbsp;&nbsp; &nbsp;float3 Normal : NORMAL0;
&nbsp;&nbsp; &nbsp;float2 UV : TEXCOORD0;
&nbsp;&nbsp; &nbsp;float4 Color : COLOR0;
};
struct VSOutput
{
&nbsp;&nbsp;&nbsp; float4 Position : SV_POSITION;
&nbsp;&nbsp; &nbsp;float4 WorldPosition : COLOR0;
&nbsp;&nbsp; &nbsp;float3 Normal : NORMAL0;
};</pre><p></p>
<p style="text-align: justify;">Вершинный шейдер лишь трансформирует координаты вершин и нормали в соответствии с указанными матрицами.</p>
<p></p><pre class="crayon-plain-tag">VSOutput ModelVS(VSInput input)
{
&nbsp;&nbsp;&nbsp; VSOutput output;
&nbsp;&nbsp; &nbsp;
&nbsp;&nbsp; &nbsp;output.WorldPosition = mul(float4(input.Position, 1), world);
&nbsp;&nbsp; &nbsp;float4 viewPosition = mul(output.WorldPosition, view);
&nbsp;&nbsp;&nbsp; output.Position = mul(viewPosition, projection);
&nbsp;&nbsp; &nbsp;output.Normal = mul(float4(input.Normal, 1), world).xyz;
&nbsp;&nbsp; &nbsp;
&nbsp;&nbsp;&nbsp; return output;
}</pre><p></p>
<p style="text-align: justify;">Наконец пиксельный шейдер выполняет сэмплинг текстуры, чтобы вывести пиксель нужного цвета. К сожалению, используемая модель содержит информацию только о координатах вершин и нормалях. Поэтому используется <a href="https://github.com/ashima/webgl-noise" target="_blank">GPU реализация симплекс шума</a> для того, чтобы получить нечто похожее на текстурные координаты по мировым координатам точки.</p>
<p></p><pre class="crayon-plain-tag">float4 ModelPS(VSOutput input) : SV_TARGET0
{
&nbsp;&nbsp; &nbsp;float2 uv = float2(
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;snoise(input.WorldPosition.xyz*2),
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;snoise(input.WorldPosition.zxy*2)
&nbsp;&nbsp; &nbsp;);
&nbsp;&nbsp; &nbsp;float3 color = colorMap.Sample(filter, uv).rgb;&nbsp;&nbsp; &nbsp;
&nbsp;&nbsp; &nbsp;
    return float4(color, 1);
}</pre><p></p>
<p style="text-align: justify;">В самом конце создаём однопроходную технику использующую вершинный и пиксельный шейдеры.</p>
<p></p><pre class="crayon-plain-tag">technique Model
{
&nbsp;&nbsp;&nbsp; pass Pass1
&nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; VertexShader = compile vs_5_0 ModelVS();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PixelShader = compile ps_5_0 ModelPS();
&nbsp;&nbsp;&nbsp; }
}</pre><p></p>
<p style="text-align: justify;">Данный шейдер расcчитан на использование DirectX 11. В дополнение можно прикрутить примитивное освещение от одного источника и увидеть результат.</p>
<p style="text-align: justify;"><a href="http://kirnosenko.com/wp-content/uploads/2015/07/monogamesample1.png"><img data-attachment-id="374" data-permalink="http://kirnosenko.com/2015/07/23/it-is-time-for-monogame/monogamesample1/" data-orig-file="http://kirnosenko.com/wp-content/uploads/2015/07/monogamesample1.png" data-orig-size="816,518" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="monogamesample1" data-image-description="" data-medium-file="http://kirnosenko.com/wp-content/uploads/2015/07/monogamesample1-300x190.png" data-large-file="http://kirnosenko.com/wp-content/uploads/2015/07/monogamesample1.png" class="aligncenter size-medium wp-image-374" src="http://kirnosenko.com/wp-content/uploads/2015/07/monogamesample1-300x190.png" alt="monogamesample1" width="300" height="190" srcset="http://kirnosenko.com/wp-content/uploads/2015/07/monogamesample1-300x190.png 300w, http://kirnosenko.com/wp-content/uploads/2015/07/monogamesample1.png 816w" sizes="(max-width: 300px) 100vw, 300px" /></a>Проект для Visual Studio доступен <a href="http://github.com/kirnosenko/MonoGameSample" target="_blank">здесь</a>.</p>
<p style="text-align: justify;">Портирование готового проекта с XNA на MonoGame в текущих реалиях является относительно несложной задачей. Потребности править код скорее всего не будет. Единственное несоответствие API XNA, с которым я столкнулся это отсутствие метода Transform у структуры Matrix. Если сложности и возникнут, то они будут связаны с шейдерами. Самое большое неудобство &#8211; крайне агрессивная оптимизация вне зависимости от того выполняется построение DEBUG или RELEASE версии проекта. Как следствие, стоит только в шейдере не воспользоваться текстурой, как переменная для неё исчезает и получаем ошибку исполнения при попытке установить соответствующий параметр шейдера. Раздражает&#8230;</p>
<p style="text-align: justify;">Для Windows мы можем выбирать между двумя графическими API: OpenGL и DirectX. Выбирая первое, как и в XNA мы будем ограничены возможностями шейдеров модели 3.0. При этом код на HLSL будет при компиляции транслироваться в GLSL. Выбирая DirectX, мы теоретически можем пользоваться возможностями шейдеров вплоть до модели 5.0, но только теоретически. Пока что MonoGame поддерживает только вершинные и пиксельные шейдеры, а значит самые интересные возможности DirectX 10 и 11 остаются недоступными. Многие относительно простые вещи, которых по понятным причинам не могло быть в XNA, отсутствуют и в MonoGame. Метода для генерации mipmap нет, возможности прочитать hardware-глубину нет и т.д. Разумеется всё решаемо. Исходный код MonoGame <a href="http://github.com/mono/MonoGame" target="_blank">доступен</a> и при желании всё необходимое можно доделать. Что-то делается совсем <a href="http://github.com/kirnosenko/MonoGame/commit/b6d42d0ba653437c7e7075e1a38a3377a96be86d" target="_blank">просто</a>, что-то сложнее&#8230;</p>
<p style="text-align: justify;">Утилита для компиляции ресурсов также не лишена проблем. Они часто возникают при обработке .fbx моделей. Иногда проблема &#8211; лишь следствие устаревшего формата входного файла и решается повторным экспортом из <a href="http://www.blender.org" target="_blank">blender</a> в новый формат. Иногда это не помогает. Обработка текстур с неполным набором каналов также может быть неудачной.</p>
<p style="text-align: justify;">Поводя итог&#8230; Использование MonoGame никогда не было совсем безболезненным процессом и сейчас таковым не является. Но теперь настал тот момент, когда можно говорить о достаточной зрелости проекта, чтобы те кто до сих пор не отказался от XNA наконец сделали это. Хотя бы по той причине, что MonoGame продолжает развиваться. Пусть и не так быстро как хотелось бы&#8230;</p>
]]></content:encoded>
									<post-id xmlns="com-wordpress:feed-additions:1">352</post-id>	</item>
		<item>
		<title>Одним кандидатом больше</title>
		<link>http://kirnosenko.com/2013/08/25/one-more-phd/</link>
				<pubDate>Sun, 25 Aug 2013 09:44:40 +0000</pubDate>
		<dc:creator><![CDATA[Semyon Kirnosenko]]></dc:creator>
				<category><![CDATA[Code Quality]]></category>
		<category><![CDATA[MSR Tools]]></category>

		<guid isPermaLink="false">http://kirnosenko.com/?p=167</guid>
				<description><![CDATA[После того как ВАК наконец прислал диплом, кажется самое время выложить плоды моего труда в открытый доступ. Если Вам интересны внутренности MSR Tools или математическая&#8230;]]></description>
								<content:encoded><![CDATA[<p style="text-align: justify;">После того как ВАК наконец прислал диплом, кажется самое время выложить плоды моего труда в открытый доступ. Если Вам интересны внутренности <a href="http://msr.sourceforge.net/" target="_blank">MSR Tools</a> или математическая кухня прогнозирования дефектов, если Ваши научные интересы лежат в области программной инженерии, то это чтиво для Вас. Автореферат, текст диссертации, наборы экспериментальных данных и <a href="http://msr.sourceforge.net/" target="_blank">MSR Tools</a> конечно &#8211; всё что может понадобиться для применения моих изысканий.<span id="more-167"></span></p>
<p style="text-align: justify;"><div class='w3eden'><!-- WPDM Link Template: Default Template --><div class="wpdm-link-tpl link-btn [color]" data-durl="http://kirnosenko.com/?wpdmdl=364" >    <div class="media">        <div class="pull-left"><img class="wpdm_icon"   src="http://kirnosenko.com/wp-content/plugins/download-manager/file-type-icons/download1.png" /></div>        <div class="media-body"><strong class="ptitle">Автореферат <span class="label label-default" style="font-weight: 400;">358.68 KB</span></strong>            <div><strong><a class='wpdm-download-link wpdm-download-locked [btnclass]' rel='noindex nofollow' href='http://kirnosenko.com/?wpdmdl=364'><i class=''></i>Download</a></strong></div>        </div>    </div></div><div style="clear: both"></div></div></p>
<p style="text-align: justify;"><div class='w3eden'><!-- WPDM Link Template: Default Template --><div class="wpdm-link-tpl link-btn [color]" data-durl="http://kirnosenko.com/?wpdmdl=366" >    <div class="media">        <div class="pull-left"><img class="wpdm_icon"   src="http://kirnosenko.com/wp-content/plugins/download-manager/file-type-icons/download1.png" /></div>        <div class="media-body"><strong class="ptitle">Диссертация <span class="label label-default" style="font-weight: 400;">1.43 MB</span></strong>            <div><strong><a class='wpdm-download-link wpdm-download-locked [btnclass]' rel='noindex nofollow' href='http://kirnosenko.com/?wpdmdl=366'><i class=''></i>Download</a></strong></div>        </div>    </div></div><div style="clear: both"></div></div></p>
<p style="text-align: justify;"><div class='w3eden'><!-- WPDM Link Template: Default Template --><div class="wpdm-link-tpl link-btn [color]" data-durl="http://kirnosenko.com/?wpdmdl=368" >    <div class="media">        <div class="pull-left"><img class="wpdm_icon"   src="http://kirnosenko.com/wp-content/plugins/download-manager/file-type-icons/download1.png" /></div>        <div class="media-body"><strong class="ptitle">Данные для MSR-Tools <span class="label label-default" style="font-weight: 400;">17.58 MB</span></strong>            <div><strong><a class='wpdm-download-link wpdm-download-locked [btnclass]' rel='noindex nofollow' href='http://kirnosenko.com/?wpdmdl=368'><i class=''></i>Download</a></strong></div>        </div>    </div></div><div style="clear: both"></div></div></p>
<p>&nbsp;</p>
]]></content:encoded>
									<post-id xmlns="com-wordpress:feed-additions:1">167</post-id>	</item>
		<item>
		<title>Fallout 2 blur shader</title>
		<link>http://kirnosenko.com/2013/07/21/fallout-2-global-shader/</link>
				<comments>http://kirnosenko.com/2013/07/21/fallout-2-global-shader/#comments</comments>
				<pubDate>Sun, 21 Jul 2013 11:55:39 +0000</pubDate>
		<dc:creator><![CDATA[Semyon Kirnosenko]]></dc:creator>
				<category><![CDATA[Games]]></category>

		<guid isPermaLink="false">http://kirnosenko.com/?p=271</guid>
				<description><![CDATA[I don&#8217;t like the available global shader for fallout 2 much. So I have made a new one. I could say that it seems to&#8230;]]></description>
								<content:encoded><![CDATA[<p style="text-align: justify;">I don&#8217;t like the <a href="http://falloutmods.wikia.com/wiki/Global_Shaders" target="_blank">available global shader for fallout 2</a> much. So I have made a new one. I could say that it seems to be better, but a picture costs a thousand words.<span id="more-271"></span></p>
<p style="text-align: justify;">Click to see full-sized image.</p>
<p><div class="slideshow_container slideshow_container_style-light" style="height: 500px; " data-session-id="0" data-style-name="style-light" data-style-version="2.2.23">

			<div class="slideshow_loading_icon"></div>
	
	<div class="slideshow_content" style="display: none;">

		<div class="slideshow_view">
			<div class="slideshow_slide slideshow_slide_image">
				<a href="http://kirnosenko.com/wp-content/uploads/2013/07/f2-classic-1.png" target="_blank" >					<img src="http://kirnosenko.com/wp-content/uploads/2013/07/f2-classic-1.png" alt="f2-classic-1" width="1280" height="960" />
				</a>				<div class="slideshow_description_box slideshow_transparent">
					<div class="slideshow_title"><a href="http://kirnosenko.com/wp-content/uploads/2013/07/f2-classic-1.png" target="_blank" >f2-classic-1</a></div>									</div>
			</div>

			<div style="clear: both;"></div></div><div class="slideshow_view">
			<div class="slideshow_slide slideshow_slide_image">
				<a href="http://kirnosenko.com/wp-content/uploads/2013/07/f2-old-1.png" target="_blank" >					<img src="http://kirnosenko.com/wp-content/uploads/2013/07/f2-old-1.png" alt="f2-old-1" width="1280" height="960" />
				</a>				<div class="slideshow_description_box slideshow_transparent">
					<div class="slideshow_title"><a href="http://kirnosenko.com/wp-content/uploads/2013/07/f2-old-1.png" target="_blank" >f2-old-1</a></div>									</div>
			</div>

			<div style="clear: both;"></div></div><div class="slideshow_view">
			<div class="slideshow_slide slideshow_slide_image">
				<a href="http://kirnosenko.com/wp-content/uploads/2013/07/f2-new-1.png" target="_blank" >					<img src="http://kirnosenko.com/wp-content/uploads/2013/07/f2-new-1.png" alt="f2-new-1" width="1280" height="960" />
				</a>				<div class="slideshow_description_box slideshow_transparent">
					<div class="slideshow_title"><a href="http://kirnosenko.com/wp-content/uploads/2013/07/f2-new-1.png" target="_blank" >f2-new-1</a></div>									</div>
			</div>

			<div style="clear: both;"></div></div><div class="slideshow_view">
			<div class="slideshow_slide slideshow_slide_image">
				<a href="http://kirnosenko.com/wp-content/uploads/2013/07/f2-classic-2.png" target="_blank" >					<img src="http://kirnosenko.com/wp-content/uploads/2013/07/f2-classic-2.png" alt="f2-classic-2" width="1280" height="960" />
				</a>				<div class="slideshow_description_box slideshow_transparent">
					<div class="slideshow_title"><a href="http://kirnosenko.com/wp-content/uploads/2013/07/f2-classic-2.png" target="_blank" >f2-classic-2</a></div>									</div>
			</div>

			<div style="clear: both;"></div></div><div class="slideshow_view">
			<div class="slideshow_slide slideshow_slide_image">
				<a href="http://kirnosenko.com/wp-content/uploads/2013/07/f2-old-2.png" target="_blank" >					<img src="http://kirnosenko.com/wp-content/uploads/2013/07/f2-old-2.png" alt="f2-old-2" width="1280" height="960" />
				</a>				<div class="slideshow_description_box slideshow_transparent">
					<div class="slideshow_title"><a href="http://kirnosenko.com/wp-content/uploads/2013/07/f2-old-2.png" target="_blank" >f2-old-2</a></div>									</div>
			</div>

			<div style="clear: both;"></div></div><div class="slideshow_view">
			<div class="slideshow_slide slideshow_slide_image">
				<a href="http://kirnosenko.com/wp-content/uploads/2013/07/f2-new-2.png" target="_blank" >					<img src="http://kirnosenko.com/wp-content/uploads/2013/07/f2-new-2.png" alt="f2-new-2" width="1280" height="960" />
				</a>				<div class="slideshow_description_box slideshow_transparent">
					<div class="slideshow_title"><a href="http://kirnosenko.com/wp-content/uploads/2013/07/f2-new-2.png" target="_blank" >f2-new-2</a></div>									</div>
			</div>

			<div style="clear: both;"></div></div><div class="slideshow_view">
			<div class="slideshow_slide slideshow_slide_image">
				<a href="http://kirnosenko.com/wp-content/uploads/2013/07/f2-classic-3.png" target="_blank" >					<img src="http://kirnosenko.com/wp-content/uploads/2013/07/f2-classic-3.png" alt="f2-classic-3" width="1280" height="960" />
				</a>				<div class="slideshow_description_box slideshow_transparent">
					<div class="slideshow_title"><a href="http://kirnosenko.com/wp-content/uploads/2013/07/f2-classic-3.png" target="_blank" >f2-classic-3</a></div>									</div>
			</div>

			<div style="clear: both;"></div></div><div class="slideshow_view">
			<div class="slideshow_slide slideshow_slide_image">
				<a href="http://kirnosenko.com/wp-content/uploads/2013/07/f2-old-3.png" target="_blank" >					<img src="http://kirnosenko.com/wp-content/uploads/2013/07/f2-old-3.png" alt="f2-old-3" width="1280" height="960" />
				</a>				<div class="slideshow_description_box slideshow_transparent">
					<div class="slideshow_title"><a href="http://kirnosenko.com/wp-content/uploads/2013/07/f2-old-3.png" target="_blank" >f2-old-3</a></div>									</div>
			</div>

			<div style="clear: both;"></div></div><div class="slideshow_view">
			<div class="slideshow_slide slideshow_slide_image">
				<a href="http://kirnosenko.com/wp-content/uploads/2013/07/f2-new-3.png" target="_blank" >					<img src="http://kirnosenko.com/wp-content/uploads/2013/07/f2-new-3.png" alt="f2-new-3" width="1280" height="960" />
				</a>				<div class="slideshow_description_box slideshow_transparent">
					<div class="slideshow_title"><a href="http://kirnosenko.com/wp-content/uploads/2013/07/f2-new-3.png" target="_blank" >f2-new-3</a></div>									</div>
			</div>

			<div style="clear: both;"></div></div>
	</div>

	<div class="slideshow_controlPanel slideshow_transparent" style="display: none;"><ul><li class="slideshow_togglePlay" data-play-text="Play" data-pause-text="Pause"></li></ul></div>

	<div class="slideshow_button slideshow_previous slideshow_transparent" role="button" data-previous-text="Previous" style="display: none;"></div>
	<div class="slideshow_button slideshow_next slideshow_transparent" role="button" data-next-text="Next" style="display: none;"></div>

	<div class="slideshow_pagination" style="display: none;" data-go-to-text="Go to slide"><div class="slideshow_pagination_center"></div></div>

	<!-- WordPress Slideshow Version 2.2.23 -->

	</div></p>
<p style="text-align: justify;">It works with Steam version and looks pretty well for me. Just place shader at \data\shaders under your fallout installation and set &#8220;Mode=4&#8221; and &#8220;GlobalShaderMode=3&#8221; in ddraw.ini. For those who remember classic&#8230;</p>
<p>Update:</p>
<p style="text-align: justify;">With sfall 3.0 and higher you need to use the following mod. Just place shader blur.fx at \data\shaders and script glblur.int at \data\scripts under your fallout installation and set &#8220;Mode=4&#8221; in ddraw.ini. It works with high resolution patch. Unfortunatly current sfall 3.1 does not set correct screen resolution for shaders. So you will have to change &#8220;resolution&#8221; variable in shader blur.fx manually via any text editor. The default is old-school 640&#215;480.</p>
<p style="text-align: justify;"><div class='w3eden'><!-- WPDM Link Template: Default Template --><div class="wpdm-link-tpl link-btn [color]" data-durl="http://kirnosenko.com/?wpdmdl=360" >    <div class="media">        <div class="pull-left"><img class="wpdm_icon"   src="http://kirnosenko.com/wp-content/plugins/download-manager/file-type-icons/download1.png" /></div>        <div class="media-body"><strong class="ptitle">Fallout 2 blur shader <span class="label label-default" style="font-weight: 400;">2.27 KB</span></strong>            <div><strong><a class='wpdm-download-link wpdm-download-locked [btnclass]' rel='noindex nofollow' href='http://kirnosenko.com/?wpdmdl=360'><i class=''></i>Download</a></strong></div>        </div>    </div></div><div style="clear: both"></div></div></p>
<p style="text-align: justify;">
]]></content:encoded>
							<wfw:commentRss>http://kirnosenko.com/2013/07/21/fallout-2-global-shader/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
						<post-id xmlns="com-wordpress:feed-additions:1">271</post-id>	</item>
		<item>
		<title>Куда податься кустарю?</title>
		<link>http://kirnosenko.com/2013/04/22/where-should-freelancer-go/</link>
				<pubDate>Mon, 22 Apr 2013 13:05:35 +0000</pubDate>
		<dc:creator><![CDATA[Semyon Kirnosenko]]></dc:creator>
				<category><![CDATA[Без рубрики]]></category>

		<guid isPermaLink="false">http://kirnosenko.com/?p=248</guid>
				<description><![CDATA[В 2002 году я стал студентом и начал осваивать азы компьютерных наук. Всё было ново и интересно. В те времена я увлекался программирование простых игр,&#8230;]]></description>
								<content:encoded><![CDATA[<p style="text-align: justify;">В 2002 году я стал студентом и начал осваивать азы компьютерных наук. Всё было ново и интересно. В те времена я увлекался программирование простых игр, но однажды бросил это занятие руководствуясь соображением о том, что это &#8220;не серьёзно&#8221;. С тех пор в качестве кустаря я попробовал себя на разных поприщах. И вот спустя 10 лет я задумался а не вернуться ли к старому увлечению? И дело не в том, что я поменял своё мнение. Просто за прошедшее время мир очень сильно изменился.<span id="more-248"></span></p>
<p style="text-align: justify;">Конец 90-х и начало 2000-х стали &#8220;золотым веком&#8221; shareware ПО. Взяв на вооружение доселе невиданные средства быстрой разработки, многие кустари принялись интенсивно осваивать новые рынки. Часто за официальным сайтом и гордым именем вроде MegaSuper Software скрывался кустарь в единственном числе, который сидя дома в нижнем белье изображал из себя одновременно разработчика, управленца, сотрудника техпомощи и ещё чёрт знает кого. Подтянувшиеся на спрос сервисы-регистраторы позволяли живя в каком-нибудь Мухосранске продавать плоды своего труда по всему миру. Многие кустари, пользуясь пробелами в законодательстве и в грамотности банковских работников, даже не утруждали себя оплатой налогов. При удачном стечении обстоятельств жизнь могла быть легка и прекрасна, что для того времени было редкостью. Но этот праздник жизни не мог продолжаться вечно. Со временем перенасыщение рынка, развитие движения open-source и ряд менее важных причин привели к резкому падению спроса. Причём во всех массовых нишах. Подобные испытания заставили ряды кустарей-софтоделов сильно поредеть. Это у нескромных стартаперов был быстрый <a href="http://ru.wikipedia.org/wiki/%D0%9F%D1%83%D0%B7%D1%8B%D1%80%D1%8C_%D0%B4%D0%BE%D1%82%D0%BA%D0%BE%D0%BC%D0%BE%D0%B2" target="_blank">кризис доткомов</a>. А для скромных кустарей-софтоделов смерть была медленной и мучительной. Множество программ часто востребованных и весьма неплохих канули в небытие просто потому что их разработка стала невыгодной. Сегодня же разработка собственной &#8220;коробки&#8221; для кустаря &#8211; практически самоубийство. Широкие ниши заняты очень качественными решениями, часто абсолютно бесплатными, а то и вовсе распространяемыми с открытым исходным кодом. Узкие же ниши слишком узки и выживание в них обычно требует либо крупных начальных капиталовложений либо наличия с потенциальными клиентами более осязаемых связей нежели Интернет.</p>
<p style="text-align: justify;">Потом пришла волна популяризации фриланса. Работодатели созрели для того, чтобы отдавать работу на сторону, а вчерашние офисные моллюски созрели для того, чтобы зарабатывать подобными вещами на жизнь. Многие из бывших кустарей-софтоделов подались во фриланс. Что давалось им не легко, т.к. требовало смены парадигмы. Ещё вчера ты продавал одно и то же много раз разным клиентам, а теперь делаешь для каждого клиента что-то уникальное. Удельная стоимость работы падает однако! Но и так жить можно. Хотя и фриланс не обошли катаклизмы эволюции. Периодические нашествия нано-гастарбайтеров готовых сворачивать горы за копейки. Постепенная трансформация отдельных фрилансеров во фриланс-организации способные формировать нечеловеческие портфолио и проводить демпинг. Короче ещё одна &#8220;лодка разбилась о быт&#8221;.</p>
<p style="text-align: justify;">А история между тем имеет тенденцию повторяться. И вот что однажды произошло со средствами быстрой разработки теперь случилось с графическими и игровыми движками. А именно их стало много, они стали действительно доступными и качественными. Сегодня найти движок под любимую платформу и любимый язык программирования легче, чем десять лет назад найти дистрибутив linux под свой cd-привод! Значительно увеличилось число потенциальных платформ: смартфоны, планшеты, консоли всех мастей, социальные сети, да и старушка персоналка пока не сдаётся. Каждая платформа предоставляет уникальное сочетание возможностей, что в свою очередь позволяет реализовывать самые разные идеи и прививать их там где у них больше всего шансов прижиться и максимально раскрыть свой потенциал.</p>
<p style="text-align: justify;">Если так происходит, значит на то есть причины. И они заключаются разумеется не только в том, что технологически процесс создания игр становится более простым и доступным. Куда более важные причины &#8211; популяризация цифровой дистрибуции и конечно рост спроса! Сегодня глядя на то как развиваются <a href="http://www.steampowered.com/" target="_blank">Steam</a> и <a href="http://www.desura.com/" target="_blank">Desura</a>, глядя на то чем <a href="http://www.kickstarter.com/blog/the-year-of-the-game" target="_blank">прирастает</a> <a href="http://www.kickstarter.com/" target="_blank">Kickstarter</a> становится ясно, что спрос растёт и растёт быстро. Самое любопытное заключается в том, что все эти кризисы, финансовые и не очень, совсем не вредят игровой индустрии. Скорее даже наоборот. А всё почему? Потому что развлечений хочется всегда, а в тяжёлые времена их хочется вдвойне. Интерактивные же развлечения &#8211; пожалуй самые доступные. Отдал 50 баксов за какой-нибудь <a href="http://ru.wikipedia.org/wiki/The_Elder_Scrolls_V:_Skyrim" target="_blank">Skyrim</a> и &#8220;развлекайся&#8221; целый месяц. Куда уж дешевле?!</p>
<p style="text-align: justify;">Улавливая ветер перемен кустари уже несколько лет активно идут в игровую индустрию. Но и здесь не всё благополучно. На любом поприще главный враг кустаря &#8211; большие и средние &#8220;игроки&#8221; на рынке. Они появляются везде где есть деньги и часто подобно саранче не оставляют за собой ничего. Игровая индустрия &#8211; одна из немногих где спроса хватает на всех, кто в состоянии предложить что-то более или менее интересное. Но как долго это продлится? Экспансия больших студий не останавливается, а рынок насыщается стремительными темпами. Разумеется сила &#8220;инди&#8221; в оригинальности и нестандартности, которые большие студии часто не могут себе позволить. Многие приводят это в довод тому, что &#8220;инди&#8221; и большие студии всегда будут занимать две разные ниши. От части это так, но в то же время глупо отрицать влияние этих двух кусков рынка друг на друга. А влияние в любой момент может привести к смене соотношения сил.</p>
<p style="text-align: justify;">Но в любом случае сегодня кажется нет более привлекательной и перспективной сферы приложения усилий для кустаря чем игровая индустрия.</p>
]]></content:encoded>
									<post-id xmlns="com-wordpress:feed-additions:1">248</post-id>	</item>
		<item>
		<title>Антипаттерны контроля версий</title>
		<link>http://kirnosenko.com/2012/12/17/version-control-antipatterns/</link>
				<pubDate>Mon, 17 Dec 2012 12:41:32 +0000</pubDate>
		<dc:creator><![CDATA[Semyon Kirnosenko]]></dc:creator>
				<category><![CDATA[Version Control]]></category>
		<category><![CDATA[antipatterns]]></category>
		<category><![CDATA[repository]]></category>

		<guid isPermaLink="false">http://kirnosenko.com/?p=244</guid>
				<description><![CDATA[Просматривая репозитории кода различных проектов всё время сталкиваешься с одними и теми же вещами, которые никак нельзя назвать результатом применения &#8220;правильных&#8221; практик. Суть и порочная&#8230;]]></description>
								<content:encoded><![CDATA[<p style="text-align: justify;">Просматривая репозитории кода различных проектов всё время сталкиваешься с одними и теми же вещами, которые никак нельзя назвать результатом применения &#8220;правильных&#8221; практик. Суть и порочная природа их очевидны, что не мешает даже самым трезвым из нас периодически оступаться. Можно вспомнить самые типичные из них.<span id="more-244"></span></p>
<p><strong>Таинственный коммит</strong></p>
<p style="text-align: justify;"><em>Суть:</em> Комментарий к коммиту не несёт полезной информации либо вовсе отсутствует.</p>
<p><em>Причины:</em> Лень и ничего больше.</p>
<p style="text-align: justify;"><em>Проблемы:</em> О назначении коммита можно судить лишь ознакомившись с набором изменений входящих в него. Как следствие, постоянные трудности при поиске определённых коммитов, попытках переноса коммитов между ветками и т.п. Каждый раз когда вы хотите что-то сделать с коммитом неизбежно возникает вопрос: &#8220;А тот ли это коммит, который мне нужен?&#8221;</p>
<p style="text-align: justify;"><em>Решения:</em> Пишите, мать вашу, комментарии! Желательно более предметные чем &#8220;bug fixed&#8221; или &#8220;some stuff added&#8221;.</p>
<p><strong>Многоцелевой &#8220;баллистический&#8221; коммит<br />
</strong></p>
<p style="text-align: justify;"><em>Суть:</em> Коммит содержит набор изменений не связанных между собой.</p>
<p style="text-align: justify;"><em>Причины:</em> Лень, недостаточный опыт эксплуатации систем контроля версий.</p>
<p style="text-align: justify;"><em>Проблемы:</em> Управление подобными коммитами в процессе их жизни в репозитории может стать настоящей головной болью, когда возникает необходимость переноса между ветками или отката лишь части изменений входящих в коммит.</p>
<p style="text-align: justify;"><em>Решения:</em> По хорошему любой несервисный коммит (не связанный с созданием/слиянием веток и т.п.) должен иметь целью одно из трёх действий: добавление новой функциональности, выполнение рефакторинга, исправление дефекта. Дробя коммиты по содержимому мы естественным образом реализуем принцип &#8220;разделяй и властвуй&#8221;. Не бойтесь сделать несколько коммитов вместо одного. Система контроля версий от этого не лопнет, а вы в перспективе только выиграете.</p>
<p><strong>Выгребная яма</strong></p>
<p style="text-align: justify;"><em>Суть:</em> Репозиторий содержит множество файлов, контроль версий для которых не оправдан разумными причинами.</p>
<p style="text-align: justify;"><em>Причины:</em> Лень, недостаточная осведомлённость о назначении и принципах работы систем контроля версий.</p>
<p style="text-align: justify;"><em>Проблемы:</em> Засорение репозитория временными файлами, файлами IDE не несущими полезной информации, бинарными файлами сборок (в совсем запущенных случаях). Ситуация с бинарными файлами осложняется тем, что для них проблематично отслеживание изменений. И даже когда в репозитории находятся только действительно нужные бинарные файлы (сторонние библиотеки, ресурсы приложения и т.п.), если объём и количество их велико и они часто меняются, то размер репозитория может очень быстро вырасти до непристойных размеров.</p>
<p style="text-align: justify;"><em>Решения:</em> Пользуйтесь средствами типа того же .gitignore, чтобы в репозиторий попадало только то чему там место. Иногда (хотя и редко) бывает полезно хранить ресурсы отдельно, не выполняя для них контроль версий.</p>
<p><strong>Черенок<br />
</strong></p>
<p style="text-align: justify;"><em>Суть:</em> Использование веток сведено к минимуму и от них отказываются даже в тех случаях когда они показаны, практически вся разработка ведётся на trunk&#8217;е.</p>
<p style="text-align: justify;"><em>Причины:</em> Лень, недостаточный опыт эксплуатации систем контроля версий.</p>
<p style="text-align: justify;"><em>Проблемы:</em> Даже частичный отказ от использования веток может привести к значительным трудностям при управлении изменениями. Разве приятно выполнить одну и ту же работу несколько раз, выкинуть почти работающий код или сохранить его дедовскими методами типа архивирования репозитория, не иметь возможности выпустить промежуточный релиз в любой момент времени?</p>
<p style="text-align: justify;"><em>Решения:</em> Учиться, учиться и учиться. Есть много материалов хорошо разъясняющих <a href="http://git-scm.com/book/en/Git-Branching-Basic-Branching-and-Merging" target="_blank">что</a>, <a href="http://nedbatchelder.com/text/quicksvnbranch.html">зачем</a> и <a href="http://nvie.com/posts/a-successful-git-branching-model/">как</a>.</p>
<p><strong>Заросли<br />
</strong></p>
<p style="text-align: justify;"><em>Суть:</em> Ветки используются чрезмерно интенсивно, даже в тех случаях когда существуют более простые средства решения задачи. При этом trunk может выглядеть примерно вот так:<a href="http://kirnosenko.com/2012/12/17/version-control-antipatterns/trunk2/" rel="attachment wp-att-254"><img data-attachment-id="254" data-permalink="http://kirnosenko.com/2012/12/17/version-control-antipatterns/trunk2/" data-orig-file="http://kirnosenko.com/wp-content/uploads/2012/12/trunk2.png" data-orig-size="1352,519" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;}" data-image-title="trunk2" data-image-description="" data-medium-file="http://kirnosenko.com/wp-content/uploads/2012/12/trunk2-300x115.png" data-large-file="http://kirnosenko.com/wp-content/uploads/2012/12/trunk2-1024x393.png" class="aligncenter size-large wp-image-254" alt="trunk2" src="http://kirnosenko.com/wp-content/uploads/2012/12/trunk2-1024x393.png" width="640" height="245" srcset="http://kirnosenko.com/wp-content/uploads/2012/12/trunk2-1024x393.png 1024w, http://kirnosenko.com/wp-content/uploads/2012/12/trunk2-300x115.png 300w, http://kirnosenko.com/wp-content/uploads/2012/12/trunk2.png 1352w" sizes="(max-width: 640px) 100vw, 640px" /></a></p>
<p style="text-align: justify;"><em>Причины:</em> После subversion простота и легковесность веток в том же git безусловно воодушевляет и мотивирует на великие свершения.</p>
<p style="text-align: justify;"><em>Проблемы:</em> При большом числе веток и интенсивном их пересечении восприятие основного тренда разработки может быть сильно затруднено. Также растёт вероятность допущения ошибок при работе с ветками.</p>
<p style="text-align: justify;"><em>Решения:</em> Разумеется ветки полезны и отказываться от них нет смысла. Но не следует делать простые вещи сложными путями. В git например есть fast-forward merging, который позволяет скрыть следы того, что ветка вообще была. А применение иерархии параллельных веток с последовательным слиянием позволяет упростить trunk, не засоряя его кучей feature branch&#8217;ей. Репозиторий <a href="http://github.com/postgres/postgres">postgresql</a> хороший пример того, что даже в крупном проекте trunk может быть прямым и изящным.</p>
<p style="text-align: justify;"><strong>Блуждающий ствол<br />
</strong></p>
<p style="text-align: justify;"><em>Суть:</em> Использование нетрадиционных подходов при управлении основными ветвями разработки.</p>
<p style="text-align: justify;"><em>Причины:</em> Недостаточный опыт эксплуатации систем контроля версий.</p>
<p style="text-align: justify;"><em>Проблемы:</em> Если вы создали некоторую структуру веток, а потом не знаете как сделать с ними простые вещи типа релиза, то вы определённо делаете что-то не так.</p>
<p style="text-align: justify;"><em>Решения:</em> Можно выделить два типичных подхода к организации основных ветвей разработки. Подход номер раз: Стабильный trunk. На trunk&#8217;е всегда стабильный код, который собирается, проходит тесты и прочее. Разработка ведётся на дополнительных ветвях. Как только всё необходимое в такой ветке реализовано и проверено ветка сливается на trunk. Возможна многоуровневая иерархия таких веток, что позволяет работать даже с очень большими объёмами кода. По ходу разработки на trunk&#8217;е появляются тэги версий. Подход номер два: Активный trunk. На trunk&#8217;е самый последний код, который может даже не собираться. По мере реализации функциональности от trunk&#8217;а отделяются ветки версий. В дальнейшем в них заносятся только исправления и на них же появляются тэги версий. Первый подход удобен для изоляции изменений, второй &#8211; для поддержки множества версий. Необходимость в более сложных вариациях на практике возникает редко.</p>
<p style="text-align: justify;"><strong>Мораль:</strong> Часто соблюдение простых правил требует гораздо меньше времени чем время, которое придётся потратить на борьбу с последствиями несоблюдения этих правил.</p>
]]></content:encoded>
									<post-id xmlns="com-wordpress:feed-additions:1">244</post-id>	</item>
		<item>
		<title>MSR Tools 0.3.3</title>
		<link>http://kirnosenko.com/2012/01/10/msr-tools-0-3-3/</link>
				<pubDate>Tue, 10 Jan 2012 09:30:24 +0000</pubDate>
		<dc:creator><![CDATA[Semyon Kirnosenko]]></dc:creator>
				<category><![CDATA[MSR Tools]]></category>
		<category><![CDATA[Quality Assurance]]></category>

		<guid isPermaLink="false">http://kirnosenko.com/?p=234</guid>
				<description><![CDATA[Рад сообщить о выходе новой версии MSR Tools 0.3.3, которая содержит больше моделей прогнозирования дефектов и методов оценки точности прогнозов. В этой версии реализован готовый&#8230;]]></description>
								<content:encoded><![CDATA[<p style="text-align: justify;">Рад сообщить о выходе новой версии <a href="http://msr.sourceforge.net/" target="_blank">MSR Tools</a> 0.3.3, которая содержит больше моделей прогнозирования дефектов и методов оценки точности прогнозов. В этой версии реализован готовый вариант предложенной мною модели (Code stability model). Она обеспечивает весьма неплохие результаты прогнозирования, в чём каждый может убедиться лично.</p>
<p style="text-align: justify;">Также <a href="http://msr.sourceforge.net/data-sets/" target="_blank">доступны</a> дополнительные наборы данных, которые я использовал в своей работе.</p>
]]></content:encoded>
									<post-id xmlns="com-wordpress:feed-additions:1">234</post-id>	</item>
		<item>
		<title>Прогнозирование дефектов в программном обеспечении</title>
		<link>http://kirnosenko.com/2011/11/17/software-defect-prediction/</link>
				<pubDate>Thu, 17 Nov 2011 11:41:49 +0000</pubDate>
		<dc:creator><![CDATA[Semyon Kirnosenko]]></dc:creator>
				<category><![CDATA[MSR]]></category>
		<category><![CDATA[MSR Tools]]></category>

		<guid isPermaLink="false">http://kirnosenko.com/?p=231</guid>
				<description><![CDATA[Уважаемые работники ВУЗ&#8217;ов больших и малых! В ближайшее время я буду рассылать автореферат своей кандидатской диссертации на тему вынесенную в заголовок. Если данная область программной&#8230;]]></description>
								<content:encoded><![CDATA[<p style="text-align: justify;">Уважаемые работники ВУЗ&#8217;ов больших и малых! В ближайшее время я буду рассылать автореферат своей кандидатской диссертации на тему вынесенную в заголовок. Если данная область программной инженерии находится в сфере Ваших интересов я могу выслать Вам копию автореферата. Оставляйте обратный адрес через <a href="http://kirnosenko.com/feedback/">форму</a> контактов. Не забудьте указать на чьё имя следует высылать автореферат.</p>
]]></content:encoded>
									<post-id xmlns="com-wordpress:feed-additions:1">231</post-id>	</item>
	</channel>
</rss>
