UnityShader学习——程序纹理

什么是程序纹理

程序纹理(Procedural Texture)指的是那些由计算机生成的图像,我们通常使用一些特定的算法来创建个性化图案或非常真实的自然元素,例如木头、石子等。使用程序纹理的好处在于我们可以使用各种参数来控制纹理的外观,而这些属性不仅仅是那些颜色属性,甚至可以是完全不同类型的图案属性,这使得我们可以得到更加丰富的动画和视觉效果。

生成程序纹理

我们将会使用代码来生成一个波点纹理:

对于每个属性我们使用了get/set的方法,为了在面板上修改属性时仍可以执行set函数,我们使用了一个开源插件SetProperty(https://github.com/LMNRY/SetProperty)。这使得当我们修改了材质属性时,可以执行_UpdateMaterial函数来使用新的属性重新生成程序纹理。

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

//让该脚本能够在编辑器模式下运行
[ExecuteInEditMode]
public class ProceduralTextureGeneration : MonoBehaviour {
	//声明一个材质,这个材质将使用该脚本中生成的程序纹理
	public Material material = null;
	//声明该程序纹理使用的各种参数
	#region Material properties
	//纹理的大小,数值通常是2的整数幂
	[SerializeField, SetProperty("textureWidth")]	
	private int m_textureWidth = 512;
	public int textureWidth {get {return m_textureWidth;} set {m_textureWidth = value;_UpdateMaterial();}}
	//纹理的背景颜色
	[SerializeField, SetProperty("backgroundColor")]
	private Color m_backgroundColor = Color.white;
	public Color backgroundColor {get {return m_backgroundColor;}set {m_backgroundColor = value;			_UpdateMaterial();}}
	//圆点的颜色
	[SerializeField, SetProperty("circleColor")]
	private Color m_circleColor = Color.yellow;
	public Color circleColor {get {return m_circleColor;}set {m_circleColor = value;_UpdateMaterial();}}
	//模糊因子,这个参数是用来模糊圆形边界的
	[SerializeField, SetProperty("blurFactor")]
	private float m_blurFactor = 2.0f;
	public float blurFactor {get {return m_blurFactor;}set {m_blurFactor = value;_UpdateMaterial();}}
	#endregion
	//保存生成的程序纹理
	private Texture2D m_generatedTexture = null;

	// 在Start函数中进行相应的检查,以得到需要使用该程序纹理的材质
	void Start () {
		if (material == null) {
			Renderer renderer = gameObject.GetComponent<Renderer>();
			if (renderer == null) {
				Debug.LogWarning("Cannot find a renderer.");
				return;
			}
			material = renderer.sharedMaterial;
		}
		_UpdateMaterial();
	}

	private void _UpdateMaterial() {
		if (material != null) {//确保material不为空
			//调用_GenerateProceduralTexture函数来生成一张程序纹理
			m_generatedTexture = _GenerateProceduralTexture();
			//利用Material.SetTexture函数把生成的纹理赋给材质
			//材质material中需要有一个名为_MainTex的纹理属性
			material.SetTexture("_MainTex", m_generatedTexture);
		}
	}
	
	//按通道混合颜色
	private Color _MixColor(Color color0, Color color1, float mixFactor) {
		Color mixColor = Color.white;
		mixColor.r = Mathf.Lerp(color0.r, color1.r, mixFactor);
		mixColor.g = Mathf.Lerp(color0.g, color1.g, mixFactor);
		mixColor.b = Mathf.Lerp(color0.b, color1.b, mixFactor);
		mixColor.a = Mathf.Lerp(color0.a, color1.a, mixFactor);
		return mixColor;
	}

	private Texture2D _GenerateProceduralTexture() {
		//【1】初始化一张二维纹理
		Texture2D proceduralTexture = new Texture2D(textureWidth, textureWidth);
		//【2】提前计算一些生成纹理时需要的变量		
		float circleInterval = textureWidth / 4.0f;//定义圆和圆之间的间距		
		float radius = textureWidth / 10.0f;//定义圆的半径		
		float edgeBlur = 1.0f / blurFactor;//定义模糊系数
		//【3】使用一个两层的嵌套循环遍历纹理中的每个像素,并在纹理上依次绘制9个圆形
		for (int w = 0; w < textureWidth; w++) {
			for (int h = 0; h < textureWidth; h++) {				
				Color pixel = backgroundColor;//使用背景颜色进行初始化
				// 依次画9个圆
				for (int i = 0; i < 3; i++) {
					for (int j = 0; j < 3; j++) {
						//计算当前所绘制的圆的圆心位置
						Vector2 circleCenter = new Vector2(circleInterval * (i + 1), circleInterval * (j + 1));
						//计算当前像素与圆心的距离
						float dist = Vector2.Distance(new Vector2(w, h), circleCenter) - radius;
						//模糊圆的边界
						Color color = _MixColor(circleColor, new Color(pixel.r, pixel.g, pixel.b, 0.0f), Mathf.SmoothStep(0f, 1.0f, dist * edgeBlur));
						//与之前得到的颜色进行混合
						pixel = _MixColor(pixel, color, color.a);
					}
				}				
				proceduralTexture.SetPixel(w, h, pixel);
			}
		}
		//【4】调用Texture2D.Apply函数来强制把像素值写入纹理中
		proceduralTexture.Apply();
		return proceduralTexture;
	}
}

虽然此脚本可以在Editor模式下运行,但是过一会儿就会消失。如果再次修改属性,则又会再次运行。在Play模式下可以正常运行。

在这里插入图片描述

程序材质

在Unity中,有一类专门使用程序纹理的材质,叫做程序材质(Procedural Materials)。这类材质和我们之前使用的那些材质在本质上是一样的,不同的是,它们使用的纹理不是普通的纹理,而是程序纹理。需要注意的是,程序材质和它使用的程序纹理并不是在Unity中创建的,而是使用了一个名为Substance Designer的软件在Unity外部生成的。

Substance Designer是一个非常出色的纹理生成工具,很多3A的游戏项目都使用了由它生成的材质。我们可以从Unity的资源商店或网络中获取到很多免费或付费的Substance材质。这些材质都是以.sbsar为后缀的。

在Unity2018.1以后要使用.sbsar文件,需要在Assets Store中导入Substance in Unity插件(免费)。当把这些文件导入Unity后,Unity就会生成一个程序纹理资源(Procedural Material Asset)。如果每个程序纹理使用了不同的纹理参数,Unity可以为它们生成不同的程序纹理。

在这里插入图片描述
在这里插入图片描述

通过单击程序材质,我们可以在程序纹理的面板上看到该材质使用的Unity Shader及其属性、生成程序纹理使用的纹理属性、材质预览等信息。程序材质的使用和普通材质是一样的,我们把它们拖曳到相应的模型上即可。

在这里插入图片描述

发布了195 篇原创文章 · 获赞 59 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/qq_36622009/article/details/105594236