【HLSL学习笔记】WPF Shader Effect Library算法解读之[BandedSwirl]
原文:【HLSL学习笔记】WPF Shader Effect Library算法解读之[BandedSwirl]
因工作原因,需要在Silverlight中使用Pixel Shader技术,这对于我来说可算是相当有难度了,首先我是个Java Web开发程序员,从来没正经地学过微软的开发语言和工具;其次,对于算法这种东西,向来有种天生的排斥,一看便头疼。不过项目逼到份上了,只能硬着头皮上,真不知道领导们是怎么想的。还是言归正传吧,记录记录自己的学习心得。
熟悉Silverlight的人都知道,SL中有一物名为Pixel Shader,江湖人称像素着色器。是Sl中可以单独操控像素的一门技术。SL3中集成了两个Shader,一为DropShadowEffect,二谓BlurEffect,可为用户产生投影与模糊的效果。此外,MS还为程序员开辟了自定义通道,程序员可以自行编写Shader文件,并通过C#封装,最终应用在SL中。而编写Shader文件则需要采用HLSL(高级着色器语言High-Level-Shader-Language),正如当年新手上路用文本文件编写Java的HelloWorld程序一样,Shader同样可以用文本文件编写,同样可以用命令行编译。本文是我工作中的一些琐碎的片段,主要针对的是开源的WPF Pixel Shader Effect Library项目中的Shader源代码进行研究和学习,从而不断的提高自己。
项目地址为:http://wpffx.codeplex.com/
其中提供了18个Shader:

图1 Shader列表
初学Shader,不知从何做起,前人有高质量的代码,何不直接取来,参详研习。这两天刚开始研究BandedSwirl.fx,做点记录:
有必要说的是逆向的解读别人的算法是一个非常痛苦的过程,只有通过特效展示结合算法文件自己去构建算法模型方可,至少这是我笨人所采用的笨办法:)
BandedSwirl直译的话应该叫做【带状螺旋】效果,初见时觉得挺震撼,觉得这种算法程序应该很长才是,没想到不过区区30行左右,可见Shader编程之精炼。先看看效果截图:
再来瞅瞅源代码:

图2 带状螺旋效果图
//++++++++++++++++++++++++++++++SRC+++++++++++++++++++++++++++++
//--------------------------------------------------------------------------------------
// 全局变量,供应用程序设置,在Silverlight中动态改变这些参数便成了动画
//--------------------------------------------------------------------------------------
//定义螺旋效果的中心点,默认是(0.5,0.5),存放在常量寄存器C0里
float2 center : register(C0);
//定义螺旋效果的强度
float spiralStrength : register(C1);
//距离的阈值
float distanceThreshold : register(C2);
//定义了2D采样器,如果应用在MediaElement上的话,MediaElement的实时画面便是采样器的内容,存放在临时寄存器S0中。
sampler2D implicitInputSampler : register(S0);
//--------------------------------------------------------------------------------------
// 像素着色器
//--------------------------------------------------------------------------------------
float4 main(float2 uv : TEXCOORD) : COLOR
{
//定义2d向由中心指向某一纹理坐标的向量
float2 dir = uv - center;
//求取向量的长度,l的值域为[0,√2/2]
float l = length(dir);
//向量除以自己的长度就是单位向量,只用于表示方向
dir = dir/l;
//求取向量和水平线的夹角,这里值域为[-PI/2,PI/2]
float angle = atan2(dir.y, dir.x);
//为了进行交替的螺旋对流,避免采用类似for循环的流程控制语句,导致额外的性能耗费,需要用一个值来控制螺旋对流的循环周期,这里采用了一个名为距离阈值的参数,remainder和l的关系图为一组周期为distanceThreshold的三角波,见图3
//值域为[0,1]
float remainder = frac(l / distanceThreshold);
//该参数是为了让螺旋周期内两路相反带装束过渡的更为平滑,在波形图上看就是为了让波形连续。
float preTransitionWidth = 0.25;
//定义一个参数,控制每个螺旋周期内的对流,每个漩涡周期内共有两路正向带状束和一路反向带装束,分别交替呈现。Fac和remainder的关系见图4
float fac;
//控制对流方向的交替以及波形的连续
if (remainder < .25)
{
fac = 1.0;
}
else if (remainder < 0.5)
{
fac = 1 - 8 * (remainder - preTransitionWidth);
}
else if (remainder < 0.75)
{
fac = -1.0;
}
else
{
fac = -(1 - 8 * (remainder - 0.75));
}
//计算基于参数【螺旋强度】的变换角度,意思就是在原来向量方向的基础上正向或者反向增大扭曲角度
float newAng = angle + fac * spiralStrength * l;
//按照螺旋强度计算出来的变换角度重新定义纹理坐标
float xAmt = cos(newAng) * l;
float yAmt = sin(newAng) * l;
float2 newCoord = center + float2(xAmt, yAmt);
//按照新的纹理坐标对原来的采样器进行纹理的渲染,得出最终的结果
return tex2D( implicitInputSampler, newCoord );
}
//++++++++++++++++++++++++++++++SRC+++++++++++++++++++++++++++++

图3 remainder和L的关系图

