ГЛАВНАЯ     АРХИВ     НАПИСАТЬ АДМИНУ     ПОДПИСАТЬСЯ НА RSS     ВОЙТИ      

Поиск

Категории

Облако тегов

  << Предыдущий пост       Следующий пост >>  
4. мая 2011 01:48

Оригинал статьи: Silverlight + Augmented reality + Shaders

Автор статьи (на хабре): Tranz

Привет всем.

Я люблю работать с Silverlight, и вот недавно натолкнулся на Дополненную реальность с использованием Silverlight. Про неё и на Хабре уже писали, и в блогах довольно много написано, но я всё же немного повторюсь. Сама идея дополненной реальности интересна, но я хотел использовать её как-то необычно. И вот недавно руки дошли до изучения пиксельных шейдеров. Стало интересно попробовать соединить это вместе.

Если интересно, что из этого получилось, то Добро пожаловать под кат:


Для начала скачиваем SLARToolkit.

В скачанном архиве содержатся необходимые библиотеки и 3 уже готовых маркера. Есть несколько свособов создания своих маркеров, но для начала хватит и готовых.

Теперь создаём новое Silverlight приложением и добавляем ссылки на SLARTooklit.dll и Matrix3DEx.dll из скачанного нами архива.

Вот XAML разметка моей заготовки


<UserControl x:Class="SilverlightForHabr.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="550" d:DesignWidth="700">

    <Grid x:Name="LayoutRoot" Background="White">
        <StackPanel>
            <TextBlock Text="Silverlight + Augmented reality + Shaders" HorizontalAlignment="Center" />
            <Grid Width="640" Height="480">
                <Rectangle Name="Viewport" Stroke="Black" StrokeThickness="2" />
                <Canvas>
                    <Image Name="Logo" Source="habr.png" Width="300" Height="300" />
                </Canvas>
            </Grid>
            <Button Content="Начнём" Padding="5" Margin="5" HorizontalAlignment="Center" />
        </StackPanel>
    </Grid>
</UserControl>

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

  1. Создаём объект CaptureSource
  2. Спрашиваем у пользователя разрешение на использование камеры
  3. Выводим картинку


Проще некуда.

Для этого в XAML добавляем ссылку на метод, который вызовется после загрузки и ссылку на обработчик нажатия кнопки:


Loaded="UserControl_Loaded">
и
<Button Content="Начнём" Padding="5" Margin="5" HorizontalAlignment="Center" Click="onStartBtnClick" />

Осталось описать сами методы:

private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
captureSource = new CaptureSource();
captureSource.VideoCaptureDevice =
CaptureDeviceConfiguration.GetDefaultVideoCaptureDevice();
 
var vidBrush = new VideoBrush();
vidBrush.SetSource(captureSource);
Viewport.Fill = vidBrush;
}

private void onStartBtnClick(object sender, RoutedEventArgs e)
{
if (CaptureDeviceConfiguration.RequestDeviceAccess())
{
captureSource.Start();
}
}

Теперь картинка с камеры выводится на экран.

Приступим к работе с Дополненной реальностью



Принцип работы примерно следующий:

  1. Создаём экземпляр класса CaptureSourceMarkerDetector, который отвечает за обнаружение маркеров во входящем видео с камеры
  2. Если что-то нашли, то вызываем обработчик
  3. Определяем матрицу проекции(положения в пространстве) самого маркера
  4. Применяем эту матрицу к объекту, который хотим наложить поверх маркера



За все эти действия отвечает следующий код:

private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
captureSource = new CaptureSource();
captureSource.VideoCaptureDevice =
CaptureDeviceConfiguration.GetDefaultVideoCaptureDevice();

var vidBrush = new VideoBrush();
vidBrush.SetSource(captureSource);
Viewport.Fill = vidBrush;


arDetector = new CaptureSourceMarkerDetector();
var marker = Marker.LoadFromResource(
"Marker_L_16x16segments_80width.pat", 16, 16, 80);
arDetector.Initialize(captureSource, 1, 4000, marker);

arDetector.MarkersDetected += (s, me) =>
{
Dispatcher.BeginInvoke(() =>
{
var dr = me.DetectionResults;
if (dr.HasResults)
{
var centerAtOrigin = Matrix3DFactory.CreateTranslation(
-Logo.ActualWidth * 0.5, -Logo.ActualHeight * 0.5, 0);
var scale = Matrix3DFactory.CreateScale(0.5, -0.5, 0.5);
var world = centerAtOrigin * scale * dr[0].Transformation;

var vp = Matrix3DFactory.CreateViewportTransformation(
Viewport.ActualWidth, Viewport.ActualHeight);

var m = Matrix3DFactory.CreateViewportProjection(
world, Matrix3D.Identity, arDetector.Projection, vp);

Logo.Projection = new Matrix3DProjection { ProjectionMatrix = m };
}
});
};
}


И конечно, добавляем в решение наш маркер. В данном случае это Marker_L_16x16segments_80width.pat. В его свойстве Build Action указываем Resource.

