(此文章只是在对WPF的Effect产生兴趣才稍微研究了一点后面的知识;需要了解更多可参考https://archive.codeplex.com/?p=shazzam的源代码以及WPF基础知识)

1.之前一直使用blend里自带的几个特效,突然有一天比较好奇这些特效是怎么来的。

然后就听说了shazzam并看到更多的特效

2.在参考网址下载了shazzam的代码来研究研究,只抽取出里面【如何将.fx文件编译为.ps,再产生一个调用.ps文件的.cs文件,然后就可以像正常使用其它自带Effect一样使用了】这一过程

3.HLSL语法网上有很多教程啊,目前就直接拿一些写好的来用就行,一个简单的ToonShader.fx

/// <description>An effect that applies cartoon-like shading (posterization).</description>

sampler2D inputSampler : register(S0);

//-----------------------------------------------------------------------------------------
// Shader constant register mappings (scalars - float, double, Point, Color, Point3D, etc.)
//----------------------------------------------------------------------------------------- /// <summary>The number of color levels to use.</summary>
/// <minValue></minValue>
/// <maxValue></maxValue>
/// <defaultValue></defaultValue>
float Levels : register(C0); float4 main(float2 uv : TEXCOORD) : COLOR
{
float4 color = tex2D( inputSampler, uv );
color.rgb /= color.a; int levels = floor(Levels);
color.rgb *= levels;
color.rgb = floor(color.rgb);
color.rgb /= levels;
color.rgb *= color.a;
return color;
}

ToonShader

4.ShaderCompiler:利用dxd的D3DXCompileShader将.fx文件转换为.ps文件

    public void Compile(string codeText, string output, string fxName, ShaderProfile shaderProfile = ShaderProfile.ps_2_0)
{
IsCompiled = false;
string path = output;
IntPtr defines = IntPtr.Zero;
IntPtr includes = IntPtr.Zero;
IntPtr ppConstantTable = IntPtr.Zero;
string methodName = "main";
string targetProfile2 = "ps_2_0";
targetProfile2 = ((shaderProfile != ShaderProfile.ps_3_0) ? "ps_2_0" : "ps_3_0");
bool useDx10 = false;
int hr2 = ;
ID3DXBuffer ppShader2;
ID3DXBuffer ppErrorMsgs2;
if (!useDx10)
{
hr2 = ((IntPtr.Size != ) ?
DxHelper.D3DXCompileShader(codeText, codeText.Length, defines, includes, methodName, targetProfile2, , out ppShader2, out ppErrorMsgs2, out ppConstantTable)
:
DxHelper.D3DXCompileShader64Bit(codeText, codeText.Length, defines, includes, methodName, targetProfile2, , out ppShader2, out ppErrorMsgs2, out ppConstantTable));
}
else
{
int pHr = ;
hr2 = DxHelper.D3DX10CompileFromMemory(codeText, codeText.Length, string.Empty, IntPtr.Zero, IntPtr.Zero, methodName, targetProfile2, , , IntPtr.Zero, out ppShader2, out ppErrorMsgs2, ref pHr);
}
if (hr2 != )
{
IntPtr errors = ppErrorMsgs2.GetBufferPointer();
ppErrorMsgs2.GetBufferSize();
ErrorText = Marshal.PtrToStringAnsi(errors);
IsCompiled = false;
}
else
{
ErrorText = "";
IsCompiled = true;
string psPath = path + fxName;
IntPtr pCompiledPs = ppShader2.GetBufferPointer();
int compiledPsSize = ppShader2.GetBufferSize();
byte[] compiledPs = new byte[compiledPsSize];
Marshal.Copy(pCompiledPs, compiledPs, , compiledPs.Length);
using (FileStream psFile = File.Open(psPath, FileMode.Create, FileAccess.Write))
{
psFile.Write(compiledPs, , compiledPs.Length);
}
}
if (ppShader2 != null)
{
Marshal.ReleaseComObject(ppShader2);
}
ppShader2 = null;
if (ppErrorMsgs2 != null)
{
Marshal.ReleaseComObject(ppErrorMsgs2);
}
ppErrorMsgs2 = null;
CompileFinished();
}

Compile(string codeText, string output, string fxName, ShaderProfile shaderProfile)

5.CodeGenerator:生成引用.ps文件的effect.cs文件

private static string GenerateCode(CodeDomProvider provider, CodeCompileUnit compileUnit)
{
// Generate source code using the code generator.
using (StringWriter writer = new StringWriter())
{
string indentString = IndentUsingTabs ? "\t" : String.Format("{0," + IndentSpaces.ToString() + "}", " ");
CodeGeneratorOptions options = new CodeGeneratorOptions { IndentString = indentString, BlankLinesBetweenMembers = true, BracingStyle = "C" };
provider.GenerateCodeFromCompileUnit(compileUnit, writer, options);
string text = writer.ToString();
// Fix up code: make static DP fields readonly, and use triple-slash or triple-quote comments for XML doc comments.
if (provider.FileExtension == "cs")
{
text = text.Replace("public static DependencyProperty", "public static readonly DependencyProperty");
text = Regex.Replace(text, @"// <(?!/?auto-generated)", @"/// <");
}
else
if (provider.FileExtension == "vb")
{
text = text.Replace("Public Shared ", "Public Shared ReadOnly ");
text = text.Replace("'<", "'''<");
}
return text;
}
}

GenerateCode(CodeDomProvider provider, CodeCompileUnit compileUnit)

生成的cs文件内容如下:

//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。
// 运行时版本:4.0.30319.42000
//
// 对此文件的更改可能会导致不正确的行为,并且如果
// 重新生成代码,这些更改将会丢失。
// </auto-generated>
//------------------------------------------------------------------------------ using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Effects;
using System.Windows.Media.Media3D; namespace ShaderPan
{ /// <summary>An effect that applies cartoon-like shading (posterization).</summary>
public class ToonShaderEffect : ShaderEffect
{ public static readonly DependencyProperty InputProperty = ShaderEffect.RegisterPixelShaderSamplerProperty("Input", typeof(ToonShaderEffect), ); public static readonly DependencyProperty LevelsProperty = DependencyProperty.Register("Levels", typeof(double), typeof(ToonShaderEffect), new UIPropertyMetadata(((double)(5D)), PixelShaderConstantCallback())); public ToonShaderEffect()
{
PixelShader pixelShader = new PixelShader();
pixelShader.UriSource = new Uri("C:\\Users\\Administrator\\Desktop\\WpfTPL\\shader\\ToonShader.ps", UriKind.Absolute);
this.PixelShader = pixelShader; this.UpdateShaderValue(InputProperty);
this.UpdateShaderValue(LevelsProperty);
} public Brush Input
{
get
{
return ((Brush)(this.GetValue(InputProperty)));
}
set
{
this.SetValue(InputProperty, value);
}
} /// <summary>The number of color levels to use.</summary>
public double Levels
{
get
{
return ((double)(this.GetValue(LevelsProperty)));
}
set
{
this.SetValue(LevelsProperty, value);
}
}
}
}

ToonShaderEffect : ShaderEffect

6.ShaderPanTest:测试功能--运用C#动态编译生成来使用Effect

 public static Assembly CompileInMemory(string code)
{
var provider = new CSharpCodeProvider(new Dictionary<string, string>() { { "CompilerVersion", "v4.0" } }); CompilerParameters options = new CompilerParameters();
options.ReferencedAssemblies.Add("System.dll");
options.ReferencedAssemblies.Add("System.Core.dll");
options.ReferencedAssemblies.Add("WindowsBase.dll");
options.ReferencedAssemblies.Add("PresentationFramework.dll");
options.ReferencedAssemblies.Add("PresentationCore.dll");
options.IncludeDebugInformation = false;
options.GenerateExecutable = false;
options.GenerateInMemory = true;
CompilerResults results = provider.CompileAssemblyFromSource(options, code);
provider.Dispose();
if (results.Errors.Count == )
return results.CompiledAssembly;
else
return null;
}

CompileInMemory(string code)

7.源码: https://github.com/lenkasetGitHub/Song_WPF_PixelShader (exe图标来自easyicon)

https://gitee.com/github-19276270/Song_WPF_PixelShader

仿制shazzam的简单功能,将hlsl转换为WPF中的ShaderEffect的更多相关文章

  1. 【 VS 插件开发 】三、Vs插件简单功能的实现

    [ VS 插件开发 ]三.Vs插件简单功能的实现

  2. 零元学Expression Blend 4 - Chapter 29 ListBox与Button结合运用的简单功能

    原文:零元学Expression Blend 4 - Chapter 29 ListBox与Button结合运用的简单功能 本章所讲的是运用ListBox.TextBox与Button,做出简单的列表 ...

  3. python库的tkinter带你进入GUI世界(计算器简单功能)

    前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: 一个处女座的程序猿 PS:如有需要Python学习资料的小伙伴可以加 ...

  4. ? 原创: 铲子哥 搜狗测试 今天 shell编程的时候,往往不会把所有功能都写在一个脚本中,这样不太好维护,需要多个脚本文件协同工作。那么问题来了,在一个脚本中怎么调用其他的脚本呢?有三种方式,分别是fork、source和exec。 1. fork 即通过sh 脚本名进行执行脚本的方式。下面通过一个简单的例子来讲解下它的特性。 创建father.sh,内容如下: #!/bin/bas

    ? 原创: 铲子哥 搜狗测试 今天 shell编程的时候,往往不会把所有功能都写在一个脚本中,这样不太好维护,需要多个脚本文件协同工作.那么问题来了,在一个脚本中怎么调用其他的脚本呢?有三种方式,分别 ...

  5. 博途V13 仿真S7-300PLC 与HMI 的以太网通讯。实现简单功能 HMI 型号是TP900

    本项目仅完成S7-300 PLC 型号为 315-2DP/PN HMI的型号是 智慧面板TP900 通过以太网进行连接.通过网络及连接 进行组态 PLC的程序 功能一 完成电动机的启动与停机 功能二 ...

  6. WPF中的触发器简单总结

    原文 http://blog.sina.com.cn/s/blog_5f2ed5cb0100p3ab.html 触发器,从某种意义上来说它也是一种Style,因为它包含有一个Setter集合,并根据一 ...

  7. C:函数:功能:实现字符数组中所有字母的倒序存放并输出

    前两天小测碰到一道题,建立一个函数,功能:实现字符数组中所有字母的倒序存放并输出,一开始觉得简单跟数字数组差不多,运行一下发现很多格式错误,这些是不必要的错误,现在就来说下,先说一下代码思路:定义一个 ...

  8. WPF中的简单水动画

    原文 https://stuff.seans.com/2008/08/21/simple-water-animation-in-wpf/ 很多年前(80年代中期),我在一家拥有Silicon Grap ...

  9. WPF中使用MVVM模式进行简单的数据绑定

    计划慢慢整理自己在WPF学习和工作应用中的一些心得和想法,先从一个简单的用法说起 在WPF中,XAML标记语言中绑定数据,而数据源就是指定为ViewModel类,而非界面本身的逻辑代码类 这样一定程度 ...

随机推荐

  1. C语言实现常用数据结构——栈

    #include<stdio.h> #include<stdlib.h> //用链表实现栈 typedef struct Node { int data; struct Nod ...

  2. 3022Java_运算

    运算 1.运算符分类 算术运算符 二元运算符 +,-,*,/,% 一元运算符 ++,-- 赋值运算符   = 扩展运算符 +=,-=,*=,/= 关系运算符 >,<,>=,<= ...

  3. 面试官:你了解过Redis对象底层实现吗

    上一章我们讲了Redis的底层数据结构,不了解的人可能会有疑问:这个和平时用的五大对象有啥关系呢?这一章我们就主要解释他们所建立的联系. 看这个文件之前,如果对ziplist.skiplist.int ...

  4. TCP使用注意事项总结

    目录 发送或者接受数据过程中对端可能发生的情况汇总 本端TCP发送数据时对端进程已经崩溃 本端TCP发送数据时对端主机已经崩溃 本端TCP发送数据时对端主机已经关机 某个连接长时间没有数据流动 TCP ...

  5. 深入理解ES6 - var-let-const

    知识点 var 声明变量: 1.存在变量提升,实际上var无论在哪里声明,都会被当做当前的作用域顶部声明变量. 2.可以重复声明,后声明的变量会覆盖前声明的变量. let 声明变量: 1.不存在变量提 ...

  6. python 参考知识点

    本笔记仅作为有编程基础的童鞋在学习python时的参考资料,不适合零基础小白,并假设在你的电脑上已经正确安装了python环境,windows下需要配置环境变量,可以在终端窗口中执行以下命令 set ...

  7. 浅入深出Vue:事件处理

    上一篇的最后留下了一个 v-on的思考,也就是本章的主题:事件处理 为什么需要事件处理 在前端开发中,经常要面对各种表单.按钮.而这里面就住着一个事件:点击 (click). 前端童鞋们肯定不陌生它, ...

  8. IO解惑:cephfs、libaio与io瓶颈

    最近笔者在对kernel cephfs客户端进行fio direct随机大io读测试时发现,在numjobs不变的情况下,使用libaio作为ioengine,无论怎么调节iodepth,测试结果都变 ...

  9. 《深入浅出RxJS》读书笔记

    rxjs的引入 // 如果以这种方式导入rxjs,那么整个库都会导入,我们一般不可能在项目中运用到rxjs的所有功能 const Rx = require('rxjs'); 解决这个问题,可以使用深链 ...

  10. Git 安装教程(2.21.0)

    获取安装包地址 1.官网(较慢):https://git-scm.com/downloads 2.下载链接:http://down-ww3.newasp.net/pcdown/soft/soft1/g ...