这几天在捣鼓一个游戏 骑马与砍杀 不知道有没有人玩过。官方出了个shader包,能够自定义shader,因而就开始学起来了,学了一点,简单的实现了一直想弄的动态世界。这期间一直在用RenderMonkey开发(貌似中止更新了,会不会有点落伍了),就记下一点过程,主要算是做为给mod做者一个简单教程,也方便刚开始捣鼓的朋友们,同时也方便本身长久不碰以后从新拾起来,。才接触几天,有问题还望指出。 app
这篇东西主要讲述如何让模型的顶点浮动来达到一种动画效果,顺便介绍下RenderMonkey。 函数
下载安装RenderMonkey没什么好说的,就这么安装呗。HLSL语言本身去学习吧,其实我也是刚学起HLSL,不敢教你们,仍是本身找资料吧。 学习
打开RenderMonkey(吐槽下这个猩猩图标真丑) 测试
嘛,这不是VC6嘛。(据说彷佛VC也能够用来开发shader?)好吧,不吐槽这个界面了。 动画
界面也没什么号解释的,上面几个图标说一下吧,虽然英文也看得懂。 spa
从左到右为:打开项目,保存项目,关闭侧边目录栏,关闭下面输出栏,打开渲染预览效果,右边的侧边栏(用处未知),三种编译方式,各类镜头有关的操做(没用过),最后一个未知。 翻译
废话很少说开始建立一个实例吧。 3d
能够选择add effect group或者add default effect, 前者更像一个项目包吧,里面能够包含不少effect, 咱们就直接add default effect吧。 code
这里咱们建立一个最基本的DirectX effect。下面还有几种能够选带贴图的,带高光的,带凹凸的等等,这些也是很好的学习内容,能够看到高光,凹凸是如何作成的。咱们只须要一个简单的例子就好了。 教程
好,咱们看到了一个红色的圆球,这个就是预览界面。
主要来看左边预览界面咱们建立的是一个Default_DirectX_Effect,固然你能够本身重命名。
其中包含了四个子节点matViewProjection,Stream Mapping,Model,Pass 0,固然咱们如今建立的是最基础的effect,实际上节点数不定的,这些应该是必须的。
先说matViewProjection,这是一个float4x4的矩阵,这个其实不太好形容是什么东西,这个矩阵用来将顶点坐标转化后输出,有教程称它为世界、观察、投影矩阵。而在以后的Vertex Shader的编写中,最后必定要将输入的坐标与这个矩阵相乘,获得转化的坐标,以后输出。这是一个预约义变量。预约义变量有很多,我如今只会用第一个时间变量,这是作动态效果的基础,其余的不明其意。
而后是Stream Mapping, 字面翻译是流映射,主要做用应该是将模型的信息传递给shader.
目前只有一个POSITION 顶点位置. 能够自行添加,好比要运用贴图时须要TEXCOORD 纹理坐标。
Model很简单,就是选用的模型,双击更换模型。
Pass 0一样不知道怎么翻译好,每一个pass内有一对VertexShader与PixelShader, 而每一个Effect能够有多个Pass. 忽然想起来准确的来讲这个Effect应该叫作Technique..
好了,介绍到这了,咱们开始写代码吧。先选择一个模型,我弄了一面旗帜来作飘动效果。
选完模型,请在预览界面上右键Fit Model to Screen, 来调整好大小,否则可能看不见模型。因为此次飘动效果只靠顶点来完成,因此咱们打开VertexShader,也就是顶点着色器。
看看代码,第一个定义的变量就是一开始提到的float4x4的矩阵matViewProjection,注意名字必须是和节点那里相同的才行。下面两个结构体。一个输入,一个输出,都有一个float4的变量,是一个四维浮点数向量。结构体并非强制的,你能够直接用其中变量做为以后对的输入参数,不过这样应该不是很科学,嗯嗯。变量后面的:POSITION代表该变量表示顶点位置,若是还记得,上文在Stream Mapping理提到过这个。下面就是入口函数了,接受输入后将顶点位置转换后输出。
好吧,真的要开始写了。动画嘛确定要有个时间变量啊,嗯嗯,上文提到过的预约义变量,咱们就增长这个变量,能够为它改个名,只要注意在代码里的声明名字要和节点里的同样,咱们就改为time. 而后在代码里声明float time;,咱们把它放在float4x4 matViewProjection;下面一行。
好了,让咱们来作飘动吧,来回的摆动是一个周期运动,因此咱们选择一个周期函数,sin,cos随便,咱们选一个sin(time)。飘动的本质就是每一个顶点在特定时间内移动一段距离。那咱们先设定一个基础距离base为0.5,固然也是float类型。可是不能每一个顶点移动同样的距离啊,为了飘动的比较和谐,咱们按照旗面上的每一个顶点离旗上边和左边的比例来缩小base。
Input.Position.x = Input.Position.x + offset_base*sin(time)*(Input.Position.y/y_length)*((z_length-Input.Position.z)/z_length);
固然移动哪一个轴的坐标,移动多大的距离要看你的模型实际尺寸。
固然最后你要限制下只能旗面动,杆子什么的不受影响。
float4x4 matViewProjection; float time; struct VS_INPUT { float4 Position : POSITION0; }; struct VS_OUTPUT { float4 Position : POSITION0; }; VS_OUTPUT vs_main( VS_INPUT Input ) { VS_OUTPUT Output; float offset_max=0.5f; float z_length=2.0f; float y_length=1.0f; if((Input.Position.z>0.6f)&&(Input.Position.z<2.0f)){ if (Input.Position.y>0.1f){ Input.Position.x = Input.Position.x + offset_max*sin(time*2)*(Input.Position.y/y_length)*((z_length-Input.Position.z)/z_length); } } Output.Position = mul( Input.Position, matViewProjection ); return( Output ); }
而后编译下看看吧,动起来了吧。
几点说明:在预览界面右键show triad能够显示坐标,可是这个坐标是左手坐标系,虽然model上右键能够改左右手坐标系,但貌似测试无效。因此坐标系可能和你的建模软件里不一样,好比我如今3dmax里是右手坐标系,因此这个要注意一下,能调成一致仍是最好了~
另外,你们以为这样精确到数值的控制选择的顶点很2吧,并且要跑去建模软件里看到底这个顶点坐标数值多少。其实也能够经过贴图坐标来完成,研究完了下次再写,包括这部分没写的如何加上贴图也一并写上。
终于写完了,头昏脑胀的,啰啰嗦嗦,感受像在写日记,不是写教程,你们将就看吧。。有错误欢迎指出,有遗漏欢迎补充。