Теперь единственное, что нам осталось, это распечатать выбранный нами маркер. Для удобства разработчики SLARToolkit положили pdf версию маркера для печати.

Запускаем, и видим, что лого Хабра накладывается поверх маркера и следует за ним.

Замечательно!

Шейдеры



В двух словах, шейдер — это программа, написанная на языке HLSL (High Level Shader Language) в котором все действия сводятся к изменению цвета или положения какого-либо пиксела.

HLSL — С-подобный язык, поэтому, чтобы разобраться в нём нужно минимум времени.

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

Существует несколько программ, которые позволяют упростить создание шейдеров. Лично мне, больше всего понравилась программа Shazzam т.к. она позволяет сразу просмотреть результат на нескольких изображениях и видео, имеет множество примеров, а самое главное — генерирует C# или VB класс, который позволяет подключить шейдер к нашему проекту в одну строчку кода.

Итак, скачиваем Shazzam с сайта.
Устанавливаем и запускаем.

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

Код самого шейдера

/// <class>ZoomBlurEffect</class>

/// <description>An effect that applies a radial blur to the input.</description>

//-----------------------------------------------------------------------------------------
// Shader constant register mappings (scalars - float, double, Point, Color, Point3D, etc.)
//-----------------------------------------------------------------------------------------

/// <summary>The center of the blur.</summary>
/// <minValue>0</minValue>
/// <maxValue>0.2</maxValue>
/// <defaultValue>0.9,0.6</defaultValue>
float2 Center : register(C0);

/// <summary>The amount of blur.</summary>
/// <minValue>0</minValue>
/// <maxValue>0.2</maxValue>
/// <defaultValue>0.1</defaultValue>
float BlurAmount : register(C1);

//--------------------------------------------------------------------------------------
// Sampler Inputs (Brushes, including ImplicitInput)
//--------------------------------------------------------------------------------------

sampler2D inputSource : register(S0);

//--------------------------------------------------------------------------------------
// Pixel Shader
//--------------------------------------------------------------------------------------

float4 main(float2 uv : TEXCOORD) : COLOR
{
float4 c = 0;
uv -= Center;

for (int i = 0; i < 15; i++)
{
float scale = 1.0 + BlurAmount * (i / 14.0);
c += tex2D(inputSource, uv * scale + Center);
}

c /= 15;
return c;
}



Результатом работы Shazzam являются файлы ZoomBlur.ps и ZoomBlurEffect.cs. Добавляем их в наш проект.

Первый файл — готовый шейдер. Второй — автоматически сгенерированный класс, который облегчает использование шейдера.

Добавим ещё одну кнопку, которая будет включать наш шейдер:


<Button Content="Включить шейдер" Name="ShadersBtn" Padding="5" HorizontalAlignment="Center" Click="SwitchOnShaders" />


В код добавляем обработчик:



private void SwitchOnShaders(object sender, RoutedEventArgs e)
{
if (Viewport.Effect == zb)
{
Viewport.Effect = null;
ShadersBtn.Content = "Включить шейдер";
return;
}

zb.Center = new Point();
zb.BlurAmount = 0.2;

Viewport.Effect = zb;
ShadersBtn.Content = "Отключить шейдер";

}



Теперь, при перемещении маркера меняется размытие.



Послесловие

Прелесть этих технологий в том, что они ограничены лишь вашей фантазией, поэтому давайте играть с ними.

Линки

Линк на скачивание исходников
Посмотреть как это работает
SLARToolkit — SDK для начала игр с дополненной реальностью
Shazzam — приложение для комфортного создания шейдеров под Silverlight и WPF.

Похожие записи


Silverlight, HTML5 и непрозрачная стратегия развития Microsoft
Оригинал статьи взят отсюда: Silverlight, HTML5 и непрозрачная стратегия развития Microsoft Автор: Peter Bright Переводчик: Mairon     По непонятным мне на данный момент причинам, похоже, что многие разработчики, присутствовавшие на недавней конференции PDC-2010 (Крупнейшая конференция Microsoft для разработчиков — Прим. переводчика), были сильн...

Официально представлен Silverlight 5
Оригинал статьи взят отсюда: Официально представлен Silverlight 5 Автор: Vladimir Yunev Вчера в ходе онлайн-семинара Silverlight Firestarter Скотт Гатри официально представил новую версию платформы Silverlight 5. Новая версия платформы получит внушительное количество нововведений, про которые речь пойдет далее. Сейчас перечислю только те, которые могут быть интер...

Стратегия Microsoft - Silverlight и HTML5
Оригинал статьи взят отсюда: Стратегия Microsoft - Silverlight и HTML5 Автор: MikhailChernomordikov   Интернет – это очень интересная среда, в которой могут возникать разные мнения, основанные на разных фактах и догадках, а затем легко и быстро транслироваться в различных слухи, домыслы, умозаключения и выводы. Собственно, это весьма интересная тема для ...

Добавить комментарий




biuquote
  • Комментарий
  • Предпросмотр
Loading


  Сохранить комментарий