异质性查询需要为连线设定_[Unity]使用ShaderGraph为生成的地形制作自定义材质

c16525a390afdbaa98cf07b87f9a77c2.png

承接上一篇

saku一只松鼠:[unity]通过高度图制作一个真实世界的地形​zhuanlan.zhihu.com
9d2489d2fde9e887b768e995cf591653.png

由于历史的车轮不断前进,松鼠为了不固步自封,在地形插件中更新了可以在SRP下使用的模式。从此使用Lightweight和High Definition Render Pipeline的用户再也不用面对生成的地块一片粉色的局面了。

a754223336f1966937d92891b4b98ca0.png
么得办法,选用srp之后原来的built-in standard就粉了

d0e3d4957aa7f60aeb73a111a3f061f0.png
unity有提供一个upgrade material的功能,来将旧材质转换为新管线支持的模式

不过通过这次更新,一个问题也浮出水面:

Unity的这一个新渲染管线目前还处于preview阶段,自带的转换工具只能处理built-in的shader,于是RTM中专门为地图应用而制作的材质全部阵亡了。

534dccce54d285409a68788dd44a92e7.png
一个根据海拔高度给地形附加颜色的小效果

不过好消息是,这样的效果借助新推出的图形化shader编辑工具可以轻松愉快地完成。于是,在这一章中,我们使用shaderGraph制作材质,并将它作为模板直接赋予到新生成的地形上。


首先,使用shadergraph需要做几个前置任务:

1.打开package manager,安装Lightweight RP。新建工程的时候使用LWRP模板也可以达到差不多的效果,不过建议之后还是在package manager中将其升级到最新版本。

2. Create > Render Pipeline > Lightweight > Pipeline Asset,之后把新建的asset拖到Project Settings > Graphics中的scriptable render pipeline setting一栏中。(如果是使用模板新建的工程则可以省略这一步。如果遇到报错的话,顺手把player setting中的color space从gamma改为linear)

3.在package manager中,安装shader graph。之后就可以新建shadergraph的文件了。

59640cb688c52ffb79b78de6d54a9c24.png

随意从这三项里选一个最简单的,建立unlit graph。之后随便create一个texture 2d的节点,连线到输出节点的color上,就可以显示这张贴图了。

a4dd3ebd46316654329605de25618163.png
轻松上手

接下来正文开始。

在使用传统的shaderlab制作依据高度着色的效果,需要两个property来设定高度最高点和最低点的高度。

_heightMax("pos Max",Float) = 10
_heightMin("pos Min",Float) = 0
_colorA ("Color Up",Color) = (0,0,0,1)
_colorB ("Color Down ",Color) = (0,0,0,1)

之后用vertrex.y来计算当前高度在最高点最低点之间的位置,并以此计算两个颜色的插值。

void 

为了完成以上工作,我们设置一些节点,并按照公式连线。

首先是第一步

2a4681a0752a90d6437c55f5cce7b6fe.png
需要注意的是红色虚线里的部分,由于世界坐标包含了xyz,所以需要一个split将y坐标单独提取出来

接着第二步,使用上面计算的结果做两个颜色之间的插值。

39cfd0a52407b426af3bae27f09189f9.png

在这里,其实unity给提供了一个更方便的节点,remap。

根据非官方文档中提供的资料:

//The following example code represents one possible outcome of this node.
 
void Unity_Remap_float4(float4 In, float2 InMinMax, float2 OutMinMax, out float4 Out)
{
 Out = OutMinMax.x + (In - InMinMax.x) * (OutMinMax.y - OutMinMax.x) / (InMinMax.y - InMinMax.x);
}

可以将连线简化,并且不用再受到除0的困扰。

e52ae370ae379bab3622290942a41990.png
使用了worldspace的坐标,虽然在预览中看不出颜色变化,但是在实际的场景中还是没问题的

17f11dc44a6fb8e35c31c1552eabd92d.png

虽然达到了效果,但是在inspector中都没有可调节的选项,这无疑会让人比较厌烦,这时就需要将一部分input的节点convert to property。

找到两个height节点和两个color节点,右键选择转换,它们就会出现在旁边的properties中

1bfe3d9c99940dc289879b0f4d337e4b.png
ShaderGraph中的property和inspector中一一对应。点击加号,新建一个property,然后直接拖转到工作区也是一种便捷的方法

