【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的一个系统级线程会自动释放该内存块.垃圾回收意味着程序不再需要的对象是"无用信息 ...
随机推荐
- 【u023】最长上升子序列(sequence)
Time Limit: 1 second Memory Limit: 128 MB [问题描述] 非常经典的问题,拿来给大家练手了. 序列 { 1,2,...,n } 的一个子序列是指序列 { i1, ...
- SoC中的IP模块学习
SoC中的IP模块学习 理解IP Spec-->register定义,理解原理+架构框图 查看testcase+model(看已有的测试例程),分析操作/使用模块的流程,寄存器的配置方法 运行仿 ...
- Swift 带有动画效果的TabBarItem
额...貌似挺长时间没有总结新知识了,最近在看swift,之前swift刚出来的时候大体看了一遍,后来时间长了没看加之swift2.0做了比较大的调整,公司项目也不是用swift写的,也就没怎么看了, ...
- 魔兽争霸war3心得体会(四):不死族vs人族1本火魔塔
QQ对战平台上玩随机的人特别多,为了应对对方的"出其不意",我最近一直用小狗去探路,小狗在家采集30个木头-摆放商店,就可以去探路了.主要有几个好处:知道对方的种族-出生点位-开局 ...
- spring getbean 方法分析(很实用!)
十年阿里,就只剩下这套Java开发体系了 >>> 在最近的项目中,有个地方我们不得不实用getBean的方法,自己从Spring context中获取bean进行数据库操作. 方 ...
- [Angular] Using NO_ERRORS_SCHEMA
For example, when testing container component we might import lots of children components, but we di ...
- [AngularFire2] Signup and logout
import {AuthProviders, FirebaseAuthState, FirebaseAuth, AuthMethods} from "angularfire2";i ...
- [CSS] No selectable effect
.noselect { -webkit-touch-callout: none; /* iOS Safari */ -webkit-user-select: none; /* Chrome/Safar ...
- [Docker] Accessing a Container
If you want to get into container and look around, you can use: docker container exec to run against ...
- html5-6 Frame框架窗口类型
html5-6 Frame框架窗口类型 一.总结 一句话总结: 1.点左侧的a链接如何打开右侧页面? <a href='user/index.html' target='right'>& ...