zoukankan      html  css  js  c++  java
  • 小随笔:利用Shader给斯坦福兔子长毛和实现雪地效果

    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脚本编程》

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

  • 相关阅读:
    python 通过*.cer *..pfx 获取公钥私钥
    python 交集 并集 差集
    python3 RSA加密、解密、签名
    Go 入门
    ansible入门篇一
    ACM/ICPC 之 两道dijkstra练习题(ZOJ1053(POJ1122)-ZOJ1053)
    数学软件 之 基于MATLAB的DFP算法
    ACM/ICPC 之 最短路径-dijkstra范例(ZOJ2750-POJ1135(ZOJ1298))
    ACM/ICPC 之 判别MST唯一性-Kruskal解法(POJ1679)
    ACM/ICPC 之 四道MST-Prim解法(POJ1258-POJ1751-POJ2349-POJ3026)
  • 原文地址:https://www.cnblogs.com/murongxiaopifu/p/7887614.html
Copyright © 2011-2022 走看看