bd70b0326307ed17b5eb345b9bf87167.gif
现在会根据高度附加上对应的颜色了

除了基于高度着色外,一个不带卫星图的地形显然是没有灵魂的,接下来我们做贴图的部分。

首先在新建一个property,并改名为_MainTex,接着将它拖到工作区。

d50c09d6217419a625af6e466369d8f1.png

根据文档中的解释Samples a Texture 2D and returns a Vector 4 color value for use in the shader.要使用texture2D就需要为它配备一个采样器,来将图片转换为RGBA的颜色数据。

742320b7c593ff57d2ef264725c9610f.png
试着直接把采样结果连到Master节点上,预览模型就被贴上这张图了。

接着,用加法或乘法的方式将贴图和颜色融合起来。

3f12899e943892d3dea6070a164bb273.png

就实现了这样的效果

bae15c24db34a87542c4d164a6261e4c.png
此处示例使用了最简单的一个乘法运算,如果有兴趣,可以搜索ps中常用的混合方式以及它们的公式

接下来,要让生成一个地形的时候直接附上我们刚刚制作的材质。在前一章使用高度图生成地形的脚本基础上,增加材质模板和贴图的变量。

 [SerializeField] 
 Texture2D Tex;
 [SerializeField] 
 Material Mat;
 string propertyname = "_MainTex";

propertyname就使用之前给贴图起的名字。

在生成texture的部分做一点修改:

 	void DrawTexture(){
		if (gameObject.GetComponent <MeshRenderer> ()==null ) {
			gameObject.AddComponent<MeshRenderer> ();
		}	
		Material diffuseMap = new Material (Shader.Find (Mat.shader.name));
		diffuseMap.CopyPropertiesFromMaterial(Mat);
		diffuseMap.SetTexture(propertyname,Tex);
		gameObject.GetComponent<Renderer> ().material = diffuseMap;
	}

这样就以我们选用的材质的shader生成一个新材质,并复制了原材质的属性,接着将贴图赋给相应的property。

169b035db7efe2bb36c13f0f6ca6ea7c.png

接着,还有一件之前忘记做的事情,为mesh的每个顶点设定一个uv,不然所有uv都是默认值(0,0)的话,是没办法正确显示贴图的。

	void setUV()
	{
		_uvs = new Vector2[(sx+1)*(sy+1)];
		float u = 1.0F / sx;
		float v = 1.0F / sy;
		for (int yy = 0; yy <= sy; yy++)
		{
			for (int xx = 0; xx <= sx; xx++)
			{	
				int self = xx + yy *(sx+1);
				_uvs[self] = new Vector2(xx * u, yy * v);
			}
		}
	}

接着,赋值给mesh。

mesh.uv = _uvs;

以上操作的作用是将所有顶点的uv按顺序均匀分配到0和1之间,即简单的让贴图均匀铺满整个mesh,并将计算结果存入数组。这个0到1的范围就对应了贴图从左下到右上的全部,而如果把范围修改为0~2的话,

		float u = 1.0F / sx;
		float v = 1.0F / sy;

根据贴图的wrap mode设置,就会得到不同的效果了。

371e34636fe753f9eb492706621dd130.png
uv坐标超过1的时候,超出的部分就会依据贴图的设定呈现拉伸或者重复的样子

新建一个空物体,挂上脚本并配置好材质和图,然后try一下,就会有带有卫星图的彩色地形生成出来了。


这一章同样出自地形生成插件:

Real Terrain Maker - Asset Store​assetstore.unity.com
cc3388fd35366944505ffd1b41a3dfc1.png

好惨啊小本生意被打差评真的闹不住,而且还是问都没问直接打。希望有兴趣的客官在阅读使用说明或者看过demo之后理性购买,能打个5星真的感激不尽,作者哭超凶的。

作者活着,随时可在客(没)服(人)群里提问


这章所用到的资源在这里获取:

sakuraplus/make-terrain-with-google-elevation​github.com

由于使用了shadergraph,这次的需求是unity2019.1.7及以上。

脚本挂在任意物体上即可使用,当然建议使用空物体,不然会造成好玩的影响。

如果出现Texture 'Trr00downloadHeightmap_143' is not readable这样的提示,将图片的import setting设为Read/Write Enabled,同时不要忘记将Power of 2设置为none,filter mode为point,不然在逐像素采样的时候会受到影响。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值