105

小随笔:利用Shader给斯坦福兔子长毛和实现雪地效果 - 慕容小匹夫

 6 years ago
source link: http://www.cnblogs.com/murongxiaopifu/p/7887614.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

0x00 前言

发现最近没有了写长篇大论的激情,可能是到了冬天了吧。所以这篇小文只是简单介绍下如何在Unity中利用shader很简单的实现雪地效果以及毛皮效果,当然虽然标题写在了一起,但其实这是俩事。
最后和大家分享一下这两个小Demo。

QQ截图20171123150603.png

0x01 斯坦福兔子和它的毛

我相信对图形学有兴趣的童靴们一定经常会见到这个上镜率超高的兔子。

v2-d8fcb1e6b2e787fdb41a00eb6cceadf2_hd.jpg
关于它的典故各位可以看看龚大的回答:斯坦福兔子模型的来源和故事有哪些?
当然,我用的兔子也是从斯坦福的网站上找到的。
https://graphics.stanford.edu/~mdfisher/Data/Meshes/bunny.obj
ok,导入到我们的Unity引擎中。
QQ截图20171123130550.png
可以看到这个丑丑的兔子已经端坐在场景内了。
接下来就开始我们对兔子的改造行动吧。
既然要生成皮毛,那么是否需要皮毛的网格数据呢?是的。
那么皮毛的网格要根据什么来生成呢?
要生在兔子的身体上,所以兔子的原始网格信息提供了皮毛的网格信息。
ok,那么具体要怎么做呢?很简单,Geometry Shader就是干这个的。而我们只需要根据兔子的网格信息,以每一个triangle为一个单位,在这个triangle上生成一个向外指的“金字塔”就可以了。
无标题.png
也就是说,在原有triangle的基础上又新生成了3个指向外面的triangle,形成毛皮的效果。
        [maxvertexcount(9)]
		void geom(triangle v2g IN[3], inout TriangleStream<g2f> tristream)
		{
			g2f o;
            ...

			for (uint i = 0; i < 3; i++)
			{
				o.vertex = UnityObjectToClipPos(IN[i].vertex);
				tristream.Append(o);

				o.vertex = UnityObjectToClipPos(IN[index].vertex);
				tristream.Append(o);

				o.vertex = UnityObjectToClipPos(float4(centerPos, 1));
				tristream.Append(o);

				tristream.RestartStrip();
			}
        }

因此总共会生成9个顶点,3个新三角形共同组成一跟毛。

QQ截图20171123130431.png

Demo地址:chenjd/Stanford-Bunny-Fur-With-Unity

0x02 雪地痕迹的效果

实现雪地印痕的思路其实也很简单,即记录玩家移动过程中的位置,之后再根据这些数据修改雪地的mesh即可。

DBP8EFZQJNU4{@M}MI50)%1.png

所以,很简单的,我们在unity中只需要一个在玩家头顶上的正交相机和一个rendertexture就可以记录玩家的移动过程中的位置了。
之后在shader文件中先用vs根据rendertexture的数据修改雪地mesh的相关顶点位置,同时为了更方便地实现光照的效果,接下来使用surface shader,实现光照。

    void vert(inout appdata_full vertex)
	{
		vertex.vertex.y -= tex2Dlod(_SnowTrackTex, float4(vertex.texcoord.xy, 0, 0)).r * _SnowTrackFactor;
	}

	void surf (Input IN, inout SurfaceOutputStandard o) {
		fixed4 c = tex2D(_MainTex, IN.uv_MainTex);
		o.Albedo = c.rgb;
		o.Normal = UnpackNormal(tex2D(_NormalMap, IN.uv_MainTex));
		o.Alpha = c.a;
    }

好了,最后的效果就是下面这样的。

633433.gif
Demo地址:chenjd/Unity-Miscellaneous-Shaders

0x03 后记

当然,如果有更多的三角形以上效果会更加真实精细。所以有时候会搭配Tessellation的处理,提供更多的三角形,提供更多的精确性。

-EOF-
最后打个广告,欢迎支持我的书《Unity 3D脚本编程》

1240

欢迎大家关注我的公众号慕容的游戏编程:chenjd01

1240
本作品采用知识共享署名-非商业性使用-相同方式共享 2.5 中国大陆许可协议进行许可,我的博客欢迎复制共享,但在同时,希望保留我的署名权陈嘉栋(慕容小匹夫),并且,不得用于商业用途。如您有任何疑问或者授权方面的协商,请给我留言
知乎专栏:
Runtime
联系方式:
Email:[email protected]

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK