Использование в WPF
В WPF Вы можете сначала на High Level Shading Language (HLSL) создать собственный эффект с использованием пиксельных шейдеров. Далее, с помощью компилятора шейдеров Direct3D fxc.exe, скомпилировать HLSL код в байт-код.
fxc /T ps_2_0 /E main /Fo<name of HLSL file>.ps <name of HLSL file>.fx
Создать PixelShader для загрузки байт-кода и обернуть эффект в ShaderEffect . В итоге этот эффект можно будет присвоить свойству Effect объекта UIElement.
Рассмотрим процесс создания «обертки» на примере шейдера с яркостью и контрастностью.

Шейдер для изменение яркости и контрастности:
sampler2D input : register(s0); float brightness : register(c0); float contrast : register(c1);
float4 main(float2 uv : TEXCOORD) : COLOR { float4 color = tex2D(input, uv); float4 result = color; result = color + brightness; result = result * (1.0+contrast)/1.0; return result; }
Создаем класс, производный от ShaderEffect, объявляем входные параметры, определим свойства зависимостей, которые представляют собой параметры эффекта и вводные значения поверхности на основе объекта Brush:
public class BrightContrastEffect : ShaderEffect { …
public Brush Input { get { return (Brush)GetValue(InputProperty); } set { SetValue(InputProperty, value); } }
public static readonly DependencyProperty InputProperty = ShaderEffect.RegisterPixelShaderSamplerProperty("Input", typeof(BrightContrastEffect), 0);
Загружаем пиксельный шейдер из ресурсов (вы должны схокпилировать ps файл как ресурсный):
private static PixelShader m_shader = new PixelShader() { UriSource = new Uri(@"pack://application:,,,/CustomPixelRender;component/bricon.ps") };
Параметры, с добавочным специальным PixelShaderConstantCallback, который получает числовое значение id для зарегистрированных свойств из пиксельного шейдера.
public float Brightness { get { return (float)GetValue(BrightnessProperty); } set { SetValue(BrightnessProperty, value); } }
public static readonly DependencyProperty BrightnessProperty = DependencyProperty.Register("Brightness", typeof(double), typeof(BrightContrastEffect), new UIPropertyMetadata(0.0, PixelShaderConstantCallback(0)));
public float Contrast { get { return (float)GetValue(ContrastProperty); } set { SetValue(ContrastProperty, value); } }
public static readonly DependencyProperty ContrastProperty = DependencyProperty.Register("Contrast", typeof(double), typeof(BrightContrastEffect), new UIPropertyMetadata(0.0, PixelShaderConstantCallback(1)));
Несколько обновлений:
public BrightContrastEffect() { PixelShader = m_shader; UpdateShaderValue(InputProperty); UpdateShaderValue(BrightnessProperty); UpdateShaderValue(ContrastProperty);
}
Следующий шаг – описание интерфейса на языке XAML.
Создадим 2 ползунка для управления яркостью и контрастностью:
<UniformGrid Grid.Row="1">
<TextBlock Text="Brightness"/>
<Slider Maximum="1" Minimum="-1" Name="bVal"/>
<TextBlock Text="Contrast"/>
<Slider Maximum="1" Minimum="-1" Name="cVal"/>
</UniformGrid>
Каждый элемент пользовательского интерфейса в WPF имеет свойство Effect, которое разработано специально для создания произвольных шейдерных эффектов. Мы работаем с изображением, также привяжем к параметрам пиксельного шейдера значения с ползунков:
<Image Source="img.jpg">
<Image.Effect>
<l:BrightContrastEffect
Brightness="{Binding ElementName=bVal, Path=Value}"
Contrast="{Binding ElementName=cVal, Path=Value}"/>
</Image.Effect>
</Image>
Получили простое приложение, использующее пиксельные шейдеры в WPF.
Еще один пример – управление прозрачностью. Используем один параметр "Opacity". Эффект делает элемент управления полупрозрачным в зависимости от этого параметра. (Давайте опустим тот факт, что эффект полностью безполезный).
Создаем пиксельный шейдер Transparency.fx:
sampler2D implicitInputSampler : register(S0);
float opacity : register(C0);
float4 main(float2 uv : TEXCOORD) : COLOR {
float4 color = tex2D(implicitInputSampler, uv);
return color * opacity;
}
Ключевое слово register используется для связи констант с регистрами, где будут сохраняться входные параметры. Существует несколько регистров изображения, которые содержат входные данные изображения и называются S0, S1, S2, и т.д. (большинство пиксельных шейдеров используют только один такой регистр). Также существуют "регистры с плавающей точкой" C0, C1, C2, и т.д., эти регистры сохраняют другую входную информацию.
Функция main – входная точка шейдера, возвращает значение типа float4. Такая функция должна быть в каждом пиксельном шейдере.
Класс эффекта, содержащийся в файле Transparency.cs:
public class Transparency : ShaderEffect {
static Transparency() {
// Associate _pixelShader with our compiled pixel shader
_pixelShader.UriSource = Global.MakePackUri("Transparency.ps");
}
private static PixelShader _pixelShader = new PixelShader();
public Transparency() {
this.PixelShader = _pixelShader;
UpdateShaderValue(InputProperty);
UpdateShaderValue(OpacityProperty);
}
public Brush Input {
get { return (Brush)GetValue(InputProperty); }
set { SetValue(InputProperty, value); }
}
public static readonly DependencyProperty InputProperty =
ShaderEffect.RegisterPixelShaderSamplerProperty("Input", typeof(Transparency), 0);
public double Opacity {
get { return (double)GetValue(OpacityProperty); }
set { SetValue(OpacityProperty, value); }
}
public static readonly DependencyProperty OpacityProperty =
DependencyProperty.Register("Opacity", typeof(double), typeof(Transparency),
new UIPropertyMetadata(1.0d, PixelShaderConstantCallback(0)));
}
Пиксельный шейдер хранится в private static поле _pixelShader. Он хранится как static, потому что одного экземпляра скомпилированного кода шейдера достаточно для всего класса. Конструктор инициализирует свойство UriSource объекта_pixelShader - оно отвечает за место расположения скомпилированного байт-кода пиксельного шейдера. Метод Global.MakePackUri() представляет имя файла в виде пути примерно следующего содержания: "pack://application:,,,/[assemblyname];component/Transparency.ps".
Должно быть свойство типа Brush под названием "Input". Это свойство содержит входное изображение и обычно оно не задается напрямую – оно будет установлено автоматически, когда наш эффект будет применен.
Уведомление: информационные материалы | Alexander Knyazev: блог
Уведомление: Технические материалы по продуктам и решениям Microsoft на русском языке – март 2011. | Dmitry Bulavko:MySpaces
Уведомление: MCP клуб г.Ставрополь » Blog Archive » Технические материалы по продуктам и решениям Microsoft на русском языке – март 2011
Уведомление: Технические материалы по продуктам и решениям Microsoft на русском языке – март 2011 « Mcp Club Minsk's Blog