初学RenderMonkey做一面旗帜飘动的效果

这几天在捣鼓一个游戏 骑马与砍杀 不知道有没有人玩过。官方出了个shader包,可以自定义shader,于是就开始学起来了,学了一点,简单的实现了一直想弄的动态世界。这期间一直在用RenderMonkey开发(貌似停止更新了,会不会有点落伍了),就记下一点过程,主要算是作为给mod作者一个简单教程,也方便刚开始捣鼓的朋友们,同时也方便自己长久不碰之后重新拾起来,。才接触几天,有问题还望指出。

这篇东西主要讲述如何让模型的顶点浮动来达到一种动画效果,顺便介绍下RenderMonkey。

下载安装RenderMonkey没什么好说的,就这么安装呗。HLSL语言自己去学习吧,其实我也是刚学起HLSL,不敢教大家,还是自己找资料吧。

打开RenderMonkey(吐槽下这个猩猩图标真丑)

嘛,这不是VC6嘛。(听说似乎VC也可以用来开发shader?)好吧,不吐槽这个界面了。

界面也没什么号解释的,上面几个图标说一下吧,虽然英文也看得懂。

从左到右为:打开项目,保存项目,关闭侧边目录栏,关闭下面输出栏,打开渲染预览效果,右边的侧边栏(用处未知),三种编译方式,各种镜头有关的操作(没用过),最后一个未知。

废话不多说开始创建一个实例吧。

可以选择add effect group或者add default effect, 前者更像一个项目包吧,里面可以包含很多effect, 我们就直接add default effect吧。

这里我们创建一个最基本的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吧,而且要跑去建模软件里看到底这个顶点坐标数值多少。其实也可以通过贴图坐标来完成,研究完了下次再写,包括这部分没写的如何加上贴图也一并写上。

终于写完了,头昏脑胀的,啰啰嗦嗦,感觉像在写日记,不是写教程,大家将就看吧。。有错误欢迎指出,有遗漏欢迎补充。

原文地址:https://www.cnblogs.com/lx-hhxxttxs/p/6000348.html