图4 fac和remainder的关系图
到这里也算大致搞明白这个算法的原理了,对于我来说,算是费了九牛二虎。从中也学到不少,以前自己写HLSL的时候,总喜欢用for循环来控制流程,比如要写一个百叶窗,首先想到的就是设定百叶窗的间隔,然后用1/间隔当做循环次数,每次用HLSLTester都勉强能编译过去,但是一旦到了要编译成ps_2_0的ps文件时总会报错,意思是每个Shader只允许64条汇编指令,超出这个数量就编译不过去。想想若是把for循环转变成汇编语言,会产生多少指令啊,效率能不低吗!!!
好像ps_3_0没有这个限制,但是SL貌似只支持ps_2_0,所以还是精炼下自己的代码吧。
总结一下心得:
1、 写Shader最好用向量,少用标量
2、 诸如for、do-while这一类的循环尽量少用
【HLSL学习笔记】WPF Shader Effect Library算法解读之[BandedSwirl]的更多相关文章
- 【HLSL学习笔记】WPF Shader Effect Library算法解读之[DirectionalBlur]
原文:[HLSL学习笔记]WPF Shader Effect Library算法解读之[DirectionalBlur] 方位模糊是一个按照指定角度循环位移并叠加纹理,最后平均颜色值并输出的一种特效. ...
- 【HLSL学习笔记】WPF Shader Effect Library算法解读之[Embossed]
原文:[HLSL学习笔记]WPF Shader Effect Library算法解读之[Embossed] Embossed(浮雕效果) 浮雕效果主要有两个参数:Amount和Wid ...
- V-rep学习笔记:Reflexxes Motion Library 3
路径规划 VS 轨迹规划 轨迹规划的目的是将输入的简单任务描述变为详细的运动轨迹描述.注意轨迹和路径的区别:Trajectory refers to a time history of positio ...
- OpenCV学习笔记(27)KAZE 算法原理与源码分析(一)非线性扩散滤波
http://blog.csdn.net/chenyusiyuan/article/details/8710462 OpenCV学习笔记(27)KAZE 算法原理与源码分析(一)非线性扩散滤波 201 ...
- 机器学习实战(Machine Learning in Action)学习笔记————06.k-均值聚类算法(kMeans)学习笔记
机器学习实战(Machine Learning in Action)学习笔记————06.k-均值聚类算法(kMeans)学习笔记 关键字:k-均值.kMeans.聚类.非监督学习作者:米仓山下时间: ...
- V-rep学习笔记:Reflexxes Motion Library 2
VREP中的simRMLMoveToPosition函数可以将静态物体按照设定的运动规律移动到指定的目标位置/姿态.If your object is dynamically enabled, it ...
- 再探快速傅里叶变换(FFT)学习笔记(其三)(循环卷积的Bluestein算法+分治FFT+FFT的优化+任意模数NTT)
再探快速傅里叶变换(FFT)学习笔记(其三)(循环卷积的Bluestein算法+分治FFT+FFT的优化+任意模数NTT) 目录 再探快速傅里叶变换(FFT)学习笔记(其三)(循环卷积的Blueste ...
- HMM的学习笔记1:前向算法
HMM的学习笔记 HMM是关于时序的概率模型.描写叙述由一个隐藏的马尔科夫链随机生成不可观測的状态随机序列,再由各个状态生成不可观測的状态随机序列,再由各个状态生成一个观測而产生观測的随机过程. HM ...
- jvm学习笔记一(垃圾回收算法)
一:垃圾回收机制的原因 java中,当没有对象引用指向原先分配给某个对象的内存时候,该内存就成为了垃圾.JVM的一个系统级线程会自动释放该内存块.垃圾回收意味着程序不再需要的对象是"无用信息 ...
随机推荐
- iOS Universal Static Framework 手动转 XCode Cocoa Framework
不须要又一次创建Project,手动改动project设置. 第一步:在Project文件里,改动type,去掉static 1. 搜索wrapper.framework.static,去掉stati ...
- Android自定义组件系列【5】——进阶实践(1)
接下来几篇文章将对任老师的博文<可下拉的PinnedHeaderExpandableListView的实现>分步骤来详细实现,来学习一下大神的代码并记录一下. 原文出处:http://bl ...
- java中的subString具体解释及应用
substring(參数)是java中截取字符串的一个方法 有两种传參方式 一种是public String substring(int beginIndex) 返回一个新的字符串,它是此字符串的一个 ...
- .Net Core身份认证:IdentityServer4实现OAuth 2.0 客户端模式 - 简书
原文:.Net Core身份认证:IdentityServer4实现OAuth 2.0 客户端模式 - 简书 一.客户端模式介绍 客户端模式(Client Credentials Grant)是指客户 ...
- 在nginx中使用lua直接訪问mysql和memcaced达到数据接口的统一
安装nginx參见<nginx+lua+redis构建高并发应用> 让nginx 中的nginx_lua_module支持mysql 和memcache 下载 https://github ...
- [Postgres] Group and Aggregate Data in Postgres
How can we see a histogram of movies on IMDB with a particular rating? Or how much movies grossed at ...
- web项目的WEB-INF目录
WEB-INF是Java的WEB应用的安全目录.所谓安全就是客户端无法访问,只有服务端可以访问的目录. 如果想在页面中直接访问其中的文件,必须通过web.xml文件对要访问的文件进行相应映射才能访问. ...
- 小强的HTML5移动开发之路(37)——jqMobi快速入门
在<小强的HTML5移动开发之路(33)-- jqMobi基础>中我们了解了什么是jqMobi,并从官方下载了jqMobi开发包,下载后解压目录如下: 拷贝上面的/css目录./plugi ...
- Erlang游戏开发-协议
Erlang游戏开发-协议 选择什么协议? 协议包含通讯协议和数据格式. 通讯协议 通讯协议目前常用的是:HTTP 和TCP .其有各自的特点根据游戏的特点而进行选择. HTTP HTTP比较成熟,使 ...
- 第二十一篇:基于WDM模型的AVStream驱动架构研究
基于WDM模型的AVStream驱动架构研 这篇论文2006年早就发表, 与当时开发这个驱动正好几乎相同的时间. 近期实际项目须要, 又回过头来将AVStre ...