【瑞模网】渲染TA实战:模型草美术效果分享-01.从做一簇草的模型开始http://t.csdn.cn/j9PZD
【瑞模网】渲染TA实战:模型草美术效果分享-02.基础的颜色、和风拂动的效果http://t.csdn.cn/kv7OG
碰撞交互
计算和物体的交互,核心要点是将物体的碰撞信息传递给草的shader。我们案例里的方法是:使用一个略大于角色(在案例里是个球)的盘型模型,将它的法线通过Render Feature渲染在一张RT上,在草计算受力的时候,再去读取这张RT,和风力结合在一起输出到顶点位移上。
这样做的好处在于:首先,相比于以往传递参数给Shader来计算碰撞的物体数量不受限制。如果在Shader里申明了固定数量的位置、大小等信息来计算碰撞,如果实际需要计算碰撞的参数少于申明的参数则会浪费,多了就会有丢失。另外,我们可以通过控制我们的盘状模型的大小、形状、法线朝向,来模拟出草和草之间互相挤压的效果。
↑受到压力的草会向周围专递压力,用一个受力的代理网格来产生推力,可以避免复杂的迭代计算
来看看我们Render Feature的核心逻辑:首先,定义好正交相机和RT的参数,在Configure()函数里,找到打了Player Tag的GameObject,并以它为中心,调整我们的正交相机、并获取正交相机的透视和投影矩阵。
Execute()里,使用ShaderTag和LayerMask来限制我们的碰撞模型只渲染在我们申请的这一张RT上。使用Context.DrawRenderers()提交我们的渲染命令。
最后,如果申请了Temporary Render Texture,一定记得要释放。
Create()和AddRenderPass()算是常规操作,就不再赘述了。碰撞模型所使用的shader也非常的简单。使用从Feature传出的矩阵做投影变换。然后输出法线。就是记得Shader的Tag和Feature里定义的保持一致。碰撞模型的GameObject碰撞物体的Layer也要设置准确。
如果feature设置成功的话,现在使用FrameDebugger应该可以看到我们已经渲了一张RT出来了。
然后我们回到草的shader部分。我们可以使用此前在Feature里传递出来的相机参数,还原出采样RT所用的UV。
采样之后,我们使用保存在b通道的深度信息和相机的信息,还原出碰撞模型的世界空间高度。我们可以用它和草顶点的相对距离,来计算RT对草推力的影响。
现在我们就已经获得了一个可以交互的草。
除此之外还有一些额外的风格化处理:我们让被碰撞体压到的草缩小一些。否则在茂密的草丛里,有碰撞体压到草丛会让受力的草戳进旁边的草丛里,看起来会稍显凌乱。
让草的交互富有弹性
到现在我们的草应该能满足一些交互的要求了,但是如果要更近一步,想要草看上去更“物理”、有弹性,我们需要对生成RT的步骤做进一步的处理:
草的受力计算算是中学物理的知识,比较简单就不再赘述。具体在Feature里实现的时候需要注意的一点是:其中计算当前帧的速度、和当前帧草的顶点位移时,都需要用到上一帧保存的速度和位移(上一帧碰撞模型的推力可以通过相机的一帧之内的位移推算出来,所以不需要跨帧保存它)。但是TemporaryRT在每帧结束都会执行FrameCleanUp,所以速度和最后的位移这两张RT需要申请普通的RenderTexture。
↑这里的Blit步骤中,Velocity_Temp在使用完之后应该可以继续用在FinalTmpde的位置。这里为了过程看起来清晰就不做修改了。